aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJung-uk Kim <jkim@FreeBSD.org>2016-09-22 13:05:59 +0000
committerJung-uk Kim <jkim@FreeBSD.org>2016-09-22 13:05:59 +0000
commit2c14c598c3061ac2533f997352aa06a2266f44d9 (patch)
tree470894a14935f308eeac93c6cbf6cf25632e1cb1
parent47b11f985b9e0ff561a67e19674de6fbcf79281d (diff)
downloadsrc-vendor/openssl-1.0.1.tar.gz
src-vendor/openssl-1.0.1.zip
Notes
Notes: svn path=/vendor-crypto/openssl/dist-1.0.1/; revision=306191 svn path=/vendor-crypto/openssl/1.0.1u/; revision=306192; tag=vendor/openssl/1.0.1u
-rw-r--r--CHANGES160
-rw-r--r--CONTRIBUTING93
-rwxr-xr-xConfigure2
-rw-r--r--FREEBSD-upgrade4
-rw-r--r--Makefile2
-rw-r--r--NEWS14
-rw-r--r--README2
-rw-r--r--apps/apps.c2
-rw-r--r--apps/enc.c2
-rw-r--r--apps/passwd.c4
-rw-r--r--apps/s_server.c2
-rw-r--r--apps/x509.c6
-rw-r--r--crypto/asn1/a_bytes.c58
-rw-r--r--crypto/asn1/a_object.c10
-rw-r--r--crypto/asn1/a_set.c9
-rw-r--r--crypto/asn1/asn1_lib.c32
-rw-r--r--crypto/asn1/asn_mime.c2
-rw-r--r--crypto/asn1/d2i_pr.c8
-rw-r--r--crypto/asn1/f_enum.c4
-rw-r--r--crypto/asn1/f_int.c4
-rw-r--r--crypto/asn1/f_string.c4
-rw-r--r--crypto/asn1/p5_pbe.c2
-rw-r--r--crypto/asn1/p5_pbev2.c4
-rw-r--r--crypto/asn1/tasn_enc.c26
-rw-r--r--crypto/asn1/tasn_prn.c2
-rw-r--r--crypto/asn1/x_name.c6
-rw-r--r--crypto/bio/bf_nbio.c4
-rw-r--r--crypto/bn/bn_lib.c2
-rw-r--r--crypto/bn/bn_print.c12
-rw-r--r--crypto/bn/bn_rand.c10
-rw-r--r--crypto/cms/cms_enc.c12
-rw-r--r--crypto/cms/cms_ess.c3
-rw-r--r--crypto/cms/cms_pwri.c4
-rw-r--r--crypto/des/des.c2
-rw-r--r--crypto/des/enc_writ.c2
-rw-r--r--crypto/dsa/dsa_gen.c2
-rw-r--r--crypto/dsa/dsa_ossl.c7
-rw-r--r--crypto/evp/bio_ok.c2
-rw-r--r--crypto/evp/digest.c16
-rw-r--r--crypto/evp/e_seed.c3
-rw-r--r--crypto/md2/md2_dgst.c2
-rw-r--r--crypto/md32_common.h10
-rw-r--r--crypto/mdc2/mdc2dgst.c2
-rwxr-xr-xcrypto/ocsp/ocsp_ext.c2
-rw-r--r--crypto/opensslv.h6
-rw-r--r--crypto/pem/pem.h1
-rw-r--r--crypto/pem/pem_err.c3
-rw-r--r--crypto/pem/pem_lib.c2
-rw-r--r--crypto/pem/pvkfmt.c7
-rw-r--r--crypto/pkcs12/p12_mutl.c2
-rw-r--r--crypto/pkcs12/p12_npas.c113
-rw-r--r--crypto/pkcs12/p12_utl.c4
-rw-r--r--crypto/pkcs12/pkcs12.h2
-rw-r--r--crypto/pkcs7/pk7_doit.c2
-rw-r--r--crypto/rand/rand_unix.c2
-rw-r--r--crypto/srp/srp_lib.c20
-rw-r--r--crypto/srp/srp_vfy.c6
-rw-r--r--crypto/ts/ts_lib.c5
-rw-r--r--crypto/whrlpool/wp_dgst.c3
-rw-r--r--crypto/x509/x509.h6
-rw-r--r--crypto/x509/x509_err.c1
-rw-r--r--crypto/x509/x509_txt.c6
-rw-r--r--crypto/x509/x509_vfy.c146
-rw-r--r--crypto/x509/x509_vfy.h24
-rw-r--r--crypto/x509v3/v3_addr.c6
-rw-r--r--doc/apps/cms.pod3
-rw-r--r--doc/apps/smime.pod3
-rw-r--r--doc/apps/verify.pod5
-rw-r--r--doc/crypto/X509_verify_cert.pod13
-rw-r--r--doc/crypto/d2i_PrivateKey.pod59
-rw-r--r--ssl/d1_both.c43
-rw-r--r--ssl/d1_clnt.c1
-rw-r--r--ssl/d1_lib.c37
-rw-r--r--ssl/d1_pkt.c92
-rw-r--r--ssl/d1_srvr.c8
-rw-r--r--ssl/s23_clnt.c8
-rw-r--r--ssl/s2_clnt.c4
-rw-r--r--ssl/s2_srvr.c12
-rw-r--r--ssl/s3_both.c38
-rw-r--r--ssl/s3_clnt.c30
-rw-r--r--ssl/s3_lib.c34
-rw-r--r--ssl/s3_srvr.c27
-rw-r--r--ssl/ssl.h1
-rw-r--r--ssl/ssl_err.c4
-rw-r--r--ssl/ssl_lib.c4
-rw-r--r--ssl/ssl_locl.h3
-rw-r--r--ssl/ssl_sess.c4
-rw-r--r--ssl/t1_lib.c89
88 files changed, 1042 insertions, 408 deletions
diff --git a/CHANGES b/CHANGES
index 1c7a5edcb421..6f7cda1f6194 100644
--- a/CHANGES
+++ b/CHANGES
@@ -2,6 +2,166 @@
OpenSSL CHANGES
_______________
+ Changes between 1.0.1t and 1.0.1u [22 Sep 2016]
+
+ *) OCSP Status Request extension unbounded memory growth
+
+ A malicious client can send an excessively large OCSP Status Request
+ extension. If that client continually requests renegotiation, sending a
+ large OCSP Status Request extension each time, then there will be unbounded
+ memory growth on the server. This will eventually lead to a Denial Of
+ Service attack through memory exhaustion. Servers with a default
+ configuration are vulnerable even if they do not support OCSP. Builds using
+ the "no-ocsp" build time option are not affected.
+
+ This issue was reported to OpenSSL by Shi Lei (Gear Team, Qihoo 360 Inc.)
+ (CVE-2016-6304)
+ [Matt Caswell]
+
+ *) In order to mitigate the SWEET32 attack, the DES ciphers were moved from
+ HIGH to MEDIUM.
+
+ This issue was reported to OpenSSL Karthikeyan Bhargavan and Gaetan
+ Leurent (INRIA)
+ (CVE-2016-2183)
+ [Rich Salz]
+
+ *) OOB write in MDC2_Update()
+
+ An overflow can occur in MDC2_Update() either if called directly or
+ through the EVP_DigestUpdate() function using MDC2. If an attacker
+ is able to supply very large amounts of input data after a previous
+ call to EVP_EncryptUpdate() with a partial block then a length check
+ can overflow resulting in a heap corruption.
+
+ The amount of data needed is comparable to SIZE_MAX which is impractical
+ on most platforms.
+
+ This issue was reported to OpenSSL by Shi Lei (Gear Team, Qihoo 360 Inc.)
+ (CVE-2016-6303)
+ [Stephen Henson]
+
+ *) Malformed SHA512 ticket DoS
+
+ If a server uses SHA512 for TLS session ticket HMAC it is vulnerable to a
+ DoS attack where a malformed ticket will result in an OOB read which will
+ ultimately crash.
+
+ The use of SHA512 in TLS session tickets is comparatively rare as it requires
+ a custom server callback and ticket lookup mechanism.
+
+ This issue was reported to OpenSSL by Shi Lei (Gear Team, Qihoo 360 Inc.)
+ (CVE-2016-6302)
+ [Stephen Henson]
+
+ *) OOB write in BN_bn2dec()
+
+ The function BN_bn2dec() does not check the return value of BN_div_word().
+ This can cause an OOB write if an application uses this function with an
+ overly large BIGNUM. This could be a problem if an overly large certificate
+ or CRL is printed out from an untrusted source. TLS is not affected because
+ record limits will reject an oversized certificate before it is parsed.
+
+ This issue was reported to OpenSSL by Shi Lei (Gear Team, Qihoo 360 Inc.)
+ (CVE-2016-2182)
+ [Stephen Henson]
+
+ *) OOB read in TS_OBJ_print_bio()
+
+ The function TS_OBJ_print_bio() misuses OBJ_obj2txt(): the return value is
+ the total length the OID text representation would use and not the amount
+ of data written. This will result in OOB reads when large OIDs are
+ presented.
+
+ This issue was reported to OpenSSL by Shi Lei (Gear Team, Qihoo 360 Inc.)
+ (CVE-2016-2180)
+ [Stephen Henson]
+
+ *) Pointer arithmetic undefined behaviour
+
+ Avoid some undefined pointer arithmetic
+
+ A common idiom in the codebase is to check limits in the following manner:
+ "p + len > limit"
+
+ Where "p" points to some malloc'd data of SIZE bytes and
+ limit == p + SIZE
+
+ "len" here could be from some externally supplied data (e.g. from a TLS
+ message).
+
+ The rules of C pointer arithmetic are such that "p + len" is only well
+ defined where len <= SIZE. Therefore the above idiom is actually
+ undefined behaviour.
+
+ For example this could cause problems if some malloc implementation
+ provides an address for "p" such that "p + len" actually overflows for
+ values of len that are too big and therefore p + len < limit.
+
+ This issue was reported to OpenSSL by Guido Vranken
+ (CVE-2016-2177)
+ [Matt Caswell]
+
+ *) Constant time flag not preserved in DSA signing
+
+ Operations in the DSA signing algorithm should run in constant time in
+ order to avoid side channel attacks. A flaw in the OpenSSL DSA
+ implementation means that a non-constant time codepath is followed for
+ certain operations. This has been demonstrated through a cache-timing
+ attack to be sufficient for an attacker to recover the private DSA key.
+
+ This issue was reported by César Pereida (Aalto University), Billy Brumley
+ (Tampere University of Technology), and Yuval Yarom (The University of
+ Adelaide and NICTA).
+ (CVE-2016-2178)
+ [César Pereida]
+
+ *) DTLS buffered message DoS
+
+ In a DTLS connection where handshake messages are delivered out-of-order
+ those messages that OpenSSL is not yet ready to process will be buffered
+ for later use. Under certain circumstances, a flaw in the logic means that
+ those messages do not get removed from the buffer even though the handshake
+ has been completed. An attacker could force up to approx. 15 messages to
+ remain in the buffer when they are no longer required. These messages will
+ be cleared when the DTLS connection is closed. The default maximum size for
+ a message is 100k. Therefore the attacker could force an additional 1500k
+ to be consumed per connection. By opening many simulataneous connections an
+ attacker could cause a DoS attack through memory exhaustion.
+
+ This issue was reported to OpenSSL by Quan Luo.
+ (CVE-2016-2179)
+ [Matt Caswell]
+
+ *) DTLS replay protection DoS
+
+ A flaw in the DTLS replay attack protection mechanism means that records
+ that arrive for future epochs update the replay protection "window" before
+ the MAC for the record has been validated. This could be exploited by an
+ attacker by sending a record for the next epoch (which does not have to
+ decrypt or have a valid MAC), with a very large sequence number. This means
+ that all subsequent legitimate packets are dropped causing a denial of
+ service for a specific DTLS connection.
+
+ This issue was reported to OpenSSL by the OCAP audit team.
+ (CVE-2016-2181)
+ [Matt Caswell]
+
+ *) Certificate message OOB reads
+
+ In OpenSSL 1.0.2 and earlier some missing message length checks can result
+ in OOB reads of up to 2 bytes beyond an allocated buffer. There is a
+ theoretical DoS risk but this has not been observed in practice on common
+ platforms.
+
+ The messages affected are client certificate, client certificate request
+ and server certificate. As a result the attack can only be performed
+ against a client or a server which enables client authentication.
+
+ This issue was reported to OpenSSL by Shi Lei (Gear Team, Qihoo 360 Inc.)
+ (CVE-2016-6306)
+ [Stephen Henson]
+
Changes between 1.0.1s and 1.0.1t [3 May 2016]
*) Prevent padding oracle in AES-NI CBC MAC check
diff --git a/CONTRIBUTING b/CONTRIBUTING
index 9d63d8abb672..07115e5a7588 100644
--- a/CONTRIBUTING
+++ b/CONTRIBUTING
@@ -1,38 +1,75 @@
-HOW TO CONTRIBUTE TO OpenSSL
-----------------------------
+HOW TO CONTRIBUTE TO PATCHES OpenSSL
+------------------------------------
-Development is coordinated on the openssl-dev mailing list (see
-http://www.openssl.org for information on subscribing). If you
-would like to submit a patch, send it to rt@openssl.org with
-the string "[PATCH]" in the subject. Please be sure to include a
-textual explanation of what your patch does.
-
-You can also make GitHub pull requests. If you do this, please also send
-mail to rt@openssl.org with a brief description and a link to the PR so
-that we can more easily keep track of it.
+(Please visit https://www.openssl.org/community/getting-started.html for
+other ideas about how to contribute.)
+Development is coordinated on the openssl-dev mailing list (see the
+above link or https://mta.openssl.org for information on subscribing).
If you are unsure as to whether a feature will be useful for the general
-OpenSSL community please discuss it on the openssl-dev mailing list first.
-Someone may be already working on the same thing or there may be a good
-reason as to why that feature isn't implemented.
+OpenSSL community you might want to discuss it on the openssl-dev mailing
+list first. Someone may be already working on the same thing or there
+may be a good reason as to why that feature isn't implemented.
-Patches should be as up to date as possible, preferably relative to the
-current Git or the last snapshot. They should follow our coding style
-(see https://www.openssl.org/policies/codingstyle.html) and compile without
-warnings using the --strict-warnings flag. OpenSSL compiles on many varied
-platforms: try to ensure you only use portable features.
+The best way to submit a patch is to make a pull request on GitHub.
+(It is not necessary to send mail to rt@openssl.org to open a ticket!)
+If you think the patch could use feedback from the community, please
+start a thread on openssl-dev.
-Our preferred format for patch files is "git format-patch" output. For example
-to provide a patch file containing the last commit in your local git repository
-use the following command:
+You can also submit patches by sending it as mail to rt@openssl.org.
+Please include the word "PATCH" and an explanation of what the patch
+does in the subject line. If you do this, our preferred format is "git
+format-patch" output. For example to provide a patch file containing the
+last commit in your local git repository use the following command:
-# git format-patch --stdout HEAD^ >mydiffs.patch
+ % git format-patch --stdout HEAD^ >mydiffs.patch
Another method of creating an acceptable patch file without using git is as
follows:
-# cd openssl-work
-# [your changes]
-# ./Configure dist; make clean
-# cd ..
-# diff -ur openssl-orig openssl-work > mydiffs.patch
+ % cd openssl-work
+ ...make your changes...
+ % ./Configure dist; make clean
+ % cd ..
+ % diff -ur openssl-orig openssl-work >mydiffs.patch
+
+Note that pull requests are generally easier for the team, and community, to
+work with. Pull requests benefit from all of the standard GitHub features,
+including code review tools, simpler integration, and CI build support.
+
+No matter how a patch is submitted, the following items will help make
+the acceptance and review process faster:
+
+ 1. Anything other than trivial contributions will require a contributor
+ licensing agreement, giving us permission to use your code. See
+ https://www.openssl.org/policies/cla.html for details.
+
+ 2. All source files should start with the following text (with
+ appropriate comment characters at the start of each line and the
+ year(s) updated):
+
+ Copyright 20xx-20yy The OpenSSL Project Authors. All Rights Reserved.
+
+ Licensed under the OpenSSL license (the "License"). You may not use
+ this file except in compliance with the License. You can obtain a copy
+ in the file LICENSE in the source distribution or at
+ https://www.openssl.org/source/license.html
+
+ 3. Patches should be as current as possible. When using GitHub, please
+ expect to have to rebase and update often. Note that we do not accept merge
+ commits. You will be asked to remove them before a patch is considered
+ acceptable.
+
+ 4. Patches should follow our coding style (see
+ https://www.openssl.org/policies/codingstyle.html) and compile without
+ warnings. Where gcc or clang is availble you should use the
+ --strict-warnings Configure option. OpenSSL compiles on many varied
+ platforms: try to ensure you only use portable features.
+
+ 5. When at all possible, patches should include tests. These can either be
+ added to an existing test, or completely new. Please see test/README
+ for information on the test framework.
+
+ 6. New features or changed functionality must include documentation. Please
+ look at the "pod" files in doc/apps, doc/crypto and doc/ssl for examples of
+ our style.
diff --git a/Configure b/Configure
index 93c4cc15fb6e..6a50cb162c49 100755
--- a/Configure
+++ b/Configure
@@ -741,7 +741,7 @@ my @experimental = ();
# This is what $depflags will look like with the above defaults
# (we need this to see if we should advise the user to run "make depend"):
-my $default_depflags = " -DOPENSSL_NO_EC_NISTP_64_GCC_128 -DOPENSSL_NO_GMP -DOPENSSL_NO_JPAKE -DOPENSSL_NO_MD2 -DOPENSSL_NO_RC5 -DOPENSSL_NO_RFC3779 -DOPENSSL_NO_SCTP -DOPENSSL_NO_STORE -DOPENSSL_NO_UNIT_TEST";
+my $default_depflags = " -DOPENSSL_NO_EC_NISTP_64_GCC_128 -DOPENSSL_NO_GMP -DOPENSSL_NO_JPAKE -DOPENSSL_NO_MD2 -DOPENSSL_NO_RC5 -DOPENSSL_NO_RFC3779 -DOPENSSL_NO_SCTP -DOPENSSL_NO_SSL2 -DOPENSSL_NO_STORE -DOPENSSL_NO_UNIT_TEST -DOPENSSL_NO_WEAK_SSL_CIPHERS";
# Explicit "no-..." options will be collected in %disabled along with the defaults.
# To remove something from %disabled, use "enable-foo" (unless it's experimental).
diff --git a/FREEBSD-upgrade b/FREEBSD-upgrade
index bcdf6babd349..dda115393b14 100644
--- a/FREEBSD-upgrade
+++ b/FREEBSD-upgrade
@@ -11,8 +11,8 @@ First, read http://wiki.freebsd.org/SubversionPrimer/VendorImports
# Xlist
setenv XLIST /FreeBSD/work/openssl/svn-FREEBSD-files/FREEBSD-Xlist
setenv FSVN "svn+ssh://svn.freebsd.org/base"
-setenv OSSLVER 1.0.1t
-# OSSLTAG format: v1_0_1t
+setenv OSSLVER 1.0.1u
+# OSSLTAG format: v1_0_1u
###setenv OSSLTAG v`echo ${OSSLVER} | tr . _`
diff --git a/Makefile b/Makefile
index f2c621d58d78..f3f6c6402a64 100644
--- a/Makefile
+++ b/Makefile
@@ -4,7 +4,7 @@
## Makefile for OpenSSL
##
-VERSION=1.0.1t
+VERSION=1.0.1u
MAJOR=1
MINOR=0.1
SHLIB_VERSION_NUMBER=1.0.0
diff --git a/NEWS b/NEWS
index 0fb2cc391a35..686ae2490a55 100644
--- a/NEWS
+++ b/NEWS
@@ -5,6 +5,20 @@
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.1t and OpenSSL 1.0.1u [22 Sep 2016]
+
+ o OCSP Status Request extension unbounded memory growth (CVE-2016-6304)
+ o SWEET32 Mitigation (CVE-2016-2183)
+ o OOB write in MDC2_Update() (CVE-2016-6303)
+ o Malformed SHA512 ticket DoS (CVE-2016-6302)
+ o OOB write in BN_bn2dec() (CVE-2016-2182)
+ o OOB read in TS_OBJ_print_bio() (CVE-2016-2180)
+ o Pointer arithmetic undefined behaviour (CVE-2016-2177)
+ o Constant time flag not preserved in DSA signing (CVE-2016-2178)
+ o DTLS buffered message DoS (CVE-2016-2179)
+ o DTLS replay protection DoS (CVE-2016-2181)
+ o Certificate message OOB reads (CVE-2016-6306)
+
Major changes between OpenSSL 1.0.1s and OpenSSL 1.0.1t [3 May 2016]
o Prevent padding oracle in AES-NI CBC MAC check (CVE-2016-2107)
diff --git a/README b/README
index 9395f2ba858c..96fecaa6f5ef 100644
--- a/README
+++ b/README
@@ -1,5 +1,5 @@
- OpenSSL 1.0.1t 3 May 2016
+ OpenSSL 1.0.1u 22 Sep 2016
Copyright (c) 1998-2015 The OpenSSL Project
Copyright (c) 1995-1998 Eric A. Young, Tim J. Hudson
diff --git a/apps/apps.c b/apps/apps.c
index 8ab4833668bc..ca9179e9a56a 100644
--- a/apps/apps.c
+++ b/apps/apps.c
@@ -2241,6 +2241,8 @@ int args_verify(char ***pargs, int *pargc,
flags |= X509_V_FLAG_CHECK_SS_SIGNATURE;
else if (!strcmp(arg, "-no_alt_chains"))
flags |= X509_V_FLAG_NO_ALT_CHAINS;
+ else if (!strcmp(arg, "-allow_proxy_certs"))
+ flags |= X509_V_FLAG_ALLOW_PROXY_CERTS;
else
return 0;
diff --git a/apps/enc.c b/apps/enc.c
index 7b7c70b132d7..8e2ef27aca34 100644
--- a/apps/enc.c
+++ b/apps/enc.c
@@ -509,7 +509,7 @@ int MAIN(int argc, char **argv)
BIO_printf(bio_err, "invalid hex salt value\n");
goto end;
}
- } else if (RAND_pseudo_bytes(salt, sizeof salt) < 0)
+ } else if (RAND_bytes(salt, sizeof salt) <= 0)
goto end;
/*
* If -P option then don't bother writing
diff --git a/apps/passwd.c b/apps/passwd.c
index 5ff53b5743c6..798a6d593616 100644
--- a/apps/passwd.c
+++ b/apps/passwd.c
@@ -416,7 +416,7 @@ static int do_passwd(int passed_salt, char **salt_p, char **salt_malloc_p,
if (*salt_malloc_p == NULL)
goto err;
}
- if (RAND_pseudo_bytes((unsigned char *)*salt_p, 2) < 0)
+ if (RAND_bytes((unsigned char *)*salt_p, 2) <= 0)
goto err;
(*salt_p)[0] = cov_2char[(*salt_p)[0] & 0x3f]; /* 6 bits */
(*salt_p)[1] = cov_2char[(*salt_p)[1] & 0x3f]; /* 6 bits */
@@ -437,7 +437,7 @@ static int do_passwd(int passed_salt, char **salt_p, char **salt_malloc_p,
if (*salt_malloc_p == NULL)
goto err;
}
- if (RAND_pseudo_bytes((unsigned char *)*salt_p, 8) < 0)
+ if (RAND_bytes((unsigned char *)*salt_p, 8) <= 0)
goto err;
for (i = 0; i < 8; i++)
diff --git a/apps/s_server.c b/apps/s_server.c
index a53cadd66052..40782bb027fd 100644
--- a/apps/s_server.c
+++ b/apps/s_server.c
@@ -2968,7 +2968,7 @@ static int generate_session_id(const SSL *ssl, unsigned char *id,
{
unsigned int count = 0;
do {
- if (RAND_pseudo_bytes(id, *id_len) < 0)
+ if (RAND_bytes(id, *id_len) <= 0)
return 0;
/*
* Prefix the session_id with the required prefix. NB: If our prefix
diff --git a/apps/x509.c b/apps/x509.c
index e5fe61087a4d..0199c55268e4 100644
--- a/apps/x509.c
+++ b/apps/x509.c
@@ -1053,6 +1053,10 @@ static int x509_certify(X509_STORE *ctx, char *CAfile, const EVP_MD *digest,
EVP_PKEY *upkey;
upkey = X509_get_pubkey(xca);
+ if (upkey == NULL) {
+ BIO_printf(bio_err, "Error obtaining CA X509 public key\n");
+ goto end;
+ }
EVP_PKEY_copy_parameters(upkey, pkey);
EVP_PKEY_free(upkey);
@@ -1161,6 +1165,8 @@ static int sign(X509 *x, EVP_PKEY *pkey, int days, int clrext,
EVP_PKEY *pktmp;
pktmp = X509_get_pubkey(x);
+ if (pktmp == NULL)
+ goto err;
EVP_PKEY_copy_parameters(pktmp, pkey);
EVP_PKEY_save_parameters(pktmp, 1);
EVP_PKEY_free(pktmp);
diff --git a/crypto/asn1/a_bytes.c b/crypto/asn1/a_bytes.c
index 385b53986a29..65e5394664a4 100644
--- a/crypto/asn1/a_bytes.c
+++ b/crypto/asn1/a_bytes.c
@@ -60,7 +60,12 @@
#include "cryptlib.h"
#include <openssl/asn1.h>
-static int asn1_collate_primitive(ASN1_STRING *a, ASN1_const_CTX *c);
+static int asn1_collate_primitive(ASN1_STRING *a, ASN1_const_CTX *c,
+ int depth);
+static ASN1_STRING *int_d2i_ASN1_bytes(ASN1_STRING **a,
+ const unsigned char **pp, long length,
+ int Ptag, int Pclass, int depth,
+ int *perr);
/*
* type is a 'bitmap' of acceptable string types.
*/
@@ -99,7 +104,7 @@ ASN1_STRING *d2i_ASN1_type_bytes(ASN1_STRING **a, const unsigned char **pp,
ret = (*a);
if (len != 0) {
- s = (unsigned char *)OPENSSL_malloc((int)len + 1);
+ s = OPENSSL_malloc((int)len + 1);
if (s == NULL) {
i = ERR_R_MALLOC_FAILURE;
goto err;
@@ -154,15 +159,38 @@ int i2d_ASN1_bytes(ASN1_STRING *a, unsigned char **pp, int tag, int xclass)
return (r);
}
+/*
+ * Maximum recursion depth of d2i_ASN1_bytes(): much more than should be
+ * encountered in pratice.
+ */
+
+#define ASN1_BYTES_MAXDEPTH 20
+
ASN1_STRING *d2i_ASN1_bytes(ASN1_STRING **a, const unsigned char **pp,
long length, int Ptag, int Pclass)
{
+ int err = 0;
+ ASN1_STRING *s = int_d2i_ASN1_bytes(a, pp, length, Ptag, Pclass, 0, &err);
+ if (err != 0)
+ ASN1err(ASN1_F_D2I_ASN1_BYTES, err);
+ return s;
+}
+
+static ASN1_STRING *int_d2i_ASN1_bytes(ASN1_STRING **a,
+ const unsigned char **pp, long length,
+ int Ptag, int Pclass,
+ int depth, int *perr)
+{
ASN1_STRING *ret = NULL;
const unsigned char *p;
unsigned char *s;
long len;
int inf, tag, xclass;
- int i = 0;
+
+ if (depth > ASN1_BYTES_MAXDEPTH) {
+ *perr = ASN1_R_NESTED_ASN1_STRING;
+ return NULL;
+ }
if ((a == NULL) || ((*a) == NULL)) {
if ((ret = ASN1_STRING_new()) == NULL)
@@ -173,18 +201,19 @@ ASN1_STRING *d2i_ASN1_bytes(ASN1_STRING **a, const unsigned char **pp,
p = *pp;
inf = ASN1_get_object(&p, &len, &tag, &xclass, length);
if (inf & 0x80) {
- i = ASN1_R_BAD_OBJECT_HEADER;
+ *perr = ASN1_R_BAD_OBJECT_HEADER;
goto err;
}
if (tag != Ptag) {
- i = ASN1_R_WRONG_TAG;
+ *perr = ASN1_R_WRONG_TAG;
goto err;
}
if (inf & V_ASN1_CONSTRUCTED) {
ASN1_const_CTX c;
+ c.error = 0;
c.pp = pp;
c.p = p;
c.inf = inf;
@@ -192,17 +221,18 @@ ASN1_STRING *d2i_ASN1_bytes(ASN1_STRING **a, const unsigned char **pp,
c.tag = Ptag;
c.xclass = Pclass;
c.max = (length == 0) ? 0 : (p + length);
- if (!asn1_collate_primitive(ret, &c))
+ if (!asn1_collate_primitive(ret, &c, depth)) {
+ *perr = c.error;
goto err;
- else {
+ } else {
p = c.p;
}
} else {
if (len != 0) {
if ((ret->length < len) || (ret->data == NULL)) {
- s = (unsigned char *)OPENSSL_malloc((int)len + 1);
+ s = OPENSSL_malloc((int)len + 1);
if (s == NULL) {
- i = ERR_R_MALLOC_FAILURE;
+ *perr = ERR_R_MALLOC_FAILURE;
goto err;
}
if (ret->data != NULL)
@@ -230,7 +260,6 @@ ASN1_STRING *d2i_ASN1_bytes(ASN1_STRING **a, const unsigned char **pp,
err:
if ((ret != NULL) && ((a == NULL) || (*a != ret)))
ASN1_STRING_free(ret);
- ASN1err(ASN1_F_D2I_ASN1_BYTES, i);
return (NULL);
}
@@ -242,7 +271,8 @@ ASN1_STRING *d2i_ASN1_bytes(ASN1_STRING **a, const unsigned char **pp,
* There have been a few bug fixes for this function from Paul Keogh
* <paul.keogh@sse.ie>, many thanks to him
*/
-static int asn1_collate_primitive(ASN1_STRING *a, ASN1_const_CTX *c)
+static int asn1_collate_primitive(ASN1_STRING *a, ASN1_const_CTX *c,
+ int depth)
{
ASN1_STRING *os = NULL;
BUF_MEM b;
@@ -270,9 +300,8 @@ static int asn1_collate_primitive(ASN1_STRING *a, ASN1_const_CTX *c)
}
c->q = c->p;
- if (d2i_ASN1_bytes(&os, &c->p, c->max - c->p, c->tag, c->xclass)
- == NULL) {
- c->error = ERR_R_ASN1_LIB;
+ if (int_d2i_ASN1_bytes(&os, &c->p, c->max - c->p, c->tag, c->xclass,
+ depth + 1, &c->error) == NULL) {
goto err;
}
@@ -297,7 +326,6 @@ static int asn1_collate_primitive(ASN1_STRING *a, ASN1_const_CTX *c)
ASN1_STRING_free(os);
return (1);
err:
- ASN1err(ASN1_F_ASN1_COLLATE_PRIMITIVE, c->error);
if (os != NULL)
ASN1_STRING_free(os);
if (b.data != NULL)
diff --git a/crypto/asn1/a_object.c b/crypto/asn1/a_object.c
index 27f9c1691462..229a40ffa344 100644
--- a/crypto/asn1/a_object.c
+++ b/crypto/asn1/a_object.c
@@ -73,7 +73,7 @@ int i2d_ASN1_OBJECT(ASN1_OBJECT *a, unsigned char **pp)
return (0);
objsize = ASN1_object_size(0, a->length, V_ASN1_OBJECT);
- if (pp == NULL)
+ if (pp == NULL || objsize == -1)
return objsize;
p = *pp;
@@ -174,8 +174,12 @@ int a2d_ASN1_OBJECT(unsigned char *out, int olen, const char *buf, int num)
if (!tmp)
goto err;
}
- while (blsize--)
- tmp[i++] = (unsigned char)BN_div_word(bl, 0x80L);
+ while (blsize--) {
+ BN_ULONG t = BN_div_word(bl, 0x80L);
+ if (t == (BN_ULONG)-1)
+ goto err;
+ tmp[i++] = (unsigned char)t;
+ }
} else {
for (;;) {
diff --git a/crypto/asn1/a_set.c b/crypto/asn1/a_set.c
index bf3f97188926..5fb58655757d 100644
--- a/crypto/asn1/a_set.c
+++ b/crypto/asn1/a_set.c
@@ -57,6 +57,7 @@
*/
#include <stdio.h>
+#include <limits.h>
#include "cryptlib.h"
#include <openssl/asn1_mac.h>
@@ -98,10 +99,14 @@ int i2d_ASN1_SET(STACK_OF(OPENSSL_BLOCK) *a, unsigned char **pp,
if (a == NULL)
return (0);
- for (i = sk_OPENSSL_BLOCK_num(a) - 1; i >= 0; i--)
+ for (i = sk_OPENSSL_BLOCK_num(a) - 1; i >= 0; i--) {
+ int tmplen = i2d(sk_OPENSSL_BLOCK_value(a, i), NULL);
+ if (tmplen > INT_MAX - ret)
+ return -1;
ret += i2d(sk_OPENSSL_BLOCK_value(a, i), NULL);
+ }
r = ASN1_object_size(1, ret, ex_tag);
- if (pp == NULL)
+ if (pp == NULL || r == -1)
return (r);
p = *pp;
diff --git a/crypto/asn1/asn1_lib.c b/crypto/asn1/asn1_lib.c
index 874b1af8b09a..e63e82a8b476 100644
--- a/crypto/asn1/asn1_lib.c
+++ b/crypto/asn1/asn1_lib.c
@@ -256,26 +256,30 @@ static void asn1_put_length(unsigned char **pp, int length)
int ASN1_object_size(int constructed, int length, int tag)
{
- int ret;
-
- ret = length;
- ret++;
+ int ret = 1;
+ if (length < 0)
+ return -1;
if (tag >= 31) {
while (tag > 0) {
tag >>= 7;
ret++;
}
}
- if (constructed == 2)
- return ret + 3;
- ret++;
- if (length > 127) {
- while (length > 0) {
- length >>= 8;
- ret++;
+ if (constructed == 2) {
+ ret += 3;
+ } else {
+ ret++;
+ if (length > 127) {
+ int tmplen = length;
+ while (tmplen > 0) {
+ tmplen >>= 8;
+ ret++;
+ }
}
}
- return (ret);
+ if (ret >= INT_MAX - length)
+ return -1;
+ return ret + length;
}
static int _asn1_Finish(ASN1_const_CTX *c)
@@ -324,7 +328,7 @@ int asn1_GetSequence(ASN1_const_CTX *c, long *length)
return (0);
}
if (c->inf == (1 | V_ASN1_CONSTRUCTED))
- c->slen = *length + *(c->pp) - c->p;
+ c->slen = *length;
c->eos = 0;
return (1);
}
@@ -366,7 +370,7 @@ int ASN1_STRING_set(ASN1_STRING *str, const void *_data, int len)
else
len = strlen(data);
}
- if ((str->length < len) || (str->data == NULL)) {
+ if ((str->length <= len) || (str->data == NULL)) {
c = str->data;
if (c == NULL)
str->data = OPENSSL_malloc(len + 1);
diff --git a/crypto/asn1/asn_mime.c b/crypto/asn1/asn_mime.c
index 96110c540f3d..9fd5bef0fc97 100644
--- a/crypto/asn1/asn_mime.c
+++ b/crypto/asn1/asn_mime.c
@@ -289,7 +289,7 @@ 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 */
- if (RAND_pseudo_bytes((unsigned char *)bound, 32) < 0)
+ if (RAND_bytes((unsigned char *)bound, 32) <= 0)
return 0;
for (i = 0; i < 32; i++) {
c = bound[i] & 0xf;
diff --git a/crypto/asn1/d2i_pr.c b/crypto/asn1/d2i_pr.c
index d21829af192f..86dcf5fba9d7 100644
--- a/crypto/asn1/d2i_pr.c
+++ b/crypto/asn1/d2i_pr.c
@@ -97,15 +97,17 @@ EVP_PKEY *d2i_PrivateKey(int type, EVP_PKEY **a, const unsigned char **pp,
if (!ret->ameth->old_priv_decode ||
!ret->ameth->old_priv_decode(ret, &p, length)) {
if (ret->ameth->priv_decode) {
+ EVP_PKEY *tmp;
PKCS8_PRIV_KEY_INFO *p8 = NULL;
p8 = d2i_PKCS8_PRIV_KEY_INFO(NULL, &p, length);
if (!p8)
goto err;
- EVP_PKEY_free(ret);
- ret = EVP_PKCS82PKEY(p8);
+ tmp = EVP_PKCS82PKEY(p8);
PKCS8_PRIV_KEY_INFO_free(p8);
- if (ret == NULL)
+ if (tmp == NULL)
goto err;
+ EVP_PKEY_free(ret);
+ ret = tmp;
} else {
ASN1err(ASN1_F_D2I_PRIVATEKEY, ERR_R_ASN1_LIB);
goto err;
diff --git a/crypto/asn1/f_enum.c b/crypto/asn1/f_enum.c
index 591c3b578127..94cd54dbeedd 100644
--- a/crypto/asn1/f_enum.c
+++ b/crypto/asn1/f_enum.c
@@ -160,8 +160,6 @@ int a2i_ASN1_ENUMERATED(BIO *bp, ASN1_ENUMERATED *bs, char *buf, int size)
i * 2);
if (sp == NULL) {
ASN1err(ASN1_F_A2I_ASN1_ENUMERATED, ERR_R_MALLOC_FAILURE);
- if (s != NULL)
- OPENSSL_free(s);
goto err;
}
s = sp;
@@ -199,5 +197,7 @@ int a2i_ASN1_ENUMERATED(BIO *bp, ASN1_ENUMERATED *bs, char *buf, int size)
err_sl:
ASN1err(ASN1_F_A2I_ASN1_ENUMERATED, ASN1_R_SHORT_LINE);
}
+ if (ret != 1)
+ OPENSSL_free(s);
return (ret);
}
diff --git a/crypto/asn1/f_int.c b/crypto/asn1/f_int.c
index 4a81f81c8832..2bdc78d74491 100644
--- a/crypto/asn1/f_int.c
+++ b/crypto/asn1/f_int.c
@@ -172,8 +172,6 @@ int a2i_ASN1_INTEGER(BIO *bp, ASN1_INTEGER *bs, char *buf, int size)
sp = OPENSSL_realloc_clean(s, slen, num + i * 2);
if (sp == NULL) {
ASN1err(ASN1_F_A2I_ASN1_INTEGER, ERR_R_MALLOC_FAILURE);
- if (s != NULL)
- OPENSSL_free(s);
goto err;
}
s = sp;
@@ -211,5 +209,7 @@ int a2i_ASN1_INTEGER(BIO *bp, ASN1_INTEGER *bs, char *buf, int size)
err_sl:
ASN1err(ASN1_F_A2I_ASN1_INTEGER, ASN1_R_SHORT_LINE);
}
+ if (ret != 1)
+ OPENSSL_free(s);
return (ret);
}
diff --git a/crypto/asn1/f_string.c b/crypto/asn1/f_string.c
index 6a6cf3471408..0f7b9cfb119b 100644
--- a/crypto/asn1/f_string.c
+++ b/crypto/asn1/f_string.c
@@ -166,8 +166,6 @@ int a2i_ASN1_STRING(BIO *bp, ASN1_STRING *bs, char *buf, int size)
i * 2);
if (sp == NULL) {
ASN1err(ASN1_F_A2I_ASN1_STRING, ERR_R_MALLOC_FAILURE);
- if (s != NULL)
- OPENSSL_free(s);
goto err;
}
s = sp;
@@ -205,5 +203,7 @@ int a2i_ASN1_STRING(BIO *bp, ASN1_STRING *bs, char *buf, int size)
err_sl:
ASN1err(ASN1_F_A2I_ASN1_STRING, ASN1_R_SHORT_LINE);
}
+ if (ret != 1)
+ OPENSSL_free(s);
return (ret);
}
diff --git a/crypto/asn1/p5_pbe.c b/crypto/asn1/p5_pbe.c
index bdbfdcd67c07..e2a1def53f1d 100644
--- a/crypto/asn1/p5_pbe.c
+++ b/crypto/asn1/p5_pbe.c
@@ -101,7 +101,7 @@ int PKCS5_pbe_set0_algor(X509_ALGOR *algor, int alg, int iter,
sstr = ASN1_STRING_data(pbe->salt);
if (salt)
memcpy(sstr, salt, saltlen);
- else if (RAND_pseudo_bytes(sstr, saltlen) < 0)
+ else if (RAND_bytes(sstr, saltlen) <= 0)
goto err;
if (!ASN1_item_pack(pbe, ASN1_ITEM_rptr(PBEPARAM), &pbe_str)) {
diff --git a/crypto/asn1/p5_pbev2.c b/crypto/asn1/p5_pbev2.c
index 73ba4a3d67aa..388053e0a1bf 100644
--- a/crypto/asn1/p5_pbev2.c
+++ b/crypto/asn1/p5_pbev2.c
@@ -120,7 +120,7 @@ X509_ALGOR *PKCS5_pbe2_set_iv(const EVP_CIPHER *cipher, int iter,
if (EVP_CIPHER_iv_length(cipher)) {
if (aiv)
memcpy(iv, aiv, EVP_CIPHER_iv_length(cipher));
- else if (RAND_pseudo_bytes(iv, EVP_CIPHER_iv_length(cipher)) < 0)
+ else if (RAND_bytes(iv, EVP_CIPHER_iv_length(cipher)) <= 0)
goto err;
}
@@ -225,7 +225,7 @@ X509_ALGOR *PKCS5_pbkdf2_set(int iter, unsigned char *salt, int saltlen,
if (salt)
memcpy(osalt->data, salt, saltlen);
- else if (RAND_pseudo_bytes(osalt->data, saltlen) < 0)
+ else if (RAND_bytes(osalt->data, saltlen) <= 0)
goto merr;
if (iter <= 0)
diff --git a/crypto/asn1/tasn_enc.c b/crypto/asn1/tasn_enc.c
index f7f83e56a981..081a9d534f8a 100644
--- a/crypto/asn1/tasn_enc.c
+++ b/crypto/asn1/tasn_enc.c
@@ -59,6 +59,7 @@
#include <stddef.h>
#include <string.h>
+#include <limits.h>
#include "cryptlib.h"
#include <openssl/asn1.h>
#include <openssl/asn1t.h>
@@ -216,17 +217,19 @@ int ASN1_item_ex_i2d(ASN1_VALUE **pval, unsigned char **out,
for (i = 0, tt = it->templates; i < it->tcount; tt++, i++) {
const ASN1_TEMPLATE *seqtt;
ASN1_VALUE **pseqval;
+ int tmplen;
seqtt = asn1_do_adb(pval, tt, 1);
if (!seqtt)
return 0;
pseqval = asn1_get_field_ptr(pval, seqtt);
- /* FIXME: check for errors in enhanced version */
- seqcontlen += asn1_template_ex_i2d(pseqval, NULL, seqtt,
- -1, aclass);
+ tmplen = asn1_template_ex_i2d(pseqval, NULL, seqtt, -1, aclass);
+ if (tmplen == -1 || (tmplen > INT_MAX - seqcontlen))
+ return -1;
+ seqcontlen += tmplen;
}
seqlen = ASN1_object_size(ndef, seqcontlen, tag);
- if (!out)
+ if (!out || seqlen == -1)
return seqlen;
/* Output SEQUENCE header */
ASN1_put_object(out, ndef, seqcontlen, tag, aclass);
@@ -339,19 +342,24 @@ static int asn1_template_ex_i2d(ASN1_VALUE **pval, unsigned char **out,
/* Determine total length of items */
skcontlen = 0;
for (i = 0; i < sk_ASN1_VALUE_num(sk); i++) {
+ int tmplen;
skitem = sk_ASN1_VALUE_value(sk, i);
- skcontlen += ASN1_item_ex_i2d(&skitem, NULL,
- ASN1_ITEM_ptr(tt->item),
- -1, iclass);
+ tmplen = ASN1_item_ex_i2d(&skitem, NULL, ASN1_ITEM_ptr(tt->item),
+ -1, iclass);
+ if (tmplen == -1 || (skcontlen > INT_MAX - tmplen))
+ return -1;
+ skcontlen += tmplen;
}
sklen = ASN1_object_size(ndef, skcontlen, sktag);
+ if (sklen == -1)
+ return -1;
/* If EXPLICIT need length of surrounding tag */
if (flags & ASN1_TFLG_EXPTAG)
ret = ASN1_object_size(ndef, sklen, ttag);
else
ret = sklen;
- if (!out)
+ if (!out || ret == -1)
return ret;
/* Now encode this lot... */
@@ -380,7 +388,7 @@ static int asn1_template_ex_i2d(ASN1_VALUE **pval, unsigned char **out,
return 0;
/* Find length of EXPLICIT tag */
ret = ASN1_object_size(ndef, i, ttag);
- if (out) {
+ if (out && ret != -1) {
/* Output tag and item */
ASN1_put_object(out, ndef, i, ttag, tclass);
ASN1_item_ex_i2d(pval, out, ASN1_ITEM_ptr(tt->item), -1, iclass);
diff --git a/crypto/asn1/tasn_prn.c b/crypto/asn1/tasn_prn.c
index 5e7d53e9854a..d163acb81400 100644
--- a/crypto/asn1/tasn_prn.c
+++ b/crypto/asn1/tasn_prn.c
@@ -446,6 +446,8 @@ static int asn1_print_integer_ctx(BIO *out, ASN1_INTEGER *str,
char *s;
int ret = 1;
s = i2s_ASN1_INTEGER(NULL, str);
+ if (s == NULL)
+ return 0;
if (BIO_puts(out, s) <= 0)
ret = 0;
OPENSSL_free(s);
diff --git a/crypto/asn1/x_name.c b/crypto/asn1/x_name.c
index a858c2993b90..26378fdb2a02 100644
--- a/crypto/asn1/x_name.c
+++ b/crypto/asn1/x_name.c
@@ -199,10 +199,8 @@ static int x509_name_ex_d2i(ASN1_VALUE **val,
int i, j, ret;
STACK_OF(X509_NAME_ENTRY) *entries;
X509_NAME_ENTRY *entry;
- if (len > X509_NAME_MAX) {
- ASN1err(ASN1_F_X509_NAME_EX_D2I, ASN1_R_TOO_LONG);
- return 0;
- }
+ if (len > X509_NAME_MAX)
+ len = X509_NAME_MAX;
q = p;
/* Get internal representation of Name */
diff --git a/crypto/bio/bf_nbio.c b/crypto/bio/bf_nbio.c
index a04f32a00817..4842bb4c82ff 100644
--- a/crypto/bio/bf_nbio.c
+++ b/crypto/bio/bf_nbio.c
@@ -139,7 +139,7 @@ static int nbiof_read(BIO *b, char *out, int outl)
BIO_clear_retry_flags(b);
#if 1
- if (RAND_pseudo_bytes(&n, 1) < 0)
+ if (RAND_bytes(&n, 1) <= 0)
return -1;
num = (n & 0x07);
@@ -179,7 +179,7 @@ static int nbiof_write(BIO *b, const char *in, int inl)
num = nt->lwn;
nt->lwn = 0;
} else {
- if (RAND_pseudo_bytes(&n, 1) < 0)
+ if (RAND_bytes(&n, 1) <= 0)
return -1;
num = (n & 7);
}
diff --git a/crypto/bn/bn_lib.c b/crypto/bn/bn_lib.c
index 80105fff410c..10b78f512607 100644
--- a/crypto/bn/bn_lib.c
+++ b/crypto/bn/bn_lib.c
@@ -569,7 +569,7 @@ void BN_clear(BIGNUM *a)
{
bn_check_top(a);
if (a->d != NULL)
- memset(a->d, 0, a->dmax * sizeof(a->d[0]));
+ OPENSSL_cleanse(a->d, a->dmax * sizeof(a->d[0]));
a->top = 0;
a->neg = 0;
}
diff --git a/crypto/bn/bn_print.c b/crypto/bn/bn_print.c
index bfa31efc5621..a9ff271b9ae9 100644
--- a/crypto/bn/bn_print.c
+++ b/crypto/bn/bn_print.c
@@ -111,6 +111,7 @@ char *BN_bn2dec(const BIGNUM *a)
char *p;
BIGNUM *t = NULL;
BN_ULONG *bn_data = NULL, *lp;
+ int bn_data_num;
/*-
* get an upper bound for the length of the decimal integer
@@ -120,9 +121,9 @@ char *BN_bn2dec(const BIGNUM *a)
*/
i = BN_num_bits(a) * 3;
num = (i / 10 + i / 1000 + 1) + 1;
- bn_data =
- (BN_ULONG *)OPENSSL_malloc((num / BN_DEC_NUM + 1) * sizeof(BN_ULONG));
- buf = (char *)OPENSSL_malloc(num + 3);
+ bn_data_num = num / BN_DEC_NUM + 1;
+ bn_data = OPENSSL_malloc(bn_data_num * sizeof(BN_ULONG));
+ buf = OPENSSL_malloc(num + 3);
if ((buf == NULL) || (bn_data == NULL)) {
BNerr(BN_F_BN_BN2DEC, ERR_R_MALLOC_FAILURE);
goto err;
@@ -140,9 +141,12 @@ char *BN_bn2dec(const BIGNUM *a)
if (BN_is_negative(t))
*p++ = '-';
- i = 0;
while (!BN_is_zero(t)) {
+ if (lp - bn_data >= bn_data_num)
+ goto err;
*lp = BN_div_word(t, BN_DEC_CONV);
+ if (*lp == (BN_ULONG)-1)
+ goto err;
lp++;
}
lp--;
diff --git a/crypto/bn/bn_rand.c b/crypto/bn/bn_rand.c
index f9fb2e9e45e0..2266d22b66aa 100644
--- a/crypto/bn/bn_rand.c
+++ b/crypto/bn/bn_rand.c
@@ -145,13 +145,9 @@ static int bnrand(int pseudorand, BIGNUM *rnd, int bits, int top, int bottom)
time(&tim);
RAND_add(&tim, sizeof(tim), 0.0);
- if (pseudorand) {
- if (RAND_pseudo_bytes(buf, bytes) == -1)
- goto err;
- } else {
- if (RAND_bytes(buf, bytes) <= 0)
- goto err;
- }
+ /* We ignore the value of pseudorand and always call RAND_bytes */
+ if (RAND_bytes(buf, bytes) <= 0)
+ goto err;
#if 1
if (pseudorand == 2) {
diff --git a/crypto/cms/cms_enc.c b/crypto/cms/cms_enc.c
index b14b4b68b5c9..90b1fcc75075 100644
--- a/crypto/cms/cms_enc.c
+++ b/crypto/cms/cms_enc.c
@@ -119,7 +119,7 @@ BIO *cms_EncryptedContent_init_bio(CMS_EncryptedContentInfo *ec)
/* Generate a random IV if we need one */
ivlen = EVP_CIPHER_CTX_iv_length(ctx);
if (ivlen > 0) {
- if (RAND_pseudo_bytes(iv, ivlen) <= 0)
+ if (RAND_bytes(iv, ivlen) <= 0)
goto err;
piv = iv;
}
@@ -179,10 +179,9 @@ BIO *cms_EncryptedContent_init_bio(CMS_EncryptedContentInfo *ec)
CMS_R_CIPHER_INITIALISATION_ERROR);
goto err;
}
-
- if (piv) {
+ if (enc) {
calg->parameter = ASN1_TYPE_new();
- if (!calg->parameter) {
+ if (calg->parameter == NULL) {
CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO, ERR_R_MALLOC_FAILURE);
goto err;
}
@@ -191,6 +190,11 @@ BIO *cms_EncryptedContent_init_bio(CMS_EncryptedContentInfo *ec)
CMS_R_CIPHER_PARAMETER_INITIALISATION_ERROR);
goto err;
}
+ /* If parameter type not set omit parameter */
+ if (calg->parameter->type == V_ASN1_UNDEF) {
+ ASN1_TYPE_free(calg->parameter);
+ calg->parameter = NULL;
+ }
}
ok = 1;
diff --git a/crypto/cms/cms_ess.c b/crypto/cms/cms_ess.c
index 8631a2eb2b30..8212560628a9 100644
--- a/crypto/cms/cms_ess.c
+++ b/crypto/cms/cms_ess.c
@@ -107,8 +107,7 @@ CMS_ReceiptRequest *CMS_ReceiptRequest_create0(unsigned char *id, int idlen,
else {
if (!ASN1_STRING_set(rr->signedContentIdentifier, NULL, 32))
goto merr;
- if (RAND_pseudo_bytes(rr->signedContentIdentifier->data, 32)
- <= 0)
+ if (RAND_bytes(rr->signedContentIdentifier->data, 32) <= 0)
goto err;
}
diff --git a/crypto/cms/cms_pwri.c b/crypto/cms/cms_pwri.c
index b91c01691fec..5c817caf2f05 100644
--- a/crypto/cms/cms_pwri.c
+++ b/crypto/cms/cms_pwri.c
@@ -134,7 +134,7 @@ CMS_RecipientInfo *CMS_add0_recipient_password(CMS_ContentInfo *cms,
ivlen = EVP_CIPHER_CTX_iv_length(&ctx);
if (ivlen > 0) {
- if (RAND_pseudo_bytes(iv, ivlen) <= 0)
+ if (RAND_bytes(iv, ivlen) <= 0)
goto err;
if (EVP_EncryptInit_ex(&ctx, NULL, NULL, NULL, iv) <= 0) {
CMSerr(CMS_F_CMS_ADD0_RECIPIENT_PASSWORD, ERR_R_EVP_LIB);
@@ -301,7 +301,7 @@ static int kek_wrap_key(unsigned char *out, size_t *outlen,
memcpy(out + 4, in, inlen);
/* Add random padding to end */
if (olen > inlen + 4
- && RAND_pseudo_bytes(out + 4 + inlen, olen - 4 - inlen) < 0)
+ && RAND_bytes(out + 4 + inlen, olen - 4 - inlen) <= 0)
return 0;
/* Encrypt twice */
EVP_EncryptUpdate(ctx, out, &dummy, out, olen);
diff --git a/crypto/des/des.c b/crypto/des/des.c
index 586aed72378c..d7374382d83a 100644
--- a/crypto/des/des.c
+++ b/crypto/des/des.c
@@ -456,7 +456,7 @@ void doencryption(void)
len = l - rem;
if (feof(DES_IN)) {
for (i = 7 - rem; i > 0; i--) {
- if (RAND_pseudo_bytes(buf + l++, 1) < 0)
+ if (RAND_bytes(buf + l++, 1) <= 0)
goto problems;
}
buf[l++] = rem;
diff --git a/crypto/des/enc_writ.c b/crypto/des/enc_writ.c
index bfaabde516ae..c2aaa8e98ca2 100644
--- a/crypto/des/enc_writ.c
+++ b/crypto/des/enc_writ.c
@@ -135,7 +135,7 @@ int DES_enc_write(int fd, const void *_buf, int len,
if (len < 8) {
cp = shortbuf;
memcpy(shortbuf, buf, len);
- if (RAND_pseudo_bytes(shortbuf + len, 8 - len) < 0) {
+ if (RAND_bytes(shortbuf + len, 8 - len) <= 0) {
return -1;
}
rnum = 8;
diff --git a/crypto/dsa/dsa_gen.c b/crypto/dsa/dsa_gen.c
index 34c6113c45e2..ba496b2d5f1d 100644
--- a/crypto/dsa/dsa_gen.c
+++ b/crypto/dsa/dsa_gen.c
@@ -195,7 +195,7 @@ int dsa_builtin_paramgen(DSA *ret, size_t bits, size_t qbits,
goto err;
if (!seed_len || !seed_in) {
- if (RAND_pseudo_bytes(seed, qsize) < 0)
+ if (RAND_bytes(seed, qsize) <= 0)
goto err;
seed_is_random = 1;
} else {
diff --git a/crypto/dsa/dsa_ossl.c b/crypto/dsa/dsa_ossl.c
index 9a3772e00dac..06cd2a2aed67 100644
--- a/crypto/dsa/dsa_ossl.c
+++ b/crypto/dsa/dsa_ossl.c
@@ -247,11 +247,13 @@ static int dsa_sign_setup(DSA *dsa, BN_CTX *ctx_in, BIGNUM **kinvp,
do
if (!BN_rand_range(&k, dsa->q))
goto err;
- while (BN_is_zero(&k)) ;
+ while (BN_is_zero(&k));
+
if ((dsa->flags & DSA_FLAG_NO_EXP_CONSTTIME) == 0) {
BN_set_flags(&k, BN_FLG_CONSTTIME);
}
+
if (dsa->flags & DSA_FLAG_CACHE_MONT_P) {
if (!BN_MONT_CTX_set_locked(&dsa->method_mont_p,
CRYPTO_LOCK_DSA, dsa->p, ctx))
@@ -264,6 +266,8 @@ static int dsa_sign_setup(DSA *dsa, BN_CTX *ctx_in, BIGNUM **kinvp,
if (!BN_copy(&kq, &k))
goto err;
+ BN_set_flags(&kq, BN_FLG_CONSTTIME);
+
/*
* We do not want timing information to leak the length of k, so we
* compute g^k using an equivalent exponent of fixed length. (This
@@ -282,6 +286,7 @@ static int dsa_sign_setup(DSA *dsa, BN_CTX *ctx_in, BIGNUM **kinvp,
} else {
K = &k;
}
+
DSA_BN_MOD_EXP(goto err, dsa, r, dsa->g, K, dsa->p, ctx,
dsa->method_mont_p);
if (!BN_mod(r, r, dsa->q, ctx))
diff --git a/crypto/evp/bio_ok.c b/crypto/evp/bio_ok.c
index 5c32e35e17b9..16e151f11017 100644
--- a/crypto/evp/bio_ok.c
+++ b/crypto/evp/bio_ok.c
@@ -491,7 +491,7 @@ 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.
*/
- if (RAND_pseudo_bytes(md->md_data, md->digest->md_size) < 0)
+ if (RAND_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);
diff --git a/crypto/evp/digest.c b/crypto/evp/digest.c
index 32167b294db1..0654050ab087 100644
--- a/crypto/evp/digest.c
+++ b/crypto/evp/digest.c
@@ -241,10 +241,10 @@ int EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl)
int EVP_DigestUpdate(EVP_MD_CTX *ctx, const void *data, size_t count)
{
#ifdef OPENSSL_FIPS
- return FIPS_digestupdate(ctx, data, count);
-#else
- return ctx->update(ctx, data, count);
+ if (FIPS_mode())
+ return FIPS_digestupdate(ctx, data, count);
#endif
+ return ctx->update(ctx, data, count);
}
/* The caller can assume that this removes any secret data from the context */
@@ -259,10 +259,11 @@ int EVP_DigestFinal(EVP_MD_CTX *ctx, unsigned char *md, unsigned int *size)
/* The caller can assume that this removes any secret data from the context */
int EVP_DigestFinal_ex(EVP_MD_CTX *ctx, unsigned char *md, unsigned int *size)
{
-#ifdef OPENSSL_FIPS
- return FIPS_digestfinal(ctx, md, size);
-#else
int ret;
+#ifdef OPENSSL_FIPS
+ if (FIPS_mode())
+ return FIPS_digestfinal(ctx, md, size);
+#endif
OPENSSL_assert(ctx->digest->md_size <= EVP_MAX_MD_SIZE);
ret = ctx->digest->final(ctx, md);
@@ -272,9 +273,8 @@ int EVP_DigestFinal_ex(EVP_MD_CTX *ctx, unsigned char *md, unsigned int *size)
ctx->digest->cleanup(ctx);
EVP_MD_CTX_set_flags(ctx, EVP_MD_CTX_FLAG_CLEANED);
}
- memset(ctx->md_data, 0, ctx->digest->ctx_size);
+ OPENSSL_cleanse(ctx->md_data, ctx->digest->ctx_size);
return ret;
-#endif
}
int EVP_MD_CTX_copy(EVP_MD_CTX *out, const EVP_MD_CTX *in)
diff --git a/crypto/evp/e_seed.c b/crypto/evp/e_seed.c
index 7249d1b1eecb..3d01eacac06e 100644
--- a/crypto/evp/e_seed.c
+++ b/crypto/evp/e_seed.c
@@ -70,7 +70,8 @@ typedef struct {
} EVP_SEED_KEY;
IMPLEMENT_BLOCK_CIPHER(seed, ks, SEED, EVP_SEED_KEY, NID_seed,
- 16, 16, 16, 128, 0, seed_init_key, 0, 0, 0, 0)
+ 16, 16, 16, 128, EVP_CIPH_FLAG_DEFAULT_ASN1,
+ seed_init_key, 0, 0, 0, 0)
static int seed_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
const unsigned char *iv, int enc)
diff --git a/crypto/md2/md2_dgst.c b/crypto/md2/md2_dgst.c
index 9cd79f8d70c3..7f5d9ba69ba2 100644
--- a/crypto/md2/md2_dgst.c
+++ b/crypto/md2/md2_dgst.c
@@ -219,6 +219,6 @@ int MD2_Final(unsigned char *md, MD2_CTX *c)
for (i = 0; i < 16; i++)
md[i] = (UCHAR) (p1[i] & 0xff);
- memset((char *)&c, 0, sizeof(c));
+ OPENSSL_cleanse(c, sizeof(*c));
return 1;
}
diff --git a/crypto/md32_common.h b/crypto/md32_common.h
index 1823833419c4..aac719139e32 100644
--- a/crypto/md32_common.h
+++ b/crypto/md32_common.h
@@ -109,6 +109,8 @@
* <appro@fy.chalmers.se>
*/
+#include <openssl/crypto.h>
+
#if !defined(DATA_ORDER_IS_BIG_ENDIAN) && !defined(DATA_ORDER_IS_LITTLE_ENDIAN)
# error "DATA_ORDER must be defined!"
#endif
@@ -311,6 +313,12 @@ int HASH_UPDATE(HASH_CTX *c, const void *data_, size_t len)
data += n;
len -= n;
c->num = 0;
+ /*
+ * We use memset rather than OPENSSL_cleanse() here deliberately.
+ * Using OPENSSL_cleanse() here could be a performance issue. It
+ * will get properly cleansed on finalisation so this isn't a
+ * security problem.
+ */
memset(p, 0, HASH_CBLOCK); /* keep it zeroed */
} else {
memcpy(p + n, data, len);
@@ -366,7 +374,7 @@ int HASH_FINAL(unsigned char *md, HASH_CTX *c)
p -= HASH_CBLOCK;
HASH_BLOCK_DATA_ORDER(c, p, 1);
c->num = 0;
- memset(p, 0, HASH_CBLOCK);
+ OPENSSL_cleanse(p, HASH_CBLOCK);
#ifndef HASH_MAKE_STRING
# error "HASH_MAKE_STRING must be defined!"
diff --git a/crypto/mdc2/mdc2dgst.c b/crypto/mdc2/mdc2dgst.c
index 6615cf84d7d2..2dce4936337a 100644
--- a/crypto/mdc2/mdc2dgst.c
+++ b/crypto/mdc2/mdc2dgst.c
@@ -91,7 +91,7 @@ int MDC2_Update(MDC2_CTX *c, const unsigned char *in, size_t len)
i = c->num;
if (i != 0) {
- if (i + len < MDC2_BLOCK) {
+ if (len < MDC2_BLOCK - i) {
/* partial block */
memcpy(&(c->data[i]), in, len);
c->num += (int)len;
diff --git a/crypto/ocsp/ocsp_ext.c b/crypto/ocsp/ocsp_ext.c
index c19648c7329b..55af31b5734a 100755
--- a/crypto/ocsp/ocsp_ext.c
+++ b/crypto/ocsp/ocsp_ext.c
@@ -361,7 +361,7 @@ 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 if (RAND_pseudo_bytes(tmpval, len) < 0)
+ else if (RAND_bytes(tmpval, len) <= 0)
goto err;
if (!X509V3_add1_i2d(exts, NID_id_pkix_OCSP_Nonce,
&os, 0, X509V3_ADD_REPLACE))
diff --git a/crypto/opensslv.h b/crypto/opensslv.h
index 2f293232f44c..4d014f430c00 100644
--- a/crypto/opensslv.h
+++ b/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 0x1000114fL
+# define OPENSSL_VERSION_NUMBER 0x1000115fL
# ifdef OPENSSL_FIPS
-# define OPENSSL_VERSION_TEXT "OpenSSL 1.0.1t-fips 3 May 2016"
+# define OPENSSL_VERSION_TEXT "OpenSSL 1.0.1u-fips 22 Sep 2016"
# else
-# define OPENSSL_VERSION_TEXT "OpenSSL 1.0.1t 3 May 2016"
+# define OPENSSL_VERSION_TEXT "OpenSSL 1.0.1u 22 Sep 2016"
# endif
# define OPENSSL_VERSION_PTEXT " part of " OPENSSL_VERSION_TEXT
diff --git a/crypto/pem/pem.h b/crypto/pem/pem.h
index 2cdad8ac2669..de4ba3ee1d56 100644
--- a/crypto/pem/pem.h
+++ b/crypto/pem/pem.h
@@ -588,6 +588,7 @@ void ERR_load_PEM_strings(void);
# define PEM_R_ERROR_CONVERTING_PRIVATE_KEY 115
# define PEM_R_EXPECTING_PRIVATE_KEY_BLOB 119
# define PEM_R_EXPECTING_PUBLIC_KEY_BLOB 120
+# define PEM_R_HEADER_TOO_LONG 128
# define PEM_R_INCONSISTENT_HEADER 121
# define PEM_R_KEYBLOB_HEADER_PARSE_ERROR 122
# define PEM_R_KEYBLOB_TOO_SHORT 123
diff --git a/crypto/pem/pem_err.c b/crypto/pem/pem_err.c
index 702c5adecb86..f02de5c44a1e 100644
--- a/crypto/pem/pem_err.c
+++ b/crypto/pem/pem_err.c
@@ -1,6 +1,6 @@
/* crypto/pem/pem_err.c */
/* ====================================================================
- * Copyright (c) 1999-2007 The OpenSSL Project. All rights reserved.
+ * Copyright (c) 1999-2016 The OpenSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -130,6 +130,7 @@ static ERR_STRING_DATA PEM_str_reasons[] = {
"expecting private key blob"},
{ERR_REASON(PEM_R_EXPECTING_PUBLIC_KEY_BLOB),
"expecting public key blob"},
+ {ERR_REASON(PEM_R_HEADER_TOO_LONG), "header too long"},
{ERR_REASON(PEM_R_INCONSISTENT_HEADER), "inconsistent header"},
{ERR_REASON(PEM_R_KEYBLOB_HEADER_PARSE_ERROR),
"keyblob header parse error"},
diff --git a/crypto/pem/pem_lib.c b/crypto/pem/pem_lib.c
index ab45a84fa265..7e598833887e 100644
--- a/crypto/pem/pem_lib.c
+++ b/crypto/pem/pem_lib.c
@@ -383,7 +383,7 @@ int PEM_ASN1_write_bio(i2d_of_void *i2d, const char *name, BIO *bp,
}
RAND_add(data, i, 0); /* put in the RSA key. */
OPENSSL_assert(enc->iv_len <= (int)sizeof(iv));
- if (RAND_pseudo_bytes(iv, enc->iv_len) < 0) /* Generate a salt */
+ if (RAND_bytes(iv, enc->iv_len) <= 0) /* Generate a salt */
goto err;
/*
* The 'iv' is used as the iv and as a salt. It is NOT taken from
diff --git a/crypto/pem/pvkfmt.c b/crypto/pem/pvkfmt.c
index 61864468f6d4..1ce5a1e319c5 100644
--- a/crypto/pem/pvkfmt.c
+++ b/crypto/pem/pvkfmt.c
@@ -127,6 +127,9 @@ static int read_lebn(const unsigned char **in, unsigned int nbyte, BIGNUM **r)
# define MS_KEYTYPE_KEYX 0x1
# define MS_KEYTYPE_SIGN 0x2
+/* Maximum length of a blob after header */
+# define BLOB_MAX_LENGTH 102400
+
/* The PVK file magic number: seems to spell out "bobsfile", who is Bob? */
# define MS_PVKMAGIC 0xb0b5f11eL
/* Salt length for PVK files */
@@ -272,6 +275,10 @@ static EVP_PKEY *do_b2i_bio(BIO *in, int ispub)
return NULL;
length = blob_length(bitlen, isdss, ispub);
+ if (length > BLOB_MAX_LENGTH) {
+ PEMerr(PEM_F_DO_B2I_BIO, PEM_R_HEADER_TOO_LONG);
+ return NULL;
+ }
buf = OPENSSL_malloc(length);
if (!buf) {
PEMerr(PEM_F_DO_B2I_BIO, ERR_R_MALLOC_FAILURE);
diff --git a/crypto/pkcs12/p12_mutl.c b/crypto/pkcs12/p12_mutl.c
index a9277827ff2d..cbf34da05ada 100644
--- a/crypto/pkcs12/p12_mutl.c
+++ b/crypto/pkcs12/p12_mutl.c
@@ -179,7 +179,7 @@ int PKCS12_setup_mac(PKCS12 *p12, int iter, unsigned char *salt, int saltlen,
}
p12->mac->salt->length = saltlen;
if (!salt) {
- if (RAND_pseudo_bytes(p12->mac->salt->data, saltlen) < 0)
+ if (RAND_bytes(p12->mac->salt->data, saltlen) <= 0)
return 0;
} else
memcpy(p12->mac->salt->data, salt, saltlen);
diff --git a/crypto/pkcs12/p12_npas.c b/crypto/pkcs12/p12_npas.c
index a89b61abab37..9e8ebb2a78c3 100644
--- a/crypto/pkcs12/p12_npas.c
+++ b/crypto/pkcs12/p12_npas.c
@@ -66,17 +66,18 @@
/* PKCS#12 password change routine */
-static int newpass_p12(PKCS12 *p12, char *oldpass, char *newpass);
-static int newpass_bags(STACK_OF(PKCS12_SAFEBAG) *bags, char *oldpass,
- char *newpass);
-static int newpass_bag(PKCS12_SAFEBAG *bag, char *oldpass, char *newpass);
+static int newpass_p12(PKCS12 *p12, const char *oldpass, const char *newpass);
+static int newpass_bags(STACK_OF(PKCS12_SAFEBAG) *bags, const char *oldpass,
+ const char *newpass);
+static int newpass_bag(PKCS12_SAFEBAG *bag, const char *oldpass,
+ const char *newpass);
static int alg_get(X509_ALGOR *alg, int *pnid, int *piter, int *psaltlen);
/*
* Change the password on a PKCS#12 structure.
*/
-int PKCS12_newpass(PKCS12 *p12, char *oldpass, char *newpass)
+int PKCS12_newpass(PKCS12 *p12, const char *oldpass, const char *newpass)
{
/* Check for NULL PKCS12 structure */
@@ -103,20 +104,21 @@ int PKCS12_newpass(PKCS12 *p12, char *oldpass, char *newpass)
/* Parse the outer PKCS#12 structure */
-static int newpass_p12(PKCS12 *p12, char *oldpass, char *newpass)
+static int newpass_p12(PKCS12 *p12, const char *oldpass, const char *newpass)
{
- STACK_OF(PKCS7) *asafes, *newsafes;
- STACK_OF(PKCS12_SAFEBAG) *bags;
+ STACK_OF(PKCS7) *asafes = NULL, *newsafes = NULL;
+ STACK_OF(PKCS12_SAFEBAG) *bags = NULL;
int i, bagnid, pbe_nid = 0, pbe_iter = 0, pbe_saltlen = 0;
PKCS7 *p7, *p7new;
- ASN1_OCTET_STRING *p12_data_tmp = NULL, *macnew = NULL;
+ ASN1_OCTET_STRING *p12_data_tmp = NULL;
unsigned char mac[EVP_MAX_MD_SIZE];
unsigned int maclen;
+ int rv = 0;
- if (!(asafes = PKCS12_unpack_authsafes(p12)))
- return 0;
- if (!(newsafes = sk_PKCS7_new_null()))
- return 0;
+ if ((asafes = PKCS12_unpack_authsafes(p12)) == NULL)
+ goto err;
+ if ((newsafes = sk_PKCS7_new_null()) == NULL)
+ goto err;
for (i = 0; i < sk_PKCS7_num(asafes); i++) {
p7 = sk_PKCS7_value(asafes, i);
bagnid = OBJ_obj2nid(p7->type);
@@ -125,67 +127,57 @@ static int newpass_p12(PKCS12 *p12, char *oldpass, char *newpass)
} else if (bagnid == NID_pkcs7_encrypted) {
bags = PKCS12_unpack_p7encdata(p7, oldpass, -1);
if (!alg_get(p7->d.encrypted->enc_data->algorithm,
- &pbe_nid, &pbe_iter, &pbe_saltlen)) {
- sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free);
- bags = NULL;
- }
- } else
+ &pbe_nid, &pbe_iter, &pbe_saltlen))
+ goto err;
+ } else {
continue;
- if (!bags) {
- sk_PKCS7_pop_free(asafes, PKCS7_free);
- return 0;
- }
- if (!newpass_bags(bags, oldpass, newpass)) {
- sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free);
- sk_PKCS7_pop_free(asafes, PKCS7_free);
- return 0;
}
+ if (bags == NULL)
+ goto err;
+ if (!newpass_bags(bags, oldpass, newpass))
+ goto err;
/* Repack bag in same form with new password */
if (bagnid == NID_pkcs7_data)
p7new = PKCS12_pack_p7data(bags);
else
p7new = PKCS12_pack_p7encdata(pbe_nid, newpass, -1, NULL,
pbe_saltlen, pbe_iter, bags);
+ if (!p7new || !sk_PKCS7_push(newsafes, p7new))
+ goto err;
sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free);
- if (!p7new) {
- sk_PKCS7_pop_free(asafes, PKCS7_free);
- return 0;
- }
- sk_PKCS7_push(newsafes, p7new);
+ bags = NULL;
}
- sk_PKCS7_pop_free(asafes, PKCS7_free);
/* Repack safe: save old safe in case of error */
p12_data_tmp = p12->authsafes->d.data;
- if (!(p12->authsafes->d.data = ASN1_OCTET_STRING_new()))
- goto saferr;
+ if ((p12->authsafes->d.data = ASN1_OCTET_STRING_new()) == NULL)
+ goto err;
if (!PKCS12_pack_authsafes(p12, newsafes))
- goto saferr;
-
+ goto err;
if (!PKCS12_gen_mac(p12, newpass, -1, mac, &maclen))
- goto saferr;
- if (!(macnew = ASN1_OCTET_STRING_new()))
- goto saferr;
- if (!ASN1_OCTET_STRING_set(macnew, mac, maclen))
- goto saferr;
- ASN1_OCTET_STRING_free(p12->mac->dinfo->digest);
- p12->mac->dinfo->digest = macnew;
- ASN1_OCTET_STRING_free(p12_data_tmp);
-
- return 1;
-
- saferr:
- /* Restore old safe */
- ASN1_OCTET_STRING_free(p12->authsafes->d.data);
- ASN1_OCTET_STRING_free(macnew);
- p12->authsafes->d.data = p12_data_tmp;
- return 0;
-
+ goto err;
+ if (!ASN1_OCTET_STRING_set(p12->mac->dinfo->digest, mac, maclen))
+ goto err;
+
+ rv = 1;
+
+err:
+ /* Restore old safe if necessary */
+ if (rv == 1) {
+ ASN1_OCTET_STRING_free(p12_data_tmp);
+ } else if (p12_data_tmp != NULL) {
+ ASN1_OCTET_STRING_free(p12->authsafes->d.data);
+ p12->authsafes->d.data = p12_data_tmp;
+ }
+ sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free);
+ sk_PKCS7_pop_free(asafes, PKCS7_free);
+ sk_PKCS7_pop_free(newsafes, PKCS7_free);
+ return rv;
}
-static int newpass_bags(STACK_OF(PKCS12_SAFEBAG) *bags, char *oldpass,
- char *newpass)
+static int newpass_bags(STACK_OF(PKCS12_SAFEBAG) *bags, const char *oldpass,
+ const char *newpass)
{
int i;
for (i = 0; i < sk_PKCS12_SAFEBAG_num(bags); i++) {
@@ -197,7 +189,8 @@ static int newpass_bags(STACK_OF(PKCS12_SAFEBAG) *bags, char *oldpass,
/* Change password of safebag: only needs handle shrouded keybags */
-static int newpass_bag(PKCS12_SAFEBAG *bag, char *oldpass, char *newpass)
+static int newpass_bag(PKCS12_SAFEBAG *bag, const char *oldpass,
+ const char *newpass)
{
PKCS8_PRIV_KEY_INFO *p8;
X509_SIG *p8new;
@@ -210,8 +203,10 @@ static int newpass_bag(PKCS12_SAFEBAG *bag, char *oldpass, char *newpass)
return 0;
if (!alg_get(bag->value.shkeybag->algor, &p8_nid, &p8_iter, &p8_saltlen))
return 0;
- if (!(p8new = PKCS8_encrypt(p8_nid, NULL, newpass, -1, NULL, p8_saltlen,
- p8_iter, p8)))
+ p8new = PKCS8_encrypt(p8_nid, NULL, newpass, -1, NULL, p8_saltlen,
+ p8_iter, p8);
+ PKCS8_PRIV_KEY_INFO_free(p8);
+ if (p8new == NULL)
return 0;
X509_SIG_free(bag->value.shkeybag);
bag->value.shkeybag = p8new;
diff --git a/crypto/pkcs12/p12_utl.c b/crypto/pkcs12/p12_utl.c
index a0b992eab66c..e466f762ffda 100644
--- a/crypto/pkcs12/p12_utl.c
+++ b/crypto/pkcs12/p12_utl.c
@@ -91,6 +91,10 @@ char *OPENSSL_uni2asc(unsigned char *uni, int unilen)
{
int asclen, i;
char *asctmp;
+
+ /* string must contain an even number of bytes */
+ if (unilen & 1)
+ return NULL;
asclen = unilen / 2;
/* If no terminating zero allow for one */
if (!unilen || uni[unilen - 1])
diff --git a/crypto/pkcs12/pkcs12.h b/crypto/pkcs12/pkcs12.h
index a39adf5eb52e..21f1f62b36c6 100644
--- a/crypto/pkcs12/pkcs12.h
+++ b/crypto/pkcs12/pkcs12.h
@@ -270,7 +270,7 @@ int i2d_PKCS12_bio(BIO *bp, PKCS12 *p12);
int i2d_PKCS12_fp(FILE *fp, PKCS12 *p12);
PKCS12 *d2i_PKCS12_bio(BIO *bp, PKCS12 **p12);
PKCS12 *d2i_PKCS12_fp(FILE *fp, PKCS12 **p12);
-int PKCS12_newpass(PKCS12 *p12, char *oldpass, char *newpass);
+int PKCS12_newpass(PKCS12 *p12, const char *oldpass, const char *newpass);
/* BEGIN ERROR CODES */
/*
diff --git a/crypto/pkcs7/pk7_doit.c b/crypto/pkcs7/pk7_doit.c
index 946aaa65435b..1ab6d5ae7129 100644
--- a/crypto/pkcs7/pk7_doit.c
+++ b/crypto/pkcs7/pk7_doit.c
@@ -340,7 +340,7 @@ BIO *PKCS7_dataInit(PKCS7 *p7, BIO *bio)
ivlen = EVP_CIPHER_iv_length(evp_cipher);
xalg->algorithm = OBJ_nid2obj(EVP_CIPHER_type(evp_cipher));
if (ivlen > 0)
- if (RAND_pseudo_bytes(iv, ivlen) <= 0)
+ if (RAND_bytes(iv, ivlen) <= 0)
goto err;
if (EVP_CipherInit_ex(ctx, evp_cipher, NULL, NULL, NULL, 1) <= 0)
goto err;
diff --git a/crypto/rand/rand_unix.c b/crypto/rand/rand_unix.c
index 266111edda8c..6c5b65da0070 100644
--- a/crypto/rand/rand_unix.c
+++ b/crypto/rand/rand_unix.c
@@ -235,7 +235,7 @@ int RAND_poll(void)
rnd >>= 8;
}
RAND_add(buf, sizeof(buf), ENTROPY_NEEDED);
- memset(buf, 0, sizeof(buf));
+ OPENSSL_cleanse(buf, sizeof(buf));
return 1;
}
diff --git a/crypto/srp/srp_lib.c b/crypto/srp/srp_lib.c
index e9a2e058f687..e310946e073b 100644
--- a/crypto/srp/srp_lib.c
+++ b/crypto/srp/srp_lib.c
@@ -159,8 +159,7 @@ BIGNUM *SRP_Calc_server_key(BIGNUM *A, BIGNUM *v, BIGNUM *u, BIGNUM *b,
if (u == NULL || A == NULL || v == NULL || b == NULL || N == NULL)
return NULL;
- if ((bn_ctx = BN_CTX_new()) == NULL ||
- (tmp = BN_new()) == NULL || (S = BN_new()) == NULL)
+ if ((bn_ctx = BN_CTX_new()) == NULL || (tmp = BN_new()) == NULL)
goto err;
/* S = (A*v**u) ** b */
@@ -169,8 +168,12 @@ BIGNUM *SRP_Calc_server_key(BIGNUM *A, BIGNUM *v, BIGNUM *u, BIGNUM *b,
goto err;
if (!BN_mod_mul(tmp, A, tmp, N, bn_ctx))
goto err;
- if (!BN_mod_exp(S, tmp, b, N, bn_ctx))
- goto err;
+
+ S = BN_new();
+ if (S != NULL && !BN_mod_exp(S, tmp, b, N, bn_ctx)) {
+ BN_free(S);
+ S = NULL;
+ }
err:
BN_CTX_free(bn_ctx);
BN_clear_free(tmp);
@@ -267,7 +270,7 @@ BIGNUM *SRP_Calc_client_key(BIGNUM *N, BIGNUM *B, BIGNUM *g, BIGNUM *x,
if ((tmp = BN_new()) == NULL ||
(tmp2 = BN_new()) == NULL ||
- (tmp3 = BN_new()) == NULL || (K = BN_new()) == NULL)
+ (tmp3 = BN_new()) == NULL)
goto err;
if (!BN_mod_exp(tmp, g, x, N, bn_ctx))
@@ -283,8 +286,11 @@ BIGNUM *SRP_Calc_client_key(BIGNUM *N, BIGNUM *B, BIGNUM *g, BIGNUM *x,
goto err;
if (!BN_mod_add(tmp2, a, tmp3, N, bn_ctx))
goto err;
- if (!BN_mod_exp(K, tmp, tmp2, N, bn_ctx))
- goto err;
+ K = BN_new();
+ if (K != NULL && !BN_mod_exp(K, tmp, tmp2, N, bn_ctx)) {
+ BN_free(K);
+ K = NULL;
+ }
err:
BN_CTX_free(bn_ctx);
diff --git a/crypto/srp/srp_vfy.c b/crypto/srp/srp_vfy.c
index 26ad3e07b4bb..986babfd493c 100644
--- a/crypto/srp/srp_vfy.c
+++ b/crypto/srp/srp_vfy.c
@@ -544,7 +544,7 @@ SRP_user_pwd *SRP_VBASE_get1_by_user(SRP_VBASE *vb, char *username)
if (!SRP_user_pwd_set_ids(user, username, NULL))
goto err;
- if (RAND_pseudo_bytes(digv, SHA_DIGEST_LENGTH) < 0)
+ if (RAND_bytes(digv, SHA_DIGEST_LENGTH) <= 0)
goto err;
EVP_MD_CTX_init(&ctxt);
EVP_DigestInit_ex(&ctxt, EVP_sha1(), NULL);
@@ -597,7 +597,7 @@ char *SRP_create_verifier(const char *user, const char *pass, char **salt,
}
if (*salt == NULL) {
- if (RAND_pseudo_bytes(tmp2, SRP_RANDOM_SALT_LEN) < 0)
+ if (RAND_bytes(tmp2, SRP_RANDOM_SALT_LEN) <= 0)
goto err;
s = BN_bin2bn(tmp2, SRP_RANDOM_SALT_LEN, NULL);
@@ -670,7 +670,7 @@ int SRP_create_verifier_BN(const char *user, const char *pass, BIGNUM **salt,
srp_bn_print(g);
if (*salt == NULL) {
- if (RAND_pseudo_bytes(tmp2, SRP_RANDOM_SALT_LEN) < 0)
+ if (RAND_bytes(tmp2, SRP_RANDOM_SALT_LEN) <= 0)
goto err;
salttmp = BN_bin2bn(tmp2, SRP_RANDOM_SALT_LEN, NULL);
diff --git a/crypto/ts/ts_lib.c b/crypto/ts/ts_lib.c
index c51538a17f42..e0f106353723 100644
--- a/crypto/ts/ts_lib.c
+++ b/crypto/ts/ts_lib.c
@@ -90,9 +90,8 @@ int TS_OBJ_print_bio(BIO *bio, const ASN1_OBJECT *obj)
{
char obj_txt[128];
- int len = OBJ_obj2txt(obj_txt, sizeof(obj_txt), obj, 0);
- BIO_write(bio, obj_txt, len);
- BIO_write(bio, "\n", 1);
+ OBJ_obj2txt(obj_txt, sizeof(obj_txt), obj, 0);
+ BIO_printf(bio, "%s\n", obj_txt);
return 1;
}
diff --git a/crypto/whrlpool/wp_dgst.c b/crypto/whrlpool/wp_dgst.c
index e33bb4f833b5..807d1c49b2d3 100644
--- a/crypto/whrlpool/wp_dgst.c
+++ b/crypto/whrlpool/wp_dgst.c
@@ -51,6 +51,7 @@
* input. This is done for perfomance.
*/
+#include <openssl/crypto.h>
#include "wp_locl.h"
#include <openssl/crypto.h>
#include <string.h>
@@ -237,7 +238,7 @@ int WHIRLPOOL_Final(unsigned char *md, WHIRLPOOL_CTX *c)
if (md) {
memcpy(md, c->H.c, WHIRLPOOL_DIGEST_LENGTH);
- memset(c, 0, sizeof(*c));
+ OPENSSL_cleanse(c, sizeof(*c));
return (1);
}
return (0);
diff --git a/crypto/x509/x509.h b/crypto/x509/x509.h
index bd600de43107..dc326a725620 100644
--- a/crypto/x509/x509.h
+++ b/crypto/x509/x509.h
@@ -1216,6 +1216,7 @@ int X509_TRUST_get_trust(X509_TRUST *xp);
* The following lines are auto generated by the script mkerr.pl. Any changes
* made after this point may be overwritten when the script is next run.
*/
+
void ERR_load_X509_strings(void);
/* Error codes for the X509 functions. */
@@ -1223,6 +1224,7 @@ void ERR_load_X509_strings(void);
/* Function codes. */
# define X509_F_ADD_CERT_DIR 100
# define X509_F_BY_FILE_CTRL 101
+# define X509_F_CHECK_NAME_CONSTRAINTS 106
# define X509_F_CHECK_POLICY 145
# define X509_F_DIR_CTRL 102
# define X509_F_GET_CERT_BY_SUBJECT 103
@@ -1296,7 +1298,7 @@ void ERR_load_X509_strings(void);
# define X509_R_WRONG_LOOKUP_TYPE 112
# define X509_R_WRONG_TYPE 122
-#ifdef __cplusplus
+# ifdef __cplusplus
}
-#endif
+# endif
#endif
diff --git a/crypto/x509/x509_err.c b/crypto/x509/x509_err.c
index a2b8b7fc358f..174b65e33130 100644
--- a/crypto/x509/x509_err.c
+++ b/crypto/x509/x509_err.c
@@ -72,6 +72,7 @@
static ERR_STRING_DATA X509_str_functs[] = {
{ERR_FUNC(X509_F_ADD_CERT_DIR), "ADD_CERT_DIR"},
{ERR_FUNC(X509_F_BY_FILE_CTRL), "BY_FILE_CTRL"},
+ {ERR_FUNC(X509_F_CHECK_NAME_CONSTRAINTS), "CHECK_NAME_CONSTRAINTS"},
{ERR_FUNC(X509_F_CHECK_POLICY), "CHECK_POLICY"},
{ERR_FUNC(X509_F_DIR_CTRL), "DIR_CTRL"},
{ERR_FUNC(X509_F_GET_CERT_BY_SUBJECT), "GET_CERT_BY_SUBJECT"},
diff --git a/crypto/x509/x509_txt.c b/crypto/x509/x509_txt.c
index d834180ec443..b249d4256731 100644
--- a/crypto/x509/x509_txt.c
+++ b/crypto/x509/x509_txt.c
@@ -183,6 +183,12 @@ const char *X509_verify_cert_error_string(long n)
return ("unsupported or invalid name syntax");
case X509_V_ERR_CRL_PATH_VALIDATION_ERROR:
return ("CRL path validation error");
+ case X509_V_ERR_INVALID_CALL:
+ return ("Invalid certificate verification context");
+ case X509_V_ERR_STORE_LOOKUP:
+ return ("Issuer certificate lookup error");
+ case X509_V_ERR_PROXY_SUBJECT_NAME_VIOLATION:
+ return ("proxy subject name violation");
default:
BIO_snprintf(buf, sizeof buf, "error number %ld", n);
diff --git a/crypto/x509/x509_vfy.c b/crypto/x509/x509_vfy.c
index 3bad523f7114..f0fa7f4f07b4 100644
--- a/crypto/x509/x509_vfy.c
+++ b/crypto/x509/x509_vfy.c
@@ -160,6 +160,7 @@ int X509_verify_cert(X509_STORE_CTX *ctx)
STACK_OF(X509) *sktmp = NULL;
if (ctx->cert == NULL) {
X509err(X509_F_X509_VERIFY_CERT, X509_R_NO_CERT_SET_FOR_US_TO_VERIFY);
+ ctx->error = X509_V_ERR_INVALID_CALL;
return -1;
}
if (ctx->chain != NULL) {
@@ -168,6 +169,7 @@ int X509_verify_cert(X509_STORE_CTX *ctx)
* cannot do another one.
*/
X509err(X509_F_X509_VERIFY_CERT, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+ ctx->error = X509_V_ERR_INVALID_CALL;
return -1;
}
@@ -180,6 +182,8 @@ int X509_verify_cert(X509_STORE_CTX *ctx)
if (((ctx->chain = sk_X509_new_null()) == NULL) ||
(!sk_X509_push(ctx->chain, ctx->cert))) {
X509err(X509_F_X509_VERIFY_CERT, ERR_R_MALLOC_FAILURE);
+ ctx->error = X509_V_ERR_OUT_OF_MEM;
+ ok = -1;
goto end;
}
CRYPTO_add(&ctx->cert->references, 1, CRYPTO_LOCK_X509);
@@ -189,6 +193,8 @@ int X509_verify_cert(X509_STORE_CTX *ctx)
if (ctx->untrusted != NULL
&& (sktmp = sk_X509_dup(ctx->untrusted)) == NULL) {
X509err(X509_F_X509_VERIFY_CERT, ERR_R_MALLOC_FAILURE);
+ ctx->error = X509_V_ERR_OUT_OF_MEM;
+ ok = -1;
goto end;
}
@@ -214,6 +220,8 @@ int X509_verify_cert(X509_STORE_CTX *ctx)
if (xtmp != NULL) {
if (!sk_X509_push(ctx->chain, xtmp)) {
X509err(X509_F_X509_VERIFY_CERT, ERR_R_MALLOC_FAILURE);
+ ctx->error = X509_V_ERR_OUT_OF_MEM;
+ ok = -1;
goto end;
}
CRYPTO_add(&xtmp->references, 1, CRYPTO_LOCK_X509);
@@ -293,15 +301,19 @@ int X509_verify_cert(X509_STORE_CTX *ctx)
if (ctx->check_issued(ctx, x, x))
break;
ok = ctx->get_issuer(&xtmp, ctx, x);
- if (ok < 0)
- return ok;
+ if (ok < 0) {
+ ctx->error = X509_V_ERR_STORE_LOOKUP;
+ goto end;
+ }
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;
+ ctx->error = X509_V_ERR_OUT_OF_MEM;
+ ok = -1;
+ goto end;
}
num++;
}
@@ -317,8 +329,10 @@ int X509_verify_cert(X509_STORE_CTX *ctx)
while (j-- > 1) {
xtmp2 = sk_X509_value(ctx->chain, j - 1);
ok = ctx->get_issuer(&xtmp, ctx, xtmp2);
- if (ok < 0)
+ if (ok < 0) {
+ ctx->error = X509_V_ERR_STORE_LOOKUP;
goto end;
+ }
/* Check if we found an alternate chain */
if (ok > 0) {
/*
@@ -432,6 +446,10 @@ int X509_verify_cert(X509_STORE_CTX *ctx)
sk_X509_free(sktmp);
if (chain_ss != NULL)
X509_free(chain_ss);
+
+ /* Safety net, error returns must set ctx->error */
+ if (ok <= 0 && ctx->error == X509_V_OK)
+ ctx->error = X509_V_ERR_UNSPECIFIED;
return ok;
}
@@ -615,13 +633,27 @@ static int check_chain_extensions(X509_STORE_CTX *ctx)
* the next certificate must be a CA certificate.
*/
if (x->ex_flags & EXFLAG_PROXY) {
- if (x->ex_pcpathlen != -1 && i > x->ex_pcpathlen) {
- ctx->error = X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED;
- ctx->error_depth = i;
- ctx->current_cert = x;
- ok = cb(0, ctx);
- if (!ok)
- goto end;
+ /*
+ * RFC3820, 4.1.3 (b)(1) stipulates that if pCPathLengthConstraint
+ * is less than max_path_length, the former should be copied to
+ * the latter, and 4.1.4 (a) stipulates that max_path_length
+ * should be verified to be larger than zero and decrement it.
+ *
+ * Because we're checking the certs in the reverse order, we start
+ * with verifying that proxy_path_length isn't larger than pcPLC,
+ * and copy the latter to the former if it is, and finally,
+ * increment proxy_path_length.
+ */
+ if (x->ex_pcpathlen != -1) {
+ if (proxy_path_length > x->ex_pcpathlen) {
+ ctx->error = X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED;
+ ctx->error_depth = i;
+ ctx->current_cert = x;
+ ok = cb(0, ctx);
+ if (!ok)
+ goto end;
+ }
+ proxy_path_length = x->ex_pcpathlen;
}
proxy_path_length++;
must_be_ca = 0;
@@ -644,6 +676,81 @@ static int check_name_constraints(X509_STORE_CTX *ctx)
/* Ignore self issued certs unless last in chain */
if (i && (x->ex_flags & EXFLAG_SI))
continue;
+
+ /*
+ * Proxy certificates policy has an extra constraint, where the
+ * certificate subject MUST be the issuer with a single CN entry
+ * added.
+ * (RFC 3820: 3.4, 4.1.3 (a)(4))
+ */
+ if (x->ex_flags & EXFLAG_PROXY) {
+ X509_NAME *tmpsubject = X509_get_subject_name(x);
+ X509_NAME *tmpissuer = X509_get_issuer_name(x);
+ X509_NAME_ENTRY *tmpentry = NULL;
+ int last_object_nid = 0;
+ int err = X509_V_OK;
+ int last_object_loc = X509_NAME_entry_count(tmpsubject) - 1;
+
+ /* Check that there are at least two RDNs */
+ if (last_object_loc < 1) {
+ err = X509_V_ERR_PROXY_SUBJECT_NAME_VIOLATION;
+ goto proxy_name_done;
+ }
+
+ /*
+ * Check that there is exactly one more RDN in subject as
+ * there is in issuer.
+ */
+ if (X509_NAME_entry_count(tmpsubject)
+ != X509_NAME_entry_count(tmpissuer) + 1) {
+ err = X509_V_ERR_PROXY_SUBJECT_NAME_VIOLATION;
+ goto proxy_name_done;
+ }
+
+ /*
+ * Check that the last subject component isn't part of a
+ * multivalued RDN
+ */
+ if (X509_NAME_get_entry(tmpsubject, last_object_loc)->set
+ == X509_NAME_get_entry(tmpsubject, last_object_loc - 1)->set) {
+ err = X509_V_ERR_PROXY_SUBJECT_NAME_VIOLATION;
+ goto proxy_name_done;
+ }
+
+ /*
+ * Check that the last subject RDN is a commonName, and that
+ * all the previous RDNs match the issuer exactly
+ */
+ tmpsubject = X509_NAME_dup(tmpsubject);
+ if (tmpsubject == NULL) {
+ X509err(X509_F_CHECK_NAME_CONSTRAINTS, ERR_R_MALLOC_FAILURE);
+ ctx->error = X509_V_ERR_OUT_OF_MEM;
+ return 0;
+ }
+
+ tmpentry =
+ X509_NAME_delete_entry(tmpsubject, last_object_loc);
+ last_object_nid =
+ OBJ_obj2nid(X509_NAME_ENTRY_get_object(tmpentry));
+
+ if (last_object_nid != NID_commonName
+ || X509_NAME_cmp(tmpsubject, tmpissuer) != 0) {
+ err = X509_V_ERR_PROXY_SUBJECT_NAME_VIOLATION;
+ }
+
+ X509_NAME_ENTRY_free(tmpentry);
+ X509_NAME_free(tmpsubject);
+
+ proxy_name_done:
+ if (err != X509_V_OK) {
+ ctx->error = err;
+ ctx->error_depth = i;
+ ctx->current_cert = x;
+ if (!ctx->verify_cb(0, ctx))
+ return 0;
+ }
+ }
+
/*
* Check against constraints for all certificates higher in chain
* including trust anchor. Trust anchor not strictly speaking needed
@@ -654,12 +761,19 @@ static int check_name_constraints(X509_STORE_CTX *ctx)
NAME_CONSTRAINTS *nc = sk_X509_value(ctx->chain, j)->nc;
if (nc) {
rv = NAME_CONSTRAINTS_check(x, nc);
- if (rv != X509_V_OK) {
+ switch (rv) {
+ case X509_V_OK:
+ continue;
+ case X509_V_ERR_OUT_OF_MEM:
+ ctx->error = rv;
+ return 0;
+ default:
ctx->error = rv;
ctx->error_depth = i;
ctx->current_cert = x;
if (!ctx->verify_cb(0, ctx))
return 0;
+ break;
}
}
}
@@ -1469,6 +1583,7 @@ static int check_policy(X509_STORE_CTX *ctx)
ctx->param->policies, ctx->param->flags);
if (ret == 0) {
X509err(X509_F_CHECK_POLICY, ERR_R_MALLOC_FAILURE);
+ ctx->error = X509_V_ERR_OUT_OF_MEM;
return 0;
}
/* Invalid or inconsistent extensions */
@@ -1497,7 +1612,12 @@ static int check_policy(X509_STORE_CTX *ctx)
if (ctx->param->flags & X509_V_FLAG_NOTIFY_POLICY) {
ctx->current_cert = NULL;
- ctx->error = X509_V_OK;
+ /*
+ * Verification errors need to be "sticky", a callback may have allowed
+ * an SSL handshake to continue despite an error, and we must then
+ * remain in an error state. Therefore, we MUST NOT clear earlier
+ * verification errors by setting the error to X509_V_OK.
+ */
if (!ctx->verify_cb(2, ctx))
return 0;
}
diff --git a/crypto/x509/x509_vfy.h b/crypto/x509/x509_vfy.h
index b7d8b2472e44..31f9f7f2c41e 100644
--- a/crypto/x509/x509_vfy.h
+++ b/crypto/x509/x509_vfy.h
@@ -365,13 +365,33 @@ void X509_STORE_CTX_set_depth(X509_STORE_CTX *ctx, int depth);
# define X509_V_ERR_PERMITTED_VIOLATION 47
# define X509_V_ERR_EXCLUDED_VIOLATION 48
# define X509_V_ERR_SUBTREE_MINMAX 49
+# define X509_V_ERR_APPLICATION_VERIFICATION 50
# define X509_V_ERR_UNSUPPORTED_CONSTRAINT_TYPE 51
# define X509_V_ERR_UNSUPPORTED_CONSTRAINT_SYNTAX 52
# define X509_V_ERR_UNSUPPORTED_NAME_SYNTAX 53
# define X509_V_ERR_CRL_PATH_VALIDATION_ERROR 54
-/* The application is not happy */
-# define X509_V_ERR_APPLICATION_VERIFICATION 50
+# if 0 /* Reserved for compatibility 1.0.2 */
+/* Suite B mode algorithm violation */
+# define X509_V_ERR_SUITE_B_INVALID_VERSION 56
+# define X509_V_ERR_SUITE_B_INVALID_ALGORITHM 57
+# define X509_V_ERR_SUITE_B_INVALID_CURVE 58
+# define X509_V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM 59
+# define X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED 60
+# define X509_V_ERR_SUITE_B_CANNOT_SIGN_P_384_WITH_P_256 61
+
+/* Host, email and IP check errors */
+# define X509_V_ERR_HOSTNAME_MISMATCH 62
+# define X509_V_ERR_EMAIL_MISMATCH 63
+# define X509_V_ERR_IP_ADDRESS_MISMATCH 64
+# endif
+
+/* Caller error */
+# define X509_V_ERR_INVALID_CALL 65
+/* Issuer lookup error */
+# define X509_V_ERR_STORE_LOOKUP 66
+
+# define X509_V_ERR_PROXY_SUBJECT_NAME_VIOLATION 67
/* Certificate verify flags */
diff --git a/crypto/x509v3/v3_addr.c b/crypto/x509v3/v3_addr.c
index 94cfed050910..1290dec9bb8c 100644
--- a/crypto/x509v3/v3_addr.c
+++ b/crypto/x509v3/v3_addr.c
@@ -1211,6 +1211,11 @@ int v3_addr_subset(IPAddrBlocks *a, IPAddrBlocks *b)
/*
* Core code for RFC 3779 2.3 path validation.
+ *
+ * Returns 1 for success, 0 on error.
+ *
+ * When returning 0, ctx->error MUST be set to an appropriate value other than
+ * X509_V_OK.
*/
static int v3_addr_validate_path_internal(X509_STORE_CTX *ctx,
STACK_OF(X509) *chain,
@@ -1245,6 +1250,7 @@ static int v3_addr_validate_path_internal(X509_STORE_CTX *ctx,
if ((child = sk_IPAddressFamily_dup(ext)) == NULL) {
X509V3err(X509V3_F_V3_ADDR_VALIDATE_PATH_INTERNAL,
ERR_R_MALLOC_FAILURE);
+ ctx->error = X509_V_ERR_OUT_OF_MEM;
ret = 0;
goto done;
}
diff --git a/doc/apps/cms.pod b/doc/apps/cms.pod
index 9a24082ba2c2..25b19d5cc583 100644
--- a/doc/apps/cms.pod
+++ b/doc/apps/cms.pod
@@ -85,6 +85,9 @@ encrypt mail for the given recipient certificates. Input file is the message
to be encrypted. The output file is the encrypted mail in MIME format. The
actual CMS type is <B>EnvelopedData<B>.
+Note that no revocation check is done for the recipient cert, so if that
+key has been compromised, others may be able to decrypt the text.
+
=item B<-decrypt>
decrypt mail using the supplied certificate and private key. Expects an
diff --git a/doc/apps/smime.pod b/doc/apps/smime.pod
index 94a882385206..acc38be67442 100644
--- a/doc/apps/smime.pod
+++ b/doc/apps/smime.pod
@@ -53,6 +53,9 @@ The meaning of the other options varies according to the operation type.
encrypt mail for the given recipient certificates. Input file is the message
to be encrypted. The output file is the encrypted mail in MIME format.
+Note that no revocation check is done for the recipient cert, so if that
+key has been compromised, others may be able to decrypt the text.
+
=item B<-decrypt>
decrypt mail using the supplied certificate and private key. Expects an
diff --git a/doc/apps/verify.pod b/doc/apps/verify.pod
index 18eeee04b932..450dd7d80990 100644
--- a/doc/apps/verify.pod
+++ b/doc/apps/verify.pod
@@ -23,6 +23,7 @@ B<openssl> B<verify>
[B<-use_deltas>]
[B<-policy_print>]
[B<-no_alt_chains>]
+[B<-allow_proxy_certs>]
[B<-untrusted file>]
[B<-help>]
[B<-issuer_checks>]
@@ -117,6 +118,10 @@ be found that is trusted. With this option that behaviour is suppressed so that
only the first chain found is ever used. Using this option will force the
behaviour to match that of previous OpenSSL versions.
+=item B<-allow_proxy_certs>
+
+Allow the verification of proxy certificates.
+
=item B<-policy_print>
Print out diagnostics related to policy processing.
diff --git a/doc/crypto/X509_verify_cert.pod b/doc/crypto/X509_verify_cert.pod
index a22e44118cfc..4689e3afea4e 100644
--- a/doc/crypto/X509_verify_cert.pod
+++ b/doc/crypto/X509_verify_cert.pod
@@ -31,12 +31,13 @@ Applications rarely call this function directly but it is used by
OpenSSL internally for certificate validation, in both the S/MIME and
SSL/TLS code.
-The negative return value from X509_verify_cert() can only occur if no
-certificate is set in B<ctx> (due to a programming error); if X509_verify_cert()
-twice without reinitialising B<ctx> in between; or if a retry
-operation is requested during internal lookups (which never happens with
-standard lookup methods). It is however recommended that application check
-for <= 0 return value on error.
+A negative return value from X509_verify_cert() can occur if it is invoked
+incorrectly, such as with no certificate set in B<ctx>, or when it is called
+twice in succession without reinitialising B<ctx> for the second call.
+A negative return value can also happen due to internal resource problems or if
+a retry operation is requested during internal lookups (which never happens
+with standard lookup methods).
+Applications must check for <= 0 return value on error.
=head1 BUGS
diff --git a/doc/crypto/d2i_PrivateKey.pod b/doc/crypto/d2i_PrivateKey.pod
new file mode 100644
index 000000000000..e06ab6c5dee8
--- /dev/null
+++ b/doc/crypto/d2i_PrivateKey.pod
@@ -0,0 +1,59 @@
+=pod
+
+=head1 NAME
+
+d2i_Private_key, d2i_AutoPrivateKey, i2d_PrivateKey - decode and encode
+functions for reading and saving EVP_PKEY structures.
+
+=head1 SYNOPSIS
+
+ #include <openssl/evp.h>
+
+ EVP_PKEY *d2i_PrivateKey(int type, EVP_PKEY **a, const unsigned char **pp,
+ long length);
+ EVP_PKEY *d2i_AutoPrivateKey(EVP_PKEY **a, const unsigned char **pp,
+ long length);
+ int i2d_PrivateKey(EVP_PKEY *a, unsigned char **pp);
+
+=head1 DESCRIPTION
+
+d2i_PrivateKey() decodes a private key using algorithm B<type>. It attempts to
+use any key specific format or PKCS#8 unencrypted PrivateKeyInfo format. The
+B<type> parameter should be a public key algorithm constant such as
+B<EVP_PKEY_RSA>. An error occurs if the decoded key does not match B<type>.
+
+d2i_AutoPrivateKey() is similar to d2i_PrivateKey() except it attempts to
+automatically detect the private key format.
+
+i2d_PrivateKey() encodes B<key>. It uses a key specific format or, if none is
+defined for that key type, PKCS#8 unencrypted PrivateKeyInfo format.
+
+These functions are similar to the d2i_X509() functions, and you should refer to
+that page for a detailed description (see L<d2i_X509(3)>).
+
+=head1 NOTES
+
+All these functions use DER format and unencrypted keys. Applications wishing
+to encrypt or decrypt private keys should use other functions such as
+d2i_PKC8PrivateKey() instead.
+
+If the B<*a> is not NULL when calling d2i_PrivateKey() or d2i_AutoPrivateKey()
+(i.e. an existing structure is being reused) and the key format is PKCS#8
+then B<*a> will be freed and replaced on a successful call.
+
+=head1 RETURN VALUES
+
+d2i_PrivateKey() and d2i_AutoPrivateKey() return a valid B<EVP_KEY> structure
+or B<NULL> if an error occurs. The error code can be obtained by calling
+L<ERR_get_error(3)>.
+
+i2d_PrivateKey() returns the number of bytes successfully encoded or a
+negative value if an error occurs. The error code can be obtained by calling
+L<ERR_get_error(3)>.
+
+=head1 SEE ALSO
+
+L<crypto(3)>,
+L<d2i_PKCS8PrivateKey(3)>
+
+=cut
diff --git a/ssl/d1_both.c b/ssl/d1_both.c
index 19c3da616122..0cf1e49fd2a1 100644
--- a/ssl/d1_both.c
+++ b/ssl/d1_both.c
@@ -577,9 +577,12 @@ static int dtls1_preprocess_fragment(SSL *s, struct hm_header_st *msg_hdr,
/*
* msg_len is limited to 2^24, but is effectively checked against max
* above
+ *
+ * Make buffer slightly larger than message length as a precaution
+ * against small OOB reads e.g. CVE-2016-6306
*/
if (!BUF_MEM_grow_clean
- (s->init_buf, msg_len + DTLS1_HM_HEADER_LENGTH)) {
+ (s->init_buf, msg_len + DTLS1_HM_HEADER_LENGTH + 16)) {
SSLerr(SSL_F_DTLS1_PREPROCESS_FRAGMENT, ERR_R_BUF_LIB);
return SSL_AD_INTERNAL_ERROR;
}
@@ -614,11 +617,23 @@ static int dtls1_retrieve_buffered_fragment(SSL *s, long max, int *ok)
int al;
*ok = 0;
- item = pqueue_peek(s->d1->buffered_messages);
- if (item == NULL)
- return 0;
+ do {
+ item = pqueue_peek(s->d1->buffered_messages);
+ if (item == NULL)
+ return 0;
+
+ frag = (hm_fragment *)item->data;
+
+ if (frag->msg_header.seq < s->d1->handshake_read_seq) {
+ /* This is a stale message that has been buffered so clear it */
+ pqueue_pop(s->d1->buffered_messages);
+ dtls1_hm_fragment_free(frag);
+ pitem_free(item);
+ item = NULL;
+ frag = NULL;
+ }
+ } while (item == NULL);
- frag = (hm_fragment *)item->data;
/* Don't return if reassembly still in progress */
if (frag->reassembly != NULL)
@@ -1416,18 +1431,6 @@ dtls1_retransmit_message(SSL *s, unsigned short seq, unsigned long frag_off,
return ret;
}
-/* call this function when the buffered messages are no longer needed */
-void dtls1_clear_record_buffer(SSL *s)
-{
- pitem *item;
-
- for (item = pqueue_pop(s->d1->sent_messages);
- item != NULL; item = pqueue_pop(s->d1->sent_messages)) {
- dtls1_hm_fragment_free((hm_fragment *)item->data);
- pitem_free(item);
- }
-}
-
unsigned char *dtls1_set_message_header(SSL *s, unsigned char *p,
unsigned char mt, unsigned long len,
unsigned long frag_off,
@@ -1589,7 +1592,7 @@ int dtls1_process_heartbeat(SSL *s)
memcpy(bp, pl, payload);
bp += payload;
/* Random padding */
- if (RAND_pseudo_bytes(bp, padding) < 0) {
+ if (RAND_bytes(bp, padding) <= 0) {
OPENSSL_free(buffer);
return -1;
}
@@ -1674,11 +1677,11 @@ int dtls1_heartbeat(SSL *s)
/* Sequence number */
s2n(s->tlsext_hb_seq, p);
/* 16 random bytes */
- if (RAND_pseudo_bytes(p, 16) < 0)
+ if (RAND_bytes(p, 16) <= 0)
goto err;
p += 16;
/* Random padding */
- if (RAND_pseudo_bytes(p, padding) < 0)
+ if (RAND_bytes(p, padding) <= 0)
goto err;
ret = dtls1_write_bytes(s, TLS1_RT_HEARTBEAT, buf, 3 + payload + padding);
diff --git a/ssl/d1_clnt.c b/ssl/d1_clnt.c
index eb371a255f89..e1f167bbd3c8 100644
--- a/ssl/d1_clnt.c
+++ b/ssl/d1_clnt.c
@@ -751,6 +751,7 @@ int dtls1_connect(SSL *s)
/* done with handshaking */
s->d1->handshake_read_seq = 0;
s->d1->next_handshake_write_seq = 0;
+ dtls1_clear_received_buffer(s);
goto end;
/* break; */
diff --git a/ssl/d1_lib.c b/ssl/d1_lib.c
index 011d7b7cbe69..99984dfe0f18 100644
--- a/ssl/d1_lib.c
+++ b/ssl/d1_lib.c
@@ -144,7 +144,6 @@ int dtls1_new(SSL *s)
static void dtls1_clear_queues(SSL *s)
{
pitem *item = NULL;
- hm_fragment *frag = NULL;
DTLS1_RECORD_DATA *rdata;
while ((item = pqueue_pop(s->d1->unprocessed_rcds.q)) != NULL) {
@@ -165,28 +164,44 @@ static void dtls1_clear_queues(SSL *s)
pitem_free(item);
}
+ while ((item = pqueue_pop(s->d1->buffered_app_data.q)) != NULL) {
+ rdata = (DTLS1_RECORD_DATA *)item->data;
+ if (rdata->rbuf.buf) {
+ OPENSSL_free(rdata->rbuf.buf);
+ }
+ OPENSSL_free(item->data);
+ pitem_free(item);
+ }
+
+ dtls1_clear_received_buffer(s);
+ dtls1_clear_sent_buffer(s);
+}
+
+void dtls1_clear_received_buffer(SSL *s)
+{
+ pitem *item = NULL;
+ hm_fragment *frag = NULL;
+
while ((item = pqueue_pop(s->d1->buffered_messages)) != NULL) {
frag = (hm_fragment *)item->data;
dtls1_hm_fragment_free(frag);
pitem_free(item);
}
+}
+
+void dtls1_clear_sent_buffer(SSL *s)
+{
+ pitem *item = NULL;
+ hm_fragment *frag = NULL;
while ((item = pqueue_pop(s->d1->sent_messages)) != NULL) {
frag = (hm_fragment *)item->data;
dtls1_hm_fragment_free(frag);
pitem_free(item);
}
-
- while ((item = pqueue_pop(s->d1->buffered_app_data.q)) != NULL) {
- rdata = (DTLS1_RECORD_DATA *)item->data;
- if (rdata->rbuf.buf) {
- OPENSSL_free(rdata->rbuf.buf);
- }
- OPENSSL_free(item->data);
- pitem_free(item);
- }
}
+
void dtls1_free(SSL *s)
{
ssl3_free(s);
@@ -420,7 +435,7 @@ void dtls1_stop_timer(SSL *s)
BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT, 0,
&(s->d1->next_timeout));
/* Clear retransmission buffer */
- dtls1_clear_record_buffer(s);
+ dtls1_clear_sent_buffer(s);
}
int dtls1_check_timeout_num(SSL *s)
diff --git a/ssl/d1_pkt.c b/ssl/d1_pkt.c
index d659ed428e6d..086ee98494dc 100644
--- a/ssl/d1_pkt.c
+++ b/ssl/d1_pkt.c
@@ -194,7 +194,7 @@ static int dtls1_record_needs_buffering(SSL *s, SSL3_RECORD *rr,
#endif
static int dtls1_buffer_record(SSL *s, record_pqueue *q,
unsigned char *priority);
-static int dtls1_process_record(SSL *s);
+static int dtls1_process_record(SSL *s, DTLS1_BITMAP *bitmap);
/* copy buffered record into SSL structure */
static int dtls1_copy_record(SSL *s, pitem *item)
@@ -319,21 +319,70 @@ static int dtls1_retrieve_buffered_record(SSL *s, record_pqueue *queue)
static int dtls1_process_buffered_records(SSL *s)
{
pitem *item;
+ SSL3_BUFFER *rb;
+ SSL3_RECORD *rr;
+ DTLS1_BITMAP *bitmap;
+ unsigned int is_next_epoch;
+ int replayok = 1;
item = pqueue_peek(s->d1->unprocessed_rcds.q);
if (item) {
/* Check if epoch is current. */
if (s->d1->unprocessed_rcds.epoch != s->d1->r_epoch)
- return (1); /* Nothing to do. */
+ return 1; /* Nothing to do. */
+
+ rr = &s->s3->rrec;
+ rb = &s->s3->rbuf;
+
+ if (rb->left > 0) {
+ /*
+ * We've still got data from the current packet to read. There could
+ * be a record from the new epoch in it - so don't overwrite it
+ * with the unprocessed records yet (we'll do it when we've
+ * finished reading the current packet).
+ */
+ return 1;
+ }
+
/* Process all the records. */
while (pqueue_peek(s->d1->unprocessed_rcds.q)) {
dtls1_get_unprocessed_record(s);
- if (!dtls1_process_record(s))
- return (0);
+ bitmap = dtls1_get_bitmap(s, rr, &is_next_epoch);
+ if (bitmap == NULL) {
+ /*
+ * Should not happen. This will only ever be NULL when the
+ * current record is from a different epoch. But that cannot
+ * be the case because we already checked the epoch above
+ */
+ SSLerr(SSL_F_DTLS1_PROCESS_BUFFERED_RECORDS,
+ ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+#ifndef OPENSSL_NO_SCTP
+ /* Only do replay check if no SCTP bio */
+ if (!BIO_dgram_is_sctp(SSL_get_rbio(s)))
+#endif
+ {
+ /*
+ * Check whether this is a repeat, or aged record. We did this
+ * check once already when we first received the record - but
+ * we might have updated the window since then due to
+ * records we subsequently processed.
+ */
+ replayok = dtls1_record_replay_check(s, bitmap);
+ }
+
+ if (!replayok || !dtls1_process_record(s, bitmap)) {
+ /* dump this record */
+ rr->length = 0;
+ s->packet_length = 0;
+ continue;
+ }
+
if (dtls1_buffer_record(s, &(s->d1->processed_rcds),
s->s3->rrec.seq_num) < 0)
- return -1;
+ return 0;
}
}
@@ -344,7 +393,7 @@ static int dtls1_process_buffered_records(SSL *s)
s->d1->processed_rcds.epoch = s->d1->r_epoch;
s->d1->unprocessed_rcds.epoch = s->d1->r_epoch + 1;
- return (1);
+ return 1;
}
#if 0
@@ -391,7 +440,7 @@ static int dtls1_get_buffered_record(SSL *s)
#endif
-static int dtls1_process_record(SSL *s)
+static int dtls1_process_record(SSL *s, DTLS1_BITMAP *bitmap)
{
int i, al;
int enc_err;
@@ -551,6 +600,10 @@ static int dtls1_process_record(SSL *s)
/* we have pulled in a full packet so zero things */
s->packet_length = 0;
+
+ /* Mark receipt of record. */
+ dtls1_record_bitmap_update(s, bitmap);
+
return (1);
f_err:
@@ -581,11 +634,12 @@ int dtls1_get_record(SSL *s)
rr = &(s->s3->rrec);
+ again:
/*
* The epoch may have changed. If so, process all the pending records.
* This is a non-blocking operation.
*/
- if (dtls1_process_buffered_records(s) < 0)
+ if (!dtls1_process_buffered_records(s))
return -1;
/* if we're renegotiating, then there may be buffered records */
@@ -593,7 +647,6 @@ int dtls1_get_record(SSL *s)
return 1;
/* get something from the wire */
- again:
/* check if we have the header */
if ((s->rstate != SSL_ST_READ_BODY) ||
(s->packet_length < DTLS1_RT_HEADER_LENGTH)) {
@@ -717,20 +770,17 @@ int dtls1_get_record(SSL *s)
if (dtls1_buffer_record
(s, &(s->d1->unprocessed_rcds), rr->seq_num) < 0)
return -1;
- /* Mark receipt of record. */
- dtls1_record_bitmap_update(s, bitmap);
}
rr->length = 0;
s->packet_length = 0;
goto again;
}
- if (!dtls1_process_record(s)) {
+ if (!dtls1_process_record(s, bitmap)) {
rr->length = 0;
s->packet_length = 0; /* dump this record */
goto again; /* get another record */
}
- dtls1_record_bitmap_update(s, bitmap); /* Mark receipt of record. */
return (1);
@@ -1627,7 +1677,8 @@ int do_dtls1_write(SSL *s, int type, const unsigned char *buf,
/* ssl3_enc can only have an error on read */
if (bs) { /* bs != 0 in case of CBC */
- RAND_pseudo_bytes(p, bs);
+ if (RAND_bytes(p, bs) <= 0)
+ goto err;
/*
* master IV and last CBC residue stand for the rest of randomness
*/
@@ -1814,8 +1865,13 @@ static DTLS1_BITMAP *dtls1_get_bitmap(SSL *s, SSL3_RECORD *rr,
if (rr->epoch == s->d1->r_epoch)
return &s->d1->bitmap;
- /* Only HM and ALERT messages can be from the next epoch */
+ /*
+ * Only HM and ALERT messages can be from the next epoch and only if we
+ * have already processed all of the unprocessed records from the last
+ * epoch
+ */
else if (rr->epoch == (unsigned long)(s->d1->r_epoch + 1) &&
+ s->d1->unprocessed_rcds.epoch != s->d1->r_epoch &&
(rr->type == SSL3_RT_HANDSHAKE || rr->type == SSL3_RT_ALERT)) {
*is_next_epoch = 1;
return &s->d1->next_bitmap;
@@ -1894,6 +1950,12 @@ void dtls1_reset_seq_numbers(SSL *s, int rw)
s->d1->r_epoch++;
memcpy(&(s->d1->bitmap), &(s->d1->next_bitmap), sizeof(DTLS1_BITMAP));
memset(&(s->d1->next_bitmap), 0x00, sizeof(DTLS1_BITMAP));
+
+ /*
+ * We must not use any buffered messages received from the previous
+ * epoch
+ */
+ dtls1_clear_received_buffer(s);
} else {
seq = s->s3->write_sequence;
memcpy(s->d1->last_write_sequence, seq,
diff --git a/ssl/d1_srvr.c b/ssl/d1_srvr.c
index f01b8a693f4e..bc30433afa2d 100644
--- a/ssl/d1_srvr.c
+++ b/ssl/d1_srvr.c
@@ -295,7 +295,7 @@ int dtls1_accept(SSL *s)
case SSL3_ST_SW_HELLO_REQ_B:
s->shutdown = 0;
- dtls1_clear_record_buffer(s);
+ dtls1_clear_sent_buffer(s);
dtls1_start_timer(s);
ret = dtls1_send_hello_request(s);
if (ret <= 0)
@@ -866,6 +866,7 @@ int dtls1_accept(SSL *s)
/* next message is server hello */
s->d1->handshake_write_seq = 0;
s->d1->next_handshake_write_seq = 0;
+ dtls1_clear_received_buffer(s);
goto end;
/* break; */
@@ -1701,7 +1702,10 @@ int dtls1_send_newsession_ticket(SSL *s)
return -1;
}
} else {
- RAND_pseudo_bytes(iv, 16);
+ if (RAND_bytes(iv, 16) <= 0) {
+ OPENSSL_free(senc);
+ return -1;
+ }
EVP_EncryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL,
tctx->tlsext_tick_aes_key, iv);
HMAC_Init_ex(&hctx, tctx->tlsext_tick_hmac_key, 16,
diff --git a/ssl/s23_clnt.c b/ssl/s23_clnt.c
index 2b2855dee4a9..e93baed43a22 100644
--- a/ssl/s23_clnt.c
+++ b/ssl/s23_clnt.c
@@ -290,9 +290,9 @@ int ssl_fill_hello_random(SSL *s, int server, unsigned char *result, int len)
unsigned long Time = (unsigned long)time(NULL);
unsigned char *p = result;
l2n(Time, p);
- return RAND_pseudo_bytes(p, len - 4);
+ return RAND_bytes(p, len - 4);
} else
- return RAND_pseudo_bytes(result, len);
+ return RAND_bytes(result, len);
}
static int ssl23_client_hello(SSL *s)
@@ -460,8 +460,8 @@ static int ssl23_client_hello(SSL *s)
i = ch_len;
s2n(i, d);
memset(&(s->s3->client_random[0]), 0, SSL3_RANDOM_SIZE);
- if (RAND_pseudo_bytes
- (&(s->s3->client_random[SSL3_RANDOM_SIZE - i]), i) <= 0)
+ if (RAND_bytes (&(s->s3->client_random[SSL3_RANDOM_SIZE - i]), i)
+ <= 0)
return -1;
memcpy(p, &(s->s3->client_random[SSL3_RANDOM_SIZE - i]), i);
diff --git a/ssl/s2_clnt.c b/ssl/s2_clnt.c
index b23b083153fb..736ba1f3ffac 100644
--- a/ssl/s2_clnt.c
+++ b/ssl/s2_clnt.c
@@ -581,7 +581,7 @@ static int client_hello(SSL *s)
/*
* challenge id data
*/
- if (RAND_pseudo_bytes(s->s2->challenge, SSL2_CHALLENGE_LENGTH) <= 0)
+ if (RAND_bytes(s->s2->challenge, SSL2_CHALLENGE_LENGTH) <= 0)
return -1;
memcpy(d, s->s2->challenge, SSL2_CHALLENGE_LENGTH);
d += SSL2_CHALLENGE_LENGTH;
@@ -629,7 +629,7 @@ static int client_master_key(SSL *s)
return -1;
}
if (i > 0)
- if (RAND_pseudo_bytes(sess->key_arg, i) <= 0)
+ if (RAND_bytes(sess->key_arg, i) <= 0)
return -1;
/* make a master key */
diff --git a/ssl/s2_srvr.c b/ssl/s2_srvr.c
index 07e9df82820a..d3b243c27e02 100644
--- a/ssl/s2_srvr.c
+++ b/ssl/s2_srvr.c
@@ -526,11 +526,8 @@ static int get_client_master_key(SSL *s)
* 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)
+ if (RAND_bytes(rand_premaster_secret,
+ (int)num_encrypted_key_bytes) <= 0)
return 0;
i = ssl_rsa_private_decrypt(s->cert, s->s2->tmp.enc,
@@ -822,8 +819,7 @@ static int server_hello(SSL *s)
/* make and send conn_id */
s2n(SSL2_CONNECTION_ID_LENGTH, p); /* add conn_id length */
s->s2->conn_id_length = SSL2_CONNECTION_ID_LENGTH;
- if (RAND_pseudo_bytes(s->s2->conn_id, (int)s->s2->conn_id_length) <=
- 0)
+ if (RAND_bytes(s->s2->conn_id, (int)s->s2->conn_id_length) <= 0)
return -1;
memcpy(d, s->s2->conn_id, SSL2_CONNECTION_ID_LENGTH);
d += SSL2_CONNECTION_ID_LENGTH;
@@ -962,7 +958,7 @@ static int request_certificate(SSL *s)
p = (unsigned char *)s->init_buf->data;
*(p++) = SSL2_MT_REQUEST_CERTIFICATE;
*(p++) = SSL2_AT_MD5_WITH_RSA_ENCRYPTION;
- if (RAND_pseudo_bytes(ccd, SSL2_MIN_CERT_CHALLENGE_LENGTH) <= 0)
+ if (RAND_bytes(ccd, SSL2_MIN_CERT_CHALLENGE_LENGTH) <= 0)
return -1;
memcpy(p, ccd, SSL2_MIN_CERT_CHALLENGE_LENGTH);
diff --git a/ssl/s3_both.c b/ssl/s3_both.c
index 107b460f27b6..d798d83cb77b 100644
--- a/ssl/s3_both.c
+++ b/ssl/s3_both.c
@@ -427,21 +427,22 @@ long ssl3_get_message(SSL *s, int st1, int stn, int mt, long max, int *ok)
}
*ok = 1;
s->state = stn;
- s->init_msg = s->init_buf->data + 4;
+ s->init_msg = s->init_buf->data + SSL3_HM_HEADER_LENGTH;
s->init_num = (int)s->s3->tmp.message_size;
return s->init_num;
}
p = (unsigned char *)s->init_buf->data;
- if (s->state == st1) { /* s->init_num < 4 */
+ if (s->state == st1) { /* s->init_num < SSL3_HM_HEADER_LENGTH */
int skip_message;
do {
- while (s->init_num < 4) {
+ while (s->init_num < SSL3_HM_HEADER_LENGTH) {
i = s->method->ssl_read_bytes(s, SSL3_RT_HANDSHAKE,
&p[s->init_num],
- 4 - s->init_num, 0);
+ SSL3_HM_HEADER_LENGTH -
+ s->init_num, 0);
if (i <= 0) {
s->rwstate = SSL_READING;
*ok = 0;
@@ -465,12 +466,13 @@ long ssl3_get_message(SSL *s, int st1, int stn, int mt, long max, int *ok)
if (s->msg_callback)
s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE,
- p, 4, s, s->msg_callback_arg);
+ p, SSL3_HM_HEADER_LENGTH, s,
+ s->msg_callback_arg);
}
}
while (skip_message);
- /* s->init_num == 4 */
+ /* s->init_num == SSL3_HM_HEADER_LENGTH */
if ((mt >= 0) && (*p != mt)) {
al = SSL_AD_UNEXPECTED_MESSAGE;
@@ -497,19 +499,20 @@ long ssl3_get_message(SSL *s, int st1, int stn, int mt, long max, int *ok)
SSLerr(SSL_F_SSL3_GET_MESSAGE, SSL_R_EXCESSIVE_MESSAGE_SIZE);
goto f_err;
}
- if (l > (INT_MAX - 4)) { /* BUF_MEM_grow takes an 'int' parameter */
- al = SSL_AD_ILLEGAL_PARAMETER;
- SSLerr(SSL_F_SSL3_GET_MESSAGE, SSL_R_EXCESSIVE_MESSAGE_SIZE);
- goto f_err;
- }
- if (l && !BUF_MEM_grow_clean(s->init_buf, (int)l + 4)) {
+ /*
+ * Make buffer slightly larger than message length as a precaution
+ * against small OOB reads e.g. CVE-2016-6306
+ */
+ if (l
+ && !BUF_MEM_grow_clean(s->init_buf,
+ (int)l + SSL3_HM_HEADER_LENGTH + 16)) {
SSLerr(SSL_F_SSL3_GET_MESSAGE, ERR_R_BUF_LIB);
goto err;
}
s->s3->tmp.message_size = l;
s->state = stn;
- s->init_msg = s->init_buf->data + 4;
+ s->init_msg = s->init_buf->data + SSL3_HM_HEADER_LENGTH;
s->init_num = 0;
}
@@ -538,10 +541,12 @@ long ssl3_get_message(SSL *s, int st1, int stn, int mt, long max, int *ok)
#endif
/* Feed this message into MAC computation. */
- ssl3_finish_mac(s, (unsigned char *)s->init_buf->data, s->init_num + 4);
+ ssl3_finish_mac(s, (unsigned char *)s->init_buf->data,
+ s->init_num + SSL3_HM_HEADER_LENGTH);
if (s->msg_callback)
s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE, s->init_buf->data,
- (size_t)s->init_num + 4, s, s->msg_callback_arg);
+ (size_t)s->init_num + SSL3_HM_HEADER_LENGTH, s,
+ s->msg_callback_arg);
*ok = 1;
return s->init_num;
f_err:
@@ -619,7 +624,10 @@ int ssl_verify_alarm_type(long type)
case X509_V_ERR_CERT_REVOKED:
al = SSL_AD_CERTIFICATE_REVOKED;
break;
+ case X509_V_ERR_UNSPECIFIED:
case X509_V_ERR_OUT_OF_MEM:
+ case X509_V_ERR_INVALID_CALL:
+ case X509_V_ERR_STORE_LOOKUP:
al = SSL_AD_INTERNAL_ERROR;
break;
case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
diff --git a/ssl/s3_clnt.c b/ssl/s3_clnt.c
index 9e5875f1f9ba..f033a2bbf0d8 100644
--- a/ssl/s3_clnt.c
+++ b/ssl/s3_clnt.c
@@ -1143,6 +1143,12 @@ int ssl3_get_server_certificate(SSL *s)
goto f_err;
}
for (nc = 0; nc < llen;) {
+ if (nc + 3 > llen) {
+ al = SSL_AD_DECODE_ERROR;
+ SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE,
+ SSL_R_CERT_LENGTH_MISMATCH);
+ goto f_err;
+ }
n2l3(p, l);
if ((l + nc + 3) > llen) {
al = SSL_AD_DECODE_ERROR;
@@ -2072,6 +2078,11 @@ int ssl3_get_certificate_request(SSL *s)
}
for (nc = 0; nc < llen;) {
+ if (nc + 2 > llen) {
+ ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
+ SSLerr(SSL_F_SSL3_GET_CERTIFICATE_REQUEST, SSL_R_CA_DN_TOO_LONG);
+ goto err;
+ }
n2s(p, l);
if ((l + nc + 2) > llen) {
if ((s->options & SSL_OP_NETSCAPE_CA_DN_BUG))
@@ -2868,19 +2879,6 @@ int ssl3_send_client_key_exchange(SSL *s)
goto err;
}
/*
- * If we have client certificate, use its secret as peer key
- */
- if (s->s3->tmp.cert_req && s->cert->key->privatekey) {
- if (EVP_PKEY_derive_set_peer
- (pkey_ctx, s->cert->key->privatekey) <= 0) {
- /*
- * If there was an error - just ignore it. Ephemeral key
- * * would be used
- */
- ERR_clear_error();
- }
- }
- /*
* Compute shared IV and store it in algorithm-specific context
* data
*/
@@ -2926,12 +2924,6 @@ int ssl3_send_client_key_exchange(SSL *s)
n = msglen + 2;
}
memcpy(p, tmp, msglen);
- /* 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) {
- /* Set flag "skip certificate verify" */
- s->s3->flags |= TLS1_FLAGS_SKIP_CERT_VERIFY;
- }
EVP_PKEY_CTX_free(pkey_ctx);
s->session->master_key_length =
s->method->ssl3_enc->generate_master_secret(s,
diff --git a/ssl/s3_lib.c b/ssl/s3_lib.c
index 35d6587da951..6b1822d8f681 100644
--- a/ssl/s3_lib.c
+++ b/ssl/s3_lib.c
@@ -334,7 +334,7 @@ OPENSSL_GLOBAL SSL_CIPHER ssl3_ciphers[] = {
SSL_3DES,
SSL_SHA1,
SSL_SSLV3,
- SSL_NOT_EXP | SSL_HIGH | SSL_FIPS,
+ SSL_NOT_EXP | SSL_MEDIUM | SSL_FIPS,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
112,
168,
@@ -387,7 +387,7 @@ OPENSSL_GLOBAL SSL_CIPHER ssl3_ciphers[] = {
SSL_3DES,
SSL_SHA1,
SSL_SSLV3,
- SSL_NOT_EXP | SSL_HIGH | SSL_FIPS,
+ SSL_NOT_EXP | SSL_MEDIUM | SSL_FIPS,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
112,
168,
@@ -439,7 +439,7 @@ OPENSSL_GLOBAL SSL_CIPHER ssl3_ciphers[] = {
SSL_3DES,
SSL_SHA1,
SSL_SSLV3,
- SSL_NOT_EXP | SSL_HIGH | SSL_FIPS,
+ SSL_NOT_EXP | SSL_MEDIUM | SSL_FIPS,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
112,
168,
@@ -492,7 +492,7 @@ OPENSSL_GLOBAL SSL_CIPHER ssl3_ciphers[] = {
SSL_3DES,
SSL_SHA1,
SSL_SSLV3,
- SSL_NOT_EXP | SSL_HIGH | SSL_FIPS,
+ SSL_NOT_EXP | SSL_MEDIUM | SSL_FIPS,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
112,
168,
@@ -544,7 +544,7 @@ OPENSSL_GLOBAL SSL_CIPHER ssl3_ciphers[] = {
SSL_3DES,
SSL_SHA1,
SSL_SSLV3,
- SSL_NOT_EXP | SSL_HIGH | SSL_FIPS,
+ SSL_NOT_EXP | SSL_MEDIUM | SSL_FIPS,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
112,
168,
@@ -630,7 +630,7 @@ OPENSSL_GLOBAL SSL_CIPHER ssl3_ciphers[] = {
SSL_3DES,
SSL_SHA1,
SSL_SSLV3,
- SSL_NOT_DEFAULT | SSL_NOT_EXP | SSL_HIGH | SSL_FIPS,
+ SSL_NOT_DEFAULT | SSL_NOT_EXP | SSL_MEDIUM | SSL_FIPS,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
112,
168,
@@ -717,7 +717,7 @@ OPENSSL_GLOBAL SSL_CIPHER ssl3_ciphers[] = {
SSL_3DES,
SSL_SHA1,
SSL_SSLV3,
- SSL_NOT_EXP | SSL_HIGH | SSL_FIPS,
+ SSL_NOT_EXP | SSL_MEDIUM | SSL_FIPS,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
112,
168,
@@ -783,7 +783,7 @@ OPENSSL_GLOBAL SSL_CIPHER ssl3_ciphers[] = {
SSL_3DES,
SSL_MD5,
SSL_SSLV3,
- SSL_NOT_EXP | SSL_HIGH,
+ SSL_NOT_EXP | SSL_MEDIUM,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
112,
168,
@@ -1733,7 +1733,7 @@ OPENSSL_GLOBAL SSL_CIPHER ssl3_ciphers[] = {
SSL_3DES,
SSL_SHA1,
SSL_TLSV1,
- SSL_NOT_EXP | SSL_HIGH | SSL_FIPS,
+ SSL_NOT_EXP | SSL_MEDIUM | SSL_FIPS,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
112,
168,
@@ -2110,7 +2110,7 @@ OPENSSL_GLOBAL SSL_CIPHER ssl3_ciphers[] = {
SSL_3DES,
SSL_SHA1,
SSL_TLSV1,
- SSL_NOT_EXP | SSL_HIGH | SSL_FIPS,
+ SSL_NOT_EXP | SSL_MEDIUM | SSL_FIPS,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
112,
168,
@@ -2190,7 +2190,7 @@ OPENSSL_GLOBAL SSL_CIPHER ssl3_ciphers[] = {
SSL_3DES,
SSL_SHA1,
SSL_TLSV1,
- SSL_NOT_EXP | SSL_HIGH | SSL_FIPS,
+ SSL_NOT_EXP | SSL_MEDIUM | SSL_FIPS,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
112,
168,
@@ -2270,7 +2270,7 @@ OPENSSL_GLOBAL SSL_CIPHER ssl3_ciphers[] = {
SSL_3DES,
SSL_SHA1,
SSL_TLSV1,
- SSL_NOT_EXP | SSL_HIGH | SSL_FIPS,
+ SSL_NOT_EXP | SSL_MEDIUM | SSL_FIPS,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
112,
168,
@@ -2350,7 +2350,7 @@ OPENSSL_GLOBAL SSL_CIPHER ssl3_ciphers[] = {
SSL_3DES,
SSL_SHA1,
SSL_TLSV1,
- SSL_NOT_EXP | SSL_HIGH | SSL_FIPS,
+ SSL_NOT_EXP | SSL_MEDIUM | SSL_FIPS,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
112,
168,
@@ -2430,7 +2430,7 @@ OPENSSL_GLOBAL SSL_CIPHER ssl3_ciphers[] = {
SSL_3DES,
SSL_SHA1,
SSL_TLSV1,
- SSL_NOT_DEFAULT | SSL_NOT_EXP | SSL_HIGH | SSL_FIPS,
+ SSL_NOT_DEFAULT | SSL_NOT_EXP | SSL_MEDIUM | SSL_FIPS,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
112,
168,
@@ -2480,7 +2480,7 @@ OPENSSL_GLOBAL SSL_CIPHER ssl3_ciphers[] = {
SSL_3DES,
SSL_SHA1,
SSL_TLSV1,
- SSL_NOT_EXP | SSL_HIGH,
+ SSL_NOT_EXP | SSL_MEDIUM,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
112,
168,
@@ -2496,7 +2496,7 @@ OPENSSL_GLOBAL SSL_CIPHER ssl3_ciphers[] = {
SSL_3DES,
SSL_SHA1,
SSL_TLSV1,
- SSL_NOT_EXP | SSL_HIGH,
+ SSL_NOT_EXP | SSL_MEDIUM,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
112,
168,
@@ -2512,7 +2512,7 @@ OPENSSL_GLOBAL SSL_CIPHER ssl3_ciphers[] = {
SSL_3DES,
SSL_SHA1,
SSL_TLSV1,
- SSL_NOT_EXP | SSL_HIGH,
+ SSL_NOT_EXP | SSL_MEDIUM,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
112,
168,
diff --git a/ssl/s3_srvr.c b/ssl/s3_srvr.c
index 04cf93a0f7c6..4f1a2e9aba80 100644
--- a/ssl/s3_srvr.c
+++ b/ssl/s3_srvr.c
@@ -1040,7 +1040,7 @@ int ssl3_get_client_hello(SSL *s)
session_length = *(p + SSL3_RANDOM_SIZE);
- if (p + SSL3_RANDOM_SIZE + session_length + 1 >= d + n) {
+ if (SSL3_RANDOM_SIZE + session_length + 1 >= (d + n) - p) {
al = SSL_AD_DECODE_ERROR;
SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_TOO_SHORT);
goto f_err;
@@ -1058,7 +1058,7 @@ int ssl3_get_client_hello(SSL *s)
/* get the session-id */
j = *(p++);
- if (p + j > d + n) {
+ if ((d + n) - p < j) {
al = SSL_AD_DECODE_ERROR;
SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_TOO_SHORT);
goto f_err;
@@ -1114,14 +1114,14 @@ int ssl3_get_client_hello(SSL *s)
if (s->version == DTLS1_VERSION || s->version == DTLS1_BAD_VER) {
/* cookie stuff */
- if (p + 1 > d + n) {
+ if ((d + n) - p < 1) {
al = SSL_AD_DECODE_ERROR;
SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_TOO_SHORT);
goto f_err;
}
cookie_len = *(p++);
- if (p + cookie_len > d + n) {
+ if ((d + n ) - p < cookie_len) {
al = SSL_AD_DECODE_ERROR;
SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_TOO_SHORT);
goto f_err;
@@ -1166,7 +1166,7 @@ int ssl3_get_client_hello(SSL *s)
p += cookie_len;
}
- if (p + 2 > d + n) {
+ if ((d + n ) - p < 2) {
al = SSL_AD_DECODE_ERROR;
SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_TOO_SHORT);
goto f_err;
@@ -1180,7 +1180,7 @@ int ssl3_get_client_hello(SSL *s)
}
/* i bytes of cipher data + 1 byte for compression length later */
- if ((p + i + 1) > (d + n)) {
+ if ((d + n) - p < i + 1) {
/* not enough data */
al = SSL_AD_DECODE_ERROR;
SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_MISMATCH);
@@ -1246,7 +1246,7 @@ int ssl3_get_client_hello(SSL *s)
/* compression */
i = *(p++);
- if ((p + i) > (d + n)) {
+ if ((d + n) - p < i) {
/* not enough data */
al = SSL_AD_DECODE_ERROR;
SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_MISMATCH);
@@ -2279,11 +2279,8 @@ int ssl3_get_client_key_exchange(SSL *s)
* 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,
- sizeof(rand_premaster_secret)) <= 0)
+ if (RAND_bytes(rand_premaster_secret,
+ sizeof(rand_premaster_secret)) <= 0)
goto err;
decrypt_len =
RSA_private_decrypt((int)n, p, p, rsa, RSA_PKCS1_PADDING);
@@ -3237,6 +3234,12 @@ int ssl3_get_client_certificate(SSL *s)
goto f_err;
}
for (nc = 0; nc < llen;) {
+ if (nc + 3 > llen) {
+ al = SSL_AD_DECODE_ERROR;
+ SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,
+ SSL_R_CERT_LENGTH_MISMATCH);
+ goto f_err;
+ }
n2l3(p, l);
if ((l + nc + 3) > llen) {
al = SSL_AD_DECODE_ERROR;
diff --git a/ssl/ssl.h b/ssl/ssl.h
index d6c475c27c08..114ee97c763b 100644
--- a/ssl/ssl.h
+++ b/ssl/ssl.h
@@ -2256,6 +2256,7 @@ void ERR_load_SSL_strings(void);
# define SSL_F_DTLS1_HEARTBEAT 305
# define SSL_F_DTLS1_OUTPUT_CERT_CHAIN 255
# define SSL_F_DTLS1_PREPROCESS_FRAGMENT 288
+# define SSL_F_DTLS1_PROCESS_BUFFERED_RECORDS 424
# define SSL_F_DTLS1_PROCESS_OUT_OF_SEQ_MESSAGE 256
# define SSL_F_DTLS1_PROCESS_RECORD 257
# define SSL_F_DTLS1_READ_BYTES 258
diff --git a/ssl/ssl_err.c b/ssl/ssl_err.c
index caa671a27078..ed679d117b63 100644
--- a/ssl/ssl_err.c
+++ b/ssl/ssl_err.c
@@ -1,6 +1,6 @@
/* ssl/ssl_err.c */
/* ====================================================================
- * Copyright (c) 1999-2011 The OpenSSL Project. All rights reserved.
+ * Copyright (c) 1999-2016 The OpenSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -93,6 +93,8 @@ static ERR_STRING_DATA SSL_str_functs[] = {
{ERR_FUNC(SSL_F_DTLS1_HEARTBEAT), "DTLS1_HEARTBEAT"},
{ERR_FUNC(SSL_F_DTLS1_OUTPUT_CERT_CHAIN), "DTLS1_OUTPUT_CERT_CHAIN"},
{ERR_FUNC(SSL_F_DTLS1_PREPROCESS_FRAGMENT), "DTLS1_PREPROCESS_FRAGMENT"},
+ {ERR_FUNC(SSL_F_DTLS1_PROCESS_BUFFERED_RECORDS),
+ "DTLS1_PROCESS_BUFFERED_RECORDS"},
{ERR_FUNC(SSL_F_DTLS1_PROCESS_OUT_OF_SEQ_MESSAGE),
"DTLS1_PROCESS_OUT_OF_SEQ_MESSAGE"},
{ERR_FUNC(SSL_F_DTLS1_PROCESS_RECORD), "DTLS1_PROCESS_RECORD"},
diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c
index 33c52ac5bf03..83ef233b5072 100644
--- a/ssl/ssl_lib.c
+++ b/ssl/ssl_lib.c
@@ -1662,7 +1662,7 @@ int SSL_export_keying_material(SSL *s, unsigned char *out, size_t olen,
const unsigned char *p, size_t plen,
int use_context)
{
- if (s->version < TLS1_VERSION)
+ if (s->version < TLS1_VERSION && s->version != DTLS1_BAD_VER)
return -1;
return s->method->ssl3_enc->export_keying_material(s, out, olen, label,
@@ -1833,7 +1833,7 @@ SSL_CTX *SSL_CTX_new(const SSL_METHOD *meth)
ret->tlsext_servername_callback = 0;
ret->tlsext_servername_arg = NULL;
/* Setup RFC4507 ticket keys */
- if ((RAND_pseudo_bytes(ret->tlsext_tick_key_name, 16) <= 0)
+ if ((RAND_bytes(ret->tlsext_tick_key_name, 16) <= 0)
|| (RAND_bytes(ret->tlsext_tick_hmac_key, 16) <= 0)
|| (RAND_bytes(ret->tlsext_tick_aes_key, 16) <= 0))
ret->options |= SSL_OP_NO_TICKET;
diff --git a/ssl/ssl_locl.h b/ssl/ssl_locl.h
index d57b902fabbf..7b1fd1f3b199 100644
--- a/ssl/ssl_locl.h
+++ b/ssl/ssl_locl.h
@@ -1026,7 +1026,8 @@ int dtls1_retransmit_message(SSL *s, unsigned short seq,
unsigned long frag_off, int *found);
int dtls1_get_queue_priority(unsigned short seq, int is_ccs);
int dtls1_retransmit_buffered_messages(SSL *s);
-void dtls1_clear_record_buffer(SSL *s);
+void dtls1_clear_received_buffer(SSL *s);
+void dtls1_clear_sent_buffer(SSL *s);
void dtls1_get_message_header(unsigned char *data,
struct hm_header_st *msg_hdr);
void dtls1_get_ccs_header(unsigned char *data, struct ccs_header_st *ccs_hdr);
diff --git a/ssl/ssl_sess.c b/ssl/ssl_sess.c
index 48fc4511f1fe..093b534bf98a 100644
--- a/ssl/ssl_sess.c
+++ b/ssl/ssl_sess.c
@@ -382,7 +382,7 @@ static int def_generate_session_id(const SSL *ssl, unsigned char *id,
{
unsigned int retry = 0;
do
- if (RAND_pseudo_bytes(id, *id_len) <= 0)
+ if (RAND_bytes(id, *id_len) <= 0)
return 0;
while (SSL_has_matching_session_id(ssl, id, *id_len) &&
(++retry < MAX_SESS_ID_ATTEMPTS)) ;
@@ -602,7 +602,7 @@ int ssl_get_prev_session(SSL *s, unsigned char *session_id, int len,
int r;
#endif
- if (session_id + len > limit) {
+ if (limit - session_id < len) {
fatal = 1;
goto err;
}
diff --git a/ssl/t1_lib.c b/ssl/t1_lib.c
index 0bdb77d49fc3..4bc13ca5ce29 100644
--- a/ssl/t1_lib.c
+++ b/ssl/t1_lib.c
@@ -942,11 +942,11 @@ static void ssl_check_for_safari(SSL *s, const unsigned char *data,
0x02, 0x03, /* SHA-1/ECDSA */
};
- if (data >= (limit - 2))
+ if (limit - data <= 2)
return;
data += 2;
- if (data > (limit - 4))
+ if (limit - data < 4)
return;
n2s(data, type);
n2s(data, size);
@@ -954,7 +954,7 @@ static void ssl_check_for_safari(SSL *s, const unsigned char *data,
if (type != TLSEXT_TYPE_server_name)
return;
- if (data + size > limit)
+ if (limit - data < size)
return;
data += size;
@@ -962,7 +962,7 @@ static void ssl_check_for_safari(SSL *s, const unsigned char *data,
const size_t len1 = sizeof(kSafariExtensionsBlock);
const size_t len2 = sizeof(kSafariTLS12ExtensionsBlock);
- if (data + len1 + len2 != limit)
+ if (limit - data != (int)(len1 + len2))
return;
if (memcmp(data, kSafariExtensionsBlock, len1) != 0)
return;
@@ -971,7 +971,7 @@ static void ssl_check_for_safari(SSL *s, const unsigned char *data,
} else {
const size_t len = sizeof(kSafariExtensionsBlock);
- if (data + len != limit)
+ if (limit - data != (int)(len))
return;
if (memcmp(data, kSafariExtensionsBlock, len) != 0)
return;
@@ -1019,19 +1019,19 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p,
if (data == limit)
goto ri_check;
- if (data > (limit - 2))
+ if (limit - data < 2)
goto err;
n2s(data, len);
- if (data + len != limit)
+ if (limit - data != len)
goto err;
- while (data <= (limit - 4)) {
+ while (limit - data >= 4) {
n2s(data, type);
n2s(data, size);
- if (data + size > (limit))
+ if (limit - data < size)
goto err;
# if 0
fprintf(stderr, "Received extension type %d size %d\n", type, size);
@@ -1284,6 +1284,23 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p,
size -= 2;
if (dsize > size)
goto err;
+
+ /*
+ * We remove any OCSP_RESPIDs from a previous handshake
+ * to prevent unbounded memory growth - CVE-2016-6304
+ */
+ sk_OCSP_RESPID_pop_free(s->tlsext_ocsp_ids,
+ OCSP_RESPID_free);
+ if (dsize > 0) {
+ s->tlsext_ocsp_ids = sk_OCSP_RESPID_new_null();
+ if (s->tlsext_ocsp_ids == NULL) {
+ *al = SSL_AD_INTERNAL_ERROR;
+ return 0;
+ }
+ } else {
+ s->tlsext_ocsp_ids = NULL;
+ }
+
while (dsize > 0) {
OCSP_RESPID *id;
int idsize;
@@ -1303,13 +1320,6 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p,
OCSP_RESPID_free(id);
goto err;
}
- if (!s->tlsext_ocsp_ids
- && !(s->tlsext_ocsp_ids =
- sk_OCSP_RESPID_new_null())) {
- OCSP_RESPID_free(id);
- *al = SSL_AD_INTERNAL_ERROR;
- return 0;
- }
if (!sk_OCSP_RESPID_push(s->tlsext_ocsp_ids, id)) {
OCSP_RESPID_free(id);
*al = SSL_AD_INTERNAL_ERROR;
@@ -1460,20 +1470,20 @@ int ssl_parse_serverhello_tlsext(SSL *s, unsigned char **p, unsigned char *d,
SSL_TLSEXT_HB_DONT_SEND_REQUESTS);
# endif
- if (data >= (d + n - 2))
+ if ((d + n) - data <= 2)
goto ri_check;
n2s(data, length);
- if (data + length != d + n) {
+ if ((d + n) - data != length) {
*al = SSL_AD_DECODE_ERROR;
return 0;
}
- while (data <= (d + n - 4)) {
+ while ((d + n) - data >= 4) {
n2s(data, type);
n2s(data, size);
- if (data + size > (d + n))
+ if ((d + n) - data < size)
goto ri_check;
if (s->tlsext_debug_cb)
@@ -2179,29 +2189,33 @@ int tls1_process_ticket(SSL *s, unsigned char *session_id, int len,
/* Skip past DTLS cookie */
if (s->version == DTLS1_VERSION || s->version == DTLS1_BAD_VER) {
i = *(p++);
- p += i;
- if (p >= limit)
+
+ if (limit - p <= i)
return -1;
+
+ p += i;
}
/* Skip past cipher list */
n2s(p, i);
- p += i;
- if (p >= limit)
+ if (limit - p <= i)
return -1;
+ p += i;
+
/* Skip past compression algorithm list */
i = *(p++);
- p += i;
- if (p > limit)
+ if (limit - p < i)
return -1;
+ p += i;
+
/* Now at start of extensions */
- if ((p + 2) >= limit)
+ if (limit - p <= 2)
return 0;
n2s(p, i);
- while ((p + 4) <= limit) {
+ while (limit - p >= 4) {
unsigned short type, size;
n2s(p, type);
n2s(p, size);
- if (p + size > limit)
+ if (limit - p < size)
return 0;
if (type == TLSEXT_TYPE_session_ticket) {
int r;
@@ -2269,9 +2283,7 @@ static int tls_decrypt_ticket(SSL *s, const unsigned char *etick,
HMAC_CTX hctx;
EVP_CIPHER_CTX ctx;
SSL_CTX *tctx = s->initial_ctx;
- /* Need at least keyname + iv + some encrypted data */
- if (eticklen < 48)
- return 2;
+
/* Initialize session ticket encryption and HMAC contexts */
HMAC_CTX_init(&hctx);
EVP_CIPHER_CTX_init(&ctx);
@@ -2305,6 +2317,13 @@ static int tls_decrypt_ticket(SSL *s, const unsigned char *etick,
if (mlen < 0) {
goto err;
}
+ /* Sanity check ticket length: must exceed keyname + IV + HMAC */
+ if (eticklen <= 16 + EVP_CIPHER_CTX_iv_length(&ctx) + mlen) {
+ HMAC_CTX_cleanup(&hctx);
+ EVP_CIPHER_CTX_cleanup(&ctx);
+ return 2;
+ }
+
eticklen -= mlen;
/* Check HMAC of encrypted ticket */
if (HMAC_Update(&hctx, etick, eticklen) <= 0
@@ -2591,7 +2610,7 @@ int tls1_process_heartbeat(SSL *s)
memcpy(bp, pl, payload);
bp += payload;
/* Random padding */
- if (RAND_pseudo_bytes(bp, padding) < 0) {
+ if (RAND_bytes(bp, padding) <= 0) {
OPENSSL_free(buffer);
return -1;
}
@@ -2677,13 +2696,13 @@ int tls1_heartbeat(SSL *s)
/* Sequence number */
s2n(s->tlsext_hb_seq, p);
/* 16 random bytes */
- if (RAND_pseudo_bytes(p, 16) < 0) {
+ if (RAND_bytes(p, 16) <= 0) {
SSLerr(SSL_F_TLS1_HEARTBEAT, ERR_R_INTERNAL_ERROR);
goto err;
}
p += 16;
/* Random padding */
- if (RAND_pseudo_bytes(p, padding) < 0) {
+ if (RAND_bytes(p, padding) <= 0) {
SSLerr(SSL_F_TLS1_HEARTBEAT, ERR_R_INTERNAL_ERROR);
goto err;
}