summaryrefslogtreecommitdiff
path: root/lib/nettle/pk.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/nettle/pk.c')
-rw-r--r--lib/nettle/pk.c153
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(&params->params[EDDSA_PRIV], &params->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(&params->params[EDDSA_PUB]);
+
+ ret =
+ _gnutls_mpi_init_scan_nz(&params->params[EDDSA_PUB], pub, sizeof(pub));
+ if (ret < 0)
+ return gnutls_assert_val(ret);
+
+ params->params_nr = 2;
+ }
+
return 0;
}