Index: net/third_party/nss/ssl/ssl3con.c |
=================================================================== |
--- net/third_party/nss/ssl/ssl3con.c (revision 166942) |
+++ net/third_party/nss/ssl/ssl3con.c (working copy) |
@@ -2,45 +2,10 @@ |
/* |
* SSL3 Protocol |
* |
- * ***** BEGIN LICENSE BLOCK ***** |
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1 |
- * |
- * The contents of this file are subject to the Mozilla Public License Version |
- * 1.1 (the "License"); you may not use this file except in compliance with |
- * the License. You may obtain a copy of the License at |
- * http://www.mozilla.org/MPL/ |
- * |
- * Software distributed under the License is distributed on an "AS IS" basis, |
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License |
- * for the specific language governing rights and limitations under the |
- * License. |
- * |
- * The Original Code is the Netscape security libraries. |
- * |
- * The Initial Developer of the Original Code is |
- * Netscape Communications Corporation. |
- * Portions created by the Initial Developer are Copyright (C) 1994-2000 |
- * the Initial Developer. All Rights Reserved. |
- * |
- * Contributor(s): |
- * Dr Stephen Henson <stephen.henson@gemplus.com> |
- * Dr Vipul Gupta <vipul.gupta@sun.com> and |
- * Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories |
- * |
- * Alternatively, the contents of this file may be used under the terms of |
- * either the GNU General Public License Version 2 or later (the "GPL"), or |
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), |
- * in which case the provisions of the GPL or the LGPL are applicable instead |
- * of those above. If you wish to allow use of your version of this file only |
- * under the terms of either the GPL or the LGPL, and not to allow others to |
- * use your version of this file under the terms of the MPL, indicate your |
- * decision by deleting the provisions above and replace them with the notice |
- * and other provisions required by the GPL or the LGPL. If you do not delete |
- * the provisions above, a recipient may use your version of this file under |
- * the terms of any one of the MPL, the GPL or the LGPL. |
- * |
- * ***** END LICENSE BLOCK ***** */ |
-/* $Id: ssl3con.c,v 1.173 2012/03/18 00:31:19 wtc%google.com Exp $ */ |
+ * This Source Code Form is subject to the terms of the Mozilla Public |
+ * License, v. 2.0. If a copy of the MPL was not distributed with this |
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
+/* $Id: ssl3con.c,v 1.192 2012/09/28 05:10:25 wtc%google.com Exp $ */ |
/* TODO(ekr): Implement HelloVerifyRequest on server side. OK for now. */ |
@@ -62,21 +27,15 @@ |
#include "pk11func.h" |
#include "secmod.h" |
+#ifndef NO_PKCS11_BYPASS |
#include "blapi.h" |
+#endif |
#include <stdio.h> |
#ifdef NSS_ENABLE_ZLIB |
#include "zlib.h" |
#endif |
-/* DSA_SIGNATURE_LEN is deprecated and replaced by DSA1_SIGNATURE_LEN |
- * in NSS 3.14. Provide a backup definition when compiling against an |
- * older system NSS library. |
- */ |
-#ifndef DSA1_SIGNATURE_LEN |
-#define DSA1_SIGNATURE_LEN 40 /* Bytes */ |
-#endif |
- |
#ifndef PK11_SETATTRS |
#define PK11_SETATTRS(x,id,v,l) (x)->type = (id); \ |
(x)->pValue=(v); (x)->ulValueLen = (l); |
@@ -112,8 +71,6 @@ |
#define MAX_SEND_BUF_LENGTH 32000 /* watch for 16-bit integer overflow */ |
#define MIN_SEND_BUF_LENGTH 4000 |
-#define MAX_CIPHER_SUITES 20 |
- |
/* This list of SSL3 cipher suites is sorted in descending order of |
* precedence (desirability). It only includes cipher suites we implement. |
* This table is modified by SSL3_SetPolicy(). The ordering of cipher suites |
@@ -127,14 +84,14 @@ |
#endif /* NSS_ENABLE_ECC */ |
{ TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE}, |
{ TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE}, |
- { TLS_DHE_RSA_WITH_AES_256_CBC_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE}, |
- { TLS_DHE_DSS_WITH_AES_256_CBC_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE}, |
+ { TLS_DHE_RSA_WITH_AES_256_CBC_SHA, SSL_NOT_ALLOWED, PR_TRUE,PR_FALSE}, |
+ { TLS_DHE_DSS_WITH_AES_256_CBC_SHA, SSL_NOT_ALLOWED, PR_TRUE,PR_FALSE}, |
#ifdef NSS_ENABLE_ECC |
{ TLS_ECDH_RSA_WITH_AES_256_CBC_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE}, |
{ TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE}, |
#endif /* NSS_ENABLE_ECC */ |
{ TLS_RSA_WITH_CAMELLIA_256_CBC_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE}, |
- { TLS_RSA_WITH_AES_256_CBC_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE}, |
+ { TLS_RSA_WITH_AES_256_CBC_SHA, SSL_NOT_ALLOWED, PR_TRUE,PR_FALSE}, |
#ifdef NSS_ENABLE_ECC |
{ TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE}, |
@@ -145,8 +102,8 @@ |
{ TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE}, |
{ TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE}, |
{ TLS_DHE_DSS_WITH_RC4_128_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE}, |
- { TLS_DHE_RSA_WITH_AES_128_CBC_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE}, |
- { TLS_DHE_DSS_WITH_AES_128_CBC_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE}, |
+ { TLS_DHE_RSA_WITH_AES_128_CBC_SHA, SSL_NOT_ALLOWED, PR_TRUE,PR_FALSE}, |
+ { TLS_DHE_DSS_WITH_AES_128_CBC_SHA, SSL_NOT_ALLOWED, PR_TRUE,PR_FALSE}, |
#ifdef NSS_ENABLE_ECC |
{ TLS_ECDH_RSA_WITH_RC4_128_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE}, |
{ TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE}, |
@@ -155,33 +112,33 @@ |
#endif /* NSS_ENABLE_ECC */ |
{ TLS_RSA_WITH_SEED_CBC_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE}, |
{ TLS_RSA_WITH_CAMELLIA_128_CBC_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE}, |
- { SSL_RSA_WITH_RC4_128_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE}, |
+ { SSL_RSA_WITH_RC4_128_SHA, SSL_NOT_ALLOWED, PR_TRUE,PR_FALSE}, |
{ SSL_RSA_WITH_RC4_128_MD5, SSL_NOT_ALLOWED, PR_TRUE, PR_FALSE}, |
- { TLS_RSA_WITH_AES_128_CBC_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE}, |
+ { TLS_RSA_WITH_AES_128_CBC_SHA, SSL_NOT_ALLOWED, PR_TRUE,PR_FALSE}, |
#ifdef NSS_ENABLE_ECC |
{ TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE}, |
{ TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE}, |
#endif /* NSS_ENABLE_ECC */ |
- { SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE}, |
- { SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE}, |
+ { SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_NOT_ALLOWED, PR_TRUE,PR_FALSE}, |
+ { SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA, SSL_NOT_ALLOWED, PR_TRUE,PR_FALSE}, |
#ifdef NSS_ENABLE_ECC |
{ TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE}, |
{ TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE}, |
#endif /* NSS_ENABLE_ECC */ |
- { SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA, SSL_NOT_ALLOWED, PR_TRUE, PR_FALSE}, |
+ { SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA, SSL_NOT_ALLOWED, PR_FALSE, PR_FALSE}, |
{ SSL_RSA_WITH_3DES_EDE_CBC_SHA, SSL_NOT_ALLOWED, PR_TRUE, PR_FALSE}, |
{ SSL_DHE_RSA_WITH_DES_CBC_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE}, |
{ SSL_DHE_DSS_WITH_DES_CBC_SHA, SSL_NOT_ALLOWED, PR_FALSE,PR_FALSE}, |
- { SSL_RSA_FIPS_WITH_DES_CBC_SHA, SSL_NOT_ALLOWED, PR_TRUE, PR_FALSE}, |
- { SSL_RSA_WITH_DES_CBC_SHA, SSL_NOT_ALLOWED, PR_TRUE, PR_FALSE}, |
- { TLS_RSA_EXPORT1024_WITH_RC4_56_SHA, SSL_NOT_ALLOWED, PR_TRUE, PR_FALSE}, |
- { TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA, SSL_NOT_ALLOWED, PR_TRUE, PR_FALSE}, |
+ { SSL_RSA_FIPS_WITH_DES_CBC_SHA, SSL_NOT_ALLOWED, PR_FALSE, PR_FALSE}, |
+ { SSL_RSA_WITH_DES_CBC_SHA, SSL_NOT_ALLOWED, PR_FALSE, PR_FALSE}, |
+ { TLS_RSA_EXPORT1024_WITH_RC4_56_SHA, SSL_NOT_ALLOWED, PR_FALSE, PR_FALSE}, |
+ { TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA, SSL_NOT_ALLOWED, PR_FALSE, PR_FALSE}, |
- { SSL_RSA_EXPORT_WITH_RC4_40_MD5, SSL_NOT_ALLOWED, PR_TRUE, PR_FALSE}, |
- { SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5, SSL_NOT_ALLOWED, PR_TRUE, PR_FALSE}, |
+ { SSL_RSA_EXPORT_WITH_RC4_40_MD5, SSL_NOT_ALLOWED, PR_FALSE, PR_FALSE}, |
+ { SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5, SSL_NOT_ALLOWED, PR_FALSE, PR_FALSE}, |
#ifdef NSS_ENABLE_ECC |
{ TLS_ECDHE_ECDSA_WITH_NULL_SHA, SSL_NOT_ALLOWED, PR_FALSE, PR_FALSE}, |
@@ -333,7 +290,6 @@ |
cipher_3des, mac_sha, kea_dhe_rsa}, |
#if 0 |
{SSL_DH_ANON_EXPORT_RC4_40_MD5, cipher_rc4_40, mac_md5, kea_dh_anon_export}, |
- {SSL_DH_ANON_EXPORT_RC4_40_MD5, cipher_rc4, mac_md5, kea_dh_anon_export}, |
{SSL_DH_ANON_EXPORT_WITH_DES40_CBC_SHA, |
cipher_des40, mac_sha, kea_dh_anon_export}, |
{SSL_DH_ANON_DES_CBC_SHA, cipher_des, mac_sha, kea_dh_anon}, |
@@ -577,6 +533,31 @@ |
} |
} |
+static PRBool |
+ssl3_CipherSuiteAllowedForVersion(ssl3CipherSuite cipherSuite, |
+ SSL3ProtocolVersion version) |
+{ |
+ switch (cipherSuite) { |
+ /* See RFC 4346 A.5. Export cipher suites must not be used in TLS 1.1 or |
+ * later. This set of cipher suites is similar to, but different from, the |
+ * set of cipher suites considered exportable by SSL_IsExportCipherSuite. |
+ */ |
+ case SSL_RSA_EXPORT_WITH_RC4_40_MD5: |
+ case SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5: |
+ /* SSL_RSA_EXPORT_WITH_DES40_CBC_SHA: never implemented |
+ * SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA: never implemented |
+ * SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA: never implemented |
+ * SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA: never implemented |
+ * SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA: never implemented |
+ * SSL_DH_ANON_EXPORT_WITH_RC4_40_MD5: never implemented |
+ * SSL_DH_ANON_EXPORT_WITH_DES40_CBC_SHA: never implemented |
+ */ |
+ return version <= SSL_LIBRARY_VERSION_TLS_1_0; |
+ default: |
+ return PR_TRUE; |
+ } |
+} |
+ |
/* return pointer to ssl3CipherSuiteDef for suite, or NULL */ |
/* XXX This does a linear search. A binary search would be better. */ |
static const ssl3CipherSuiteDef * |
@@ -920,7 +901,7 @@ |
hashItem.data = hash->sha; |
hashItem.len = sizeof(hash->sha); |
/* Allow DER encoded DSA signatures in SSL 3.0 */ |
- if (isTLS || buf->len != DSA1_SIGNATURE_LEN) { |
+ if (isTLS || buf->len != SECKEY_SignatureLen(key)) { |
signature = DSAU_DecodeDerSig(buf); |
if (!signature) { |
PORT_SetError(SSL_ERROR_BAD_HANDSHAKE_HASH_VALUE); |
@@ -986,10 +967,13 @@ |
{ |
SECStatus rv = SECSuccess; |
+#ifndef NO_PKCS11_BYPASS |
if (bypassPKCS11) { |
MD5_HashBuf (hashes->md5, hashBuf, bufLen); |
SHA1_HashBuf(hashes->sha, hashBuf, bufLen); |
- } else { |
+ } else |
+#endif |
+ { |
rv = PK11_HashBuf(SEC_OID_MD5, hashes->md5, hashBuf, bufLen); |
if (rv != SECSuccess) { |
ssl_MapLowLevelError(SSL_ERROR_MD5_DIGEST_FAILURE); |
@@ -1410,6 +1394,7 @@ |
return SECSuccess; |
} |
+#ifndef NO_PKCS11_BYPASS |
/* Initialize encryption and MAC contexts for pending spec. |
* Master Secret already is derived in spec->msItem |
* Caller holds Spec write lock. |
@@ -1576,6 +1561,7 @@ |
bail_out: |
return SECFailure; |
} |
+#endif |
/* This function should probably be moved to pk11wrap and be named |
* PK11_ParamFromIVAndEffectiveKeyBits |
@@ -1775,6 +1761,7 @@ |
goto done; /* err code set by ssl3_DeriveMasterSecret */ |
} |
} |
+#ifndef NO_PKCS11_BYPASS |
if (ss->opt.bypassPKCS11 && pwSpec->msItem.len && pwSpec->msItem.data) { |
/* Double Bypass succeeded in extracting the master_secret */ |
const ssl3KEADef * kea_def = ss->ssl3.hs.kea_def; |
@@ -1789,7 +1776,9 @@ |
if (rv == SECSuccess) { |
rv = ssl3_InitPendingContextsBypass(ss); |
} |
- } else if (pwSpec->master_secret) { |
+ } else |
+#endif |
+ if (pwSpec->master_secret) { |
rv = ssl3_DeriveConnectionKeysPKCS11(ss); |
if (rv == SECSuccess) { |
rv = ssl3_InitPendingContextsPKCS11(ss); |
@@ -1875,7 +1864,9 @@ |
{ |
const ssl3MACDef * mac_def; |
SECStatus rv; |
+#ifndef NO_PKCS11_BYPASS |
PRBool isTLS; |
+#endif |
unsigned int tempLen; |
unsigned char temp[MAX_MAC_LENGTH]; |
@@ -1899,7 +1890,9 @@ |
temp[9] = MSB(inputLength); |
temp[10] = LSB(inputLength); |
tempLen = 11; |
+#ifndef NO_PKCS11_BYPASS |
isTLS = PR_FALSE; |
+#endif |
} else { |
/* New TLS hash includes version. */ |
if (isDTLS) { |
@@ -1915,7 +1908,9 @@ |
temp[11] = MSB(inputLength); |
temp[12] = LSB(inputLength); |
tempLen = 13; |
+#ifndef NO_PKCS11_BYPASS |
isTLS = PR_TRUE; |
+#endif |
} |
PRINT_BUF(95, (NULL, "frag hash1: temp", temp, tempLen)); |
@@ -1926,15 +1921,8 @@ |
*outLength = 0; |
return SECSuccess; |
} |
- if (! spec->bypassCiphers) { |
- PK11Context *mac_context = |
- (useServerMacKey ? spec->server.write_mac_context |
- : spec->client.write_mac_context); |
- rv = PK11_DigestBegin(mac_context); |
- rv |= PK11_DigestOp(mac_context, temp, tempLen); |
- rv |= PK11_DigestOp(mac_context, input, inputLength); |
- rv |= PK11_DigestFinal(mac_context, outbuf, outLength, spec->mac_size); |
- } else { |
+#ifndef NO_PKCS11_BYPASS |
+ if (spec->bypassCiphers) { |
/* bypass version */ |
const SECHashObject *hashObj = NULL; |
unsigned int pad_bytes = 0; |
@@ -2017,6 +2005,16 @@ |
} |
#undef cx |
} |
+ } else |
+#endif |
+ { |
+ PK11Context *mac_context = |
+ (useServerMacKey ? spec->server.write_mac_context |
+ : spec->client.write_mac_context); |
+ rv = PK11_DigestBegin(mac_context); |
+ rv |= PK11_DigestOp(mac_context, temp, tempLen); |
+ rv |= PK11_DigestOp(mac_context, input, inputLength); |
+ rv |= PK11_DigestFinal(mac_context, outbuf, outLength, spec->mac_size); |
} |
PORT_Assert(rv != SECSuccess || *outLength == (unsigned)spec->mac_size); |
@@ -2802,7 +2800,7 @@ |
/* |
- * Send handshake_Failure alert. Set generic error number. |
+ * Send decode_error alert. Set generic error number. |
*/ |
SECStatus |
ssl3_DecodeError(sslSocket *ss) |
@@ -3173,6 +3171,7 @@ |
ssl_MapLowLevelError(SSL_ERROR_SESSION_KEY_GEN_FAILURE); |
return rv; |
} |
+#ifndef NO_PKCS11_BYPASS |
if (ss->opt.bypassPKCS11) { |
SECItem * keydata; |
/* In hope of doing a "double bypass", |
@@ -3208,6 +3207,7 @@ |
return SECFailure; |
} |
} |
+#endif |
return SECSuccess; |
} |
@@ -3355,11 +3355,14 @@ |
{ |
SECStatus rv = SECSuccess; |
+#ifndef NO_PKCS11_BYPASS |
if (ss->opt.bypassPKCS11) { |
ss->ssl3.hs.messages.len = 0; |
MD5_Begin((MD5Context *)ss->ssl3.hs.md5_cx); |
SHA1_Begin((SHA1Context *)ss->ssl3.hs.sha_cx); |
- } else { |
+ } else |
+#endif |
+ { |
rv = PK11_DigestBegin(ss->ssl3.hs.md5); |
if (rv != SECSuccess) { |
ssl_MapLowLevelError(SSL_ERROR_MD5_DIGEST_FAILURE); |
@@ -3386,11 +3389,14 @@ |
* that the master secret will wind up in ... |
*/ |
SSL_TRC(30,("%d: SSL3[%d]: start handshake hashes", SSL_GETPID(), ss->fd)); |
+#ifndef NO_PKCS11_BYPASS |
if (ss->opt.bypassPKCS11) { |
PORT_Assert(!ss->ssl3.hs.messages.buf && !ss->ssl3.hs.messages.space); |
ss->ssl3.hs.messages.buf = NULL; |
ss->ssl3.hs.messages.space = 0; |
- } else { |
+ } else |
+#endif |
+ { |
ss->ssl3.hs.md5 = md5 = PK11_CreateDigestContext(SEC_OID_MD5); |
ss->ssl3.hs.sha = sha = PK11_CreateDigestContext(SEC_OID_SHA1); |
if (md5 == NULL) { |
@@ -3438,6 +3444,7 @@ |
PRINT_BUF(90, (NULL, "MD5 & SHA handshake hash input:", b, l)); |
+#ifndef NO_PKCS11_BYPASS |
if (ss->opt.bypassPKCS11) { |
MD5_Update((MD5Context *)ss->ssl3.hs.md5_cx, b, l); |
SHA1_Update((SHA1Context *)ss->ssl3.hs.sha_cx, b, l); |
@@ -3446,6 +3453,7 @@ |
#endif |
return rv; |
} |
+#endif |
rv = PK11_DigestOp(ss->ssl3.hs.md5, b, l); |
if (rv != SECSuccess) { |
ssl_MapLowLevelError(SSL_ERROR_MD5_DIGEST_FAILURE); |
@@ -3739,6 +3747,7 @@ |
PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) ); |
+#ifndef NO_PKCS11_BYPASS |
if (ss->opt.bypassPKCS11) { |
/* compute them without PKCS11 */ |
PRUint64 md5_cx[MAX_MAC_CONTEXT_LLONGS]; |
@@ -3821,7 +3830,9 @@ |
rv = SECSuccess; |
#undef md5cx |
#undef shacx |
- } else { |
+ } else |
+#endif |
+ { |
/* compute hases with PKCS11 */ |
PK11Context * md5; |
PK11Context * sha = NULL; |
@@ -4294,7 +4305,8 @@ |
} |
if (ss->firstHsDone) { |
- /* Work around the Windows SChannel bug described above. */ |
+ /* The client hello version must stay unchanged to work around |
+ * the Windows SChannel bug described above. */ |
PORT_Assert(ss->version == ss->clientHelloVersion); |
} |
ss->clientHelloVersion = ss->version; |
@@ -4910,9 +4922,11 @@ |
/* hexEncode hex encodes |length| bytes from |in| and writes it as |length*2| |
* bytes to |out|. */ |
-static void hexEncode(char *out, const unsigned char *in, size_t length) { |
+static void |
+hexEncode(char *out, const unsigned char *in, unsigned int length) |
+{ |
static const char hextable[] = "0123456789abcdef"; |
- size_t i; |
+ unsigned int i; |
for (i = 0; i < length; i++) { |
*(out++) = hextable[in[i] >> 4]; |
@@ -5382,8 +5396,17 @@ |
ssl3_config_match_init(ss); |
for (i = 0; i < ssl_V3_SUITES_IMPLEMENTED; i++) { |
ssl3CipherSuiteCfg *suite = &ss->cipherSuites[i]; |
- if ((temp == suite->cipher_suite) && |
- (config_match(suite, ss->ssl3.policy, PR_TRUE))) { |
+ if (temp == suite->cipher_suite) { |
+ if (!config_match(suite, ss->ssl3.policy, PR_TRUE)) { |
+ break; /* failure */ |
+ } |
+ if (!ssl3_CipherSuiteAllowedForVersion(suite->cipher_suite, |
+ ss->version)) { |
+ desc = handshake_failure; |
+ errCode = SSL_ERROR_CIPHER_DISALLOWED_FOR_VERSION; |
+ goto alert_loser; |
+ } |
+ |
suite_found = PR_TRUE; |
break; /* success */ |
} |
@@ -5408,8 +5431,10 @@ |
} |
suite_found = PR_FALSE; |
for (i = 0; i < compressionMethodsCount; i++) { |
- if (temp == compressions[i] && |
- compressionEnabled(ss, compressions[i])) { |
+ if (temp == compressions[i]) { |
+ if (!compressionEnabled(ss, compressions[i])) { |
+ break; /* failure */ |
+ } |
suite_found = PR_TRUE; |
break; /* success */ |
} |
@@ -5494,12 +5519,14 @@ |
PK11SymKey * wrapKey; /* wrapping key */ |
CK_FLAGS keyFlags = 0; |
+#ifndef NO_PKCS11_BYPASS |
if (ss->opt.bypassPKCS11) { |
/* we cannot restart a non-bypass session in a |
** bypass socket. |
*/ |
break; |
} |
+#endif |
/* unwrap master secret with PKCS11 */ |
slot = SECMOD_LookupSlot(sid->u.ssl3.masterModuleID, |
sid->u.ssl3.masterSlotID); |
@@ -5534,6 +5561,7 @@ |
if (pwSpec->master_secret == NULL) { |
break; /* errorCode set just after call to UnwrapSymKey. */ |
} |
+#ifndef NO_PKCS11_BYPASS |
} else if (ss->opt.bypassPKCS11) { |
/* MS is not wrapped */ |
wrappedMS.data = sid->u.ssl3.keys.wrapped_master_secret; |
@@ -5541,6 +5569,7 @@ |
memcpy(pwSpec->raw_master_secret, wrappedMS.data, wrappedMS.len); |
pwSpec->msItem.data = pwSpec->raw_master_secret; |
pwSpec->msItem.len = wrappedMS.len; |
+#endif |
} else { |
/* We CAN restart a bypass session in a non-bypass socket. */ |
/* need to import the raw master secret to session object */ |
@@ -5578,6 +5607,7 @@ |
ssl3_CopyPeerCertsFromSID(ss, sid); |
} |
+ |
/* NULL value for PMS signifies re-use of the old MS */ |
rv = ssl3_InitPendingCipherSpec(ss, NULL); |
if (rv != SECSuccess) { |
@@ -5640,10 +5670,10 @@ |
return SECFailure; |
} |
-/* ssl3_BigIntGreaterThan1 returns true iff |mpint|, taken as an unsigned, |
+/* ssl3_BigIntGreaterThanOne returns true iff |mpint|, taken as an unsigned, |
* big-endian integer is > 1 */ |
static PRBool |
-ssl3_BigIntGreaterThan1(const SECItem* mpint) { |
+ssl3_BigIntGreaterThanOne(const SECItem* mpint) { |
unsigned char firstNonZeroByte = 0; |
unsigned int i; |
@@ -5659,8 +5689,8 @@ |
if (firstNonZeroByte > 1) |
return PR_TRUE; |
- // firstNonZeroByte == 1, therefore mpint > 1 iff the first non-zero byte |
- // is followed by another byte. |
+ /* firstNonZeroByte == 1, therefore mpint > 1 iff the first non-zero byte |
+ * is followed by another byte. */ |
return (i < mpint->len - 1); |
} |
@@ -5795,13 +5825,13 @@ |
if (rv != SECSuccess) { |
goto loser; /* malformed. */ |
} |
- if (dh_g.len > dh_p.len || !ssl3_BigIntGreaterThan1(&dh_g)) |
+ if (dh_g.len > dh_p.len || !ssl3_BigIntGreaterThanOne(&dh_g)) |
goto alert_loser; |
rv = ssl3_ConsumeHandshakeVariable(ss, &dh_Ys, 2, &b, &length); |
if (rv != SECSuccess) { |
goto loser; /* malformed. */ |
} |
- if (dh_Ys.len > dh_p.len || !ssl3_BigIntGreaterThan1(&dh_Ys)) |
+ if (dh_Ys.len > dh_p.len || !ssl3_BigIntGreaterThanOne(&dh_Ys)) |
goto alert_loser; |
rv = ssl3_ConsumeHandshakeVariable(ss, &signature, 2, &b, &length); |
if (rv != SECSuccess) { |
@@ -6949,13 +6979,26 @@ |
#endif |
/* Select a cipher suite. |
+ ** |
** NOTE: This suite selection algorithm should be the same as the one in |
- ** ssl3_HandleV2ClientHello(). |
+ ** ssl3_HandleV2ClientHello(). |
+ ** |
+ ** If TLS 1.0 is enabled, we could handle the case where the client |
+ ** offered TLS 1.1 but offered only export cipher suites by choosing TLS |
+ ** 1.0 and selecting one of those export cipher suites. However, a secure |
+ ** TLS 1.1 client should not have export cipher suites enabled at all, |
+ ** and a TLS 1.1 client should definitely not be offering *only* export |
+ ** cipher suites. Therefore, we refuse to negotiate export cipher suites |
+ ** with any client that indicates support for TLS 1.1 or higher when we |
+ ** (the server) have TLS 1.1 support enabled. |
*/ |
for (j = 0; j < ssl_V3_SUITES_IMPLEMENTED; j++) { |
ssl3CipherSuiteCfg *suite = &ss->cipherSuites[j]; |
- if (!config_match(suite, ss->ssl3.policy, PR_TRUE)) |
+ if (!config_match(suite, ss->ssl3.policy, PR_TRUE) || |
+ !ssl3_CipherSuiteAllowedForVersion(suite->cipher_suite, |
+ ss->version)) { |
continue; |
+ } |
for (i = 0; i + 1 < suites.len; i += 2) { |
PRUint16 suite_i = (suites.data[i] << 8) | suites.data[i + 1]; |
if (suite_i == suite->cipher_suite) { |
@@ -6972,9 +7015,10 @@ |
suite_found: |
/* Look for a matching compression algorithm. */ |
for (i = 0; i < comps.len; i++) { |
+ if (!compressionEnabled(ss, comps.data[i])) |
+ continue; |
for (j = 0; j < compressionMethodsCount; j++) { |
- if (comps.data[i] == compressions[j] && |
- compressionEnabled(ss, compressions[j])) { |
+ if (comps.data[i] == compressions[j]) { |
ss->ssl3.hs.compression = |
(SSLCompressionMethod)compressions[j]; |
goto compression_found; |
@@ -7000,7 +7044,8 @@ |
SECItem wrappedMS; /* wrapped key */ |
if (sid->version != ss->version || |
- sid->u.ssl3.cipherSuite != ss->ssl3.hs.cipher_suite) { |
+ sid->u.ssl3.cipherSuite != ss->ssl3.hs.cipher_suite || |
+ sid->u.ssl3.compression != ss->ssl3.hs.compression) { |
break; /* not an error */ |
} |
@@ -7020,12 +7065,14 @@ |
if (sid->u.ssl3.keys.msIsWrapped) { |
PK11SymKey * wrapKey; /* wrapping key */ |
CK_FLAGS keyFlags = 0; |
+#ifndef NO_PKCS11_BYPASS |
if (ss->opt.bypassPKCS11) { |
/* we cannot restart a non-bypass session in a |
** bypass socket. |
*/ |
break; |
} |
+#endif |
wrapKey = getWrappingKey(ss, NULL, sid->u.ssl3.exchKeyType, |
sid->u.ssl3.masterWrapMech, |
@@ -7051,12 +7098,14 @@ |
if (pwSpec->master_secret == NULL) { |
break; /* not an error */ |
} |
+#ifndef NO_PKCS11_BYPASS |
} else if (ss->opt.bypassPKCS11) { |
wrappedMS.data = sid->u.ssl3.keys.wrapped_master_secret; |
wrappedMS.len = sid->u.ssl3.keys.wrapped_master_secret_len; |
memcpy(pwSpec->raw_master_secret, wrappedMS.data, wrappedMS.len); |
pwSpec->msItem.data = pwSpec->raw_master_secret; |
pwSpec->msItem.len = wrappedMS.len; |
+#endif |
} else { |
/* We CAN restart a bypass session in a non-bypass socket. */ |
/* need to import the raw master secret to session object */ |
@@ -7460,13 +7509,19 @@ |
} |
/* Select a cipher suite. |
+ ** |
** NOTE: This suite selection algorithm should be the same as the one in |
- ** ssl3_HandleClientHello(). |
+ ** ssl3_HandleClientHello(). |
+ ** |
+ ** See the comments about export cipher suites in ssl3_HandleClientHello(). |
*/ |
for (j = 0; j < ssl_V3_SUITES_IMPLEMENTED; j++) { |
ssl3CipherSuiteCfg *suite = &ss->cipherSuites[j]; |
- if (!config_match(suite, ss->ssl3.policy, PR_TRUE)) |
+ if (!config_match(suite, ss->ssl3.policy, PR_TRUE) || |
+ !ssl3_CipherSuiteAllowedForVersion(suite->cipher_suite, |
+ ss->version)) { |
continue; |
+ } |
for (i = 0; i+2 < suite_length; i += 3) { |
PRUint32 suite_i = (suites[i] << 16)|(suites[i+1] << 8)|suites[i+2]; |
if (suite_i == suite->cipher_suite) { |
@@ -7792,8 +7847,6 @@ |
nnames = ca_list->nnames; |
} |
- /* There used to be a test here to require a CA, but there |
- * are cases where you want to have no CAs offered. */ |
for (i = 0, name = names; i < nnames; i++, name++) { |
calen += 2 + name->len; |
} |
@@ -7999,10 +8052,12 @@ |
SECKEYPrivateKey *serverKey) |
{ |
PK11SymKey * pms; |
+#ifndef NO_PKCS11_BYPASS |
unsigned char * cr = (unsigned char *)&ss->ssl3.hs.client_random; |
unsigned char * sr = (unsigned char *)&ss->ssl3.hs.server_random; |
ssl3CipherSpec * pwSpec = ss->ssl3.pwSpec; |
unsigned int outLen = 0; |
+#endif |
PRBool isTLS = PR_FALSE; |
SECStatus rv; |
SECItem enc_pms; |
@@ -8032,6 +8087,7 @@ |
isTLS = (PRBool)(ss->ssl3.hs.kea_def->tls_keygen != 0); |
} |
+#ifndef NO_PKCS11_BYPASS |
if (ss->opt.bypassPKCS11) { |
/* TRIPLE BYPASS, get PMS directly from RSA decryption. |
* Use PK11_PrivDecryptPKCS1 to decrypt the PMS to a buffer, |
@@ -8068,8 +8124,12 @@ |
PK11_GenerateRandom(pwSpec->msItem.data, pwSpec->msItem.len); |
} |
rv = ssl3_InitPendingCipherSpec(ss, NULL); |
- } else { |
+ } else |
+#endif |
+ { |
+#ifndef NO_PKCS11_BYPASS |
double_bypass: |
+#endif |
/* |
* unwrap pms out of the incoming buffer |
* Note: CKM_SSL3_MASTER_KEY_DERIVE is NOT the mechanism used to do |
@@ -8961,6 +9021,11 @@ |
PK11_DestroyContext(prf_context, PR_TRUE); |
} else { |
/* bypass PKCS11 */ |
+#ifdef NO_PKCS11_BYPASS |
+ PORT_Assert(spec->master_secret); |
+ PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); |
+ rv = SECFailure; |
+#else |
SECItem inData = { siBuffer, }; |
SECItem outData = { siBuffer, }; |
PRBool isFIPS = PR_FALSE; |
@@ -8971,6 +9036,7 @@ |
outData.len = outLen; |
rv = TLS_PRF(&spec->msItem, label, &inData, &outData, isFIPS); |
PORT_Assert(rv != SECSuccess || outData.len == outLen); |
+#endif |
} |
return rv; |
} |
@@ -9009,6 +9075,68 @@ |
return rv; |
} |
+/* called from ssl3_SendFinished |
+ * |
+ * This function is simply a debugging aid and therefore does not return a |
+ * SECStatus. */ |
+static void |
+ssl3_RecordKeyLog(sslSocket *ss) |
+{ |
+ sslSessionID *sid; |
+ SECStatus rv; |
+ SECItem *keyData; |
+ char buf[14 /* "CLIENT_RANDOM " */ + |
+ SSL3_RANDOM_LENGTH*2 /* client_random */ + |
+ 1 /* " " */ + |
+ 48*2 /* master secret */ + |
+ 1 /* new line */]; |
+ unsigned int j; |
+ |
+ PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss)); |
+ |
+ sid = ss->sec.ci.sid; |
+ |
+ if (!ssl_keylog_iob) |
+ return; |
+ |
+ rv = PK11_ExtractKeyValue(ss->ssl3.cwSpec->master_secret); |
+ if (rv != SECSuccess) |
+ return; |
+ |
+ ssl_GetSpecReadLock(ss); |
+ |
+ /* keyData does not need to be freed. */ |
+ keyData = PK11_GetKeyData(ss->ssl3.cwSpec->master_secret); |
+ if (!keyData || !keyData->data || keyData->len != 48) { |
+ ssl_ReleaseSpecReadLock(ss); |
+ return; |
+ } |
+ |
+ /* https://developer.mozilla.org/en/NSS_Key_Log_Format */ |
+ |
+ /* There could be multiple, concurrent writers to the |
+ * keylog, so we have to do everything in a single call to |
+ * fwrite. */ |
+ |
+ memcpy(buf, "CLIENT_RANDOM ", 14); |
+ j = 14; |
+ hexEncode(buf + j, ss->ssl3.hs.client_random.rand, SSL3_RANDOM_LENGTH); |
+ j += SSL3_RANDOM_LENGTH*2; |
+ buf[j++] = ' '; |
+ hexEncode(buf + j, keyData->data, 48); |
+ j += 48*2; |
+ buf[j++] = '\n'; |
+ |
+ PORT_Assert(j == sizeof(buf)); |
+ |
+ ssl_ReleaseSpecReadLock(ss); |
+ |
+ if (fwrite(buf, sizeof(buf), 1, ssl_keylog_iob) != 1) |
+ return; |
+ fflush(ssl_keylog_iob); |
+ return; |
+} |
+ |
/* called from ssl3_SendClientSecondRound |
* ssl3_HandleFinished |
*/ |
@@ -9167,69 +9295,6 @@ |
return SECSuccess; |
} |
-/* called from ssl3_SendFinished |
- * |
- * Caller must already hold the SpecReadLock. (wish we could assert that!). |
- * This function is simply a debugging aid and therefore does not return a |
- * SECStatus. */ |
-static void |
-ssl3_RecordKeyLog(sslSocket *ss) |
-{ |
- sslSessionID *sid; |
- SECStatus rv; |
- SECItem *keyData; |
- char buf[14 /* "CLIENT_RANDOM " */ + |
- SSL3_RANDOM_LENGTH*2 /* client_random */ + |
- 1 /* " " */ + |
- 48*2 /* master secret */ + |
- 1 /* new line */]; |
- unsigned int j; |
- |
- PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss)); |
- |
- sid = ss->sec.ci.sid; |
- |
- if (!ssl_keylog_iob) |
- return; |
- |
- rv = PK11_ExtractKeyValue(ss->ssl3.cwSpec->master_secret); |
- if (rv != SECSuccess) |
- return; |
- |
- ssl_GetSpecReadLock(ss); |
- |
- /* keyData does not need to be freed. */ |
- keyData = PK11_GetKeyData(ss->ssl3.cwSpec->master_secret); |
- if (!keyData || !keyData->data || keyData->len != 48) { |
- ssl_ReleaseSpecReadLock(ss); |
- return; |
- } |
- |
- /* https://developer.mozilla.org/en/NSS_Key_Log_Format */ |
- |
- /* There could be multiple, concurrent writers to the |
- * keylog, so we have to do everything in a single call to |
- * fwrite. */ |
- |
- memcpy(buf, "CLIENT_RANDOM ", 14); |
- j = 14; |
- hexEncode(buf + j, ss->ssl3.hs.client_random.rand, SSL3_RANDOM_LENGTH); |
- j += SSL3_RANDOM_LENGTH*2; |
- buf[j++] = ' '; |
- hexEncode(buf + j, keyData->data, 48); |
- j += 48*2; |
- buf[j++] = '\n'; |
- |
- PORT_Assert(j == sizeof(buf)); |
- |
- ssl_ReleaseSpecReadLock(ss); |
- |
- if (fwrite(buf, sizeof(buf), 1, ssl_keylog_iob) != 1) |
- return; |
- fflush(ssl_keylog_iob); |
- return; |
-} |
- |
/* called from ssl3_HandleServerHelloDone |
* ssl3_HandleClientHello |
* ssl3_HandleFinished |
@@ -9935,7 +10000,7 @@ |
/* must be copied to msg_body and dealt with from there */ |
unsigned int bytes; |
- PORT_Assert(ss->ssl3.hs.msg_body.len <= ss->ssl3.hs.msg_len); |
+ PORT_Assert(ss->ssl3.hs.msg_body.len < ss->ssl3.hs.msg_len); |
bytes = PR_MIN(buf->len, ss->ssl3.hs.msg_len - ss->ssl3.hs.msg_body.len); |
/* Grow the buffer if needed */ |
@@ -9957,18 +10022,19 @@ |
if (ss->ssl3.hs.msg_body.len == ss->ssl3.hs.msg_len) { |
rv = ssl3_HandleHandshakeMessage( |
ss, ss->ssl3.hs.msg_body.buf, ss->ssl3.hs.msg_len); |
- /* |
- * XXX This appears to be wrong. This error handling |
- * should clean up after a SECWouldBlock return, like the |
- * error handling used 40 lines before/above this one, |
- */ |
- if (rv != SECSuccess) { |
- /* ssl3_HandleHandshakeMessage MUST set error code. */ |
+ if (rv == SECFailure) { |
+ /* This test wants to fall through on either |
+ * SECSuccess or SECWouldBlock. |
+ * ssl3_HandleHandshakeMessage MUST set error code. |
+ */ |
return rv; |
} |
ss->ssl3.hs.msg_body.len = 0; |
- ss->ssl3.hs.msg_len = 0; |
+ ss->ssl3.hs.msg_len = 0; |
ss->ssl3.hs.header_bytes = 0; |
+ if (rv != SECSuccess) { /* return if SECWouldBlock. */ |
+ return rv; |
+ } |
} else { |
PORT_Assert(buf->len == 0); |
break; |
@@ -10457,13 +10523,8 @@ |
ss->ssl3.hs.recvMessageSeq = 0; |
ss->ssl3.hs.rtTimeoutMs = INITIAL_DTLS_TIMEOUT_MS; |
ss->ssl3.hs.rtRetries = 0; |
- |
- /* Have to allocate this because ssl_FreeSocket relocates |
- * this structure in DEBUG mode */ |
- if (!(ss->ssl3.hs.lastMessageFlight = PORT_New(PRCList))) |
- return SECFailure; |
ss->ssl3.hs.recvdHighWater = -1; |
- PR_INIT_CLIST(ss->ssl3.hs.lastMessageFlight); |
+ PR_INIT_CLIST(&ss->ssl3.hs.lastMessageFlight); |
dtls_SetMTU(ss, 0); /* Set the MTU to the highest plateau */ |
} |
@@ -10836,10 +10897,12 @@ |
} |
/* clean up handshake */ |
+#ifndef NO_PKCS11_BYPASS |
if (ss->opt.bypassPKCS11) { |
SHA1_DestroyContext((SHA1Context *)ss->ssl3.hs.sha_cx, PR_FALSE); |
MD5_DestroyContext((MD5Context *)ss->ssl3.hs.md5_cx, PR_FALSE); |
} |
+#endif |
if (ss->ssl3.hs.md5) { |
PK11_DestroyContext(ss->ssl3.hs.md5,PR_TRUE); |
} |
@@ -10868,10 +10931,7 @@ |
/* Destroy the DTLS data */ |
if (IS_DTLS(ss)) { |
- if (ss->ssl3.hs.lastMessageFlight) { |
- dtls_FreeHandshakeMessages(ss->ssl3.hs.lastMessageFlight); |
- PORT_Free(ss->ssl3.hs.lastMessageFlight); |
- } |
+ dtls_FreeHandshakeMessages(&ss->ssl3.hs.lastMessageFlight); |
if (ss->ssl3.hs.recvdFragments.buf) { |
PORT_Free(ss->ssl3.hs.recvdFragments.buf); |
} |