diff options
author | agl@chromium.org <agl@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-11-18 22:00:04 +0000 |
---|---|---|
committer | agl@chromium.org <agl@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-11-18 22:00:04 +0000 |
commit | 2b0dbd272de36d95c7cd0890a5b3f391f7a13970 (patch) | |
tree | 6abd8f6620444bbe7654ec8ee0990f24d5d0000f /net/third_party | |
parent | c19b6a6365a680222f73edfd57b1fd40cba97409 (diff) | |
download | chromium_src-2b0dbd272de36d95c7cd0890a5b3f391f7a13970.zip chromium_src-2b0dbd272de36d95c7cd0890a5b3f391f7a13970.tar.gz chromium_src-2b0dbd272de36d95c7cd0890a5b3f391f7a13970.tar.bz2 |
Support new ChannelID extension.
This change switches over to use the new-style ChannelID extension.
BUG=305951
Review URL: https://codereview.chromium.org/27589002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@235826 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net/third_party')
-rw-r--r-- | net/third_party/nss/README.chromium | 1 | ||||
-rwxr-xr-x | net/third_party/nss/patches/applypatches.sh | 2 | ||||
-rw-r--r-- | net/third_party/nss/patches/channelid2.patch | 156 | ||||
-rw-r--r-- | net/third_party/nss/ssl/ssl3con.c | 58 | ||||
-rw-r--r-- | net/third_party/nss/ssl/ssl3ext.c | 10 | ||||
-rw-r--r-- | net/third_party/nss/ssl/sslimpl.h | 8 | ||||
-rw-r--r-- | net/third_party/nss/ssl/sslnonce.c | 3 | ||||
-rw-r--r-- | net/third_party/nss/ssl/sslt.h | 2 |
8 files changed, 233 insertions, 7 deletions
diff --git a/net/third_party/nss/README.chromium b/net/third_party/nss/README.chromium index ab2d0b03..088252a 100644 --- a/net/third_party/nss/README.chromium +++ b/net/third_party/nss/README.chromium @@ -57,6 +57,7 @@ Patches: * Add support for TLS Channel IDs patches/channelid.patch + patches/channelid2.patch * Add support for extracting the tls-unique channel binding value patches/tlsunique.patch diff --git a/net/third_party/nss/patches/applypatches.sh b/net/third_party/nss/patches/applypatches.sh index 5bdc670..ca05c92 100755 --- a/net/third_party/nss/patches/applypatches.sh +++ b/net/third_party/nss/patches/applypatches.sh @@ -69,3 +69,5 @@ patch -p4 < $patches_dir/nullcipher_934016.patch patch -p4 < $patches_dir/paddingextension.patch patch -p4 < $patches_dir/paddingextensionall.patch + +patch -p4 < $patches_dir/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 0000000..011db87 --- /dev/null +++ b/net/third_party/nss/patches/channelid2.patch @@ -0,0 +1,156 @@ +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,16 @@ 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. */ ++ PORT_Assert(0); ++ 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; diff --git a/net/third_party/nss/ssl/ssl3con.c b/net/third_party/nss/ssl/ssl3con.c index 882e356..396c408 100644 --- a/net/third_party/nss/ssl/ssl3con.c +++ b/net/third_party/nss/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); - - rv = PK11_HashBuf(SEC_OID_SHA256, digest, signed_data, - sizeof(CHANNEL_ID_MAGIC) + 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); + + 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/net/third_party/nss/ssl/ssl3ext.c b/net/third_party/nss/ssl/ssl3ext.c index 03cf05c..adb81ed 100644 --- a/net/third_party/nss/ssl/ssl3ext.c +++ b/net/third_party/nss/ssl/ssl3ext.c @@ -812,6 +812,16 @@ 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. */ + PORT_Assert(0); + return 0; + } + if (append) { SECStatus rv; rv = ssl3_AppendHandshakeNumber(ss, ssl_channel_id_xtn, 2); diff --git a/net/third_party/nss/ssl/sslimpl.h b/net/third_party/nss/ssl/sslimpl.h index 9c789bf..ca68727 100644 --- a/net/third_party/nss/ssl/sslimpl.h +++ b/net/third_party/nss/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/net/third_party/nss/ssl/sslnonce.c b/net/third_party/nss/ssl/sslnonce.c index a6f7349..eb5004c 100644 --- a/net/third_party/nss/ssl/sslnonce.c +++ b/net/third_party/nss/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/net/third_party/nss/ssl/sslt.h b/net/third_party/nss/ssl/sslt.h index e4d188f..b813c04 100644 --- a/net/third_party/nss/ssl/sslt.h +++ b/net/third_party/nss/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; |