diff options
Diffstat (limited to 'lib/nettle/pk.c')
-rw-r--r-- | lib/nettle/pk.c | 153 |
1 files changed, 137 insertions, 16 deletions
diff --git a/lib/nettle/pk.c b/lib/nettle/pk.c index c7ef0d78c5..e05a84f4c9 100644 --- a/lib/nettle/pk.c +++ b/lib/nettle/pk.c @@ -46,10 +46,11 @@ #include <nettle/ecc.h> #include <nettle/ecdsa.h> #include <nettle/ecc-curve.h> +#include <nettle/eddsa.h> #include <gnettle.h> #include <fips.h> -static inline const struct ecc_curve *get_supported_curve(int curve); +static inline const struct ecc_curve *get_supported_nist_curve(int curve); static void rnd_func(void *_ctx, size_t length, uint8_t * data) { @@ -251,7 +252,7 @@ dh_cleanup: out->data = NULL; - curve = get_supported_curve(priv->flags); + curve = get_supported_nist_curve(priv->flags); if (curve == NULL) return gnutls_assert_val @@ -445,14 +446,44 @@ _wrap_nettle_pk_sign(gnutls_pk_algorithm_t algo, const mac_entry_st *me; switch (algo) { - case GNUTLS_PK_EC: /* we do ECDSA */ + case GNUTLS_PK_EDDSA: + { + uint8_t key[32]; + uint8_t pub[32]; + int curve_id = pk_params->flags; + + if (curve_id != GNUTLS_ECC_CURVE_ED25519PH) + return + gnutls_assert_val + (GNUTLS_E_ECC_UNSUPPORTED_CURVE); + + /* curve25519 for now */ + if (nettle_mpz_sizeinbase_256_u(TOMPZ(pk_params->params[EDDSA_PRIV])) > 32) + return gnutls_assert_val(GNUTLS_E_PK_SIGN_FAILED); + + if (nettle_mpz_sizeinbase_256_u(TOMPZ(pk_params->params[EDDSA_PUB])) > 32) + return gnutls_assert_val(GNUTLS_E_PK_SIGN_FAILED); + + nettle_mpz_get_str_256(32, key, TOMPZ(pk_params->params[EDDSA_PRIV])); + nettle_mpz_get_str_256(32, pub, TOMPZ(pk_params->params[EDDSA_PUB])); + + signature->data = gnutls_malloc(ED25519_SIGNATURE_SIZE); + if (signature->data == NULL) + return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); + + signature->size = ED25519_SIGNATURE_SIZE; + + ed25519_sha512_sign(pub, key, vdata->size, vdata->data, signature->data); + break; + } + case GNUTLS_PK_ECDSA: /* we do ECDSA */ { struct ecc_scalar priv; struct dsa_signature sig; int curve_id = pk_params->flags; const struct ecc_curve *curve; - curve = get_supported_curve(curve_id); + curve = get_supported_nist_curve(curve_id); if (curve == NULL) return gnutls_assert_val @@ -599,14 +630,41 @@ _wrap_nettle_pk_verify(gnutls_pk_algorithm_t algo, bigint_t tmp[2] = { NULL, NULL }; switch (algo) { - case GNUTLS_PK_EC: /* ECDSA */ + case GNUTLS_PK_EDDSA: /* EdDSA */ + { + uint8_t pub[32]; + int curve_id = pk_params->flags; + + if (curve_id != GNUTLS_ECC_CURVE_ED25519PH) + return + gnutls_assert_val + (GNUTLS_E_ECC_UNSUPPORTED_CURVE); + + /* curve25519 for now */ + if (signature->size != ED25519_SIGNATURE_SIZE) + return gnutls_assert_val(GNUTLS_E_PK_SIG_VERIFY_FAILED); + + if (nettle_mpz_sizeinbase_256_u(pk_params->params[EDDSA_PUB]) > 32) + return gnutls_assert_val(GNUTLS_E_PK_SIG_VERIFY_FAILED); + + nettle_mpz_get_str_256(32, pub, pk_params->params[EDDSA_PUB]); + + ret = ed25519_sha512_verify(pub, vdata->size, vdata->data, signature->data); + if (ret == 0) { + gnutls_assert(); + ret = GNUTLS_E_PK_SIG_VERIFY_FAILED; + } else + ret = 0; + break; + } + case GNUTLS_PK_ECDSA: /* ECDSA */ { struct ecc_point pub; struct dsa_signature sig; int curve_id = pk_params->flags; const struct ecc_curve *curve; - curve = get_supported_curve(curve_id); + curve = get_supported_nist_curve(curve_id); if (curve == NULL) return gnutls_assert_val @@ -724,7 +782,7 @@ _wrap_nettle_pk_verify(gnutls_pk_algorithm_t algo, return ret; } -static inline const struct ecc_curve *get_supported_curve(int curve) +static inline const struct ecc_curve *get_supported_nist_curve(int curve) { switch (curve) { #ifdef ENABLE_NON_SUITEB_CURVES @@ -744,15 +802,25 @@ static inline const struct ecc_curve *get_supported_curve(int curve) } } +static inline bool get_supported_ed_curve(int curve) +{ + switch (curve) { + case GNUTLS_ECC_CURVE_ED25519PH: + return 1; + default: + return 0; + } +} + static int _wrap_nettle_pk_curve_exists(gnutls_ecc_curve_t curve) { - return ((get_supported_curve(curve)!=NULL)?1:0); + return ((get_supported_nist_curve(curve)!=NULL||get_supported_ed_curve(curve))?1:0); } /* Generates algorithm's parameters. That is: * For DSA: p, q, and g are generated. * For RSA: nothing - * For ECDSA: just checks the curve is ok + * For ECDSA/EDDSA: nothing */ static int wrap_nettle_pk_generate_params(gnutls_pk_algorithm_t algo, @@ -868,7 +936,8 @@ wrap_nettle_pk_generate_params(gnutls_pk_algorithm_t algo, break; } case GNUTLS_PK_RSA: - case GNUTLS_PK_EC: + case GNUTLS_PK_ECDSA: + case GNUTLS_PK_EDDSA: ret = 0; break; default: @@ -1337,7 +1406,34 @@ wrap_nettle_pk_generate_keys(gnutls_pk_algorithm_t algo, break; } - case GNUTLS_PK_EC: + case GNUTLS_PK_EDDSA: + { + /* one option for now -> curve25519 */ + uint8_t key[32]; + uint8_t pub[32]; + + if (params->flags & GNUTLS_PK_FLAG_PROVABLE) + return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); + + ret = gnutls_rnd(GNUTLS_RND_RANDOM, key, sizeof(key)); + if (ret < 0) + return gnutls_assert_val(ret); + + ed25519_sha512_public_key(pub, key); + + ret = _gnutls_mpi_init_multi(¶ms->params[EDDSA_PRIV], ¶ms->params[EDDSA_PUB], NULL); + if (ret < 0) + return gnutls_assert_val(ret); + + nettle_mpz_set_str_256_u(TOMPZ(params->params[EDDSA_PRIV]), 32, key); + nettle_mpz_set_str_256_u(TOMPZ(params->params[EDDSA_PUB]), 32, pub); + + params->flags = GNUTLS_ECC_CURVE_ED25519PH; + params->params_nr = 2; + + break; + } + case GNUTLS_PK_ECDSA: if (params->flags & GNUTLS_PK_FLAG_PROVABLE) return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); @@ -1346,7 +1442,7 @@ wrap_nettle_pk_generate_keys(gnutls_pk_algorithm_t algo, struct ecc_point pub; const struct ecc_curve *curve; - curve = get_supported_curve(level); + curve = get_supported_nist_curve(level); if (curve == NULL) return gnutls_assert_val @@ -1526,7 +1622,7 @@ wrap_nettle_pk_verify_priv_params(gnutls_pk_algorithm_t algo, } break; - case GNUTLS_PK_EC: + case GNUTLS_PK_ECDSA: { struct ecc_point r, pub; struct ecc_scalar priv; @@ -1538,7 +1634,7 @@ wrap_nettle_pk_verify_priv_params(gnutls_pk_algorithm_t algo, gnutls_assert_val (GNUTLS_E_INVALID_REQUEST); - curve = get_supported_curve(params->flags); + curve = get_supported_nist_curve(params->flags); if (curve == NULL) return gnutls_assert_val @@ -1599,6 +1695,9 @@ wrap_nettle_pk_verify_priv_params(gnutls_pk_algorithm_t algo, mpz_clear(y2); } break; + case GNUTLS_PK_EDDSA: + ret = 0; + break; default: ret = gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); } @@ -1615,8 +1714,9 @@ wrap_nettle_pk_verify_pub_params(gnutls_pk_algorithm_t algo, switch (algo) { case GNUTLS_PK_RSA: case GNUTLS_PK_DSA: + case GNUTLS_PK_EDDSA: return 0; - case GNUTLS_PK_EC: + case GNUTLS_PK_ECDSA: { /* just verify that x and y lie on the curve */ struct ecc_point r, pub; @@ -1627,7 +1727,7 @@ wrap_nettle_pk_verify_pub_params(gnutls_pk_algorithm_t algo, gnutls_assert_val (GNUTLS_E_INVALID_REQUEST); - curve = get_supported_curve(params->flags); + curve = get_supported_nist_curve(params->flags); if (curve == NULL) return gnutls_assert_val @@ -1741,6 +1841,27 @@ wrap_nettle_pk_fixup(gnutls_pk_algorithm_t algo, params->params_nr = RSA_PRIVATE_PARAMS; } + if (direction == GNUTLS_IMPORT && algo == GNUTLS_PK_EDDSA) { + uint8_t key[32]; + uint8_t pub[32]; + + if (params->flags != GNUTLS_ECC_CURVE_ED25519PH) + return gnutls_assert_val(GNUTLS_E_ECC_UNSUPPORTED_CURVE); + + nettle_mpz_get_str_256(32, key, params->params[EDDSA_PRIV]); + + ed25519_sha512_public_key(pub, key); + + zrelease_mpi_key(¶ms->params[EDDSA_PUB]); + + ret = + _gnutls_mpi_init_scan_nz(¶ms->params[EDDSA_PUB], pub, sizeof(pub)); + if (ret < 0) + return gnutls_assert_val(ret); + + params->params_nr = 2; + } + return 0; } |