From da52be7e5dfa2845b34da40ad0b04f69d6d18b73 Mon Sep 17 00:00:00 2001 From: jkim Date: Thu, 4 Jan 2018 01:21:24 +0000 Subject: [PATCH] MFS: r295060, r296462, r296597-296598, r299053, r306229, r306335, r308200 Sync. OpenSSL with stable/9. r295060 (delphij): Fix OpenSSL SSLv2 ciphersuite downgrade vulnerability. [SA-16:11] r296462, r296597-296598 (delphij): Fix multiple OpenSSL vulnerabilities. [SA-16:12] r299053 (delphij): Fix several OpenSSL vulnerabilities. [SA-16:17] r306229, r306335 (delphij): Fix multiple OpenSSL vulnerabilities. [SA-16:26] r308200 (delphij): Fix OpenSSL remote DoS vulnerability. [SA-16:35] Requested by: danfe git-svn-id: svn://svn.freebsd.org/base/stable/8@327537 ccf9f872-aa2e-dd11-9fc8-001c23d0bc1f --- crypto/openssl/crypto/asn1/a_type.c | 2 - crypto/openssl/crypto/asn1/tasn_dec.c | 2 - crypto/openssl/crypto/asn1/tasn_enc.c | 2 - crypto/openssl/crypto/bio/b_print.c | 578 ++++++++++++++------------ crypto/openssl/crypto/bn/bn.h | 38 +- crypto/openssl/crypto/bn/bn_exp.c | 65 ++- crypto/openssl/crypto/bn/bn_print.c | 91 ++-- crypto/openssl/crypto/dsa/dsa_ossl.c | 7 +- crypto/openssl/crypto/evp/encode.c | 12 +- crypto/openssl/crypto/evp/evp_enc.c | 2 +- crypto/openssl/crypto/mdc2/mdc2dgst.c | 2 +- crypto/openssl/crypto/x509/x509_obj.c | 5 +- crypto/openssl/doc/apps/ciphers.pod | 22 +- crypto/openssl/ssl/d1_both.c | 32 +- crypto/openssl/ssl/d1_clnt.c | 1 + crypto/openssl/ssl/d1_lib.c | 37 +- crypto/openssl/ssl/d1_pkt.c | 116 +++++- crypto/openssl/ssl/d1_srvr.c | 3 +- crypto/openssl/ssl/s2_lib.c | 84 ++-- crypto/openssl/ssl/s2_srvr.c | 15 +- crypto/openssl/ssl/s3_clnt.c | 11 + crypto/openssl/ssl/s3_pkt.c | 15 + crypto/openssl/ssl/s3_srvr.c | 22 +- crypto/openssl/ssl/ssl.h | 2 + crypto/openssl/ssl/ssl3.h | 2 + crypto/openssl/ssl/ssl_err.c | 4 +- crypto/openssl/ssl/ssl_lib.c | 19 +- crypto/openssl/ssl/ssl_locl.h | 7 +- crypto/openssl/ssl/ssl_sess.c | 2 +- crypto/openssl/ssl/t1_lib.c | 103 +++-- 30 files changed, 804 insertions(+), 499 deletions(-) diff --git a/crypto/openssl/crypto/asn1/a_type.c b/crypto/openssl/crypto/asn1/a_type.c index 69a5cf6f4..be6eeedf3 100644 --- a/crypto/openssl/crypto/asn1/a_type.c +++ b/crypto/openssl/crypto/asn1/a_type.c @@ -123,9 +123,7 @@ int ASN1_TYPE_cmp(const ASN1_TYPE *a, const ASN1_TYPE *b) result = 0; /* They do not have content. */ break; case V_ASN1_INTEGER: - case V_ASN1_NEG_INTEGER: case V_ASN1_ENUMERATED: - case V_ASN1_NEG_ENUMERATED: case V_ASN1_BIT_STRING: case V_ASN1_OCTET_STRING: case V_ASN1_SEQUENCE: diff --git a/crypto/openssl/crypto/asn1/tasn_dec.c b/crypto/openssl/crypto/asn1/tasn_dec.c index 91e769811..c72ed08f4 100644 --- a/crypto/openssl/crypto/asn1/tasn_dec.c +++ b/crypto/openssl/crypto/asn1/tasn_dec.c @@ -901,9 +901,7 @@ int asn1_ex_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len, break; case V_ASN1_INTEGER: - case V_ASN1_NEG_INTEGER: case V_ASN1_ENUMERATED: - case V_ASN1_NEG_ENUMERATED: tint = (ASN1_INTEGER **)pval; if (!c2i_ASN1_INTEGER(tint, &cont, len)) goto err; diff --git a/crypto/openssl/crypto/asn1/tasn_enc.c b/crypto/openssl/crypto/asn1/tasn_enc.c index b93f3f69c..928416db3 100644 --- a/crypto/openssl/crypto/asn1/tasn_enc.c +++ b/crypto/openssl/crypto/asn1/tasn_enc.c @@ -610,9 +610,7 @@ int asn1_ex_i2c(ASN1_VALUE **pval, unsigned char *cout, int *putype, break; case V_ASN1_INTEGER: - case V_ASN1_NEG_INTEGER: case V_ASN1_ENUMERATED: - case V_ASN1_NEG_ENUMERATED: /* * These are all have the same content format as ASN1_INTEGER */ diff --git a/crypto/openssl/crypto/bio/b_print.c b/crypto/openssl/crypto/bio/b_print.c index 6c93f9381..9f7f6344a 100644 --- a/crypto/openssl/crypto/bio/b_print.c +++ b/crypto/openssl/crypto/bio/b_print.c @@ -122,20 +122,20 @@ # define LLONG long long # endif #else -# define LLONG long -#endif - -static void fmtstr(char **, char **, size_t *, size_t *, - const char *, int, int, int); -static void fmtint(char **, char **, size_t *, size_t *, - LLONG, int, int, int, int); -static void fmtfp(char **, char **, size_t *, size_t *, - LDOUBLE, int, int, int); -static void doapr_outch(char **, char **, size_t *, size_t *, int); -static void _dopr(char **sbuffer, char **buffer, - size_t *maxlen, size_t *retlen, int *truncated, - const char *format, va_list args); - +# define LLONG long +#endif + +static int fmtstr(char **, char **, size_t *, size_t *, + const char *, int, int, int); +static int fmtint(char **, char **, size_t *, size_t *, + LLONG, int, int, int, int); +static int fmtfp(char **, char **, size_t *, size_t *, + LDOUBLE, int, int, int); +static int doapr_outch(char **, char **, size_t *, size_t *, int); +static int _dopr(char **sbuffer, char **buffer, + size_t *maxlen, size_t *retlen, int *truncated, + const char *format, va_list args); + /* format read states */ #define DP_S_DEFAULT 0 #define DP_S_FLAGS 1 @@ -162,13 +162,13 @@ static void _dopr(char **sbuffer, char **buffer, #define DP_C_LLONG 4 /* some handy macros */ -#define char_to_int(p) (p - '0') -#define OSSL_MAX(p,q) ((p >= q) ? p : q) - -static void -_dopr(char **sbuffer, - char **buffer, - size_t *maxlen, +#define char_to_int(p) (p - '0') +#define OSSL_MAX(p,q) ((p >= q) ? p : q) + +static int +_dopr(char **sbuffer, + char **buffer, + size_t *maxlen, size_t *retlen, int *truncated, const char *format, va_list args) { char ch; @@ -193,13 +193,14 @@ _dopr(char **sbuffer, switch (state) { case DP_S_DEFAULT: - if (ch == '%') - state = DP_S_FLAGS; - else - doapr_outch(sbuffer, buffer, &currlen, maxlen, ch); - ch = *format++; - break; - case DP_S_FLAGS: + if (ch == '%') + state = DP_S_FLAGS; + else + if(!doapr_outch(sbuffer, buffer, &currlen, maxlen, ch)) + return 0; + ch = *format++; + break; + case DP_S_FLAGS: switch (ch) { case '-': flags |= DP_F_MINUS; @@ -299,14 +300,15 @@ _dopr(char **sbuffer, value = va_arg(args, LLONG); break; default: - value = va_arg(args, int); - break; - } - fmtint(sbuffer, buffer, &currlen, maxlen, - value, 10, min, max, flags); - break; - case 'X': - flags |= DP_F_UP; + value = va_arg(args, int); + break; + } + if (!fmtint(sbuffer, buffer, &currlen, maxlen, value, 10, min, + max, flags)) + return 0; + break; + case 'X': + flags |= DP_F_UP; /* FALLTHROUGH */ case 'x': case 'o': @@ -323,23 +325,25 @@ _dopr(char **sbuffer, value = va_arg(args, unsigned LLONG); break; default: - value = (LLONG) va_arg(args, unsigned int); - break; - } - fmtint(sbuffer, buffer, &currlen, maxlen, value, - ch == 'o' ? 8 : (ch == 'u' ? 10 : 16), - min, max, flags); - break; - case 'f': - if (cflags == DP_C_LDOUBLE) - fvalue = va_arg(args, LDOUBLE); - else - fvalue = va_arg(args, double); - fmtfp(sbuffer, buffer, &currlen, maxlen, - fvalue, min, max, flags); - break; - case 'E': - flags |= DP_F_UP; + value = (LLONG) va_arg(args, unsigned int); + break; + } + if (!fmtint(sbuffer, buffer, &currlen, maxlen, value, + ch == 'o' ? 8 : (ch == 'u' ? 10 : 16), + min, max, flags)) + return 0; + break; + case 'f': + if (cflags == DP_C_LDOUBLE) + fvalue = va_arg(args, LDOUBLE); + else + fvalue = va_arg(args, double); + if (!fmtfp(sbuffer, buffer, &currlen, maxlen, fvalue, min, max, + flags)) + return 0; + break; + case 'E': + flags |= DP_F_UP; case 'e': if (cflags == DP_C_LDOUBLE) fvalue = va_arg(args, LDOUBLE); @@ -352,30 +356,33 @@ _dopr(char **sbuffer, if (cflags == DP_C_LDOUBLE) fvalue = va_arg(args, LDOUBLE); else - fvalue = va_arg(args, double); - break; - case 'c': - doapr_outch(sbuffer, buffer, &currlen, maxlen, - va_arg(args, int)); - break; - case 's': - strvalue = va_arg(args, char *); + fvalue = va_arg(args, double); + break; + case 'c': + if(!doapr_outch(sbuffer, buffer, &currlen, maxlen, + va_arg(args, int))) + return 0; + break; + case 's': + strvalue = va_arg(args, char *); if (max < 0) { if (buffer) max = INT_MAX; - else - max = *maxlen; - } - fmtstr(sbuffer, buffer, &currlen, maxlen, strvalue, - flags, min, max); - break; - case 'p': - value = (long)va_arg(args, void *); - fmtint(sbuffer, buffer, &currlen, maxlen, - value, 16, min, max, flags | DP_F_NUM); - break; - case 'n': /* XXX */ - if (cflags == DP_C_SHORT) { + else + max = *maxlen; + } + if (!fmtstr(sbuffer, buffer, &currlen, maxlen, strvalue, + flags, min, max)) + return 0; + break; + case 'p': + value = (long)va_arg(args, void *); + if (!fmtint(sbuffer, buffer, &currlen, maxlen, + value, 16, min, max, flags | DP_F_NUM)) + return 0; + break; + case 'n': /* XXX */ + if (cflags == DP_C_SHORT) { short int *num; num = va_arg(args, short int *); *num = currlen; @@ -391,13 +398,14 @@ _dopr(char **sbuffer, int *num; num = va_arg(args, int *); *num = currlen; - } - break; - case '%': - doapr_outch(sbuffer, buffer, &currlen, maxlen, ch); - break; - case 'w': - /* not supported yet, treat as next char */ + } + break; + case '%': + if(!doapr_outch(sbuffer, buffer, &currlen, maxlen, ch)) + return 0; + break; + case 'w': + /* not supported yet, treat as next char */ ch = *format++; break; default: @@ -415,52 +423,62 @@ _dopr(char **sbuffer, break; } } - *truncated = (currlen > *maxlen - 1); - if (*truncated) - currlen = *maxlen - 1; - doapr_outch(sbuffer, buffer, &currlen, maxlen, '\0'); - *retlen = currlen - 1; - return; -} - -static void -fmtstr(char **sbuffer, - char **buffer, - size_t *currlen, - size_t *maxlen, const char *value, int flags, int min, int max) -{ - int padlen, strln; - int cnt = 0; - - if (value == 0) - value = ""; - for (strln = 0; value[strln]; ++strln) ; - padlen = min - strln; - if (padlen < 0) - padlen = 0; - if (flags & DP_F_MINUS) - padlen = -padlen; - - while ((padlen > 0) && (cnt < max)) { - doapr_outch(sbuffer, buffer, currlen, maxlen, ' '); - --padlen; - ++cnt; - } - while (*value && (cnt < max)) { - doapr_outch(sbuffer, buffer, currlen, maxlen, *value++); - ++cnt; - } - while ((padlen < 0) && (cnt < max)) { - doapr_outch(sbuffer, buffer, currlen, maxlen, ' '); - ++padlen; - ++cnt; - } -} - -static void -fmtint(char **sbuffer, - char **buffer, - size_t *currlen, + *truncated = (currlen > *maxlen - 1); + if (*truncated) + currlen = *maxlen - 1; + if(!doapr_outch(sbuffer, buffer, &currlen, maxlen, '\0')) + return 0; + *retlen = currlen - 1; + return 1; +} + +static int +fmtstr(char **sbuffer, + char **buffer, + size_t *currlen, + size_t *maxlen, const char *value, int flags, int min, int max) +{ + int padlen; + size_t strln; + int cnt = 0; + + if (value == 0) + value = ""; + + strln = strlen(value); + if (strln > INT_MAX) + strln = INT_MAX; + + padlen = min - strln; + if (min < 0 || padlen < 0) + padlen = 0; + if (flags & DP_F_MINUS) + padlen = -padlen; + + while ((padlen > 0) && (cnt < max)) { + if(!doapr_outch(sbuffer, buffer, currlen, maxlen, ' ')) + return 0; + --padlen; + ++cnt; + } + while (*value && (cnt < max)) { + if(!doapr_outch(sbuffer, buffer, currlen, maxlen, *value++)) + return 0; + ++cnt; + } + while ((padlen < 0) && (cnt < max)) { + if(!doapr_outch(sbuffer, buffer, currlen, maxlen, ' ')) + return 0; + ++padlen; + ++cnt; + } + return 1; +} + +static int +fmtint(char **sbuffer, + char **buffer, + size_t *currlen, size_t *maxlen, LLONG value, int base, int min, int max, int flags) { int signvalue = 0; @@ -514,43 +532,50 @@ fmtint(char **sbuffer, } if (flags & DP_F_MINUS) spadlen = -spadlen; - - /* spaces */ - while (spadlen > 0) { - doapr_outch(sbuffer, buffer, currlen, maxlen, ' '); - --spadlen; - } - - /* sign */ - if (signvalue) - doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue); - - /* prefix */ - while (*prefix) { - doapr_outch(sbuffer, buffer, currlen, maxlen, *prefix); - prefix++; - } - - /* zeros */ - if (zpadlen > 0) { - while (zpadlen > 0) { - doapr_outch(sbuffer, buffer, currlen, maxlen, '0'); - --zpadlen; - } - } - /* digits */ - while (place > 0) - doapr_outch(sbuffer, buffer, currlen, maxlen, convert[--place]); - - /* left justified spaces */ - while (spadlen < 0) { - doapr_outch(sbuffer, buffer, currlen, maxlen, ' '); - ++spadlen; - } - return; -} - -static LDOUBLE abs_val(LDOUBLE value) + + /* spaces */ + while (spadlen > 0) { + if(!doapr_outch(sbuffer, buffer, currlen, maxlen, ' ')) + return 0; + --spadlen; + } + + /* sign */ + if (signvalue) + if(!doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue)) + return 0; + + /* prefix */ + while (*prefix) { + if(!doapr_outch(sbuffer, buffer, currlen, maxlen, *prefix)) + return 0; + prefix++; + } + + /* zeros */ + if (zpadlen > 0) { + while (zpadlen > 0) { + if(!doapr_outch(sbuffer, buffer, currlen, maxlen, '0')) + return 0; + --zpadlen; + } + } + /* digits */ + while (place > 0) { + if (!doapr_outch(sbuffer, buffer, currlen, maxlen, convert[--place])) + return 0; + } + + /* left justified spaces */ + while (spadlen < 0) { + if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' ')) + return 0; + ++spadlen; + } + return 1; +} + +static LDOUBLE abs_val(LDOUBLE value) { LDOUBLE result = value; if (value < 0) @@ -575,13 +600,13 @@ static long roundv(LDOUBLE value) value = value - intpart; if (value >= 0.5) intpart++; - return intpart; -} - -static void -fmtfp(char **sbuffer, - char **buffer, - size_t *currlen, + return intpart; +} + +static int +fmtfp(char **sbuffer, + char **buffer, + size_t *currlen, size_t *maxlen, LDOUBLE fvalue, int min, int max, int flags) { int signvalue = 0; @@ -657,87 +682,107 @@ fmtfp(char **sbuffer, padlen = 0; if (flags & DP_F_MINUS) padlen = -padlen; - - if ((flags & DP_F_ZERO) && (padlen > 0)) { - if (signvalue) { - doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue); - --padlen; - signvalue = 0; - } - while (padlen > 0) { - doapr_outch(sbuffer, buffer, currlen, maxlen, '0'); - --padlen; - } - } - while (padlen > 0) { - doapr_outch(sbuffer, buffer, currlen, maxlen, ' '); - --padlen; - } - if (signvalue) - doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue); - - while (iplace > 0) - doapr_outch(sbuffer, buffer, currlen, maxlen, iconvert[--iplace]); - - /* - * Decimal point. This should probably use locale to find the correct - * char to print out. - */ - if (max > 0 || (flags & DP_F_NUM)) { - doapr_outch(sbuffer, buffer, currlen, maxlen, '.'); - - while (fplace > 0) - doapr_outch(sbuffer, buffer, currlen, maxlen, fconvert[--fplace]); - } - while (zpadlen > 0) { - doapr_outch(sbuffer, buffer, currlen, maxlen, '0'); - --zpadlen; - } - - while (padlen < 0) { - doapr_outch(sbuffer, buffer, currlen, maxlen, ' '); - ++padlen; - } -} - -static void -doapr_outch(char **sbuffer, - char **buffer, size_t *currlen, size_t *maxlen, int c) -{ - /* If we haven't at least one buffer, someone has doe a big booboo */ - assert(*sbuffer != NULL || buffer != NULL); - - if (buffer) { - while (*currlen >= *maxlen) { - if (*buffer == NULL) { - if (*maxlen == 0) - *maxlen = 1024; - *buffer = OPENSSL_malloc(*maxlen); - if (*currlen > 0) { - assert(*sbuffer != NULL); - memcpy(*buffer, *sbuffer, *currlen); - } - *sbuffer = NULL; - } else { - *maxlen += 1024; - *buffer = OPENSSL_realloc(*buffer, *maxlen); - } - } - /* What to do if *buffer is NULL? */ - assert(*sbuffer != NULL || *buffer != NULL); - } - - if (*currlen < *maxlen) { - if (*sbuffer) + + if ((flags & DP_F_ZERO) && (padlen > 0)) { + if (signvalue) { + if (!doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue)) + return 0; + --padlen; + signvalue = 0; + } + while (padlen > 0) { + if (!doapr_outch(sbuffer, buffer, currlen, maxlen, '0')) + return 0; + --padlen; + } + } + while (padlen > 0) { + if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' ')) + return 0; + --padlen; + } + if (signvalue && !doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue)) + return 0; + + while (iplace > 0) { + if (!doapr_outch(sbuffer, buffer, currlen, maxlen, iconvert[--iplace])) + return 0; + } + + /* + * Decimal point. This should probably use locale to find the correct + * char to print out. + */ + if (max > 0 || (flags & DP_F_NUM)) { + if (!doapr_outch(sbuffer, buffer, currlen, maxlen, '.')) + return 0; + + while (fplace > 0) { + if(!doapr_outch(sbuffer, buffer, currlen, maxlen, + fconvert[--fplace])) + return 0; + } + } + while (zpadlen > 0) { + if (!doapr_outch(sbuffer, buffer, currlen, maxlen, '0')) + return 0; + --zpadlen; + } + + while (padlen < 0) { + if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' ')) + return 0; + ++padlen; + } + return 1; +} + +#define BUFFER_INC 1024 + +static int +doapr_outch(char **sbuffer, + char **buffer, size_t *currlen, size_t *maxlen, int c) +{ + /* If we haven't at least one buffer, someone has doe a big booboo */ + assert(*sbuffer != NULL || buffer != NULL); + + /* |currlen| must always be <= |*maxlen| */ + assert(*currlen <= *maxlen); + + if (buffer && *currlen == *maxlen) { + if (*maxlen > INT_MAX - BUFFER_INC) + return 0; + + *maxlen += BUFFER_INC; + if (*buffer == NULL) { + *buffer = OPENSSL_malloc(*maxlen); + if (*buffer == NULL) + return 0; + if (*currlen > 0) { + assert(*sbuffer != NULL); + memcpy(*buffer, *sbuffer, *currlen); + } + *sbuffer = NULL; + } else { + char *tmpbuf; + tmpbuf = OPENSSL_realloc(*buffer, *maxlen); + if (tmpbuf == NULL) + return 0; + *buffer = tmpbuf; + } + } + + if (*currlen < *maxlen) { + if (*sbuffer) (*sbuffer)[(*currlen)++] = (char)c; else - (*buffer)[(*currlen)++] = (char)c; - } - - return; -} - -/***************************************************************************/ + (*buffer)[(*currlen)++] = (char)c; + } + + return 1; +} + +/***************************************************************************/ int BIO_printf(BIO *bio, const char *format, ...) { @@ -763,13 +808,17 @@ int BIO_vprintf(BIO *bio, const char *format, va_list args) size_t hugebufsize = sizeof(hugebuf); char *dynbuf = NULL; int ignored; - - dynbuf = NULL; - CRYPTO_push_info("doapr()"); - _dopr(&hugebufp, &dynbuf, &hugebufsize, &retlen, &ignored, format, args); - if (dynbuf) { - ret = BIO_write(bio, dynbuf, (int)retlen); - OPENSSL_free(dynbuf); + + dynbuf = NULL; + CRYPTO_push_info("doapr()"); + if (!_dopr(&hugebufp, &dynbuf, &hugebufsize, &retlen, &ignored, format, + args)) { + OPENSSL_free(dynbuf); + return -1; + } + if (dynbuf) { + ret = BIO_write(bio, dynbuf, (int)retlen); + OPENSSL_free(dynbuf); } else { ret = BIO_write(bio, hugebuf, (int)retlen); } @@ -798,13 +847,14 @@ int BIO_snprintf(char *buf, size_t n, const char *format, ...) int BIO_vsnprintf(char *buf, size_t n, const char *format, va_list args) { - size_t retlen; - int truncated; - - _dopr(&buf, NULL, &n, &retlen, &truncated, format, args); - - if (truncated) - /* + size_t retlen; + int truncated; + + if(!_dopr(&buf, NULL, &n, &retlen, &truncated, format, args)) + return -1; + + if (truncated) + /* * In case of truncation, return -1 like traditional snprintf. * (Current drafts for ISO/IEC 9899 say snprintf should return the * number of characters that would have been written, had the buffer diff --git a/crypto/openssl/crypto/bn/bn.h b/crypto/openssl/crypto/bn/bn.h index fa3520b36..894fed135 100644 --- a/crypto/openssl/crypto/bn/bn.h +++ b/crypto/openssl/crypto/bn/bn.h @@ -69,12 +69,13 @@ * */ -#ifndef HEADER_BN_H -# define HEADER_BN_H - -# include -# ifndef OPENSSL_NO_FP_API -# include /* FILE */ +#ifndef HEADER_BN_H +# define HEADER_BN_H + +# include +# include +# ifndef OPENSSL_NO_FP_API +# include /* FILE */ # endif # include @@ -701,14 +702,23 @@ const BIGNUM *BN_get0_nist_prime_224(void); const BIGNUM *BN_get0_nist_prime_256(void); const BIGNUM *BN_get0_nist_prime_384(void); const BIGNUM *BN_get0_nist_prime_521(void); - -/* library internal functions */ - -# define bn_expand(a,bits) ((((((bits+BN_BITS2-1))/BN_BITS2)) <= (a)->dmax)?\ - (a):bn_expand2((a),(bits+BN_BITS2-1)/BN_BITS2)) -# define bn_wexpand(a,words) (((words) <= (a)->dmax)?(a):bn_expand2((a),(words))) -BIGNUM *bn_expand2(BIGNUM *a, int words); -# ifndef OPENSSL_NO_DEPRECATED + +/* library internal functions */ + +# define bn_expand(a,bits) \ + ( \ + bits > (INT_MAX - BN_BITS2 + 1) ? \ + NULL \ + : \ + (((bits+BN_BITS2-1)/BN_BITS2) <= (a)->dmax) ? \ + (a) \ + : \ + bn_expand2((a),(bits+BN_BITS2-1)/BN_BITS2) \ + ) + +# define bn_wexpand(a,words) (((words) <= (a)->dmax)?(a):bn_expand2((a),(words))) +BIGNUM *bn_expand2(BIGNUM *a, int words); +# ifndef OPENSSL_NO_DEPRECATED BIGNUM *bn_dup_expand(const BIGNUM *a, int words); /* unused */ # endif diff --git a/crypto/openssl/crypto/bn/bn_exp.c b/crypto/openssl/crypto/bn/bn_exp.c index ef67843fc..2ce056d13 100644 --- a/crypto/openssl/crypto/bn/bn_exp.c +++ b/crypto/openssl/crypto/bn/bn_exp.c @@ -110,6 +110,7 @@ */ #include "cryptlib.h" +#include "constant_time_locl.h" #include "bn_lcl.h" /* maximum precomputation table size for *variable* sliding windows */ @@ -523,9 +524,11 @@ int BN_mod_exp_mont(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p, static int MOD_EXP_CTIME_COPY_TO_PREBUF(BIGNUM *b, int top, unsigned char *buf, int idx, - int width) + int window) { - size_t i, j; + int i, j; + int width = 1 << window; + BN_ULONG *table = (BN_ULONG *)buf; if (bn_wexpand(b, top) == NULL) return 0; @@ -533,8 +536,8 @@ static int MOD_EXP_CTIME_COPY_TO_PREBUF(BIGNUM *b, int top, b->d[b->top++] = 0; } - for (i = 0, j = idx; i < top * sizeof b->d[0]; i++, j += width) { - buf[j] = ((unsigned char *)b->d)[i]; + for (i = 0, j = idx; i < top; i++, j += width) { + table[j] = b->d[i]; } bn_correct_top(b); @@ -543,15 +546,51 @@ static int MOD_EXP_CTIME_COPY_TO_PREBUF(BIGNUM *b, int top, static int MOD_EXP_CTIME_COPY_FROM_PREBUF(BIGNUM *b, int top, unsigned char *buf, int idx, - int width) + int window) { - size_t i, j; + int i, j; + int width = 1 << window; + volatile BN_ULONG *table = (volatile BN_ULONG *)buf; if (bn_wexpand(b, top) == NULL) return 0; - for (i = 0, j = idx; i < top * sizeof b->d[0]; i++, j += width) { - ((unsigned char *)b->d)[i] = buf[j]; + if (window <= 3) { + for (i = 0; i < top; i++, table += width) { + BN_ULONG acc = 0; + + for (j = 0; j < width; j++) { + acc |= table[j] & + ((BN_ULONG)0 - (constant_time_eq_int(j,idx)&1)); + } + + b->d[i] = acc; + } + } else { + int xstride = 1 << (window - 2); + BN_ULONG y0, y1, y2, y3; + + i = idx >> (window - 2); /* equivalent of idx / xstride */ + idx &= xstride - 1; /* equivalent of idx % xstride */ + + y0 = (BN_ULONG)0 - (constant_time_eq_int(i,0)&1); + y1 = (BN_ULONG)0 - (constant_time_eq_int(i,1)&1); + y2 = (BN_ULONG)0 - (constant_time_eq_int(i,2)&1); + y3 = (BN_ULONG)0 - (constant_time_eq_int(i,3)&1); + + for (i = 0; i < top; i++, table += width) { + BN_ULONG acc = 0; + + for (j = 0; j < xstride; j++) { + acc |= ( (table[j + 0 * xstride] & y0) | + (table[j + 1 * xstride] & y1) | + (table[j + 2 * xstride] & y2) | + (table[j + 3 * xstride] & y3) ) + & ((BN_ULONG)0 - (constant_time_eq_int(j,idx)&1)); + } + + b->d[i] = acc; + } } b->top = top; @@ -648,7 +687,7 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p, */ if (!BN_to_montgomery(r, BN_value_one(), mont, ctx)) goto err; - if (!MOD_EXP_CTIME_COPY_TO_PREBUF(r, top, powerbuf, 0, numPowers)) + if (!MOD_EXP_CTIME_COPY_TO_PREBUF(r, top, powerbuf, 0, window)) goto err; /* Initialize computeTemp as a^1 with montgomery precalcs */ @@ -667,7 +706,7 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p, goto err; if (!BN_copy(computeTemp, am)) goto err; - if (!MOD_EXP_CTIME_COPY_TO_PREBUF(am, top, powerbuf, 1, numPowers)) + if (!MOD_EXP_CTIME_COPY_TO_PREBUF(am, top, powerbuf, 1, window)) goto err; /* @@ -682,8 +721,8 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p, if (!BN_mod_mul_montgomery (computeTemp, am, computeTemp, mont, ctx)) goto err; - if (!MOD_EXP_CTIME_COPY_TO_PREBUF - (computeTemp, top, powerbuf, i, numPowers)) + if (!MOD_EXP_CTIME_COPY_TO_PREBUF(computeTemp, top, powerbuf, i, + window)) goto err; } } @@ -719,7 +758,7 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p, * Fetch the appropriate pre-computed value from the pre-buf */ if (!MOD_EXP_CTIME_COPY_FROM_PREBUF - (computeTemp, top, powerbuf, wvalue, numPowers)) + (computeTemp, top, powerbuf, wvalue, window)) goto err; /* Multiply the result into the intermediate result */ diff --git a/crypto/openssl/crypto/bn/bn_print.c b/crypto/openssl/crypto/bn/bn_print.c index 611765341..ad652e7f1 100644 --- a/crypto/openssl/crypto/bn/bn_print.c +++ b/crypto/openssl/crypto/bn/bn_print.c @@ -55,12 +55,13 @@ * copied and put under another distribution licence * [including the GNU Public Licence.] */ - -#include -#include -#include "cryptlib.h" -#include -#include "bn_lcl.h" + +#include +#include +#include +#include "cryptlib.h" +#include +#include "bn_lcl.h" static const char Hex[] = "0123456789ABCDEF"; @@ -110,6 +111,7 @@ char *BN_bn2dec(const BIGNUM *a) char *p; BIGNUM *t = NULL; BN_ULONG *bn_data = NULL, *lp; + int bn_data_num; /*- * get an upper bound for the length of the decimal integer @@ -119,8 +121,8 @@ char *BN_bn2dec(const BIGNUM *a) */ i = BN_num_bits(a) * 3; num = (i / 10 + i / 1000 + 1) + 1; - bn_data = - (BN_ULONG *)OPENSSL_malloc((num / BN_DEC_NUM + 1) * sizeof(BN_ULONG)); + bn_data_num = num / BN_DEC_NUM + 1; + bn_data = OPENSSL_malloc(bn_data_num * sizeof(BN_ULONG)); buf = (char *)OPENSSL_malloc(num + 3); if ((buf == NULL) || (bn_data == NULL)) { BNerr(BN_F_BN_BN2DEC, ERR_R_MALLOC_FAILURE); @@ -139,9 +141,12 @@ char *BN_bn2dec(const BIGNUM *a) if (BN_is_negative(t)) *p++ = '-'; - i = 0; while (!BN_is_zero(t)) { + if (lp - bn_data >= bn_data_num) + goto err; *lp = BN_div_word(t, BN_DEC_CONV); + if (*lp == (BN_ULONG)-1) + goto err; lp++; } lp--; @@ -186,14 +191,18 @@ int BN_hex2bn(BIGNUM **bn, const char *a) if (*a == '-') { neg = 1; - a++; - } - - for (i = 0; isxdigit((unsigned char)a[i]); i++) ; - - num = i + neg; - if (bn == NULL) - return (num); + a++; + } + + for (i = 0; i <= (INT_MAX/4) && isxdigit((unsigned char)a[i]); i++) + continue; + + if (i > INT_MAX/4) + goto err; + + num = i + neg; + if (bn == NULL) + return (num); /* a is the start of the hex digits, and it is 'i' long */ if (*bn == NULL) { @@ -201,13 +210,13 @@ int BN_hex2bn(BIGNUM **bn, const char *a) return (0); } else { ret = *bn; - BN_zero(ret); - } - - /* i is the number of hex digests; */ - if (bn_expand(ret, i * 4) == NULL) - goto err; - + BN_zero(ret); + } + + /* i is the number of hex digits */ + if (bn_expand(ret, i * 4) == NULL) + goto err; + j = i; /* least significant 'hex' */ m = 0; h = 0; @@ -257,14 +266,18 @@ int BN_dec2bn(BIGNUM **bn, const char *a) return (0); if (*a == '-') { neg = 1; - a++; - } - - for (i = 0; isdigit((unsigned char)a[i]); i++) ; - - num = i + neg; - if (bn == NULL) - return (num); + a++; + } + + for (i = 0; i <= (INT_MAX/4) && isdigit((unsigned char)a[i]); i++) + continue; + + if (i > INT_MAX/4) + goto err; + + num = i + neg; + if (bn == NULL) + return (num); /* * a is the start of the digits, and it is 'i' long. We chop it into @@ -275,13 +288,13 @@ int BN_dec2bn(BIGNUM **bn, const char *a) return (0); } else { ret = *bn; - BN_zero(ret); - } - - /* i is the number of digests, a bit of an over expand; */ - if (bn_expand(ret, i * 4) == NULL) - goto err; - + BN_zero(ret); + } + + /* i is the number of digits, a bit of an over expand */ + if (bn_expand(ret, i * 4) == NULL) + goto err; + j = BN_DEC_NUM - (i % BN_DEC_NUM); if (j == BN_DEC_NUM) j = 0; diff --git a/crypto/openssl/crypto/dsa/dsa_ossl.c b/crypto/openssl/crypto/dsa/dsa_ossl.c index c44a4e36a..e26a62d62 100644 --- a/crypto/openssl/crypto/dsa/dsa_ossl.c +++ b/crypto/openssl/crypto/dsa/dsa_ossl.c @@ -235,11 +235,13 @@ static int dsa_sign_setup(DSA *dsa, BN_CTX *ctx_in, BIGNUM **kinvp, do if (!BN_rand_range(&k, dsa->q)) goto err; - while (BN_is_zero(&k)) ; + while (BN_is_zero(&k)); + if ((dsa->flags & DSA_FLAG_NO_EXP_CONSTTIME) == 0) { BN_set_flags(&k, BN_FLG_CONSTTIME); } + if (dsa->flags & DSA_FLAG_CACHE_MONT_P) { if (!BN_MONT_CTX_set_locked(&dsa->method_mont_p, CRYPTO_LOCK_DSA, dsa->p, ctx)) @@ -252,6 +254,8 @@ static int dsa_sign_setup(DSA *dsa, BN_CTX *ctx_in, BIGNUM **kinvp, if (!BN_copy(&kq, &k)) goto err; + BN_set_flags(&kq, BN_FLG_CONSTTIME); + /* * We do not want timing information to leak the length of k, so we * compute g^k using an equivalent exponent of fixed length. (This @@ -270,6 +274,7 @@ static int dsa_sign_setup(DSA *dsa, BN_CTX *ctx_in, BIGNUM **kinvp, } else { K = &k; } + DSA_BN_MOD_EXP(goto err, dsa, r, dsa->g, K, dsa->p, ctx, dsa->method_mont_p); if (!BN_mod(r, r, dsa->q, ctx)) diff --git a/crypto/openssl/crypto/evp/encode.c b/crypto/openssl/crypto/evp/encode.c index 9bdcd5724..eb42a18a3 100644 --- a/crypto/openssl/crypto/evp/encode.c +++ b/crypto/openssl/crypto/evp/encode.c @@ -57,6 +57,7 @@ */ #include +#include #include "cryptlib.h" #include @@ -134,13 +135,13 @@ void EVP_EncodeUpdate(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl, const unsigned char *in, int inl) { int i, j; - unsigned int total = 0; + size_t total = 0; *outl = 0; if (inl == 0) return; OPENSSL_assert(ctx->length <= (int)sizeof(ctx->enc_data)); - if ((ctx->num + inl) < ctx->length) { + if (ctx->length - ctx->num > inl) { memcpy(&(ctx->enc_data[ctx->num]), in, inl); ctx->num += inl; return; @@ -157,7 +158,7 @@ void EVP_EncodeUpdate(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl, *out = '\0'; total = j + 1; } - while (inl >= ctx->length) { + while (inl >= ctx->length && total <= INT_MAX) { j = EVP_EncodeBlock(out, in, ctx->length); in += ctx->length; inl -= ctx->length; @@ -166,6 +167,11 @@ void EVP_EncodeUpdate(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl, *out = '\0'; total += j + 1; } + if (total > INT_MAX) { + /* Too much output data! */ + *outl = 0; + return; + } if (inl != 0) memcpy(&(ctx->enc_data[0]), in, inl); ctx->num = inl; diff --git a/crypto/openssl/crypto/evp/evp_enc.c b/crypto/openssl/crypto/evp/evp_enc.c index 8a91a679b..5205047e4 100644 --- a/crypto/openssl/crypto/evp/evp_enc.c +++ b/crypto/openssl/crypto/evp/evp_enc.c @@ -166,7 +166,7 @@ int EVP_EncryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl, bl = ctx->cipher->block_size; OPENSSL_assert(bl <= (int)sizeof(ctx->buf)); if (i != 0) { - if (i + inl < bl) { + if (bl - i > inl) { memcpy(&(ctx->buf[i]), in, inl); ctx->buf_len += inl; *outl = 0; diff --git a/crypto/openssl/crypto/mdc2/mdc2dgst.c b/crypto/openssl/crypto/mdc2/mdc2dgst.c index 82cd6b452..2868ae033 100644 --- a/crypto/openssl/crypto/mdc2/mdc2dgst.c +++ b/crypto/openssl/crypto/mdc2/mdc2dgst.c @@ -94,7 +94,7 @@ int MDC2_Update(MDC2_CTX *c, const unsigned char *in, size_t len) i = c->num; if (i != 0) { - if (i + len < MDC2_BLOCK) { + if (len < MDC2_BLOCK - i) { /* partial block */ memcpy(&(c->data[i]), in, len); c->num += (int)len; diff --git a/crypto/openssl/crypto/x509/x509_obj.c b/crypto/openssl/crypto/x509/x509_obj.c index c334d3b05..e9822b0e9 100644 --- a/crypto/openssl/crypto/x509/x509_obj.c +++ b/crypto/openssl/crypto/x509/x509_obj.c @@ -117,8 +117,9 @@ char *X509_NAME_oneline(X509_NAME *a, char *buf, int len) type == V_ASN1_PRINTABLESTRING || type == V_ASN1_TELETEXSTRING || type == V_ASN1_VISIBLESTRING || type == V_ASN1_IA5STRING) { - ascii2ebcdic(ebcdic_buf, q, (num > sizeof ebcdic_buf) - ? sizeof ebcdic_buf : num); + if (num > (int)sizeof(ebcdic_buf)) + num = sizeof(ebcdic_buf); + ascii2ebcdic(ebcdic_buf, q, num); q = ebcdic_buf; } #endif diff --git a/crypto/openssl/doc/apps/ciphers.pod b/crypto/openssl/doc/apps/ciphers.pod index 01d31ddfc..f763cdc95 100644 --- a/crypto/openssl/doc/apps/ciphers.pod +++ b/crypto/openssl/doc/apps/ciphers.pod @@ -380,17 +380,17 @@ Note: these ciphers can also be used in SSL v3. TLS_DHE_DSS_EXPORT1024_WITH_RC4_56_SHA EXP1024-DHE-DSS-RC4-SHA TLS_DHE_DSS_WITH_RC4_128_SHA DHE-DSS-RC4-SHA -=head2 SSL v2.0 cipher suites. - - SSL_CK_RC4_128_WITH_MD5 RC4-MD5 - SSL_CK_RC4_128_EXPORT40_WITH_MD5 EXP-RC4-MD5 - SSL_CK_RC2_128_CBC_WITH_MD5 RC2-MD5 - SSL_CK_RC2_128_CBC_EXPORT40_WITH_MD5 EXP-RC2-MD5 - SSL_CK_IDEA_128_CBC_WITH_MD5 IDEA-CBC-MD5 - SSL_CK_DES_64_CBC_WITH_MD5 DES-CBC-MD5 - SSL_CK_DES_192_EDE3_CBC_WITH_MD5 DES-CBC3-MD5 - -=head1 NOTES +=head2 SSL v2.0 cipher suites. + + SSL_CK_RC4_128_WITH_MD5 RC4-MD5 + SSL_CK_RC4_128_EXPORT40_WITH_MD5 Not implemented. + SSL_CK_RC2_128_CBC_WITH_MD5 RC2-CBC-MD5 + SSL_CK_RC2_128_CBC_EXPORT40_WITH_MD5 Not implemented. + SSL_CK_IDEA_128_CBC_WITH_MD5 IDEA-CBC-MD5 + SSL_CK_DES_64_CBC_WITH_MD5 Not implemented. + SSL_CK_DES_192_EDE3_CBC_WITH_MD5 DES-CBC3-MD5 + +=head1 NOTES The non-ephemeral DH modes are currently unimplemented in OpenSSL because there is no support for DH certificates. diff --git a/crypto/openssl/ssl/d1_both.c b/crypto/openssl/ssl/d1_both.c index 4642d7729..9856cfc2e 100644 --- a/crypto/openssl/ssl/d1_both.c +++ b/crypto/openssl/ssl/d1_both.c @@ -543,11 +543,23 @@ static int dtls1_retrieve_buffered_fragment(SSL *s, long max, int *ok) int al; *ok = 0; - item = pqueue_peek(s->d1->buffered_messages); - if (item == NULL) - return 0; + do { + item = pqueue_peek(s->d1->buffered_messages); + if (item == NULL) + return 0; + + frag = (hm_fragment *)item->data; + + if (frag->msg_header.seq < s->d1->handshake_read_seq) { + /* This is a stale message that has been buffered so clear it */ + pqueue_pop(s->d1->buffered_messages); + dtls1_hm_fragment_free(frag); + pitem_free(item); + item = NULL; + frag = NULL; + } + } while (item == NULL); - frag = (hm_fragment *)item->data; /* Don't return if reassembly still in progress */ if (frag->reassembly != NULL) @@ -1335,18 +1347,6 @@ dtls1_retransmit_message(SSL *s, unsigned short seq, unsigned long frag_off, return ret; } -/* call this function when the buffered messages are no longer needed */ -void dtls1_clear_record_buffer(SSL *s) -{ - pitem *item; - - for (item = pqueue_pop(s->d1->sent_messages); - item != NULL; item = pqueue_pop(s->d1->sent_messages)) { - dtls1_hm_fragment_free((hm_fragment *)item->data); - pitem_free(item); - } -} - unsigned char *dtls1_set_message_header(SSL *s, unsigned char *p, unsigned char mt, unsigned long len, unsigned long frag_off, diff --git a/crypto/openssl/ssl/d1_clnt.c b/crypto/openssl/ssl/d1_clnt.c index 335111a4f..afe1aa60e 100644 --- a/crypto/openssl/ssl/d1_clnt.c +++ b/crypto/openssl/ssl/d1_clnt.c @@ -564,6 +564,7 @@ int dtls1_connect(SSL *s) /* done with handshaking */ s->d1->handshake_read_seq = 0; s->d1->next_handshake_write_seq = 0; + dtls1_clear_received_buffer(s); goto end; /* break; */ diff --git a/crypto/openssl/ssl/d1_lib.c b/crypto/openssl/ssl/d1_lib.c index b4f5fcd7e..b166c1fe9 100644 --- a/crypto/openssl/ssl/d1_lib.c +++ b/crypto/openssl/ssl/d1_lib.c @@ -155,7 +155,6 @@ int dtls1_new(SSL *s) static void dtls1_clear_queues(SSL *s) { pitem *item = NULL; - hm_fragment *frag = NULL; DTLS1_RECORD_DATA *rdata; while ((item = pqueue_pop(s->d1->unprocessed_rcds.q)) != NULL) { @@ -176,12 +175,36 @@ static void dtls1_clear_queues(SSL *s) pitem_free(item); } + while ((item = pqueue_pop(s->d1->buffered_app_data.q)) != NULL) { + rdata = (DTLS1_RECORD_DATA *)item->data; + if (rdata->rbuf.buf) { + OPENSSL_free(rdata->rbuf.buf); + } + OPENSSL_free(item->data); + pitem_free(item); + } + + dtls1_clear_received_buffer(s); + dtls1_clear_sent_buffer(s); +} + +void dtls1_clear_received_buffer(SSL *s) +{ + pitem *item = NULL; + hm_fragment *frag = NULL; + while ((item = pqueue_pop(s->d1->buffered_messages)) != NULL) { frag = (hm_fragment *)item->data; OPENSSL_free(frag->fragment); OPENSSL_free(frag); pitem_free(item); } +} + +void dtls1_clear_sent_buffer(SSL *s) +{ + pitem *item = NULL; + hm_fragment *frag = NULL; while ((item = pqueue_pop(s->d1->sent_messages)) != NULL) { frag = (hm_fragment *)item->data; @@ -189,17 +212,9 @@ static void dtls1_clear_queues(SSL *s) OPENSSL_free(frag); pitem_free(item); } - - while ((item = pqueue_pop(s->d1->buffered_app_data.q)) != NULL) { - rdata = (DTLS1_RECORD_DATA *)item->data; - if (rdata->rbuf.buf) { - OPENSSL_free(rdata->rbuf.buf); - } - OPENSSL_free(item->data); - pitem_free(item); - } } + void dtls1_free(SSL *s) { ssl3_free(s); @@ -431,7 +446,7 @@ void dtls1_stop_timer(SSL *s) BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT, 0, &(s->d1->next_timeout)); /* Clear retransmission buffer */ - dtls1_clear_record_buffer(s); + dtls1_clear_sent_buffer(s); } int dtls1_check_timeout_num(SSL *s) diff --git a/crypto/openssl/ssl/d1_pkt.c b/crypto/openssl/ssl/d1_pkt.c index b5c3653d8..9a5b14582 100644 --- a/crypto/openssl/ssl/d1_pkt.c +++ b/crypto/openssl/ssl/d1_pkt.c @@ -124,8 +124,7 @@ static int have_handshake_fragment(SSL *s, int type, unsigned char *buf, int len, int peek); -static int dtls1_record_replay_check(SSL *s, DTLS1_BITMAP *bitmap, - PQ_64BIT * seq_num); +static int dtls1_record_replay_check(SSL *s, DTLS1_BITMAP *bitmap); static void dtls1_record_bitmap_update(SSL *s, DTLS1_BITMAP *bitmap); static DTLS1_BITMAP *dtls1_get_bitmap(SSL *s, SSL3_RECORD *rr, unsigned int *is_next_epoch); @@ -135,7 +134,7 @@ static int dtls1_record_needs_buffering(SSL *s, SSL3_RECORD *rr, unsigned long *offset); #endif static int dtls1_buffer_record(SSL *s, record_pqueue *q, PQ_64BIT * priority); -static int dtls1_process_record(SSL *s); +static int dtls1_process_record(SSL *s, DTLS1_BITMAP *bitmap); #if PQ_64BIT_IS_INTEGER static PQ_64BIT bytes_to_long_long(unsigned char *bytes, PQ_64BIT * num); #endif @@ -248,20 +247,66 @@ static int dtls1_retrieve_buffered_record(SSL *s, record_pqueue *queue) static int dtls1_process_buffered_records(SSL *s) { pitem *item; + SSL3_BUFFER *rb; + SSL3_RECORD *rr; + DTLS1_BITMAP *bitmap; + unsigned int is_next_epoch; + int replayok = 1; item = pqueue_peek(s->d1->unprocessed_rcds.q); if (item) { /* Check if epoch is current. */ if (s->d1->unprocessed_rcds.epoch != s->d1->r_epoch) - return (1); /* Nothing to do. */ + return 1; /* Nothing to do. */ + + rr = &s->s3->rrec; + rb = &s->s3->rbuf; + + if (rb->left > 0) { + /* + * We've still got data from the current packet to read. There could + * be a record from the new epoch in it - so don't overwrite it + * with the unprocessed records yet (we'll do it when we've + * finished reading the current packet). + */ + return 1; + } + /* Process all the records. */ while (pqueue_peek(s->d1->unprocessed_rcds.q)) { dtls1_get_unprocessed_record(s); - if (!dtls1_process_record(s)) - return (0); - dtls1_buffer_record(s, &(s->d1->processed_rcds), - &s->s3->rrec.seq_num); + bitmap = dtls1_get_bitmap(s, rr, &is_next_epoch); + if (bitmap == NULL) { + /* + * Should not happen. This will only ever be NULL when the + * current record is from a different epoch. But that cannot + * be the case because we already checked the epoch above + */ + SSLerr(SSL_F_DTLS1_PROCESS_BUFFERED_RECORDS, + ERR_R_INTERNAL_ERROR); + return 0; + } + { + /* + * Check whether this is a repeat, or aged record. We did this + * check once already when we first received the record - but + * we might have updated the window since then due to + * records we subsequently processed. + */ + replayok = dtls1_record_replay_check(s, bitmap); + } + + if (!replayok || !dtls1_process_record(s, bitmap)) { + /* dump this record */ + rr->length = 0; + s->packet_length = 0; + continue; + } + + if (dtls1_buffer_record(s, &(s->d1->processed_rcds), + &s->s3->rrec.seq_num) < 0) + return 0; } } @@ -272,7 +317,7 @@ static int dtls1_process_buffered_records(SSL *s) s->d1->processed_rcds.epoch = s->d1->r_epoch; s->d1->unprocessed_rcds.epoch = s->d1->r_epoch + 1; - return (1); + return 1; } #if 0 @@ -319,7 +364,7 @@ static int dtls1_get_buffered_record(SSL *s) #endif -static int dtls1_process_record(SSL *s) +static int dtls1_process_record(SSL *s, DTLS1_BITMAP *bitmap) { int i, al; int enc_err; @@ -478,8 +523,10 @@ static int dtls1_process_record(SSL *s) /* we have pulled in a full packet so zero things */ s->packet_length = 0; - dtls1_record_bitmap_update(s, &(s->d1->bitmap)); /* Mark receipt of - * record. */ + + /* Mark receipt of record. */ + dtls1_record_bitmap_update(s, bitmap); + return (1); f_err: @@ -510,6 +557,7 @@ int dtls1_get_record(SSL *s) rr = &(s->s3->rrec); + again: /* * The epoch may have changed. If so, process all the pending records. * This is a non-blocking operation. @@ -521,7 +569,6 @@ int dtls1_get_record(SSL *s) return 1; /* get something from the wire */ - again: /* check if we have the header */ if ((s->rstate != SSL_ST_READ_BODY) || (s->packet_length < DTLS1_RT_HEADER_LENGTH)) { @@ -620,7 +667,7 @@ int dtls1_get_record(SSL *s) if (!(s->d1->listen && rr->type == SSL3_RT_HANDSHAKE && s->packet_length > DTLS1_RT_HEADER_LENGTH && s->packet[DTLS1_RT_HEADER_LENGTH] == SSL3_MT_CLIENT_HELLO) && - !dtls1_record_replay_check(s, bitmap, &(rr->seq_num))) { + !dtls1_record_replay_check(s, bitmap)) { rr->length = 0; s->packet_length = 0; /* dump this record */ goto again; /* get another record */ @@ -638,14 +685,16 @@ int dtls1_get_record(SSL *s) */ if (is_next_epoch) { if ((SSL_in_init(s) || s->in_handshake) && !s->d1->listen) { - dtls1_buffer_record(s, &(s->d1->unprocessed_rcds), &rr->seq_num); + if (dtls1_buffer_record + (s, &(s->d1->unprocessed_rcds), &rr->seq_num) < 0) + return -1; } rr->length = 0; s->packet_length = 0; goto again; } - if (!dtls1_process_record(s)) { + if (!dtls1_process_record(s, bitmap)) { rr->length = 0; s->packet_length = 0; /* dump this record */ goto again; /* get another record */ @@ -771,6 +820,13 @@ int dtls1_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek) goto start; } + /* + * Reset the count of consecutive warning alerts if we've got a non-empty + * record that isn't an alert. + */ + if (rr->type != SSL3_RT_ALERT && rr->length != 0) + s->s3->alert_count = 0; + /* we now have a packet which can be read and processed */ if (s->s3->change_cipher_spec /* set when we receive ChangeCipherSpec, @@ -994,6 +1050,14 @@ int dtls1_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek) if (alert_level == 1) { /* warning */ s->s3->warn_alert = alert_descr; + + s->s3->alert_count++; + if (s->s3->alert_count == MAX_WARN_ALERT_COUNT) { + al = SSL_AD_UNEXPECTED_MESSAGE; + SSLerr(SSL_F_DTLS1_READ_BYTES, SSL_R_TOO_MANY_WARN_ALERTS); + goto f_err; + } + if (alert_descr == SSL_AD_CLOSE_NOTIFY) { s->shutdown |= SSL_RECEIVED_SHUTDOWN; return (0); @@ -1514,8 +1578,7 @@ int do_dtls1_write(SSL *s, int type, const unsigned char *buf, return -1; } -static int dtls1_record_replay_check(SSL *s, DTLS1_BITMAP *bitmap, - PQ_64BIT * seq_num) +static int dtls1_record_replay_check(SSL *s, DTLS1_BITMAP *bitmap) { #if PQ_64BIT_IS_INTEGER PQ_64BIT mask = 0x0000000000000001L; @@ -1530,7 +1593,7 @@ static int dtls1_record_replay_check(SSL *s, DTLS1_BITMAP *bitmap, if (pq_64bit_gt(&rcd_num, &(bitmap->max_seq_num)) || pq_64bit_eq(&rcd_num, &(bitmap->max_seq_num))) { - pq_64bit_assign(seq_num, &rcd_num); + pq_64bit_assign(&s->s3->rrec.seq_num, &rcd_num); pq_64bit_free(&rcd_num); pq_64bit_free(&tmp); return 1; /* this record is new */ @@ -1561,7 +1624,7 @@ static int dtls1_record_replay_check(SSL *s, DTLS1_BITMAP *bitmap, return 0; /* record previously received */ #endif - pq_64bit_assign(seq_num, &rcd_num); + pq_64bit_assign(&s->s3->rrec.seq_num, &rcd_num); pq_64bit_free(&rcd_num); pq_64bit_free(&tmp); return 1; @@ -1687,8 +1750,13 @@ static DTLS1_BITMAP *dtls1_get_bitmap(SSL *s, SSL3_RECORD *rr, if (rr->epoch == s->d1->r_epoch) return &s->d1->bitmap; - /* Only HM and ALERT messages can be from the next epoch */ + /* + * Only HM and ALERT messages can be from the next epoch and only if we + * have already processed all of the unprocessed records from the last + * epoch + */ else if (rr->epoch == (unsigned long)(s->d1->r_epoch + 1) && + s->d1->unprocessed_rcds.epoch != s->d1->r_epoch && (rr->type == SSL3_RT_HANDSHAKE || rr->type == SSL3_RT_ALERT)) { *is_next_epoch = 1; return &s->d1->next_bitmap; @@ -1776,6 +1844,12 @@ void dtls1_reset_seq_numbers(SSL *s, int rw) memset(&(s->d1->next_bitmap), 0x00, sizeof(DTLS1_BITMAP)); pq_64bit_init(&(s->d1->next_bitmap.map)); pq_64bit_init(&(s->d1->next_bitmap.max_seq_num)); + + /* + * We must not use any buffered messages received from the previous + * epoch + */ + dtls1_clear_received_buffer(s); } else { seq = s->s3->write_sequence; memcpy(s->d1->last_write_sequence, seq, diff --git a/crypto/openssl/ssl/d1_srvr.c b/crypto/openssl/ssl/d1_srvr.c index c5dac9fa2..7a8f8bbaa 100644 --- a/crypto/openssl/ssl/d1_srvr.c +++ b/crypto/openssl/ssl/d1_srvr.c @@ -242,7 +242,7 @@ int dtls1_accept(SSL *s) case SSL3_ST_SW_HELLO_REQ_B: s->shutdown = 0; - dtls1_clear_record_buffer(s); + dtls1_clear_sent_buffer(s); dtls1_start_timer(s); ret = dtls1_send_hello_request(s); if (ret <= 0) @@ -648,6 +648,7 @@ int dtls1_accept(SSL *s) /* next message is server hello */ s->d1->handshake_write_seq = 0; s->d1->next_handshake_write_seq = 0; + dtls1_clear_received_buffer(s); goto end; /* break; */ diff --git a/crypto/openssl/ssl/s2_lib.c b/crypto/openssl/ssl/s2_lib.c index 4386ac53b..6739afc9d 100644 --- a/crypto/openssl/ssl/s2_lib.c +++ b/crypto/openssl/ssl/s2_lib.c @@ -94,12 +94,14 @@ OPENSSL_GLOBAL SSL_CIPHER ssl2_ciphers[] = { 0, 128, 128, - SSL_ALL_CIPHERS, - SSL_ALL_STRENGTHS, - }, -/* RC4_128_EXPORT40_WITH_MD5 */ - { - 1, + SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS, + }, + +# if 0 +/* RC4_128_EXPORT40_WITH_MD5 */ + { + 1, SSL2_TXT_RC4_128_EXPORT40_WITH_MD5, SSL2_CK_RC4_128_EXPORT40_WITH_MD5, SSL_kRSA | SSL_aRSA | SSL_RC4 | SSL_MD5 | SSL_SSLV2, @@ -107,12 +109,14 @@ OPENSSL_GLOBAL SSL_CIPHER ssl2_ciphers[] = { SSL2_CF_5_BYTE_ENC, 40, 128, - SSL_ALL_CIPHERS, - SSL_ALL_STRENGTHS, - }, -/* RC2_128_CBC_WITH_MD5 */ - { - 1, + SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS, + }, +# endif + +/* RC2_128_CBC_WITH_MD5 */ + { + 1, SSL2_TXT_RC2_128_CBC_WITH_MD5, SSL2_CK_RC2_128_CBC_WITH_MD5, SSL_kRSA | SSL_aRSA | SSL_RC2 | SSL_MD5 | SSL_SSLV2, @@ -120,12 +124,14 @@ OPENSSL_GLOBAL SSL_CIPHER ssl2_ciphers[] = { 0, 128, 128, - SSL_ALL_CIPHERS, - SSL_ALL_STRENGTHS, - }, -/* RC2_128_CBC_EXPORT40_WITH_MD5 */ - { - 1, + SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS, + }, + +# if 0 +/* RC2_128_CBC_EXPORT40_WITH_MD5 */ + { + 1, SSL2_TXT_RC2_128_CBC_EXPORT40_WITH_MD5, SSL2_CK_RC2_128_CBC_EXPORT40_WITH_MD5, SSL_kRSA | SSL_aRSA | SSL_RC2 | SSL_MD5 | SSL_SSLV2, @@ -133,12 +139,14 @@ OPENSSL_GLOBAL SSL_CIPHER ssl2_ciphers[] = { SSL2_CF_5_BYTE_ENC, 40, 128, - SSL_ALL_CIPHERS, - SSL_ALL_STRENGTHS, - }, -/* IDEA_128_CBC_WITH_MD5 */ -# ifndef OPENSSL_NO_IDEA - { + SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS, + }, +# endif + +/* IDEA_128_CBC_WITH_MD5 */ +# ifndef OPENSSL_NO_IDEA + { 1, SSL2_TXT_IDEA_128_CBC_WITH_MD5, SSL2_CK_IDEA_128_CBC_WITH_MD5, @@ -148,12 +156,14 @@ OPENSSL_GLOBAL SSL_CIPHER ssl2_ciphers[] = { 128, 128, SSL_ALL_CIPHERS, - SSL_ALL_STRENGTHS, - }, -# endif -/* DES_64_CBC_WITH_MD5 */ - { - 1, + SSL_ALL_STRENGTHS, + }, +# endif + +# if 0 +/* DES_64_CBC_WITH_MD5 */ + { + 1, SSL2_TXT_DES_64_CBC_WITH_MD5, SSL2_CK_DES_64_CBC_WITH_MD5, SSL_kRSA | SSL_aRSA | SSL_DES | SSL_MD5 | SSL_SSLV2, @@ -161,12 +171,14 @@ OPENSSL_GLOBAL SSL_CIPHER ssl2_ciphers[] = { 0, 56, 56, - SSL_ALL_CIPHERS, - SSL_ALL_STRENGTHS, - }, -/* DES_192_EDE3_CBC_WITH_MD5 */ - { - 1, + SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS, + }, +# endif + +/* DES_192_EDE3_CBC_WITH_MD5 */ + { + 1, SSL2_TXT_DES_192_EDE3_CBC_WITH_MD5, SSL2_CK_DES_192_EDE3_CBC_WITH_MD5, SSL_kRSA | SSL_aRSA | SSL_3DES | SSL_MD5 | SSL_SSLV2, diff --git a/crypto/openssl/ssl/s2_srvr.c b/crypto/openssl/ssl/s2_srvr.c index ba8c8e885..48cc764fc 100644 --- a/crypto/openssl/ssl/s2_srvr.c +++ b/crypto/openssl/ssl/s2_srvr.c @@ -396,7 +396,7 @@ static int get_client_master_key(SSL *s) } cp = ssl2_get_cipher_by_char(p); - if (cp == NULL) { + if (cp == NULL || sk_SSL_CIPHER_find(s->session->ciphers, cp) < 0) { ssl2_return_error(s, SSL2_PE_NO_CIPHER); SSLerr(SSL_F_GET_CLIENT_MASTER_KEY, SSL_R_NO_CIPHER_MATCH); return (-1); @@ -687,8 +687,12 @@ static int get_client_hello(SSL *s) prio = cs; allow = cl; } + + /* Generate list of SSLv2 ciphers shared between client and server */ for (z = 0; z < sk_SSL_CIPHER_num(prio); z++) { - if (sk_SSL_CIPHER_find(allow, sk_SSL_CIPHER_value(prio, z)) < 0) { + const SSL_CIPHER *cp = sk_SSL_CIPHER_value(prio, z); + if ((cp->algorithms & SSL_SSLV2) == 0 || + sk_SSL_CIPHER_find(allow, cp) < 0) { (void)sk_SSL_CIPHER_delete(prio, z); z--; } @@ -697,6 +701,13 @@ static int get_client_hello(SSL *s) sk_SSL_CIPHER_free(s->session->ciphers); s->session->ciphers = prio; } + + /* Make sure we have at least one cipher in common */ + if (sk_SSL_CIPHER_num(s->session->ciphers) == 0) { + ssl2_return_error(s, SSL2_PE_NO_CIPHER); + SSLerr(SSL_F_GET_CLIENT_HELLO, SSL_R_NO_CIPHER_MATCH); + return -1; + } /* * s->session->ciphers should now have a list of ciphers that are on * both the client and server. This list is ordered by the order the diff --git a/crypto/openssl/ssl/s3_clnt.c b/crypto/openssl/ssl/s3_clnt.c index 8d035f7cf..62a48431d 100644 --- a/crypto/openssl/ssl/s3_clnt.c +++ b/crypto/openssl/ssl/s3_clnt.c @@ -931,6 +931,12 @@ int ssl3_get_server_certificate(SSL *s) goto f_err; } for (nc = 0; nc < llen;) { + if (nc + 3 > llen) { + al = SSL_AD_DECODE_ERROR; + SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE, + SSL_R_CERT_LENGTH_MISMATCH); + goto f_err; + } n2l3(p, l); if ((l + nc + 3) > llen) { al = SSL_AD_DECODE_ERROR; @@ -1627,6 +1633,11 @@ int ssl3_get_certificate_request(SSL *s) } for (nc = 0; nc < llen;) { + if (nc + 2 > llen) { + ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); + SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST, SSL_R_CA_DN_TOO_LONG); + goto err; + } n2s(p, l); if ((l + nc + 2) > llen) { if ((s->options & SSL_OP_NETSCAPE_CA_DN_BUG)) diff --git a/crypto/openssl/ssl/s3_pkt.c b/crypto/openssl/ssl/s3_pkt.c index ca0ef7064..8a9c92e6f 100644 --- a/crypto/openssl/ssl/s3_pkt.c +++ b/crypto/openssl/ssl/s3_pkt.c @@ -922,6 +922,13 @@ int ssl3_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek) return (ret); } + /* + * Reset the count of consecutive warning alerts if we've got a non-empty + * record that isn't an alert. + */ + if (rr->type != SSL3_RT_ALERT && rr->length != 0) + s->s3->alert_count = 0; + /* we now have a packet which can be read and processed */ if (s->s3->change_cipher_spec /* set when we receive ChangeCipherSpec, @@ -1121,6 +1128,14 @@ int ssl3_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek) if (alert_level == 1) { /* warning */ s->s3->warn_alert = alert_descr; + + s->s3->alert_count++; + if (s->s3->alert_count == MAX_WARN_ALERT_COUNT) { + al = SSL_AD_UNEXPECTED_MESSAGE; + SSLerr(SSL_F_SSL3_READ_BYTES, SSL_R_TOO_MANY_WARN_ALERTS); + goto f_err; + } + if (alert_descr == SSL_AD_CLOSE_NOTIFY) { s->shutdown |= SSL_RECEIVED_SHUTDOWN; return (0); diff --git a/crypto/openssl/ssl/s3_srvr.c b/crypto/openssl/ssl/s3_srvr.c index 8749ea243..0badd1d08 100644 --- a/crypto/openssl/ssl/s3_srvr.c +++ b/crypto/openssl/ssl/s3_srvr.c @@ -819,7 +819,7 @@ int ssl3_get_client_hello(SSL *s) session_length = *(p + SSL3_RANDOM_SIZE); - if (p + SSL3_RANDOM_SIZE + session_length + 1 >= d + n) { + if (SSL3_RANDOM_SIZE + session_length + 1 >= (d + n) - p) { al = SSL_AD_DECODE_ERROR; SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_TOO_SHORT); goto f_err; @@ -837,7 +837,7 @@ int ssl3_get_client_hello(SSL *s) /* get the session-id */ j = *(p++); - if (p + j > d + n) { + if ((d + n) - p < j) { al = SSL_AD_DECODE_ERROR; SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_TOO_SHORT); goto f_err; @@ -874,14 +874,14 @@ int ssl3_get_client_hello(SSL *s) if (s->version == DTLS1_VERSION || s->version == DTLS1_BAD_VER) { /* cookie stuff */ - if (p + 1 > d + n) { + if ((d + n) - p < 1) { al = SSL_AD_DECODE_ERROR; SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_TOO_SHORT); goto f_err; } cookie_len = *(p++); - if (p + cookie_len > d + n) { + if ((d + n ) - p < cookie_len) { al = SSL_AD_DECODE_ERROR; SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_TOO_SHORT); goto f_err; @@ -927,7 +927,7 @@ int ssl3_get_client_hello(SSL *s) p += cookie_len; } - if (p + 2 > d + n) { + if ((d + n ) - p < 2) { al = SSL_AD_DECODE_ERROR; SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_TOO_SHORT); goto f_err; @@ -941,7 +941,7 @@ int ssl3_get_client_hello(SSL *s) } /* i bytes of cipher data + 1 byte for compression length later */ - if ((p + i + 1) > (d + n)) { + if ((d + n) - p < i + 1) { /* not enough data */ al = SSL_AD_DECODE_ERROR; SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_MISMATCH); @@ -1007,7 +1007,7 @@ int ssl3_get_client_hello(SSL *s) /* compression */ i = *(p++); - if ((p + i) > (d + n)) { + if ((d + n) - p < i) { /* not enough data */ al = SSL_AD_DECODE_ERROR; SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_MISMATCH); @@ -1029,7 +1029,7 @@ int ssl3_get_client_hello(SSL *s) #ifndef OPENSSL_NO_TLSEXT /* TLS extensions */ if (s->version >= SSL3_VERSION) { - if (!ssl_parse_clienthello_tlsext(s, &p, d, n, &al)) { + if (!ssl_parse_clienthello_tlsext(s, &p, d + n, &al)) { /* 'al' set by ssl_parse_clienthello_tlsext */ SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_PARSE_TLSEXT); goto f_err; @@ -2526,6 +2526,12 @@ int ssl3_get_client_certificate(SSL *s) goto f_err; } for (nc = 0; nc < llen;) { + if (nc + 3 > llen) { + al = SSL_AD_DECODE_ERROR; + SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE, + SSL_R_CERT_LENGTH_MISMATCH); + goto f_err; + } n2l3(p, l); if ((l + nc + 3) > llen) { al = SSL_AD_DECODE_ERROR; diff --git a/crypto/openssl/ssl/ssl.h b/crypto/openssl/ssl/ssl.h index 2dcc3b8e9..b6aa2cdab 100644 --- a/crypto/openssl/ssl/ssl.h +++ b/crypto/openssl/ssl/ssl.h @@ -1803,6 +1803,7 @@ void ERR_load_SSL_strings(void); # define SSL_F_DTLS1_HANDLE_TIMEOUT 282 # define SSL_F_DTLS1_OUTPUT_CERT_CHAIN 255 # define SSL_F_DTLS1_PREPROCESS_FRAGMENT 277 +# define SSL_F_DTLS1_PROCESS_BUFFERED_RECORDS 424 # define SSL_F_DTLS1_PROCESS_OUT_OF_SEQ_MESSAGE 256 # define SSL_F_DTLS1_PROCESS_RECORD 257 # define SSL_F_DTLS1_READ_BYTES 258 @@ -2194,6 +2195,7 @@ void ERR_load_SSL_strings(void); # define SSL_R_TLSV1_UNSUPPORTED_EXTENSION 1110 # define SSL_R_TLS_CLIENT_CERT_REQ_WITH_ANON_CIPHER 232 # define SSL_R_TLS_INVALID_ECPOINTFORMAT_LIST 227 +# define SSL_R_TOO_MANY_WARN_ALERTS 409 # define SSL_R_TLS_PEER_DID_NOT_RESPOND_WITH_CERTIFICATE_LIST 233 # define SSL_R_TLS_RSA_ENCRYPTED_VALUE_LENGTH_IS_WRONG 234 # define SSL_R_TRIED_TO_USE_UNSUPPORTED_CIPHER 235 diff --git a/crypto/openssl/ssl/ssl3.h b/crypto/openssl/ssl/ssl3.h index 761a0e20b..eda992fce 100644 --- a/crypto/openssl/ssl/ssl3.h +++ b/crypto/openssl/ssl/ssl3.h @@ -491,6 +491,8 @@ typedef struct ssl3_state_st { char is_probably_safari; # endif /* !OPENSSL_NO_EC */ # endif /* !OPENSSL_NO_TLSEXT */ + /* Count of the number of consecutive warning alerts received */ + unsigned int alert_count; } SSL3_STATE; /* SSLv3 */ diff --git a/crypto/openssl/ssl/ssl_err.c b/crypto/openssl/ssl/ssl_err.c index 65c8f61e7..42b50cba5 100644 --- a/crypto/openssl/ssl/ssl_err.c +++ b/crypto/openssl/ssl/ssl_err.c @@ -1,6 +1,6 @@ /* ssl/ssl_err.c */ /* ==================================================================== - * Copyright (c) 1999-2011 The OpenSSL Project. All rights reserved. + * Copyright (c) 1999-2016 The OpenSSL Project. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -92,6 +92,8 @@ static ERR_STRING_DATA SSL_str_functs[] = { {ERR_FUNC(SSL_F_DTLS1_HANDLE_TIMEOUT), "DTLS1_HANDLE_TIMEOUT"}, {ERR_FUNC(SSL_F_DTLS1_OUTPUT_CERT_CHAIN), "DTLS1_OUTPUT_CERT_CHAIN"}, {ERR_FUNC(SSL_F_DTLS1_PREPROCESS_FRAGMENT), "DTLS1_PREPROCESS_FRAGMENT"}, + {ERR_FUNC(SSL_F_DTLS1_PROCESS_BUFFERED_RECORDS), + "DTLS1_PROCESS_BUFFERED_RECORDS"}, {ERR_FUNC(SSL_F_DTLS1_PROCESS_OUT_OF_SEQ_MESSAGE), "DTLS1_PROCESS_OUT_OF_SEQ_MESSAGE"}, {ERR_FUNC(SSL_F_DTLS1_PROCESS_RECORD), "DTLS1_PROCESS_RECORD"}, diff --git a/crypto/openssl/ssl/ssl_lib.c b/crypto/openssl/ssl/ssl_lib.c index 7182bd225..e70cfb5fc 100644 --- a/crypto/openssl/ssl/ssl_lib.c +++ b/crypto/openssl/ssl/ssl_lib.c @@ -1632,12 +1632,19 @@ SSL_CTX *SSL_CTX_new(SSL_METHOD *meth) /* * Default is to connect to non-RI servers. When RI is more widely * deployed might change this. - */ - ret->options |= SSL_OP_LEGACY_SERVER_CONNECT; - - return (ret); - err: - SSLerr(SSL_F_SSL_CTX_NEW, ERR_R_MALLOC_FAILURE); + */ + ret->options |= SSL_OP_LEGACY_SERVER_CONNECT; + + /* + * Disable SSLv2 by default, callers that want to enable SSLv2 will have to + * explicitly clear this option via either of SSL_CTX_clear_options() or + * SSL_clear_options(). + */ + ret->options |= SSL_OP_NO_SSLv2; + + return (ret); + err: + SSLerr(SSL_F_SSL_CTX_NEW, ERR_R_MALLOC_FAILURE); err2: if (ret != NULL) SSL_CTX_free(ret); diff --git a/crypto/openssl/ssl/ssl_locl.h b/crypto/openssl/ssl/ssl_locl.h index 038554f0d..ecb0814f3 100644 --- a/crypto/openssl/ssl/ssl_locl.h +++ b/crypto/openssl/ssl/ssl_locl.h @@ -247,6 +247,8 @@ # define DEC32(a) ((a)=((a)-1)&0xffffffffL) # define MAX_MAC_SIZE 20 /* up from 16 for SSLv3 */ +# define MAX_WARN_ALERT_COUNT 5 + /* * Define the Bitmasks for SSL_CIPHER.algorithms. * This bits are used packed as dense as possible. If new methods/ciphers @@ -910,7 +912,8 @@ int dtls1_retransmit_message(SSL *s, unsigned short seq, unsigned long frag_off, int *found); int dtls1_get_queue_priority(unsigned short seq, int is_ccs); int dtls1_retransmit_buffered_messages(SSL *s); -void dtls1_clear_record_buffer(SSL *s); +void dtls1_clear_received_buffer(SSL *s); +void dtls1_clear_sent_buffer(SSL *s); void dtls1_get_message_header(unsigned char *data, struct hm_header_st *msg_hdr); void dtls1_get_ccs_header(unsigned char *data, struct ccs_header_st *ccs_hdr); @@ -1022,7 +1025,7 @@ unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *p, unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *p, unsigned char *limit); int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **data, - unsigned char *d, int n, int *al); + unsigned char *limit, int *al); int ssl_parse_serverhello_tlsext(SSL *s, unsigned char **data, unsigned char *d, int n, int *al); int ssl_prepare_clienthello_tlsext(SSL *s); diff --git a/crypto/openssl/ssl/ssl_sess.c b/crypto/openssl/ssl/ssl_sess.c index 51c02dc9e..19e284a43 100644 --- a/crypto/openssl/ssl/ssl_sess.c +++ b/crypto/openssl/ssl/ssl_sess.c @@ -384,7 +384,7 @@ int ssl_get_prev_session(SSL *s, unsigned char *session_id, int len, if (len > SSL_MAX_SSL_SESSION_ID_LENGTH) goto err; - if (session_id + len > limit) { + if (limit - session_id < len) { fatal = 1; goto err; } diff --git a/crypto/openssl/ssl/t1_lib.c b/crypto/openssl/ssl/t1_lib.c index dd02c933c..d4ee92cc9 100644 --- a/crypto/openssl/ssl/t1_lib.c +++ b/crypto/openssl/ssl/t1_lib.c @@ -357,7 +357,7 @@ unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *p, * 10.8..10.8.3 (which don't work). */ static void ssl_check_for_safari(SSL *s, const unsigned char *data, - const unsigned char *d, int n) + const unsigned char *limit) { unsigned short type, size; static const unsigned char kSafariExtensionsBlock[] = { @@ -386,11 +386,11 @@ static void ssl_check_for_safari(SSL *s, const unsigned char *data, 0x02, 0x03, /* SHA-1/ECDSA */ }; - if (data >= (d + n - 2)) + if (limit - data <= 2) return; data += 2; - if (data > (d + n - 4)) + if (limit - data < 4) return; n2s(data, type); n2s(data, size); @@ -398,7 +398,7 @@ static void ssl_check_for_safari(SSL *s, const unsigned char *data, if (type != TLSEXT_TYPE_server_name) return; - if (data + size > d + n) + if (limit - data < size) return; data += size; @@ -406,7 +406,7 @@ static void ssl_check_for_safari(SSL *s, const unsigned char *data, const size_t len1 = sizeof(kSafariExtensionsBlock); const size_t len2 = sizeof(kSafariTLS12ExtensionsBlock); - if (data + len1 + len2 != d + n) + if (limit - data != (int)(len1 + len2)) return; if (memcmp(data, kSafariExtensionsBlock, len1) != 0) return; @@ -415,7 +415,7 @@ static void ssl_check_for_safari(SSL *s, const unsigned char *data, } else { const size_t len = sizeof(kSafariExtensionsBlock); - if (data + len != d + n) + if (limit - data != (int)(len)) return; if (memcmp(data, kSafariExtensionsBlock, len) != 0) return; @@ -425,8 +425,8 @@ static void ssl_check_for_safari(SSL *s, const unsigned char *data, } # endif /* !OPENSSL_NO_EC */ -int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, - int n, int *al) +int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, + unsigned char *limit, int *al) { unsigned short type; unsigned short size; @@ -439,24 +439,26 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, # ifndef OPENSSL_NO_EC if (s->options & SSL_OP_SAFARI_ECDHE_ECDSA_BUG) - ssl_check_for_safari(s, data, d, n); + ssl_check_for_safari(s, data, limit); # endif /* !OPENSSL_NO_EC */ - if (data >= (d + n - 2)) + if (data == limit) goto ri_check; + if (limit - data < 2) + goto err; + n2s(data, len); - if (data > (d + n - len)) - goto ri_check; + if (limit - data != len) + goto err; - while (data <= (d + n - 4)) { + while (limit - data >= 4) { n2s(data, type); n2s(data, size); - if (data + size > (d + n)) - goto ri_check; - + if (limit - data < size) + goto err; if (s->tlsext_debug_cb) s->tlsext_debug_cb(s, 0, type, data, size, s->tlsext_debug_arg); /*- @@ -580,6 +582,23 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, *al = SSL_AD_DECODE_ERROR; return 0; } + + /* + * We remove any OCSP_RESPIDs from a previous handshake + * to prevent unbounded memory growth - CVE-2016-6304 + */ + sk_OCSP_RESPID_pop_free(s->tlsext_ocsp_ids, + OCSP_RESPID_free); + if (dsize > 0) { + s->tlsext_ocsp_ids = sk_OCSP_RESPID_new_null(); + if (s->tlsext_ocsp_ids == NULL) { + *al = SSL_AD_INTERNAL_ERROR; + return 0; + } + } else { + s->tlsext_ocsp_ids = NULL; + } + while (dsize > 0) { OCSP_RESPID *id; int idsize; @@ -606,13 +625,6 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, *al = SSL_AD_DECODE_ERROR; return 0; } - if (!s->tlsext_ocsp_ids - && !(s->tlsext_ocsp_ids = - sk_OCSP_RESPID_new_null())) { - OCSP_RESPID_free(id); - *al = SSL_AD_INTERNAL_ERROR; - return 0; - } if (!sk_OCSP_RESPID_push(s->tlsext_ocsp_ids, id)) { OCSP_RESPID_free(id); *al = SSL_AD_INTERNAL_ERROR; @@ -672,6 +684,10 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, } return 1; + +err: + *al = SSL_AD_DECODE_ERROR; + return 0; } int ssl_parse_serverhello_tlsext(SSL *s, unsigned char **p, unsigned char *d, @@ -684,20 +700,20 @@ int ssl_parse_serverhello_tlsext(SSL *s, unsigned char **p, unsigned char *d, int tlsext_servername = 0; int renegotiate_seen = 0; - if (data >= (d + n - 2)) + if ((d + n) - data <= 2) goto ri_check; n2s(data, length); - if (data + length != d + n) { + if ((d + n) - data != length) { *al = SSL_AD_DECODE_ERROR; return 0; } - while (data <= (d + n - 4)) { + while ((d + n) - data >= 4) { n2s(data, type); n2s(data, size); - if (data + size > (d + n)) + if ((d + n) - data < size) goto ri_check; if (s->tlsext_debug_cb) @@ -960,29 +976,33 @@ int tls1_process_ticket(SSL *s, unsigned char *session_id, int len, /* Skip past DTLS cookie */ if (s->version == DTLS1_VERSION || s->version == DTLS1_BAD_VER) { i = *(p++); - p += i; - if (p >= limit) + + if (limit - p <= i) return -1; + + p += i; } /* Skip past cipher list */ n2s(p, i); - p += i; - if (p >= limit) + if (limit - p <= i) return -1; + p += i; + /* Skip past compression algorithm list */ i = *(p++); - p += i; - if (p > limit) + if (limit - p < i) return -1; + p += i; + /* Now at start of extensions */ - if ((p + 2) >= limit) + if (limit - p <= 2) return 1; n2s(p, i); - while ((p + 4) <= limit) { + while (limit - p >= 4) { unsigned short type, size; n2s(p, type); n2s(p, size); - if (p + size > limit) + if (limit - p < size) return 1; if (type == TLSEXT_TYPE_session_ticket) { /* @@ -1012,9 +1032,7 @@ static int tls_decrypt_ticket(SSL *s, const unsigned char *etick, HMAC_CTX hctx; EVP_CIPHER_CTX ctx; SSL_CTX *tctx = s->initial_ctx; - /* Need at least keyname + iv + some encrypted data */ - if (eticklen < 48) - goto tickerr; + /* Initialize session ticket encryption and HMAC contexts */ HMAC_CTX_init(&hctx); EVP_CIPHER_CTX_init(&ctx); @@ -1042,6 +1060,13 @@ static int tls_decrypt_ticket(SSL *s, const unsigned char *etick, * checks on ticket. */ mlen = HMAC_size(&hctx); + /* Sanity check ticket length: must exceed keyname + IV + HMAC */ + if (eticklen <= 16 + EVP_CIPHER_CTX_iv_length(&ctx) + mlen) { + HMAC_CTX_cleanup(&hctx); + EVP_CIPHER_CTX_cleanup(&ctx); + return 2; + } + eticklen -= mlen; /* Check HMAC of encrypted ticket */ HMAC_Update(&hctx, etick, eticklen); -- 2.42.0