From: Tobias Brunner Date: Thu, 23 Apr 2020 08:26:33 +0000 (+0200) Subject: wolfssl: Add support for x448 Diffie-Hellman X-Git-Tag: 5.9.0dr1~28 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=59a987b8f368783530ed4996b7958c247865e515;p=thirdparty%2Fstrongswan.git wolfssl: Add support for x448 Diffie-Hellman --- diff --git a/src/libstrongswan/plugins/wolfssl/wolfssl_plugin.c b/src/libstrongswan/plugins/wolfssl/wolfssl_plugin.c index 925f08ee37..d692136396 100644 --- a/src/libstrongswan/plugins/wolfssl/wolfssl_plugin.c +++ b/src/libstrongswan/plugins/wolfssl/wolfssl_plugin.c @@ -377,10 +377,15 @@ METHOD(plugin_t, get_features, int, #endif #endif /* HAVE_ECC_VERIFY */ #endif /* HAVE_ECC */ -#ifdef HAVE_CURVE25519 +#if defined (HAVE_CURVE25519) || defined(HAVE_CURVE448) PLUGIN_REGISTER(DH, wolfssl_x_diffie_hellman_create), + #ifdef HAVE_CURVE25519 PLUGIN_PROVIDE(DH, CURVE_25519), -#endif + #endif + #ifdef HAVE_CURVE448 + PLUGIN_PROVIDE(DH, CURVE_448), + #endif +#endif /* HAVE_CURVE25519 || HAVE_CURVE448 */ #ifdef HAVE_ED25519 /* EdDSA private/public key loading */ PLUGIN_REGISTER(PUBKEY, wolfssl_ed_public_key_load, TRUE), diff --git a/src/libstrongswan/plugins/wolfssl/wolfssl_x_diffie_hellman.c b/src/libstrongswan/plugins/wolfssl/wolfssl_x_diffie_hellman.c index 5c21eb66c2..7325395fcb 100644 --- a/src/libstrongswan/plugins/wolfssl/wolfssl_x_diffie_hellman.c +++ b/src/libstrongswan/plugins/wolfssl/wolfssl_x_diffie_hellman.c @@ -1,4 +1,7 @@ /* + * Copyright (C) 2020 Tobias Brunner + * HSR Hochschule fuer Technik Rapperswil + * * Copyright (C) 2019 Sean Parkinson, wolfSSL Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy @@ -22,13 +25,19 @@ #include "wolfssl_common.h" -#ifdef HAVE_CURVE25519 +#if defined(HAVE_CURVE25519) || defined(HAVE_CURVE448) #include "wolfssl_x_diffie_hellman.h" #include +#ifdef HAVE_CURVE25519 #include +#endif +#ifdef HAVE_CURVE448 +#include +#endif + #include typedef struct private_diffie_hellman_t private_diffie_hellman_t; @@ -50,7 +59,14 @@ struct private_diffie_hellman_t { /** * Private (public) key */ - curve25519_key key; + union { +#ifdef HAVE_CURVE25519 + curve25519_key key25519; +#endif +#ifdef HAVE_CURVE448 + curve448_key key448; +#endif + } key; /** * Shared secret @@ -58,24 +74,12 @@ struct private_diffie_hellman_t { chunk_t shared_secret; }; -/** - * Compute the shared secret - */ -static bool compute_shared_key(private_diffie_hellman_t *this, - curve25519_key *pub, chunk_t *shared_secret) -{ - word32 len = CURVE25519_KEYSIZE; - int ret; - - *shared_secret = chunk_alloc(len); - ret = wc_curve25519_shared_secret_ex(&this->key, pub, shared_secret->ptr, - &len, EC25519_LITTLE_ENDIAN); - return ret == 0; -} +#ifdef HAVE_CURVE25519 -METHOD(diffie_hellman_t, set_other_public_value, bool, +METHOD(diffie_hellman_t, set_other_public_value_25519, bool, private_diffie_hellman_t *this, chunk_t value) { + word32 len = CURVE25519_KEYSIZE; curve25519_key pub; int ret; @@ -102,8 +106,9 @@ METHOD(diffie_hellman_t, set_other_public_value, bool, } chunk_clear(&this->shared_secret); - - if (!compute_shared_key(this, &pub, &this->shared_secret)) + this->shared_secret = chunk_alloc(len); + if (wc_curve25519_shared_secret_ex(&this->key.key25519, &pub, + this->shared_secret.ptr, &len, EC25519_LITTLE_ENDIAN) != 0) { DBG1(DBG_LIB, "%N shared secret computation failed", diffie_hellman_group_names, this->group); @@ -115,13 +120,13 @@ METHOD(diffie_hellman_t, set_other_public_value, bool, return TRUE; } -METHOD(diffie_hellman_t, get_my_public_value, bool, +METHOD(diffie_hellman_t, get_my_public_value_25519, bool, private_diffie_hellman_t *this, chunk_t *value) { word32 len = CURVE25519_KEYSIZE; *value = chunk_alloc(len); - if (wc_curve25519_export_public_ex(&this->key, value->ptr, &len, + if (wc_curve25519_export_public_ex(&this->key.key25519, value->ptr, &len, EC25519_LITTLE_ENDIAN) != 0) { chunk_free(value); @@ -130,7 +135,7 @@ METHOD(diffie_hellman_t, get_my_public_value, bool, return TRUE; } -METHOD(diffie_hellman_t, set_private_value, bool, +METHOD(diffie_hellman_t, set_private_value_25519, bool, private_diffie_hellman_t *this, chunk_t value) { curve25519_key pub; @@ -147,17 +152,112 @@ METHOD(diffie_hellman_t, set_private_value, bool, } if (ret == 0) { - ret = wc_curve25519_import_private_ex(value.ptr, value.len, &this->key, - EC25519_LITTLE_ENDIAN); + ret = wc_curve25519_import_private_ex(value.ptr, value.len, + &this->key.key25519, EC25519_LITTLE_ENDIAN); + } + if (ret == 0) + { + ret = wc_curve25519_shared_secret_ex(&this->key.key25519, &pub, + this->key.key25519.p.point, &len, + EC25519_LITTLE_ENDIAN); + } + return ret == 0; +} + +#endif /* HAVE_CURVE25519 */ + +#ifdef HAVE_CURVE448 + +METHOD(diffie_hellman_t, set_other_public_value_448, bool, + private_diffie_hellman_t *this, chunk_t value) +{ + word32 len = CURVE448_KEY_SIZE; + curve448_key pub; + int ret; + + if (!diffie_hellman_verify_value(this->group, value)) + { + return FALSE; + } + + ret = wc_curve448_init(&pub); + if (ret != 0) + { + DBG1(DBG_LIB, "%N public key initialization failed", + diffie_hellman_group_names, this->group); + return FALSE; + } + + ret = wc_curve448_import_public_ex(value.ptr, value.len, &pub, + EC448_LITTLE_ENDIAN); + if (ret != 0) + { + DBG1(DBG_LIB, "%N public value is malformed", + diffie_hellman_group_names, this->group); + return FALSE; + } + + chunk_clear(&this->shared_secret); + this->shared_secret = chunk_alloc(len); + if (wc_curve448_shared_secret_ex(&this->key.key448, &pub, + this->shared_secret.ptr, &len, EC448_LITTLE_ENDIAN) != 0) + { + DBG1(DBG_LIB, "%N shared secret computation failed", + diffie_hellman_group_names, this->group); + chunk_clear(&this->shared_secret); + wc_curve448_free(&pub); + return FALSE; + } + wc_curve448_free(&pub); + return TRUE; +} + +METHOD(diffie_hellman_t, get_my_public_value_448, bool, + private_diffie_hellman_t *this, chunk_t *value) +{ + word32 len = CURVE448_KEY_SIZE; + + *value = chunk_alloc(len); + if (wc_curve448_export_public_ex(&this->key.key448, value->ptr, &len, + EC448_LITTLE_ENDIAN) != 0) + { + chunk_free(value); + return FALSE; + } + return TRUE; +} + +METHOD(diffie_hellman_t, set_private_value_448, bool, + private_diffie_hellman_t *this, chunk_t value) +{ + curve448_key pub; + u_char basepoint[CURVE448_KEY_SIZE] = {5}; + word32 len = CURVE448_KEY_SIZE; + int ret; + + ret = wc_curve448_init(&pub); + /* create base point for calculating public key */ + if (ret == 0) + { + ret = wc_curve448_import_public_ex(basepoint, CURVE448_KEY_SIZE, + &pub, EC448_LITTLE_ENDIAN); } if (ret == 0) { - ret = wc_curve25519_shared_secret_ex(&this->key, &pub, - this->key.p.point, &len, EC25519_LITTLE_ENDIAN); + ret = wc_curve448_import_private_ex(value.ptr, value.len, + &this->key.key448, EC448_LITTLE_ENDIAN); + } + if (ret == 0) + { + ret = wc_curve448_shared_secret_ex(&this->key.key448, &pub, + this->key.key448.p, &len, + EC448_LITTLE_ENDIAN); } return ret == 0; } +#endif /* HAVE_CURVE448 */ + METHOD(diffie_hellman_t, get_shared_secret, bool, private_diffie_hellman_t *this, chunk_t *secret) { @@ -178,7 +278,18 @@ METHOD(diffie_hellman_t, get_dh_group, diffie_hellman_group_t, METHOD(diffie_hellman_t, destroy, void, private_diffie_hellman_t *this) { - wc_curve25519_free(&this->key); + if (this->group == CURVE_25519) + { +#ifdef HAVE_CURVE25519 + wc_curve25519_free(&this->key.key25519); +#endif + } + else if (this->group == CURVE_448) + { +#ifdef HAVE_CURVE448 + wc_curve448_free(&this->key.key448); +#endif + } chunk_clear(&this->shared_secret); free(this); } @@ -190,34 +301,57 @@ diffie_hellman_t *wolfssl_x_diffie_hellman_create(diffie_hellman_group_t group) { private_diffie_hellman_t *this; WC_RNG rng; - int ret; + int ret = -1; INIT(this, .public = { .get_shared_secret = _get_shared_secret, - .set_other_public_value = _set_other_public_value, - .get_my_public_value = _get_my_public_value, - .set_private_value = _set_private_value, .get_dh_group = _get_dh_group, .destroy = _destroy, }, .group = group, ); - if (wc_curve25519_init(&this->key) != 0) - { - DBG1(DBG_LIB, "initializing key failed"); - free(this); - return NULL; - } - if (wc_InitRng(&rng) != 0) { DBG1(DBG_LIB, "initializing a random number generator failed"); destroy(this); return NULL; } - ret = wc_curve25519_make_key(&rng, CURVE25519_KEYSIZE, &this->key); + + if (group == CURVE_25519) + { +#ifdef HAVE_CURVE25519 + this->public.set_other_public_value = _set_other_public_value_25519; + this->public.get_my_public_value = _get_my_public_value_25519; + this->public.set_private_value = _set_private_value_25519; + + if (wc_curve25519_init(&this->key.key25519) != 0) + { + DBG1(DBG_LIB, "initializing key failed"); + free(this); + return NULL; + } + ret = wc_curve25519_make_key(&rng, CURVE25519_KEYSIZE, + &this->key.key25519); +#endif + } + else if (group == CURVE_448) + { +#ifdef HAVE_CURVE448 + this->public.set_other_public_value = _set_other_public_value_448; + this->public.get_my_public_value = _get_my_public_value_448; + this->public.set_private_value = _set_private_value_448; + + if (wc_curve448_init(&this->key.key448) != 0) + { + DBG1(DBG_LIB, "initializing key failed"); + free(this); + return NULL; + } + ret = wc_curve448_make_key(&rng, CURVE448_KEY_SIZE, &this->key.key448); +#endif + } wc_FreeRng(&rng); if (ret != 0) { @@ -228,4 +362,4 @@ diffie_hellman_t *wolfssl_x_diffie_hellman_create(diffie_hellman_group_t group) return &this->public; } -#endif /* HAVE_CURVE25519 */ +#endif /* HAVE_CURVE25519 || HAVE_CURVE448 */ diff --git a/src/libstrongswan/plugins/wolfssl/wolfssl_x_diffie_hellman.h b/src/libstrongswan/plugins/wolfssl/wolfssl_x_diffie_hellman.h index 56760e5d2c..91b3e19f18 100644 --- a/src/libstrongswan/plugins/wolfssl/wolfssl_x_diffie_hellman.h +++ b/src/libstrongswan/plugins/wolfssl/wolfssl_x_diffie_hellman.h @@ -21,7 +21,7 @@ */ /** - * Implementation of the X25519 Diffie-Hellman algorithm using wolfSSL. + * Implementation of the X25519/X448 Diffie-Hellman algorithm using wolfSSL. * * @defgroup wolfssl_x_diffie_hellman wolfssl_x_diffie_hellman * @{ @ingroup wolfssl_p