4 * ***** BEGIN LICENSE BLOCK *****
5 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
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/
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
17 * The Original Code is the Netscape security libraries.
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.
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.
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.
41 * ***** END LICENSE BLOCK ***** */
43 /* TLS extension code moved here from ssl3ecc.c */
44 /* $Id: ssl3ext.c,v 1.3 2008/10/06 22:04:15 nelson%bolyard.com Exp $ */
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
;
58 static unsigned char session_ticket_enc_key
[32];
59 static unsigned char session_ticket_mac_key
[SHA256_LENGTH
];
61 static PRBool session_ticket_keys_initialized
= PR_FALSE
;
62 static PRCallOnceType generate_session_keys_once
;
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
,
70 static SECStatus
ssl3_AppendNumberToItem(SECItem
*item
, PRUint32 num
,
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
);
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.
84 ssl3_AppendToItem(SECItem
*item
, const unsigned char *buf
, PRUint32 bytes
)
86 if (bytes
> item
->len
)
89 PORT_Memcpy(item
->data
, buf
, bytes
);
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.
101 ssl3_AppendNumberToItem(SECItem
*item
, PRUint32 num
, PRInt32 lenSize
)
109 *p
++ = (uint8
) (num
>> 24);
111 *p
++ = (uint8
) (num
>> 16);
113 *p
++ = (uint8
) (num
>> 8);
117 rv
= ssl3_AppendToItem(item
, &b
[0], lenSize
);
121 static SECStatus
ssl3_SessionTicketShutdown(void* appData
, void* nssData
)
123 if (session_ticket_enc_key_pkcs11
) {
124 PK11_FreeSymKey(session_ticket_enc_key_pkcs11
);
125 session_ticket_enc_key_pkcs11
= NULL
;
127 if (session_ticket_mac_key_pkcs11
) {
128 PK11_FreeSymKey(session_ticket_mac_key_pkcs11
);
129 session_ticket_mac_key_pkcs11
= NULL
;
131 PORT_Memset(&generate_session_keys_once
, 0,
132 sizeof(generate_session_keys_once
));
138 ssl3_GenerateSessionTicketKeysPKCS11(void *data
)
141 sslSocket
*ss
= (sslSocket
*)data
;
142 SECKEYPrivateKey
*svrPrivKey
= ss
->serverCerts
[kt_rsa
].SERVERKEY
;
143 SECKEYPublicKey
*svrPubKey
= ss
->serverCerts
[kt_rsa
].serverKeyPair
->pubKey
;
145 if (svrPrivKey
== NULL
|| svrPubKey
== NULL
) {
146 SSL_DBG(("%d: SSL[%d]: Pub or priv key(s) is NULL.",
147 SSL_GETPID(), ss
->fd
));
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
))
159 rv
= NSS_RegisterShutdown(ssl3_SessionTicketShutdown
, NULL
);
160 if (rv
!= SECSuccess
)
166 ssl3_SessionTicketShutdown(NULL
, NULL
);
171 ssl3_GetSessionTicketKeysPKCS11(sslSocket
*ss
, PK11SymKey
**aes_key
,
172 PK11SymKey
**mac_key
)
174 if (PR_CallOnceWithArg(&generate_session_keys_once
,
175 ssl3_GenerateSessionTicketKeysPKCS11
, ss
) != PR_SUCCESS
)
178 if (session_ticket_enc_key_pkcs11
== NULL
||
179 session_ticket_mac_key_pkcs11
== NULL
)
182 *aes_key
= session_ticket_enc_key_pkcs11
;
183 *mac_key
= session_ticket_mac_key_pkcs11
;
188 ssl3_GenerateSessionTicketKeys(void)
190 PORT_Memcpy(key_name
, SESS_TICKET_KEY_NAME_PREFIX
,
191 sizeof(SESS_TICKET_KEY_NAME_PREFIX
));
193 if (!ssl_GetSessionTicketKeys(&key_name
[SESS_TICKET_KEY_NAME_PREFIX_LEN
],
194 session_ticket_enc_key
, session_ticket_mac_key
))
197 session_ticket_keys_initialized
= PR_TRUE
;
202 ssl3_GetSessionTicketKeys(const unsigned char **aes_key
,
203 PRUint32
*aes_key_length
, const unsigned char **mac_key
,
204 PRUint32
*mac_key_length
)
206 if (PR_CallOnce(&generate_session_keys_once
,
207 ssl3_GenerateSessionTicketKeys
) != SECSuccess
)
210 if (!session_ticket_keys_initialized
)
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
);
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.
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
},
231 { session_ticket_xtn
, &ssl3_ServerHandleSessionTicketXtn
},
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
},
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.
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
},
257 { session_ticket_xtn
, ssl3_SendSessionTicketXtn
}
261 arrayContainsExtension(const PRUint16
*array
, PRUint32 len
, PRUint16 ex_type
)
264 for (i
= 0; i
< len
; i
++) {
265 if (ex_type
== array
[i
])
272 ssl3_ExtensionNegotiated(sslSocket
*ss
, PRUint16 ex_type
) {
273 TLSExtensionData
*xtnData
= &ss
->xtnData
;
274 return arrayContainsExtension(xtnData
->negotiated
,
275 xtnData
->numNegotiated
, ex_type
);
279 ssl3_ClientExtensionAdvertised(sslSocket
*ss
, PRUint16 ex_type
) {
280 TLSExtensionData
*xtnData
= &ss
->xtnData
;
281 return arrayContainsExtension(xtnData
->advertised
,
282 xtnData
->numAdvertised
, ex_type
);
285 /* Format an SNI extension, using the name from the socket's URL,
286 * unless that name is a dotted decimal string.
289 ssl3_SendServerNameXtn(
297 /* must have a hostname */
298 if (!ss
|| !ss
->url
|| !ss
->url
[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) */
305 len
= PORT_Strlen(ss
->url
);
306 if (append
&& maxBytes
>= len
+ 9) {
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
;
331 /* handle an incoming SNI extension, by ignoring it. */
333 ssl3_HandleServerNameXtn(sslSocket
* ss
, PRUint16 ex_type
, SECItem
*data
)
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. :-) */
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.
346 ssl3_SendSessionTicketXtn(
351 PRInt32 extension_length
;
352 NewSessionTicket
*session_ticket
= NULL
;
354 /* Ignore the SessionTicket extension if processing is disabled. */
355 if (!ss
->opt
.enableSessionTickets
)
358 /* Empty extension length = extension_type (2-bytes) +
359 * length(extension_data) (2-bytes)
361 extension_length
= 4;
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.
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
;
383 if (append
&& maxBytes
>= extension_length
) {
386 rv
= ssl3_AppendHandshakeNumber(ss
, session_ticket_xtn
, 2);
387 if (rv
!= SECSuccess
)
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
;
395 rv
= ssl3_AppendHandshakeNumber(ss
, 0, 2);
397 if (rv
!= SECSuccess
)
400 if (!ss
->sec
.isServer
) {
401 TLSExtensionData
*xtnData
= &ss
->xtnData
;
402 xtnData
->advertised
[xtnData
->numAdvertised
++] = session_ticket_xtn
;
404 } else if (maxBytes
< extension_length
) {
408 return extension_length
;
411 ss
->xtnData
.ticketTimestampVerified
= PR_FALSE
;
417 * Called from ssl3_HandleFinished
420 ssl3_SendNewSessionTicket(sslSocket
*ss
)
424 NewSessionTicket ticket
;
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
;
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
];
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
];
457 CK_MECHANISM_TYPE msWrapMech
= 0; /* dummy default value,
460 SSL_TRC(3, ("%d: SSL3[%d]: send session_ticket handshake",
461 SSL_GETPID(), ss
->fd
));
463 PORT_Assert( ss
->opt
.noLocks
|| ssl_HaveXmitBufLock(ss
));
464 PORT_Assert( ss
->opt
.noLocks
|| ssl_HaveSSL3HandshakeLock(ss
));
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;
470 /* Get IV and encryption keys */
472 ivItem
.len
= sizeof(iv
);
473 rv
= PK11_GenerateRandom(iv
, sizeof(iv
));
474 if (rv
!= SECSuccess
) goto loser
;
476 if (ss
->opt
.bypassPKCS11
) {
477 rv
= ssl3_GetSessionTicketKeys(&aes_key
, &aes_key_length
,
478 &mac_key
, &mac_key_length
);
480 rv
= ssl3_GetSessionTicketKeysPKCS11(ss
, &aes_key_pkcs11
,
483 if (rv
!= SECSuccess
) goto loser
;
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
;
491 /* Extract the master secret wrapped. */
493 PORT_Memset(&sid
, 0, sizeof(sslSessionID
));
495 if (ss
->ssl3
.hs
.kea_def
->kea
== kea_ecdhe_rsa
) {
496 effectiveExchKeyType
= kt_rsa
;
498 effectiveExchKeyType
= ss
->ssl3
.hs
.kea_def
->exchKeyType
;
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
))
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
;
512 /* TODO: else send an empty ticket. */
515 ms_is_wrapped
= PR_TRUE
;
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 */
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
;
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 */
545 if (SECITEM_AllocItem(NULL
, &plaintext_item
, ciphertext_length
) == NULL
)
548 plaintext
= plaintext_item
;
551 rv
= ssl3_AppendNumberToItem(&plaintext
, TLS_EX_SESS_TICKET_VERSION
,
553 if (rv
!= SECSuccess
) goto loser
;
556 rv
= ssl3_AppendNumberToItem(&plaintext
, ss
->version
,
557 sizeof(SSL3ProtocolVersion
));
558 if (rv
!= SECSuccess
) goto loser
;
561 rv
= ssl3_AppendNumberToItem(&plaintext
, ss
->ssl3
.hs
.cipher_suite
,
562 sizeof(ssl3CipherSuite
));
563 if (rv
!= SECSuccess
) goto loser
;
566 rv
= ssl3_AppendNumberToItem(&plaintext
, ss
->ssl3
.hs
.compression
, 1);
567 if (rv
!= SECSuccess
) goto loser
;
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
;
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
;
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
;
603 rv
= ssl3_AppendNumberToItem(&plaintext
, 0, 1);
604 if (rv
!= SECSuccess
) goto loser
;
609 rv
= ssl3_AppendNumberToItem(&plaintext
, now
,
610 sizeof(ticket
.ticket_lifetime_hint
));
611 if (rv
!= SECSuccess
) goto loser
;
613 PORT_Assert(plaintext
.len
== padding_length
);
614 for (i
= 0; i
< padding_length
; i
++)
615 plaintext
.data
[i
] = (unsigned char)padding_length
;
617 if (SECITEM_AllocItem(NULL
, &ciphertext
, ciphertext_length
) == NULL
) {
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
;
629 rv
= AES_Encrypt(aes_ctx
, ciphertext
.data
, &ciphertext
.len
,
630 ciphertext
.len
, plaintext_item
.data
,
632 if (rv
!= SECSuccess
) goto loser
;
634 aes_ctx_pkcs11
= PK11_CreateContextBySymKey(cipherMech
,
635 CKA_ENCRYPT
, aes_key_pkcs11
, &ivItem
);
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
;
647 /* Convert ciphertext length to network order. */
648 length_buf
[0] = (ciphertext
.len
>> 8) & 0xff;
649 length_buf
[1] = (ciphertext
.len
) & 0xff;
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
)
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
));
668 macParam
.data
= NULL
;
670 hmac_ctx_pkcs11
= PK11_CreateContextBySymKey(macMech
,
671 CKA_SIGN
, mac_key_pkcs11
, &macParam
);
672 if (!hmac_ctx_pkcs11
)
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
;
687 /* Serialize the handshake message. */
688 rv
= ssl3_AppendHandshakeHeader(ss
, new_session_ticket
, message_length
);
689 if (rv
!= SECSuccess
) goto loser
;
691 rv
= ssl3_AppendHandshakeNumber(ss
, ticket
.ticket_lifetime_hint
,
692 sizeof(ticket
.ticket_lifetime_hint
));
693 if (rv
!= SECSuccess
) goto loser
;
695 rv
= ssl3_AppendHandshakeNumber(ss
,
696 message_length
- sizeof(ticket
.ticket_lifetime_hint
) - 2, 2);
697 if (rv
!= SECSuccess
) goto loser
;
699 rv
= ssl3_AppendHandshake(ss
, key_name
, SESS_TICKET_KEY_NAME_LEN
);
700 if (rv
!= SECSuccess
) goto loser
;
702 rv
= ssl3_AppendHandshake(ss
, iv
, sizeof(iv
));
703 if (rv
!= SECSuccess
) goto loser
;
705 rv
= ssl3_AppendHandshakeVariable(ss
, ciphertext
.data
, ciphertext
.len
, 2);
706 if (rv
!= SECSuccess
) goto loser
;
708 rv
= ssl3_AppendHandshake(ss
, computed_mac
, computed_mac_length
);
709 if (rv
!= SECSuccess
) goto loser
;
712 if (plaintext_item
.data
)
713 SECITEM_FreeItem(&plaintext_item
, PR_FALSE
);
715 SECITEM_FreeItem(&ciphertext
, PR_FALSE
);
720 /* When a client receives a SessionTicket extension a NewSessionTicket
721 * message is expected during the handshake.
724 ssl3_ClientHandleSessionTicketXtn(sslSocket
*ss
, PRUint16 ex_type
,
730 /* Keep track of negotiated extensions. */
731 ss
->xtnData
.negotiated
[ss
->xtnData
.numNegotiated
++] = ex_type
;
736 ssl3_ServerHandleSessionTicketXtn(sslSocket
*ss
, PRUint16 ex_type
,
740 SECItem
*decrypted_state
= NULL
;
741 SessionTicket
*parsed_session_ticket
= NULL
;
742 sslSessionID
*sid
= NULL
;
743 SSL3Statistics
*ssl3stats
;
745 /* Ignore the SessionTicket extension if processing is disabled. */
746 if (!ss
->opt
.enableSessionTickets
)
749 /* Keep track of negotiated extensions. */
750 ss
->xtnData
.negotiated
[ss
->xtnData
.numNegotiated
++] = ex_type
;
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.
756 if (data
->len
== 0) {
757 ss
->xtnData
.emptySessionTicket
= PR_TRUE
;
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
];
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
;
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
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
;
797 extension_data
.data
= data
->data
; /* Keep a copy for future use. */
798 extension_data
.len
= data
->len
;
800 if (ssl3_ParseEncryptedSessionTicket(ss
, data
, &enc_session_ticket
)
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
);
809 rv
= ssl3_GetSessionTicketKeysPKCS11(ss
, &aes_key_pkcs11
,
812 if (rv
!= SECSuccess
) {
813 SSL_DBG(("%d: SSL[%d]: Unable to get/generate session ticket keys.",
814 SSL_GETPID(), ss
->fd
));
818 /* If the ticket sent by the client was generated under a key different
819 * from the one we have, bypass ticket processing.
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
));
828 /* Verify the MAC on the ticket. MAC verification may also
829 * fail if the MAC key has been recently refreshed.
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
)
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
)
845 macParam
.data
= NULL
;
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()));
854 SSL_DBG(("%d: SSL[%d]: Successfully created HMAC context.",
855 SSL_GETPID(), ss
->fd
));
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
);
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
)
870 if (PORT_Memcmp(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
));
877 /* We ignore key_name for now.
878 * This is ok as MAC verification succeeded.
881 /* Decrypt the ticket. */
883 /* Plaintext is shorter than the ciphertext due to padding. */
884 decrypted_state
= SECITEM_AllocItem(NULL
, NULL
,
885 enc_session_ticket
.encrypted_state
.len
);
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
));
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
)
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
));
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
)
928 (PRUint32
)decrypted_state
->data
[decrypted_state
->len
- 1];
929 if (padding_length
== 0 || padding_length
> AES_BLOCK_SIZE
)
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
)
938 /* Deserialize session state. */
939 buffer
= decrypted_state
->data
;
940 buffer_len
= decrypted_state
->len
;
942 parsed_session_ticket
= PORT_ZAlloc(sizeof(SessionTicket
));
943 if (parsed_session_ticket
== NULL
) {
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
;
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
;
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
;
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
= (SSL3CompressionMethod
)temp
;
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
;
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
;
987 temp
= ssl3_ConsumeHandshakeNumber(ss
, 1, &buffer
, &buffer_len
);
988 if (temp
< 0) goto no_ticket
;
989 parsed_session_ticket
->exchKeyType
= (SSL3KEAType
)temp
;
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
;
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
))
1003 /* Allow for the wrapped master secret to be longer. */
1004 if (buffer_len
< sizeof(SSL3_MASTER_SECRET_LENGTH
))
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
;
1011 /* Read client_identity */
1012 temp
= ssl3_ConsumeHandshakeNumber(ss
, 1, &buffer
, &buffer_len
);
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
:
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
,
1026 if (rv
!= SECSuccess
) goto no_ticket
;
1031 /* Read timestamp. */
1032 temp
= ssl3_ConsumeHandshakeNumber(ss
, 4, &buffer
, &buffer_len
);
1035 parsed_session_ticket
->timestamp
= (PRUint32
)temp
;
1037 /* Done parsing. Check that all bytes have been consumed. */
1038 if (buffer_len
!= padding_length
)
1041 /* Use the ticket if it has not expired, otherwise free the allocated
1042 * memory since the ticket is of no use.
1044 if (parsed_session_ticket
->timestamp
!= 0 &&
1045 parsed_session_ticket
->timestamp
+
1046 TLS_EX_SESS_TICKET_LIFETIME_HINT
> ssl_Time()) {
1048 sid
= ssl3_NewSessionID(ss
, PR_TRUE
);
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
;
1063 /* Copy master secret. */
1064 if (ss
->opt
.bypassPKCS11
&&
1065 parsed_session_ticket
->ms_is_wrapped
)
1067 if (parsed_session_ticket
->ms_length
>
1068 sizeof(sid
->u
.ssl3
.keys
.wrapped_master_secret
))
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
;
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
) {
1093 ss
->statelessResume
= PR_TRUE
;
1094 ss
->sec
.ci
.sid
= sid
;
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
);
1112 if (decrypted_state
!= NULL
) {
1113 SECITEM_FreeItem(decrypted_state
, PR_TRUE
);
1114 decrypted_state
= NULL
;
1117 if (parsed_session_ticket
!= NULL
) {
1118 if (parsed_session_ticket
->peer_cert
.data
) {
1119 SECITEM_FreeItem(&parsed_session_ticket
->peer_cert
, PR_FALSE
);
1121 PORT_ZFree(parsed_session_ticket
, sizeof(SessionTicket
));
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.
1133 ssl3_ConsumeFromItem(SECItem
*item
, unsigned char **buf
, PRUint32 bytes
)
1135 if (bytes
> item
->len
)
1139 item
->data
+= bytes
;
1145 ssl3_ParseEncryptedSessionTicket(sslSocket
*ss
, SECItem
*data
,
1146 EncryptedSessionTicket
*enc_session_ticket
)
1148 if (ssl3_ConsumeFromItem(data
, &enc_session_ticket
->key_name
,
1149 SESS_TICKET_KEY_NAME_LEN
) != SECSuccess
)
1151 if (ssl3_ConsumeFromItem(data
, &enc_session_ticket
->iv
,
1152 AES_BLOCK_SIZE
) != SECSuccess
)
1154 if (ssl3_ConsumeHandshakeVariable(ss
, &enc_session_ticket
->encrypted_state
,
1155 2, &data
->data
, &data
->len
) != SECSuccess
)
1157 if (ssl3_ConsumeFromItem(data
, &enc_session_ticket
->mac
,
1158 TLS_EX_SESS_TICKET_MAC_LENGTH
) != SECSuccess
)
1160 if (data
->len
!= 0) /* Make sure that we have consumed all bytes. */
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.
1173 ssl3_HandleHelloExtensions(sslSocket
*ss
, SSL3Opaque
**b
, PRUint32
*length
)
1175 const ssl3HelloExtensionHandler
* handlers
=
1176 ss
->sec
.isServer
? clientHelloHandlers
: serverHelloHandlers
;
1179 const ssl3HelloExtensionHandler
* handler
;
1181 PRInt32 extension_type
;
1182 SECItem extension_data
;
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 */
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
)
1194 /* Check whether the server sent an extension which was not advertised
1195 * in the ClientHello.
1197 if (!ss
->sec
.isServer
&&
1198 !ssl3_ClientExtensionAdvertised(ss
, extension_type
))
1199 return SECFailure
; /* TODO: send unsupported_extension alert */
1201 /* Check whether an extension has been sent multiple times. */
1202 if (ssl3_ExtensionNegotiated(ss
, extension_type
))
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
,
1211 /* Ignore this result */
1212 /* Treat all bad extensions as unrecognized types. */
1220 /* Add a callback function to the table of senders of server hello extensions.
1223 ssl3_RegisterServerHelloExtensionSender(sslSocket
*ss
, PRUint16 ex_type
,
1224 ssl3HelloExtensionSenderFunc cb
)
1227 ssl3HelloExtensionSender
*sender
= &ss
->xtnData
.serverSenders
[0];
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
;
1235 /* detect duplicate senders */
1236 PORT_Assert(sender
->ex_type
!= ex_type
);
1237 if (sender
->ex_type
== ex_type
) {
1242 PORT_Assert(i
< MAX_EXTENSIONS
); /* table needs to grow */
1243 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE
);
1247 /* call each of the extension senders and return the accumulated length */
1249 ssl3_CallHelloExtensionSenders(sslSocket
*ss
, PRBool append
, PRUint32 maxBytes
,
1250 const ssl3HelloExtensionSender
*sender
)
1252 PRInt32 total_exten_len
= 0;
1256 sender
= &clientHelloSenders
[0];
1258 for (i
= 0; i
< MAX_EXTENSIONS
; ++i
, ++sender
) {
1259 if (sender
->ex_sender
) {
1260 PRInt32 extLen
= (*sender
->ex_sender
)(ss
, append
, maxBytes
);
1264 total_exten_len
+= extLen
;
1267 return total_exten_len
;