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);