/* q = a / b */ static int wrap_nettle_mpi_div(bigint_t q, const bigint_t a, const bigint_t b) { mpz_cdiv_q(TOMPZ(q), TOMPZ(a), TOMPZ(b)); return 0; }
static int wrap_nettle_pk_fixup (gnutls_pk_algorithm_t algo, gnutls_direction_t direction, gnutls_pk_params_st * params) { int result; if (direction == GNUTLS_IMPORT && algo == GNUTLS_PK_RSA) { /* do not trust the generated values. Some old private keys * generated by us have mess on the values. Those were very * old but it seemed some of the shipped example private * keys were as old. */ mpz_invert (TOMPZ (params->params[RSA_COEF]), TOMPZ (params->params[RSA_PRIME2]), TOMPZ (params->params[RSA_PRIME1])); /* calculate exp1 [6] and exp2 [7] */ _gnutls_mpi_release (¶ms->params[RSA_E1]); _gnutls_mpi_release (¶ms->params[RSA_E2]); result = calc_rsa_exp (params); if (result < 0) { gnutls_assert (); return result; } params->params_nr = RSA_PRIVATE_PARAMS; } return 0; }
static int wrap_nettle_mpi_mul(bigint_t w, const bigint_t a, const bigint_t b) { mpz_mul(TOMPZ(w), TOMPZ(a), TOMPZ(b)); return 0; }
static int wrap_nettle_mpi_mul_ui(bigint_t w, const bigint_t a, unsigned long b) { mpz_mul_ui(TOMPZ(w), TOMPZ(a), b); return 0; }
static int wrap_nettle_mpi_powm(bigint_t w, const bigint_t b, const bigint_t e, const bigint_t m) { mpz_powm(TOMPZ(w), TOMPZ(b), TOMPZ(e), TOMPZ(m)); return 0; }
static int wrap_nettle_mpi_modm(bigint_t r, const bigint_t a, const bigint_t b) { if (mpz_cmp_ui(TOMPZ(b), 0) == 0) return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); mpz_mod(TOMPZ(r), TOMPZ(a), TOMPZ(b)); return 0; }
static int wrap_nettle_pk_verify_pub_params(gnutls_pk_algorithm_t algo, const gnutls_pk_params_st * params) { int ret; switch (algo) { case GNUTLS_PK_RSA: case GNUTLS_PK_DSA: return 0; case GNUTLS_PK_EC: { /* just verify that x and y lie on the curve */ struct ecc_point r, pub; const struct ecc_curve *curve; if (params->params_nr != ECC_PUBLIC_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); 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); ret = 0; ecc_cleanup: ecc_point_clear(&pub); } break; default: ret = gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); } return ret; }
static int wrap_nettle_mpi_init_multi(bigint_t *w, ...) { va_list args; bigint_t *next; int ret; bigint_t* last_failed = NULL; ret = wrap_nettle_mpi_init(w); if (ret < 0) { gnutls_assert(); return ret; } va_start(args, w); do { next = va_arg(args, bigint_t*); if (next != NULL) { ret = wrap_nettle_mpi_init(next); if (ret < 0) { gnutls_assert(); va_end(args); last_failed = next; goto fail; } } } while(next != 0); va_end(args); return 0; fail: mpz_clear(TOMPZ(*w)); gnutls_free(*w); va_start(args, w); do { next = va_arg(args, bigint_t*); if (next != last_failed) { mpz_clear(TOMPZ(*next)); gnutls_free(*next); } } while(next != last_failed); va_end(args); return GNUTLS_E_MEMORY_ERROR; }
static int _wrap_nettle_pk_encrypt (gnutls_pk_algorithm_t algo, gnutls_datum_t * ciphertext, const gnutls_datum_t * plaintext, const gnutls_pk_params_st * pk_params) { int ret; switch (algo) { case GNUTLS_PK_RSA: { bigint_t p; if (_gnutls_mpi_scan_nz (&p, plaintext->data, plaintext->size) != 0) { gnutls_assert (); return GNUTLS_E_MPI_SCAN_FAILED; } mpz_powm (p, p, TOMPZ (pk_params->params[1]) /*e */ , TOMPZ (pk_params->params[0] /*m */ )); ret = _gnutls_mpi_dprint_size (p, ciphertext, plaintext->size); _gnutls_mpi_release (&p); if (ret < 0) { gnutls_assert (); goto cleanup; } break; } default: gnutls_assert (); ret = GNUTLS_E_INTERNAL_ERROR; goto cleanup; } ret = 0; cleanup: return ret; }
static int _int_rsa_verify (const gnutls_pk_params_st * pk_params, bigint_t m, bigint_t s) { int res; mpz_t m1; if ((mpz_sgn (TOMPZ (s)) <= 0) || (mpz_cmp (TOMPZ (s), TOMPZ (pk_params->params[0])) >= 0)) return GNUTLS_E_PK_SIG_VERIFY_FAILED; mpz_init (m1); mpz_powm (m1, TOMPZ (s), TOMPZ (pk_params->params[1]), TOMPZ (pk_params->params[0])); res = !mpz_cmp (TOMPZ (m), m1); mpz_clear (m1); if (res == 0) res = GNUTLS_E_PK_SIG_VERIFY_FAILED; else res = 0; return res; }
static int wrap_nettle_prime_check(bigint_t pp) { int ret; ret = mpz_probab_prime_p(TOMPZ(pp), PRIME_CHECK_PARAM); if (ret > 0) { return 0; } return GNUTLS_E_INTERNAL_ERROR; /* ignored */ }
static void _rsa_params_to_privkey (const gnutls_pk_params_st * pk_params, struct rsa_private_key *priv) { memcpy (&priv->d, pk_params->params[2], sizeof (mpz_t)); memcpy (&priv->p, pk_params->params[3], sizeof (mpz_t)); memcpy (&priv->q, pk_params->params[4], sizeof (mpz_t)); memcpy (&priv->c, pk_params->params[5], sizeof (mpz_t)); memcpy (&priv->a, pk_params->params[6], sizeof (mpz_t)); memcpy (&priv->b, pk_params->params[7], sizeof (mpz_t)); priv->size = nettle_mpz_sizeinbase_256_u(TOMPZ(pk_params->params[RSA_MODULUS])); }
static int wrap_nettle_mpi_scan(bigint_t r, const void *buffer, size_t nbytes, gnutls_bigint_format_t format) { if (format == GNUTLS_MPI_FORMAT_USG) { nettle_mpz_set_str_256_u(TOMPZ(r), nbytes, buffer); } else if (format == GNUTLS_MPI_FORMAT_STD) { nettle_mpz_set_str_256_s(TOMPZ(r), nbytes, buffer); #if ENABLE_GOST } else if (format == GNUTLS_MPI_FORMAT_ULE) { nettle_mpz_set_str_256_u_le(TOMPZ(r), nbytes, buffer); #endif } else { gnutls_assert(); goto fail; } return 0; fail: return GNUTLS_E_MPI_SCAN_FAILED; }
static bigint_t wrap_nettle_mpi_copy(const bigint_t u) { int ret; bigint_t w; ret = wrap_nettle_mpi_init(&w); if (ret < 0) return NULL; mpz_set(TOMPZ(w), u); return w; }
static int wrap_nettle_pk_fixup(gnutls_pk_algorithm_t algo, gnutls_direction_t direction, gnutls_pk_params_st * params) { int ret; if (direction == GNUTLS_IMPORT && algo == GNUTLS_PK_RSA) { /* do not trust the generated values. Some old private keys * generated by us have mess on the values. Those were very * old but it seemed some of the shipped example private * keys were as old. */ if (params->params_nr < RSA_PRIVATE_PARAMS - 3) return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); if (params->params[RSA_COEF] == NULL) { ret = _gnutls_mpi_init(¶ms->params[RSA_COEF]); if (ret < 0) return gnutls_assert_val(ret); } mpz_invert(TOMPZ(params->params[RSA_COEF]), TOMPZ(params->params[RSA_PRIME2]), TOMPZ(params->params[RSA_PRIME1])); /* calculate exp1 [6] and exp2 [7] */ zrelease_mpi_key(¶ms->params[RSA_E1]); zrelease_mpi_key(¶ms->params[RSA_E2]); ret = calc_rsa_exp(params); if (ret < 0) return gnutls_assert_val(ret); params->params_nr = RSA_PRIVATE_PARAMS; } return 0; }
static int wrap_nettle_mpi_mulm(bigint_t w, const bigint_t a, const bigint_t b, const bigint_t m) { mpz_mul(TOMPZ(w), TOMPZ(a), TOMPZ(b)); mpz_fdiv_r(TOMPZ(w), TOMPZ(w), TOMPZ(m)); return 0; }
static int wrap_nettle_mpi_init(bigint_t *w) { bigint_t r; r = gnutls_malloc(SIZEOF_MPZT); if (r == NULL) { gnutls_assert(); return GNUTLS_E_MEMORY_ERROR; } mpz_init(TOMPZ(r)); *w = r; return 0; }
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; }
static int _wrap_nettle_pk_verify (gnutls_pk_algorithm_t algo, const gnutls_datum_t * vdata, const gnutls_datum_t * signature, const gnutls_pk_params_st * pk_params) { int ret; unsigned int hash_len; bigint_t tmp[2] = { NULL, NULL }; switch (algo) { case GNUTLS_PK_EC: /* ECDSA */ { ecc_key pub; struct dsa_signature sig; int stat; int curve_id = pk_params->flags; if (is_supported_curve(curve_id) == 0) return gnutls_assert_val(GNUTLS_E_ECC_UNSUPPORTED_CURVE); ret = _gnutls_decode_ber_rs (signature, &tmp[0], &tmp[1]); if (ret < 0) { gnutls_assert (); goto cleanup; } _ecc_params_to_pubkey(pk_params, &pub); memcpy (&sig.r, tmp[0], sizeof (sig.r)); memcpy (&sig.s, tmp[1], sizeof (sig.s)); _gnutls_dsa_q_to_hash (algo, pk_params, &hash_len); if (hash_len > vdata->size) hash_len = vdata->size; ret = ecc_verify_hash(&sig, vdata->data, hash_len, &stat, &pub, curve_id); if (ret != 0 || stat != 1) { gnutls_assert(); ret = GNUTLS_E_PK_SIG_VERIFY_FAILED; } else ret = 0; _gnutls_mpi_release (&tmp[0]); _gnutls_mpi_release (&tmp[1]); _ecc_params_clear( &pub); break; } case GNUTLS_PK_DSA: { struct dsa_public_key pub; struct dsa_signature sig; ret = _gnutls_decode_ber_rs (signature, &tmp[0], &tmp[1]); if (ret < 0) { gnutls_assert (); goto cleanup; } memset(&pub, 0, sizeof(pub)); _dsa_params_to_pubkey (pk_params, &pub); memcpy (&sig.r, tmp[0], sizeof (sig.r)); memcpy (&sig.s, tmp[1], sizeof (sig.s)); _gnutls_dsa_q_to_hash (algo, pk_params, &hash_len); if (hash_len > vdata->size) hash_len = vdata->size; ret = _dsa_verify (&pub, hash_len, vdata->data, &sig); if (ret == 0) { gnutls_assert(); ret = GNUTLS_E_PK_SIG_VERIFY_FAILED; } else ret = 0; _gnutls_mpi_release (&tmp[0]); _gnutls_mpi_release (&tmp[1]); break; } case GNUTLS_PK_RSA: { struct rsa_public_key pub; _rsa_params_to_pubkey (pk_params, &pub); ret = _gnutls_mpi_scan_nz (&tmp[0], signature->data, signature->size); if (ret < 0) { gnutls_assert (); goto cleanup; } ret = rsa_pkcs1_verify (&pub, vdata->size, vdata->data, TOMPZ(tmp[0])); if (ret == 0) ret = gnutls_assert_val(GNUTLS_E_PK_SIG_VERIFY_FAILED); else ret = 0; _gnutls_mpi_release (&tmp[0]); break; } default: gnutls_assert (); ret = GNUTLS_E_INTERNAL_ERROR; goto cleanup; } cleanup: return ret; }
static int _wrap_nettle_pk_decrypt (gnutls_pk_algorithm_t algo, gnutls_datum_t * plaintext, const gnutls_datum_t * ciphertext, const gnutls_pk_params_st * pk_params) { int ret; plaintext->data = NULL; /* make a sexp from pkey */ switch (algo) { case GNUTLS_PK_RSA: { struct rsa_private_key priv; struct rsa_public_key pub; unsigned length; bigint_t c; _rsa_params_to_privkey (pk_params, &priv); _rsa_params_to_pubkey (pk_params, &pub); if (_gnutls_mpi_scan_nz (&c, ciphertext->data, ciphertext->size) != 0) { ret = gnutls_assert_val(GNUTLS_E_MPI_SCAN_FAILED); goto cleanup; } length = pub.size; plaintext->data = gnutls_malloc(length); if (plaintext->data == NULL) { ret = gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); goto cleanup; } ret = rsa_decrypt_tr(&pub, &priv, NULL, rnd_func, &length, plaintext->data, TOMPZ(c)); _gnutls_mpi_release (&c); plaintext->size = length; if (ret == 0) { ret = gnutls_assert_val(GNUTLS_E_DECRYPTION_FAILED); goto cleanup; } break; } default: gnutls_assert (); ret = GNUTLS_E_INTERNAL_ERROR; goto cleanup; } ret = 0; cleanup: if (ret < 0) gnutls_free(plaintext->data); return ret; }
static void wrap_nettle_mpi_release(bigint_t a) { mpz_clear(TOMPZ(a)); gnutls_free(a); }
/* in case of DSA puts into data, r,s */ static int _wrap_nettle_pk_sign (gnutls_pk_algorithm_t algo, gnutls_datum_t * signature, const gnutls_datum_t * vdata, const gnutls_pk_params_st * pk_params) { int ret; unsigned int hash; unsigned int hash_len; switch (algo) { case GNUTLS_PK_EC: /* we do ECDSA */ { ecc_key priv; struct dsa_signature sig; _ecc_params_to_privkey(pk_params, &priv); dsa_signature_init (&sig); hash = _gnutls_dsa_q_to_hash (algo, pk_params, &hash_len); if (hash_len > vdata->size) { gnutls_assert (); _gnutls_debug_log("Security level of algorithm requires hash %s(%d) or better\n", gnutls_mac_get_name(hash), hash_len); hash_len = vdata->size; } ret = ecc_sign_hash(vdata->data, hash_len, &sig, NULL, rnd_func, &priv); if (ret != 0) { gnutls_assert (); ret = GNUTLS_E_PK_SIGN_FAILED; goto ecdsa_fail; } ret = _gnutls_encode_ber_rs (signature, &sig.r, &sig.s); ecdsa_fail: dsa_signature_clear (&sig); _ecc_params_clear( &priv); if (ret < 0) { gnutls_assert (); goto cleanup; } break; } case GNUTLS_PK_DSA: { struct dsa_public_key pub; struct dsa_private_key priv; struct dsa_signature sig; memset(&priv, 0, sizeof(priv)); memset(&pub, 0, sizeof(pub)); _dsa_params_to_pubkey (pk_params, &pub); _dsa_params_to_privkey (pk_params, &priv); dsa_signature_init (&sig); hash = _gnutls_dsa_q_to_hash (algo, pk_params, &hash_len); if (hash_len > vdata->size) { gnutls_assert (); _gnutls_debug_log("Security level of algorithm requires hash %s(%d) or better\n", gnutls_mac_get_name(hash), hash_len); hash_len = vdata->size; } ret = _dsa_sign (&pub, &priv, NULL, rnd_func, hash_len, vdata->data, &sig); if (ret == 0) { gnutls_assert (); ret = GNUTLS_E_PK_SIGN_FAILED; goto dsa_fail; } ret = _gnutls_encode_ber_rs (signature, &sig.r, &sig.s); dsa_fail: dsa_signature_clear (&sig); if (ret < 0) { gnutls_assert (); goto cleanup; } break; } case GNUTLS_PK_RSA: { struct rsa_private_key priv; bigint_t hash, nc, ri; if (_gnutls_mpi_scan_nz (&hash, vdata->data, vdata->size) != 0) { gnutls_assert (); return GNUTLS_E_MPI_SCAN_FAILED; } memset(&priv, 0, sizeof(priv)); _rsa_params_to_privkey (pk_params, &priv); nc = rsa_blind (hash, pk_params->params[1] /*e */ , pk_params->params[0] /*m */ , &ri); _gnutls_mpi_release (&hash); if (nc == NULL) { gnutls_assert (); ret = GNUTLS_E_MEMORY_ERROR; goto rsa_fail; } rsa_compute_root (&priv, TOMPZ (nc), TOMPZ (nc)); rsa_unblind (nc, ri, pk_params->params[0] /*m */ ); ret = _gnutls_mpi_dprint (nc, signature); rsa_fail: _gnutls_mpi_release (&nc); _gnutls_mpi_release (&ri); if (ret < 0) { gnutls_assert (); goto cleanup; } break; } default: gnutls_assert (); ret = GNUTLS_E_INTERNAL_ERROR; goto cleanup; } ret = 0; cleanup: return ret; }
static int _wrap_nettle_pk_decrypt (gnutls_pk_algorithm_t algo, gnutls_datum_t * plaintext, const gnutls_datum_t * ciphertext, const gnutls_pk_params_st * pk_params) { int ret; /* make a sexp from pkey */ switch (algo) { case GNUTLS_PK_RSA: { struct rsa_private_key priv; bigint_t c, ri, nc; if (_gnutls_mpi_scan_nz (&c, ciphertext->data, ciphertext->size) != 0) { gnutls_assert (); return GNUTLS_E_MPI_SCAN_FAILED; } nc = rsa_blind (c, pk_params->params[1] /*e */ , pk_params->params[0] /*m */ , &ri); _gnutls_mpi_release (&c); if (nc == NULL) { gnutls_assert (); return GNUTLS_E_MEMORY_ERROR; } memset(&priv, 0, sizeof(priv)); _rsa_params_to_privkey (pk_params, &priv); rsa_compute_root (&priv, TOMPZ (nc), TOMPZ (nc)); rsa_unblind (nc, ri, pk_params->params[0] /*m */ ); ret = _gnutls_mpi_dprint_size (nc, plaintext, ciphertext->size); _gnutls_mpi_release (&nc); _gnutls_mpi_release (&ri); if (ret < 0) { gnutls_assert (); goto cleanup; } break; } default: gnutls_assert (); ret = GNUTLS_E_INTERNAL_ERROR; goto cleanup; } ret = 0; cleanup: return ret; }
static void wrap_nettle_mpi_clear(bigint_t a) { zeroize_key(TOMPZ(a)[0]._mp_d, TOMPZ(a)[0]._mp_alloc * sizeof(mp_limb_t)); }
static unsigned int wrap_nettle_mpi_get_nbits(bigint_t a) { return mpz_sizeinbase(TOMPZ(a), 2); }
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_mpi_set(bigint_t w, const bigint_t u) { mpz_set(TOMPZ(w), TOMPZ(u)); return 0; }
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; }
static int wrap_nettle_mpi_set_ui(bigint_t w, unsigned long u) { mpz_set_ui(TOMPZ(w), u); return 0; }