6dc7017
Dr S N Henson of the OpenSSL core team and Open Network Security
6dc7017
recently developed an ASN1 test suite for NISCC (www.niscc.gov.uk). When
6dc7017
the test suite was run against OpenSSL two denial of service
6dc7017
vulnerabilities were discovered.
6dc7017
6dc7017
Certain types of public key can take disproportionate amounts of time
6dc7017
to process. This could be used by an attacker in a denial of service attack.
6dc7017
CVE-2006-2940
6dc7017
6dc7017
Any code which uses OpenSSL to parse ASN1 data from untrusted sources is
6dc7017
affected. This includes SSL servers which enable client authentication,
6dc7017
and S/MIME applications.
6dc7017
6dc7017
6dc7017
diff -u -r1.37.2.2 dh.h
6dc7017
--- crypto/dh/dh.h	9 Jan 2006 16:05:22 -0000	1.37.2.2
6dc7017
+++ crypto/dh/dh.h	15 Sep 2006 13:59:47 -0000
6dc7017
@@ -73,6 +73,8 @@
6dc7017
 #include <openssl/bn.h>
6dc7017
 #endif
6dc7017
 	
6dc7017
+#define OPENSSL_DH_MAX_MODULUS_BITS	10000
6dc7017
+
6dc7017
 #define DH_FLAG_CACHE_MONT_P     0x01
6dc7017
 #define DH_FLAG_NO_EXP_CONSTTIME 0x02 /* new with 0.9.7h; the built-in DH
6dc7017
                                        * implementation now uses constant time
6dc7017
@@ -221,6 +223,7 @@
6dc7017
 /* Reason codes. */
6dc7017
 #define DH_R_BAD_GENERATOR				 101
6dc7017
 #define DH_R_INVALID_PUBKEY				 102
6dc7017
+#define DH_R_MODULUS_TOO_LARGE				 103
6dc7017
 #define DH_R_NO_PRIVATE_VALUE				 100
6dc7017
 
6dc7017
 #ifdef  __cplusplus
6dc7017
diff -u -r1.11.2.2 dh_err.c
6dc7017
--- crypto/dh/dh_err.c	9 Jan 2006 16:05:22 -0000	1.11.2.2
6dc7017
+++ crypto/dh/dh_err.c	15 Sep 2006 13:59:47 -0000
6dc7017
@@ -84,6 +84,7 @@
6dc7017
 	{
6dc7017
 {ERR_REASON(DH_R_BAD_GENERATOR)          ,"bad generator"},
6dc7017
 {ERR_REASON(DH_R_INVALID_PUBKEY)         ,"invalid public key"},
6dc7017
+{ERR_REASON(DH_R_MODULUS_TOO_LARGE)      ,"modulus too large"},
6dc7017
 {ERR_REASON(DH_R_NO_PRIVATE_VALUE)       ,"no private value"},
6dc7017
 {0,NULL}
6dc7017
 	};
6dc7017
diff -u -r1.24.2.3 dh_key.c
6dc7017
--- crypto/dh/dh_key.c	13 Mar 2006 23:12:06 -0000	1.24.2.3
6dc7017
+++ crypto/dh/dh_key.c	15 Sep 2006 13:59:47 -0000
6dc7017
@@ -179,6 +179,12 @@
6dc7017
 	int ret= -1;
6dc7017
         int check_result;
6dc7017
 
6dc7017
+	if (BN_num_bits(dh->p) > OPENSSL_DH_MAX_MODULUS_BITS)
6dc7017
+		{
6dc7017
+		DHerr(DH_F_COMPUTE_KEY,DH_R_MODULUS_TOO_LARGE);
98d8457
+		return -1;
6dc7017
+		}
6dc7017
+
6dc7017
 	ctx = BN_CTX_new();
6dc7017
 	if (ctx == NULL) goto err;
6dc7017
 	BN_CTX_start(ctx);
6dc7017
diff -u -r1.39 dsa.h
6dc7017
--- crypto/dsa/dsa.h	16 May 2005 01:43:30 -0000	1.39
6dc7017
+++ crypto/dsa/dsa.h	15 Sep 2006 13:59:47 -0000
6dc7017
@@ -84,6 +84,8 @@
6dc7017
 #endif
6dc7017
 #endif
6dc7017
 
6dc7017
+#define OPENSSL_DSA_MAX_MODULUS_BITS	10000
6dc7017
+
6dc7017
 #define DSA_FLAG_CACHE_MONT_P	0x01
6dc7017
 #define DSA_FLAG_NO_EXP_CONSTTIME       0x02 /* new with 0.9.7h; the built-in DSA
6dc7017
                                               * implementation now uses constant time
6dc7017
@@ -270,8 +272,10 @@
6dc7017
 #define DSA_F_SIG_CB					 114
