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..b2144418a055e0b46c3b7f6d84fede8081828274 |
--- /dev/null |
+++ b/net/third_party/nss/patches/channelid2.patch |
@@ -0,0 +1,150 @@ |
+diff --git a/nss/lib/ssl/ssl3con.c b/nss/lib/ssl/ssl3con.c |
+index 8b8b758..1c55bc4 100644 |
+--- a/nss/lib/ssl/ssl3con.c |
++++ b/nss/lib/ssl/ssl3con.c |
+@@ -7570,6 +7570,30 @@ ssl3_SendClientSecondRound(sslSocket *ss) |
+ goto loser; /* err code was set. */ |
+ } |
+ |
++ 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 *lastHandshakeHash = &ss->sec.ci.sid->u.ssl3.lastHandshakeHash; |
++ |
++ ssl_GetSpecReadLock(ss); |
++ /* the cwSpec and zero arguments are only used for SSLv3, but we know |
++ * that this connection is not SSLv3 because we negotiated ChannelID. */ |
++ PORT_Assert(ss->version > SSL_LIBRARY_VERSION_3_0); |
++ ssl3_ComputeHandshakeHashes(ss, ss->ssl3.cwSpec, &hashes, 0); |
++ ssl_ReleaseSpecReadLock(ss); |
++ |
++ PORT_Assert(lastHandshakeHash->len == 0); |
++ lastHandshakeHash->data = PORT_Alloc(hashes.len); |
++ if (!lastHandshakeHash->data) |
++ goto loser; |
++ lastHandshakeHash->len = hashes.len; |
++ memcpy(lastHandshakeHash->data, hashes.u.raw, hashes.len); |
++ } |
++ |
+ ssl_ReleaseXmitBufLock(ss); /*******************************/ |
+ |
+ if (ssl3_ExtensionNegotiated(ss, ssl_session_ticket_xtn)) |
+@@ -10568,6 +10592,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 |
+@@ -10593,7 +10618,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 j; |
+ unsigned char digest[SHA256_LENGTH]; |
+ SECItem digest_item; |
+ unsigned char signature[64]; |
+@@ -10643,11 +10671,24 @@ 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); |
++ j = 0; |
++ memcpy(signed_data + j, CHANNEL_ID_MAGIC, sizeof(CHANNEL_ID_MAGIC)); |
++ j += sizeof(CHANNEL_ID_MAGIC); |
++ if (ss->ssl3.hs.isResuming) { |
++ SECItem *lastHandshakeHash = &ss->sec.ci.sid->u.ssl3.lastHandshakeHash; |
++ PORT_Assert(lastHandshakeHash->len > 0); |
+ |
+- rv = PK11_HashBuf(SEC_OID_SHA256, digest, signed_data, |
+- sizeof(CHANNEL_ID_MAGIC) + hashes.len); |
++ memcpy(signed_data + j, CHANNEL_ID_RESUMPTION_MAGIC, |
++ sizeof(CHANNEL_ID_RESUMPTION_MAGIC)); |
++ j += sizeof(CHANNEL_ID_RESUMPTION_MAGIC); |
++ memcpy(signed_data + j, lastHandshakeHash->data, |
++ lastHandshakeHash->len); |
++ j += lastHandshakeHash->len; |
++ } |
++ memcpy(signed_data + j, hashes.u.raw, hashes.len); |
++ j += hashes.len; |
++ |
++ rv = PK11_HashBuf(SEC_OID_SHA256, digest, signed_data, j); |
+ if (rv != SECSuccess) |
+ goto loser; |
+ |
+diff --git a/nss/lib/ssl/ssl3ext.c b/nss/lib/ssl/ssl3ext.c |
+index 0415770..8142c3a 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.lastHandshakeHash.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 614eed1..bc0e85c 100644 |
+--- a/nss/lib/ssl/sslimpl.h |
++++ b/nss/lib/ssl/sslimpl.h |
+@@ -698,6 +698,14 @@ struct sslSessionIDStr { |
+ */ |
+ NewSessionTicket sessionTicket; |
+ SECItem srvName; |
++ |
++ /* lastHandshakeHash contains the hash of the original, full |
++ * handshake. This is either a SHA-1/MD5 combination (for TLS < |
++ * 1.2) or a SHA-2 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 lastHandshakeHash; |
+ } ssl3; |
+ } u; |
+ }; |
+diff --git a/nss/lib/ssl/sslnonce.c b/nss/lib/ssl/sslnonce.c |
+index a6f7349..a18c4e3 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.lastHandshakeHash.data) { |
++ SECITEM_FreeItem(&sid->u.ssl3.lastHandshakeHash, PR_FALSE); |
++ } |
+ |
+ PORT_ZFree(sid, sizeof(sslSessionID)); |
+ } |
+diff --git a/nss/lib/ssl/sslt.h b/nss/lib/ssl/sslt.h |
+index a8007d8..77ab4b1 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_renegotiation_info_xtn = 0xff01 /* experimental number */ |
+ } SSLExtensionType; |
+ |