/
aead.go
141 lines (126 loc) · 4.75 KB
/
aead.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
package crypto
import (
"crypto/cipher"
"crypto/rand"
"encoding/hex"
"errors"
"log"
"github.com/msgboxio/ike/protocol"
)
/*
rfc5282
Using Authenticated Encryption Algorithms with the Encrypted Payload
of the Internet Key Exchange version 2 (IKEv2) Protocol
sk payload ->
1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! Next Payload !C! RESERVED ! Payload Length !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! Initialization Vector !
! 8B !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
~ Ciphertext (C) ~
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
P (plaintext) ->
1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
~ IKE Payloads to be Encrypted ~
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! ! Padding (0-255 octets) !
+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+
! ! Pad Length !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
A (additional data) ->
1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
~ IKEv2 Header ~
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
~ Unencrypted IKE Payloads ~
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! Next Payload !C! RESERVED ! Payload Length !
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
length of SK_ai and SK_ar is 0
SK_ei and SK_er include salt bytes
if keyLen is 128, then 20 bits (16B + 4B salt)
ICV is atag
*/
type aeadFunc func(key []byte) (cipher.AEAD, error)
type aeadCipher struct {
aeadFunc
blockLen, keyLen, saltLen, ivLen, icvLen int
protocol.EncrTransformId
}
func (cs *aeadCipher) String() string {
return cs.EncrTransformId.String()
}
func (cs *aeadCipher) Overhead(clear []byte) int {
// padding + iv + icv
padlen := cs.blockLen - len(clear)%cs.blockLen
return padlen + cs.ivLen + cs.icvLen
}
const aadLen = protocol.IKE_HEADER_LEN + protocol.PAYLOAD_HEADER_LENGTH
func (cs *aeadCipher) VerifyDecrypt(ike, skA, skE []byte) (dec []byte, err error) {
// Encryption key has salt appended to it
key := skE[:cs.keyLen]
salt := skE[cs.keyLen : cs.keyLen+cs.saltLen]
aead, err := cs.aeadFunc(key)
if err != nil {
return
}
aad := ike[:aadLen]
iv := ike[aadLen : aadLen+cs.ivLen]
ct := ike[aadLen+cs.ivLen:]
nonce := append(append([]byte{}, salt...), iv...) // 12B; 4B salt + 8B iv
if DebugCrypto {
log.Printf("aead Verify&Decrypt:\nKey:\n%sSalt:\n%sIV:\n%sAd:\n%sCT:\n%s",
hex.Dump(key), hex.Dump(salt), hex.Dump(iv), hex.Dump(aad), hex.Dump(ct))
}
clear, err := aead.Open([]byte{}, nonce, ct, aad)
if err != nil {
return
}
// remove pad
padlen := clear[len(clear)-1] + 1 // padlen byte itself
if int(padlen) > cs.blockLen {
err = errors.New("pad length is larger than block size")
return
}
dec = clear[:len(clear)-int(padlen)]
if DebugCrypto {
log.Printf("Padlen:%d Clear:\n%s", padlen, hex.Dump(clear))
}
return
}
func (cs *aeadCipher) EncryptMac(ike, skA, skE []byte) (encr []byte, err error) {
key := skE[:cs.keyLen]
salt := skE[cs.keyLen : cs.keyLen+cs.saltLen]
aead, err := cs.aeadFunc(key)
if err != nil {
return
}
aad := ike[:aadLen] // additional data
iv, err := rand.Prime(rand.Reader, cs.ivLen*8) // bits
if err != nil {
return
}
ivBytes := iv.Bytes()
payload := ike[aadLen:]
nonce := append(append([]byte{}, salt...), ivBytes...)
// pad
padlen := cs.blockLen - len(payload)%cs.blockLen
if padlen != 0 {
pad := make([]byte, padlen)
pad[padlen-1] = byte(padlen - 1) // write length
payload = append(append([]byte{}, payload...), pad...)
}
encr = aead.Seal([]byte{}, nonce, payload, aad)
if DebugCrypto {
log.Printf("aead encrypt&mac:\nKey:\n%sSalt:\n%sIV:\n%sAd:\n%sPadlen:%d\nencr\n%s",
hex.Dump(key), hex.Dump(salt), hex.Dump(ivBytes), hex.Dump(aad), padlen, hex.Dump(encr))
}
encr = append(append(append([]byte{}, aad...), ivBytes...), encr...)
return
}