/* 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 bits; bits = _gnutls_mpi_get_nbits (n); tmpa = _gnutls_mpi_randomize (NULL, bits, GNUTLS_RND_RANDOM); A = _gnutls_mpi_new (bits); if (A == NULL) { gnutls_assert (); _gnutls_mpi_release (&tmpa); return NULL; } _gnutls_mpi_powm (A, g, tmpa, n); if (a != NULL) *a = tmpa; else _gnutls_mpi_release (&tmpa); return A; }
/* 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 int wrap_gcry_pk_fixup (gnutls_pk_algorithm_t algo, gnutls_direction_t direction, gnutls_pk_params_st * params) { int ret, result; /* only for RSA we invert the coefficient --pgp type */ if (algo != GNUTLS_PK_RSA) return 0; if (params->params[5] == NULL) params->params[5] = _gnutls_mpi_new (_gnutls_mpi_get_nbits (params->params[0])); if (params->params[5] == NULL) { gnutls_assert (); return GNUTLS_E_MEMORY_ERROR; } ret = 1; if (direction == GNUTLS_IMPORT) { /* calculate exp1 [6] and exp2 [7] */ _gnutls_mpi_release (¶ms->params[6]); _gnutls_mpi_release (¶ms->params[7]); result = _gnutls_calc_rsa_exp (params->params, RSA_PRIVATE_PARAMS); if (result < 0) { gnutls_assert (); return result; } ret = gcry_mpi_invm (params->params[5], params->params[3], params->params[4]); params->params_nr = RSA_PRIVATE_PARAMS; } else if (direction == GNUTLS_EXPORT) ret = gcry_mpi_invm (params->params[5], params->params[4], params->params[3]); if (ret == 0) { gnutls_assert (); return GNUTLS_E_INVALID_REQUEST; } return 0; }
/* * Copyright (C) 2007-2012 Free Software Foundation, Inc. * * Author: Nikos Mavrogiannopoulos, Simon Josefsson * * This file is part of GnuTLS. * * GnuTLS is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * GnuTLS is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with GnuTLS; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ #ifdef HAVE_CONFIG_H #include <config.h> #endif #include <stdio.h> #include "utils.h" #include "../lib/gnutls_int.h" #include "../lib/gnutls_mpi.h" #include "../lib/gnutls_errors.h" #include "../lib/debug.h" static void tls_log_func (int level, const char *str) { fprintf (stderr, "|<%d>| %s", level, str); } #define RND_BITS 510 /* not multiple of 8 */ void doit (void) { int rc; bigint_t n1, n2, n3, n4; gnutls_global_init (); gnutls_global_set_log_function (tls_log_func); if (debug) gnutls_global_set_log_level (99); n1 = _gnutls_mpi_new (1000); if (n1 == NULL) fail ("mpi_new failed\n"); n2 = _gnutls_mpi_set_ui (NULL, 2); if (n2 == NULL) fail ("mpi_set_ui failed\n"); n3 = _gnutls_mpi_set_ui (NULL, 5); if (n3 == NULL) fail ("mpi_set_ui failed\n"); _gnutls_mpi_randomize (n1, RND_BITS, GNUTLS_RND_NONCE); _gnutls_mpi_log ("rand:", n1); rc = _gnutls_mpi_get_nbits (n1); if (rc > RND_BITS) fail ("mpi_get_nbits failed... returned %d\n", rc); n4 = _gnutls_mpi_addm (NULL, n1, n3, n2); if (n4 == NULL) fail ("mpi_set_ui failed\n"); if (_gnutls_mpi_cmp_ui (n4, 0) != 0 && _gnutls_mpi_cmp_ui (n4, 1) != 0) fail ("mpi_cmp_ui failed\n"); _gnutls_mpi_release (&n1); _gnutls_mpi_release (&n2); _gnutls_mpi_release (&n3); _gnutls_mpi_release (&n4); gnutls_global_deinit (); if (debug) success ("mpi ops ok\n"); }
/* 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; }
/**************** * 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 bits; /* calculate: B = (k*v + g^b) % N */ bits = _gnutls_mpi_get_nbits (n); tmpV = _gnutls_mpi_alloc_like (n); if (tmpV == NULL) { gnutls_assert (); goto error; } b = _gnutls_mpi_randomize (NULL, bits, GNUTLS_RND_RANDOM); tmpB = _gnutls_mpi_new (bits); if (tmpB == NULL) { gnutls_assert (); goto error; } B = _gnutls_mpi_new (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_verify_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); t1 = _gnutls_mpi_new (256); if (t1 == NULL) return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); _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); t2 = _gnutls_mpi_mod (params->params[RSA_PRIV], t1); if (t2 == NULL) { 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); _gnutls_mpi_release(&t2); t2 = _gnutls_mpi_mod (params->params[RSA_PRIV], t1); if (t2 == NULL) { 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: _gnutls_mpi_release(&t1); _gnutls_mpi_release(&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); t1 = _gnutls_mpi_new (256); if (t1 == NULL) return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); _gnutls_mpi_powm (t1, params->params[DSA_G], params->params[DSA_X], params->params[DSA_P]); 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: _gnutls_mpi_release(&t1); } break; case GNUTLS_PK_EC: { int curve = params->flags; ecc_key ecc_priv; ecc_point *R; ecc_point zero; if (params->params_nr != ECC_PRIVATE_PARAMS) return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); if (is_supported_curve(curve) == 0) return gnutls_assert_val(GNUTLS_E_ECC_UNSUPPORTED_CURVE); _ecc_params_to_privkey(params, &ecc_priv); R = ecc_new_point(); /* verify that x,y lie on the curve */ ret = ecc_projective_check_point(&ecc_priv.pubkey, TOMPZ(params->params[ECC_B]), params->params[ECC_PRIME]); if (ret != 0) { ret = gnutls_assert_val(GNUTLS_E_ILLEGAL_PARAMETER); goto ecc_cleanup; } memcpy(&zero.x, ecc_priv.Gx, sizeof(mpz_t)); memcpy(&zero.y, ecc_priv.Gy, sizeof(mpz_t)); memcpy(&zero.z, ecc_priv.pubkey.z, sizeof(mpz_t)); /* z = 1 */ /* verify that k*(Gx,Gy)=(x,y) */ ret = ecc_mulmod_cached(ecc_priv.k, curve, R, TOMPZ(params->params[ECC_A]), TOMPZ(params->params[ECC_PRIME]), 1); if (ret != 0) { ret = gnutls_assert_val(GNUTLS_E_ILLEGAL_PARAMETER); goto ecc_cleanup; } if (mpz_cmp(ecc_priv.pubkey.x, R->x) != 0 || mpz_cmp(ecc_priv.pubkey.y, R->y) != 0) { ret = gnutls_assert_val(GNUTLS_E_ILLEGAL_PARAMETER); goto ecc_cleanup; } ret = 0; ecc_cleanup: _ecc_params_clear(&ecc_priv); ecc_del_point(R); } break; default: ret = gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); } return ret; }
static int wrap_nettle_pk_verify_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); t1 = _gnutls_mpi_new(256); if (t1 == NULL) return gnutls_assert_val (GNUTLS_E_MEMORY_ERROR); _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); t2 = _gnutls_mpi_mod(params->params[RSA_PRIV], t1); if (t2 == NULL) { 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); _gnutls_mpi_release(&t2); t2 = _gnutls_mpi_mod(params->params[RSA_PRIV], t1); if (t2 == NULL) { 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: _gnutls_mpi_release(&t1); _gnutls_mpi_release(&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); t1 = _gnutls_mpi_new(256); if (t1 == NULL) return gnutls_assert_val (GNUTLS_E_MEMORY_ERROR); _gnutls_mpi_powm(t1, params->params[DSA_G], params->params[DSA_X], params->params[DSA_P]); 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: _gnutls_mpi_release(&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_clear(&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_clear(&priv); ecc_point_clear(&pub); } break; default: ret = gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); } 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; }