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; }
/* 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; }