diff --git a/crypto/dh/dh_check.c b/crypto/dh/dh_check.c index 4ac169e..9cb4482 100644 --- a/crypto/dh/dh_check.c +++ b/crypto/dh/dh_check.c @@ -184,6 +184,20 @@ int DH_check_pub_key(const DH *dh, const BIGNUM *pub_key, int *ret) BN_CTX *ctx = NULL; *ret = 0; + + /* Don't do any checks at all with an excessively large modulus */ + if (BN_num_bits(dh->p) > OPENSSL_DH_CHECK_MAX_MODULUS_BITS) { + DHerr(DH_F_DH_CHECK_EX, DH_R_MODULUS_TOO_LARGE); + *ret = DH_MODULUS_TOO_LARGE | DH_CHECK_PUBKEY_INVALID; + return 0; + } + + if (dh->q != NULL && BN_ucmp(dh->p, dh->q) < 0) { + *ret |= DH_CHECK_INVALID_Q_VALUE | DH_CHECK_PUBKEY_INVALID; + return 1; + } + + ctx = BN_CTX_new(); if (ctx == NULL) goto err; diff --git a/crypto/dh/dh_err.c b/crypto/dh/dh_err.c index 7285587..85f1e51 100644 --- a/crypto/dh/dh_err.c +++ b/crypto/dh/dh_err.c @@ -81,6 +81,7 @@ static const ERR_STRING_DATA DH_str_reasons[] = { {ERR_PACK(ERR_LIB_DH, 0, DH_R_PARAMETER_ENCODING_ERROR), "parameter encoding error"}, {ERR_PACK(ERR_LIB_DH, 0, DH_R_PEER_KEY_ERROR), "peer key error"}, + {ERR_PACK(ERR_LIB_DH, 0, DH_R_Q_TOO_LARGE), "q too large"}, {ERR_PACK(ERR_LIB_DH, 0, DH_R_SHARED_INFO_ERROR), "shared info error"}, {ERR_PACK(ERR_LIB_DH, 0, DH_R_UNABLE_TO_CHECK_GENERATOR), "unable to check generator"}, diff --git a/crypto/dh/dh_key.c b/crypto/dh/dh_key.c index 117f2fa..b4c789d 100644 --- a/crypto/dh/dh_key.c +++ b/crypto/dh/dh_key.c @@ -109,6 +109,12 @@ static int generate_key(DH *dh) BN_MONT_CTX *mont = NULL; BIGNUM *pub_key = NULL, *priv_key = NULL; + if (dh->q != NULL + && BN_num_bits(dh->q) > OPENSSL_DH_MAX_MODULUS_BITS) { + DHerr(DH_F_GENERATE_KEY, DH_R_Q_TOO_LARGE); + return 0; + } + if (BN_num_bits(dh->p) > OPENSSL_DH_MAX_MODULUS_BITS) { DHerr(DH_F_GENERATE_KEY, DH_R_MODULUS_TOO_LARGE); return 0; @@ -202,6 +208,12 @@ static int compute_key(unsigned char *key, const BIGNUM *pub_key, DH *dh) int ret = -1; int check_result; + if (dh->q != NULL + && BN_num_bits(dh->q) > OPENSSL_DH_MAX_MODULUS_BITS) { + DHerr(DH_F_COMPUTE_KEY, DH_R_Q_TOO_LARGE); + goto err; + } + if (BN_num_bits(dh->p) > OPENSSL_DH_MAX_MODULUS_BITS) { DHerr(DH_F_COMPUTE_KEY, DH_R_MODULUS_TOO_LARGE); goto err; diff --git a/crypto/err/openssl.txt b/crypto/err/openssl.txt index 7e17763..405c116 100644 --- a/crypto/err/openssl.txt +++ b/crypto/err/openssl.txt @@ -2100,6 +2100,7 @@ DH_R_NO_PARAMETERS_SET:107:no parameters set DH_R_NO_PRIVATE_VALUE:100:no private value DH_R_PARAMETER_ENCODING_ERROR:105:parameter encoding error DH_R_PEER_KEY_ERROR:111:peer key error +DH_R_Q_TOO_LARGE:130:q too large DH_R_SHARED_INFO_ERROR:113:shared info error DH_R_UNABLE_TO_CHECK_GENERATOR:121:unable to check generator DSA_R_BAD_Q_VALUE:102:bad q value diff --git a/include/openssl/dh.h b/include/openssl/dh.h index 3527540..a50ad96 100644 --- a/include/openssl/dh.h +++ b/include/openssl/dh.h @@ -68,14 +68,15 @@ DECLARE_ASN1_ITEM(DHparams) /* #define DH_GENERATOR_3 3 */ # define DH_GENERATOR_5 5 -/* DH_check error codes */ +/* DH_check error codes, some of them shared with DH_check_pub_key */ # define DH_CHECK_P_NOT_PRIME 0x01 # define DH_CHECK_P_NOT_SAFE_PRIME 0x02 # define DH_UNABLE_TO_CHECK_GENERATOR 0x04 # define DH_NOT_SUITABLE_GENERATOR 0x08 # define DH_CHECK_Q_NOT_PRIME 0x10 -# define DH_CHECK_INVALID_Q_VALUE 0x20 +# define DH_CHECK_INVALID_Q_VALUE 0x20 /* +DH_check_pub_key */ # define DH_CHECK_INVALID_J_VALUE 0x40 +# define DH_MODULUS_TOO_LARGE 0x100 /* DH_check_pub_key error codes */ # define DH_CHECK_PUBKEY_TOO_SMALL 0x01 diff --git a/include/openssl/dherr.h b/include/openssl/dherr.h index 916b3be..88c3a6c 100644 --- a/include/openssl/dherr.h +++ b/include/openssl/dherr.h @@ -81,6 +81,7 @@ int ERR_load_DH_strings(void); # define DH_R_NO_PRIVATE_VALUE 100 # define DH_R_PARAMETER_ENCODING_ERROR 105 # define DH_R_PEER_KEY_ERROR 111 +# define DH_R_Q_TOO_LARGE 130 # define DH_R_SHARED_INFO_ERROR 113 # define DH_R_UNABLE_TO_CHECK_GENERATOR 121