Annotation of embedaddon/strongswan/src/libstrongswan/plugins/ccm/ccm_aead.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:  * Copyright (C) 2010 Martin Willi
                      3:  * Copyright (C) 2010 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 "ccm_aead.h"
                     17: 
                     18: #include <crypto/iv/iv_gen_seq.h>
                     19: 
                     20: #define BLOCK_SIZE 16
                     21: #define SALT_SIZE 3
                     22: #define IV_SIZE 8
                     23: #define NONCE_SIZE (SALT_SIZE + IV_SIZE) /* 11 */
                     24: #define Q_SIZE (BLOCK_SIZE - NONCE_SIZE - 1) /* 4 */
                     25: 
                     26: typedef struct private_ccm_aead_t private_ccm_aead_t;
                     27: 
                     28: /**
                     29:  * Private data of an ccm_aead_t object.
                     30:  */
                     31: struct private_ccm_aead_t {
                     32: 
                     33:        /**
                     34:         * Public ccm_aead_t interface.
                     35:         */
                     36:        ccm_aead_t public;
                     37: 
                     38:        /**
                     39:         * Underlying CBC crypter.
                     40:         */
                     41:        crypter_t *crypter;
                     42: 
                     43:        /**
                     44:         * IV generator.
                     45:         */
                     46:        iv_gen_t *iv_gen;
                     47: 
                     48:        /**
                     49:         * Length of the integrity check value
                     50:         */
                     51:        size_t icv_size;
                     52: 
                     53:        /**
                     54:         * salt to add to nonce
                     55:         */
                     56:        u_char salt[SALT_SIZE];
                     57: };
                     58: 
                     59: /**
                     60:  * First block with control information
                     61:  */
                     62: typedef struct __attribute__((packed)) {
                     63:        BITFIELD4(uint8_t,
                     64:                /* size of p length field q, as q-1 */
                     65:                q_len: 3,
                     66:                /* size of our ICV t, as (t-2)/2 */
                     67:                t_len: 3,
                     68:                /* do we have associated data */
                     69:                assoc: 1,
                     70:                reserved: 1,
                     71:        ) flags;
                     72:        /* nonce value */
                     73:        struct __attribute__((packed)) {
                     74:                u_char salt[SALT_SIZE];
                     75:                u_char iv[IV_SIZE];
                     76:        } nonce;
                     77:        /* length of plain text, q */
                     78:        u_char q[Q_SIZE];
                     79: } b0_t;
                     80: 
                     81: /**
                     82:  * Counter block
                     83:  */
                     84: typedef struct __attribute__((packed)) {
                     85:        BITFIELD3(uint8_t,
                     86:                /* size of p length field q, as q-1 */
                     87:                q_len: 3,
                     88:                zero: 3,
                     89:                reserved: 2,
                     90:        ) flags;
                     91:        /* nonce value */
                     92:        struct __attribute__((packed)) {
                     93:                u_char salt[SALT_SIZE];
                     94:                u_char iv[IV_SIZE];
                     95:        } nonce;
                     96:        /* counter value */
                     97:        u_char i[Q_SIZE];
                     98: } ctr_t;
                     99: 
                    100: /**
                    101:  * Build the first block B0
                    102:  */
                    103: static void build_b0(private_ccm_aead_t *this, chunk_t plain, chunk_t assoc,
                    104:                                         chunk_t iv, char *out)
                    105: {
                    106:        b0_t *block = (b0_t*)out;
                    107: 
                    108:        block->flags.reserved = 0;
                    109:        block->flags.assoc = assoc.len ? 1 : 0;
                    110:        block->flags.t_len = (this->icv_size - 2) / 2;
                    111:        block->flags.q_len = Q_SIZE - 1;
                    112:        memcpy(block->nonce.salt, this->salt, SALT_SIZE);
                    113:        memcpy(block->nonce.iv, iv.ptr, IV_SIZE);
                    114:        htoun32(block->q, plain.len);
                    115: }
                    116: 
                    117: /**
                    118:  * Build a counter block for counter i
                    119:  */
                    120: static void build_ctr(private_ccm_aead_t *this, uint32_t i, chunk_t iv,
                    121:                                          char *out)
                    122: {
                    123:        ctr_t *ctr = (ctr_t*)out;
                    124: 
                    125:        ctr->flags.reserved = 0;
                    126:        ctr->flags.zero = 0;
                    127:        ctr->flags.q_len = Q_SIZE - 1;
                    128:        memcpy(ctr->nonce.salt, this->salt, SALT_SIZE);
                    129:        memcpy(ctr->nonce.iv, iv.ptr, IV_SIZE);
                    130:        htoun32(ctr->i, i);
                    131: }
                    132: 
                    133: /**
                    134:  * En-/Decrypt data
                    135:  */
                    136: static bool crypt_data(private_ccm_aead_t *this, chunk_t iv,
                    137:                                           chunk_t in, chunk_t out)
                    138: {
                    139:        char ctr[BLOCK_SIZE];
                    140:        char zero[BLOCK_SIZE];
                    141:        char block[BLOCK_SIZE];
                    142: 
                    143:        build_ctr(this, 1, iv, ctr);
                    144:        memset(zero, 0, BLOCK_SIZE);
                    145: 
                    146:        while (in.len > 0)
                    147:        {
                    148:                memcpy(block, ctr, BLOCK_SIZE);
                    149:                if (!this->crypter->encrypt(this->crypter, chunk_from_thing(block),
                    150:                                                                        chunk_from_thing(zero), NULL))
                    151:                {
                    152:                        return FALSE;
                    153:                }
                    154:                chunk_increment(chunk_from_thing(ctr));
                    155: 
                    156:                if (in.ptr != out.ptr)
                    157:                {
                    158:                        memcpy(out.ptr, in.ptr, min(in.len, BLOCK_SIZE));
                    159:                }
                    160:                memxor(out.ptr, block, min(in.len, BLOCK_SIZE));
                    161:                in = chunk_skip(in, BLOCK_SIZE);
                    162:                out = chunk_skip(out, BLOCK_SIZE);
                    163:        }
                    164:        return TRUE;
                    165: }
                    166: 
                    167: /**
                    168:  * En-/Decrypt the ICV
                    169:  */
                    170: static bool crypt_icv(private_ccm_aead_t *this, chunk_t iv, char *icv)
                    171: {
                    172:        char ctr[BLOCK_SIZE];
                    173:        char zero[BLOCK_SIZE];
                    174: 
                    175:        build_ctr(this, 0, iv, ctr);
                    176:        memset(zero, 0, BLOCK_SIZE);
                    177: 
                    178:        if (!this->crypter->encrypt(this->crypter, chunk_from_thing(ctr),
                    179:                                                                chunk_from_thing(zero), NULL))
                    180:        {
                    181:                return FALSE;
                    182:        }
                    183:        memxor(icv, ctr, this->icv_size);
                    184:        return TRUE;
                    185: }
                    186: 
                    187: /**
                    188:  * Create the ICV
                    189:  */
                    190: static bool create_icv(private_ccm_aead_t *this, chunk_t plain, chunk_t assoc,
                    191:                                           chunk_t iv, char *icv)
                    192: {
                    193:        char zero[BLOCK_SIZE];
                    194:        chunk_t chunk;
                    195:        char *pos;
                    196:        int r, len;
                    197: 
                    198:        memset(zero, 0, BLOCK_SIZE);
                    199: 
                    200:        /* calculate number of blocks, including b0 */
                    201:        r = 1;
                    202:        if (assoc.len)
                    203:        {       /* assoc gets a 2 byte length header, gets padded to BLOCK_SIZE */
                    204:                r += (2 + assoc.len + BLOCK_SIZE - 1) / BLOCK_SIZE;
                    205:        }
                    206:        /* plain text gets padded to BLOCK_SIZE */
                    207:        r += (plain.len + BLOCK_SIZE - 1) / BLOCK_SIZE;
                    208: 
                    209:        /* concatenate data to a new chunk */
                    210:        chunk = chunk_alloc(r * BLOCK_SIZE);
                    211:        /* write control block */
                    212:        build_b0(this, plain, assoc, iv, chunk.ptr);
                    213:        pos = chunk.ptr + BLOCK_SIZE;
                    214:        /* append associated data, with length header */
                    215:        if (assoc.len)
                    216:        {
                    217:                /* currently we support two byte headers only (up to 2^16-2^8 bytes) */
                    218:                htoun16(pos, assoc.len);
                    219:                memcpy(pos + 2, assoc.ptr, assoc.len);
                    220:                pos += 2 + assoc.len;
                    221:                /* padding */
                    222:                len = (BLOCK_SIZE - ((2 + assoc.len) % BLOCK_SIZE)) % BLOCK_SIZE;
                    223:                memset(pos, 0, len);
                    224:                pos += len;
                    225:        }
                    226:        /* write plain data */
                    227:        memcpy(pos, plain.ptr, plain.len);
                    228:        pos += plain.len;
                    229:        /* padding */
                    230:        len = (BLOCK_SIZE - (plain.len % BLOCK_SIZE)) % BLOCK_SIZE;
                    231: 
                    232:        memset(pos, 0, len);
                    233: 
                    234:        /* encrypt inline with CBC, zero IV */
                    235:        if (!this->crypter->encrypt(this->crypter, chunk,
                    236:                                                                chunk_from_thing(zero), NULL))
                    237:        {
                    238:                free(chunk.ptr);
                    239:                return FALSE;
                    240:        }
                    241:        /* copy last icv_size bytes as ICV to output */
                    242:        memcpy(icv, chunk.ptr + chunk.len - BLOCK_SIZE, this->icv_size);
                    243: 
                    244:        free(chunk.ptr);
                    245: 
                    246:        /* encrypt the ICV value */
                    247:        return crypt_icv(this, iv, icv);
                    248: }
                    249: 
                    250: /**
                    251:  * Verify the ICV
                    252:  */
                    253: static bool verify_icv(private_ccm_aead_t *this, chunk_t plain, chunk_t assoc,
                    254:                                           chunk_t iv, char *icv)
                    255: {
                    256:        char buf[this->icv_size];
                    257: 
                    258:        return create_icv(this, plain, assoc, iv, buf) &&
                    259:                   memeq_const(buf, icv, this->icv_size);
                    260: }
                    261: 
                    262: METHOD(aead_t, encrypt, bool,
                    263:        private_ccm_aead_t *this, chunk_t plain, chunk_t assoc, chunk_t iv,
                    264:        chunk_t *encrypted)
                    265: {
                    266:        if (encrypted)
                    267:        {
                    268:                *encrypted = chunk_alloc(plain.len + this->icv_size);
                    269:                return create_icv(this, plain, assoc, iv, encrypted->ptr + plain.len) &&
                    270:                           crypt_data(this, iv, plain, *encrypted);
                    271:        }
                    272:        return create_icv(this, plain, assoc, iv, plain.ptr + plain.len) &&
                    273:                   crypt_data(this, iv, plain, plain);
                    274: }
                    275: 
                    276: METHOD(aead_t, decrypt, bool,
                    277:        private_ccm_aead_t *this, chunk_t encrypted, chunk_t assoc, chunk_t iv,
                    278:        chunk_t *plain)
                    279: {
                    280:        if (encrypted.len < this->icv_size)
                    281:        {
                    282:                return FALSE;
                    283:        }
                    284:        encrypted.len -= this->icv_size;
                    285:        if (plain)
                    286:        {
                    287:                *plain = chunk_alloc(encrypted.len);
                    288:                return crypt_data(this, iv, encrypted, *plain) &&
                    289:                           verify_icv(this, *plain, assoc, iv,
                    290:                                                  encrypted.ptr + encrypted.len);
                    291:        }
                    292:        return crypt_data(this, iv, encrypted, encrypted) &&
                    293:                   verify_icv(this, encrypted, assoc, iv,
                    294:                                          encrypted.ptr + encrypted.len);
                    295: }
                    296: 
                    297: METHOD(aead_t, get_block_size, size_t,
                    298:        private_ccm_aead_t *this)
                    299: {
                    300:        return 1;
                    301: }
                    302: 
                    303: METHOD(aead_t, get_icv_size, size_t,
                    304:        private_ccm_aead_t *this)
                    305: {
                    306:        return this->icv_size;
                    307: }
                    308: 
                    309: METHOD(aead_t, get_iv_size, size_t,
                    310:        private_ccm_aead_t *this)
                    311: {
                    312:        return IV_SIZE;
                    313: }
                    314: 
                    315: METHOD(aead_t, get_iv_gen, iv_gen_t*,
                    316:        private_ccm_aead_t *this)
                    317: {
                    318:        return this->iv_gen;
                    319: }
                    320: 
                    321: METHOD(aead_t, get_key_size, size_t,
                    322:        private_ccm_aead_t *this)
                    323: {
                    324:        return this->crypter->get_key_size(this->crypter) + SALT_SIZE;
                    325: }
                    326: 
                    327: METHOD(aead_t, set_key, bool,
                    328:        private_ccm_aead_t *this, chunk_t key)
                    329: {
                    330:        memcpy(this->salt, key.ptr + key.len - SALT_SIZE, SALT_SIZE);
                    331:        key.len -= SALT_SIZE;
                    332:        return this->crypter->set_key(this->crypter, key);
                    333: }
                    334: 
                    335: METHOD(aead_t, destroy, void,
                    336:        private_ccm_aead_t *this)
                    337: {
                    338:        this->crypter->destroy(this->crypter);
                    339:        this->iv_gen->destroy(this->iv_gen);
                    340:        free(this);
                    341: }
                    342: 
                    343: /**
                    344:  * See header
                    345:  */
                    346: ccm_aead_t *ccm_aead_create(encryption_algorithm_t algo,
                    347:                                                        size_t key_size, size_t salt_size)
                    348: {
                    349:        private_ccm_aead_t *this;
                    350:        size_t icv_size;
                    351: 
                    352:        switch (key_size)
                    353:        {
                    354:                case 0:
                    355:                        key_size = 16;
                    356:                        break;
                    357:                case 16:
                    358:                case 24:
                    359:                case 32:
                    360:                        break;
                    361:                default:
                    362:                        return NULL;
                    363:        }
                    364:        if (salt_size && salt_size != SALT_SIZE)
                    365:        {
                    366:                /* currently not supported */
                    367:                return NULL;
                    368:        }
                    369:        switch (algo)
                    370:        {
                    371:                case ENCR_AES_CCM_ICV8:
                    372:                        algo = ENCR_AES_CBC;
                    373:                        icv_size = 8;
                    374:                        break;
                    375:                case ENCR_AES_CCM_ICV12:
                    376:                        algo = ENCR_AES_CBC;
                    377:                        icv_size = 12;
                    378:                        break;
                    379:                case ENCR_AES_CCM_ICV16:
                    380:                        algo = ENCR_AES_CBC;
                    381:                        icv_size = 16;
                    382:                        break;
                    383:                case ENCR_CAMELLIA_CCM_ICV8:
                    384:                        algo = ENCR_CAMELLIA_CBC;
                    385:                        icv_size = 8;
                    386:                        break;
                    387:                case ENCR_CAMELLIA_CCM_ICV12:
                    388:                        algo = ENCR_CAMELLIA_CBC;
                    389:                        icv_size = 12;
                    390:                        break;
                    391:                case ENCR_CAMELLIA_CCM_ICV16:
                    392:                        algo = ENCR_CAMELLIA_CBC;
                    393:                        icv_size = 16;
                    394:                        break;
                    395:                default:
                    396:                        return NULL;
                    397:        }
                    398: 
                    399:        INIT(this,
                    400:                .public = {
                    401:                        .aead = {
                    402:                                .encrypt = _encrypt,
                    403:                                .decrypt = _decrypt,
                    404:                                .get_block_size = _get_block_size,
                    405:                                .get_icv_size = _get_icv_size,
                    406:                                .get_iv_size = _get_iv_size,
                    407:                                .get_iv_gen = _get_iv_gen,
                    408:                                .get_key_size = _get_key_size,
                    409:                                .set_key = _set_key,
                    410:                                .destroy = _destroy,
                    411:                        },
                    412:                },
                    413:                .crypter = lib->crypto->create_crypter(lib->crypto, algo, key_size),
                    414:                .iv_gen = iv_gen_seq_create(),
                    415:                .icv_size = icv_size,
                    416:        );
                    417: 
                    418:        if (!this->crypter)
                    419:        {
                    420:                free(this);
                    421:                return NULL;
                    422:        }
                    423: 
                    424:        return &this->public;
                    425: }

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