/* A = g^a % N * returns A and a (which is random) */ bigint_t _gnutls_calc_srp_A(bigint_t * a, bigint_t g, bigint_t n) { bigint_t tmpa; bigint_t A; int ret; ret = _gnutls_mpi_init_multi(&A, &tmpa, NULL); if (ret < 0) { gnutls_assert(); return NULL; } _gnutls_mpi_random_modp(tmpa, n, GNUTLS_RND_RANDOM); ret = _gnutls_mpi_powm(A, g, tmpa, n); if (ret < 0) goto error; if (a != NULL) *a = tmpa; else _gnutls_mpi_release(&tmpa); return A; error: _gnutls_mpi_release(&tmpa); _gnutls_mpi_release(&A); return NULL; }
/**************** * Choose a random value b and calculate B = (k* v + g^b) % N. * where k == SHA1(N|g) * Return: B and if ret_b is not NULL b. */ bigint_t _gnutls_calc_srp_B(bigint_t * ret_b, bigint_t g, bigint_t n, bigint_t v) { bigint_t tmpB = NULL, tmpV = NULL; bigint_t b = NULL, B = NULL, k = NULL; int ret; /* calculate: B = (k*v + g^b) % N */ ret = _gnutls_mpi_init_multi(&tmpV, &tmpB, &B, &b, NULL); if (ret < 0) return NULL; _gnutls_mpi_random_modp(b, n, GNUTLS_RND_RANDOM); k = _gnutls_calc_srp_u(n, g, n); if (k == NULL) { gnutls_assert(); goto error; } ret = _gnutls_mpi_mulm(tmpV, k, v, n); if (ret < 0) { gnutls_assert(); goto error; } ret = _gnutls_mpi_powm(tmpB, g, b, n); if (ret < 0) { gnutls_assert(); goto error; } ret = _gnutls_mpi_addm(B, tmpV, tmpB, n); if (ret < 0) { gnutls_assert(); goto error; } _gnutls_mpi_release(&k); _gnutls_mpi_release(&tmpB); _gnutls_mpi_release(&tmpV); if (ret_b) *ret_b = b; else _gnutls_mpi_release(&b); return B; error: _gnutls_mpi_release(&b); _gnutls_mpi_release(&B); _gnutls_mpi_release(&k); _gnutls_mpi_release(&tmpB); _gnutls_mpi_release(&tmpV); return NULL; }
static int calc_rsa_exp(gnutls_pk_params_st * params) { bigint_t tmp; int ret; if (params->params_nr < RSA_PRIVATE_PARAMS - 2) { gnutls_assert(); return GNUTLS_E_INTERNAL_ERROR; } params->params[6] = params->params[7] = NULL; ret = _gnutls_mpi_init_multi(&tmp, ¶ms->params[6], ¶ms->params[7], NULL); if (ret < 0) return gnutls_assert_val(ret); /* [6] = d % p-1, [7] = d % q-1 */ _gnutls_mpi_sub_ui(tmp, params->params[3], 1); ret = _gnutls_mpi_modm(params->params[6], params->params[2] /*d */ , tmp); if (ret < 0) goto fail; _gnutls_mpi_sub_ui(tmp, params->params[4], 1); ret = _gnutls_mpi_modm(params->params[7], params->params[2] /*d */ , tmp); if (ret < 0) goto fail; zrelease_mpi_key(&tmp); return 0; fail: zrelease_mpi_key(&tmp); zrelease_mpi_key(¶ms->params[6]); zrelease_mpi_key(¶ms->params[7]); return ret; }
/* S = (A * v^u) ^ b % N * this is our shared key (server premaster secret) */ bigint_t _gnutls_calc_srp_S1(bigint_t A, bigint_t b, bigint_t u, bigint_t v, bigint_t n) { bigint_t tmp1 = NULL, tmp2 = NULL; bigint_t S = NULL; int ret; ret = _gnutls_mpi_init_multi(&S, &tmp1, &tmp2, NULL); if (ret < 0) return NULL; ret = _gnutls_mpi_powm(tmp1, v, u, n); if (ret < 0) { gnutls_assert(); goto error; } ret = _gnutls_mpi_mulm(tmp2, A, tmp1, n); if (ret < 0) { gnutls_assert(); goto error; } _gnutls_mpi_powm(S, tmp2, b, n); _gnutls_mpi_release(&tmp1); _gnutls_mpi_release(&tmp2); return S; error: _gnutls_mpi_release(&S); _gnutls_mpi_release(&tmp1); _gnutls_mpi_release(&tmp2); return NULL; }
/* Check if N is a prime and G a generator of the * group. This check is only done if N is big enough. * Otherwise only the included parameters must be used. */ static int group_check_g_n(gnutls_session_t session, bigint_t g, bigint_t n) { bigint_t q = NULL, two = NULL, w = NULL; int ret; if (_gnutls_mpi_get_nbits(n) < (session->internals.srp_prime_bits ? session->internals.srp_prime_bits : 2048)) { gnutls_assert(); return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER; } /* N must be of the form N=2q+1 * where q is also a prime. */ if (_gnutls_prime_check(n) != 0) { _gnutls_mpi_log("no prime N: ", n); gnutls_assert(); return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER; } ret = _gnutls_mpi_init_multi(&two, &q, &w, NULL); if (ret < 0) { gnutls_assert(); return ret; } /* q = n-1 */ ret = _gnutls_mpi_sub_ui(q, n, 1); if (ret < 0) { gnutls_assert(); goto error; } /* q = q/2, remember that q is divisible by 2 (prime - 1) */ ret = _gnutls_mpi_set_ui(two, 2); if (ret < 0) { gnutls_assert(); goto error; } ret = _gnutls_mpi_div(q, q, two); if (ret < 0) { gnutls_assert(); goto error; } if (_gnutls_prime_check(q) != 0) { /* N was not on the form N=2q+1, where q = prime */ _gnutls_mpi_log("no prime Q: ", q); gnutls_assert(); ret = GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER; goto error; } /* We also check whether g is a generator, */ /* check if g < q < N */ if (_gnutls_mpi_cmp(g, q) >= 0) { gnutls_assert(); ret = GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER; goto error; } /* check if g^q mod N == N-1 * w = g^q mod N */ ret = _gnutls_mpi_powm(w, g, q, n); if (ret < 0) { gnutls_assert(); goto error; } /* w++ */ ret = _gnutls_mpi_add_ui(w, w, 1); if (ret < 0) { gnutls_assert(); goto error; } if (_gnutls_mpi_cmp(w, n) != 0) { gnutls_assert(); ret = GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER; goto error; } ret = 0; error: _gnutls_mpi_release(&q); _gnutls_mpi_release(&two); _gnutls_mpi_release(&w); return ret; }
/* S = (B - k*g^x) ^ (a + u * x) % N * this is our shared key (client premaster secret) */ bigint_t _gnutls_calc_srp_S2(bigint_t B, bigint_t g, bigint_t x, bigint_t a, bigint_t u, bigint_t n) { bigint_t S = NULL, tmp1 = NULL, tmp2 = NULL; bigint_t tmp4 = NULL, tmp3 = NULL, k = NULL; int ret; ret = _gnutls_mpi_init_multi(&S, &tmp1, &tmp2, &tmp3, &tmp4, NULL); if (ret < 0) return NULL; k = _gnutls_calc_srp_u(n, g, n); if (k == NULL) { gnutls_assert(); goto freeall; } ret = _gnutls_mpi_powm(tmp1, g, x, n); /* g^x */ if (ret < 0) { gnutls_assert(); goto freeall; } ret = _gnutls_mpi_mulm(tmp3, tmp1, k, n); /* k*g^x mod n */ if (ret < 0) { gnutls_assert(); goto freeall; } ret = _gnutls_mpi_subm(tmp2, B, tmp3, n); if (ret < 0) { gnutls_assert(); goto freeall; } ret = _gnutls_mpi_mul(tmp1, u, x); if (ret < 0) { gnutls_assert(); goto freeall; } ret = _gnutls_mpi_add(tmp4, a, tmp1); if (ret < 0) { gnutls_assert(); goto freeall; } ret = _gnutls_mpi_powm(S, tmp2, tmp4, n); if (ret < 0) { gnutls_assert(); goto freeall; } _gnutls_mpi_release(&tmp1); _gnutls_mpi_release(&tmp2); _gnutls_mpi_release(&tmp3); _gnutls_mpi_release(&tmp4); _gnutls_mpi_release(&k); return S; freeall: _gnutls_mpi_release(&k); _gnutls_mpi_release(&tmp1); _gnutls_mpi_release(&tmp2); _gnutls_mpi_release(&tmp3); _gnutls_mpi_release(&tmp4); _gnutls_mpi_release(&S); return NULL; }
/* 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 or curve*/ , gnutls_pk_params_st * params) { int ret; unsigned int i, q_bits; params->algo = algo; switch (algo) { case GNUTLS_PK_DSA: case GNUTLS_PK_DH: { struct dsa_public_key pub; struct dsa_private_key priv; #ifdef ENABLE_FIPS140 struct dss_params_validation_seeds cert; unsigned index; #endif dsa_public_key_init(&pub); dsa_private_key_init(&priv); if (GNUTLS_BITS_HAVE_SUBGROUP(level)) { q_bits = GNUTLS_BITS_TO_SUBGROUP(level); level = GNUTLS_BITS_TO_GROUP(level); } else { q_bits = _gnutls_pk_bits_to_subgroup_bits(level); } if (q_bits == 0) return gnutls_assert_val(GNUTLS_E_ILLEGAL_PARAMETER); #ifdef ENABLE_FIPS140 if (algo==GNUTLS_PK_DSA) index = 1; else index = 2; ret = dsa_generate_dss_pqg(&pub, &cert, index, NULL, rnd_func, NULL, NULL, level, q_bits); if (ret != 1) { gnutls_assert(); ret = GNUTLS_E_PK_GENERATION_ERROR; goto dsa_fail; } /* verify the generated parameters */ ret = dsa_validate_dss_pqg(&pub, &cert, index); if (ret != 1) { gnutls_assert(); ret = GNUTLS_E_PK_GENERATION_ERROR; goto dsa_fail; } #else /* unfortunately nettle only accepts 160 or 256 * q_bits size. The check below makes sure we handle * cases in between by rounding up, but fail when * larger numbers are requested. */ if (q_bits < 160) q_bits = 160; else if (q_bits > 160 && q_bits <= 256) q_bits = 256; ret = dsa_generate_keypair(&pub, &priv, NULL, rnd_func, NULL, NULL, level, q_bits); if (ret != 1) { gnutls_assert(); ret = GNUTLS_E_PK_GENERATION_ERROR; goto dsa_fail; } #endif params->params_nr = 0; ret = _gnutls_mpi_init_multi(¶ms->params[DSA_P], ¶ms->params[DSA_Q], ¶ms->params[DSA_G], NULL); if (ret < 0) { gnutls_assert(); goto dsa_fail; } params->params_nr = 3; mpz_set(TOMPZ(params->params[DSA_P]), pub.p); mpz_set(TOMPZ(params->params[DSA_Q]), pub.q); mpz_set(TOMPZ(params->params[DSA_G]), pub.g); ret = 0; dsa_fail: dsa_private_key_clear(&priv); dsa_public_key_clear(&pub); if (ret < 0) goto fail; break; } case GNUTLS_PK_RSA: case GNUTLS_PK_EC: ret = 0; break; default: gnutls_assert(); return GNUTLS_E_INVALID_REQUEST; } FAIL_IF_LIB_ERROR; return 0; fail: for (i = 0; i < params->params_nr; i++) { _gnutls_mpi_release(¶ms->params[i]); } params->params_nr = 0; FAIL_IF_LIB_ERROR; return ret; }
/* This is used for DH or ECDH key derivation. In DH for example * it is given the peers Y and our x, and calculates Y^x */ static int _wrap_nettle_pk_derive(gnutls_pk_algorithm_t algo, gnutls_datum_t * out, const gnutls_pk_params_st * priv, const gnutls_pk_params_st * pub) { int ret; switch (algo) { case GNUTLS_PK_DH: { bigint_t f, x, prime; bigint_t k = NULL, ff = NULL; unsigned int bits; f = pub->params[DH_Y]; x = priv->params[DH_X]; prime = priv->params[DH_P]; ret = _gnutls_mpi_init_multi(&k, &ff, NULL); if (ret < 0) return gnutls_assert_val(ret); ret = _gnutls_mpi_modm(ff, f, prime); if (ret < 0) { gnutls_assert(); goto dh_cleanup; } ret = _gnutls_mpi_add_ui(ff, ff, 1); if (ret < 0) { gnutls_assert(); goto dh_cleanup; } /* check if f==0,1,p-1. * or (ff=f+1) equivalently ff==1,2,p */ if ((_gnutls_mpi_cmp_ui(ff, 2) == 0) || (_gnutls_mpi_cmp_ui(ff, 1) == 0) || (_gnutls_mpi_cmp(ff, prime) == 0)) { gnutls_assert(); ret = GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER; goto dh_cleanup; } /* prevent denial of service */ bits = _gnutls_mpi_get_nbits(prime); if (bits == 0 || bits > MAX_DH_BITS) { gnutls_assert(); ret = GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER; goto dh_cleanup; } ret = _gnutls_mpi_powm(k, f, x, prime); if (ret < 0) { gnutls_assert(); goto dh_cleanup; } ret = _gnutls_mpi_dprint(k, out); if (ret < 0) { gnutls_assert(); goto dh_cleanup; } ret = 0; dh_cleanup: _gnutls_mpi_release(&ff); zrelease_temp_mpi_key(&k); if (ret < 0) goto cleanup; break; } case GNUTLS_PK_EC: { struct ecc_scalar ecc_priv; struct ecc_point ecc_pub; const struct ecc_curve *curve; out->data = NULL; curve = get_supported_curve(priv->flags); if (curve == NULL) return gnutls_assert_val (GNUTLS_E_ECC_UNSUPPORTED_CURVE); ret = _ecc_params_to_pubkey(pub, &ecc_pub, curve); if (ret < 0) return gnutls_assert_val(ret); ret = _ecc_params_to_privkey(priv, &ecc_priv, curve); if (ret < 0) { ecc_point_clear(&ecc_pub); return gnutls_assert_val(ret); } out->size = gnutls_ecc_curve_get_size(priv->flags); /*ecc_size(curve)*sizeof(mp_limb_t); */ out->data = gnutls_malloc(out->size); if (out->data == NULL) { ret = gnutls_assert_val (GNUTLS_E_MEMORY_ERROR); goto ecc_cleanup; } ecc_shared_secret(&ecc_priv, &ecc_pub, out->data, out->size); ecc_cleanup: ecc_point_clear(&ecc_pub); ecc_scalar_zclear(&ecc_priv); if (ret < 0) goto cleanup; break; } default: gnutls_assert(); ret = GNUTLS_E_INTERNAL_ERROR; goto cleanup; } ret = 0; cleanup: return ret; }
static int wrap_nettle_pk_verify_priv_params(gnutls_pk_algorithm_t algo, const gnutls_pk_params_st * params) { int ret; switch (algo) { case GNUTLS_PK_RSA: { bigint_t t1 = NULL, t2 = NULL; if (params->params_nr != RSA_PRIVATE_PARAMS) return gnutls_assert_val (GNUTLS_E_INVALID_REQUEST); ret = _gnutls_mpi_init_multi(&t1, &t2, NULL); if (ret < 0) return gnutls_assert_val(ret); _gnutls_mpi_mulm(t1, params->params[RSA_PRIME1], params->params[RSA_PRIME2], params->params[RSA_MODULUS]); if (_gnutls_mpi_cmp_ui(t1, 0) != 0) { ret = gnutls_assert_val (GNUTLS_E_ILLEGAL_PARAMETER); goto rsa_cleanup; } mpz_invert(TOMPZ(t1), TOMPZ(params->params[RSA_PRIME2]), TOMPZ(params->params[RSA_PRIME1])); if (_gnutls_mpi_cmp(t1, params->params[RSA_COEF]) != 0) { ret = gnutls_assert_val (GNUTLS_E_ILLEGAL_PARAMETER); goto rsa_cleanup; } /* [RSA_PRIME1] = d % p-1, [RSA_PRIME2] = d % q-1 */ _gnutls_mpi_sub_ui(t1, params->params[RSA_PRIME1], 1); ret = _gnutls_mpi_modm(t2, params->params[RSA_PRIV], t1); if (ret < 0) { ret = gnutls_assert_val (GNUTLS_E_MEMORY_ERROR); goto rsa_cleanup; } if (_gnutls_mpi_cmp(params->params[RSA_E1], t2) != 0) { ret = gnutls_assert_val (GNUTLS_E_ILLEGAL_PARAMETER); goto rsa_cleanup; } _gnutls_mpi_sub_ui(t1, params->params[RSA_PRIME2], 1); ret = _gnutls_mpi_modm(t2, params->params[RSA_PRIV], t1); if (ret < 0) { ret = gnutls_assert_val (GNUTLS_E_MEMORY_ERROR); goto rsa_cleanup; } if (_gnutls_mpi_cmp(params->params[RSA_E2], t2) != 0) { ret = gnutls_assert_val (GNUTLS_E_ILLEGAL_PARAMETER); goto rsa_cleanup; } ret = 0; rsa_cleanup: zrelease_mpi_key(&t1); zrelease_mpi_key(&t2); } break; case GNUTLS_PK_DSA: { bigint_t t1 = NULL; if (params->params_nr != DSA_PRIVATE_PARAMS) return gnutls_assert_val (GNUTLS_E_INVALID_REQUEST); ret = _gnutls_mpi_init(&t1); if (ret < 0) return gnutls_assert_val(ret); ret = _gnutls_mpi_powm(t1, params->params[DSA_G], params->params[DSA_X], params->params[DSA_P]); if (ret < 0) { gnutls_assert(); goto dsa_cleanup; } if (_gnutls_mpi_cmp(t1, params->params[DSA_Y]) != 0) { ret = gnutls_assert_val (GNUTLS_E_ILLEGAL_PARAMETER); goto dsa_cleanup; } ret = 0; dsa_cleanup: zrelease_mpi_key(&t1); } break; case GNUTLS_PK_EC: { struct ecc_point r, pub; struct ecc_scalar priv; mpz_t x1, y1, x2, y2; const struct ecc_curve *curve; if (params->params_nr != ECC_PRIVATE_PARAMS) return gnutls_assert_val (GNUTLS_E_INVALID_REQUEST); curve = get_supported_curve(params->flags); if (curve == NULL) return gnutls_assert_val (GNUTLS_E_ECC_UNSUPPORTED_CURVE); ret = _ecc_params_to_pubkey(params, &pub, curve); if (ret < 0) return gnutls_assert_val(ret); ret = _ecc_params_to_privkey(params, &priv, curve); if (ret < 0) { ecc_point_clear(&pub); return gnutls_assert_val(ret); } ecc_point_init(&r, curve); /* verify that x,y lie on the curve */ ret = ecc_point_set(&r, TOMPZ(params->params[ECC_X]), TOMPZ(params->params[ECC_Y])); if (ret == 0) { ret = gnutls_assert_val (GNUTLS_E_ILLEGAL_PARAMETER); goto ecc_cleanup; } ecc_point_clear(&r); ecc_point_init(&r, curve); ecc_point_mul_g(&r, &priv); mpz_init(x1); mpz_init(y1); ecc_point_get(&r, x1, y1); ecc_point_zclear(&r); mpz_init(x2); mpz_init(y2); ecc_point_get(&pub, x2, y2); /* verify that k*(Gx,Gy)=(x,y) */ if (mpz_cmp(x1, x2) != 0 || mpz_cmp(y1, y2) != 0) { ret = gnutls_assert_val (GNUTLS_E_ILLEGAL_PARAMETER); goto ecc_cleanup; } ret = 0; ecc_cleanup: ecc_scalar_zclear(&priv); ecc_point_clear(&pub); } break; default: ret = gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); } return ret; }
/* To generate a DH key either q must be set in the params or * level should be set to the number of required bits. */ 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: #ifdef ENABLE_FIPS140 { struct dsa_public_key pub; struct dsa_private_key priv; if (params->params[DSA_Q] == NULL) return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); _dsa_params_to_pubkey(params, &pub); dsa_private_key_init(&priv); mpz_init(pub.y); ret = dsa_generate_dss_keypair(&pub, &priv, NULL, rnd_func, NULL, NULL); if (ret != 1) { gnutls_assert(); ret = GNUTLS_E_PK_GENERATION_ERROR; goto dsa_fail; } ret = _gnutls_mpi_init_multi(¶ms->params[DSA_Y], ¶ms->params[DSA_X], NULL); if (ret < 0) { gnutls_assert(); goto dsa_fail; } mpz_set(TOMPZ(params->params[DSA_Y]), pub.y); mpz_set(TOMPZ(params->params[DSA_X]), priv.x); params->params_nr += 2; dsa_fail: dsa_private_key_clear(&priv); mpz_clear(pub.y); if (ret < 0) goto fail; break; } #endif case GNUTLS_PK_DH: { struct dsa_public_key pub; mpz_t r; mpz_t x, y; int max_tries; unsigned have_q = 0; if (algo != params->algo) return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); _dsa_params_to_pubkey(params, &pub); if (params->params[DSA_Q] != NULL) have_q = 1; /* This check is for the case !ENABLE_FIPS140 */ if (algo == GNUTLS_PK_DSA && have_q == 0) return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); mpz_init(r); mpz_init(x); mpz_init(y); max_tries = 3; do { if (have_q) { 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); } else { unsigned size = mpz_sizeinbase(pub.p, 2); if (level == 0) level = MIN(size, DH_EXPONENT_SIZE(size)); nettle_mpz_random_size(x, NULL, rnd_func, level); if (level >= size) mpz_mod(x, x, pub.p); } mpz_powm(y, pub.g, x, pub.p); max_tries--; if (max_tries <= 0) { gnutls_assert(); ret = GNUTLS_E_RANDOM_FAILED; goto dh_fail; } } while(mpz_cmp_ui(y, 1) == 0); ret = _gnutls_mpi_init_multi(¶ms->params[DSA_Y], ¶ms->params[DSA_X], NULL); if (ret < 0) { gnutls_assert(); goto dh_fail; } mpz_set(TOMPZ(params->params[DSA_Y]), y); mpz_set(TOMPZ(params->params[DSA_X]), x); params->params_nr += 2; ret = 0; dh_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; rsa_public_key_init(&pub); rsa_private_key_init(&priv); mpz_set_ui(pub.e, 65537); #ifdef ENABLE_FIPS140 ret = rsa_generate_fips186_4_keypair(&pub, &priv, NULL, rnd_func, NULL, NULL, level); #else ret = rsa_generate_keypair(&pub, &priv, NULL, rnd_func, NULL, NULL, level, 0); #endif if (ret != 1) { gnutls_assert(); ret = GNUTLS_E_PK_GENERATION_ERROR; goto rsa_fail; } params->params_nr = 0; for (i = 0; i < RSA_PRIVATE_PARAMS; i++) { ret = _gnutls_mpi_init(¶ms->params[i]); if (ret < 0) { gnutls_assert(); goto rsa_fail; } params->params_nr++; } mpz_set(TOMPZ(params->params[0]), pub.n); mpz_set(TOMPZ(params->params[1]), pub.e); mpz_set(TOMPZ(params->params[2]), priv.d); mpz_set(TOMPZ(params->params[3]), priv.p); mpz_set(TOMPZ(params->params[4]), priv.q); mpz_set(TOMPZ(params->params[5]), priv.c); mpz_set(TOMPZ(params->params[6]), priv.a); mpz_set(TOMPZ(params->params[7]), priv.b); ret = 0; rsa_fail: rsa_private_key_clear(&priv); rsa_public_key_clear(&pub); if (ret < 0) goto fail; break; } case GNUTLS_PK_EC: { struct ecc_scalar key; struct ecc_point pub; const struct ecc_curve *curve; curve = get_supported_curve(level); if (curve == NULL) return gnutls_assert_val (GNUTLS_E_ECC_UNSUPPORTED_CURVE); ecc_scalar_init(&key, curve); ecc_point_init(&pub, curve); ecdsa_generate_keypair(&pub, &key, NULL, rnd_func); ret = _gnutls_mpi_init_multi(¶ms->params[ECC_X], ¶ms->params[ECC_Y], ¶ms->params[ECC_K], NULL); if (ret < 0) { gnutls_assert(); goto ecc_fail; } params->flags = level; params->params_nr = ECC_PRIVATE_PARAMS; ecc_point_get(&pub, TOMPZ(params->params[ECC_X]), TOMPZ(params->params[ECC_Y])); ecc_scalar_get(&key, TOMPZ(params->params[ECC_K])); ret = 0; ecc_fail: ecc_point_clear(&pub); ecc_scalar_clear(&key); if (ret < 0) goto fail; break; } default: gnutls_assert(); return GNUTLS_E_INVALID_REQUEST; } FAIL_IF_LIB_ERROR; return 0; fail: for (i = 0; i < params->params_nr; i++) { _gnutls_mpi_release(¶ms->params[i]); } params->params_nr = 0; FAIL_IF_LIB_ERROR; return ret; }