From b3734bf3e437fc8ed8ef49b74aa214df32b5d01d 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/10.1@284295 ccf9f872-aa2e-dd11-9fc8-001c23d0bc1f --- UPDATING | 3 + crypto/openssl/apps/dhparam.c | 4 +- crypto/openssl/apps/gendh.c | 2 +- crypto/openssl/apps/s_server.c | 103 ++++++----- crypto/openssl/crypto/bio/bio_lib.c | 8 +- crypto/openssl/crypto/bn/bn_gf2m.c | 16 +- crypto/openssl/crypto/bn/bn_print.c | 7 +- crypto/openssl/crypto/buffer/buffer.c | 2 +- crypto/openssl/crypto/cms/cms_smime.c | 2 +- crypto/openssl/crypto/ec/ec2_oct.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_oct.c | 3 +- crypto/openssl/crypto/ec/ectest.c | 24 +-- crypto/openssl/crypto/evp/e_aes.c | 5 +- crypto/openssl/crypto/evp/e_rc4_hmac_md5.c | 3 +- crypto/openssl/crypto/evp/evp.h | 1 - crypto/openssl/crypto/hmac/hmac.c | 1 + crypto/openssl/crypto/modes/gcm128.c | 2 +- crypto/openssl/crypto/objects/obj_dat.c | 3 + crypto/openssl/crypto/pkcs12/p12_mutl.c | 4 +- crypto/openssl/crypto/pkcs7/pk7_doit.c | 8 +- crypto/openssl/crypto/x509/x509_vfy.c | 150 ++++++++++------ crypto/openssl/crypto/x509/x509type.c | 3 - crypto/openssl/doc/apps/dhparam.pod | 13 +- .../doc/ssl/SSL_CTX_set_tmp_dh_callback.pod | 106 +++++------ crypto/openssl/ssl/d1_both.c | 33 +++- crypto/openssl/ssl/d1_lib.c | 3 + crypto/openssl/ssl/d1_pkt.c | 2 +- crypto/openssl/ssl/s3_cbc.c | 2 +- crypto/openssl/ssl/s3_clnt.c | 165 +++++++++++++----- crypto/openssl/ssl/s3_srvr.c | 21 ++- crypto/openssl/ssl/ssl.h | 2 + crypto/openssl/ssl/ssl_err.c | 2 + crypto/openssl/ssl/ssl_locl.h | 1 + crypto/openssl/ssl/ssl_sess.c | 124 +++++++++++++ crypto/openssl/ssl/t1_lib.c | 133 +++++--------- sys/conf/newvers.sh | 2 +- 39 files changed, 619 insertions(+), 361 deletions(-) diff --git a/UPDATING b/UPDATING index f4ec148eb..d06f8a99b 100644 --- a/UPDATING +++ b/UPDATING @@ -16,6 +16,9 @@ from older versions of FreeBSD, try WITHOUT_CLANG to bootstrap to the tip of stable/10, and then rebuild without this option. The bootstrap process from older version of current is a bit fragile. +20150612: p12 FreeBSD-SA-15:10.openssl + Fix multiple vulnerabilities in OpenSSL. [SA-15:10] + 20150609: p11 FreeBSD-EN-15:06.file FreeBSD-EN-15:07.zfs diff --git a/crypto/openssl/apps/dhparam.c b/crypto/openssl/apps/dhparam.c index 1297d6fb5..b0c05befc 100644 --- a/crypto/openssl/apps/dhparam.c +++ b/crypto/openssl/apps/dhparam.c @@ -130,7 +130,7 @@ #undef PROG #define PROG dhparam_main -#define DEFBITS 512 +#define DEFBITS 2048 /* -inform arg - input format - default PEM (DER or PEM) * -outform arg - output format - default PEM @@ -253,7 +253,7 @@ bad: BIO_printf(bio_err," -C Output C code\n"); BIO_printf(bio_err," -2 generate parameters using 2 as the generator value\n"); BIO_printf(bio_err," -5 generate parameters using 5 as the generator value\n"); - BIO_printf(bio_err," numbits number of bits in to generate (default 512)\n"); + BIO_printf(bio_err," numbits number of bits in to generate (default 2048)\n"); #ifndef OPENSSL_NO_ENGINE BIO_printf(bio_err," -engine e use engine e, possibly a hardware device.\n"); #endif diff --git a/crypto/openssl/apps/gendh.c b/crypto/openssl/apps/gendh.c index 4ec776ba9..8df8c62f8 100644 --- a/crypto/openssl/apps/gendh.c +++ b/crypto/openssl/apps/gendh.c @@ -78,7 +78,7 @@ #include #include -#define DEFBITS 512 +#define DEFBITS 2048 #undef PROG #define PROG gendh_main diff --git a/crypto/openssl/apps/s_server.c b/crypto/openssl/apps/s_server.c index f47328ab3..7586314d6 100644 --- a/crypto/openssl/apps/s_server.c +++ b/crypto/openssl/apps/s_server.c @@ -214,7 +214,7 @@ static int generate_session_id(const SSL *ssl, unsigned char *id, unsigned int *id_len); #ifndef OPENSSL_NO_DH static DH *load_dh_param(const char *dhfile); -static DH *get_dh512(void); +static DH *get_dh2048(void); #endif #ifdef MONOLITH @@ -222,29 +222,49 @@ static void s_server_init(void); #endif #ifndef OPENSSL_NO_DH -static unsigned char dh512_p[]={ - 0xDA,0x58,0x3C,0x16,0xD9,0x85,0x22,0x89,0xD0,0xE4,0xAF,0x75, - 0x6F,0x4C,0xCA,0x92,0xDD,0x4B,0xE5,0x33,0xB8,0x04,0xFB,0x0F, - 0xED,0x94,0xEF,0x9C,0x8A,0x44,0x03,0xED,0x57,0x46,0x50,0xD3, - 0x69,0x99,0xDB,0x29,0xD7,0x76,0x27,0x6B,0xA2,0xD3,0xD4,0x12, - 0xE2,0x18,0xF4,0xDD,0x1E,0x08,0x4C,0xF6,0xD8,0x00,0x3E,0x7C, - 0x47,0x74,0xE8,0x33, - }; -static unsigned char dh512_g[]={ +static unsigned char dh2048_p[] = { + 0xF6,0x42,0x57,0xB7,0x08,0x7F,0x08,0x17,0x72,0xA2,0xBA,0xD6, + 0xA9,0x42,0xF3,0x05,0xE8,0xF9,0x53,0x11,0x39,0x4F,0xB6,0xF1, + 0x6E,0xB9,0x4B,0x38,0x20,0xDA,0x01,0xA7,0x56,0xA3,0x14,0xE9, + 0x8F,0x40,0x55,0xF3,0xD0,0x07,0xC6,0xCB,0x43,0xA9,0x94,0xAD, + 0xF7,0x4C,0x64,0x86,0x49,0xF8,0x0C,0x83,0xBD,0x65,0xE9,0x17, + 0xD4,0xA1,0xD3,0x50,0xF8,0xF5,0x59,0x5F,0xDC,0x76,0x52,0x4F, + 0x3D,0x3D,0x8D,0xDB,0xCE,0x99,0xE1,0x57,0x92,0x59,0xCD,0xFD, + 0xB8,0xAE,0x74,0x4F,0xC5,0xFC,0x76,0xBC,0x83,0xC5,0x47,0x30, + 0x61,0xCE,0x7C,0xC9,0x66,0xFF,0x15,0xF9,0xBB,0xFD,0x91,0x5E, + 0xC7,0x01,0xAA,0xD3,0x5B,0x9E,0x8D,0xA0,0xA5,0x72,0x3A,0xD4, + 0x1A,0xF0,0xBF,0x46,0x00,0x58,0x2B,0xE5,0xF4,0x88,0xFD,0x58, + 0x4E,0x49,0xDB,0xCD,0x20,0xB4,0x9D,0xE4,0x91,0x07,0x36,0x6B, + 0x33,0x6C,0x38,0x0D,0x45,0x1D,0x0F,0x7C,0x88,0xB3,0x1C,0x7C, + 0x5B,0x2D,0x8E,0xF6,0xF3,0xC9,0x23,0xC0,0x43,0xF0,0xA5,0x5B, + 0x18,0x8D,0x8E,0xBB,0x55,0x8C,0xB8,0x5D,0x38,0xD3,0x34,0xFD, + 0x7C,0x17,0x57,0x43,0xA3,0x1D,0x18,0x6C,0xDE,0x33,0x21,0x2C, + 0xB5,0x2A,0xFF,0x3C,0xE1,0xB1,0x29,0x40,0x18,0x11,0x8D,0x7C, + 0x84,0xA7,0x0A,0x72,0xD6,0x86,0xC4,0x03,0x19,0xC8,0x07,0x29, + 0x7A,0xCA,0x95,0x0C,0xD9,0x96,0x9F,0xAB,0xD0,0x0A,0x50,0x9B, + 0x02,0x46,0xD3,0x08,0x3D,0x66,0xA4,0x5D,0x41,0x9F,0x9C,0x7C, + 0xBD,0x89,0x4B,0x22,0x19,0x26,0xBA,0xAB,0xA2,0x5E,0xC3,0x55, + 0xE9,0x32,0x0B,0x3B, +}; + +static unsigned char dh2048_g[] = { 0x02, - }; +}; -static DH *get_dh512(void) - { - DH *dh=NULL; - - if ((dh=DH_new()) == NULL) return(NULL); - dh->p=BN_bin2bn(dh512_p,sizeof(dh512_p),NULL); - dh->g=BN_bin2bn(dh512_g,sizeof(dh512_g),NULL); - if ((dh->p == NULL) || (dh->g == NULL)) - return(NULL); - return(dh); +DH *get_dh2048() +{ + DH *dh; + + if ((dh = DH_new()) == NULL) + return NULL; + dh->p=BN_bin2bn(dh2048_p, sizeof(dh2048_p), NULL); + dh->g=BN_bin2bn(dh2048_g, sizeof(dh2048_g), NULL); + if (dh->p == NULL || dh->g == NULL) { + DH_free(dh); + return NULL; } + return dh; +} #endif @@ -1661,45 +1681,42 @@ bad: #endif #ifndef OPENSSL_NO_DH - if (!no_dhe) - { - DH *dh=NULL; + if (!no_dhe) { + DH *dh = NULL; if (dhfile) dh = load_dh_param(dhfile); else if (s_cert_file) dh = load_dh_param(s_cert_file); - if (dh != NULL) - { - BIO_printf(bio_s_out,"Setting temp DH parameters\n"); + if (dh != NULL) { + BIO_printf(bio_s_out, "Setting temp DH parameters\n"); + } else { + BIO_printf(bio_s_out, "Using default temp DH parameters\n"); + dh = get_dh2048(); + if (dh == NULL) { + ERR_print_errors(bio_err); + goto end; } - else - { - BIO_printf(bio_s_out,"Using default temp DH parameters\n"); - dh=get_dh512(); } (void)BIO_flush(bio_s_out); - SSL_CTX_set_tmp_dh(ctx,dh); -#ifndef OPENSSL_NO_TLSEXT - if (ctx2) - { - if (!dhfile) - { - DH *dh2=load_dh_param(s_cert_file2); - if (dh2 != NULL) - { - BIO_printf(bio_s_out,"Setting temp DH parameters\n"); + SSL_CTX_set_tmp_dh(ctx, dh); +# ifndef OPENSSL_NO_TLSEXT + if (ctx2) { + if (!dhfile) { + DH *dh2 = load_dh_param(s_cert_file2); + if (dh2 != NULL) { + BIO_printf(bio_s_out, "Setting temp DH parameters\n"); (void)BIO_flush(bio_s_out); DH_free(dh); dh = dh2; } } - SSL_CTX_set_tmp_dh(ctx2,dh); + SSL_CTX_set_tmp_dh(ctx2, dh); } -#endif +# endif DH_free(dh); } #endif diff --git a/crypto/openssl/crypto/bio/bio_lib.c b/crypto/openssl/crypto/bio/bio_lib.c index 4793a453e..c9773234c 100644 --- a/crypto/openssl/crypto/bio/bio_lib.c +++ b/crypto/openssl/crypto/bio/bio_lib.c @@ -543,8 +543,10 @@ BIO *BIO_dup_chain(BIO *in) /* copy app data */ if (!CRYPTO_dup_ex_data(CRYPTO_EX_INDEX_BIO, &new_bio->ex_data, - &bio->ex_data)) + &bio->ex_data)) { + BIO_free(new_bio); goto err; + } if (ret == NULL) { @@ -559,8 +561,8 @@ BIO *BIO_dup_chain(BIO *in) } return(ret); err: - if (ret != NULL) - BIO_free(ret); + BIO_free_all(ret); + return(NULL); } diff --git a/crypto/openssl/crypto/bn/bn_gf2m.c b/crypto/openssl/crypto/bn/bn_gf2m.c index 8a4dc20ad..bda2aa604 100644 --- a/crypto/openssl/crypto/bn/bn_gf2m.c +++ b/crypto/openssl/crypto/bn/bn_gf2m.c @@ -568,10 +568,11 @@ int BN_GF2m_mod_inv(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx) } #else { - int i, ubits = BN_num_bits(u), - vbits = BN_num_bits(v), /* v is copy of p */ - top = p->top; - BN_ULONG *udp,*bdp,*vdp,*cdp; + int i; + int ubits = BN_num_bits(u); + int vbits = BN_num_bits(v); /* v is copy of p */ + int top = p->top; + BN_ULONG *udp, *bdp, *vdp, *cdp; bn_wexpand(u,top); udp = u->d; for (i=u->top;itop*BN_BYTES*2+2); + 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); + } if (buf == NULL) { BNerr(BN_F_BN_BN2HEX,ERR_R_MALLOC_FAILURE); diff --git a/crypto/openssl/crypto/buffer/buffer.c b/crypto/openssl/crypto/buffer/buffer.c index d4a4ce43b..8ae456c0c 100644 --- a/crypto/openssl/crypto/buffer/buffer.c +++ b/crypto/openssl/crypto/buffer/buffer.c @@ -88,7 +88,7 @@ void BUF_MEM_free(BUF_MEM *a) if (a->data != NULL) { - memset(a->data,0,(unsigned int)a->max); + OPENSSL_cleanse(a->data, a->max); OPENSSL_free(a->data); } OPENSSL_free(a); diff --git a/crypto/openssl/crypto/cms/cms_smime.c b/crypto/openssl/crypto/cms/cms_smime.c index 1af9f3a60..1d7725c1f 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_oct.c b/crypto/openssl/crypto/ec/ec2_oct.c index f1d75e5dd..91f13e97d 100644 --- a/crypto/openssl/crypto/ec/ec2_oct.c +++ b/crypto/openssl/crypto/ec/ec2_oct.c @@ -390,7 +390,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 7fa247593..577e45a01 100644 --- a/crypto/openssl/crypto/ec/ec_key.c +++ b/crypto/openssl/crypto/ec/ec_key.c @@ -326,7 +326,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 0992c393b..37be9e9e4 100644 --- a/crypto/openssl/crypto/ec/ec_lib.c +++ b/crypto/openssl/crypto/ec/ec_lib.c @@ -972,7 +972,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_oct.c b/crypto/openssl/crypto/ec/ecp_oct.c index 374a0ee73..2e785b049 100644 --- a/crypto/openssl/crypto/ec/ecp_oct.c +++ b/crypto/openssl/crypto/ec/ecp_oct.c @@ -416,7 +416,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 8e4154d86..1ac60e159 100644 --- a/crypto/openssl/crypto/ec/ectest.c +++ b/crypto/openssl/crypto/ec/ectest.c @@ -343,7 +343,7 @@ static void prime_field_tests(void) 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"); @@ -439,7 +439,7 @@ static void prime_field_tests(void) 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; @@ -473,7 +473,7 @@ static void prime_field_tests(void) 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; @@ -507,7 +507,7 @@ static void prime_field_tests(void) 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; @@ -541,7 +541,7 @@ static void prime_field_tests(void) 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; @@ -580,7 +580,7 @@ static void prime_field_tests(void) 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; @@ -624,7 +624,7 @@ static void prime_field_tests(void) "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; @@ -657,7 +657,7 @@ static void prime_field_tests(void) 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; @@ -771,7 +771,7 @@ static void prime_field_tests(void) #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; \ @@ -789,7 +789,7 @@ static void prime_field_tests(void) 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; \ @@ -894,7 +894,7 @@ static void char2_field_tests(void) 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 @@ -1133,7 +1133,7 @@ static void char2_field_tests(void) 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/evp/e_aes.c b/crypto/openssl/crypto/evp/e_aes.c index dc3c2a162..e62fcc780 100644 --- a/crypto/openssl/crypto/evp/e_aes.c +++ b/crypto/openssl/crypto/evp/e_aes.c @@ -50,6 +50,7 @@ #include #ifndef OPENSSL_NO_AES +#include #include #include #include @@ -967,7 +968,7 @@ static int aes_gcm_tls_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, CRYPTO_gcm128_tag(&gctx->gcm, ctx->buf, EVP_GCM_TLS_TAG_LEN); /* If tag mismatch wipe buffer */ - if (memcmp(ctx->buf, in + len, EVP_GCM_TLS_TAG_LEN)) + if (CRYPTO_memcmp(ctx->buf, in + len, EVP_GCM_TLS_TAG_LEN)) { OPENSSL_cleanse(out, len); goto err; @@ -1351,7 +1352,7 @@ static int aes_ccm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, unsigned char tag[16]; if (CRYPTO_ccm128_tag(ccm, tag, cctx->M)) { - if (!memcmp(tag, ctx->buf, cctx->M)) + if (!CRYPTO_memcmp(tag, ctx->buf, cctx->M)) rv = len; } } diff --git a/crypto/openssl/crypto/evp/e_rc4_hmac_md5.c b/crypto/openssl/crypto/evp/e_rc4_hmac_md5.c index 56563191b..a70ed2e5f 100644 --- a/crypto/openssl/crypto/evp/e_rc4_hmac_md5.c +++ b/crypto/openssl/crypto/evp/e_rc4_hmac_md5.c @@ -54,6 +54,7 @@ #if !defined(OPENSSL_NO_RC4) && !defined(OPENSSL_NO_MD5) +#include #include #include #include @@ -205,7 +206,7 @@ static int rc4_hmac_md5_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, MD5_Update(&key->md,mac,MD5_DIGEST_LENGTH); MD5_Final(mac,&key->md); - if (memcmp(out+plen,mac,MD5_DIGEST_LENGTH)) + if (CRYPTO_memcmp(out + plen, mac, MD5_DIGEST_LENGTH)) return 0; } else { MD5_Update(&key->md,out+md5_off,len-md5_off); diff --git a/crypto/openssl/crypto/evp/evp.h b/crypto/openssl/crypto/evp/evp.h index faeb3c24e..bbd51fed5 100644 --- a/crypto/openssl/crypto/evp/evp.h +++ b/crypto/openssl/crypto/evp/evp.h @@ -103,7 +103,6 @@ #define EVP_PKS_RSA 0x0100 #define EVP_PKS_DSA 0x0200 #define EVP_PKS_EC 0x0400 -#define EVP_PKT_EXP 0x1000 /* <= 512 bit key */ #define EVP_PKEY_NONE NID_undef #define EVP_PKEY_RSA NID_rsaEncryption diff --git a/crypto/openssl/crypto/hmac/hmac.c b/crypto/openssl/crypto/hmac/hmac.c index ba27cbf56..70375ee0f 100644 --- a/crypto/openssl/crypto/hmac/hmac.c +++ b/crypto/openssl/crypto/hmac/hmac.c @@ -240,6 +240,7 @@ unsigned char *HMAC(const EVP_MD *evp_md, const void *key, int key_len, HMAC_CTX_cleanup(&c); return md; err: + HMAC_CTX_cleanup(&c); return NULL; } diff --git a/crypto/openssl/crypto/modes/gcm128.c b/crypto/openssl/crypto/modes/gcm128.c index e1dc2b0f4..2cf83b1bb 100644 --- a/crypto/openssl/crypto/modes/gcm128.c +++ b/crypto/openssl/crypto/modes/gcm128.c @@ -1525,7 +1525,7 @@ int CRYPTO_gcm128_finish(GCM128_CONTEXT *ctx,const unsigned char *tag, ctx->Xi.u[1] ^= ctx->EK0.u[1]; if (tag && len<=sizeof(ctx->Xi)) - return memcmp(ctx->Xi.c,tag,len); + return CRYPTO_memcmp(ctx->Xi.c, tag, len); else return -1; } diff --git a/crypto/openssl/crypto/objects/obj_dat.c b/crypto/openssl/crypto/objects/obj_dat.c index 0b2f44241..1783233d8 100644 --- a/crypto/openssl/crypto/objects/obj_dat.c +++ b/crypto/openssl/crypto/objects/obj_dat.c @@ -405,6 +405,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/pkcs12/p12_mutl.c b/crypto/openssl/crypto/pkcs12/p12_mutl.c index 96de1bd11..53ab7506f 100644 --- a/crypto/openssl/crypto/pkcs12/p12_mutl.c +++ b/crypto/openssl/crypto/pkcs12/p12_mutl.c @@ -59,6 +59,7 @@ #ifndef OPENSSL_NO_HMAC #include #include "cryptlib.h" +#include #include #include #include @@ -123,7 +124,8 @@ int PKCS12_verify_mac(PKCS12 *p12, const char *pass, int passlen) return 0; } if ((maclen != (unsigned int)p12->mac->dinfo->digest->length) - || memcmp (mac, p12->mac->dinfo->digest->data, maclen)) return 0; + || CRYPTO_memcmp(mac, p12->mac->dinfo->digest->data, maclen)) + return 0; return 1; } diff --git a/crypto/openssl/crypto/pkcs7/pk7_doit.c b/crypto/openssl/crypto/pkcs7/pk7_doit.c index 5eb2a5bc6..7b138ca1b 100644 --- a/crypto/openssl/crypto/pkcs7/pk7_doit.c +++ b/crypto/openssl/crypto/pkcs7/pk7_doit.c @@ -504,6 +504,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) { @@ -660,7 +666,7 @@ BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, X509 *pcert) } #if 1 - if (PKCS7_is_detached(p7) || (in_bio != NULL)) + if (in_bio != NULL) { bio=in_bio; } diff --git a/crypto/openssl/crypto/x509/x509_vfy.c b/crypto/openssl/crypto/x509/x509_vfy.c index 920066aeb..d68ea4bf6 100644 --- a/crypto/openssl/crypto/x509/x509_vfy.c +++ b/crypto/openssl/crypto/x509/x509_vfy.c @@ -1679,83 +1679,121 @@ int X509_cmp_current_time(const ASN1_TIME *ctm) } int X509_cmp_time(const 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; - } - - if ((*str == 'Z') || (*str == '-') || (*str == '+')) - { *(p++)='0'; *(p++)='0'; } - else - { - *(p++)= *(str++); - *(p++)= *(str++); - /* Skip any fractional seconds... */ - if (*str == '.') - { + 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 { + /* 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.type = ctm->type; atm.flags = 0; - atm.length=sizeof(buff2); - atm.data=(unsigned char *)buff2; + 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 (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 (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/crypto/x509/x509type.c b/crypto/openssl/crypto/x509/x509type.c index 9702ec531..e2bd51af6 100644 --- a/crypto/openssl/crypto/x509/x509type.c +++ b/crypto/openssl/crypto/x509/x509type.c @@ -122,9 +122,6 @@ int X509_certificate_type(X509 *x, EVP_PKEY *pkey) } } - if (EVP_PKEY_size(pk) <= 1024/8)/* /8 because it's 1024 bits we look - for, not bytes */ - ret|=EVP_PKT_EXP; if(pkey==NULL) EVP_PKEY_free(pk); return(ret); } diff --git a/crypto/openssl/doc/apps/dhparam.pod b/crypto/openssl/doc/apps/dhparam.pod index 6e27cf5c1..1cd4c7666 100644 --- a/crypto/openssl/doc/apps/dhparam.pod +++ b/crypto/openssl/doc/apps/dhparam.pod @@ -71,8 +71,10 @@ check if the parameters are valid primes and generator. =item B<-2>, B<-5> -The generator to use, either 2 or 5. 2 is the default. If present then the -input file is ignored and parameters are generated instead. +The generator to use, either 2 or 5. If present then the +input file is ignored and parameters are generated instead. If not +present but B is present, parameters are generated with the +default generator 2. =item B<-rand> I @@ -85,9 +87,10 @@ all others. =item I this option specifies that a parameter set should be generated of size -I. It must be the last option. If not present then a value of 512 -is used. If this option is present then the input file is ignored and -parameters are generated instead. +I. It must be the last option. If this option is present then +the input file is ignored and parameters are generated instead. If +this option is not present but a generator (B<-2> or B<-5>) is +present, parameters are generated with a default length of 2048 bits. =item B<-noout> diff --git a/crypto/openssl/doc/ssl/SSL_CTX_set_tmp_dh_callback.pod b/crypto/openssl/doc/ssl/SSL_CTX_set_tmp_dh_callback.pod index 7a27eef50..b754c16a8 100644 --- a/crypto/openssl/doc/ssl/SSL_CTX_set_tmp_dh_callback.pod +++ b/crypto/openssl/doc/ssl/SSL_CTX_set_tmp_dh_callback.pod @@ -61,12 +61,12 @@ negotiation is being saved. If "strong" primes were used to generate the DH parameters, it is not strictly necessary to generate a new key for each handshake but it does improve forward -secrecy. If it is not assured, that "strong" primes were used (see especially -the section about DSA parameters below), SSL_OP_SINGLE_DH_USE must be used -in order to prevent small subgroup attacks. Always using SSL_OP_SINGLE_DH_USE -has an impact on the computer time needed during negotiation, but it is not -very large, so application authors/users should consider to always enable -this option. +secrecy. If it is not assured that "strong" primes were used, +SSL_OP_SINGLE_DH_USE must be used in order to prevent small subgroup +attacks. Always using SSL_OP_SINGLE_DH_USE has an impact on the +computer time needed during negotiation, but it is not very large, so +application authors/users should consider always enabling this option. +The option is required to implement perfect forward secrecy (PFS). As generating DH parameters is extremely time consuming, an application should not generate the parameters on the fly but supply the parameters. @@ -74,82 +74,62 @@ DH parameters can be reused, as the actual key is newly generated during the negotiation. The risk in reusing DH parameters is that an attacker may specialize on a very often used DH group. Applications should therefore generate their own DH parameters during the installation process using the -openssl L application. In order to reduce the computer -time needed for this generation, it is possible to use DSA parameters -instead (see L), but in this case SSL_OP_SINGLE_DH_USE -is mandatory. +openssl L application. This application +guarantees that "strong" primes are used. -Application authors may compile in DH parameters. Files dh512.pem, -dh1024.pem, dh2048.pem, and dh4096.pem in the 'apps' directory of current +Files dh2048.pem, and dh4096.pem in the 'apps' directory of the current version of the OpenSSL distribution contain the 'SKIP' DH parameters, which use safe primes and were generated verifiably pseudo-randomly. These files can be converted into C code using the B<-C> option of the -L application. -Authors may also generate their own set of parameters using -L, but a user may not be sure how the parameters were -generated. The generation of DH parameters during installation is therefore -recommended. +L application. Generation of custom DH +parameters during installation should still be preferred to stop an +attacker from specializing on a commonly used group. Files dh1024.pem +and dh512.pem contain old parameters that must not be used by +applications. An application may either directly specify the DH parameters or -can supply the DH parameters via a callback function. The callback approach -has the advantage, that the callback may supply DH parameters for different -key lengths. +can supply the DH parameters via a callback function. -The B is called with the B needed and -the B information. The B flag is set, when the -ephemeral DH key exchange is performed with an export cipher. +Previous versions of the callback used B and B +parameters to control parameter generation for export and non-export +cipher suites. Modern servers that do not support export ciphersuites +are advised to either use SSL_CTX_set_tmp_dh() in combination with +SSL_OP_SINGLE_DH_USE, or alternatively, use the callback but ignore +B and B and simply supply at least 2048-bit +parameters in the callback. =head1 EXAMPLES -Handle DH parameters for key lengths of 512 and 1024 bits. (Error handling +Setup DH parameters with a key length of 2048 bits. (Error handling partly left out.) - ... - /* Set up ephemeral DH stuff */ - DH *dh_512 = NULL; - DH *dh_1024 = NULL; - FILE *paramfile; + Command-line parameter generation: + $ openssl dhparam -out dh_param_2048.pem 2048 + + Code for setting up parameters during server initialization: ... - /* "openssl dhparam -out dh_param_512.pem -2 512" */ - paramfile = fopen("dh_param_512.pem", "r"); + SSL_CTX ctx = SSL_CTX_new(); + ... + + /* Set up ephemeral DH parameters. */ + DH *dh_2048 = NULL; + FILE *paramfile; + paramfile = fopen("dh_param_2048.pem", "r"); if (paramfile) { - dh_512 = PEM_read_DHparams(paramfile, NULL, NULL, NULL); + dh_2048 = PEM_read_DHparams(paramfile, NULL, NULL, NULL); fclose(paramfile); + } else { + /* Error. */ } - /* "openssl dhparam -out dh_param_1024.pem -2 1024" */ - paramfile = fopen("dh_param_1024.pem", "r"); - if (paramfile) { - dh_1024 = PEM_read_DHparams(paramfile, NULL, NULL, NULL); - fclose(paramfile); + if (dh_2048 == NULL) { + /* Error. */ } - ... - - /* "openssl dhparam -C -2 512" etc... */ - DH *get_dh512() { ... } - DH *get_dh1024() { ... } - - DH *tmp_dh_callback(SSL *s, int is_export, int keylength) - { - DH *dh_tmp=NULL; - - switch (keylength) { - case 512: - if (!dh_512) - dh_512 = get_dh512(); - dh_tmp = dh_512; - break; - case 1024: - if (!dh_1024) - dh_1024 = get_dh1024(); - dh_tmp = dh_1024; - break; - default: - /* Generating a key on the fly is very costly, so use what is there */ - setup_dh_parameters_like_above(); - } - return(dh_tmp); + if (SSL_CTX_set_tmp_dh(ctx, dh_2048) != 1) { + /* Error. */ } + SSL_CTX_set_options(ctx, SSL_OP_SINGLE_DH_USE); + ... =head1 RETURN VALUES diff --git a/crypto/openssl/ssl/d1_both.c b/crypto/openssl/ssl/d1_both.c index 1b9d64bf6..f08bf36bc 100644 --- a/crypto/openssl/ssl/d1_both.c +++ b/crypto/openssl/ssl/d1_both.c @@ -481,6 +481,12 @@ again: else if ( i <= 0 && !*ok) return i; + if (mt >= 0 && s->s3->tmp.message_type != mt) { + al = SSL_AD_UNEXPECTED_MESSAGE; + SSLerr(SSL_F_DTLS1_GET_MESSAGE, SSL_R_UNEXPECTED_MESSAGE); + goto f_err; + } + p = (unsigned char *)s->init_buf->data; msg_len = msg_hdr->msg_len; @@ -869,6 +875,20 @@ dtls1_get_message_fragment(SSL *s, int st1, int stn, long max, int *ok) /* parse the message fragment header */ dtls1_get_message_header(wire, &msg_hdr); + len = msg_hdr.msg_len; + frag_off = msg_hdr.frag_off; + frag_len = msg_hdr.frag_len; + + /* + * We must have at least frag_len bytes left in the record to be read. + * Fragments must not span records. + */ + if (frag_len > s->s3->rrec.length) { + al = SSL3_AD_ILLEGAL_PARAMETER; + SSLerr(SSL_F_DTLS1_GET_MESSAGE_FRAGMENT, SSL_R_BAD_LENGTH); + goto f_err; + } + /* * if this is a future (or stale) message it gets buffered * (or dropped)--no further processing at this time @@ -878,10 +898,6 @@ dtls1_get_message_fragment(SSL *s, int st1, int stn, long max, int *ok) if (msg_hdr.seq != s->d1->handshake_read_seq && !(s->d1->listen && msg_hdr.seq == 1)) return dtls1_process_out_of_seq_message(s, &msg_hdr, ok); - len = msg_hdr.msg_len; - frag_off = msg_hdr.frag_off; - frag_len = msg_hdr.frag_len; - if (frag_len && frag_len < len) return dtls1_reassemble_fragment(s, &msg_hdr, ok); @@ -913,16 +929,16 @@ dtls1_get_message_fragment(SSL *s, int st1, int stn, long max, int *ok) if ((al=dtls1_preprocess_fragment(s,&msg_hdr,max))) goto f_err; - /* XDTLS: ressurect this when restart is in place */ - s->state=stn; - if ( frag_len > 0) { unsigned char *p=(unsigned char *)s->init_buf->data+DTLS1_HM_HEADER_LENGTH; i=s->method->ssl_read_bytes(s,SSL3_RT_HANDSHAKE, &p[frag_off],frag_len,0); - /* XDTLS: fix this--message fragments cannot span multiple packets */ + /* + * This shouldn't ever fail due to NBIO because we already checked + * that we have enough data in the record + */ if (i <= 0) { s->rwstate=SSL_READING; @@ -943,6 +959,7 @@ dtls1_get_message_fragment(SSL *s, int st1, int stn, long max, int *ok) } *ok = 1; + s->state = stn; /* Note that s->init_num is *not* used as current offset in * s->init_buf->data, but as a counter summing up fragments' diff --git a/crypto/openssl/ssl/d1_lib.c b/crypto/openssl/ssl/d1_lib.c index 14337b31a..48de07988 100644 --- a/crypto/openssl/ssl/d1_lib.c +++ b/crypto/openssl/ssl/d1_lib.c @@ -509,6 +509,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/d1_pkt.c b/crypto/openssl/ssl/d1_pkt.c index 0059fe2f1..bce8619c1 100644 --- a/crypto/openssl/ssl/d1_pkt.c +++ b/crypto/openssl/ssl/d1_pkt.c @@ -1056,7 +1056,7 @@ start: { al=SSL_AD_DECODE_ERROR; SSLerr(SSL_F_DTLS1_READ_BYTES,SSL_R_BAD_HELLO_REQUEST); - goto err; + goto f_err; } /* no need to check sequence number on HELLO REQUEST messages */ diff --git a/crypto/openssl/ssl/s3_cbc.c b/crypto/openssl/ssl/s3_cbc.c index 11f13adbf..e850e3ed8 100644 --- a/crypto/openssl/ssl/s3_cbc.c +++ b/crypto/openssl/ssl/s3_cbc.c @@ -143,7 +143,7 @@ int tls1_cbc_remove_padding(const SSL* s, if ( (s->options&SSL_OP_TLS_BLOCK_PADDING_BUG) && !s->expand) { /* First packet is even in size, so check */ - if ((memcmp(s->s3->read_sequence, "\0\0\0\0\0\0\0\0",8) == 0) && + if ((CRYPTO_memcmp(s->s3->read_sequence, "\0\0\0\0\0\0\0\0", 8) == 0) && !(padding_length & 1)) { s->s3->flags|=TLS1_FLAGS_TLS_PADDING_BUG; diff --git a/crypto/openssl/ssl/s3_clnt.c b/crypto/openssl/ssl/s3_clnt.c index 769271698..8628f1cb8 100644 --- a/crypto/openssl/ssl/s3_clnt.c +++ b/crypto/openssl/ssl/s3_clnt.c @@ -1606,6 +1606,13 @@ int ssl3_get_key_exchange(SSL *s) SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_INTERNAL_ERROR); goto err; } + + if (EVP_PKEY_bits(pkey) <= SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher)) { + al = SSL_AD_UNEXPECTED_MESSAGE; + SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_UNEXPECTED_MESSAGE); + goto f_err; + } + s->session->sess_cert->peer_rsa_tmp=rsa; rsa=NULL; } @@ -2190,7 +2197,39 @@ int ssl3_get_new_session_ticket(SSL *s) goto f_err; } - p=d=(unsigned char *)s->init_msg; + 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 */ @@ -3319,6 +3358,7 @@ int ssl3_check_cert_and_algorithm(SSL *s) int i,idx; long alg_k,alg_a; EVP_PKEY *pkey=NULL; + int pkey_bits; SESS_CERT *sc; #ifndef OPENSSL_NO_RSA RSA *rsa; @@ -3326,6 +3366,7 @@ int ssl3_check_cert_and_algorithm(SSL *s) #ifndef OPENSSL_NO_DH DH *dh; #endif + int al = SSL_AD_HANDSHAKE_FAILURE; alg_k=s->s3->tmp.new_cipher->algorithm_mkey; alg_a=s->s3->tmp.new_cipher->algorithm_auth; @@ -3367,6 +3408,7 @@ int ssl3_check_cert_and_algorithm(SSL *s) } #endif pkey=X509_get_pubkey(sc->peer_pkeys[idx].x509); + pkey_bits = EVP_PKEY_bits(pkey); i=X509_certificate_type(sc->peer_pkeys[idx].x509,pkey); EVP_PKEY_free(pkey); @@ -3385,71 +3427,108 @@ int ssl3_check_cert_and_algorithm(SSL *s) } #endif #ifndef OPENSSL_NO_RSA - if ((alg_k & SSL_kRSA) && - !(has_bits(i,EVP_PK_RSA|EVP_PKT_ENC) || (rsa != NULL))) - { - SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_MISSING_RSA_ENCRYPTING_CERT); + if (alg_k & SSL_kRSA) { + if (!SSL_C_IS_EXPORT(s->s3->tmp.new_cipher) && + !has_bits(i, EVP_PK_RSA | EVP_PKT_ENC)) { + SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM, + SSL_R_MISSING_RSA_ENCRYPTING_CERT); goto f_err; - } + } else if (SSL_C_IS_EXPORT(s->s3->tmp.new_cipher)) { + if (pkey_bits <= SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher)) { + if (!has_bits(i, EVP_PK_RSA | EVP_PKT_ENC)) { + SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM, + SSL_R_MISSING_RSA_ENCRYPTING_CERT); + goto f_err; + } + if (rsa != NULL) { + /* server key exchange is not allowed. */ + al = SSL_AD_INTERNAL_ERROR; + SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM, ERR_R_INTERNAL_ERROR); + goto f_err; + } + } + } + } #endif #ifndef OPENSSL_NO_DH - if ((alg_k & SSL_kEDH) && - !(has_bits(i,EVP_PK_DH|EVP_PKT_EXCH) || (dh != NULL))) - { - SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_MISSING_DH_KEY); + if ((alg_k & SSL_kEDH) && dh == NULL) { + al = SSL_AD_INTERNAL_ERROR; + SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM, ERR_R_INTERNAL_ERROR); goto f_err; } - else if ((alg_k & SSL_kDHr) && !has_bits(i,EVP_PK_DH|EVP_PKS_RSA)) - { - SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_MISSING_DH_RSA_CERT); + if ((alg_k & SSL_kDHr) && !has_bits(i, EVP_PK_DH | EVP_PKS_RSA)) { + SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM, + SSL_R_MISSING_DH_RSA_CERT); goto f_err; } -#ifndef OPENSSL_NO_DSA - else if ((alg_k & SSL_kDHd) && !has_bits(i,EVP_PK_DH|EVP_PKS_DSA)) - { - SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_MISSING_DH_DSA_CERT); +# ifndef OPENSSL_NO_DSA + if ((alg_k & SSL_kDHd) && !has_bits(i, EVP_PK_DH | EVP_PKS_DSA)) { + SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM, + SSL_R_MISSING_DH_DSA_CERT); goto f_err; } -#endif -#endif +# endif + + /* Check DHE only: static DH not implemented. */ + if (alg_k & SSL_kEDH) { + int dh_size = BN_num_bits(dh->p); + if ((!SSL_C_IS_EXPORT(s->s3->tmp.new_cipher) && dh_size < 768) + || (SSL_C_IS_EXPORT(s->s3->tmp.new_cipher) && dh_size < 512)) { + SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM, SSL_R_DH_KEY_TOO_SMALL); + goto f_err; + } + } +#endif /* !OPENSSL_NO_DH */ - if (SSL_C_IS_EXPORT(s->s3->tmp.new_cipher) && !has_bits(i,EVP_PKT_EXP)) + if (SSL_C_IS_EXPORT(s->s3->tmp.new_cipher) && + pkey_bits > SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher)) { #ifndef OPENSSL_NO_RSA - if (alg_k & SSL_kRSA) - { - if (rsa == NULL - || RSA_size(rsa)*8 > SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher)) - { - SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_MISSING_EXPORT_TMP_RSA_KEY); + if (alg_k & SSL_kRSA) { + if (rsa == NULL) { + SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM, + SSL_R_MISSING_EXPORT_TMP_RSA_KEY); goto f_err; + } else if (BN_num_bits(rsa->n) > + SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher)) { + /* We have a temporary RSA key but it's too large. */ + al = SSL_AD_EXPORT_RESTRICTION; + SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM, + SSL_R_MISSING_EXPORT_TMP_RSA_KEY); + goto f_err; } - } - else + } else #endif #ifndef OPENSSL_NO_DH - if (alg_k & (SSL_kEDH|SSL_kDHr|SSL_kDHd)) - { - if (dh == NULL - || DH_size(dh)*8 > SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher)) - { - SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_MISSING_EXPORT_TMP_DH_KEY); + if (alg_k & SSL_kEDH) { + if (BN_num_bits(dh->p) > + SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher)) { + /* We have a temporary DH key but it's too large. */ + al = SSL_AD_EXPORT_RESTRICTION; + SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM, + SSL_R_MISSING_EXPORT_TMP_DH_KEY); goto f_err; } - } - else + } else if (alg_k & (SSL_kDHr | SSL_kDHd)) { + /* The cert should have had an export DH key. */ + al = SSL_AD_EXPORT_RESTRICTION; + SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM, + SSL_R_MISSING_EXPORT_TMP_DH_KEY); + goto f_err; + } else #endif { - SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_UNKNOWN_KEY_EXCHANGE_TYPE); + SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM, + SSL_R_UNKNOWN_KEY_EXCHANGE_TYPE); goto f_err; } } - return(1); -f_err: - ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_HANDSHAKE_FAILURE); -err: - return(0); - } + return (1); + f_err: + ssl3_send_alert(s, SSL3_AL_FATAL, al); + err: + return (0); +} #if !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_NEXTPROTONEG) int ssl3_send_next_proto(SSL *s) diff --git a/crypto/openssl/ssl/s3_srvr.c b/crypto/openssl/ssl/s3_srvr.c index fadca74ec..6852e0858 100644 --- a/crypto/openssl/ssl/s3_srvr.c +++ b/crypto/openssl/ssl/s3_srvr.c @@ -2418,6 +2418,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); @@ -2530,26 +2531,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)))) { @@ -2565,7 +2570,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; } } @@ -2591,6 +2597,11 @@ int ssl3_get_client_key_exchange(SSL *s) ** kssl_ctx = kssl_ctx_free(kssl_ctx); ** if (s->kssl_ctx) s->kssl_ctx = NULL; */ + + kclean: + OPENSSL_cleanse(pms, sizeof(pms)); + if (kerr) + goto err; } else #endif /* OPENSSL_NO_KRB5 */ diff --git a/crypto/openssl/ssl/ssl.h b/crypto/openssl/ssl/ssl.h index 2ba592320..1b98e290f 100644 --- a/crypto/openssl/ssl/ssl.h +++ b/crypto/openssl/ssl/ssl.h @@ -2263,6 +2263,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_SESSION_SET1_ID_CONTEXT 312 @@ -2377,6 +2378,7 @@ void ERR_load_SSL_strings(void); #define SSL_R_DATA_LENGTH_TOO_LONG 146 #define SSL_R_DECRYPTION_FAILED 147 #define SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC 281 +#define SSL_R_DH_KEY_TOO_SMALL 372 #define SSL_R_DH_PUBLIC_VALUE_LENGTH_IS_WRONG 148 #define SSL_R_DIGEST_CHECK_FAILED 149 #define SSL_R_DTLS_MESSAGE_TOO_BIG 334 diff --git a/crypto/openssl/ssl/ssl_err.c b/crypto/openssl/ssl/ssl_err.c index 1b7eb47e1..7b6aa9998 100644 --- a/crypto/openssl/ssl/ssl_err.c +++ b/crypto/openssl/ssl/ssl_err.c @@ -245,6 +245,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_SESSION_SET1_ID_CONTEXT), "SSL_SESSION_set1_id_context"}, @@ -362,6 +363,7 @@ static ERR_STRING_DATA SSL_str_reasons[]= {ERR_REASON(SSL_R_DATA_LENGTH_TOO_LONG) ,"data length too long"}, {ERR_REASON(SSL_R_DECRYPTION_FAILED) ,"decryption failed"}, {ERR_REASON(SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC),"decryption failed or bad record mac"}, +{ERR_REASON(SSL_R_DH_KEY_TOO_SMALL), "dh key too small"}, {ERR_REASON(SSL_R_DH_PUBLIC_VALUE_LENGTH_IS_WRONG),"dh public value length is wrong"}, {ERR_REASON(SSL_R_DIGEST_CHECK_FAILED) ,"digest check failed"}, {ERR_REASON(SSL_R_DTLS_MESSAGE_TOO_BIG) ,"dtls message too big"}, diff --git a/crypto/openssl/ssl/ssl_locl.h b/crypto/openssl/ssl/ssl_locl.h index 1b8fa8c4c..12d07b267 100644 --- a/crypto/openssl/ssl/ssl_locl.h +++ b/crypto/openssl/ssl/ssl_locl.h @@ -831,6 +831,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); DECLARE_OBJ_BSEARCH_GLOBAL_CMP_FN(SSL_CIPHER, SSL_CIPHER, ssl_cipher_id); diff --git a/crypto/openssl/ssl/ssl_sess.c b/crypto/openssl/ssl/ssl_sess.c index 235f92d82..31fbf23b1 100644 --- a/crypto/openssl/ssl/ssl_sess.c +++ b/crypto/openssl/ssl/ssl_sess.c @@ -224,6 +224,130 @@ 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 + */ +#ifndef OPENSSL_NO_PSK + dest->psk_identity_hint = NULL; + dest->psk_identity = NULL; +#endif + dest->ciphers = NULL; +#ifndef OPENSSL_NO_TLSEXT + dest->tlsext_hostname = NULL; +# ifndef OPENSSL_NO_EC + dest->tlsext_ecpointformatlist = NULL; + dest->tlsext_ellipticcurvelist = NULL; +# endif +#endif + dest->tlsext_tick = NULL; +#ifndef OPENSSL_NO_SRP + dest->srp_username = NULL; +#endif + 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); + +#ifndef OPENSSL_NO_PSK + if (src->psk_identity_hint) { + dest->psk_identity_hint = BUF_strdup(src->psk_identity_hint); + if (dest->psk_identity_hint == NULL) { + goto err; + } + } + if (src->psk_identity) { + dest->psk_identity = BUF_strdup(src->psk_identity); + if (dest->psk_identity == NULL) { + goto err; + } + } +#endif + + 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; + } + } +# ifndef OPENSSL_NO_EC + if (src->tlsext_ecpointformatlist) { + dest->tlsext_ecpointformatlist = + BUF_memdup(src->tlsext_ecpointformatlist, + src->tlsext_ecpointformatlist_length); + if (dest->tlsext_ecpointformatlist == NULL) + goto err; + } + if (src->tlsext_ellipticcurvelist) { + dest->tlsext_ellipticcurvelist = + BUF_memdup(src->tlsext_ellipticcurvelist, + src->tlsext_ellipticcurvelist_length); + if (dest->tlsext_ellipticcurvelist == NULL) + goto err; + } +# endif +#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; + } + +#ifndef OPENSSL_NO_SRP + if (src->srp_username) { + dest->srp_username = BUF_strdup(src->srp_username); + if (dest->srp_username == NULL) { + goto err; + } + } +#endif + + 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/crypto/openssl/ssl/t1_lib.c b/crypto/openssl/ssl/t1_lib.c index 179b467d4..afd5eee40 100644 --- a/crypto/openssl/ssl/t1_lib.c +++ b/crypto/openssl/ssl/t1_lib.c @@ -1015,12 +1015,16 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in s->srtp_profile = NULL; - if (data >= (d+n-2)) + if (data >= (d + n - 2)) { + if (data != d + n) + goto err; + else goto ri_check; + } n2s(data,len); if (data > (d+n-len)) - goto ri_check; + goto err; while (data <= (d+n-4)) { @@ -1028,7 +1032,7 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in n2s(data,size); if (data+size > (d+n)) - goto ri_check; + goto err; #if 0 fprintf(stderr,"Received extension type %d size %d\n",type,size); #endif @@ -1065,17 +1069,11 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in int dsize; if (size < 2) - { - *al = SSL_AD_DECODE_ERROR; - return 0; - } + goto err; n2s(data,dsize); size -= 2; if (dsize > size ) - { - *al = SSL_AD_DECODE_ERROR; - return 0; - } + goto err; sdata = data; while (dsize > 3) @@ -1085,10 +1083,7 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in dsize -= 3; if (len > dsize) - { - *al = SSL_AD_DECODE_ERROR; - return 0; - } + goto err; if (s->servername_done == 0) switch (servname_type) { @@ -1096,10 +1091,7 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in if (!s->hit) { if(s->session->tlsext_hostname) - { - *al = SSL_AD_DECODE_ERROR; - return 0; - } + goto err; if (len > TLSEXT_MAXLEN_host_name) { *al = TLS1_AD_UNRECOGNIZED_NAME; @@ -1135,36 +1127,24 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in dsize -= len; } if (dsize != 0) - { - *al = SSL_AD_DECODE_ERROR; - return 0; - } + goto err; } #ifndef OPENSSL_NO_SRP else if (type == TLSEXT_TYPE_srp) { if (size <= 0 || ((len = data[0])) != (size -1)) - { - *al = SSL_AD_DECODE_ERROR; - return 0; - } + goto err; if (s->srp_ctx.login != NULL) - { - *al = SSL_AD_DECODE_ERROR; - return 0; - } + goto err; if ((s->srp_ctx.login = OPENSSL_malloc(len+1)) == NULL) return -1; memcpy(s->srp_ctx.login, &data[1], len); s->srp_ctx.login[len]='\0'; if (strlen(s->srp_ctx.login) != len) - { - *al = SSL_AD_DECODE_ERROR; - return 0; + goto err; } - } #endif #ifndef OPENSSL_NO_EC @@ -1174,10 +1154,7 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in int ecpointformatlist_length = *(sdata++); if (ecpointformatlist_length != size - 1) - { - *al = TLS1_AD_DECODE_ERROR; - return 0; - } + goto err; if (!s->hit) { if(s->session->tlsext_ecpointformatlist) @@ -1212,17 +1189,12 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in ellipticcurvelist_length < 1 || /* Each NamedCurve is 2 bytes. */ ellipticcurvelist_length & 1) - { - *al = TLS1_AD_DECODE_ERROR; - return 0; - } + goto err; if (!s->hit) { if(s->session->tlsext_ellipticcurvelist) - { - *al = TLS1_AD_DECODE_ERROR; - return 0; - } + goto err; + s->session->tlsext_ellipticcurvelist_length = 0; if ((s->session->tlsext_ellipticcurvelist = OPENSSL_malloc(ellipticcurvelist_length)) == NULL) { @@ -1291,33 +1263,21 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in { int dsize; if (sigalg_seen || size < 2) - { - *al = SSL_AD_DECODE_ERROR; - return 0; - } + goto err; sigalg_seen = 1; n2s(data,dsize); size -= 2; if (dsize != size || dsize & 1) - { - *al = SSL_AD_DECODE_ERROR; - return 0; - } + goto err; if (!tls1_process_sigalgs(s, data, dsize)) - { - *al = SSL_AD_DECODE_ERROR; - return 0; + goto err; } - } else if (type == TLSEXT_TYPE_status_request && s->version != DTLS1_VERSION) { if (size < 5) - { - *al = SSL_AD_DECODE_ERROR; - return 0; - } + goto err; s->tlsext_status_type = *data++; size--; @@ -1329,41 +1289,28 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in n2s(data,dsize); size -= 2; if (dsize > size ) - { - *al = SSL_AD_DECODE_ERROR; - return 0; - } + goto err; while (dsize > 0) { OCSP_RESPID *id; int idsize; if (dsize < 4) - { - *al = SSL_AD_DECODE_ERROR; - return 0; - } + goto err; n2s(data, idsize); dsize -= 2 + idsize; size -= 2 + idsize; if (dsize < 0) - { - *al = SSL_AD_DECODE_ERROR; - return 0; - } + goto err; sdata = data; data += idsize; id = d2i_OCSP_RESPID(NULL, &sdata, idsize); if (!id) - { - *al = SSL_AD_DECODE_ERROR; - return 0; - } + goto err; if (data != sdata) { OCSP_RESPID_free(id); - *al = SSL_AD_DECODE_ERROR; - return 0; + goto err; } if (!s->tlsext_ocsp_ids && !(s->tlsext_ocsp_ids = @@ -1384,17 +1331,11 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in /* Read in request_extensions */ if (size < 2) - { - *al = SSL_AD_DECODE_ERROR; - return 0; - } + goto err; n2s(data,dsize); size -= 2; if (dsize != size) - { - *al = SSL_AD_DECODE_ERROR; - return 0; - } + goto err; sdata = data; if (dsize > 0) { @@ -1409,12 +1350,9 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in &sdata, dsize); if (!s->tlsext_ocsp_exts || (data + dsize != sdata)) - { - *al = SSL_AD_DECODE_ERROR; - return 0; + goto err; } } - } /* We don't know what to do with any other type * so ignore it. */ @@ -1475,6 +1413,10 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in data+=size; } + /* Spurious data on the end */ + if (data != d + n) + goto err; + *p = data; ri_check: @@ -1491,7 +1433,10 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in } return 1; - } +err: + *al = SSL_AD_DECODE_ERROR; + return 0; +} #ifndef OPENSSL_NO_NEXTPROTONEG /* ssl_next_proto_validate validates a Next Protocol Negotiation block. No diff --git a/sys/conf/newvers.sh b/sys/conf/newvers.sh index 691b57f3f..cba1d4e4f 100644 --- a/sys/conf/newvers.sh +++ b/sys/conf/newvers.sh @@ -32,7 +32,7 @@ TYPE="FreeBSD" REVISION="10.1" -BRANCH="RELEASE-p11" +BRANCH="RELEASE-p12" if [ "X${BRANCH_OVERRIDE}" != "X" ]; then BRANCH=${BRANCH_OVERRIDE} fi -- 2.45.0