Annotation of embedaddon/strongswan/src/libstrongswan/plugins/aesni/aesni_ccm.c, revision 1.1.1.1

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: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>