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

1.1       misho       1: /*
                      2:  * Copyright (C) 2020 Tobias Brunner
                      3:  * HSR Hochschule fuer Technik Rapperswil
                      4:  *
                      5:  * Copyright (C) 2014 Martin Willi
                      6:  * Copyright (C) 2014 revosec AG
                      7:  *
                      8:  * This program is free software; you can redistribute it and/or modify it
                      9:  * under the terms of the GNU General Public License as published by the
                     10:  * Free Software Foundation; either version 2 of the License, or (at your
                     11:  * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
                     12:  *
                     13:  * This program is distributed in the hope that it will be useful, but
                     14:  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
                     15:  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
                     16:  * for more details.
                     17:  */
                     18: 
                     19: #include "tls_aead.h"
                     20: 
                     21: #include <bio/bio_writer.h>
                     22: 
                     23: typedef struct private_tls_aead_t private_tls_aead_t;
                     24: 
                     25: /**
                     26:  * Private data of an tls_aead_t object.
                     27:  */
                     28: struct private_tls_aead_t {
                     29: 
                     30:        /**
                     31:         * Public tls_aead_t interface.
                     32:         */
                     33:        tls_aead_t public;
                     34: 
                     35:        /**
                     36:         * AEAD transform.
                     37:         */
                     38:        aead_t *aead;
                     39: 
                     40:        /**
                     41:         * IV derived from key material.
                     42:         */
                     43:        chunk_t iv;
                     44: 
                     45:        /**
                     46:         * Size of the salt that's internally used by the AEAD implementation.
                     47:         */
                     48:        size_t salt;
                     49: };
                     50: 
                     51: /**
                     52:  * Additional data for AEAD (record header)
                     53:  */
                     54: typedef struct __attribute__((__packed__)) {
                     55:        uint8_t type;
                     56:        uint16_t version;
                     57:        uint16_t length;
                     58: } sigheader_t;
                     59: 
                     60: /**
                     61:  * Generate the IV from the given sequence number.
                     62:  */
                     63: static bool generate_iv(private_tls_aead_t *this, uint64_t seq, chunk_t iv)
                     64: {
                     65:        if (iv.len < sizeof(uint64_t) ||
                     66:                iv.len < this->iv.len)
                     67:        {
                     68:                return FALSE;
                     69:        }
                     70:        memset(iv.ptr, 0, iv.len);
                     71:        htoun64(iv.ptr + iv.len - sizeof(uint64_t), seq);
                     72:        memxor(iv.ptr + iv.len - this->iv.len, this->iv.ptr, this->iv.len);
                     73:        return TRUE;
                     74: }
                     75: 
                     76: METHOD(tls_aead_t, encrypt, bool,
                     77:        private_tls_aead_t *this, tls_version_t version, tls_content_type_t *type,
                     78:        uint64_t seq, chunk_t *data)
                     79: {
                     80:        bio_writer_t *writer;
                     81:        chunk_t assoc, encrypted, iv, padding, plain;
                     82:        uint8_t icvlen;
                     83:        sigheader_t hdr;
                     84: 
                     85:        iv = chunk_alloca(this->aead->get_iv_size(this->aead));
                     86:        if (!generate_iv(this, seq, iv))
                     87:        {
                     88:                return FALSE;
                     89:        }
                     90: 
                     91:        /* no padding for now */
                     92:        padding = chunk_empty;
                     93:        icvlen = this->aead->get_icv_size(this->aead);
                     94: 
                     95:        writer = bio_writer_create(data->len + 1 + padding.len + icvlen);
                     96:        writer->write_data(writer, *data);
                     97:        writer->write_uint8(writer, *type);
                     98:        writer->write_data(writer, padding);
                     99:        writer->skip(writer, icvlen);
                    100:        encrypted = writer->extract_buf(writer);
                    101:        writer->destroy(writer);
                    102: 
                    103:        plain = encrypted;
                    104:        plain.len -= icvlen;
                    105: 
                    106:        hdr.type = TLS_APPLICATION_DATA;
                    107:        htoun16(&hdr.version, TLS_1_2);
                    108:        htoun16(&hdr.length, encrypted.len);
                    109: 
                    110:        assoc = chunk_from_thing(hdr);
                    111:        if (!this->aead->encrypt(this->aead, plain, assoc, iv, NULL))
                    112:        {
                    113:                chunk_free(&encrypted);
                    114:                return FALSE;
                    115:        }
                    116:        chunk_free(data);
                    117:        *type = TLS_APPLICATION_DATA;
                    118:        *data = encrypted;
                    119:        return TRUE;
                    120: }
                    121: 
                    122: METHOD(tls_aead_t, decrypt, bool,
                    123:        private_tls_aead_t *this, tls_version_t version, tls_content_type_t *type,
                    124:        uint64_t seq, chunk_t *data)
                    125: {
                    126:        chunk_t assoc, iv;
                    127:        uint8_t icvlen;
                    128:        sigheader_t hdr;
                    129: 
                    130:        iv = chunk_alloca(this->aead->get_iv_size(this->aead));
                    131:        if (!generate_iv(this, seq, iv))
                    132:        {
                    133:                return FALSE;
                    134:        }
                    135: 
                    136:        icvlen = this->aead->get_icv_size(this->aead);
                    137:        if (data->len < icvlen)
                    138:        {
                    139:                return FALSE;
                    140:        }
                    141: 
                    142:        hdr.type = TLS_APPLICATION_DATA;
                    143:        htoun16(&hdr.version, TLS_1_2);
                    144:        htoun16(&hdr.length, data->len);
                    145: 
                    146:        assoc = chunk_from_thing(hdr);
                    147:        if (!this->aead->decrypt(this->aead, *data, assoc, iv, NULL))
                    148:        {
                    149:                return FALSE;
                    150:        }
                    151:        data->len -= icvlen;
                    152: 
                    153:        while (data->len && !data->ptr[data->len-1])
                    154:        {       /* ignore any padding */
                    155:                data->len--;
                    156:        }
                    157:        if (data->len < 1)
                    158:        {
                    159:                return FALSE;
                    160:        }
                    161:        *type = data->ptr[data->len-1];
                    162:        data->len--;
                    163:        return TRUE;
                    164: }
                    165: 
                    166: METHOD(tls_aead_t, get_mac_key_size, size_t,
                    167:        private_tls_aead_t *this)
                    168: {
                    169:        return 0;
                    170: }
                    171: 
                    172: METHOD(tls_aead_t, get_encr_key_size, size_t,
                    173:        private_tls_aead_t *this)
                    174: {
                    175:        /* our AEAD implementations add the salt length here, so subtract it */
                    176:        return this->aead->get_key_size(this->aead) - this->salt;
                    177: }
                    178: 
                    179: METHOD(tls_aead_t, get_iv_size, size_t,
                    180:        private_tls_aead_t *this)
                    181: {
                    182:        /* analogous to the change above, we add the salt length here */
                    183:        return this->aead->get_iv_size(this->aead) + this->salt;
                    184: }
                    185: 
                    186: METHOD(tls_aead_t, set_keys, bool,
                    187:        private_tls_aead_t *this, chunk_t mac, chunk_t encr, chunk_t iv)
                    188: {
                    189:        chunk_t key, salt;
                    190:        bool success;
                    191: 
                    192:        if (mac.len || iv.len < this->salt)
                    193:        {
                    194:                return FALSE;
                    195:        }
                    196: 
                    197:        /* we have to recombine the keys as our AEAD implementations expect the
                    198:         * salt as part of the key */
                    199:        chunk_clear(&this->iv);
                    200:        chunk_split(iv, "ma", this->salt, &salt, iv.len - this->salt, &this->iv);
                    201:        key = chunk_cata("cc", encr, salt);
                    202:        success = this->aead->set_key(this->aead, key);
                    203:        memwipe(key.ptr, key.len);
                    204:        return success;
                    205: }
                    206: 
                    207: METHOD(tls_aead_t, destroy, void,
                    208:        private_tls_aead_t *this)
                    209: {
                    210:        this->aead->destroy(this->aead);
                    211:        chunk_clear(&this->iv);
                    212:        free(this);
                    213: }
                    214: 
                    215: /*
                    216:  * Described in header
                    217:  */
                    218: tls_aead_t *tls_aead_create_seq(encryption_algorithm_t encr, size_t encr_size)
                    219: {
                    220:        private_tls_aead_t *this;
                    221:        size_t salt;
                    222: 
                    223:        switch (encr)
                    224:        {
                    225:                case ENCR_AES_GCM_ICV16:
                    226:                case ENCR_CHACHA20_POLY1305:
                    227:                        salt = 4;
                    228:                        break;
                    229:                case ENCR_AES_CCM_ICV8:
                    230:                case ENCR_AES_CCM_ICV16:
                    231:                        salt = 3;
                    232:                        break;
                    233:                default:
                    234:                        return NULL;
                    235:        }
                    236: 
                    237:        INIT(this,
                    238:                .public = {
                    239:                        .encrypt = _encrypt,
                    240:                        .decrypt = _decrypt,
                    241:                        .get_mac_key_size = _get_mac_key_size,
                    242:                        .get_encr_key_size = _get_encr_key_size,
                    243:                        .get_iv_size = _get_iv_size,
                    244:                        .set_keys = _set_keys,
                    245:                        .destroy = _destroy,
                    246:                },
                    247:                .aead = lib->crypto->create_aead(lib->crypto, encr, encr_size, salt),
                    248:                .salt = salt,
                    249:        );
                    250: 
                    251:        if (!this->aead)
                    252:        {
                    253:                free(this);
                    254:                return NULL;
                    255:        }
                    256: 
                    257:        if (this->aead->get_block_size(this->aead) != 1)
                    258:        {       /* TLS does not define any padding scheme for AEAD */
                    259:                destroy(this);
                    260:                return NULL;
                    261:        }
                    262: 
                    263:        return &this->public;
                    264: }

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