From 952181054e00ea2f528fbebfd76127fc2f5febdd Mon Sep 17 00:00:00 2001 From: Colin Percival Date: Thu, 28 Sep 2006 13:06:23 +0000 Subject: 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) --- UPDATING | 5 ++++ crypto/openssl/crypto/asn1/tasn_dec.c | 3 +++ crypto/openssl/crypto/dh/dh.h | 5 ++++ crypto/openssl/crypto/dh/dh_err.c | 1 + crypto/openssl/crypto/dh/dh_key.c | 6 +++++ crypto/openssl/crypto/dsa/dsa.h | 6 +++++ crypto/openssl/crypto/dsa/dsa_err.c | 2 ++ crypto/openssl/crypto/dsa/dsa_ossl.c | 12 ++++++++++ crypto/openssl/crypto/rsa/rsa.h | 12 ++++++++++ crypto/openssl/crypto/rsa/rsa_eay.c | 44 +++++++++++++++++++++++++++++++++++ crypto/openssl/crypto/rsa/rsa_err.c | 1 + crypto/openssl/ssl/s2_clnt.c | 3 ++- crypto/openssl/ssl/s3_srvr.c | 2 +- crypto/openssl/ssl/ssl_lib.c | 2 +- sys/conf/newvers.sh | 2 +- 15 files changed, 102 insertions(+), 4 deletions(-) diff --git a/UPDATING b/UPDATING index d0bcfdc17470..a3ea2256bbb1 100644 --- a/UPDATING +++ b/UPDATING @@ -8,6 +8,11 @@ Items affecting the ports and packages system can be found in /usr/ports/UPDATING. Please read that file before running portupgrade. +20060928: p13 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: p12 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 #include +#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 c2715044c912..998257669073 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 ff125c2296fb..f735fa78f1a5 100644 --- a/crypto/openssl/crypto/dh/dh_key.c +++ b/crypto/openssl/crypto/dh/dh_key.c @@ -164,6 +164,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 225ff391f9be..43e2f6060bdf 100644 --- a/crypto/openssl/crypto/dsa/dsa.h +++ b/crypto/openssl/crypto/dsa/dsa.h @@ -79,6 +79,10 @@ # include #endif +#ifndef OPENSSL_DSA_MAX_MODULUS_BITS +# define OPENSSL_DSA_MAX_MODULUS_BITS 10000 +#endif + #define DSA_FLAG_CACHE_MONT_P 0x01 #if defined(OPENSSL_FIPS) @@ -245,8 +249,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 f1a85afcde86..dda7c3d7c967 100644 --- a/crypto/openssl/crypto/dsa/dsa_ossl.c +++ b/crypto/openssl/crypto/dsa/dsa_ossl.c @@ -245,6 +245,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 c82363ee1392..582ad57aeae0 100644 --- a/crypto/openssl/crypto/rsa/rsa.h +++ b/crypto/openssl/crypto/rsa/rsa.h @@ -155,6 +155,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 @@ -348,6 +359,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 0d17acb87b9c..d9264da47c3d 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 c67829f4957c..ddac1a3c0c6a 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 44248ba55941..87b0b2ac59db 100644 --- a/crypto/openssl/ssl/s3_srvr.c +++ b/crypto/openssl/ssl/s3_srvr.c @@ -1733,7 +1733,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 f5705af0f616..c50b58a20458 100644 --- a/crypto/openssl/ssl/ssl_lib.c +++ b/crypto/openssl/ssl/ssl_lib.c @@ -1167,7 +1167,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 1dd45b843a33..7bbb54d3ff95 100644 --- a/sys/conf/newvers.sh +++ b/sys/conf/newvers.sh @@ -32,7 +32,7 @@ TYPE="FreeBSD" REVISION="6.0" -BRANCH="RELEASE-p12" +BRANCH="RELEASE-p13" if [ "X${BRANCH_OVERRIDE}" != "X" ]; then BRANCH=${BRANCH_OVERRIDE} fi -- cgit v1.2.3