Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(283)

Side by Side Diff: net/third_party/nss/ssl/ssl3ext.c

Issue 394003: Linux: enable building with a local version of libssl. (Closed)
Patch Set: ... Created 11 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « net/third_party/nss/ssl/ssl3ecc.c ('k') | net/third_party/nss/ssl/ssl3gthr.c » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /*
2 * SSL3 Protocol
3 *
4 * ***** BEGIN LICENSE BLOCK *****
5 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
6 *
7 * The contents of this file are subject to the Mozilla Public License Version
8 * 1.1 (the "License"); you may not use this file except in compliance with
9 * the License. You may obtain a copy of the License at
10 * http://www.mozilla.org/MPL/
11 *
12 * Software distributed under the License is distributed on an "AS IS" basis,
13 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
14 * for the specific language governing rights and limitations under the
15 * License.
16 *
17 * The Original Code is the Netscape security libraries.
18 *
19 * The Initial Developer of the Original Code is
20 * Netscape Communications Corporation.
21 * Portions created by the Initial Developer are Copyright (C) 1994-2000
22 * the Initial Developer. All Rights Reserved.
23 *
24 * Contributor(s):
25 * Dr Vipul Gupta <vipul.gupta@sun.com> and
26 * Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
27 * Nagendra Modadugu <ngm@google.com>, Google Inc.
28 *
29 * Alternatively, the contents of this file may be used under the terms of
30 * either the GNU General Public License Version 2 or later (the "GPL"), or
31 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
32 * in which case the provisions of the GPL or the LGPL are applicable instead
33 * of those above. If you wish to allow use of your version of this file only
34 * under the terms of either the GPL or the LGPL, and not to allow others to
35 * use your version of this file under the terms of the MPL, indicate your
36 * decision by deleting the provisions above and replace them with the notice
37 * and other provisions required by the GPL or the LGPL. If you do not delete
38 * the provisions above, a recipient may use your version of this file under
39 * the terms of any one of the MPL, the GPL or the LGPL.
40 *
41 * ***** END LICENSE BLOCK ***** */
42
43 /* TLS extension code moved here from ssl3ecc.c */
44 /* $Id: ssl3ext.c,v 1.5 2009/11/07 18:23:06 wtc%google.com Exp $ */
45
46 #include "nssrenam.h"
47 #include "nss.h"
48 #include "ssl.h"
49 #include "sslimpl.h"
50 #include "pk11pub.h"
51 #include "blapi.h"
52 #include "prinit.h"
53
54 static unsigned char key_name[SESS_TICKET_KEY_NAME_LEN];
55 static PK11SymKey *session_ticket_enc_key_pkcs11 = NULL;
56 static PK11SymKey *session_ticket_mac_key_pkcs11 = NULL;
57
58 static unsigned char session_ticket_enc_key[32];
59 static unsigned char session_ticket_mac_key[SHA256_LENGTH];
60
61 static PRBool session_ticket_keys_initialized = PR_FALSE;
62 static PRCallOnceType generate_session_keys_once;
63
64 static PRInt32 ssl3_SendServerNameXtn(sslSocket * ss,
65 PRBool append, PRUint32 maxBytes);
66 static SECStatus ssl3_ParseEncryptedSessionTicket(sslSocket *ss,
67 SECItem *data, EncryptedSessionTicket *enc_session_ticket);
68 static SECStatus ssl3_AppendToItem(SECItem *item, const unsigned char *buf,
69 PRUint32 bytes);
70 static SECStatus ssl3_AppendNumberToItem(SECItem *item, PRUint32 num,
71 PRInt32 lenSize);
72 static SECStatus ssl3_GetSessionTicketKeysPKCS11(sslSocket *ss,
73 PK11SymKey **aes_key, PK11SymKey **mac_key);
74 static SECStatus ssl3_GetSessionTicketKeys(const unsigned char **aes_key,
75 PRUint32 *aes_key_length, const unsigned char **mac_key,
76 PRUint32 *mac_key_length);
77
78 /*
79 * Write bytes. Using this function means the SECItem structure
80 * cannot be freed. The caller is expected to call this function
81 * on a shallow copy of the structure.
82 */
83 static SECStatus
84 ssl3_AppendToItem(SECItem *item, const unsigned char *buf, PRUint32 bytes)
85 {
86 if (bytes > item->len)
87 return SECFailure;
88
89 PORT_Memcpy(item->data, buf, bytes);
90 item->data += bytes;
91 item->len -= bytes;
92 return SECSuccess;
93 }
94
95 /*
96 * Write a number in network byte order. Using this function means the
97 * SECItem structure cannot be freed. The caller is expected to call
98 * this function on a shallow copy of the structure.
99 */
100 static SECStatus
101 ssl3_AppendNumberToItem(SECItem *item, PRUint32 num, PRInt32 lenSize)
102 {
103 SECStatus rv;
104 uint8 b[4];
105 uint8 * p = b;
106
107 switch (lenSize) {
108 case 4:
109 *p++ = (uint8) (num >> 24);
110 case 3:
111 *p++ = (uint8) (num >> 16);
112 case 2:
113 *p++ = (uint8) (num >> 8);
114 case 1:
115 *p = (uint8) num;
116 }
117 rv = ssl3_AppendToItem(item, &b[0], lenSize);
118 return rv;
119 }
120
121 static SECStatus ssl3_SessionTicketShutdown(void* appData, void* nssData)
122 {
123 if (session_ticket_enc_key_pkcs11) {
124 PK11_FreeSymKey(session_ticket_enc_key_pkcs11);
125 session_ticket_enc_key_pkcs11 = NULL;
126 }
127 if (session_ticket_mac_key_pkcs11) {
128 PK11_FreeSymKey(session_ticket_mac_key_pkcs11);
129 session_ticket_mac_key_pkcs11 = NULL;
130 }
131 PORT_Memset(&generate_session_keys_once, 0,
132 sizeof(generate_session_keys_once));
133 return SECSuccess;
134 }
135
136
137 static PRStatus
138 ssl3_GenerateSessionTicketKeysPKCS11(void *data)
139 {
140 SECStatus rv;
141 sslSocket *ss = (sslSocket *)data;
142 SECKEYPrivateKey *svrPrivKey = ss->serverCerts[kt_rsa].SERVERKEY;
143 SECKEYPublicKey *svrPubKey = ss->serverCerts[kt_rsa].serverKeyPair->pubKey;
144
145 if (svrPrivKey == NULL || svrPubKey == NULL) {
146 SSL_DBG(("%d: SSL[%d]: Pub or priv key(s) is NULL.",
147 SSL_GETPID(), ss->fd));
148 goto loser;
149 }
150
151 /* Get a copy of the session keys from shared memory. */
152 PORT_Memcpy(key_name, SESS_TICKET_KEY_NAME_PREFIX,
153 sizeof(SESS_TICKET_KEY_NAME_PREFIX));
154 if (!ssl_GetSessionTicketKeysPKCS11(svrPrivKey, svrPubKey,
155 ss->pkcs11PinArg, &key_name[SESS_TICKET_KEY_NAME_PREFIX_LEN],
156 &session_ticket_enc_key_pkcs11, &session_ticket_mac_key_pkcs11))
157 return PR_FAILURE;
158
159 rv = NSS_RegisterShutdown(ssl3_SessionTicketShutdown, NULL);
160 if (rv != SECSuccess)
161 goto loser;
162
163 return PR_SUCCESS;
164
165 loser:
166 ssl3_SessionTicketShutdown(NULL, NULL);
167 return PR_FAILURE;
168 }
169
170 static SECStatus
171 ssl3_GetSessionTicketKeysPKCS11(sslSocket *ss, PK11SymKey **aes_key,
172 PK11SymKey **mac_key)
173 {
174 if (PR_CallOnceWithArg(&generate_session_keys_once,
175 ssl3_GenerateSessionTicketKeysPKCS11, ss) != PR_SUCCESS)
176 return SECFailure;
177
178 if (session_ticket_enc_key_pkcs11 == NULL ||
179 session_ticket_mac_key_pkcs11 == NULL)
180 return SECFailure;
181
182 *aes_key = session_ticket_enc_key_pkcs11;
183 *mac_key = session_ticket_mac_key_pkcs11;
184 return SECSuccess;
185 }
186
187 static PRStatus
188 ssl3_GenerateSessionTicketKeys(void)
189 {
190 PORT_Memcpy(key_name, SESS_TICKET_KEY_NAME_PREFIX,
191 sizeof(SESS_TICKET_KEY_NAME_PREFIX));
192
193 if (!ssl_GetSessionTicketKeys(&key_name[SESS_TICKET_KEY_NAME_PREFIX_LEN],
194 session_ticket_enc_key, session_ticket_mac_key))
195 return PR_FAILURE;
196
197 session_ticket_keys_initialized = PR_TRUE;
198 return PR_SUCCESS;
199 }
200
201 static SECStatus
202 ssl3_GetSessionTicketKeys(const unsigned char **aes_key,
203 PRUint32 *aes_key_length, const unsigned char **mac_key,
204 PRUint32 *mac_key_length)
205 {
206 if (PR_CallOnce(&generate_session_keys_once,
207 ssl3_GenerateSessionTicketKeys) != SECSuccess)
208 return SECFailure;
209
210 if (!session_ticket_keys_initialized)
211 return SECFailure;
212
213 *aes_key = session_ticket_enc_key;
214 *aes_key_length = sizeof(session_ticket_enc_key);
215 *mac_key = session_ticket_mac_key;
216 *mac_key_length = sizeof(session_ticket_mac_key);
217
218 return SECSuccess;
219 }
220
221 /* Table of handlers for received TLS hello extensions, one per extension.
222 * In the second generation, this table will be dynamic, and functions
223 * will be registered here.
224 */
225 static const ssl3HelloExtensionHandler clientHelloHandlers[] = {
226 { server_name_xtn, &ssl3_HandleServerNameXtn },
227 #ifdef NSS_ENABLE_ECC
228 { elliptic_curves_xtn, &ssl3_HandleSupportedCurvesXtn },
229 { ec_point_formats_xtn, &ssl3_HandleSupportedPointFormatsXtn },
230 #endif
231 { session_ticket_xtn, &ssl3_ServerHandleSessionTicketXtn },
232 { -1, NULL }
233 };
234
235 static const ssl3HelloExtensionHandler serverHelloHandlers[] = {
236 { server_name_xtn, &ssl3_HandleServerNameXtn },
237 /* TODO: add a handler for ec_point_formats_xtn */
238 { session_ticket_xtn, &ssl3_ClientHandleSessionTicketXtn },
239 { -1, NULL }
240 };
241
242 /* Table of functions to format TLS hello extensions, one per extension.
243 * This static table is for the formatting of client hello extensions.
244 * The server's table of hello senders is dynamic, in the socket struct,
245 * and sender functions are registered there.
246 */
247 static const
248 ssl3HelloExtensionSender clientHelloSenders[MAX_EXTENSIONS] = {
249 { server_name_xtn, &ssl3_SendServerNameXtn },
250 #ifdef NSS_ENABLE_ECC
251 { elliptic_curves_xtn, &ssl3_SendSupportedCurvesXtn },
252 { ec_point_formats_xtn, &ssl3_SendSupportedPointFormatsXtn },
253 #else
254 { -1, NULL },
255 { -1, NULL },
256 #endif
257 { session_ticket_xtn, ssl3_SendSessionTicketXtn }
258 };
259
260 static PRBool
261 arrayContainsExtension(const PRUint16 *array, PRUint32 len, PRUint16 ex_type)
262 {
263 int i;
264 for (i = 0; i < len; i++) {
265 if (ex_type == array[i])
266 return PR_TRUE;
267 }
268 return PR_FALSE;
269 }
270
271 PRBool
272 ssl3_ExtensionNegotiated(sslSocket *ss, PRUint16 ex_type) {
273 TLSExtensionData *xtnData = &ss->xtnData;
274 return arrayContainsExtension(xtnData->negotiated,
275 xtnData->numNegotiated, ex_type);
276 }
277
278 static PRBool
279 ssl3_ClientExtensionAdvertised(sslSocket *ss, PRUint16 ex_type) {
280 TLSExtensionData *xtnData = &ss->xtnData;
281 return arrayContainsExtension(xtnData->advertised,
282 xtnData->numAdvertised, ex_type);
283 }
284
285 /* Format an SNI extension, using the name from the socket's URL,
286 * unless that name is a dotted decimal string.
287 */
288 static PRInt32
289 ssl3_SendServerNameXtn(
290 sslSocket * ss,
291 PRBool append,
292 PRUint32 maxBytes)
293 {
294 PRUint32 len;
295 PRNetAddr netAddr;
296
297 /* must have a hostname */
298 if (!ss || !ss->url || !ss->url[0])
299 return 0;
300 /* must not be an IPv4 or IPv6 address */
301 if (PR_SUCCESS == PR_StringToNetAddr(ss->url, &netAddr)) {
302 /* is an IP address (v4 or v6) */
303 return 0;
304 }
305 len = PORT_Strlen(ss->url);
306 if (append && maxBytes >= len + 9) {
307 SECStatus rv;
308 /* extension_type */
309 rv = ssl3_AppendHandshakeNumber(ss, server_name_xtn, 2);
310 if (rv != SECSuccess) return -1;
311 /* length of extension_data */
312 rv = ssl3_AppendHandshakeNumber(ss, len + 5, 2);
313 if (rv != SECSuccess) return -1;
314 /* length of server_name_list */
315 rv = ssl3_AppendHandshakeNumber(ss, len + 3, 2);
316 if (rv != SECSuccess) return -1;
317 /* Name Type (host_name) */
318 rv = ssl3_AppendHandshake(ss, "\0", 1);
319 if (rv != SECSuccess) return -1;
320 /* HostName (length and value) */
321 rv = ssl3_AppendHandshakeVariable(ss, (unsigned char *)ss->url, len, 2);
322 if (rv != SECSuccess) return -1;
323 if (!ss->sec.isServer) {
324 TLSExtensionData *xtnData = &ss->xtnData;
325 xtnData->advertised[xtnData->numAdvertised++] = server_name_xtn;
326 }
327 }
328 return len + 9;
329 }
330
331 /* handle an incoming SNI extension, by ignoring it. */
332 SECStatus
333 ssl3_HandleServerNameXtn(sslSocket * ss, PRUint16 ex_type, SECItem *data)
334 {
335 /* TODO: if client, should verify extension_data is empty. */
336 /* TODO: if server, should send empty extension_data. */
337 /* For now, we ignore this, as if we didn't understand it. :-) */
338 return SECSuccess;
339 }
340
341 /* Called by both clients and servers.
342 * Clients sends a filled in session ticket if one is available, and otherwise
343 * sends an empty ticket. Servers always send empty tickets.
344 */
345 PRInt32
346 ssl3_SendSessionTicketXtn(
347 sslSocket * ss,
348 PRBool append,
349 PRUint32 maxBytes)
350 {
351 PRInt32 extension_length;
352 NewSessionTicket *session_ticket = NULL;
353
354 /* Ignore the SessionTicket extension if processing is disabled. */
355 if (!ss->opt.enableSessionTickets)
356 return 0;
357
358 /* Empty extension length = extension_type (2-bytes) +
359 * length(extension_data) (2-bytes)
360 */
361 extension_length = 4;
362
363 /* If we are a client then send a session ticket if one is availble.
364 * Servers that support the extension and are willing to negotiate the
365 * the extension always respond with an empty extension.
366 */
367 if (!ss->sec.isServer) {
368 sslSessionID *sid = ss->sec.ci.sid;
369 session_ticket = &sid->u.ssl3.sessionTicket;
370 if (session_ticket->ticket.data) {
371 if (ss->xtnData.ticketTimestampVerified) {
372 extension_length += session_ticket->ticket.len;
373 } else if (!append &&
374 (session_ticket->ticket_lifetime_hint == 0 ||
375 (session_ticket->ticket_lifetime_hint +
376 session_ticket->received_timestamp > ssl_Time()))) {
377 extension_length += session_ticket->ticket.len;
378 ss->xtnData.ticketTimestampVerified = PR_TRUE;
379 }
380 }
381 }
382
383 if (append && maxBytes >= extension_length) {
384 SECStatus rv;
385 /* extension_type */
386 rv = ssl3_AppendHandshakeNumber(ss, session_ticket_xtn, 2);
387 if (rv != SECSuccess)
388 goto loser;
389 if (session_ticket && session_ticket->ticket.data &&
390 ss->xtnData.ticketTimestampVerified) {
391 rv = ssl3_AppendHandshakeVariable(ss, session_ticket->ticket.data,
392 session_ticket->ticket.len, 2);
393 ss->xtnData.ticketTimestampVerified = PR_FALSE;
394 } else {
395 rv = ssl3_AppendHandshakeNumber(ss, 0, 2);
396 }
397 if (rv != SECSuccess)
398 goto loser;
399
400 if (!ss->sec.isServer) {
401 TLSExtensionData *xtnData = &ss->xtnData;
402 xtnData->advertised[xtnData->numAdvertised++] = session_ticket_xtn;
403 }
404 } else if (maxBytes < extension_length) {
405 PORT_Assert(0);
406 return 0;
407 }
408 return extension_length;
409
410 loser:
411 ss->xtnData.ticketTimestampVerified = PR_FALSE;
412 return -1;
413 }
414
415 /*
416 * NewSessionTicket
417 * Called from ssl3_HandleFinished
418 */
419 SECStatus
420 ssl3_SendNewSessionTicket(sslSocket *ss)
421 {
422 int i;
423 SECStatus rv;
424 NewSessionTicket ticket;
425 SECItem plaintext;
426 SECItem plaintext_item = {0, NULL, 0};
427 SECItem ciphertext = {0, NULL, 0};
428 PRUint32 ciphertext_length;
429 PRBool ms_is_wrapped;
430 unsigned char wrapped_ms[SSL3_MASTER_SECRET_LENGTH];
431 SECItem ms_item = {0, NULL, 0};
432 SSL3KEAType effectiveExchKeyType = ssl_kea_null;
433 PRUint32 padding_length;
434 PRUint32 message_length;
435 PRUint32 cert_length;
436 uint8 length_buf[4];
437 PRUint32 now;
438 PK11SymKey *aes_key_pkcs11;
439 PK11SymKey *mac_key_pkcs11;
440 const unsigned char *aes_key;
441 const unsigned char *mac_key;
442 PRUint32 aes_key_length;
443 PRUint32 mac_key_length;
444 PRUint64 aes_ctx_buf[MAX_CIPHER_CONTEXT_LLONGS];
445 AESContext *aes_ctx;
446 CK_MECHANISM_TYPE cipherMech = CKM_AES_CBC;
447 PK11Context *aes_ctx_pkcs11;
448 const SECHashObject *hashObj = NULL;
449 PRUint64 hmac_ctx_buf[MAX_MAC_CONTEXT_LLONGS];
450 HMACContext *hmac_ctx;
451 CK_MECHANISM_TYPE macMech = CKM_SHA256_HMAC;
452 PK11Context *hmac_ctx_pkcs11;
453 unsigned char computed_mac[TLS_EX_SESS_TICKET_MAC_LENGTH];
454 unsigned int computed_mac_length;
455 unsigned char iv[AES_BLOCK_SIZE];
456 SECItem ivItem;
457 CK_MECHANISM_TYPE msWrapMech = 0; /* dummy default value,
458 * must be >= 0 */
459
460 SSL_TRC(3, ("%d: SSL3[%d]: send session_ticket handshake",
461 SSL_GETPID(), ss->fd));
462
463 PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
464 PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
465
466 ticket.ticket_lifetime_hint = TLS_EX_SESS_TICKET_LIFETIME_HINT;
467 cert_length = (ss->opt.requestCertificate && ss->sec.ci.sid->peerCert) ?
468 3 + ss->sec.ci.sid->peerCert->derCert.len : 0;
469
470 /* Get IV and encryption keys */
471 ivItem.data = iv;
472 ivItem.len = sizeof(iv);
473 rv = PK11_GenerateRandom(iv, sizeof(iv));
474 if (rv != SECSuccess) goto loser;
475
476 if (ss->opt.bypassPKCS11) {
477 rv = ssl3_GetSessionTicketKeys(&aes_key, &aes_key_length,
478 &mac_key, &mac_key_length);
479 } else {
480 rv = ssl3_GetSessionTicketKeysPKCS11(ss, &aes_key_pkcs11,
481 &mac_key_pkcs11);
482 }
483 if (rv != SECSuccess) goto loser;
484
485 if (ss->ssl3.pwSpec->msItem.len && ss->ssl3.pwSpec->msItem.data) {
486 /* The master secret is available unwrapped. */
487 ms_item.data = ss->ssl3.pwSpec->msItem.data;
488 ms_item.len = ss->ssl3.pwSpec->msItem.len;
489 ms_is_wrapped = PR_FALSE;
490 } else {
491 /* Extract the master secret wrapped. */
492 sslSessionID sid;
493 PORT_Memset(&sid, 0, sizeof(sslSessionID));
494
495 if (ss->ssl3.hs.kea_def->kea == kea_ecdhe_rsa) {
496 effectiveExchKeyType = kt_rsa;
497 } else {
498 effectiveExchKeyType = ss->ssl3.hs.kea_def->exchKeyType;
499 }
500
501 rv = ssl3_CacheWrappedMasterSecret(ss, &sid, ss->ssl3.pwSpec,
502 effectiveExchKeyType);
503 if (rv == SECSuccess) {
504 if (sid.u.ssl3.keys.wrapped_master_secret_len > sizeof(wrapped_ms))
505 goto loser;
506 memcpy(wrapped_ms, sid.u.ssl3.keys.wrapped_master_secret,
507 sid.u.ssl3.keys.wrapped_master_secret_len);
508 ms_item.data = wrapped_ms;
509 ms_item.len = sid.u.ssl3.keys.wrapped_master_secret_len;
510 msWrapMech = sid.u.ssl3.masterWrapMech;
511 } else {
512 /* TODO: else send an empty ticket. */
513 goto loser;
514 }
515 ms_is_wrapped = PR_TRUE;
516 }
517
518 ciphertext_length =
519 sizeof(PRUint16) /* ticket_version */
520 + sizeof(SSL3ProtocolVersion) /* ssl_version */
521 + sizeof(ssl3CipherSuite) /* ciphersuite */
522 + 1 /* compression */
523 + 10 /* cipher spec parameters */
524 + 1 /* SessionTicket.ms_is_wrapped */
525 + 1 /* effectiveExchKeyType */
526 + 4 /* msWrapMech */
527 + 2 /* master_secret.length */
528 + ms_item.len /* master_secret */
529 + 1 /* client_auth_type */
530 + cert_length /* cert */
531 + sizeof(ticket.ticket_lifetime_hint);
532 padding_length = AES_BLOCK_SIZE -
533 (ciphertext_length % AES_BLOCK_SIZE);
534 ciphertext_length += padding_length;
535
536 message_length =
537 sizeof(ticket.ticket_lifetime_hint) /* ticket_lifetime_hint */
538 + 2 /* length field for NewSessionTicket.ticket */
539 + SESS_TICKET_KEY_NAME_LEN /* key_name */
540 + AES_BLOCK_SIZE /* iv */
541 + 2 /* length field for NewSessionTicket.ticket.encrypted_state */
542 + ciphertext_length /* encrypted_state */
543 + TLS_EX_SESS_TICKET_MAC_LENGTH; /* mac */
544
545 if (SECITEM_AllocItem(NULL, &plaintext_item, ciphertext_length) == NULL)
546 goto loser;
547
548 plaintext = plaintext_item;
549
550 /* ticket_version */
551 rv = ssl3_AppendNumberToItem(&plaintext, TLS_EX_SESS_TICKET_VERSION,
552 sizeof(PRUint16));
553 if (rv != SECSuccess) goto loser;
554
555 /* ssl_version */
556 rv = ssl3_AppendNumberToItem(&plaintext, ss->version,
557 sizeof(SSL3ProtocolVersion));
558 if (rv != SECSuccess) goto loser;
559
560 /* ciphersuite */
561 rv = ssl3_AppendNumberToItem(&plaintext, ss->ssl3.hs.cipher_suite,
562 sizeof(ssl3CipherSuite));
563 if (rv != SECSuccess) goto loser;
564
565 /* compression */
566 rv = ssl3_AppendNumberToItem(&plaintext, ss->ssl3.hs.compression, 1);
567 if (rv != SECSuccess) goto loser;
568
569 /* cipher spec parameters */
570 rv = ssl3_AppendNumberToItem(&plaintext, ss->sec.authAlgorithm, 1);
571 if (rv != SECSuccess) goto loser;
572 rv = ssl3_AppendNumberToItem(&plaintext, ss->sec.authKeyBits, 4);
573 if (rv != SECSuccess) goto loser;
574 rv = ssl3_AppendNumberToItem(&plaintext, ss->sec.keaType, 1);
575 if (rv != SECSuccess) goto loser;
576 rv = ssl3_AppendNumberToItem(&plaintext, ss->sec.keaKeyBits, 4);
577 if (rv != SECSuccess) goto loser;
578
579 /* master_secret */
580 rv = ssl3_AppendNumberToItem(&plaintext, ms_is_wrapped, 1);
581 if (rv != SECSuccess) goto loser;
582 rv = ssl3_AppendNumberToItem(&plaintext, effectiveExchKeyType, 1);
583 if (rv != SECSuccess) goto loser;
584 rv = ssl3_AppendNumberToItem(&plaintext, msWrapMech, 4);
585 if (rv != SECSuccess) goto loser;
586 rv = ssl3_AppendNumberToItem(&plaintext, ms_item.len, 2);
587 if (rv != SECSuccess) goto loser;
588 rv = ssl3_AppendToItem(&plaintext, ms_item.data, ms_item.len);
589 if (rv != SECSuccess) goto loser;
590
591 /* client_identity */
592 if (ss->opt.requestCertificate && ss->sec.ci.sid->peerCert) {
593 rv = ssl3_AppendNumberToItem(&plaintext, CLIENT_AUTH_CERTIFICATE, 1);
594 if (rv != SECSuccess) goto loser;
595 rv = ssl3_AppendNumberToItem(&plaintext,
596 ss->sec.ci.sid->peerCert->derCert.len, 3);
597 if (rv != SECSuccess) goto loser;
598 rv = ssl3_AppendToItem(&plaintext,
599 ss->sec.ci.sid->peerCert->derCert.data,
600 ss->sec.ci.sid->peerCert->derCert.len);
601 if (rv != SECSuccess) goto loser;
602 } else {
603 rv = ssl3_AppendNumberToItem(&plaintext, 0, 1);
604 if (rv != SECSuccess) goto loser;
605 }
606
607 /* timestamp */
608 now = ssl_Time();
609 rv = ssl3_AppendNumberToItem(&plaintext, now,
610 sizeof(ticket.ticket_lifetime_hint));
611 if (rv != SECSuccess) goto loser;
612
613 PORT_Assert(plaintext.len == padding_length);
614 for (i = 0; i < padding_length; i++)
615 plaintext.data[i] = (unsigned char)padding_length;
616
617 if (SECITEM_AllocItem(NULL, &ciphertext, ciphertext_length) == NULL) {
618 rv = SECFailure;
619 goto loser;
620 }
621
622 /* Generate encrypted portion of ticket. */
623 if (ss->opt.bypassPKCS11) {
624 aes_ctx = (AESContext *)aes_ctx_buf;
625 rv = AES_InitContext(aes_ctx, aes_key, aes_key_length, iv,
626 NSS_AES_CBC, 1, AES_BLOCK_SIZE);
627 if (rv != SECSuccess) goto loser;
628
629 rv = AES_Encrypt(aes_ctx, ciphertext.data, &ciphertext.len,
630 ciphertext.len, plaintext_item.data,
631 plaintext_item.len);
632 if (rv != SECSuccess) goto loser;
633 } else {
634 aes_ctx_pkcs11 = PK11_CreateContextBySymKey(cipherMech,
635 CKA_ENCRYPT, aes_key_pkcs11, &ivItem);
636 if (!aes_ctx_pkcs11)
637 goto loser;
638
639 rv = PK11_CipherOp(aes_ctx_pkcs11, ciphertext.data,
640 (int *)&ciphertext.len, ciphertext.len,
641 plaintext_item.data, plaintext_item.len);
642 PK11_Finalize(aes_ctx_pkcs11);
643 PK11_DestroyContext(aes_ctx_pkcs11, PR_TRUE);
644 if (rv != SECSuccess) goto loser;
645 }
646
647 /* Convert ciphertext length to network order. */
648 length_buf[0] = (ciphertext.len >> 8) & 0xff;
649 length_buf[1] = (ciphertext.len ) & 0xff;
650
651 /* Compute MAC. */
652 if (ss->opt.bypassPKCS11) {
653 hmac_ctx = (HMACContext *)hmac_ctx_buf;
654 hashObj = HASH_GetRawHashObject(HASH_AlgSHA256);
655 if (HMAC_Init(hmac_ctx, hashObj, mac_key,
656 mac_key_length, PR_FALSE) != SECSuccess)
657 goto loser;
658
659 HMAC_Begin(hmac_ctx);
660 HMAC_Update(hmac_ctx, key_name, SESS_TICKET_KEY_NAME_LEN);
661 HMAC_Update(hmac_ctx, iv, sizeof(iv));
662 HMAC_Update(hmac_ctx, (unsigned char *)length_buf, 2);
663 HMAC_Update(hmac_ctx, ciphertext.data, ciphertext.len);
664 HMAC_Finish(hmac_ctx, computed_mac, &computed_mac_length,
665 sizeof(computed_mac));
666 } else {
667 SECItem macParam;
668 macParam.data = NULL;
669 macParam.len = 0;
670 hmac_ctx_pkcs11 = PK11_CreateContextBySymKey(macMech,
671 CKA_SIGN, mac_key_pkcs11, &macParam);
672 if (!hmac_ctx_pkcs11)
673 goto loser;
674
675 rv = PK11_DigestBegin(hmac_ctx_pkcs11);
676 rv = PK11_DigestOp(hmac_ctx_pkcs11, key_name,
677 SESS_TICKET_KEY_NAME_LEN);
678 rv = PK11_DigestOp(hmac_ctx_pkcs11, iv, sizeof(iv));
679 rv = PK11_DigestOp(hmac_ctx_pkcs11, (unsigned char *)length_buf, 2);
680 rv = PK11_DigestOp(hmac_ctx_pkcs11, ciphertext.data, ciphertext.len);
681 rv = PK11_DigestFinal(hmac_ctx_pkcs11, computed_mac,
682 &computed_mac_length, sizeof(computed_mac));
683 PK11_DestroyContext(hmac_ctx_pkcs11, PR_TRUE);
684 if (rv != SECSuccess) goto loser;
685 }
686
687 /* Serialize the handshake message. */
688 rv = ssl3_AppendHandshakeHeader(ss, new_session_ticket, message_length);
689 if (rv != SECSuccess) goto loser;
690
691 rv = ssl3_AppendHandshakeNumber(ss, ticket.ticket_lifetime_hint,
692 sizeof(ticket.ticket_lifetime_hint));
693 if (rv != SECSuccess) goto loser;
694
695 rv = ssl3_AppendHandshakeNumber(ss,
696 message_length - sizeof(ticket.ticket_lifetime_hint) - 2, 2);
697 if (rv != SECSuccess) goto loser;
698
699 rv = ssl3_AppendHandshake(ss, key_name, SESS_TICKET_KEY_NAME_LEN);
700 if (rv != SECSuccess) goto loser;
701
702 rv = ssl3_AppendHandshake(ss, iv, sizeof(iv));
703 if (rv != SECSuccess) goto loser;
704
705 rv = ssl3_AppendHandshakeVariable(ss, ciphertext.data, ciphertext.len, 2);
706 if (rv != SECSuccess) goto loser;
707
708 rv = ssl3_AppendHandshake(ss, computed_mac, computed_mac_length);
709 if (rv != SECSuccess) goto loser;
710
711 loser:
712 if (plaintext_item.data)
713 SECITEM_FreeItem(&plaintext_item, PR_FALSE);
714 if (ciphertext.data)
715 SECITEM_FreeItem(&ciphertext, PR_FALSE);
716
717 return rv;
718 }
719
720 /* When a client receives a SessionTicket extension a NewSessionTicket
721 * message is expected during the handshake.
722 */
723 SECStatus
724 ssl3_ClientHandleSessionTicketXtn(sslSocket *ss, PRUint16 ex_type,
725 SECItem *data)
726 {
727 if (data->len != 0)
728 return SECFailure;
729
730 /* Keep track of negotiated extensions. */
731 ss->xtnData.negotiated[ss->xtnData.numNegotiated++] = ex_type;
732 return SECSuccess;
733 }
734
735 SECStatus
736 ssl3_ServerHandleSessionTicketXtn(sslSocket *ss, PRUint16 ex_type,
737 SECItem *data)
738 {
739 SECStatus rv;
740 SECItem *decrypted_state = NULL;
741 SessionTicket *parsed_session_ticket = NULL;
742 sslSessionID *sid = NULL;
743 SSL3Statistics *ssl3stats;
744
745 /* Ignore the SessionTicket extension if processing is disabled. */
746 if (!ss->opt.enableSessionTickets)
747 return SECSuccess;
748
749 /* Keep track of negotiated extensions. */
750 ss->xtnData.negotiated[ss->xtnData.numNegotiated++] = ex_type;
751
752 /* Parse the received ticket sent in by the client. We are
753 * lenient about some parse errors, falling back to a fullshake
754 * instead of terminating the current connection.
755 */
756 if (data->len == 0) {
757 ss->xtnData.emptySessionTicket = PR_TRUE;
758 } else {
759 int i;
760 SECItem extension_data;
761 EncryptedSessionTicket enc_session_ticket;
762 unsigned char computed_mac[TLS_EX_SESS_TICKET_MAC_LENGTH];
763 unsigned int computed_mac_length;
764 const SECHashObject *hashObj;
765 const unsigned char *aes_key;
766 const unsigned char *mac_key;
767 PK11SymKey *aes_key_pkcs11;
768 PK11SymKey *mac_key_pkcs11;
769 PRUint32 aes_key_length;
770 PRUint32 mac_key_length;
771 PRUint64 hmac_ctx_buf[MAX_MAC_CONTEXT_LLONGS];
772 HMACContext *hmac_ctx;
773 PK11Context *hmac_ctx_pkcs11;
774 CK_MECHANISM_TYPE macMech = CKM_SHA256_HMAC;
775 PRUint64 aes_ctx_buf[MAX_CIPHER_CONTEXT_LLONGS];
776 AESContext *aes_ctx;
777 PK11Context *aes_ctx_pkcs11;
778 CK_MECHANISM_TYPE cipherMech = CKM_AES_CBC;
779 unsigned char * padding;
780 PRUint32 padding_length;
781 unsigned char *buffer;
782 unsigned int buffer_len;
783 PRInt32 temp;
784 SECItem cert_item;
785
786 /* Turn off stateless session resumption if the client sends a
787 * SessionTicket extension, even if the extension turns out to be
788 * malformed (ss->sec.ci.sid is non-NULL when doing session
789 * renegotiation.)
790 */
791 if (ss->sec.ci.sid != NULL) {
792 ss->sec.uncache(ss->sec.ci.sid);
793 ssl_FreeSID(ss->sec.ci.sid);
794 ss->sec.ci.sid = NULL;
795 }
796
797 extension_data.data = data->data; /* Keep a copy for future use. */
798 extension_data.len = data->len;
799
800 if (ssl3_ParseEncryptedSessionTicket(ss, data, &enc_session_ticket)
801 != SECSuccess)
802 return SECFailure;
803
804 /* Get session ticket keys. */
805 if (ss->opt.bypassPKCS11) {
806 rv = ssl3_GetSessionTicketKeys(&aes_key, &aes_key_length,
807 &mac_key, &mac_key_length);
808 } else {
809 rv = ssl3_GetSessionTicketKeysPKCS11(ss, &aes_key_pkcs11,
810 &mac_key_pkcs11);
811 }
812 if (rv != SECSuccess) {
813 SSL_DBG(("%d: SSL[%d]: Unable to get/generate session ticket keys.",
814 SSL_GETPID(), ss->fd));
815 goto loser;
816 }
817
818 /* If the ticket sent by the client was generated under a key different
819 * from the one we have, bypass ticket processing.
820 */
821 if (PORT_Memcmp(enc_session_ticket.key_name, key_name,
822 SESS_TICKET_KEY_NAME_LEN) != 0) {
823 SSL_DBG(("%d: SSL[%d]: Session ticket key_name sent mismatch.",
824 SSL_GETPID(), ss->fd));
825 goto no_ticket;
826 }
827
828 /* Verify the MAC on the ticket. MAC verification may also
829 * fail if the MAC key has been recently refreshed.
830 */
831 if (ss->opt.bypassPKCS11) {
832 hmac_ctx = (HMACContext *)hmac_ctx_buf;
833 hashObj = HASH_GetRawHashObject(HASH_AlgSHA256);
834 if (HMAC_Init(hmac_ctx, hashObj, mac_key,
835 sizeof(session_ticket_mac_key), PR_FALSE) != SECSuccess)
836 goto no_ticket;
837 HMAC_Begin(hmac_ctx);
838 HMAC_Update(hmac_ctx, extension_data.data,
839 extension_data.len - TLS_EX_SESS_TICKET_MAC_LENGTH);
840 if (HMAC_Finish(hmac_ctx, computed_mac, &computed_mac_length,
841 sizeof(computed_mac)) != SECSuccess)
842 goto no_ticket;
843 } else {
844 SECItem macParam;
845 macParam.data = NULL;
846 macParam.len = 0;
847 hmac_ctx_pkcs11 = PK11_CreateContextBySymKey(macMech,
848 CKA_SIGN, mac_key_pkcs11, &macParam);
849 if (!hmac_ctx_pkcs11) {
850 SSL_DBG(("%d: SSL[%d]: Unable to create HMAC context: %d.",
851 SSL_GETPID(), ss->fd, PORT_GetError()));
852 goto no_ticket;
853 } else {
854 SSL_DBG(("%d: SSL[%d]: Successfully created HMAC context.",
855 SSL_GETPID(), ss->fd));
856 }
857 rv = PK11_DigestBegin(hmac_ctx_pkcs11);
858 rv = PK11_DigestOp(hmac_ctx_pkcs11, extension_data.data,
859 extension_data.len - TLS_EX_SESS_TICKET_MAC_LENGTH);
860 if (rv != SECSuccess) {
861 PK11_DestroyContext(hmac_ctx_pkcs11, PR_TRUE);
862 goto no_ticket;
863 }
864 rv = PK11_DigestFinal(hmac_ctx_pkcs11, computed_mac,
865 &computed_mac_length, sizeof(computed_mac));
866 PK11_DestroyContext(hmac_ctx_pkcs11, PR_TRUE);
867 if (rv != SECSuccess)
868 goto no_ticket;
869 }
870 if (NSS_SecureMemcmp(computed_mac, enc_session_ticket.mac,
871 computed_mac_length) != 0) {
872 SSL_DBG(("%d: SSL[%d]: Session ticket MAC mismatch.",
873 SSL_GETPID(), ss->fd));
874 goto no_ticket;
875 }
876
877 /* We ignore key_name for now.
878 * This is ok as MAC verification succeeded.
879 */
880
881 /* Decrypt the ticket. */
882
883 /* Plaintext is shorter than the ciphertext due to padding. */
884 decrypted_state = SECITEM_AllocItem(NULL, NULL,
885 enc_session_ticket.encrypted_state.len);
886
887 if (ss->opt.bypassPKCS11) {
888 aes_ctx = (AESContext *)aes_ctx_buf;
889 rv = AES_InitContext(aes_ctx, aes_key,
890 sizeof(session_ticket_enc_key), enc_session_ticket.iv,
891 NSS_AES_CBC, 0,AES_BLOCK_SIZE);
892 if (rv != SECSuccess) {
893 SSL_DBG(("%d: SSL[%d]: Unable to create AES context.",
894 SSL_GETPID(), ss->fd));
895 goto no_ticket;
896 }
897
898 rv = AES_Decrypt(aes_ctx, decrypted_state->data,
899 &decrypted_state->len, decrypted_state->len,
900 enc_session_ticket.encrypted_state.data,
901 enc_session_ticket.encrypted_state.len);
902 if (rv != SECSuccess)
903 goto no_ticket;
904 } else {
905 SECItem ivItem;
906 ivItem.data = enc_session_ticket.iv;
907 ivItem.len = AES_BLOCK_SIZE;
908 aes_ctx_pkcs11 = PK11_CreateContextBySymKey(cipherMech,
909 CKA_DECRYPT, aes_key_pkcs11, &ivItem);
910 if (!aes_ctx_pkcs11) {
911 SSL_DBG(("%d: SSL[%d]: Unable to create AES context.",
912 SSL_GETPID(), ss->fd));
913 goto no_ticket;
914 }
915
916 rv = PK11_CipherOp(aes_ctx_pkcs11, decrypted_state->data,
917 (int *)&decrypted_state->len, decrypted_state->len,
918 enc_session_ticket.encrypted_state.data,
919 enc_session_ticket.encrypted_state.len);
920 PK11_Finalize(aes_ctx_pkcs11);
921 PK11_DestroyContext(aes_ctx_pkcs11, PR_TRUE);
922 if (rv != SECSuccess)
923 goto no_ticket;
924 }
925
926 /* Check padding. */
927 padding_length =
928 (PRUint32)decrypted_state->data[decrypted_state->len - 1];
929 if (padding_length == 0 || padding_length > AES_BLOCK_SIZE)
930 goto no_ticket;
931
932 padding = &decrypted_state->data[decrypted_state->len - padding_length];
933 for (i = 0; i < padding_length; i++, padding++) {
934 if (padding_length != (PRUint32)*padding)
935 goto no_ticket;
936 }
937
938 /* Deserialize session state. */
939 buffer = decrypted_state->data;
940 buffer_len = decrypted_state->len;
941
942 parsed_session_ticket = PORT_ZAlloc(sizeof(SessionTicket));
943 if (parsed_session_ticket == NULL) {
944 rv = SECFailure;
945 goto loser;
946 }
947
948 /* Read ticket_version (which is ignored for now.) */
949 temp = ssl3_ConsumeHandshakeNumber(ss, 2, &buffer, &buffer_len);
950 if (temp < 0) goto no_ticket;
951 parsed_session_ticket->ticket_version = (SSL3ProtocolVersion)temp;
952
953 /* Read SSLVersion. */
954 temp = ssl3_ConsumeHandshakeNumber(ss, 2, &buffer, &buffer_len);
955 if (temp < 0) goto no_ticket;
956 parsed_session_ticket->ssl_version = (SSL3ProtocolVersion)temp;
957
958 /* Read cipher_suite. */
959 temp = ssl3_ConsumeHandshakeNumber(ss, 2, &buffer, &buffer_len);
960 if (temp < 0) goto no_ticket;
961 parsed_session_ticket->cipher_suite = (ssl3CipherSuite)temp;
962
963 /* Read compression_method. */
964 temp = ssl3_ConsumeHandshakeNumber(ss, 1, &buffer, &buffer_len);
965 if (temp < 0) goto no_ticket;
966 parsed_session_ticket->compression_method = (SSLCompressionMethod)temp;
967
968 /* Read cipher spec parameters. */
969 temp = ssl3_ConsumeHandshakeNumber(ss, 1, &buffer, &buffer_len);
970 if (temp < 0) goto no_ticket;
971 parsed_session_ticket->authAlgorithm = (SSLSignType)temp;
972 temp = ssl3_ConsumeHandshakeNumber(ss, 4, &buffer, &buffer_len);
973 if (temp < 0) goto no_ticket;
974 parsed_session_ticket->authKeyBits = (PRUint32)temp;
975 temp = ssl3_ConsumeHandshakeNumber(ss, 1, &buffer, &buffer_len);
976 if (temp < 0) goto no_ticket;
977 parsed_session_ticket->keaType = (SSLKEAType)temp;
978 temp = ssl3_ConsumeHandshakeNumber(ss, 4, &buffer, &buffer_len);
979 if (temp < 0) goto no_ticket;
980 parsed_session_ticket->keaKeyBits = (PRUint32)temp;
981
982 /* Read wrapped master_secret. */
983 temp = ssl3_ConsumeHandshakeNumber(ss, 1, &buffer, &buffer_len);
984 if (temp < 0) goto no_ticket;
985 parsed_session_ticket->ms_is_wrapped = (PRBool)temp;
986
987 temp = ssl3_ConsumeHandshakeNumber(ss, 1, &buffer, &buffer_len);
988 if (temp < 0) goto no_ticket;
989 parsed_session_ticket->exchKeyType = (SSL3KEAType)temp;
990
991 temp = ssl3_ConsumeHandshakeNumber(ss, 4, &buffer, &buffer_len);
992 if (temp < 0) goto no_ticket;
993 parsed_session_ticket->msWrapMech = (CK_MECHANISM_TYPE)temp;
994
995 temp = ssl3_ConsumeHandshakeNumber(ss, 2, &buffer, &buffer_len);
996 if (temp < 0) goto no_ticket;
997 parsed_session_ticket->ms_length = (PRUint16)temp;
998 if (parsed_session_ticket->ms_length == 0 || /* sanity check MS. */
999 parsed_session_ticket->ms_length >
1000 sizeof(parsed_session_ticket->master_secret))
1001 goto no_ticket;
1002
1003 /* Allow for the wrapped master secret to be longer. */
1004 if (buffer_len < sizeof(SSL3_MASTER_SECRET_LENGTH))
1005 goto no_ticket;
1006 PORT_Memcpy(parsed_session_ticket->master_secret, buffer,
1007 parsed_session_ticket->ms_length);
1008 buffer += parsed_session_ticket->ms_length;
1009 buffer_len -= parsed_session_ticket->ms_length;
1010
1011 /* Read client_identity */
1012 temp = ssl3_ConsumeHandshakeNumber(ss, 1, &buffer, &buffer_len);
1013 if (temp < 0)
1014 goto no_ticket;
1015 parsed_session_ticket->client_identity.client_auth_type =
1016 (ClientAuthenticationType)temp;
1017 switch(parsed_session_ticket->client_identity.client_auth_type) {
1018 case CLIENT_AUTH_ANONYMOUS:
1019 break;
1020 case CLIENT_AUTH_CERTIFICATE:
1021 rv = ssl3_ConsumeHandshakeVariable(ss, &cert_item, 3,
1022 &buffer, &buffer_len);
1023 if (rv != SECSuccess) goto no_ticket;
1024 rv = SECITEM_CopyItem(NULL, &parsed_session_ticket->peer_cert,
1025 &cert_item);
1026 if (rv != SECSuccess) goto no_ticket;
1027 break;
1028 default:
1029 goto no_ticket;
1030 }
1031 /* Read timestamp. */
1032 temp = ssl3_ConsumeHandshakeNumber(ss, 4, &buffer, &buffer_len);
1033 if (temp < 0)
1034 goto no_ticket;
1035 parsed_session_ticket->timestamp = (PRUint32)temp;
1036
1037 /* Done parsing. Check that all bytes have been consumed. */
1038 if (buffer_len != padding_length)
1039 goto no_ticket;
1040
1041 /* Use the ticket if it has not expired, otherwise free the allocated
1042 * memory since the ticket is of no use.
1043 */
1044 if (parsed_session_ticket->timestamp != 0 &&
1045 parsed_session_ticket->timestamp +
1046 TLS_EX_SESS_TICKET_LIFETIME_HINT > ssl_Time()) {
1047
1048 sid = ssl3_NewSessionID(ss, PR_TRUE);
1049 if (sid == NULL) {
1050 rv = SECFailure;
1051 goto loser;
1052 }
1053
1054 /* Copy over parameters. */
1055 sid->version = parsed_session_ticket->ssl_version;
1056 sid->u.ssl3.cipherSuite = parsed_session_ticket->cipher_suite;
1057 sid->u.ssl3.compression = parsed_session_ticket->compression_method;
1058 sid->authAlgorithm = parsed_session_ticket->authAlgorithm;
1059 sid->authKeyBits = parsed_session_ticket->authKeyBits;
1060 sid->keaType = parsed_session_ticket->keaType;
1061 sid->keaKeyBits = parsed_session_ticket->keaKeyBits;
1062
1063 /* Copy master secret. */
1064 if (ss->opt.bypassPKCS11 &&
1065 parsed_session_ticket->ms_is_wrapped)
1066 goto no_ticket;
1067 if (parsed_session_ticket->ms_length >
1068 sizeof(sid->u.ssl3.keys.wrapped_master_secret))
1069 goto no_ticket;
1070 PORT_Memcpy(sid->u.ssl3.keys.wrapped_master_secret,
1071 parsed_session_ticket->master_secret,
1072 parsed_session_ticket->ms_length);
1073 sid->u.ssl3.keys.wrapped_master_secret_len =
1074 parsed_session_ticket->ms_length;
1075 sid->u.ssl3.exchKeyType = parsed_session_ticket->exchKeyType;
1076 sid->u.ssl3.masterWrapMech = parsed_session_ticket->msWrapMech;
1077 sid->u.ssl3.keys.msIsWrapped =
1078 parsed_session_ticket->ms_is_wrapped;
1079 sid->u.ssl3.masterValid = PR_TRUE;
1080 sid->u.ssl3.keys.resumable = PR_TRUE;
1081
1082 /* Copy over client cert from session ticket if there is one. */
1083 if (parsed_session_ticket->peer_cert.data != NULL) {
1084 if (sid->peerCert != NULL)
1085 CERT_DestroyCertificate(sid->peerCert);
1086 sid->peerCert = CERT_NewTempCertificate(ss->dbHandle,
1087 &parsed_session_ticket->peer_cert, NULL, PR_FALSE, PR_TRUE);
1088 if (sid->peerCert == NULL) {
1089 rv = SECFailure;
1090 goto loser;
1091 }
1092 }
1093 ss->statelessResume = PR_TRUE;
1094 ss->sec.ci.sid = sid;
1095 }
1096 }
1097
1098 if (0) {
1099 no_ticket:
1100 SSL_DBG(("%d: SSL[%d]: Session ticket parsing failed.",
1101 SSL_GETPID(), ss->fd));
1102 ssl3stats = SSL_GetStatistics();
1103 SSL_AtomicIncrementLong(& ssl3stats->hch_sid_ticket_parse_failures );
1104 if (sid) {
1105 ssl_FreeSID(sid);
1106 sid = NULL;
1107 }
1108 }
1109 rv = SECSuccess;
1110
1111 loser:
1112 if (decrypted_state != NULL) {
1113 SECITEM_FreeItem(decrypted_state, PR_TRUE);
1114 decrypted_state = NULL;
1115 }
1116
1117 if (parsed_session_ticket != NULL) {
1118 if (parsed_session_ticket->peer_cert.data) {
1119 SECITEM_FreeItem(&parsed_session_ticket->peer_cert, PR_FALSE);
1120 }
1121 PORT_ZFree(parsed_session_ticket, sizeof(SessionTicket));
1122 }
1123
1124 return rv;
1125 }
1126
1127 /*
1128 * Read bytes. Using this function means the SECItem structure
1129 * cannot be freed. The caller is expected to call this function
1130 * on a shallow copy of the structure.
1131 */
1132 static SECStatus
1133 ssl3_ConsumeFromItem(SECItem *item, unsigned char **buf, PRUint32 bytes)
1134 {
1135 if (bytes > item->len)
1136 return SECFailure;
1137
1138 *buf = item->data;
1139 item->data += bytes;
1140 item->len -= bytes;
1141 return SECSuccess;
1142 }
1143
1144 static SECStatus
1145 ssl3_ParseEncryptedSessionTicket(sslSocket *ss, SECItem *data,
1146 EncryptedSessionTicket *enc_session_ticket)
1147 {
1148 if (ssl3_ConsumeFromItem(data, &enc_session_ticket->key_name,
1149 SESS_TICKET_KEY_NAME_LEN) != SECSuccess)
1150 return SECFailure;
1151 if (ssl3_ConsumeFromItem(data, &enc_session_ticket->iv,
1152 AES_BLOCK_SIZE) != SECSuccess)
1153 return SECFailure;
1154 if (ssl3_ConsumeHandshakeVariable(ss, &enc_session_ticket->encrypted_state,
1155 2, &data->data, &data->len) != SECSuccess)
1156 return SECFailure;
1157 if (ssl3_ConsumeFromItem(data, &enc_session_ticket->mac,
1158 TLS_EX_SESS_TICKET_MAC_LENGTH) != SECSuccess)
1159 return SECFailure;
1160 if (data->len != 0) /* Make sure that we have consumed all bytes. */
1161 return SECFailure;
1162
1163 return SECSuccess;
1164 }
1165
1166 /* go through hello extensions in buffer "b".
1167 * For each one, find the extension handler in the table, and
1168 * if present, invoke that handler.
1169 * Servers ignore any extensions with unknown extension types.
1170 * Clients reject any extensions with unadvertised extension types.
1171 */
1172 SECStatus
1173 ssl3_HandleHelloExtensions(sslSocket *ss, SSL3Opaque **b, PRUint32 *length)
1174 {
1175 const ssl3HelloExtensionHandler * handlers =
1176 ss->sec.isServer ? clientHelloHandlers : serverHelloHandlers;
1177
1178 while (*length) {
1179 const ssl3HelloExtensionHandler * handler;
1180 SECStatus rv;
1181 PRInt32 extension_type;
1182 SECItem extension_data;
1183
1184 /* Get the extension's type field */
1185 extension_type = ssl3_ConsumeHandshakeNumber(ss, 2, b, length);
1186 if (extension_type < 0) /* failure to decode extension_type */
1187 return SECFailure; /* alert already sent */
1188
1189 /* get the data for this extension, so we can pass it or skip it. */
1190 rv = ssl3_ConsumeHandshakeVariable(ss, &extension_data, 2, b, length);
1191 if (rv != SECSuccess)
1192 return rv;
1193
1194 /* Check whether the server sent an extension which was not advertised
1195 * in the ClientHello.
1196 */
1197 if (!ss->sec.isServer &&
1198 !ssl3_ClientExtensionAdvertised(ss, extension_type))
1199 return SECFailure; /* TODO: send unsupported_extension alert */
1200
1201 /* Check whether an extension has been sent multiple times. */
1202 if (ssl3_ExtensionNegotiated(ss, extension_type))
1203 return SECFailure;
1204
1205 /* find extension_type in table of Hello Extension Handlers */
1206 for (handler = handlers; handler->ex_type >= 0; handler++) {
1207 /* if found, call this handler */
1208 if (handler->ex_type == extension_type) {
1209 rv = (*handler->ex_handler)(ss, (PRUint16)extension_type,
1210 &extension_data);
1211 /* Ignore this result */
1212 /* Treat all bad extensions as unrecognized types. */
1213 break;
1214 }
1215 }
1216 }
1217 return SECSuccess;
1218 }
1219
1220 /* Add a callback function to the table of senders of server hello extensions.
1221 */
1222 SECStatus
1223 ssl3_RegisterServerHelloExtensionSender(sslSocket *ss, PRUint16 ex_type,
1224 ssl3HelloExtensionSenderFunc cb)
1225 {
1226 int i;
1227 ssl3HelloExtensionSender *sender = &ss->xtnData.serverSenders[0];
1228
1229 for (i = 0; i < MAX_EXTENSIONS; ++i, ++sender) {
1230 if (!sender->ex_sender) {
1231 sender->ex_type = ex_type;
1232 sender->ex_sender = cb;
1233 return SECSuccess;
1234 }
1235 /* detect duplicate senders */
1236 PORT_Assert(sender->ex_type != ex_type);
1237 if (sender->ex_type == ex_type) {
1238 /* duplicate */
1239 break;
1240 }
1241 }
1242 PORT_Assert(i < MAX_EXTENSIONS); /* table needs to grow */
1243 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
1244 return SECFailure;
1245 }
1246
1247 /* call each of the extension senders and return the accumulated length */
1248 PRInt32
1249 ssl3_CallHelloExtensionSenders(sslSocket *ss, PRBool append, PRUint32 maxBytes,
1250 const ssl3HelloExtensionSender *sender)
1251 {
1252 PRInt32 total_exten_len = 0;
1253 int i;
1254
1255 if (!sender)
1256 sender = &clientHelloSenders[0];
1257
1258 for (i = 0; i < MAX_EXTENSIONS; ++i, ++sender) {
1259 if (sender->ex_sender) {
1260 PRInt32 extLen = (*sender->ex_sender)(ss, append, maxBytes);
1261 if (extLen < 0)
1262 return -1;
1263 maxBytes -= extLen;
1264 total_exten_len += extLen;
1265 }
1266 }
1267 return total_exten_len;
1268 }
OLDNEW
« no previous file with comments | « net/third_party/nss/ssl/ssl3ecc.c ('k') | net/third_party/nss/ssl/ssl3gthr.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698