diff options
author | Daiki Ueno <ueno@gnu.org> | 2021-09-23 07:50:38 +0000 |
---|---|---|
committer | Daiki Ueno <ueno@gnu.org> | 2021-09-23 07:50:38 +0000 |
commit | 7a220bf3899f3a32d6ff667d3861d15312ccd35b (patch) | |
tree | 131eb151d1185653a4c34ad345872a980420e4c0 /lib/nettle | |
parent | 970000abfe3f88a8659da084852db258310246fd (diff) | |
parent | a00a79ddf41eb14d56bdea076b5c252029896431 (diff) | |
download | gnutls-7a220bf3899f3a32d6ff667d3861d15312ccd35b.tar.gz |
Merge branch 'x25519-and-x448' into 'master'
certtool: generate, parse, and manipulate X25519 and X448 pubkeys, privkeys, and certificates
See merge request gnutls/gnutls!1428
Diffstat (limited to 'lib/nettle')
-rw-r--r-- | lib/nettle/pk.c | 67 |
1 files changed, 67 insertions, 0 deletions
diff --git a/lib/nettle/pk.c b/lib/nettle/pk.c index 16d9b4a04c..6af19c459f 100644 --- a/lib/nettle/pk.c +++ b/lib/nettle/pk.c @@ -831,6 +831,19 @@ get_eddsa_curve(gnutls_pk_algorithm_t algo) } } +static inline gnutls_ecc_curve_t +get_ecdh_curve(gnutls_pk_algorithm_t algo) +{ + switch (algo) { + case GNUTLS_PK_ECDH_X25519: + return GNUTLS_ECC_CURVE_X25519; + case GNUTLS_PK_ECDH_X448: + return GNUTLS_ECC_CURVE_X448; + default: + return gnutls_assert_val(GNUTLS_ECC_CURVE_INVALID); + } +} + static inline int eddsa_sign(gnutls_pk_algorithm_t algo, const uint8_t *pub, @@ -1789,6 +1802,8 @@ wrap_nettle_pk_generate_params(gnutls_pk_algorithm_t algo, case GNUTLS_PK_ECDSA: case GNUTLS_PK_EDDSA_ED25519: case GNUTLS_PK_EDDSA_ED448: + case GNUTLS_PK_ECDH_X25519: + case GNUTLS_PK_ECDH_X448: #if ENABLE_GOST case GNUTLS_PK_GOST_01: case GNUTLS_PK_GOST_12_256: @@ -3098,6 +3113,34 @@ wrap_nettle_pk_verify_priv_params(gnutls_pk_algorithm_t algo, ret = 0; break; } + case GNUTLS_PK_ECDH_X25519: + case GNUTLS_PK_ECDH_X448: { + gnutls_ecc_curve_t curve; + const gnutls_ecc_curve_entry_st *e; + uint8_t pub[57]; /* can accommodate both curves */ + + curve = get_ecdh_curve(algo); + e = _gnutls_ecc_curve_get_params(curve); + if (e == NULL) + return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); + + if (params->raw_pub.data == NULL) { + return 0; /* nothing to verify */ + } + + if (params->raw_pub.size != e->size) + return gnutls_assert_val(GNUTLS_E_ILLEGAL_PARAMETER); + + ret = edwards_curve_mul_g(algo, pub, params->raw_priv.data); + if (ret < 0) + return ret; + + if (memcmp(params->raw_pub.data, pub, e->size) != 0) + return gnutls_assert_val(GNUTLS_E_ILLEGAL_PARAMETER); + + ret = 0; + break; + } #if ENABLE_GOST case GNUTLS_PK_GOST_01: case GNUTLS_PK_GOST_12_256: @@ -3464,6 +3507,30 @@ wrap_nettle_pk_fixup(gnutls_pk_algorithm_t algo, } params->raw_pub.size = params->raw_priv.size; + } else if (algo == GNUTLS_PK_ECDH_X25519 || + algo == GNUTLS_PK_ECDH_X448) { + if (unlikely(get_ecdh_curve(algo) != params->curve)) + return gnutls_assert_val(GNUTLS_E_ECC_UNSUPPORTED_CURVE); + + if (params->raw_priv.data == NULL) + return gnutls_assert_val(GNUTLS_E_PK_INVALID_PRIVKEY); + + if (params->raw_pub.data == NULL) { + params->raw_pub.data = gnutls_malloc(params->raw_priv.size); + } + + if (params->raw_pub.data == NULL) + return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); + + ret = edwards_curve_mul_g(algo, + params->raw_pub.data, + params->raw_priv.data); + if (ret < 0) { + gnutls_free(params->raw_pub.data); + return ret; + } + + params->raw_pub.size = params->raw_priv.size; } else if (algo == GNUTLS_PK_RSA_PSS) { if (params->params_nr < RSA_PRIVATE_PARAMS - 3) return gnutls_assert_val(GNUTLS_E_PK_INVALID_PRIVKEY); |