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

1.1       misho       1: /*
                      2:  * Copyright (C) 2012 Tobias Brunner
                      3:  * Copyright (C) 2008 Martin Willi
                      4:  * HSR Hochschule fuer Technik Rapperswil
                      5:  *
                      6:  * This program is free software; you can redistribute it and/or modify it
                      7:  * under the terms of the GNU General Public License as published by the
                      8:  * Free Software Foundation; either version 2 of the License, or (at your
                      9:  * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
                     10:  *
                     11:  * This program is distributed in the hope that it will be useful, but
                     12:  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
                     13:  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
                     14:  * for more details.
                     15:  */
                     16: 
                     17: #include <string.h>
                     18: 
                     19: #include "xcbc.h"
                     20: 
                     21: #include <utils/debug.h>
                     22: #include <crypto/mac.h>
                     23: #include <crypto/prfs/mac_prf.h>
                     24: #include <crypto/signers/mac_signer.h>
                     25: 
                     26: typedef struct private_mac_t private_mac_t;
                     27: 
                     28: /**
                     29:  * Private data of a mac_t object.
                     30:  *
                     31:  * The variable names are the same as in the RFC.
                     32:  */
                     33: struct private_mac_t {
                     34: 
                     35:        /**
                     36:         * Public mac_t interface.
                     37:         */
                     38:        mac_t public;
                     39: 
                     40:        /**
                     41:         * Block size, in bytes
                     42:         */
                     43:        uint8_t b;
                     44: 
                     45:        /**
                     46:         * crypter using k1
                     47:         */
                     48:        crypter_t *k1;
                     49: 
                     50:        /**
                     51:         * k2
                     52:         */
                     53:        uint8_t *k2;
                     54: 
                     55:        /**
                     56:         * k3
                     57:         */
                     58:        uint8_t *k3;
                     59: 
                     60:        /**
                     61:         * E
                     62:         */
                     63:        uint8_t *e;
                     64: 
                     65:        /**
                     66:         * remaining, unprocessed bytes in append mode
                     67:         */
                     68:        uint8_t *remaining;
                     69: 
                     70:        /**
                     71:         * number of bytes in remaining
                     72:         */
                     73:        int remaining_bytes;
                     74: 
                     75:        /**
                     76:         * TRUE if we have zero bytes to xcbc in final()
                     77:         */
                     78:        bool zero;
                     79: };
                     80: 
                     81: /**
                     82:  * xcbc supplied data, but do not run final operation
                     83:  */
                     84: static bool update(private_mac_t *this, chunk_t data)
                     85: {
                     86:        chunk_t iv;
                     87: 
                     88:        if (data.len)
                     89:        {
                     90:                this->zero = FALSE;
                     91:        }
                     92: 
                     93:        if (this->remaining_bytes + data.len <= this->b)
                     94:        {       /* no complete block, just copy into remaining */
                     95:                memcpy(this->remaining + this->remaining_bytes, data.ptr, data.len);
                     96:                this->remaining_bytes += data.len;
                     97:                return TRUE;
                     98:        }
                     99: 
                    100:        iv = chunk_alloca(this->b);
                    101:        memset(iv.ptr, 0, iv.len);
                    102: 
                    103:        /* (3) For each block M[i], where i = 1 ... n-1:
                    104:         *     XOR M[i] with E[i-1], then encrypt the result with Key K1,
                    105:         *     yielding E[i].
                    106:         */
                    107: 
                    108:        /* append data to remaining bytes, process block M[1] */
                    109:        memcpy(this->remaining + this->remaining_bytes, data.ptr,
                    110:                   this->b - this->remaining_bytes);
                    111:        data = chunk_skip(data, this->b - this->remaining_bytes);
                    112:        memxor(this->e, this->remaining, this->b);
                    113:        if (!this->k1->encrypt(this->k1, chunk_create(this->e, this->b), iv, NULL))
                    114:        {
                    115:                return FALSE;
                    116:        }
                    117: 
                    118:        /* process blocks M[2] ... M[n-1] */
                    119:        while (data.len > this->b)
                    120:        {
                    121:                memcpy(this->remaining, data.ptr, this->b);
                    122:                data = chunk_skip(data, this->b);
                    123:                memxor(this->e, this->remaining, this->b);
                    124:                if (!this->k1->encrypt(this->k1, chunk_create(this->e, this->b),
                    125:                                                           iv, NULL))
                    126:                {
                    127:                        return FALSE;
                    128:                }
                    129:        }
                    130: 
                    131:        /* store remaining bytes of block M[n] */
                    132:        memcpy(this->remaining, data.ptr, data.len);
                    133:        this->remaining_bytes = data.len;
                    134: 
                    135:        return TRUE;
                    136: }
                    137: 
                    138: /**
                    139:  * run last round, data is in this->e
                    140:  */
                    141: static bool final(private_mac_t *this, uint8_t *out)
                    142: {
                    143:        chunk_t iv;
                    144: 
                    145:        iv = chunk_alloca(this->b);
                    146:        memset(iv.ptr, 0, iv.len);
                    147: 
                    148:        /* (4) For block M[n]: */
                    149:        if (this->remaining_bytes == this->b && !this->zero)
                    150:        {
                    151:                /* a) If the blocksize of M[n] is 128 bits:
                    152:                 *    XOR M[n] with E[n-1] and Key K2, then encrypt the result with
                    153:                 *    Key K1, yielding E[n].
                    154:                 */
                    155:                memxor(this->e, this->remaining, this->b);
                    156:                memxor(this->e, this->k2, this->b);
                    157:        }
                    158:        else
                    159:        {
                    160:                /* b) If the blocksize of M[n] is less than 128 bits:
                    161:                 *
                    162:                 *  i) Pad M[n] with a single "1" bit, followed by the number of
                    163:                 *     "0" bits (possibly none) required to increase M[n]'s
                    164:                 *     blocksize to 128 bits.
                    165:                 */
                    166:                if (this->remaining_bytes < this->b)
                    167:                {
                    168:                        this->remaining[this->remaining_bytes] = 0x80;
                    169:                        while (++this->remaining_bytes < this->b)
                    170:                        {
                    171:                                this->remaining[this->remaining_bytes] = 0x00;
                    172:                        }
                    173:                }
                    174:                /*  ii) XOR M[n] with E[n-1] and Key K3, then encrypt the result
                    175:                 *      with Key K1, yielding E[n].
                    176:                 */
                    177:                memxor(this->e, this->remaining, this->b);
                    178:                memxor(this->e, this->k3, this->b);
                    179:        }
                    180:        if (!this->k1->encrypt(this->k1, chunk_create(this->e, this->b), iv, NULL))
                    181:        {
                    182:                return FALSE;
                    183:        }
                    184: 
                    185:        memcpy(out, this->e, this->b);
                    186: 
                    187:        /* (2) Define E[0] = 0x00000000000000000000000000000000 */
                    188:        memset(this->e, 0, this->b);
                    189:        this->remaining_bytes = 0;
                    190:        this->zero = TRUE;
                    191: 
                    192:        return TRUE;
                    193: }
                    194: 
                    195: METHOD(mac_t, get_mac, bool,
                    196:        private_mac_t *this, chunk_t data, uint8_t *out)
                    197: {
                    198:        /* update E, do not process last block */
                    199:        if (!update(this, data))
                    200:        {
                    201:                return FALSE;
                    202:        }
                    203: 
                    204:        if (out)
                    205:        {       /* if not in append mode, process last block and output result */
                    206:                return final(this, out);
                    207:        }
                    208:        return TRUE;
                    209: }
                    210: 
                    211: METHOD(mac_t, get_mac_size, size_t,
                    212:        private_mac_t *this)
                    213: {
                    214:        return this->b;
                    215: }
                    216: 
                    217: METHOD(mac_t, set_key, bool,
                    218:        private_mac_t *this, chunk_t key)
                    219: {
                    220:        chunk_t iv, k1, lengthened;
                    221: 
                    222:        memset(this->e, 0, this->b);
                    223:        this->remaining_bytes = 0;
                    224:        this->zero = TRUE;
                    225: 
                    226:        /* we support variable keys from RFC4434 */
                    227:        if (key.len == this->b)
                    228:        {
                    229:                lengthened = key;
                    230:        }
                    231:        else if (key.len < this->b)
                    232:        {       /* pad short keys */
                    233:                lengthened = chunk_alloca(this->b);
                    234:                memset(lengthened.ptr, 0, lengthened.len);
                    235:                memcpy(lengthened.ptr, key.ptr, key.len);
                    236:        }
                    237:        else
                    238:        {       /* shorten key using xcbc */
                    239:                lengthened = chunk_alloca(this->b);
                    240:                memset(lengthened.ptr, 0, lengthened.len);
                    241:                if (!set_key(this, lengthened) ||
                    242:                        !get_mac(this, key, lengthened.ptr))
                    243:                {
                    244:                        return FALSE;
                    245:                }
                    246:        }
                    247: 
                    248:        k1 = chunk_alloca(this->b);
                    249:        iv = chunk_alloca(this->b);
                    250:        memset(iv.ptr, 0, iv.len);
                    251: 
                    252:        /*
                    253:         * (1) Derive 3 128-bit keys (K1, K2 and K3) from the 128-bit secret
                    254:         *     key K, as follows:
                    255:         *     K1 = 0x01010101010101010101010101010101 encrypted with Key K
                    256:         *     K2 = 0x02020202020202020202020202020202 encrypted with Key K
                    257:         *     K3 = 0x03030303030303030303030303030303 encrypted with Key K
                    258:         */
                    259: 
                    260:        memset(k1.ptr, 0x01, this->b);
                    261:        memset(this->k2, 0x02, this->b);
                    262:        memset(this->k3, 0x03, this->b);
                    263: 
                    264:        if (!this->k1->set_key(this->k1, lengthened) ||
                    265:                !this->k1->encrypt(this->k1, chunk_create(this->k2, this->b), iv, NULL) ||
                    266:                !this->k1->encrypt(this->k1, chunk_create(this->k3, this->b), iv, NULL) ||
                    267:                !this->k1->encrypt(this->k1, k1, iv, NULL) ||
                    268:                !this->k1->set_key(this->k1, k1))
                    269:        {
                    270:                memwipe(k1.ptr, k1.len);
                    271:                return FALSE;
                    272:        }
                    273:        memwipe(k1.ptr, k1.len);
                    274:        return TRUE;
                    275: }
                    276: 
                    277: METHOD(mac_t, destroy, void,
                    278:        private_mac_t *this)
                    279: {
                    280:        this->k1->destroy(this->k1);
                    281:        memwipe(this->k2, this->b);
                    282:        free(this->k2);
                    283:        memwipe(this->k3, this->b);
                    284:        free(this->k3);
                    285:        free(this->e);
                    286:        free(this->remaining);
                    287:        free(this);
                    288: }
                    289: 
                    290: /*
                    291:  * Described in header
                    292:  */
                    293: static mac_t *xcbc_create(encryption_algorithm_t algo, size_t key_size)
                    294: {
                    295:        private_mac_t *this;
                    296:        crypter_t *crypter;
                    297:        uint8_t b;
                    298: 
                    299:        crypter = lib->crypto->create_crypter(lib->crypto, algo, key_size);
                    300:        if (!crypter)
                    301:        {
                    302:                return NULL;
                    303:        }
                    304:        b = crypter->get_block_size(crypter);
                    305:        /* input and output of crypter must be equal for xcbc */
                    306:        if (b != key_size)
                    307:        {
                    308:                crypter->destroy(crypter);
                    309:                return NULL;
                    310:        }
                    311: 
                    312:        INIT(this,
                    313:                .public = {
                    314:                        .get_mac = _get_mac,
                    315:                        .get_mac_size = _get_mac_size,
                    316:                        .set_key = _set_key,
                    317:                        .destroy = _destroy,
                    318:                },
                    319:                .b = b,
                    320:                .k1 = crypter,
                    321:                .k2 = malloc(b),
                    322:                .k3 = malloc(b),
                    323:                .e = malloc(b),
                    324:                .remaining = malloc(b),
                    325:                .zero = TRUE,
                    326:        );
                    327:        memset(this->e, 0, b);
                    328: 
                    329:        return &this->public;
                    330: }
                    331: 
                    332: /*
                    333:  * Described in header.
                    334:  */
                    335: prf_t *xcbc_prf_create(pseudo_random_function_t algo)
                    336: {
                    337:        mac_t *xcbc;
                    338: 
                    339:        switch (algo)
                    340:        {
                    341:                case PRF_AES128_XCBC:
                    342:                        xcbc = xcbc_create(ENCR_AES_CBC, 16);
                    343:                        break;
                    344:                case PRF_CAMELLIA128_XCBC:
                    345:                        xcbc = xcbc_create(ENCR_CAMELLIA_CBC, 16);
                    346:                        break;
                    347:                default:
                    348:                        return NULL;
                    349:        }
                    350:        if (xcbc)
                    351:        {
                    352:                return mac_prf_create(xcbc);
                    353:        }
                    354:        return NULL;
                    355: }
                    356: 
                    357: /*
                    358:  * Described in header
                    359:  */
                    360: signer_t *xcbc_signer_create(integrity_algorithm_t algo)
                    361: {
                    362:        size_t trunc;
                    363:        mac_t *xcbc;
                    364: 
                    365:        switch (algo)
                    366:        {
                    367:                case AUTH_AES_XCBC_96:
                    368:                        xcbc = xcbc_create(ENCR_AES_CBC, 16);
                    369:                        trunc = 12;
                    370:                        break;
                    371:                case AUTH_CAMELLIA_XCBC_96:
                    372:                        xcbc = xcbc_create(ENCR_CAMELLIA_CBC, 16);
                    373:                        trunc = 12;
                    374:                        break;
                    375:                default:
                    376:                        return NULL;
                    377:        }
                    378:        if (xcbc)
                    379:        {
                    380:                return mac_signer_create(xcbc, trunc);
                    381:        }
                    382:        return NULL;
                    383: }

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