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