aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorColin Percival <cperciva@FreeBSD.org>2006-09-28 13:06:23 +0000
committerColin Percival <cperciva@FreeBSD.org>2006-09-28 13:06:23 +0000
commit30a6ffb3330a4ce39d12906a7dda5c4d9ed91dc3 (patch)
treedd781c2038cbc6db2809f44aae4144784fa53814
parentb55396780782c474e291f8557a14c033f4c6941d (diff)
downloadsrc-30a6ffb3330a4ce39d12906a7dda5c4d9ed91dc3.tar.gz
src-30a6ffb3330a4ce39d12906a7dda5c4d9ed91dc3.zip
Correct multiple vulnerabilities in crypto(3).
Limit the size of public keys used in order to protect applications from a denial of service via insane key sizes. Security: FreeBSD-SA-06:23.openssl Approved by: so (cperciva)
Notes
Notes: svn path=/releng/4.11/; revision=162724
-rw-r--r--UPDATING5
-rw-r--r--crypto/openssl/crypto/asn1/tasn_dec.c3
-rw-r--r--crypto/openssl/crypto/dh/dh.h5
-rw-r--r--crypto/openssl/crypto/dh/dh_err.c1
-rw-r--r--crypto/openssl/crypto/dh/dh_key.c6
-rw-r--r--crypto/openssl/crypto/dsa/dsa.h6
-rw-r--r--crypto/openssl/crypto/dsa/dsa_err.c2
-rw-r--r--crypto/openssl/crypto/dsa/dsa_ossl.c12
-rw-r--r--crypto/openssl/crypto/rsa/rsa.h12
-rw-r--r--crypto/openssl/crypto/rsa/rsa_eay.c44
-rw-r--r--crypto/openssl/crypto/rsa/rsa_err.c1
-rw-r--r--crypto/openssl/ssl/s2_clnt.c3
-rw-r--r--crypto/openssl/ssl/s3_srvr.c2
-rw-r--r--crypto/openssl/ssl/ssl_lib.c2
-rw-r--r--sys/conf/newvers.sh2
15 files changed, 102 insertions, 4 deletions
diff --git a/UPDATING b/UPDATING
index 4baf87e92235..298f43522cc3 100644
--- a/UPDATING
+++ b/UPDATING
@@ -17,6 +17,11 @@ minimal number of processes, if possible, for that patch. For those
updates that don't have an advisory, or to be safe, you can do a full
build and install as described in the COMMON ITEMS section.
+20060928: p23 FreeBSD-SA-06:23.openssl
+ Correct multiple vulnerabilities in crypto(3).
+ Limit the size of public keys used in order to protect applications
+ from a denial of service via insane key sizes.
+
20060919: p22 FreeBSD-SA-06:21.gzip
Correct multiple vulnerabilities in gzip(1).
diff --git a/crypto/openssl/crypto/asn1/tasn_dec.c b/crypto/openssl/crypto/asn1/tasn_dec.c
index 2426cb6253a3..db6417a333ec 100644
--- a/crypto/openssl/crypto/asn1/tasn_dec.c
+++ b/crypto/openssl/crypto/asn1/tasn_dec.c
@@ -628,6 +628,9 @@ static int asn1_d2i_ex_primitive(ASN1_VALUE **pval, unsigned char **in, long inl
ASN1err(ASN1_F_ASN1_D2I_EX_PRIMITIVE, ERR_R_NESTED_ASN1_ERROR);
return 0;
} else if(ret == -1) return -1;
+
+ ret = 0;
+
/* SEQUENCE, SET and "OTHER" are left in encoded form */
if((utype == V_ASN1_SEQUENCE) || (utype == V_ASN1_SET) || (utype == V_ASN1_OTHER)) {
/* Clear context cache for type OTHER because the auto clear when
diff --git a/crypto/openssl/crypto/dh/dh.h b/crypto/openssl/crypto/dh/dh.h
index 05851f84294c..31453e9b2103 100644
--- a/crypto/openssl/crypto/dh/dh.h
+++ b/crypto/openssl/crypto/dh/dh.h
@@ -70,6 +70,10 @@
#include <openssl/crypto.h>
#include <openssl/ossl_typ.h>
+#ifndef OPENSSL_DH_MAX_MODULUS_BITS
+# define OPENSSL_DH_MAX_MODULUS_BITS 10000
+#endif
+
#define DH_FLAG_CACHE_MONT_P 0x01
#ifdef __cplusplus
@@ -200,6 +204,7 @@ void ERR_load_DH_strings(void);
/* Reason codes. */
#define DH_R_BAD_GENERATOR 101
#define DH_R_NO_PRIVATE_VALUE 100
+#define DH_R_MODULUS_TOO_LARGE 103
#ifdef __cplusplus
}
diff --git a/crypto/openssl/crypto/dh/dh_err.c b/crypto/openssl/crypto/dh/dh_err.c
index d837950aecb3..4e029603c802 100644
--- a/crypto/openssl/crypto/dh/dh_err.c
+++ b/crypto/openssl/crypto/dh/dh_err.c
@@ -78,6 +78,7 @@ static ERR_STRING_DATA DH_str_functs[]=
static ERR_STRING_DATA DH_str_reasons[]=
{
{DH_R_BAD_GENERATOR ,"bad generator"},
+{DH_R_MODULUS_TOO_LARGE ,"modulus too large"},
{DH_R_NO_PRIVATE_VALUE ,"no private value"},
{0,NULL}
};
diff --git a/crypto/openssl/crypto/dh/dh_key.c b/crypto/openssl/crypto/dh/dh_key.c
index 77f2f50b5166..649aa5cffde4 100644
--- a/crypto/openssl/crypto/dh/dh_key.c
+++ b/crypto/openssl/crypto/dh/dh_key.c
@@ -162,6 +162,12 @@ static int compute_key(unsigned char *key, const BIGNUM *pub_key, DH *dh)
BIGNUM *tmp;
int ret= -1;
+ if (BN_num_bits(dh->p) > OPENSSL_DH_MAX_MODULUS_BITS)
+ {
+ DHerr(DH_F_DH_COMPUTE_KEY,DH_R_MODULUS_TOO_LARGE);
+ goto err;
+ }
+
ctx = BN_CTX_new();
if (ctx == NULL) goto err;
BN_CTX_start(ctx);
diff --git a/crypto/openssl/crypto/dsa/dsa.h b/crypto/openssl/crypto/dsa/dsa.h
index 9b3baadf2c49..d85258b87831 100644
--- a/crypto/openssl/crypto/dsa/dsa.h
+++ b/crypto/openssl/crypto/dsa/dsa.h
@@ -79,6 +79,10 @@
# include <openssl/dh.h>
#endif
+#ifndef OPENSSL_DSA_MAX_MODULUS_BITS
+# define OPENSSL_DSA_MAX_MODULUS_BITS 10000
+#endif
+
#define DSA_FLAG_CACHE_MONT_P 0x01
#ifdef __cplusplus
@@ -241,8 +245,10 @@ void ERR_load_DSA_strings(void);
#define DSA_F_SIG_CB 114
/* Reason codes. */
+#define DSA_R_BAD_Q_VALUE 102
#define DSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE 100
#define DSA_R_MISSING_PARAMETERS 101
+#define DSA_R_MODULUS_TOO_LARGE 103
#ifdef __cplusplus
}
diff --git a/crypto/openssl/crypto/dsa/dsa_err.c b/crypto/openssl/crypto/dsa/dsa_err.c
index 79aa4ff526c4..bf96765ccd6d 100644
--- a/crypto/openssl/crypto/dsa/dsa_err.c
+++ b/crypto/openssl/crypto/dsa/dsa_err.c
@@ -85,8 +85,10 @@ static ERR_STRING_DATA DSA_str_functs[]=
static ERR_STRING_DATA DSA_str_reasons[]=
{
+{DSA_R_BAD_Q_VALUE ,"bad q value"},
{DSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE ,"data too large for key size"},
{DSA_R_MISSING_PARAMETERS ,"missing parameters"},
+{DSA_R_MODULUS_TOO_LARGE ,"modulus too large"},
{0,NULL}
};
diff --git a/crypto/openssl/crypto/dsa/dsa_ossl.c b/crypto/openssl/crypto/dsa/dsa_ossl.c
index b9e7f3ea5c66..1dfbc250d2b0 100644
--- a/crypto/openssl/crypto/dsa/dsa_ossl.c
+++ b/crypto/openssl/crypto/dsa/dsa_ossl.c
@@ -244,6 +244,18 @@ static int dsa_do_verify(const unsigned char *dgst, int dgst_len, DSA_SIG *sig,
return -1;
}
+ if (BN_num_bits(dsa->q) != 160)
+ {
+ DSAerr(DSA_F_DSA_DO_VERIFY,DSA_R_BAD_Q_VALUE);
+ return -1;
+ }
+
+ if (BN_num_bits(dsa->p) > OPENSSL_DSA_MAX_MODULUS_BITS)
+ {
+ DSAerr(DSA_F_DSA_DO_VERIFY,DSA_R_MODULUS_TOO_LARGE);
+ return -1;
+ }
+
BN_init(&u1);
BN_init(&u2);
BN_init(&t1);
diff --git a/crypto/openssl/crypto/rsa/rsa.h b/crypto/openssl/crypto/rsa/rsa.h
index 1ea0fe10a535..050715aec74c 100644
--- a/crypto/openssl/crypto/rsa/rsa.h
+++ b/crypto/openssl/crypto/rsa/rsa.h
@@ -151,6 +151,17 @@ struct rsa_st
BN_BLINDING *blinding;
};
+#ifndef OPENSSL_RSA_MAX_MODULUS_BITS
+# define OPENSSL_RSA_MAX_MODULUS_BITS 16400
+#endif
+
+#ifndef OPENSSL_RSA_SMALL_MODULUS_BITS
+# define OPENSSL_RSA_SMALL_MODULUS_BITS 4112
+#endif
+#ifndef OPENSSL_RSA_MAX_PUBEXP_BITS
+# define OPENSSL_RSA_MAX_PUBEXP_BITS 72 /* exponent limit enforced for "large" modulus only */
+#endif
+
#define RSA_3 0x3L
#define RSA_F4 0x10001L
@@ -344,6 +355,7 @@ void ERR_load_RSA_strings(void);
#define RSA_R_INVALID_MESSAGE_LENGTH 131
#define RSA_R_IQMP_NOT_INVERSE_OF_Q 126
#define RSA_R_KEY_SIZE_TOO_SMALL 120
+#define RSA_R_MODULUS_TOO_LARGE 105
#define RSA_R_NULL_BEFORE_BLOCK_MISSING 113
#define RSA_R_N_DOES_NOT_EQUAL_P_Q 127
#define RSA_R_OAEP_DECODING_ERROR 121
diff --git a/crypto/openssl/crypto/rsa/rsa_eay.c b/crypto/openssl/crypto/rsa/rsa_eay.c
index 5f7a1f20a359..43737cd00b97 100644
--- a/crypto/openssl/crypto/rsa/rsa_eay.c
+++ b/crypto/openssl/crypto/rsa/rsa_eay.c
@@ -105,6 +105,28 @@ static int RSA_eay_public_encrypt(int flen, const unsigned char *from,
unsigned char *buf=NULL;
BN_CTX *ctx=NULL;
+ if (BN_num_bits(rsa->n) > OPENSSL_RSA_MAX_MODULUS_BITS)
+ {
+ RSAerr(RSA_F_RSA_EAY_PUBLIC_ENCRYPT, RSA_R_MODULUS_TOO_LARGE);
+ return -1;
+ }
+
+ if (BN_ucmp(rsa->n, rsa->e) <= 0)
+ {
+ RSAerr(RSA_F_RSA_EAY_PUBLIC_ENCRYPT, RSA_R_BAD_E_VALUE);
+ return -1;
+ }
+
+ /* for large moduli, enforce exponent limit */
+ if (BN_num_bits(rsa->n) > OPENSSL_RSA_SMALL_MODULUS_BITS)
+ {
+ if (BN_num_bits(rsa->e) > OPENSSL_RSA_MAX_PUBEXP_BITS)
+ {
+ RSAerr(RSA_F_RSA_EAY_PUBLIC_ENCRYPT, RSA_R_BAD_E_VALUE);
+ return -1;
+ }
+ }
+
BN_init(&f);
BN_init(&ret);
if ((ctx=BN_CTX_new()) == NULL) goto err;
@@ -505,6 +527,28 @@ static int RSA_eay_public_decrypt(int flen, const unsigned char *from,
unsigned char *buf=NULL;
BN_CTX *ctx=NULL;
+ if (BN_num_bits(rsa->n) > OPENSSL_RSA_MAX_MODULUS_BITS)
+ {
+ RSAerr(RSA_F_RSA_EAY_PUBLIC_DECRYPT, RSA_R_MODULUS_TOO_LARGE);
+ return -1;
+ }
+
+ if (BN_ucmp(rsa->n, rsa->e) <= 0)
+ {
+ RSAerr(RSA_F_RSA_EAY_PUBLIC_DECRYPT, RSA_R_BAD_E_VALUE);
+ return -1;
+ }
+
+ /* for large moduli, enforce exponent limit */
+ if (BN_num_bits(rsa->n) > OPENSSL_RSA_SMALL_MODULUS_BITS)
+ {
+ if (BN_num_bits(rsa->e) > OPENSSL_RSA_MAX_PUBEXP_BITS)
+ {
+ RSAerr(RSA_F_RSA_EAY_PUBLIC_DECRYPT, RSA_R_BAD_E_VALUE);
+ return -1;
+ }
+ }
+
BN_init(&f);
BN_init(&ret);
ctx=BN_CTX_new();
diff --git a/crypto/openssl/crypto/rsa/rsa_err.c b/crypto/openssl/crypto/rsa/rsa_err.c
index a7766c3b762e..8221a921e7b3 100644
--- a/crypto/openssl/crypto/rsa/rsa_err.c
+++ b/crypto/openssl/crypto/rsa/rsa_err.c
@@ -116,6 +116,7 @@ static ERR_STRING_DATA RSA_str_reasons[]=
{RSA_R_INVALID_MESSAGE_LENGTH ,"invalid message length"},
{RSA_R_IQMP_NOT_INVERSE_OF_Q ,"iqmp not inverse of q"},
{RSA_R_KEY_SIZE_TOO_SMALL ,"key size too small"},
+{RSA_R_MODULUS_TOO_LARGE ,"modulus too large"},
{RSA_R_NULL_BEFORE_BLOCK_MISSING ,"null before block missing"},
{RSA_R_N_DOES_NOT_EQUAL_P_Q ,"n does not equal p q"},
{RSA_R_OAEP_DECODING_ERROR ,"oaep decoding error"},
diff --git a/crypto/openssl/ssl/s2_clnt.c b/crypto/openssl/ssl/s2_clnt.c
index 43b32eb4159f..38f29c5c3ad9 100644
--- a/crypto/openssl/ssl/s2_clnt.c
+++ b/crypto/openssl/ssl/s2_clnt.c
@@ -538,7 +538,8 @@ static int get_server_hello(SSL *s)
CRYPTO_add(&s->session->peer->references, 1, CRYPTO_LOCK_X509);
}
- if (s->session->peer != s->session->sess_cert->peer_key->x509)
+ if (s->session->sess_cert == NULL
+ || s->session->peer != s->session->sess_cert->peer_key->x509)
/* can't happen */
{
ssl2_return_error(s, SSL2_PE_UNDEFINED_ERROR);
diff --git a/crypto/openssl/ssl/s3_srvr.c b/crypto/openssl/ssl/s3_srvr.c
index deb3cffabeb5..1a261cc7bb8b 100644
--- a/crypto/openssl/ssl/s3_srvr.c
+++ b/crypto/openssl/ssl/s3_srvr.c
@@ -1722,7 +1722,7 @@ static int ssl3_get_client_key_exchange(SSL *s)
if (kssl_ctx->client_princ)
{
- int len = strlen(kssl_ctx->client_princ);
+ size_t len = strlen(kssl_ctx->client_princ);
if ( len < SSL_MAX_KRB5_PRINCIPAL_LENGTH )
{
s->session->krb5_client_princ_len = len;
diff --git a/crypto/openssl/ssl/ssl_lib.c b/crypto/openssl/ssl/ssl_lib.c
index ee9a82d5860d..33e089dc0164 100644
--- a/crypto/openssl/ssl/ssl_lib.c
+++ b/crypto/openssl/ssl/ssl_lib.c
@@ -1166,7 +1166,7 @@ char *SSL_get_shared_ciphers(SSL *s,char *buf,int len)
c=sk_SSL_CIPHER_value(sk,i);
for (cp=c->name; *cp; )
{
- if (len-- == 0)
+ if (len-- <= 0)
{
*p='\0';
return(buf);
diff --git a/sys/conf/newvers.sh b/sys/conf/newvers.sh
index c68e6f41efc8..ea79e0a96281 100644
--- a/sys/conf/newvers.sh
+++ b/sys/conf/newvers.sh
@@ -36,7 +36,7 @@
TYPE="FreeBSD"
REVISION="4.11"
-BRANCH="RELEASE-p22"
+BRANCH="RELEASE-p23"
RELEASE="${REVISION}-${BRANCH}"
VERSION="${TYPE} ${RELEASE}"