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 |