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