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