Annotation of embedaddon/strongswan/src/libtls/tls_aead_seq.c, revision 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>