@@ -15,101 +15,100 @@ import (
15
15
. "code.google.com/p/go-sqlite/go1/sqlite3"
16
16
)
17
17
18
- // TODO(max): Remove the master key.
19
- // TODO(max): MAC the cipher spec.
20
- // TODO(max): HMAC key should be the same size as the output.
21
-
22
18
type aesHmac struct {
23
- key []byte // Key provided to newAesHmac
24
- p1k []byte // Page 1 key (subslice of key)
25
- p1i []byte // Page 1 HKDF info ("go-sqlite")
26
- buf []byte // Page encryption buffer
27
- kLen int // Cipher and HMAC key length in bytes (16, 24, or 32)
28
- tLen int // Tag length in bytes (HMAC truncation)
29
-
30
- // Hash function and cipher chaining mode constructors
19
+ key []byte // Key provided to newAesHmac with the master key removed
20
+ buf []byte // Page encryption buffer
21
+ hdr [4 ]byte // Header included in each HMAC calculation (page number)
22
+ tLen int // Tag length in bytes (HMAC truncation)
23
+
24
+ // Hash function and chaining mode constructors
31
25
hash func () hash.Hash
32
26
mode func (block cipher.Block , iv []byte ) cipher.Stream
33
27
34
- // Block cipher and HMAC hash initialized from the master key
28
+ // Block cipher and HMAC initialized from the master key
35
29
block cipher.Block
36
30
hmac hash.Hash
37
31
}
38
32
39
33
func newAesHmac (ctx * CodecCtx , key []byte ) (Codec , * Error ) {
40
- _ , opts , mk := parseKey (key )
41
- if mk == nil {
34
+ name , opts , mk := parseKey (key )
35
+ if len ( mk ) == 0 {
42
36
return nil , keyErr
43
37
}
38
+ defer wipe (mk )
39
+
40
+ // Configure the codec
44
41
c := & aesHmac {
45
- key : key ,
46
- p1k : mk ,
47
- p1i : []byte ("go-sqlite\x00 " )[:9 ],
48
- kLen : 16 ,
42
+ key : key [:len (key )- len (mk )],
49
43
tLen : 16 ,
50
44
hash : sha1 .New ,
51
45
mode : cipher .NewCTR ,
52
46
}
53
- if err := c .config (opts ); err != nil {
47
+ suite := suiteId {
48
+ Cipher : "aes" ,
49
+ KeySize : "128" ,
50
+ Mode : "ctr" ,
51
+ MAC : "hmac" ,
52
+ Hash : "sha1" ,
53
+ Trunc : "128" ,
54
+ }
55
+ kLen := 16
56
+ if err := c .config (opts , & suite , & kLen ); err != nil {
54
57
return nil , err
55
58
}
59
+
60
+ // Derive encryption and authentication keys
61
+ hLen := c .hash ().Size ()
62
+ salt := make ([]byte , hLen )
63
+ copy (salt , name )
64
+ dk := hkdf (mk , salt , kLen + hLen , c .hash )(suite .Id ())
65
+ defer wipe (dk )
66
+
67
+ // Initialize the block cipher and HMAC
68
+ var err error
69
+ if c .block , err = aes .NewCipher (dk [:kLen ]); err != nil {
70
+ return nil , NewError (MISUSE , err .Error ())
71
+ }
72
+ c .hmac = hmac .New (c .hash , dk [kLen :])
56
73
return c , nil
57
74
}
58
75
59
76
func (c * aesHmac ) Reserve () int {
60
- return c . kLen + aes .BlockSize + c .tLen
77
+ return aes .BlockSize + c .tLen
61
78
}
62
79
63
80
func (c * aesHmac ) Resize (pageSize , reserve int ) {
64
81
if reserve != c .Reserve () {
65
82
panic ("sqlite3: codec reserve value mismatch" )
66
83
}
67
- tMax := c .hash ().Size ()
68
- c .buf = make ([]byte , pageSize , pageSize - c .tLen + tMax )
84
+ hLen := c .hash ().Size ()
85
+ c .buf = make ([]byte , pageSize , pageSize - c .tLen + hLen )
69
86
}
70
87
71
88
func (c * aesHmac ) Encode (p []byte , n uint32 , op int ) ([]byte , * Error ) {
72
- // Generate new random IV (HKDF salt for page 1)
73
89
iv := c .pIV (c .buf )
74
90
if ! rnd (iv ) {
75
91
return nil , prngErr
76
92
}
77
-
78
- // Create the master key if encrypting page 1 for a new database
79
- if c .block == nil && ! c .init (p , n , true ) {
80
- return nil , codecErr
81
- }
82
-
83
- // Encrypt-then-MAC
84
- cipher , hmac := c .cipher (n , iv )
85
- cipher .XORKeyStream (c .buf , c .pText (p ))
93
+ c .mode (c .block , iv ).XORKeyStream (c .buf , c .pText (p ))
86
94
if n == 1 {
87
- copy (c .buf [16 :], p [16 :24 ]) // Bytes 16 through 23 cannot be encrypted
95
+ copy (c .buf [16 :], p [16 :24 ])
88
96
}
89
- c .mac (c .buf , n , hmac , false )
97
+ c .auth (c .buf , n , false )
90
98
return c .buf , nil
91
99
}
92
100
93
101
func (c * aesHmac ) Decode (p []byte , n uint32 , op int ) * Error {
94
- // Verify tag
95
- cipher , hmac := c .cipher (n , c .pIV (p ))
96
- if ! c .mac (p , n , hmac , true ) {
102
+ if ! c .auth (p , n , true ) {
97
103
return codecErr
98
104
}
99
-
100
- // Decrypt
101
105
if n == 1 {
102
106
copy (c .buf , p [16 :24 ])
103
107
}
104
- cipher .XORKeyStream (p , c .pText (p ))
108
+ c . mode ( c . block , c . pIV ( p )) .XORKeyStream (p , c .pText (p ))
105
109
if n == 1 {
106
110
copy (p [16 :24 ], c .buf )
107
111
}
108
-
109
- // Get the master key if decrypting page 1 for the first time
110
- if c .block == nil && ! c .init (p , n , false ) {
111
- return codecErr
112
- }
113
112
return nil
114
113
}
115
114
@@ -118,21 +117,26 @@ func (c *aesHmac) Key() []byte {
118
117
}
119
118
120
119
func (c * aesHmac ) Free () {
121
- wipe (c .key )
122
- * c = aesHmac {}
120
+ c .buf = nil
121
+ c .block = nil
122
+ c .hmac = nil
123
123
}
124
124
125
125
// config applies the codec options that were provided in the key.
126
- func (c * aesHmac ) config (opts map [string ]string ) * Error {
126
+ func (c * aesHmac ) config (opts map [string ]string , s * suiteId , kLen * int ) * Error {
127
127
for k := range opts {
128
128
switch k {
129
129
case "192" :
130
- c .kLen = 24
130
+ s .KeySize = k
131
+ * kLen = 24
131
132
case "256" :
132
- c .kLen = 32
133
+ s .KeySize = k
134
+ * kLen = 32
133
135
case "ofb" :
136
+ s .Mode = k
134
137
c .mode = cipher .NewOFB
135
138
case "sha256" :
139
+ s .Hash = k
136
140
c .hash = sha256 .New
137
141
default :
138
142
return NewError (MISUSE , "invalid codec option: " + k )
@@ -141,66 +145,21 @@ func (c *aesHmac) config(opts map[string]string) *Error {
141
145
return nil
142
146
}
143
147
144
- // cipher returns the stream cipher and HMAC hash for page n. Both are reset to
145
- // their initial state.
146
- func (c * aesHmac ) cipher (n uint32 , iv []byte ) (cipher.Stream , hash.Hash ) {
147
- if n > 1 {
148
- c .hmac .Reset ()
149
- return c .mode (c .block , iv ), c .hmac
150
- }
151
-
152
- // Derive page 1 cipher key, HMAC key, and IV
153
- dkLen := 2 * c .kLen
154
- dk := hkdf (c .p1k , iv , dkLen + aes .BlockSize , c .hash )(c .p1i )
155
- dk , iv = dk [:dkLen ], dk [dkLen :]
156
- defer wipe (dk )
148
+ // auth calculates and verifies the HMAC tag for page p. It returns true iff the
149
+ // tag is successfully verified.
150
+ func (c * aesHmac ) auth (p []byte , n uint32 , verify bool ) bool {
151
+ c .hdr [0 ] = byte (n >> 24 )
152
+ c .hdr [1 ] = byte (n >> 16 )
153
+ c .hdr [2 ] = byte (n >> 8 )
154
+ c .hdr [3 ] = byte (n )
157
155
158
- // Initialize the stream cipher and HMAC for page 1
159
- if block , hmac := c .rekey (dk [:c .kLen ], dk [c .kLen :]); block != nil {
160
- return c .mode (block , iv ), hmac
161
- }
162
- return nil , nil
163
- }
164
-
165
- // mac calculates and optionally verifies the HMAC tag for page p. It returns
166
- // true iff the tag verification is successful.
167
- func (c * aesHmac ) mac (p []byte , n uint32 , h hash.Hash , verify bool ) bool {
168
- h .Write ([]byte {byte (n >> 24 ), byte (n >> 16 ), byte (n >> 8 ), byte (n )})
169
- h .Write (c .pAuth (p ))
170
156
tag := c .pTag (c .buf )
171
- h .Sum (tag [:0 ])
172
- return verify && hmac .Equal (tag , c .pTag (p ))
173
- }
174
-
175
- // init initializes the block cipher and HMAC hash using the page 1 master key.
176
- // It returns true on success and false otherwise.
177
- func (c * aesHmac ) init (p []byte , n uint32 , newKey bool ) bool {
178
- if n != 1 {
179
- return false // First call to Encrypt or Decrypt must be for page 1
180
- }
181
-
182
- // Load or generate the master key
183
- mk := c .pKey (p )
184
- if newKey && ! rnd (mk ) {
185
- return false
186
- }
157
+ c .hmac .Reset ()
158
+ c .hmac .Write (c .hdr [:])
159
+ c .hmac .Write (c .pAuth (p ))
160
+ c .hmac .Sum (tag [:0 ])
187
161
188
- // Derive cipher and HMAC keys from the master key
189
- hdr := append (make ([]byte , 0 , 17 ), p [:16 ]... )
190
- dk := hkdf (mk , nil , 2 * c .kLen , c .hash )(hdr )
191
- defer wipe (dk )
192
-
193
- // Initialize the block cipher and HMAC
194
- c .block , c .hmac = c .rekey (dk [:c .kLen ], dk [c .kLen :])
195
- return c .block != nil
196
- }
197
-
198
- // rekey creates a new block cipher and HMAC hash using the specified keys.
199
- func (c * aesHmac ) rekey (ck , hk []byte ) (cipher.Block , hash.Hash ) {
200
- if block , err := aes .NewCipher (ck ); err == nil {
201
- return block , hmac .New (c .hash , hk )
202
- }
203
- return nil , nil
162
+ return verify && hmac .Equal (tag , c .pTag (p ))
204
163
}
205
164
206
165
// pAuth returns the page subslice that gets authenticated.
@@ -213,16 +172,9 @@ func (c *aesHmac) pText(p []byte) []byte {
213
172
return p [:len (p )- c .tLen - aes .BlockSize ]
214
173
}
215
174
216
- // pKey returns the master key from page 1.
217
- func (c * aesHmac ) pKey (p []byte ) []byte {
218
- off := len (p ) - c .tLen - aes .BlockSize - c .kLen
219
- return p [off : off + c .kLen ]
220
- }
221
-
222
- // pIV returns the page initialization vector (HKDF salt for page 1).
175
+ // pIV returns the page initialization vector.
223
176
func (c * aesHmac ) pIV (p []byte ) []byte {
224
- off := len (p ) - c .tLen - aes .BlockSize
225
- return p [off : off + aes .BlockSize ]
177
+ return p [len (p )- c .tLen - aes .BlockSize : len (p )- c .tLen ]
226
178
}
227
179
228
180
// pTag returns the page authentication tag.
0 commit comments