Index: net/third_party/nss/patches/channelid2.patch |
diff --git a/net/third_party/nss/patches/channelid2.patch b/net/third_party/nss/patches/channelid2.patch |
new file mode 100644 |
index 0000000000000000000000000000000000000000..6817ca5fadd1606e29c1ece6dc85e2a25e4e5f5c |
--- /dev/null |
+++ b/net/third_party/nss/patches/channelid2.patch |
@@ -0,0 +1,155 @@ |
+diff --git a/nss/lib/ssl/ssl3con.c b/nss/lib/ssl/ssl3con.c |
+index 882e356..396c408 100644 |
+--- a/nss/lib/ssl/ssl3con.c |
++++ b/nss/lib/ssl/ssl3con.c |
+@@ -7594,6 +7594,33 @@ ssl3_SendClientSecondRound(sslSocket *ss) |
+ |
+ ssl_ReleaseXmitBufLock(ss); /*******************************/ |
+ |
++ if (!ss->ssl3.hs.isResuming && |
++ ssl3_ExtensionNegotiated(ss, ssl_channel_id_xtn)) { |
++ /* If we are negotiating ChannelID on a full handshake then we record |
++ * the handshake hashes in |sid| at this point. They will be needed in |
++ * the event that we resume this session and use ChannelID on the |
++ * resumption handshake. */ |
++ SSL3Hashes hashes; |
++ SECItem *originalHandshakeHash = |
++ &ss->sec.ci.sid->u.ssl3.originalHandshakeHash; |
++ PORT_Assert(ss->sec.ci.sid->cached == never_cached); |
++ |
++ ssl_GetSpecReadLock(ss); |
++ PORT_Assert(ss->version > SSL_LIBRARY_VERSION_3_0); |
++ rv = ssl3_ComputeHandshakeHashes(ss, ss->ssl3.cwSpec, &hashes, 0); |
++ ssl_ReleaseSpecReadLock(ss); |
++ if (rv != SECSuccess) { |
++ return rv; |
++ } |
++ |
++ PORT_Assert(originalHandshakeHash->len == 0); |
++ originalHandshakeHash->data = PORT_Alloc(hashes.len); |
++ if (!originalHandshakeHash->data) |
++ return SECFailure; |
++ originalHandshakeHash->len = hashes.len; |
++ memcpy(originalHandshakeHash->data, hashes.u.raw, hashes.len); |
++ } |
++ |
+ if (ssl3_ExtensionNegotiated(ss, ssl_session_ticket_xtn)) |
+ ss->ssl3.hs.ws = wait_new_session_ticket; |
+ else |
+@@ -10590,6 +10617,7 @@ static SECStatus |
+ ssl3_SendEncryptedExtensions(sslSocket *ss) |
+ { |
+ static const char CHANNEL_ID_MAGIC[] = "TLS Channel ID signature"; |
++ static const char CHANNEL_ID_RESUMPTION_MAGIC[] = "Resumption"; |
+ /* This is the ASN.1 prefix for a P-256 public key. Specifically it's: |
+ * SEQUENCE |
+ * SEQUENCE |
+@@ -10615,7 +10643,10 @@ ssl3_SendEncryptedExtensions(sslSocket *ss) |
+ SECItem *spki = NULL; |
+ SSL3Hashes hashes; |
+ const unsigned char *pub_bytes; |
+- unsigned char signed_data[sizeof(CHANNEL_ID_MAGIC) + sizeof(SSL3Hashes)]; |
++ unsigned char signed_data[sizeof(CHANNEL_ID_MAGIC) + |
++ sizeof(CHANNEL_ID_RESUMPTION_MAGIC) + |
++ sizeof(SSL3Hashes)*2]; |
++ size_t signed_data_len; |
+ unsigned char digest[SHA256_LENGTH]; |
+ SECItem digest_item; |
+ unsigned char signature[64]; |
+@@ -10665,11 +10696,26 @@ ssl3_SendEncryptedExtensions(sslSocket *ss) |
+ |
+ pub_bytes = spki->data + sizeof(P256_SPKI_PREFIX); |
+ |
+- memcpy(signed_data, CHANNEL_ID_MAGIC, sizeof(CHANNEL_ID_MAGIC)); |
+- memcpy(signed_data + sizeof(CHANNEL_ID_MAGIC), hashes.u.raw, hashes.len); |
++ signed_data_len = 0; |
++ memcpy(signed_data + signed_data_len, CHANNEL_ID_MAGIC, |
++ sizeof(CHANNEL_ID_MAGIC)); |
++ signed_data_len += sizeof(CHANNEL_ID_MAGIC); |
++ if (ss->ssl3.hs.isResuming) { |
++ SECItem *originalHandshakeHash = |
++ &ss->sec.ci.sid->u.ssl3.originalHandshakeHash; |
++ PORT_Assert(originalHandshakeHash->len > 0); |
+ |
+- rv = PK11_HashBuf(SEC_OID_SHA256, digest, signed_data, |
+- sizeof(CHANNEL_ID_MAGIC) + hashes.len); |
++ memcpy(signed_data + signed_data_len, CHANNEL_ID_RESUMPTION_MAGIC, |
++ sizeof(CHANNEL_ID_RESUMPTION_MAGIC)); |
++ signed_data_len += sizeof(CHANNEL_ID_RESUMPTION_MAGIC); |
++ memcpy(signed_data + signed_data_len, originalHandshakeHash->data, |
++ originalHandshakeHash->len); |
++ signed_data_len += originalHandshakeHash->len; |
++ } |
++ memcpy(signed_data + signed_data_len, hashes.u.raw, hashes.len); |
++ signed_data_len += hashes.len; |
++ |
++ rv = PK11_HashBuf(SEC_OID_SHA256, digest, signed_data, signed_data_len); |
+ if (rv != SECSuccess) |
+ goto loser; |
+ |
+diff --git a/nss/lib/ssl/ssl3ext.c b/nss/lib/ssl/ssl3ext.c |
+index 03cf05c..166022c 100644 |
+--- a/nss/lib/ssl/ssl3ext.c |
++++ b/nss/lib/ssl/ssl3ext.c |
+@@ -812,6 +812,15 @@ ssl3_ClientSendChannelIDXtn(sslSocket * ss, PRBool append, |
+ return 0; |
+ } |
+ |
++ if (ss->ssl3.hs.isResuming && |
++ ss->sec.ci.sid->u.ssl3.originalHandshakeHash.len == 0) { |
++ /* We can't do ChannelID on a connection if we're resuming and didn't |
++ * do ChannelID on the original connection: without ChannelID on the |
++ * original connection we didn't record the handshake hashes needed for |
++ * the signature. */ |
++ return 0; |
++ } |
++ |
+ if (append) { |
+ SECStatus rv; |
+ rv = ssl3_AppendHandshakeNumber(ss, ssl_channel_id_xtn, 2); |
+diff --git a/nss/lib/ssl/sslimpl.h b/nss/lib/ssl/sslimpl.h |
+index 9c789bf..ca68727 100644 |
+--- a/nss/lib/ssl/sslimpl.h |
++++ b/nss/lib/ssl/sslimpl.h |
+@@ -705,6 +705,14 @@ struct sslSessionIDStr { |
+ */ |
+ NewSessionTicket sessionTicket; |
+ SECItem srvName; |
++ |
++ /* originalHandshakeHash contains the hash of the original, full |
++ * handshake prior to the server's final flow. This is either a |
++ * SHA-1/MD5 combination (for TLS < 1.2) or the TLS PRF hash (for |
++ * TLS 1.2). This is recorded and used only when ChannelID is |
++ * negotiated as it's used to bind the ChannelID signature on the |
++ * resumption handshake to the original handshake. */ |
++ SECItem originalHandshakeHash; |
+ } ssl3; |
+ } u; |
+ }; |
+diff --git a/nss/lib/ssl/sslnonce.c b/nss/lib/ssl/sslnonce.c |
+index a6f7349..eb5004c 100644 |
+--- a/nss/lib/ssl/sslnonce.c |
++++ b/nss/lib/ssl/sslnonce.c |
+@@ -148,6 +148,9 @@ ssl_DestroySID(sslSessionID *sid) |
+ if (sid->u.ssl3.srvName.data) { |
+ SECITEM_FreeItem(&sid->u.ssl3.srvName, PR_FALSE); |
+ } |
++ if (sid->u.ssl3.originalHandshakeHash.data) { |
++ SECITEM_FreeItem(&sid->u.ssl3.originalHandshakeHash, PR_FALSE); |
++ } |
+ |
+ PORT_ZFree(sid, sizeof(sslSessionID)); |
+ } |
+diff --git a/nss/lib/ssl/sslt.h b/nss/lib/ssl/sslt.h |
+index e4d188f..b813c04 100644 |
+--- a/nss/lib/ssl/sslt.h |
++++ b/nss/lib/ssl/sslt.h |
+@@ -204,7 +204,7 @@ typedef enum { |
+ ssl_app_layer_protocol_xtn = 16, |
+ ssl_session_ticket_xtn = 35, |
+ ssl_next_proto_nego_xtn = 13172, |
+- ssl_channel_id_xtn = 30031, |
++ ssl_channel_id_xtn = 30032, |
+ ssl_padding_xtn = 35655, |
+ ssl_renegotiation_info_xtn = 0xff01 /* experimental number */ |
+ } SSLExtensionType; |