/* S = (A * v^u) ^ b % N * this is our shared key (server premaster secret) */ mpi_t _gnutls_calc_srp_S1 (mpi_t A, mpi_t b, mpi_t u, mpi_t v, mpi_t n) { mpi_t tmp1 = NULL, tmp2 = NULL; mpi_t S = NULL; S = _gnutls_mpi_alloc_like (n); if (S == NULL) return NULL; tmp1 = _gnutls_mpi_alloc_like (n); tmp2 = _gnutls_mpi_alloc_like (n); if (tmp1 == NULL || tmp2 == NULL) goto freeall; _gnutls_mpi_powm (tmp1, v, u, n); _gnutls_mpi_mulm (tmp2, A, tmp1, n); _gnutls_mpi_powm (S, tmp2, b, n); _gnutls_mpi_release (&tmp1); _gnutls_mpi_release (&tmp2); return S; freeall: _gnutls_mpi_release (&tmp1); _gnutls_mpi_release (&tmp2); return NULL; }
/* 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; S = _gnutls_mpi_alloc_like (n); if (S == NULL) return NULL; tmp1 = _gnutls_mpi_alloc_like (n); tmp2 = _gnutls_mpi_alloc_like (n); tmp3 = _gnutls_mpi_alloc_like (n); if (tmp1 == NULL || tmp2 == NULL || tmp3 == NULL) { goto freeall; } k = _gnutls_calc_srp_u (n, g, n); if (k == NULL) { gnutls_assert (); goto freeall; } _gnutls_mpi_powm (tmp1, g, x, n); /* g^x */ _gnutls_mpi_mulm (tmp3, tmp1, k, n); /* k*g^x mod n */ _gnutls_mpi_subm (tmp2, B, tmp3, n); tmp4 = _gnutls_mpi_alloc_like (n); if (tmp4 == NULL) goto freeall; _gnutls_mpi_mul (tmp1, u, x); _gnutls_mpi_add (tmp4, a, tmp1); _gnutls_mpi_powm (S, tmp2, tmp4, n); _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; }
/* returns the blinded c and the inverse of a random * number r; */ static bigint_t rsa_blind (bigint_t c, bigint_t e, bigint_t n, bigint_t * _ri) { bigint_t nc = NULL, r = NULL, ri = NULL; /* nc = c*(r^e) * ri = r^(-1) */ nc = _gnutls_mpi_alloc_like (n); if (nc == NULL) { gnutls_assert (); return NULL; } ri = _gnutls_mpi_alloc_like (n); if (nc == NULL) { gnutls_assert (); goto fail; } r = _gnutls_mpi_randomize (NULL, _gnutls_mpi_get_nbits (n), GNUTLS_RND_NONCE); if (r == NULL) { gnutls_assert (); goto fail; } /* invert r */ if (mpz_invert (ri, r, n) == 0) { gnutls_assert (); goto fail; } /* r = r^e */ _gnutls_mpi_powm (r, r, e, n); _gnutls_mpi_mulm (nc, c, r, n); *_ri = ri; _gnutls_mpi_release (&r); return nc; fail: _gnutls_mpi_release (&nc); _gnutls_mpi_release (&r); return NULL; }
int _gnutls_calc_rsa_exp (bigint_t * params, unsigned int params_size) { bigint_t tmp = _gnutls_mpi_alloc_like (params[0]); if (params_size < RSA_PRIVATE_PARAMS - 2) { gnutls_assert (); return GNUTLS_E_INTERNAL_ERROR; } if (tmp == NULL) { gnutls_assert (); return GNUTLS_E_MEMORY_ERROR; } /* [6] = d % p-1, [7] = d % q-1 */ _gnutls_mpi_sub_ui (tmp, params[3], 1); params[6] = _gnutls_mpi_mod (params[2] /*d */ , tmp); _gnutls_mpi_sub_ui (tmp, params[4], 1); params[7] = _gnutls_mpi_mod (params[2] /*d */ , tmp); _gnutls_mpi_release (&tmp); if (params[7] == NULL || params[6] == NULL) { gnutls_assert (); return GNUTLS_E_MEMORY_ERROR; } return 0; }
/* Checks if b%n==0 which is a fatal srp error. * Returns a proper error code in that case, and 0 when * all are ok. */ inline static int check_b_mod_n (mpi_t b, mpi_t n) { int ret; mpi_t r = _gnutls_mpi_alloc_like (b); if (r == NULL) { gnutls_assert (); return GNUTLS_E_MEMORY_ERROR; } _gnutls_mpi_mod (r, b, n); ret = _gnutls_mpi_cmp_ui (r, 0); _gnutls_mpi_release (&r); if (ret == 0) { gnutls_assert (); return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER; } return 0; }
/* returns the public value (X), and the secret (ret_x). */ mpi_t gnutls_calc_dh_secret (mpi_t * ret_x, mpi_t g, mpi_t prime) { mpi_t e, x; int x_size = _gnutls_mpi_get_nbits (prime) - 1; /* The size of the secret key is less than * prime/2 */ if (x_size > MAX_BITS || x_size <= 0) { gnutls_assert (); return NULL; } x = _gnutls_mpi_new (x_size); if (x == NULL) { gnutls_assert (); if (ret_x) *ret_x = NULL; return NULL; } /* FIXME: (x_size/8)*8 is there to overcome a bug in libgcrypt * which does not really check the bits given but the bytes. */ do { _gnutls_mpi_randomize (x, (x_size / 8) * 8, GCRY_STRONG_RANDOM); /* Check whether x is zero. */ } while (_gnutls_mpi_cmp_ui (x, 0) == 0); e = _gnutls_mpi_alloc_like (prime); if (e == NULL) { gnutls_assert (); if (ret_x) *ret_x = NULL; _gnutls_mpi_release (&x); return NULL; } _gnutls_mpi_powm (e, g, x, prime); if (ret_x) *ret_x = x; else _gnutls_mpi_release (&x); return e; }
static bigint_t wrap_gcry_mpi_mod (const bigint_t a, const bigint_t b) { bigint_t r = _gnutls_mpi_alloc_like (b); if (r == NULL) return NULL; gcry_mpi_mod (r, a, b); return r; }
static bigint_t wrap_gcry_mpi_mul_ui (bigint_t w, const bigint_t a, unsigned long b) { if (w == NULL) w = _gnutls_mpi_alloc_like (a); if (w == NULL) return NULL; gcry_mpi_mul_ui (w, a, b); return w; }
/* q = a / b */ static bigint_t wrap_gcry_mpi_div (bigint_t q, const bigint_t a, const bigint_t b) { if (q == NULL) q = _gnutls_mpi_alloc_like (a); if (q == NULL) return NULL; gcry_mpi_div (q, NULL, a, b, 0); return q; }
static bigint_t wrap_gcry_mpi_mul (bigint_t w, const bigint_t a, const bigint_t b) { if (w == NULL) w = _gnutls_mpi_alloc_like (b); if (w == NULL) return NULL; gcry_mpi_mul (w, a, b); return w; }
static bigint_t wrap_gcry_mpi_subm (bigint_t w, const bigint_t a, const bigint_t b, const bigint_t m) { if (w == NULL) w = _gnutls_mpi_alloc_like (m); if (w == NULL) return NULL; gcry_mpi_subm (w, a, b, m); return w; }
int _gnutls_srp_gx (opaque * text, size_t textsize, opaque ** result, bigint_t g, bigint_t prime, gnutls_alloc_function galloc_func) { bigint_t x, e; size_t result_size; int ret; if (_gnutls_mpi_scan_nz (&x, text, textsize)) { gnutls_assert (); return GNUTLS_E_MPI_SCAN_FAILED; } e = _gnutls_mpi_alloc_like (prime); if (e == NULL) { gnutls_assert (); _gnutls_mpi_release (&x); return GNUTLS_E_MEMORY_ERROR; } /* e = g^x mod prime (n) */ _gnutls_mpi_powm (e, g, x, prime); _gnutls_mpi_release (&x); ret = _gnutls_mpi_print (e, NULL, &result_size); if (ret == GNUTLS_E_SHORT_MEMORY_BUFFER) { *result = galloc_func (result_size); if ((*result) == NULL) return GNUTLS_E_MEMORY_ERROR; _gnutls_mpi_print (e, *result, &result_size); ret = result_size; } else { gnutls_assert (); ret = GNUTLS_E_MPI_PRINT_FAILED; } _gnutls_mpi_release (&e); return ret; }
mpi_t gnutls_calc_dh_key (mpi_t f, mpi_t x, mpi_t prime) { mpi_t k; int bits; bits = _gnutls_mpi_get_nbits (prime); if (bits <= 0 || bits > MAX_BITS) { gnutls_assert (); return NULL; } k = _gnutls_mpi_alloc_like (prime); if (k == NULL) return NULL; _gnutls_mpi_powm (k, f, x, prime); return k; }
int _gnutls_srp_gx (opaque * text, size_t textsize, opaque ** result, mpi_t g, mpi_t prime, gnutls_alloc_function galloc_func) { mpi_t x, e; size_t result_size; if (_gnutls_mpi_scan_nz (&x, text, &textsize)) { gnutls_assert (); return GNUTLS_E_MPI_SCAN_FAILED; } e = _gnutls_mpi_alloc_like (prime); if (e == NULL) { gnutls_assert (); _gnutls_mpi_release (&x); return GNUTLS_E_MEMORY_ERROR; } /* e = g^x mod prime (n) */ _gnutls_mpi_powm (e, g, x, prime); _gnutls_mpi_release (&x); _gnutls_mpi_print (NULL, &result_size, e); if (result != NULL) { *result = galloc_func (result_size); if ((*result) == NULL) return GNUTLS_E_MEMORY_ERROR; _gnutls_mpi_print (*result, &result_size, e); } _gnutls_mpi_release (&e); return result_size; }
/* Check if N is a prime and G a generator of the * group. This is check only done if N is big enough. * Otherwise only the included parameters must be used. */ static int group_check_g_n (mpi_t g, mpi_t n) { mpi_t q = NULL, two = NULL, w = NULL; int ret; if (_gnutls_mpi_get_nbits (n) < 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) != 0) { _gnutls_dump_mpi ("no prime N: ", n); gnutls_assert (); return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER; } two = _gnutls_mpi_new (4); if (two == NULL) { gnutls_assert (); return GNUTLS_E_MEMORY_ERROR; } q = _gnutls_mpi_alloc_like (n); if (q == NULL) { gnutls_assert (); ret = GNUTLS_E_MEMORY_ERROR; goto error; } /* q = n-1 */ _gnutls_mpi_sub_ui (q, n, 1); /* q = q/2, remember that q is divisible by 2 (prime - 1) */ _gnutls_mpi_set_ui (two, 2); _gnutls_mpi_div (q, NULL, q, two, 0); if (_gnutls_prime_check (q, 0) != 0) { /* N was not on the form N=2q+1, where q = prime */ _gnutls_dump_mpi ("no prime Q: ", q); gnutls_assert (); return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER; } /* 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; } w = _gnutls_mpi_alloc_like (q); if (w == NULL) { gnutls_assert (); ret = GNUTLS_E_MEMORY_ERROR; goto error; } /* check if g^q mod N == N-1 * w = g^q mod N */ _gnutls_mpi_powm (w, g, q, n); /* w++ */ _gnutls_mpi_add_ui (w, w, 1); 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; }
static int _rsa_generate_params (bigint_t * resarr, int *resarr_len, int bits) { int ret, i; gcry_sexp_t parms, key, list; bigint_t tmp; if (*resarr_len < RSA_PRIVATE_PARAMS) { gnutls_assert (); return GNUTLS_E_INTERNAL_ERROR; } ret = gcry_sexp_build (&parms, NULL, "(genkey(rsa(nbits %d)))", bits); if (ret != 0) { gnutls_assert (); return GNUTLS_E_INTERNAL_ERROR; } /* generate the RSA key */ ret = gcry_pk_genkey (&key, parms); gcry_sexp_release (parms); if (ret != 0) { gnutls_assert (); return GNUTLS_E_INTERNAL_ERROR; } list = gcry_sexp_find_token (key, "n", 0); if (list == NULL) { gnutls_assert (); gcry_sexp_release (key); return GNUTLS_E_INTERNAL_ERROR; } resarr[0] = gcry_sexp_nth_mpi (list, 1, GCRYMPI_FMT_USG); gcry_sexp_release (list); list = gcry_sexp_find_token (key, "e", 0); if (list == NULL) { gnutls_assert (); gcry_sexp_release (key); return GNUTLS_E_INTERNAL_ERROR; } resarr[1] = gcry_sexp_nth_mpi (list, 1, GCRYMPI_FMT_USG); gcry_sexp_release (list); list = gcry_sexp_find_token (key, "d", 0); if (list == NULL) { gnutls_assert (); gcry_sexp_release (key); return GNUTLS_E_INTERNAL_ERROR; } resarr[2] = gcry_sexp_nth_mpi (list, 1, GCRYMPI_FMT_USG); gcry_sexp_release (list); list = gcry_sexp_find_token (key, "p", 0); if (list == NULL) { gnutls_assert (); gcry_sexp_release (key); return GNUTLS_E_INTERNAL_ERROR; } resarr[3] = gcry_sexp_nth_mpi (list, 1, GCRYMPI_FMT_USG); gcry_sexp_release (list); list = gcry_sexp_find_token (key, "q", 0); if (list == NULL) { gnutls_assert (); gcry_sexp_release (key); return GNUTLS_E_INTERNAL_ERROR; } resarr[4] = gcry_sexp_nth_mpi (list, 1, GCRYMPI_FMT_USG); gcry_sexp_release (list); list = gcry_sexp_find_token (key, "u", 0); if (list == NULL) { gnutls_assert (); gcry_sexp_release (key); return GNUTLS_E_INTERNAL_ERROR; } resarr[5] = gcry_sexp_nth_mpi (list, 1, GCRYMPI_FMT_USG); gcry_sexp_release (list); gcry_sexp_release (key); _gnutls_mpi_log ("n: ", resarr[0]); _gnutls_mpi_log ("e: ", resarr[1]); _gnutls_mpi_log ("d: ", resarr[2]); _gnutls_mpi_log ("p: ", resarr[3]); _gnutls_mpi_log ("q: ", resarr[4]); _gnutls_mpi_log ("u: ", resarr[5]); /* generate e1 and e2 */ *resarr_len = 6; tmp = _gnutls_mpi_alloc_like (resarr[0]); if (tmp == NULL) { gnutls_assert (); ret = GNUTLS_E_MEMORY_ERROR; goto cleanup; } ret = _gnutls_calc_rsa_exp (resarr, 2 + *resarr_len); if (ret < 0) { gnutls_assert (); ret = GNUTLS_E_MEMORY_ERROR; goto cleanup; } (*resarr_len) += 2; return 0; cleanup: for (i = 0; i < *resarr_len; i++) _gnutls_mpi_release (&resarr[i]); return ret; }
static int wrap_nettle_pk_generate_params(gnutls_pk_algorithm_t algo, unsigned int level /*bits */ , gnutls_pk_params_st * params) { int ret; unsigned int i, q_bits; memset(params, 0, sizeof(*params)); switch (algo) { case GNUTLS_PK_DSA: { struct dsa_public_key pub; struct dsa_private_key priv; dsa_public_key_init(&pub); dsa_private_key_init(&priv); /* the best would be to use _gnutls_pk_bits_to_subgroup_bits() * but we do NIST DSA here */ if (level <= 1024) q_bits = 160; else 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_INTERNAL_ERROR; goto dsa_fail; } params->params_nr = 0; for (i = 0; i < DSA_PRIVATE_PARAMS; i++) { params->params[i] = _gnutls_mpi_alloc_like(&pub.p); if (params->params[i] == NULL) { ret = GNUTLS_E_MEMORY_ERROR; goto dsa_fail; } params->params_nr++; } ret = 0; _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); dsa_public_key_clear(&pub); 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); _gnutls_mpi_set_ui(&pub.e, 65537); ret = rsa_generate_keypair(&pub, &priv, NULL, rnd_func, NULL, NULL, level, 0); if (ret != 1) { gnutls_assert(); ret = GNUTLS_E_INTERNAL_ERROR; goto rsa_fail; } params->params_nr = 0; for (i = 0; i < RSA_PRIVATE_PARAMS; i++) { params->params[i] = _gnutls_mpi_alloc_like(&pub.n); if (params->params[i] == NULL) { ret = GNUTLS_E_MEMORY_ERROR; goto rsa_fail; } params->params_nr++; } ret = 0; _gnutls_mpi_set(params->params[0], pub.n); _gnutls_mpi_set(params->params[1], pub.e); _gnutls_mpi_set(params->params[2], priv.d); _gnutls_mpi_set(params->params[3], priv.p); _gnutls_mpi_set(params->params[4], priv.q); _gnutls_mpi_set(params->params[5], priv.c); _gnutls_mpi_set(params->params[6], priv.a); _gnutls_mpi_set(params->params[7], priv.b); 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); params->params[ECC_X] = _gnutls_mpi_new(0); params->params[ECC_Y] = _gnutls_mpi_new(0); params->params[ECC_K] = _gnutls_mpi_new(0); if (params->params[ECC_X] == NULL || params->params[ECC_Y] == NULL || params->params[ECC_K] == NULL) { _gnutls_mpi_release(¶ms-> params[ECC_X]); _gnutls_mpi_release(¶ms-> params[ECC_Y]); _gnutls_mpi_release(¶ms-> params[ECC_K]); goto ecc_cleanup; } 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])); ecc_cleanup: ecc_point_clear(&pub); ecc_scalar_clear(&key); 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; }
/**************** * 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. */ mpi_t _gnutls_calc_srp_B (mpi_t * ret_b, mpi_t g, mpi_t n, mpi_t v) { mpi_t tmpB = NULL, tmpV = NULL; mpi_t b = NULL, B = NULL, k = NULL; int bits; /* calculate: B = (k*v + g^b) % N */ bits = _gnutls_mpi_get_nbits (n); b = _gnutls_mpi_snew (bits); if (b == NULL) { gnutls_assert (); return NULL; } tmpV = _gnutls_mpi_alloc_like (n); if (tmpV == NULL) { gnutls_assert (); goto error; } _gnutls_mpi_randomize (b, bits, GCRY_STRONG_RANDOM); tmpB = _gnutls_mpi_snew (bits); if (tmpB == NULL) { gnutls_assert (); goto error; } B = _gnutls_mpi_snew (bits); if (B == NULL) { gnutls_assert (); goto error; } k = _gnutls_calc_srp_u (n, g, n); if (k == NULL) { gnutls_assert (); goto error; } _gnutls_mpi_mulm (tmpV, k, v, n); _gnutls_mpi_powm (tmpB, g, b, n); _gnutls_mpi_addm (B, tmpV, tmpB, n); _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 wrap_nettle_pk_generate_params (gnutls_pk_algorithm_t algo, unsigned int level /*bits */ , gnutls_pk_params_st * params) { int ret; unsigned int i, q_bits; memset(params, 0, sizeof(*params)); switch (algo) { case GNUTLS_PK_DSA: { struct dsa_public_key pub; struct dsa_private_key priv; dsa_public_key_init (&pub); dsa_private_key_init (&priv); /* the best would be to use _gnutls_pk_bits_to_subgroup_bits() * but we do NIST DSA here */ if (level <= 1024) q_bits = 160; else 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_INTERNAL_ERROR; goto dsa_fail; } params->params_nr = 0; for (i = 0; i < DSA_PRIVATE_PARAMS; i++) { params->params[i] = _gnutls_mpi_alloc_like (&pub.p); if (params->params[i] == NULL) { ret = GNUTLS_E_MEMORY_ERROR; goto dsa_fail; } params->params_nr++; } ret = 0; _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); dsa_public_key_clear (&pub); 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); _gnutls_mpi_set_ui (&pub.e, 65537); ret = rsa_generate_keypair (&pub, &priv, NULL, rnd_func, NULL, NULL, level, 0); if (ret != 1) { gnutls_assert (); ret = GNUTLS_E_INTERNAL_ERROR; goto rsa_fail; } params->params_nr = 0; for (i = 0; i < RSA_PRIVATE_PARAMS; i++) { params->params[i] = _gnutls_mpi_alloc_like (&pub.n); if (params->params[i] == NULL) { ret = GNUTLS_E_MEMORY_ERROR; goto rsa_fail; } params->params_nr++; } ret = 0; _gnutls_mpi_set (params->params[0], pub.n); _gnutls_mpi_set (params->params[1], pub.e); _gnutls_mpi_set (params->params[2], priv.d); _gnutls_mpi_set (params->params[3], priv.p); _gnutls_mpi_set (params->params[4], priv.q); _gnutls_mpi_set (params->params[5], priv.c); _gnutls_mpi_set (params->params[6], priv.a); _gnutls_mpi_set (params->params[7], priv.b); rsa_fail: rsa_private_key_clear (&priv); rsa_public_key_clear (&pub); if (ret < 0) goto fail; break; } case GNUTLS_PK_EC: { ecc_key key; ecc_set_type tls_ecc_set; const gnutls_ecc_curve_entry_st *st; st = _gnutls_ecc_curve_get_params(level); if (st == NULL) return gnutls_assert_val(GNUTLS_E_ECC_UNSUPPORTED_CURVE); tls_ecc_set.size = st->size; tls_ecc_set.prime = st->prime; tls_ecc_set.order = st->order; tls_ecc_set.Gx = st->Gx; tls_ecc_set.Gy = st->Gy; tls_ecc_set.A = st->A; tls_ecc_set.B = st->B; ret = ecc_make_key(NULL, rnd_func, &key, &tls_ecc_set, st->id); if (ret != 0) return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); params->params_nr = 0; for (i = 0; i < ECC_PRIVATE_PARAMS; i++) { params->params[i] = _gnutls_mpi_alloc_like(&key.prime); if (params->params[i] == NULL) { ret = GNUTLS_E_MEMORY_ERROR; goto ecc_fail; } params->params_nr++; } params->flags = level; mpz_set(TOMPZ(params->params[ECC_PRIME]), key.prime); mpz_set(TOMPZ(params->params[ECC_ORDER]), key.order); mpz_set(TOMPZ(params->params[ECC_A]), key.A); mpz_set(TOMPZ(params->params[ECC_B]), key.B); mpz_set(TOMPZ(params->params[ECC_GX]), key.Gx); mpz_set(TOMPZ(params->params[ECC_GY]), key.Gy); mpz_set(TOMPZ(params->params[ECC_X]), key.pubkey.x); mpz_set(TOMPZ(params->params[ECC_Y]), key.pubkey.y); mpz_set(TOMPZ(params->params[ECC_K]), key.k); ecc_fail: ecc_free(&key); if (ret < 0) goto fail; 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; }