Mercurial > dropbear
comparison src/encauth/ccm/ccm_memory.c @ 380:d5faf4814ddb libtomcrypt-orig libtomcrypt-1.16
Update to LibTomCrypt 1.16
author | Matt Johnston <matt@ucc.asn.au> |
---|---|
date | Thu, 11 Jan 2007 02:22:00 +0000 |
parents | 59400faa4b44 |
children |
comparison
equal
deleted
inserted
replaced
280:59400faa4b44 | 380:d5faf4814ddb |
---|---|
4 * algorithms in a highly modular and flexible manner. | 4 * algorithms in a highly modular and flexible manner. |
5 * | 5 * |
6 * The library is free for all purposes without any express | 6 * The library is free for all purposes without any express |
7 * guarantee it works. | 7 * guarantee it works. |
8 * | 8 * |
9 * Tom St Denis, [email protected], http://libtomcrypt.org | 9 * Tom St Denis, [email protected], http://libtomcrypt.com |
10 */ | 10 */ |
11 #include "tomcrypt.h" | 11 #include "tomcrypt.h" |
12 | 12 |
13 /** | 13 /** |
14 @file ccm_memory.c | 14 @file ccm_memory.c |
20 /** | 20 /** |
21 CCM encrypt/decrypt and produce an authentication tag | 21 CCM encrypt/decrypt and produce an authentication tag |
22 @param cipher The index of the cipher desired | 22 @param cipher The index of the cipher desired |
23 @param key The secret key to use | 23 @param key The secret key to use |
24 @param keylen The length of the secret key (octets) | 24 @param keylen The length of the secret key (octets) |
25 @param uskey A previously scheduled key [optional can be NULL] | |
25 @param nonce The session nonce [use once] | 26 @param nonce The session nonce [use once] |
26 @param noncelen The length of the nonce | 27 @param noncelen The length of the nonce |
27 @param header The header for the session | 28 @param header The header for the session |
28 @param headerlen The length of the header (octets) | 29 @param headerlen The length of the header (octets) |
29 @param pt [out] The plaintext | 30 @param pt [out] The plaintext |
34 @param direction Encrypt or Decrypt direction (0 or 1) | 35 @param direction Encrypt or Decrypt direction (0 or 1) |
35 @return CRYPT_OK if successful | 36 @return CRYPT_OK if successful |
36 */ | 37 */ |
37 int ccm_memory(int cipher, | 38 int ccm_memory(int cipher, |
38 const unsigned char *key, unsigned long keylen, | 39 const unsigned char *key, unsigned long keylen, |
40 symmetric_key *uskey, | |
39 const unsigned char *nonce, unsigned long noncelen, | 41 const unsigned char *nonce, unsigned long noncelen, |
40 const unsigned char *header, unsigned long headerlen, | 42 const unsigned char *header, unsigned long headerlen, |
41 unsigned char *pt, unsigned long ptlen, | 43 unsigned char *pt, unsigned long ptlen, |
42 unsigned char *ct, | 44 unsigned char *ct, |
43 unsigned char *tag, unsigned long *taglen, | 45 unsigned char *tag, unsigned long *taglen, |
46 unsigned char PAD[16], ctr[16], CTRPAD[16], b; | 48 unsigned char PAD[16], ctr[16], CTRPAD[16], b; |
47 symmetric_key *skey; | 49 symmetric_key *skey; |
48 int err; | 50 int err; |
49 unsigned long len, L, x, y, z, CTRlen; | 51 unsigned long len, L, x, y, z, CTRlen; |
50 | 52 |
51 LTC_ARGCHK(key != NULL); | 53 if (uskey == NULL) { |
54 LTC_ARGCHK(key != NULL); | |
55 } | |
52 LTC_ARGCHK(nonce != NULL); | 56 LTC_ARGCHK(nonce != NULL); |
53 if (headerlen > 0) { | 57 if (headerlen > 0) { |
54 LTC_ARGCHK(header != NULL); | 58 LTC_ARGCHK(header != NULL); |
55 } | 59 } |
56 LTC_ARGCHK(pt != NULL); | 60 LTC_ARGCHK(pt != NULL); |
83 return CRYPT_INVALID_ARG; | 87 return CRYPT_INVALID_ARG; |
84 } | 88 } |
85 | 89 |
86 /* is there an accelerator? */ | 90 /* is there an accelerator? */ |
87 if (cipher_descriptor[cipher].accel_ccm_memory != NULL) { | 91 if (cipher_descriptor[cipher].accel_ccm_memory != NULL) { |
88 cipher_descriptor[cipher].accel_ccm_memory( | 92 return cipher_descriptor[cipher].accel_ccm_memory( |
89 key, keylen, | 93 key, keylen, |
94 uskey, | |
90 nonce, noncelen, | 95 nonce, noncelen, |
91 header, headerlen, | 96 header, headerlen, |
92 pt, ptlen, | 97 pt, ptlen, |
93 ct, | 98 ct, |
94 tag, taglen, | 99 tag, taglen, |
95 direction); | 100 direction); |
96 return CRYPT_OK; | |
97 } | 101 } |
98 | 102 |
99 /* let's get the L value */ | 103 /* let's get the L value */ |
100 len = ptlen; | 104 len = ptlen; |
101 L = 0; | 105 L = 0; |
111 noncelen = (noncelen > 13) ? 13 : noncelen; | 115 noncelen = (noncelen > 13) ? 13 : noncelen; |
112 if ((15 - noncelen) > L) { | 116 if ((15 - noncelen) > L) { |
113 L = 15 - noncelen; | 117 L = 15 - noncelen; |
114 } | 118 } |
115 | 119 |
120 /* decrease noncelen to match L */ | |
121 if ((noncelen + L) > 15) { | |
122 noncelen = 15 - L; | |
123 } | |
124 | |
116 /* allocate mem for the symmetric key */ | 125 /* allocate mem for the symmetric key */ |
117 skey = XMALLOC(sizeof(*skey)); | 126 if (uskey == NULL) { |
118 if (skey == NULL) { | 127 skey = XMALLOC(sizeof(*skey)); |
119 return CRYPT_MEM; | 128 if (skey == NULL) { |
120 } | 129 return CRYPT_MEM; |
121 | 130 } |
122 /* initialize the cipher */ | 131 |
123 if ((err = cipher_descriptor[cipher].setup(key, keylen, 0, skey)) != CRYPT_OK) { | 132 /* initialize the cipher */ |
124 XFREE(skey); | 133 if ((err = cipher_descriptor[cipher].setup(key, keylen, 0, skey)) != CRYPT_OK) { |
125 return err; | 134 XFREE(skey); |
135 return err; | |
136 } | |
137 } else { | |
138 skey = uskey; | |
126 } | 139 } |
127 | 140 |
128 /* form B_0 == flags | Nonce N | l(m) */ | 141 /* form B_0 == flags | Nonce N | l(m) */ |
129 x = 0; | 142 x = 0; |
130 PAD[x++] = ((headerlen > 0) ? (1<<6) : 0) | | 143 PAD[x++] = (unsigned char)(((headerlen > 0) ? (1<<6) : 0) | |
131 (((*taglen - 2)>>1)<<3) | | 144 (((*taglen - 2)>>1)<<3) | |
132 (L-1); | 145 (L-1)); |
133 | 146 |
134 /* nonce */ | 147 /* nonce */ |
135 for (y = 0; y < (16 - (L + 1)); y++) { | 148 for (y = 0; y < (16 - (L + 1)); y++) { |
136 PAD[x++] = nonce[y]; | 149 PAD[x++] = nonce[y]; |
137 } | 150 } |
147 /* store l(m) (only store 32-bits) */ | 160 /* store l(m) (only store 32-bits) */ |
148 for (y = 0; L > 4 && (L-y)>4; y++) { | 161 for (y = 0; L > 4 && (L-y)>4; y++) { |
149 PAD[x++] = 0; | 162 PAD[x++] = 0; |
150 } | 163 } |
151 for (; y < L; y++) { | 164 for (; y < L; y++) { |
152 PAD[x++] = (len >> 24) & 255; | 165 PAD[x++] = (unsigned char)((len >> 24) & 255); |
153 len <<= 8; | 166 len <<= 8; |
154 } | 167 } |
155 | 168 |
156 /* encrypt PAD */ | 169 /* encrypt PAD */ |
157 cipher_descriptor[cipher].ecb_encrypt(PAD, PAD, skey); | 170 if ((err = cipher_descriptor[cipher].ecb_encrypt(PAD, PAD, skey)) != CRYPT_OK) { |
171 goto error; | |
172 } | |
158 | 173 |
159 /* handle header */ | 174 /* handle header */ |
160 if (headerlen > 0) { | 175 if (headerlen > 0) { |
161 x = 0; | 176 x = 0; |
162 | 177 |
175 | 190 |
176 /* now add the data */ | 191 /* now add the data */ |
177 for (y = 0; y < headerlen; y++) { | 192 for (y = 0; y < headerlen; y++) { |
178 if (x == 16) { | 193 if (x == 16) { |
179 /* full block so let's encrypt it */ | 194 /* full block so let's encrypt it */ |
180 cipher_descriptor[cipher].ecb_encrypt(PAD, PAD, skey); | 195 if ((err = cipher_descriptor[cipher].ecb_encrypt(PAD, PAD, skey)) != CRYPT_OK) { |
196 goto error; | |
197 } | |
181 x = 0; | 198 x = 0; |
182 } | 199 } |
183 PAD[x++] ^= header[y]; | 200 PAD[x++] ^= header[y]; |
184 } | 201 } |
185 | 202 |
186 /* remainder? */ | 203 /* remainder? */ |
187 if (x != 0) { | 204 if (x != 0) { |
188 cipher_descriptor[cipher].ecb_encrypt(PAD, PAD, skey); | 205 if ((err = cipher_descriptor[cipher].ecb_encrypt(PAD, PAD, skey)) != CRYPT_OK) { |
206 goto error; | |
207 } | |
189 } | 208 } |
190 } | 209 } |
191 | 210 |
192 /* setup the ctr counter */ | 211 /* setup the ctr counter */ |
193 x = 0; | 212 x = 0; |
194 | 213 |
195 /* flags */ | 214 /* flags */ |
196 ctr[x++] = L-1; | 215 ctr[x++] = (unsigned char)L-1; |
197 | 216 |
198 /* nonce */ | 217 /* nonce */ |
199 for (y = 0; y < (16 - (L+1)); ++y) { | 218 for (y = 0; y < (16 - (L+1)); ++y) { |
200 ctr[x++] = nonce[y]; | 219 ctr[x++] = nonce[y]; |
201 } | 220 } |
217 /* increment the ctr? */ | 236 /* increment the ctr? */ |
218 for (z = 15; z > 15-L; z--) { | 237 for (z = 15; z > 15-L; z--) { |
219 ctr[z] = (ctr[z] + 1) & 255; | 238 ctr[z] = (ctr[z] + 1) & 255; |
220 if (ctr[z]) break; | 239 if (ctr[z]) break; |
221 } | 240 } |
222 cipher_descriptor[cipher].ecb_encrypt(ctr, CTRPAD, skey); | 241 if ((err = cipher_descriptor[cipher].ecb_encrypt(ctr, CTRPAD, skey)) != CRYPT_OK) { |
242 goto error; | |
243 } | |
223 | 244 |
224 /* xor the PT against the pad first */ | 245 /* xor the PT against the pad first */ |
225 for (z = 0; z < 16; z += sizeof(LTC_FAST_TYPE)) { | 246 for (z = 0; z < 16; z += sizeof(LTC_FAST_TYPE)) { |
226 *((LTC_FAST_TYPE*)(&PAD[z])) ^= *((LTC_FAST_TYPE*)(&pt[y+z])); | 247 *((LTC_FAST_TYPE*)(&PAD[z])) ^= *((LTC_FAST_TYPE*)(&pt[y+z])); |
227 *((LTC_FAST_TYPE*)(&ct[y+z])) = *((LTC_FAST_TYPE*)(&pt[y+z])) ^ *((LTC_FAST_TYPE*)(&CTRPAD[z])); | 248 *((LTC_FAST_TYPE*)(&ct[y+z])) = *((LTC_FAST_TYPE*)(&pt[y+z])) ^ *((LTC_FAST_TYPE*)(&CTRPAD[z])); |
228 } | 249 } |
229 cipher_descriptor[cipher].ecb_encrypt(PAD, PAD, skey); | 250 if ((err = cipher_descriptor[cipher].ecb_encrypt(PAD, PAD, skey)) != CRYPT_OK) { |
251 goto error; | |
252 } | |
230 } | 253 } |
231 } else { | 254 } else { |
232 for (; y < (ptlen & ~15); y += 16) { | 255 for (; y < (ptlen & ~15); y += 16) { |
233 /* increment the ctr? */ | 256 /* increment the ctr? */ |
234 for (z = 15; z > 15-L; z--) { | 257 for (z = 15; z > 15-L; z--) { |
235 ctr[z] = (ctr[z] + 1) & 255; | 258 ctr[z] = (ctr[z] + 1) & 255; |
236 if (ctr[z]) break; | 259 if (ctr[z]) break; |
237 } | 260 } |
238 cipher_descriptor[cipher].ecb_encrypt(ctr, CTRPAD, skey); | 261 if ((err = cipher_descriptor[cipher].ecb_encrypt(ctr, CTRPAD, skey)) != CRYPT_OK) { |
262 goto error; | |
263 } | |
239 | 264 |
240 /* xor the PT against the pad last */ | 265 /* xor the PT against the pad last */ |
241 for (z = 0; z < 16; z += sizeof(LTC_FAST_TYPE)) { | 266 for (z = 0; z < 16; z += sizeof(LTC_FAST_TYPE)) { |
242 *((LTC_FAST_TYPE*)(&pt[y+z])) = *((LTC_FAST_TYPE*)(&ct[y+z])) ^ *((LTC_FAST_TYPE*)(&CTRPAD[z])); | 267 *((LTC_FAST_TYPE*)(&pt[y+z])) = *((LTC_FAST_TYPE*)(&ct[y+z])) ^ *((LTC_FAST_TYPE*)(&CTRPAD[z])); |
243 *((LTC_FAST_TYPE*)(&PAD[z])) ^= *((LTC_FAST_TYPE*)(&pt[y+z])); | 268 *((LTC_FAST_TYPE*)(&PAD[z])) ^= *((LTC_FAST_TYPE*)(&pt[y+z])); |
244 } | 269 } |
245 cipher_descriptor[cipher].ecb_encrypt(PAD, PAD, skey); | 270 if ((err = cipher_descriptor[cipher].ecb_encrypt(PAD, PAD, skey)) != CRYPT_OK) { |
271 goto error; | |
272 } | |
246 } | 273 } |
247 } | 274 } |
248 } | 275 } |
249 #endif | 276 #endif |
250 | 277 |
253 if (CTRlen == 16) { | 280 if (CTRlen == 16) { |
254 for (z = 15; z > 15-L; z--) { | 281 for (z = 15; z > 15-L; z--) { |
255 ctr[z] = (ctr[z] + 1) & 255; | 282 ctr[z] = (ctr[z] + 1) & 255; |
256 if (ctr[z]) break; | 283 if (ctr[z]) break; |
257 } | 284 } |
258 cipher_descriptor[cipher].ecb_encrypt(ctr, CTRPAD, skey); | 285 if ((err = cipher_descriptor[cipher].ecb_encrypt(ctr, CTRPAD, skey)) != CRYPT_OK) { |
286 goto error; | |
287 } | |
259 CTRlen = 0; | 288 CTRlen = 0; |
260 } | 289 } |
261 | 290 |
262 /* if we encrypt we add the bytes to the MAC first */ | 291 /* if we encrypt we add the bytes to the MAC first */ |
263 if (direction == CCM_ENCRYPT) { | 292 if (direction == CCM_ENCRYPT) { |
267 b = ct[y] ^ CTRPAD[CTRlen++]; | 296 b = ct[y] ^ CTRPAD[CTRlen++]; |
268 pt[y] = b; | 297 pt[y] = b; |
269 } | 298 } |
270 | 299 |
271 if (x == 16) { | 300 if (x == 16) { |
272 cipher_descriptor[cipher].ecb_encrypt(PAD, PAD, skey); | 301 if ((err = cipher_descriptor[cipher].ecb_encrypt(PAD, PAD, skey)) != CRYPT_OK) { |
302 goto error; | |
303 } | |
273 x = 0; | 304 x = 0; |
274 } | 305 } |
275 PAD[x++] ^= b; | 306 PAD[x++] ^= b; |
276 } | 307 } |
277 | 308 |
278 if (x != 0) { | 309 if (x != 0) { |
279 cipher_descriptor[cipher].ecb_encrypt(PAD, PAD, skey); | 310 if ((err = cipher_descriptor[cipher].ecb_encrypt(PAD, PAD, skey)) != CRYPT_OK) { |
280 } | 311 goto error; |
281 } | 312 } |
282 | 313 } |
283 /* setup CTR for the TAG */ | 314 } |
284 ctr[14] = ctr[15] = 0x00; | 315 |
285 cipher_descriptor[cipher].ecb_encrypt(ctr, CTRPAD, skey); | 316 /* setup CTR for the TAG (zero the count) */ |
286 cipher_descriptor[cipher].done(skey); | 317 for (y = 15; y > 15 - L; y--) { |
318 ctr[y] = 0x00; | |
319 } | |
320 if ((err = cipher_descriptor[cipher].ecb_encrypt(ctr, CTRPAD, skey)) != CRYPT_OK) { | |
321 goto error; | |
322 } | |
323 | |
324 if (skey != uskey) { | |
325 cipher_descriptor[cipher].done(skey); | |
326 } | |
287 | 327 |
288 /* store the TAG */ | 328 /* store the TAG */ |
289 for (x = 0; x < 16 && x < *taglen; x++) { | 329 for (x = 0; x < 16 && x < *taglen; x++) { |
290 tag[x] = PAD[x] ^ CTRPAD[x]; | 330 tag[x] = PAD[x] ^ CTRPAD[x]; |
291 } | 331 } |
294 #ifdef LTC_CLEAN_STACK | 334 #ifdef LTC_CLEAN_STACK |
295 zeromem(skey, sizeof(*skey)); | 335 zeromem(skey, sizeof(*skey)); |
296 zeromem(PAD, sizeof(PAD)); | 336 zeromem(PAD, sizeof(PAD)); |
297 zeromem(CTRPAD, sizeof(CTRPAD)); | 337 zeromem(CTRPAD, sizeof(CTRPAD)); |
298 #endif | 338 #endif |
299 | 339 error: |
300 XFREE(skey); | 340 if (skey != uskey) { |
301 | 341 XFREE(skey); |
302 return CRYPT_OK; | 342 } |
343 | |
344 return err; | |
303 } | 345 } |
304 | 346 |
305 #endif | 347 #endif |
306 | 348 |
307 /* $Source: /cvs/libtom/libtomcrypt/src/encauth/ccm/ccm_memory.c,v $ */ | 349 /* $Source: /cvs/libtom/libtomcrypt/src/encauth/ccm/ccm_memory.c,v $ */ |
308 /* $Revision: 1.9 $ */ | 350 /* $Revision: 1.18 $ */ |
309 /* $Date: 2005/05/05 14:35:58 $ */ | 351 /* $Date: 2006/12/04 21:34:03 $ */ |