ssl3ext.c revision c2e0dbddbe15c98d52c4786dac06cb8952a8ae6d
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * SSL3 Protocol
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * This Source Code Form is subject to the terms of the Mozilla Public
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * License, v. 2.0. If a copy of the MPL was not distributed with this
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* TLS extension code moved here from ssl3ecc.c */
9c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)/* $Id$ */
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "nssrenam.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "nss.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ssl.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sslimpl.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sslproto.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "pk11pub.h"
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#ifdef NO_PKCS11_BYPASS
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "blapit.h"
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#else
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "blapi.h"
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "prinit.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static unsigned char  key_name[SESS_TICKET_KEY_NAME_LEN];
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static PK11SymKey    *session_ticket_enc_key_pkcs11 = NULL;
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static PK11SymKey    *session_ticket_mac_key_pkcs11 = NULL;
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#ifndef NO_PKCS11_BYPASS
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static unsigned char  session_ticket_enc_key[AES_256_KEY_LENGTH];
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static unsigned char  session_ticket_mac_key[SHA256_LENGTH];
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static PRBool         session_ticket_keys_initialized = PR_FALSE;
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static PRCallOnceType generate_session_keys_once;
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* forward static function declarations */
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static SECStatus ssl3_ParseEncryptedSessionTicket(sslSocket *ss,
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SECItem *data, EncryptedSessionTicket *enc_session_ticket);
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static SECStatus ssl3_AppendToItem(SECItem *item, const unsigned char *buf,
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PRUint32 bytes);
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static SECStatus ssl3_AppendNumberToItem(SECItem *item, PRUint32 num,
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PRInt32 lenSize);
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static SECStatus ssl3_GetSessionTicketKeysPKCS11(sslSocket *ss,
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PK11SymKey **aes_key, PK11SymKey **mac_key);
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#ifndef NO_PKCS11_BYPASS
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static SECStatus ssl3_GetSessionTicketKeys(const unsigned char **aes_key,
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PRUint32 *aes_key_length, const unsigned char **mac_key,
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PRUint32 *mac_key_length);
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static PRInt32 ssl3_SendRenegotiationInfoXtn(sslSocket * ss,
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PRBool append, PRUint32 maxBytes);
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static SECStatus ssl3_HandleRenegotiationInfoXtn(sslSocket *ss,
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PRUint16 ex_type, SECItem *data);
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static SECStatus ssl3_ClientHandleNextProtoNegoXtn(sslSocket *ss,
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			PRUint16 ex_type, SECItem *data);
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static SECStatus ssl3_ServerHandleNextProtoNegoXtn(sslSocket *ss,
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			PRUint16 ex_type, SECItem *data);
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static PRInt32 ssl3_ClientSendNextProtoNegoXtn(sslSocket *ss, PRBool append,
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					       PRUint32 maxBytes);
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static PRInt32 ssl3_SendUseSRTPXtn(sslSocket *ss, PRBool append,
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PRUint32 maxBytes);
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static SECStatus ssl3_HandleUseSRTPXtn(sslSocket * ss, PRUint16 ex_type,
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SECItem *data);
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static SECStatus ssl3_ClientHandleChannelIDXtn(sslSocket *ss,
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    PRUint16 ex_type, SECItem *data);
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static PRInt32 ssl3_ClientSendChannelIDXtn(sslSocket *ss, PRBool append,
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    PRUint32 maxBytes);
68c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static SECStatus ssl3_ServerSendStatusRequestXtn(sslSocket * ss,
69c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    PRBool      append, PRUint32    maxBytes);
70c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static SECStatus ssl3_ServerHandleStatusRequestXtn(sslSocket *ss,
71c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    PRUint16 ex_type, SECItem *data);
72c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static SECStatus ssl3_ClientHandleStatusRequestXtn(sslSocket *ss,
73c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                                  PRUint16 ex_type,
74c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                                  SECItem *data);
75c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static PRInt32 ssl3_ClientSendStatusRequestXtn(sslSocket * ss, PRBool append,
76c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                              PRUint32 maxBytes);
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Write bytes.  Using this function means the SECItem structure
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * cannot be freed.  The caller is expected to call this function
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * on a shallow copy of the structure.
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static SECStatus
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ssl3_AppendToItem(SECItem *item, const unsigned char *buf, PRUint32 bytes)
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (bytes > item->len)
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return SECFailure;
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PORT_Memcpy(item->data, buf, bytes);
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    item->data += bytes;
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    item->len -= bytes;
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SECSuccess;
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Write a number in network byte order. Using this function means the
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * SECItem structure cannot be freed.  The caller is expected to call
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * this function on a shallow copy of the structure.
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static SECStatus
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ssl3_AppendNumberToItem(SECItem *item, PRUint32 num, PRInt32 lenSize)
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SECStatus rv;
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint8     b[4];
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint8 *   p = b;
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    switch (lenSize) {
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case 4:
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	*p++ = (uint8) (num >> 24);
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case 3:
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	*p++ = (uint8) (num >> 16);
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case 2:
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	*p++ = (uint8) (num >> 8);
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case 1:
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	*p = (uint8) num;
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rv = ssl3_AppendToItem(item, &b[0], lenSize);
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return rv;
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static SECStatus ssl3_SessionTicketShutdown(void* appData, void* nssData)
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (session_ticket_enc_key_pkcs11) {
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	PK11_FreeSymKey(session_ticket_enc_key_pkcs11);
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	session_ticket_enc_key_pkcs11 = NULL;
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (session_ticket_mac_key_pkcs11) {
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	PK11_FreeSymKey(session_ticket_mac_key_pkcs11);
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	session_ticket_mac_key_pkcs11 = NULL;
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PORT_Memset(&generate_session_keys_once, 0,
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	sizeof(generate_session_keys_once));
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SECSuccess;
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static PRStatus
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ssl3_GenerateSessionTicketKeysPKCS11(void *data)
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SECStatus rv;
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sslSocket *ss = (sslSocket *)data;
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SECKEYPrivateKey *svrPrivKey = ss->serverCerts[kt_rsa].SERVERKEY;
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SECKEYPublicKey *svrPubKey = ss->serverCerts[kt_rsa].serverKeyPair->pubKey;
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (svrPrivKey == NULL || svrPubKey == NULL) {
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	SSL_DBG(("%d: SSL[%d]: Pub or priv key(s) is NULL.",
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			SSL_GETPID(), ss->fd));
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	goto loser;
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Get a copy of the session keys from shared memory. */
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PORT_Memcpy(key_name, SESS_TICKET_KEY_NAME_PREFIX,
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	sizeof(SESS_TICKET_KEY_NAME_PREFIX));
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!ssl_GetSessionTicketKeysPKCS11(svrPrivKey, svrPubKey,
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    ss->pkcs11PinArg, &key_name[SESS_TICKET_KEY_NAME_PREFIX_LEN],
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    &session_ticket_enc_key_pkcs11, &session_ticket_mac_key_pkcs11))
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return PR_FAILURE;
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rv = NSS_RegisterShutdown(ssl3_SessionTicketShutdown, NULL);
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (rv != SECSuccess)
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	goto loser;
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return PR_SUCCESS;
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)loser:
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ssl3_SessionTicketShutdown(NULL, NULL);
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return PR_FAILURE;
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static SECStatus
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ssl3_GetSessionTicketKeysPKCS11(sslSocket *ss, PK11SymKey **aes_key,
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                PK11SymKey **mac_key)
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (PR_CallOnceWithArg(&generate_session_keys_once,
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    ssl3_GenerateSessionTicketKeysPKCS11, ss) != PR_SUCCESS)
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return SECFailure;
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (session_ticket_enc_key_pkcs11 == NULL ||
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	session_ticket_mac_key_pkcs11 == NULL)
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return SECFailure;
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *aes_key = session_ticket_enc_key_pkcs11;
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *mac_key = session_ticket_mac_key_pkcs11;
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SECSuccess;
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#ifndef NO_PKCS11_BYPASS
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static PRStatus
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ssl3_GenerateSessionTicketKeys(void)
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PORT_Memcpy(key_name, SESS_TICKET_KEY_NAME_PREFIX,
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	sizeof(SESS_TICKET_KEY_NAME_PREFIX));
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!ssl_GetSessionTicketKeys(&key_name[SESS_TICKET_KEY_NAME_PREFIX_LEN],
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    session_ticket_enc_key, session_ticket_mac_key))
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return PR_FAILURE;
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    session_ticket_keys_initialized = PR_TRUE;
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return PR_SUCCESS;
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static SECStatus
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ssl3_GetSessionTicketKeys(const unsigned char **aes_key,
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PRUint32 *aes_key_length, const unsigned char **mac_key,
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PRUint32 *mac_key_length)
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (PR_CallOnce(&generate_session_keys_once,
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    ssl3_GenerateSessionTicketKeys) != SECSuccess)
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return SECFailure;
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!session_ticket_keys_initialized)
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return SECFailure;
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *aes_key = session_ticket_enc_key;
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *aes_key_length = sizeof(session_ticket_enc_key);
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *mac_key = session_ticket_mac_key;
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *mac_key_length = sizeof(session_ticket_mac_key);
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SECSuccess;
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Table of handlers for received TLS hello extensions, one per extension.
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * In the second generation, this table will be dynamic, and functions
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * will be registered here.
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* This table is used by the server, to handle client hello extensions. */
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const ssl3HelloExtensionHandler clientHelloHandlers[] = {
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { ssl_server_name_xtn,        &ssl3_HandleServerNameXtn },
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef NSS_ENABLE_ECC
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { ssl_elliptic_curves_xtn,    &ssl3_HandleSupportedCurvesXtn },
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { ssl_ec_point_formats_xtn,   &ssl3_HandleSupportedPointFormatsXtn },
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { ssl_session_ticket_xtn,     &ssl3_ServerHandleSessionTicketXtn },
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { ssl_renegotiation_info_xtn, &ssl3_HandleRenegotiationInfoXtn },
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { ssl_next_proto_nego_xtn,    &ssl3_ServerHandleNextProtoNegoXtn },
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { ssl_use_srtp_xtn,           &ssl3_HandleUseSRTPXtn },
238c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    { ssl_cert_status_xtn,        &ssl3_ServerHandleStatusRequestXtn },
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { -1, NULL }
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* These two tables are used by the client, to handle server hello
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * extensions. */
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const ssl3HelloExtensionHandler serverHelloHandlersTLS[] = {
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { ssl_server_name_xtn,        &ssl3_HandleServerNameXtn },
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* TODO: add a handler for ssl_ec_point_formats_xtn */
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { ssl_session_ticket_xtn,     &ssl3_ClientHandleSessionTicketXtn },
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { ssl_renegotiation_info_xtn, &ssl3_HandleRenegotiationInfoXtn },
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { ssl_next_proto_nego_xtn,    &ssl3_ClientHandleNextProtoNegoXtn },
2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    { ssl_use_srtp_xtn,           &ssl3_HandleUseSRTPXtn },
2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    { ssl_channel_id_xtn,         &ssl3_ClientHandleChannelIDXtn },
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { ssl_cert_status_xtn,        &ssl3_ClientHandleStatusRequestXtn },
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { -1, NULL }
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const ssl3HelloExtensionHandler serverHelloHandlersSSL3[] = {
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { ssl_renegotiation_info_xtn, &ssl3_HandleRenegotiationInfoXtn },
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { -1, NULL }
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Tables of functions to format TLS hello extensions, one function per
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * extension.
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * These static tables are for the formatting of client hello extensions.
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The server's table of hello senders is dynamic, in the socket struct,
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * and sender functions are registered there.
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ssl3HelloExtensionSender clientHelloSendersTLS[SSL_MAX_EXTENSIONS] = {
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { ssl_server_name_xtn,        &ssl3_SendServerNameXtn        },
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { ssl_renegotiation_info_xtn, &ssl3_SendRenegotiationInfoXtn },
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef NSS_ENABLE_ECC
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { ssl_elliptic_curves_xtn,    &ssl3_SendSupportedCurvesXtn },
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { ssl_ec_point_formats_xtn,   &ssl3_SendSupportedPointFormatsXtn },
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { ssl_session_ticket_xtn,     &ssl3_SendSessionTicketXtn },
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { ssl_next_proto_nego_xtn,    &ssl3_ClientSendNextProtoNegoXtn },
2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    { ssl_use_srtp_xtn,           &ssl3_SendUseSRTPXtn },
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { ssl_channel_id_xtn,         &ssl3_ClientSendChannelIDXtn },
2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    { ssl_cert_status_xtn,        &ssl3_ClientSendStatusRequestXtn }
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* any extra entries will appear as { 0, NULL }    */
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ssl3HelloExtensionSender clientHelloSendersSSL3[SSL_MAX_EXTENSIONS] = {
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { ssl_renegotiation_info_xtn, &ssl3_SendRenegotiationInfoXtn }
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* any extra entries will appear as { 0, NULL }    */
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static PRBool
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)arrayContainsExtension(const PRUint16 *array, PRUint32 len, PRUint16 ex_type)
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int i;
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (i = 0; i < len; i++) {
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (ex_type == array[i])
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    return PR_TRUE;
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return PR_FALSE;
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PRBool
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ssl3_ExtensionNegotiated(sslSocket *ss, PRUint16 ex_type) {
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TLSExtensionData *xtnData = &ss->xtnData;
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return arrayContainsExtension(xtnData->negotiated,
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	                          xtnData->numNegotiated, ex_type);
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static PRBool
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ssl3_ClientExtensionAdvertised(sslSocket *ss, PRUint16 ex_type) {
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TLSExtensionData *xtnData = &ss->xtnData;
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return arrayContainsExtension(xtnData->advertised,
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	                          xtnData->numAdvertised, ex_type);
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Format an SNI extension, using the name from the socket's URL,
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * unless that name is a dotted decimal string.
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Used by client and server.
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PRInt32
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ssl3_SendServerNameXtn(sslSocket * ss, PRBool append,
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       PRUint32 maxBytes)
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SECStatus rv;
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!ss)
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    	return 0;
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!ss->sec.isServer) {
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        PRUint32 len;
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        PRNetAddr netAddr;
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        /* must have a hostname */
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!ss->url || !ss->url[0])
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return 0;
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        /* must not be an IPv4 or IPv6 address */
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (PR_SUCCESS == PR_StringToNetAddr(ss->url, &netAddr)) {
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            /* is an IP address (v4 or v6) */
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return 0;
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        len  = PORT_Strlen(ss->url);
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (append && maxBytes >= len + 9) {
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            /* extension_type */
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            rv = ssl3_AppendHandshakeNumber(ss, ssl_server_name_xtn, 2);
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if (rv != SECSuccess) return -1;
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            /* length of extension_data */
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            rv = ssl3_AppendHandshakeNumber(ss, len + 5, 2);
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if (rv != SECSuccess) return -1;
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            /* length of server_name_list */
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            rv = ssl3_AppendHandshakeNumber(ss, len + 3, 2);
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if (rv != SECSuccess) return -1;
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            /* Name Type (sni_host_name) */
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            rv = ssl3_AppendHandshake(ss,       "\0",    1);
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if (rv != SECSuccess) return -1;
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            /* HostName (length and value) */
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            rv = ssl3_AppendHandshakeVariable(ss, (PRUint8 *)ss->url, len, 2);
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if (rv != SECSuccess) return -1;
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if (!ss->sec.isServer) {
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                TLSExtensionData *xtnData = &ss->xtnData;
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                xtnData->advertised[xtnData->numAdvertised++] =
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		    ssl_server_name_xtn;
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return len + 9;
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Server side */
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (append && maxBytes >= 4) {
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rv = ssl3_AppendHandshakeNumber(ss, ssl_server_name_xtn, 2);
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (rv != SECSuccess)  return -1;
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        /* length of extension_data */
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rv = ssl3_AppendHandshakeNumber(ss, 0, 2);
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (rv != SECSuccess) return -1;
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 4;
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* handle an incoming SNI extension, by ignoring it. */
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SECStatus
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ssl3_HandleServerNameXtn(sslSocket * ss, PRUint16 ex_type, SECItem *data)
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SECItem *names = NULL;
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PRUint32 listCount = 0, namesPos = 0, i;
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TLSExtensionData *xtnData = &ss->xtnData;
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SECItem  ldata;
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PRInt32  listLenBytes = 0;
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!ss->sec.isServer) {
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        /* Verify extension_data is empty. */
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (data->data || data->len ||
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            !ssl3_ExtensionNegotiated(ss, ssl_server_name_xtn)) {
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            /* malformed or was not initiated by the client.*/
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return SECFailure;
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return SECSuccess;
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Server side - consume client data and register server sender. */
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* do not parse the data if don't have user extension handling function. */
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!ss->sniSocketConfig) {
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return SECSuccess;
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* length of server_name_list */
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    listLenBytes = ssl3_ConsumeHandshakeNumber(ss, 2, &data->data, &data->len);
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (listLenBytes == 0 || listLenBytes != data->len) {
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return SECFailure;
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ldata = *data;
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Calculate the size of the array.*/
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while (listLenBytes > 0) {
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SECItem litem;
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SECStatus rv;
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        PRInt32  type;
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        /* Name Type (sni_host_name) */
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        type = ssl3_ConsumeHandshakeNumber(ss, 1, &ldata.data, &ldata.len);
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!ldata.len) {
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return SECFailure;
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rv = ssl3_ConsumeHandshakeVariable(ss, &litem, 2, &ldata.data, &ldata.len);
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (rv != SECSuccess) {
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return SECFailure;
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        /* Adjust total length for cunsumed item, item len and type.*/
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        listLenBytes -= litem.len + 3;
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (listLenBytes > 0 && !ldata.len) {
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return SECFailure;
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        listCount += 1;
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!listCount) {
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return SECFailure;
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    names = PORT_ZNewArray(SECItem, listCount);
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!names) {
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return SECFailure;
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (i = 0;i < listCount;i++) {
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        int j;
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        PRInt32  type;
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SECStatus rv;
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        PRBool nametypePresent = PR_FALSE;
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        /* Name Type (sni_host_name) */
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        type = ssl3_ConsumeHandshakeNumber(ss, 1, &data->data, &data->len);
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        /* Check if we have such type in the list */
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        for (j = 0;j < listCount && names[j].data;j++) {
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if (names[j].type == type) {
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                nametypePresent = PR_TRUE;
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                break;
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        /* HostName (length and value) */
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rv = ssl3_ConsumeHandshakeVariable(ss, &names[namesPos], 2,
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           &data->data, &data->len);
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (rv != SECSuccess) {
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            goto loser;
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (nametypePresent == PR_FALSE) {
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            namesPos += 1;
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Free old and set the new data. */
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (xtnData->sniNameArr) {
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        PORT_Free(ss->xtnData.sniNameArr);
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xtnData->sniNameArr = names;
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xtnData->sniNameArrSize = namesPos;
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xtnData->negotiated[xtnData->numNegotiated++] = ssl_server_name_xtn;
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SECSuccess;
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)loser:
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PORT_Free(names);
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SECFailure;
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Called by both clients and servers.
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Clients sends a filled in session ticket if one is available, and otherwise
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * sends an empty ticket.  Servers always send empty tickets.
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PRInt32
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ssl3_SendSessionTicketXtn(
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			sslSocket * ss,
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			PRBool      append,
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			PRUint32    maxBytes)
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PRInt32 extension_length;
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NewSessionTicket *session_ticket = NULL;
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Ignore the SessionTicket extension if processing is disabled. */
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!ss->opt.enableSessionTickets)
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return 0;
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Empty extension length = extension_type (2-bytes) +
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * length(extension_data) (2-bytes)
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     */
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    extension_length = 4;
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* If we are a client then send a session ticket if one is availble.
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * Servers that support the extension and are willing to negotiate the
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * the extension always respond with an empty extension.
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     */
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!ss->sec.isServer) {
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	sslSessionID *sid = ss->sec.ci.sid;
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	session_ticket = &sid->u.ssl3.sessionTicket;
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (session_ticket->ticket.data) {
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    if (ss->xtnData.ticketTimestampVerified) {
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		extension_length += session_ticket->ticket.len;
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    } else if (!append &&
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		(session_ticket->ticket_lifetime_hint == 0 ||
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		(session_ticket->ticket_lifetime_hint +
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		    session_ticket->received_timestamp > ssl_Time()))) {
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		extension_length += session_ticket->ticket.len;
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		ss->xtnData.ticketTimestampVerified = PR_TRUE;
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    }
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (append && maxBytes >= extension_length) {
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	SECStatus rv;
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	/* extension_type */
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rv = ssl3_AppendHandshakeNumber(ss, ssl_session_ticket_xtn, 2);
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (rv != SECSuccess)
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    goto loser;
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (session_ticket && session_ticket->ticket.data &&
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    ss->xtnData.ticketTimestampVerified) {
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    rv = ssl3_AppendHandshakeVariable(ss, session_ticket->ticket.data,
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		session_ticket->ticket.len, 2);
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    ss->xtnData.ticketTimestampVerified = PR_FALSE;
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	} else {
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    rv = ssl3_AppendHandshakeNumber(ss, 0, 2);
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (rv != SECSuccess)
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    goto loser;
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (!ss->sec.isServer) {
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    TLSExtensionData *xtnData = &ss->xtnData;
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    xtnData->advertised[xtnData->numAdvertised++] =
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		ssl_session_ticket_xtn;
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (maxBytes < extension_length) {
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	PORT_Assert(0);
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return 0;
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return extension_length;
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) loser:
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ss->xtnData.ticketTimestampVerified = PR_FALSE;
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return -1;
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* handle an incoming Next Protocol Negotiation extension. */
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static SECStatus
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ssl3_ServerHandleNextProtoNegoXtn(sslSocket * ss, PRUint16 ex_type, SECItem *data)
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (ss->firstHsDone || data->len != 0) {
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	/* Clients MUST send an empty NPN extension, if any. */
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	PORT_SetError(SSL_ERROR_NEXT_PROTOCOL_DATA_INVALID);
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return SECFailure;
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ss->xtnData.negotiated[ss->xtnData.numNegotiated++] = ex_type;
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* TODO: server side NPN support would require calling
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * ssl3_RegisterServerHelloExtensionSender here in order to echo the
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * extension back to the client. */
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SECSuccess;
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* ssl3_ValidateNextProtoNego checks that the given block of data is valid: none
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * of the lengths may be 0 and the sum of the lengths must equal the length of
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * the block. */
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SECStatus
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ssl3_ValidateNextProtoNego(const unsigned char* data, unsigned int length)
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned int offset = 0;
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while (offset < length) {
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	unsigned int newOffset = offset + 1 + (unsigned int) data[offset];
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	/* Reject embedded nulls to protect against buggy applications that
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 * store protocol identifiers in null-terminated strings.
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 */
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (newOffset > length || data[offset] == 0) {
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    PORT_SetError(SSL_ERROR_NEXT_PROTOCOL_DATA_INVALID);
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    return SECFailure;
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	offset = newOffset;
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (offset > length) {
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	PORT_SetError(SSL_ERROR_NEXT_PROTOCOL_DATA_INVALID);
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return SECFailure;
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SECSuccess;
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static SECStatus
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ssl3_ClientHandleNextProtoNegoXtn(sslSocket *ss, PRUint16 ex_type,
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				  SECItem *data)
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SECStatus rv;
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned char resultBuffer[255];
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SECItem result = { siBuffer, resultBuffer, 0 };
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PORT_Assert(!ss->firstHsDone);
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rv = ssl3_ValidateNextProtoNego(data->data, data->len);
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (rv != SECSuccess)
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return rv;
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* ss->nextProtoCallback cannot normally be NULL if we negotiated the
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * extension. However, It is possible that an application erroneously
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * cleared the callback between the time we sent the ClientHello and now.
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     */
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PORT_Assert(ss->nextProtoCallback != NULL);
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!ss->nextProtoCallback) {
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	/* XXX Use a better error code. This is an application error, not an
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 * NSS bug. */
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return SECFailure;
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rv = ss->nextProtoCallback(ss->nextProtoArg, ss->fd, data->data, data->len,
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			       result.data, &result.len, sizeof resultBuffer);
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (rv != SECSuccess)
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return rv;
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* If the callback wrote more than allowed to |result| it has corrupted our
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * stack. */
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (result.len > sizeof resultBuffer) {
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	PORT_SetError(SEC_ERROR_OUTPUT_LEN);
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return SECFailure;
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ss->xtnData.negotiated[ss->xtnData.numNegotiated++] = ex_type;
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SECITEM_FreeItem(&ss->ssl3.nextProto, PR_FALSE);
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SECITEM_CopyItem(NULL, &ss->ssl3.nextProto, &result);
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static PRInt32
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ssl3_ClientSendNextProtoNegoXtn(sslSocket * ss, PRBool append,
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				PRUint32 maxBytes)
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PRInt32 extension_length;
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Renegotiations do not send this extension. */
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!ss->nextProtoCallback || ss->firstHsDone) {
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return 0;
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    extension_length = 4;
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (append && maxBytes >= extension_length) {
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	SECStatus rv;
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	rv = ssl3_AppendHandshakeNumber(ss, ssl_next_proto_nego_xtn, 2);
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (rv != SECSuccess)
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    goto loser;
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	rv = ssl3_AppendHandshakeNumber(ss, 0, 2);
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (rv != SECSuccess)
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    goto loser;
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	ss->xtnData.advertised[ss->xtnData.numAdvertised++] =
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		ssl_next_proto_nego_xtn;
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (maxBytes < extension_length) {
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return 0;
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return extension_length;
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)loser:
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return -1;
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static SECStatus
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ssl3_ClientHandleChannelIDXtn(sslSocket *ss, PRUint16 ex_type,
6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			     SECItem *data)
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PORT_Assert(ss->getChannelID != NULL);
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (data->len) {
6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	PORT_SetError(SSL_ERROR_BAD_CHANNEL_ID_DATA);
6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return SECFailure;
6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ss->xtnData.negotiated[ss->xtnData.numNegotiated++] = ex_type;
6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SECSuccess;
6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static PRInt32
6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ssl3_ClientSendChannelIDXtn(sslSocket * ss, PRBool append,
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			    PRUint32 maxBytes)
6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PRInt32 extension_length = 4;
6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!ss->getChannelID)
6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return 0;
6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (maxBytes < extension_length) {
6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	PORT_Assert(0);
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return 0;
6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (append) {
6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	SECStatus rv;
6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	rv = ssl3_AppendHandshakeNumber(ss, ssl_channel_id_xtn, 2);
7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (rv != SECSuccess)
7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    goto loser;
7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	rv = ssl3_AppendHandshakeNumber(ss, 0, 2);
7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (rv != SECSuccess)
7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    goto loser;
7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	ss->xtnData.advertised[ss->xtnData.numAdvertised++] =
7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		ssl_channel_id_xtn;
7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return extension_length;
7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)loser:
7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return -1;
7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
715c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static SECStatus
7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ssl3_ClientHandleStatusRequestXtn(sslSocket *ss, PRUint16 ex_type,
717c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                 SECItem *data)
7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* The echoed extension must be empty. */
7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (data->len != 0)
721c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)       return SECFailure;
7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Keep track of negotiated extensions. */
7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ss->xtnData.negotiated[ss->xtnData.numNegotiated++] = ex_type;
7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SECSuccess;
7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
729c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static PRInt32
730c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)ssl3_ServerSendStatusRequestXtn(
731c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)			sslSocket * ss,
732c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)			PRBool      append,
733c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)			PRUint32    maxBytes)
734c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles){
735c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    PRInt32 extension_length;
736c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    SECStatus rv;
737c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
738c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (!ss->certStatusArray)
739c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)	return 0;
740c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
741c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    extension_length = 2 + 2;
742c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (append && maxBytes >= extension_length) {
743c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)	/* extension_type */
744c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)	rv = ssl3_AppendHandshakeNumber(ss, ssl_cert_status_xtn, 2);
745c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)	if (rv != SECSuccess)
746c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)	    return -1;
747c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)	/* length of extension_data */
748c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)	rv = ssl3_AppendHandshakeNumber(ss, 0, 2);
749c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)	if (rv != SECSuccess)
750c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)	    return -1;
751c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
752c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
753c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return extension_length;
754c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
755c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* ssl3_ClientSendStatusRequestXtn builds the status_request extension on the
7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * client side. See RFC 4366 section 3.6. */
758c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static PRInt32
7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ssl3_ClientSendStatusRequestXtn(sslSocket * ss, PRBool append,
760c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                               PRUint32 maxBytes)
7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PRInt32 extension_length;
7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!ss->opt.enableOCSPStapling)
765c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)       return 0;
7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* extension_type (2-bytes) +
7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * length(extension_data) (2-bytes) +
7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * status_type (1) +
7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * responder_id_list length (2) +
7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * request_extensions length (2)
7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     */
7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    extension_length = 9;
7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (append && maxBytes >= extension_length) {
776c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)       SECStatus rv;
777c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)       TLSExtensionData *xtnData;
778c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
779c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)       /* extension_type */
780c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)       rv = ssl3_AppendHandshakeNumber(ss, ssl_cert_status_xtn, 2);
781c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)       if (rv != SECSuccess)
782c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)           return -1;
783c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)       rv = ssl3_AppendHandshakeNumber(ss, extension_length - 4, 2);
784c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)       if (rv != SECSuccess)
785c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)           return -1;
786c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)       rv = ssl3_AppendHandshakeNumber(ss, 1 /* status_type ocsp */, 1);
787c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)       if (rv != SECSuccess)
788c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)           return -1;
789c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)       /* A zero length responder_id_list means that the responders are
790c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        * implicitly known to the server. */
791c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)       rv = ssl3_AppendHandshakeNumber(ss, 0, 2);
792c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)       if (rv != SECSuccess)
793c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)           return -1;
794c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)       /* A zero length request_extensions means that there are no extensions.
795c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        * Specifically, we don't set the id-pkix-ocsp-nonce extension. This
796c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        * means that the server can replay a cached OCSP response to us. */
797c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)       rv = ssl3_AppendHandshakeNumber(ss, 0, 2);
798c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)       if (rv != SECSuccess)
799c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)           return -1;
800c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
801c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)       xtnData = &ss->xtnData;
802c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)       xtnData->advertised[xtnData->numAdvertised++] = ssl_cert_status_xtn;
8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (maxBytes < extension_length) {
804c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)       PORT_Assert(0);
805c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)       return 0;
8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return extension_length;
8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * NewSessionTicket
8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Called from ssl3_HandleFinished
8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SECStatus
8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ssl3_SendNewSessionTicket(sslSocket *ss)
8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int                  i;
8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SECStatus            rv;
8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NewSessionTicket     ticket;
8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SECItem              plaintext;
8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SECItem              plaintext_item = {0, NULL, 0};
8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SECItem              ciphertext     = {0, NULL, 0};
8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PRUint32             ciphertext_length;
8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PRBool               ms_is_wrapped;
8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned char        wrapped_ms[SSL3_MASTER_SECRET_LENGTH];
8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SECItem              ms_item = {0, NULL, 0};
8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SSL3KEAType          effectiveExchKeyType = ssl_kea_null;
8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PRUint32             padding_length;
8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PRUint32             message_length;
8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PRUint32             cert_length;
8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint8                length_buf[4];
8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PRUint32             now;
8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PK11SymKey          *aes_key_pkcs11;
8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PK11SymKey          *mac_key_pkcs11;
8352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#ifndef NO_PKCS11_BYPASS
8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const unsigned char *aes_key;
8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const unsigned char *mac_key;
8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PRUint32             aes_key_length;
8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PRUint32             mac_key_length;
8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PRUint64             aes_ctx_buf[MAX_CIPHER_CONTEXT_LLONGS];
8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AESContext          *aes_ctx;
8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const SECHashObject *hashObj = NULL;
8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PRUint64             hmac_ctx_buf[MAX_MAC_CONTEXT_LLONGS];
8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    HMACContext         *hmac_ctx;
8452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif
8462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CK_MECHANISM_TYPE    cipherMech = CKM_AES_CBC;
8472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    PK11Context         *aes_ctx_pkcs11;
8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CK_MECHANISM_TYPE    macMech = CKM_SHA256_HMAC;
8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PK11Context         *hmac_ctx_pkcs11;
8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned char        computed_mac[TLS_EX_SESS_TICKET_MAC_LENGTH];
8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned int         computed_mac_length;
8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned char        iv[AES_BLOCK_SIZE];
8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SECItem              ivItem;
8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SECItem             *srvName = NULL;
8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PRUint32             srvNameLen = 0;
8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CK_MECHANISM_TYPE    msWrapMech = 0; /* dummy default value,
8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          * must be >= 0 */
8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SSL_TRC(3, ("%d: SSL3[%d]: send session_ticket handshake",
8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		SSL_GETPID(), ss->fd));
8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ticket.ticket_lifetime_hint = TLS_EX_SESS_TICKET_LIFETIME_HINT;
8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cert_length = (ss->opt.requestCertificate && ss->sec.ci.sid->peerCert) ?
8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	3 + ss->sec.ci.sid->peerCert->derCert.len : 0;
8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Get IV and encryption keys */
8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ivItem.data = iv;
8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ivItem.len = sizeof(iv);
8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rv = PK11_GenerateRandom(iv, sizeof(iv));
8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (rv != SECSuccess) goto loser;
8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#ifndef NO_PKCS11_BYPASS
8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (ss->opt.bypassPKCS11) {
8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	rv = ssl3_GetSessionTicketKeys(&aes_key, &aes_key_length,
8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    &mac_key, &mac_key_length);
8792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    } else
8802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif
8812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    {
8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	rv = ssl3_GetSessionTicketKeysPKCS11(ss, &aes_key_pkcs11,
8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    &mac_key_pkcs11);
8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (rv != SECSuccess) goto loser;
8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (ss->ssl3.pwSpec->msItem.len && ss->ssl3.pwSpec->msItem.data) {
8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	/* The master secret is available unwrapped. */
8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	ms_item.data = ss->ssl3.pwSpec->msItem.data;
8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	ms_item.len = ss->ssl3.pwSpec->msItem.len;
8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	ms_is_wrapped = PR_FALSE;
8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	/* Extract the master secret wrapped. */
8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	sslSessionID sid;
8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	PORT_Memset(&sid, 0, sizeof(sslSessionID));
8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (ss->ssl3.hs.kea_def->kea == kea_ecdhe_rsa) {
8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    effectiveExchKeyType = kt_rsa;
8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	} else {
9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    effectiveExchKeyType = ss->ssl3.hs.kea_def->exchKeyType;
9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	rv = ssl3_CacheWrappedMasterSecret(ss, &sid, ss->ssl3.pwSpec,
9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    effectiveExchKeyType);
9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (rv == SECSuccess) {
9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    if (sid.u.ssl3.keys.wrapped_master_secret_len > sizeof(wrapped_ms))
9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		goto loser;
9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    memcpy(wrapped_ms, sid.u.ssl3.keys.wrapped_master_secret,
9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		sid.u.ssl3.keys.wrapped_master_secret_len);
9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    ms_item.data = wrapped_ms;
9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    ms_item.len = sid.u.ssl3.keys.wrapped_master_secret_len;
9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    msWrapMech = sid.u.ssl3.masterWrapMech;
9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	} else {
9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    /* TODO: else send an empty ticket. */
9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    goto loser;
9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	ms_is_wrapped = PR_TRUE;
9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Prep to send negotiated name */
9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    srvName = &ss->ssl3.pwSpec->srvVirtName;
9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (srvName->data && srvName->len) {
9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        srvNameLen = 2 + srvName->len; /* len bytes + name len */
9235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ciphertext_length =
9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	sizeof(PRUint16)                     /* ticket_version */
9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	+ sizeof(SSL3ProtocolVersion)        /* ssl_version */
9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	+ sizeof(ssl3CipherSuite)            /* ciphersuite */
9295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	+ 1                                  /* compression */
9305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	+ 10                                 /* cipher spec parameters */
9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	+ 1                                  /* SessionTicket.ms_is_wrapped */
9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	+ 1                                  /* effectiveExchKeyType */
9335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	+ 4                                  /* msWrapMech */
9345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	+ 2                                  /* master_secret.length */
9355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	+ ms_item.len                        /* master_secret */
9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	+ 1                                  /* client_auth_type */
9375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	+ cert_length                        /* cert */
9385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        + 1                                  /* server name type */
9395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        + srvNameLen                         /* name len + length field */
9405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	+ sizeof(ticket.ticket_lifetime_hint);
9415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    padding_length =  AES_BLOCK_SIZE -
9425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	(ciphertext_length % AES_BLOCK_SIZE);
9435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ciphertext_length += padding_length;
9445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    message_length =
9465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	sizeof(ticket.ticket_lifetime_hint)    /* ticket_lifetime_hint */
9475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	+ 2 /* length field for NewSessionTicket.ticket */
9485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	+ SESS_TICKET_KEY_NAME_LEN             /* key_name */
9495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	+ AES_BLOCK_SIZE                       /* iv */
9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	+ 2 /* length field for NewSessionTicket.ticket.encrypted_state */
9515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	+ ciphertext_length                    /* encrypted_state */
9525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	+ TLS_EX_SESS_TICKET_MAC_LENGTH;       /* mac */
9535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (SECITEM_AllocItem(NULL, &plaintext_item, ciphertext_length) == NULL)
9555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	goto loser;
9565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    plaintext = plaintext_item;
9585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* ticket_version */
9605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rv = ssl3_AppendNumberToItem(&plaintext, TLS_EX_SESS_TICKET_VERSION,
9615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	sizeof(PRUint16));
9625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (rv != SECSuccess) goto loser;
9635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* ssl_version */
9655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rv = ssl3_AppendNumberToItem(&plaintext, ss->version,
9665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	sizeof(SSL3ProtocolVersion));
9675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (rv != SECSuccess) goto loser;
9685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* ciphersuite */
9705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rv = ssl3_AppendNumberToItem(&plaintext, ss->ssl3.hs.cipher_suite,
9715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	sizeof(ssl3CipherSuite));
9725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (rv != SECSuccess) goto loser;
9735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* compression */
9755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rv = ssl3_AppendNumberToItem(&plaintext, ss->ssl3.hs.compression, 1);
9765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (rv != SECSuccess) goto loser;
9775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* cipher spec parameters */
9795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rv = ssl3_AppendNumberToItem(&plaintext, ss->sec.authAlgorithm, 1);
9805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (rv != SECSuccess) goto loser;
9815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rv = ssl3_AppendNumberToItem(&plaintext, ss->sec.authKeyBits, 4);
9825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (rv != SECSuccess) goto loser;
9835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rv = ssl3_AppendNumberToItem(&plaintext, ss->sec.keaType, 1);
9845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (rv != SECSuccess) goto loser;
9855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rv = ssl3_AppendNumberToItem(&plaintext, ss->sec.keaKeyBits, 4);
9865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (rv != SECSuccess) goto loser;
9875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* master_secret */
9895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rv = ssl3_AppendNumberToItem(&plaintext, ms_is_wrapped, 1);
9905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (rv != SECSuccess) goto loser;
9915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rv = ssl3_AppendNumberToItem(&plaintext, effectiveExchKeyType, 1);
9925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (rv != SECSuccess) goto loser;
9935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rv = ssl3_AppendNumberToItem(&plaintext, msWrapMech, 4);
9945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (rv != SECSuccess) goto loser;
9955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rv = ssl3_AppendNumberToItem(&plaintext, ms_item.len, 2);
9965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (rv != SECSuccess) goto loser;
9975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rv = ssl3_AppendToItem(&plaintext, ms_item.data, ms_item.len);
9985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (rv != SECSuccess) goto loser;
9995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* client_identity */
10015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (ss->opt.requestCertificate && ss->sec.ci.sid->peerCert) {
10025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	rv = ssl3_AppendNumberToItem(&plaintext, CLIENT_AUTH_CERTIFICATE, 1);
10035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (rv != SECSuccess) goto loser;
10045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	rv = ssl3_AppendNumberToItem(&plaintext,
10055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    ss->sec.ci.sid->peerCert->derCert.len, 3);
10065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (rv != SECSuccess) goto loser;
10075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	rv = ssl3_AppendToItem(&plaintext,
10085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    ss->sec.ci.sid->peerCert->derCert.data,
10095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    ss->sec.ci.sid->peerCert->derCert.len);
10105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (rv != SECSuccess) goto loser;
10115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
10125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	rv = ssl3_AppendNumberToItem(&plaintext, 0, 1);
10135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (rv != SECSuccess) goto loser;
10145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
10155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* timestamp */
10175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    now = ssl_Time();
10185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rv = ssl3_AppendNumberToItem(&plaintext, now,
10195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	sizeof(ticket.ticket_lifetime_hint));
10205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (rv != SECSuccess) goto loser;
10215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (srvNameLen) {
10235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        /* Name Type (sni_host_name) */
10245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rv = ssl3_AppendNumberToItem(&plaintext, srvName->type, 1);
10255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (rv != SECSuccess) goto loser;
10265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        /* HostName (length and value) */
10275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rv = ssl3_AppendNumberToItem(&plaintext, srvName->len, 2);
10285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (rv != SECSuccess) goto loser;
10295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rv = ssl3_AppendToItem(&plaintext, srvName->data, srvName->len);
10305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (rv != SECSuccess) goto loser;
10315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
10325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        /* No Name */
10335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rv = ssl3_AppendNumberToItem(&plaintext, (char)TLS_STE_NO_SERVER_NAME,
10345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     1);
10355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (rv != SECSuccess) goto loser;
10365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
10375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PORT_Assert(plaintext.len == padding_length);
10395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (i = 0; i < padding_length; i++)
10405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	plaintext.data[i] = (unsigned char)padding_length;
10415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (SECITEM_AllocItem(NULL, &ciphertext, ciphertext_length) == NULL) {
10435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	rv = SECFailure;
10445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	goto loser;
10455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
10465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Generate encrypted portion of ticket. */
10482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#ifndef NO_PKCS11_BYPASS
10495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (ss->opt.bypassPKCS11) {
10505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	aes_ctx = (AESContext *)aes_ctx_buf;
10515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	rv = AES_InitContext(aes_ctx, aes_key, aes_key_length, iv,
10525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    NSS_AES_CBC, 1, AES_BLOCK_SIZE);
10535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (rv != SECSuccess) goto loser;
10545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	rv = AES_Encrypt(aes_ctx, ciphertext.data, &ciphertext.len,
10565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    ciphertext.len, plaintext_item.data,
10575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    plaintext_item.len);
10585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (rv != SECSuccess) goto loser;
10592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    } else
10602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif
10612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    {
10625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	aes_ctx_pkcs11 = PK11_CreateContextBySymKey(cipherMech,
10635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    CKA_ENCRYPT, aes_key_pkcs11, &ivItem);
10645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (!aes_ctx_pkcs11)
10655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    goto loser;
10665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	rv = PK11_CipherOp(aes_ctx_pkcs11, ciphertext.data,
10685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    (int *)&ciphertext.len, ciphertext.len,
10695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    plaintext_item.data, plaintext_item.len);
10705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	PK11_Finalize(aes_ctx_pkcs11);
10715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	PK11_DestroyContext(aes_ctx_pkcs11, PR_TRUE);
10725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (rv != SECSuccess) goto loser;
10735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
10745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Convert ciphertext length to network order. */
10765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    length_buf[0] = (ciphertext.len >> 8) & 0xff;
10775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    length_buf[1] = (ciphertext.len     ) & 0xff;
10785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Compute MAC. */
10802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#ifndef NO_PKCS11_BYPASS
10815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (ss->opt.bypassPKCS11) {
10825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	hmac_ctx = (HMACContext *)hmac_ctx_buf;
10835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	hashObj = HASH_GetRawHashObject(HASH_AlgSHA256);
10845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (HMAC_Init(hmac_ctx, hashObj, mac_key,
10855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		mac_key_length, PR_FALSE) != SECSuccess)
10865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    goto loser;
10875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	HMAC_Begin(hmac_ctx);
10895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	HMAC_Update(hmac_ctx, key_name, SESS_TICKET_KEY_NAME_LEN);
10905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	HMAC_Update(hmac_ctx, iv, sizeof(iv));
10915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	HMAC_Update(hmac_ctx, (unsigned char *)length_buf, 2);
10925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	HMAC_Update(hmac_ctx, ciphertext.data, ciphertext.len);
10935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	HMAC_Finish(hmac_ctx, computed_mac, &computed_mac_length,
10945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    sizeof(computed_mac));
10952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    } else
10962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif
10972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    {
10985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	SECItem macParam;
10995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	macParam.data = NULL;
11005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	macParam.len = 0;
11015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	hmac_ctx_pkcs11 = PK11_CreateContextBySymKey(macMech,
11025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    CKA_SIGN, mac_key_pkcs11, &macParam);
11035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (!hmac_ctx_pkcs11)
11045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    goto loser;
11055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	rv = PK11_DigestBegin(hmac_ctx_pkcs11);
11075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	rv = PK11_DigestOp(hmac_ctx_pkcs11, key_name,
11085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    SESS_TICKET_KEY_NAME_LEN);
11095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	rv = PK11_DigestOp(hmac_ctx_pkcs11, iv, sizeof(iv));
11105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	rv = PK11_DigestOp(hmac_ctx_pkcs11, (unsigned char *)length_buf, 2);
11115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	rv = PK11_DigestOp(hmac_ctx_pkcs11, ciphertext.data, ciphertext.len);
11125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	rv = PK11_DigestFinal(hmac_ctx_pkcs11, computed_mac,
11135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    &computed_mac_length, sizeof(computed_mac));
11145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	PK11_DestroyContext(hmac_ctx_pkcs11, PR_TRUE);
11155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (rv != SECSuccess) goto loser;
11165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
11175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Serialize the handshake message. */
11195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rv = ssl3_AppendHandshakeHeader(ss, new_session_ticket, message_length);
11205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (rv != SECSuccess) goto loser;
11215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rv = ssl3_AppendHandshakeNumber(ss, ticket.ticket_lifetime_hint,
11235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	sizeof(ticket.ticket_lifetime_hint));
11245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (rv != SECSuccess) goto loser;
11255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rv = ssl3_AppendHandshakeNumber(ss,
11275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	message_length - sizeof(ticket.ticket_lifetime_hint) - 2, 2);
11285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (rv != SECSuccess) goto loser;
11295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rv = ssl3_AppendHandshake(ss, key_name, SESS_TICKET_KEY_NAME_LEN);
11315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (rv != SECSuccess) goto loser;
11325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rv = ssl3_AppendHandshake(ss, iv, sizeof(iv));
11345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (rv != SECSuccess) goto loser;
11355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rv = ssl3_AppendHandshakeVariable(ss, ciphertext.data, ciphertext.len, 2);
11375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (rv != SECSuccess) goto loser;
11385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rv = ssl3_AppendHandshake(ss, computed_mac, computed_mac_length);
11405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (rv != SECSuccess) goto loser;
11415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)loser:
11435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (plaintext_item.data)
11445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	SECITEM_FreeItem(&plaintext_item, PR_FALSE);
11455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (ciphertext.data)
11465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	SECITEM_FreeItem(&ciphertext, PR_FALSE);
11475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return rv;
11495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* When a client receives a SessionTicket extension a NewSessionTicket
11525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * message is expected during the handshake.
11535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
11545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SECStatus
11555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ssl3_ClientHandleSessionTicketXtn(sslSocket *ss, PRUint16 ex_type,
11565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  SECItem *data)
11575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
11585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (data->len != 0)
11595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return SECFailure;
11605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Keep track of negotiated extensions. */
11625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ss->xtnData.negotiated[ss->xtnData.numNegotiated++] = ex_type;
11635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SECSuccess;
11645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SECStatus
11675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ssl3_ServerHandleSessionTicketXtn(sslSocket *ss, PRUint16 ex_type,
11685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  SECItem *data)
11695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
11705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SECStatus rv;
11715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SECItem *decrypted_state = NULL;
11725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SessionTicket *parsed_session_ticket = NULL;
11735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sslSessionID *sid = NULL;
11745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SSL3Statistics *ssl3stats;
11755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Ignore the SessionTicket extension if processing is disabled. */
11775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!ss->opt.enableSessionTickets)
11785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return SECSuccess;
11795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Keep track of negotiated extensions. */
11815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ss->xtnData.negotiated[ss->xtnData.numNegotiated++] = ex_type;
11825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Parse the received ticket sent in by the client.  We are
11845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * lenient about some parse errors, falling back to a fullshake
11855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * instead of terminating the current connection.
11865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     */
11875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (data->len == 0) {
11885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	ss->xtnData.emptySessionTicket = PR_TRUE;
11895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
11905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	int                    i;
11915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	SECItem                extension_data;
11925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	EncryptedSessionTicket enc_session_ticket;
11935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	unsigned char          computed_mac[TLS_EX_SESS_TICKET_MAC_LENGTH];
11945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	unsigned int           computed_mac_length;
11952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#ifndef NO_PKCS11_BYPASS
11965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	const SECHashObject   *hashObj;
11975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	const unsigned char   *aes_key;
11985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	const unsigned char   *mac_key;
11995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	PRUint32               aes_key_length;
12005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	PRUint32               mac_key_length;
12015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	PRUint64               hmac_ctx_buf[MAX_MAC_CONTEXT_LLONGS];
12025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	HMACContext           *hmac_ctx;
12035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	PRUint64               aes_ctx_buf[MAX_CIPHER_CONTEXT_LLONGS];
12045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	AESContext            *aes_ctx;
12052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif
12062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	PK11SymKey            *aes_key_pkcs11;
12072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	PK11SymKey            *mac_key_pkcs11;
12082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	PK11Context           *hmac_ctx_pkcs11;
12092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	CK_MECHANISM_TYPE      macMech = CKM_SHA256_HMAC;
12105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	PK11Context           *aes_ctx_pkcs11;
12115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	CK_MECHANISM_TYPE      cipherMech = CKM_AES_CBC;
12125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	unsigned char *        padding;
12135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	PRUint32               padding_length;
12145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	unsigned char         *buffer;
12155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	unsigned int           buffer_len;
12165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	PRInt32                temp;
12175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	SECItem                cert_item;
12185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        PRInt8                 nameType = TLS_STE_NO_SERVER_NAME;
12195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	/* Turn off stateless session resumption if the client sends a
12215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 * SessionTicket extension, even if the extension turns out to be
12225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 * malformed (ss->sec.ci.sid is non-NULL when doing session
12235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 * renegotiation.)
12245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 */
12255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (ss->sec.ci.sid != NULL) {
12265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    if (ss->sec.uncache)
12275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		ss->sec.uncache(ss->sec.ci.sid);
12285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    ssl_FreeSID(ss->sec.ci.sid);
12295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    ss->sec.ci.sid = NULL;
12305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
12315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	extension_data.data = data->data; /* Keep a copy for future use. */
12335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	extension_data.len = data->len;
12345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (ssl3_ParseEncryptedSessionTicket(ss, data, &enc_session_ticket)
12365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    != SECSuccess)
12375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    return SECFailure;
12385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	/* Get session ticket keys. */
12402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#ifndef NO_PKCS11_BYPASS
12415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (ss->opt.bypassPKCS11) {
12425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    rv = ssl3_GetSessionTicketKeys(&aes_key, &aes_key_length,
12435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		&mac_key, &mac_key_length);
12442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	} else
12452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif
1246c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)	{
12475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    rv = ssl3_GetSessionTicketKeysPKCS11(ss, &aes_key_pkcs11,
12485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		&mac_key_pkcs11);
12495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
12505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (rv != SECSuccess) {
12515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    SSL_DBG(("%d: SSL[%d]: Unable to get/generate session ticket keys.",
12525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			SSL_GETPID(), ss->fd));
12535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    goto loser;
12545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
12555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	/* If the ticket sent by the client was generated under a key different
12575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 * from the one we have, bypass ticket processing.
12585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 */
12595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (PORT_Memcmp(enc_session_ticket.key_name, key_name,
12605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		SESS_TICKET_KEY_NAME_LEN) != 0) {
12615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    SSL_DBG(("%d: SSL[%d]: Session ticket key_name sent mismatch.",
12625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			SSL_GETPID(), ss->fd));
12635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    goto no_ticket;
12645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
12655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	/* Verify the MAC on the ticket.  MAC verification may also
12675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 * fail if the MAC key has been recently refreshed.
12685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 */
12692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#ifndef NO_PKCS11_BYPASS
12705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (ss->opt.bypassPKCS11) {
12715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    hmac_ctx = (HMACContext *)hmac_ctx_buf;
12725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    hashObj = HASH_GetRawHashObject(HASH_AlgSHA256);
12735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    if (HMAC_Init(hmac_ctx, hashObj, mac_key,
12745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		    sizeof(session_ticket_mac_key), PR_FALSE) != SECSuccess)
12755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		goto no_ticket;
12765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    HMAC_Begin(hmac_ctx);
12775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    HMAC_Update(hmac_ctx, extension_data.data,
12785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		extension_data.len - TLS_EX_SESS_TICKET_MAC_LENGTH);
12795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    if (HMAC_Finish(hmac_ctx, computed_mac, &computed_mac_length,
12805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		    sizeof(computed_mac)) != SECSuccess)
12815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		goto no_ticket;
12822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	} else
12832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif
1284c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)	{
12855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    SECItem macParam;
12865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    macParam.data = NULL;
12875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    macParam.len = 0;
12885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    hmac_ctx_pkcs11 = PK11_CreateContextBySymKey(macMech,
12895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		CKA_SIGN, mac_key_pkcs11, &macParam);
12905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    if (!hmac_ctx_pkcs11) {
12915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		SSL_DBG(("%d: SSL[%d]: Unable to create HMAC context: %d.",
12925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			    SSL_GETPID(), ss->fd, PORT_GetError()));
12935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		goto no_ticket;
12945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    } else {
12955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		SSL_DBG(("%d: SSL[%d]: Successfully created HMAC context.",
12965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			    SSL_GETPID(), ss->fd));
12975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    }
12985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    rv = PK11_DigestBegin(hmac_ctx_pkcs11);
12995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    rv = PK11_DigestOp(hmac_ctx_pkcs11, extension_data.data,
13005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		extension_data.len - TLS_EX_SESS_TICKET_MAC_LENGTH);
13015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    if (rv != SECSuccess) {
13025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		PK11_DestroyContext(hmac_ctx_pkcs11, PR_TRUE);
13035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		goto no_ticket;
13045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    }
13055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    rv = PK11_DigestFinal(hmac_ctx_pkcs11, computed_mac,
13065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		&computed_mac_length, sizeof(computed_mac));
13075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    PK11_DestroyContext(hmac_ctx_pkcs11, PR_TRUE);
13085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    if (rv != SECSuccess)
13095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		goto no_ticket;
13105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
13115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (NSS_SecureMemcmp(computed_mac, enc_session_ticket.mac,
13125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		computed_mac_length) != 0) {
13135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    SSL_DBG(("%d: SSL[%d]: Session ticket MAC mismatch.",
13145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			SSL_GETPID(), ss->fd));
13155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    goto no_ticket;
13165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
13175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	/* We ignore key_name for now.
13195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 * This is ok as MAC verification succeeded.
13205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 */
13215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	/* Decrypt the ticket. */
13235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	/* Plaintext is shorter than the ciphertext due to padding. */
13255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	decrypted_state = SECITEM_AllocItem(NULL, NULL,
13265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    enc_session_ticket.encrypted_state.len);
13275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#ifndef NO_PKCS11_BYPASS
13295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (ss->opt.bypassPKCS11) {
13305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    aes_ctx = (AESContext *)aes_ctx_buf;
13315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    rv = AES_InitContext(aes_ctx, aes_key,
13325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		sizeof(session_ticket_enc_key), enc_session_ticket.iv,
13335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		NSS_AES_CBC, 0,AES_BLOCK_SIZE);
13345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    if (rv != SECSuccess) {
13355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		SSL_DBG(("%d: SSL[%d]: Unable to create AES context.",
13365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			    SSL_GETPID(), ss->fd));
13375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		goto no_ticket;
13385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    }
13395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    rv = AES_Decrypt(aes_ctx, decrypted_state->data,
13415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		&decrypted_state->len, decrypted_state->len,
13425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		enc_session_ticket.encrypted_state.data,
13435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		enc_session_ticket.encrypted_state.len);
13445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    if (rv != SECSuccess)
13455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		goto no_ticket;
13462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	} else
13472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif
1348c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)	{
13495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    SECItem ivItem;
13505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    ivItem.data = enc_session_ticket.iv;
13515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    ivItem.len = AES_BLOCK_SIZE;
13525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    aes_ctx_pkcs11 = PK11_CreateContextBySymKey(cipherMech,
13535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		CKA_DECRYPT, aes_key_pkcs11, &ivItem);
13545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    if (!aes_ctx_pkcs11) {
13555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		SSL_DBG(("%d: SSL[%d]: Unable to create AES context.",
13565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			    SSL_GETPID(), ss->fd));
13575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		goto no_ticket;
13585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    }
13595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    rv = PK11_CipherOp(aes_ctx_pkcs11, decrypted_state->data,
13615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		(int *)&decrypted_state->len, decrypted_state->len,
13625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		enc_session_ticket.encrypted_state.data,
13635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		enc_session_ticket.encrypted_state.len);
13645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    PK11_Finalize(aes_ctx_pkcs11);
13655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    PK11_DestroyContext(aes_ctx_pkcs11, PR_TRUE);
13665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    if (rv != SECSuccess)
13675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		goto no_ticket;
13685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
13695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	/* Check padding. */
13715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	padding_length =
13725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    (PRUint32)decrypted_state->data[decrypted_state->len - 1];
13735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (padding_length == 0 || padding_length > AES_BLOCK_SIZE)
13745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    goto no_ticket;
13755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	padding = &decrypted_state->data[decrypted_state->len - padding_length];
13775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	for (i = 0; i < padding_length; i++, padding++) {
13785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    if (padding_length != (PRUint32)*padding)
13795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		goto no_ticket;
13805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
13815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	/* Deserialize session state. */
13835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	buffer = decrypted_state->data;
13845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	buffer_len = decrypted_state->len;
13855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	parsed_session_ticket = PORT_ZAlloc(sizeof(SessionTicket));
13875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (parsed_session_ticket == NULL) {
13885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    rv = SECFailure;
13895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    goto loser;
13905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
13915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	/* Read ticket_version (which is ignored for now.) */
13935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	temp = ssl3_ConsumeHandshakeNumber(ss, 2, &buffer, &buffer_len);
13945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (temp < 0) goto no_ticket;
13955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	parsed_session_ticket->ticket_version = (SSL3ProtocolVersion)temp;
13965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	/* Read SSLVersion. */
13985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	temp = ssl3_ConsumeHandshakeNumber(ss, 2, &buffer, &buffer_len);
13995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (temp < 0) goto no_ticket;
14005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	parsed_session_ticket->ssl_version = (SSL3ProtocolVersion)temp;
14015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	/* Read cipher_suite. */
14035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	temp =  ssl3_ConsumeHandshakeNumber(ss, 2, &buffer, &buffer_len);
14045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (temp < 0) goto no_ticket;
14055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	parsed_session_ticket->cipher_suite = (ssl3CipherSuite)temp;
14065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	/* Read compression_method. */
14085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	temp = ssl3_ConsumeHandshakeNumber(ss, 1, &buffer, &buffer_len);
14095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (temp < 0) goto no_ticket;
14105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	parsed_session_ticket->compression_method = (SSLCompressionMethod)temp;
14115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	/* Read cipher spec parameters. */
14135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	temp = ssl3_ConsumeHandshakeNumber(ss, 1, &buffer, &buffer_len);
14145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (temp < 0) goto no_ticket;
14155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	parsed_session_ticket->authAlgorithm = (SSLSignType)temp;
14165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	temp = ssl3_ConsumeHandshakeNumber(ss, 4, &buffer, &buffer_len);
14175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (temp < 0) goto no_ticket;
14185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	parsed_session_ticket->authKeyBits = (PRUint32)temp;
14195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	temp = ssl3_ConsumeHandshakeNumber(ss, 1, &buffer, &buffer_len);
14205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (temp < 0) goto no_ticket;
14215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	parsed_session_ticket->keaType = (SSLKEAType)temp;
14225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	temp = ssl3_ConsumeHandshakeNumber(ss, 4, &buffer, &buffer_len);
14235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (temp < 0) goto no_ticket;
14245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	parsed_session_ticket->keaKeyBits = (PRUint32)temp;
14255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	/* Read wrapped master_secret. */
14275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	temp = ssl3_ConsumeHandshakeNumber(ss, 1, &buffer, &buffer_len);
14285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (temp < 0) goto no_ticket;
14295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	parsed_session_ticket->ms_is_wrapped = (PRBool)temp;
14305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	temp = ssl3_ConsumeHandshakeNumber(ss, 1, &buffer, &buffer_len);
14325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (temp < 0) goto no_ticket;
14335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	parsed_session_ticket->exchKeyType = (SSL3KEAType)temp;
14345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	temp = ssl3_ConsumeHandshakeNumber(ss, 4, &buffer, &buffer_len);
14365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (temp < 0) goto no_ticket;
14375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	parsed_session_ticket->msWrapMech = (CK_MECHANISM_TYPE)temp;
14385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	temp = ssl3_ConsumeHandshakeNumber(ss, 2, &buffer, &buffer_len);
14405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (temp < 0) goto no_ticket;
14415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	parsed_session_ticket->ms_length = (PRUint16)temp;
14425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (parsed_session_ticket->ms_length == 0 ||  /* sanity check MS. */
14435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    parsed_session_ticket->ms_length >
14445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    sizeof(parsed_session_ticket->master_secret))
14455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    goto no_ticket;
14465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	/* Allow for the wrapped master secret to be longer. */
14485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (buffer_len < sizeof(SSL3_MASTER_SECRET_LENGTH))
14495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    goto no_ticket;
14505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	PORT_Memcpy(parsed_session_ticket->master_secret, buffer,
14515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    parsed_session_ticket->ms_length);
14525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	buffer += parsed_session_ticket->ms_length;
14535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	buffer_len -= parsed_session_ticket->ms_length;
14545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	/* Read client_identity */
14565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	temp = ssl3_ConsumeHandshakeNumber(ss, 1, &buffer, &buffer_len);
14575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (temp < 0)
14585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    goto no_ticket;
14595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	parsed_session_ticket->client_identity.client_auth_type =
14605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    (ClientAuthenticationType)temp;
14615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	switch(parsed_session_ticket->client_identity.client_auth_type) {
14625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            case CLIENT_AUTH_ANONYMOUS:
14635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		break;
14645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            case CLIENT_AUTH_CERTIFICATE:
14655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		rv = ssl3_ConsumeHandshakeVariable(ss, &cert_item, 3,
14665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		    &buffer, &buffer_len);
14675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		if (rv != SECSuccess) goto no_ticket;
14685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		rv = SECITEM_CopyItem(NULL, &parsed_session_ticket->peer_cert,
14695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		    &cert_item);
14705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		if (rv != SECSuccess) goto no_ticket;
14715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		break;
14725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            default:
14735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		goto no_ticket;
14745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
14755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	/* Read timestamp. */
14765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	temp = ssl3_ConsumeHandshakeNumber(ss, 4, &buffer, &buffer_len);
14775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (temp < 0)
14785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    goto no_ticket;
14795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	parsed_session_ticket->timestamp = (PRUint32)temp;
14805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        /* Read server name */
14825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        nameType =
14835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                ssl3_ConsumeHandshakeNumber(ss, 1, &buffer, &buffer_len);
14845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (nameType != TLS_STE_NO_SERVER_NAME) {
14855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            SECItem name_item;
14865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            rv = ssl3_ConsumeHandshakeVariable(ss, &name_item, 2, &buffer,
14875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                               &buffer_len);
14885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if (rv != SECSuccess) goto no_ticket;
14895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            rv = SECITEM_CopyItem(NULL, &parsed_session_ticket->srvName,
14905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  &name_item);
14915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if (rv != SECSuccess) goto no_ticket;
14925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            parsed_session_ticket->srvName.type = nameType;
14935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
14945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	/* Done parsing.  Check that all bytes have been consumed. */
14965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (buffer_len != padding_length)
14975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    goto no_ticket;
14985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	/* Use the ticket if it has not expired, otherwise free the allocated
15005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 * memory since the ticket is of no use.
15015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 */
15025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (parsed_session_ticket->timestamp != 0 &&
15035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    parsed_session_ticket->timestamp +
15045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    TLS_EX_SESS_TICKET_LIFETIME_HINT > ssl_Time()) {
15055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    sid = ssl3_NewSessionID(ss, PR_TRUE);
15075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    if (sid == NULL) {
15085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		rv = SECFailure;
15095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		goto loser;
15105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    }
15115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    /* Copy over parameters. */
15135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    sid->version = parsed_session_ticket->ssl_version;
15145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    sid->u.ssl3.cipherSuite = parsed_session_ticket->cipher_suite;
15155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    sid->u.ssl3.compression = parsed_session_ticket->compression_method;
15165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    sid->authAlgorithm = parsed_session_ticket->authAlgorithm;
15175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    sid->authKeyBits = parsed_session_ticket->authKeyBits;
15185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    sid->keaType = parsed_session_ticket->keaType;
15195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    sid->keaKeyBits = parsed_session_ticket->keaKeyBits;
15205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    /* Copy master secret. */
15222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#ifndef NO_PKCS11_BYPASS
15235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    if (ss->opt.bypassPKCS11 &&
15245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		    parsed_session_ticket->ms_is_wrapped)
15255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		goto no_ticket;
15262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif
15275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    if (parsed_session_ticket->ms_length >
15285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		    sizeof(sid->u.ssl3.keys.wrapped_master_secret))
15295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		goto no_ticket;
15305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    PORT_Memcpy(sid->u.ssl3.keys.wrapped_master_secret,
15315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		parsed_session_ticket->master_secret,
15325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		parsed_session_ticket->ms_length);
15335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    sid->u.ssl3.keys.wrapped_master_secret_len =
15345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		parsed_session_ticket->ms_length;
15355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    sid->u.ssl3.exchKeyType = parsed_session_ticket->exchKeyType;
15365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    sid->u.ssl3.masterWrapMech = parsed_session_ticket->msWrapMech;
15375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    sid->u.ssl3.keys.msIsWrapped =
15385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		parsed_session_ticket->ms_is_wrapped;
15395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    sid->u.ssl3.masterValid    = PR_TRUE;
15405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    sid->u.ssl3.keys.resumable = PR_TRUE;
15415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    /* Copy over client cert from session ticket if there is one. */
15435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    if (parsed_session_ticket->peer_cert.data != NULL) {
15445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		if (sid->peerCert != NULL)
15455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		    CERT_DestroyCertificate(sid->peerCert);
15465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		sid->peerCert = CERT_NewTempCertificate(ss->dbHandle,
15475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		    &parsed_session_ticket->peer_cert, NULL, PR_FALSE, PR_TRUE);
15485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		if (sid->peerCert == NULL) {
15495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		    rv = SECFailure;
15505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		    goto loser;
15515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		}
15525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    }
15535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    if (parsed_session_ticket->srvName.data != NULL) {
15545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                sid->u.ssl3.srvName = parsed_session_ticket->srvName;
15555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
15565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    ss->statelessResume = PR_TRUE;
15575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    ss->sec.ci.sid = sid;
15585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
15595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
15605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (0) {
15625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)no_ticket:
15635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	SSL_DBG(("%d: SSL[%d]: Session ticket parsing failed.",
15645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			SSL_GETPID(), ss->fd));
15655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	ssl3stats = SSL_GetStatistics();
15665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	SSL_AtomicIncrementLong(& ssl3stats->hch_sid_ticket_parse_failures );
15675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
15685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rv = SECSuccess;
15695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)loser:
15715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	/* ss->sec.ci.sid == sid if it did NOT come here via goto statement
15725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 * in that case do not free sid
15735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 */
15745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (sid && (ss->sec.ci.sid != sid)) {
15755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    ssl_FreeSID(sid);
15765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    sid = NULL;
15775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
15785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (decrypted_state != NULL) {
15795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	SECITEM_FreeItem(decrypted_state, PR_TRUE);
15805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	decrypted_state = NULL;
15815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
15825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (parsed_session_ticket != NULL) {
15845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (parsed_session_ticket->peer_cert.data) {
15855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    SECITEM_FreeItem(&parsed_session_ticket->peer_cert, PR_FALSE);
15865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
15875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	PORT_ZFree(parsed_session_ticket, sizeof(SessionTicket));
15885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
15895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return rv;
15915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
15925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
15945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Read bytes.  Using this function means the SECItem structure
15955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * cannot be freed.  The caller is expected to call this function
15965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * on a shallow copy of the structure.
15975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
15985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static SECStatus
15995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ssl3_ConsumeFromItem(SECItem *item, unsigned char **buf, PRUint32 bytes)
16005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
16015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (bytes > item->len)
16025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return SECFailure;
16035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *buf = item->data;
16055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    item->data += bytes;
16065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    item->len -= bytes;
16075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SECSuccess;
16085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
16095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static SECStatus
16115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ssl3_ParseEncryptedSessionTicket(sslSocket *ss, SECItem *data,
16125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 EncryptedSessionTicket *enc_session_ticket)
16135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
16145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (ssl3_ConsumeFromItem(data, &enc_session_ticket->key_name,
16155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    SESS_TICKET_KEY_NAME_LEN) != SECSuccess)
16165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return SECFailure;
16175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (ssl3_ConsumeFromItem(data, &enc_session_ticket->iv,
16185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    AES_BLOCK_SIZE) != SECSuccess)
16195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return SECFailure;
16205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (ssl3_ConsumeHandshakeVariable(ss, &enc_session_ticket->encrypted_state,
16215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    2, &data->data, &data->len) != SECSuccess)
16225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return SECFailure;
16235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (ssl3_ConsumeFromItem(data, &enc_session_ticket->mac,
16245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    TLS_EX_SESS_TICKET_MAC_LENGTH) != SECSuccess)
16255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return SECFailure;
16265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (data->len != 0)  /* Make sure that we have consumed all bytes. */
16275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return SECFailure;
16285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SECSuccess;
16305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
16315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* go through hello extensions in buffer "b".
16335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * For each one, find the extension handler in the table, and
16345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * if present, invoke that handler.
16355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Servers ignore any extensions with unknown extension types.
16365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Clients reject any extensions with unadvertised extension types.
16375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
16385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SECStatus
16395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ssl3_HandleHelloExtensions(sslSocket *ss, SSL3Opaque **b, PRUint32 *length)
16405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
16415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ssl3HelloExtensionHandler * handlers;
16425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (ss->sec.isServer) {
16445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        handlers = clientHelloHandlers;
16455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (ss->version > SSL_LIBRARY_VERSION_3_0) {
16465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        handlers = serverHelloHandlersTLS;
16475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
16485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        handlers = serverHelloHandlersSSL3;
16495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
16505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while (*length) {
16525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	const ssl3HelloExtensionHandler * handler;
16535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	SECStatus rv;
16545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	PRInt32   extension_type;
16555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	SECItem   extension_data;
16565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	/* Get the extension's type field */
16585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	extension_type = ssl3_ConsumeHandshakeNumber(ss, 2, b, length);
16595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (extension_type < 0)  /* failure to decode extension_type */
16605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    return SECFailure;   /* alert already sent */
16615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	/* get the data for this extension, so we can pass it or skip it. */
16635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	rv = ssl3_ConsumeHandshakeVariable(ss, &extension_data, 2, b, length);
16645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (rv != SECSuccess)
16655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    return rv;
16665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	/* Check whether the server sent an extension which was not advertised
16685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 * in the ClientHello.
16695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 */
16705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (!ss->sec.isServer &&
16715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    !ssl3_ClientExtensionAdvertised(ss, extension_type))
16725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    return SECFailure;  /* TODO: send unsupported_extension alert */
16735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	/* Check whether an extension has been sent multiple times. */
16755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (ssl3_ExtensionNegotiated(ss, extension_type))
16765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    return SECFailure;
16775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	/* find extension_type in table of Hello Extension Handlers */
16795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	for (handler = handlers; handler->ex_type >= 0; handler++) {
16805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    /* if found, call this handler */
16815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    if (handler->ex_type == extension_type) {
16825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		rv = (*handler->ex_handler)(ss, (PRUint16)extension_type,
16835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	                                         	&extension_data);
16845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		/* Ignore this result */
16855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		/* Treat all bad extensions as unrecognized types. */
16865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	        break;
16875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    }
16885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
16895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
16905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SECSuccess;
16915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
16925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Add a callback function to the table of senders of server hello extensions.
16945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
16955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SECStatus
16965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ssl3_RegisterServerHelloExtensionSender(sslSocket *ss, PRUint16 ex_type,
16975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				        ssl3HelloExtensionSenderFunc cb)
16985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
16995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int i;
17005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ssl3HelloExtensionSender *sender = &ss->xtnData.serverSenders[0];
17015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (i = 0; i < SSL_MAX_EXTENSIONS; ++i, ++sender) {
17035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!sender->ex_sender) {
17045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    sender->ex_type   = ex_type;
17055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    sender->ex_sender = cb;
17065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    return SECSuccess;
17075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
17085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	/* detect duplicate senders */
17095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	PORT_Assert(sender->ex_type != ex_type);
17105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (sender->ex_type == ex_type) {
17115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    /* duplicate */
17125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    break;
17135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
17145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
17155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PORT_Assert(i < SSL_MAX_EXTENSIONS); /* table needs to grow */
17165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
17175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SECFailure;
17185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
17195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* call each of the extension senders and return the accumulated length */
17215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PRInt32
17225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ssl3_CallHelloExtensionSenders(sslSocket *ss, PRBool append, PRUint32 maxBytes,
17235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               const ssl3HelloExtensionSender *sender)
17245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
17255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PRInt32 total_exten_len = 0;
17265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int i;
17275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!sender) {
17295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    	sender = ss->version > SSL_LIBRARY_VERSION_3_0 ?
17305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 &clientHelloSendersTLS[0] : &clientHelloSendersSSL3[0];
17315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
17325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (i = 0; i < SSL_MAX_EXTENSIONS; ++i, ++sender) {
17345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (sender->ex_sender) {
17355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    PRInt32 extLen = (*sender->ex_sender)(ss, append, maxBytes);
17365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    if (extLen < 0)
17375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    	return -1;
17385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    maxBytes        -= extLen;
17395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    total_exten_len += extLen;
17405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
17415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
17425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return total_exten_len;
17435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
17445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Extension format:
17475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Extension number:   2 bytes
17485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Extension length:   2 bytes
17495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Verify Data Length: 1 byte
17505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Verify Data (TLS): 12 bytes (client) or 24 bytes (server)
17515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Verify Data (SSL): 36 bytes (client) or 72 bytes (server)
17525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
17535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static PRInt32
17545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ssl3_SendRenegotiationInfoXtn(
17555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			sslSocket * ss,
17565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			PRBool      append,
17575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			PRUint32    maxBytes)
17585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
17595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PRInt32 len, needed;
17605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* In draft-ietf-tls-renegotiation-03, it is NOT RECOMMENDED to send
17625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * both the SCSV and the empty RI, so when we send SCSV in
17635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * the initial handshake, we don't also send RI.
17645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     */
17655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!ss || ss->ssl3.hs.sendingSCSV)
17665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    	return 0;
17675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    len = !ss->firstHsDone ? 0 :
17685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	   (ss->sec.isServer ? ss->ssl3.hs.finishedBytes * 2
17695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			     : ss->ssl3.hs.finishedBytes);
17705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    needed = 5 + len;
17715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (append && maxBytes >= needed) {
17725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	SECStatus rv;
17735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	/* extension_type */
17745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	rv = ssl3_AppendHandshakeNumber(ss, ssl_renegotiation_info_xtn, 2);
17755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (rv != SECSuccess) return -1;
17765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	/* length of extension_data */
17775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	rv = ssl3_AppendHandshakeNumber(ss, len + 1, 2);
17785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (rv != SECSuccess) return -1;
17795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	/* verify_Data from previous Finished message(s) */
17805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	rv = ssl3_AppendHandshakeVariable(ss,
17815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		  ss->ssl3.hs.finishedMsgs.data, len, 1);
17825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (rv != SECSuccess) return -1;
17835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (!ss->sec.isServer) {
17845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    TLSExtensionData *xtnData = &ss->xtnData;
17855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    xtnData->advertised[xtnData->numAdvertised++] =
17865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	                                           ssl_renegotiation_info_xtn;
17875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
17885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
17895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return needed;
17905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
17915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1792c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static SECStatus
1793c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)ssl3_ServerHandleStatusRequestXtn(sslSocket *ss, PRUint16 ex_type,
1794c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)				  SECItem *data)
1795c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles){
1796c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    SECStatus rv = SECSuccess;
1797c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    PRUint32 len = 0;
1798c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1799c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    /* remember that we got this extension. */
1800c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    ss->xtnData.negotiated[ss->xtnData.numNegotiated++] = ex_type;
1801c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    PORT_Assert(ss->sec.isServer);
1802c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    /* prepare to send back the appropriate response */
1803c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    rv = ssl3_RegisterServerHelloExtensionSender(ss, ex_type,
1804c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)					    ssl3_ServerSendStatusRequestXtn);
1805c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return rv;
1806c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
1807c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
18085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* This function runs in both the client and server.  */
18095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static SECStatus
18105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ssl3_HandleRenegotiationInfoXtn(sslSocket *ss, PRUint16 ex_type, SECItem *data)
18115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
18125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SECStatus rv = SECSuccess;
18135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PRUint32 len = 0;
18145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (ss->firstHsDone) {
18165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	len = ss->sec.isServer ? ss->ssl3.hs.finishedBytes
18175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	                       : ss->ssl3.hs.finishedBytes * 2;
18185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
18195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (data->len != 1 + len  ||
18205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	data->data[0] != len  || (len &&
18215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	NSS_SecureMemcmp(ss->ssl3.hs.finishedMsgs.data,
18225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	                 data->data + 1, len))) {
18235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	/* Can we do this here? Or, must we arrange for the caller to do it? */
18245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	(void)SSL3_SendAlert(ss, alert_fatal, handshake_failure);
18255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	PORT_SetError(SSL_ERROR_BAD_HANDSHAKE_HASH_VALUE);
18265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return SECFailure;
18275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
18285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* remember that we got this extension and it was correct. */
18295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ss->peerRequestedProtection = 1;
18305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ss->xtnData.negotiated[ss->xtnData.numNegotiated++] = ex_type;
18315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (ss->sec.isServer) {
18325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	/* prepare to send back the appropriate response */
18335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	rv = ssl3_RegisterServerHelloExtensionSender(ss, ex_type,
18345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					     ssl3_SendRenegotiationInfoXtn);
18355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
18365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return rv;
18375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
18385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static PRInt32
18405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ssl3_SendUseSRTPXtn(sslSocket *ss, PRBool append, PRUint32 maxBytes)
18415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
18425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PRUint32 ext_data_len;
18435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PRInt16 i;
18445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SECStatus rv;
18455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!ss)
18475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return 0;
18485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!ss->sec.isServer) {
18505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	/* Client side */
18515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (!IS_DTLS(ss) || !ss->ssl3.dtlsSRTPCipherCount)
18535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    return 0;  /* Not relevant */
18545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	ext_data_len = 2 + 2 * ss->ssl3.dtlsSRTPCipherCount + 1;
18565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (append && maxBytes >= 4 + ext_data_len) {
18585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    /* Extension type */
18595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    rv = ssl3_AppendHandshakeNumber(ss, ssl_use_srtp_xtn, 2);
18605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    if (rv != SECSuccess) return -1;
18615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    /* Length of extension data */
18625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    rv = ssl3_AppendHandshakeNumber(ss, ext_data_len, 2);
18635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    if (rv != SECSuccess) return -1;
18645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    /* Length of the SRTP cipher list */
18655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    rv = ssl3_AppendHandshakeNumber(ss,
18665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					    2 * ss->ssl3.dtlsSRTPCipherCount,
18675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					    2);
18685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    if (rv != SECSuccess) return -1;
18695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    /* The SRTP ciphers */
18705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    for (i = 0; i < ss->ssl3.dtlsSRTPCipherCount; i++) {
18715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		rv = ssl3_AppendHandshakeNumber(ss,
18725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)						ss->ssl3.dtlsSRTPCiphers[i],
18735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)						2);
18745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    }
18755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    /* Empty MKI value */
18765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    ssl3_AppendHandshakeVariable(ss, NULL, 0, 1);
18775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    ss->xtnData.advertised[ss->xtnData.numAdvertised++] =
18795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		ssl_use_srtp_xtn;
18805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
18815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return 4 + ext_data_len;
18835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
18845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Server side */
18865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (append && maxBytes >= 9) {
18875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	/* Extension type */
18885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	rv = ssl3_AppendHandshakeNumber(ss, ssl_use_srtp_xtn, 2);
18895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (rv != SECSuccess) return -1;
18905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	/* Length of extension data */
18915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	rv = ssl3_AppendHandshakeNumber(ss, 5, 2);
18925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (rv != SECSuccess) return -1;
18935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	/* Length of the SRTP cipher list */
18945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	rv = ssl3_AppendHandshakeNumber(ss, 2, 2);
18955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (rv != SECSuccess) return -1;
18965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	/* The selected cipher */
18975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	rv = ssl3_AppendHandshakeNumber(ss, ss->ssl3.dtlsSRTPCipherSuite, 2);
18985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (rv != SECSuccess) return -1;
18995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	/* Empty MKI value */
19005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	ssl3_AppendHandshakeVariable(ss, NULL, 0, 1);
19015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
19025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 9;
19045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
19055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static SECStatus
19075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ssl3_HandleUseSRTPXtn(sslSocket * ss, PRUint16 ex_type, SECItem *data)
19085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
19095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SECStatus rv;
19105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SECItem ciphers = {siBuffer, NULL, 0};
19112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    PRUint16 i;
19122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    unsigned int j;
19135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PRUint16 cipher = 0;
19145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PRBool found = PR_FALSE;
19155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SECItem litem;
19165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!ss->sec.isServer) {
19185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	/* Client side */
19195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (!data->data || !data->len) {
19205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            /* malformed */
19215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return SECFailure;
19225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
19235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	/* Get the cipher list */
19255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	rv = ssl3_ConsumeHandshakeVariable(ss, &ciphers, 2,
19265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					   &data->data, &data->len);
19275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (rv != SECSuccess) {
19285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    return SECFailure;
19295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
19305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	/* Now check that the number of ciphers listed is 1 (len = 2) */
19315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (ciphers.len != 2) {
19325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    return SECFailure;
19335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
19345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	/* Get the selected cipher */
19365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	cipher = (ciphers.data[0] << 8) | ciphers.data[1];
19375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	/* Now check that this is one of the ciphers we offered */
19395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	for (i = 0; i < ss->ssl3.dtlsSRTPCipherCount; i++) {
19405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    if (cipher == ss->ssl3.dtlsSRTPCiphers[i]) {
19415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		found = PR_TRUE;
19425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		break;
19435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    }
19445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
19455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (!found) {
19475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    return SECFailure;
19485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
19495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	/* Get the srtp_mki value */
19515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rv = ssl3_ConsumeHandshakeVariable(ss, &litem, 1,
19525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					   &data->data, &data->len);
19535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (rv != SECSuccess) {
19545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return SECFailure;
19555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
19565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	/* We didn't offer an MKI, so this must be 0 length */
19585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	/* XXX RFC 5764 Section 4.1.3 says:
19595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 *   If the client detects a nonzero-length MKI in the server's
19605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 *   response that is different than the one the client offered,
19615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 *   then the client MUST abort the handshake and SHOULD send an
19625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 *   invalid_parameter alert.
19635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 *
19645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 * Due to a limitation of the ssl3_HandleHelloExtensions function,
19655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 * returning SECFailure here won't abort the handshake.  It will
19665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 * merely cause the use_srtp extension to be not negotiated.  We
19675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 * should fix this.  See NSS bug 753136.
19685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 */
19695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (litem.len != 0) {
19705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    return SECFailure;
19715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
19725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (data->len != 0) {
19745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            /* malformed */
19755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return SECFailure;
19765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
19775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	/* OK, this looks fine. */
19795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	ss->xtnData.negotiated[ss->xtnData.numNegotiated++] = ssl_use_srtp_xtn;
19805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	ss->ssl3.dtlsSRTPCipherSuite = cipher;
19815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return SECSuccess;
19825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
19835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Server side */
19855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!IS_DTLS(ss) || !ss->ssl3.dtlsSRTPCipherCount) {
19865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	/* Ignore the extension if we aren't doing DTLS or no DTLS-SRTP
19875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 * preferences have been set. */
19885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return SECSuccess;
19895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
19905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!data->data || data->len < 5) {
19925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	/* malformed */
19935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return SECFailure;
19945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
19955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Get the cipher list */
19975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rv = ssl3_ConsumeHandshakeVariable(ss, &ciphers, 2,
19985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				       &data->data, &data->len);
19995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (rv != SECSuccess) {
20005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return SECFailure;
20015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
20025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Check that the list is even length */
20035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (ciphers.len % 2) {
20045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return SECFailure;
20055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
20065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Walk through the offered list and pick the most preferred of our
20085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * ciphers, if any */
20095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (i = 0; !found && i < ss->ssl3.dtlsSRTPCipherCount; i++) {
20105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	for (j = 0; j + 1 < ciphers.len; j += 2) {
20115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    cipher = (ciphers.data[j] << 8) | ciphers.data[j + 1];
20125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    if (cipher == ss->ssl3.dtlsSRTPCiphers[i]) {
20135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		found = PR_TRUE;
20145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		break;
20155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    }
20165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
20175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
20185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Get the srtp_mki value */
20205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rv = ssl3_ConsumeHandshakeVariable(ss, &litem, 1, &data->data, &data->len);
20215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (rv != SECSuccess) {
20225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return SECFailure;
20235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
20245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (data->len != 0) {
20265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return SECFailure; /* Malformed */
20275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
20285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Now figure out what to do */
20305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!found) {
20315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	/* No matching ciphers */
20325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return SECSuccess;
20335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
20345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* OK, we have a valid cipher and we've selected it */
20365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ss->ssl3.dtlsSRTPCipherSuite = cipher;
20375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ss->xtnData.negotiated[ss->xtnData.numNegotiated++] = ssl_use_srtp_xtn;
20385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ssl3_RegisterServerHelloExtensionSender(ss, ssl_use_srtp_xtn,
20405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)						   ssl3_SendUseSRTPXtn);
20415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2042