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

1.1       misho       1: /*
1.1.1.2 ! misho       2:  * Copyright (C) 2020 Tobias Brunner
        !             3:  * HSR Hochschule fuer Technik Rapperswil
        !             4:  *
1.1       misho       5:  * Copyright (C) 2019 Sean Parkinson, wolfSSL Inc.
                      6:  *
                      7:  * Permission is hereby granted, free of charge, to any person obtaining a copy
                      8:  * of this software and associated documentation files (the "Software"), to deal
                      9:  * in the Software without restriction, including without limitation the rights
                     10:  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
                     11:  * copies of the Software, and to permit persons to whom the Software is
                     12:  * furnished to do so, subject to the following conditions:
                     13:  *
                     14:  * The above copyright notice and this permission notice shall be included in
                     15:  * all copies or substantial portions of the Software.
                     16:  *
                     17:  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
                     18:  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
                     19:  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
                     20:  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
                     21:  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
                     22:  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
                     23:  * THE SOFTWARE.
                     24:  */
                     25: 
                     26: #include "wolfssl_common.h"
                     27: 
1.1.1.2 ! misho      28: #if defined(HAVE_CURVE25519) || defined(HAVE_CURVE448)
1.1       misho      29: 
                     30: #include "wolfssl_x_diffie_hellman.h"
                     31: 
                     32: #include <utils/debug.h>
                     33: 
1.1.1.2 ! misho      34: #ifdef HAVE_CURVE25519
1.1       misho      35: #include <wolfssl/wolfcrypt/curve25519.h>
1.1.1.2 ! misho      36: #endif
        !            37: #ifdef HAVE_CURVE448
        !            38: #include <wolfssl/wolfcrypt/curve448.h>
        !            39: #endif
        !            40: 
1.1       misho      41: #include <wolfssl/wolfcrypt/fe_operations.h>
                     42: 
                     43: typedef struct private_diffie_hellman_t private_diffie_hellman_t;
                     44: 
                     45: /**
                     46:  * Private data
                     47:  */
                     48: struct private_diffie_hellman_t {
                     49:        /**
                     50:         * Public interface.
                     51:         */
                     52:        diffie_hellman_t public;
                     53: 
                     54:        /**
                     55:         * Diffie Hellman group number.
                     56:         */
                     57:        diffie_hellman_group_t group;
                     58: 
                     59:        /**
                     60:         * Private (public) key
                     61:         */
1.1.1.2 ! misho      62:        union {
        !            63: #ifdef HAVE_CURVE25519
        !            64:                curve25519_key key25519;
        !            65: #endif
        !            66: #ifdef HAVE_CURVE448
        !            67:                curve448_key key448;
        !            68: #endif
        !            69:        } key;
1.1       misho      70: 
                     71:        /**
                     72:         * Shared secret
                     73:         */
                     74:        chunk_t shared_secret;
                     75: };
                     76: 
1.1.1.2 ! misho      77: #ifdef HAVE_CURVE25519
1.1       misho      78: 
1.1.1.2 ! misho      79: METHOD(diffie_hellman_t, set_other_public_value_25519, bool,
1.1       misho      80:        private_diffie_hellman_t *this, chunk_t value)
                     81: {
1.1.1.2 ! misho      82:        word32 len = CURVE25519_KEYSIZE;
1.1       misho      83:        curve25519_key pub;
                     84:        int ret;
                     85: 
                     86:        if (!diffie_hellman_verify_value(this->group, value))
                     87:        {
                     88:                return FALSE;
                     89:        }
                     90: 
                     91:        ret = wc_curve25519_init(&pub);
                     92:        if (ret != 0)
                     93:        {
                     94:                DBG1(DBG_LIB, "%N public key initialization failed",
                     95:                         diffie_hellman_group_names, this->group);
                     96:                return FALSE;
                     97:        }
                     98: 
                     99:        ret = wc_curve25519_import_public_ex(value.ptr, value.len, &pub,
                    100:                                                                                 EC25519_LITTLE_ENDIAN);
                    101:        if (ret != 0)
                    102:        {
                    103:                DBG1(DBG_LIB, "%N public value is malformed",
                    104:                         diffie_hellman_group_names, this->group);
                    105:                return FALSE;
                    106:        }
                    107: 
                    108:        chunk_clear(&this->shared_secret);
1.1.1.2 ! misho     109:        this->shared_secret = chunk_alloc(len);
        !           110:        if (wc_curve25519_shared_secret_ex(&this->key.key25519, &pub,
        !           111:                                        this->shared_secret.ptr, &len, EC25519_LITTLE_ENDIAN) != 0)
1.1       misho     112:        {
                    113:                DBG1(DBG_LIB, "%N shared secret computation failed",
                    114:                         diffie_hellman_group_names, this->group);
                    115:                chunk_clear(&this->shared_secret);
                    116:                wc_curve25519_free(&pub);
                    117:                return FALSE;
                    118:        }
                    119:        wc_curve25519_free(&pub);
                    120:        return TRUE;
                    121: }
                    122: 
