Annotation of embedaddon/strongswan/src/libtls/tls_aead_expl.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:  * Copyright (C) 2014 Martin Willi
                      3:  * Copyright (C) 2014 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 "tls_aead.h"
                     17: 
                     18: #include <crypto/iv/iv_gen_rand.h>
                     19: 
                     20: typedef struct private_tls_aead_t private_tls_aead_t;
                     21: 
                     22: /**
                     23:  * Private data of an tls_aead_t object.
                     24:  */
                     25: struct private_tls_aead_t {
                     26: 
                     27:        /**
                     28:         * Public tls_aead_t interface.
                     29:         */
                     30:        tls_aead_t public;
                     31: 
                     32:        /**
                     33:         * traditional crypter
                     34:         */
                     35:        crypter_t *crypter;
                     36: 
                     37:        /**
                     38:         * traditional signer
                     39:         */
                     40:        signer_t *signer;
                     41: 
                     42:        /**
                     43:         * IV generator
                     44:         */
                     45:        iv_gen_t *iv_gen;
                     46: };
                     47: 
                     48: /**
                     49:  * Associated header data to create signature over
                     50:  */
                     51: typedef struct __attribute__((__packed__)) {
                     52:        uint64_t seq;
                     53:        uint8_t type;
                     54:        uint16_t version;
                     55:        uint16_t length;
                     56: } sigheader_t;
                     57: 
                     58: METHOD(tls_aead_t, encrypt, bool,
                     59:        private_tls_aead_t *this, tls_version_t version, tls_content_type_t type,
                     60:        uint64_t seq, chunk_t *data)
                     61: {
                     62:        chunk_t assoc, mac, padding, iv;
                     63:        uint8_t bs, padlen;
                     64:        sigheader_t hdr;
                     65: 
                     66:        hdr.type = type;
                     67:        htoun64(&hdr.seq, seq);
                     68:        htoun16(&hdr.version, version);
                     69:        htoun16(&hdr.length, data->len);
                     70: 
                     71:        assoc = chunk_from_thing(hdr);
                     72:        if (!this->signer->get_signature(this->signer, assoc, NULL) ||
                     73:                !this->signer->allocate_signature(this->signer, *data, &mac))
                     74:        {
                     75:                return FALSE;
                     76:        }
                     77:        bs = this->crypter->get_block_size(this->crypter);
                     78:        padlen = pad_len(data->len + mac.len + 1, bs);
                     79: 
                     80:        padding = chunk_alloca(padlen);
                     81:        memset(padding.ptr, padlen, padding.len);
                     82: 
                     83:        /* TLSv1.1 uses random IVs, prepended to record */
                     84:        iv.len = this->crypter->get_iv_size(this->crypter);
                     85:        iv = chunk_alloca(iv.len);
                     86:        if (!this->iv_gen->get_iv(this->iv_gen, seq, iv.len, iv.ptr))
                     87:        {
                     88:                return FALSE;
                     89:        }
                     90:        *data = chunk_cat("mmcc", *data, mac, padding, chunk_from_thing(padlen));
                     91:        /* encrypt inline */
                     92:        if (!this->crypter->encrypt(this->crypter, *data, iv, NULL))
                     93:        {
                     94:                return FALSE;
                     95:        }
                     96:        /* prepend IV */
                     97:        *data = chunk_cat("cm", iv, *data);
                     98:        return TRUE;
                     99: }
                    100: 
                    101: METHOD(tls_aead_t, decrypt, bool,
                    102:        private_tls_aead_t *this, tls_version_t version, tls_content_type_t type,
                    103:        uint64_t seq, chunk_t *data)
                    104: {
                    105:        chunk_t assoc, mac, iv;
                    106:        uint8_t bs, padlen;
                    107:        sigheader_t hdr;
                    108:        size_t i;
                    109: 
                    110:        iv.len = this->crypter->get_iv_size(this->crypter);
                    111:        if (data->len < iv.len)
                    112:        {
                    113:                return FALSE;
                    114:        }
                    115:        iv.ptr = data->ptr;
                    116:        *data = chunk_skip(*data, iv.len);
                    117:        bs = this->crypter->get_block_size(this->crypter);
                    118:        if (data->len < bs || data->len % bs)
                    119:        {
                    120:                return FALSE;
                    121:        }
                    122:        if (!this->crypter->decrypt(this->crypter, *data, iv, NULL))
                    123:        {
                    124:                return FALSE;
                    125:        }
                    126:        padlen = data->ptr[data->len - 1];
                    127:        if (padlen < data->len)
                    128:        {       /* If padding looks valid, remove it */
                    129:                for (i = data->len - padlen - 1; i < data->len - 1; i++)
                    130:                {
                    131:                        if (data->ptr[i] != padlen)
                    132:                        {
                    133:                                return FALSE;
                    134:                        }
                    135:                }
                    136:                data->len -= padlen + 1;
                    137:        }
                    138: 
                    139:        bs = this->signer->get_block_size(this->signer);
                    140:        if (data->len < bs)
                    141:        {
                    142:                return FALSE;
                    143:        }
                    144:        mac = chunk_skip(*data, data->len - bs);
                    145:        data->len -= bs;
                    146: 
                    147:        hdr.type = type;
                    148:        htoun64(&hdr.seq, seq);
                    149:        htoun16(&hdr.version, version);
                    150:        htoun16(&hdr.length, data->len);
                    151: 
                    152:        assoc = chunk_from_thing(hdr);
                    153:        if (!this->signer->get_signature(this->signer, assoc, NULL) ||
                    154:                !this->signer->verify_signature(this->signer, *data, mac))
                    155:        {
                    156:                return FALSE;
                    157:        }
                    158:        return TRUE;
                    159: }
                    160: 
                    161: METHOD(tls_aead_t, get_mac_key_size, size_t,
                    162:        private_tls_aead_t *this)
                    163: {
                    164:        return this->signer->get_key_size(this->signer);
                    165: }
                    166: 
                    167: METHOD(tls_aead_t, get_encr_key_size, size_t,
                    168:        private_tls_aead_t *this)
                    169: {
                    170:        return this->crypter->get_key_size(this->crypter);
                    171: }
                    172: 
                    173: METHOD(tls_aead_t, get_iv_size, size_t,
                    174:        private_tls_aead_t *this)
                    175: {
                    176:        return 0;
                    177: }
                    178: 
                    179: METHOD(tls_aead_t, set_keys, bool,
                    180:        private_tls_aead_t *this, chunk_t mac, chunk_t encr, chunk_t iv)
                    181: {
                    182:        if (iv.len)
                    183:        {
                    184:                return FALSE;
                    185:        }
                    186:        return this->signer->set_key(this->signer, mac) &&
                    187:                   this->crypter->set_key(this->crypter, encr);
                    188: }
                    189: 
                    190: METHOD(tls_aead_t, destroy, void,
                    191:        private_tls_aead_t *this)
                    192: {
                    193:        this->iv_gen->destroy(this->iv_gen);
                    194:        DESTROY_IF(this->crypter);
                    195:        DESTROY_IF(this->signer);
                    196:        free(this);
                    197: }
                    198: 
                    199: /**
                    200:  * See header
                    201:  */
                    202: tls_aead_t *tls_aead_create_explicit(integrity_algorithm_t mac,
                    203:                                                                encryption_algorithm_t encr, size_t encr_size)
                    204: {
                    205:        private_tls_aead_t *this;
                    206: 
                    207:        INIT(this,
                    208:                .public = {
                    209:                        .encrypt = _encrypt,
                    210:                        .decrypt = _decrypt,
                    211:                        .get_mac_key_size = _get_mac_key_size,
                    212:                        .get_encr_key_size = _get_encr_key_size,
                    213:                        .get_iv_size = _get_iv_size,
                    214:                        .set_keys = _set_keys,
                    215:                        .destroy = _destroy,
                    216:                },
                    217:                .crypter = lib->crypto->create_crypter(lib->crypto, encr, encr_size),
                    218:                .signer = lib->crypto->create_signer(lib->crypto, mac),
                    219:                .iv_gen = iv_gen_rand_create(),
                    220:        );
                    221: 
                    222:        if (!this->crypter || !this->signer)
                    223:        {
                    224:                destroy(this);
                    225:                return NULL;
                    226:        }
                    227: 
                    228:        return &this->public;
                    229: }

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