/* 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; }
/**************** * 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; }
/* 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; }
/* 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; }
/**************** * 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; }
/* 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; }
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; }
/* c = c*ri mod n */ static inline void rsa_unblind (bigint_t c, bigint_t ri, bigint_t n) { _gnutls_mpi_mulm (c, c, ri, n); }
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; }