Add Full Public Key Check for DH
authorSimo Sorce <simo@redhat.com>
Fri, 3 May 2019 16:32:56 +0000 (12:32 -0400)
committerNikos Mavrogiannopoulos <nmav@redhat.com>
Thu, 23 May 2019 09:35:12 +0000 (11:35 +0200)
This is for NIST SP800-56A requirements and FIPS CAVS testing.
GnuTLS never passes in a non-empty Q for normal operations, but tests will
and if Q is passed in it needs to be checked.

Signed-off-by: Simo Sorce <simo@redhat.com>
lib/nettle/pk.c

index 9aa51660d8f6c7dfd622813f5b9fb40047d58fc9..1874bca54f5dce8b71903b6d177766e71a6f32e5 100644 (file)
@@ -240,15 +240,16 @@ static int _wrap_nettle_pk_derive(gnutls_pk_algorithm_t algo,
 
        switch (algo) {
        case GNUTLS_PK_DH: {
-               bigint_t f, x, prime;
-               bigint_t k = NULL, ff = NULL;
+               bigint_t f, x, q, prime;
+               bigint_t k = NULL, ff = NULL, r = NULL;
                unsigned int bits;
 
                f = pub->params[DH_Y];
                x = priv->params[DH_X];
+               q = priv->params[DH_Q];
                prime = priv->params[DH_P];
 
-               ret = _gnutls_mpi_init_multi(&k, &ff, NULL);
+               ret = _gnutls_mpi_init_multi(&k, &ff, &r, NULL);
                if (ret < 0)
                        return gnutls_assert_val(ret);
 
@@ -268,6 +269,21 @@ static int _wrap_nettle_pk_derive(gnutls_pk_algorithm_t algo,
                        goto dh_cleanup;
                }
 
+               /* if we have Q check that y ^ q mod p == 1 */
+               if (q != NULL) {
+                       ret = _gnutls_mpi_powm(r, f, q, prime);
+                       if (ret < 0) {
+                               gnutls_assert();
+                               goto dh_cleanup;
+                       }
+                       ret = _gnutls_mpi_cmp_ui(r, 1);
+                       if (ret != 0) {
+                               gnutls_assert();
+                               ret = GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
+                               goto dh_cleanup;
+                       }
+               }
+
                /* prevent denial of service */
                bits = _gnutls_mpi_get_nbits(prime);
                if (bits == 0 || bits > MAX_DH_BITS) {
@@ -298,6 +314,7 @@ static int _wrap_nettle_pk_derive(gnutls_pk_algorithm_t algo,
 
                ret = 0;
 dh_cleanup:
+               _gnutls_mpi_release(&r);
                _gnutls_mpi_release(&ff);
                zrelease_temp_mpi_key(&k);
                if (ret < 0)