diff --git a/lib/gnutls_global.c b/lib/gnutls_global.c index b9ca0cb..ac8a922 100644 --- a/lib/gnutls_global.c +++ b/lib/gnutls_global.c @@ -297,6 +297,7 @@ int gnutls_global_init(void) * res == not in fips140 mode */ if (res != 0) { + _gnutls_debug_log("FIPS140-2 mode: %d\n", res); _gnutls_priority_update_fips(); /* first round of self checks, these are done on the diff --git a/lib/libgnutls.map b/lib/libgnutls.map index 5de541d..cbd62d7 100644 --- a/lib/libgnutls.map +++ b/lib/libgnutls.map @@ -1043,6 +1043,10 @@ GNUTLS_FIPS140 { _gnutls_prf_raw; _gnutls_encode_ber_rs_raw; _rsa_generate_fips186_4_keypair; + _gnutls_dh_compute_key; + _gnutls_dh_generate_key; + _gnutls_ecdh_generate_key; + _gnutls_ecdh_compute_key; }; GNUTLS_PRIVATE { diff --git a/lib/nettle/pk.c b/lib/nettle/pk.c index fbc3da1..1b61051 100644 --- a/lib/nettle/pk.c +++ b/lib/nettle/pk.c @@ -844,7 +844,7 @@ wrap_nettle_pk_generate_params(gnutls_pk_algorithm_t algo, #endif params->params_nr = 0; - + ret = _gnutls_mpi_init_multi(¶ms->params[DSA_P], ¶ms->params[DSA_Q], ¶ms->params[DSA_G], NULL); if (ret < 0) { @@ -891,6 +891,249 @@ wrap_nettle_pk_generate_params(gnutls_pk_algorithm_t algo, return ret; } +#ifdef ENABLE_FIPS140 +int _gnutls_dh_generate_key(gnutls_dh_params_t dh_params, + gnutls_datum_t *priv_key, gnutls_datum_t *pub_key); + +int _gnutls_dh_compute_key(gnutls_dh_params_t dh_params, + const gnutls_datum_t *priv_key, const gnutls_datum_t *pub_key, + const gnutls_datum_t *peer_key, gnutls_datum_t *Z); + +int _gnutls_ecdh_compute_key(gnutls_ecc_curve_t curve, + const gnutls_datum_t *x, const gnutls_datum_t *y, + const gnutls_datum_t *k, + const gnutls_datum_t *peer_x, const gnutls_datum_t *peer_y, + gnutls_datum_t *Z); + +int _gnutls_ecdh_generate_key(gnutls_ecc_curve_t curve, + gnutls_datum_t *x, gnutls_datum_t *y, + gnutls_datum_t *k); + + +int _gnutls_dh_generate_key(gnutls_dh_params_t dh_params, + gnutls_datum_t *priv_key, gnutls_datum_t *pub_key) +{ + gnutls_pk_params_st params; + int ret; + + gnutls_pk_params_init(¶ms); + params.params[DH_P] = _gnutls_mpi_copy(dh_params->params[0]); + params.params[DH_G] = _gnutls_mpi_copy(dh_params->params[1]); + + params.params_nr = 3; /* include empty q */ + params.algo = GNUTLS_PK_DH; + + priv_key->data = NULL; + pub_key->data = NULL; + + ret = _gnutls_pk_generate_keys(GNUTLS_PK_DH, 0, ¶ms); + if (ret < 0) { + return gnutls_assert_val(ret); + } + + ret = + _gnutls_mpi_dprint_lz(params.params[DH_X], priv_key); + if (ret < 0) { + gnutls_assert(); + goto fail; + } + + ret = + _gnutls_mpi_dprint_lz(params.params[DH_Y], pub_key); + if (ret < 0) { + gnutls_assert(); + goto fail; + } + + ret = 0; + goto cleanup; + fail: + gnutls_free(pub_key->data); + gnutls_free(priv_key->data); + cleanup: + gnutls_pk_params_clear(¶ms); + return ret; +} + +int _gnutls_dh_compute_key(gnutls_dh_params_t dh_params, + const gnutls_datum_t *priv_key, const gnutls_datum_t *pub_key, + const gnutls_datum_t *peer_key, gnutls_datum_t *Z) +{ + gnutls_pk_params_st pub, priv; + int ret; + + gnutls_pk_params_init(&pub); + gnutls_pk_params_init(&priv); + pub.algo = GNUTLS_PK_DH; + + if (_gnutls_mpi_init_scan_nz + (&pub.params[DH_Y], peer_key->data, + peer_key->size) != 0) { + ret = + gnutls_assert_val(GNUTLS_E_MPI_SCAN_FAILED); + goto cleanup; + } + + priv.params[DH_P] = _gnutls_mpi_copy(dh_params->params[0]); + priv.params[DH_G] = _gnutls_mpi_copy(dh_params->params[1]); + + if (_gnutls_mpi_init_scan_nz + (&priv.params[DH_X], priv_key->data, + priv_key->size) != 0) { + ret = + gnutls_assert_val(GNUTLS_E_MPI_SCAN_FAILED); + goto cleanup; + } + + priv.params_nr = 3; /* include empty q */ + priv.algo = GNUTLS_PK_DH; + + Z->data = NULL; + + ret = _gnutls_pk_derive(GNUTLS_PK_DH, Z, &priv, &pub); + if (ret < 0) { + gnutls_assert(); + goto cleanup; + } + + ret = 0; + cleanup: + gnutls_pk_params_clear(&pub); + gnutls_pk_params_clear(&priv); + return ret; +} + +int _gnutls_ecdh_generate_key(gnutls_ecc_curve_t curve, + gnutls_datum_t *x, gnutls_datum_t *y, + gnutls_datum_t *k) +{ + gnutls_pk_params_st params; + int ret; + + gnutls_pk_params_init(¶ms); + params.flags = curve; + params.algo = GNUTLS_PK_EC; + + x->data = NULL; + y->data = NULL; + k->data = NULL; + + ret = _gnutls_pk_generate_keys(GNUTLS_PK_EC, curve, ¶ms); + if (ret < 0) { + return gnutls_assert_val(ret); + } + + ret = + _gnutls_mpi_dprint_lz(params.params[ECC_X], x); + if (ret < 0) { + gnutls_assert(); + goto fail; + } + + ret = + _gnutls_mpi_dprint_lz(params.params[ECC_Y], y); + if (ret < 0) { + gnutls_assert(); + goto fail; + } + + ret = + _gnutls_mpi_dprint_lz(params.params[ECC_K], k); + if (ret < 0) { + gnutls_assert(); + goto fail; + } + + ret = 0; + goto cleanup; + fail: + gnutls_free(y->data); + gnutls_free(x->data); + gnutls_free(k->data); + cleanup: + gnutls_pk_params_clear(¶ms); + return ret; +} + +int _gnutls_ecdh_compute_key(gnutls_ecc_curve_t curve, + const gnutls_datum_t *x, const gnutls_datum_t *y, + const gnutls_datum_t *k, + const gnutls_datum_t *peer_x, const gnutls_datum_t *peer_y, + gnutls_datum_t *Z) +{ + gnutls_pk_params_st pub, priv; + int ret; + + gnutls_pk_params_init(&pub); + gnutls_pk_params_init(&priv); + + pub.algo = GNUTLS_PK_EC; + pub.flags = curve; + + if (_gnutls_mpi_init_scan_nz + (&pub.params[ECC_Y], peer_y->data, + peer_y->size) != 0) { + ret = + gnutls_assert_val(GNUTLS_E_MPI_SCAN_FAILED); + goto cleanup; + } + + if (_gnutls_mpi_init_scan_nz + (&pub.params[ECC_X], peer_x->data, + peer_x->size) != 0) { + ret = + gnutls_assert_val(GNUTLS_E_MPI_SCAN_FAILED); + goto cleanup; + } + + priv.params_nr = 2; + + if (_gnutls_mpi_init_scan_nz + (&priv.params[ECC_Y], y->data, + y->size) != 0) { + ret = + gnutls_assert_val(GNUTLS_E_MPI_SCAN_FAILED); + goto cleanup; + } + + if (_gnutls_mpi_init_scan_nz + (&priv.params[ECC_X], x->data, + x->size) != 0) { + ret = + gnutls_assert_val(GNUTLS_E_MPI_SCAN_FAILED); + goto cleanup; + } + + if (_gnutls_mpi_init_scan_nz + (&priv.params[ECC_K], k->data, + k->size) != 0) { + ret = + gnutls_assert_val(GNUTLS_E_MPI_SCAN_FAILED); + goto cleanup; + } + + + priv.params_nr = 3; + priv.algo = GNUTLS_PK_EC; + priv.flags = curve; + + Z->data = NULL; + + ret = _gnutls_pk_derive(GNUTLS_PK_EC, Z, &priv, &pub); + if (ret < 0) { + gnutls_assert(); + goto cleanup; + } + + ret = 0; + cleanup: + gnutls_pk_params_clear(&pub); + gnutls_pk_params_clear(&priv); + return ret; +} +#endif + + /* To generate a DH key either q must be set in the params or * level should be set to the number of required bits. */ @@ -1398,12 +1641,12 @@ static int calc_rsa_exp(gnutls_pk_params_st * params) { bigint_t tmp; int ret; - + if (params->params_nr < RSA_PRIVATE_PARAMS - 2) { gnutls_assert(); return GNUTLS_E_INTERNAL_ERROR; } - + params->params[6] = params->params[7] = NULL; ret = _gnutls_mpi_init_multi(&tmp, ¶ms->params[6], ¶ms->params[7], NULL);