• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1diff --git a/nss/lib/ssl/ssl3con.c b/nss/lib/ssl/ssl3con.c
2index 882e356..396c408 100644
3--- a/nss/lib/ssl/ssl3con.c
4+++ b/nss/lib/ssl/ssl3con.c
5@@ -7594,6 +7594,33 @@ ssl3_SendClientSecondRound(sslSocket *ss)
6
7     ssl_ReleaseXmitBufLock(ss);		/*******************************/
8
9+    if (!ss->ssl3.hs.isResuming &&
10+        ssl3_ExtensionNegotiated(ss, ssl_channel_id_xtn)) {
11+        /* If we are negotiating ChannelID on a full handshake then we record
12+         * the handshake hashes in |sid| at this point. They will be needed in
13+         * the event that we resume this session and use ChannelID on the
14+         * resumption handshake. */
15+        SSL3Hashes hashes;
16+        SECItem *originalHandshakeHash =
17+            &ss->sec.ci.sid->u.ssl3.originalHandshakeHash;
18+        PORT_Assert(ss->sec.ci.sid->cached == never_cached);
19+
20+        ssl_GetSpecReadLock(ss);
21+        PORT_Assert(ss->version > SSL_LIBRARY_VERSION_3_0);
22+        rv = ssl3_ComputeHandshakeHashes(ss, ss->ssl3.cwSpec, &hashes, 0);
23+        ssl_ReleaseSpecReadLock(ss);
24+        if (rv != SECSuccess) {
25+            return rv;
26+        }
27+
28+        PORT_Assert(originalHandshakeHash->len == 0);
29+        originalHandshakeHash->data = PORT_Alloc(hashes.len);
30+        if (!originalHandshakeHash->data)
31+            return SECFailure;
32+        originalHandshakeHash->len = hashes.len;
33+        memcpy(originalHandshakeHash->data, hashes.u.raw, hashes.len);
34+    }
35+
36     if (ssl3_ExtensionNegotiated(ss, ssl_session_ticket_xtn))
37 	ss->ssl3.hs.ws = wait_new_session_ticket;
38     else
39@@ -10590,6 +10617,7 @@ static SECStatus
40 ssl3_SendEncryptedExtensions(sslSocket *ss)
41 {
42     static const char CHANNEL_ID_MAGIC[] = "TLS Channel ID signature";
43+    static const char CHANNEL_ID_RESUMPTION_MAGIC[] = "Resumption";
44     /* This is the ASN.1 prefix for a P-256 public key. Specifically it's:
45      * SEQUENCE
46      *   SEQUENCE
47@@ -10615,7 +10643,10 @@ ssl3_SendEncryptedExtensions(sslSocket *ss)
48     SECItem *spki = NULL;
49     SSL3Hashes hashes;
50     const unsigned char *pub_bytes;
51-    unsigned char signed_data[sizeof(CHANNEL_ID_MAGIC) + sizeof(SSL3Hashes)];
52+    unsigned char signed_data[sizeof(CHANNEL_ID_MAGIC) +
53+                              sizeof(CHANNEL_ID_RESUMPTION_MAGIC) +
54+                              sizeof(SSL3Hashes)*2];
55+    size_t signed_data_len;
56     unsigned char digest[SHA256_LENGTH];
57     SECItem digest_item;
58     unsigned char signature[64];
59@@ -10665,11 +10696,26 @@ ssl3_SendEncryptedExtensions(sslSocket *ss)
60
61     pub_bytes = spki->data + sizeof(P256_SPKI_PREFIX);
62
63-    memcpy(signed_data, CHANNEL_ID_MAGIC, sizeof(CHANNEL_ID_MAGIC));
64-    memcpy(signed_data + sizeof(CHANNEL_ID_MAGIC), hashes.u.raw, hashes.len);
65+    signed_data_len = 0;
66+    memcpy(signed_data + signed_data_len, CHANNEL_ID_MAGIC,
67+           sizeof(CHANNEL_ID_MAGIC));
68+    signed_data_len += sizeof(CHANNEL_ID_MAGIC);
69+    if (ss->ssl3.hs.isResuming) {
70+        SECItem *originalHandshakeHash =
71+            &ss->sec.ci.sid->u.ssl3.originalHandshakeHash;
72+        PORT_Assert(originalHandshakeHash->len > 0);
73
74-    rv = PK11_HashBuf(SEC_OID_SHA256, digest, signed_data,
75-		      sizeof(CHANNEL_ID_MAGIC) + hashes.len);
76+        memcpy(signed_data + signed_data_len, CHANNEL_ID_RESUMPTION_MAGIC,
77+               sizeof(CHANNEL_ID_RESUMPTION_MAGIC));
78+        signed_data_len += sizeof(CHANNEL_ID_RESUMPTION_MAGIC);
79+        memcpy(signed_data + signed_data_len, originalHandshakeHash->data,
80+               originalHandshakeHash->len);
81+        signed_data_len += originalHandshakeHash->len;
82+    }
83+    memcpy(signed_data + signed_data_len, hashes.u.raw, hashes.len);
84+    signed_data_len += hashes.len;
85+
86+    rv = PK11_HashBuf(SEC_OID_SHA256, digest, signed_data, signed_data_len);
87     if (rv != SECSuccess)
88 	goto loser;
89
90diff --git a/nss/lib/ssl/ssl3ext.c b/nss/lib/ssl/ssl3ext.c
91index 03cf05c..166022c 100644
92--- a/nss/lib/ssl/ssl3ext.c
93+++ b/nss/lib/ssl/ssl3ext.c
94@@ -812,6 +812,15 @@ ssl3_ClientSendChannelIDXtn(sslSocket * ss, PRBool append,
95 	return 0;
96     }
97
98+    if (ss->sec.ci.sid->cached != never_cached &&
99+        ss->sec.ci.sid->u.ssl3.originalHandshakeHash.len == 0) {
100+        /* We can't do ChannelID on a connection if we're resuming and didn't
101+         * do ChannelID on the original connection: without ChannelID on the
102+         * original connection we didn't record the handshake hashes needed for
103+         * the signature. */
104+	return 0;
105+    }
106+
107     if (append) {
108 	SECStatus rv;
109 	rv = ssl3_AppendHandshakeNumber(ss, ssl_channel_id_xtn, 2);
110diff --git a/nss/lib/ssl/sslimpl.h b/nss/lib/ssl/sslimpl.h
111index 9c789bf..ca68727 100644
112--- a/nss/lib/ssl/sslimpl.h
113+++ b/nss/lib/ssl/sslimpl.h
114@@ -705,6 +705,14 @@ struct sslSessionIDStr {
115 	     */
116 	    NewSessionTicket  sessionTicket;
117             SECItem           srvName;
118+
119+            /* originalHandshakeHash contains the hash of the original, full
120+             * handshake prior to the server's final flow. This is either a
121+             * SHA-1/MD5 combination (for TLS < 1.2) or the TLS PRF hash (for
122+             * TLS 1.2). This is recorded and used only when ChannelID is
123+             * negotiated as it's used to bind the ChannelID signature on the
124+             * resumption handshake to the original handshake. */
125+	    SECItem           originalHandshakeHash;
126 	} ssl3;
127     } u;
128 };
129diff --git a/nss/lib/ssl/sslnonce.c b/nss/lib/ssl/sslnonce.c
130index a6f7349..eb5004c 100644
131--- a/nss/lib/ssl/sslnonce.c
132+++ b/nss/lib/ssl/sslnonce.c
133@@ -148,6 +148,9 @@ ssl_DestroySID(sslSessionID *sid)
134     if (sid->u.ssl3.srvName.data) {
135 	SECITEM_FreeItem(&sid->u.ssl3.srvName, PR_FALSE);
136     }
137+    if (sid->u.ssl3.originalHandshakeHash.data) {
138+	SECITEM_FreeItem(&sid->u.ssl3.originalHandshakeHash, PR_FALSE);
139+    }
140
141     PORT_ZFree(sid, sizeof(sslSessionID));
142 }
143diff --git a/nss/lib/ssl/sslt.h b/nss/lib/ssl/sslt.h
144index e4d188f..b813c04 100644
145--- a/nss/lib/ssl/sslt.h
146+++ b/nss/lib/ssl/sslt.h
147@@ -204,7 +204,7 @@ typedef enum {
148     ssl_app_layer_protocol_xtn       = 16,
149     ssl_session_ticket_xtn           = 35,
150     ssl_next_proto_nego_xtn          = 13172,
151-    ssl_channel_id_xtn               = 30031,
152+    ssl_channel_id_xtn               = 30032,
153     ssl_padding_xtn                  = 35655,
154     ssl_renegotiation_info_xtn       = 0xff01	/* experimental number */
155 } SSLExtensionType;
156