diff options
author | wtc@chromium.org <wtc@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-06-09 01:18:58 +0000 |
---|---|---|
committer | wtc@chromium.org <wtc@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-06-09 01:18:58 +0000 |
commit | 5785c113c2fd716604b27a900768ae9c6cf77acb (patch) | |
tree | 53aacd0dc6f90d77a0ce104045202fd2887e1a16 /net/third_party | |
parent | 533a6247e738e15277a50a65a6f076c8cc2c57e8 (diff) | |
download | chromium_src-5785c113c2fd716604b27a900768ae9c6cf77acb.zip chromium_src-5785c113c2fd716604b27a900768ae9c6cf77acb.tar.gz chromium_src-5785c113c2fd716604b27a900768ae9c6cf77acb.tar.bz2 |
Remove the TLS Snap Start code from NSS.
R=agl@chromium.org
BUG=none
TEST=none
Review URL: http://codereview.chromium.org/7003069
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@88459 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net/third_party')
-rw-r--r-- | net/third_party/nss/README.chromium | 5 | ||||
-rwxr-xr-x | net/third_party/nss/patches/applypatches.sh | 3 | ||||
-rw-r--r-- | net/third_party/nss/patches/snapstart.patch | 2131 | ||||
-rw-r--r-- | net/third_party/nss/patches/snapstart2.patch | 93 | ||||
-rw-r--r-- | net/third_party/nss/ssl.gyp | 2 | ||||
-rw-r--r-- | net/third_party/nss/ssl/fnv1a64.c | 72 | ||||
-rw-r--r-- | net/third_party/nss/ssl/snapstart.c | 1061 | ||||
-rw-r--r-- | net/third_party/nss/ssl/ssl.def | 12 | ||||
-rw-r--r-- | net/third_party/nss/ssl/ssl.h | 54 | ||||
-rw-r--r-- | net/third_party/nss/ssl/ssl3con.c | 364 | ||||
-rw-r--r-- | net/third_party/nss/ssl/ssl3ext.c | 13 | ||||
-rw-r--r-- | net/third_party/nss/ssl/sslimpl.h | 79 | ||||
-rw-r--r-- | net/third_party/nss/ssl/sslsock.c | 10 | ||||
-rw-r--r-- | net/third_party/nss/ssl/sslt.h | 16 |
14 files changed, 146 insertions, 3769 deletions
diff --git a/net/third_party/nss/README.chromium b/net/third_party/nss/README.chromium index f956ffd..193fef0 100644 --- a/net/third_party/nss/README.chromium +++ b/net/third_party/nss/README.chromium @@ -27,11 +27,6 @@ Patches: patches/cachecerts.patch https://bugzilla.mozilla.org/show_bug.cgi?id=606049 - * Add Snap Start support - patches/snapstart.patch - patches/snapstart2.patch - http://tools.ietf.org/html/draft-agl-tls-snapstart-00 - * Add the SSL_PeerCertificateChain function patches/peercertchain.patch diff --git a/net/third_party/nss/patches/applypatches.sh b/net/third_party/nss/patches/applypatches.sh index 0a858f8..0c2a687 100755 --- a/net/third_party/nss/patches/applypatches.sh +++ b/net/third_party/nss/patches/applypatches.sh @@ -13,9 +13,6 @@ patch -p4 < $patches_dir/renegoscsv.patch patch -p4 < $patches_dir/cachecerts.patch -patch -p5 < $patches_dir/snapstart.patch -patch -p3 < $patches_dir/snapstart2.patch - patch -p3 < $patches_dir/peercertchain.patch patch -p4 < $patches_dir/ocspstapling.patch diff --git a/net/third_party/nss/patches/snapstart.patch b/net/third_party/nss/patches/snapstart.patch deleted file mode 100644 index f9c05c8..0000000 --- a/net/third_party/nss/patches/snapstart.patch +++ /dev/null @@ -1,2131 +0,0 @@ -diff --git a/mozilla/security/nss/lib/ssl/fnv1a64.c b/mozilla/security/nss/lib/ssl/fnv1a64.c -new file mode 100644 -index 0000000..c7c4b08 ---- /dev/null -+++ b/mozilla/security/nss/lib/ssl/fnv1a64.c -@@ -0,0 +1,72 @@ -+/* -+ * FNV1A64 Hash -+ * http://www.isthe.com/chongo/tech/comp/fnv/index.html#FNV-param -+ * -+ * ***** 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): -+ * Adam Langley, Google Inc. -+ * -+ * 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: fnv1a64.c,v 1.0 2010/08/09 13:00:00 agl%google.com Exp $ */ -+ -+#include "prtypes.h" -+#include "prnetdb.h" -+ -+/* Older versions of Visual C++ don't support the 'ull' suffix. */ -+#ifdef _MSC_VER -+static const PRUint64 FNV1A64_OFFSET_BASIS = 14695981039346656037ui64; -+static const PRUint64 FNV1A64_PRIME = 1099511628211ui64; -+#else -+static const PRUint64 FNV1A64_OFFSET_BASIS = 14695981039346656037ull; -+static const PRUint64 FNV1A64_PRIME = 1099511628211ull; -+#endif -+ -+void FNV1A64_Init(PRUint64* digest) { -+ *digest = FNV1A64_OFFSET_BASIS; -+} -+ -+void FNV1A64_Update(PRUint64* digest, const unsigned char *data, -+ unsigned int length) { -+ unsigned int i; -+ -+ for (i = 0; i < length; i++) { -+ *digest ^= data[i]; -+ *digest *= FNV1A64_PRIME; -+ } -+} -+ -+void FNV1A64_Final(PRUint64 *digest) { -+ *digest = PR_htonll(*digest); -+} -diff --git a/mozilla/security/nss/lib/ssl/snapstart.c b/mozilla/security/nss/lib/ssl/snapstart.c -new file mode 100644 -index 0000000..ca2cafa ---- /dev/null -+++ b/mozilla/security/nss/lib/ssl/snapstart.c -@@ -0,0 +1,1062 @@ -+/* -+ * TLS Snap Start -+ * -+ * ***** 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): -+ * Adam Langley, Google Inc. -+ * -+ * 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: ssl3snap.c,v 1.0 2010/08/09 13:00:00 agl%google.com Exp $ */ -+ -+ -+/* TODO(agl): Refactor ssl3_CompressMACEncryptRecord so that it can write to -+** |sendBuf| directly and fix ssl3_AppendSnapStartHandshakeRecord and -+** ssl3_AppendSnapStartApplicationData. -+*/ -+ -+/* TODO(agl): Add support for snap starting with compression. */ -+ -+/* TODO(agl): Free snapStartApplicationData as soon as the handshake has -+** completed. -+*/ -+ -+#include "pk11pub.h" -+#include "ssl.h" -+#include "sslimpl.h" -+#include "sslproto.h" -+ -+static unsigned int GetBE16(const void *in) -+{ -+ const unsigned char *p = in; -+ return ((unsigned) p[0]) << 8 | -+ p[1]; -+} -+ -+static unsigned int GetBE24(const void *in) -+{ -+ const unsigned char *p = in; -+ return ((unsigned) p[0]) << 16 | -+ ((unsigned) p[1]) << 8 | -+ p[2]; -+} -+ -+static void PutBE16(void *out, unsigned int value) -+{ -+ unsigned char *p = out; -+ p[0] = value >> 8; -+ p[1] = value; -+} -+ -+static void PutBE24(void *out, unsigned int value) -+{ -+ unsigned char *p = out; -+ p[0] = value >> 16; -+ p[1] = value >> 8; -+ p[2] = value; -+} -+ -+/* ssl3_ForEachExtension calls a callback for each TLS extension in |extensions| -+** extensions: points to a block of extensions which includes the two prefix -+** length bytes -+** is_resuming: if true, certain extensions will be omitted -+** f: a function which is called with the data of each extension, which -+** includes the four type and length bytes at the beginning. -+*/ -+static PRBool -+ssl3_ForEachExtension(const SECItem *extensions, PRBool is_resuming, -+ void (*f) (const unsigned char *data, unsigned int length, -+ void *ctx), -+ void *ctx) { -+ unsigned int extensions_len, offset; -+ -+ if (extensions->len == 0) -+ return PR_TRUE; -+ -+ if (extensions->len < 2) -+ goto loser; -+ -+ extensions_len = GetBE16(extensions->data); -+ offset = 2; -+ -+ if (extensions->len != 2 + extensions_len) -+ goto loser; -+ -+ while (extensions_len) { -+ unsigned int extension_num, extension_len; -+ -+ if (extensions->len - offset < 4) -+ goto loser; -+ -+ extension_num = GetBE16(extensions->data + offset); -+ extension_len = GetBE16(extensions->data + offset + 2); -+ -+ if (extensions->len - offset < 4 + extension_len) -+ goto loser; -+ -+ /* When resuming, the server will omit some extensions from the -+ * previous non-resume ServerHello. */ -+ if (!is_resuming || -+ (extension_num != ssl_server_name_xtn && -+ extension_num != ssl_session_ticket_xtn)) { -+ f(extensions->data + offset, 4 + extension_len, ctx); -+ } -+ -+ offset += 4 + extension_len; -+ extensions_len -= 4 + extension_len; -+ } -+ -+ return PR_TRUE; -+ -+loser: -+ PORT_SetError(SEC_ERROR_INPUT_LEN); -+ return PR_FALSE; -+} -+ -+static void -+ssl3_AccumlateLengths(const unsigned char *data, unsigned int length, void *ptr) -+{ -+ unsigned int *sum = (unsigned int *) ptr; -+ *sum += length; -+} -+ -+/* ssl3_PredictServerResponse predicts the contents of the server's -+** ServerHello...ServerHelloDone (inclusive) and progressively calls a callback -+** with the contents of those messages. -+** previous_server_hello: the contents of a previous ServerHello from the -+** server where the 'random' field has been replaced with our suggested -+** server random. -+** is_resuming: if false, Certificate and ServerHelloDone messages will be -+** predicted -+** hashUpdate: a callback which is called repeated with the contents of the -+** predicted messages. -+*/ -+static PRBool -+ssl3_PredictServerResponse( -+ sslSocket *ss, SECItem *previous_server_hello, PRBool is_resuming, -+ void (*hashUpdate) (const unsigned char *data, unsigned int length, -+ void *ctx), -+ void *ctx) { -+ unsigned int old_session_id_length, old_extensions_len; -+ unsigned int extensions_len, server_hello_len; -+ unsigned char session_id_len, header[4]; -+ SECItem extensions; -+ -+ /* Keep the structure of a ServerHello in mind when reading the following: -+ * -+ * struct ServerHello { -+ * uint16_t version; -+ * uint8_t random[32]; -+ * uint8_t session_id_len; -+ * uint8_t session_id[session_id_len]; -+ * uint16_t cipher -+ * uint8_t compression -+ * -+ * // Optional: -+ * uint16_t extensions_len; -+ * struct Extension { -+ * uint16_t num; -+ * uint16_t len; -+ * uint8_t payload[len]; -+ * } -+ */ -+ -+ /* 38 bytes is the shortest possible ServerHello with a zero-length -+ * session_id and no extensions. */ -+ if (previous_server_hello->len < 38) { -+ PORT_SetError(SEC_ERROR_INPUT_LEN); -+ return PR_FALSE; -+ } -+ -+ /* First we need to figure out the length of the predicted ServerHello. Any -+ * session id in |previous_server_hello| needs to be removed -+ * (or replaced). */ -+ old_session_id_length = previous_server_hello->data[34]; -+ -+ extensions.len = 0; -+ -+ if (previous_server_hello->len >= 35 + old_session_id_length + 3 + 2) { -+ /* Extensions present */ -+ unsigned int offset = 35 + old_session_id_length + 3; -+ extensions.data = previous_server_hello->data + offset; -+ extensions.len = previous_server_hello->len - offset; -+ } -+ -+ /* Sum the lengths of all the extensions that we wish to include */ -+ extensions_len = 0; -+ if (!ssl3_ForEachExtension(&extensions, is_resuming, ssl3_AccumlateLengths, -+ &extensions_len)) { -+ return PR_FALSE; -+ } -+ -+ old_extensions_len = -+ (previous_server_hello->len - 35 - old_session_id_length - 3 - 2); -+ -+ session_id_len = 0; -+ if (ss->sec.ci.sid) -+ session_id_len = ss->sec.ci.sid->u.ssl3.sessionIDLength; -+ server_hello_len = previous_server_hello->len + -+ session_id_len - old_session_id_length + -+ extensions_len - old_extensions_len; -+ -+ header[0] = server_hello; -+ PutBE24(header + 1, server_hello_len); -+ hashUpdate(header, 4, ctx); -+ -+ hashUpdate(previous_server_hello->data, 34, ctx); -+ hashUpdate(&session_id_len, sizeof(session_id_len), ctx); -+ if (session_id_len) -+ hashUpdate(ss->sec.ci.sid->u.ssl3.sessionID, session_id_len, ctx); -+ hashUpdate(previous_server_hello->data + 35 + old_session_id_length, 3, -+ ctx); -+ -+ if (extensions.len) { -+ PutBE16(header, extensions_len); -+ hashUpdate(header, 2, ctx); -+ -+ if (!ssl3_ForEachExtension(&extensions, is_resuming, hashUpdate, ctx)) -+ return PR_FALSE; -+ } -+ -+ if (!is_resuming) { -+ unsigned int certificate_message_len = 3, i; -+ for (i = 0; ss->ssl3.predictedCertChain[i]; i++) { -+ certificate_message_len += 3; -+ certificate_message_len += -+ ss->ssl3.predictedCertChain[i]->derCert.len; -+ } -+ -+ header[0] = certificate; -+ PutBE24(header + 1, certificate_message_len); -+ hashUpdate(header, 4, ctx); -+ -+ PutBE24(header, certificate_message_len - 3); -+ hashUpdate(header, 3, ctx); -+ -+ for (i = 0; ss->ssl3.predictedCertChain[i]; i++) { -+ unsigned int len = ss->ssl3.predictedCertChain[i]->derCert.len; -+ PutBE24(header, len); -+ hashUpdate(header, 3, ctx); -+ hashUpdate(ss->ssl3.predictedCertChain[i]->derCert.data, len, ctx); -+ } -+ -+ header[0] = server_hello_done; -+ header[1] = header[2] = header[3] = 0; -+ hashUpdate(header, 4, ctx); -+ } -+ -+ return PR_TRUE; -+} -+ -+/* ssl3_SnapStartHash is called with the contents of the server's predicted -+ * response and updates both the Finished hash and an FNV641a hash. */ -+static void -+ssl3_SnapStartHash(const unsigned char *data, unsigned int len, void *ctx) -+{ -+ SECStatus rv; -+ void **ptrs = (void **) ctx; -+ sslSocket *ss = ptrs[0]; -+ PRUint64 *fnv = ptrs[1]; -+ -+ FNV1A64_Update(fnv, data, len); -+ rv = ssl3_UpdateHandshakeHashes(ss, (unsigned char *) data, len); -+ if (rv != SECSuccess) -+ PR_Assert("rv == SECSuccess", __FILE__, __LINE__); -+} -+ -+static PRInt32 -+ssl3_SendEmptySnapStartXtn(sslSocket *ss, PRBool append, PRUint32 maxBytes) -+{ -+ SECStatus rv; -+ -+ if (maxBytes < 4) -+ return 0; -+ -+ if (append) { -+ rv = ssl3_AppendHandshakeNumber(ss, ssl_snap_start_xtn, 2); -+ if (rv != SECSuccess) -+ return -1; -+ rv = ssl3_AppendHandshakeNumber(ss, 0 /* empty extension */, 2); -+ if (rv != SECSuccess) -+ return -1; -+ if (!ss->sec.isServer) { -+ TLSExtensionData *xtnData = &ss->xtnData; -+ xtnData->advertised[xtnData->numAdvertised++] = ssl_snap_start_xtn; -+ } -+ } -+ return 4; -+} -+ -+static SECStatus -+ssl3_BufferEnsure(sslBuffer *buf, unsigned int extra_bytes) -+{ -+ if (buf->space < buf->len + extra_bytes) -+ return sslBuffer_Grow(buf, buf->len + extra_bytes); -+ return SECSuccess; -+} -+ -+/* ssl3_AppendSnapStartRecordHeader appends a 5 byte TLS record header to the -+ * sendBuf of the given sslSocket. */ -+static SECStatus -+ssl3_AppendSnapStartRecordHeader(sslSocket *ss, SSL3ContentType type, -+ unsigned int len) -+{ -+ SECStatus rv; -+ -+ rv = ssl3_BufferEnsure(&ss->sec.ci.sendBuf, 5); -+ if (rv != SECSuccess) -+ return rv; -+ ss->sec.ci.sendBuf.buf[ss->sec.ci.sendBuf.len + 0] = type; -+ PutBE16(&ss->sec.ci.sendBuf.buf[ss->sec.ci.sendBuf.len + 1], ss->version); -+ PutBE16(&ss->sec.ci.sendBuf.buf[ss->sec.ci.sendBuf.len + 3], len); -+ ss->sec.ci.sendBuf.len += 5; -+ return SECSuccess; -+} -+ -+/* ssl3_AppendSnapStartHandshakeRecord appends a (possibly encrypted) record to -+** the sendBuf of the given sslSocket. -+** f: a function which will append the bytes of the record (not including the -+** 5 byte header) to the sendBuf. -+*/ -+static SECStatus -+ssl3_AppendSnapStartHandshakeRecord(sslSocket *ss, SECStatus (*f) (sslSocket*), -+ PRBool encrypt) -+{ -+ SECStatus rv; -+ unsigned int record_offset, record_len; -+ -+ /* ssl3_CompressMACEncryptRecord will deal with the record header if we are -+ * encrypting. */ -+ if (!encrypt) { -+ /* The zero length argument here is a dummy value. We write the real -+ * length once we know it, below. */ -+ rv = ssl3_AppendSnapStartRecordHeader(ss, content_handshake, 0); -+ if (rv != SECSuccess) -+ return rv; -+ } -+ -+ record_offset = ss->sec.ci.sendBuf.len; -+ rv = f(ss); -+ if (rv != SECSuccess) -+ return rv; -+ record_len = ss->sec.ci.sendBuf.len - record_offset; -+ if (!encrypt) { -+ PutBE16(&ss->sec.ci.sendBuf.buf[record_offset - 2], record_len); -+ } else { -+ /* ssl3_CompressMACEncryptRecord writes to |ss->sec.writeBuf| -+ * so we copy it back to |ss->sec.ci.sendBuf| */ -+ /* TODO(agl): the buffer copy here is a bodge. See TODO at the top of -+ * the file. */ -+ rv = ssl3_CompressMACEncryptRecord( -+ ss, content_handshake, -+ &ss->sec.ci.sendBuf.buf[record_offset], record_len); -+ if (rv != SECSuccess) -+ return rv; -+ ss->sec.ci.sendBuf.len -= record_len; -+ ssl3_BufferEnsure(&ss->sec.ci.sendBuf, ss->sec.writeBuf.len); -+ memcpy(&ss->sec.ci.sendBuf.buf[record_offset], ss->sec.writeBuf.buf, -+ ss->sec.writeBuf.len); -+ ss->sec.ci.sendBuf.len += ss->sec.writeBuf.len; -+ ss->sec.writeBuf.len = 0; -+ } -+ -+ return SECSuccess; -+} -+ -+/* ssl3_AppendSnapStartApplicationData appends an encrypted Application Data -+** record the sendBuf of the given sslSocket. -+*/ -+static SECStatus ssl3_AppendSnapStartApplicationData( -+ sslSocket *ss, const SSL3Opaque *data, unsigned int len) -+{ -+ SECStatus rv; -+ -+ /* TODO(agl): the buffer copy here is a bodge. See TODO at the top of the -+ * file. */ -+ rv = ssl3_CompressMACEncryptRecord(ss, content_application_data, data, len); -+ if (rv != SECSuccess) -+ return rv; -+ rv = ssl3_BufferEnsure(&ss->sec.ci.sendBuf, ss->sec.writeBuf.len); -+ if (rv != SECSuccess) -+ return rv; -+ memcpy(&ss->sec.ci.sendBuf.buf[ss->sec.ci.sendBuf.len], -+ ss->sec.writeBuf.buf, ss->sec.writeBuf.len); -+ ss->sec.ci.sendBuf.len += ss->sec.writeBuf.len; -+ ss->sec.writeBuf.len = 0; -+ -+ return SECSuccess; -+} -+ -+static SECStatus ssl3_SendSnapStartFinished(sslSocket *ss) -+{ -+ /* We use ssl_SEND_FLAG_NO_FLUSH here because this finished message is -+ * going to end up in the middle of the Snap Start extension. So -+ * transmitting |sendBuf| at this point would result in an incomplete -+ * ClientHello. */ -+ return ssl3_SendFinished(ss, ssl_SEND_FLAG_NO_FLUSH); -+} -+ -+/* ssl3_FindOrbit is called for each extension in a ServerHello message. It -+** tests for a Snap Start extension and records the server's orbit when found. -+** data: the extension data (including the four type and length bytes) -+** length: the length, in bytes, of |data| -+** ptr: a pointer to a uint8_t[9]. The orbit, if found, is copied into the -+** first 8 bytes and then the ninth byte is set to one. -+*/ -+static void -+ssl3_FindOrbit(const unsigned char *data, unsigned int length, void *ptr) -+{ -+ unsigned char *orbit = (unsigned char *) ptr; -+ -+ unsigned int extension_num = GetBE16(data); -+ if (extension_num == ssl_snap_start_xtn && -+ length == 4 + 8 /* orbit */ + 2 /* snap start cipher suite */) { -+ memcpy(orbit, data + 4, 8); -+ /* A last byte of 1 indicates that the previous eight are valid. */ -+ orbit[8] = 1; -+ } -+} -+ -+/* ssl3_CanSnapStart returns true if we are able to perform Snap Start on -+** the given socket. -+** extensions: on successful return, this is filled in with the contents of -+** the server's predicted extensions. This points within -+** |ss->ssl3.serverHelloPredictionData|. -+** resuming: PR_TRUE iff we wish to attempt a Snap Start resume -+** out_orbit: if this function returns PR_TRUE, then |out_orbit| is filled -+** with the server's predicted orbit value. -+** The |hs.cipher_suite|, |hs.cipher_def| and |hs.compression| fields of |ss| -+** are set to match the predicted ServerHello on successful exit (and may still -+** be modified on failure). -+*/ -+static PRBool -+ssl3_CanSnapStart(sslSocket *ss, SECItem *extensions, PRBool resuming, -+ unsigned char out_orbit[8]) { -+ const unsigned char *server_hello; -+ unsigned int server_hello_len, session_id_len, cipher_suite_offset; -+ unsigned int extensions_offset, cipher_suite, compression_method; -+ unsigned char orbit[9]; -+ SECStatus rv; -+ SSL3ProtocolVersion version; -+ -+ /* If we don't have the information needed then we can't perform a Snap -+ * Start. */ -+ if (!ss->ssl3.predictedCertChain || !ss->ssl3.serverHelloPredictionData.data) -+ return PR_FALSE; -+ -+ /* When the sizes of the fields in the ClientHello are calculated, they'll -+ * take the length of the Snap Start extension to be zero, so currently -+ * it's as if this extension didn't exist, which is the state that we -+ * need. */ -+ -+ server_hello = ss->ssl3.serverHelloPredictionData.data; -+ server_hello_len = ss->ssl3.serverHelloPredictionData.len; -+ -+ if (server_hello_len < 2 + 32 + 1) -+ return PR_FALSE; -+ session_id_len = server_hello[2 + 32]; -+ cipher_suite_offset = 2 + 32 + 1 + session_id_len; -+ if (server_hello_len < cipher_suite_offset + 3) -+ return PR_FALSE; -+ extensions_offset = cipher_suite_offset + 3; -+ -+ version = (SSL3ProtocolVersion) GetBE16(server_hello); -+ if (MSB(version) < MSB(SSL_LIBRARY_VERSION_3_0)) -+ return PR_FALSE; -+ rv = ssl3_NegotiateVersion(ss, version); -+ if (rv != SECSuccess) -+ return PR_FALSE; -+ -+ cipher_suite = GetBE16(&server_hello[cipher_suite_offset]); -+ ss->ssl3.hs.cipher_suite = (ssl3CipherSuite)cipher_suite; -+ ss->ssl3.hs.suite_def = ssl_LookupCipherSuiteDef(ss->ssl3.hs.cipher_suite); -+ if (!ss->ssl3.hs.suite_def) -+ return PR_FALSE; -+ compression_method = server_hello[cipher_suite_offset + 2]; -+ if (compression_method != ssl_compression_null) { -+ /* TODO(agl): support compression. */ -+ return PR_FALSE; -+ } -+ ss->ssl3.hs.compression = ssl_compression_null; -+ -+ extensions->data = (unsigned char *) server_hello + extensions_offset; -+ extensions->len = server_hello_len - extensions_offset; -+ -+ /* The last byte is used to indictate that the previous eight are valid. */ -+ orbit[8] = 0; -+ if (!ssl3_ForEachExtension(extensions, resuming, ssl3_FindOrbit, orbit)) -+ return PR_FALSE; -+ -+ if (!orbit[8]) -+ return PR_FALSE; -+ -+ memcpy(out_orbit, orbit, 8); -+ -+ return PR_TRUE; -+} -+ -+/* ssl3_UpdateClientHelloLengths rewrites the handshake header length and -+** extensions length in the ClientHello to reflect the addition of the Snap -+** Start extension. -+** snap_start_extension_len_offset: the number of bytes of the ClientHello to -+** skip in order to find the embedded length of the Snap Start extension. -+*/ -+static void -+ssl3_UpdateClientHelloLengths(sslSocket *ss, -+ unsigned int snap_start_extension_len_offset, -+ sslSessionID *sid) { -+ unsigned int extension_length, old_length, new_length, new_session_id_len; -+ unsigned int offset, ciphers_length, compressions_len; -+ -+ extension_length = -+ ss->sec.ci.sendBuf.len - snap_start_extension_len_offset - 2; -+ PutBE16(&ss->sec.ci.sendBuf.buf[snap_start_extension_len_offset], -+ extension_length); -+ -+ /* The length in the handshake header is short by extension_length + 4 -+ * bytes. */ -+ old_length = GetBE24(&ss->sec.ci.sendBuf.buf[1]); -+ new_length = old_length + extension_length + 4; -+ PutBE24(&ss->sec.ci.sendBuf.buf[1], new_length); -+ -+ /* The length of the extensions block is similarly wrong. */ -+ new_session_id_len = 0; -+ if (sid) -+ new_session_id_len = sid->u.ssl3.sessionIDLength; -+ offset = 4 + 2 + 32 + 1 + new_session_id_len; -+ ciphers_length = GetBE16(&ss->sec.ci.sendBuf.buf[offset]); -+ offset += 2 + ciphers_length; -+ compressions_len = ss->sec.ci.sendBuf.buf[offset]; -+ offset += 1 + compressions_len; -+ old_length = GetBE16(&ss->sec.ci.sendBuf.buf[offset]); -+ new_length = old_length + extension_length + 4; -+ PutBE16(&ss->sec.ci.sendBuf.buf[offset], new_length); -+} -+ -+/* ssl3_FindServerNPNExtension is a callback function for ssl3_ForEachExtension. -+ * It looks for a Next Protocol Negotiation and saves the payload of the -+ * extension in the given SECItem */ -+static void -+ssl3_FindServerNPNExtension(const unsigned char* data, unsigned int length, -+ void *ctx) -+{ -+ SECItem *server_npn_extension = (SECItem*) ctx; -+ -+ unsigned int extension_num = GetBE16(data); -+ if (extension_num == ssl_next_proto_neg_xtn && length >= 4) { -+ server_npn_extension->data = (unsigned char*)data + 4; -+ server_npn_extension->len = length - 4; -+ } -+} -+ -+/* ssl3_MaybeWriteNextProtocol deals with the interaction of Next Protocol -+ * Negotiation and Snap Start. It's called just before we serialise the embedded -+ * Finished message in the extension. At this point, if NPN is enabled, we have -+ * to include a NextProtocol message. */ -+static SECStatus -+ssl3_MaybeWriteNextProtocol(sslSocket *ss, SECItem *server_hello_extensions) -+{ -+ PRUint16 i16; -+ SECItem server_npn_extension; -+ -+ for (i16 = 0; i16 < ss->xtnData.numAdvertised; i16++) { -+ if (ss->xtnData.advertised[i16] == ssl_next_proto_neg_xtn) -+ break; -+ } -+ -+ if (i16 == ss->xtnData.numAdvertised) { -+ /* We didn't send an NPN extension, so no need to do anything here. */ -+ return SECSuccess; -+ } -+ -+ memset(&server_npn_extension, 0, sizeof(server_npn_extension)); -+ -+ ssl3_ForEachExtension( -+ server_hello_extensions, PR_FALSE /* is_resuming: value doesn't matter -+ in this case */, ssl3_FindServerNPNExtension, &server_npn_extension); -+ -+ if (server_npn_extension.data == NULL) { -+ /* We predicted that the server doesn't support NPN, so nothing to do -+ * here. */ -+ return SECSuccess; -+ } -+ -+ ssl3_ClientHandleNextProtoNegoXtn(ss, ssl_next_proto_neg_xtn, -+ &server_npn_extension); -+ -+ if (ss->ssl3.nextProtoState == SSL_NEXT_PROTO_NO_SUPPORT) { -+ /* The server's predicted NPN extension was malformed. We're didn't pick -+ * a protocol so we won't send a NextProtocol message. However, this is -+ * probably fatal to the connection. */ -+ return SECSuccess; -+ } -+ -+ return ssl3_AppendSnapStartHandshakeRecord(ss, ssl3_SendNextProto, -+ PR_TRUE /* encrypt */); -+} -+ -+/* ssl3_SendSnapStartXtn appends a Snap Start extension. It assumes that the -+ * inchoate ClientHello is in |ss->sec.ci.sendBuf|. */ -+PRInt32 -+ssl3_SendSnapStartXtn(sslSocket *ss, PRBool append, PRUint32 maxBytes) -+{ -+ unsigned char orbit[8]; -+ PRBool resuming = PR_FALSE; -+ unsigned char suggested_server_random[32]; -+ SECStatus rv; -+ PRUint64 fnv; -+ /* The context for |ssl3_SnapStartHash|. The first pointer points to |ss| -+ * and the second to the running FNV1A64 hash of the predicted server -+ * response. */ -+ void *ctx[2]; -+ unsigned int snap_start_extension_len_offset, original_sendbuf_len; -+ ssl3CipherSpec *temp; -+ sslSessionID *sid; -+ SECItem server_extensions; -+ -+ if (!ss->opt.enableSnapStart) -+ return 0; -+ -+ original_sendbuf_len = ss->sec.ci.sendBuf.len; -+ -+ /* This function is called twice for each ClientHello emitted. The first -+ * time around is to calculate the sizes of the extension (|append| is -+ * false). The second time around is to actually write out the bytes -+ * (|append| is true). -+ * -+ * We always return 0 bytes in each case because we want to be able to hash -+ * the inchoate ClientHello as if this extension was missing: that's why -+ * it's important that this always be the last extension serialised. */ -+ sid = ss->sec.ci.sid; -+ -+ if (!ss->opt.enableSessionTickets || ss->sec.isServer) -+ return 0; -+ -+ /* If we are sending a SessionTicket then the first time around -+ * ticketTimestampVerified will be true but it's reset after serialising -+ * the session ticket extension, so we have -+ * |clientSentNonEmptySessionTicket|. */ -+ if (ss->xtnData.clientSentNonEmptySessionTicket) { -+ resuming = PR_TRUE; -+ } else if (sid->u.ssl3.sessionTicket.ticket.data && -+ ss->xtnData.ticketTimestampVerified) { -+ resuming = PR_TRUE; -+ } -+ -+ if (!ssl3_CanSnapStart(ss, &server_extensions, resuming, orbit)) -+ return ssl3_SendEmptySnapStartXtn(ss, append, maxBytes); -+ -+ /* At this point we are happy that we are going to send a non-empty Snap -+ * Start extension. If we are still calculating length then we lie and -+ * return 0 so that everything is set up as if the extension didn't exist -+ * when this function is called again later. */ -+ -+ if (!append) -+ return 0; -+ -+ /* |ss->sec.ci.sendBuf.buf| contains the inchoate ClientHello. This copies -+ * the ClientHello's gmt_unix_time into the suggested server random. */ -+ memcpy(suggested_server_random, ss->sec.ci.sendBuf.buf + 6, 4); -+ memcpy(suggested_server_random + 4, orbit, 8); -+ rv = PK11_GenerateRandom(suggested_server_random + 12, 20); -+ if (rv != SECSuccess) -+ goto loser; -+ memcpy(ss->ssl3.serverHelloPredictionData.data + 2, suggested_server_random, -+ 32); -+ -+ memcpy(&ss->ssl3.hs.server_random, suggested_server_random, 32); -+ -+ PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) ); -+ rv = ssl3_SetupPendingCipherSpec(ss); -+ if (rv != SECSuccess) -+ goto loser; -+ ss->ssl3.hs.isResuming = resuming; -+ -+ FNV1A64_Init(&fnv); -+ ctx[0] = ss; -+ ctx[1] = &fnv; -+ -+ if (!ssl3_PredictServerResponse(ss, &ss->ssl3.serverHelloPredictionData, -+ resuming, ssl3_SnapStartHash, ctx)) { -+ /* It's not a fatal error if the predicted ServerHello was invalid. */ -+ return 0; -+ } -+ FNV1A64_Final(&fnv); -+ -+ /* Now we grow the send buffer to accomodate the extension type and length, -+ * orbit, suggested random and predicted server response hash without -+ * calling ssl3_AppendHandshake (which would also update the Finished -+ * hash). */ -+ if (ssl3_BufferEnsure(&ss->sec.ci.sendBuf, 4 + 8 + 20 + 8) != SECSuccess) -+ goto loser; -+ -+ PutBE16(&ss->sec.ci.sendBuf.buf[ss->sec.ci.sendBuf.len], -+ ssl_snap_start_xtn); -+ ss->sec.ci.sendBuf.len += 2; -+ /* Skip over the length for now. */ -+ snap_start_extension_len_offset = ss->sec.ci.sendBuf.len; -+ ss->sec.ci.sendBuf.len += 2; -+ memcpy(ss->sec.ci.sendBuf.buf + ss->sec.ci.sendBuf.len, orbit, 8); -+ ss->sec.ci.sendBuf.len += 8; -+ memcpy(&ss->sec.ci.sendBuf.buf[ss->sec.ci.sendBuf.len], -+ suggested_server_random + 12, 20); -+ ss->sec.ci.sendBuf.len += 20; -+ memcpy(ss->sec.ci.sendBuf.buf + ss->sec.ci.sendBuf.len, &fnv, 8); -+ ss->sec.ci.sendBuf.len += 8; -+ -+ if (!resuming) { -+ /* Write ClientKeyExchange */ -+ ss->sec.peerCert = -+ CERT_DupCertificate(ss->ssl3.predictedCertChain[0]); -+ rv = ssl3_AppendSnapStartHandshakeRecord( -+ ss, ssl3_SendClientKeyExchange, PR_FALSE /* do not encrypt */); -+ if (rv != SECSuccess) -+ goto loser; -+ } else { -+ SSL3Finished hashes; -+ TLSFinished tlsFinished; -+ unsigned char hdr[4]; -+ -+ rv = ssl3_SetupMasterSecretFromSessionID(ss); -+ if (rv == SECFailure) -+ goto loser; -+ -+ if (sid->peerCert != NULL) { -+ ss->sec.peerCert = CERT_DupCertificate(sid->peerCert); -+ ssl3_CopyPeerCertsFromSID(ss, sid); -+ } -+ -+ rv = ssl3_InitPendingCipherSpec(ss, NULL /* re-use master secret */); -+ if (rv != SECSuccess) -+ goto loser; -+ -+ /* Need to add the server's predicted Finished message to our handshake -+ * hash in order to be able to produce our own Finished message. */ -+ rv = ssl3_ComputeHandshakeHashes(ss, ss->ssl3.pwSpec, &hashes, -+ 0 /* only for SSL3 */); -+ if (rv != SECSuccess) -+ goto loser; -+ -+ rv = ssl3_ComputeTLSFinished(ss->ssl3.pwSpec, PR_TRUE /* isServer */, -+ &hashes, &tlsFinished); -+ if (rv != SECSuccess) -+ goto loser; -+ -+ hdr[0] = (unsigned char) finished; -+ hdr[1] = hdr[2] = 0; -+ hdr[3] = sizeof(tlsFinished.verify_data); -+ ssl3_UpdateHandshakeHashes(ss, hdr, sizeof(hdr)); -+ ssl3_UpdateHandshakeHashes(ss, tlsFinished.verify_data, -+ sizeof(tlsFinished.verify_data)); -+ -+ /* Store the Finished message so that we can verify it later */ -+ memcpy(&ss->ssl3.hs.finishedMsgs.tFinished[1], tlsFinished.verify_data, -+ sizeof(tlsFinished.verify_data)); -+ } -+ -+ /* Write ChangeCipherSpec */ -+ rv = ssl3_AppendSnapStartRecordHeader(ss, content_change_cipher_spec, 1); -+ if (rv != SECSuccess) -+ goto loser; -+ rv = ssl3_BufferEnsure(&ss->sec.ci.sendBuf, 1); -+ if (rv != SECSuccess) -+ goto loser; -+ ss->sec.ci.sendBuf.buf[ss->sec.ci.sendBuf.len] = change_cipher_spec_choice; -+ ss->sec.ci.sendBuf.len++; -+ -+ /* We swap |cwSpec| and |pwSpec| temporarily in order to encrypt some -+ * records before switching them back so that the whole ClientHello doesn't -+ * get encrypted. */ -+ ssl_GetSpecWriteLock(ss); -+ temp = ss->ssl3.cwSpec; -+ ss->ssl3.cwSpec = ss->ssl3.pwSpec; -+ ss->ssl3.pwSpec = temp; -+ ss->ssl3.cwSpec->write_seq_num.high = 0; -+ ss->ssl3.cwSpec->write_seq_num.low = 0; -+ ssl_ReleaseSpecWriteLock(ss); -+ -+ rv = ssl3_MaybeWriteNextProtocol(ss, &server_extensions); -+ if (rv != SECSuccess) -+ goto loser; -+ -+ /* Write Finished */ -+ rv = ssl3_AppendSnapStartHandshakeRecord(ss, ssl3_SendSnapStartFinished, -+ PR_TRUE /* encrypt */); -+ if (rv != SECSuccess) -+ goto loser; -+ -+ /* Write application data */ -+ if (ss->ssl3.snapStartApplicationData.data) { -+ rv = ssl3_AppendSnapStartApplicationData( -+ ss, ss->ssl3.snapStartApplicationData.data, -+ ss->ssl3.snapStartApplicationData.len); -+ if (rv != SECSuccess) -+ goto loser; -+ } -+ -+ /* Revert the write cipher spec because the ClientHello will get encrypted -+ * with it otherwise. */ -+ ssl_GetSpecWriteLock(ss); -+ temp = ss->ssl3.cwSpec; -+ ss->ssl3.cwSpec = ss->ssl3.pwSpec; -+ ss->ssl3.pwSpec = temp; -+ ssl_ReleaseSpecWriteLock(ss); -+ -+ /* Update the lengths in the ClientHello to reflect this extension. */ -+ ssl3_UpdateClientHelloLengths(ss, snap_start_extension_len_offset, sid); -+ -+ /* Keep a copy of the ClientHello around so that we can hash it in the case -+ * the the Snap Start handshake is rejected. */ -+ -+ if (SECITEM_AllocItem(NULL, &ss->ssl3.hs.origClientHello, -+ ss->sec.ci.sendBuf.len) == NULL) { -+ goto loser; -+ } -+ memcpy(ss->ssl3.hs.origClientHello.data, ss->sec.ci.sendBuf.buf, -+ ss->sec.ci.sendBuf.len); -+ ss->ssl3.hs.origClientHello.len = ss->sec.ci.sendBuf.len; -+ -+ ss->xtnData.advertised[ss->xtnData.numAdvertised++] = ssl_snap_start_xtn; -+ -+ if (resuming) { -+ ss->ssl3.hs.snapStartType = snap_start_resume; -+ } else { -+ ss->ssl3.hs.snapStartType = snap_start_full; -+ } -+ -+ return 0; -+ -+loser: -+ /* In the case of an error we revert the length of the sendBuf to remove -+ * any partial data that we may have appended. */ -+ ss->sec.ci.sendBuf.len = original_sendbuf_len; -+ return -1; -+} -+ -+SECStatus ssl3_ClientHandleSnapStartXtn(sslSocket *ss, PRUint16 ex_type, -+ SECItem *data) { -+ /* The work of saving the ServerHello is done in ssl3_HandleServerHello, -+ * where its contents are available. Here we renognise that the saved -+ * ServerHello message contains a Snap Start extension and mark it as -+ * valid. */ -+ ss->ssl3.serverHelloPredictionDataValid = PR_TRUE; -+ return SECSuccess; -+} -+ -+SECStatus -+SSL_SetPredictedPeerCertificates(PRFileDesc *fd, CERTCertificate **certs, -+ unsigned int numCerts) -+{ -+ sslSocket *ss; -+ unsigned int i; -+ -+ ss = ssl_FindSocket(fd); -+ if (!ss) { -+ SSL_DBG(("%d: SSL[%d]: bad socket in SSL_SetPredictedPeerCertificates", -+ SSL_GETPID(), fd)); -+ return SECFailure; -+ } -+ -+ ss->ssl3.predictedCertChain = -+ PORT_NewArray(CERTCertificate*, numCerts + 1); -+ if (!ss->ssl3.predictedCertChain) -+ return SECFailure; /* error code was set */ -+ for (i = 0; i < numCerts; i++) -+ ss->ssl3.predictedCertChain[i] = CERT_DupCertificate(certs[i]); -+ ss->ssl3.predictedCertChain[numCerts] = NULL; -+ -+ return SECSuccess; -+} -+ -+void -+ssl3_CleanupPredictedPeerCertificates(sslSocket *ss) { -+ unsigned int i; -+ -+ if (!ss->ssl3.predictedCertChain) -+ return; -+ -+ for (i = 0; ss->ssl3.predictedCertChain[i]; i++) { -+ CERT_DestroyCertificate(ss->ssl3.predictedCertChain[i]); -+ } -+ -+ PORT_Free(ss->ssl3.predictedCertChain); -+ ss->ssl3.predictedCertChain = NULL; -+} -+ -+SECStatus -+SSL_GetPredictedServerHelloData(PRFileDesc *fd, const unsigned char **data, -+ unsigned int *data_len) -+{ -+ sslSocket *ss; -+ -+ ss = ssl_FindSocket(fd); -+ if (!ss) { -+ SSL_DBG(("%d: SSL[%d]: bad socket in SSL_GetPredictedServerHelloData", -+ SSL_GETPID(), fd)); -+ *data = NULL; -+ *data_len = 0; -+ return SECFailure; -+ } -+ -+ if (!ss->ssl3.serverHelloPredictionDataValid) { -+ *data = NULL; -+ *data_len = 0; -+ } else { -+ *data = ss->ssl3.serverHelloPredictionData.data; -+ *data_len = ss->ssl3.serverHelloPredictionData.len; -+ } -+ return SECSuccess; -+} -+ -+SECStatus -+SSL_SetPredictedServerHelloData(PRFileDesc *fd, const unsigned char *data, -+ unsigned int data_len) -+{ -+ sslSocket *ss; -+ -+ ss = ssl_FindSocket(fd); -+ if (!ss) { -+ SSL_DBG(("%d: SSL[%d]: bad socket in SSL_SetPredictedServerHelloData", -+ SSL_GETPID(), fd)); -+ return SECFailure; -+ } -+ -+ if (ss->ssl3.serverHelloPredictionData.data) -+ SECITEM_FreeItem(&ss->ssl3.serverHelloPredictionData, PR_FALSE); -+ if (!SECITEM_AllocItem(NULL, &ss->ssl3.serverHelloPredictionData, data_len)) -+ return SECFailure; -+ memcpy(ss->ssl3.serverHelloPredictionData.data, data, data_len); -+ return SECSuccess; -+} -+ -+SECStatus -+SSL_SetSnapStartApplicationData(PRFileDesc *fd, const unsigned char *data, -+ unsigned int data_len) -+{ -+ sslSocket *ss; -+ -+ ss = ssl_FindSocket(fd); -+ if (!ss) { -+ SSL_DBG(("%d: SSL[%d]: bad socket in SSL_SetSnapStartApplicationData", -+ SSL_GETPID(), fd)); -+ return SECFailure; -+ } -+ -+ if (ss->ssl3.snapStartApplicationData.data) -+ SECITEM_FreeItem(&ss->ssl3.snapStartApplicationData, PR_FALSE); -+ if (!SECITEM_AllocItem(NULL, &ss->ssl3.snapStartApplicationData, data_len)) -+ return SECFailure; -+ memcpy(ss->ssl3.snapStartApplicationData.data, data, data_len); -+ return SECSuccess; -+} -+ -+SECStatus -+SSL_GetSnapStartResult(PRFileDesc *fd, SSLSnapStartResult *result) -+{ -+ sslSocket *ss; -+ -+ ss = ssl_FindSocket(fd); -+ if (!ss) { -+ SSL_DBG(("%d: SSL[%d]: bad socket in SSL_GetSnapStartResult", -+ SSL_GETPID(), fd)); -+ return SECFailure; -+ } -+ -+ switch (ss->ssl3.hs.snapStartType) { -+ case snap_start_full: -+ *result = SSL_SNAP_START_FULL; -+ break; -+ case snap_start_recovery: -+ *result = SSL_SNAP_START_RECOVERY; -+ break; -+ case snap_start_resume: -+ *result = SSL_SNAP_START_RESUME; -+ break; -+ case snap_start_resume_recovery: -+ *result = SSL_SNAP_START_RESUME_RECOVERY; -+ break; -+ default: -+ PORT_Assert(ss->ssl3.hs.snapStartType == snap_start_none); -+ *result = SSL_SNAP_START_NONE; -+ break; -+ } -+ -+ return SECSuccess; -+} -+ -+/* Called form ssl3_HandleServerHello in the case that we sent a Snap Start -+** ClientHello but received a ServerHello in reply. -+*/ -+SECStatus -+ssl3_ResetForSnapStartRecovery(sslSocket *ss, SSL3Opaque *b, PRUint32 length) -+{ -+ SECStatus rv; -+ PRUint8 hdr[4]; -+ -+ ss->ssl3.hs.ws = wait_server_hello; -+ -+ /* Need to reset the Finished hashes to include the full ClientHello -+ * message. */ -+ -+ rv = ssl3_RestartHandshakeHashes(ss); -+ if (rv != SECSuccess) -+ return rv; -+ rv = ssl3_UpdateHandshakeHashes(ss, ss->ssl3.hs.origClientHello.data, -+ ss->ssl3.hs.origClientHello.len); -+ SECITEM_FreeItem(&ss->ssl3.hs.origClientHello, PR_FALSE); -+ if (rv != SECSuccess) -+ return rv; -+ -+ hdr[0] = (PRUint8)server_hello; -+ hdr[1] = (PRUint8)(length >> 16); -+ hdr[2] = (PRUint8)(length >> 8); -+ hdr[3] = (PRUint8)(length ); -+ -+ rv = ssl3_UpdateHandshakeHashes(ss, hdr, sizeof(hdr)); -+ if (rv != SECSuccess) -+ return rv; -+ rv = ssl3_UpdateHandshakeHashes(ss, b, length); -+ if (rv != SECSuccess) -+ return rv; -+ -+ if (ss->ssl3.hs.snapStartType == snap_start_full) { -+ ss->ssl3.hs.snapStartType = snap_start_recovery; -+ } else { -+ ss->ssl3.hs.snapStartType = snap_start_resume_recovery; -+ } -+ -+ ssl3_DestroyCipherSpec(ss->ssl3.pwSpec, PR_TRUE/*freeSrvName*/); -+ -+ return SECSuccess; -+} -diff --git a/mozilla/security/nss/lib/ssl/ssl.def b/mozilla/security/nss/lib/ssl/ssl.def -index a1f4b51..effc35d 100644 ---- a/mozilla/security/nss/lib/ssl/ssl.def -+++ b/mozilla/security/nss/lib/ssl/ssl.def -@@ -159,3 +159,13 @@ SSL_SetNextProtoNego; - ;+ local: - ;+*; - ;+}; -+;+NSS_3.13 { # NSS 3.13 release -+;+ global: -+SSL_GetPredictedServerHelloData; -+SSL_GetSnapStartResult; -+SSL_SetPredictedPeerCertificates; -+SSL_SetPredictedServerHelloData; -+SSL_SetSnapStartApplicationData; -+;+ local: -+;+*; -+;+}; -diff --git a/mozilla/security/nss/lib/ssl/ssl.h b/mozilla/security/nss/lib/ssl/ssl.h -index d87ae56..8217d2e 100644 ---- a/mozilla/security/nss/lib/ssl/ssl.h -+++ b/mozilla/security/nss/lib/ssl/ssl.h -@@ -139,6 +139,15 @@ SSL_IMPORT PRFileDesc *SSL_ImportFD(PRFileDesc *model, PRFileDesc *fd); - /* occur on RSA or DH ciphersuites where the cipher's key length is >= 80 */ - /* bits. The advantage of False Start is that it saves a round trip for */ - /* client-speaks-first protocols when performing a full handshake. */ -+#define SSL_ENABLE_SNAP_START 23 /* Enable SSL snap start (off by */ -+ /* default, applies only to */ -+ /* clients). Snap start is a way */ -+/* of performing TLS handshakes with no round trips. The client's entire */ -+/* handshake is included in the first handshake message, along with */ -+/* optional application data. In order to do this, information from a */ -+/* previous connection to the same server is required. See */ -+/* SSL_GetPredictedServerHelloData, SSL_SetPredictedPeerCertificates and */ -+/* SSL_SetSnapStartApplicationData. */ - - #ifdef SSL_DEPRECATED_FUNCTION - /* Old deprecated function names */ -@@ -376,6 +385,49 @@ SSL_IMPORT SECStatus SSL_BadCertHook(PRFileDesc *fd, SSLBadCertHandler f, - void *arg); - - /* -+** Set the predicted chain of certificates for the peer. This is used for the -+** TLS Snap Start extension. Note that the SSL_ENABLE_SNAP_START option must -+** be set for this to occur. -+** -+** This function takes a reference to each of the given certificates. -+*/ -+SSL_IMPORT SECStatus SSL_SetPredictedPeerCertificates( -+ PRFileDesc *fd, CERTCertificate **certs, -+ unsigned int numCerts); -+ -+/* -+** Get the data needed to predict the server's hello message in the future. On -+** return, |*data| will either be NULL (in which case no data is available and -+** |*data_len| will be zero) or it will point to a buffer within the internal -+** data of |fd| and |*data_len| will contain the number of bytes available. If -+** non-NULL, |*data| will persist at least until the next handshake on |fd|. -+*/ -+SSL_IMPORT SECStatus SSL_GetPredictedServerHelloData( -+ PRFileDesc *fd, const unsigned char **data, -+ unsigned int *data_len); -+ -+/* -+** Set the predicted server hello data. This is used for the TLS Snap Start -+** extension. Note that the SSL_ENABLE_SNAP_START option must be set for this -+** to occur. -+*/ -+SSL_IMPORT SECStatus SSL_SetPredictedServerHelloData( -+ PRFileDesc *fd, const unsigned char *data, unsigned int data_len); -+ -+/* Set the application data which will be transmitted in a Snap Start -+** handshake. If the Snap Start handshake fails, this data will be -+* retransmitted automatically. */ -+SSL_IMPORT SECStatus SSL_SetSnapStartApplicationData( -+ PRFileDesc *fd, const unsigned char *data, unsigned int data_len); -+ -+/* Get the result of a Snap Start handshake. It's valid to call then even if -+** SSL_ENABLE_SNAP_START hasn't been set, although the result will always be -+** SSL_SNAP_START_NONE. -+*/ -+SSL_IMPORT SECStatus SSL_GetSnapStartResult(PRFileDesc* socket, -+ SSLSnapStartResult* result); -+ -+/* - ** Configure SSL socket for running a secure server. Needs the - ** certificate for the server and the servers private key. The arguments - ** are copied. -diff --git a/mozilla/security/nss/lib/ssl/ssl3con.c b/mozilla/security/nss/lib/ssl/ssl3con.c -index 64c3452..9ab2a1c 100644 ---- a/mozilla/security/nss/lib/ssl/ssl3con.c -+++ b/mozilla/security/nss/lib/ssl/ssl3con.c -@@ -72,7 +72,8 @@ - #endif - - static void ssl3_CleanupPeerCerts(sslSocket *ss); --static void ssl3_CopyPeerCertsFromSID(sslSocket *ss, sslSessionID *sid); -+static void ssl3_CopyPeerCertsToSID(ssl3CertNode *certs, -+ sslSessionID *sid); - static PK11SymKey *ssl3_GenerateRSAPMS(sslSocket *ss, ssl3CipherSpec *spec, - PK11SlotInfo * serverKeySlot); - static SECStatus ssl3_DeriveMasterSecret(sslSocket *ss, PK11SymKey *pms); -@@ -82,14 +83,10 @@ static SECStatus ssl3_InitState( sslSocket *ss); - static SECStatus ssl3_SendCertificate( sslSocket *ss); - static SECStatus ssl3_SendEmptyCertificate( sslSocket *ss); - static SECStatus ssl3_SendCertificateRequest(sslSocket *ss); --static SECStatus ssl3_SendNextProto( sslSocket *ss); --static SECStatus ssl3_SendFinished( sslSocket *ss, PRInt32 flags); - static SECStatus ssl3_SendServerHello( sslSocket *ss); - static SECStatus ssl3_SendServerHelloDone( sslSocket *ss); - static SECStatus ssl3_SendServerKeyExchange( sslSocket *ss); - static SECStatus ssl3_NewHandshakeHashes( sslSocket *ss); --static SECStatus ssl3_UpdateHandshakeHashes( sslSocket *ss, unsigned char *b, -- unsigned int l); - - static SECStatus Null_Cipher(void *ctx, unsigned char *output, int *outputLen, - int maxOutputLen, const unsigned char *input, -@@ -583,7 +580,7 @@ void SSL_AtomicIncrementLong(long * x) - - /* return pointer to ssl3CipherSuiteDef for suite, or NULL */ - /* XXX This does a linear search. A binary search would be better. */ --static const ssl3CipherSuiteDef * -+const ssl3CipherSuiteDef * - ssl_LookupCipherSuiteDef(ssl3CipherSuite suite) - { - int cipher_suite_def_len = -@@ -1169,7 +1166,7 @@ ssl3_CleanupKeyMaterial(ssl3KeyMaterial *mat) - ** ssl3_DestroySSL3Info - ** Caller must hold SpecWriteLock. - */ --static void -+void - ssl3_DestroyCipherSpec(ssl3CipherSpec *spec, PRBool freeSrvName) - { - PRBool freeit = (PRBool)(!spec->bypassCiphers); -@@ -1211,7 +1208,7 @@ ssl3_DestroyCipherSpec(ssl3CipherSpec *spec, PRBool freeSrvName) - ** Caller must hold the ssl3 handshake lock. - ** Acquires & releases SpecWriteLock. - */ --static SECStatus -+SECStatus - ssl3_SetupPendingCipherSpec(sslSocket *ss) - { - ssl3CipherSpec * pwSpec; -@@ -2039,7 +2036,7 @@ ssl3_ClientAuthTokenPresent(sslSessionID *sid) { - return isPresent; - } - --static SECStatus -+SECStatus - ssl3_CompressMACEncryptRecord(sslSocket * ss, - SSL3ContentType type, - const SSL3Opaque * pIn, -@@ -3097,7 +3094,7 @@ loser: - return SECFailure; - } - --static SECStatus -+SECStatus - ssl3_RestartHandshakeHashes(sslSocket *ss) - { - SECStatus rv = SECSuccess; -@@ -3175,7 +3172,7 @@ loser: - ** ssl3_HandleHandshakeMessage() - ** Caller must hold the ssl3Handshake lock. - */ --static SECStatus -+SECStatus - ssl3_UpdateHandshakeHashes(sslSocket *ss, unsigned char *b, unsigned int l) - { - SECStatus rv = SECSuccess; -@@ -3434,7 +3431,7 @@ ssl3_ConsumeHandshakeVariable(sslSocket *ss, SECItem *i, PRInt32 bytes, - * Caller must hold a read or write lock on the Spec R/W lock. - * (There is presently no way to assert on a Read lock.) - */ --static SECStatus -+SECStatus - ssl3_ComputeHandshakeHashes(sslSocket * ss, - ssl3CipherSpec *spec, /* uses ->master_secret */ - SSL3Hashes * hashes, /* output goes here. */ -@@ -4032,7 +4029,18 @@ ssl3_SendClientHello(sslSocket *ss) - return rv; /* error code set by ssl3_FlushHandshake */ - } - -- ss->ssl3.hs.ws = wait_server_hello; -+ switch (ss->ssl3.hs.snapStartType) { -+ case snap_start_full: -+ ss->ssl3.hs.ws = wait_new_session_ticket; -+ break; -+ case snap_start_resume: -+ ss->ssl3.hs.ws = wait_change_cipher; -+ break; -+ default: -+ ss->ssl3.hs.ws = wait_server_hello; -+ break; -+ } -+ - return rv; - } - -@@ -4723,7 +4731,7 @@ loser: - - - /* Called from ssl3_HandleServerHelloDone(). */ --static SECStatus -+SECStatus - ssl3_SendClientKeyExchange(sslSocket *ss) - { - SECKEYPublicKey * serverKey = NULL; -@@ -4862,6 +4870,94 @@ done: - return rv; - } - -+/* Called from ssl3_HandleServerHello to set up the master secret in -+ * ss->ssl3.pwSpec and the auth algorithm and kea type in ss->sec in the case -+ * of a successful session resumption. */ -+SECStatus ssl3_SetupMasterSecretFromSessionID(sslSocket* ss) { -+ sslSessionID *sid = ss->sec.ci.sid; -+ ssl3CipherSpec *pwSpec = ss->ssl3.pwSpec; -+ SECItem wrappedMS; /* wrapped master secret. */ -+ -+ ss->sec.authAlgorithm = sid->authAlgorithm; -+ ss->sec.authKeyBits = sid->authKeyBits; -+ ss->sec.keaType = sid->keaType; -+ ss->sec.keaKeyBits = sid->keaKeyBits; -+ -+ /* 3 cases here: -+ * a) key is wrapped (implies using PKCS11) -+ * b) key is unwrapped, but we're still using PKCS11 -+ * c) key is unwrapped, and we're bypassing PKCS11. -+ */ -+ if (sid->u.ssl3.keys.msIsWrapped) { -+ PK11SlotInfo *slot; -+ PK11SymKey * wrapKey; /* wrapping key */ -+ CK_FLAGS keyFlags = 0; -+ -+ if (ss->opt.bypassPKCS11) { -+ /* we cannot restart a non-bypass session in a -+ ** bypass socket. -+ */ -+ return SECFailure; -+ } -+ /* unwrap master secret with PKCS11 */ -+ slot = SECMOD_LookupSlot(sid->u.ssl3.masterModuleID, -+ sid->u.ssl3.masterSlotID); -+ if (slot == NULL) { -+ return SECFailure; -+ } -+ if (!PK11_IsPresent(slot)) { -+ PK11_FreeSlot(slot); -+ return SECFailure; -+ } -+ wrapKey = PK11_GetWrapKey(slot, sid->u.ssl3.masterWrapIndex, -+ sid->u.ssl3.masterWrapMech, -+ sid->u.ssl3.masterWrapSeries, -+ ss->pkcs11PinArg); -+ PK11_FreeSlot(slot); -+ if (wrapKey == NULL) { -+ return SECFailure; -+ } -+ -+ if (ss->version > SSL_LIBRARY_VERSION_3_0) { /* isTLS */ -+ keyFlags = CKF_SIGN | CKF_VERIFY; -+ } -+ -+ wrappedMS.data = sid->u.ssl3.keys.wrapped_master_secret; -+ wrappedMS.len = sid->u.ssl3.keys.wrapped_master_secret_len; -+ pwSpec->master_secret = -+ PK11_UnwrapSymKeyWithFlags(wrapKey, sid->u.ssl3.masterWrapMech, -+ NULL, &wrappedMS, CKM_SSL3_MASTER_KEY_DERIVE, -+ CKA_DERIVE, sizeof(SSL3MasterSecret), keyFlags); -+ PK11_FreeSymKey(wrapKey); -+ if (pwSpec->master_secret == NULL) { -+ return SECFailure; -+ } -+ } else if (ss->opt.bypassPKCS11) { -+ /* MS is not wrapped */ -+ 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; -+ } else { -+ /* We CAN restart a bypass session in a non-bypass socket. */ -+ /* need to import the raw master secret to session object */ -+ PK11SlotInfo *slot = PK11_GetInternalSlot(); -+ wrappedMS.data = sid->u.ssl3.keys.wrapped_master_secret; -+ wrappedMS.len = sid->u.ssl3.keys.wrapped_master_secret_len; -+ pwSpec->master_secret = -+ PK11_ImportSymKey(slot, CKM_SSL3_MASTER_KEY_DERIVE, -+ PK11_OriginUnwrap, CKA_ENCRYPT, -+ &wrappedMS, NULL); -+ PK11_FreeSlot(slot); -+ if (pwSpec->master_secret == NULL) { -+ return SECFailure; -+ } -+ } -+ -+ return SECSuccess; -+} -+ - /* Called from ssl3_HandleHandshakeMessage() when it has deciphered a complete - * ssl3 ServerHello message. - * Caller must hold Handshake and RecvBuf locks. -@@ -4886,6 +4982,14 @@ ssl3_HandleServerHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length) - PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) ); - PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) ); - -+ if (ss->ssl3.hs.snapStartType == snap_start_full || -+ ss->ssl3.hs.snapStartType == snap_start_resume) { -+ /* Snap Start handshake was rejected. */ -+ rv = ssl3_ResetForSnapStartRecovery(ss, b, length); -+ if (rv != SECSuccess) -+ return rv; -+ } -+ - rv = ssl3_InitState(ss); - if (rv != SECSuccess) { - errCode = PORT_GetError(); /* ssl3_InitState has set the error code. */ -@@ -4897,6 +5001,21 @@ ssl3_HandleServerHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length) - goto alert_loser; - } - -+ if (!ss->ssl3.serverHelloPredictionData.data) { -+ /* If this allocation fails it will only stop the application from -+ * recording the ServerHello information and performing future Snap -+ * Starts. */ -+ if (SECITEM_AllocItem(NULL, &ss->ssl3.serverHelloPredictionData, -+ length)) -+ memcpy(ss->ssl3.serverHelloPredictionData.data, b, length); -+ /* ss->ssl3.serverHelloPredictionDataValid is still false at this -+ * point. We have to record the contents of the ServerHello here -+ * because we don't have a pointer to the whole message when handling -+ * the extensions. However, we wait until the Snap Start extenion -+ * handler to recognise that the server supports Snap Start and to set -+ * serverHelloPredictionDataValid. */ -+ } -+ - temp = ssl3_ConsumeHandshakeNumber(ss, 2, &b, &length); - if (temp < 0) { - goto loser; /* alert has been sent */ -@@ -5037,118 +5156,40 @@ ssl3_HandleServerHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length) - - if (sid_match && - sid->version == ss->version && -- sid->u.ssl3.cipherSuite == ss->ssl3.hs.cipher_suite) do { -- ssl3CipherSpec *pwSpec = ss->ssl3.pwSpec; -- -- SECItem wrappedMS; /* wrapped master secret. */ -+ sid->u.ssl3.cipherSuite == ss->ssl3.hs.cipher_suite) { -+ rv = ssl3_SetupMasterSecretFromSessionID(ss); -+ /* Failure of ssl3_SetupMasterSecretFromSessionID not considered an -+ * error. Continue with a full handshake. */ -+ if (rv == SECSuccess) { -+ /* Got a Match */ -+ SSL_AtomicIncrementLong(& ssl3stats.hsh_sid_cache_hits ); - -- ss->sec.authAlgorithm = sid->authAlgorithm; -- ss->sec.authKeyBits = sid->authKeyBits; -- ss->sec.keaType = sid->keaType; -- ss->sec.keaKeyBits = sid->keaKeyBits; -+ /* If we sent a session ticket, then this is a stateless resume. */ -+ if (sid->version > SSL_LIBRARY_VERSION_3_0 && -+ sid->u.ssl3.sessionTicket.ticket.data != NULL) -+ SSL_AtomicIncrementLong(& ssl3stats.hsh_sid_stateless_resumes ); - -- /* 3 cases here: -- * a) key is wrapped (implies using PKCS11) -- * b) key is unwrapped, but we're still using PKCS11 -- * c) key is unwrapped, and we're bypassing PKCS11. -- */ -- if (sid->u.ssl3.keys.msIsWrapped) { -- PK11SlotInfo *slot; -- PK11SymKey * wrapKey; /* wrapping key */ -- CK_FLAGS keyFlags = 0; -+ if (ssl3_ExtensionNegotiated(ss, ssl_session_ticket_xtn)) -+ ss->ssl3.hs.ws = wait_new_session_ticket; -+ else -+ ss->ssl3.hs.ws = wait_change_cipher; - -- if (ss->opt.bypassPKCS11) { -- /* we cannot restart a non-bypass session in a -- ** bypass socket. -- */ -- break; -- } -- /* unwrap master secret with PKCS11 */ -- slot = SECMOD_LookupSlot(sid->u.ssl3.masterModuleID, -- sid->u.ssl3.masterSlotID); -- if (slot == NULL) { -- break; /* not considered an error. */ -- } -- if (!PK11_IsPresent(slot)) { -- PK11_FreeSlot(slot); -- break; /* not considered an error. */ -- } -- wrapKey = PK11_GetWrapKey(slot, sid->u.ssl3.masterWrapIndex, -- sid->u.ssl3.masterWrapMech, -- sid->u.ssl3.masterWrapSeries, -- ss->pkcs11PinArg); -- PK11_FreeSlot(slot); -- if (wrapKey == NULL) { -- break; /* not considered an error. */ -- } -+ ss->ssl3.hs.isResuming = PR_TRUE; - -- if (ss->version > SSL_LIBRARY_VERSION_3_0) { /* isTLS */ -- keyFlags = CKF_SIGN | CKF_VERIFY; -+ /* copy the peer cert from the SID */ -+ if (sid->peerCert != NULL) { -+ ss->sec.peerCert = CERT_DupCertificate(sid->peerCert); -+ ssl3_CopyPeerCertsFromSID(ss, sid); - } - -- wrappedMS.data = sid->u.ssl3.keys.wrapped_master_secret; -- wrappedMS.len = sid->u.ssl3.keys.wrapped_master_secret_len; -- pwSpec->master_secret = -- PK11_UnwrapSymKeyWithFlags(wrapKey, sid->u.ssl3.masterWrapMech, -- NULL, &wrappedMS, CKM_SSL3_MASTER_KEY_DERIVE, -- CKA_DERIVE, sizeof(SSL3MasterSecret), keyFlags); -- errCode = PORT_GetError(); -- PK11_FreeSymKey(wrapKey); -- if (pwSpec->master_secret == NULL) { -- break; /* errorCode set just after call to UnwrapSymKey. */ -- } -- } else if (ss->opt.bypassPKCS11) { -- /* MS is not wrapped */ -- 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; -- } else { -- /* We CAN restart a bypass session in a non-bypass socket. */ -- /* need to import the raw master secret to session object */ -- PK11SlotInfo *slot = PK11_GetInternalSlot(); -- wrappedMS.data = sid->u.ssl3.keys.wrapped_master_secret; -- wrappedMS.len = sid->u.ssl3.keys.wrapped_master_secret_len; -- pwSpec->master_secret = -- PK11_ImportSymKey(slot, CKM_SSL3_MASTER_KEY_DERIVE, -- PK11_OriginUnwrap, CKA_ENCRYPT, -- &wrappedMS, NULL); -- PK11_FreeSlot(slot); -- if (pwSpec->master_secret == NULL) { -- break; -+ /* NULL value for PMS signifies re-use of the old MS */ -+ rv = ssl3_InitPendingCipherSpec(ss, NULL); -+ if (rv != SECSuccess) { -+ goto alert_loser; - } -+ return SECSuccess; - } -- -- /* Got a Match */ -- SSL_AtomicIncrementLong(& ssl3stats.hsh_sid_cache_hits ); -- -- /* If we sent a session ticket, then this is a stateless resume. */ -- if (sid->version > SSL_LIBRARY_VERSION_3_0 && -- sid->u.ssl3.sessionTicket.ticket.data != NULL) -- SSL_AtomicIncrementLong(& ssl3stats.hsh_sid_stateless_resumes ); -- -- if (ssl3_ExtensionNegotiated(ss, ssl_session_ticket_xtn)) -- ss->ssl3.hs.ws = wait_new_session_ticket; -- else -- ss->ssl3.hs.ws = wait_change_cipher; -- -- ss->ssl3.hs.isResuming = PR_TRUE; -- -- /* copy the peer cert from the SID */ -- if (sid->peerCert != NULL) { -- ss->sec.peerCert = CERT_DupCertificate(sid->peerCert); -- ssl3_CopyPeerCertsFromSID(ss, sid); -- } -- -- -- /* NULL value for PMS signifies re-use of the old MS */ -- rv = ssl3_InitPendingCipherSpec(ss, NULL); -- if (rv != SECSuccess) { -- goto alert_loser; /* err code was set */ -- } -- return SECSuccess; -- } while (0); -+ } - - if (sid_match) - SSL_AtomicIncrementLong(& ssl3stats.hsh_sid_cache_not_ok ); -@@ -6116,7 +6157,7 @@ ssl3_HandleClientHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length) - * ticket extension, but sent an empty ticket. - */ - if (!ssl3_ExtensionNegotiated(ss, ssl_session_ticket_xtn) || -- ss->xtnData.emptySessionTicket) { -+ ss->xtnData.serverReceivedEmptySessionTicket) { - if (sidBytes.len > 0 && !ss->opt.noCache) { - SSL_TRC(7, ("%d: SSL3[%d]: server, lookup client session-id for 0x%08x%08x%08x%08x", - SSL_GETPID(), ss->fd, ss->sec.ci.peer.pr_s6_addr32[0], -@@ -7569,6 +7610,12 @@ ssl3_HandleNewSessionTicket(sslSocket *ss, SSL3Opaque *b, PRUint32 length) - return SECFailure; /* malformed */ - } - -+ if (ss->sec.ci.sid->peerCert == NULL) { -+ ss->sec.ci.sid->peerCert = CERT_DupCertificate(ss->sec.peerCert); -+ ssl3_CopyPeerCertsToSID((ssl3CertNode *)ss->ssl3.peerCertChain, -+ ss->sec.ci.sid); -+ } -+ - rv = ssl3_SetSIDSessionTicket(ss->sec.ci.sid, &session_ticket); - if (rv != SECSuccess) { - (void)SSL3_SendAlert(ss, alert_fatal, handshake_failure); -@@ -7760,7 +7807,7 @@ ssl3_CleanupPeerCerts(sslSocket *ss) - ss->ssl3.peerCertChain = NULL; - } - --static void -+void - ssl3_CopyPeerCertsFromSID(sslSocket *ss, sslSessionID *sid) - { - PRArenaPool *arena; -@@ -8163,7 +8210,7 @@ ssl3_RestartHandshakeAfterServerCert(sslSocket *ss) - return rv; - } - --static SECStatus -+SECStatus - ssl3_ComputeTLSFinished(ssl3CipherSpec *spec, - PRBool isServer, - const SSL3Finished * hashes, -@@ -8211,7 +8258,7 @@ ssl3_ComputeTLSFinished(ssl3CipherSpec *spec, - - /* called from ssl3_HandleServerHelloDone - */ --static SECStatus -+SECStatus - ssl3_SendNextProto(sslSocket *ss) - { - SECStatus rv; -@@ -8247,7 +8294,7 @@ ssl3_SendNextProto(sslSocket *ss) - * ssl3_HandleClientHello - * ssl3_HandleFinished - */ --static SECStatus -+SECStatus - ssl3_SendFinished(sslSocket *ss, PRInt32 flags) - { - ssl3CipherSpec *cwSpec; -@@ -8300,10 +8347,27 @@ ssl3_SendFinished(sslSocket *ss, PRInt32 flags) - if (rv != SECSuccess) - goto fail; /* err set by AppendHandshake. */ - } -- rv = ssl3_FlushHandshake(ss, flags); -- if (rv != SECSuccess) { -- goto fail; /* error code set by ssl3_FlushHandshake */ -+ if ((flags & ssl_SEND_FLAG_NO_FLUSH) == 0) { -+ rv = ssl3_FlushHandshake(ss, flags); -+ if (rv != SECSuccess) { -+ goto fail; /* error code set by ssl3_FlushHandshake */ -+ } - } -+ -+ if ((ss->ssl3.hs.snapStartType == snap_start_recovery || -+ ss->ssl3.hs.snapStartType == snap_start_resume_recovery) && -+ ss->ssl3.snapStartApplicationData.data) { -+ /* In the event that the server ignored the application data in our -+ * snap start extension, we need to retransmit it now. */ -+ PRInt32 sent = ssl3_SendRecord(ss, content_application_data, -+ ss->ssl3.snapStartApplicationData.data, -+ ss->ssl3.snapStartApplicationData.len, -+ flags); -+ SECITEM_FreeItem(&ss->ssl3.snapStartApplicationData, PR_FALSE); -+ if (sent < 0) -+ return (SECStatus)sent; /* error code set by ssl3_SendRecord */ -+ } -+ - return SECSuccess; - - fail: -@@ -8420,6 +8484,16 @@ ssl3_HandleFinished(sslSocket *ss, SSL3Opaque *b, PRUint32 length, - return SECFailure; - } - -+ if (ss->ssl3.hs.snapStartType == snap_start_full || -+ ss->ssl3.hs.snapStartType == snap_start_resume) { -+ /* Snap Start handshake was successful. Switch the cipher spec. */ -+ ssl_GetSpecWriteLock(ss); -+ ssl3_DestroyCipherSpec(ss->ssl3.cwSpec, PR_TRUE/*freeSrvName*/); -+ ss->ssl3.cwSpec = ss->ssl3.pwSpec; -+ ss->ssl3.pwSpec = NULL; -+ ssl_ReleaseSpecWriteLock(ss); -+ } -+ - isTLS = (PRBool)(ss->ssl3.crSpec->version > SSL_LIBRARY_VERSION_3_0); - if (isTLS) { - TLSFinished tlsFinished; -@@ -8429,12 +8503,21 @@ ssl3_HandleFinished(sslSocket *ss, SSL3Opaque *b, PRUint32 length, - PORT_SetError(SSL_ERROR_RX_MALFORMED_FINISHED); - return SECFailure; - } -- rv = ssl3_ComputeTLSFinished(ss->ssl3.crSpec, !isServer, -- hashes, &tlsFinished); -- if (!isServer) -- ss->ssl3.hs.finishedMsgs.tFinished[1] = tlsFinished; -- else -- ss->ssl3.hs.finishedMsgs.tFinished[0] = tlsFinished; -+ -+ if (ss->ssl3.hs.snapStartType == snap_start_resume) { -+ /* In this case we have already advanced the Finished hash past the -+ * server's verify_data because we needed to predict the server's -+ * Finished message in order to compute our own (which includes -+ * it). When we did this, we stored a copy in tFinished[1]. */ -+ tlsFinished = ss->ssl3.hs.finishedMsgs.tFinished[1]; -+ } else { -+ rv = ssl3_ComputeTLSFinished(ss->ssl3.crSpec, !isServer, -+ hashes, &tlsFinished); -+ if (!isServer) -+ ss->ssl3.hs.finishedMsgs.tFinished[1] = tlsFinished; -+ else -+ ss->ssl3.hs.finishedMsgs.tFinished[0] = tlsFinished; -+ } - ss->ssl3.hs.finishedBytes = sizeof tlsFinished; - if (rv != SECSuccess || - 0 != NSS_SecureMemcmp(&tlsFinished, b, length)) { -@@ -8465,8 +8548,9 @@ ssl3_HandleFinished(sslSocket *ss, SSL3Opaque *b, PRUint32 length, - - ssl_GetXmitBufLock(ss); /*************************************/ - -- if ((isServer && !ss->ssl3.hs.isResuming) || -- (!isServer && ss->ssl3.hs.isResuming)) { -+ if (ss->ssl3.hs.snapStartType != snap_start_resume && -+ ((isServer && !ss->ssl3.hs.isResuming) || -+ (!isServer && ss->ssl3.hs.isResuming))) { - PRInt32 flags = 0; - - /* Send a NewSessionTicket message if the client sent us -@@ -8582,7 +8666,10 @@ xmit_loser: - ss->ssl3.hs.ws = idle_handshake; - - /* Do the handshake callback for sslv3 here, if we cannot false start. */ -- if (ss->handshakeCallback != NULL && !ssl3_CanFalseStart(ss)) { -+ if (ss->handshakeCallback != NULL && -+ (!ssl3_CanFalseStart(ss) || -+ ss->ssl3.hs.snapStartType == snap_start_full || -+ ss->ssl3.hs.snapStartType == snap_start_resume)) { - (ss->handshakeCallback)(ss->fd, ss->handshakeCallbackData); - } - -@@ -8643,8 +8730,13 @@ ssl3_HandleHandshakeMessage(sslSocket *ss, SSL3Opaque *b, PRUint32 length) - return rv; - } - } -- /* We should not include hello_request messages in the handshake hashes */ -- if (ss->ssl3.hs.msg_type != hello_request) { -+ /* We should not include hello_request messages in the handshake hashes. -+ * Likewise, for Finished messages from the server during a Snap Start -+ * resume, we have already predicted and included the message in our -+ * Finished hash. */ -+ if (ss->ssl3.hs.msg_type != hello_request && -+ !(ss->ssl3.hs.msg_type == finished && -+ ss->ssl3.hs.snapStartType == snap_start_resume)) { - rv = ssl3_UpdateHandshakeHashes(ss, (unsigned char*) hdr, 4); - if (rv != SECSuccess) return rv; /* err code already set. */ - rv = ssl3_UpdateHandshakeHashes(ss, b, length); -@@ -9545,6 +9637,15 @@ ssl3_DestroySSL3Info(sslSocket *ss) - ss->ssl3.clientCertChain = NULL; - } - -+ if (ss->ssl3.predictedCertChain != NULL) -+ ssl3_CleanupPredictedPeerCertificates(ss); -+ -+ if (ss->ssl3.serverHelloPredictionData.data) -+ SECITEM_FreeItem(&ss->ssl3.serverHelloPredictionData, PR_FALSE); -+ -+ if (ss->ssl3.snapStartApplicationData.data) -+ SECITEM_FreeItem(&ss->ssl3.snapStartApplicationData, PR_FALSE); -+ - /* clean up handshake */ - if (ss->opt.bypassPKCS11) { - SHA1_DestroyContext((SHA1Context *)ss->ssl3.hs.sha_cx, PR_FALSE); -@@ -9562,6 +9663,9 @@ ssl3_DestroySSL3Info(sslSocket *ss) - ss->ssl3.hs.messages.len = 0; - ss->ssl3.hs.messages.space = 0; - } -+ if (ss->ssl3.hs.origClientHello.data) { -+ SECITEM_FreeItem(&ss->ssl3.hs.origClientHello, PR_FALSE); -+ } - - /* free the SSL3Buffer (msg_body) */ - PORT_Free(ss->ssl3.hs.msg_body.buf); -diff --git a/mozilla/security/nss/lib/ssl/ssl3ext.c b/mozilla/security/nss/lib/ssl/ssl3ext.c -index fbd5a91..a7ae062 100644 ---- a/mozilla/security/nss/lib/ssl/ssl3ext.c -+++ b/mozilla/security/nss/lib/ssl/ssl3ext.c -@@ -247,6 +247,7 @@ static const ssl3HelloExtensionHandler serverHelloHandlersTLS[] = { - { ssl_session_ticket_xtn, &ssl3_ClientHandleSessionTicketXtn }, - { ssl_renegotiation_info_xtn, &ssl3_HandleRenegotiationInfoXtn }, - { ssl_next_proto_neg_xtn, &ssl3_ClientHandleNextProtoNegoXtn }, -+ { ssl_snap_start_xtn, &ssl3_ClientHandleSnapStartXtn }, - { -1, NULL } - }; - -@@ -270,7 +271,9 @@ ssl3HelloExtensionSender clientHelloSendersTLS[SSL_MAX_EXTENSIONS] = { - { ssl_ec_point_formats_xtn, &ssl3_SendSupportedPointFormatsXtn }, - #endif - { ssl_session_ticket_xtn, &ssl3_SendSessionTicketXtn }, -- { ssl_next_proto_neg_xtn, &ssl3_ClientSendNextProtoNegoXtn } -+ { ssl_next_proto_neg_xtn, &ssl3_ClientSendNextProtoNegoXtn }, -+ { ssl_snap_start_xtn, &ssl3_SendSnapStartXtn } -+ /* NOTE: The Snap Start sender MUST be the last extension in the list. */ - /* any extra entries will appear as { 0, NULL } */ - }; - -@@ -298,7 +301,7 @@ ssl3_ExtensionNegotiated(sslSocket *ss, PRUint16 ex_type) { - xtnData->numNegotiated, ex_type); - } - --static PRBool -+PRBool - ssl3_ClientExtensionAdvertised(sslSocket *ss, PRUint16 ex_type) { - TLSExtensionData *xtnData = &ss->xtnData; - return arrayContainsExtension(xtnData->advertised, -@@ -515,6 +518,8 @@ ssl3_SendSessionTicketXtn( - rv = ssl3_AppendHandshakeVariable(ss, session_ticket->ticket.data, - session_ticket->ticket.len, 2); - ss->xtnData.ticketTimestampVerified = PR_FALSE; -+ if (!ss->sec.isServer) -+ ss->xtnData.clientSentNonEmptySessionTicket = PR_TRUE; - } else { - rv = ssl3_AppendHandshakeNumber(ss, 0, 2); - } -@@ -573,7 +578,7 @@ ssl3_ValidateNextProtoNego(const unsigned char* data, unsigned short length) - - SECStatus - ssl3_ClientHandleNextProtoNegoXtn(sslSocket *ss, PRUint16 ex_type, -- SECItem *data) -+ SECItem *data) - { - unsigned int i, j; - SECStatus rv; -@@ -1021,7 +1026,7 @@ ssl3_ServerHandleSessionTicketXtn(sslSocket *ss, PRUint16 ex_type, - * instead of terminating the current connection. - */ - if (data->len == 0) { -- ss->xtnData.emptySessionTicket = PR_TRUE; -+ ss->xtnData.serverReceivedEmptySessionTicket = PR_TRUE; - } else { - int i; - SECItem extension_data; -diff --git a/mozilla/security/nss/lib/ssl/sslimpl.h b/mozilla/security/nss/lib/ssl/sslimpl.h -index fe7ac7a..f708696 100644 ---- a/mozilla/security/nss/lib/ssl/sslimpl.h -+++ b/mozilla/security/nss/lib/ssl/sslimpl.h -@@ -278,6 +278,7 @@ struct sslSocketOpsStr { - /* Flags interpreted by ssl send functions. */ - #define ssl_SEND_FLAG_FORCE_INTO_BUFFER 0x40000000 - #define ssl_SEND_FLAG_NO_BUFFER 0x20000000 -+#define ssl_SEND_FLAG_NO_FLUSH 0x10000000 - #define ssl_SEND_FLAG_MASK 0x7f000000 - - /* -@@ -339,6 +340,7 @@ typedef struct sslOptionsStr { - unsigned int enableRenegotiation : 2; /* 20-21 */ - unsigned int requireSafeNegotiation : 1; /* 22 */ - unsigned int enableFalseStart : 1; /* 23 */ -+ unsigned int enableSnapStart : 1; /* 24 */ - } sslOptions; - - typedef enum { sslHandshakingUndetermined = 0, -@@ -743,7 +745,8 @@ struct TLSExtensionDataStr { - - /* SessionTicket Extension related data. */ - PRBool ticketTimestampVerified; -- PRBool emptySessionTicket; -+ PRBool serverReceivedEmptySessionTicket; -+ PRBool clientSentNonEmptySessionTicket; - - /* SNI Extension related data - * Names data is not coppied from the input buffer. It can not be -@@ -753,6 +756,14 @@ struct TLSExtensionDataStr { - PRUint32 sniNameArrSize; - }; - -+typedef enum { -+ snap_start_none = 0, -+ snap_start_full, -+ snap_start_recovery, -+ snap_start_resume, -+ snap_start_resume_recovery -+} TLSSnapStartType; -+ - /* - ** This is the "hs" member of the "ssl3" struct. - ** This entire struct is protected by ssl3HandshakeLock -@@ -791,6 +802,14 @@ const ssl3CipherSuiteDef *suite_def; - SSL3Hashes sFinished[2]; - SSL3Opaque data[72]; - } finishedMsgs; -+ -+ TLSSnapStartType snapStartType; -+ /* When we perform a Snap Start handshake, we hash our ClientHello as if -+ * the Snap Start extension wasn't included. However, if the server rejects -+ * our Snap Start attempt, then it will hash the whole ClientHello. Thus we -+ * store the original ClientHello that we sent in case we need to reset our -+ * Finished hash to cover it. */ -+ SECItem origClientHello; - #ifdef NSS_ENABLE_ECC - PRUint32 negotiatedECCurves; /* bit mask */ - #endif /* NSS_ENABLE_ECC */ -@@ -823,6 +842,17 @@ struct ssl3StateStr { - CERTCertificateList *clientCertChain; /* used by client */ - PRBool sendEmptyCert; /* used by client */ - -+ /* TLS Snap Start: */ -+ CERTCertificate ** predictedCertChain; -+ /* An array terminated with a NULL. */ -+ SECItem serverHelloPredictionData; -+ PRBool serverHelloPredictionDataValid; -+ /* data needed to predict the ServerHello from -+ * this server. */ -+ SECItem snapStartApplicationData; -+ /* the application data to include in the Snap -+ * Start extension. */ -+ - int policy; - /* This says what cipher suites we can do, and should - * be either SSL_ALLOWED or SSL_RESTRICTED -@@ -1258,10 +1288,13 @@ extern sslSessionID *ssl3_NewSessionID(sslSocket *ss, PRBool is_server); - extern sslSessionID *ssl_LookupSID(const PRIPv6Addr *addr, PRUint16 port, - const char *peerID, const char *urlSvrName); - extern void ssl_FreeSID(sslSessionID *sid); -+extern void ssl3_CopyPeerCertsFromSID(sslSocket *ss, sslSessionID *sid); - - extern int ssl3_SendApplicationData(sslSocket *ss, const PRUint8 *in, - int len, int flags); - -+extern SECStatus ssl3_RestartHandshakeHashes(sslSocket *ss); -+ - extern PRBool ssl_FdIsBlocking(PRFileDesc *fd); - - extern PRBool ssl_SocketIsBlocking(sslSocket *ss); -@@ -1434,6 +1467,9 @@ ECName ssl3_GetCurveWithECKeyStrength(PRUint32 curvemsk, int requiredECCbits); - - #endif /* NSS_ENABLE_ECC */ - -+extern SECStatus ssl3_UpdateHandshakeHashes(sslSocket* ss, unsigned char *b, -+ unsigned int l); -+ - extern SECStatus ssl3_CipherPrefSetDefault(ssl3CipherSuite which, PRBool on); - extern SECStatus ssl3_CipherPrefGetDefault(ssl3CipherSuite which, PRBool *on); - extern SECStatus ssl2_CipherPrefSetDefault(PRInt32 which, PRBool enabled); -@@ -1454,6 +1490,7 @@ extern void ssl3_InitSocketPolicy(sslSocket *ss); - - extern SECStatus ssl3_ConstructV2CipherSpecsHack(sslSocket *ss, - unsigned char *cs, int *size); -+extern void ssl3_DestroyCipherSpec(ssl3CipherSpec* spec, PRBool freeSrvName); - - extern SECStatus ssl3_RedoHandshake(sslSocket *ss, PRBool flushCache); - -@@ -1503,6 +1540,31 @@ extern SECStatus ssl3_VerifySignedHashes(SSL3Hashes *hash, - extern SECStatus ssl3_CacheWrappedMasterSecret(sslSocket *ss, - sslSessionID *sid, ssl3CipherSpec *spec, - SSL3KEAType effectiveExchKeyType); -+extern void ssl3_CleanupPredictedPeerCertificates(sslSocket *ss); -+extern const ssl3CipherSuiteDef* ssl_LookupCipherSuiteDef(ssl3CipherSuite suite); -+extern SECStatus ssl3_SetupPendingCipherSpec(sslSocket *ss); -+extern SECStatus ssl3_SendClientKeyExchange(sslSocket *ss); -+extern SECStatus ssl3_SendNextProto(sslSocket *ss); -+extern SECStatus ssl3_SendFinished(sslSocket *ss, PRInt32 flags); -+extern SECStatus ssl3_CompressMACEncryptRecord -+ (sslSocket * ss, -+ SSL3ContentType type, -+ const SSL3Opaque * pIn, -+ PRUint32 contentLen); -+extern PRBool ssl3_ClientExtensionAdvertised(sslSocket *ss, PRUint16 ex_type); -+extern SECStatus ssl3_SetupMasterSecretFromSessionID(sslSocket* ss); -+extern SECStatus ssl3_ComputeHandshakeHashes( -+ sslSocket * ss, -+ ssl3CipherSpec *spec, /* uses ->master_secret */ -+ SSL3Hashes * hashes, /* output goes here. */ -+ PRUint32 sender); -+extern SECStatus ssl3_UpdateHandshakeHashes(sslSocket* ss, unsigned char *b, -+ unsigned int l); -+extern SECStatus ssl3_ComputeTLSFinished( -+ ssl3CipherSpec *spec, -+ PRBool isServer, -+ const SSL3Finished * hashes, -+ TLSFinished * tlsFinished); - - /* Functions that handle ClientHello and ServerHello extensions. */ - extern SECStatus ssl3_HandleServerNameXtn(sslSocket * ss, -@@ -1532,6 +1594,13 @@ extern PRInt32 ssl3_SendSessionTicketXtn(sslSocket *ss, PRBool append, - */ - extern PRInt32 ssl3_SendServerNameXtn(sslSocket *ss, PRBool append, - PRUint32 maxBytes); -+extern PRInt32 ssl3_SendSnapStartXtn(sslSocket *ss, PRBool append, -+ PRUint32 maxBytes); -+extern SECStatus ssl3_ClientHandleSnapStartXtn(sslSocket *ss, PRUint16 ex_type, -+ SECItem *data); -+ -+extern SECStatus ssl3_ResetForSnapStartRecovery(sslSocket *ss, -+ SSL3Opaque *b, PRUint32 length); - - /* Assigns new cert, cert chain and keys to ss->serverCerts - * struct. If certChain is NULL, tries to find one. Aborts if -@@ -1635,6 +1704,12 @@ SECStatus SSL_DisableDefaultExportCipherSuites(void); - SECStatus SSL_DisableExportCipherSuites(PRFileDesc * fd); - PRBool SSL_IsExportCipherSuite(PRUint16 cipherSuite); - -+/********************** FNV hash *********************/ -+ -+void FNV1A64_Init(PRUint64 *digest); -+void FNV1A64_Update(PRUint64 *digest, const unsigned char *data, -+ unsigned int length); -+void FNV1A64_Final(PRUint64 *digest); - - #ifdef TRACE - #define SSL_TRACE(msg) ssl_Trace msg -diff --git a/mozilla/security/nss/lib/ssl/sslsock.c b/mozilla/security/nss/lib/ssl/sslsock.c -index ca0d714..2898b88 100644 ---- a/mozilla/security/nss/lib/ssl/sslsock.c -+++ b/mozilla/security/nss/lib/ssl/sslsock.c -@@ -738,6 +738,10 @@ SSL_OptionSet(PRFileDesc *fd, PRInt32 which, PRBool on) - ss->opt.enableFalseStart = on; - break; - -+ case SSL_ENABLE_SNAP_START: -+ ss->opt.enableSnapStart = on; -+ break; -+ - default: - PORT_SetError(SEC_ERROR_INVALID_ARGS); - rv = SECFailure; -@@ -802,6 +806,7 @@ SSL_OptionGet(PRFileDesc *fd, PRInt32 which, PRBool *pOn) - case SSL_REQUIRE_SAFE_NEGOTIATION: - on = ss->opt.requireSafeNegotiation; break; - case SSL_ENABLE_FALSE_START: on = ss->opt.enableFalseStart; break; -+ case SSL_ENABLE_SNAP_START: on = ss->opt.enableSnapStart; break; - - default: - PORT_SetError(SEC_ERROR_INVALID_ARGS); -@@ -853,6 +858,7 @@ SSL_OptionGetDefault(PRInt32 which, PRBool *pOn) - on = ssl_defaults.requireSafeNegotiation; - break; - case SSL_ENABLE_FALSE_START: on = ssl_defaults.enableFalseStart; break; -+ case SSL_ENABLE_SNAP_START: on = ssl_defaults.enableSnapStart; break; - - default: - PORT_SetError(SEC_ERROR_INVALID_ARGS); -@@ -1000,6 +1006,10 @@ SSL_OptionSetDefault(PRInt32 which, PRBool on) - ssl_defaults.enableFalseStart = on; - break; - -+ case SSL_ENABLE_SNAP_START: -+ ssl_defaults.enableSnapStart = on; -+ break; -+ - default: - PORT_SetError(SEC_ERROR_INVALID_ARGS); - return SECFailure; -diff --git a/mozilla/security/nss/lib/ssl/sslt.h b/mozilla/security/nss/lib/ssl/sslt.h -index f6e0b62..68cbf87 100644 ---- a/mozilla/security/nss/lib/ssl/sslt.h -+++ b/mozilla/security/nss/lib/ssl/sslt.h -@@ -204,9 +204,23 @@ typedef enum { - #endif - ssl_session_ticket_xtn = 35, - ssl_next_proto_neg_xtn = 13172, -+ ssl_snap_start_xtn = 13174, - ssl_renegotiation_info_xtn = 0xff01 /* experimental number */ - } SSLExtensionType; - --#define SSL_MAX_EXTENSIONS 6 -+#define SSL_MAX_EXTENSIONS 7 -+ -+typedef enum { -+ /* No Snap Start handshake was attempted. */ -+ SSL_SNAP_START_NONE = 0, -+ /* A Snap Start full handshake was completed. */ -+ SSL_SNAP_START_FULL = 1, -+ /* A Snap Start full handshake was attempted, but failed. */ -+ SSL_SNAP_START_RECOVERY = 2, -+ /* A Snap Start resume handshake was completed. */ -+ SSL_SNAP_START_RESUME = 3, -+ /* A Snap Start resume handshake was attempted, but failed. */ -+ SSL_SNAP_START_RESUME_RECOVERY = 4 -+} SSLSnapStartResult; - - #endif /* __sslt_h_ */ diff --git a/net/third_party/nss/patches/snapstart2.patch b/net/third_party/nss/patches/snapstart2.patch deleted file mode 100644 index 34ec562..0000000 --- a/net/third_party/nss/patches/snapstart2.patch +++ /dev/null @@ -1,93 +0,0 @@ -Index: net/third_party/nss/ssl/snapstart.c -=================================================================== ---- net/third_party/nss/ssl/snapstart.c (revision 64952) -+++ net/third_party/nss/ssl/snapstart.c (revision 64953) -@@ -48,10 +48,6 @@ - - /* TODO(agl): Add support for snap starting with compression. */ - --/* TODO(agl): Free snapStartApplicationData as soon as the handshake has --** completed. --*/ -- - #include "pk11pub.h" - #include "ssl.h" - #include "sslimpl.h" -@@ -821,6 +817,7 @@ - rv = ssl3_AppendSnapStartApplicationData( - ss, ss->ssl3.snapStartApplicationData.data, - ss->ssl3.snapStartApplicationData.len); -+ SECITEM_FreeItem(&ss->ssl3.snapStartApplicationData, PR_FALSE); - if (rv != SECSuccess) - goto loser; - } -@@ -1053,6 +1053,8 @@ - ss->ssl3.hs.snapStartType = snap_start_resume_recovery; - } - -+ ss->ssl3.nextProtoState = SSL_NEXT_PROTO_NO_SUPPORT; -+ - ssl3_DestroyCipherSpec(ss->ssl3.pwSpec, PR_TRUE/*freeSrvName*/); - - return SECSuccess; -Index: net/third_party/nss/ssl/ssl3con.c -=================================================================== ---- net/third_party/nss/ssl/ssl3con.c (revision 65946) -+++ net/third_party/nss/ssl/ssl3con.c (revision 65947) -@@ -5023,21 +5023,21 @@ - goto alert_loser; - } - -- if (!ss->ssl3.serverHelloPredictionData.data) { -- /* If this allocation fails it will only stop the application from -- * recording the ServerHello information and performing future Snap -- * Starts. */ -- if (SECITEM_AllocItem(NULL, &ss->ssl3.serverHelloPredictionData, -- length)) -- memcpy(ss->ssl3.serverHelloPredictionData.data, b, length); -- /* ss->ssl3.serverHelloPredictionDataValid is still false at this -- * point. We have to record the contents of the ServerHello here -- * because we don't have a pointer to the whole message when handling -- * the extensions. However, we wait until the Snap Start extenion -- * handler to recognise that the server supports Snap Start and to set -- * serverHelloPredictionDataValid. */ -- } -+ if (ss->ssl3.serverHelloPredictionData.data) -+ SECITEM_FreeItem(&ss->ssl3.serverHelloPredictionData, PR_FALSE); - -+ /* If this allocation fails it will only stop the application from -+ * recording the ServerHello information and performing future Snap -+ * Starts. */ -+ if (SECITEM_AllocItem(NULL, &ss->ssl3.serverHelloPredictionData, length)) -+ memcpy(ss->ssl3.serverHelloPredictionData.data, b, length); -+ /* ss->ssl3.serverHelloPredictionDataValid is still false at this -+ * point. We have to record the contents of the ServerHello here -+ * because we don't have a pointer to the whole message when handling -+ * the extensions. However, we wait until the Snap Start extension -+ * handler to recognise that the server supports Snap Start and to set -+ * serverHelloPredictionDataValid. */ -+ - temp = ssl3_ConsumeHandshakeNumber(ss, 2, &b, &length); - if (temp < 0) { - goto loser; /* alert has been sent */ -@@ -8366,20 +8366,6 @@ - } - } - -- if ((ss->ssl3.hs.snapStartType == snap_start_recovery || -- ss->ssl3.hs.snapStartType == snap_start_resume_recovery) && -- ss->ssl3.snapStartApplicationData.data) { -- /* In the event that the server ignored the application data in our -- * snap start extension, we need to retransmit it now. */ -- PRInt32 sent = ssl3_SendRecord(ss, content_application_data, -- ss->ssl3.snapStartApplicationData.data, -- ss->ssl3.snapStartApplicationData.len, -- flags); -- SECITEM_FreeItem(&ss->ssl3.snapStartApplicationData, PR_FALSE); -- if (sent < 0) -- return (SECStatus)sent; /* error code set by ssl3_SendRecord */ -- } -- - return SECSuccess; - - fail: diff --git a/net/third_party/nss/ssl.gyp b/net/third_party/nss/ssl.gyp index eb732a0..bb8eabe 100644 --- a/net/third_party/nss/ssl.gyp +++ b/net/third_party/nss/ssl.gyp @@ -28,13 +28,11 @@ 'ssl/authcert.c', 'ssl/cmpcert.c', 'ssl/derive.c', - 'ssl/fnv1a64.c', 'ssl/nsskea.c', 'ssl/os2_err.c', 'ssl/os2_err.h', 'ssl/preenc.h', 'ssl/prelib.c', - 'ssl/snapstart.c', 'ssl/ssl.h', 'ssl/ssl3con.c', 'ssl/ssl3ecc.c', diff --git a/net/third_party/nss/ssl/fnv1a64.c b/net/third_party/nss/ssl/fnv1a64.c deleted file mode 100644 index c7c4b08..0000000 --- a/net/third_party/nss/ssl/fnv1a64.c +++ /dev/null @@ -1,72 +0,0 @@ -/* - * FNV1A64 Hash - * http://www.isthe.com/chongo/tech/comp/fnv/index.html#FNV-param - * - * ***** 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): - * Adam Langley, Google Inc. - * - * 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: fnv1a64.c,v 1.0 2010/08/09 13:00:00 agl%google.com Exp $ */ - -#include "prtypes.h" -#include "prnetdb.h" - -/* Older versions of Visual C++ don't support the 'ull' suffix. */ -#ifdef _MSC_VER -static const PRUint64 FNV1A64_OFFSET_BASIS = 14695981039346656037ui64; -static const PRUint64 FNV1A64_PRIME = 1099511628211ui64; -#else -static const PRUint64 FNV1A64_OFFSET_BASIS = 14695981039346656037ull; -static const PRUint64 FNV1A64_PRIME = 1099511628211ull; -#endif - -void FNV1A64_Init(PRUint64* digest) { - *digest = FNV1A64_OFFSET_BASIS; -} - -void FNV1A64_Update(PRUint64* digest, const unsigned char *data, - unsigned int length) { - unsigned int i; - - for (i = 0; i < length; i++) { - *digest ^= data[i]; - *digest *= FNV1A64_PRIME; - } -} - -void FNV1A64_Final(PRUint64 *digest) { - *digest = PR_htonll(*digest); -} diff --git a/net/third_party/nss/ssl/snapstart.c b/net/third_party/nss/ssl/snapstart.c deleted file mode 100644 index 92406a7..0000000 --- a/net/third_party/nss/ssl/snapstart.c +++ /dev/null @@ -1,1061 +0,0 @@ -/* - * TLS Snap Start - * - * ***** 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): - * Adam Langley, Google Inc. - * - * 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: ssl3snap.c,v 1.0 2010/08/09 13:00:00 agl%google.com Exp $ */ - - -/* TODO(agl): Refactor ssl3_CompressMACEncryptRecord so that it can write to -** |sendBuf| directly and fix ssl3_AppendSnapStartHandshakeRecord and -** ssl3_AppendSnapStartApplicationData. -*/ - -/* TODO(agl): Add support for snap starting with compression. */ - -#include "pk11pub.h" -#include "ssl.h" -#include "sslimpl.h" -#include "sslproto.h" - -static unsigned int GetBE16(const void *in) -{ - const unsigned char *p = in; - return ((unsigned) p[0]) << 8 | - p[1]; -} - -static unsigned int GetBE24(const void *in) -{ - const unsigned char *p = in; - return ((unsigned) p[0]) << 16 | - ((unsigned) p[1]) << 8 | - p[2]; -} - -static void PutBE16(void *out, unsigned int value) -{ - unsigned char *p = out; - p[0] = value >> 8; - p[1] = value; -} - -static void PutBE24(void *out, unsigned int value) -{ - unsigned char *p = out; - p[0] = value >> 16; - p[1] = value >> 8; - p[2] = value; -} - -/* ssl3_ForEachExtension calls a callback for each TLS extension in |extensions| -** extensions: points to a block of extensions which includes the two prefix -** length bytes -** is_resuming: if true, certain extensions will be omitted -** f: a function which is called with the data of each extension, which -** includes the four type and length bytes at the beginning. -*/ -static PRBool -ssl3_ForEachExtension(const SECItem *extensions, PRBool is_resuming, - void (*f) (const unsigned char *data, unsigned int length, - void *ctx), - void *ctx) { - unsigned int extensions_len, offset; - - if (extensions->len == 0) - return PR_TRUE; - - if (extensions->len < 2) - goto loser; - - extensions_len = GetBE16(extensions->data); - offset = 2; - - if (extensions->len != 2 + extensions_len) - goto loser; - - while (extensions_len) { - unsigned int extension_num, extension_len; - - if (extensions->len - offset < 4) - goto loser; - - extension_num = GetBE16(extensions->data + offset); - extension_len = GetBE16(extensions->data + offset + 2); - - if (extensions->len - offset < 4 + extension_len) - goto loser; - - /* When resuming, the server will omit some extensions from the - * previous non-resume ServerHello. */ - if (!is_resuming || - (extension_num != ssl_server_name_xtn && - extension_num != ssl_session_ticket_xtn)) { - f(extensions->data + offset, 4 + extension_len, ctx); - } - - offset += 4 + extension_len; - extensions_len -= 4 + extension_len; - } - - return PR_TRUE; - -loser: - PORT_SetError(SEC_ERROR_INPUT_LEN); - return PR_FALSE; -} - -static void -ssl3_AccumlateLengths(const unsigned char *data, unsigned int length, void *ptr) -{ - unsigned int *sum = (unsigned int *) ptr; - *sum += length; -} - -/* ssl3_PredictServerResponse predicts the contents of the server's -** ServerHello...ServerHelloDone (inclusive) and progressively calls a callback -** with the contents of those messages. -** previous_server_hello: the contents of a previous ServerHello from the -** server where the 'random' field has been replaced with our suggested -** server random. -** is_resuming: if false, Certificate and ServerHelloDone messages will be -** predicted -** hashUpdate: a callback which is called repeated with the contents of the -** predicted messages. -*/ -static PRBool -ssl3_PredictServerResponse( - sslSocket *ss, SECItem *previous_server_hello, PRBool is_resuming, - void (*hashUpdate) (const unsigned char *data, unsigned int length, - void *ctx), - void *ctx) { - unsigned int old_session_id_length, old_extensions_len; - unsigned int extensions_len, server_hello_len; - unsigned char session_id_len, header[4]; - SECItem extensions; - - /* Keep the structure of a ServerHello in mind when reading the following: - * - * struct ServerHello { - * uint16_t version; - * uint8_t random[32]; - * uint8_t session_id_len; - * uint8_t session_id[session_id_len]; - * uint16_t cipher - * uint8_t compression - * - * // Optional: - * uint16_t extensions_len; - * struct Extension { - * uint16_t num; - * uint16_t len; - * uint8_t payload[len]; - * } - */ - - /* 38 bytes is the shortest possible ServerHello with a zero-length - * session_id and no extensions. */ - if (previous_server_hello->len < 38) { - PORT_SetError(SEC_ERROR_INPUT_LEN); - return PR_FALSE; - } - - /* First we need to figure out the length of the predicted ServerHello. Any - * session id in |previous_server_hello| needs to be removed - * (or replaced). */ - old_session_id_length = previous_server_hello->data[34]; - - extensions.len = 0; - - if (previous_server_hello->len >= 35 + old_session_id_length + 3 + 2) { - /* Extensions present */ - unsigned int offset = 35 + old_session_id_length + 3; - extensions.data = previous_server_hello->data + offset; - extensions.len = previous_server_hello->len - offset; - } - - /* Sum the lengths of all the extensions that we wish to include */ - extensions_len = 0; - if (!ssl3_ForEachExtension(&extensions, is_resuming, ssl3_AccumlateLengths, - &extensions_len)) { - return PR_FALSE; - } - - old_extensions_len = - (previous_server_hello->len - 35 - old_session_id_length - 3 - 2); - - session_id_len = 0; - if (ss->sec.ci.sid) - session_id_len = ss->sec.ci.sid->u.ssl3.sessionIDLength; - server_hello_len = previous_server_hello->len + - session_id_len - old_session_id_length + - extensions_len - old_extensions_len; - - header[0] = server_hello; - PutBE24(header + 1, server_hello_len); - hashUpdate(header, 4, ctx); - - hashUpdate(previous_server_hello->data, 34, ctx); - hashUpdate(&session_id_len, sizeof(session_id_len), ctx); - if (session_id_len) - hashUpdate(ss->sec.ci.sid->u.ssl3.sessionID, session_id_len, ctx); - hashUpdate(previous_server_hello->data + 35 + old_session_id_length, 3, - ctx); - - if (extensions.len) { - PutBE16(header, extensions_len); - hashUpdate(header, 2, ctx); - - if (!ssl3_ForEachExtension(&extensions, is_resuming, hashUpdate, ctx)) - return PR_FALSE; - } - - if (!is_resuming) { - unsigned int certificate_message_len = 3, i; - for (i = 0; ss->ssl3.predictedCertChain[i]; i++) { - certificate_message_len += 3; - certificate_message_len += - ss->ssl3.predictedCertChain[i]->derCert.len; - } - - header[0] = certificate; - PutBE24(header + 1, certificate_message_len); - hashUpdate(header, 4, ctx); - - PutBE24(header, certificate_message_len - 3); - hashUpdate(header, 3, ctx); - - for (i = 0; ss->ssl3.predictedCertChain[i]; i++) { - unsigned int len = ss->ssl3.predictedCertChain[i]->derCert.len; - PutBE24(header, len); - hashUpdate(header, 3, ctx); - hashUpdate(ss->ssl3.predictedCertChain[i]->derCert.data, len, ctx); - } - - header[0] = server_hello_done; - header[1] = header[2] = header[3] = 0; - hashUpdate(header, 4, ctx); - } - - return PR_TRUE; -} - -/* ssl3_SnapStartHash is called with the contents of the server's predicted - * response and updates both the Finished hash and an FNV641a hash. */ -static void -ssl3_SnapStartHash(const unsigned char *data, unsigned int len, void *ctx) -{ - SECStatus rv; - void **ptrs = (void **) ctx; - sslSocket *ss = ptrs[0]; - PRUint64 *fnv = ptrs[1]; - - FNV1A64_Update(fnv, data, len); - rv = ssl3_UpdateHandshakeHashes(ss, (unsigned char *) data, len); - if (rv != SECSuccess) - PR_Assert("rv == SECSuccess", __FILE__, __LINE__); -} - -static PRInt32 -ssl3_SendEmptySnapStartXtn(sslSocket *ss, PRBool append, PRUint32 maxBytes) -{ - SECStatus rv; - - if (maxBytes < 4) - return 0; - - if (append) { - rv = ssl3_AppendHandshakeNumber(ss, ssl_snap_start_xtn, 2); - if (rv != SECSuccess) - return -1; - rv = ssl3_AppendHandshakeNumber(ss, 0 /* empty extension */, 2); - if (rv != SECSuccess) - return -1; - if (!ss->sec.isServer) { - TLSExtensionData *xtnData = &ss->xtnData; - xtnData->advertised[xtnData->numAdvertised++] = ssl_snap_start_xtn; - } - } - return 4; -} - -static SECStatus -ssl3_BufferEnsure(sslBuffer *buf, unsigned int extra_bytes) -{ - if (buf->space < buf->len + extra_bytes) - return sslBuffer_Grow(buf, buf->len + extra_bytes); - return SECSuccess; -} - -/* ssl3_AppendSnapStartRecordHeader appends a 5 byte TLS record header to the - * sendBuf of the given sslSocket. */ -static SECStatus -ssl3_AppendSnapStartRecordHeader(sslSocket *ss, SSL3ContentType type, - unsigned int len) -{ - SECStatus rv; - - rv = ssl3_BufferEnsure(&ss->sec.ci.sendBuf, 5); - if (rv != SECSuccess) - return rv; - ss->sec.ci.sendBuf.buf[ss->sec.ci.sendBuf.len + 0] = type; - PutBE16(&ss->sec.ci.sendBuf.buf[ss->sec.ci.sendBuf.len + 1], ss->version); - PutBE16(&ss->sec.ci.sendBuf.buf[ss->sec.ci.sendBuf.len + 3], len); - ss->sec.ci.sendBuf.len += 5; - return SECSuccess; -} - -/* ssl3_AppendSnapStartHandshakeRecord appends a (possibly encrypted) record to -** the sendBuf of the given sslSocket. -** f: a function which will append the bytes of the record (not including the -** 5 byte header) to the sendBuf. -*/ -static SECStatus -ssl3_AppendSnapStartHandshakeRecord(sslSocket *ss, SECStatus (*f) (sslSocket*), - PRBool encrypt) -{ - SECStatus rv; - unsigned int record_offset, record_len; - - /* ssl3_CompressMACEncryptRecord will deal with the record header if we are - * encrypting. */ - if (!encrypt) { - /* The zero length argument here is a dummy value. We write the real - * length once we know it, below. */ - rv = ssl3_AppendSnapStartRecordHeader(ss, content_handshake, 0); - if (rv != SECSuccess) - return rv; - } - - record_offset = ss->sec.ci.sendBuf.len; - rv = f(ss); - if (rv != SECSuccess) - return rv; - record_len = ss->sec.ci.sendBuf.len - record_offset; - if (!encrypt) { - PutBE16(&ss->sec.ci.sendBuf.buf[record_offset - 2], record_len); - } else { - /* ssl3_CompressMACEncryptRecord writes to |ss->sec.writeBuf| - * so we copy it back to |ss->sec.ci.sendBuf| */ - /* TODO(agl): the buffer copy here is a bodge. See TODO at the top of - * the file. */ - rv = ssl3_CompressMACEncryptRecord( - ss, content_handshake, - &ss->sec.ci.sendBuf.buf[record_offset], record_len); - if (rv != SECSuccess) - return rv; - ss->sec.ci.sendBuf.len -= record_len; - ssl3_BufferEnsure(&ss->sec.ci.sendBuf, ss->sec.writeBuf.len); - memcpy(&ss->sec.ci.sendBuf.buf[record_offset], ss->sec.writeBuf.buf, - ss->sec.writeBuf.len); - ss->sec.ci.sendBuf.len += ss->sec.writeBuf.len; - ss->sec.writeBuf.len = 0; - } - - return SECSuccess; -} - -/* ssl3_AppendSnapStartApplicationData appends an encrypted Application Data -** record the sendBuf of the given sslSocket. -*/ -static SECStatus ssl3_AppendSnapStartApplicationData( - sslSocket *ss, const SSL3Opaque *data, unsigned int len) -{ - SECStatus rv; - - /* TODO(agl): the buffer copy here is a bodge. See TODO at the top of the - * file. */ - rv = ssl3_CompressMACEncryptRecord(ss, content_application_data, data, len); - if (rv != SECSuccess) - return rv; - rv = ssl3_BufferEnsure(&ss->sec.ci.sendBuf, ss->sec.writeBuf.len); - if (rv != SECSuccess) - return rv; - memcpy(&ss->sec.ci.sendBuf.buf[ss->sec.ci.sendBuf.len], - ss->sec.writeBuf.buf, ss->sec.writeBuf.len); - ss->sec.ci.sendBuf.len += ss->sec.writeBuf.len; - ss->sec.writeBuf.len = 0; - - return SECSuccess; -} - -static SECStatus ssl3_SendSnapStartFinished(sslSocket *ss) -{ - /* We use ssl_SEND_FLAG_NO_FLUSH here because this finished message is - * going to end up in the middle of the Snap Start extension. So - * transmitting |sendBuf| at this point would result in an incomplete - * ClientHello. */ - return ssl3_SendFinished(ss, ssl_SEND_FLAG_NO_FLUSH); -} - -/* ssl3_FindOrbit is called for each extension in a ServerHello message. It -** tests for a Snap Start extension and records the server's orbit when found. -** data: the extension data (including the four type and length bytes) -** length: the length, in bytes, of |data| -** ptr: a pointer to a uint8_t[9]. The orbit, if found, is copied into the -** first 8 bytes and then the ninth byte is set to one. -*/ -static void -ssl3_FindOrbit(const unsigned char *data, unsigned int length, void *ptr) -{ - unsigned char *orbit = (unsigned char *) ptr; - - unsigned int extension_num = GetBE16(data); - if (extension_num == ssl_snap_start_xtn && - length == 4 + 8 /* orbit */ + 2 /* snap start cipher suite */) { - memcpy(orbit, data + 4, 8); - /* A last byte of 1 indicates that the previous eight are valid. */ - orbit[8] = 1; - } -} - -/* ssl3_CanSnapStart returns true if we are able to perform Snap Start on -** the given socket. -** extensions: on successful return, this is filled in with the contents of -** the server's predicted extensions. This points within -** |ss->ssl3.serverHelloPredictionData|. -** resuming: PR_TRUE iff we wish to attempt a Snap Start resume -** out_orbit: if this function returns PR_TRUE, then |out_orbit| is filled -** with the server's predicted orbit value. -** The |hs.cipher_suite|, |hs.cipher_def| and |hs.compression| fields of |ss| -** are set to match the predicted ServerHello on successful exit (and may still -** be modified on failure). -*/ -static PRBool -ssl3_CanSnapStart(sslSocket *ss, SECItem *extensions, PRBool resuming, - unsigned char out_orbit[8]) { - const unsigned char *server_hello; - unsigned int server_hello_len, session_id_len, cipher_suite_offset; - unsigned int extensions_offset, cipher_suite, compression_method; - unsigned char orbit[9]; - SECStatus rv; - SSL3ProtocolVersion version; - - /* If we don't have the information needed then we can't perform a Snap - * Start. */ - if (!ss->ssl3.predictedCertChain || !ss->ssl3.serverHelloPredictionData.data) - return PR_FALSE; - - /* When the sizes of the fields in the ClientHello are calculated, they'll - * take the length of the Snap Start extension to be zero, so currently - * it's as if this extension didn't exist, which is the state that we - * need. */ - - server_hello = ss->ssl3.serverHelloPredictionData.data; - server_hello_len = ss->ssl3.serverHelloPredictionData.len; - - if (server_hello_len < 2 + 32 + 1) - return PR_FALSE; - session_id_len = server_hello[2 + 32]; - cipher_suite_offset = 2 + 32 + 1 + session_id_len; - if (server_hello_len < cipher_suite_offset + 3) - return PR_FALSE; - extensions_offset = cipher_suite_offset + 3; - - version = (SSL3ProtocolVersion) GetBE16(server_hello); - if (MSB(version) < MSB(SSL_LIBRARY_VERSION_3_0)) - return PR_FALSE; - rv = ssl3_NegotiateVersion(ss, version); - if (rv != SECSuccess) - return PR_FALSE; - - cipher_suite = GetBE16(&server_hello[cipher_suite_offset]); - ss->ssl3.hs.cipher_suite = (ssl3CipherSuite)cipher_suite; - ss->ssl3.hs.suite_def = ssl_LookupCipherSuiteDef(ss->ssl3.hs.cipher_suite); - if (!ss->ssl3.hs.suite_def) - return PR_FALSE; - compression_method = server_hello[cipher_suite_offset + 2]; - if (compression_method != ssl_compression_null) { - /* TODO(agl): support compression. */ - return PR_FALSE; - } - ss->ssl3.hs.compression = ssl_compression_null; - - extensions->data = (unsigned char *) server_hello + extensions_offset; - extensions->len = server_hello_len - extensions_offset; - - /* The last byte is used to indictate that the previous eight are valid. */ - orbit[8] = 0; - if (!ssl3_ForEachExtension(extensions, resuming, ssl3_FindOrbit, orbit)) - return PR_FALSE; - - if (!orbit[8]) - return PR_FALSE; - - memcpy(out_orbit, orbit, 8); - - return PR_TRUE; -} - -/* ssl3_UpdateClientHelloLengths rewrites the handshake header length and -** extensions length in the ClientHello to reflect the addition of the Snap -** Start extension. -** snap_start_extension_len_offset: the number of bytes of the ClientHello to -** skip in order to find the embedded length of the Snap Start extension. -*/ -static void -ssl3_UpdateClientHelloLengths(sslSocket *ss, - unsigned int snap_start_extension_len_offset, - sslSessionID *sid) { - unsigned int extension_length, old_length, new_length, new_session_id_len; - unsigned int offset, ciphers_length, compressions_len; - - extension_length = - ss->sec.ci.sendBuf.len - snap_start_extension_len_offset - 2; - PutBE16(&ss->sec.ci.sendBuf.buf[snap_start_extension_len_offset], - extension_length); - - /* The length in the handshake header is short by extension_length + 4 - * bytes. */ - old_length = GetBE24(&ss->sec.ci.sendBuf.buf[1]); - new_length = old_length + extension_length + 4; - PutBE24(&ss->sec.ci.sendBuf.buf[1], new_length); - - /* The length of the extensions block is similarly wrong. */ - new_session_id_len = 0; - if (sid) - new_session_id_len = sid->u.ssl3.sessionIDLength; - offset = 4 + 2 + 32 + 1 + new_session_id_len; - ciphers_length = GetBE16(&ss->sec.ci.sendBuf.buf[offset]); - offset += 2 + ciphers_length; - compressions_len = ss->sec.ci.sendBuf.buf[offset]; - offset += 1 + compressions_len; - old_length = GetBE16(&ss->sec.ci.sendBuf.buf[offset]); - new_length = old_length + extension_length + 4; - PutBE16(&ss->sec.ci.sendBuf.buf[offset], new_length); -} - -/* ssl3_FindServerNPNExtension is a callback function for ssl3_ForEachExtension. - * It looks for a Next Protocol Negotiation and saves the payload of the - * extension in the given SECItem */ -static void -ssl3_FindServerNPNExtension(const unsigned char* data, unsigned int length, - void *ctx) -{ - SECItem *server_npn_extension = (SECItem*) ctx; - - unsigned int extension_num = GetBE16(data); - if (extension_num == ssl_next_proto_neg_xtn && length >= 4) { - server_npn_extension->data = (unsigned char*)data + 4; - server_npn_extension->len = length - 4; - } -} - -/* ssl3_MaybeWriteNextProtocol deals with the interaction of Next Protocol - * Negotiation and Snap Start. It's called just before we serialise the embedded - * Finished message in the extension. At this point, if NPN is enabled, we have - * to include a NextProtocol message. */ -static SECStatus -ssl3_MaybeWriteNextProtocol(sslSocket *ss, SECItem *server_hello_extensions) -{ - PRUint16 i16; - SECItem server_npn_extension; - - for (i16 = 0; i16 < ss->xtnData.numAdvertised; i16++) { - if (ss->xtnData.advertised[i16] == ssl_next_proto_neg_xtn) - break; - } - - if (i16 == ss->xtnData.numAdvertised) { - /* We didn't send an NPN extension, so no need to do anything here. */ - return SECSuccess; - } - - memset(&server_npn_extension, 0, sizeof(server_npn_extension)); - - ssl3_ForEachExtension( - server_hello_extensions, PR_FALSE /* is_resuming: value doesn't matter - in this case */, ssl3_FindServerNPNExtension, &server_npn_extension); - - if (server_npn_extension.data == NULL) { - /* We predicted that the server doesn't support NPN, so nothing to do - * here. */ - return SECSuccess; - } - - ssl3_ClientHandleNextProtoNegoXtn(ss, ssl_next_proto_neg_xtn, - &server_npn_extension); - - if (ss->ssl3.nextProtoState == SSL_NEXT_PROTO_NO_SUPPORT) { - /* The server's predicted NPN extension was malformed. We're didn't pick - * a protocol so we won't send a NextProtocol message. However, this is - * probably fatal to the connection. */ - return SECSuccess; - } - - return ssl3_AppendSnapStartHandshakeRecord(ss, ssl3_SendNextProto, - PR_TRUE /* encrypt */); -} - -/* ssl3_SendSnapStartXtn appends a Snap Start extension. It assumes that the - * inchoate ClientHello is in |ss->sec.ci.sendBuf|. */ -PRInt32 -ssl3_SendSnapStartXtn(sslSocket *ss, PRBool append, PRUint32 maxBytes) -{ - unsigned char orbit[8]; - PRBool resuming = PR_FALSE; - unsigned char suggested_server_random[32]; - SECStatus rv; - PRUint64 fnv; - /* The context for |ssl3_SnapStartHash|. The first pointer points to |ss| - * and the second to the running FNV1A64 hash of the predicted server - * response. */ - void *ctx[2]; - unsigned int snap_start_extension_len_offset, original_sendbuf_len; - ssl3CipherSpec *temp; - sslSessionID *sid; - SECItem server_extensions; - - if (!ss->opt.enableSnapStart) - return 0; - - original_sendbuf_len = ss->sec.ci.sendBuf.len; - - /* This function is called twice for each ClientHello emitted. The first - * time around is to calculate the sizes of the extension (|append| is - * false). The second time around is to actually write out the bytes - * (|append| is true). - * - * We always return 0 bytes in each case because we want to be able to hash - * the inchoate ClientHello as if this extension was missing: that's why - * it's important that this always be the last extension serialised. */ - sid = ss->sec.ci.sid; - - if (!ss->opt.enableSessionTickets || ss->sec.isServer) - return 0; - - /* If we are sending a SessionTicket then the first time around - * ticketTimestampVerified will be true but it's reset after serialising - * the session ticket extension, so we have - * |clientSentNonEmptySessionTicket|. */ - if (ss->xtnData.clientSentNonEmptySessionTicket) { - resuming = PR_TRUE; - } else if (sid->u.ssl3.sessionTicket.ticket.data && - ss->xtnData.ticketTimestampVerified) { - resuming = PR_TRUE; - } - - if (!ssl3_CanSnapStart(ss, &server_extensions, resuming, orbit)) - return ssl3_SendEmptySnapStartXtn(ss, append, maxBytes); - - /* At this point we are happy that we are going to send a non-empty Snap - * Start extension. If we are still calculating length then we lie and - * return 0 so that everything is set up as if the extension didn't exist - * when this function is called again later. */ - - if (!append) - return 0; - - /* |ss->sec.ci.sendBuf.buf| contains the inchoate ClientHello. This copies - * the ClientHello's gmt_unix_time into the suggested server random. */ - memcpy(suggested_server_random, ss->sec.ci.sendBuf.buf + 6, 4); - memcpy(suggested_server_random + 4, orbit, 8); - rv = PK11_GenerateRandom(suggested_server_random + 12, 20); - if (rv != SECSuccess) - goto loser; - memcpy(ss->ssl3.serverHelloPredictionData.data + 2, suggested_server_random, - 32); - - memcpy(&ss->ssl3.hs.server_random, suggested_server_random, 32); - - PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) ); - rv = ssl3_SetupPendingCipherSpec(ss); - if (rv != SECSuccess) - goto loser; - ss->ssl3.hs.isResuming = resuming; - - FNV1A64_Init(&fnv); - ctx[0] = ss; - ctx[1] = &fnv; - - if (!ssl3_PredictServerResponse(ss, &ss->ssl3.serverHelloPredictionData, - resuming, ssl3_SnapStartHash, ctx)) { - /* It's not a fatal error if the predicted ServerHello was invalid. */ - return 0; - } - FNV1A64_Final(&fnv); - - /* Now we grow the send buffer to accomodate the extension type and length, - * orbit, suggested random and predicted server response hash without - * calling ssl3_AppendHandshake (which would also update the Finished - * hash). */ - if (ssl3_BufferEnsure(&ss->sec.ci.sendBuf, 4 + 8 + 20 + 8) != SECSuccess) - goto loser; - - PutBE16(&ss->sec.ci.sendBuf.buf[ss->sec.ci.sendBuf.len], - ssl_snap_start_xtn); - ss->sec.ci.sendBuf.len += 2; - /* Skip over the length for now. */ - snap_start_extension_len_offset = ss->sec.ci.sendBuf.len; - ss->sec.ci.sendBuf.len += 2; - memcpy(ss->sec.ci.sendBuf.buf + ss->sec.ci.sendBuf.len, orbit, 8); - ss->sec.ci.sendBuf.len += 8; - memcpy(&ss->sec.ci.sendBuf.buf[ss->sec.ci.sendBuf.len], - suggested_server_random + 12, 20); - ss->sec.ci.sendBuf.len += 20; - memcpy(ss->sec.ci.sendBuf.buf + ss->sec.ci.sendBuf.len, &fnv, 8); - ss->sec.ci.sendBuf.len += 8; - - if (!resuming) { - /* Write ClientKeyExchange */ - ss->sec.peerCert = - CERT_DupCertificate(ss->ssl3.predictedCertChain[0]); - rv = ssl3_AppendSnapStartHandshakeRecord( - ss, ssl3_SendClientKeyExchange, PR_FALSE /* do not encrypt */); - if (rv != SECSuccess) - goto loser; - } else { - SSL3Finished hashes; - TLSFinished tlsFinished; - unsigned char hdr[4]; - - rv = ssl3_SetupMasterSecretFromSessionID(ss); - if (rv == SECFailure) - goto loser; - - if (sid->peerCert != NULL) { - ss->sec.peerCert = CERT_DupCertificate(sid->peerCert); - ssl3_CopyPeerCertsFromSID(ss, sid); - } - - rv = ssl3_InitPendingCipherSpec(ss, NULL /* re-use master secret */); - if (rv != SECSuccess) - goto loser; - - /* Need to add the server's predicted Finished message to our handshake - * hash in order to be able to produce our own Finished message. */ - rv = ssl3_ComputeHandshakeHashes(ss, ss->ssl3.pwSpec, &hashes, - 0 /* only for SSL3 */); - if (rv != SECSuccess) - goto loser; - - rv = ssl3_ComputeTLSFinished(ss->ssl3.pwSpec, PR_TRUE /* isServer */, - &hashes, &tlsFinished); - if (rv != SECSuccess) - goto loser; - - hdr[0] = (unsigned char) finished; - hdr[1] = hdr[2] = 0; - hdr[3] = sizeof(tlsFinished.verify_data); - ssl3_UpdateHandshakeHashes(ss, hdr, sizeof(hdr)); - ssl3_UpdateHandshakeHashes(ss, tlsFinished.verify_data, - sizeof(tlsFinished.verify_data)); - - /* Store the Finished message so that we can verify it later */ - memcpy(&ss->ssl3.hs.finishedMsgs.tFinished[1], tlsFinished.verify_data, - sizeof(tlsFinished.verify_data)); - } - - /* Write ChangeCipherSpec */ - rv = ssl3_AppendSnapStartRecordHeader(ss, content_change_cipher_spec, 1); - if (rv != SECSuccess) - goto loser; - rv = ssl3_BufferEnsure(&ss->sec.ci.sendBuf, 1); - if (rv != SECSuccess) - goto loser; - ss->sec.ci.sendBuf.buf[ss->sec.ci.sendBuf.len] = change_cipher_spec_choice; - ss->sec.ci.sendBuf.len++; - - /* We swap |cwSpec| and |pwSpec| temporarily in order to encrypt some - * records before switching them back so that the whole ClientHello doesn't - * get encrypted. */ - ssl_GetSpecWriteLock(ss); - temp = ss->ssl3.cwSpec; - ss->ssl3.cwSpec = ss->ssl3.pwSpec; - ss->ssl3.pwSpec = temp; - ss->ssl3.cwSpec->write_seq_num.high = 0; - ss->ssl3.cwSpec->write_seq_num.low = 0; - ssl_ReleaseSpecWriteLock(ss); - - rv = ssl3_MaybeWriteNextProtocol(ss, &server_extensions); - if (rv != SECSuccess) - goto loser; - - /* Write Finished */ - rv = ssl3_AppendSnapStartHandshakeRecord(ss, ssl3_SendSnapStartFinished, - PR_TRUE /* encrypt */); - if (rv != SECSuccess) - goto loser; - - /* Write application data */ - if (ss->ssl3.snapStartApplicationData.data) { - rv = ssl3_AppendSnapStartApplicationData( - ss, ss->ssl3.snapStartApplicationData.data, - ss->ssl3.snapStartApplicationData.len); - SECITEM_FreeItem(&ss->ssl3.snapStartApplicationData, PR_FALSE); - if (rv != SECSuccess) - goto loser; - } - - /* Revert the write cipher spec because the ClientHello will get encrypted - * with it otherwise. */ - ssl_GetSpecWriteLock(ss); - temp = ss->ssl3.cwSpec; - ss->ssl3.cwSpec = ss->ssl3.pwSpec; - ss->ssl3.pwSpec = temp; - ssl_ReleaseSpecWriteLock(ss); - - /* Update the lengths in the ClientHello to reflect this extension. */ - ssl3_UpdateClientHelloLengths(ss, snap_start_extension_len_offset, sid); - - /* Keep a copy of the ClientHello around so that we can hash it in the case - * the the Snap Start handshake is rejected. */ - - if (SECITEM_AllocItem(NULL, &ss->ssl3.hs.origClientHello, - ss->sec.ci.sendBuf.len) == NULL) { - goto loser; - } - memcpy(ss->ssl3.hs.origClientHello.data, ss->sec.ci.sendBuf.buf, - ss->sec.ci.sendBuf.len); - ss->ssl3.hs.origClientHello.len = ss->sec.ci.sendBuf.len; - - ss->xtnData.advertised[ss->xtnData.numAdvertised++] = ssl_snap_start_xtn; - - if (resuming) { - ss->ssl3.hs.snapStartType = snap_start_resume; - } else { - ss->ssl3.hs.snapStartType = snap_start_full; - } - - return 0; - -loser: - /* In the case of an error we revert the length of the sendBuf to remove - * any partial data that we may have appended. */ - ss->sec.ci.sendBuf.len = original_sendbuf_len; - return -1; -} - -SECStatus ssl3_ClientHandleSnapStartXtn(sslSocket *ss, PRUint16 ex_type, - SECItem *data) { - /* The work of saving the ServerHello is done in ssl3_HandleServerHello, - * where its contents are available. Here we renognise that the saved - * ServerHello message contains a Snap Start extension and mark it as - * valid. */ - ss->ssl3.serverHelloPredictionDataValid = PR_TRUE; - return SECSuccess; -} - -SECStatus -SSL_SetPredictedPeerCertificates(PRFileDesc *fd, CERTCertificate **certs, - unsigned int numCerts) -{ - sslSocket *ss; - unsigned int i; - - ss = ssl_FindSocket(fd); - if (!ss) { - SSL_DBG(("%d: SSL[%d]: bad socket in SSL_SetPredictedPeerCertificates", - SSL_GETPID(), fd)); - return SECFailure; - } - - ss->ssl3.predictedCertChain = - PORT_NewArray(CERTCertificate*, numCerts + 1); - if (!ss->ssl3.predictedCertChain) - return SECFailure; /* error code was set */ - for (i = 0; i < numCerts; i++) - ss->ssl3.predictedCertChain[i] = CERT_DupCertificate(certs[i]); - ss->ssl3.predictedCertChain[numCerts] = NULL; - - return SECSuccess; -} - -void -ssl3_CleanupPredictedPeerCertificates(sslSocket *ss) { - unsigned int i; - - if (!ss->ssl3.predictedCertChain) - return; - - for (i = 0; ss->ssl3.predictedCertChain[i]; i++) { - CERT_DestroyCertificate(ss->ssl3.predictedCertChain[i]); - } - - PORT_Free(ss->ssl3.predictedCertChain); - ss->ssl3.predictedCertChain = NULL; -} - -SECStatus -SSL_GetPredictedServerHelloData(PRFileDesc *fd, const unsigned char **data, - unsigned int *data_len) -{ - sslSocket *ss; - - ss = ssl_FindSocket(fd); - if (!ss) { - SSL_DBG(("%d: SSL[%d]: bad socket in SSL_GetPredictedServerHelloData", - SSL_GETPID(), fd)); - *data = NULL; - *data_len = 0; - return SECFailure; - } - - if (!ss->ssl3.serverHelloPredictionDataValid) { - *data = NULL; - *data_len = 0; - } else { - *data = ss->ssl3.serverHelloPredictionData.data; - *data_len = ss->ssl3.serverHelloPredictionData.len; - } - return SECSuccess; -} - -SECStatus -SSL_SetPredictedServerHelloData(PRFileDesc *fd, const unsigned char *data, - unsigned int data_len) -{ - sslSocket *ss; - - ss = ssl_FindSocket(fd); - if (!ss) { - SSL_DBG(("%d: SSL[%d]: bad socket in SSL_SetPredictedServerHelloData", - SSL_GETPID(), fd)); - return SECFailure; - } - - if (ss->ssl3.serverHelloPredictionData.data) - SECITEM_FreeItem(&ss->ssl3.serverHelloPredictionData, PR_FALSE); - if (!SECITEM_AllocItem(NULL, &ss->ssl3.serverHelloPredictionData, data_len)) - return SECFailure; - memcpy(ss->ssl3.serverHelloPredictionData.data, data, data_len); - return SECSuccess; -} - -SECStatus -SSL_SetSnapStartApplicationData(PRFileDesc *fd, const unsigned char *data, - unsigned int data_len) -{ - sslSocket *ss; - - ss = ssl_FindSocket(fd); - if (!ss) { - SSL_DBG(("%d: SSL[%d]: bad socket in SSL_SetSnapStartApplicationData", - SSL_GETPID(), fd)); - return SECFailure; - } - - if (ss->ssl3.snapStartApplicationData.data) - SECITEM_FreeItem(&ss->ssl3.snapStartApplicationData, PR_FALSE); - if (!SECITEM_AllocItem(NULL, &ss->ssl3.snapStartApplicationData, data_len)) - return SECFailure; - memcpy(ss->ssl3.snapStartApplicationData.data, data, data_len); - return SECSuccess; -} - -SECStatus -SSL_GetSnapStartResult(PRFileDesc *fd, SSLSnapStartResult *result) -{ - sslSocket *ss; - - ss = ssl_FindSocket(fd); - if (!ss) { - SSL_DBG(("%d: SSL[%d]: bad socket in SSL_GetSnapStartResult", - SSL_GETPID(), fd)); - return SECFailure; - } - - switch (ss->ssl3.hs.snapStartType) { - case snap_start_full: - *result = SSL_SNAP_START_FULL; - break; - case snap_start_recovery: - *result = SSL_SNAP_START_RECOVERY; - break; - case snap_start_resume: - *result = SSL_SNAP_START_RESUME; - break; - case snap_start_resume_recovery: - *result = SSL_SNAP_START_RESUME_RECOVERY; - break; - default: - PORT_Assert(ss->ssl3.hs.snapStartType == snap_start_none); - *result = SSL_SNAP_START_NONE; - break; - } - - return SECSuccess; -} - -/* Called form ssl3_HandleServerHello in the case that we sent a Snap Start -** ClientHello but received a ServerHello in reply. -*/ -SECStatus -ssl3_ResetForSnapStartRecovery(sslSocket *ss, SSL3Opaque *b, PRUint32 length) -{ - SECStatus rv; - PRUint8 hdr[4]; - - ss->ssl3.hs.ws = wait_server_hello; - - /* Need to reset the Finished hashes to include the full ClientHello - * message. */ - - rv = ssl3_RestartHandshakeHashes(ss); - if (rv != SECSuccess) - return rv; - rv = ssl3_UpdateHandshakeHashes(ss, ss->ssl3.hs.origClientHello.data, - ss->ssl3.hs.origClientHello.len); - SECITEM_FreeItem(&ss->ssl3.hs.origClientHello, PR_FALSE); - if (rv != SECSuccess) - return rv; - - hdr[0] = (PRUint8)server_hello; - hdr[1] = (PRUint8)(length >> 16); - hdr[2] = (PRUint8)(length >> 8); - hdr[3] = (PRUint8)(length ); - - rv = ssl3_UpdateHandshakeHashes(ss, hdr, sizeof(hdr)); - if (rv != SECSuccess) - return rv; - rv = ssl3_UpdateHandshakeHashes(ss, b, length); - if (rv != SECSuccess) - return rv; - - if (ss->ssl3.hs.snapStartType == snap_start_full) { - ss->ssl3.hs.snapStartType = snap_start_recovery; - } else { - ss->ssl3.hs.snapStartType = snap_start_resume_recovery; - } - - ss->ssl3.nextProtoState = SSL_NEXT_PROTO_NO_SUPPORT; - - ssl3_DestroyCipherSpec(ss->ssl3.pwSpec, PR_TRUE/*freeSrvName*/); - - return SECSuccess; -} diff --git a/net/third_party/nss/ssl/ssl.def b/net/third_party/nss/ssl/ssl.def index 76417d0..35cc1e3 100644 --- a/net/third_party/nss/ssl/ssl.def +++ b/net/third_party/nss/ssl/ssl.def @@ -155,19 +155,9 @@ SSL_SNISocketConfigHook; ;+NSS_CHROMIUM { ;+ global: SSL_GetNextProto; -SSL_SetNextProtoNego; -;+ local: -;+*; -;+}; -;+NSS_3.13 { # NSS 3.13 release -;+ global: -SSL_GetPredictedServerHelloData; -SSL_GetSnapStartResult; SSL_GetStapledOCSPResponse; SSL_PeerCertificateChain; -SSL_SetPredictedPeerCertificates; -SSL_SetPredictedServerHelloData; -SSL_SetSnapStartApplicationData; +SSL_SetNextProtoNego; ;+ local: ;+*; ;+}; diff --git a/net/third_party/nss/ssl/ssl.h b/net/third_party/nss/ssl/ssl.h index f2a0c11..563cfd5 100644 --- a/net/third_party/nss/ssl/ssl.h +++ b/net/third_party/nss/ssl/ssl.h @@ -139,16 +139,7 @@ SSL_IMPORT PRFileDesc *SSL_ImportFD(PRFileDesc *model, PRFileDesc *fd); /* occur on RSA or DH ciphersuites where the cipher's key length is >= 80 */ /* bits. The advantage of False Start is that it saves a round trip for */ /* client-speaks-first protocols when performing a full handshake. */ -#define SSL_ENABLE_SNAP_START 23 /* Enable SSL snap start (off by */ - /* default, applies only to */ - /* clients). Snap start is a way */ -/* of performing TLS handshakes with no round trips. The client's entire */ -/* handshake is included in the first handshake message, along with */ -/* optional application data. In order to do this, information from a */ -/* previous connection to the same server is required. See */ -/* SSL_GetPredictedServerHelloData, SSL_SetPredictedPeerCertificates and */ -/* SSL_SetSnapStartApplicationData. */ -#define SSL_ENABLE_OCSP_STAPLING 24 /* Request OCSP stapling (client) */ +#define SSL_ENABLE_OCSP_STAPLING 23 /* Request OCSP stapling (client) */ #ifdef SSL_DEPRECATED_FUNCTION /* Old deprecated function names */ @@ -447,49 +438,6 @@ SSL_IMPORT SECStatus SSL_BadCertHook(PRFileDesc *fd, SSLBadCertHandler f, void *arg); /* -** Set the predicted chain of certificates for the peer. This is used for the -** TLS Snap Start extension. Note that the SSL_ENABLE_SNAP_START option must -** be set for this to occur. -** -** This function takes a reference to each of the given certificates. -*/ -SSL_IMPORT SECStatus SSL_SetPredictedPeerCertificates( - PRFileDesc *fd, CERTCertificate **certs, - unsigned int numCerts); - -/* -** Get the data needed to predict the server's hello message in the future. On -** return, |*data| will either be NULL (in which case no data is available and -** |*data_len| will be zero) or it will point to a buffer within the internal -** data of |fd| and |*data_len| will contain the number of bytes available. If -** non-NULL, |*data| will persist at least until the next handshake on |fd|. -*/ -SSL_IMPORT SECStatus SSL_GetPredictedServerHelloData( - PRFileDesc *fd, const unsigned char **data, - unsigned int *data_len); - -/* -** Set the predicted server hello data. This is used for the TLS Snap Start -** extension. Note that the SSL_ENABLE_SNAP_START option must be set for this -** to occur. -*/ -SSL_IMPORT SECStatus SSL_SetPredictedServerHelloData( - PRFileDesc *fd, const unsigned char *data, unsigned int data_len); - -/* Set the application data which will be transmitted in a Snap Start -** handshake. If the Snap Start handshake fails, this data will be -* retransmitted automatically. */ -SSL_IMPORT SECStatus SSL_SetSnapStartApplicationData( - PRFileDesc *fd, const unsigned char *data, unsigned int data_len); - -/* Get the result of a Snap Start handshake. It's valid to call then even if -** SSL_ENABLE_SNAP_START hasn't been set, although the result will always be -** SSL_SNAP_START_NONE. -*/ -SSL_IMPORT SECStatus SSL_GetSnapStartResult(PRFileDesc* socket, - SSLSnapStartResult* result); - -/* ** Configure SSL socket for running a secure server. Needs the ** certificate for the server and the servers private key. The arguments ** are copied. diff --git a/net/third_party/nss/ssl/ssl3con.c b/net/third_party/nss/ssl/ssl3con.c index ac23c4c..0997e18 100644 --- a/net/third_party/nss/ssl/ssl3con.c +++ b/net/third_party/nss/ssl/ssl3con.c @@ -72,8 +72,7 @@ #endif static void ssl3_CleanupPeerCerts(sslSocket *ss); -static void ssl3_CopyPeerCertsToSID(ssl3CertNode *certs, - sslSessionID *sid); +static void ssl3_CopyPeerCertsFromSID(sslSocket *ss, sslSessionID *sid); static PK11SymKey *ssl3_GenerateRSAPMS(sslSocket *ss, ssl3CipherSpec *spec, PK11SlotInfo * serverKeySlot); static SECStatus ssl3_DeriveMasterSecret(sslSocket *ss, PK11SymKey *pms); @@ -83,10 +82,14 @@ static SECStatus ssl3_InitState( sslSocket *ss); static SECStatus ssl3_SendCertificate( sslSocket *ss); static SECStatus ssl3_SendEmptyCertificate( sslSocket *ss); static SECStatus ssl3_SendCertificateRequest(sslSocket *ss); +static SECStatus ssl3_SendNextProto( sslSocket *ss); +static SECStatus ssl3_SendFinished( sslSocket *ss, PRInt32 flags); static SECStatus ssl3_SendServerHello( sslSocket *ss); static SECStatus ssl3_SendServerHelloDone( sslSocket *ss); static SECStatus ssl3_SendServerKeyExchange( sslSocket *ss); static SECStatus ssl3_NewHandshakeHashes( sslSocket *ss); +static SECStatus ssl3_UpdateHandshakeHashes( sslSocket *ss, unsigned char *b, + unsigned int l); static SECStatus Null_Cipher(void *ctx, unsigned char *output, int *outputLen, int maxOutputLen, const unsigned char *input, @@ -580,7 +583,7 @@ void SSL_AtomicIncrementLong(long * x) /* return pointer to ssl3CipherSuiteDef for suite, or NULL */ /* XXX This does a linear search. A binary search would be better. */ -const ssl3CipherSuiteDef * +static const ssl3CipherSuiteDef * ssl_LookupCipherSuiteDef(ssl3CipherSuite suite) { int cipher_suite_def_len = @@ -1166,7 +1169,7 @@ ssl3_CleanupKeyMaterial(ssl3KeyMaterial *mat) ** ssl3_DestroySSL3Info ** Caller must hold SpecWriteLock. */ -void +static void ssl3_DestroyCipherSpec(ssl3CipherSpec *spec, PRBool freeSrvName) { PRBool freeit = (PRBool)(!spec->bypassCiphers); @@ -1208,7 +1211,7 @@ ssl3_DestroyCipherSpec(ssl3CipherSpec *spec, PRBool freeSrvName) ** Caller must hold the ssl3 handshake lock. ** Acquires & releases SpecWriteLock. */ -SECStatus +static SECStatus ssl3_SetupPendingCipherSpec(sslSocket *ss) { ssl3CipherSpec * pwSpec; @@ -2040,7 +2043,7 @@ ssl3_ClientAuthTokenPresent(sslSessionID *sid) { #endif /* NSS_PLATFORM_CLIENT_AUTH */ } -SECStatus +static SECStatus ssl3_CompressMACEncryptRecord(sslSocket * ss, SSL3ContentType type, const SSL3Opaque * pIn, @@ -3102,7 +3105,7 @@ loser: return SECFailure; } -SECStatus +static SECStatus ssl3_RestartHandshakeHashes(sslSocket *ss) { SECStatus rv = SECSuccess; @@ -3180,7 +3183,7 @@ loser: ** ssl3_HandleHandshakeMessage() ** Caller must hold the ssl3Handshake lock. */ -SECStatus +static SECStatus ssl3_UpdateHandshakeHashes(sslSocket *ss, unsigned char *b, unsigned int l) { SECStatus rv = SECSuccess; @@ -3439,7 +3442,7 @@ ssl3_ConsumeHandshakeVariable(sslSocket *ss, SECItem *i, PRInt32 bytes, * Caller must hold a read or write lock on the Spec R/W lock. * (There is presently no way to assert on a Read lock.) */ -SECStatus +static SECStatus ssl3_ComputeHandshakeHashes(sslSocket * ss, ssl3CipherSpec *spec, /* uses ->master_secret */ SSL3Hashes * hashes, /* output goes here. */ @@ -4037,18 +4040,7 @@ ssl3_SendClientHello(sslSocket *ss) return rv; /* error code set by ssl3_FlushHandshake */ } - switch (ss->ssl3.hs.snapStartType) { - case snap_start_full: - ss->ssl3.hs.ws = wait_new_session_ticket; - break; - case snap_start_resume: - ss->ssl3.hs.ws = wait_change_cipher; - break; - default: - ss->ssl3.hs.ws = wait_server_hello; - break; - } - + ss->ssl3.hs.ws = wait_server_hello; return rv; } @@ -4739,7 +4731,7 @@ loser: /* Called from ssl3_HandleServerHelloDone(). */ -SECStatus +static SECStatus ssl3_SendClientKeyExchange(sslSocket *ss) { SECKEYPublicKey * serverKey = NULL; @@ -4879,94 +4871,6 @@ done: return rv; } -/* Called from ssl3_HandleServerHello to set up the master secret in - * ss->ssl3.pwSpec and the auth algorithm and kea type in ss->sec in the case - * of a successful session resumption. */ -SECStatus ssl3_SetupMasterSecretFromSessionID(sslSocket* ss) { - sslSessionID *sid = ss->sec.ci.sid; - ssl3CipherSpec *pwSpec = ss->ssl3.pwSpec; - SECItem wrappedMS; /* wrapped master secret. */ - - ss->sec.authAlgorithm = sid->authAlgorithm; - ss->sec.authKeyBits = sid->authKeyBits; - ss->sec.keaType = sid->keaType; - ss->sec.keaKeyBits = sid->keaKeyBits; - - /* 3 cases here: - * a) key is wrapped (implies using PKCS11) - * b) key is unwrapped, but we're still using PKCS11 - * c) key is unwrapped, and we're bypassing PKCS11. - */ - if (sid->u.ssl3.keys.msIsWrapped) { - PK11SlotInfo *slot; - PK11SymKey * wrapKey; /* wrapping key */ - CK_FLAGS keyFlags = 0; - - if (ss->opt.bypassPKCS11) { - /* we cannot restart a non-bypass session in a - ** bypass socket. - */ - return SECFailure; - } - /* unwrap master secret with PKCS11 */ - slot = SECMOD_LookupSlot(sid->u.ssl3.masterModuleID, - sid->u.ssl3.masterSlotID); - if (slot == NULL) { - return SECFailure; - } - if (!PK11_IsPresent(slot)) { - PK11_FreeSlot(slot); - return SECFailure; - } - wrapKey = PK11_GetWrapKey(slot, sid->u.ssl3.masterWrapIndex, - sid->u.ssl3.masterWrapMech, - sid->u.ssl3.masterWrapSeries, - ss->pkcs11PinArg); - PK11_FreeSlot(slot); - if (wrapKey == NULL) { - return SECFailure; - } - - if (ss->version > SSL_LIBRARY_VERSION_3_0) { /* isTLS */ - keyFlags = CKF_SIGN | CKF_VERIFY; - } - - wrappedMS.data = sid->u.ssl3.keys.wrapped_master_secret; - wrappedMS.len = sid->u.ssl3.keys.wrapped_master_secret_len; - pwSpec->master_secret = - PK11_UnwrapSymKeyWithFlags(wrapKey, sid->u.ssl3.masterWrapMech, - NULL, &wrappedMS, CKM_SSL3_MASTER_KEY_DERIVE, - CKA_DERIVE, sizeof(SSL3MasterSecret), keyFlags); - PK11_FreeSymKey(wrapKey); - if (pwSpec->master_secret == NULL) { - return SECFailure; - } - } else if (ss->opt.bypassPKCS11) { - /* MS is not wrapped */ - 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; - } else { - /* We CAN restart a bypass session in a non-bypass socket. */ - /* need to import the raw master secret to session object */ - PK11SlotInfo *slot = PK11_GetInternalSlot(); - wrappedMS.data = sid->u.ssl3.keys.wrapped_master_secret; - wrappedMS.len = sid->u.ssl3.keys.wrapped_master_secret_len; - pwSpec->master_secret = - PK11_ImportSymKey(slot, CKM_SSL3_MASTER_KEY_DERIVE, - PK11_OriginUnwrap, CKA_ENCRYPT, - &wrappedMS, NULL); - PK11_FreeSlot(slot); - if (pwSpec->master_secret == NULL) { - return SECFailure; - } - } - - return SECSuccess; -} - /* Called from ssl3_HandleHandshakeMessage() when it has deciphered a complete * ssl3 ServerHello message. * Caller must hold Handshake and RecvBuf locks. @@ -4991,14 +4895,6 @@ ssl3_HandleServerHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length) PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) ); PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) ); - if (ss->ssl3.hs.snapStartType == snap_start_full || - ss->ssl3.hs.snapStartType == snap_start_resume) { - /* Snap Start handshake was rejected. */ - rv = ssl3_ResetForSnapStartRecovery(ss, b, length); - if (rv != SECSuccess) - return rv; - } - rv = ssl3_InitState(ss); if (rv != SECSuccess) { errCode = PORT_GetError(); /* ssl3_InitState has set the error code. */ @@ -5030,21 +4926,6 @@ ssl3_HandleServerHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length) } #endif /* NSS_PLATFORM_CLIENT_AUTH */ - if (ss->ssl3.serverHelloPredictionData.data) - SECITEM_FreeItem(&ss->ssl3.serverHelloPredictionData, PR_FALSE); - - /* If this allocation fails it will only stop the application from - * recording the ServerHello information and performing future Snap - * Starts. */ - if (SECITEM_AllocItem(NULL, &ss->ssl3.serverHelloPredictionData, length)) - memcpy(ss->ssl3.serverHelloPredictionData.data, b, length); - /* ss->ssl3.serverHelloPredictionDataValid is still false at this - * point. We have to record the contents of the ServerHello here - * because we don't have a pointer to the whole message when handling - * the extensions. However, we wait until the Snap Start extension - * handler to recognise that the server supports Snap Start and to set - * serverHelloPredictionDataValid. */ - temp = ssl3_ConsumeHandshakeNumber(ss, 2, &b, &length); if (temp < 0) { goto loser; /* alert has been sent */ @@ -5185,40 +5066,118 @@ ssl3_HandleServerHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length) if (sid_match && sid->version == ss->version && - sid->u.ssl3.cipherSuite == ss->ssl3.hs.cipher_suite) { - rv = ssl3_SetupMasterSecretFromSessionID(ss); - /* Failure of ssl3_SetupMasterSecretFromSessionID not considered an - * error. Continue with a full handshake. */ - if (rv == SECSuccess) { - /* Got a Match */ - SSL_AtomicIncrementLong(& ssl3stats.hsh_sid_cache_hits ); + sid->u.ssl3.cipherSuite == ss->ssl3.hs.cipher_suite) do { + ssl3CipherSpec *pwSpec = ss->ssl3.pwSpec; - /* If we sent a session ticket, then this is a stateless resume. */ - if (sid->version > SSL_LIBRARY_VERSION_3_0 && - sid->u.ssl3.sessionTicket.ticket.data != NULL) - SSL_AtomicIncrementLong(& ssl3stats.hsh_sid_stateless_resumes ); + SECItem wrappedMS; /* wrapped master secret. */ - if (ssl3_ExtensionNegotiated(ss, ssl_session_ticket_xtn)) - ss->ssl3.hs.ws = wait_new_session_ticket; - else - ss->ssl3.hs.ws = wait_change_cipher; + ss->sec.authAlgorithm = sid->authAlgorithm; + ss->sec.authKeyBits = sid->authKeyBits; + ss->sec.keaType = sid->keaType; + ss->sec.keaKeyBits = sid->keaKeyBits; - ss->ssl3.hs.isResuming = PR_TRUE; + /* 3 cases here: + * a) key is wrapped (implies using PKCS11) + * b) key is unwrapped, but we're still using PKCS11 + * c) key is unwrapped, and we're bypassing PKCS11. + */ + if (sid->u.ssl3.keys.msIsWrapped) { + PK11SlotInfo *slot; + PK11SymKey * wrapKey; /* wrapping key */ + CK_FLAGS keyFlags = 0; - /* copy the peer cert from the SID */ - if (sid->peerCert != NULL) { - ss->sec.peerCert = CERT_DupCertificate(sid->peerCert); - ssl3_CopyPeerCertsFromSID(ss, sid); + if (ss->opt.bypassPKCS11) { + /* we cannot restart a non-bypass session in a + ** bypass socket. + */ + break; + } + /* unwrap master secret with PKCS11 */ + slot = SECMOD_LookupSlot(sid->u.ssl3.masterModuleID, + sid->u.ssl3.masterSlotID); + if (slot == NULL) { + break; /* not considered an error. */ + } + if (!PK11_IsPresent(slot)) { + PK11_FreeSlot(slot); + break; /* not considered an error. */ + } + wrapKey = PK11_GetWrapKey(slot, sid->u.ssl3.masterWrapIndex, + sid->u.ssl3.masterWrapMech, + sid->u.ssl3.masterWrapSeries, + ss->pkcs11PinArg); + PK11_FreeSlot(slot); + if (wrapKey == NULL) { + break; /* not considered an error. */ } - /* NULL value for PMS signifies re-use of the old MS */ - rv = ssl3_InitPendingCipherSpec(ss, NULL); - if (rv != SECSuccess) { - goto alert_loser; + if (ss->version > SSL_LIBRARY_VERSION_3_0) { /* isTLS */ + keyFlags = CKF_SIGN | CKF_VERIFY; + } + + wrappedMS.data = sid->u.ssl3.keys.wrapped_master_secret; + wrappedMS.len = sid->u.ssl3.keys.wrapped_master_secret_len; + pwSpec->master_secret = + PK11_UnwrapSymKeyWithFlags(wrapKey, sid->u.ssl3.masterWrapMech, + NULL, &wrappedMS, CKM_SSL3_MASTER_KEY_DERIVE, + CKA_DERIVE, sizeof(SSL3MasterSecret), keyFlags); + errCode = PORT_GetError(); + PK11_FreeSymKey(wrapKey); + if (pwSpec->master_secret == NULL) { + break; /* errorCode set just after call to UnwrapSymKey. */ + } + } else if (ss->opt.bypassPKCS11) { + /* MS is not wrapped */ + 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; + } else { + /* We CAN restart a bypass session in a non-bypass socket. */ + /* need to import the raw master secret to session object */ + PK11SlotInfo *slot = PK11_GetInternalSlot(); + wrappedMS.data = sid->u.ssl3.keys.wrapped_master_secret; + wrappedMS.len = sid->u.ssl3.keys.wrapped_master_secret_len; + pwSpec->master_secret = + PK11_ImportSymKey(slot, CKM_SSL3_MASTER_KEY_DERIVE, + PK11_OriginUnwrap, CKA_ENCRYPT, + &wrappedMS, NULL); + PK11_FreeSlot(slot); + if (pwSpec->master_secret == NULL) { + break; } - return SECSuccess; } - } + + /* Got a Match */ + SSL_AtomicIncrementLong(& ssl3stats.hsh_sid_cache_hits ); + + /* If we sent a session ticket, then this is a stateless resume. */ + if (sid->version > SSL_LIBRARY_VERSION_3_0 && + sid->u.ssl3.sessionTicket.ticket.data != NULL) + SSL_AtomicIncrementLong(& ssl3stats.hsh_sid_stateless_resumes ); + + if (ssl3_ExtensionNegotiated(ss, ssl_session_ticket_xtn)) + ss->ssl3.hs.ws = wait_new_session_ticket; + else + ss->ssl3.hs.ws = wait_change_cipher; + + ss->ssl3.hs.isResuming = PR_TRUE; + + /* copy the peer cert from the SID */ + if (sid->peerCert != NULL) { + ss->sec.peerCert = CERT_DupCertificate(sid->peerCert); + ssl3_CopyPeerCertsFromSID(ss, sid); + } + + + /* NULL value for PMS signifies re-use of the old MS */ + rv = ssl3_InitPendingCipherSpec(ss, NULL); + if (rv != SECSuccess) { + goto alert_loser; /* err code was set */ + } + return SECSuccess; + } while (0); if (sid_match) SSL_AtomicIncrementLong(& ssl3stats.hsh_sid_cache_not_ok ); @@ -6250,7 +6209,7 @@ ssl3_HandleClientHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length) * ticket extension, but sent an empty ticket. */ if (!ssl3_ExtensionNegotiated(ss, ssl_session_ticket_xtn) || - ss->xtnData.serverReceivedEmptySessionTicket) { + ss->xtnData.emptySessionTicket) { if (sidBytes.len > 0 && !ss->opt.noCache) { SSL_TRC(7, ("%d: SSL3[%d]: server, lookup client session-id for 0x%08x%08x%08x%08x", SSL_GETPID(), ss->fd, ss->sec.ci.peer.pr_s6_addr32[0], @@ -7703,12 +7662,6 @@ ssl3_HandleNewSessionTicket(sslSocket *ss, SSL3Opaque *b, PRUint32 length) return SECFailure; /* malformed */ } - if (ss->sec.ci.sid->peerCert == NULL) { - ss->sec.ci.sid->peerCert = CERT_DupCertificate(ss->sec.peerCert); - ssl3_CopyPeerCertsToSID((ssl3CertNode *)ss->ssl3.peerCertChain, - ss->sec.ci.sid); - } - rv = ssl3_SetSIDSessionTicket(ss->sec.ci.sid, &session_ticket); if (rv != SECSuccess) { (void)SSL3_SendAlert(ss, alert_fatal, handshake_failure); @@ -7900,7 +7853,7 @@ ssl3_CleanupPeerCerts(sslSocket *ss) ss->ssl3.peerCertChain = NULL; } -void +static void ssl3_CopyPeerCertsFromSID(sslSocket *ss, sslSessionID *sid) { PRArenaPool *arena; @@ -8366,7 +8319,7 @@ ssl3_RestartHandshakeAfterServerCert(sslSocket *ss) return rv; } -SECStatus +static SECStatus ssl3_ComputeTLSFinished(ssl3CipherSpec *spec, PRBool isServer, const SSL3Finished * hashes, @@ -8414,7 +8367,7 @@ ssl3_ComputeTLSFinished(ssl3CipherSpec *spec, /* called from ssl3_HandleServerHelloDone */ -SECStatus +static SECStatus ssl3_SendNextProto(sslSocket *ss) { SECStatus rv; @@ -8450,7 +8403,7 @@ ssl3_SendNextProto(sslSocket *ss) * ssl3_HandleClientHello * ssl3_HandleFinished */ -SECStatus +static SECStatus ssl3_SendFinished(sslSocket *ss, PRInt32 flags) { ssl3CipherSpec *cwSpec; @@ -8503,13 +8456,10 @@ ssl3_SendFinished(sslSocket *ss, PRInt32 flags) if (rv != SECSuccess) goto fail; /* err set by AppendHandshake. */ } - if ((flags & ssl_SEND_FLAG_NO_FLUSH) == 0) { - rv = ssl3_FlushHandshake(ss, flags); - if (rv != SECSuccess) { - goto fail; /* error code set by ssl3_FlushHandshake */ - } + rv = ssl3_FlushHandshake(ss, flags); + if (rv != SECSuccess) { + goto fail; /* error code set by ssl3_FlushHandshake */ } - return SECSuccess; fail: @@ -8626,16 +8576,6 @@ ssl3_HandleFinished(sslSocket *ss, SSL3Opaque *b, PRUint32 length, return SECFailure; } - if (ss->ssl3.hs.snapStartType == snap_start_full || - ss->ssl3.hs.snapStartType == snap_start_resume) { - /* Snap Start handshake was successful. Switch the cipher spec. */ - ssl_GetSpecWriteLock(ss); - ssl3_DestroyCipherSpec(ss->ssl3.cwSpec, PR_TRUE/*freeSrvName*/); - ss->ssl3.cwSpec = ss->ssl3.pwSpec; - ss->ssl3.pwSpec = NULL; - ssl_ReleaseSpecWriteLock(ss); - } - isTLS = (PRBool)(ss->ssl3.crSpec->version > SSL_LIBRARY_VERSION_3_0); if (isTLS) { TLSFinished tlsFinished; @@ -8645,21 +8585,12 @@ ssl3_HandleFinished(sslSocket *ss, SSL3Opaque *b, PRUint32 length, PORT_SetError(SSL_ERROR_RX_MALFORMED_FINISHED); return SECFailure; } - - if (ss->ssl3.hs.snapStartType == snap_start_resume) { - /* In this case we have already advanced the Finished hash past the - * server's verify_data because we needed to predict the server's - * Finished message in order to compute our own (which includes - * it). When we did this, we stored a copy in tFinished[1]. */ - tlsFinished = ss->ssl3.hs.finishedMsgs.tFinished[1]; - } else { - rv = ssl3_ComputeTLSFinished(ss->ssl3.crSpec, !isServer, - hashes, &tlsFinished); - if (!isServer) - ss->ssl3.hs.finishedMsgs.tFinished[1] = tlsFinished; - else - ss->ssl3.hs.finishedMsgs.tFinished[0] = tlsFinished; - } + rv = ssl3_ComputeTLSFinished(ss->ssl3.crSpec, !isServer, + hashes, &tlsFinished); + if (!isServer) + ss->ssl3.hs.finishedMsgs.tFinished[1] = tlsFinished; + else + ss->ssl3.hs.finishedMsgs.tFinished[0] = tlsFinished; ss->ssl3.hs.finishedBytes = sizeof tlsFinished; if (rv != SECSuccess || 0 != NSS_SecureMemcmp(&tlsFinished, b, length)) { @@ -8690,9 +8621,8 @@ ssl3_HandleFinished(sslSocket *ss, SSL3Opaque *b, PRUint32 length, ssl_GetXmitBufLock(ss); /*************************************/ - if (ss->ssl3.hs.snapStartType != snap_start_resume && - ((isServer && !ss->ssl3.hs.isResuming) || - (!isServer && ss->ssl3.hs.isResuming))) { + if ((isServer && !ss->ssl3.hs.isResuming) || + (!isServer && ss->ssl3.hs.isResuming)) { PRInt32 flags = 0; /* Send a NewSessionTicket message if the client sent us @@ -8808,10 +8738,7 @@ xmit_loser: ss->ssl3.hs.ws = idle_handshake; /* Do the handshake callback for sslv3 here, if we cannot false start. */ - if (ss->handshakeCallback != NULL && - (!ssl3_CanFalseStart(ss) || - ss->ssl3.hs.snapStartType == snap_start_full || - ss->ssl3.hs.snapStartType == snap_start_resume)) { + if (ss->handshakeCallback != NULL && !ssl3_CanFalseStart(ss)) { (ss->handshakeCallback)(ss->fd, ss->handshakeCallbackData); } @@ -8892,13 +8819,8 @@ ssl3_HandleHandshakeMessage(sslSocket *ss, SSL3Opaque *b, PRUint32 length) return rv; } } - /* We should not include hello_request messages in the handshake hashes. - * Likewise, for Finished messages from the server during a Snap Start - * resume, we have already predicted and included the message in our - * Finished hash. */ - if (ss->ssl3.hs.msg_type != hello_request && - !(ss->ssl3.hs.msg_type == finished && - ss->ssl3.hs.snapStartType == snap_start_resume)) { + /* We should not include hello_request messages in the handshake hashes */ + if (ss->ssl3.hs.msg_type != hello_request) { rv = ssl3_UpdateHandshakeHashes(ss, (unsigned char*) hdr, 4); if (rv != SECSuccess) return rv; /* err code already set. */ rv = ssl3_UpdateHandshakeHashes(ss, b, length); @@ -9837,15 +9759,6 @@ ssl3_DestroySSL3Info(sslSocket *ss) ss->ssl3.clientCertChain = NULL; } - if (ss->ssl3.predictedCertChain != NULL) - ssl3_CleanupPredictedPeerCertificates(ss); - - if (ss->ssl3.serverHelloPredictionData.data) - SECITEM_FreeItem(&ss->ssl3.serverHelloPredictionData, PR_FALSE); - - if (ss->ssl3.snapStartApplicationData.data) - SECITEM_FreeItem(&ss->ssl3.snapStartApplicationData, PR_FALSE); - /* clean up handshake */ if (ss->opt.bypassPKCS11) { SHA1_DestroyContext((SHA1Context *)ss->ssl3.hs.sha_cx, PR_FALSE); @@ -9863,9 +9776,6 @@ ssl3_DestroySSL3Info(sslSocket *ss) ss->ssl3.hs.messages.len = 0; ss->ssl3.hs.messages.space = 0; } - if (ss->ssl3.hs.origClientHello.data) { - SECITEM_FreeItem(&ss->ssl3.hs.origClientHello, PR_FALSE); - } if (ss->ssl3.hs.pending_cert_msg.data) { SECITEM_FreeItem(&ss->ssl3.hs.pending_cert_msg, PR_FALSE); } diff --git a/net/third_party/nss/ssl/ssl3ext.c b/net/third_party/nss/ssl/ssl3ext.c index b93671e..94dab58 100644 --- a/net/third_party/nss/ssl/ssl3ext.c +++ b/net/third_party/nss/ssl/ssl3ext.c @@ -248,7 +248,6 @@ static const ssl3HelloExtensionHandler serverHelloHandlersTLS[] = { { ssl_renegotiation_info_xtn, &ssl3_HandleRenegotiationInfoXtn }, { ssl_next_proto_neg_xtn, &ssl3_ClientHandleNextProtoNegoXtn }, { ssl_cert_status_xtn, &ssl3_ClientHandleStatusRequestXtn }, - { ssl_snap_start_xtn, &ssl3_ClientHandleSnapStartXtn }, { -1, NULL } }; @@ -273,9 +272,7 @@ ssl3HelloExtensionSender clientHelloSendersTLS[SSL_MAX_EXTENSIONS] = { #endif { ssl_session_ticket_xtn, &ssl3_SendSessionTicketXtn }, { ssl_next_proto_neg_xtn, &ssl3_ClientSendNextProtoNegoXtn }, - { ssl_cert_status_xtn, &ssl3_ClientSendStatusRequestXtn }, - { ssl_snap_start_xtn, &ssl3_SendSnapStartXtn } - /* NOTE: The Snap Start sender MUST be the last extension in the list. */ + { ssl_cert_status_xtn, &ssl3_ClientSendStatusRequestXtn } /* any extra entries will appear as { 0, NULL } */ }; @@ -303,7 +300,7 @@ ssl3_ExtensionNegotiated(sslSocket *ss, PRUint16 ex_type) { xtnData->numNegotiated, ex_type); } -PRBool +static PRBool ssl3_ClientExtensionAdvertised(sslSocket *ss, PRUint16 ex_type) { TLSExtensionData *xtnData = &ss->xtnData; return arrayContainsExtension(xtnData->advertised, @@ -520,8 +517,6 @@ ssl3_SendSessionTicketXtn( rv = ssl3_AppendHandshakeVariable(ss, session_ticket->ticket.data, session_ticket->ticket.len, 2); ss->xtnData.ticketTimestampVerified = PR_FALSE; - if (!ss->sec.isServer) - ss->xtnData.clientSentNonEmptySessionTicket = PR_TRUE; } else { rv = ssl3_AppendHandshakeNumber(ss, 0, 2); } @@ -580,7 +575,7 @@ ssl3_ValidateNextProtoNego(const unsigned char* data, unsigned short length) SECStatus ssl3_ClientHandleNextProtoNegoXtn(sslSocket *ss, PRUint16 ex_type, - SECItem *data) + SECItem *data) { unsigned int i, j; SECStatus rv; @@ -1102,7 +1097,7 @@ ssl3_ServerHandleSessionTicketXtn(sslSocket *ss, PRUint16 ex_type, * instead of terminating the current connection. */ if (data->len == 0) { - ss->xtnData.serverReceivedEmptySessionTicket = PR_TRUE; + ss->xtnData.emptySessionTicket = PR_TRUE; } else { int i; SECItem extension_data; diff --git a/net/third_party/nss/ssl/sslimpl.h b/net/third_party/nss/ssl/sslimpl.h index 95beb57..2e1364e 100644 --- a/net/third_party/nss/ssl/sslimpl.h +++ b/net/third_party/nss/ssl/sslimpl.h @@ -287,7 +287,6 @@ struct sslSocketOpsStr { /* Flags interpreted by ssl send functions. */ #define ssl_SEND_FLAG_FORCE_INTO_BUFFER 0x40000000 #define ssl_SEND_FLAG_NO_BUFFER 0x20000000 -#define ssl_SEND_FLAG_NO_FLUSH 0x10000000 #define ssl_SEND_FLAG_MASK 0x7f000000 /* @@ -349,8 +348,7 @@ typedef struct sslOptionsStr { unsigned int enableRenegotiation : 2; /* 20-21 */ unsigned int requireSafeNegotiation : 1; /* 22 */ unsigned int enableFalseStart : 1; /* 23 */ - unsigned int enableSnapStart : 1; /* 24 */ - unsigned int enableOCSPStapling : 1; /* 25 */ + unsigned int enableOCSPStapling : 1; /* 24 */ } sslOptions; typedef enum { sslHandshakingUndetermined = 0, @@ -765,8 +763,7 @@ struct TLSExtensionDataStr { /* SessionTicket Extension related data. */ PRBool ticketTimestampVerified; - PRBool serverReceivedEmptySessionTicket; - PRBool clientSentNonEmptySessionTicket; + PRBool emptySessionTicket; /* SNI Extension related data * Names data is not coppied from the input buffer. It can not be @@ -776,14 +773,6 @@ struct TLSExtensionDataStr { PRUint32 sniNameArrSize; }; -typedef enum { - snap_start_none = 0, - snap_start_full, - snap_start_recovery, - snap_start_resume, - snap_start_resume_recovery -} TLSSnapStartType; - /* ** This is the "hs" member of the "ssl3" struct. ** This entire struct is protected by ssl3HandshakeLock @@ -830,14 +819,6 @@ const ssl3CipherSuiteDef *suite_def; SSL3Hashes sFinished[2]; SSL3Opaque data[72]; } finishedMsgs; - - TLSSnapStartType snapStartType; - /* When we perform a Snap Start handshake, we hash our ClientHello as if - * the Snap Start extension wasn't included. However, if the server rejects - * our Snap Start attempt, then it will hash the whole ClientHello. Thus we - * store the original ClientHello that we sent in case we need to reset our - * Finished hash to cover it. */ - SECItem origClientHello; #ifdef NSS_ENABLE_ECC PRUint32 negotiatedECCurves; /* bit mask */ #endif /* NSS_ENABLE_ECC */ @@ -873,17 +854,6 @@ struct ssl3StateStr { CERTCertificateList *clientCertChain; /* used by client */ PRBool sendEmptyCert; /* used by client */ - /* TLS Snap Start: */ - CERTCertificate ** predictedCertChain; - /* An array terminated with a NULL. */ - SECItem serverHelloPredictionData; - PRBool serverHelloPredictionDataValid; - /* data needed to predict the ServerHello from - * this server. */ - SECItem snapStartApplicationData; - /* the application data to include in the Snap - * Start extension. */ - int policy; /* This says what cipher suites we can do, and should * be either SSL_ALLOWED or SSL_RESTRICTED @@ -1323,13 +1293,10 @@ extern sslSessionID *ssl3_NewSessionID(sslSocket *ss, PRBool is_server); extern sslSessionID *ssl_LookupSID(const PRIPv6Addr *addr, PRUint16 port, const char *peerID, const char *urlSvrName); extern void ssl_FreeSID(sslSessionID *sid); -extern void ssl3_CopyPeerCertsFromSID(sslSocket *ss, sslSessionID *sid); extern int ssl3_SendApplicationData(sslSocket *ss, const PRUint8 *in, int len, int flags); -extern SECStatus ssl3_RestartHandshakeHashes(sslSocket *ss); - extern PRBool ssl_FdIsBlocking(PRFileDesc *fd); extern PRBool ssl_SocketIsBlocking(sslSocket *ss); @@ -1502,9 +1469,6 @@ ECName ssl3_GetCurveWithECKeyStrength(PRUint32 curvemsk, int requiredECCbits); #endif /* NSS_ENABLE_ECC */ -extern SECStatus ssl3_UpdateHandshakeHashes(sslSocket* ss, unsigned char *b, - unsigned int l); - extern SECStatus ssl3_CipherPrefSetDefault(ssl3CipherSuite which, PRBool on); extern SECStatus ssl3_CipherPrefGetDefault(ssl3CipherSuite which, PRBool *on); extern SECStatus ssl2_CipherPrefSetDefault(PRInt32 which, PRBool enabled); @@ -1525,7 +1489,6 @@ extern void ssl3_InitSocketPolicy(sslSocket *ss); extern SECStatus ssl3_ConstructV2CipherSpecsHack(sslSocket *ss, unsigned char *cs, int *size); -extern void ssl3_DestroyCipherSpec(ssl3CipherSpec* spec, PRBool freeSrvName); extern SECStatus ssl3_RedoHandshake(sslSocket *ss, PRBool flushCache); @@ -1575,31 +1538,6 @@ extern SECStatus ssl3_VerifySignedHashes(SSL3Hashes *hash, extern SECStatus ssl3_CacheWrappedMasterSecret(sslSocket *ss, sslSessionID *sid, ssl3CipherSpec *spec, SSL3KEAType effectiveExchKeyType); -extern void ssl3_CleanupPredictedPeerCertificates(sslSocket *ss); -extern const ssl3CipherSuiteDef* ssl_LookupCipherSuiteDef(ssl3CipherSuite suite); -extern SECStatus ssl3_SetupPendingCipherSpec(sslSocket *ss); -extern SECStatus ssl3_SendClientKeyExchange(sslSocket *ss); -extern SECStatus ssl3_SendNextProto(sslSocket *ss); -extern SECStatus ssl3_SendFinished(sslSocket *ss, PRInt32 flags); -extern SECStatus ssl3_CompressMACEncryptRecord - (sslSocket * ss, - SSL3ContentType type, - const SSL3Opaque * pIn, - PRUint32 contentLen); -extern PRBool ssl3_ClientExtensionAdvertised(sslSocket *ss, PRUint16 ex_type); -extern SECStatus ssl3_SetupMasterSecretFromSessionID(sslSocket* ss); -extern SECStatus ssl3_ComputeHandshakeHashes( - sslSocket * ss, - ssl3CipherSpec *spec, /* uses ->master_secret */ - SSL3Hashes * hashes, /* output goes here. */ - PRUint32 sender); -extern SECStatus ssl3_UpdateHandshakeHashes(sslSocket* ss, unsigned char *b, - unsigned int l); -extern SECStatus ssl3_ComputeTLSFinished( - ssl3CipherSpec *spec, - PRBool isServer, - const SSL3Finished * hashes, - TLSFinished * tlsFinished); /* Functions that handle ClientHello and ServerHello extensions. */ extern SECStatus ssl3_HandleServerNameXtn(sslSocket * ss, @@ -1633,13 +1571,6 @@ extern PRInt32 ssl3_ClientSendStatusRequestXtn(sslSocket *ss, PRBool append, */ extern PRInt32 ssl3_SendServerNameXtn(sslSocket *ss, PRBool append, PRUint32 maxBytes); -extern PRInt32 ssl3_SendSnapStartXtn(sslSocket *ss, PRBool append, - PRUint32 maxBytes); -extern SECStatus ssl3_ClientHandleSnapStartXtn(sslSocket *ss, PRUint16 ex_type, - SECItem *data); - -extern SECStatus ssl3_ResetForSnapStartRecovery(sslSocket *ss, - SSL3Opaque *b, PRUint32 length); /* Assigns new cert, cert chain and keys to ss->serverCerts * struct. If certChain is NULL, tries to find one. Aborts if @@ -1763,12 +1694,6 @@ SECStatus SSL_DisableDefaultExportCipherSuites(void); SECStatus SSL_DisableExportCipherSuites(PRFileDesc * fd); PRBool SSL_IsExportCipherSuite(PRUint16 cipherSuite); -/********************** FNV hash *********************/ - -void FNV1A64_Init(PRUint64 *digest); -void FNV1A64_Update(PRUint64 *digest, const unsigned char *data, - unsigned int length); -void FNV1A64_Final(PRUint64 *digest); #ifdef TRACE #define SSL_TRACE(msg) ssl_Trace msg diff --git a/net/third_party/nss/ssl/sslsock.c b/net/third_party/nss/ssl/sslsock.c index c5b63d1..1bb211e 100644 --- a/net/third_party/nss/ssl/sslsock.c +++ b/net/third_party/nss/ssl/sslsock.c @@ -743,10 +743,6 @@ SSL_OptionSet(PRFileDesc *fd, PRInt32 which, PRBool on) ss->opt.enableFalseStart = on; break; - case SSL_ENABLE_SNAP_START: - ss->opt.enableSnapStart = on; - break; - case SSL_ENABLE_OCSP_STAPLING: ss->opt.enableOCSPStapling = on; break; @@ -815,7 +811,6 @@ SSL_OptionGet(PRFileDesc *fd, PRInt32 which, PRBool *pOn) case SSL_REQUIRE_SAFE_NEGOTIATION: on = ss->opt.requireSafeNegotiation; break; case SSL_ENABLE_FALSE_START: on = ss->opt.enableFalseStart; break; - case SSL_ENABLE_SNAP_START: on = ss->opt.enableSnapStart; break; case SSL_ENABLE_OCSP_STAPLING: on = ss->opt.enableOCSPStapling; break; default: @@ -868,7 +863,6 @@ SSL_OptionGetDefault(PRInt32 which, PRBool *pOn) on = ssl_defaults.requireSafeNegotiation; break; case SSL_ENABLE_FALSE_START: on = ssl_defaults.enableFalseStart; break; - case SSL_ENABLE_SNAP_START: on = ssl_defaults.enableSnapStart; break; case SSL_ENABLE_OCSP_STAPLING: on = ssl_defaults.enableOCSPStapling; break; @@ -1019,10 +1013,6 @@ SSL_OptionSetDefault(PRInt32 which, PRBool on) ssl_defaults.enableFalseStart = on; break; - case SSL_ENABLE_SNAP_START: - ssl_defaults.enableSnapStart = on; - break; - case SSL_ENABLE_OCSP_STAPLING: ssl_defaults.enableOCSPStapling = on; break; diff --git a/net/third_party/nss/ssl/sslt.h b/net/third_party/nss/ssl/sslt.h index 3fa3f9b..917c093 100644 --- a/net/third_party/nss/ssl/sslt.h +++ b/net/third_party/nss/ssl/sslt.h @@ -205,23 +205,9 @@ typedef enum { #endif ssl_session_ticket_xtn = 35, ssl_next_proto_neg_xtn = 13172, - ssl_snap_start_xtn = 13174, ssl_renegotiation_info_xtn = 0xff01 /* experimental number */ } SSLExtensionType; -#define SSL_MAX_EXTENSIONS 8 - -typedef enum { - /* No Snap Start handshake was attempted. */ - SSL_SNAP_START_NONE = 0, - /* A Snap Start full handshake was completed. */ - SSL_SNAP_START_FULL = 1, - /* A Snap Start full handshake was attempted, but failed. */ - SSL_SNAP_START_RECOVERY = 2, - /* A Snap Start resume handshake was completed. */ - SSL_SNAP_START_RESUME = 3, - /* A Snap Start resume handshake was attempted, but failed. */ - SSL_SNAP_START_RESUME_RECOVERY = 4 -} SSLSnapStartResult; +#define SSL_MAX_EXTENSIONS 7 #endif /* __sslt_h_ */ |