6dc7017
 
6dc7017
 /* Reason codes. */
6dc7017
+#define DSA_R_BAD_Q_VALUE				 102
6dc7017
 #define DSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE		 100
6dc7017
 #define DSA_R_MISSING_PARAMETERS			 101
6dc7017
+#define DSA_R_MODULUS_TOO_LARGE				 103
6dc7017
 
6dc7017
 #ifdef  __cplusplus
6dc7017
 }
6dc7017
diff -u -r1.13 dsa_err.c
6dc7017
--- crypto/dsa/dsa_err.c	12 Apr 2005 16:15:12 -0000	1.13
6dc7017
+++ crypto/dsa/dsa_err.c	15 Sep 2006 13:59:47 -0000
6dc7017
@@ -89,8 +89,10 @@
6dc7017
 
6dc7017
 static ERR_STRING_DATA DSA_str_reasons[]=
6dc7017
 	{
6dc7017
+{ERR_REASON(DSA_R_BAD_Q_VALUE)           ,"bad q value"},
6dc7017
 {ERR_REASON(DSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE),"data too large for key size"},
6dc7017
 {ERR_REASON(DSA_R_MISSING_PARAMETERS)    ,"missing parameters"},
6dc7017
+{ERR_REASON(DSA_R_MODULUS_TOO_LARGE)     ,"modulus too large"},
6dc7017
 {0,NULL}
6dc7017
 	};
6dc7017
 
6dc7017
diff -u -r1.24.2.1 dsa_ossl.c
6dc7017
--- crypto/dsa/dsa_ossl.c	26 May 2005 04:40:57 -0000	1.24.2.1
6dc7017
+++ crypto/dsa/dsa_ossl.c	15 Sep 2006 13:59:47 -0000
6dc7017
@@ -304,6 +304,18 @@
6dc7017
 		return -1;
6dc7017
 		}
6dc7017
 