1.1.1.2 ! misho     123: METHOD(diffie_hellman_t, get_my_public_value_25519, bool,
1.1       misho     124:        private_diffie_hellman_t *this, chunk_t *value)
                    125: {
                    126:        word32 len = CURVE25519_KEYSIZE;
                    127: 
                    128:        *value = chunk_alloc(len);
1.1.1.2 ! misho     129:        if (wc_curve25519_export_public_ex(&this->key.key25519, value->ptr, &len,
1.1       misho     130:                                                                           EC25519_LITTLE_ENDIAN) != 0)
                    131:        {
                    132:                chunk_free(value);
                    133:                return FALSE;
                    134:        }
                    135:        return TRUE;
                    136: }
                    137: 
1.1.1.2 ! misho     138: METHOD(diffie_hellman_t, set_private_value_25519, bool,
1.1       misho     139:        private_diffie_hellman_t *this, chunk_t value)
                    140: {
                    141:        curve25519_key pub;
                    142:        u_char basepoint[CURVE25519_KEYSIZE] = {9};
                    143:        word32 len = CURVE25519_KEYSIZE;
                    144:        int ret;
                    145: 
                    146:        ret = wc_curve25519_init(&pub);
                    147:        /* create base point for calculating public key */
                    148:        if (ret == 0)
                    149:        {
                    150:                ret = wc_curve25519_import_public_ex(basepoint, CURVE25519_KEYSIZE,
                    151:                                                                                         &pub, EC25519_LITTLE_ENDIAN);
                    152:        }
                    153:        if (ret == 0)
                    154:        {
1.1.1.2 ! misho     155:                ret = wc_curve25519_import_private_ex(value.ptr, value.len,
        !           156:                                                                        &this->key.key25519, EC25519_LITTLE_ENDIAN);
        !           157:        }
        !           158:        if (ret == 0)
        !           159:        {
        !           160:                ret = wc_curve25519_shared_secret_ex(&this->key.key25519, &pub,
        !           161:                                                                                         this->key.key25519.p.point, &len,
        !           162:                                                                                         EC25519_LITTLE_ENDIAN);
        !           163:        }
        !           164:        return ret == 0;
        !           165: }
        !           166: 
        !           167: #endif /* HAVE_CURVE25519 */
        !           168: 
        !           169: #ifdef HAVE_CURVE448
        !           170: 
        !           171: METHOD(diffie_hellman_t, set_other_public_value_448, bool,
        !           172:        private_diffie_hellman_t *this, chunk_t value)
        !           173: {
        !           174:        word32 len = CURVE448_KEY_SIZE;
        !           175:        curve448_key pub;
        !           176:        int ret;
        !           177: 
        !           178:        if (!diffie_hellman_verify_value(this->group, value))
        !           179:        {
        !           180:                return FALSE;
        !           181:        }
        !           182: 
        !           183:        ret = wc_curve448_init(&pub);
        !           184:        if (ret != 0)
        !           185:        {
        !           186:                DBG1(DBG_LIB, "%N public key initialization failed",
        !           187:                         diffie_hellman_group_names, this->group);
        !           188:                return FALSE;
        !           189:        }
        !           190: 
        !           191:        ret = wc_curve448_import_public_ex(value.ptr, value.len, &pub,
        !           192:                                                                           EC448_LITTLE_ENDIAN);
        !           193:        if (ret != 0)
        !           194:        {
        !           195:                DBG1(DBG_LIB, "%N public value is malformed",
        !           196:                         diffie_hellman_group_names, this->group);
        !           197:                return FALSE;
        !           198:        }
        !           199: 
        !           200:        chunk_clear(&this->shared_secret);
        !           201:        this->shared_secret = chunk_alloc(len);
        !           202:        if (wc_curve448_shared_secret_ex(&this->key.key448, &pub,
        !           203:                                        this->shared_secret.ptr, &len, EC448_LITTLE_ENDIAN) != 0)
        !           204:        {
        !           205:                DBG1(DBG_LIB, "%N shared secret computation failed",
        !           206:                         diffie_hellman_group_names, this->group);
        !           207:                chunk_clear(&this->shared_secret);
        !           208:                wc_curve448_free(&pub);
        !           209:                return FALSE;
        !           210:        }
        !           211:        wc_curve448_free(&pub);
        !           212:        return TRUE;
        !           213: }
        !           214: 
        !           215: METHOD(diffie_hellman_t, get_my_public_value_448, bool,
        !           216:        private_diffie_hellman_t *this, chunk_t *value)
        !           217: {
        !           218:        word32 len = CURVE448_KEY_SIZE;
        !           219: 
        !           220:        *value = chunk_alloc(len);
        !           221:        if (wc_curve448_export_public_ex(&this->key.key448, value->ptr, &len,
        !           222:                                                                         EC448_LITTLE_ENDIAN) != 0)
        !           223:        {
        !           224:                chunk_free(value);
        !           225:                return FALSE;
        !           226:        }
        !           227:        return TRUE;
        !           228: }
        !           229: 
        !           230: METHOD(diffie_hellman_t, set_private_value_448, bool,
        !           231:        private_diffie_hellman_t *this, chunk_t value)
        !           232: {
        !           233:        curve448_key pub;
        !           234:        u_char basepoint[CURVE448_KEY_SIZE] = {5};
        !           235:        word32 len = CURVE448_KEY_SIZE;
        !           236:        int ret;
        !           237: 
        !           238:        ret = wc_curve448_init(&pub);
        !           239:        /* create base point for calculating public key */
        !           240:        if (ret == 0)
        !           241:        {
        !           242:                ret = wc_curve448_import_public_ex(basepoint, CURVE448_KEY_SIZE,
        !           243:                                                                                   &pub, EC448_LITTLE_ENDIAN);
        !           244:        }
        !           245:        if (ret == 0)
        !           246:        {
        !           247:                ret = wc_curve448_import_private_ex(value.ptr, value.len,
        !           248:                                                                                &this->key.key448, EC448_LITTLE_ENDIAN);
1.1       misho     249:        }
                    250:        if (ret == 0)
                    251:        {
1.1.1.2 ! misho     252:                ret = wc_curve448_shared_secret_ex(&this->key.key448, &pub,
        !           253:                                                                                   this->key.key448.p, &len,
        !           254:                                                                                   EC448_LITTLE_ENDIAN);
1.1       misho     255:        }
                    256:        return ret == 0;
                    257: }
                    258: 
