[openssl-users] RFC 7919 DH parameters and OpenSSL DH_check()

Viktor Dukhovni openssl-users at dukhovni.org
Thu Jan 3 21:54:19 UTC 2019


On Jan 3, 2019, at 3:18 PM, Andy Schmidt <andrewrobertschmidt at gmail.com> wrote:

> I am adding the RFC 7919 Diffie-Hellman parameters to our TLS
> servers, and I've found that these parameters won't pass OpenSSL's
> Diffie Hellman parameter check function DH_check(). The return code
> is DH_NOT_SUITABLE_GENERATOR. Looking at the source code, it appears
> to fail because the remainder of the prime divided by 24 is not 11.
> That its, p mod 24 != 11. I have a couple of questions:
>
> What relationship between the prime p and the generator g is this checking
> for? I thought that since p was a safe prime, as long as the generator g
> wasn't 1 the only choice is between the full group and the subgroup of the
> squares?

For a safe prime $p = 2q + 1$ with $q$ also prime, the order of $2$ is $q$
provided $2$ is quadratic residue mod $p$, which, by quadratic reciprocity,
considering that $q$ is odd and not a multiple of 3 for any primes of interest,
gives $p \cong 23 mod 24$, which then gives $q \cong 11 mod 12$.

The order of $2$ is $2q$ when $2$ is not a quadratic residue mod $p$, which
then gives $p \cong 3 mod 8$ and so taking mod 3 into account
$p \cong 11 mod 24$.

So it seems that the check in question wants $2$ to generates the
full multiplicative group of order $2q$, rather than the prime-order
subgroup of quadratic residues of order $q$.

> I would like to use DH_check() to attempt to ensure that Diffie Hellman
> parameters haven't been tampered on operating systems that don't have
> digital signatures for executable binaries.
> 
> The OpenSSL version in use is 1.0.2q.

The primes in RFC7919 are all 23 mod 24, which has $o(2) = q$ rather
than $o(2) = 2q$.  This is actually fine, perhaps even better, and
the code in DH_check() is too strict in wanting the generator to
generate the full multiplicative group mod $p$, rather than just
the subgroup of of quadratic residues of order $q$.

So a pull request for OpenSSL would be welcome.  Given that we
should not care whether the order of $g$ is $q$ or $2q$, it suffices
to just check that $p$ is plausibly prime and $q = (p-1)/2 == (p
>> 1)$ is plausibly prime.  The special checks for $g == 2, 3 and
5$ should be removed.  For 1.1.1 the patch would be something like:

--- a/crypto/dh/dh_check.c
+++ b/crypto/dh/dh_check.c
@@ -88,8 +88,6 @@ int DH_check_ex(const DH *dh)
         DHerr(DH_F_DH_CHECK_EX, DH_R_CHECK_INVALID_Q_VALUE);
     if ((errflags & DH_CHECK_INVALID_J_VALUE) != 0)
         DHerr(DH_F_DH_CHECK_EX, DH_R_CHECK_INVALID_J_VALUE);
-    if ((errflags & DH_UNABLE_TO_CHECK_GENERATOR) != 0)
-        DHerr(DH_F_DH_CHECK_EX, DH_R_UNABLE_TO_CHECK_GENERATOR);
     if ((errflags & DH_CHECK_P_NOT_PRIME) != 0)
         DHerr(DH_F_DH_CHECK_EX, DH_R_CHECK_P_NOT_PRIME);
     if ((errflags & DH_CHECK_P_NOT_SAFE_PRIME) != 0)
@@ -140,20 +138,7 @@ int DH_check(const DH *dh, int *ret)
         if (dh->j && BN_cmp(dh->j, t1))
             *ret |= DH_CHECK_INVALID_J_VALUE;
 
-    } else if (BN_is_word(dh->g, DH_GENERATOR_2)) {
-        l = BN_mod_word(dh->p, 24);
-        if (l == (BN_ULONG)-1)
-            goto err;
-        if (l != 11)
-            *ret |= DH_NOT_SUITABLE_GENERATOR;
-    } else if (BN_is_word(dh->g, DH_GENERATOR_5)) {
-        l = BN_mod_word(dh->p, 10);
-        if (l == (BN_ULONG)-1)
-            goto err;
-        if ((l != 3) && (l != 7))
-            *ret |= DH_NOT_SUITABLE_GENERATOR;
-    } else
-        *ret |= DH_UNABLE_TO_CHECK_GENERATOR;
+    }
 
     r = BN_is_prime_ex(dh->p, BN_prime_checks, ctx, NULL);
     if (r < 0)

-- 
	Viktor.



More information about the openssl-users mailing list