| OLD | NEW |
| (Empty) |
| 1 diff -pu a/nss/lib/ssl/ssl3con.c b/nss/lib/ssl/ssl3con.c | |
| 2 --- a/nss/lib/ssl/ssl3con.c 2014-01-18 10:39:50.799150460 -0800 | |
| 3 +++ b/nss/lib/ssl/ssl3con.c 2014-01-18 10:40:15.489552270 -0800 | |
| 4 @@ -55,6 +55,7 @@ static SECStatus ssl3_SendCertificateSta | |
| 5 static SECStatus ssl3_SendEmptyCertificate( sslSocket *ss); | |
| 6 static SECStatus ssl3_SendCertificateRequest(sslSocket *ss); | |
| 7 static SECStatus ssl3_SendNextProto( sslSocket *ss); | |
| 8 +static SECStatus ssl3_SendEncryptedExtensions(sslSocket *ss); | |
| 9 static SECStatus ssl3_SendFinished( sslSocket *ss, PRInt32 flags); | |
| 10 static SECStatus ssl3_SendServerHello( sslSocket *ss); | |
| 11 static SECStatus ssl3_SendServerHelloDone( sslSocket *ss); | |
| 12 @@ -6221,6 +6222,15 @@ ssl3_HandleServerHello(sslSocket *ss, SS | |
| 13 } | |
| 14 #endif /* NSS_PLATFORM_CLIENT_AUTH */ | |
| 15 | |
| 16 + if (ss->ssl3.channelID != NULL) { | |
| 17 + SECKEY_DestroyPrivateKey(ss->ssl3.channelID); | |
| 18 + ss->ssl3.channelID = NULL; | |
| 19 + } | |
| 20 + if (ss->ssl3.channelIDPub != NULL) { | |
| 21 + SECKEY_DestroyPublicKey(ss->ssl3.channelIDPub); | |
| 22 + ss->ssl3.channelIDPub = NULL; | |
| 23 + } | |
| 24 + | |
| 25 temp = ssl3_ConsumeHandshakeNumber(ss, 2, &b, &length); | |
| 26 if (temp < 0) { | |
| 27 goto loser; /* alert has been sent */ | |
| 28 @@ -6503,7 +6513,7 @@ ssl3_HandleServerHello(sslSocket *ss, SS | |
| 29 if (rv != SECSuccess) { | |
| 30 goto alert_loser; /* err code was set */ | |
| 31 } | |
| 32 - return SECSuccess; | |
| 33 + goto winner; | |
| 34 } while (0); | |
| 35 | |
| 36 if (sid_match) | |
| 37 @@ -6529,6 +6539,27 @@ ssl3_HandleServerHello(sslSocket *ss, SS | |
| 38 | |
| 39 ss->ssl3.hs.isResuming = PR_FALSE; | |
| 40 ss->ssl3.hs.ws = wait_server_cert; | |
| 41 + | |
| 42 +winner: | |
| 43 + /* If we will need a ChannelID key then we make the callback now. This | |
| 44 + * allows the handshake to be restarted cleanly if the callback returns | |
| 45 + * SECWouldBlock. */ | |
| 46 + if (ssl3_ExtensionNegotiated(ss, ssl_channel_id_xtn)) { | |
| 47 + rv = ss->getChannelID(ss->getChannelIDArg, ss->fd, | |
| 48 + &ss->ssl3.channelIDPub, &ss->ssl3.channelID); | |
| 49 + if (rv == SECWouldBlock) { | |
| 50 + ssl3_SetAlwaysBlock(ss); | |
| 51 + return rv; | |
| 52 + } | |
| 53 + if (rv != SECSuccess || | |
| 54 + ss->ssl3.channelIDPub == NULL || | |
| 55 + ss->ssl3.channelID == NULL) { | |
| 56 + PORT_SetError(SSL_ERROR_GET_CHANNEL_ID_FAILED); | |
| 57 + desc = internal_error; | |
| 58 + goto alert_loser; | |
| 59 + } | |
| 60 + } | |
| 61 + | |
| 62 return SECSuccess; | |
| 63 | |
| 64 alert_loser: | |
| 65 @@ -7490,7 +7521,14 @@ ssl3_SendClientSecondRound(sslSocket *ss | |
| 66 if (rv != SECSuccess) { | |
| 67 goto loser; /* err code was set. */ | |
| 68 } | |
| 69 + } | |
| 70 | |
| 71 + rv = ssl3_SendEncryptedExtensions(ss); | |
| 72 + if (rv != SECSuccess) { | |
| 73 + goto loser; /* err code was set. */ | |
| 74 + } | |
| 75 + | |
| 76 + if (!ss->firstHsDone) { | |
| 77 if (ss->opt.enableFalseStart) { | |
| 78 if (!ss->ssl3.hs.authCertificatePending) { | |
| 79 /* When we fix bug 589047, we will need to know whether we are | |
| 80 @@ -7527,6 +7565,33 @@ ssl3_SendClientSecondRound(sslSocket *ss | |
| 81 | |
| 82 ssl_ReleaseXmitBufLock(ss); /*******************************
/ | |
| 83 | |
| 84 + if (!ss->ssl3.hs.isResuming && | |
| 85 + ssl3_ExtensionNegotiated(ss, ssl_channel_id_xtn)) { | |
| 86 + /* If we are negotiating ChannelID on a full handshake then we record | |
| 87 + * the handshake hashes in |sid| at this point. They will be needed in | |
| 88 + * the event that we resume this session and use ChannelID on the | |
| 89 + * resumption handshake. */ | |
| 90 + SSL3Hashes hashes; | |
| 91 + SECItem *originalHandshakeHash = | |
| 92 + &ss->sec.ci.sid->u.ssl3.originalHandshakeHash; | |
| 93 + PORT_Assert(ss->sec.ci.sid->cached == never_cached); | |
| 94 + | |
| 95 + ssl_GetSpecReadLock(ss); | |
| 96 + PORT_Assert(ss->version > SSL_LIBRARY_VERSION_3_0); | |
| 97 + rv = ssl3_ComputeHandshakeHashes(ss, ss->ssl3.cwSpec, &hashes, 0); | |
| 98 + ssl_ReleaseSpecReadLock(ss); | |
| 99 + if (rv != SECSuccess) { | |
| 100 + return rv; | |
| 101 + } | |
| 102 + | |
| 103 + PORT_Assert(originalHandshakeHash->len == 0); | |
| 104 + originalHandshakeHash->data = PORT_Alloc(hashes.len); | |
| 105 + if (!originalHandshakeHash->data) | |
| 106 + return SECFailure; | |
| 107 + originalHandshakeHash->len = hashes.len; | |
| 108 + memcpy(originalHandshakeHash->data, hashes.u.raw, hashes.len); | |
| 109 + } | |
| 110 + | |
| 111 if (ssl3_ExtensionNegotiated(ss, ssl_session_ticket_xtn)) | |
| 112 ss->ssl3.hs.ws = wait_new_session_ticket; | |
| 113 else | |
| 114 @@ -10494,6 +10559,184 @@ ssl3_RecordKeyLog(sslSocket *ss) | |
| 115 } | |
| 116 | |
| 117 /* called from ssl3_SendClientSecondRound | |
| 118 + * ssl3_HandleFinished | |
| 119 + */ | |
| 120 +static SECStatus | |
| 121 +ssl3_SendEncryptedExtensions(sslSocket *ss) | |
| 122 +{ | |
| 123 + static const char CHANNEL_ID_MAGIC[] = "TLS Channel ID signature"; | |
| 124 + static const char CHANNEL_ID_RESUMPTION_MAGIC[] = "Resumption"; | |
| 125 + /* This is the ASN.1 prefix for a P-256 public key. Specifically it's: | |
| 126 + * SEQUENCE | |
| 127 + * SEQUENCE | |
| 128 + * OID id-ecPublicKey | |
| 129 + * OID prime256v1 | |
| 130 + * BIT STRING, length 66, 0 trailing bits: 0x04 | |
| 131 + * | |
| 132 + * The 0x04 in the BIT STRING is the prefix for an uncompressed, X9.62 | |
| 133 + * public key. Following that are the two field elements as 32-byte, | |
| 134 + * big-endian numbers, as required by the Channel ID. */ | |
| 135 + static const unsigned char P256_SPKI_PREFIX[] = { | |
| 136 + 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, | |
| 137 + 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a, | |
| 138 + 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, | |
| 139 + 0x42, 0x00, 0x04 | |
| 140 + }; | |
| 141 + /* ChannelIDs are always 128 bytes long: 64 bytes of P-256 public key and 6
4 | |
| 142 + * bytes of ECDSA signature. */ | |
| 143 + static const int CHANNEL_ID_PUBLIC_KEY_LENGTH = 64; | |
| 144 + static const int CHANNEL_ID_LENGTH = 128; | |
| 145 + | |
| 146 + SECStatus rv = SECFailure; | |
| 147 + SECItem *spki = NULL; | |
| 148 + SSL3Hashes hashes; | |
| 149 + const unsigned char *pub_bytes; | |
| 150 + unsigned char signed_data[sizeof(CHANNEL_ID_MAGIC) + | |
| 151 + sizeof(CHANNEL_ID_RESUMPTION_MAGIC) + | |
| 152 + sizeof(SSL3Hashes)*2]; | |
| 153 + size_t signed_data_len; | |
| 154 + unsigned char digest[SHA256_LENGTH]; | |
| 155 + SECItem digest_item; | |
| 156 + unsigned char signature[64]; | |
| 157 + SECItem signature_item; | |
| 158 + | |
| 159 + PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss)); | |
| 160 + PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss)); | |
| 161 + | |
| 162 + if (ss->ssl3.channelID == NULL) | |
| 163 + return SECSuccess; | |
| 164 + | |
| 165 + PORT_Assert(ssl3_ExtensionNegotiated(ss, ssl_channel_id_xtn)); | |
| 166 + | |
| 167 + if (SECKEY_GetPrivateKeyType(ss->ssl3.channelID) != ecKey || | |
| 168 + PK11_SignatureLen(ss->ssl3.channelID) != sizeof(signature)) { | |
| 169 + PORT_SetError(SSL_ERROR_INVALID_CHANNEL_ID_KEY); | |
| 170 + rv = SECFailure; | |
| 171 + goto loser; | |
| 172 + } | |
| 173 + | |
| 174 + ssl_GetSpecReadLock(ss); | |
| 175 + rv = ssl3_ComputeHandshakeHashes(ss, ss->ssl3.cwSpec, &hashes, 0); | |
| 176 + ssl_ReleaseSpecReadLock(ss); | |
| 177 + | |
| 178 + if (rv != SECSuccess) | |
| 179 + goto loser; | |
| 180 + | |
| 181 + rv = ssl3_AppendHandshakeHeader(ss, encrypted_extensions, | |
| 182 + 2 + 2 + CHANNEL_ID_LENGTH); | |
| 183 + if (rv != SECSuccess) | |
| 184 + goto loser; /* error code set by AppendHandshakeHeader */ | |
| 185 + rv = ssl3_AppendHandshakeNumber(ss, ssl_channel_id_xtn, 2); | |
| 186 + if (rv != SECSuccess) | |
| 187 + goto loser; /* error code set by AppendHandshake */ | |
| 188 + rv = ssl3_AppendHandshakeNumber(ss, CHANNEL_ID_LENGTH, 2); | |
| 189 + if (rv != SECSuccess) | |
| 190 + goto loser; /* error code set by AppendHandshake */ | |
| 191 + | |
| 192 + spki = SECKEY_EncodeDERSubjectPublicKeyInfo(ss->ssl3.channelIDPub); | |
| 193 + | |
| 194 + if (spki->len != sizeof(P256_SPKI_PREFIX) + CHANNEL_ID_PUBLIC_KEY_LENGTH || | |
| 195 + memcmp(spki->data, P256_SPKI_PREFIX, sizeof(P256_SPKI_PREFIX)) != 0) { | |
| 196 + PORT_SetError(SSL_ERROR_INVALID_CHANNEL_ID_KEY); | |
| 197 + rv = SECFailure; | |
| 198 + goto loser; | |
| 199 + } | |
| 200 + | |
| 201 + pub_bytes = spki->data + sizeof(P256_SPKI_PREFIX); | |
| 202 + | |
| 203 + signed_data_len = 0; | |
| 204 + memcpy(signed_data + signed_data_len, CHANNEL_ID_MAGIC, | |
| 205 + sizeof(CHANNEL_ID_MAGIC)); | |
| 206 + signed_data_len += sizeof(CHANNEL_ID_MAGIC); | |
| 207 + if (ss->ssl3.hs.isResuming) { | |
| 208 + SECItem *originalHandshakeHash = | |
| 209 + &ss->sec.ci.sid->u.ssl3.originalHandshakeHash; | |
| 210 + PORT_Assert(originalHandshakeHash->len > 0); | |
| 211 + | |
| 212 + memcpy(signed_data + signed_data_len, CHANNEL_ID_RESUMPTION_MAGIC, | |
| 213 + sizeof(CHANNEL_ID_RESUMPTION_MAGIC)); | |
| 214 + signed_data_len += sizeof(CHANNEL_ID_RESUMPTION_MAGIC); | |
| 215 + memcpy(signed_data + signed_data_len, originalHandshakeHash->data, | |
| 216 + originalHandshakeHash->len); | |
| 217 + signed_data_len += originalHandshakeHash->len; | |
| 218 + } | |
| 219 + memcpy(signed_data + signed_data_len, hashes.u.raw, hashes.len); | |
| 220 + signed_data_len += hashes.len; | |
| 221 + | |
| 222 + rv = PK11_HashBuf(SEC_OID_SHA256, digest, signed_data, signed_data_len); | |
| 223 + if (rv != SECSuccess) | |
| 224 + goto loser; | |
| 225 + | |
| 226 + digest_item.data = digest; | |
| 227 + digest_item.len = sizeof(digest); | |
| 228 + | |
| 229 + signature_item.data = signature; | |
| 230 + signature_item.len = sizeof(signature); | |
| 231 + | |
| 232 + rv = PK11_Sign(ss->ssl3.channelID, &signature_item, &digest_item); | |
| 233 + if (rv != SECSuccess) | |
| 234 + goto loser; | |
| 235 + | |
| 236 + rv = ssl3_AppendHandshake(ss, pub_bytes, CHANNEL_ID_PUBLIC_KEY_LENGTH); | |
| 237 + if (rv != SECSuccess) | |
| 238 + goto loser; | |
| 239 + rv = ssl3_AppendHandshake(ss, signature, sizeof(signature)); | |
| 240 + | |
| 241 +loser: | |
| 242 + if (spki) | |
| 243 + SECITEM_FreeItem(spki, PR_TRUE); | |
| 244 + if (ss->ssl3.channelID) { | |
| 245 + SECKEY_DestroyPrivateKey(ss->ssl3.channelID); | |
| 246 + ss->ssl3.channelID = NULL; | |
| 247 + } | |
| 248 + if (ss->ssl3.channelIDPub) { | |
| 249 + SECKEY_DestroyPublicKey(ss->ssl3.channelIDPub); | |
| 250 + ss->ssl3.channelIDPub = NULL; | |
| 251 + } | |
| 252 + | |
| 253 + return rv; | |
| 254 +} | |
| 255 + | |
| 256 +/* ssl3_RestartHandshakeAfterChannelIDReq is called to restart a handshake | |
| 257 + * after a ChannelID callback returned SECWouldBlock. At this point we have | |
| 258 + * processed the server's ServerHello but not yet any further messages. We will | |
| 259 + * always get a message from the server after a ServerHello so either they are | |
| 260 + * waiting in the buffer or we'll get network I/O. */ | |
| 261 +SECStatus | |
| 262 +ssl3_RestartHandshakeAfterChannelIDReq(sslSocket *ss, | |
| 263 + SECKEYPublicKey *channelIDPub, | |
| 264 + SECKEYPrivateKey *channelID) | |
| 265 +{ | |
| 266 + if (ss->handshake == 0) { | |
| 267 + SECKEY_DestroyPublicKey(channelIDPub); | |
| 268 + SECKEY_DestroyPrivateKey(channelID); | |
| 269 + PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); | |
| 270 + return SECFailure; | |
| 271 + } | |
| 272 + | |
| 273 + if (channelIDPub == NULL || | |
| 274 + channelID == NULL) { | |
| 275 + if (channelIDPub) | |
| 276 + SECKEY_DestroyPublicKey(channelIDPub); | |
| 277 + if (channelID) | |
| 278 + SECKEY_DestroyPrivateKey(channelID); | |
| 279 + PORT_SetError(PR_INVALID_ARGUMENT_ERROR); | |
| 280 + return SECFailure; | |
| 281 + } | |
| 282 + | |
| 283 + if (ss->ssl3.channelID) | |
| 284 + SECKEY_DestroyPrivateKey(ss->ssl3.channelID); | |
| 285 + if (ss->ssl3.channelIDPub) | |
| 286 + SECKEY_DestroyPublicKey(ss->ssl3.channelIDPub); | |
| 287 + | |
| 288 + ss->handshake = ssl_GatherRecord1stHandshake; | |
| 289 + ss->ssl3.channelID = channelID; | |
| 290 + ss->ssl3.channelIDPub = channelIDPub; | |
| 291 + | |
| 292 + return SECSuccess; | |
| 293 +} | |
| 294 + | |
| 295 +/* called from ssl3_SendClientSecondRound | |
| 296 * ssl3_HandleClientHello | |
| 297 * ssl3_HandleFinished | |
| 298 */ | |
| 299 @@ -10753,11 +10996,16 @@ ssl3_HandleFinished(sslSocket *ss, SSL3O | |
| 300 flags = ssl_SEND_FLAG_FORCE_INTO_BUFFER; | |
| 301 } | |
| 302 | |
| 303 - if (!isServer && !ss->firstHsDone) { | |
| 304 - rv = ssl3_SendNextProto(ss); | |
| 305 - if (rv != SECSuccess) { | |
| 306 - goto xmit_loser; /* err code was set. */ | |
| 307 + if (!isServer) { | |
| 308 + if (!ss->firstHsDone) { | |
| 309 + rv = ssl3_SendNextProto(ss); | |
| 310 + if (rv != SECSuccess) { | |
| 311 + goto xmit_loser; /* err code was set. */ | |
| 312 + } | |
| 313 } | |
| 314 + rv = ssl3_SendEncryptedExtensions(ss); | |
| 315 + if (rv != SECSuccess) | |
| 316 + goto xmit_loser; /* err code was set. */ | |
| 317 } | |
| 318 | |
| 319 if (IS_DTLS(ss)) { | |
| 320 @@ -12237,6 +12485,11 @@ ssl3_DestroySSL3Info(sslSocket *ss) | |
| 321 ssl_FreePlatformKey(ss->ssl3.platformClientKey); | |
| 322 #endif /* NSS_PLATFORM_CLIENT_AUTH */ | |
| 323 | |
| 324 + if (ss->ssl3.channelID) | |
| 325 + SECKEY_DestroyPrivateKey(ss->ssl3.channelID); | |
| 326 + if (ss->ssl3.channelIDPub) | |
| 327 + SECKEY_DestroyPublicKey(ss->ssl3.channelIDPub); | |
| 328 + | |
| 329 if (ss->ssl3.peerCertArena != NULL) | |
| 330 ssl3_CleanupPeerCerts(ss); | |
| 331 | |
| 332 diff -pu a/nss/lib/ssl/ssl3ext.c b/nss/lib/ssl/ssl3ext.c | |
| 333 --- a/nss/lib/ssl/ssl3ext.c 2014-01-18 10:39:50.749149654 -0800 | |
| 334 +++ b/nss/lib/ssl/ssl3ext.c 2014-01-18 10:43:52.543083984 -0800 | |
| 335 @@ -64,6 +64,10 @@ static PRInt32 ssl3_SendUseSRTPXtn(sslSo | |
| 336 PRUint32 maxBytes); | |
| 337 static SECStatus ssl3_HandleUseSRTPXtn(sslSocket * ss, PRUint16 ex_type, | |
| 338 SECItem *data); | |
| 339 +static SECStatus ssl3_ClientHandleChannelIDXtn(sslSocket *ss, | |
| 340 + PRUint16 ex_type, SECItem *data); | |
| 341 +static PRInt32 ssl3_ClientSendChannelIDXtn(sslSocket *ss, PRBool append, | |
| 342 + PRUint32 maxBytes); | |
| 343 static SECStatus ssl3_ServerSendStatusRequestXtn(sslSocket * ss, | |
| 344 PRBool append, PRUint32 maxBytes); | |
| 345 static SECStatus ssl3_ServerHandleStatusRequestXtn(sslSocket *ss, | |
| 346 @@ -253,6 +257,7 @@ static const ssl3HelloExtensionHandler s | |
| 347 { ssl_next_proto_nego_xtn, &ssl3_ClientHandleNextProtoNegoXtn }, | |
| 348 { ssl_app_layer_protocol_xtn, &ssl3_ClientHandleAppProtoXtn }, | |
| 349 { ssl_use_srtp_xtn, &ssl3_HandleUseSRTPXtn }, | |
| 350 + { ssl_channel_id_xtn, &ssl3_ClientHandleChannelIDXtn }, | |
| 351 { ssl_cert_status_xtn, &ssl3_ClientHandleStatusRequestXtn }, | |
| 352 { -1, NULL } | |
| 353 }; | |
| 354 @@ -280,6 +285,7 @@ ssl3HelloExtensionSender clientHelloSend | |
| 355 { ssl_next_proto_nego_xtn, &ssl3_ClientSendNextProtoNegoXtn }, | |
| 356 { ssl_app_layer_protocol_xtn, &ssl3_ClientSendAppProtoXtn }, | |
| 357 { ssl_use_srtp_xtn, &ssl3_SendUseSRTPXtn }, | |
| 358 + { ssl_channel_id_xtn, &ssl3_ClientSendChannelIDXtn }, | |
| 359 { ssl_cert_status_xtn, &ssl3_ClientSendStatusRequestXtn }, | |
| 360 { ssl_signature_algorithms_xtn, &ssl3_ClientSendSigAlgsXtn } | |
| 361 /* any extra entries will appear as { 0, NULL } */ | |
| 362 @@ -795,6 +801,61 @@ loser: | |
| 363 return -1; | |
| 364 } | |
| 365 | |
| 366 +static SECStatus | |
| 367 +ssl3_ClientHandleChannelIDXtn(sslSocket *ss, PRUint16 ex_type, | |
| 368 + SECItem *data) | |
| 369 +{ | |
| 370 + PORT_Assert(ss->getChannelID != NULL); | |
| 371 + | |
| 372 + if (data->len) { | |
| 373 + PORT_SetError(SSL_ERROR_BAD_CHANNEL_ID_DATA); | |
| 374 + return SECFailure; | |
| 375 + } | |
| 376 + ss->xtnData.negotiated[ss->xtnData.numNegotiated++] = ex_type; | |
| 377 + return SECSuccess; | |
| 378 +} | |
| 379 + | |
| 380 +static PRInt32 | |
| 381 +ssl3_ClientSendChannelIDXtn(sslSocket * ss, PRBool append, | |
| 382 + PRUint32 maxBytes) | |
| 383 +{ | |
| 384 + PRInt32 extension_length = 4; | |
| 385 + | |
| 386 + if (!ss->getChannelID) | |
| 387 + return 0; | |
| 388 + | |
| 389 + if (maxBytes < extension_length) { | |
| 390 + PORT_Assert(0); | |
| 391 + return 0; | |
| 392 + } | |
| 393 + | |
| 394 + if (ss->sec.ci.sid->cached != never_cached && | |
| 395 + ss->sec.ci.sid->u.ssl3.originalHandshakeHash.len == 0) { | |
| 396 + /* We can't do ChannelID on a connection if we're resuming and didn't | |
| 397 + * do ChannelID on the original connection: without ChannelID on the | |
| 398 + * original connection we didn't record the handshake hashes needed for | |
| 399 + * the signature. */ | |
| 400 + return 0; | |
| 401 + } | |
| 402 + | |
| 403 + if (append) { | |
| 404 + SECStatus rv; | |
| 405 + rv = ssl3_AppendHandshakeNumber(ss, ssl_channel_id_xtn, 2); | |
| 406 + if (rv != SECSuccess) | |
| 407 + goto loser; | |
| 408 + rv = ssl3_AppendHandshakeNumber(ss, 0, 2); | |
| 409 + if (rv != SECSuccess) | |
| 410 + goto loser; | |
| 411 + ss->xtnData.advertised[ss->xtnData.numAdvertised++] = | |
| 412 + ssl_channel_id_xtn; | |
| 413 + } | |
| 414 + | |
| 415 + return extension_length; | |
| 416 + | |
| 417 +loser: | |
| 418 + return -1; | |
| 419 +} | |
| 420 + | |
| 421 static SECStatus | |
| 422 ssl3_ClientHandleStatusRequestXtn(sslSocket *ss, PRUint16 ex_type, | |
| 423 SECItem *data) | |
| 424 diff -pu a/nss/lib/ssl/ssl3prot.h b/nss/lib/ssl/ssl3prot.h | |
| 425 --- a/nss/lib/ssl/ssl3prot.h 2014-01-18 10:39:34.278881614 -0800 | |
| 426 +++ b/nss/lib/ssl/ssl3prot.h 2014-01-18 10:40:15.499552430 -0800 | |
| 427 @@ -129,7 +129,8 @@ typedef enum { | |
| 428 client_key_exchange = 16, | |
| 429 finished = 20, | |
| 430 certificate_status = 22, | |
| 431 - next_proto = 67 | |
| 432 + next_proto = 67, | |
| 433 + encrypted_extensions= 203 | |
| 434 } SSL3HandshakeType; | |
| 435 | |
| 436 typedef struct { | |
| 437 diff -pu a/nss/lib/ssl/sslauth.c b/nss/lib/ssl/sslauth.c | |
| 438 --- a/nss/lib/ssl/sslauth.c 2014-01-18 10:39:50.749149654 -0800 | |
| 439 +++ b/nss/lib/ssl/sslauth.c 2014-01-18 10:40:15.499552430 -0800 | |
| 440 @@ -216,6 +216,24 @@ SSL_GetClientAuthDataHook(PRFileDesc *s, | |
| 441 return SECSuccess; | |
| 442 } | |
| 443 | |
| 444 +SECStatus | |
| 445 +SSL_SetClientChannelIDCallback(PRFileDesc *fd, | |
| 446 + SSLClientChannelIDCallback callback, | |
| 447 + void *arg) { | |
| 448 + sslSocket *ss = ssl_FindSocket(fd); | |
| 449 + | |
| 450 + if (!ss) { | |
| 451 + SSL_DBG(("%d: SSL[%d]: bad socket in SSL_SetClientChannelIDCallback", | |
| 452 + SSL_GETPID(), fd)); | |
| 453 + return SECFailure; | |
| 454 + } | |
| 455 + | |
| 456 + ss->getChannelID = callback; | |
| 457 + ss->getChannelIDArg = arg; | |
| 458 + | |
| 459 + return SECSuccess; | |
| 460 +} | |
| 461 + | |
| 462 #ifdef NSS_PLATFORM_CLIENT_AUTH | |
| 463 /* NEED LOCKS IN HERE. */ | |
| 464 SECStatus | |
| 465 diff -pu a/nss/lib/ssl/sslerr.h b/nss/lib/ssl/sslerr.h | |
| 466 --- a/nss/lib/ssl/sslerr.h 2014-01-18 10:39:34.288881780 -0800 | |
| 467 +++ b/nss/lib/ssl/sslerr.h 2014-01-18 10:40:15.499552430 -0800 | |
| 468 @@ -193,6 +193,10 @@ SSL_ERROR_UNSUPPORTED_HASH_ALGORITHM = ( | |
| 469 SSL_ERROR_DIGEST_FAILURE = (SSL_ERROR_BASE + 127), | |
| 470 SSL_ERROR_INCORRECT_SIGNATURE_ALGORITHM = (SSL_ERROR_BASE + 128), | |
| 471 | |
| 472 +SSL_ERROR_BAD_CHANNEL_ID_DATA = (SSL_ERROR_BASE + 129), | |
| 473 +SSL_ERROR_INVALID_CHANNEL_ID_KEY = (SSL_ERROR_BASE + 130), | |
| 474 +SSL_ERROR_GET_CHANNEL_ID_FAILED = (SSL_ERROR_BASE + 131), | |
| 475 + | |
| 476 SSL_ERROR_END_OF_LIST /* let the c compiler determine the value of this. */ | |
| 477 } SSLErrorCodes; | |
| 478 #endif /* NO_SECURITY_ERROR_ENUM */ | |
| 479 diff -pu a/nss/lib/ssl/SSLerrs.h b/nss/lib/ssl/SSLerrs.h | |
| 480 --- a/nss/lib/ssl/SSLerrs.h 2014-01-18 10:39:34.238880964 -0800 | |
| 481 +++ b/nss/lib/ssl/SSLerrs.h 2014-01-18 10:40:15.499552430 -0800 | |
| 482 @@ -412,3 +412,12 @@ ER3(SSL_ERROR_DIGEST_FAILURE, (SSL_ERROR | |
| 483 | |
| 484 ER3(SSL_ERROR_INCORRECT_SIGNATURE_ALGORITHM, (SSL_ERROR_BASE + 128), | |
| 485 "Incorrect signature algorithm specified in a digitally-signed element.") | |
| 486 + | |
| 487 +ER3(SSL_ERROR_BAD_CHANNEL_ID_DATA, (SSL_ERROR_BASE + 129), | |
| 488 +"SSL received a malformed TLS Channel ID extension.") | |
| 489 + | |
| 490 +ER3(SSL_ERROR_INVALID_CHANNEL_ID_KEY, (SSL_ERROR_BASE + 130), | |
| 491 +"The application provided an invalid TLS Channel ID key.") | |
| 492 + | |
| 493 +ER3(SSL_ERROR_GET_CHANNEL_ID_FAILED, (SSL_ERROR_BASE + 131), | |
| 494 +"The application could not get a TLS Channel ID.") | |
| 495 diff -pu a/nss/lib/ssl/ssl.h b/nss/lib/ssl/ssl.h | |
| 496 --- a/nss/lib/ssl/ssl.h 2014-01-18 10:39:50.799150460 -0800 | |
| 497 +++ b/nss/lib/ssl/ssl.h 2014-01-18 10:40:15.499552430 -0800 | |
| 498 @@ -1015,6 +1015,34 @@ SSL_IMPORT SECStatus SSL_HandshakeNegoti | |
| 499 SSL_IMPORT SECStatus SSL_HandshakeResumedSession(PRFileDesc *fd, | |
| 500 PRBool *last_handshake_resumed
); | |
| 501 | |
| 502 +/* See SSL_SetClientChannelIDCallback for usage. If the callback returns | |
| 503 + * SECWouldBlock then SSL_RestartHandshakeAfterChannelIDReq should be called in | |
| 504 + * the future to restart the handshake. On SECSuccess, the callback must have | |
| 505 + * written a P-256, EC key pair to |*out_public_key| and |*out_private_key|. */ | |
| 506 +typedef SECStatus (PR_CALLBACK *SSLClientChannelIDCallback)( | |
| 507 + void *arg, | |
| 508 + PRFileDesc *fd, | |
| 509 + SECKEYPublicKey **out_public_key, | |
| 510 + SECKEYPrivateKey **out_private_key); | |
| 511 + | |
| 512 +/* SSL_RestartHandshakeAfterChannelIDReq attempts to restart the handshake | |
| 513 + * after a ChannelID callback returned SECWouldBlock. | |
| 514 + * | |
| 515 + * This function takes ownership of |channelIDPub| and |channelID|. */ | |
| 516 +SSL_IMPORT SECStatus SSL_RestartHandshakeAfterChannelIDReq( | |
| 517 + PRFileDesc *fd, | |
| 518 + SECKEYPublicKey *channelIDPub, | |
| 519 + SECKEYPrivateKey *channelID); | |
| 520 + | |
| 521 +/* SSL_SetClientChannelIDCallback sets a callback function that will be called | |
| 522 + * once the server's ServerHello has been processed. This is only applicable to | |
| 523 + * a client socket and setting this callback causes the TLS Channel ID | |
| 524 + * extension to be advertised. */ | |
| 525 +SSL_IMPORT SECStatus SSL_SetClientChannelIDCallback( | |
| 526 + PRFileDesc *fd, | |
| 527 + SSLClientChannelIDCallback callback, | |
| 528 + void *arg); | |
| 529 + | |
| 530 /* | |
| 531 ** How long should we wait before retransmitting the next flight of | |
| 532 ** the DTLS handshake? Returns SECFailure if not DTLS or not in a | |
| 533 diff -pu a/nss/lib/ssl/sslimpl.h b/nss/lib/ssl/sslimpl.h | |
| 534 --- a/nss/lib/ssl/sslimpl.h 2014-01-18 10:39:50.799150460 -0800 | |
| 535 +++ b/nss/lib/ssl/sslimpl.h 2014-01-18 10:40:15.499552430 -0800 | |
| 536 @@ -709,6 +709,14 @@ struct sslSessionIDStr { | |
| 537 | |
| 538 SECItem srvName; | |
| 539 | |
| 540 + /* originalHandshakeHash contains the hash of the original, full | |
| 541 + * handshake prior to the server's final flow. This is either a | |
| 542 + * SHA-1/MD5 combination (for TLS < 1.2) or the TLS PRF hash (for | |
| 543 + * TLS 1.2). This is recorded and used only when ChannelID is | |
| 544 + * negotiated as it's used to bind the ChannelID signature on the | |
| 545 + * resumption handshake to the original handshake. */ | |
| 546 + SECItem originalHandshakeHash; | |
| 547 + | |
| 548 /* This lock is lazily initialized by CacheSID when a sid is first | |
| 549 * cached. Before then, there is no need to lock anything because | |
| 550 * the sid isn't being shared by anything. | |
| 551 @@ -978,6 +986,9 @@ struct ssl3StateStr { | |
| 552 CERTCertificateList *clientCertChain; /* used by client */ | |
| 553 PRBool sendEmptyCert; /* used by client */ | |
| 554 | |
| 555 + SECKEYPrivateKey *channelID; /* used by client */ | |
| 556 + SECKEYPublicKey *channelIDPub; /* used by client */ | |
| 557 + | |
| 558 int policy; | |
| 559 /* This says what cipher suites we can do, and should | |
| 560 * be either SSL_ALLOWED or SSL_RESTRICTED | |
| 561 @@ -1255,6 +1266,8 @@ const unsigned char * preferredCipher; | |
| 562 void *pkcs11PinArg; | |
| 563 SSLNextProtoCallback nextProtoCallback; | |
| 564 void *nextProtoArg; | |
| 565 + SSLClientChannelIDCallback getChannelID; | |
| 566 + void *getChannelIDArg; | |
| 567 | |
| 568 PRIntervalTime rTimeout; /* timeout for NSPR I/O */ | |
| 569 PRIntervalTime wTimeout; /* timeout for NSPR I/O */ | |
| 570 @@ -1599,6 +1612,11 @@ extern SECStatus ssl3_RestartHandshakeAf | |
| 571 SECKEYPrivateKey * key, | |
| 572 CERTCertificateList *certChain); | |
| 573 | |
| 574 +extern SECStatus ssl3_RestartHandshakeAfterChannelIDReq( | |
| 575 + sslSocket *ss, | |
| 576 + SECKEYPublicKey *channelIDPub, | |
| 577 + SECKEYPrivateKey *channelID); | |
| 578 + | |
| 579 extern SECStatus ssl3_AuthCertificateComplete(sslSocket *ss, PRErrorCode error)
; | |
| 580 | |
| 581 /* | |
| 582 diff -pu a/nss/lib/ssl/sslnonce.c b/nss/lib/ssl/sslnonce.c | |
| 583 --- a/nss/lib/ssl/sslnonce.c 2014-01-18 10:39:50.739149486 -0800 | |
| 584 +++ b/nss/lib/ssl/sslnonce.c 2014-01-18 10:40:15.499552430 -0800 | |
| 585 @@ -180,6 +180,9 @@ ssl_DestroySID(sslSessionID *sid) | |
| 586 if (sid->u.ssl3.srvName.data) { | |
| 587 SECITEM_FreeItem(&sid->u.ssl3.srvName, PR_FALSE); | |
| 588 } | |
| 589 + if (sid->u.ssl3.originalHandshakeHash.data) { | |
| 590 + SECITEM_FreeItem(&sid->u.ssl3.originalHandshakeHash, PR_FALSE); | |
| 591 + } | |
| 592 | |
| 593 if (sid->u.ssl3.lock) { | |
| 594 PR_DestroyRWLock(sid->u.ssl3.lock); | |
| 595 diff -pu a/nss/lib/ssl/sslsecur.c b/nss/lib/ssl/sslsecur.c | |
| 596 --- a/nss/lib/ssl/sslsecur.c 2014-01-18 10:39:50.799150460 -0800 | |
| 597 +++ b/nss/lib/ssl/sslsecur.c 2014-01-18 10:40:15.499552430 -0800 | |
| 598 @@ -1584,6 +1584,42 @@ SSL_RestartHandshakeAfterCertReq(PRFileD | |
| 599 return ret; | |
| 600 } | |
| 601 | |
| 602 +SECStatus | |
| 603 +SSL_RestartHandshakeAfterChannelIDReq(PRFileDesc * fd, | |
| 604 + SECKEYPublicKey * channelIDPub, | |
| 605 + SECKEYPrivateKey *channelID) | |
| 606 +{ | |
| 607 + sslSocket * ss = ssl_FindSocket(fd); | |
| 608 + SECStatus ret; | |
| 609 + | |
| 610 + if (!ss) { | |
| 611 + SSL_DBG(("%d: SSL[%d]: bad socket in" | |
| 612 + " SSL_RestartHandshakeAfterChannelIDReq", | |
| 613 + SSL_GETPID(), fd)); | |
| 614 + goto loser; | |
| 615 + } | |
| 616 + | |
| 617 + | |
| 618 + ssl_Get1stHandshakeLock(ss); | |
| 619 + | |
| 620 + if (ss->version < SSL_LIBRARY_VERSION_3_0) { | |
| 621 + PORT_SetError(SSL_ERROR_FEATURE_NOT_SUPPORTED_FOR_SSL2); | |
| 622 + ssl_Release1stHandshakeLock(ss); | |
| 623 + goto loser; | |
| 624 + } | |
| 625 + | |
| 626 + ret = ssl3_RestartHandshakeAfterChannelIDReq(ss, channelIDPub, | |
| 627 + channelID); | |
| 628 + ssl_Release1stHandshakeLock(ss); | |
| 629 + | |
| 630 + return ret; | |
| 631 + | |
| 632 +loser: | |
| 633 + SECKEY_DestroyPublicKey(channelIDPub); | |
| 634 + SECKEY_DestroyPrivateKey(channelID); | |
| 635 + return SECFailure; | |
| 636 +} | |
| 637 + | |
| 638 /* DO NOT USE. This function was exported in ssl.def with the wrong signature; | |
| 639 * this implementation exists to maintain link-time compatibility. | |
| 640 */ | |
| 641 diff -pu a/nss/lib/ssl/sslsock.c b/nss/lib/ssl/sslsock.c | |
| 642 --- a/nss/lib/ssl/sslsock.c 2014-01-18 10:39:50.769149984 -0800 | |
| 643 +++ b/nss/lib/ssl/sslsock.c 2014-01-18 10:40:15.499552430 -0800 | |
| 644 @@ -276,6 +276,8 @@ ssl_DupSocket(sslSocket *os) | |
| 645 ss->canFalseStartCallback = os->canFalseStartCallback; | |
| 646 ss->canFalseStartCallbackData = os->canFalseStartCallbackData; | |
| 647 ss->pkcs11PinArg = os->pkcs11PinArg; | |
| 648 + ss->getChannelID = os->getChannelID; | |
| 649 + ss->getChannelIDArg = os->getChannelIDArg; | |
| 650 | |
| 651 /* Create security data */ | |
| 652 rv = ssl_CopySecurityInfo(ss, os); | |
| 653 @@ -1691,6 +1693,10 @@ SSL_ReconfigFD(PRFileDesc *model, PRFile | |
| 654 ss->handshakeCallbackData = sm->handshakeCallbackData; | |
| 655 if (sm->pkcs11PinArg) | |
| 656 ss->pkcs11PinArg = sm->pkcs11PinArg; | |
| 657 + if (sm->getChannelID) | |
| 658 + ss->getChannelID = sm->getChannelID; | |
| 659 + if (sm->getChannelIDArg) | |
| 660 + ss->getChannelIDArg = sm->getChannelIDArg; | |
| 661 return fd; | |
| 662 loser: | |
| 663 return NULL; | |
| 664 @@ -2968,6 +2974,8 @@ ssl_NewSocket(PRBool makeLocks, SSLProto | |
| 665 ss->badCertArg = NULL; | |
| 666 ss->pkcs11PinArg = NULL; | |
| 667 ss->ephemeralECDHKeyPair = NULL; | |
| 668 + ss->getChannelID = NULL; | |
| 669 + ss->getChannelIDArg = NULL; | |
| 670 | |
| 671 ssl_ChooseOps(ss); | |
| 672 ssl2_InitSocketPolicy(ss); | |
| 673 diff -pu a/nss/lib/ssl/sslt.h b/nss/lib/ssl/sslt.h | |
| 674 --- a/nss/lib/ssl/sslt.h 2014-01-18 10:39:34.328882426 -0800 | |
| 675 +++ b/nss/lib/ssl/sslt.h 2014-01-18 10:40:15.499552430 -0800 | |
| 676 @@ -190,10 +190,11 @@ typedef enum { | |
| 677 ssl_app_layer_protocol_xtn = 16, | |
| 678 ssl_session_ticket_xtn = 35, | |
| 679 ssl_next_proto_nego_xtn = 13172, | |
| 680 + ssl_channel_id_xtn = 30032, | |
| 681 ssl_padding_xtn = 35655, | |
| 682 ssl_renegotiation_info_xtn = 0xff01 /* experimental number */ | |
| 683 } SSLExtensionType; | |
| 684 | |
| 685 -#define SSL_MAX_EXTENSIONS 10 /* doesn't include ssl_padding_xtn. *
/ | |
| 686 +#define SSL_MAX_EXTENSIONS 11 /* doesn't include ssl_padding_xtn. *
/ | |
| 687 | |
| 688 #endif /* __sslt_h_ */ | |
| OLD | NEW |