1.1.1.2 ! misho     259: #endif /* HAVE_CURVE448 */
        !           260: 
1.1       misho     261: METHOD(diffie_hellman_t, get_shared_secret, bool,
                    262:        private_diffie_hellman_t *this, chunk_t *secret)
                    263: {
                    264:        if (!this->shared_secret.len)
                    265:        {
                    266:                return FALSE;
                    267:        }
                    268:        *secret = chunk_clone(this->shared_secret);
                    269:        return TRUE;
                    270: }
                    271: 
                    272: METHOD(diffie_hellman_t, get_dh_group, diffie_hellman_group_t,
                    273:        private_diffie_hellman_t *this)
                    274: {
                    275:        return this->group;
                    276: }
                    277: 
                    278: METHOD(diffie_hellman_t, destroy, void,
                    279:        private_diffie_hellman_t *this)
                    280: {
1.1.1.2 ! misho     281:        if (this->group == CURVE_25519)
        !           282:        {
        !           283: #ifdef HAVE_CURVE25519
        !           284:                wc_curve25519_free(&this->key.key25519);
        !           285: #endif
        !           286:        }
        !           287:        else if (this->group == CURVE_448)
        !           288:        {
        !           289: #ifdef HAVE_CURVE448
        !           290:                wc_curve448_free(&this->key.key448);
        !           291: #endif
        !           292:        }
1.1       misho     293:        chunk_clear(&this->shared_secret);
                    294:        free(this);
                    295: }
                    296: 
                    297: /*
                    298:  * Described in header
                    299:  */
                    300: diffie_hellman_t *wolfssl_x_diffie_hellman_create(diffie_hellman_group_t group)
                    301: {
                    302:        private_diffie_hellman_t *this;
                    303:        WC_RNG rng;
1.1.1.2 ! misho     304:        int ret = -1;
1.1       misho     305: 
                    306:        INIT(this,
                    307:                .public = {
                    308:                        .get_shared_secret = _get_shared_secret,
                    309:                        .get_dh_group = _get_dh_group,
                    310:                        .destroy = _destroy,
                    311:                },
                    312:                .group = group,
                    313:        );
                    314: 
                    315:        if (wc_InitRng(&rng) != 0)
                    316:        {
                    317:                DBG1(DBG_LIB, "initializing a random number generator failed");
                    318:                destroy(this);
                    319:                return NULL;
                    320:        }
1.1.1.2 ! misho     321: 
        !           322:        if (group == CURVE_25519)
        !           323:        {
        !           324: #ifdef HAVE_CURVE25519
        !           325:                this->public.set_other_public_value = _set_other_public_value_25519;
        !           326:                this->public.get_my_public_value = _get_my_public_value_25519;
        !           327:                this->public.set_private_value = _set_private_value_25519;
        !           328: 
        !           329:                if (wc_curve25519_init(&this->key.key25519) != 0)
        !           330:                {
        !           331:                        DBG1(DBG_LIB, "initializing key failed");
        !           332:                        free(this);
        !           333:                        return NULL;
        !           334:                }
        !           335:                ret = wc_curve25519_make_key(&rng, CURVE25519_KEYSIZE,
        !           336:                                                                         &this->key.key25519);
        !           337: #endif
        !           338:        }
        !           339:        else if (group == CURVE_448)
        !           340:        {
        !           341: #ifdef HAVE_CURVE448
        !           342:                this->public.set_other_public_value = _set_other_public_value_448;
        !           343:                this->public.get_my_public_value = _get_my_public_value_448;
        !           344:                this->public.set_private_value = _set_private_value_448;
        !           345: 
        !           346:                if (wc_curve448_init(&this->key.key448) != 0)
        !           347:                {
        !           348:                        DBG1(DBG_LIB, "initializing key failed");
        !           349:                        free(this);
        !           350:                        return NULL;
        !           351:                }
        !           352:                ret = wc_curve448_make_key(&rng, CURVE448_KEY_SIZE, &this->key.key448);
        !           353: #endif
        !           354:        }
1.1       misho     355:        wc_FreeRng(&rng);
                    356:        if (ret != 0)
                    357:        {
                    358:                DBG1(DBG_LIB, "making a key failed");
                    359:                destroy(this);
                    360:                return NULL;
                    361:        }
                    362:        return &this->public;
                    363: }
                    364: 
1.1.1.2 ! misho     365: #endif /* HAVE_CURVE25519 || HAVE_CURVE448 */

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