Annotation of embedaddon/strongswan/src/libstrongswan/plugins/wolfssl/wolfssl_x_diffie_hellman.c, revision 1.1

1.1     ! misho       1: /*
        !             2:  * Copyright (C) 2019 Sean Parkinson, wolfSSL Inc.
        !             3:  *
        !             4:  * Permission is hereby granted, free of charge, to any person obtaining a copy
        !             5:  * of this software and associated documentation files (the "Software"), to deal
        !             6:  * in the Software without restriction, including without limitation the rights
        !             7:  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
        !             8:  * copies of the Software, and to permit persons to whom the Software is
        !             9:  * furnished to do so, subject to the following conditions:
        !            10:  *
        !            11:  * The above copyright notice and this permission notice shall be included in
        !            12:  * all copies or substantial portions of the Software.
        !            13:  *
        !            14:  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
        !            15:  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
        !            16:  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
        !            17:  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
        !            18:  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
        !            19:  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
        !            20:  * THE SOFTWARE.
        !            21:  */
        !            22: 
        !            23: #include "wolfssl_common.h"
        !            24: 
        !            25: #ifdef HAVE_CURVE25519
        !            26: 
        !            27: #include "wolfssl_x_diffie_hellman.h"
        !            28: 
        !            29: #include <utils/debug.h>
        !            30: 
        !            31: #include <wolfssl/wolfcrypt/curve25519.h>
        !            32: #include <wolfssl/wolfcrypt/fe_operations.h>
        !            33: 
        !            34: typedef struct private_diffie_hellman_t private_diffie_hellman_t;
        !            35: 
        !            36: /**
        !            37:  * Private data
        !            38:  */
        !            39: struct private_diffie_hellman_t {
        !            40:        /**
        !            41:         * Public interface.
        !            42:         */
        !            43:        diffie_hellman_t public;
        !            44: 
        !            45:        /**
        !            46:         * Diffie Hellman group number.
        !            47:         */
        !            48:        diffie_hellman_group_t group;
        !            49: 
        !            50:        /**
        !            51:         * Private (public) key
        !            52:         */
        !            53:        curve25519_key key;
        !            54: 
        !            55:        /**
        !            56:         * Shared secret
        !            57:         */
        !            58:        chunk_t shared_secret;
        !            59: };
        !            60: 
        !            61: /**
        !            62:  * Compute the shared secret
        !            63:  */
        !            64: static bool compute_shared_key(private_diffie_hellman_t *this,
        !            65:                                                           curve25519_key *pub, chunk_t *shared_secret)
        !            66: {
        !            67:        word32 len = CURVE25519_KEYSIZE;
        !            68:        int ret;
        !            69: 
        !            70:        *shared_secret = chunk_alloc(len);
        !            71:        ret = wc_curve25519_shared_secret_ex(&this->key, pub, shared_secret->ptr,
        !            72:                                                                                 &len, EC25519_LITTLE_ENDIAN);
        !            73:        return ret == 0;
        !            74: }
        !            75: 
        !            76: METHOD(diffie_hellman_t, set_other_public_value, bool,
        !            77:        private_diffie_hellman_t *this, chunk_t value)
        !            78: {
        !            79:        curve25519_key pub;
        !            80:        int ret;
        !            81: 
        !            82:        if (!diffie_hellman_verify_value(this->group, value))
        !            83:        {
        !            84:                return FALSE;
        !            85:        }
        !            86: 
        !            87:        ret = wc_curve25519_init(&pub);
        !            88:        if (ret != 0)
        !            89:        {
        !            90:                DBG1(DBG_LIB, "%N public key initialization failed",
        !            91:                         diffie_hellman_group_names, this->group);
        !            92:                return FALSE;
        !            93:        }
        !            94: 
        !            95:        ret = wc_curve25519_import_public_ex(value.ptr, value.len, &pub,
        !            96:                                                                                 EC25519_LITTLE_ENDIAN);
        !            97:        if (ret != 0)
        !            98:        {
        !            99:                DBG1(DBG_LIB, "%N public value is malformed",
        !           100:                         diffie_hellman_group_names, this->group);
        !           101:                return FALSE;
        !           102:        }
        !           103: 
        !           104:        chunk_clear(&this->shared_secret);
        !           105: 
        !           106:        if (!compute_shared_key(this, &pub, &this->shared_secret))
        !           107:        {
        !           108:                DBG1(DBG_LIB, "%N shared secret computation failed",
        !           109:                         diffie_hellman_group_names, this->group);
        !           110:                chunk_clear(&this->shared_secret);
        !           111:                wc_curve25519_free(&pub);
        !           112:                return FALSE;
        !           113:        }
        !           114:        wc_curve25519_free(&pub);
        !           115:        return TRUE;
        !           116: }
        !           117: 
        !           118: METHOD(diffie_hellman_t, get_my_public_value, bool,
        !           119:        private_diffie_hellman_t *this, chunk_t *value)
        !           120: {
        !           121:        word32 len = CURVE25519_KEYSIZE;
        !           122: 
        !           123:        *value = chunk_alloc(len);
        !           124:        if (wc_curve25519_export_public_ex(&this->key, value->ptr, &len,
        !           125:                                                                           EC25519_LITTLE_ENDIAN) != 0)
        !           126:        {
        !           127:                chunk_free(value);
        !           128:                return FALSE;
        !           129:        }
        !           130:        return TRUE;
        !           131: }
        !           132: 
        !           133: METHOD(diffie_hellman_t, set_private_value, bool,
        !           134:        private_diffie_hellman_t *this, chunk_t value)
        !           135: {
        !           136:        curve25519_key pub;
        !           137:        u_char basepoint[CURVE25519_KEYSIZE] = {9};
        !           138:        word32 len = CURVE25519_KEYSIZE;
        !           139:        int ret;
        !           140: 
        !           141:        ret = wc_curve25519_init(&pub);
        !           142:        /* create base point for calculating public key */
        !           143:        if (ret == 0)
        !           144:        {
        !           145:                ret = wc_curve25519_import_public_ex(basepoint, CURVE25519_KEYSIZE,
        !           146:                                                                                         &pub, EC25519_LITTLE_ENDIAN);
        !           147:        }
        !           148:        if (ret == 0)
        !           149:        {
        !           150:                ret = wc_curve25519_import_private_ex(value.ptr, value.len, &this->key,
        !           151:                                                                                          EC25519_LITTLE_ENDIAN);
        !           152:        }
        !           153:        if (ret == 0)
        !           154:        {
        !           155:                ret = wc_curve25519_shared_secret_ex(&this->key, &pub,
        !           156:                                                                this->key.p.point, &len, EC25519_LITTLE_ENDIAN);
        !           157:        }
        !           158:        return ret == 0;
        !           159: }
        !           160: 
        !           161: METHOD(diffie_hellman_t, get_shared_secret, bool,
        !           162:        private_diffie_hellman_t *this, chunk_t *secret)
        !           163: {
        !           164:        if (!this->shared_secret.len)
        !           165:        {
        !           166:                return FALSE;
        !           167:        }
        !           168:        *secret = chunk_clone(this->shared_secret);
        !           169:        return TRUE;
        !           170: }
        !           171: 
        !           172: METHOD(diffie_hellman_t, get_dh_group, diffie_hellman_group_t,
        !           173:        private_diffie_hellman_t *this)
        !           174: {
        !           175:        return this->group;
        !           176: }
        !           177: 
        !           178: METHOD(diffie_hellman_t, destroy, void,
        !           179:        private_diffie_hellman_t *this)
        !           180: {
        !           181:        wc_curve25519_free(&this->key);
        !           182:        chunk_clear(&this->shared_secret);
        !           183:        free(this);
        !           184: }
        !           185: 
        !           186: /*
        !           187:  * Described in header
        !           188:  */
        !           189: diffie_hellman_t *wolfssl_x_diffie_hellman_create(diffie_hellman_group_t group)
        !           190: {
        !           191:        private_diffie_hellman_t *this;
        !           192:        WC_RNG rng;
        !           193:        int ret;
        !           194: 
        !           195:        INIT(this,
        !           196:                .public = {
        !           197:                        .get_shared_secret = _get_shared_secret,
        !           198:                        .set_other_public_value = _set_other_public_value,
        !           199:                        .get_my_public_value = _get_my_public_value,
        !           200:                        .set_private_value = _set_private_value,
        !           201:                        .get_dh_group = _get_dh_group,
        !           202:                        .destroy = _destroy,
        !           203:                },
        !           204:                .group = group,
        !           205:        );
        !           206: 
        !           207:        if (wc_curve25519_init(&this->key) != 0)
        !           208:        {
        !           209:                DBG1(DBG_LIB, "initializing key failed");
        !           210:                free(this);
        !           211:                return NULL;
        !           212:        }
        !           213: 
        !           214:        if (wc_InitRng(&rng) != 0)
        !           215:        {
        !           216:                DBG1(DBG_LIB, "initializing a random number generator failed");
        !           217:                destroy(this);
        !           218:                return NULL;
        !           219:        }
        !           220:        ret = wc_curve25519_make_key(&rng, CURVE25519_KEYSIZE, &this->key);
        !           221:        wc_FreeRng(&rng);
        !           222:        if (ret != 0)
        !           223:        {
        !           224:                DBG1(DBG_LIB, "making a key failed");
        !           225:                destroy(this);
        !           226:                return NULL;
        !           227:        }
        !           228:        return &this->public;
        !           229: }
        !           230: 
        !           231: #endif /* HAVE_CURVE25519 */

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