6dc7017
+	if (BN_num_bits(dsa->q) != 160)
6dc7017
+		{
6dc7017
+		DSAerr(DSA_F_DSA_DO_VERIFY,DSA_R_BAD_Q_VALUE);
6dc7017
+		return -1;
6dc7017
+		}
6dc7017
+
6dc7017
+	if (BN_num_bits(dsa->p) > OPENSSL_DSA_MAX_MODULUS_BITS)
6dc7017
+		{
6dc7017
+		DSAerr(DSA_F_DSA_DO_VERIFY,DSA_R_MODULUS_TOO_LARGE);
6dc7017
+		return -1;
6dc7017
+		}
6dc7017
+
6dc7017
 	BN_init(&u1;;
6dc7017
 	BN_init(&u2;;
6dc7017
 	BN_init(&t1;;
6dc7017
diff -u -r1.55.2.6 rsa.h
6dc7017
--- crypto/rsa/rsa.h	6 Sep 2006 06:43:25 -0000	1.55.2.6
6dc7017
+++ crypto/rsa/rsa.h	15 Sep 2006 13:59:48 -0000
6dc7017
@@ -159,6 +159,11 @@
6dc7017
 	BN_BLINDING *mt_blinding;
6dc7017
 	};
6dc7017
 
6dc7017
+#define OPENSSL_RSA_MAX_MODULUS_BITS	16384
6dc7017
+
6dc7017
+#define OPENSSL_RSA_SMALL_MODULUS_BITS	3072
6dc7017
+#define OPENSSL_RSA_MAX_PUBEXP_BITS	64 /* exponent limit enforced for "small" modulus only */
6dc7017
+
6dc7017
 #define RSA_3	0x3L
6dc7017
 #define RSA_F4	0x10001L
6dc7017
 
6dc7017
@@ -407,6 +412,7 @@
6dc7017
 #define RSA_R_IQMP_NOT_INVERSE_OF_Q			 126
6dc7017
 #define RSA_R_KEY_SIZE_TOO_SMALL			 120
6dc7017
 #define RSA_R_LAST_OCTET_INVALID			 134
6dc7017
+#define RSA_R_MODULUS_TOO_LARGE				 105
6dc7017
 #define RSA_R_NO_PUBLIC_EXPONENT			 140
6dc7017
 #define RSA_R_NULL_BEFORE_BLOCK_MISSING			 113
6dc7017
 #define RSA_R_N_DOES_NOT_EQUAL_P_Q			 127
6dc7017
diff -u -r1.46.2.6 rsa_eay.c
6dc7017
--- crypto/rsa/rsa_eay.c	6 Sep 2006 06:43:25 -0000	1.46.2.6
6dc7017
+++ crypto/rsa/rsa_eay.c	15 Sep 2006 13:59:48 -0000
6dc7017
@@ -168,6 +168,28 @@
6dc7017
 	unsigned char *buf=NULL;
6dc7017
 	BN_CTX *ctx=NULL;
6dc7017
 
6dc7017
+	if (BN_num_bits(rsa->n) > OPENSSL_RSA_MAX_MODULUS_BITS)
6dc7017
+		{
6dc7017
+		RSAerr(RSA_F_RSA_EAY_PUBLIC_ENCRYPT, RSA_R_MODULUS_TOO_LARGE);
6dc7017
+		return -1;
6dc7017
+		}
6dc7017
+
6dc7017
+	if (BN_ucmp(rsa->n, rsa->e) <= 0)
6dc7017
+		{
6dc7017
+		RSAerr(RSA_F_RSA_EAY_PUBLIC_ENCRYPT, RSA_R_BAD_E_VALUE);
6dc7017
+		return -1;
6dc7017
+		}
6dc7017
+
6dc7017
+	/* for large moduli, enforce exponent limit */
6dc7017
+	if (BN_num_bits(rsa->n) > OPENSSL_RSA_SMALL_MODULUS_BITS)
6dc7017
+		{
6dc7017
+		if (BN_num_bits(rsa->e) > OPENSSL_RSA_MAX_PUBEXP_BITS)
6dc7017
+			{
6dc7017
+			RSAerr(RSA_F_RSA_EAY_PUBLIC_ENCRYPT, RSA_R_BAD_E_VALUE);
6dc7017
+			return -1;
6dc7017
+			}
6dc7017
+		}
6dc7017
+	
6dc7017
 	if ((ctx=BN_CTX_new()) == NULL) goto err;
6dc7017
 	BN_CTX_start(ctx);
6dc7017
 	f = BN_CTX_get(ctx);
6dc7017
@@ -597,6 +619,28 @@
6dc7017
 	unsigned char *buf=NULL;
6dc7017
 	BN_CTX *ctx=NULL;
6dc7017
 
6dc7017
+	if (BN_num_bits(rsa->n) > OPENSSL_RSA_MAX_MODULUS_BITS)
6dc7017
+		{
6dc7017
+		RSAerr(RSA_F_RSA_EAY_PUBLIC_DECRYPT, RSA_R_MODULUS_TOO_LARGE);
6dc7017
+		return -1;
6dc7017
+		}
6dc7017
+
6dc7017
+	if (BN_ucmp(rsa->n, rsa->e) <= 0)
6dc7017
+		{
6dc7017
+		RSAerr(RSA_F_RSA_EAY_PUBLIC_DECRYPT, RSA_R_BAD_E_VALUE);
6dc7017
+		return -1;
6dc7017
+		}
6dc7017
+
6dc7017
+	/* for large moduli, enforce exponent limit */
6dc7017
+	if (BN_num_bits(rsa->n) > OPENSSL_RSA_SMALL_MODULUS_BITS)
6dc7017
+		{
6dc7017
+		if (BN_num_bits(rsa->e) > OPENSSL_RSA_MAX_PUBEXP_BITS)
6dc7017
+			{
6dc7017
+			RSAerr(RSA_F_RSA_EAY_PUBLIC_DECRYPT, RSA_R_BAD_E_VALUE);
6dc7017
+			return -1;
6dc7017
+			}
6dc7017
+		}
6dc7017
+	
6dc7017
 	if((ctx = BN_CTX_new()) == NULL) goto err;
6dc7017
 	BN_CTX_start(ctx);
6dc7017
 	f = BN_CTX_get(ctx);
6dc7017
diff -u -r1.17.2.5 rsa_err.c
6dc7017
--- crypto/rsa/rsa_err.c	6 Sep 2006 06:43:26 -0000	1.17.2.5
6dc7017
+++ crypto/rsa/rsa_err.c	15 Sep 2006 13:59:48 -0000
6dc7017
@@ -137,6 +137,7 @@
6dc7017
 {ERR_REASON(RSA_R_IQMP_NOT_INVERSE_OF_Q) ,"iqmp not inverse of q"},
6dc7017
 {ERR_REASON(RSA_R_KEY_SIZE_TOO_SMALL)    ,"key size too small"},
6dc7017
 {ERR_REASON(RSA_R_LAST_OCTET_INVALID)    ,"last octet invalid"},
6dc7017
+{ERR_REASON(RSA_R_MODULUS_TOO_LARGE)     ,"modulus too large"},
6dc7017
 {ERR_REASON(RSA_R_NO_PUBLIC_EXPONENT)    ,"no public exponent"},
6dc7017
 {ERR_REASON(RSA_R_NULL_BEFORE_BLOCK_MISSING),"null before block missing"},
6dc7017
 {ERR_REASON(RSA_R_N_DOES_NOT_EQUAL_P_Q)  ,"n does not equal p q"},