summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimo Sorce <simo@redhat.com>2019-05-03 12:32:56 -0400
committerNikos Mavrogiannopoulos <nmav@redhat.com>2019-05-23 11:35:12 +0200
commit2555412f8982ec0a1bbbf6b3c10a0330fe848820 (patch)
treeb59ab064e03f347b168c2e5c1e374f68df51f048
parent431307e1b3da3c782961623c7b19cb7c7fbf84b8 (diff)
downloadgnutls-2555412f8982ec0a1bbbf6b3c10a0330fe848820.tar.gz
Add Full Public Key Check for DH
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>
-rw-r--r--lib/nettle/pk.c23
1 files changed, 20 insertions, 3 deletions
diff --git a/lib/nettle/pk.c b/lib/nettle/pk.c
index 9aa51660d8..1874bca54f 100644
--- a/lib/nettle/pk.c
+++ b/lib/nettle/pk.c
@@ -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)