From f08440f90b282a3c577f53c3dfc2be731576a8df Mon Sep 17 00:00:00 2001 From: delphij Date: Fri, 12 Jun 2015 07:23:55 +0000 Subject: [PATCH] Fix OpenSSL multiple vulnerabilities. Security: FreeBSD-SA-15:10.openssl Approved by: so git-svn-id: svn://svn.freebsd.org/base/releng/9.3@284295 ccf9f872-aa2e-dd11-9fc8-001c23d0bc1f --- UPDATING | 3 + crypto/openssl/crypto/bn/bn_print.c | 6 + crypto/openssl/crypto/cms/cms_smime.c | 2 +- crypto/openssl/crypto/ec/ec2_smpl.c | 3 +- crypto/openssl/crypto/ec/ec_check.c | 2 +- crypto/openssl/crypto/ec/ec_key.c | 2 +- crypto/openssl/crypto/ec/ec_lib.c | 10 +- crypto/openssl/crypto/ec/ecp_smpl.c | 3 +- crypto/openssl/crypto/ec/ectest.c | 24 ++-- crypto/openssl/crypto/objects/obj_dat.c | 3 + crypto/openssl/crypto/pkcs7/pk7_doit.c | 15 ++- crypto/openssl/crypto/x509/x509_vfy.c | 148 +++++++++++++++--------- crypto/openssl/ssl/d1_lib.c | 3 + crypto/openssl/ssl/s3_clnt.c | 32 +++++ crypto/openssl/ssl/s3_srvr.c | 24 ++-- crypto/openssl/ssl/ssl.h | 1 + crypto/openssl/ssl/ssl_err.c | 1 + crypto/openssl/ssl/ssl_locl.h | 1 + crypto/openssl/ssl/ssl_sess.c | 73 ++++++++++++ sys/conf/newvers.sh | 2 +- 20 files changed, 271 insertions(+), 87 deletions(-) diff --git a/UPDATING b/UPDATING index 81060c4d8..ade4d5303 100644 --- a/UPDATING +++ b/UPDATING @@ -11,6 +11,9 @@ handbook: Items affecting the ports and packages system can be found in /usr/ports/UPDATING. Please read that file before running portupgrade. +20150612: p16 FreeBSD-SA-15:10.openssl + Fix multiple vulnerabilities in OpenSSL. [SA-15:10] + 20150609: p15 FreeBSD-EN-15:06.file Updated base system file(1) to 5.22 to address multiple denial diff --git a/crypto/openssl/crypto/bn/bn_print.c b/crypto/openssl/crypto/bn/bn_print.c index 810dde34e..c11a68b27 100644 --- a/crypto/openssl/crypto/bn/bn_print.c +++ b/crypto/openssl/crypto/bn/bn_print.c @@ -71,6 +71,12 @@ char *BN_bn2hex(const BIGNUM *a) char *buf; char *p; + if (a->neg && BN_is_zero(a)) { + /* "-0" == 3 bytes including NULL terminator */ + buf = OPENSSL_malloc(3); + } else { + buf = OPENSSL_malloc(a->top * BN_BYTES * 2 + 2); + } buf=(char *)OPENSSL_malloc(a->top*BN_BYTES*2+2); if (buf == NULL) { diff --git a/crypto/openssl/crypto/cms/cms_smime.c b/crypto/openssl/crypto/cms/cms_smime.c index a3f67df08..c4c6baae8 100644 --- a/crypto/openssl/crypto/cms/cms_smime.c +++ b/crypto/openssl/crypto/cms/cms_smime.c @@ -141,7 +141,7 @@ static void do_free_upto(BIO *f, BIO *upto) BIO_free(f); f = tbio; } - while (f != upto); + while (f && f != upto); } else BIO_free_all(f); diff --git a/crypto/openssl/crypto/ec/ec2_smpl.c b/crypto/openssl/crypto/ec/ec2_smpl.c index c06b3b667..e02aa0eb4 100644 --- a/crypto/openssl/crypto/ec/ec2_smpl.c +++ b/crypto/openssl/crypto/ec/ec2_smpl.c @@ -657,7 +657,8 @@ int ec_GF2m_simple_oct2point(const EC_GROUP *group, EC_POINT *point, if (!EC_POINT_set_affine_coordinates_GF2m(group, point, x, y, ctx)) goto err; } - if (!EC_POINT_is_on_curve(group, point, ctx)) /* test required by X9.62 */ + /* test required by X9.62 */ + if (EC_POINT_is_on_curve(group, point, ctx) <= 0) { ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_POINT_IS_NOT_ON_CURVE); goto err; diff --git a/crypto/openssl/crypto/ec/ec_check.c b/crypto/openssl/crypto/ec/ec_check.c index 0e316b4b3..5ff7b2827 100644 --- a/crypto/openssl/crypto/ec/ec_check.c +++ b/crypto/openssl/crypto/ec/ec_check.c @@ -88,7 +88,7 @@ int EC_GROUP_check(const EC_GROUP *group, BN_CTX *ctx) ECerr(EC_F_EC_GROUP_CHECK, EC_R_UNDEFINED_GENERATOR); goto err; } - if (!EC_POINT_is_on_curve(group, group->generator, ctx)) + if (EC_POINT_is_on_curve(group, group->generator, ctx) <= 0) { ECerr(EC_F_EC_GROUP_CHECK, EC_R_POINT_IS_NOT_ON_CURVE); goto err; diff --git a/crypto/openssl/crypto/ec/ec_key.c b/crypto/openssl/crypto/ec/ec_key.c index 584b15598..4135789be 100644 --- a/crypto/openssl/crypto/ec/ec_key.c +++ b/crypto/openssl/crypto/ec/ec_key.c @@ -316,7 +316,7 @@ int EC_KEY_check_key(const EC_KEY *eckey) goto err; /* testing whether the pub_key is on the elliptic curve */ - if (!EC_POINT_is_on_curve(eckey->group, eckey->pub_key, ctx)) + if (EC_POINT_is_on_curve(eckey->group, eckey->pub_key, ctx) <= 0) { ECerr(EC_F_EC_KEY_CHECK_KEY, EC_R_POINT_IS_NOT_ON_CURVE); goto err; diff --git a/crypto/openssl/crypto/ec/ec_lib.c b/crypto/openssl/crypto/ec/ec_lib.c index e7d11ffe3..0e51399bf 100644 --- a/crypto/openssl/crypto/ec/ec_lib.c +++ b/crypto/openssl/crypto/ec/ec_lib.c @@ -1040,7 +1040,15 @@ int EC_POINT_is_at_infinity(const EC_GROUP *group, const EC_POINT *point) } -int EC_POINT_is_on_curve(const EC_GROUP *group, const EC_POINT *point, BN_CTX *ctx) +/* + * Check whether an EC_POINT is on the curve or not. Note that the return + * value for this function should NOT be treated as a boolean. Return values: + * 1: The point is on the curve + * 0: The point is not on the curve + * -1: An error occurred + */ +int EC_POINT_is_on_curve(const EC_GROUP *group, const EC_POINT *point, + BN_CTX *ctx) { if (group->meth->is_on_curve == 0) { diff --git a/crypto/openssl/crypto/ec/ecp_smpl.c b/crypto/openssl/crypto/ec/ecp_smpl.c index 1dc35d72a..507ebb9cd 100644 --- a/crypto/openssl/crypto/ec/ecp_smpl.c +++ b/crypto/openssl/crypto/ec/ecp_smpl.c @@ -983,7 +983,8 @@ int ec_GFp_simple_oct2point(const EC_GROUP *group, EC_POINT *point, if (!EC_POINT_set_affine_coordinates_GFp(group, point, x, y, ctx)) goto err; } - if (!EC_POINT_is_on_curve(group, point, ctx)) /* test required by X9.62 */ + /* test required by X9.62 */ + if (EC_POINT_is_on_curve(group, point, ctx) <= 0) { ECerr(EC_F_EC_GFP_SIMPLE_OCT2POINT, EC_R_POINT_IS_NOT_ON_CURVE); goto err; diff --git a/crypto/openssl/crypto/ec/ectest.c b/crypto/openssl/crypto/ec/ectest.c index 6148d553f..3d77b0aff 100644 --- a/crypto/openssl/crypto/ec/ectest.c +++ b/crypto/openssl/crypto/ec/ectest.c @@ -267,7 +267,7 @@ void prime_field_tests() if (!BN_hex2bn(&x, "D")) ABORT; if (!EC_POINT_set_compressed_coordinates_GFp(group, Q, x, 1, ctx)) ABORT; - if (!EC_POINT_is_on_curve(group, Q, ctx)) + if (EC_POINT_is_on_curve(group, Q, ctx) <= 0) { if (!EC_POINT_get_affine_coordinates_GFp(group, Q, x, y, ctx)) ABORT; fprintf(stderr, "Point is not on curve: x = 0x"); @@ -363,7 +363,7 @@ void prime_field_tests() if (!BN_hex2bn(&x, "4A96B5688EF573284664698968C38BB913CBFC82")) ABORT; if (!BN_hex2bn(&y, "23a628553168947d59dcc912042351377ac5fb32")) ABORT; if (!EC_POINT_set_affine_coordinates_GFp(group, P, x, y, ctx)) ABORT; - if (!EC_POINT_is_on_curve(group, P, ctx)) ABORT; + if (EC_POINT_is_on_curve(group, P, ctx) <= 0) ABORT; if (!BN_hex2bn(&z, "0100000000000000000001F4C8F927AED3CA752257")) ABORT; if (!EC_GROUP_set_generator(group, P, z, BN_value_one())) ABORT; @@ -407,7 +407,7 @@ void prime_field_tests() if (!BN_hex2bn(&x, "188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012")) ABORT; if (!EC_POINT_set_compressed_coordinates_GFp(group, P, x, 1, ctx)) ABORT; - if (!EC_POINT_is_on_curve(group, P, ctx)) ABORT; + if (EC_POINT_is_on_curve(group, P, ctx) <= 0) ABORT; if (!BN_hex2bn(&z, "FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831")) ABORT; if (!EC_GROUP_set_generator(group, P, z, BN_value_one())) ABORT; @@ -453,7 +453,7 @@ void prime_field_tests() if (!BN_hex2bn(&x, "B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21")) ABORT; if (!EC_POINT_set_compressed_coordinates_GFp(group, P, x, 0, ctx)) ABORT; - if (!EC_POINT_is_on_curve(group, P, ctx)) ABORT; + if (EC_POINT_is_on_curve(group, P, ctx) <= 0) ABORT; if (!BN_hex2bn(&z, "FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D")) ABORT; if (!EC_GROUP_set_generator(group, P, z, BN_value_one())) ABORT; @@ -499,7 +499,7 @@ void prime_field_tests() if (!BN_hex2bn(&x, "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296")) ABORT; if (!EC_POINT_set_compressed_coordinates_GFp(group, P, x, 1, ctx)) ABORT; - if (!EC_POINT_is_on_curve(group, P, ctx)) ABORT; + if (EC_POINT_is_on_curve(group, P, ctx) <= 0) ABORT; if (!BN_hex2bn(&z, "FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E" "84F3B9CAC2FC632551")) ABORT; if (!EC_GROUP_set_generator(group, P, z, BN_value_one())) ABORT; @@ -550,7 +550,7 @@ void prime_field_tests() if (!BN_hex2bn(&x, "AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B" "9859F741E082542A385502F25DBF55296C3A545E3872760AB7")) ABORT; if (!EC_POINT_set_compressed_coordinates_GFp(group, P, x, 1, ctx)) ABORT; - if (!EC_POINT_is_on_curve(group, P, ctx)) ABORT; + if (EC_POINT_is_on_curve(group, P, ctx) <= 0) ABORT; if (!BN_hex2bn(&z, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" "FFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973")) ABORT; if (!EC_GROUP_set_generator(group, P, z, BN_value_one())) ABORT; @@ -606,7 +606,7 @@ void prime_field_tests() "B521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B" "3C1856A429BF97E7E31C2E5BD66")) ABORT; if (!EC_POINT_set_compressed_coordinates_GFp(group, P, x, 0, ctx)) ABORT; - if (!EC_POINT_is_on_curve(group, P, ctx)) ABORT; + if (EC_POINT_is_on_curve(group, P, ctx) <= 0) ABORT; if (!BN_hex2bn(&z, "1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" "FFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5" "C9B8899C47AEBB6FB71E91386409")) ABORT; @@ -651,7 +651,7 @@ void prime_field_tests() if (!EC_POINT_copy(Q, P)) ABORT; if (EC_POINT_is_at_infinity(group, Q)) ABORT; if (!EC_POINT_dbl(group, P, P, ctx)) ABORT; - if (!EC_POINT_is_on_curve(group, P, ctx)) ABORT; + if (EC_POINT_is_on_curve(group, P, ctx) <= 0) ABORT; if (!EC_POINT_invert(group, Q, ctx)) ABORT; /* P = -2Q */ if (!EC_POINT_add(group, R, P, Q, ctx)) ABORT; @@ -764,7 +764,7 @@ void prime_field_tests() #define CHAR2_CURVE_TEST_INTERNAL(_name, _p, _a, _b, _x, _y, _y_bit, _order, _cof, _degree, _variable) \ if (!BN_hex2bn(&x, _x)) ABORT; \ if (!EC_POINT_set_compressed_coordinates_GF2m(group, P, x, _y_bit, ctx)) ABORT; \ - if (!EC_POINT_is_on_curve(group, P, ctx)) ABORT; \ + if (EC_POINT_is_on_curve(group, P, ctx) <= 0) ABORT; \ if (!BN_hex2bn(&z, _order)) ABORT; \ if (!BN_hex2bn(&cof, _cof)) ABORT; \ if (!EC_GROUP_set_generator(group, P, z, cof)) ABORT; \ @@ -782,7 +782,7 @@ void prime_field_tests() if (!BN_hex2bn(&x, _x)) ABORT; \ if (!BN_hex2bn(&y, _y)) ABORT; \ if (!EC_POINT_set_affine_coordinates_GF2m(group, P, x, y, ctx)) ABORT; \ - if (!EC_POINT_is_on_curve(group, P, ctx)) ABORT; \ + if (EC_POINT_is_on_curve(group, P, ctx) <= 0) ABORT; \ if (!BN_hex2bn(&z, _order)) ABORT; \ if (!BN_hex2bn(&cof, _cof)) ABORT; \ if (!EC_GROUP_set_generator(group, P, z, cof)) ABORT; \ @@ -895,7 +895,7 @@ void char2_field_tests() if (!BN_hex2bn(&y, "8")) ABORT; if (!EC_POINT_set_affine_coordinates_GF2m(group, Q, x, y, ctx)) ABORT; #endif - if (!EC_POINT_is_on_curve(group, Q, ctx)) + if (EC_POINT_is_on_curve(group, Q, ctx) <= 0) { /* Change test based on whether binary point compression is enabled or not. */ #ifdef OPENSSL_EC_BIN_PT_COMP @@ -1134,7 +1134,7 @@ void char2_field_tests() if (!EC_POINT_copy(Q, P)) ABORT; if (EC_POINT_is_at_infinity(group, Q)) ABORT; if (!EC_POINT_dbl(group, P, P, ctx)) ABORT; - if (!EC_POINT_is_on_curve(group, P, ctx)) ABORT; + if (EC_POINT_is_on_curve(group, P, ctx) <= 0) ABORT; if (!EC_POINT_invert(group, Q, ctx)) ABORT; /* P = -2Q */ if (!EC_POINT_add(group, R, P, Q, ctx)) ABORT; diff --git a/crypto/openssl/crypto/objects/obj_dat.c b/crypto/openssl/crypto/objects/obj_dat.c index cf5ba2a1c..9e80abda9 100644 --- a/crypto/openssl/crypto/objects/obj_dat.c +++ b/crypto/openssl/crypto/objects/obj_dat.c @@ -377,6 +377,9 @@ int OBJ_obj2nid(const ASN1_OBJECT *a) if (a->nid != 0) return(a->nid); + if (a->length == 0) + return NID_undef; + if (added != NULL) { ad.type=ADDED_DATA; diff --git a/crypto/openssl/crypto/pkcs7/pk7_doit.c b/crypto/openssl/crypto/pkcs7/pk7_doit.c index ec3096e53..839c5cac2 100644 --- a/crypto/openssl/crypto/pkcs7/pk7_doit.c +++ b/crypto/openssl/crypto/pkcs7/pk7_doit.c @@ -410,6 +410,12 @@ BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, X509 *pcert) goto err; } + /* Detached content must be supplied via in_bio instead. */ + if (data_body == NULL && in_bio == NULL) { + PKCS7err(PKCS7_F_PKCS7_DATADECODE, PKCS7_R_NO_CONTENT); + goto err; + } + /* We will be checking the signature */ if (md_sk != NULL) { @@ -587,12 +593,9 @@ BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, X509 *pcert) } #if 1 - if (PKCS7_is_detached(p7) || (in_bio != NULL)) - { - bio=in_bio; - } - else - { + if (in_bio != NULL) { + bio = in_bio; + } else { #if 0 bio=BIO_new(BIO_s_mem()); /* We need to set this so that when we have read all diff --git a/crypto/openssl/crypto/x509/x509_vfy.c b/crypto/openssl/crypto/x509/x509_vfy.c index b92758480..d0d9b5618 100644 --- a/crypto/openssl/crypto/x509/x509_vfy.c +++ b/crypto/openssl/crypto/x509/x509_vfy.c @@ -1040,82 +1040,120 @@ int X509_cmp_current_time(ASN1_TIME *ctm) } int X509_cmp_time(ASN1_TIME *ctm, time_t *cmp_time) - { +{ char *str; ASN1_TIME atm; long offset; - char buff1[24],buff2[24],*p; - int i,j; - - p=buff1; - i=ctm->length; - str=(char *)ctm->data; - if (ctm->type == V_ASN1_UTCTIME) - { - if ((i < 11) || (i > 17)) return 0; - memcpy(p,str,10); - p+=10; - str+=10; - } - else - { - if (i < 13) return 0; - memcpy(p,str,12); - p+=12; - str+=12; + char buff1[24], buff2[24], *p; + int i, j, remaining; + + p = buff1; + remaining = ctm->length; + str = (char *)ctm->data; + /* + * Note that the following (historical) code allows much more slack in the + * time format than RFC5280. In RFC5280, the representation is fixed: + * UTCTime: YYMMDDHHMMSSZ + * GeneralizedTime: YYYYMMDDHHMMSSZ + */ + if (ctm->type == V_ASN1_UTCTIME) { + /* YYMMDDHHMM[SS]Z or YYMMDDHHMM[SS](+-)hhmm */ + int min_length = sizeof("YYMMDDHHMMZ") - 1; + int max_length = sizeof("YYMMDDHHMMSS+hhmm") - 1; + if (remaining < min_length || remaining > max_length) + return 0; + memcpy(p, str, 10); + p += 10; + str += 10; + remaining -= 10; + } else { + /* YYYYMMDDHHMM[SS[.fff]]Z or YYYYMMDDHHMM[SS[.f[f[f]]]](+-)hhmm */ + int min_length = sizeof("YYYYMMDDHHMMZ") - 1; + int max_length = sizeof("YYYYMMDDHHMMSS.fff+hhmm") - 1; + if (remaining < min_length || remaining > max_length) + return 0; + memcpy(p, str, 12); + p += 12; + str += 12; + remaining -= 12; } - if ((*str == 'Z') || (*str == '-') || (*str == '+')) - { *(p++)='0'; *(p++)='0'; } - else - { - *(p++)= *(str++); - *(p++)= *(str++); - /* Skip any fractional seconds... */ - if (*str == '.') - { + if ((*str == 'Z') || (*str == '-') || (*str == '+')) { + *(p++) = '0'; + *(p++) = '0'; + } else { + /* SS (seconds) */ + if (remaining < 2) + return 0; + *(p++) = *(str++); + *(p++) = *(str++); + remaining -= 2; + /* + * Skip any (up to three) fractional seconds... + * TODO(emilia): in RFC5280, fractional seconds are forbidden. + * Can we just kill them altogether? + */ + if (remaining && *str == '.') { str++; - while ((*str >= '0') && (*str <= '9')) str++; + remaining--; + for (i = 0; i < 3 && remaining; i++, str++, remaining--) { + if (*str < '0' || *str > '9') + break; } - } - *(p++)='Z'; - *(p++)='\0'; - if (*str == 'Z') - offset=0; - else - { + } + *(p++) = 'Z'; + *(p++) = '\0'; + + /* We now need either a terminating 'Z' or an offset. */ + if (!remaining) + return 0; + if (*str == 'Z') { + if (remaining != 1) + return 0; + offset = 0; + } else { + /* (+-)HHMM */ if ((*str != '+') && (*str != '-')) return 0; - offset=((str[1]-'0')*10+(str[2]-'0'))*60; - offset+=(str[3]-'0')*10+(str[4]-'0'); + /* Historical behaviour: the (+-)hhmm offset is forbidden in RFC5280. */ + if (remaining != 5) + return 0; + if (str[1] < '0' || str[1] > '9' || str[2] < '0' || str[2] > '9' || + str[3] < '0' || str[3] > '9' || str[4] < '0' || str[4] > '9') + return 0; + offset = ((str[1] - '0') * 10 + (str[2] - '0')) * 60; + offset += (str[3] - '0') * 10 + (str[4] - '0'); if (*str == '-') - offset= -offset; + offset = -offset; } - atm.type=ctm->type; - atm.length=sizeof(buff2); - atm.data=(unsigned char *)buff2; + atm.type = ctm->type; + atm.length = sizeof(buff2); + atm.data = (unsigned char *)buff2; - if (X509_time_adj(&atm, offset*60, cmp_time) == NULL) + if (X509_time_adj(&atm, offset * 60, cmp_time) == NULL) return 0; - if (ctm->type == V_ASN1_UTCTIME) - { - i=(buff1[0]-'0')*10+(buff1[1]-'0'); - if (i < 50) i+=100; /* cf. RFC 2459 */ - j=(buff2[0]-'0')*10+(buff2[1]-'0'); - if (j < 50) j+=100; - - if (i < j) return -1; - if (i > j) return 1; + if (ctm->type == V_ASN1_UTCTIME) { + i = (buff1[0] - '0') * 10 + (buff1[1] - '0'); + if (i < 50) + i += 100; /* cf. RFC 2459 */ + j = (buff2[0] - '0') * 10 + (buff2[1] - '0'); + if (j < 50) + j += 100; + + if (i < j) + return -1; + if (i > j) + return 1; } - i=strcmp(buff1,buff2); + i = strcmp(buff1, buff2); if (i == 0) /* wait a second then return younger :-) */ return -1; else return i; - } +} ASN1_TIME *X509_gmtime_adj(ASN1_TIME *s, long adj) { diff --git a/crypto/openssl/ssl/d1_lib.c b/crypto/openssl/ssl/d1_lib.c index 8427798bb..245fb3baa 100644 --- a/crypto/openssl/ssl/d1_lib.c +++ b/crypto/openssl/ssl/d1_lib.c @@ -507,6 +507,9 @@ int dtls1_listen(SSL *s, struct sockaddr *client) { int ret; + /* Ensure there is no state left over from a previous invocation */ + SSL_clear(s); + SSL_set_options(s, SSL_OP_COOKIE_EXCHANGE); s->d1->listen = 1; diff --git a/crypto/openssl/ssl/s3_clnt.c b/crypto/openssl/ssl/s3_clnt.c index 3352e2d19..b0dbcd618 100644 --- a/crypto/openssl/ssl/s3_clnt.c +++ b/crypto/openssl/ssl/s3_clnt.c @@ -1805,6 +1805,38 @@ int ssl3_get_new_session_ticket(SSL *s) } p=d=(unsigned char *)s->init_msg; + + if (s->session->session_id_length > 0) { + int i = s->session_ctx->session_cache_mode; + SSL_SESSION *new_sess; + /* + * We reused an existing session, so we need to replace it with a new + * one + */ + if (i & SSL_SESS_CACHE_CLIENT) { + /* + * Remove the old session from the cache + */ + if (i & SSL_SESS_CACHE_NO_INTERNAL_STORE) { + if (s->session_ctx->remove_session_cb != NULL) + s->session_ctx->remove_session_cb(s->session_ctx, + s->session); + } else { + /* We carry on if this fails */ + SSL_CTX_remove_session(s->session_ctx, s->session); + } + } + + if ((new_sess = ssl_session_dup(s->session, 0)) == 0) { + al = SSL_AD_INTERNAL_ERROR; + SSLerr(SSL_F_SSL3_GET_NEW_SESSION_TICKET, ERR_R_MALLOC_FAILURE); + goto f_err; + } + + SSL_SESSION_free(s->session); + s->session = new_sess; + } + n2l(p, s->session->tlsext_tick_lifetime_hint); n2s(p, ticklen); /* ticket_lifetime_hint + ticket_length + ticket */ diff --git a/crypto/openssl/ssl/s3_srvr.c b/crypto/openssl/ssl/s3_srvr.c index 496ae80a2..d5364c4a5 100644 --- a/crypto/openssl/ssl/s3_srvr.c +++ b/crypto/openssl/ssl/s3_srvr.c @@ -2012,6 +2012,7 @@ int ssl3_get_client_key_exchange(SSL *s) int padl, outl; krb5_timestamp authtime = 0; krb5_ticket_times ttimes; + int kerr = 0; EVP_CIPHER_CTX_init(&ciph_ctx); @@ -2124,26 +2125,30 @@ int ssl3_get_client_key_exchange(SSL *s) { SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, SSL_R_DECRYPTION_FAILED); - goto err; + kerr = 1; + goto kclean; } if (outl > SSL_MAX_MASTER_KEY_LENGTH) { SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, SSL_R_DATA_LENGTH_TOO_LONG); - goto err; + kerr = 1; + goto kclean; } if (!EVP_DecryptFinal_ex(&ciph_ctx,&(pms[outl]),&padl)) { SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, SSL_R_DECRYPTION_FAILED); - goto err; + kerr = 1; + goto kclean; } outl += padl; if (outl > SSL_MAX_MASTER_KEY_LENGTH) { SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, SSL_R_DATA_LENGTH_TOO_LONG); - goto err; + kerr = 1; + goto kclean; } if (!((pms[0] == (s->client_version>>8)) && (pms[1] == (s->client_version & 0xff)))) { @@ -2159,7 +2164,8 @@ int ssl3_get_client_key_exchange(SSL *s) { SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, SSL_AD_DECODE_ERROR); - goto err; + kerr = 1; + goto kclean; } } @@ -2185,8 +2191,12 @@ int ssl3_get_client_key_exchange(SSL *s) ** kssl_ctx = kssl_ctx_free(kssl_ctx); ** if (s->kssl_ctx) s->kssl_ctx = NULL; */ - } - else + + kclean: + OPENSSL_cleanse(pms, sizeof(pms)); + if (kerr) + goto err; + } else #endif /* OPENSSL_NO_KRB5 */ #ifndef OPENSSL_NO_ECDH diff --git a/crypto/openssl/ssl/ssl.h b/crypto/openssl/ssl/ssl.h index 8420100cf..0521777a3 100644 --- a/crypto/openssl/ssl/ssl.h +++ b/crypto/openssl/ssl/ssl.h @@ -1851,6 +1851,7 @@ void ERR_load_SSL_strings(void); #define SSL_F_SSL_READ 223 #define SSL_F_SSL_RSA_PRIVATE_DECRYPT 187 #define SSL_F_SSL_RSA_PUBLIC_ENCRYPT 188 +#define SSL_F_SSL_SESSION_DUP 348 #define SSL_F_SSL_SESSION_NEW 189 #define SSL_F_SSL_SESSION_PRINT_FP 190 #define SSL_F_SSL_SESS_CERT_NEW 225 diff --git a/crypto/openssl/ssl/ssl_err.c b/crypto/openssl/ssl/ssl_err.c index 2896f58cb..ec02ac4aa 100644 --- a/crypto/openssl/ssl/ssl_err.c +++ b/crypto/openssl/ssl/ssl_err.c @@ -233,6 +233,7 @@ static ERR_STRING_DATA SSL_str_functs[]= {ERR_FUNC(SSL_F_SSL_READ), "SSL_read"}, {ERR_FUNC(SSL_F_SSL_RSA_PRIVATE_DECRYPT), "SSL_RSA_PRIVATE_DECRYPT"}, {ERR_FUNC(SSL_F_SSL_RSA_PUBLIC_ENCRYPT), "SSL_RSA_PUBLIC_ENCRYPT"}, +{ERR_FUNC(SSL_F_SSL_SESSION_DUP), "ssl_session_dup"}, {ERR_FUNC(SSL_F_SSL_SESSION_NEW), "SSL_SESSION_new"}, {ERR_FUNC(SSL_F_SSL_SESSION_PRINT_FP), "SSL_SESSION_print_fp"}, {ERR_FUNC(SSL_F_SSL_SESS_CERT_NEW), "SSL_SESS_CERT_NEW"}, diff --git a/crypto/openssl/ssl/ssl_locl.h b/crypto/openssl/ssl/ssl_locl.h index d4b642c5a..f7242f21e 100644 --- a/crypto/openssl/ssl/ssl_locl.h +++ b/crypto/openssl/ssl/ssl_locl.h @@ -731,6 +731,7 @@ void ssl_sess_cert_free(SESS_CERT *sc); int ssl_set_peer_cert_type(SESS_CERT *c, int type); int ssl_get_new_session(SSL *s, int session); int ssl_get_prev_session(SSL *s, unsigned char *session,int len, const unsigned char *limit); +SSL_SESSION *ssl_session_dup(SSL_SESSION *src, int ticket); int ssl_cipher_id_cmp(const SSL_CIPHER *a,const SSL_CIPHER *b); int ssl_cipher_ptr_id_cmp(const SSL_CIPHER * const *ap, const SSL_CIPHER * const *bp); diff --git a/crypto/openssl/ssl/ssl_sess.c b/crypto/openssl/ssl/ssl_sess.c index e7802e1d9..e12e1b02c 100644 --- a/crypto/openssl/ssl/ssl_sess.c +++ b/crypto/openssl/ssl/ssl_sess.c @@ -132,6 +132,79 @@ SSL_SESSION *SSL_SESSION_new(void) return(ss); } +/* + * Create a new SSL_SESSION and duplicate the contents of |src| into it. If + * ticket == 0 then no ticket information is duplicated, otherwise it is. + */ +SSL_SESSION *ssl_session_dup(SSL_SESSION *src, int ticket) +{ + SSL_SESSION *dest; + + dest = OPENSSL_malloc(sizeof(*src)); + if (dest == NULL) { + goto err; + } + memcpy(dest, src, sizeof(*dest)); + + /* + * Set the various pointers to NULL so that we can call SSL_SESSION_free in + * the case of an error whilst halfway through constructing dest + */ + dest->ciphers = NULL; +#ifndef OPENSSL_NO_TLSEXT + dest->tlsext_hostname = NULL; +#endif + dest->tlsext_tick = NULL; + memset(&dest->ex_data, 0, sizeof(dest->ex_data)); + + /* We deliberately don't copy the prev and next pointers */ + dest->prev = NULL; + dest->next = NULL; + + dest->references = 1; + + if (src->sess_cert != NULL) + CRYPTO_add(&src->sess_cert->references, 1, CRYPTO_LOCK_SSL_SESS_CERT); + + if (src->peer != NULL) + CRYPTO_add(&src->peer->references, 1, CRYPTO_LOCK_X509); + + if(src->ciphers != NULL) { + dest->ciphers = sk_SSL_CIPHER_dup(src->ciphers); + if (dest->ciphers == NULL) + goto err; + } + + if (!CRYPTO_dup_ex_data(CRYPTO_EX_INDEX_SSL_SESSION, + &dest->ex_data, &src->ex_data)) { + goto err; + } + +#ifndef OPENSSL_NO_TLSEXT + if (src->tlsext_hostname) { + dest->tlsext_hostname = BUF_strdup(src->tlsext_hostname); + if (dest->tlsext_hostname == NULL) { + goto err; + } + } +#endif + + if (ticket != 0) { + dest->tlsext_tick = BUF_memdup(src->tlsext_tick, src->tlsext_ticklen); + if(dest->tlsext_tick == NULL) + goto err; + } else { + dest->tlsext_tick_lifetime_hint = 0; + dest->tlsext_ticklen = 0; + } + + return dest; +err: + SSLerr(SSL_F_SSL_SESSION_DUP, ERR_R_MALLOC_FAILURE); + SSL_SESSION_free(dest); + return NULL; +} + const unsigned char *SSL_SESSION_get_id(const SSL_SESSION *s, unsigned int *len) { if(len) diff --git a/sys/conf/newvers.sh b/sys/conf/newvers.sh index 46bbbb465..7561a45f6 100644 --- a/sys/conf/newvers.sh +++ b/sys/conf/newvers.sh @@ -32,7 +32,7 @@ TYPE="FreeBSD" REVISION="9.3" -BRANCH="RELEASE-p15" +BRANCH="RELEASE-p16" if [ "X${BRANCH_OVERRIDE}" != "X" ]; then BRANCH=${BRANCH_OVERRIDE} fi -- 2.42.0