Return to aesni_ccm.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / strongswan / src / libstrongswan / plugins / aesni |
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: algo = ENCR_AES_CBC; 864: icv_size = 8; 865: break; 866: case ENCR_AES_CCM_ICV12: 867: algo = ENCR_AES_CBC; 868: icv_size = 12; 869: break; 870: case ENCR_AES_CCM_ICV16: 871: algo = ENCR_AES_CBC; 872: icv_size = 16; 873: break; 874: default: 875: return NULL; 876: } 877: 878: INIT_ALIGN(this, sizeof(__m128i), 879: .public = { 880: .aead = { 881: .encrypt = _encrypt, 882: .decrypt = _decrypt, 883: .get_block_size = _get_block_size, 884: .get_icv_size = _get_icv_size, 885: .get_iv_size = _get_iv_size, 886: .get_iv_gen = _get_iv_gen, 887: .get_key_size = _get_key_size, 888: .set_key = _set_key, 889: .destroy = _destroy, 890: }, 891: }, 892: .key_size = key_size, 893: .iv_gen = iv_gen_seq_create(), 894: .icv_size = icv_size, 895: ); 896: 897: switch (key_size) 898: { 899: case 16: 900: this->encrypt = encrypt_ccm128; 901: this->decrypt = decrypt_ccm128; 902: break; 903: case 24: 904: this->encrypt = encrypt_ccm192; 905: this->decrypt = decrypt_ccm192; 906: break; 907: case 32: 908: this->encrypt = encrypt_ccm256; 909: this->decrypt = decrypt_ccm256; 910: break; 911: } 912: 913: return &this->public; 914: }