Skip to content

Commit

Permalink
Backport DH_check from OpenSSL 1.1.0.
Browse files Browse the repository at this point in the history
OpenSSL 1.0.2's DH_check considers the q parameter, allowing it
validate more generators and primes; however, OpenSSL 1.1.0's DH_check
includes code to handle errors in BN functions, so it's preferred.
  • Loading branch information
markrwilliams committed Jan 31, 2017
1 parent c7a2e72 commit 5252a88
Show file tree
Hide file tree
Showing 2 changed files with 101 additions and 3 deletions.
100 changes: 99 additions & 1 deletion src/_cffi_src/openssl/dh.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
DH *DH_new(void);
void DH_free(DH *);
int DH_size(const DH *);
int DH_check(const DH *, int *);
int DH_check_pub_key(const DH *, const BIGNUM *, int *);
int DH_generate_key(DH *);
int DH_compute_key(unsigned char *, const BIGNUM *, DH *);
Expand All @@ -28,6 +27,9 @@
int DHparams_print(BIO *, const DH *);
DH *DHparams_dup(DH *);
int Cryptography_DH_check(const DH *, int *);
/* added in 1.1.0 when the DH struct was opaqued */
void DH_get0_pqg(const DH *, const BIGNUM **, const BIGNUM **,
const BIGNUM **);
Expand Down Expand Up @@ -114,4 +116,100 @@
return 1;
}
#endif
#ifdef CRYPTOGRAPHY_OPENSSL_LESS_THAN_110 || defined(LIBRESSL_VERSION_NUMBER)
/*-
* Check that p is a safe prime and
* if g is 2, 3 or 5, check that it is a suitable generator
* where
* for 2, p mod 24 == 11
* for 3, p mod 12 == 5
* for 5, p mod 10 == 3 or 7
* should hold.
*/
int Cryptography_DH_check(const DH *dh, int *ret)
{
int ok = 0, r;
BN_CTX *ctx = NULL;
BN_ULONG l;
BIGNUM *t1 = NULL, *t2 = NULL;
*ret = 0;
ctx = BN_CTX_new();
if (ctx == NULL)
goto err;
BN_CTX_start(ctx);
t1 = BN_CTX_get(ctx);
if (t1 == NULL)
goto err;
t2 = BN_CTX_get(ctx);
if (t2 == NULL)
goto err;
if (dh->q) {
if (BN_cmp(dh->g, BN_value_one()) <= 0)
*ret |= DH_NOT_SUITABLE_GENERATOR;
else if (BN_cmp(dh->g, dh->p) >= 0)
*ret |= DH_NOT_SUITABLE_GENERATOR;
else {
/* Check g^q == 1 mod p */
if (!BN_mod_exp(t1, dh->g, dh->q, dh->p, ctx))
goto err;
if (!BN_is_one(t1))
*ret |= DH_NOT_SUITABLE_GENERATOR;
}
r = BN_is_prime_ex(dh->q, BN_prime_checks, ctx, NULL);
if (r < 0)
goto err;
if (!r)
*ret |= DH_CHECK_Q_NOT_PRIME;
/* Check p == 1 mod q i.e. q divides p - 1 */
if (!BN_div(t1, t2, dh->p, dh->q, ctx))
goto err;
if (!BN_is_one(t2))
*ret |= DH_CHECK_INVALID_Q_VALUE;
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)
goto err;
if (!r)
*ret |= DH_CHECK_P_NOT_PRIME;
else if (!dh->q) {
if (!BN_rshift1(t1, dh->p))
goto err;
r = BN_is_prime_ex(t1, BN_prime_checks, ctx, NULL);
if (r < 0)
goto err;
if (!r)
*ret |= DH_CHECK_P_NOT_SAFE_PRIME;
}
ok = 1;
err:
if (ctx != NULL) {
BN_CTX_end(ctx);
BN_CTX_free(ctx);
}
return (ok);
}
#else
int (*Cryptography_DH_check)(const DH *dh, int *ret) = DH_check;
#endif
"""
4 changes: 2 additions & 2 deletions src/cryptography/hazmat/backends/openssl/backend.py
Original file line number Diff line number Diff line change
Expand Up @@ -1763,7 +1763,7 @@ def load_dh_private_numbers(self, numbers):
self.openssl_assert(res == 1)

codes = self._ffi.new("int[]", 1)
res = self._lib.DH_check(dh_cdata, codes)
res = self._lib.Cryptography_DH_check(dh_cdata, codes)
self.openssl_assert(res == 1)

if codes[0] != 0:
Expand Down Expand Up @@ -1815,7 +1815,7 @@ def dh_parameters_supported(self, p, g):
self.openssl_assert(res == 1)

codes = self._ffi.new("int[]", 1)
res = self._lib.DH_check(dh_cdata, codes)
res = self._lib.Cryptography_DH_check(dh_cdata, codes)
self.openssl_assert(res == 1)

return codes[0] == 0
Expand Down

0 comments on commit 5252a88

Please sign in to comment.