From 25952ef9630b0828388a6b4180dc54899e136622 Mon Sep 17 00:00:00 2001 From: Sascha Wildner Date: Thu, 11 Jun 2015 21:03:27 +0200 Subject: [PATCH] Import OpenSSL 1.0.1n. Fixes CVE-2015-1788, CVE-2015-1789, CVE-2015-1790, CVE-2015-1791, and CVE-2015-1792. Rejects DH handshakes with parameters shorter than 768 bits. --- crypto/openssl/CHANGES | 71 +++++ crypto/openssl/NEWS | 8 + crypto/openssl/README | 2 +- crypto/openssl/apps/apps.c | 6 +- crypto/openssl/apps/asn1pars.c | 2 +- crypto/openssl/apps/ca.c | 10 +- crypto/openssl/apps/cms.c | 2 + crypto/openssl/apps/dhparam.c | 4 +- crypto/openssl/apps/enc.c | 13 +- crypto/openssl/apps/gendh.c | 2 +- crypto/openssl/apps/ocsp.c | 2 + crypto/openssl/apps/s_cb.c | 3 +- crypto/openssl/apps/s_client.c | 15 +- crypto/openssl/apps/s_server.c | 73 +++-- crypto/openssl/apps/s_time.c | 2 +- crypto/openssl/apps/smime.c | 2 + crypto/openssl/apps/srp.c | 4 +- crypto/openssl/apps/verify.c | 2 +- crypto/openssl/crypto/asn1/a_int.c | 6 +- crypto/openssl/crypto/asn1/asn1_gen.c | 40 ++- crypto/openssl/crypto/asn1/asn_mime.c | 3 +- crypto/openssl/crypto/asn1/bio_ndef.c | 4 +- crypto/openssl/crypto/asn1/tasn_new.c | 3 - crypto/openssl/crypto/asn1/tasn_prn.c | 2 +- crypto/openssl/crypto/asn1/x_x509.c | 4 +- crypto/openssl/crypto/bio/b_print.c | 45 ++- crypto/openssl/crypto/bio/bf_nbio.c | 6 +- crypto/openssl/crypto/bio/bio_lib.c | 8 +- crypto/openssl/crypto/bio/bss_dgram.c | 21 +- crypto/openssl/crypto/bn/bn.h | 5 + crypto/openssl/crypto/bn/bn_err.c | 6 +- crypto/openssl/crypto/bn/bn_gf2m.c | 15 +- crypto/openssl/crypto/bn/bn_lcl.h | 2 +- crypto/openssl/crypto/bn/bn_print.c | 7 +- crypto/openssl/crypto/bn/bn_rand.c | 10 +- crypto/openssl/crypto/bn/bn_shift.c | 10 + crypto/openssl/crypto/buffer/buffer.c | 2 +- crypto/openssl/crypto/cmac/cmac.c | 2 + crypto/openssl/crypto/cms/cms_pwri.c | 7 +- crypto/openssl/crypto/cms/cms_smime.c | 2 +- crypto/openssl/crypto/cryptlib.c | 2 - crypto/openssl/crypto/des/enc_writ.c | 7 +- crypto/openssl/crypto/dh/dh_ameth.c | 2 +- crypto/openssl/crypto/dsa/dsa_gen.c | 3 +- crypto/openssl/crypto/dsa/dsa_ossl.c | 8 +- crypto/openssl/crypto/dso/dso_lib.c | 2 +- crypto/openssl/crypto/ec/ec2_oct.c | 2 +- crypto/openssl/crypto/ec/ec_asn1.c | 20 +- crypto/openssl/crypto/ec/ec_check.c | 2 +- crypto/openssl/crypto/ec/ec_key.c | 2 +- crypto/openssl/crypto/ec/ec_lcl.h | 8 - crypto/openssl/crypto/ec/ec_lib.c | 7 + crypto/openssl/crypto/ec/eck_prn.c | 4 +- crypto/openssl/crypto/ec/ecp_oct.c | 2 +- crypto/openssl/crypto/engine/eng_table.c | 6 +- crypto/openssl/crypto/evp/bio_ok.c | 3 +- crypto/openssl/crypto/evp/e_aes.c | 7 +- .../openssl/crypto/evp/e_aes_cbc_hmac_sha1.c | 9 +- crypto/openssl/crypto/evp/e_rc4_hmac_md5.c | 10 +- crypto/openssl/crypto/evp/encode.c | 2 +- crypto/openssl/crypto/evp/evp.h | 4 +- crypto/openssl/crypto/evp/p_seal.c | 5 +- crypto/openssl/crypto/hmac/hmac.c | 28 +- crypto/openssl/crypto/hmac/hmac.h | 1 + crypto/openssl/crypto/md32_common.h | 4 +- crypto/openssl/crypto/mem.c | 3 + crypto/openssl/crypto/modes/gcm128.c | 2 +- crypto/openssl/crypto/objects/o_names.c | 2 +- crypto/openssl/crypto/objects/obj_dat.c | 7 +- crypto/openssl/crypto/objects/objects.README | 8 +- crypto/openssl/crypto/ocsp/ocsp_ext.c | 4 +- crypto/openssl/crypto/ocsp/ocsp_vfy.c | 21 +- crypto/openssl/crypto/opensslv.h | 6 +- crypto/openssl/crypto/pem/pem_lib.c | 2 +- crypto/openssl/crypto/pem/pem_pk8.c | 2 + crypto/openssl/crypto/pkcs12/p12_mutl.c | 3 +- crypto/openssl/crypto/pkcs7/pk7_doit.c | 16 +- crypto/openssl/crypto/rsa/rsa_pmeth.c | 8 +- crypto/openssl/crypto/srp/srp_vfy.c | 9 +- crypto/openssl/crypto/threads/th-lock.c | 12 +- crypto/openssl/crypto/x509/x509_lu.c | 2 + crypto/openssl/crypto/x509/x509_vfy.c | 226 ++++++++++----- crypto/openssl/crypto/x509/x509_vfy.h | 6 + crypto/openssl/crypto/x509/x509_vpm.c | 2 + crypto/openssl/crypto/x509/x509type.c | 3 - crypto/openssl/crypto/x509v3/v3_alt.c | 18 +- crypto/openssl/crypto/x509v3/v3_cpols.c | 8 +- crypto/openssl/crypto/x509v3/v3_utl.c | 4 + crypto/openssl/e_os2.h | 8 +- crypto/openssl/engines/ccgost/e_gost_err.c | 3 +- crypto/openssl/engines/ccgost/e_gost_err.h | 1 + crypto/openssl/engines/ccgost/gost2001.c | 229 +++++++++++---- crypto/openssl/engines/ccgost/gost94_keyx.c | 6 +- crypto/openssl/engines/ccgost/gost_ameth.c | 36 ++- crypto/openssl/engines/ccgost/gost_pmeth.c | 2 +- crypto/openssl/engines/ccgost/gost_sign.c | 87 ++++-- crypto/openssl/engines/e_sureware.c | 27 +- crypto/openssl/ssl/d1_both.c | 46 ++- crypto/openssl/ssl/d1_clnt.c | 10 + crypto/openssl/ssl/d1_lib.c | 3 + crypto/openssl/ssl/d1_pkt.c | 2 +- crypto/openssl/ssl/d1_srvr.c | 28 +- crypto/openssl/ssl/s2_pkt.c | 14 + crypto/openssl/ssl/s2_srvr.c | 104 ++++--- crypto/openssl/ssl/s3_both.c | 2 +- crypto/openssl/ssl/s3_cbc.c | 16 +- crypto/openssl/ssl/s3_clnt.c | 273 +++++++++++++++--- crypto/openssl/ssl/s3_pkt.c | 13 +- crypto/openssl/ssl/s3_srvr.c | 230 ++++++++++----- crypto/openssl/ssl/ssl.h | 4 + crypto/openssl/ssl/ssl_err.c | 3 + crypto/openssl/ssl/ssl_lib.c | 8 +- crypto/openssl/ssl/ssl_locl.h | 1 + crypto/openssl/ssl/ssl_sess.c | 131 ++++++++- crypto/openssl/ssl/ssl_stat.c | 6 + crypto/openssl/ssl/t1_enc.c | 9 +- crypto/openssl/ssl/t1_lib.c | 176 +++++------ crypto/openssl/ssl/tls_srp.c | 3 +- 118 files changed, 1749 insertions(+), 689 deletions(-) diff --git a/crypto/openssl/CHANGES b/crypto/openssl/CHANGES index 74179ab872..2565187204 100644 --- a/crypto/openssl/CHANGES +++ b/crypto/openssl/CHANGES @@ -2,6 +2,77 @@ OpenSSL CHANGES _______________ + Changes between 1.0.1m and 1.0.1n [11 Jun 2015] + + *) Malformed ECParameters causes infinite loop + + When processing an ECParameters structure OpenSSL enters an infinite loop + if the curve specified is over a specially malformed binary polynomial + field. + + This can be used to perform denial of service against any + system which processes public keys, certificate requests or + certificates. This includes TLS clients and TLS servers with + client authentication enabled. + + This issue was reported to OpenSSL by Joseph Barr-Pixton. + (CVE-2015-1788) + [Andy Polyakov] + + *) Exploitable out-of-bounds read in X509_cmp_time + + X509_cmp_time does not properly check the length of the ASN1_TIME + string and can read a few bytes out of bounds. In addition, + X509_cmp_time accepts an arbitrary number of fractional seconds in the + time string. + + An attacker can use this to craft malformed certificates and CRLs of + various sizes and potentially cause a segmentation fault, resulting in + a DoS on applications that verify certificates or CRLs. TLS clients + that verify CRLs are affected. TLS clients and servers with client + authentication enabled may be affected if they use custom verification + callbacks. + + This issue was reported to OpenSSL by Robert Swiecki (Google), and + independently by Hanno Böck. + (CVE-2015-1789) + [Emilia Käsper] + + *) PKCS7 crash with missing EnvelopedContent + + The PKCS#7 parsing code does not handle missing inner EncryptedContent + correctly. An attacker can craft malformed ASN.1-encoded PKCS#7 blobs + with missing content and trigger a NULL pointer dereference on parsing. + + Applications that decrypt PKCS#7 data or otherwise parse PKCS#7 + structures from untrusted sources are affected. OpenSSL clients and + servers are not affected. + + This issue was reported to OpenSSL by Michal Zalewski (Google). + (CVE-2015-1790) + [Emilia Käsper] + + *) CMS verify infinite loop with unknown hash function + + When verifying a signedData message the CMS code can enter an infinite loop + if presented with an unknown hash function OID. This can be used to perform + denial of service against any system which verifies signedData messages using + the CMS code. + This issue was reported to OpenSSL by Johannes Bauer. + (CVE-2015-1792) + [Stephen Henson] + + *) Race condition handling NewSessionTicket + + If a NewSessionTicket is received by a multi-threaded client when attempting to + reuse a previous ticket then a race condition can occur potentially leading to + a double free of the ticket data. + (CVE-2015-1791) + [Matt Caswell] + + *) Reject DH handshakes with parameters shorter than 768 bits. + [Kurt Roeckx and Emilia Kasper] + Changes between 1.0.1l and 1.0.1m [19 Mar 2015] *) Segmentation fault in ASN1_TYPE_cmp fix diff --git a/crypto/openssl/NEWS b/crypto/openssl/NEWS index 12616d2c1f..e866e94fa6 100644 --- a/crypto/openssl/NEWS +++ b/crypto/openssl/NEWS @@ -5,6 +5,14 @@ This file gives a brief overview of the major changes between each OpenSSL release. For more details please read the CHANGES file. + Major changes between OpenSSL 1.0.1m and OpenSSL 1.0.1n [11 Jun 2015] + + o Malformed ECParameters causes infinite loop (CVE-2015-1788) + o Exploitable out-of-bounds read in X509_cmp_time (CVE-2015-1789) + o PKCS7 crash with missing EnvelopedContent (CVE-2015-1790) + o CMS verify infinite loop with unknown hash function (CVE-2015-1792) + o Race condition handling NewSessionTicket (CVE-2015-1791) + Major changes between OpenSSL 1.0.1l and OpenSSL 1.0.1m [19 Mar 2015] o Segmentation fault in ASN1_TYPE_cmp fix (CVE-2015-0286) diff --git a/crypto/openssl/README b/crypto/openssl/README index ecdcfb2370..8718a24346 100644 --- a/crypto/openssl/README +++ b/crypto/openssl/README @@ -1,5 +1,5 @@ - OpenSSL 1.0.1m 19 Mar 2015 + OpenSSL 1.0.1n 11 Jun 2015 Copyright (c) 1998-2011 The OpenSSL Project Copyright (c) 1995-1998 Eric A. Young, Tim J. Hudson diff --git a/crypto/openssl/apps/apps.c b/crypto/openssl/apps/apps.c index 9862afde3a..6801238348 100644 --- a/crypto/openssl/apps/apps.c +++ b/crypto/openssl/apps/apps.c @@ -572,7 +572,7 @@ int password_callback(char *buf, int bufsiz, int verify, PW_CB_DATA *cb_tmp) char *prompt = NULL; prompt = UI_construct_prompt(ui, "pass phrase", prompt_info); - if(!prompt) { + if (!prompt) { BIO_printf(bio_err, "Out of memory\n"); UI_free(ui); return 0; @@ -586,7 +586,7 @@ int password_callback(char *buf, int bufsiz, int verify, PW_CB_DATA *cb_tmp) PW_MIN_LENGTH, bufsiz - 1); if (ok >= 0 && verify) { buff = (char *)OPENSSL_malloc(bufsiz); - if(!buff) { + if (!buff) { BIO_printf(bio_err, "Out of memory\n"); UI_free(ui); OPENSSL_free(prompt); @@ -2238,6 +2238,8 @@ int args_verify(char ***pargs, int *pargc, flags |= X509_V_FLAG_NOTIFY_POLICY; else if (!strcmp(arg, "-check_ss_sig")) flags |= X509_V_FLAG_CHECK_SS_SIGNATURE; + else if (!strcmp(arg, "-no_alt_chains")) + flags |= X509_V_FLAG_NO_ALT_CHAINS; else return 0; diff --git a/crypto/openssl/apps/asn1pars.c b/crypto/openssl/apps/asn1pars.c index 7a0f169432..11b0787594 100644 --- a/crypto/openssl/apps/asn1pars.c +++ b/crypto/openssl/apps/asn1pars.c @@ -375,7 +375,7 @@ static int do_generate(BIO *bio, char *genstr, char *genconf, BUF_MEM *buf) { CONF *cnf = NULL; int len; - long errline; + long errline = 0; unsigned char *p; ASN1_TYPE *atyp = NULL; diff --git a/crypto/openssl/apps/ca.c b/crypto/openssl/apps/ca.c index 5d29a64c57..97ad0c1ffe 100644 --- a/crypto/openssl/apps/ca.c +++ b/crypto/openssl/apps/ca.c @@ -558,7 +558,7 @@ int MAIN(int argc, char **argv) #ifdef OPENSSL_SYS_VMS len = strlen(s) + sizeof(CONFIG_FILE); tofree = OPENSSL_malloc(len); - if(!tofree) { + if (!tofree) { BIO_printf(bio_err, "Out of memory\n"); goto err; } @@ -566,7 +566,7 @@ int MAIN(int argc, char **argv) #else len = strlen(s) + sizeof(CONFIG_FILE) + 1; tofree = OPENSSL_malloc(len); - if(!tofree) { + if (!tofree) { BIO_printf(bio_err, "Out of memory\n"); goto err; } @@ -2803,7 +2803,7 @@ int unpack_revinfo(ASN1_TIME **prevtm, int *preason, ASN1_OBJECT **phold, ASN1_GENERALIZEDTIME *comp_time = NULL; tmp = BUF_strdup(str); - if(!tmp) { + if (!tmp) { BIO_printf(bio_err, "memory allocation failure\n"); goto err; } @@ -2825,7 +2825,7 @@ int unpack_revinfo(ASN1_TIME **prevtm, int *preason, ASN1_OBJECT **phold, if (prevtm) { *prevtm = ASN1_UTCTIME_new(); - if(!*prevtm) { + if (!*prevtm) { BIO_printf(bio_err, "memory allocation failure\n"); goto err; } @@ -2869,7 +2869,7 @@ int unpack_revinfo(ASN1_TIME **prevtm, int *preason, ASN1_OBJECT **phold, goto err; } comp_time = ASN1_GENERALIZEDTIME_new(); - if(!comp_time) { + if (!comp_time) { BIO_printf(bio_err, "memory allocation failure\n"); goto err; } diff --git a/crypto/openssl/apps/cms.c b/crypto/openssl/apps/cms.c index 0cc4b46d8e..d7645c0d62 100644 --- a/crypto/openssl/apps/cms.c +++ b/crypto/openssl/apps/cms.c @@ -580,6 +580,8 @@ int MAIN(int argc, char **argv) BIO_printf(bio_err, "-CApath dir trusted certificates directory\n"); BIO_printf(bio_err, "-CAfile file trusted certificates file\n"); + BIO_printf(bio_err, + "-no_alt_chains only ever use the first certificate chain found\n"); BIO_printf(bio_err, "-crl_check check revocation status of signer's certificate using CRLs\n"); BIO_printf(bio_err, diff --git a/crypto/openssl/apps/dhparam.c b/crypto/openssl/apps/dhparam.c index f86311c28f..d3b6d58ad2 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) @@ -254,7 +254,7 @@ int MAIN(int argc, char **argv) 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"); + " 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"); diff --git a/crypto/openssl/apps/enc.c b/crypto/openssl/apps/enc.c index 5c2cf7a4ac..7b7c70b132 100644 --- a/crypto/openssl/apps/enc.c +++ b/crypto/openssl/apps/enc.c @@ -548,9 +548,14 @@ int MAIN(int argc, char **argv) else OPENSSL_cleanse(str, strlen(str)); } - if ((hiv != NULL) && !set_hex(hiv, iv, sizeof iv)) { - BIO_printf(bio_err, "invalid hex iv value\n"); - goto end; + if (hiv != NULL) { + int siz = EVP_CIPHER_iv_length(cipher); + if (siz == 0) { + BIO_printf(bio_err, "warning: iv not use by this cipher\n"); + } else if (!set_hex(hiv, iv, sizeof iv)) { + BIO_printf(bio_err, "invalid hex iv value\n"); + goto end; + } } if ((hiv == NULL) && (str == NULL) && EVP_CIPHER_iv_length(cipher) != 0) { @@ -562,7 +567,7 @@ int MAIN(int argc, char **argv) BIO_printf(bio_err, "iv undefined\n"); goto end; } - if ((hkey != NULL) && !set_hex(hkey, key, sizeof key)) { + if ((hkey != NULL) && !set_hex(hkey, key, EVP_CIPHER_key_length(cipher))) { BIO_printf(bio_err, "invalid hex key value\n"); goto end; } diff --git a/crypto/openssl/apps/gendh.c b/crypto/openssl/apps/gendh.c index adaa101783..fef6f1b177 100644 --- a/crypto/openssl/apps/gendh.c +++ b/crypto/openssl/apps/gendh.c @@ -80,7 +80,7 @@ # include # include -# define DEFBITS 512 +# define DEFBITS 2048 # undef PROG # define PROG gendh_main diff --git a/crypto/openssl/apps/ocsp.c b/crypto/openssl/apps/ocsp.c index 71def2611a..572f0643e1 100644 --- a/crypto/openssl/apps/ocsp.c +++ b/crypto/openssl/apps/ocsp.c @@ -518,6 +518,8 @@ int MAIN(int argc, char **argv) "-CApath dir trusted certificates directory\n"); BIO_printf(bio_err, "-CAfile file trusted certificates file\n"); + BIO_printf(bio_err, + "-no_alt_chains only ever use the first certificate chain found\n"); BIO_printf(bio_err, "-VAfile file validator certificates file\n"); BIO_printf(bio_err, diff --git a/crypto/openssl/apps/s_cb.c b/crypto/openssl/apps/s_cb.c index 7918500a6c..fabf9cfb22 100644 --- a/crypto/openssl/apps/s_cb.c +++ b/crypto/openssl/apps/s_cb.c @@ -111,6 +111,7 @@ #include #include +#include /* for memcpy() */ #define USE_SOCKETS #define NON_MAIN #include "apps.h" @@ -747,7 +748,7 @@ int MS_CALLBACK generate_cookie_callback(SSL *ssl, unsigned char *cookie, /* Initialize a random secret */ if (!cookie_initialized) { - if (!RAND_bytes(cookie_secret, COOKIE_SECRET_LENGTH)) { + if (RAND_bytes(cookie_secret, COOKIE_SECRET_LENGTH) <= 0) { BIO_printf(bio_err, "error setting random cookie secret\n"); return 0; } diff --git a/crypto/openssl/apps/s_client.c b/crypto/openssl/apps/s_client.c index ef41cec1aa..28737b6d1e 100644 --- a/crypto/openssl/apps/s_client.c +++ b/crypto/openssl/apps/s_client.c @@ -322,6 +322,8 @@ static void sc_usage(void) " -pass arg - private key file pass phrase source\n"); BIO_printf(bio_err, " -CApath arg - PEM format directory of CA's\n"); BIO_printf(bio_err, " -CAfile arg - PEM format file of CA's\n"); + BIO_printf(bio_err, + " -no_alt_chains - only ever use the first certificate chain found\n"); BIO_printf(bio_err, " -reconnect - Drop and re-make the connection with the same Session-ID\n"); BIO_printf(bio_err, @@ -547,7 +549,7 @@ static char *MS_CALLBACK ssl_give_srp_client_pwd_cb(SSL *s, void *arg) PW_CB_DATA cb_tmp; int l; - if(!pass) { + if (!pass) { BIO_printf(bio_err, "Malloc failure\n"); return NULL; } @@ -1177,13 +1179,12 @@ int MAIN(int argc, char **argv) if (!set_cert_key_stuff(ctx, cert, key)) goto end; - if ((!SSL_CTX_load_verify_locations(ctx, CAfile, CApath)) || - (!SSL_CTX_set_default_verify_paths(ctx))) { - /* - * BIO_printf(bio_err,"error setting default verify locations\n"); - */ + if ((CAfile || CApath) + && !SSL_CTX_load_verify_locations(ctx, CAfile, CApath)) { + ERR_print_errors(bio_err); + } + if (!SSL_CTX_set_default_verify_paths(ctx)) { ERR_print_errors(bio_err); - /* goto end; */ } #ifndef OPENSSL_NO_TLSEXT if (servername != NULL) { diff --git a/crypto/openssl/apps/s_server.c b/crypto/openssl/apps/s_server.c index bcf5c33137..b58e5e07c4 100644 --- a/crypto/openssl/apps/s_server.c +++ b/crypto/openssl/apps/s_server.c @@ -219,7 +219,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 @@ -227,30 +227,48 @@ 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 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 dh512_g[] = { +static unsigned char dh2048_g[] = { 0x02, }; -static DH *get_dh512(void) +DH *get_dh2048() { - DH *dh = NULL; + DH *dh; 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); + 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 @@ -522,6 +540,8 @@ static void sv_usage(void) BIO_printf(bio_err, " -state - Print the SSL states\n"); BIO_printf(bio_err, " -CApath arg - PEM format directory of CA's\n"); BIO_printf(bio_err, " -CAfile arg - PEM format file of CA's\n"); + BIO_printf(bio_err, + " -no_alt_chains - only ever use the first certificate chain found\n"); BIO_printf(bio_err, " -nocert - Don't use any certificates (Anon-DH)\n"); BIO_printf(bio_err, @@ -720,7 +740,7 @@ static int ebcdic_write(BIO *b, const char *in, int inl) num = inl; wbuf = (EBCDIC_OUTBUFF *) OPENSSL_malloc(sizeof(EBCDIC_OUTBUFF) + num); - if(!wbuf) + if (!wbuf) return 0; OPENSSL_free(b->ptr); @@ -998,7 +1018,7 @@ int MAIN(int argc, char *argv[]) int off = 0; int no_tmp_rsa = 0, no_dhe = 0, nocert = 0; #ifndef OPENSSL_NO_ECDH - int no_ecdhe; + int no_ecdhe = 0; #endif int state = 0; const SSL_METHOD *meth = NULL; @@ -1654,7 +1674,11 @@ int MAIN(int argc, char *argv[]) BIO_printf(bio_s_out, "Setting temp DH parameters\n"); } else { BIO_printf(bio_s_out, "Using default temp DH parameters\n"); - dh = get_dh512(); + dh = get_dh2048(); + if (dh == NULL) { + ERR_print_errors(bio_err); + goto end; + } } (void)BIO_flush(bio_s_out); @@ -2251,8 +2275,10 @@ static int sv_body(char *hostname, int s, unsigned char *context) ret = 1; goto err; } - l += k; - i -= k; + if (k > 0) { + l += k; + i -= k; + } if (i <= 0) break; } @@ -2916,7 +2942,8 @@ static int generate_session_id(const SSL *ssl, unsigned char *id, { unsigned int count = 0; do { - RAND_pseudo_bytes(id, *id_len); + if (RAND_pseudo_bytes(id, *id_len) < 0) + return 0; /* * Prefix the session_id with the required prefix. NB: If our prefix * is too long, clip it - but there will be worse effects anyway, eg. diff --git a/crypto/openssl/apps/s_time.c b/crypto/openssl/apps/s_time.c index a40997a22e..38788f7130 100644 --- a/crypto/openssl/apps/s_time.c +++ b/crypto/openssl/apps/s_time.c @@ -302,7 +302,7 @@ static int parseArgs(int argc, char **argv) if (--argc < 1) goto bad; maxTime = atoi(*(++argv)); - if(maxTime <= 0) { + if (maxTime <= 0) { BIO_printf(bio_err, "time must be > 0\n"); badop = 1; } diff --git a/crypto/openssl/apps/smime.c b/crypto/openssl/apps/smime.c index 7b351f601c..53e43c5e73 100644 --- a/crypto/openssl/apps/smime.c +++ b/crypto/openssl/apps/smime.c @@ -441,6 +441,8 @@ int MAIN(int argc, char **argv) BIO_printf(bio_err, "-CApath dir trusted certificates directory\n"); BIO_printf(bio_err, "-CAfile file trusted certificates file\n"); + BIO_printf(bio_err, + "-no_alt_chains only ever use the first certificate chain found\n"); BIO_printf(bio_err, "-crl_check check revocation status of signer's certificate using CRLs\n"); BIO_printf(bio_err, diff --git a/crypto/openssl/apps/srp.c b/crypto/openssl/apps/srp.c index c679448ee7..c0ff4171ca 100644 --- a/crypto/openssl/apps/srp.c +++ b/crypto/openssl/apps/srp.c @@ -435,7 +435,7 @@ int MAIN(int argc, char **argv) # ifdef OPENSSL_SYS_VMS len = strlen(s) + sizeof(CONFIG_FILE); tofree = OPENSSL_malloc(len); - if(!tofree) { + if (!tofree) { BIO_printf(bio_err, "Out of memory\n"); goto err; } @@ -443,7 +443,7 @@ int MAIN(int argc, char **argv) # else len = strlen(s) + sizeof(CONFIG_FILE) + 1; tofree = OPENSSL_malloc(len); - if(!tofree) { + if (!tofree) { BIO_printf(bio_err, "Out of memory\n"); goto err; } diff --git a/crypto/openssl/apps/verify.c b/crypto/openssl/apps/verify.c index 7295c769f3..e29f9bb7e0 100644 --- a/crypto/openssl/apps/verify.c +++ b/crypto/openssl/apps/verify.c @@ -227,7 +227,7 @@ int MAIN(int argc, char **argv) if (ret == 1) { BIO_printf(bio_err, "usage: verify [-verbose] [-CApath path] [-CAfile file] [-purpose purpose] [-crl_check]"); - BIO_printf(bio_err, " [-attime timestamp]"); + BIO_printf(bio_err, " [-no_alt_chains] [-attime timestamp]"); #ifndef OPENSSL_NO_ENGINE BIO_printf(bio_err, " [-engine e]"); #endif diff --git a/crypto/openssl/crypto/asn1/a_int.c b/crypto/openssl/crypto/asn1/a_int.c index 70c2b8e62c..7e26704a54 100644 --- a/crypto/openssl/crypto/asn1/a_int.c +++ b/crypto/openssl/crypto/asn1/a_int.c @@ -124,6 +124,8 @@ int i2c_ASN1_INTEGER(ASN1_INTEGER *a, unsigned char **pp) else { ret = a->length; i = a->data[0]; + if (ret == 1 && i == 0) + neg = 0; if (!neg && (i > 127)) { pad = 1; pb = 0; @@ -162,7 +164,7 @@ int i2c_ASN1_INTEGER(ASN1_INTEGER *a, unsigned char **pp) p += a->length - 1; i = a->length; /* Copy zeros to destination as long as source is zero */ - while (!*n) { + while (!*n && i > 1) { *(p--) = 0; n--; i--; @@ -419,7 +421,7 @@ ASN1_INTEGER *BN_to_ASN1_INTEGER(const BIGNUM *bn, ASN1_INTEGER *ai) ASN1err(ASN1_F_BN_TO_ASN1_INTEGER, ERR_R_NESTED_ASN1_ERROR); goto err; } - if (BN_is_negative(bn)) + if (BN_is_negative(bn) && !BN_is_zero(bn)) ret->type = V_ASN1_NEG_INTEGER; else ret->type = V_ASN1_INTEGER; diff --git a/crypto/openssl/crypto/asn1/asn1_gen.c b/crypto/openssl/crypto/asn1/asn1_gen.c index 11b582dd37..65749239b1 100644 --- a/crypto/openssl/crypto/asn1/asn1_gen.c +++ b/crypto/openssl/crypto/asn1/asn1_gen.c @@ -74,6 +74,8 @@ #define ASN1_GEN_STR(str,val) {str, sizeof(str) - 1, val} #define ASN1_FLAG_EXP_MAX 20 +/* Maximum number of nested sequences */ +#define ASN1_GEN_SEQ_MAX_DEPTH 50 /* Input formats */ @@ -110,13 +112,16 @@ typedef struct { int exp_count; } tag_exp_arg; +static ASN1_TYPE *generate_v3(char *str, X509V3_CTX *cnf, int depth, + int *perr); static int bitstr_cb(const char *elem, int len, void *bitstr); static int asn1_cb(const char *elem, int len, void *bitstr); static int append_exp(tag_exp_arg *arg, int exp_tag, int exp_class, int exp_constructed, int exp_pad, int imp_ok); static int parse_tagging(const char *vstart, int vlen, int *ptag, int *pclass); -static ASN1_TYPE *asn1_multi(int utype, const char *section, X509V3_CTX *cnf); +static ASN1_TYPE *asn1_multi(int utype, const char *section, X509V3_CTX *cnf, + int depth, int *perr); static ASN1_TYPE *asn1_str2type(const char *str, int format, int utype); static int asn1_str2tag(const char *tagstr, int len); @@ -132,6 +137,16 @@ ASN1_TYPE *ASN1_generate_nconf(char *str, CONF *nconf) } ASN1_TYPE *ASN1_generate_v3(char *str, X509V3_CTX *cnf) +{ + int err = 0; + ASN1_TYPE *ret = generate_v3(str, cnf, 0, &err); + if (err) + ASN1err(ASN1_F_ASN1_GENERATE_V3, err); + return ret; +} + +static ASN1_TYPE *generate_v3(char *str, X509V3_CTX *cnf, int depth, + int *perr) { ASN1_TYPE *ret; tag_exp_arg asn1_tags; @@ -152,17 +167,22 @@ ASN1_TYPE *ASN1_generate_v3(char *str, X509V3_CTX *cnf) asn1_tags.imp_class = -1; asn1_tags.format = ASN1_GEN_FORMAT_ASCII; asn1_tags.exp_count = 0; - if (CONF_parse_list(str, ',', 1, asn1_cb, &asn1_tags) != 0) + if (CONF_parse_list(str, ',', 1, asn1_cb, &asn1_tags) != 0) { + *perr = ASN1_R_UNKNOWN_TAG; return NULL; + } if ((asn1_tags.utype == V_ASN1_SEQUENCE) || (asn1_tags.utype == V_ASN1_SET)) { if (!cnf) { - ASN1err(ASN1_F_ASN1_GENERATE_V3, - ASN1_R_SEQUENCE_OR_SET_NEEDS_CONFIG); + *perr = ASN1_R_SEQUENCE_OR_SET_NEEDS_CONFIG; return NULL; } - ret = asn1_multi(asn1_tags.utype, asn1_tags.str, cnf); + if (depth >= ASN1_GEN_SEQ_MAX_DEPTH) { + *perr = ASN1_R_ILLEGAL_NESTED_TAGGING; + return NULL; + } + ret = asn1_multi(asn1_tags.utype, asn1_tags.str, cnf, depth, perr); } else ret = asn1_str2type(asn1_tags.str, asn1_tags.format, asn1_tags.utype); @@ -280,7 +300,7 @@ static int asn1_cb(const char *elem, int len, void *bitstr) int tmp_tag, tmp_class; if (elem == NULL) - return 0; + return -1; for (i = 0, p = elem; i < len; p++, i++) { /* Look for the ':' in name value pairs */ @@ -353,7 +373,7 @@ static int asn1_cb(const char *elem, int len, void *bitstr) break; case ASN1_GEN_FLAG_FORMAT: - if(!vstart) { + if (!vstart) { ASN1err(ASN1_F_ASN1_CB, ASN1_R_UNKNOWN_FORMAT); return -1; } @@ -435,7 +455,8 @@ static int parse_tagging(const char *vstart, int vlen, int *ptag, int *pclass) /* Handle multiple types: SET and SEQUENCE */ -static ASN1_TYPE *asn1_multi(int utype, const char *section, X509V3_CTX *cnf) +static ASN1_TYPE *asn1_multi(int utype, const char *section, X509V3_CTX *cnf, + int depth, int *perr) { ASN1_TYPE *ret = NULL; STACK_OF(ASN1_TYPE) *sk = NULL; @@ -454,7 +475,8 @@ static ASN1_TYPE *asn1_multi(int utype, const char *section, X509V3_CTX *cnf) goto bad; for (i = 0; i < sk_CONF_VALUE_num(sect); i++) { ASN1_TYPE *typ = - ASN1_generate_v3(sk_CONF_VALUE_value(sect, i)->value, cnf); + generate_v3(sk_CONF_VALUE_value(sect, i)->value, cnf, + depth + 1, perr); if (!typ) goto bad; if (!sk_ASN1_TYPE_push(sk, typ)) diff --git a/crypto/openssl/crypto/asn1/asn_mime.c b/crypto/openssl/crypto/asn1/asn_mime.c index 7e2f28e6d5..96110c540f 100644 --- a/crypto/openssl/crypto/asn1/asn_mime.c +++ b/crypto/openssl/crypto/asn1/asn_mime.c @@ -289,7 +289,8 @@ int SMIME_write_ASN1(BIO *bio, ASN1_VALUE *val, BIO *data, int flags, if ((flags & SMIME_DETACHED) && data) { /* We want multipart/signed */ /* Generate a random boundary */ - RAND_pseudo_bytes((unsigned char *)bound, 32); + if (RAND_pseudo_bytes((unsigned char *)bound, 32) < 0) + return 0; for (i = 0; i < 32; i++) { c = bound[i] & 0xf; if (c < 10) diff --git a/crypto/openssl/crypto/asn1/bio_ndef.c b/crypto/openssl/crypto/asn1/bio_ndef.c index 4a73ca9eac..31949b8794 100644 --- a/crypto/openssl/crypto/asn1/bio_ndef.c +++ b/crypto/openssl/crypto/asn1/bio_ndef.c @@ -162,7 +162,7 @@ static int ndef_prefix(BIO *b, unsigned char **pbuf, int *plen, void *parg) derlen = ASN1_item_ndef_i2d(ndef_aux->val, NULL, ndef_aux->it); p = OPENSSL_malloc(derlen); - if(!p) + if (!p) return 0; ndef_aux->derbuf = p; @@ -232,7 +232,7 @@ static int ndef_suffix(BIO *b, unsigned char **pbuf, int *plen, void *parg) derlen = ASN1_item_ndef_i2d(ndef_aux->val, NULL, ndef_aux->it); p = OPENSSL_malloc(derlen); - if(!p) + if (!p) return 0; ndef_aux->derbuf = p; diff --git a/crypto/openssl/crypto/asn1/tasn_new.c b/crypto/openssl/crypto/asn1/tasn_new.c index 7d2964f023..b0c73beeb5 100644 --- a/crypto/openssl/crypto/asn1/tasn_new.c +++ b/crypto/openssl/crypto/asn1/tasn_new.c @@ -100,9 +100,6 @@ static int asn1_item_ex_combine_new(ASN1_VALUE **pval, const ASN1_ITEM *it, else asn1_cb = 0; - if (!combine) - *pval = NULL; - #ifdef CRYPTO_MDEBUG if (it->sname) CRYPTO_push_info(it->sname); diff --git a/crypto/openssl/crypto/asn1/tasn_prn.c b/crypto/openssl/crypto/asn1/tasn_prn.c index 7c54f9d1d4..5e7d53e985 100644 --- a/crypto/openssl/crypto/asn1/tasn_prn.c +++ b/crypto/openssl/crypto/asn1/tasn_prn.c @@ -290,7 +290,7 @@ static int asn1_item_print_ctx(BIO *out, ASN1_VALUE **fld, int indent, for (i = 0, tt = it->templates; i < it->tcount; i++, tt++) { const ASN1_TEMPLATE *seqtt; seqtt = asn1_do_adb(fld, tt, 1); - if(!seqtt) + if (!seqtt) return 0; tmpfld = asn1_get_field_ptr(fld, seqtt); if (!asn1_template_print_ctx(out, tmpfld, diff --git a/crypto/openssl/crypto/asn1/x_x509.c b/crypto/openssl/crypto/asn1/x_x509.c index d51b76e79e..f56e837b3a 100644 --- a/crypto/openssl/crypto/asn1/x_x509.c +++ b/crypto/openssl/crypto/asn1/x_x509.c @@ -177,7 +177,7 @@ X509 *d2i_X509_AUX(X509 **a, const unsigned char **pp, long length) /* Save start position */ q = *pp; - if(!a || *a == NULL) { + if (!a || *a == NULL) { freeret = 1; } ret = d2i_X509(a, pp, length); @@ -192,7 +192,7 @@ X509 *d2i_X509_AUX(X509 **a, const unsigned char **pp, long length) goto err; return ret; err: - if(freeret) { + if (freeret) { X509_free(ret); if (a) *a = NULL; diff --git a/crypto/openssl/crypto/bio/b_print.c b/crypto/openssl/crypto/bio/b_print.c index c2cf6e619e..7c81e25d48 100644 --- a/crypto/openssl/crypto/bio/b_print.c +++ b/crypto/openssl/crypto/bio/b_print.c @@ -704,32 +704,29 @@ doapr_outch(char **sbuffer, /* 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(!*buffer) { - /* Panic! Can't really do anything sensible. Just return */ - return; - } - if (*currlen > 0) { - assert(*sbuffer != NULL); - memcpy(*buffer, *sbuffer, *currlen); - } - *sbuffer = NULL; - } else { - *maxlen += 1024; - *buffer = OPENSSL_realloc(*buffer, *maxlen); - if(!*buffer) { - /* Panic! Can't really do anything sensible. Just return */ - return; - } + /* |currlen| must always be <= |*maxlen| */ + assert(*currlen <= *maxlen); + + if (buffer && *currlen == *maxlen) { + *maxlen += 1024; + if (*buffer == NULL) { + *buffer = OPENSSL_malloc(*maxlen); + if (!*buffer) { + /* Panic! Can't really do anything sensible. Just return */ + return; + } + if (*currlen > 0) { + assert(*sbuffer != NULL); + memcpy(*buffer, *sbuffer, *currlen); + } + *sbuffer = NULL; + } else { + *buffer = OPENSSL_realloc(*buffer, *maxlen); + if (!*buffer) { + /* Panic! Can't really do anything sensible. Just return */ + return; } } - /* What to do if *buffer is NULL? */ - assert(*sbuffer != NULL || *buffer != NULL); } if (*currlen < *maxlen) { diff --git a/crypto/openssl/crypto/bio/bf_nbio.c b/crypto/openssl/crypto/bio/bf_nbio.c index da88a8a1bf..a04f32a008 100644 --- a/crypto/openssl/crypto/bio/bf_nbio.c +++ b/crypto/openssl/crypto/bio/bf_nbio.c @@ -139,7 +139,8 @@ static int nbiof_read(BIO *b, char *out, int outl) BIO_clear_retry_flags(b); #if 1 - RAND_pseudo_bytes(&n, 1); + if (RAND_pseudo_bytes(&n, 1) < 0) + return -1; num = (n & 0x07); if (outl > num) @@ -178,7 +179,8 @@ static int nbiof_write(BIO *b, const char *in, int inl) num = nt->lwn; nt->lwn = 0; } else { - RAND_pseudo_bytes(&n, 1); + if (RAND_pseudo_bytes(&n, 1) < 0) + return -1; num = (n & 7); } diff --git a/crypto/openssl/crypto/bio/bio_lib.c b/crypto/openssl/crypto/bio/bio_lib.c index 5267010cb0..07934f8a66 100644 --- a/crypto/openssl/crypto/bio/bio_lib.c +++ b/crypto/openssl/crypto/bio/bio_lib.c @@ -536,8 +536,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) { eoc = new_bio; @@ -549,8 +551,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/bio/bss_dgram.c b/crypto/openssl/crypto/bio/bss_dgram.c index b495db26e1..e3e3dd0503 100644 --- a/crypto/openssl/crypto/bio/bss_dgram.c +++ b/crypto/openssl/crypto/bio/bss_dgram.c @@ -299,16 +299,17 @@ static void dgram_adjust_rcv_timeout(BIO *b) /* Calculate time left until timer expires */ memcpy(&timeleft, &(data->next_timeout), sizeof(struct timeval)); - timeleft.tv_sec -= timenow.tv_sec; - timeleft.tv_usec -= timenow.tv_usec; - if (timeleft.tv_usec < 0) { + if (timeleft.tv_usec < timenow.tv_usec) { + timeleft.tv_usec = 1000000 - timenow.tv_usec + timeleft.tv_usec; timeleft.tv_sec--; - timeleft.tv_usec += 1000000; + } else { + timeleft.tv_usec -= timenow.tv_usec; } - - if (timeleft.tv_sec < 0) { + if (timeleft.tv_sec < timenow.tv_sec) { timeleft.tv_sec = 0; timeleft.tv_usec = 1; + } else { + timeleft.tv_sec -= timenow.tv_sec; } /* @@ -953,7 +954,7 @@ BIO *BIO_new_dgram_sctp(int fd, int close_flag) */ sockopt_len = (socklen_t) (sizeof(sctp_assoc_t) + 256 * sizeof(uint8_t)); authchunks = OPENSSL_malloc(sockopt_len); - if(!authchunks) { + if (!authchunks) { BIO_vfree(bio); return (NULL); } @@ -1293,7 +1294,7 @@ static int dgram_sctp_read(BIO *b, char *out, int outl) (socklen_t) (sizeof(sctp_assoc_t) + 256 * sizeof(uint8_t)); authchunks = OPENSSL_malloc(optlen); if (!authchunks) { - BIOerr(BIO_F_DGRAM_SCTP_READ, ERR_R_MALLOC_ERROR); + BIOerr(BIO_F_DGRAM_SCTP_READ, ERR_R_MALLOC_FAILURE); return -1; } memset(authchunks, 0, sizeof(optlen)); @@ -1364,8 +1365,8 @@ static int dgram_sctp_write(BIO *b, const char *in, int inl) if (data->save_shutdown && !BIO_dgram_sctp_wait_for_dry(b)) { char *tmp; data->saved_message.bio = b; - if(!(tmp = OPENSSL_malloc(inl))) { - BIOerr(BIO_F_DGRAM_SCTP_WRITE, ERR_R_MALLOC_ERROR); + if (!(tmp = OPENSSL_malloc(inl))) { + BIOerr(BIO_F_DGRAM_SCTP_WRITE, ERR_R_MALLOC_FAILURE); return -1; } if (data->saved_message.data) diff --git a/crypto/openssl/crypto/bn/bn.h b/crypto/openssl/crypto/bn/bn.h index 7d57e9834a..47d8c71d9e 100644 --- a/crypto/openssl/crypto/bn/bn.h +++ b/crypto/openssl/crypto/bn/bn.h @@ -797,6 +797,7 @@ int RAND_pseudo_bytes(unsigned char *buf, int num); * wouldn't be constructed with top!=dmax. */ \ BN_ULONG *_not_const; \ memcpy(&_not_const, &_bnum1->d, sizeof(BN_ULONG*)); \ + /* Debug only - safe to ignore error return */ \ RAND_pseudo_bytes(&_tmp_char, 1); \ memset((unsigned char *)(_not_const + _bnum1->top), _tmp_char, \ (_bnum1->dmax - _bnum1->top) * sizeof(BN_ULONG)); \ @@ -910,6 +911,7 @@ void ERR_load_BN_strings(void); # define BN_F_BN_GF2M_MOD_SOLVE_QUAD_ARR 135 # define BN_F_BN_GF2M_MOD_SQR 136 # define BN_F_BN_GF2M_MOD_SQRT 137 +# define BN_F_BN_LSHIFT 145 # define BN_F_BN_MOD_EXP2_MONT 118 # define BN_F_BN_MOD_EXP_MONT 109 # define BN_F_BN_MOD_EXP_MONT_CONSTTIME 124 @@ -925,12 +927,14 @@ void ERR_load_BN_strings(void); # define BN_F_BN_NEW 113 # define BN_F_BN_RAND 114 # define BN_F_BN_RAND_RANGE 122 +# define BN_F_BN_RSHIFT 146 # define BN_F_BN_USUB 115 /* Reason codes. */ # define BN_R_ARG2_LT_ARG3 100 # define BN_R_BAD_RECIPROCAL 101 # define BN_R_BIGNUM_TOO_LONG 114 +# define BN_R_BITS_TOO_SMALL 118 # define BN_R_CALLED_WITH_EVEN_MODULUS 102 # define BN_R_DIV_BY_ZERO 103 # define BN_R_ENCODING_ERROR 104 @@ -938,6 +942,7 @@ void ERR_load_BN_strings(void); # define BN_R_INPUT_NOT_REDUCED 110 # define BN_R_INVALID_LENGTH 106 # define BN_R_INVALID_RANGE 115 +# define BN_R_INVALID_SHIFT 119 # define BN_R_NOT_A_SQUARE 111 # define BN_R_NOT_INITIALIZED 107 # define BN_R_NO_INVERSE 108 diff --git a/crypto/openssl/crypto/bn/bn_err.c b/crypto/openssl/crypto/bn/bn_err.c index faa7e226ba..e7a703826e 100644 --- a/crypto/openssl/crypto/bn/bn_err.c +++ b/crypto/openssl/crypto/bn/bn_err.c @@ -1,6 +1,6 @@ /* crypto/bn/bn_err.c */ /* ==================================================================== - * Copyright (c) 1999-2007 The OpenSSL Project. All rights reserved. + * Copyright (c) 1999-2015 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 @@ -94,6 +94,7 @@ static ERR_STRING_DATA BN_str_functs[] = { {ERR_FUNC(BN_F_BN_GF2M_MOD_SOLVE_QUAD_ARR), "BN_GF2m_mod_solve_quad_arr"}, {ERR_FUNC(BN_F_BN_GF2M_MOD_SQR), "BN_GF2m_mod_sqr"}, {ERR_FUNC(BN_F_BN_GF2M_MOD_SQRT), "BN_GF2m_mod_sqrt"}, + {ERR_FUNC(BN_F_BN_LSHIFT), "BN_lshift"}, {ERR_FUNC(BN_F_BN_MOD_EXP2_MONT), "BN_mod_exp2_mont"}, {ERR_FUNC(BN_F_BN_MOD_EXP_MONT), "BN_mod_exp_mont"}, {ERR_FUNC(BN_F_BN_MOD_EXP_MONT_CONSTTIME), "BN_mod_exp_mont_consttime"}, @@ -109,6 +110,7 @@ static ERR_STRING_DATA BN_str_functs[] = { {ERR_FUNC(BN_F_BN_NEW), "BN_new"}, {ERR_FUNC(BN_F_BN_RAND), "BN_rand"}, {ERR_FUNC(BN_F_BN_RAND_RANGE), "BN_rand_range"}, + {ERR_FUNC(BN_F_BN_RSHIFT), "BN_rshift"}, {ERR_FUNC(BN_F_BN_USUB), "BN_usub"}, {0, NULL} }; @@ -117,6 +119,7 @@ static ERR_STRING_DATA BN_str_reasons[] = { {ERR_REASON(BN_R_ARG2_LT_ARG3), "arg2 lt arg3"}, {ERR_REASON(BN_R_BAD_RECIPROCAL), "bad reciprocal"}, {ERR_REASON(BN_R_BIGNUM_TOO_LONG), "bignum too long"}, + {ERR_REASON(BN_R_BITS_TOO_SMALL), "bits too small"}, {ERR_REASON(BN_R_CALLED_WITH_EVEN_MODULUS), "called with even modulus"}, {ERR_REASON(BN_R_DIV_BY_ZERO), "div by zero"}, {ERR_REASON(BN_R_ENCODING_ERROR), "encoding error"}, @@ -125,6 +128,7 @@ static ERR_STRING_DATA BN_str_reasons[] = { {ERR_REASON(BN_R_INPUT_NOT_REDUCED), "input not reduced"}, {ERR_REASON(BN_R_INVALID_LENGTH), "invalid length"}, {ERR_REASON(BN_R_INVALID_RANGE), "invalid range"}, + {ERR_REASON(BN_R_INVALID_SHIFT), "invalid shift"}, {ERR_REASON(BN_R_NOT_A_SQUARE), "not a square"}, {ERR_REASON(BN_R_NOT_INITIALIZED), "not initialized"}, {ERR_REASON(BN_R_NO_INVERSE), "no inverse"}, diff --git a/crypto/openssl/crypto/bn/bn_gf2m.c b/crypto/openssl/crypto/bn/bn_gf2m.c index aeee49a015..a0ba8de31a 100644 --- a/crypto/openssl/crypto/bn/bn_gf2m.c +++ b/crypto/openssl/crypto/bn/bn_gf2m.c @@ -694,9 +694,10 @@ 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; + 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); @@ -740,8 +741,12 @@ int BN_GF2m_mod_inv(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx) ubits--; } - if (ubits <= BN_BITS2 && udp[0] == 1) - break; + if (ubits <= BN_BITS2) { + if (udp[0] == 0) /* poly was reducible */ + goto err; + if (udp[0] == 1) + break; + } if (ubits < vbits) { i = ubits; diff --git a/crypto/openssl/crypto/bn/bn_lcl.h b/crypto/openssl/crypto/bn/bn_lcl.h index 1059d1d4b5..904a723497 100644 --- a/crypto/openssl/crypto/bn/bn_lcl.h +++ b/crypto/openssl/crypto/bn/bn_lcl.h @@ -276,7 +276,7 @@ unsigned __int64 _umul128(unsigned __int64 a, unsigned __int64 b, # endif # elif defined(__mips) && (defined(SIXTY_FOUR_BIT) || defined(SIXTY_FOUR_BIT_LONG)) # if defined(__GNUC__) && __GNUC__>=2 -# if __GNUC__>=4 && __GNUC_MINOR__>=4 +# if __GNUC__>4 || (__GNUC__>=4 && __GNUC_MINOR__>=4) /* "h" constraint is no more since 4.4 */ # define BN_UMULT_HIGH(a,b) (((__uint128_t)(a)*(b))>>64) # define BN_UMULT_LOHI(low,high,a,b) ({ \ diff --git a/crypto/openssl/crypto/bn/bn_print.c b/crypto/openssl/crypto/bn/bn_print.c index 4dcaae32bf..ab10b957ba 100644 --- a/crypto/openssl/crypto/bn/bn_print.c +++ b/crypto/openssl/crypto/bn/bn_print.c @@ -71,7 +71,12 @@ char *BN_bn2hex(const BIGNUM *a) char *buf; char *p; - buf = (char *)OPENSSL_malloc(a->top * 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); goto err; diff --git a/crypto/openssl/crypto/bn/bn_rand.c b/crypto/openssl/crypto/bn/bn_rand.c index 7ac71ec8ed..f9fb2e9e45 100644 --- a/crypto/openssl/crypto/bn/bn_rand.c +++ b/crypto/openssl/crypto/bn/bn_rand.c @@ -121,6 +121,11 @@ static int bnrand(int pseudorand, BIGNUM *rnd, int bits, int top, int bottom) int ret = 0, bit, bytes, mask; time_t tim; + if (bits < 0 || (bits == 1 && top > 0)) { + BNerr(BN_F_BNRAND, BN_R_BITS_TOO_SMALL); + return 0; + } + if (bits == 0) { BN_zero(rnd); return 1; @@ -157,7 +162,8 @@ static int bnrand(int pseudorand, BIGNUM *rnd, int bits, int top, int bottom) unsigned char c; for (i = 0; i < bytes; i++) { - RAND_pseudo_bytes(&c, 1); + if (RAND_pseudo_bytes(&c, 1) < 0) + goto err; if (c >= 128 && i > 0) buf[i] = buf[i - 1]; else if (c < 42) @@ -168,7 +174,7 @@ static int bnrand(int pseudorand, BIGNUM *rnd, int bits, int top, int bottom) } #endif - if (top != -1) { + if (top >= 0) { if (top) { if (bit == 0) { buf[0] = 1; diff --git a/crypto/openssl/crypto/bn/bn_shift.c b/crypto/openssl/crypto/bn/bn_shift.c index 4f3e8ffed7..9673d9a306 100644 --- a/crypto/openssl/crypto/bn/bn_shift.c +++ b/crypto/openssl/crypto/bn/bn_shift.c @@ -137,6 +137,11 @@ int BN_lshift(BIGNUM *r, const BIGNUM *a, int n) bn_check_top(r); bn_check_top(a); + if (n < 0) { + BNerr(BN_F_BN_LSHIFT, BN_R_INVALID_SHIFT); + return 0; + } + r->neg = a->neg; nw = n / BN_BITS2; if (bn_wexpand(r, a->top + nw + 1) == NULL) @@ -174,6 +179,11 @@ int BN_rshift(BIGNUM *r, const BIGNUM *a, int n) bn_check_top(r); bn_check_top(a); + if (n < 0) { + BNerr(BN_F_BN_RSHIFT, BN_R_INVALID_SHIFT); + return 0; + } + nw = n / BN_BITS2; rb = n % BN_BITS2; lb = BN_BITS2 - rb; diff --git a/crypto/openssl/crypto/buffer/buffer.c b/crypto/openssl/crypto/buffer/buffer.c index d287e340a2..eff3e08157 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) return; 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/cmac/cmac.c b/crypto/openssl/crypto/cmac/cmac.c index c5597a3f73..774e6dc919 100644 --- a/crypto/openssl/crypto/cmac/cmac.c +++ b/crypto/openssl/crypto/cmac/cmac.c @@ -126,6 +126,8 @@ EVP_CIPHER_CTX *CMAC_CTX_get0_cipher_ctx(CMAC_CTX *ctx) void CMAC_CTX_free(CMAC_CTX *ctx) { + if (!ctx) + return; CMAC_CTX_cleanup(ctx); OPENSSL_free(ctx); } diff --git a/crypto/openssl/crypto/cms/cms_pwri.c b/crypto/openssl/crypto/cms/cms_pwri.c index 076b545789..a8322dcdf1 100644 --- a/crypto/openssl/crypto/cms/cms_pwri.c +++ b/crypto/openssl/crypto/cms/cms_pwri.c @@ -231,7 +231,7 @@ static int kek_unwrap_key(unsigned char *out, size_t *outlen, return 0; } tmp = OPENSSL_malloc(inlen); - if(!tmp) + if (!tmp) return 0; /* setup IV by decrypting last two blocks */ EVP_DecryptUpdate(ctx, tmp + inlen - 2 * blocklen, &outl, @@ -297,8 +297,9 @@ static int kek_wrap_key(unsigned char *out, size_t *outlen, out[3] = in[2] ^ 0xFF; memcpy(out + 4, in, inlen); /* Add random padding to end */ - if (olen > inlen + 4) - RAND_pseudo_bytes(out + 4 + inlen, olen - 4 - inlen); + if (olen > inlen + 4 + && RAND_pseudo_bytes(out + 4 + inlen, olen - 4 - inlen) < 0) + return 0; /* Encrypt twice */ EVP_EncryptUpdate(ctx, out, &dummy, out, olen); EVP_EncryptUpdate(ctx, out, &dummy, out, olen); diff --git a/crypto/openssl/crypto/cms/cms_smime.c b/crypto/openssl/crypto/cms/cms_smime.c index 8851603f6f..8b37560821 100644 --- a/crypto/openssl/crypto/cms/cms_smime.c +++ b/crypto/openssl/crypto/cms/cms_smime.c @@ -131,7 +131,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/cryptlib.c b/crypto/openssl/crypto/cryptlib.c index 6353bbe3bc..c654a5c84f 100644 --- a/crypto/openssl/crypto/cryptlib.c +++ b/crypto/openssl/crypto/cryptlib.c @@ -806,8 +806,6 @@ int OPENSSL_isservice(void) if (_OPENSSL_isservice.p != (void *)-1) return (*_OPENSSL_isservice.f) (); - (void)GetDesktopWindow(); /* return value is ignored */ - h = GetProcessWindowStation(); if (h == NULL) return -1; diff --git a/crypto/openssl/crypto/des/enc_writ.c b/crypto/openssl/crypto/des/enc_writ.c index b4eecc3812..bfaabde516 100644 --- a/crypto/openssl/crypto/des/enc_writ.c +++ b/crypto/openssl/crypto/des/enc_writ.c @@ -96,6 +96,9 @@ int DES_enc_write(int fd, const void *_buf, int len, const unsigned char *cp; static int start = 1; + if (len < 0) + return -1; + if (outbuf == NULL) { outbuf = OPENSSL_malloc(BSIZE + HDRSIZE); if (outbuf == NULL) @@ -132,7 +135,9 @@ int DES_enc_write(int fd, const void *_buf, int len, if (len < 8) { cp = shortbuf; memcpy(shortbuf, buf, len); - RAND_pseudo_bytes(shortbuf + len, 8 - len); + if (RAND_pseudo_bytes(shortbuf + len, 8 - len) < 0) { + return -1; + } rnum = 8; } else { cp = buf; diff --git a/crypto/openssl/crypto/dh/dh_ameth.c b/crypto/openssl/crypto/dh/dh_ameth.c index 1dec109835..873eb2e22d 100644 --- a/crypto/openssl/crypto/dh/dh_ameth.c +++ b/crypto/openssl/crypto/dh/dh_ameth.c @@ -135,7 +135,7 @@ static int dh_pub_encode(X509_PUBKEY *pk, const EVP_PKEY *pkey) dh = pkey->pkey.dh; str = ASN1_STRING_new(); - if(!str) { + if (!str) { DHerr(DH_F_DH_PUB_ENCODE, ERR_R_MALLOC_FAILURE); goto err; } diff --git a/crypto/openssl/crypto/dsa/dsa_gen.c b/crypto/openssl/crypto/dsa/dsa_gen.c index c808ab6097..d686ab0af7 100644 --- a/crypto/openssl/crypto/dsa/dsa_gen.c +++ b/crypto/openssl/crypto/dsa/dsa_gen.c @@ -202,7 +202,8 @@ int dsa_builtin_paramgen(DSA *ret, size_t bits, size_t qbits, goto err; if (!seed_len) { - RAND_pseudo_bytes(seed, qsize); + if (RAND_pseudo_bytes(seed, qsize) < 0) + goto err; seed_is_random = 1; } else { seed_is_random = 0; diff --git a/crypto/openssl/crypto/dsa/dsa_ossl.c b/crypto/openssl/crypto/dsa/dsa_ossl.c index b30eab0319..6edb26d973 100644 --- a/crypto/openssl/crypto/dsa/dsa_ossl.c +++ b/crypto/openssl/crypto/dsa/dsa_ossl.c @@ -106,23 +106,23 @@ static DSA_METHOD openssl_dsa_meth = { #define DSA_MOD_EXP(err_instr,dsa,rr,a1,p1,a2,p2,m,ctx,in_mont) \ do { \ int _tmp_res53; \ - if((dsa)->meth->dsa_mod_exp) \ + if ((dsa)->meth->dsa_mod_exp) \ _tmp_res53 = (dsa)->meth->dsa_mod_exp((dsa), (rr), (a1), (p1), \ (a2), (p2), (m), (ctx), (in_mont)); \ else \ _tmp_res53 = BN_mod_exp2_mont((rr), (a1), (p1), (a2), (p2), \ (m), (ctx), (in_mont)); \ - if(!_tmp_res53) err_instr; \ + if (!_tmp_res53) err_instr; \ } while(0) #define DSA_BN_MOD_EXP(err_instr,dsa,r,a,p,m,ctx,m_ctx) \ do { \ int _tmp_res53; \ - if((dsa)->meth->bn_mod_exp) \ + if ((dsa)->meth->bn_mod_exp) \ _tmp_res53 = (dsa)->meth->bn_mod_exp((dsa), (r), (a), (p), \ (m), (ctx), (m_ctx)); \ else \ _tmp_res53 = BN_mod_exp_mont((r), (a), (p), (m), (ctx), (m_ctx)); \ - if(!_tmp_res53) err_instr; \ + if (!_tmp_res53) err_instr; \ } while(0) const DSA_METHOD *DSA_OpenSSL(void) diff --git a/crypto/openssl/crypto/dso/dso_lib.c b/crypto/openssl/crypto/dso/dso_lib.c index d2a48bb664..09b8eafcca 100644 --- a/crypto/openssl/crypto/dso/dso_lib.c +++ b/crypto/openssl/crypto/dso/dso_lib.c @@ -285,7 +285,7 @@ DSO_FUNC_TYPE DSO_bind_func(DSO *dso, const char *symname) * honest. For one thing, I think I have to return a negative value for any * error because possible DSO_ctrl() commands may return values such as * "size"s that can legitimately be zero (making the standard - * "if(DSO_cmd(...))" form that works almost everywhere else fail at odd + * "if (DSO_cmd(...))" form that works almost everywhere else fail at odd * times. I'd prefer "output" values to be passed by reference and the return * value as success/failure like usual ... but we conform when we must... :-) */ diff --git a/crypto/openssl/crypto/ec/ec2_oct.c b/crypto/openssl/crypto/ec/ec2_oct.c index c245d886da..0d04cc6923 100644 --- a/crypto/openssl/crypto/ec/ec2_oct.c +++ b/crypto/openssl/crypto/ec/ec2_oct.c @@ -387,7 +387,7 @@ int ec_GF2m_simple_oct2point(const EC_GROUP *group, EC_POINT *point, } /* test required by X9.62 */ - if (!EC_POINT_is_on_curve(group, point, ctx)) { + 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_asn1.c b/crypto/openssl/crypto/ec/ec_asn1.c index b4b0e9f3b8..4ad8494981 100644 --- a/crypto/openssl/crypto/ec/ec_asn1.c +++ b/crypto/openssl/crypto/ec/ec_asn1.c @@ -1114,7 +1114,7 @@ int i2d_ECPrivateKey(EC_KEY *a, unsigned char **out) { int ret = 0, ok = 0; unsigned char *buffer = NULL; - size_t buf_len = 0, tmp_len; + size_t buf_len = 0, tmp_len, bn_len; EC_PRIVATEKEY *priv_key = NULL; if (a == NULL || a->group == NULL || a->priv_key == NULL || @@ -1130,18 +1130,32 @@ int i2d_ECPrivateKey(EC_KEY *a, unsigned char **out) priv_key->version = a->version; - buf_len = (size_t)BN_num_bytes(a->priv_key); + bn_len = (size_t)BN_num_bytes(a->priv_key); + + /* Octetstring may need leading zeros if BN is to short */ + + buf_len = (EC_GROUP_get_degree(a->group) + 7) / 8; + + if (bn_len > buf_len) { + ECerr(EC_F_I2D_ECPRIVATEKEY, EC_R_BUFFER_TOO_SMALL); + goto err; + } + buffer = OPENSSL_malloc(buf_len); if (buffer == NULL) { ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_MALLOC_FAILURE); goto err; } - if (!BN_bn2bin(a->priv_key, buffer)) { + if (!BN_bn2bin(a->priv_key, buffer + buf_len - bn_len)) { ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_BN_LIB); goto err; } + if (buf_len - bn_len > 0) { + memset(buffer, 0, buf_len - bn_len); + } + if (!M_ASN1_OCTET_STRING_set(priv_key->privateKey, buffer, buf_len)) { ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_ASN1_LIB); goto err; diff --git a/crypto/openssl/crypto/ec/ec_check.c b/crypto/openssl/crypto/ec/ec_check.c index d3f534999e..dd6f0ac409 100644 --- a/crypto/openssl/crypto/ec/ec_check.c +++ b/crypto/openssl/crypto/ec/ec_check.c @@ -85,7 +85,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 ebdffc8212..55ce3fe9be 100644 --- a/crypto/openssl/crypto/ec/ec_key.c +++ b/crypto/openssl/crypto/ec/ec_key.c @@ -314,7 +314,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_lcl.h b/crypto/openssl/crypto/ec/ec_lcl.h index 319e651f67..d79ed1e4d9 100644 --- a/crypto/openssl/crypto/ec/ec_lcl.h +++ b/crypto/openssl/crypto/ec/ec_lcl.h @@ -451,14 +451,6 @@ int ec_GF2m_simple_mul(const EC_GROUP *group, EC_POINT *r, int ec_GF2m_precompute_mult(EC_GROUP *group, BN_CTX *ctx); int ec_GF2m_have_precompute_mult(const EC_GROUP *group); -/* method functions in ec2_mult.c */ -int ec_GF2m_simple_mul(const EC_GROUP *group, EC_POINT *r, - const BIGNUM *scalar, size_t num, - const EC_POINT *points[], const BIGNUM *scalars[], - BN_CTX *); -int ec_GF2m_precompute_mult(EC_GROUP *group, BN_CTX *ctx); -int ec_GF2m_have_precompute_mult(const EC_GROUP *group); - #ifndef OPENSSL_NO_EC_NISTP_64_GCC_128 /* method functions in ecp_nistp224.c */ int ec_GFp_nistp224_group_init(EC_GROUP *group); diff --git a/crypto/openssl/crypto/ec/ec_lib.c b/crypto/openssl/crypto/ec/ec_lib.c index 9a54f41e4e..e2275207ed 100644 --- a/crypto/openssl/crypto/ec/ec_lib.c +++ b/crypto/openssl/crypto/ec/ec_lib.c @@ -934,6 +934,13 @@ int EC_POINT_is_at_infinity(const EC_GROUP *group, const EC_POINT *point) return group->meth->is_at_infinity(group, point); } +/* + * 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) { diff --git a/crypto/openssl/crypto/ec/eck_prn.c b/crypto/openssl/crypto/ec/eck_prn.c index a911a0ac40..5ef12ec024 100644 --- a/crypto/openssl/crypto/ec/eck_prn.c +++ b/crypto/openssl/crypto/ec/eck_prn.c @@ -338,12 +338,14 @@ static int print_bin(BIO *fp, const char *name, const unsigned char *buf, if (buf == NULL) return 1; - if (off) { + if (off > 0) { if (off > 128) off = 128; memset(str, ' ', off); if (BIO_write(fp, str, off) <= 0) return 0; + } else { + off = 0; } if (BIO_printf(fp, "%s", name) <= 0) diff --git a/crypto/openssl/crypto/ec/ecp_oct.c b/crypto/openssl/crypto/ec/ecp_oct.c index e5cec8be82..1bc3f39ad1 100644 --- a/crypto/openssl/crypto/ec/ecp_oct.c +++ b/crypto/openssl/crypto/ec/ecp_oct.c @@ -413,7 +413,7 @@ int ec_GFp_simple_oct2point(const EC_GROUP *group, EC_POINT *point, } /* test required by X9.62 */ - if (!EC_POINT_is_on_curve(group, point, ctx)) { + 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/engine/eng_table.c b/crypto/openssl/crypto/engine/eng_table.c index 2e1a7e855a..27d31f70c8 100644 --- a/crypto/openssl/crypto/engine/eng_table.c +++ b/crypto/openssl/crypto/engine/eng_table.c @@ -351,6 +351,8 @@ void engine_table_doall(ENGINE_TABLE *table, engine_table_doall_cb *cb, ENGINE_PILE_DOALL dall; dall.cb = cb; dall.arg = arg; - lh_ENGINE_PILE_doall_arg(&table->piles, LHASH_DOALL_ARG_FN(int_cb), - ENGINE_PILE_DOALL, &dall); + if (table) + lh_ENGINE_PILE_doall_arg(&table->piles, + LHASH_DOALL_ARG_FN(int_cb), + ENGINE_PILE_DOALL, &dall); } diff --git a/crypto/openssl/crypto/evp/bio_ok.c b/crypto/openssl/crypto/evp/bio_ok.c index a4550349be..5c32e35e17 100644 --- a/crypto/openssl/crypto/evp/bio_ok.c +++ b/crypto/openssl/crypto/evp/bio_ok.c @@ -491,7 +491,8 @@ static int sig_out(BIO *b) * FIXME: there's absolutely no guarantee this makes any sense at all, * particularly now EVP_MD_CTX has been restructured. */ - RAND_pseudo_bytes(md->md_data, md->digest->md_size); + if (RAND_pseudo_bytes(md->md_data, md->digest->md_size) < 0) + goto berr; memcpy(&(ctx->buf[ctx->buf_len]), md->md_data, md->digest->md_size); longswap(&(ctx->buf[ctx->buf_len]), md->digest->md_size); ctx->buf_len += md->digest->md_size; diff --git a/crypto/openssl/crypto/evp/e_aes.c b/crypto/openssl/crypto/evp/e_aes.c index 245c18a693..1ede7bd39e 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 @@ -753,7 +754,7 @@ static int aes_gcm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr) case EVP_CTRL_AEAD_TLS1_AAD: /* Save the AAD for later use */ - if (arg != 13) + if (arg != EVP_AEAD_TLS1_AAD_LEN) return 0; memcpy(c->buf, ptr, arg); gctx->tls_aad_len = arg; @@ -914,7 +915,7 @@ static int aes_gcm_tls_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, /* Retrieve tag */ 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; } @@ -1259,7 +1260,7 @@ static int aes_ccm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, !CRYPTO_ccm128_decrypt(ccm, in, out, len)) { 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_aes_cbc_hmac_sha1.c b/crypto/openssl/crypto/evp/e_aes_cbc_hmac_sha1.c index 3f8a5ae391..d1f5928f62 100644 --- a/crypto/openssl/crypto/evp/e_aes_cbc_hmac_sha1.c +++ b/crypto/openssl/crypto/evp/e_aes_cbc_hmac_sha1.c @@ -503,7 +503,12 @@ static int aesni_cbc_hmac_sha1_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, case EVP_CTRL_AEAD_TLS1_AAD: { unsigned char *p = ptr; - unsigned int len = p[arg - 2] << 8 | p[arg - 1]; + unsigned int len; + + if (arg != EVP_AEAD_TLS1_AAD_LEN) + return -1; + + len = p[arg - 2] << 8 | p[arg - 1]; if (ctx->encrypt) { key->payload_length = len; @@ -520,8 +525,6 @@ static int aesni_cbc_hmac_sha1_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, AES_BLOCK_SIZE) & -AES_BLOCK_SIZE) - len); } else { - if (arg > 13) - arg = 13; memcpy(key->aux.tls_aad, ptr, arg); key->payload_length = arg; diff --git a/crypto/openssl/crypto/evp/e_rc4_hmac_md5.c b/crypto/openssl/crypto/evp/e_rc4_hmac_md5.c index 80735d345a..2da1117829 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 @@ -210,7 +211,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); @@ -258,7 +259,12 @@ static int rc4_hmac_md5_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, case EVP_CTRL_AEAD_TLS1_AAD: { unsigned char *p = ptr; - unsigned int len = p[arg - 2] << 8 | p[arg - 1]; + unsigned int len; + + if (arg != EVP_AEAD_TLS1_AAD_LEN) + return -1; + + len = p[arg - 2] << 8 | p[arg - 1]; if (!ctx->encrypt) { len -= MD5_DIGEST_LENGTH; diff --git a/crypto/openssl/crypto/evp/encode.c b/crypto/openssl/crypto/evp/encode.c index d1d8a07c14..5c5988fc45 100644 --- a/crypto/openssl/crypto/evp/encode.c +++ b/crypto/openssl/crypto/evp/encode.c @@ -137,7 +137,7 @@ void EVP_EncodeUpdate(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl, unsigned int total = 0; *outl = 0; - if (inl == 0) + if (inl <= 0) return; OPENSSL_assert(ctx->length <= (int)sizeof(ctx->enc_data)); if ((ctx->num + inl) < ctx->length) { diff --git a/crypto/openssl/crypto/evp/evp.h b/crypto/openssl/crypto/evp/evp.h index b00997b149..6cf98acc0b 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 @@ -409,6 +408,9 @@ struct evp_cipher_st { /* Set the GCM invocation field, decrypt only */ # define EVP_CTRL_GCM_SET_IV_INV 0x18 +/* RFC 5246 defines additional data to be 13 bytes in length */ +# define EVP_AEAD_TLS1_AAD_LEN 13 + /* GCM TLS constants */ /* Length of fixed part of IV derived from PRF */ # define EVP_GCM_TLS_FIXED_IV_LEN 4 diff --git a/crypto/openssl/crypto/evp/p_seal.c b/crypto/openssl/crypto/evp/p_seal.c index caabbf406f..ba9dfff215 100644 --- a/crypto/openssl/crypto/evp/p_seal.c +++ b/crypto/openssl/crypto/evp/p_seal.c @@ -82,8 +82,9 @@ int EVP_SealInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *type, return 1; if (EVP_CIPHER_CTX_rand_key(ctx, key) <= 0) return 0; - if (EVP_CIPHER_CTX_iv_length(ctx)) - RAND_pseudo_bytes(iv, EVP_CIPHER_CTX_iv_length(ctx)); + if (EVP_CIPHER_CTX_iv_length(ctx) + && RAND_bytes(iv, EVP_CIPHER_CTX_iv_length(ctx)) <= 0) + return 0; if (!EVP_EncryptInit_ex(ctx, NULL, NULL, key, iv)) return 0; diff --git a/crypto/openssl/crypto/hmac/hmac.c b/crypto/openssl/crypto/hmac/hmac.c index 5477816551..5925467818 100644 --- a/crypto/openssl/crypto/hmac/hmac.c +++ b/crypto/openssl/crypto/hmac/hmac.c @@ -91,8 +91,14 @@ int HMAC_Init_ex(HMAC_CTX *ctx, const void *key, int len, if (md != NULL) { reset = 1; ctx->md = md; - } else + } else if (ctx->md) { md = ctx->md; + } else { + return 0; + } + + if (!ctx->key_init && key == NULL) + return 0; if (key != NULL) { reset = 1; @@ -107,13 +113,15 @@ int HMAC_Init_ex(HMAC_CTX *ctx, const void *key, int len, &ctx->key_length)) goto err; } else { - OPENSSL_assert(len >= 0 && len <= (int)sizeof(ctx->key)); + if (len < 0 || len > (int)sizeof(ctx->key)) + return 0; memcpy(ctx->key, key, len); ctx->key_length = len; } if (ctx->key_length != HMAC_MAX_MD_CBLOCK) memset(&ctx->key[ctx->key_length], 0, HMAC_MAX_MD_CBLOCK - ctx->key_length); + ctx->key_init = 1; } if (reset) { @@ -151,6 +159,9 @@ int HMAC_Update(HMAC_CTX *ctx, const unsigned char *data, size_t len) if (FIPS_mode() && !ctx->i_ctx.engine) return FIPS_hmac_update(ctx, data, len); #endif + if (!ctx->key_init) + return 0; + return EVP_DigestUpdate(&ctx->md_ctx, data, len); } @@ -163,6 +174,9 @@ int HMAC_Final(HMAC_CTX *ctx, unsigned char *md, unsigned int *len) return FIPS_hmac_final(ctx, md, len); #endif + if (!ctx->key_init) + goto err; + if (!EVP_DigestFinal_ex(&ctx->md_ctx, buf, &i)) goto err; if (!EVP_MD_CTX_copy_ex(&ctx->md_ctx, &ctx->o_ctx)) @@ -181,6 +195,8 @@ void HMAC_CTX_init(HMAC_CTX *ctx) EVP_MD_CTX_init(&ctx->i_ctx); EVP_MD_CTX_init(&ctx->o_ctx); EVP_MD_CTX_init(&ctx->md_ctx); + ctx->key_init = 0; + ctx->md = NULL; } int HMAC_CTX_copy(HMAC_CTX *dctx, HMAC_CTX *sctx) @@ -191,8 +207,11 @@ int HMAC_CTX_copy(HMAC_CTX *dctx, HMAC_CTX *sctx) goto err; if (!EVP_MD_CTX_copy(&dctx->md_ctx, &sctx->md_ctx)) goto err; - memcpy(dctx->key, sctx->key, HMAC_MAX_MD_CBLOCK); - dctx->key_length = sctx->key_length; + dctx->key_init = sctx->key_init; + if (sctx->key_init) { + memcpy(dctx->key, sctx->key, HMAC_MAX_MD_CBLOCK); + dctx->key_length = sctx->key_length; + } dctx->md = sctx->md; return 1; err: @@ -232,6 +251,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/hmac/hmac.h b/crypto/openssl/crypto/hmac/hmac.h index b8b55cda7d..f8e9f5e4f3 100644 --- a/crypto/openssl/crypto/hmac/hmac.h +++ b/crypto/openssl/crypto/hmac/hmac.h @@ -79,6 +79,7 @@ typedef struct hmac_ctx_st { EVP_MD_CTX o_ctx; unsigned int key_length; unsigned char key[HMAC_MAX_MD_CBLOCK]; + int key_init; } HMAC_CTX; # define HMAC_size(e) (EVP_MD_size((e)->md)) diff --git a/crypto/openssl/crypto/md32_common.h b/crypto/openssl/crypto/md32_common.h index c1efb45f1c..1823833419 100644 --- a/crypto/openssl/crypto/md32_common.h +++ b/crypto/openssl/crypto/md32_common.h @@ -142,8 +142,10 @@ */ #undef ROTATE #ifndef PEDANTIC -# if defined(_MSC_VER) || defined(__ICC) +# if defined(_MSC_VER) # define ROTATE(a,n) _lrotl(a,n) +# elif defined(__ICC) +# define ROTATE(a,n) _rotl(a,n) # elif defined(__MWERKS__) # if defined(__POWERPC__) # define ROTATE(a,n) __rlwinm(a,n,0,31) diff --git a/crypto/openssl/crypto/mem.c b/crypto/openssl/crypto/mem.c index 2ce3e89487..fdad49b76e 100644 --- a/crypto/openssl/crypto/mem.c +++ b/crypto/openssl/crypto/mem.c @@ -365,6 +365,9 @@ char *CRYPTO_strdup(const char *str, const char *file, int line) { char *ret = CRYPTO_malloc(strlen(str) + 1, file, line); + if (ret == NULL) + return NULL; + strcpy(ret, str); return ret; } diff --git a/crypto/openssl/crypto/modes/gcm128.c b/crypto/openssl/crypto/modes/gcm128.c index f69f2c9db6..0ee569fb7a 100644 --- a/crypto/openssl/crypto/modes/gcm128.c +++ b/crypto/openssl/crypto/modes/gcm128.c @@ -1622,7 +1622,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/o_names.c b/crypto/openssl/crypto/objects/o_names.c index c6774f4578..24859926ac 100644 --- a/crypto/openssl/crypto/objects/o_names.c +++ b/crypto/openssl/crypto/objects/o_names.c @@ -313,7 +313,7 @@ void OBJ_NAME_do_all_sorted(int type, d.names = OPENSSL_malloc(lh_OBJ_NAME_num_items(names_lh) * sizeof *d.names); /* Really should return an error if !d.names...but its a void function! */ - if(d.names) { + if (d.names) { d.n = 0; OBJ_NAME_do_all(type, do_all_sorted_fn, &d); diff --git a/crypto/openssl/crypto/objects/obj_dat.c b/crypto/openssl/crypto/objects/obj_dat.c index e42a1c147d..aca382a6e9 100644 --- a/crypto/openssl/crypto/objects/obj_dat.c +++ b/crypto/openssl/crypto/objects/obj_dat.c @@ -142,7 +142,7 @@ static unsigned long added_obj_hash(const ADDED_OBJ *ca) return 0; } ret &= 0x3fffffffL; - ret |= ca->type << 30L; + ret |= ((unsigned long)ca->type) << 30L; return (ret); } @@ -400,6 +400,8 @@ static int obj_cmp(const ASN1_OBJECT *const *ap, const unsigned int *bp) j = (a->length - b->length); if (j) return (j); + if (a->length == 0) + return 0; return (memcmp(a->data, b->data, a->length)); } @@ -415,6 +417,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; ad.obj = (ASN1_OBJECT *)a; /* XXX: ugly but harmless */ diff --git a/crypto/openssl/crypto/objects/objects.README b/crypto/openssl/crypto/objects/objects.README index 4d745508d8..cb1d216ce8 100644 --- a/crypto/openssl/crypto/objects/objects.README +++ b/crypto/openssl/crypto/objects/objects.README @@ -8,9 +8,9 @@ The basic syntax for adding an object is as follows: 1 2 3 4 : shortName : Long Name - If the long name doesn't contain spaces, or no short name - exists, the long name is used as basis for the base name - in C. Otherwise, the short name is used. + If Long Name contains only word characters and hyphen-minus + (0x2D) or full stop (0x2E) then Long Name is used as basis + for the base name in C. Otherwise, the shortName is used. The base name (let's call it 'base') will then be used to create the C macros SN_base, LN_base, NID_base and OBJ_base. @@ -22,7 +22,7 @@ Then there are some extra commands: !Alias foo 1 2 3 4 - This juts makes a name foo for an OID. The C macro + This just makes a name foo for an OID. The C macro OBJ_foo will be created as a result. !Cname foo diff --git a/crypto/openssl/crypto/ocsp/ocsp_ext.c b/crypto/openssl/crypto/ocsp/ocsp_ext.c index 849cb2f762..c19648c732 100644 --- a/crypto/openssl/crypto/ocsp/ocsp_ext.c +++ b/crypto/openssl/crypto/ocsp/ocsp_ext.c @@ -361,8 +361,8 @@ static int ocsp_add1_nonce(STACK_OF(X509_EXTENSION) **exts, ASN1_put_object(&tmpval, 0, len, V_ASN1_OCTET_STRING, V_ASN1_UNIVERSAL); if (val) memcpy(tmpval, val, len); - else - RAND_pseudo_bytes(tmpval, len); + else if (RAND_pseudo_bytes(tmpval, len) < 0) + goto err; if (!X509V3_add1_i2d(exts, NID_id_pkix_OCSP_Nonce, &os, 0, X509V3_ADD_REPLACE)) goto err; diff --git a/crypto/openssl/crypto/ocsp/ocsp_vfy.c b/crypto/openssl/crypto/ocsp/ocsp_vfy.c index 6c0ccb565d..d4a257c33b 100644 --- a/crypto/openssl/crypto/ocsp/ocsp_vfy.c +++ b/crypto/openssl/crypto/ocsp/ocsp_vfy.c @@ -83,6 +83,7 @@ int OCSP_basic_verify(OCSP_BASICRESP *bs, STACK_OF(X509) *certs, { X509 *signer, *x; STACK_OF(X509) *chain = NULL; + STACK_OF(X509) *untrusted = NULL; X509_STORE_CTX ctx; int i, ret = 0; ret = ocsp_find_signer(&signer, bs, certs, st, flags); @@ -107,10 +108,20 @@ int OCSP_basic_verify(OCSP_BASICRESP *bs, STACK_OF(X509) *certs, } if (!(flags & OCSP_NOVERIFY)) { int init_res; - if (flags & OCSP_NOCHAIN) - init_res = X509_STORE_CTX_init(&ctx, st, signer, NULL); - else - init_res = X509_STORE_CTX_init(&ctx, st, signer, bs->certs); + if (flags & OCSP_NOCHAIN) { + untrusted = NULL; + } else if (bs->certs && certs) { + untrusted = sk_X509_dup(bs->certs); + for (i = 0; i < sk_X509_num(certs); i++) { + if (!sk_X509_push(untrusted, sk_X509_value(certs, i))) { + OCSPerr(OCSP_F_OCSP_BASIC_VERIFY, ERR_R_MALLOC_FAILURE); + goto end; + } + } + } else { + untrusted = bs->certs; + } + init_res = X509_STORE_CTX_init(&ctx, st, signer, untrusted); if (!init_res) { ret = -1; OCSPerr(OCSP_F_OCSP_BASIC_VERIFY, ERR_R_X509_LIB); @@ -161,6 +172,8 @@ int OCSP_basic_verify(OCSP_BASICRESP *bs, STACK_OF(X509) *certs, end: if (chain) sk_X509_pop_free(chain, X509_free); + if (bs->certs && certs) + sk_X509_free(untrusted); return ret; } diff --git a/crypto/openssl/crypto/opensslv.h b/crypto/openssl/crypto/opensslv.h index daf3905dfb..94a95f3482 100644 --- a/crypto/openssl/crypto/opensslv.h +++ b/crypto/openssl/crypto/opensslv.h @@ -30,11 +30,11 @@ extern "C" { * (Prior to 0.9.5a beta1, a different scheme was used: MMNNFFRBB for * major minor fix final patch/beta) */ -# define OPENSSL_VERSION_NUMBER 0x100010dfL +# define OPENSSL_VERSION_NUMBER 0x100010efL # ifdef OPENSSL_FIPS -# define OPENSSL_VERSION_TEXT "OpenSSL 1.0.1m-fips 19 Mar 2015" +# define OPENSSL_VERSION_TEXT "OpenSSL 1.0.1n-fips 11 Jun 2015" # else -# define OPENSSL_VERSION_TEXT "OpenSSL 1.0.1m 19 Mar 2015" +# define OPENSSL_VERSION_TEXT "OpenSSL 1.0.1n 11 Jun 2015" # endif # define OPENSSL_VERSION_PTEXT " part of " OPENSSL_VERSION_TEXT diff --git a/crypto/openssl/crypto/pem/pem_lib.c b/crypto/openssl/crypto/pem/pem_lib.c index febb53ed0e..55071616e2 100644 --- a/crypto/openssl/crypto/pem/pem_lib.c +++ b/crypto/openssl/crypto/pem/pem_lib.c @@ -435,7 +435,7 @@ int PEM_ASN1_write_bio(i2d_of_void *i2d, const char *name, BIO *bp, int PEM_do_header(EVP_CIPHER_INFO *cipher, unsigned char *data, long *plen, pem_password_cb *callback, void *u) { - int i, j, o, klen; + int i = 0, j, o, klen; long len; EVP_CIPHER_CTX ctx; unsigned char key[EVP_MAX_KEY_LENGTH]; diff --git a/crypto/openssl/crypto/pem/pem_pk8.c b/crypto/openssl/crypto/pem/pem_pk8.c index b98c76c4a9..5747c7366e 100644 --- a/crypto/openssl/crypto/pem/pem_pk8.c +++ b/crypto/openssl/crypto/pem/pem_pk8.c @@ -138,6 +138,8 @@ static int do_pk8pkey(BIO *bp, EVP_PKEY *x, int isder, int nid, if (kstr == buf) OPENSSL_cleanse(buf, klen); PKCS8_PRIV_KEY_INFO_free(p8inf); + if (p8 == NULL) + return 0; if (isder) ret = i2d_PKCS8_bio(bp, p8); else diff --git a/crypto/openssl/crypto/pkcs12/p12_mutl.c b/crypto/openssl/crypto/pkcs12/p12_mutl.c index 256b210cce..5ab4bf290e 100644 --- a/crypto/openssl/crypto/pkcs12/p12_mutl.c +++ b/crypto/openssl/crypto/pkcs12/p12_mutl.c @@ -60,6 +60,7 @@ #ifndef OPENSSL_NO_HMAC # include # include "cryptlib.h" +# include # include # include # include @@ -123,7 +124,7 @@ 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)) + || 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 31a1b983f1..c8d7db01bd 100644 --- a/crypto/openssl/crypto/pkcs7/pk7_doit.c +++ b/crypto/openssl/crypto/pkcs7/pk7_doit.c @@ -445,6 +445,12 @@ BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, X509 *pcert) switch (i) { case NID_pkcs7_signed: + /* + * p7->d.sign->contents is a PKCS7 structure consisting of a contentType + * field and optional content. + * data_body is NULL if that structure has no (=detached) content + * or if the contentType is wrong (i.e., not "data"). + */ data_body = PKCS7_get_octet_string(p7->d.sign->contents); if (!PKCS7_is_detached(p7) && data_body == NULL) { PKCS7err(PKCS7_F_PKCS7_DATADECODE, @@ -456,6 +462,7 @@ BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, X509 *pcert) case NID_pkcs7_signedAndEnveloped: rsk = p7->d.signed_and_enveloped->recipientinfo; md_sk = p7->d.signed_and_enveloped->md_algs; + /* data_body is NULL if the optional EncryptedContent is missing. */ data_body = p7->d.signed_and_enveloped->enc_data->enc_data; enc_alg = p7->d.signed_and_enveloped->enc_data->algorithm; evp_cipher = EVP_get_cipherbyobj(enc_alg->algorithm); @@ -468,6 +475,7 @@ BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, X509 *pcert) case NID_pkcs7_enveloped: rsk = p7->d.enveloped->recipientinfo; enc_alg = p7->d.enveloped->enc_data->algorithm; + /* data_body is NULL if the optional EncryptedContent is missing. */ data_body = p7->d.enveloped->enc_data->enc_data; evp_cipher = EVP_get_cipherbyobj(enc_alg->algorithm); if (evp_cipher == NULL) { @@ -481,6 +489,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) { for (i = 0; i < sk_X509_ALGOR_num(md_sk); i++) { @@ -623,7 +637,7 @@ BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, X509 *pcert) etmp = NULL; } #if 1 - if (PKCS7_is_detached(p7) || (in_bio != NULL)) { + if (in_bio != NULL) { bio = in_bio; } else { # if 0 diff --git a/crypto/openssl/crypto/rsa/rsa_pmeth.c b/crypto/openssl/crypto/rsa/rsa_pmeth.c index d61d6e8b66..6a7c67cdb8 100644 --- a/crypto/openssl/crypto/rsa/rsa_pmeth.c +++ b/crypto/openssl/crypto/rsa/rsa_pmeth.c @@ -228,8 +228,14 @@ static int pkey_rsa_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, return ret; ret = sltmp; } else if (rctx->pad_mode == RSA_X931_PADDING) { - if (!setup_tbuf(rctx, ctx)) + if ((size_t)EVP_PKEY_size(ctx->pkey) < tbslen + 1) { + RSAerr(RSA_F_PKEY_RSA_SIGN, RSA_R_KEY_SIZE_TOO_SMALL); + return -1; + } + if (!setup_tbuf(rctx, ctx)) { + RSAerr(RSA_F_PKEY_RSA_SIGN, ERR_R_MALLOC_FAILURE); return -1; + } memcpy(rctx->tbuf, tbs, tbslen); rctx->tbuf[tbslen] = RSA_X931_hash_id(EVP_MD_type(rctx->md)); ret = RSA_private_encrypt(tbslen + 1, rctx->tbuf, diff --git a/crypto/openssl/crypto/srp/srp_vfy.c b/crypto/openssl/crypto/srp/srp_vfy.c index 701b5cd011..50f75d7e4c 100644 --- a/crypto/openssl/crypto/srp/srp_vfy.c +++ b/crypto/openssl/crypto/srp/srp_vfy.c @@ -497,7 +497,8 @@ SRP_user_pwd *SRP_VBASE_get_by_user(SRP_VBASE *vb, char *username) if (!SRP_user_pwd_set_ids(user, username, NULL)) goto err; - RAND_pseudo_bytes(digv, SHA_DIGEST_LENGTH); + if (RAND_pseudo_bytes(digv, SHA_DIGEST_LENGTH) < 0) + goto err; EVP_MD_CTX_init(&ctxt); EVP_DigestInit_ex(&ctxt, EVP_sha1(), NULL); EVP_DigestUpdate(&ctxt, vb->seed_key, strlen(vb->seed_key)); @@ -549,7 +550,8 @@ char *SRP_create_verifier(const char *user, const char *pass, char **salt, } if (*salt == NULL) { - RAND_pseudo_bytes(tmp2, SRP_RANDOM_SALT_LEN); + if (RAND_pseudo_bytes(tmp2, SRP_RANDOM_SALT_LEN) < 0) + goto err; s = BN_bin2bn(tmp2, SRP_RANDOM_SALT_LEN, NULL); } else { @@ -609,7 +611,8 @@ int SRP_create_verifier_BN(const char *user, const char *pass, BIGNUM **salt, srp_bn_print(g); if (*salt == NULL) { - RAND_pseudo_bytes(tmp2, SRP_RANDOM_SALT_LEN); + if (RAND_pseudo_bytes(tmp2, SRP_RANDOM_SALT_LEN) < 0) + goto err; *salt = BN_bin2bn(tmp2, SRP_RANDOM_SALT_LEN, NULL); } diff --git a/crypto/openssl/crypto/threads/th-lock.c b/crypto/openssl/crypto/threads/th-lock.c index 28884c2d44..cc8cf2581d 100644 --- a/crypto/openssl/crypto/threads/th-lock.c +++ b/crypto/openssl/crypto/threads/th-lock.c @@ -117,7 +117,7 @@ void CRYPTO_thread_setup(void) int i; lock_cs = OPENSSL_malloc(CRYPTO_num_locks() * sizeof(HANDLE)); - if(!lock_cs) { + if (!lock_cs) { /* Nothing we can do about this...void function! */ return; } @@ -172,7 +172,7 @@ void CRYPTO_thread_setup(void) # else lock_cs = OPENSSL_malloc(CRYPTO_num_locks() * sizeof(rwlock_t)); # endif - if(!lock_cs) { + if (!lock_cs) { /* Nothing we can do about this...void function! */ return; } @@ -260,7 +260,7 @@ void CRYPTO_thread_setup(void) char filename[20]; lock_cs = OPENSSL_malloc(CRYPTO_num_locks() * sizeof(usema_t *)); - if(!lock_cs) { + if (!lock_cs) { /* Nothing we can do about this...void function! */ return; } @@ -328,11 +328,11 @@ void CRYPTO_thread_setup(void) lock_cs = OPENSSL_malloc(CRYPTO_num_locks() * sizeof(pthread_mutex_t)); lock_count = OPENSSL_malloc(CRYPTO_num_locks() * sizeof(long)); - if(!lock_cs || !lock_count) { + if (!lock_cs || !lock_count) { /* Nothing we can do about this...void function! */ - if(lock_cs) + if (lock_cs) OPENSSL_free(lock_cs); - if(lock_count) + if (lock_count) OPENSSL_free(lock_count); return; } diff --git a/crypto/openssl/crypto/x509/x509_lu.c b/crypto/openssl/crypto/x509/x509_lu.c index a910636f82..8415d1d8b3 100644 --- a/crypto/openssl/crypto/x509/x509_lu.c +++ b/crypto/openssl/crypto/x509/x509_lu.c @@ -216,6 +216,8 @@ X509_STORE *X509_STORE_new(void) static void cleanup(X509_OBJECT *a) { + if (!a) + return; if (a->type == X509_LU_X509) { X509_free(a->data.x509); } else if (a->type == X509_LU_CRL) { diff --git a/crypto/openssl/crypto/x509/x509_vfy.c b/crypto/openssl/crypto/x509/x509_vfy.c index 136bfbda61..16db4c025a 100644 --- a/crypto/openssl/crypto/x509/x509_vfy.c +++ b/crypto/openssl/crypto/x509/x509_vfy.c @@ -151,11 +151,11 @@ static int x509_subject_cmp(X509 **a, X509 **b) int X509_verify_cert(X509_STORE_CTX *ctx) { - X509 *x, *xtmp, *chain_ss = NULL; + X509 *x, *xtmp, *xtmp2, *chain_ss = NULL; int bad_chain = 0; X509_VERIFY_PARAM *param = ctx->param; int depth, i, ok = 0; - int num; + int num, j, retry; int (*cb) (int xok, X509_STORE_CTX *xctx); STACK_OF(X509) *sktmp = NULL; if (ctx->cert == NULL) { @@ -224,85 +224,118 @@ int X509_verify_cert(X509_STORE_CTX *ctx) break; } + /* Remember how many untrusted certs we have */ + j = num; /* * at this point, chain should contain a list of untrusted certificates. * We now need to add at least one trusted one, if possible, otherwise we * complain. */ - /* - * Examine last certificate in chain and see if it is self signed. - */ - - i = sk_X509_num(ctx->chain); - x = sk_X509_value(ctx->chain, i - 1); - if (ctx->check_issued(ctx, x, x)) { - /* we have a self signed certificate */ - if (sk_X509_num(ctx->chain) == 1) { - /* - * We have a single self signed certificate: see if we can find - * it in the store. We must have an exact match to avoid possible - * impersonation. - */ - ok = ctx->get_issuer(&xtmp, ctx, x); - if ((ok <= 0) || X509_cmp(x, xtmp)) { - ctx->error = X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT; - ctx->current_cert = x; - ctx->error_depth = i - 1; - if (ok == 1) - X509_free(xtmp); - bad_chain = 1; - ok = cb(0, ctx); - if (!ok) - goto end; + do { + /* + * Examine last certificate in chain and see if it is self signed. + */ + i = sk_X509_num(ctx->chain); + x = sk_X509_value(ctx->chain, i - 1); + if (ctx->check_issued(ctx, x, x)) { + /* we have a self signed certificate */ + if (sk_X509_num(ctx->chain) == 1) { + /* + * We have a single self signed certificate: see if we can + * find it in the store. We must have an exact match to avoid + * possible impersonation. + */ + ok = ctx->get_issuer(&xtmp, ctx, x); + if ((ok <= 0) || X509_cmp(x, xtmp)) { + ctx->error = X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT; + ctx->current_cert = x; + ctx->error_depth = i - 1; + if (ok == 1) + X509_free(xtmp); + bad_chain = 1; + ok = cb(0, ctx); + if (!ok) + goto end; + } else { + /* + * We have a match: replace certificate with store + * version so we get any trust settings. + */ + X509_free(x); + x = xtmp; + (void)sk_X509_set(ctx->chain, i - 1, x); + ctx->last_untrusted = 0; + } } else { /* - * We have a match: replace certificate with store version so - * we get any trust settings. + * extract and save self signed certificate for later use */ - X509_free(x); - x = xtmp; - (void)sk_X509_set(ctx->chain, i - 1, x); - ctx->last_untrusted = 0; + chain_ss = sk_X509_pop(ctx->chain); + ctx->last_untrusted--; + num--; + j--; + x = sk_X509_value(ctx->chain, num - 1); } - } else { - /* - * extract and save self signed certificate for later use - */ - chain_ss = sk_X509_pop(ctx->chain); - ctx->last_untrusted--; - num--; - x = sk_X509_value(ctx->chain, num - 1); } - } - - /* We now lookup certs from the certificate store */ - for (;;) { - /* If we have enough, we break */ - if (depth < num) - break; - - /* If we are self signed, we break */ - if (ctx->check_issued(ctx, x, x)) - break; - - ok = ctx->get_issuer(&xtmp, ctx, x); + /* We now lookup certs from the certificate store */ + for (;;) { + /* If we have enough, we break */ + if (depth < num) + break; + /* If we are self signed, we break */ + if (ctx->check_issued(ctx, x, x)) + break; + ok = ctx->get_issuer(&xtmp, ctx, x); + if (ok < 0) + return ok; + if (ok == 0) + break; + x = xtmp; + if (!sk_X509_push(ctx->chain, x)) { + X509_free(xtmp); + X509err(X509_F_X509_VERIFY_CERT, ERR_R_MALLOC_FAILURE); + return 0; + } + num++; + } - if (ok < 0) - return ok; - if (ok == 0) - break; + /* + * If we haven't got a least one certificate from our store then check + * if there is an alternative chain that could be used. We only do this + * if the user hasn't switched off alternate chain checking + */ + retry = 0; + if (j == ctx->last_untrusted && + !(ctx->param->flags & X509_V_FLAG_NO_ALT_CHAINS)) { + while (j-- > 1) { + xtmp2 = sk_X509_value(ctx->chain, j - 1); + ok = ctx->get_issuer(&xtmp, ctx, xtmp2); + if (ok < 0) + goto end; + /* Check if we found an alternate chain */ + if (ok > 0) { + /* + * Free up the found cert we'll add it again later + */ + X509_free(xtmp); - x = xtmp; - if (!sk_X509_push(ctx->chain, x)) { - X509_free(xtmp); - X509err(X509_F_X509_VERIFY_CERT, ERR_R_MALLOC_FAILURE); - return 0; + /* + * Dump all the certs above this point - we've found an + * alternate chain + */ + while (num > j) { + xtmp = sk_X509_pop(ctx->chain); + X509_free(xtmp); + num--; + ctx->last_untrusted--; + } + retry = 1; + break; + } + } } - num++; - } - - /* we now have our chain, lets check it... */ + } while (retry); /* Is last certificate looked up self signed? */ if (!ctx->check_issued(ctx, x, x)) { @@ -1604,47 +1637,84 @@ int X509_cmp_time(const ASN1_TIME *ctm, time_t *cmp_time) ASN1_TIME atm; long offset; char buff1[24], buff2[24], *p; - int i, j; + int i, j, remaining; p = buff1; - i = ctm->length; + 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) { - if ((i < 11) || (i > 17)) + /* 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 { - if (i < 13) + /* 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++); - /* Skip any fractional seconds... */ - if (*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') + /* 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 { + } else { + /* (+-)HHMM */ if ((*str != '+') && (*str != '-')) return 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 == '-') @@ -1921,6 +1991,8 @@ X509_STORE_CTX *X509_STORE_CTX_new(void) void X509_STORE_CTX_free(X509_STORE_CTX *ctx) { + if (!ctx) + return; X509_STORE_CTX_cleanup(ctx); OPENSSL_free(ctx); } diff --git a/crypto/openssl/crypto/x509/x509_vfy.h b/crypto/openssl/crypto/x509/x509_vfy.h index 1f8c0eccbf..aacdf55aa2 100644 --- a/crypto/openssl/crypto/x509/x509_vfy.h +++ b/crypto/openssl/crypto/x509/x509_vfy.h @@ -405,6 +405,12 @@ void X509_STORE_CTX_set_depth(X509_STORE_CTX *ctx, int depth); # define X509_V_FLAG_USE_DELTAS 0x2000 /* Check selfsigned CA signature */ # define X509_V_FLAG_CHECK_SS_SIGNATURE 0x4000 +/* + * If the initial chain is not trusted, do not attempt to build an alternative + * chain. Alternate chain checking was introduced in 1.0.1n/1.0.2b. Setting + * this flag will force the behaviour to match that of previous versions. + */ +# define X509_V_FLAG_NO_ALT_CHAINS 0x100000 # define X509_VP_FLAG_DEFAULT 0x1 # define X509_VP_FLAG_OVERWRITE 0x2 diff --git a/crypto/openssl/crypto/x509/x509_vpm.c b/crypto/openssl/crypto/x509/x509_vpm.c index d0543662c0..6b0bf8a6e6 100644 --- a/crypto/openssl/crypto/x509/x509_vpm.c +++ b/crypto/openssl/crypto/x509/x509_vpm.c @@ -100,6 +100,8 @@ X509_VERIFY_PARAM *X509_VERIFY_PARAM_new(void) void X509_VERIFY_PARAM_free(X509_VERIFY_PARAM *param) { + if (param == NULL) + return; x509_verify_param_zero(param); OPENSSL_free(param); } diff --git a/crypto/openssl/crypto/x509/x509type.c b/crypto/openssl/crypto/x509/x509type.c index 033175257a..9219f753bf 100644 --- a/crypto/openssl/crypto/x509/x509type.c +++ b/crypto/openssl/crypto/x509/x509type.c @@ -121,9 +121,6 @@ int X509_certificate_type(X509 *x, EVP_PKEY *pkey) } } - /* /8 because it's 1024 bits we look for, not bytes */ - if (EVP_PKEY_size(pk) <= 1024 / 8) - ret |= EVP_PKT_EXP; if (pkey == NULL) EVP_PKEY_free(pk); return (ret); diff --git a/crypto/openssl/crypto/x509v3/v3_alt.c b/crypto/openssl/crypto/x509v3/v3_alt.c index 807867b918..22ec202846 100644 --- a/crypto/openssl/crypto/x509v3/v3_alt.c +++ b/crypto/openssl/crypto/x509v3/v3_alt.c @@ -584,24 +584,26 @@ static int do_othername(GENERAL_NAME *gen, char *value, X509V3_CTX *ctx) static int do_dirname(GENERAL_NAME *gen, char *value, X509V3_CTX *ctx) { - int ret; - STACK_OF(CONF_VALUE) *sk; - X509_NAME *nm; + int ret = 0; + STACK_OF(CONF_VALUE) *sk = NULL; + X509_NAME *nm = NULL; if (!(nm = X509_NAME_new())) - return 0; + goto err; sk = X509V3_get_section(ctx, value); if (!sk) { X509V3err(X509V3_F_DO_DIRNAME, X509V3_R_SECTION_NOT_FOUND); ERR_add_error_data(2, "section=", value); - X509_NAME_free(nm); - return 0; + goto err; } /* FIXME: should allow other character types... */ ret = X509V3_NAME_from_section(nm, sk, MBSTRING_ASC); if (!ret) - X509_NAME_free(nm); + goto err; gen->d.dirn = nm; - X509V3_section_free(ctx, sk); +err: + if (ret == 0) + X509_NAME_free(nm); + X509V3_section_free(ctx, sk); return ret; } diff --git a/crypto/openssl/crypto/x509v3/v3_cpols.c b/crypto/openssl/crypto/x509v3/v3_cpols.c index dca6ab2ec9..0febc1b3ed 100644 --- a/crypto/openssl/crypto/x509v3/v3_cpols.c +++ b/crypto/openssl/crypto/x509v3/v3_cpols.c @@ -230,11 +230,11 @@ static POLICYINFO *policy_section(X509V3_CTX *ctx, goto merr; if (!sk_POLICYQUALINFO_push(pol->qualifiers, qual)) goto merr; - if(!(qual->pqualid = OBJ_nid2obj(NID_id_qt_cps))) { + if (!(qual->pqualid = OBJ_nid2obj(NID_id_qt_cps))) { X509V3err(X509V3_F_POLICY_SECTION, ERR_R_INTERNAL_ERROR); goto err; } - if(!(qual->d.cpsuri = M_ASN1_IA5STRING_new())) + if (!(qual->d.cpsuri = M_ASN1_IA5STRING_new())) goto merr; if (!ASN1_STRING_set(qual->d.cpsuri, cnf->value, strlen(cnf->value))) @@ -294,7 +294,7 @@ static POLICYQUALINFO *notice_section(X509V3_CTX *ctx, POLICYQUALINFO *qual; if (!(qual = POLICYQUALINFO_new())) goto merr; - if(!(qual->pqualid = OBJ_nid2obj(NID_id_qt_unotice))) { + if (!(qual->pqualid = OBJ_nid2obj(NID_id_qt_unotice))) { X509V3err(X509V3_F_NOTICE_SECTION, ERR_R_INTERNAL_ERROR); goto err; } @@ -304,7 +304,7 @@ static POLICYQUALINFO *notice_section(X509V3_CTX *ctx, for (i = 0; i < sk_CONF_VALUE_num(unot); i++) { cnf = sk_CONF_VALUE_value(unot, i); if (!strcmp(cnf->name, "explicitText")) { - if(!(not->exptext = M_ASN1_VISIBLESTRING_new())) + if (!(not->exptext = M_ASN1_VISIBLESTRING_new())) goto merr; if (!ASN1_STRING_set(not->exptext, cnf->value, strlen(cnf->value))) diff --git a/crypto/openssl/crypto/x509v3/v3_utl.c b/crypto/openssl/crypto/x509v3/v3_utl.c index 65dd1e2fb3..94aaebba3e 100644 --- a/crypto/openssl/crypto/x509v3/v3_utl.c +++ b/crypto/openssl/crypto/x509v3/v3_utl.c @@ -285,6 +285,10 @@ STACK_OF(CONF_VALUE) *X509V3_parse_list(const char *line) int state; /* We are going to modify the line so copy it first */ linebuf = BUF_strdup(line); + if (linebuf == NULL) { + X509V3err(X509V3_F_X509V3_PARSE_LIST, ERR_R_MALLOC_FAILURE); + goto err; + } state = HDR_NAME; ntmp = NULL; /* Go through all characters */ diff --git a/crypto/openssl/e_os2.h b/crypto/openssl/e_os2.h index d400ac77cf..2b1b78ffea 100644 --- a/crypto/openssl/e_os2.h +++ b/crypto/openssl/e_os2.h @@ -109,6 +109,12 @@ extern "C" { # undef OPENSSL_SYS_UNIX # define OPENSSL_SYS_WIN32 # endif +# if defined(_WIN64) || defined(OPENSSL_SYSNAME_WIN64) +# undef OPENSSL_SYS_UNIX +# if !defined(OPENSSL_SYS_WIN64) +# define OPENSSL_SYS_WIN64 +# endif +# endif # if defined(OPENSSL_SYSNAME_WINNT) # undef OPENSSL_SYS_UNIX # define OPENSSL_SYS_WINNT @@ -121,7 +127,7 @@ extern "C" { # endif /* Anything that tries to look like Microsoft is "Windows" */ -# if defined(OPENSSL_SYS_WIN32) || defined(OPENSSL_SYS_WINNT) || defined(OPENSSL_SYS_WINCE) +# if defined(OPENSSL_SYS_WIN32) || defined(OPENSSL_SYS_WIN64) || defined(OPENSSL_SYS_WINNT) || defined(OPENSSL_SYS_WINCE) # undef OPENSSL_SYS_UNIX # define OPENSSL_SYS_WINDOWS # ifndef OPENSSL_SYS_MSDOS diff --git a/crypto/openssl/engines/ccgost/e_gost_err.c b/crypto/openssl/engines/ccgost/e_gost_err.c index 3201b648fb..80ef58f8ca 100644 --- a/crypto/openssl/engines/ccgost/e_gost_err.c +++ b/crypto/openssl/engines/ccgost/e_gost_err.c @@ -1,6 +1,6 @@ /* e_gost_err.c */ /* ==================================================================== - * Copyright (c) 1999-2009 The OpenSSL Project. All rights reserved. + * Copyright (c) 1999-2015 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 @@ -90,6 +90,7 @@ static ERR_STRING_DATA GOST_str_functs[] = { {ERR_FUNC(GOST_F_GOST_IMIT_CTRL), "GOST_IMIT_CTRL"}, {ERR_FUNC(GOST_F_GOST_IMIT_FINAL), "GOST_IMIT_FINAL"}, {ERR_FUNC(GOST_F_GOST_IMIT_UPDATE), "GOST_IMIT_UPDATE"}, + {ERR_FUNC(GOST_F_GOST_SIGN_KEYGEN), "GOST_SIGN_KEYGEN"}, {ERR_FUNC(GOST_F_PARAM_COPY_GOST01), "PARAM_COPY_GOST01"}, {ERR_FUNC(GOST_F_PARAM_COPY_GOST94), "PARAM_COPY_GOST94"}, {ERR_FUNC(GOST_F_PKEY_GOST01CP_DECRYPT), "PKEY_GOST01CP_DECRYPT"}, diff --git a/crypto/openssl/engines/ccgost/e_gost_err.h b/crypto/openssl/engines/ccgost/e_gost_err.h index 92be558452..a2018ec4de 100644 --- a/crypto/openssl/engines/ccgost/e_gost_err.h +++ b/crypto/openssl/engines/ccgost/e_gost_err.h @@ -90,6 +90,7 @@ void ERR_GOST_error(int function, int reason, char *file, int line); # define GOST_F_GOST_IMIT_CTRL 114 # define GOST_F_GOST_IMIT_FINAL 140 # define GOST_F_GOST_IMIT_UPDATE 115 +# define GOST_F_GOST_SIGN_KEYGEN 142 # define GOST_F_PARAM_COPY_GOST01 116 # define GOST_F_PARAM_COPY_GOST94 117 # define GOST_F_PKEY_GOST01CP_DECRYPT 118 diff --git a/crypto/openssl/engines/ccgost/gost2001.c b/crypto/openssl/engines/ccgost/gost2001.c index 2b96694821..9536295430 100644 --- a/crypto/openssl/engines/ccgost/gost2001.c +++ b/crypto/openssl/engines/ccgost/gost2001.c @@ -41,6 +41,11 @@ int fill_GOST2001_params(EC_KEY *eckey, int nid) BN_CTX *ctx = BN_CTX_new(); int ok = 0; + if(!ctx) { + GOSTerr(GOST_F_FILL_GOST2001_PARAMS, ERR_R_MALLOC_FAILURE); + goto err; + } + BN_CTX_start(ctx); p = BN_CTX_get(ctx); a = BN_CTX_get(ctx); @@ -48,6 +53,10 @@ int fill_GOST2001_params(EC_KEY *eckey, int nid) x = BN_CTX_get(ctx); y = BN_CTX_get(ctx); q = BN_CTX_get(ctx); + if(!p || !a || !b || !x || !y || !q) { + GOSTerr(GOST_F_FILL_GOST2001_PARAMS, ERR_R_MALLOC_FAILURE); + goto err; + } while (params->nid != NID_undef && params->nid != nid) params++; if (params->nid == NID_undef) { @@ -55,18 +64,33 @@ int fill_GOST2001_params(EC_KEY *eckey, int nid) GOST_R_UNSUPPORTED_PARAMETER_SET); goto err; } - BN_hex2bn(&p, params->p); - BN_hex2bn(&a, params->a); - BN_hex2bn(&b, params->b); + if(!BN_hex2bn(&p, params->p) + || !BN_hex2bn(&a, params->a) + || !BN_hex2bn(&b, params->b)) { + GOSTerr(GOST_F_FILL_GOST2001_PARAMS, + ERR_R_INTERNAL_ERROR); + goto err; + } grp = EC_GROUP_new_curve_GFp(p, a, b, ctx); + if(!grp) { + GOSTerr(GOST_F_FILL_GOST2001_PARAMS, ERR_R_MALLOC_FAILURE); + goto err; + } P = EC_POINT_new(grp); + if(!P) { + GOSTerr(GOST_F_FILL_GOST2001_PARAMS, ERR_R_MALLOC_FAILURE); + goto err; + } - BN_hex2bn(&x, params->x); - BN_hex2bn(&y, params->y); - EC_POINT_set_affine_coordinates_GFp(grp, P, x, y, ctx); - BN_hex2bn(&q, params->q); + if(!BN_hex2bn(&x, params->x) + || !BN_hex2bn(&y, params->y) + || !EC_POINT_set_affine_coordinates_GFp(grp, P, x, y, ctx) + || !BN_hex2bn(&q, params->q)) { + GOSTerr(GOST_F_FILL_GOST2001_PARAMS, ERR_R_INTERNAL_ERROR); + goto err; + } #ifdef DEBUG_KEYS fprintf(stderr, "Set params index %d oid %s\nq=", (params - R3410_2001_paramset), OBJ_nid2sn(params->nid)); @@ -74,16 +98,23 @@ int fill_GOST2001_params(EC_KEY *eckey, int nid) fprintf(stderr, "\n"); #endif - EC_GROUP_set_generator(grp, P, q, NULL); + if(!EC_GROUP_set_generator(grp, P, q, NULL)) { + GOSTerr(GOST_F_FILL_GOST2001_PARAMS, ERR_R_INTERNAL_ERROR); + goto err; + } EC_GROUP_set_curve_name(grp, params->nid); - - EC_KEY_set_group(eckey, grp); + if(!EC_KEY_set_group(eckey, grp)) { + GOSTerr(GOST_F_FILL_GOST2001_PARAMS, ERR_R_INTERNAL_ERROR); + goto err; + } ok = 1; err: - EC_POINT_free(P); - EC_GROUP_free(grp); - BN_CTX_end(ctx); - BN_CTX_free(ctx); + if (P) EC_POINT_free(P); + if (grp) EC_GROUP_free(grp); + if (ctx) { + BN_CTX_end(ctx); + BN_CTX_free(ctx); + } return ok; } @@ -94,7 +125,7 @@ int fill_GOST2001_params(EC_KEY *eckey, int nid) */ DSA_SIG *gost2001_do_sign(const unsigned char *dgst, int dlen, EC_KEY *eckey) { - DSA_SIG *newsig = NULL; + DSA_SIG *newsig = NULL, *ret = NULL; BIGNUM *md = hashsum2bn(dgst); BIGNUM *order = NULL; const EC_GROUP *group; @@ -103,6 +134,10 @@ DSA_SIG *gost2001_do_sign(const unsigned char *dgst, int dlen, EC_KEY *eckey) NULL, *e = NULL; EC_POINT *C = NULL; BN_CTX *ctx = BN_CTX_new(); + if(!ctx || !md) { + GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_MALLOC_FAILURE); + goto err; + } BN_CTX_start(ctx); OPENSSL_assert(dlen == 32); newsig = DSA_SIG_new(); @@ -111,11 +146,25 @@ DSA_SIG *gost2001_do_sign(const unsigned char *dgst, int dlen, EC_KEY *eckey) goto err; } group = EC_KEY_get0_group(eckey); + if(!group) { + GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_INTERNAL_ERROR); + goto err; + } order = BN_CTX_get(ctx); - EC_GROUP_get_order(group, order, ctx); + if(!order || !EC_GROUP_get_order(group, order, ctx)) { + GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_INTERNAL_ERROR); + goto err; + } priv_key = EC_KEY_get0_private_key(eckey); + if(!priv_key) { + GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_INTERNAL_ERROR); + goto err; + } e = BN_CTX_get(ctx); - BN_mod(e, md, order, ctx); + if(!e || !BN_mod(e, md, order, ctx)) { + GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_INTERNAL_ERROR); + goto err; + } #ifdef DEBUG_SIGN fprintf(stderr, "digest as bignum="); BN_print_fp(stderr, md); @@ -128,55 +177,80 @@ DSA_SIG *gost2001_do_sign(const unsigned char *dgst, int dlen, EC_KEY *eckey) } k = BN_CTX_get(ctx); C = EC_POINT_new(group); + if(!k || !C) { + GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_MALLOC_FAILURE); + goto err; + } do { do { if (!BN_rand_range(k, order)) { GOSTerr(GOST_F_GOST2001_DO_SIGN, GOST_R_RANDOM_NUMBER_GENERATOR_FAILED); - DSA_SIG_free(newsig); - newsig = NULL; goto err; } if (!EC_POINT_mul(group, C, k, NULL, NULL, ctx)) { GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_EC_LIB); - DSA_SIG_free(newsig); - newsig = NULL; goto err; } if (!X) X = BN_CTX_get(ctx); + if (!r) + r = BN_CTX_get(ctx); + if (!X || !r) { + GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_MALLOC_FAILURE); + goto err; + } if (!EC_POINT_get_affine_coordinates_GFp(group, C, X, NULL, ctx)) { GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_EC_LIB); - DSA_SIG_free(newsig); - newsig = NULL; goto err; } - if (!r) - r = BN_CTX_get(ctx); - BN_nnmod(r, X, order, ctx); + + if(!BN_nnmod(r, X, order, ctx)) { + GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_INTERNAL_ERROR); + goto err; + } } while (BN_is_zero(r)); /* s = (r*priv_key+k*e) mod order */ if (!tmp) tmp = BN_CTX_get(ctx); - BN_mod_mul(tmp, priv_key, r, order, ctx); if (!tmp2) tmp2 = BN_CTX_get(ctx); - BN_mod_mul(tmp2, k, e, order, ctx); if (!s) s = BN_CTX_get(ctx); - BN_mod_add(s, tmp, tmp2, order, ctx); + if (!tmp || !tmp2 || !s) { + GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_MALLOC_FAILURE); + goto err; + } + + if(!BN_mod_mul(tmp, priv_key, r, order, ctx) + || !BN_mod_mul(tmp2, k, e, order, ctx) + || !BN_mod_add(s, tmp, tmp2, order, ctx)) { + GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_INTERNAL_ERROR); + goto err; + } } while (BN_is_zero(s)); newsig->s = BN_dup(s); newsig->r = BN_dup(r); + if(!newsig->s || !newsig->r) { + GOSTerr(GOST_F_GOST2001_DO_SIGN, ERR_R_MALLOC_FAILURE); + goto err; + } + + ret = newsig; err: - BN_CTX_end(ctx); - BN_CTX_free(ctx); - EC_POINT_free(C); - BN_free(md); - return newsig; + if(ctx) { + BN_CTX_end(ctx); + BN_CTX_free(ctx); + } + if (C) EC_POINT_free(C); + if (md) BN_free(md); + if (!ret && newsig) { + DSA_SIG_free(newsig); + } + return ret; } /* @@ -196,6 +270,11 @@ int gost2001_do_verify(const unsigned char *dgst, int dgst_len, const EC_POINT *pub_key = NULL; int ok = 0; + if(!ctx || !group) { + GOSTerr(GOST_F_GOST2001_DO_VERIFY, ERR_R_INTERNAL_ERROR); + goto err; + } + BN_CTX_start(ctx); order = BN_CTX_get(ctx); e = BN_CTX_get(ctx); @@ -205,9 +284,17 @@ int gost2001_do_verify(const unsigned char *dgst, int dgst_len, X = BN_CTX_get(ctx); R = BN_CTX_get(ctx); v = BN_CTX_get(ctx); + if(!order || !e || !z1 || !z2 || !tmp || !X || !R || !v) { + GOSTerr(GOST_F_GOST2001_DO_VERIFY, ERR_R_MALLOC_FAILURE); + goto err; + } - EC_GROUP_get_order(group, order, ctx); pub_key = EC_KEY_get0_public_key(ec); + if(!pub_key || !EC_GROUP_get_order(group, order, ctx)) { + GOSTerr(GOST_F_GOST2001_DO_VERIFY, ERR_R_INTERNAL_ERROR); + goto err; + } + if (BN_is_zero(sig->s) || BN_is_zero(sig->r) || (BN_cmp(sig->s, order) >= 1) || (BN_cmp(sig->r, order) >= 1)) { GOSTerr(GOST_F_GOST2001_DO_VERIFY, @@ -217,19 +304,28 @@ int gost2001_do_verify(const unsigned char *dgst, int dgst_len, } md = hashsum2bn(dgst); - BN_mod(e, md, order, ctx); + if(!md || !BN_mod(e, md, order, ctx)) { + GOSTerr(GOST_F_GOST2001_DO_VERIFY, ERR_R_INTERNAL_ERROR); + goto err; + } #ifdef DEBUG_SIGN fprintf(stderr, "digest as bignum: "); BN_print_fp(stderr, md); fprintf(stderr, "\ndigest mod q: "); BN_print_fp(stderr, e); #endif - if (BN_is_zero(e)) - BN_one(e); + if (BN_is_zero(e) && !BN_one(e)) { + GOSTerr(GOST_F_GOST2001_DO_VERIFY, ERR_R_INTERNAL_ERROR); + goto err; + } v = BN_mod_inverse(v, e, order, ctx); - BN_mod_mul(z1, sig->s, v, order, ctx); - BN_sub(tmp, order, sig->r); - BN_mod_mul(z2, tmp, v, order, ctx); + if(!v + || !BN_mod_mul(z1, sig->s, v, order, ctx) + || !BN_sub(tmp, order, sig->r) + || !BN_mod_mul(z2, tmp, v, order, ctx)) { + GOSTerr(GOST_F_GOST2001_DO_VERIFY, ERR_R_INTERNAL_ERROR); + goto err; + } #ifdef DEBUG_SIGN fprintf(stderr, "\nInverted digest value: "); BN_print_fp(stderr, v); @@ -239,6 +335,10 @@ int gost2001_do_verify(const unsigned char *dgst, int dgst_len, BN_print_fp(stderr, z2); #endif C = EC_POINT_new(group); + if (!C) { + GOSTerr(GOST_F_GOST2001_DO_VERIFY, ERR_R_MALLOC_FAILURE); + goto err; + } if (!EC_POINT_mul(group, C, z1, pub_key, z2, ctx)) { GOSTerr(GOST_F_GOST2001_DO_VERIFY, ERR_R_EC_LIB); goto err; @@ -247,7 +347,10 @@ int gost2001_do_verify(const unsigned char *dgst, int dgst_len, GOSTerr(GOST_F_GOST2001_DO_VERIFY, ERR_R_EC_LIB); goto err; } - BN_mod(R, X, order, ctx); + if(!BN_mod(R, X, order, ctx)) { + GOSTerr(GOST_F_GOST2001_DO_VERIFY, ERR_R_INTERNAL_ERROR); + goto err; + } #ifdef DEBUG_SIGN fprintf(stderr, "\nX="); BN_print_fp(stderr, X); @@ -261,10 +364,12 @@ int gost2001_do_verify(const unsigned char *dgst, int dgst_len, ok = 1; } err: - EC_POINT_free(C); - BN_CTX_end(ctx); - BN_CTX_free(ctx); - BN_free(md); + if (C) EC_POINT_free(C); + if (ctx) { + BN_CTX_end(ctx); + BN_CTX_free(ctx); + } + if (md) BN_free(md); return ok; } @@ -287,6 +392,10 @@ int gost2001_compute_public(EC_KEY *ec) return 0; } ctx = BN_CTX_new(); + if(!ctx) { + GOSTerr(GOST_F_GOST2001_COMPUTE_PUBLIC, ERR_R_MALLOC_FAILURE); + goto err; + } BN_CTX_start(ctx); if (!(priv_key = EC_KEY_get0_private_key(ec))) { GOSTerr(GOST_F_GOST2001_COMPUTE_PUBLIC, ERR_R_EC_LIB); @@ -294,6 +403,10 @@ int gost2001_compute_public(EC_KEY *ec) } pub_key = EC_POINT_new(group); + if(!pub_key) { + GOSTerr(GOST_F_GOST2001_COMPUTE_PUBLIC, ERR_R_MALLOC_FAILURE); + goto err; + } if (!EC_POINT_mul(group, pub_key, priv_key, NULL, NULL, ctx)) { GOSTerr(GOST_F_GOST2001_COMPUTE_PUBLIC, ERR_R_EC_LIB); goto err; @@ -304,9 +417,11 @@ int gost2001_compute_public(EC_KEY *ec) } ok = 256; err: - BN_CTX_end(ctx); - EC_POINT_free(pub_key); - BN_CTX_free(ctx); + if (pub_key) EC_POINT_free(pub_key); + if (ctx) { + BN_CTX_end(ctx); + BN_CTX_free(ctx); + } return ok; } @@ -320,7 +435,13 @@ int gost2001_keygen(EC_KEY *ec) { BIGNUM *order = BN_new(), *d = BN_new(); const EC_GROUP *group = EC_KEY_get0_group(ec); - EC_GROUP_get_order(group, order, NULL); + + if(!group || !EC_GROUP_get_order(group, order, NULL)) { + GOSTerr(GOST_F_GOST2001_KEYGEN, ERR_R_INTERNAL_ERROR); + BN_free(d); + BN_free(order); + return 0; + } do { if (!BN_rand_range(d, order)) { @@ -332,7 +453,13 @@ int gost2001_keygen(EC_KEY *ec) } } while (BN_is_zero(d)); - EC_KEY_set_private_key(ec, d); + + if(!EC_KEY_set_private_key(ec, d)) { + GOSTerr(GOST_F_GOST2001_KEYGEN, ERR_R_INTERNAL_ERROR); + BN_free(d); + BN_free(order); + return 0; + } BN_free(d); BN_free(order); return gost2001_compute_public(ec); diff --git a/crypto/openssl/engines/ccgost/gost94_keyx.c b/crypto/openssl/engines/ccgost/gost94_keyx.c index 85f4bc8998..ce57f17cbf 100644 --- a/crypto/openssl/engines/ccgost/gost94_keyx.c +++ b/crypto/openssl/engines/ccgost/gost94_keyx.c @@ -104,6 +104,7 @@ int pkey_GOST94cp_encrypt(EVP_PKEY_CTX *ctx, unsigned char *out, struct gost_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx); gost_ctx cctx; int key_is_ephemeral = 1; + int tmp_outlen; EVP_PKEY *mykey = EVP_PKEY_CTX_get0_peerkey(ctx); /* Do not use vizir cipher parameters with cryptopro */ @@ -174,12 +175,13 @@ int pkey_GOST94cp_encrypt(EVP_PKEY_CTX *ctx, unsigned char *out, } ASN1_OBJECT_free(gkt->key_agreement_info->cipher); gkt->key_agreement_info->cipher = OBJ_nid2obj(param->nid); - *outlen = i2d_GOST_KEY_TRANSPORT(gkt, out ? &out : NULL); - if (*outlen <= 0) { + tmp_outlen = i2d_GOST_KEY_TRANSPORT(gkt, out ? &out : NULL); + if (tmp_outlen <= 0) { GOSTerr(GOST_F_PKEY_GOST94CP_ENCRYPT, GOST_R_ERROR_PACKING_KEY_TRANSPORT_INFO); goto err; } + *outlen = tmp_outlen; if (!key_is_ephemeral) { /* Set control "public key from client certificate used" */ if (EVP_PKEY_CTX_ctrl(ctx, -1, -1, EVP_PKEY_CTRL_PEER_KEY, 3, NULL) <= diff --git a/crypto/openssl/engines/ccgost/gost_ameth.c b/crypto/openssl/engines/ccgost/gost_ameth.c index 713a0face5..b7c5354c1a 100644 --- a/crypto/openssl/engines/ccgost/gost_ameth.c +++ b/crypto/openssl/engines/ccgost/gost_ameth.c @@ -115,7 +115,10 @@ static int decode_gost_algor_params(EVP_PKEY *pkey, X509_ALGOR *palg) } param_nid = OBJ_obj2nid(gkp->key_params); GOST_KEY_PARAMS_free(gkp); - EVP_PKEY_set_type(pkey, pkey_nid); + if(!EVP_PKEY_set_type(pkey, pkey_nid)) { + GOSTerr(GOST_F_DECODE_GOST_ALGOR_PARAMS, ERR_R_INTERNAL_ERROR); + return 0; + } switch (pkey_nid) { case NID_id_GostR3410_94: { @@ -552,9 +555,19 @@ static int param_copy_gost01(EVP_PKEY *to, const EVP_PKEY *from) } if (!eto) { eto = EC_KEY_new(); - EVP_PKEY_assign(to, EVP_PKEY_base_id(from), eto); + if(!eto) { + GOSTerr(GOST_F_PARAM_COPY_GOST01, ERR_R_MALLOC_FAILURE); + return 0; + } + if(!EVP_PKEY_assign(to, EVP_PKEY_base_id(from), eto)) { + GOSTerr(GOST_F_PARAM_COPY_GOST01, ERR_R_INTERNAL_ERROR); + return 0; + } + } + if(!EC_KEY_set_group(eto, EC_KEY_get0_group(efrom))) { + GOSTerr(GOST_F_PARAM_COPY_GOST01, ERR_R_INTERNAL_ERROR); + return 0; } - EC_KEY_set_group(eto, EC_KEY_get0_group(efrom)); if (EC_KEY_get0_private_key(eto)) { gost2001_compute_public(eto); } @@ -729,8 +742,21 @@ static int pub_encode_gost01(X509_PUBKEY *pub, const EVP_PKEY *pk) } X = BN_new(); Y = BN_new(); - EC_POINT_get_affine_coordinates_GFp(EC_KEY_get0_group(ec), - pub_key, X, Y, NULL); + if(!X || !Y) { + GOSTerr(GOST_F_PUB_ENCODE_GOST01, ERR_R_MALLOC_FAILURE); + if(X) BN_free(X); + if(Y) BN_free(Y); + BN_free(order); + return 0; + } + if(!EC_POINT_get_affine_coordinates_GFp(EC_KEY_get0_group(ec), + pub_key, X, Y, NULL)) { + GOSTerr(GOST_F_PUB_ENCODE_GOST01, ERR_R_INTERNAL_ERROR); + BN_free(X); + BN_free(Y); + BN_free(order); + return 0; + } data_len = 2 * BN_num_bytes(order); BN_free(order); databuf = OPENSSL_malloc(data_len); diff --git a/crypto/openssl/engines/ccgost/gost_pmeth.c b/crypto/openssl/engines/ccgost/gost_pmeth.c index 9af7b06d43..b6275b2558 100644 --- a/crypto/openssl/engines/ccgost/gost_pmeth.c +++ b/crypto/openssl/engines/ccgost/gost_pmeth.c @@ -502,7 +502,7 @@ static int pkey_gost_mac_ctrl_str(EVP_PKEY_CTX *ctx, long keylen; int ret; unsigned char *keybuf = string_to_hex(value, &keylen); - if (keylen != 32) { + if (!keybuf || keylen != 32) { GOSTerr(GOST_F_PKEY_GOST_MAC_CTRL_STR, GOST_R_INVALID_MAC_KEY_LENGTH); OPENSSL_free(keybuf); diff --git a/crypto/openssl/engines/ccgost/gost_sign.c b/crypto/openssl/engines/ccgost/gost_sign.c index 0116e47400..07ad921ab5 100644 --- a/crypto/openssl/engines/ccgost/gost_sign.c +++ b/crypto/openssl/engines/ccgost/gost_sign.c @@ -12,6 +12,7 @@ #include #include #include +#include #include "gost_params.h" #include "gost_lcl.h" @@ -52,11 +53,16 @@ void dump_dsa_sig(const char *message, DSA_SIG *sig) DSA_SIG *gost_do_sign(const unsigned char *dgst, int dlen, DSA *dsa) { BIGNUM *k = NULL, *tmp = NULL, *tmp2 = NULL; - DSA_SIG *newsig = DSA_SIG_new(); + DSA_SIG *newsig = NULL, *ret = NULL; BIGNUM *md = hashsum2bn(dgst); /* check if H(M) mod q is zero */ BN_CTX *ctx = BN_CTX_new(); + if(!ctx) { + GOSTerr(GOST_F_GOST_DO_SIGN, ERR_R_MALLOC_FAILURE); + goto err; + } BN_CTX_start(ctx); + newsig = DSA_SIG_new(); if (!newsig) { GOSTerr(GOST_F_GOST_DO_SIGN, GOST_R_NO_MEMORY); goto err; @@ -64,6 +70,10 @@ DSA_SIG *gost_do_sign(const unsigned char *dgst, int dlen, DSA *dsa) tmp = BN_CTX_get(ctx); k = BN_CTX_get(ctx); tmp2 = BN_CTX_get(ctx); + if(!tmp || !k || !tmp2) { + GOSTerr(GOST_F_GOST_DO_SIGN, ERR_R_MALLOC_FAILURE); + goto err; + } BN_mod(tmp, md, dsa->q, ctx); if (BN_is_zero(tmp)) { BN_one(md); @@ -76,24 +86,41 @@ DSA_SIG *gost_do_sign(const unsigned char *dgst, int dlen, DSA *dsa) BN_rand_range(k, dsa->q); /* generate r = (a^x mod p) mod q */ BN_mod_exp(tmp, dsa->g, k, dsa->p, ctx); - if (!(newsig->r)) + if (!(newsig->r)) { newsig->r = BN_new(); + if(!newsig->r) { + GOSTerr(GOST_F_GOST_DO_SIGN, ERR_R_MALLOC_FAILURE); + goto err; + } + } BN_mod(newsig->r, tmp, dsa->q, ctx); } while (BN_is_zero(newsig->r)); /* generate s = (xr + k(Hm)) mod q */ BN_mod_mul(tmp, dsa->priv_key, newsig->r, dsa->q, ctx); BN_mod_mul(tmp2, k, md, dsa->q, ctx); - if (!newsig->s) + if (!newsig->s) { newsig->s = BN_new(); + if(!newsig->s) { + GOSTerr(GOST_F_GOST_DO_SIGN, ERR_R_MALLOC_FAILURE); + goto err; + } + } BN_mod_add(newsig->s, tmp, tmp2, dsa->q, ctx); } while (BN_is_zero(newsig->s)); + + ret = newsig; err: BN_free(md); - BN_CTX_end(ctx); - BN_CTX_free(ctx); - return newsig; + if(ctx) { + BN_CTX_end(ctx); + BN_CTX_free(ctx); + } + if(!ret && newsig) { + DSA_SIG_free(newsig); + } + return ret; } /* @@ -135,17 +162,21 @@ int pack_sign_cp(DSA_SIG *s, int order, unsigned char *sig, size_t *siglen) int gost_do_verify(const unsigned char *dgst, int dgst_len, DSA_SIG *sig, DSA *dsa) { - BIGNUM *md, *tmp = NULL; + BIGNUM *md = NULL, *tmp = NULL; BIGNUM *q2 = NULL; BIGNUM *u = NULL, *v = NULL, *z1 = NULL, *z2 = NULL; BIGNUM *tmp2 = NULL, *tmp3 = NULL; - int ok; + int ok = 0; BN_CTX *ctx = BN_CTX_new(); + if(!ctx) { + GOSTerr(GOST_F_GOST_DO_VERIFY, ERR_R_MALLOC_FAILURE); + goto err; + } BN_CTX_start(ctx); if (BN_cmp(sig->s, dsa->q) >= 1 || BN_cmp(sig->r, dsa->q) >= 1) { GOSTerr(GOST_F_GOST_DO_VERIFY, GOST_R_SIGNATURE_PARTS_GREATER_THAN_Q); - return 0; + goto err; } md = hashsum2bn(dgst); @@ -157,6 +188,10 @@ int gost_do_verify(const unsigned char *dgst, int dgst_len, tmp2 = BN_CTX_get(ctx); tmp3 = BN_CTX_get(ctx); u = BN_CTX_get(ctx); + if(!tmp || !v || !q2 || !z1 || !z2 || !tmp2 || !tmp3 || !u) { + GOSTerr(GOST_F_GOST_DO_VERIFY, ERR_R_MALLOC_FAILURE); + goto err; + } BN_mod(tmp, md, dsa->q, ctx); if (BN_is_zero(tmp)) { @@ -172,15 +207,18 @@ int gost_do_verify(const unsigned char *dgst, int dgst_len, BN_mod_exp(tmp2, dsa->pub_key, z2, dsa->p, ctx); BN_mod_mul(tmp3, tmp, tmp2, dsa->p, ctx); BN_mod(u, tmp3, dsa->q, ctx); - ok = BN_cmp(u, sig->r); + ok = (BN_cmp(u, sig->r) == 0); - BN_free(md); - BN_CTX_end(ctx); - BN_CTX_free(ctx); - if (ok != 0) { + if (!ok) { GOSTerr(GOST_F_GOST_DO_VERIFY, GOST_R_SIGNATURE_MISMATCH); } - return (ok == 0); +err: + if(md) BN_free(md); + if(ctx) { + BN_CTX_end(ctx); + BN_CTX_free(ctx); + } + return ok; } /* @@ -190,13 +228,24 @@ int gost_do_verify(const unsigned char *dgst, int dgst_len, int gost94_compute_public(DSA *dsa) { /* Now fill algorithm parameters with correct values */ - BN_CTX *ctx = BN_CTX_new(); + BN_CTX *ctx; if (!dsa->g) { GOSTerr(GOST_F_GOST94_COMPUTE_PUBLIC, GOST_R_KEY_IS_NOT_INITALIZED); return 0; } - /* Compute public key y = a^x mod p */ + ctx = BN_CTX_new(); + if(!ctx) { + GOSTerr(GOST_F_GOST94_COMPUTE_PUBLIC, ERR_R_MALLOC_FAILURE); + return 0; + } + dsa->pub_key = BN_new(); + if(!dsa->pub_key) { + GOSTerr(GOST_F_GOST94_COMPUTE_PUBLIC, ERR_R_MALLOC_FAILURE); + BN_CTX_free(ctx); + return 0; + } + /* Compute public key y = a^x mod p */ BN_mod_exp(dsa->pub_key, dsa->g, dsa->priv_key, dsa->p, ctx); BN_CTX_free(ctx); return 1; @@ -243,6 +292,10 @@ int fill_GOST94_params(DSA *dsa, int nid) int gost_sign_keygen(DSA *dsa) { dsa->priv_key = BN_new(); + if(!dsa->priv_key) { + GOSTerr(GOST_F_GOST_SIGN_KEYGEN, ERR_R_MALLOC_FAILURE); + return 0; + } BN_rand_range(dsa->priv_key, dsa->q); return gost94_compute_public(dsa); } diff --git a/crypto/openssl/engines/e_sureware.c b/crypto/openssl/engines/e_sureware.c index 1005dfc903..8a23763f75 100644 --- a/crypto/openssl/engines/e_sureware.c +++ b/crypto/openssl/engines/e_sureware.c @@ -712,10 +712,12 @@ static EVP_PKEY *sureware_load_public(ENGINE *e, const char *key_id, /* set public big nums */ rsatmp->e = BN_new(); rsatmp->n = BN_new(); + if(!rsatmp->e || !rsatmp->n) + goto err; bn_expand2(rsatmp->e, el / sizeof(BN_ULONG)); bn_expand2(rsatmp->n, el / sizeof(BN_ULONG)); - if (!rsatmp->e || rsatmp->e->dmax != (int)(el / sizeof(BN_ULONG)) || - !rsatmp->n || rsatmp->n->dmax != (int)(el / sizeof(BN_ULONG))) + if (rsatmp->e->dmax != (int)(el / sizeof(BN_ULONG)) || + rsatmp->n->dmax != (int)(el / sizeof(BN_ULONG))) goto err; ret = p_surewarehk_Load_Rsa_Pubkey(msg, key_id, el, (unsigned long *)rsatmp->n->d, @@ -752,15 +754,16 @@ static EVP_PKEY *sureware_load_public(ENGINE *e, const char *key_id, dsatmp->p = BN_new(); dsatmp->q = BN_new(); dsatmp->g = BN_new(); + if(!dsatmp->pub_key || !dsatmp->p || !dsatmp->q || !dsatmp->g) + goto err; bn_expand2(dsatmp->pub_key, el / sizeof(BN_ULONG)); bn_expand2(dsatmp->p, el / sizeof(BN_ULONG)); bn_expand2(dsatmp->q, 20 / sizeof(BN_ULONG)); bn_expand2(dsatmp->g, el / sizeof(BN_ULONG)); - if (!dsatmp->pub_key - || dsatmp->pub_key->dmax != (int)(el / sizeof(BN_ULONG)) - || !dsatmp->p || dsatmp->p->dmax != (int)(el / sizeof(BN_ULONG)) - || !dsatmp->q || dsatmp->q->dmax != 20 / sizeof(BN_ULONG) - || !dsatmp->g || dsatmp->g->dmax != (int)(el / sizeof(BN_ULONG))) + if (dsatmp->pub_key->dmax != (int)(el / sizeof(BN_ULONG)) + || dsatmp->p->dmax != (int)(el / sizeof(BN_ULONG)) + || dsatmp->q->dmax != 20 / sizeof(BN_ULONG) + || dsatmp->g->dmax != (int)(el / sizeof(BN_ULONG))) goto err; ret = p_surewarehk_Load_Dsa_Pubkey(msg, key_id, el, @@ -1038,10 +1041,12 @@ static DSA_SIG *surewarehk_dsa_do_sign(const unsigned char *from, int flen, } psign->r = BN_new(); psign->s = BN_new(); + if(!psign->r || !psign->s) + goto err; bn_expand2(psign->r, 20 / sizeof(BN_ULONG)); bn_expand2(psign->s, 20 / sizeof(BN_ULONG)); - if (!psign->r || psign->r->dmax != 20 / sizeof(BN_ULONG) || - !psign->s || psign->s->dmax != 20 / sizeof(BN_ULONG)) + if (psign->r->dmax != 20 / sizeof(BN_ULONG) || + psign->s->dmax != 20 / sizeof(BN_ULONG)) goto err; ret = p_surewarehk_Dsa_Sign(msg, flen, from, (unsigned long *)psign->r->d, @@ -1070,9 +1075,9 @@ static int surewarehk_modexp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, char msg[64] = "ENGINE_modexp"; if (!p_surewarehk_Mod_Exp) { SUREWAREerr(SUREWARE_F_SUREWAREHK_MODEXP, ENGINE_R_NOT_INITIALISED); - } else { + } else if (r) { bn_expand2(r, m->top); - if (r && r->dmax == m->top) { + if (r->dmax == m->top) { /* do it */ ret = p_surewarehk_Mod_Exp(msg, m->top * sizeof(BN_ULONG), diff --git a/crypto/openssl/ssl/d1_both.c b/crypto/openssl/ssl/d1_both.c index c18ec03bd1..8dd8ea33ca 100644 --- a/crypto/openssl/ssl/d1_both.c +++ b/crypto/openssl/ssl/d1_both.c @@ -485,6 +485,12 @@ long dtls1_get_message(SSL *s, int st1, int stn, int mt, long max, int *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 @@ -879,10 +899,6 @@ dtls1_get_message_fragment(SSL *s, int st1, int stn, long max, int *ok) && !(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,17 +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; @@ -944,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 @@ -1540,7 +1556,10 @@ int dtls1_process_heartbeat(SSL *s) memcpy(bp, pl, payload); bp += payload; /* Random padding */ - RAND_pseudo_bytes(bp, padding); + if (RAND_pseudo_bytes(bp, padding) < 0) { + OPENSSL_free(buffer); + return -1; + } r = dtls1_write_bytes(s, TLS1_RT_HEARTBEAT, buffer, write_length); @@ -1574,7 +1593,7 @@ int dtls1_process_heartbeat(SSL *s) int dtls1_heartbeat(SSL *s) { unsigned char *buf, *p; - int ret; + int ret = -1; unsigned int payload = 18; /* Sequence number + random bytes */ unsigned int padding = 16; /* Use minimum padding */ @@ -1622,10 +1641,12 @@ int dtls1_heartbeat(SSL *s) /* Sequence number */ s2n(s->tlsext_hb_seq, p); /* 16 random bytes */ - RAND_pseudo_bytes(p, 16); + if (RAND_pseudo_bytes(p, 16) < 0) + goto err; p += 16; /* Random padding */ - RAND_pseudo_bytes(p, padding); + if (RAND_pseudo_bytes(p, padding) < 0) + goto err; ret = dtls1_write_bytes(s, TLS1_RT_HEARTBEAT, buf, 3 + payload + padding); if (ret >= 0) { @@ -1638,6 +1659,7 @@ int dtls1_heartbeat(SSL *s) s->tlsext_hb_pending = 1; } +err: OPENSSL_free(buf); return ret; diff --git a/crypto/openssl/ssl/d1_clnt.c b/crypto/openssl/ssl/d1_clnt.c index 1394781c04..377c1e61f7 100644 --- a/crypto/openssl/ssl/d1_clnt.c +++ b/crypto/openssl/ssl/d1_clnt.c @@ -212,6 +212,7 @@ int dtls1_connect(SSL *s) (s->version & 0xff00) != (DTLS1_BAD_VER & 0xff00)) { SSLerr(SSL_F_DTLS1_CONNECT, ERR_R_INTERNAL_ERROR); ret = -1; + s->state = SSL_ST_ERR; goto end; } @@ -221,10 +222,12 @@ int dtls1_connect(SSL *s) if (s->init_buf == NULL) { if ((buf = BUF_MEM_new()) == NULL) { ret = -1; + s->state = SSL_ST_ERR; goto end; } if (!BUF_MEM_grow(buf, SSL3_RT_MAX_PLAIN_LENGTH)) { ret = -1; + s->state = SSL_ST_ERR; goto end; } s->init_buf = buf; @@ -233,12 +236,14 @@ int dtls1_connect(SSL *s) if (!ssl3_setup_buffers(s)) { ret = -1; + s->state = SSL_ST_ERR; goto end; } /* setup buffing BIO */ if (!ssl_init_wbio_buffer(s, 0)) { ret = -1; + s->state = SSL_ST_ERR; goto end; } @@ -417,6 +422,7 @@ int dtls1_connect(SSL *s) */ if (!ssl3_check_cert_and_algorithm(s)) { ret = -1; + s->state = SSL_ST_ERR; goto end; } break; @@ -548,6 +554,7 @@ int dtls1_connect(SSL *s) #endif if (!s->method->ssl3_enc->setup_key_block(s)) { ret = -1; + s->state = SSL_ST_ERR; goto end; } @@ -555,6 +562,7 @@ int dtls1_connect(SSL *s) SSL3_CHANGE_CIPHER_CLIENT_WRITE)) { ret = -1; + s->state = SSL_ST_ERR; goto end; } #ifndef OPENSSL_NO_SCTP @@ -735,6 +743,7 @@ int dtls1_connect(SSL *s) goto end; /* break; */ + case SSL_ST_ERR: default: SSLerr(SSL_F_DTLS1_CONNECT, SSL_R_UNKNOWN_STATE); ret = -1; @@ -945,6 +954,7 @@ static int dtls1_get_hello_verify(SSL *s) f_err: ssl3_send_alert(s, SSL3_AL_FATAL, al); + s->state = SSL_ST_ERR; return -1; } diff --git a/crypto/openssl/ssl/d1_lib.c b/crypto/openssl/ssl/d1_lib.c index 94acb15de6..011d7b7cbe 100644 --- a/crypto/openssl/ssl/d1_lib.c +++ b/crypto/openssl/ssl/d1_lib.c @@ -496,6 +496,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 7b49a7dd7a..d659ed428e 100644 --- a/crypto/openssl/ssl/d1_pkt.c +++ b/crypto/openssl/ssl/d1_pkt.c @@ -1065,7 +1065,7 @@ int dtls1_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek) (s->d1->handshake_fragment[3] != 0)) { al = SSL_AD_DECODE_ERROR; SSLerr(SSL_F_DTLS1_READ_BYTES, SSL_R_BAD_HELLO_REQUEST); - goto err; + goto f_err; } /* diff --git a/crypto/openssl/ssl/d1_srvr.c b/crypto/openssl/ssl/d1_srvr.c index c4ec9fe108..41c7dc519f 100644 --- a/crypto/openssl/ssl/d1_srvr.c +++ b/crypto/openssl/ssl/d1_srvr.c @@ -224,11 +224,13 @@ int dtls1_accept(SSL *s) if (s->init_buf == NULL) { if ((buf = BUF_MEM_new()) == NULL) { ret = -1; + s->state = SSL_ST_ERR; goto end; } if (!BUF_MEM_grow(buf, SSL3_RT_MAX_PLAIN_LENGTH)) { BUF_MEM_free(buf); ret = -1; + s->state = SSL_ST_ERR; goto end; } s->init_buf = buf; @@ -236,6 +238,7 @@ int dtls1_accept(SSL *s) if (!ssl3_setup_buffers(s)) { ret = -1; + s->state = SSL_ST_ERR; goto end; } @@ -257,6 +260,7 @@ int dtls1_accept(SSL *s) #endif if (!ssl_init_wbio_buffer(s, 1)) { ret = -1; + s->state = SSL_ST_ERR; goto end; } @@ -470,7 +474,7 @@ int dtls1_accept(SSL *s) #ifndef OPENSSL_NO_PSK || ((alg_k & SSL_kPSK) && s->ctx->psk_identity_hint) #endif - || (alg_k & (SSL_kEDH | SSL_kDHr | SSL_kDHd)) + || (alg_k & SSL_kEDH) || (alg_k & SSL_kEECDH) || ((alg_k & SSL_kRSA) && (s->cert->pkeys[SSL_PKEY_RSA_ENC].privatekey == NULL @@ -665,15 +669,6 @@ int dtls1_accept(SSL *s) case SSL3_ST_SR_CERT_VRFY_A: case SSL3_ST_SR_CERT_VRFY_B: - /* - * This *should* be the first time we enable CCS, but be - * extra careful about surrounding code changes. We need - * to set this here because we don't know if we're - * expecting a CertificateVerify or not. - */ - if (!s->s3->change_cipher_spec) - s->d1->change_cipher_spec_ok = 1; - /* we should decide if we expected this one */ ret = ssl3_get_cert_verify(s); if (ret <= 0) goto end; @@ -690,11 +685,10 @@ int dtls1_accept(SSL *s) case SSL3_ST_SR_FINISHED_A: case SSL3_ST_SR_FINISHED_B: /* - * Enable CCS for resumed handshakes. - * In a full handshake, we end up here through - * SSL3_ST_SR_CERT_VRFY_B, so change_cipher_spec_ok was - * already set. Receiving a CCS clears the flag, so make - * sure not to re-enable it to ban duplicates. + * Enable CCS. Receiving a CCS clears the flag, so make + * sure not to re-enable it to ban duplicates. This *should* be the + * first time we have received one - but we check anyway to be + * cautious. * s->s3->change_cipher_spec is set when a CCS is * processed in d1_pkt.c, and remains set until * the client's Finished message is read. @@ -744,6 +738,7 @@ int dtls1_accept(SSL *s) s->session->cipher = s->s3->tmp.new_cipher; if (!s->method->ssl3_enc->setup_key_block(s)) { ret = -1; + s->state = SSL_ST_ERR; goto end; } @@ -772,6 +767,7 @@ int dtls1_accept(SSL *s) SSL3_CHANGE_CIPHER_SERVER_WRITE)) { ret = -1; + s->state = SSL_ST_ERR; goto end; } @@ -852,6 +848,7 @@ int dtls1_accept(SSL *s) goto end; /* break; */ + case SSL_ST_ERR: default: SSLerr(SSL_F_DTLS1_ACCEPT, SSL_R_UNKNOWN_STATE); ret = -1; @@ -932,6 +929,7 @@ int dtls1_send_hello_verify_request(SSL *s) &(s->d1->cookie_len)) == 0) { SSLerr(SSL_F_DTLS1_SEND_HELLO_VERIFY_REQUEST, ERR_R_INTERNAL_ERROR); + s->state = SSL_ST_ERR; return 0; } diff --git a/crypto/openssl/ssl/s2_pkt.c b/crypto/openssl/ssl/s2_pkt.c index 614b9a35d2..7a61888134 100644 --- a/crypto/openssl/ssl/s2_pkt.c +++ b/crypto/openssl/ssl/s2_pkt.c @@ -576,6 +576,20 @@ static int n_do_ssl_write(SSL *s, const unsigned char *buf, unsigned int len) s->s2->padding = p; s->s2->mac_data = &(s->s2->wbuf[3]); s->s2->wact_data = &(s->s2->wbuf[3 + mac_size]); + + /* + * It would be clearer to write this as follows: + * if (mac_size + len + p > SSL2_MAX_RECORD_LENGTH_2_BYTE_HEADER) + * However |len| is user input that could in theory be very large. We + * know |mac_size| and |p| are small, so to avoid any possibility of + * overflow we write it like this. + * + * In theory this should never fail because the logic above should have + * modified |len| if it is too big. But we are being cautious. + */ + if (len > (SSL2_MAX_RECORD_LENGTH_2_BYTE_HEADER - (mac_size + p))) { + return -1; + } /* we copy the data into s->s2->wbuf */ memcpy(s->s2->wact_data, buf, len); if (p) diff --git a/crypto/openssl/ssl/s2_srvr.c b/crypto/openssl/ssl/s2_srvr.c index 19bb48c9cd..4289272b73 100644 --- a/crypto/openssl/ssl/s2_srvr.c +++ b/crypto/openssl/ssl/s2_srvr.c @@ -111,6 +111,7 @@ #include "ssl_locl.h" #ifndef OPENSSL_NO_SSL2 +#include "../crypto/constant_time_locl.h" # include # include # include @@ -372,12 +373,15 @@ int ssl2_accept(SSL *s) static int get_client_master_key(SSL *s) { int is_export, i, n, keya; - unsigned int ek; + unsigned int num_encrypted_key_bytes, key_length; unsigned long len; unsigned char *p; const SSL_CIPHER *cp; const EVP_CIPHER *c; const EVP_MD *md; + unsigned char rand_premaster_secret[SSL_MAX_MASTER_KEY_LENGTH]; + unsigned char decrypt_good; + size_t j; p = (unsigned char *)s->init_buf->data; if (s->state == SSL2_ST_GET_CLIENT_MASTER_KEY_A) { @@ -465,12 +469,6 @@ static int get_client_master_key(SSL *s) return (0); } - if (s->session->cipher->algorithm2 & SSL2_CF_8_BYTE_ENC) { - is_export = 1; - ek = 8; - } else - ek = 5; - /* * The format of the CLIENT-MASTER-KEY message is * 1 byte message type @@ -484,12 +482,27 @@ static int get_client_master_key(SSL *s) * * If the cipher is an export cipher, then the encrypted key bytes * are a fixed portion of the total key (5 or 8 bytes). The size of - * this portion is in |ek|. If the cipher is not an export cipher, - * then the entire key material is encrypted (i.e., clear key length - * must be zero). + * this portion is in |num_encrypted_key_bytes|. If the cipher is not an + * export cipher, then the entire key material is encrypted (i.e., clear + * key length must be zero). */ - if ((!is_export && s->s2->tmp.clear != 0) || - (is_export && s->s2->tmp.clear + ek != (unsigned int)EVP_CIPHER_key_length(c))) { + key_length = (unsigned int)EVP_CIPHER_key_length(c); + if (key_length > SSL_MAX_MASTER_KEY_LENGTH) { + ssl2_return_error(s, SSL2_PE_UNDEFINED_ERROR); + SSLerr(SSL_F_GET_CLIENT_MASTER_KEY, ERR_R_INTERNAL_ERROR); + return -1; + } + + if (s->session->cipher->algorithm2 & SSL2_CF_8_BYTE_ENC) { + is_export = 1; + num_encrypted_key_bytes = 8; + } else if (is_export) { + num_encrypted_key_bytes = 5; + } else { + num_encrypted_key_bytes = key_length; + } + + if (s->s2->tmp.clear + num_encrypted_key_bytes != key_length) { ssl2_return_error(s, SSL2_PE_UNDEFINED_ERROR); SSLerr(SSL_F_GET_CLIENT_MASTER_KEY,SSL_R_BAD_LENGTH); return -1; @@ -499,64 +512,49 @@ static int get_client_master_key(SSL *s) * Decryption can't be expanding, so if we don't have enough encrypted * bytes to fit the key in the buffer, stop now. */ - if ((is_export && s->s2->tmp.enc < ek) || - (!is_export && s->s2->tmp.enc < (unsigned int)EVP_CIPHER_key_length(c))) { + if (s->s2->tmp.enc < num_encrypted_key_bytes) { ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR); SSLerr(SSL_F_GET_CLIENT_MASTER_KEY,SSL_R_LENGTH_TOO_SHORT); return -1; } + /* + * We must not leak whether a decryption failure occurs because of + * Bleichenbacher's attack on PKCS #1 v1.5 RSA padding (see RFC 2246, + * section 7.4.7.1). The code follows that advice of the TLS RFC and + * generates a random premaster secret for the case that the decrypt + * fails. See https://tools.ietf.org/html/rfc5246#section-7.4.7.1 + */ + + /* + * should be RAND_bytes, but we cannot work around a failure. + */ + if (RAND_pseudo_bytes(rand_premaster_secret, + (int)num_encrypted_key_bytes) <= 0) + return 0; + i = ssl_rsa_private_decrypt(s->cert, s->s2->tmp.enc, &(p[s->s2->tmp.clear]), &(p[s->s2->tmp.clear]), (s->s2->ssl2_rollback) ? RSA_SSLV23_PADDING : RSA_PKCS1_PADDING); - - /* bad decrypt */ -# if 1 + ERR_clear_error(); /* * If a bad decrypt, continue with protocol but with a random master * secret (Bleichenbacher attack) */ - if ((i < 0) || ((!is_export && i != EVP_CIPHER_key_length(c)) - || (is_export && i != (int)ek))) { - ERR_clear_error(); - if (is_export) - i = ek; - else - i = EVP_CIPHER_key_length(c); - if (RAND_pseudo_bytes(&p[s->s2->tmp.clear], i) <= 0) - return 0; - } -# else - if (i < 0) { - error = 1; - SSLerr(SSL_F_GET_CLIENT_MASTER_KEY, SSL_R_BAD_RSA_DECRYPT); - } - /* incorrect number of key bytes for non export cipher */ - else if ((!is_export && (i != EVP_CIPHER_key_length(c))) - || (is_export && ((i != ek) || (s->s2->tmp.clear + i != - EVP_CIPHER_key_length(c))))) { - error = 1; - SSLerr(SSL_F_GET_CLIENT_MASTER_KEY, SSL_R_WRONG_NUMBER_OF_KEY_BITS); - } - if (error) { - ssl2_return_error(s, SSL2_PE_UNDEFINED_ERROR); - return (-1); + decrypt_good = constant_time_eq_int_8(i, (int)num_encrypted_key_bytes); + for (j = 0; j < num_encrypted_key_bytes; j++) { + p[s->s2->tmp.clear + j] = + constant_time_select_8(decrypt_good, p[s->s2->tmp.clear + j], + rand_premaster_secret[j]); } -# endif - if (is_export) - i = EVP_CIPHER_key_length(c); + s->session->master_key_length = (int)key_length; + memcpy(s->session->master_key, p, key_length); + OPENSSL_cleanse(p, key_length); - if (i > SSL_MAX_MASTER_KEY_LENGTH) { - ssl2_return_error(s, SSL2_PE_UNDEFINED_ERROR); - SSLerr(SSL_F_GET_CLIENT_MASTER_KEY, ERR_R_INTERNAL_ERROR); - return -1; - } - s->session->master_key_length = i; - memcpy(s->session->master_key, p, (unsigned int)i); - return (1); + return 1; } static int get_client_hello(SSL *s) diff --git a/crypto/openssl/ssl/s3_both.c b/crypto/openssl/ssl/s3_both.c index 77374f41ee..107b460f27 100644 --- a/crypto/openssl/ssl/s3_both.c +++ b/crypto/openssl/ssl/s3_both.c @@ -169,7 +169,7 @@ int ssl3_send_finished(SSL *s, int a, int b, const char *sender, int slen) i = s->method->ssl3_enc->final_finish_mac(s, sender, slen, s->s3->tmp.finish_md); - if (i == 0) + if (i <= 0) return 0; s->s3->tmp.finish_md_len = i; memcpy(p, s->s3->tmp.finish_md, i); diff --git a/crypto/openssl/ssl/s3_cbc.c b/crypto/openssl/ssl/s3_cbc.c index 598d27edcc..2fb71f277e 100644 --- a/crypto/openssl/ssl/s3_cbc.c +++ b/crypto/openssl/ssl/s3_cbc.c @@ -149,7 +149,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; } @@ -639,12 +639,22 @@ void ssl3_cbc_digest_record(const EVP_MD_CTX *ctx, if (k > 0) { if (is_sslv3) { + unsigned overhang; + /* * The SSLv3 header is larger than a single block. overhang is * the number of bytes beyond a single block that the header - * consumes: either 7 bytes (SHA1) or 11 bytes (MD5). + * consumes: either 7 bytes (SHA1) or 11 bytes (MD5). There are no + * ciphersuites in SSLv3 that are not SHA1 or MD5 based and + * therefore we can be confident that the header_length will be + * greater than |md_block_size|. However we add a sanity check just + * in case */ - unsigned overhang = header_length - md_block_size; + if (header_length <= md_block_size) { + /* Should never happen */ + return; + } + overhang = header_length - md_block_size; md_transform(md_state.c, header); memcpy(first_block, header + md_block_size, overhang); memcpy(first_block + overhang, data, md_block_size - overhang); diff --git a/crypto/openssl/ssl/s3_clnt.c b/crypto/openssl/ssl/s3_clnt.c index 0e5acecabb..0879a0f8ba 100644 --- a/crypto/openssl/ssl/s3_clnt.c +++ b/crypto/openssl/ssl/s3_clnt.c @@ -168,6 +168,9 @@ #endif static int ca_dn_cmp(const X509_NAME *const *a, const X509_NAME *const *b); +#ifndef OPENSSL_NO_TLSEXT +static int ssl3_check_finished(SSL *s); +#endif #ifndef OPENSSL_NO_SSL3_METHOD static const SSL_METHOD *ssl3_get_client_method(int ver) @@ -235,6 +238,7 @@ int ssl3_connect(SSL *s) if ((s->version & 0xff00) != 0x0300) { SSLerr(SSL_F_SSL3_CONNECT, ERR_R_INTERNAL_ERROR); + s->state = SSL_ST_ERR; ret = -1; goto end; } @@ -245,10 +249,12 @@ int ssl3_connect(SSL *s) if (s->init_buf == NULL) { if ((buf = BUF_MEM_new()) == NULL) { ret = -1; + s->state = SSL_ST_ERR; goto end; } if (!BUF_MEM_grow(buf, SSL3_RT_MAX_PLAIN_LENGTH)) { ret = -1; + s->state = SSL_ST_ERR; goto end; } s->init_buf = buf; @@ -263,6 +269,7 @@ int ssl3_connect(SSL *s) /* setup buffing BIO */ if (!ssl_init_wbio_buffer(s, 0)) { ret = -1; + s->state = SSL_ST_ERR; goto end; } @@ -317,12 +324,24 @@ int ssl3_connect(SSL *s) case SSL3_ST_CR_CERT_A: case SSL3_ST_CR_CERT_B: +#ifndef OPENSSL_NO_TLSEXT + /* Noop (ret = 0) for everything but EAP-FAST. */ + ret = ssl3_check_finished(s); + if (ret < 0) + goto end; + if (ret == 1) { + s->hit = 1; + s->state = SSL3_ST_CR_FINISHED_A; + s->init_num = 0; + break; + } +#endif /* Check if it is anon DH/ECDH, SRP auth */ /* or PSK */ if (! (s->s3->tmp. new_cipher->algorithm_auth & (SSL_aNULL | SSL_aSRP)) -&& !(s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK)) { + && !(s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK)) { ret = ssl3_get_server_certificate(s); if (ret <= 0) goto end; @@ -358,6 +377,7 @@ int ssl3_connect(SSL *s) */ if (!ssl3_check_cert_and_algorithm(s)) { ret = -1; + s->state = SSL_ST_ERR; goto end; } break; @@ -381,6 +401,7 @@ int ssl3_connect(SSL *s) if ((ret = SRP_Calc_A_param(s)) <= 0) { SSLerr(SSL_F_SSL3_CONNECT, SSL_R_SRP_A_CALC); ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR); + s->state = SSL_ST_ERR; goto end; } } @@ -472,6 +493,7 @@ int ssl3_connect(SSL *s) #endif if (!s->method->ssl3_enc->setup_key_block(s)) { ret = -1; + s->state = SSL_ST_ERR; goto end; } @@ -479,6 +501,7 @@ int ssl3_connect(SSL *s) SSL3_CHANGE_CIPHER_CLIENT_WRITE)) { ret = -1; + s->state = SSL_ST_ERR; goto end; } @@ -553,7 +576,8 @@ int ssl3_connect(SSL *s) case SSL3_ST_CR_FINISHED_A: case SSL3_ST_CR_FINISHED_B: - s->s3->flags |= SSL3_FLAGS_CCS_OK; + if (!s->s3->change_cipher_spec) + s->s3->flags |= SSL3_FLAGS_CCS_OK; ret = ssl3_get_finished(s, SSL3_ST_CR_FINISHED_A, SSL3_ST_CR_FINISHED_B); if (ret <= 0) @@ -612,6 +636,7 @@ int ssl3_connect(SSL *s) goto end; /* break; */ + case SSL_ST_ERR: default: SSLerr(SSL_F_SSL3_CONNECT, SSL_R_UNKNOWN_STATE); ret = -1; @@ -658,9 +683,17 @@ int ssl3_client_hello(SSL *s) buf = (unsigned char *)s->init_buf->data; if (s->state == SSL3_ST_CW_CLNT_HELLO_A) { SSL_SESSION *sess = s->session; - if ((sess == NULL) || - (sess->ssl_version != s->version) || - !sess->session_id_length || (sess->not_resumable)) { + if ((sess == NULL) || (sess->ssl_version != s->version) || +#ifdef OPENSSL_NO_TLSEXT + !sess->session_id_length || +#else + /* + * In the case of EAP-FAST, we can have a pre-shared + * "ticket" without a session ID. + */ + (!sess->session_id_length && !sess->tlsext_tick) || +#endif + (sess->not_resumable)) { if (!ssl_get_new_session(s, 0)) goto err; } @@ -798,6 +831,7 @@ int ssl3_client_hello(SSL *s) /* SSL3_ST_CW_CLNT_HELLO_B */ return (ssl3_do_write(s, SSL3_RT_HANDSHAKE)); err: + s->state = SSL_ST_ERR; return (-1); } @@ -867,10 +901,19 @@ int ssl3_get_server_hello(SSL *s) } #ifndef OPENSSL_NO_TLSEXT /* - * check if we want to resume the session based on external pre-shared - * secret + * Check if we can resume the session based on external pre-shared secret. + * EAP-FAST (RFC 4851) supports two types of session resumption. + * Resumption based on server-side state works with session IDs. + * Resumption based on pre-shared Protected Access Credentials (PACs) + * works by overriding the SessionTicket extension at the application + * layer, and does not send a session ID. (We do not know whether EAP-FAST + * servers would honour the session ID.) Therefore, the session ID alone + * is not a reliable indicator of session resumption, so we first check if + * we can resume, and later peek at the next handshake message to see if the + * server wants to resume. */ - if (s->version >= TLS1_VERSION && s->tls_session_secret_cb) { + if (s->version >= TLS1_VERSION && s->tls_session_secret_cb && + s->session->tlsext_tick) { SSL_CIPHER *pref_cipher = NULL; s->session->master_key_length = sizeof(s->session->master_key); if (s->tls_session_secret_cb(s, s->session->master_key, @@ -879,12 +922,15 @@ int ssl3_get_server_hello(SSL *s) s->tls_session_secret_cb_arg)) { s->session->cipher = pref_cipher ? pref_cipher : ssl_get_cipher_by_char(s, p + j); - s->hit = 1; + } else { + SSLerr(SSL_F_SSL3_GET_SERVER_HELLO, ERR_R_INTERNAL_ERROR); + al = SSL_AD_INTERNAL_ERROR; + goto f_err; } } #endif /* OPENSSL_NO_TLSEXT */ - if (!s->hit && j != 0 && j == s->session->session_id_length + if (j != 0 && j == s->session->session_id_length && memcmp(p, s->session->session_id, j) == 0) { if (s->sid_ctx_length != s->session->sid_ctx_length || memcmp(s->session->sid_ctx, s->sid_ctx, s->sid_ctx_length)) { @@ -895,12 +941,13 @@ int ssl3_get_server_hello(SSL *s) goto f_err; } s->hit = 1; - } - /* a miss or crap from the other end */ - if (!s->hit) { + } else { /* - * If we were trying for session-id reuse, make a new SSL_SESSION so - * we don't stuff up other people + * If we were trying for session-id reuse but the server + * didn't echo the ID, make a new SSL_SESSION. + * In the case of EAP-FAST and PAC, we do not send a session ID, + * so the PAC-based session secret is always preserved. It'll be + * overwritten if the server refuses resumption. */ if (s->session->session_id_length > 0) { if (!ssl_get_new_session(s, 0)) { @@ -1045,6 +1092,7 @@ int ssl3_get_server_hello(SSL *s) f_err: ssl3_send_alert(s, SSL3_AL_FATAL, al); err: + s->state = SSL_ST_ERR; return (-1); } @@ -1223,8 +1271,10 @@ int ssl3_get_server_certificate(SSL *s) if (0) { f_err: ssl3_send_alert(s, SSL3_AL_FATAL, al); - } err: + s->state = SSL_ST_ERR; + } + EVP_PKEY_free(pkey); X509_free(x); sk_X509_pop_free(sk, X509_free); @@ -1546,6 +1596,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; } @@ -1894,6 +1951,7 @@ int ssl3_get_key_exchange(SSL *s) EC_KEY_free(ecdh); #endif EVP_MD_CTX_cleanup(&md_ctx); + s->state = SSL_ST_ERR; return (-1); } @@ -2050,7 +2108,10 @@ int ssl3_get_certificate_request(SSL *s) ca_sk = NULL; ret = 1; + goto done; err: + s->state = SSL_ST_ERR; + done: if (ca_sk != NULL) sk_X509_NAME_pop_free(ca_sk, X509_NAME_free); return (ret); @@ -2085,6 +2146,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 */ @@ -2127,6 +2220,7 @@ int ssl3_get_new_session_ticket(SSL *s) f_err: ssl3_send_alert(s, SSL3_AL_FATAL, al); err: + s->state = SSL_ST_ERR; return (-1); } @@ -2187,6 +2281,7 @@ int ssl3_get_cert_status(SSL *s) return 1; f_err: ssl3_send_alert(s, SSL3_AL_FATAL, al); + s->state = SSL_ST_ERR; return (-1); } #endif @@ -2208,6 +2303,7 @@ int ssl3_get_server_done(SSL *s) /* should contain no data */ ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); SSLerr(SSL_F_SSL3_GET_SERVER_DONE, SSL_R_LENGTH_MISMATCH); + s->state = SSL_ST_ERR; return -1; } ret = 1; @@ -2506,8 +2602,6 @@ int ssl3_send_client_key_exchange(SSL *s) n += 2; DH_free(dh_clnt); - - /* perhaps clean things up a bit EAY EAY EAY EAY */ } #endif @@ -2729,7 +2823,10 @@ int ssl3_send_client_key_exchange(SSL *s) EVP_PKEY_encrypt_init(pkey_ctx); /* Generate session key */ - RAND_bytes(premaster_secret, 32); + if (RAND_bytes(premaster_secret, 32) <= 0) { + EVP_PKEY_CTX_free(pkey_ctx); + goto err; + } /* * If we have client certificate, use its secret as peer key */ @@ -2948,6 +3045,7 @@ int ssl3_send_client_key_exchange(SSL *s) EC_KEY_free(clnt_ecdh); EVP_PKEY_free(srvr_pub_pkey); #endif + s->state = SSL_ST_ERR; return (-1); } @@ -3081,6 +3179,7 @@ int ssl3_send_client_verify(SSL *s) err: EVP_MD_CTX_cleanup(&mctx); EVP_PKEY_CTX_free(pctx); + s->state = SSL_ST_ERR; return (-1); } @@ -3149,6 +3248,7 @@ int ssl3_send_client_certificate(SSL *s) if (!l) { SSLerr(SSL_F_SSL3_SEND_CLIENT_CERTIFICATE, ERR_R_INTERNAL_ERROR); ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR); + s->state = SSL_ST_ERR; return 0; } s->init_num = (int)l; @@ -3165,6 +3265,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; @@ -3172,6 +3273,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; @@ -3207,6 +3309,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); @@ -3224,38 +3327,71 @@ 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); - goto f_err; + 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)) { + } + 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)) { + 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 - if (SSL_C_IS_EXPORT(s->s3->tmp.new_cipher) && !has_bits(i, EVP_PKT_EXP)) { + /* 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) && + 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 > + 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; @@ -3263,14 +3399,21 @@ int ssl3_check_cert_and_algorithm(SSL *s) } else #endif #ifndef OPENSSL_NO_DH - if (alg_k & (SSL_kEDH | SSL_kDHr | SSL_kDHd)) { - if (dh == NULL - || DH_size(dh) * 8 > + 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 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 { @@ -3281,12 +3424,62 @@ int ssl3_check_cert_and_algorithm(SSL *s) } return (1); f_err: - ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE); + ssl3_send_alert(s, SSL3_AL_FATAL, al); err: return (0); } -#if !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_NEXTPROTONEG) +#ifndef OPENSSL_NO_TLSEXT +/* + * Normally, we can tell if the server is resuming the session from + * the session ID. EAP-FAST (RFC 4851), however, relies on the next server + * message after the ServerHello to determine if the server is resuming. + * Therefore, we allow EAP-FAST to peek ahead. + * ssl3_check_finished returns 1 if we are resuming from an external + * pre-shared secret, we have a "ticket" and the next server handshake message + * is Finished; and 0 otherwise. It returns -1 upon an error. + */ +static int ssl3_check_finished(SSL *s) +{ + int ok = 0; + + if (s->version < TLS1_VERSION || !s->tls_session_secret_cb || + !s->session->tlsext_tick) + return 0; + + /* Need to permit this temporarily, in case the next message is Finished. */ + s->s3->flags |= SSL3_FLAGS_CCS_OK; + /* + * This function is called when we might get a Certificate message instead, + * so permit appropriate message length. + * We ignore the return value as we're only interested in the message type + * and not its length. + */ + s->method->ssl_get_message(s, + SSL3_ST_CR_CERT_A, + SSL3_ST_CR_CERT_B, + -1, s->max_cert_list, &ok); + s->s3->flags &= ~SSL3_FLAGS_CCS_OK; + + if (!ok) + return -1; + + s->s3->tmp.reuse_message = 1; + + if (s->s3->tmp.message_type == SSL3_MT_FINISHED) + return 1; + + /* If we're not done, then the CCS arrived early and we should bail. */ + if (s->s3->change_cipher_spec) { + SSLerr(SSL_F_SSL3_CHECK_FINISHED, SSL_R_CCS_RECEIVED_EARLY); + ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE); + return -1; + } + + return 0; +} + +# ifndef OPENSSL_NO_NEXTPROTONEG int ssl3_send_next_proto(SSL *s) { unsigned int len, padding_len; @@ -3309,8 +3502,8 @@ int ssl3_send_next_proto(SSL *s) return ssl3_do_write(s, SSL3_RT_HANDSHAKE); } -#endif /* !OPENSSL_NO_TLSEXT && - * !OPENSSL_NO_NEXTPROTONEG */ +#endif /* !OPENSSL_NO_NEXTPROTONEG */ +#endif /* !OPENSSL_NO_TLSEXT */ int ssl_do_client_cert_cb(SSL *s, X509 **px509, EVP_PKEY **ppkey) { diff --git a/crypto/openssl/ssl/s3_pkt.c b/crypto/openssl/ssl/s3_pkt.c index 7c9f20c8f9..25cf929a55 100644 --- a/crypto/openssl/ssl/s3_pkt.c +++ b/crypto/openssl/ssl/s3_pkt.c @@ -347,11 +347,22 @@ static int ssl3_get_record(SSL *s) if (version != s->version) { SSLerr(SSL_F_SSL3_GET_RECORD, SSL_R_WRONG_VERSION_NUMBER); if ((s->version & 0xFF00) == (version & 0xFF00) - && !s->enc_write_ctx && !s->write_hash) + && !s->enc_write_ctx && !s->write_hash) { + if (rr->type == SSL3_RT_ALERT) { + /* + * The record is using an incorrect version number, but + * what we've got appears to be an alert. We haven't + * read the body yet to check whether its a fatal or + * not - but chances are it is. We probably shouldn't + * send a fatal alert back. We'll just end. + */ + goto err; + } /* * Send back error using their minor version number :-) */ s->version = (unsigned short)version; + } al = SSL_AD_PROTOCOL_VERSION; goto f_err; } diff --git a/crypto/openssl/ssl/s3_srvr.c b/crypto/openssl/ssl/s3_srvr.c index b8f91bc945..9aa329260a 100644 --- a/crypto/openssl/ssl/s3_srvr.c +++ b/crypto/openssl/ssl/s3_srvr.c @@ -266,6 +266,7 @@ int ssl3_accept(SSL *s) if ((s->version >> 8) != 3) { SSLerr(SSL_F_SSL3_ACCEPT, ERR_R_INTERNAL_ERROR); + s->state = SSL_ST_ERR; return -1; } s->type = SSL_ST_ACCEPT; @@ -273,11 +274,13 @@ int ssl3_accept(SSL *s) if (s->init_buf == NULL) { if ((buf = BUF_MEM_new()) == NULL) { ret = -1; + s->state = SSL_ST_ERR; goto end; } if (!BUF_MEM_grow(buf, SSL3_RT_MAX_PLAIN_LENGTH)) { BUF_MEM_free(buf); ret = -1; + s->state = SSL_ST_ERR; goto end; } s->init_buf = buf; @@ -285,6 +288,7 @@ int ssl3_accept(SSL *s) if (!ssl3_setup_buffers(s)) { ret = -1; + s->state = SSL_ST_ERR; goto end; } @@ -303,6 +307,7 @@ int ssl3_accept(SSL *s) */ if (!ssl_init_wbio_buffer(s, 1)) { ret = -1; + s->state = SSL_ST_ERR; goto end; } @@ -320,6 +325,7 @@ int ssl3_accept(SSL *s) SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED); ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE); ret = -1; + s->state = SSL_ST_ERR; goto end; } else { /* @@ -379,6 +385,7 @@ int ssl3_accept(SSL *s) SSLerr(SSL_F_SSL3_ACCEPT, SSL_R_CLIENTHELLO_TLSEXT); ret = SSL_TLSEXT_ERR_ALERT_FATAL; ret = -1; + s->state = SSL_ST_ERR; goto end; } } @@ -529,9 +536,12 @@ int ssl3_accept(SSL *s) skip = 1; s->s3->tmp.cert_request = 0; s->state = SSL3_ST_SW_SRVR_DONE_A; - if (s->s3->handshake_buffer) - if (!ssl3_digest_cached_records(s)) + if (s->s3->handshake_buffer) { + if (!ssl3_digest_cached_records(s)) { + s->state = SSL_ST_ERR; return -1; + } + } } else { s->s3->tmp.cert_request = 1; ret = ssl3_send_certificate_request(s); @@ -629,11 +639,14 @@ int ssl3_accept(SSL *s) */ if (!s->s3->handshake_buffer) { SSLerr(SSL_F_SSL3_ACCEPT, ERR_R_INTERNAL_ERROR); + s->state = SSL_ST_ERR; return -1; } s->s3->flags |= TLS1_FLAGS_KEEP_HANDSHAKE; - if (!ssl3_digest_cached_records(s)) + if (!ssl3_digest_cached_records(s)) { + s->state = SSL_ST_ERR; return -1; + } } else { int offset = 0; int dgst_num; @@ -647,9 +660,12 @@ int ssl3_accept(SSL *s) * CertificateVerify should be generalized. But it is next * step */ - if (s->s3->handshake_buffer) - if (!ssl3_digest_cached_records(s)) + if (s->s3->handshake_buffer) { + if (!ssl3_digest_cached_records(s)) { + s->state = SSL_ST_ERR; return -1; + } + } for (dgst_num = 0; dgst_num < SSL_MAX_DIGEST; dgst_num++) if (s->s3->handshake_dgst[dgst_num]) { int dgst_size; @@ -665,6 +681,7 @@ int ssl3_accept(SSL *s) dgst_size = EVP_MD_CTX_size(s->s3->handshake_dgst[dgst_num]); if (dgst_size < 0) { + s->state = SSL_ST_ERR; ret = -1; goto end; } @@ -675,15 +692,6 @@ int ssl3_accept(SSL *s) case SSL3_ST_SR_CERT_VRFY_A: case SSL3_ST_SR_CERT_VRFY_B: - /* - * This *should* be the first time we enable CCS, but be - * extra careful about surrounding code changes. We need - * to set this here because we don't know if we're - * expecting a CertificateVerify or not. - */ - if (!s->s3->change_cipher_spec) - s->s3->flags |= SSL3_FLAGS_CCS_OK; - /* we should decide if we expected this one */ ret = ssl3_get_cert_verify(s); if (ret <= 0) goto end; @@ -703,11 +711,10 @@ int ssl3_accept(SSL *s) case SSL3_ST_SR_NEXT_PROTO_A: case SSL3_ST_SR_NEXT_PROTO_B: /* - * Enable CCS for resumed handshakes with NPN. - * In a full handshake with NPN, we end up here through - * SSL3_ST_SR_CERT_VRFY_B, where SSL3_FLAGS_CCS_OK was - * already set. Receiving a CCS clears the flag, so make - * sure not to re-enable it to ban duplicates. + * Enable CCS for NPN. Receiving a CCS clears the flag, so make + * sure not to re-enable it to ban duplicates. This *should* be the + * first time we have received one - but we check anyway to be + * cautious. * s->s3->change_cipher_spec is set when a CCS is * processed in s3_pkt.c, and remains set until * the client's Finished message is read. @@ -726,10 +733,8 @@ int ssl3_accept(SSL *s) case SSL3_ST_SR_FINISHED_A: case SSL3_ST_SR_FINISHED_B: /* - * Enable CCS for resumed handshakes without NPN. - * In a full handshake, we end up here through - * SSL3_ST_SR_CERT_VRFY_B, where SSL3_FLAGS_CCS_OK was - * already set. Receiving a CCS clears the flag, so make + * Enable CCS for handshakes without NPN. In NPN the CCS flag has + * already been set. Receiving a CCS clears the flag, so make * sure not to re-enable it to ban duplicates. * s->s3->change_cipher_spec is set when a CCS is * processed in s3_pkt.c, and remains set until @@ -779,6 +784,7 @@ int ssl3_accept(SSL *s) s->session->cipher = s->s3->tmp.new_cipher; if (!s->method->ssl3_enc->setup_key_block(s)) { ret = -1; + s->state = SSL_ST_ERR; goto end; } @@ -795,6 +801,7 @@ int ssl3_accept(SSL *s) SSL3_CHANGE_CIPHER_SERVER_WRITE)) { ret = -1; + s->state = SSL_ST_ERR; goto end; } @@ -857,6 +864,7 @@ int ssl3_accept(SSL *s) goto end; /* break; */ + case SSL_ST_ERR: default: SSLerr(SSL_F_SSL3_ACCEPT, SSL_R_UNKNOWN_STATE); ret = -1; @@ -991,6 +999,16 @@ int ssl3_get_client_hello(SSL *s) s->first_packet = 0; d = p = (unsigned char *)s->init_msg; + /* + * 2 bytes for client version, SSL3_RANDOM_SIZE bytes for random, 1 byte + * for session id length + */ + if (n < 2 + SSL3_RANDOM_SIZE + 1) { + al = SSL_AD_DECODE_ERROR; + SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_TOO_SHORT); + goto f_err; + } + /* * use version from inside client hello, not from record header (may * differ: see RFC 2246, Appendix E, second paragraph) @@ -1022,6 +1040,12 @@ int ssl3_get_client_hello(SSL *s) unsigned int session_length, cookie_length; session_length = *(p + SSL3_RANDOM_SIZE); + + if (p + SSL3_RANDOM_SIZE + session_length + 1 >= d + n) { + al = SSL_AD_DECODE_ERROR; + SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_TOO_SHORT); + goto f_err; + } cookie_length = *(p + SSL3_RANDOM_SIZE + session_length + 1); if (cookie_length == 0) @@ -1035,6 +1059,12 @@ int ssl3_get_client_hello(SSL *s) /* get the session-id */ j = *(p++); + if (p + j > d + n) { + al = SSL_AD_DECODE_ERROR; + SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_TOO_SHORT); + goto f_err; + } + s->hit = 0; /* * Versions before 0.9.7 always allow clients to resume sessions in @@ -1079,8 +1109,19 @@ int ssl3_get_client_hello(SSL *s) if (s->version == DTLS1_VERSION || s->version == DTLS1_BAD_VER) { /* cookie stuff */ + if (p + 1 > d + n) { + 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) { + al = SSL_AD_DECODE_ERROR; + SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_TOO_SHORT); + goto f_err; + } + /* * The ClientHello may contain a cookie even if the * HelloVerify message has not been sent--make sure that it @@ -1121,27 +1162,33 @@ int ssl3_get_client_hello(SSL *s) p += cookie_len; } + if (p + 2 > d + n) { + al = SSL_AD_DECODE_ERROR; + SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_TOO_SHORT); + goto f_err; + } n2s(p, i); - if ((i == 0) && (j != 0)) { - /* we need a cipher if we are not resuming a session */ + + if (i == 0) { al = SSL_AD_ILLEGAL_PARAMETER; SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_NO_CIPHERS_SPECIFIED); goto f_err; } - if ((p + i) >= (d + n)) { + + /* i bytes of cipher data + 1 byte for compression length later */ + if ((p + i + 1) > (d + n)) { /* not enough data */ al = SSL_AD_DECODE_ERROR; SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_MISMATCH); goto f_err; } - if ((i > 0) && (ssl_bytes_to_cipher_list(s, p, i, &(ciphers)) - == NULL)) { + if (ssl_bytes_to_cipher_list(s, p, i, &(ciphers)) == NULL) { goto err; } p += i; /* If it is a hit, check that the cipher is in the list */ - if ((s->hit) && (i > 0)) { + if (s->hit) { j = 0; id = s->session->cipher->id; @@ -1377,8 +1424,8 @@ int ssl3_get_client_hello(SSL *s) sk_SSL_CIPHER_free(s->session->ciphers); s->session->ciphers = ciphers; if (ciphers == NULL) { - al = SSL_AD_ILLEGAL_PARAMETER; - SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_NO_CIPHERS_PASSED); + al = SSL_AD_INTERNAL_ERROR; + SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, ERR_R_INTERNAL_ERROR); goto f_err; } ciphers = NULL; @@ -1450,8 +1497,10 @@ int ssl3_get_client_hello(SSL *s) if (0) { f_err: ssl3_send_alert(s, SSL3_AL_FATAL, al); - } err: + s->state = SSL_ST_ERR; + } + if (ciphers != NULL) sk_SSL_CIPHER_free(ciphers); return (ret); @@ -1468,8 +1517,10 @@ int ssl3_send_server_hello(SSL *s) buf = (unsigned char *)s->init_buf->data; #ifdef OPENSSL_NO_TLSEXT p = s->s3->server_random; - if (ssl_fill_hello_random(s, 1, p, SSL3_RANDOM_SIZE) <= 0) + if (ssl_fill_hello_random(s, 1, p, SSL3_RANDOM_SIZE) <= 0) { + s->state = SSL_ST_ERR; return -1; + } #endif /* Do the message type and length last */ d = p = &(buf[4]); @@ -1504,6 +1555,7 @@ int ssl3_send_server_hello(SSL *s) sl = s->session->session_id_length; if (sl > (int)sizeof(s->session->session_id)) { SSLerr(SSL_F_SSL3_SEND_SERVER_HELLO, ERR_R_INTERNAL_ERROR); + s->state = SSL_ST_ERR; return -1; } *(p++) = sl; @@ -1526,6 +1578,7 @@ int ssl3_send_server_hello(SSL *s) #ifndef OPENSSL_NO_TLSEXT if (ssl_prepare_serverhello_tlsext(s) <= 0) { SSLerr(SSL_F_SSL3_SEND_SERVER_HELLO, SSL_R_SERVERHELLO_TLSEXT); + s->state = SSL_ST_ERR; return -1; } if ((p = @@ -1533,6 +1586,7 @@ int ssl3_send_server_hello(SSL *s) buf + SSL3_RT_MAX_PLAIN_LENGTH)) == NULL) { SSLerr(SSL_F_SSL3_SEND_SERVER_HELLO, ERR_R_INTERNAL_ERROR); + s->state = SSL_ST_ERR; return -1; } #endif @@ -2016,6 +2070,7 @@ int ssl3_send_server_key_exchange(SSL *s) BN_CTX_free(bn_ctx); #endif EVP_MD_CTX_cleanup(&md_ctx); + s->state = SSL_ST_ERR; return (-1); } @@ -2113,6 +2168,7 @@ int ssl3_send_certificate_request(SSL *s) /* SSL3_ST_SW_CERT_REQ_B */ return (ssl3_do_write(s, SSL3_RT_HANDSHAKE)); err: + s->state = SSL_ST_ERR; return (-1); } @@ -2367,6 +2423,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); @@ -2470,23 +2527,27 @@ 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)))) { @@ -2503,7 +2564,8 @@ int ssl3_get_client_key_exchange(SSL *s) if (!(s->options & SSL_OP_TLS_ROLLBACK_BUG)) { SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, SSL_AD_DECODE_ERROR); - goto err; + kerr = 1; + goto kclean; } } @@ -2529,6 +2591,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 */ @@ -2847,6 +2914,7 @@ int ssl3_get_client_key_exchange(SSL *s) s-> session->master_key, premaster_secret, 32); + OPENSSL_cleanse(premaster_secret, sizeof(premaster_secret)); /* Check if pubkey from client certificate was used */ if (EVP_PKEY_CTX_ctrl (pkey_ctx, -1, -1, EVP_PKEY_CTRL_PEER_KEY, 2, NULL) > 0) @@ -2879,6 +2947,7 @@ int ssl3_get_client_key_exchange(SSL *s) EC_KEY_free(srvr_ecdh); BN_CTX_free(bn_ctx); #endif + s->state = SSL_ST_ERR; return (-1); } @@ -2894,39 +2963,31 @@ int ssl3_get_cert_verify(SSL *s) EVP_MD_CTX mctx; EVP_MD_CTX_init(&mctx); + /* + * We should only process a CertificateVerify message if we have received + * a Certificate from the client. If so then |s->session->peer| will be non + * NULL. In some instances a CertificateVerify message is not required even + * if the peer has sent a Certificate (e.g. such as in the case of static + * DH). In that case the ClientKeyExchange processing will skip the + * CertificateVerify state so we should not arrive here. + */ + if (s->session->peer == NULL) { + ret = 1; + goto end; + } + n = s->method->ssl_get_message(s, SSL3_ST_SR_CERT_VRFY_A, SSL3_ST_SR_CERT_VRFY_B, - -1, SSL3_RT_MAX_PLAIN_LENGTH, &ok); + SSL3_MT_CERTIFICATE_VERIFY, + SSL3_RT_MAX_PLAIN_LENGTH, &ok); if (!ok) return ((int)n); - if (s->session->peer != NULL) { - peer = s->session->peer; - pkey = X509_get_pubkey(peer); - type = X509_certificate_type(peer, pkey); - } else { - peer = NULL; - pkey = NULL; - } - - if (s->s3->tmp.message_type != SSL3_MT_CERTIFICATE_VERIFY) { - s->s3->tmp.reuse_message = 1; - if (peer != NULL) { - al = SSL_AD_UNEXPECTED_MESSAGE; - SSLerr(SSL_F_SSL3_GET_CERT_VERIFY, SSL_R_MISSING_VERIFY_MESSAGE); - goto f_err; - } - ret = 1; - goto end; - } - - if (peer == NULL) { - SSLerr(SSL_F_SSL3_GET_CERT_VERIFY, SSL_R_NO_CLIENT_CERT_RECEIVED); - al = SSL_AD_UNEXPECTED_MESSAGE; - goto f_err; - } + peer = s->session->peer; + pkey = X509_get_pubkey(peer); + type = X509_certificate_type(peer, pkey); if (!(type & EVP_PKT_SIGN)) { SSLerr(SSL_F_SSL3_GET_CERT_VERIFY, @@ -2935,12 +2996,6 @@ int ssl3_get_cert_verify(SSL *s) goto f_err; } - if (s->s3->change_cipher_spec) { - SSLerr(SSL_F_SSL3_GET_CERT_VERIFY, SSL_R_CCS_RECEIVED_EARLY); - al = SSL_AD_UNEXPECTED_MESSAGE; - goto f_err; - } - /* we now have a signature that we need to verify */ p = (unsigned char *)s->init_msg; /* Check for broken implementations of GOST ciphersuites */ @@ -3093,6 +3148,7 @@ int ssl3_get_cert_verify(SSL *s) if (0) { f_err: ssl3_send_alert(s, SSL3_AL_FATAL, al); + s->state = SSL_ST_ERR; } end: if (s->s3->handshake_buffer) { @@ -3251,8 +3307,10 @@ int ssl3_get_client_certificate(SSL *s) if (0) { f_err: ssl3_send_alert(s, SSL3_AL_FATAL, al); - } err: + s->state = SSL_ST_ERR; + } + if (x != NULL) X509_free(x); if (sk != NULL) @@ -3273,6 +3331,7 @@ int ssl3_send_server_certificate(SSL *s) (s->s3->tmp.new_cipher->algorithm_mkey & SSL_kKRB5)) { SSLerr(SSL_F_SSL3_SEND_SERVER_CERTIFICATE, ERR_R_INTERNAL_ERROR); + s->state = SSL_ST_ERR; return (0); } } @@ -3280,6 +3339,7 @@ int ssl3_send_server_certificate(SSL *s) l = ssl3_output_cert_chain(s, x); if (!l) { SSLerr(SSL_F_SSL3_SEND_SERVER_CERTIFICATE, ERR_R_INTERNAL_ERROR); + s->state = SSL_ST_ERR; return (0); } s->state = SSL3_ST_SW_CERT_B; @@ -3315,11 +3375,15 @@ int ssl3_send_newsession_ticket(SSL *s) * Some length values are 16 bits, so forget it if session is too * long */ - if (slen_full == 0 || slen_full > 0xFF00) + if (slen_full == 0 || slen_full > 0xFF00) { + s->state = SSL_ST_ERR; return -1; + } senc = OPENSSL_malloc(slen_full); - if (!senc) + if (!senc) { + s->state = SSL_ST_ERR; return -1; + } EVP_CIPHER_CTX_init(&ctx); HMAC_CTX_init(&hctx); @@ -3442,6 +3506,7 @@ int ssl3_send_newsession_ticket(SSL *s) OPENSSL_free(senc); EVP_CIPHER_CTX_cleanup(&ctx); HMAC_CTX_cleanup(&hctx); + s->state = SSL_ST_ERR; return -1; } @@ -3455,8 +3520,10 @@ int ssl3_send_cert_status(SSL *s) * 1 (ocsp response type) + 3 (ocsp response length) * + (ocsp response) */ - if (!BUF_MEM_grow(s->init_buf, 8 + s->tlsext_ocsp_resplen)) + if (!BUF_MEM_grow(s->init_buf, 8 + s->tlsext_ocsp_resplen)) { + s->state = SSL_ST_ERR; return -1; + } p = (unsigned char *)s->init_buf->data; @@ -3499,6 +3566,7 @@ int ssl3_get_next_proto(SSL *s) if (!s->s3->next_proto_neg_seen) { SSLerr(SSL_F_SSL3_GET_NEXT_PROTO, SSL_R_GOT_NEXT_PROTO_WITHOUT_EXTENSION); + s->state = SSL_ST_ERR; return -1; } @@ -3518,11 +3586,14 @@ int ssl3_get_next_proto(SSL *s) */ if (!s->s3->change_cipher_spec) { SSLerr(SSL_F_SSL3_GET_NEXT_PROTO, SSL_R_GOT_NEXT_PROTO_BEFORE_A_CCS); + s->state = SSL_ST_ERR; return -1; } - if (n < 2) + if (n < 2) { + s->state = SSL_ST_ERR; return 0; /* The body must be > 1 bytes long */ + } p = (unsigned char *)s->init_msg; @@ -3534,15 +3605,20 @@ int ssl3_get_next_proto(SSL *s) * uint8 padding[padding_len]; */ proto_len = p[0]; - if (proto_len + 2 > s->init_num) + if (proto_len + 2 > s->init_num) { + s->state = SSL_ST_ERR; return 0; + } padding_len = p[proto_len + 1]; - if (proto_len + padding_len + 2 != s->init_num) + if (proto_len + padding_len + 2 != s->init_num) { + s->state = SSL_ST_ERR; return 0; + } s->next_proto_negotiated = OPENSSL_malloc(proto_len); if (!s->next_proto_negotiated) { SSLerr(SSL_F_SSL3_GET_NEXT_PROTO, ERR_R_MALLOC_FAILURE); + s->state = SSL_ST_ERR; return 0; } memcpy(s->next_proto_negotiated, p + 1, proto_len); diff --git a/crypto/openssl/ssl/ssl.h b/crypto/openssl/ssl/ssl.h index b93b67b14b..d2ab0c074c 100644 --- a/crypto/openssl/ssl/ssl.h +++ b/crypto/openssl/ssl/ssl.h @@ -1544,6 +1544,7 @@ extern "C" { # define SSL_ST_BEFORE 0x4000 # define SSL_ST_OK 0x03 # define SSL_ST_RENEGOTIATE (0x04|SSL_ST_INIT) +# define SSL_ST_ERR 0x05 # define SSL_CB_LOOP 0x01 # define SSL_CB_EXIT 0x02 @@ -2303,6 +2304,7 @@ void ERR_load_SSL_strings(void); # define SSL_F_SSL3_CHANGE_CIPHER_STATE 129 # define SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM 130 # define SSL_F_SSL3_CHECK_CLIENT_HELLO 304 +# define SSL_F_SSL3_CHECK_FINISHED 339 # define SSL_F_SSL3_CLIENT_HELLO 131 # define SSL_F_SSL3_CONNECT 132 # define SSL_F_SSL3_CTRL 213 @@ -2408,6 +2410,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 @@ -2522,6 +2525,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 ac7312e31b..88621b7250 100644 --- a/crypto/openssl/ssl/ssl_err.c +++ b/crypto/openssl/ssl/ssl_err.c @@ -160,6 +160,7 @@ static ERR_STRING_DATA SSL_str_functs[] = { {ERR_FUNC(SSL_F_SSL3_DO_CHANGE_CIPHER_SPEC), "SSL3_DO_CHANGE_CIPHER_SPEC"}, {ERR_FUNC(SSL_F_SSL3_ENC), "SSL3_ENC"}, + {ERR_FUNC(SSL_F_SSL3_CHECK_FINISHED), "SSL3_CHECK_FINISHED"}, {ERR_FUNC(SSL_F_SSL3_GENERATE_KEY_BLOCK), "SSL3_GENERATE_KEY_BLOCK"}, {ERR_FUNC(SSL_F_SSL3_GET_CERTIFICATE_REQUEST), "SSL3_GET_CERTIFICATE_REQUEST"}, @@ -298,6 +299,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), @@ -440,6 +442,7 @@ static ERR_STRING_DATA SSL_str_reasons[] = { {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"}, diff --git a/crypto/openssl/ssl/ssl_lib.c b/crypto/openssl/ssl/ssl_lib.c index dead126184..e11746a695 100644 --- a/crypto/openssl/ssl/ssl_lib.c +++ b/crypto/openssl/ssl/ssl_lib.c @@ -1440,9 +1440,13 @@ STACK_OF(SSL_CIPHER) *ssl_bytes_to_cipher_list(SSL *s, unsigned char *p, SSL_R_ERROR_IN_RECEIVED_CIPHER_LIST); return (NULL); } - if ((skp == NULL) || (*skp == NULL)) + if ((skp == NULL) || (*skp == NULL)) { sk = sk_SSL_CIPHER_new_null(); /* change perhaps later */ - else { + if(sk == NULL) { + SSLerr(SSL_F_SSL_BYTES_TO_CIPHER_LIST, ERR_R_MALLOC_FAILURE); + return NULL; + } + } else { sk = *skp; sk_SSL_CIPHER_zero(sk); } diff --git a/crypto/openssl/ssl/ssl_locl.h b/crypto/openssl/ssl/ssl_locl.h index aff3b65d17..a7f3f8dad4 100644 --- a/crypto/openssl/ssl/ssl_locl.h +++ b/crypto/openssl/ssl/ssl_locl.h @@ -865,6 +865,7 @@ 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); int ssl_cipher_ptr_id_cmp(const SSL_CIPHER *const *ap, diff --git a/crypto/openssl/ssl/ssl_sess.c b/crypto/openssl/ssl/ssl_sess.c index fb4e8c5259..1ad9dc7949 100644 --- a/crypto/openssl/ssl/ssl_sess.c +++ b/crypto/openssl/ssl/ssl_sess.c @@ -227,6 +227,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) { @@ -478,9 +602,14 @@ int ssl_get_prev_session(SSL *s, unsigned char *session_id, int len, int r; #endif - if (len > SSL_MAX_SSL_SESSION_ID_LENGTH) + if (len < 0 || len > SSL_MAX_SSL_SESSION_ID_LENGTH) goto err; + if (session_id + len > limit) { + fatal = 1; + goto err; + } + if (len == 0) try_session_cache = 0; diff --git a/crypto/openssl/ssl/ssl_stat.c b/crypto/openssl/ssl/ssl_stat.c index d725d78342..1b9069f978 100644 --- a/crypto/openssl/ssl/ssl_stat.c +++ b/crypto/openssl/ssl/ssl_stat.c @@ -117,6 +117,9 @@ const char *SSL_state_string_long(const SSL *s) case SSL_ST_OK | SSL_ST_ACCEPT: str = "ok/accept SSL initialization"; break; + case SSL_ST_ERR: + str = "error"; + break; #ifndef OPENSSL_NO_SSL2 case SSL2_ST_CLIENT_START_ENCRYPTION: str = "SSLv2 client start encryption"; @@ -496,6 +499,9 @@ const char *SSL_state_string(const SSL *s) case SSL_ST_OK: str = "SSLOK "; break; + case SSL_ST_ERR: + str = "SSLERR"; + break; #ifndef OPENSSL_NO_SSL2 case SSL2_ST_CLIENT_START_ENCRYPTION: str = "2CSENC"; diff --git a/crypto/openssl/ssl/t1_enc.c b/crypto/openssl/ssl/t1_enc.c index 4e2845fa6e..8f45294e55 100644 --- a/crypto/openssl/ssl/t1_enc.c +++ b/crypto/openssl/ssl/t1_enc.c @@ -261,7 +261,7 @@ static int tls1_PRF(long digest_mask, if ((m << TLS1_PRF_DGST_SHIFT) & digest_mask) count++; } - if(!count) { + if (!count) { /* Should never happen */ SSLerr(SSL_F_TLS1_PRF, ERR_R_INTERNAL_ERROR); goto err; @@ -785,7 +785,7 @@ int tls1_enc(SSL *s, int send) bs = EVP_CIPHER_block_size(ds->cipher); if (EVP_CIPHER_flags(ds->cipher) & EVP_CIPH_FLAG_AEAD_CIPHER) { - unsigned char buf[13], *seq; + unsigned char buf[EVP_AEAD_TLS1_AAD_LEN], *seq; seq = send ? s->s3->write_sequence : s->s3->read_sequence; @@ -809,7 +809,10 @@ int tls1_enc(SSL *s, int send) buf[10] = (unsigned char)(s->version); buf[11] = rec->length >> 8; buf[12] = rec->length & 0xff; - pad = EVP_CIPHER_CTX_ctrl(ds, EVP_CTRL_AEAD_TLS1_AAD, 13, buf); + pad = EVP_CIPHER_CTX_ctrl(ds, EVP_CTRL_AEAD_TLS1_AAD, + EVP_AEAD_TLS1_AAD_LEN, buf); + if (pad <= 0) + return -1; if (send) { l += pad; rec->length += pad; diff --git a/crypto/openssl/ssl/t1_lib.c b/crypto/openssl/ssl/t1_lib.c index 243a70f7a6..c2d7d72071 100644 --- a/crypto/openssl/ssl/t1_lib.c +++ b/crypto/openssl/ssl/t1_lib.c @@ -1016,19 +1016,23 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, s->srtp_profile = NULL; - if (data >= (d + n - 2)) - goto ri_check; + 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)) { n2s(data, type); 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 @@ -1064,16 +1068,12 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, int servname_type; int dsize; - if (size < 2) { - *al = SSL_AD_DECODE_ERROR; - return 0; - } + if (size < 2) + goto err; n2s(data, dsize); size -= 2; - if (dsize > size) { - *al = SSL_AD_DECODE_ERROR; - return 0; - } + if (dsize > size) + goto err; sdata = data; while (dsize > 3) { @@ -1081,18 +1081,16 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, n2s(sdata, len); dsize -= 3; - if (len > dsize) { - *al = SSL_AD_DECODE_ERROR; - return 0; - } + if (len > dsize) + goto err; + if (s->servername_done == 0) switch (servname_type) { case TLSEXT_NAMETYPE_host_name: if (!s->hit) { - if (s->session->tlsext_hostname) { - *al = SSL_AD_DECODE_ERROR; - return 0; - } + if (s->session->tlsext_hostname) + goto err; + if (len > TLSEXT_MAXLEN_host_name) { *al = TLS1_AD_UNRECOGNIZED_NAME; return 0; @@ -1126,31 +1124,23 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, dsize -= len; } - if (dsize != 0) { - *al = SSL_AD_DECODE_ERROR; - return 0; - } + if (dsize != 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; - } - if (s->srp_ctx.login != NULL) { - *al = SSL_AD_DECODE_ERROR; - return 0; - } + if (size == 0 || ((len = data[0])) != (size - 1)) + goto err; + if (s->srp_ctx.login != NULL) + 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; - } + if (strlen(s->srp_ctx.login) != len) + goto err; } # endif @@ -1159,10 +1149,8 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, unsigned char *sdata = data; int ecpointformatlist_length = *(sdata++); - if (ecpointformatlist_length != size - 1) { - *al = TLS1_AD_DECODE_ERROR; - return 0; - } + if (ecpointformatlist_length != size - 1) + goto err; if (!s->hit) { if (s->session->tlsext_ecpointformatlist) { OPENSSL_free(s->session->tlsext_ecpointformatlist); @@ -1196,15 +1184,13 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, if (ellipticcurvelist_length != size - 2 || ellipticcurvelist_length < 1 || /* Each NamedCurve is 2 bytes. */ - ellipticcurvelist_length & 1) { - *al = TLS1_AD_DECODE_ERROR; - return 0; - } + ellipticcurvelist_length & 1) + goto err; + if (!s->hit) { - if (s->session->tlsext_ellipticcurvelist) { - *al = TLS1_AD_DECODE_ERROR; - return 0; - } + if (s->session->tlsext_ellipticcurvelist) + goto err; + s->session->tlsext_ellipticcurvelist_length = 0; if ((s->session->tlsext_ellipticcurvelist = OPENSSL_malloc(ellipticcurvelist_length)) == NULL) { @@ -1273,28 +1259,20 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, renegotiate_seen = 1; } else if (type == TLSEXT_TYPE_signature_algorithms) { int dsize; - if (sigalg_seen || size < 2) { - *al = SSL_AD_DECODE_ERROR; - return 0; - } + if (sigalg_seen || size < 2) + goto err; sigalg_seen = 1; n2s(data, dsize); size -= 2; - if (dsize != size || dsize & 1) { - *al = SSL_AD_DECODE_ERROR; - return 0; - } - if (!tls1_process_sigalgs(s, data, dsize)) { - *al = SSL_AD_DECODE_ERROR; - return 0; - } + if (dsize != size || dsize & 1) + goto err; + if (!tls1_process_sigalgs(s, data, dsize)) + goto err; } else if (type == TLSEXT_TYPE_status_request && s->version != DTLS1_VERSION) { - if (size < 5) { - *al = SSL_AD_DECODE_ERROR; - return 0; - } + if (size < 5) + goto err; s->tlsext_status_type = *data++; size--; @@ -1304,35 +1282,26 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, /* Read in responder_id_list */ n2s(data, dsize); size -= 2; - if (dsize > size) { - *al = SSL_AD_DECODE_ERROR; - return 0; - } + if (dsize > size) + goto err; while (dsize > 0) { OCSP_RESPID *id; int idsize; - if (dsize < 4) { - *al = SSL_AD_DECODE_ERROR; - return 0; - } + if (dsize < 4) + goto err; n2s(data, idsize); dsize -= 2 + idsize; size -= 2 + idsize; - if (dsize < 0) { - *al = SSL_AD_DECODE_ERROR; - return 0; - } + if (dsize < 0) + goto err; sdata = data; data += idsize; id = d2i_OCSP_RESPID(NULL, &sdata, idsize); - if (!id) { - *al = SSL_AD_DECODE_ERROR; - return 0; - } + if (!id) + 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 = @@ -1349,16 +1318,12 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, } /* Read in request_extensions */ - if (size < 2) { - *al = SSL_AD_DECODE_ERROR; - return 0; - } + if (size < 2) + goto err; n2s(data, dsize); size -= 2; - if (dsize != size) { - *al = SSL_AD_DECODE_ERROR; - return 0; - } + if (dsize != size) + goto err; sdata = data; if (dsize > 0) { if (s->tlsext_ocsp_exts) { @@ -1368,10 +1333,8 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, s->tlsext_ocsp_exts = d2i_X509_EXTENSIONS(NULL, &sdata, dsize); - if (!s->tlsext_ocsp_exts || (data + dsize != sdata)) { - *al = SSL_AD_DECODE_ERROR; - return 0; - } + if (!s->tlsext_ocsp_exts || (data + dsize != sdata)) + goto err; } } /* @@ -1432,6 +1395,10 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, data += size; } + /* Spurious data on the end */ + if (data != d + n) + goto err; + *p = data; ri_check: @@ -1447,6 +1414,9 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, } return 1; +err: + *al = SSL_AD_DECODE_ERROR; + return 0; } # ifndef OPENSSL_NO_NEXTPROTONEG @@ -2612,7 +2582,10 @@ int tls1_process_heartbeat(SSL *s) memcpy(bp, pl, payload); bp += payload; /* Random padding */ - RAND_pseudo_bytes(bp, padding); + if (RAND_pseudo_bytes(bp, padding) < 0) { + OPENSSL_free(buffer); + return -1; + } r = ssl3_write_bytes(s, TLS1_RT_HEARTBEAT, buffer, 3 + payload + padding); @@ -2647,7 +2620,7 @@ int tls1_process_heartbeat(SSL *s) int tls1_heartbeat(SSL *s) { unsigned char *buf, *p; - int ret; + int ret = -1; unsigned int payload = 18; /* Sequence number + random bytes */ unsigned int padding = 16; /* Use minimum padding */ @@ -2695,10 +2668,16 @@ int tls1_heartbeat(SSL *s) /* Sequence number */ s2n(s->tlsext_hb_seq, p); /* 16 random bytes */ - RAND_pseudo_bytes(p, 16); + if (RAND_pseudo_bytes(p, 16) < 0) { + SSLerr(SSL_F_TLS1_HEARTBEAT, ERR_R_INTERNAL_ERROR); + goto err; + } p += 16; /* Random padding */ - RAND_pseudo_bytes(p, padding); + if (RAND_pseudo_bytes(p, padding) < 0) { + SSLerr(SSL_F_TLS1_HEARTBEAT, ERR_R_INTERNAL_ERROR); + goto err; + } ret = ssl3_write_bytes(s, TLS1_RT_HEARTBEAT, buf, 3 + payload + padding); if (ret >= 0) { @@ -2710,6 +2689,7 @@ int tls1_heartbeat(SSL *s) s->tlsext_hb_pending = 1; } +err: OPENSSL_free(buf); return ret; diff --git a/crypto/openssl/ssl/tls_srp.c b/crypto/openssl/ssl/tls_srp.c index d36cfa0a5c..bb719ba4cf 100644 --- a/crypto/openssl/ssl/tls_srp.c +++ b/crypto/openssl/ssl/tls_srp.c @@ -454,7 +454,8 @@ int SRP_Calc_A_param(SSL *s) { unsigned char rnd[SSL_MAX_MASTER_KEY_LENGTH]; - RAND_bytes(rnd, sizeof(rnd)); + if (RAND_bytes(rnd, sizeof(rnd)) <= 0) + return -1; s->srp_ctx.a = BN_bin2bn(rnd, sizeof(rnd), s->srp_ctx.a); OPENSSL_cleanse(rnd, sizeof(rnd)); -- 2.41.0