Annotation of embedaddon/strongswan/src/libstrongswan/plugins/gcm/gcm_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 "gcm_aead.h"
                     17: 
                     18: #include <limits.h>
                     19: #include <crypto/iv/iv_gen_seq.h>
                     20: 
                     21: #define BLOCK_SIZE 16
                     22: #define NONCE_SIZE 12
                     23: #define IV_SIZE 8
                     24: #define SALT_SIZE (NONCE_SIZE - IV_SIZE)
                     25: 
                     26: typedef struct private_gcm_aead_t private_gcm_aead_t;
                     27: 
                     28: /**
                     29:  * Private data of an gcm_aead_t object.
                     30:  */
                     31: struct private_gcm_aead_t {
                     32: 
                     33:        /**
                     34:         * Public gcm_aead_t interface.
                     35:         */
                     36:        gcm_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:         * Size of the integrity check value
                     50:         */
                     51:        size_t icv_size;
                     52: 
                     53:        /**
                     54:         * Salt value
                     55:         */
                     56:        char salt[SALT_SIZE];
                     57: 
                     58:        /**
                     59:         * GHASH subkey H
                     60:         */
                     61:        char h[BLOCK_SIZE];
                     62: };
                     63: 
                     64: /**
                     65:  * Find a suitable word size and network order conversion functions
                     66:  */
                     67: #if ULONG_MAX == 18446744073709551615UL && defined(htobe64)
                     68: #      define htobeword htobe64
                     69: #      define bewordtoh be64toh
                     70: #      define SHIFT_WORD_TYPE uint64_t
                     71: #else
                     72: #      define htobeword htonl
                     73: #      define bewordtoh ntohl
                     74: #      define SHIFT_WORD_TYPE uint32_t
                     75: #endif
                     76: 
                     77: /**
                     78:  * Bitshift a block right by one bit
                     79:  */
                     80: static void sr_block(char *block)
                     81: {
                     82:        int i;
                     83:        SHIFT_WORD_TYPE *word = (SHIFT_WORD_TYPE*)block;
                     84: 
                     85:        for (i = 0; i < BLOCK_SIZE / sizeof(*word); i++)
                     86:        {
                     87:                word[i] = bewordtoh(word[i]);
                     88:        }
                     89:        for (i = BLOCK_SIZE / sizeof(*word) - 1; i >= 0; i--)
                     90:        {
                     91:                word[i] >>= 1;
                     92:                if (i != 0)
                     93:                {
                     94:                        word[i] |= word[i - 1] << (sizeof(*word) * 8 - 1);
                     95:                }
                     96:        }
                     97:        for (i = 0; i < BLOCK_SIZE / sizeof(*word); i++)
                     98:        {
                     99:                word[i] = htobeword(word[i]);
                    100:        }
                    101: }
                    102: 
                    103: /**
                    104:  * Naive implementation of block multiplication in GF128, no tables
                    105:  */
                    106: static void mult_block(char *x, char *y, char *res)
                    107: {
                    108:        char z[BLOCK_SIZE], v[BLOCK_SIZE], r;
                    109:        int bit, byte;
                    110: 
                    111:        r = 0xE1;
                    112:        memset(z, 0, BLOCK_SIZE);
                    113:        memcpy(v, y, BLOCK_SIZE);
                    114: 
                    115:        for (byte = 0; byte < BLOCK_SIZE; byte++)
                    116:        {
                    117:                for (bit = 7; bit >= 0; bit--)
                    118:                {
                    119:                        if (x[byte] & (1 << bit))
                    120:                        {
                    121:                                memxor(z, v, BLOCK_SIZE);
                    122:                        }
                    123:                        if (v[BLOCK_SIZE - 1] & 0x01)
                    124:                        {
                    125:                                sr_block(v);
                    126:                                v[0] ^= r;
                    127:                        }
                    128:                        else
                    129:                        {
                    130:                                sr_block(v);
                    131:                        }
                    132:                }
                    133:        }
                    134:        memcpy(res, z, BLOCK_SIZE);
                    135: }
                    136: 
                    137: /**
                    138:  * GHASH function
                    139:  */
                    140: static void ghash(private_gcm_aead_t *this, chunk_t x, char *res)
                    141: {
                    142:        char y[BLOCK_SIZE];
                    143: 
                    144:        memset(y, 0, BLOCK_SIZE);
                    145: 
                    146:        while (x.len)
                    147:        {
                    148:                memxor(y, x.ptr, BLOCK_SIZE);
                    149:                mult_block(y, this->h, y);
                    150:                x = chunk_skip(x, BLOCK_SIZE);
                    151:        }
                    152:        memcpy(res, y, BLOCK_SIZE);
                    153: }
                    154: 
                    155: /**
                    156:  * GCTR function, en-/decrypts x inline
                    157:  */
                    158: static bool gctr(private_gcm_aead_t *this, char *icb, chunk_t x)
                    159: {
                    160:        char cb[BLOCK_SIZE], iv[BLOCK_SIZE], tmp[BLOCK_SIZE];
                    161: 
                    162:        memset(iv, 0, BLOCK_SIZE);
                    163:        memcpy(cb, icb, BLOCK_SIZE);
                    164: 
                    165:        while (x.len)
                    166:        {
                    167:                memcpy(tmp, cb, BLOCK_SIZE);
                    168:                if (!this->crypter->encrypt(this->crypter, chunk_from_thing(tmp),
                    169:                                                                        chunk_from_thing(iv), NULL))
                    170:                {
                    171:                        return FALSE;
                    172:                }
                    173:                memxor(x.ptr, tmp, min(BLOCK_SIZE, x.len));
                    174:                chunk_increment(chunk_from_thing(cb));
                    175:                x = chunk_skip(x, BLOCK_SIZE);
                    176:        }
                    177:        return TRUE;
                    178: }
                    179: 
                    180: /**
                    181:  * Generate the block J0
                    182:  */
                    183: static void create_j(private_gcm_aead_t *this, char *iv, char *j)
                    184: {
                    185:        memcpy(j, this->salt, SALT_SIZE);
                    186:        memcpy(j + SALT_SIZE, iv, IV_SIZE);
                    187:        htoun32(j + SALT_SIZE + IV_SIZE, 1);
                    188: }
                    189: 
                    190: /**
                    191:  * Create GHASH subkey H
                    192:  */
                    193: static bool create_h(private_gcm_aead_t *this, char *h)
                    194: {
                    195:        char zero[BLOCK_SIZE];
                    196: 
                    197:        memset(zero, 0, BLOCK_SIZE);
                    198:        memset(h, 0, BLOCK_SIZE);
                    199: 
                    200:        return this->crypter->encrypt(this->crypter, chunk_create(h, BLOCK_SIZE),
                    201:                                                                  chunk_from_thing(zero), NULL);
                    202: }
                    203: 
                    204: /**
                    205:  * Encrypt/decrypt
                    206:  */
                    207: static bool crypt(private_gcm_aead_t *this, char *j, chunk_t in, chunk_t out)
                    208: {
                    209:        char icb[BLOCK_SIZE];
                    210: 
                    211:        memcpy(icb, j, BLOCK_SIZE);
                    212:        chunk_increment(chunk_from_thing(icb));
                    213: 
                    214:        out.len = in.len;
                    215:        if (in.ptr != out.ptr)
                    216:        {
                    217:                memcpy(out.ptr, in.ptr, in.len);
                    218:        }
                    219:        return gctr(this, icb, out);
                    220: }
                    221: 
                    222: /**
                    223:  * Create ICV
                    224:  */
                    225: static bool create_icv(private_gcm_aead_t *this, chunk_t assoc, chunk_t crypt,
                    226:                                           char *j, char *icv)
                    227: {
                    228:        size_t assoc_pad, crypt_pad;
                    229:        chunk_t chunk;
                    230:        char s[BLOCK_SIZE], *pos;
                    231: 
                    232:        assoc_pad = (BLOCK_SIZE - (assoc.len % BLOCK_SIZE)) % BLOCK_SIZE;
                    233:        crypt_pad = (BLOCK_SIZE - (crypt.len % BLOCK_SIZE)) % BLOCK_SIZE;
                    234: 
                    235:        /* concatenate data to a new chunk */
                    236:        chunk = chunk_alloc(assoc.len + assoc_pad +
                    237:                                                crypt.len + crypt_pad + BLOCK_SIZE);
                    238:        pos = chunk.ptr;
                    239:        /* add associated data */
                    240:        memcpy(pos, assoc.ptr, assoc.len);
                    241:        pos += assoc.len;
                    242:        memset(pos, 0, assoc_pad);
                    243:        pos += assoc_pad;
                    244:        /* add encrypted data */
                    245:        memcpy(pos, crypt.ptr, crypt.len);
                    246:        pos += crypt.len;
                    247:        memset(pos, 0, crypt_pad);
                    248:        pos += crypt_pad;
                    249:        /* write associated len */
                    250:        memset(pos, 0, 4);
                    251:        pos += 4;
                    252:        htoun32(pos, assoc.len * 8);
                    253:        pos += 4;
                    254:        /* write encrypted length */
                    255:        memset(pos, 0, 4);
                    256:        pos += 4;
                    257:        htoun32(pos, crypt.len * 8);
                    258:        pos += 4;
                    259: 
                    260:        ghash(this, chunk, s);
                    261:        free(chunk.ptr);
                    262:        if (!gctr(this, j, chunk_from_thing(s)))
                    263:        {
                    264:                return FALSE;
                    265:        }
                    266:        memcpy(icv, s, this->icv_size);
                    267:        return TRUE;
                    268: }
                    269: 
                    270: /**
                    271:  * Verify the ICV value
                    272:  */
                    273: static bool verify_icv(private_gcm_aead_t *this, chunk_t assoc, chunk_t crypt,
                    274:                                           char *j, char *icv)
                    275: {
                    276:        char tmp[this->icv_size];
                    277: 
                    278:        return create_icv(this, assoc, crypt, j, tmp) &&
                    279:                   memeq_const(tmp, icv, this->icv_size);
                    280: }
                    281: 
                    282: METHOD(aead_t, encrypt, bool,
                    283:        private_gcm_aead_t *this, chunk_t plain, chunk_t assoc, chunk_t iv,
                    284:        chunk_t *encrypted)
                    285: {
                    286:        char j[BLOCK_SIZE];
                    287: 
                    288:        create_j(this, iv.ptr, j);
                    289: 
                    290:        if (encrypted)
                    291:        {
                    292:                *encrypted = chunk_alloc(plain.len + this->icv_size);
                    293:                return crypt(this, j, plain, *encrypted) &&
                    294:                           create_icv(this, assoc,
                    295:                                        chunk_create(encrypted->ptr, encrypted->len - this->icv_size),
                    296:                                        j, encrypted->ptr + encrypted->len - this->icv_size);
                    297:        }
                    298:        return crypt(this, j, plain, plain) &&
                    299:                   create_icv(this, assoc, plain, j, plain.ptr + plain.len);
                    300: }
                    301: 
                    302: METHOD(aead_t, decrypt, bool,
                    303:        private_gcm_aead_t *this, chunk_t encrypted, chunk_t assoc, chunk_t iv,
                    304:        chunk_t *plain)
                    305: {
                    306:        char j[BLOCK_SIZE];
                    307: 
                    308:        if (encrypted.len < this->icv_size)
                    309:        {
                    310:                return FALSE;
                    311:        }
                    312: 
                    313:        create_j(this, iv.ptr, j);
                    314: 
                    315:        encrypted.len -= this->icv_size;
                    316:        if (!verify_icv(this, assoc, encrypted, j, encrypted.ptr + encrypted.len))
                    317:        {
                    318:                return FALSE;
                    319:        }
                    320:        if (plain)
                    321:        {
                    322:                *plain = chunk_alloc(encrypted.len);
                    323:                return crypt(this, j, encrypted, *plain);
                    324:        }
                    325:        return crypt(this, j, encrypted, encrypted);
                    326: }
                    327: 
                    328: METHOD(aead_t, get_block_size, size_t,
                    329:        private_gcm_aead_t *this)
                    330: {
                    331:        return 1;
                    332: }
                    333: 
                    334: METHOD(aead_t, get_icv_size, size_t,
                    335:        private_gcm_aead_t *this)
                    336: {
                    337:        return this->icv_size;
                    338: }
                    339: 
                    340: METHOD(aead_t, get_iv_size, size_t,
                    341:        private_gcm_aead_t *this)
                    342: {
                    343:        return IV_SIZE;
                    344: }
                    345: 
                    346: METHOD(aead_t, get_iv_gen, iv_gen_t*,
                    347:        private_gcm_aead_t *this)
                    348: {
                    349:        return this->iv_gen;
                    350: }
                    351: 
                    352: METHOD(aead_t, get_key_size, size_t,
                    353:        private_gcm_aead_t *this)
                    354: {
                    355:        return this->crypter->get_key_size(this->crypter) + SALT_SIZE;
                    356: }
                    357: 
                    358: METHOD(aead_t, set_key, bool,
                    359:        private_gcm_aead_t *this, chunk_t key)
                    360: {
                    361:        memcpy(this->salt, key.ptr + key.len - SALT_SIZE, SALT_SIZE);
                    362:        key.len -= SALT_SIZE;
                    363:        return this->crypter->set_key(this->crypter, key) &&
                    364:                   create_h(this, this->h);
                    365: }
                    366: 
                    367: METHOD(aead_t, destroy, void,
                    368:        private_gcm_aead_t *this)
                    369: {
                    370:        this->crypter->destroy(this->crypter);
                    371:        this->iv_gen->destroy(this->iv_gen);
                    372:        free(this);
                    373: }
                    374: 
                    375: /**
                    376:  * See header
                    377:  */
                    378: gcm_aead_t *gcm_aead_create(encryption_algorithm_t algo,
                    379:                                                        size_t key_size, size_t salt_size)
                    380: {
                    381:        private_gcm_aead_t *this;
                    382:        size_t icv_size;
                    383: 
                    384:        switch (key_size)
                    385:        {
                    386:                case 0:
                    387:                        key_size = 16;
                    388:                        break;
                    389:                case 16:
                    390:                case 24:
                    391:                case 32:
                    392:                        break;
                    393:                default:
                    394:                        return NULL;
                    395:        }
                    396:        if (salt_size && salt_size != SALT_SIZE)
                    397:        {
                    398:                /* currently not supported */
                    399:                return NULL;
                    400:        }
                    401:        switch (algo)
                    402:        {
                    403:                case ENCR_AES_GCM_ICV8:
                    404:                        algo = ENCR_AES_CBC;
                    405:                        icv_size = 8;
                    406:                        break;
                    407:                case ENCR_AES_GCM_ICV12:
                    408:                        algo = ENCR_AES_CBC;
                    409:                        icv_size = 12;
                    410:                        break;
                    411:                case ENCR_AES_GCM_ICV16:
                    412:                        algo = ENCR_AES_CBC;
                    413:                        icv_size = 16;
                    414:                        break;
                    415:                default:
                    416:                        return NULL;
                    417:        }
                    418: 
                    419:        INIT(this,
                    420:                .public = {
                    421:                        .aead = {
                    422:                                .encrypt = _encrypt,
                    423:                                .decrypt = _decrypt,
                    424:                                .get_block_size = _get_block_size,
                    425:                                .get_icv_size = _get_icv_size,
                    426:                                .get_iv_size = _get_iv_size,
                    427:                                .get_iv_gen = _get_iv_gen,
                    428:                                .get_key_size = _get_key_size,
                    429:                                .set_key = _set_key,
                    430:                                .destroy = _destroy,
                    431:                        },
                    432:                },
                    433:                .crypter = lib->crypto->create_crypter(lib->crypto, algo, key_size),
                    434:                .iv_gen = iv_gen_seq_create(),
                    435:                .icv_size = icv_size,
                    436:        );
                    437: 
                    438:        if (!this->crypter)
                    439:        {
                    440:                free(this);
                    441:                return NULL;
                    442:        }
                    443: 
                    444:        return &this->public;
                    445: }

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