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$ */