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