Annotation of embedaddon/strongswan/src/libtls/tls_aead_impl.c, revision 1.1.1.2

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

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