Annotation of embedaddon/strongswan/src/libstrongswan/plugins/aesni/aesni_ccm.c, revision 1.1.1.2
1.1 misho 1: /*
2: * Copyright (C) 2010-2015 Martin Willi
3: * Copyright (C) 2010-2015 revosec AG
4: *
5: * This program is free software; you can redistribute it and/or modify it
6: * under the terms of the GNU General Public License as published by the
7: * Free Software Foundation; either version 2 of the License, or (at your
8: * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
9: *
10: * This program is distributed in the hope that it will be useful, but
11: * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13: * for more details.
14: */
15:
16: #include "aesni_ccm.h"
17: #include "aesni_key.h"
18:
19: #include <crypto/iv/iv_gen_seq.h>
20:
21: #include <tmmintrin.h>
22:
23: #define SALT_SIZE 3
24: #define IV_SIZE 8
25: #define NONCE_SIZE (SALT_SIZE + IV_SIZE) /* 11 */
26: #define Q_SIZE (AES_BLOCK_SIZE - NONCE_SIZE - 1) /* 4 */
27:
28: typedef struct private_aesni_ccm_t private_aesni_ccm_t;
29:
30: /**
31: * CCM en/decryption method type
32: */
33: typedef void (*aesni_ccm_fn_t)(private_aesni_ccm_t*, size_t, u_char*, u_char*,
34: u_char*, size_t, u_char*, u_char*);
35:
36: /**
37: * Private data of an aesni_ccm_t object.
38: */
39: struct private_aesni_ccm_t {
40:
41: /**
42: * Public aesni_ccm_t interface.
43: */
44: aesni_ccm_t public;
45:
46: /**
47: * Encryption key schedule
48: */
49: aesni_key_t *key;
50:
51: /**
52: * IV generator.
53: */
54: iv_gen_t *iv_gen;
55:
56: /**
57: * Length of the integrity check value
58: */
59: size_t icv_size;
60:
61: /**
62: * Length of the key in bytes
63: */
64: size_t key_size;
65:
66: /**
67: * CCM encryption function
68: */
69: aesni_ccm_fn_t encrypt;
70:
71: /**
72: * CCM decryption function
73: */
74: aesni_ccm_fn_t decrypt;
75:
76: /**
77: * salt to add to nonce
78: */
79: u_char salt[SALT_SIZE];
80: };
81:
82: /**
83: * First block with control information
84: */
85: typedef struct __attribute__((packed)) {
86: BITFIELD4(uint8_t,
87: /* size of p length field q, as q-1 */
88: q_len: 3,
89: /* size of our ICV t, as (t-2)/2 */
90: t_len: 3,
91: /* do we have associated data */
92: assoc: 1,
93: reserved: 1,
94: ) flags;
95: /* nonce value */
96: struct __attribute__((packed)) {
97: u_char salt[SALT_SIZE];
98: u_char iv[IV_SIZE];
99: } nonce;
100: /* length of plain text, q */
101: u_char q[Q_SIZE];
102: } b0_t;
103:
104: /**
105: * Counter block
106: */
107: typedef struct __attribute__((packed)) {
108: BITFIELD3(uint8_t,
109: /* size of p length field q, as q-1 */
110: q_len: 3,
111: zero: 3,
112: reserved: 2,
113: ) flags;
114: /* nonce value */
115: struct __attribute__((packed)) {
116: u_char salt[SALT_SIZE];
117: u_char iv[IV_SIZE];
118: } nonce;
119: /* counter value */
120: u_char i[Q_SIZE];
121: } ctr_t;
122:
123: /**
124: * Build the first block B0
125: */
126: static void build_b0(private_aesni_ccm_t *this, size_t len, size_t alen,
127: u_char *iv, void *out)
128: {
129: b0_t *block = out;
130:
131: block->flags.reserved = 0;
132: block->flags.assoc = alen ? 1 : 0;
133: block->flags.t_len = (this->icv_size - 2) / 2;
134: block->flags.q_len = Q_SIZE - 1;
135: memcpy(block->nonce.salt, this->salt, SALT_SIZE);
136: memcpy(block->nonce.iv, iv, IV_SIZE);
137: htoun32(block->q, len);
138: }
139:
140: /**
141: * Build a counter block for counter i
142: */
143: static void build_ctr(private_aesni_ccm_t *this, uint32_t i, u_char *iv,
144: void *out)
145: {
146: ctr_t *ctr = out;
147:
148: ctr->flags.reserved = 0;
149: ctr->flags.zero = 0;
150: ctr->flags.q_len = Q_SIZE - 1;
151: memcpy(ctr->nonce.salt, this->salt, SALT_SIZE);
152: memcpy(ctr->nonce.iv, iv, IV_SIZE);
153: htoun32(ctr->i, i);
154: }
155:
156: /**
157: * Calculate the ICV for the b0 and associated data
158: */
159: static __m128i icv_header(private_aesni_ccm_t *this, size_t len, u_char *iv,
160: uint16_t alen, u_char *assoc)
161: {
162: __m128i *ks, b, t, c;
163: u_int i, round, blocks, rem;
164:
165: ks = this->key->schedule;
166: build_b0(this, len, alen, iv, &b);
167: c = _mm_loadu_si128(&b);
168: c = _mm_xor_si128(c, ks[0]);
169: for (round = 1; round < this->key->rounds; round++)
170: {
171: c = _mm_aesenc_si128(c, ks[round]);
172: }
173: c = _mm_aesenclast_si128(c, ks[this->key->rounds]);
174:
175: if (alen)
176: {
177: blocks = (alen + sizeof(alen)) / AES_BLOCK_SIZE;
178: rem = (alen + sizeof(alen)) % AES_BLOCK_SIZE;
179: if (rem)
180: {
181: blocks++;
182: }
183: for (i = 0; i < blocks; i++)
184: {
185: if (i == 0)
186: { /* first block */
187: memset(&b, 0, sizeof(b));
188: htoun16(&b, alen);
189: memcpy(((u_char*)&b) + sizeof(alen), assoc,
190: min(alen, sizeof(b) - sizeof(alen)));
191: t = _mm_loadu_si128(&b);
192: }
193: else if (i == blocks - 1 && rem)
194: { /* last block with padding */
195: memset(&b, 0, sizeof(b));
196: memcpy(&b, ((__m128i*)(assoc - sizeof(alen))) + i, rem);
197: t = _mm_loadu_si128(&b);
198: }
199: else
200: { /* full block */
201: t = _mm_loadu_si128(((__m128i*)(assoc - sizeof(alen))) + i);
202: }
203: c = _mm_xor_si128(t, c);
204: c = _mm_xor_si128(c, ks[0]);
205: for (round = 1; round < this->key->rounds; round++)
206: {
207: c = _mm_aesenc_si128(c, ks[round]);
208: }
209: c = _mm_aesenclast_si128(c, ks[this->key->rounds]);
210: }
211: }
212: return c;
213: }
214:
215: /**
216: * En-/Decrypt the ICV, trim and store it
217: */
218: static void crypt_icv(private_aesni_ccm_t *this, u_char *iv,
219: __m128i c, u_char *icv)
220: {
221: __m128i *ks, b, t;
222: u_int round;
223:
224: ks = this->key->schedule;
225: build_ctr(this, 0, iv, &b);
226:
227: t = _mm_loadu_si128(&b);
228: t = _mm_xor_si128(t, ks[0]);
229: for (round = 1; round < this->key->rounds; round++)
230: {
231: t = _mm_aesenc_si128(t, ks[round]);
232: }
233: t = _mm_aesenclast_si128(t, ks[this->key->rounds]);
234:
235: t = _mm_xor_si128(t, c);
236:
237: _mm_storeu_si128(&b, t);
238: memcpy(icv, &b, this->icv_size);
239: }
240:
241: /**
242: * Do big-endian increment on x
243: */
244: static inline __m128i increment_be(__m128i x)
245: {
246: __m128i swap;
247:
248: swap = _mm_set_epi8(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15);
249:
250: x = _mm_shuffle_epi8(x, swap);
251: x = _mm_add_epi64(x, _mm_set_epi32(0, 0, 0, 1));
252: x = _mm_shuffle_epi8(x, swap);
253:
254: return x;
255: }
256:
257: /**
258: * Encrypt a remaining incomplete block
259: */
260: static __m128i encrypt_ccm_rem(aesni_key_t *key, u_int rem, __m128i state,
261: void *in, void *out, __m128i c)
262: {
263: __m128i *ks, t, b, d;
264: u_int round;
265:
266: ks = key->schedule;
267: memset(&b, 0, sizeof(b));
268: memcpy(&b, in, rem);
269: d = _mm_loadu_si128(&b);
270:
271: c = _mm_xor_si128(d, c);
272: c = _mm_xor_si128(c, ks[0]);
273: t = _mm_xor_si128(state, ks[0]);
274: for (round = 1; round < key->rounds; round++)
275: {
276: c = _mm_aesenc_si128(c, ks[round]);
277: t = _mm_aesenc_si128(t, ks[round]);
278: }
279: c = _mm_aesenclast_si128(c, ks[key->rounds]);
280: t = _mm_aesenclast_si128(t, ks[key->rounds]);
281:
282: t = _mm_xor_si128(t, d);
283: _mm_storeu_si128(&b, t);
284:
285: memcpy(out, &b, rem);
286:
287: return c;
288: }
289:
290: /**
291: * Decrypt a remaining incomplete block
292: */
293: static __m128i decrypt_ccm_rem(aesni_key_t *key, u_int rem, __m128i state,
294: void *in, void *out, __m128i c)
295: {
296: __m128i *ks, t, b, d;
297: u_int round;
298:
299: ks = key->schedule;
300: memset(&b, 0, sizeof(b));
301: memcpy(&b, in, rem);
302: d = _mm_loadu_si128(&b);
303:
304: t = _mm_xor_si128(state, ks[0]);
305: for (round = 1; round < key->rounds; round++)
306: {
307: t = _mm_aesenc_si128(t, ks[round]);
308: }
309: t = _mm_aesenclast_si128(t, ks[key->rounds]);
310: t = _mm_xor_si128(t, d);
311: _mm_storeu_si128(&b, t);
312:
313: memset((u_char*)&b + rem, 0, sizeof(b) - rem);
314: t = _mm_loadu_si128(&b);
315: c = _mm_xor_si128(t, c);
316: c = _mm_xor_si128(c, ks[0]);
317: for (round = 1; round < key->rounds; round++)
318: {
319: c = _mm_aesenc_si128(c, ks[round]);
320: }
321: c = _mm_aesenclast_si128(c, ks[key->rounds]);
322:
323: memcpy(out, &b, rem);
324:
325: return c;
326: }
327:
328: /**
329: * AES-128 CCM encryption/ICV generation
330: */
331: static void encrypt_ccm128(private_aesni_ccm_t *this,
332: size_t len, u_char *in, u_char *out, u_char *iv,
333: size_t alen, u_char *assoc, u_char *icv)
334: {
335: __m128i *ks, d, t, c, b, state, *bi, *bo;
336: u_int blocks, rem, i;
337:
338: c = icv_header(this, len, iv, alen, assoc);
339: build_ctr(this, 1, iv, &b);
340: state = _mm_load_si128(&b);
341: blocks = len / AES_BLOCK_SIZE;
342: rem = len % AES_BLOCK_SIZE;
343: bi = (__m128i*)in;
344: bo = (__m128i*)out;
345:
346: ks = this->key->schedule;
347:
348: for (i = 0; i < blocks; i++)
349: {
350: d = _mm_loadu_si128(bi + i);
351:
352: c = _mm_xor_si128(d, c);
353: c = _mm_xor_si128(c, ks[0]);
354: t = _mm_xor_si128(state, ks[0]);
355:
356: c = _mm_aesenc_si128(c, ks[1]);
357: t = _mm_aesenc_si128(t, ks[1]);
358: c = _mm_aesenc_si128(c, ks[2]);
359: t = _mm_aesenc_si128(t, ks[2]);
360: c = _mm_aesenc_si128(c, ks[3]);
361: t = _mm_aesenc_si128(t, ks[3]);
362: c = _mm_aesenc_si128(c, ks[4]);
363: t = _mm_aesenc_si128(t, ks[4]);
364: c = _mm_aesenc_si128(c, ks[5]);
365: t = _mm_aesenc_si128(t, ks[5]);
366: c = _mm_aesenc_si128(c, ks[6]);
367: t = _mm_aesenc_si128(t, ks[6]);
368: c = _mm_aesenc_si128(c, ks[7]);
369: t = _mm_aesenc_si128(t, ks[7]);
370: c = _mm_aesenc_si128(c, ks[8]);
371: t = _mm_aesenc_si128(t, ks[8]);
372: c = _mm_aesenc_si128(c, ks[9]);
373: t = _mm_aesenc_si128(t, ks[9]);
374:
375: c = _mm_aesenclast_si128(c, ks[10]);
376: t = _mm_aesenclast_si128(t, ks[10]);
377:
378: t = _mm_xor_si128(t, d);
379: _mm_storeu_si128(bo + i, t);
380:
381: state = increment_be(state);
382: }
383:
384: if (rem)
385: {
386: c = encrypt_ccm_rem(this->key, rem, state, bi + blocks, bo + blocks, c);
387: }
388: crypt_icv(this, iv, c, icv);
389: }
390:
391: /**
392: * AES-128 CCM decryption/ICV generation
393: */
394: static void decrypt_ccm128(private_aesni_ccm_t *this,
395: size_t len, u_char *in, u_char *out, u_char *iv,
396: size_t alen, u_char *assoc, u_char *icv)
397: {
398: __m128i *ks, d, t, c, b, state, *bi, *bo;
399: u_int blocks, rem, i;
400:
401: c = icv_header(this, len, iv, alen, assoc);
402: build_ctr(this, 1, iv, &b);
403: state = _mm_load_si128(&b);
404: blocks = len / AES_BLOCK_SIZE;
405: rem = len % AES_BLOCK_SIZE;
406: bi = (__m128i*)in;
407: bo = (__m128i*)out;
408:
409: ks = this->key->schedule;
410:
411: for (i = 0; i < blocks; i++)
412: {
413: d = _mm_loadu_si128(bi + i);
414:
415: t = _mm_xor_si128(state, ks[0]);
416:
417: t = _mm_aesenc_si128(t, ks[1]);
418: t = _mm_aesenc_si128(t, ks[2]);
419: t = _mm_aesenc_si128(t, ks[3]);
420: t = _mm_aesenc_si128(t, ks[4]);
421: t = _mm_aesenc_si128(t, ks[5]);
422: t = _mm_aesenc_si128(t, ks[6]);
423: t = _mm_aesenc_si128(t, ks[7]);
424: t = _mm_aesenc_si128(t, ks[8]);
425: t = _mm_aesenc_si128(t, ks[9]);
426:
427: t = _mm_aesenclast_si128(t, ks[10]);
428: t = _mm_xor_si128(t, d);
429: _mm_storeu_si128(bo + i, t);
430:
431: c = _mm_xor_si128(t, c);
432: c = _mm_xor_si128(c, ks[0]);
433:
434: c = _mm_aesenc_si128(c, ks[1]);
435: c = _mm_aesenc_si128(c, ks[2]);
436: c = _mm_aesenc_si128(c, ks[3]);
437: c = _mm_aesenc_si128(c, ks[4]);
438: c = _mm_aesenc_si128(c, ks[5]);
439: c = _mm_aesenc_si128(c, ks[6]);
440: c = _mm_aesenc_si128(c, ks[7]);
441: c = _mm_aesenc_si128(c, ks[8]);
442: c = _mm_aesenc_si128(c, ks[9]);
443:
444: c = _mm_aesenclast_si128(c, ks[10]);
445:
446: state = increment_be(state);
447: }
448:
449: if (rem)
450: {
451: c = decrypt_ccm_rem(this->key, rem, state, bi + blocks, bo + blocks, c);
452: }
453: crypt_icv(this, iv, c, icv);
454: }
455:
456: /**
457: * AES-192 CCM encryption/ICV generation
458: */
459: static void encrypt_ccm192(private_aesni_ccm_t *this,
460: size_t len, u_char *in, u_char *out, u_char *iv,
461: size_t alen, u_char *assoc, u_char *icv)
462: {
463: __m128i *ks, d, t, c, b, state, *bi, *bo;
464: u_int blocks, rem, i;
465:
466: c = icv_header(this, len, iv, alen, assoc);
467: build_ctr(this, 1, iv, &b);
468: state = _mm_load_si128(&b);
469: blocks = len / AES_BLOCK_SIZE;
470: rem = len % AES_BLOCK_SIZE;
471: bi = (__m128i*)in;
472: bo = (__m128i*)out;
473:
474: ks = this->key->schedule;
475:
476: for (i = 0; i < blocks; i++)
477: {
478: d = _mm_loadu_si128(bi + i);
479:
480: c = _mm_xor_si128(d, c);
481: c = _mm_xor_si128(c, ks[0]);
482: t = _mm_xor_si128(state, ks[0]);
483:
484: c = _mm_aesenc_si128(c, ks[1]);
485: t = _mm_aesenc_si128(t, ks[1]);
486: c = _mm_aesenc_si128(c, ks[2]);
487: t = _mm_aesenc_si128(t, ks[2]);
488: c = _mm_aesenc_si128(c, ks[3]);
489: t = _mm_aesenc_si128(t, ks[3]);
490: c = _mm_aesenc_si128(c, ks[4]);
491: t = _mm_aesenc_si128(t, ks[4]);
492: c = _mm_aesenc_si128(c, ks[5]);
493: t = _mm_aesenc_si128(t, ks[5]);
494: c = _mm_aesenc_si128(c, ks[6]);
495: t = _mm_aesenc_si128(t, ks[6]);
496: c = _mm_aesenc_si128(c, ks[7]);
497: t = _mm_aesenc_si128(t, ks[7]);
498: c = _mm_aesenc_si128(c, ks[8]);
499: t = _mm_aesenc_si128(t, ks[8]);
500: c = _mm_aesenc_si128(c, ks[9]);
501: t = _mm_aesenc_si128(t, ks[9]);
502: c = _mm_aesenc_si128(c, ks[10]);
503: t = _mm_aesenc_si128(t, ks[10]);
504: c = _mm_aesenc_si128(c, ks[11]);
505: t = _mm_aesenc_si128(t, ks[11]);
506:
507: c = _mm_aesenclast_si128(c, ks[12]);
508: t = _mm_aesenclast_si128(t, ks[12]);
509:
510: t = _mm_xor_si128(t, d);
511: _mm_storeu_si128(bo + i, t);
512:
513: state = increment_be(state);
514: }
515:
516: if (rem)
517: {
518: c = encrypt_ccm_rem(this->key, rem, state, bi + blocks, bo + blocks, c);
519: }
520: crypt_icv(this, iv, c, icv);
521: }
522:
523: /**
524: * AES-192 CCM decryption/ICV generation
525: */
526: static void decrypt_ccm192(private_aesni_ccm_t *this,
527: size_t len, u_char *in, u_char *out, u_char *iv,
528: size_t alen, u_char *assoc, u_char *icv)
529: {
530: __m128i *ks, d, t, c, b, state, *bi, *bo;
531: u_int blocks, rem, i;
532:
533: c = icv_header(this, len, iv, alen, assoc);
534: build_ctr(this, 1, iv, &b);
535: state = _mm_load_si128(&b);
536: blocks = len / AES_BLOCK_SIZE;
537: rem = len % AES_BLOCK_SIZE;
538: bi = (__m128i*)in;
539: bo = (__m128i*)out;
540:
541: ks = this->key->schedule;
542:
543: for (i = 0; i < blocks; i++)
544: {
545: d = _mm_loadu_si128(bi + i);
546:
547: t = _mm_xor_si128(state, ks[0]);
548:
549: t = _mm_aesenc_si128(t, ks[1]);
550: t = _mm_aesenc_si128(t, ks[2]);
551: t = _mm_aesenc_si128(t, ks[3]);
552: t = _mm_aesenc_si128(t, ks[4]);
553: t = _mm_aesenc_si128(t, ks[5]);
554: t = _mm_aesenc_si128(t, ks[6]);
555: t = _mm_aesenc_si128(t, ks[7]);
556: t = _mm_aesenc_si128(t, ks[8]);
557: t = _mm_aesenc_si128(t, ks[9]);
558: t = _mm_aesenc_si128(t, ks[10]);
559: t = _mm_aesenc_si128(t, ks[11]);
560:
561: t = _mm_aesenclast_si128(t, ks[12]);
562: t = _mm_xor_si128(t, d);
563: _mm_storeu_si128(bo + i, t);
564:
565: c = _mm_xor_si128(t, c);
566: c = _mm_xor_si128(c, ks[0]);
567:
568: c = _mm_aesenc_si128(c, ks[1]);
569: c = _mm_aesenc_si128(c, ks[2]);
570: c = _mm_aesenc_si128(c, ks[3]);
571: c = _mm_aesenc_si128(c, ks[4]);
572: c = _mm_aesenc_si128(c, ks[5]);
573: c = _mm_aesenc_si128(c, ks[6]);
574: c = _mm_aesenc_si128(c, ks[7]);
575: c = _mm_aesenc_si128(c, ks[8]);
576: c = _mm_aesenc_si128(c, ks[9]);
577: c = _mm_aesenc_si128(c, ks[10]);
578: c = _mm_aesenc_si128(c, ks[11]);
579:
580: c = _mm_aesenclast_si128(c, ks[12]);
581:
582: state = increment_be(state);
583: }
584:
585: if (rem)
586: {
587: c = decrypt_ccm_rem(this->key, rem, state, bi + blocks, bo + blocks, c);
588: }
589: crypt_icv(this, iv, c, icv);
590: }
591:
592: /**
593: * AES-256 CCM encryption/ICV generation
594: */
595: static void encrypt_ccm256(private_aesni_ccm_t *this,
596: size_t len, u_char *in, u_char *out, u_char *iv,
597: size_t alen, u_char *assoc, u_char *icv)
598: {
599: __m128i *ks, d, t, c, b, state, *bi, *bo;
600: u_int blocks, rem, i;
601:
602: c = icv_header(this, len, iv, alen, assoc);
603: build_ctr(this, 1, iv, &b);
604: state = _mm_load_si128(&b);
605: blocks = len / AES_BLOCK_SIZE;
606: rem = len % AES_BLOCK_SIZE;
607: bi = (__m128i*)in;
608: bo = (__m128i*)out;
609:
610: ks = this->key->schedule;
611:
612: for (i = 0; i < blocks; i++)
613: {
614: d = _mm_loadu_si128(bi + i);
615:
616: c = _mm_xor_si128(d, c);
617: c = _mm_xor_si128(c, ks[0]);
618: t = _mm_xor_si128(state, ks[0]);
619:
620: c = _mm_aesenc_si128(c, ks[1]);
621: t = _mm_aesenc_si128(t, ks[1]);
622: c = _mm_aesenc_si128(c, ks[2]);
623: t = _mm_aesenc_si128(t, ks[2]);
624: c = _mm_aesenc_si128(c, ks[3]);
625: t = _mm_aesenc_si128(t, ks[3]);
626: c = _mm_aesenc_si128(c, ks[4]);
627: t = _mm_aesenc_si128(t, ks[4]);
628: c = _mm_aesenc_si128(c, ks[5]);
629: t = _mm_aesenc_si128(t, ks[5]);
630: c = _mm_aesenc_si128(c, ks[6]);
631: t = _mm_aesenc_si128(t, ks[6]);
632: c = _mm_aesenc_si128(c, ks[7]);
633: t = _mm_aesenc_si128(t, ks[7]);
634: c = _mm_aesenc_si128(c, ks[8]);
635: t = _mm_aesenc_si128(t, ks[8]);
636: c = _mm_aesenc_si128(c, ks[9]);
637: t = _mm_aesenc_si128(t, ks[9]);
638: c = _mm_aesenc_si128(c, ks[10]);
639: t = _mm_aesenc_si128(t, ks[10]);
640: c = _mm_aesenc_si128(c, ks[11]);
641: t = _mm_aesenc_si128(t, ks[11]);
642: c = _mm_aesenc_si128(c, ks[12]);
643: t = _mm_aesenc_si128(t, ks[12]);
644: c = _mm_aesenc_si128(c, ks[13]);
645: t = _mm_aesenc_si128(t, ks[13]);
646:
647: c = _mm_aesenclast_si128(c, ks[14]);
648: t = _mm_aesenclast_si128(t, ks[14]);
649:
650: t = _mm_xor_si128(t, d);
651: _mm_storeu_si128(bo + i, t);
652:
653: state = increment_be(state);
654: }
655:
656: if (rem)
657: {
658: c = encrypt_ccm_rem(this->key, rem, state, bi + blocks, bo + blocks, c);
659: }
660: crypt_icv(this, iv, c, icv);
661: }
662:
663: /**
664: * AES-256 CCM decryption/ICV generation
665: */
666: static void decrypt_ccm256(private_aesni_ccm_t *this,
667: size_t len, u_char *in, u_char *out, u_char *iv,
668: size_t alen, u_char *assoc, u_char *icv)
669: {
670: __m128i *ks, d, t, c, b, state, *bi, *bo;
671: u_int blocks, rem, i;
672:
673: c = icv_header(this, len, iv, alen, assoc);
674: build_ctr(this, 1, iv, &b);
675: state = _mm_load_si128(&b);
676: blocks = len / AES_BLOCK_SIZE;
677: rem = len % AES_BLOCK_SIZE;
678: bi = (__m128i*)in;
679: bo = (__m128i*)out;
680:
681: ks = this->key->schedule;
682:
683: for (i = 0; i < blocks; i++)
684: {
685: d = _mm_loadu_si128(bi + i);
686:
687: t = _mm_xor_si128(state, ks[0]);
688:
689: t = _mm_aesenc_si128(t, ks[1]);
690: t = _mm_aesenc_si128(t, ks[2]);
691: t = _mm_aesenc_si128(t, ks[3]);
692: t = _mm_aesenc_si128(t, ks[4]);
693: t = _mm_aesenc_si128(t, ks[5]);
694: t = _mm_aesenc_si128(t, ks[6]);
695: t = _mm_aesenc_si128(t, ks[7]);
696: t = _mm_aesenc_si128(t, ks[8]);
697: t = _mm_aesenc_si128(t, ks[9]);
698: t = _mm_aesenc_si128(t, ks[10]);
699: t = _mm_aesenc_si128(t, ks[11]);
700: t = _mm_aesenc_si128(t, ks[12]);
701: t = _mm_aesenc_si128(t, ks[13]);
702:
703: t = _mm_aesenclast_si128(t, ks[14]);
704: t = _mm_xor_si128(t, d);
705: _mm_storeu_si128(bo + i, t);
706:
707: c = _mm_xor_si128(t, c);
708: c = _mm_xor_si128(c, ks[0]);
709:
710: c = _mm_aesenc_si128(c, ks[1]);
711: c = _mm_aesenc_si128(c, ks[2]);
712: c = _mm_aesenc_si128(c, ks[3]);
713: c = _mm_aesenc_si128(c, ks[4]);
714: c = _mm_aesenc_si128(c, ks[5]);
715: c = _mm_aesenc_si128(c, ks[6]);
716: c = _mm_aesenc_si128(c, ks[7]);
717: c = _mm_aesenc_si128(c, ks[8]);
718: c = _mm_aesenc_si128(c, ks[9]);
719: c = _mm_aesenc_si128(c, ks[10]);
720: c = _mm_aesenc_si128(c, ks[11]);
721: c = _mm_aesenc_si128(c, ks[12]);
722: c = _mm_aesenc_si128(c, ks[13]);
723:
724: c = _mm_aesenclast_si128(c, ks[14]);
725:
726: state = increment_be(state);
727: }
728:
729: if (rem)
730: {
731: c = decrypt_ccm_rem(this->key, rem, state, bi + blocks, bo + blocks, c);
732: }
733: crypt_icv(this, iv, c, icv);
734: }
735:
736: METHOD(aead_t, encrypt, bool,
737: private_aesni_ccm_t *this, chunk_t plain, chunk_t assoc, chunk_t iv,
738: chunk_t *encr)
739: {
740: u_char *out;
741:
742: if (!this->key || iv.len != IV_SIZE)
743: {
744: return FALSE;
745: }
746: out = plain.ptr;
747: if (encr)
748: {
749: *encr = chunk_alloc(plain.len + this->icv_size);
750: out = encr->ptr;
751: }
752: this->encrypt(this, plain.len, plain.ptr, out, iv.ptr,
753: assoc.len, assoc.ptr, out + plain.len);
754: return TRUE;
755: }
756:
757: METHOD(aead_t, decrypt, bool,
758: private_aesni_ccm_t *this, chunk_t encr, chunk_t assoc, chunk_t iv,
759: chunk_t *plain)
760: {
761: u_char *out, icv[this->icv_size];
762:
763: if (!this->key || iv.len != IV_SIZE || encr.len < this->icv_size)
764: {
765: return FALSE;
766: }
767: encr.len -= this->icv_size;
768: out = encr.ptr;
769: if (plain)
770: {
771: *plain = chunk_alloc(encr.len);
772: out = plain->ptr;
773: }
774:
775: this->decrypt(this, encr.len, encr.ptr, out, iv.ptr,
776: assoc.len, assoc.ptr, icv);
777: return memeq_const(icv, encr.ptr + encr.len, this->icv_size);
778: }
779:
780: METHOD(aead_t, get_block_size, size_t,
781: private_aesni_ccm_t *this)
782: {
783: return 1;
784: }
785:
786: METHOD(aead_t, get_icv_size, size_t,
787: private_aesni_ccm_t *this)
788: {
789: return this->icv_size;
790: }
791:
792: METHOD(aead_t, get_iv_size, size_t,
793: private_aesni_ccm_t *this)
794: {
795: return IV_SIZE;
796: }
797:
798: METHOD(aead_t, get_iv_gen, iv_gen_t*,
799: private_aesni_ccm_t *this)
800: {
801: return this->iv_gen;
802: }
803:
804: METHOD(aead_t, get_key_size, size_t,
805: private_aesni_ccm_t *this)
806: {
807: return this->key_size + SALT_SIZE;
808: }
809:
810: METHOD(aead_t, set_key, bool,
811: private_aesni_ccm_t *this, chunk_t key)
812: {
813: if (key.len != this->key_size + SALT_SIZE)
814: {
815: return FALSE;
816: }
817:
818: memcpy(this->salt, key.ptr + key.len - SALT_SIZE, SALT_SIZE);
819: key.len -= SALT_SIZE;
820:
821: DESTROY_IF(this->key);
822: this->key = aesni_key_create(TRUE, key);
823: return TRUE;
824: }
825:
826: METHOD(aead_t, destroy, void,
827: private_aesni_ccm_t *this)
828: {
829: DESTROY_IF(this->key);
830: this->iv_gen->destroy(this->iv_gen);
831: free_align(this);
832: }
833:
834: /**
835: * See header
836: */
837: aesni_ccm_t *aesni_ccm_create(encryption_algorithm_t algo,
838: size_t key_size, size_t salt_size)
839: {
840: private_aesni_ccm_t *this;
841: size_t icv_size;
842:
843: switch (key_size)
844: {
845: case 0:
846: key_size = 16;
847: break;
848: case 16:
849: case 24:
850: case 32:
851: break;
852: default:
853: return NULL;
854: }
855: if (salt_size && salt_size != SALT_SIZE)
856: {
857: /* currently not supported */
858: return NULL;
859: }
860: switch (algo)
861: {
862: case ENCR_AES_CCM_ICV8:
863: icv_size = 8;
864: break;
865: case ENCR_AES_CCM_ICV12:
866: icv_size = 12;
867: break;
868: case ENCR_AES_CCM_ICV16:
869: icv_size = 16;
870: break;
871: default:
872: return NULL;
873: }
874:
875: INIT_ALIGN(this, sizeof(__m128i),
876: .public = {
877: .aead = {
878: .encrypt = _encrypt,
879: .decrypt = _decrypt,
880: .get_block_size = _get_block_size,
881: .get_icv_size = _get_icv_size,
882: .get_iv_size = _get_iv_size,
883: .get_iv_gen = _get_iv_gen,
884: .get_key_size = _get_key_size,
885: .set_key = _set_key,
886: .destroy = _destroy,
887: },
888: },
889: .key_size = key_size,
890: .iv_gen = iv_gen_seq_create(),
891: .icv_size = icv_size,
892: );
893:
894: switch (key_size)
895: {
896: case 16:
897: this->encrypt = encrypt_ccm128;
898: this->decrypt = decrypt_ccm128;
899: break;
900: case 24:
901: this->encrypt = encrypt_ccm192;
902: this->decrypt = decrypt_ccm192;
903: break;
904: case 32:
905: this->encrypt = encrypt_ccm256;
906: this->decrypt = decrypt_ccm256;
907: break;
908: }
909:
910: return &this->public;
911: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>