1 diff --git a/nss/lib/ssl/ssl3con.c b/nss/lib/ssl/ssl3con.c 2 index 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 90 diff --git a/nss/lib/ssl/ssl3ext.c b/nss/lib/ssl/ssl3ext.c 91 index 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); 110 diff --git a/nss/lib/ssl/sslimpl.h b/nss/lib/ssl/sslimpl.h 111 index 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 }; 129 diff --git a/nss/lib/ssl/sslnonce.c b/nss/lib/ssl/sslnonce.c 130 index 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 } 143 diff --git a/nss/lib/ssl/sslt.h b/nss/lib/ssl/sslt.h 144 index 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