Mercurial > dropbear
comparison libtomcrypt/src/encauth/ccm/ccm_memory.c @ 1471:6dba84798cd5
Update to libtomcrypt 1.18.1, merged with Dropbear changes
author | Matt Johnston <matt@ucc.asn.au> |
---|---|
date | Fri, 09 Feb 2018 21:44:05 +0800 |
parents | f849a5ca2efc |
children | e9dba7abd939 |
comparison
equal
deleted
inserted
replaced
1470:8bba51a55704 | 1471:6dba84798cd5 |
---|---|
3 * LibTomCrypt is a library that provides various cryptographic | 3 * LibTomCrypt is a library that provides various cryptographic |
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 * | |
9 * Tom St Denis, [email protected], http://libtom.org | |
10 */ | 8 */ |
11 #include "tomcrypt.h" | 9 #include "tomcrypt.h" |
12 | 10 |
13 /** | 11 /** |
14 @file ccm_memory.c | 12 @file ccm_memory.c |
17 | 15 |
18 #ifdef LTC_CCM_MODE | 16 #ifdef LTC_CCM_MODE |
19 | 17 |
20 /** | 18 /** |
21 CCM encrypt/decrypt and produce an authentication tag | 19 CCM encrypt/decrypt and produce an authentication tag |
20 | |
21 *1 'pt', 'ct' and 'tag' can both be 'in' or 'out', depending on 'direction' | |
22 | |
22 @param cipher The index of the cipher desired | 23 @param cipher The index of the cipher desired |
23 @param key The secret key to use | 24 @param key The secret key to use |
24 @param keylen The length of the secret key (octets) | 25 @param keylen The length of the secret key (octets) |
25 @param uskey A previously scheduled key [optional can be NULL] | 26 @param uskey A previously scheduled key [optional can be NULL] |
26 @param nonce The session nonce [use once] | 27 @param nonce The session nonce [use once] |
27 @param noncelen The length of the nonce | 28 @param noncelen The length of the nonce |
28 @param header The header for the session | 29 @param header The header for the session |
29 @param headerlen The length of the header (octets) | 30 @param headerlen The length of the header (octets) |
30 @param pt [out] The plaintext | 31 @param pt [*1] The plaintext |
31 @param ptlen The length of the plaintext (octets) | 32 @param ptlen The length of the plaintext (octets) |
32 @param ct [out] The ciphertext | 33 @param ct [*1] The ciphertext |
33 @param tag [out] The destination tag | 34 @param tag [*1] The destination tag |
34 @param taglen [in/out] The max size and resulting size of the authentication tag | 35 @param taglen The max size and resulting size of the authentication tag |
35 @param direction Encrypt or Decrypt direction (0 or 1) | 36 @param direction Encrypt or Decrypt direction (0 or 1) |
36 @return CRYPT_OK if successful | 37 @return CRYPT_OK if successful |
37 */ | 38 */ |
38 int ccm_memory(int cipher, | 39 int ccm_memory(int cipher, |
39 const unsigned char *key, unsigned long keylen, | 40 const unsigned char *key, unsigned long keylen, |
43 unsigned char *pt, unsigned long ptlen, | 44 unsigned char *pt, unsigned long ptlen, |
44 unsigned char *ct, | 45 unsigned char *ct, |
45 unsigned char *tag, unsigned long *taglen, | 46 unsigned char *tag, unsigned long *taglen, |
46 int direction) | 47 int direction) |
47 { | 48 { |
48 unsigned char PAD[16], ctr[16], CTRPAD[16], b; | 49 unsigned char PAD[16], ctr[16], CTRPAD[16], ptTag[16], b, *pt_real; |
50 unsigned char *pt_work = NULL; | |
49 symmetric_key *skey; | 51 symmetric_key *skey; |
50 int err; | 52 int err; |
51 unsigned long len, L, x, y, z, CTRlen; | 53 unsigned long len, L, x, y, z, CTRlen; |
54 #ifdef LTC_FAST | |
55 LTC_FAST_TYPE fastMask = ~0; /* initialize fastMask at all zeroes */ | |
56 #endif | |
57 unsigned char mask = 0xff; /* initialize mask at all zeroes */ | |
52 | 58 |
53 if (uskey == NULL) { | 59 if (uskey == NULL) { |
54 LTC_ARGCHK(key != NULL); | 60 LTC_ARGCHK(key != NULL); |
55 } | 61 } |
56 LTC_ARGCHK(nonce != NULL); | 62 LTC_ARGCHK(nonce != NULL); |
59 } | 65 } |
60 LTC_ARGCHK(pt != NULL); | 66 LTC_ARGCHK(pt != NULL); |
61 LTC_ARGCHK(ct != NULL); | 67 LTC_ARGCHK(ct != NULL); |
62 LTC_ARGCHK(tag != NULL); | 68 LTC_ARGCHK(tag != NULL); |
63 LTC_ARGCHK(taglen != NULL); | 69 LTC_ARGCHK(taglen != NULL); |
70 | |
71 pt_real = pt; | |
64 | 72 |
65 #ifdef LTC_FAST | 73 #ifdef LTC_FAST |
66 if (16 % sizeof(LTC_FAST_TYPE)) { | 74 if (16 % sizeof(LTC_FAST_TYPE)) { |
67 return CRYPT_INVALID_ARG; | 75 return CRYPT_INVALID_ARG; |
68 } | 76 } |
93 key, keylen, | 101 key, keylen, |
94 uskey, | 102 uskey, |
95 nonce, noncelen, | 103 nonce, noncelen, |
96 header, headerlen, | 104 header, headerlen, |
97 pt, ptlen, | 105 pt, ptlen, |
98 ct, | 106 ct, |
99 tag, taglen, | 107 tag, taglen, |
100 direction); | 108 direction); |
101 } | 109 } |
102 | 110 |
103 /* let's get the L value */ | 111 /* let's get the L value */ |
115 noncelen = (noncelen > 13) ? 13 : noncelen; | 123 noncelen = (noncelen > 13) ? 13 : noncelen; |
116 if ((15 - noncelen) > L) { | 124 if ((15 - noncelen) > L) { |
117 L = 15 - noncelen; | 125 L = 15 - noncelen; |
118 } | 126 } |
119 | 127 |
120 /* decrease noncelen to match L */ | |
121 if ((noncelen + L) > 15) { | |
122 noncelen = 15 - L; | |
123 } | |
124 | |
125 /* allocate mem for the symmetric key */ | 128 /* allocate mem for the symmetric key */ |
126 if (uskey == NULL) { | 129 if (uskey == NULL) { |
127 skey = XMALLOC(sizeof(*skey)); | 130 skey = XMALLOC(sizeof(*skey)); |
128 if (skey == NULL) { | 131 if (skey == NULL) { |
129 return CRYPT_MEM; | 132 return CRYPT_MEM; |
136 } | 139 } |
137 } else { | 140 } else { |
138 skey = uskey; | 141 skey = uskey; |
139 } | 142 } |
140 | 143 |
144 /* initialize buffer for pt */ | |
145 if (direction == CCM_DECRYPT && ptlen > 0) { | |
146 pt_work = XMALLOC(ptlen); | |
147 if (pt_work == NULL) { | |
148 goto error; | |
149 } | |
150 pt = pt_work; | |
151 } | |
152 | |
141 /* form B_0 == flags | Nonce N | l(m) */ | 153 /* form B_0 == flags | Nonce N | l(m) */ |
142 x = 0; | 154 x = 0; |
143 PAD[x++] = (unsigned char)(((headerlen > 0) ? (1<<6) : 0) | | 155 PAD[x++] = (unsigned char)(((headerlen > 0) ? (1<<6) : 0) | |
144 (((*taglen - 2)>>1)<<3) | | 156 (((*taglen - 2)>>1)<<3) | |
145 (L-1)); | 157 (L-1)); |
172 } | 184 } |
173 | 185 |
174 /* handle header */ | 186 /* handle header */ |
175 if (headerlen > 0) { | 187 if (headerlen > 0) { |
176 x = 0; | 188 x = 0; |
177 | 189 |
178 /* store length */ | 190 /* store length */ |
179 if (headerlen < ((1UL<<16) - (1UL<<8))) { | 191 if (headerlen < ((1UL<<16) - (1UL<<8))) { |
180 PAD[x++] ^= (headerlen>>8) & 255; | 192 PAD[x++] ^= (headerlen>>8) & 255; |
181 PAD[x++] ^= headerlen & 255; | 193 PAD[x++] ^= headerlen & 255; |
182 } else { | 194 } else { |
198 x = 0; | 210 x = 0; |
199 } | 211 } |
200 PAD[x++] ^= header[y]; | 212 PAD[x++] ^= header[y]; |
201 } | 213 } |
202 | 214 |
203 /* remainder? */ | 215 /* remainder */ |
204 if (x != 0) { | 216 if ((err = cipher_descriptor[cipher].ecb_encrypt(PAD, PAD, skey)) != CRYPT_OK) { |
205 if ((err = cipher_descriptor[cipher].ecb_encrypt(PAD, PAD, skey)) != CRYPT_OK) { | 217 goto error; |
206 goto error; | |
207 } | |
208 } | 218 } |
209 } | 219 } |
210 | 220 |
211 /* setup the ctr counter */ | 221 /* setup the ctr counter */ |
212 x = 0; | 222 x = 0; |
213 | 223 |
214 /* flags */ | 224 /* flags */ |
215 ctr[x++] = (unsigned char)L-1; | 225 ctr[x++] = (unsigned char)L-1; |
216 | 226 |
217 /* nonce */ | 227 /* nonce */ |
218 for (y = 0; y < (16 - (L+1)); ++y) { | 228 for (y = 0; y < (16 - (L+1)); ++y) { |
219 ctr[x++] = nonce[y]; | 229 ctr[x++] = nonce[y]; |
220 } | 230 } |
221 /* offset */ | 231 /* offset */ |
242 goto error; | 252 goto error; |
243 } | 253 } |
244 | 254 |
245 /* xor the PT against the pad first */ | 255 /* xor the PT against the pad first */ |
246 for (z = 0; z < 16; z += sizeof(LTC_FAST_TYPE)) { | 256 for (z = 0; z < 16; z += sizeof(LTC_FAST_TYPE)) { |
247 *((LTC_FAST_TYPE*)(&PAD[z])) ^= *((LTC_FAST_TYPE*)(&pt[y+z])); | 257 *(LTC_FAST_TYPE_PTR_CAST(&PAD[z])) ^= *(LTC_FAST_TYPE_PTR_CAST(&pt[y+z])); |
248 *((LTC_FAST_TYPE*)(&ct[y+z])) = *((LTC_FAST_TYPE*)(&pt[y+z])) ^ *((LTC_FAST_TYPE*)(&CTRPAD[z])); | 258 *(LTC_FAST_TYPE_PTR_CAST(&ct[y+z])) = *(LTC_FAST_TYPE_PTR_CAST(&pt[y+z])) ^ *(LTC_FAST_TYPE_PTR_CAST(&CTRPAD[z])); |
249 } | 259 } |
250 if ((err = cipher_descriptor[cipher].ecb_encrypt(PAD, PAD, skey)) != CRYPT_OK) { | 260 if ((err = cipher_descriptor[cipher].ecb_encrypt(PAD, PAD, skey)) != CRYPT_OK) { |
251 goto error; | 261 goto error; |
252 } | 262 } |
253 } | 263 } |
254 } else { | 264 } else { /* direction == CCM_DECRYPT */ |
255 for (; y < (ptlen & ~15); y += 16) { | 265 for (; y < (ptlen & ~15); y += 16) { |
256 /* increment the ctr? */ | 266 /* increment the ctr? */ |
257 for (z = 15; z > 15-L; z--) { | 267 for (z = 15; z > 15-L; z--) { |
258 ctr[z] = (ctr[z] + 1) & 255; | 268 ctr[z] = (ctr[z] + 1) & 255; |
259 if (ctr[z]) break; | 269 if (ctr[z]) break; |
262 goto error; | 272 goto error; |
263 } | 273 } |
264 | 274 |
265 /* xor the PT against the pad last */ | 275 /* xor the PT against the pad last */ |
266 for (z = 0; z < 16; z += sizeof(LTC_FAST_TYPE)) { | 276 for (z = 0; z < 16; z += sizeof(LTC_FAST_TYPE)) { |
267 *((LTC_FAST_TYPE*)(&pt[y+z])) = *((LTC_FAST_TYPE*)(&ct[y+z])) ^ *((LTC_FAST_TYPE*)(&CTRPAD[z])); | 277 *(LTC_FAST_TYPE_PTR_CAST(&pt[y+z])) = *(LTC_FAST_TYPE_PTR_CAST(&ct[y+z])) ^ *(LTC_FAST_TYPE_PTR_CAST(&CTRPAD[z])); |
268 *((LTC_FAST_TYPE*)(&PAD[z])) ^= *((LTC_FAST_TYPE*)(&pt[y+z])); | 278 *(LTC_FAST_TYPE_PTR_CAST(&PAD[z])) ^= *(LTC_FAST_TYPE_PTR_CAST(&pt[y+z])); |
269 } | 279 } |
270 if ((err = cipher_descriptor[cipher].ecb_encrypt(PAD, PAD, skey)) != CRYPT_OK) { | 280 if ((err = cipher_descriptor[cipher].ecb_encrypt(PAD, PAD, skey)) != CRYPT_OK) { |
271 goto error; | 281 goto error; |
272 } | 282 } |
273 } | 283 } |
274 } | 284 } |
275 } | 285 } |
276 #endif | 286 #endif |
277 | 287 |
278 for (; y < ptlen; y++) { | 288 for (; y < ptlen; y++) { |
279 /* increment the ctr? */ | 289 /* increment the ctr? */ |
280 if (CTRlen == 16) { | 290 if (CTRlen == 16) { |
303 } | 313 } |
304 x = 0; | 314 x = 0; |
305 } | 315 } |
306 PAD[x++] ^= b; | 316 PAD[x++] ^= b; |
307 } | 317 } |
308 | 318 |
309 if (x != 0) { | 319 if (x != 0) { |
310 if ((err = cipher_descriptor[cipher].ecb_encrypt(PAD, PAD, skey)) != CRYPT_OK) { | 320 if ((err = cipher_descriptor[cipher].ecb_encrypt(PAD, PAD, skey)) != CRYPT_OK) { |
311 goto error; | 321 goto error; |
312 } | 322 } |
313 } | 323 } |
321 goto error; | 331 goto error; |
322 } | 332 } |
323 | 333 |
324 if (skey != uskey) { | 334 if (skey != uskey) { |
325 cipher_descriptor[cipher].done(skey); | 335 cipher_descriptor[cipher].done(skey); |
326 } | |
327 | |
328 /* store the TAG */ | |
329 for (x = 0; x < 16 && x < *taglen; x++) { | |
330 tag[x] = PAD[x] ^ CTRPAD[x]; | |
331 } | |
332 *taglen = x; | |
333 | |
334 #ifdef LTC_CLEAN_STACK | 336 #ifdef LTC_CLEAN_STACK |
335 zeromem(skey, sizeof(*skey)); | 337 zeromem(skey, sizeof(*skey)); |
338 #endif | |
339 } | |
340 | |
341 if (direction == CCM_ENCRYPT) { | |
342 /* store the TAG */ | |
343 for (x = 0; x < 16 && x < *taglen; x++) { | |
344 tag[x] = PAD[x] ^ CTRPAD[x]; | |
345 } | |
346 *taglen = x; | |
347 } else { /* direction == CCM_DECRYPT */ | |
348 /* decrypt the tag */ | |
349 for (x = 0; x < 16 && x < *taglen; x++) { | |
350 ptTag[x] = tag[x] ^ CTRPAD[x]; | |
351 } | |
352 *taglen = x; | |
353 | |
354 /* check validity of the decrypted tag against the computed PAD (in constant time) */ | |
355 /* HACK: the boolean value of XMEM_NEQ becomes either 0 (CRYPT_OK) or 1 (CRYPT_ERR). | |
356 * there should be a better way of setting the correct error code in constant | |
357 * time. | |
358 */ | |
359 err = XMEM_NEQ(ptTag, PAD, *taglen); | |
360 | |
361 /* Zero the plaintext if the tag was invalid (in constant time) */ | |
362 if (ptlen > 0) { | |
363 y = 0; | |
364 mask *= 1 - err; /* mask = ( err ? 0 : 0xff ) */ | |
365 #ifdef LTC_FAST | |
366 fastMask *= 1 - err; | |
367 if (ptlen & ~15) { | |
368 for (; y < (ptlen & ~15); y += 16) { | |
369 for (z = 0; z < 16; z += sizeof(LTC_FAST_TYPE)) { | |
370 *(LTC_FAST_TYPE_PTR_CAST(&pt_real[y+z])) = *(LTC_FAST_TYPE_PTR_CAST(&pt[y+z])) & fastMask; | |
371 } | |
372 } | |
373 } | |
374 #endif | |
375 for (; y < ptlen; y++) { | |
376 pt_real[y] = pt[y] & mask; | |
377 } | |
378 } | |
379 } | |
380 | |
381 #ifdef LTC_CLEAN_STACK | |
382 #ifdef LTC_FAST | |
383 fastMask = 0; | |
384 #endif | |
385 mask = 0; | |
336 zeromem(PAD, sizeof(PAD)); | 386 zeromem(PAD, sizeof(PAD)); |
337 zeromem(CTRPAD, sizeof(CTRPAD)); | 387 zeromem(CTRPAD, sizeof(CTRPAD)); |
388 if (pt_work != NULL) { | |
389 zeromem(pt_work, ptlen); | |
390 } | |
338 #endif | 391 #endif |
339 error: | 392 error: |
393 if (pt_work) { | |
394 XFREE(pt_work); | |
395 } | |
340 if (skey != uskey) { | 396 if (skey != uskey) { |
341 XFREE(skey); | 397 XFREE(skey); |
342 } | 398 } |
343 | 399 |
344 return err; | 400 return err; |
345 } | 401 } |
346 | 402 |
347 #endif | 403 #endif |
348 | 404 |
349 /* $Source$ */ | 405 /* ref: $Format:%D$ */ |
350 /* $Revision$ */ | 406 /* git commit: $Format:%H$ */ |
351 /* $Date$ */ | 407 /* commit time: $Format:%ai$ */ |