diff options
-rw-r--r-- | lib/auth/ecdhe.c | 8 | ||||
-rw-r--r-- | lib/crypto-backend.h | 5 | ||||
-rw-r--r-- | lib/gnutls_pk.h | 3 | ||||
-rw-r--r-- | lib/nettle/pk.c | 115 | ||||
-rw-r--r-- | lib/x509/privkey.c | 8 |
5 files changed, 121 insertions, 18 deletions
diff --git a/lib/auth/ecdhe.c b/lib/auth/ecdhe.c index 94988fe814..4074002307 100644 --- a/lib/auth/ecdhe.c +++ b/lib/auth/ecdhe.c @@ -202,8 +202,8 @@ _gnutls_gen_ecdh_common_client_kx_int(gnutls_session_t session, /* generate temporal key */ ret = - _gnutls_pk_generate(GNUTLS_PK_EC, curve, - &session->key.ecdh_params); + _gnutls_pk_generate_keys(GNUTLS_PK_EC, curve, + &session->key.ecdh_params); if (ret < 0) return gnutls_assert_val(ret); @@ -320,8 +320,8 @@ int _gnutls_ecdh_common_print_server_kx(gnutls_session_t session, /* generate temporal key */ ret = - _gnutls_pk_generate(GNUTLS_PK_EC, curve, - &session->key.ecdh_params); + _gnutls_pk_generate_keys(GNUTLS_PK_EC, curve, + &session->key.ecdh_params); if (ret < 0) return gnutls_assert_val(ret); diff --git a/lib/crypto-backend.h b/lib/crypto-backend.h index f7bcd53fa5..6472d2ef37 100644 --- a/lib/crypto-backend.h +++ b/lib/crypto-backend.h @@ -181,6 +181,7 @@ typedef struct { bigint_t params[GNUTLS_MAX_PK_PARAMS]; unsigned int params_nr; /* the number of parameters */ unsigned int flags; + gnutls_pk_algorithm_t algo; } gnutls_pk_params_st; /** @@ -317,7 +318,9 @@ typedef struct gnutls_crypto_pk { /* sanity checks the public key parameters */ int (*verify_params) (gnutls_pk_algorithm_t, const gnutls_pk_params_st * pub); - int (*generate) (gnutls_pk_algorithm_t, unsigned int nbits, + int (*generate_keys) (gnutls_pk_algorithm_t, unsigned int nbits, + gnutls_pk_params_st *); + int (*generate_params) (gnutls_pk_algorithm_t, unsigned int nbits, gnutls_pk_params_st *); /* this function should convert params to ones suitable * for the above functions diff --git a/lib/gnutls_pk.h b/lib/gnutls_pk.h index 22ff54a08d..46eb3d4f7a 100644 --- a/lib/gnutls_pk.h +++ b/lib/gnutls_pk.h @@ -32,7 +32,8 @@ extern gnutls_crypto_pk_st _gnutls_pk_ops; #define _gnutls_pk_verify( algo, data, sig, params) _gnutls_pk_ops.verify( algo, data, sig, params) #define _gnutls_pk_verify_params( algo, params) _gnutls_pk_ops.verify_params( algo, params) #define _gnutls_pk_derive( algo, out, pub, priv) _gnutls_pk_ops.derive( algo, out, pub, priv) -#define _gnutls_pk_generate( algo, bits, priv) _gnutls_pk_ops.generate( algo, bits, priv) +#define _gnutls_pk_generate_keys( algo, bits, priv) _gnutls_pk_ops.generate_keys( algo, bits, priv) +#define _gnutls_pk_generate_params( algo, bits, priv) _gnutls_pk_ops.generate_params( algo, bits, priv) #define _gnutls_pk_hash_algorithm( pk, sig, params, hash) _gnutls_pk_ops.hash_algorithm(pk, sig, params, hash) inline static int diff --git a/lib/nettle/pk.c b/lib/nettle/pk.c index ae16f5aca0..765b2a60bd 100644 --- a/lib/nettle/pk.c +++ b/lib/nettle/pk.c @@ -51,7 +51,8 @@ static inline const struct ecc_curve *get_supported_curve(int curve); static void rnd_func(void *_ctx, unsigned length, uint8_t * data) { - _gnutls_rnd(GNUTLS_RND_RANDOM, data, length); + if (_gnutls_rnd(GNUTLS_RND_RANDOM, data, length) < 0) + abort(); } static void @@ -76,7 +77,9 @@ _dsa_params_to_pubkey(const gnutls_pk_params_st * pk_params, memcpy(&pub->p, pk_params->params[0], sizeof(mpz_t)); memcpy(&pub->q, pk_params->params[1], sizeof(mpz_t)); memcpy(&pub->g, pk_params->params[2], sizeof(mpz_t)); - memcpy(&pub->y, pk_params->params[3], sizeof(mpz_t)); + + if (pk_params->params[3] != NULL) + memcpy(&pub->y, pk_params->params[3], sizeof(mpz_t)); } static void @@ -655,20 +658,25 @@ static inline const struct ecc_curve *get_supported_curve(int curve) } } - +/* 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 + */ static int wrap_nettle_pk_generate_params(gnutls_pk_algorithm_t algo, - unsigned int level /*bits */ , + unsigned int level /*bits or curve*/ , gnutls_pk_params_st * params) { int ret; unsigned int i, q_bits; memset(params, 0, sizeof(*params)); + params->algo = algo; switch (algo) { - case GNUTLS_PK_DSA: + case GNUTLS_PK_DH: { struct dsa_public_key pub; struct dsa_private_key priv; @@ -694,7 +702,7 @@ wrap_nettle_pk_generate_params(gnutls_pk_algorithm_t algo, } params->params_nr = 0; - for (i = 0; i < DSA_PRIVATE_PARAMS; i++) { + for (i = 0; i < DSA_PRIVATE_PARAMS-2; i++) { params->params[i] = _gnutls_mpi_alloc_like(&pub.p); if (params->params[i] == NULL) { @@ -708,8 +716,6 @@ wrap_nettle_pk_generate_params(gnutls_pk_algorithm_t algo, _gnutls_mpi_set(params->params[0], pub.p); _gnutls_mpi_set(params->params[1], pub.q); _gnutls_mpi_set(params->params[2], pub.g); - _gnutls_mpi_set(params->params[3], pub.y); - _gnutls_mpi_set(params->params[4], priv.x); dsa_fail: dsa_private_key_clear(&priv); @@ -721,6 +727,86 @@ wrap_nettle_pk_generate_params(gnutls_pk_algorithm_t algo, break; } case GNUTLS_PK_RSA: + case GNUTLS_PK_EC: + ret = 0; + break; + default: + gnutls_assert(); + return GNUTLS_E_INVALID_REQUEST; + } + + return 0; + + fail: + + for (i = 0; i < params->params_nr; i++) { + _gnutls_mpi_release(¶ms->params[i]); + } + params->params_nr = 0; + + return ret; +} + +static int +wrap_nettle_pk_generate_keys(gnutls_pk_algorithm_t algo, + unsigned int level /*bits */ , + gnutls_pk_params_st * params) +{ + int ret; + unsigned int i; + + switch (algo) { + case GNUTLS_PK_DSA: + case GNUTLS_PK_DH: + { + struct dsa_public_key pub; + mpz_t r; + mpz_t x, y; + + if (algo != params->algo) + return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); + + _dsa_params_to_pubkey(params, &pub); + + mpz_init(r); + mpz_init(x); + mpz_init(y); + mpz_set(r, pub.q); + mpz_sub_ui(r, r, 2); + nettle_mpz_random(x, NULL, rnd_func, r); + mpz_add_ui(x, x, 1); + + mpz_powm(y, pub.g, x, pub.p); + + params->params[DSA_Y] = _gnutls_mpi_alloc_like(&pub.p); + if (params->params[DSA_Y] == NULL) { + ret = GNUTLS_E_MEMORY_ERROR; + goto dsa_fail; + } + + params->params[DSA_X] = _gnutls_mpi_alloc_like(&pub.p); + if (params->params[DSA_X] == NULL) { + ret = GNUTLS_E_MEMORY_ERROR; + goto dsa_fail; + } + + _gnutls_mpi_set(params->params[DSA_Y], y); + _gnutls_mpi_set(params->params[DSA_X], x); + params->params_nr += 2; + + ret = 0; + + dsa_fail: + mpz_clear(r); + mpz_clear(x); + mpz_clear(y); + + if (ret < 0) + goto fail; + + break; + } + case GNUTLS_PK_RSA: { struct rsa_public_key pub; struct rsa_private_key priv; @@ -802,7 +888,8 @@ wrap_nettle_pk_generate_params(gnutls_pk_algorithm_t algo, params[ECC_Y]); _gnutls_mpi_release(¶ms-> params[ECC_K]); - goto ecc_cleanup; + ret = gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); + goto ecc_fail; } params->flags = level; @@ -812,9 +899,14 @@ wrap_nettle_pk_generate_params(gnutls_pk_algorithm_t algo, TOMPZ(params->params[ECC_Y])); ecc_scalar_get(&key, TOMPZ(params->params[ECC_K])); - ecc_cleanup: + ret = 0; + + ecc_fail: ecc_point_clear(&pub); ecc_scalar_clear(&key); + + if (ret < 0) + goto fail; break; } @@ -1247,7 +1339,8 @@ gnutls_crypto_pk_st _gnutls_pk_ops = { .sign = _wrap_nettle_pk_sign, .verify = _wrap_nettle_pk_verify, .verify_params = wrap_nettle_pk_verify_params, - .generate = wrap_nettle_pk_generate_params, + .generate_params = wrap_nettle_pk_generate_params, + .generate_keys = wrap_nettle_pk_generate_keys, .pk_fixup_private_params = wrap_nettle_pk_fixup, .derive = _wrap_nettle_pk_derive, }; diff --git a/lib/x509/privkey.c b/lib/x509/privkey.c index bf4b77637d..1cc7176881 100644 --- a/lib/x509/privkey.c +++ b/lib/x509/privkey.c @@ -1490,7 +1490,13 @@ gnutls_x509_privkey_generate(gnutls_x509_privkey_t key, bits = _gnutls_ecc_bits_to_curve(bits); } - ret = _gnutls_pk_generate(algo, bits, &key->params); + ret = _gnutls_pk_generate_params(algo, bits, &key->params); + if (ret < 0) { + gnutls_assert(); + return ret; + } + + ret = _gnutls_pk_generate_keys(algo, bits, &key->params); if (ret < 0) { gnutls_assert(); return ret; |