Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
michael@0 | 1 | /* |
michael@0 | 2 | * SSL3 Protocol |
michael@0 | 3 | * |
michael@0 | 4 | * This Source Code Form is subject to the terms of the Mozilla Public |
michael@0 | 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
michael@0 | 6 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
michael@0 | 7 | |
michael@0 | 8 | /* TLS extension code moved here from ssl3ecc.c */ |
michael@0 | 9 | |
michael@0 | 10 | #include "nssrenam.h" |
michael@0 | 11 | #include "nss.h" |
michael@0 | 12 | #include "ssl.h" |
michael@0 | 13 | #include "sslproto.h" |
michael@0 | 14 | #include "sslimpl.h" |
michael@0 | 15 | #include "pk11pub.h" |
michael@0 | 16 | #ifdef NO_PKCS11_BYPASS |
michael@0 | 17 | #include "blapit.h" |
michael@0 | 18 | #else |
michael@0 | 19 | #include "blapi.h" |
michael@0 | 20 | #endif |
michael@0 | 21 | #include "prinit.h" |
michael@0 | 22 | |
michael@0 | 23 | static unsigned char key_name[SESS_TICKET_KEY_NAME_LEN]; |
michael@0 | 24 | static PK11SymKey *session_ticket_enc_key_pkcs11 = NULL; |
michael@0 | 25 | static PK11SymKey *session_ticket_mac_key_pkcs11 = NULL; |
michael@0 | 26 | |
michael@0 | 27 | #ifndef NO_PKCS11_BYPASS |
michael@0 | 28 | static unsigned char session_ticket_enc_key[AES_256_KEY_LENGTH]; |
michael@0 | 29 | static unsigned char session_ticket_mac_key[SHA256_LENGTH]; |
michael@0 | 30 | |
michael@0 | 31 | static PRBool session_ticket_keys_initialized = PR_FALSE; |
michael@0 | 32 | #endif |
michael@0 | 33 | static PRCallOnceType generate_session_keys_once; |
michael@0 | 34 | |
michael@0 | 35 | /* forward static function declarations */ |
michael@0 | 36 | static SECStatus ssl3_ParseEncryptedSessionTicket(sslSocket *ss, |
michael@0 | 37 | SECItem *data, EncryptedSessionTicket *enc_session_ticket); |
michael@0 | 38 | static SECStatus ssl3_AppendToItem(SECItem *item, const unsigned char *buf, |
michael@0 | 39 | PRUint32 bytes); |
michael@0 | 40 | static SECStatus ssl3_AppendNumberToItem(SECItem *item, PRUint32 num, |
michael@0 | 41 | PRInt32 lenSize); |
michael@0 | 42 | static SECStatus ssl3_GetSessionTicketKeysPKCS11(sslSocket *ss, |
michael@0 | 43 | PK11SymKey **aes_key, PK11SymKey **mac_key); |
michael@0 | 44 | #ifndef NO_PKCS11_BYPASS |
michael@0 | 45 | static SECStatus ssl3_GetSessionTicketKeys(const unsigned char **aes_key, |
michael@0 | 46 | PRUint32 *aes_key_length, const unsigned char **mac_key, |
michael@0 | 47 | PRUint32 *mac_key_length); |
michael@0 | 48 | #endif |
michael@0 | 49 | static PRInt32 ssl3_SendRenegotiationInfoXtn(sslSocket * ss, |
michael@0 | 50 | PRBool append, PRUint32 maxBytes); |
michael@0 | 51 | static SECStatus ssl3_HandleRenegotiationInfoXtn(sslSocket *ss, |
michael@0 | 52 | PRUint16 ex_type, SECItem *data); |
michael@0 | 53 | static SECStatus ssl3_ClientHandleNextProtoNegoXtn(sslSocket *ss, |
michael@0 | 54 | PRUint16 ex_type, SECItem *data); |
michael@0 | 55 | static SECStatus ssl3_ClientHandleAppProtoXtn(sslSocket *ss, |
michael@0 | 56 | PRUint16 ex_type, SECItem *data); |
michael@0 | 57 | static SECStatus ssl3_ServerHandleNextProtoNegoXtn(sslSocket *ss, |
michael@0 | 58 | PRUint16 ex_type, SECItem *data); |
michael@0 | 59 | static SECStatus ssl3_ServerHandleAppProtoXtn(sslSocket *ss, PRUint16 ex_type, |
michael@0 | 60 | SECItem *data); |
michael@0 | 61 | static PRInt32 ssl3_ClientSendNextProtoNegoXtn(sslSocket *ss, PRBool append, |
michael@0 | 62 | PRUint32 maxBytes); |
michael@0 | 63 | static PRInt32 ssl3_ClientSendAppProtoXtn(sslSocket *ss, PRBool append, |
michael@0 | 64 | PRUint32 maxBytes); |
michael@0 | 65 | static PRInt32 ssl3_ServerSendAppProtoXtn(sslSocket *ss, PRBool append, |
michael@0 | 66 | PRUint32 maxBytes); |
michael@0 | 67 | static PRInt32 ssl3_SendUseSRTPXtn(sslSocket *ss, PRBool append, |
michael@0 | 68 | PRUint32 maxBytes); |
michael@0 | 69 | static SECStatus ssl3_HandleUseSRTPXtn(sslSocket * ss, PRUint16 ex_type, |
michael@0 | 70 | SECItem *data); |
michael@0 | 71 | static PRInt32 ssl3_ServerSendStatusRequestXtn(sslSocket * ss, |
michael@0 | 72 | PRBool append, PRUint32 maxBytes); |
michael@0 | 73 | static SECStatus ssl3_ServerHandleStatusRequestXtn(sslSocket *ss, |
michael@0 | 74 | PRUint16 ex_type, SECItem *data); |
michael@0 | 75 | static SECStatus ssl3_ClientHandleStatusRequestXtn(sslSocket *ss, |
michael@0 | 76 | PRUint16 ex_type, |
michael@0 | 77 | SECItem *data); |
michael@0 | 78 | static PRInt32 ssl3_ClientSendStatusRequestXtn(sslSocket * ss, PRBool append, |
michael@0 | 79 | PRUint32 maxBytes); |
michael@0 | 80 | static PRInt32 ssl3_ClientSendSigAlgsXtn(sslSocket *ss, PRBool append, |
michael@0 | 81 | PRUint32 maxBytes); |
michael@0 | 82 | static SECStatus ssl3_ServerHandleSigAlgsXtn(sslSocket *ss, PRUint16 ex_type, |
michael@0 | 83 | SECItem *data); |
michael@0 | 84 | |
michael@0 | 85 | /* |
michael@0 | 86 | * Write bytes. Using this function means the SECItem structure |
michael@0 | 87 | * cannot be freed. The caller is expected to call this function |
michael@0 | 88 | * on a shallow copy of the structure. |
michael@0 | 89 | */ |
michael@0 | 90 | static SECStatus |
michael@0 | 91 | ssl3_AppendToItem(SECItem *item, const unsigned char *buf, PRUint32 bytes) |
michael@0 | 92 | { |
michael@0 | 93 | if (bytes > item->len) |
michael@0 | 94 | return SECFailure; |
michael@0 | 95 | |
michael@0 | 96 | PORT_Memcpy(item->data, buf, bytes); |
michael@0 | 97 | item->data += bytes; |
michael@0 | 98 | item->len -= bytes; |
michael@0 | 99 | return SECSuccess; |
michael@0 | 100 | } |
michael@0 | 101 | |
michael@0 | 102 | /* |
michael@0 | 103 | * Write a number in network byte order. Using this function means the |
michael@0 | 104 | * SECItem structure cannot be freed. The caller is expected to call |
michael@0 | 105 | * this function on a shallow copy of the structure. |
michael@0 | 106 | */ |
michael@0 | 107 | static SECStatus |
michael@0 | 108 | ssl3_AppendNumberToItem(SECItem *item, PRUint32 num, PRInt32 lenSize) |
michael@0 | 109 | { |
michael@0 | 110 | SECStatus rv; |
michael@0 | 111 | PRUint8 b[4]; |
michael@0 | 112 | PRUint8 * p = b; |
michael@0 | 113 | |
michael@0 | 114 | switch (lenSize) { |
michael@0 | 115 | case 4: |
michael@0 | 116 | *p++ = (PRUint8) (num >> 24); |
michael@0 | 117 | case 3: |
michael@0 | 118 | *p++ = (PRUint8) (num >> 16); |
michael@0 | 119 | case 2: |
michael@0 | 120 | *p++ = (PRUint8) (num >> 8); |
michael@0 | 121 | case 1: |
michael@0 | 122 | *p = (PRUint8) num; |
michael@0 | 123 | } |
michael@0 | 124 | rv = ssl3_AppendToItem(item, &b[0], lenSize); |
michael@0 | 125 | return rv; |
michael@0 | 126 | } |
michael@0 | 127 | |
michael@0 | 128 | static SECStatus ssl3_SessionTicketShutdown(void* appData, void* nssData) |
michael@0 | 129 | { |
michael@0 | 130 | if (session_ticket_enc_key_pkcs11) { |
michael@0 | 131 | PK11_FreeSymKey(session_ticket_enc_key_pkcs11); |
michael@0 | 132 | session_ticket_enc_key_pkcs11 = NULL; |
michael@0 | 133 | } |
michael@0 | 134 | if (session_ticket_mac_key_pkcs11) { |
michael@0 | 135 | PK11_FreeSymKey(session_ticket_mac_key_pkcs11); |
michael@0 | 136 | session_ticket_mac_key_pkcs11 = NULL; |
michael@0 | 137 | } |
michael@0 | 138 | PORT_Memset(&generate_session_keys_once, 0, |
michael@0 | 139 | sizeof(generate_session_keys_once)); |
michael@0 | 140 | return SECSuccess; |
michael@0 | 141 | } |
michael@0 | 142 | |
michael@0 | 143 | |
michael@0 | 144 | static PRStatus |
michael@0 | 145 | ssl3_GenerateSessionTicketKeysPKCS11(void *data) |
michael@0 | 146 | { |
michael@0 | 147 | SECStatus rv; |
michael@0 | 148 | sslSocket *ss = (sslSocket *)data; |
michael@0 | 149 | SECKEYPrivateKey *svrPrivKey = ss->serverCerts[kt_rsa].SERVERKEY; |
michael@0 | 150 | SECKEYPublicKey *svrPubKey = ss->serverCerts[kt_rsa].serverKeyPair->pubKey; |
michael@0 | 151 | |
michael@0 | 152 | if (svrPrivKey == NULL || svrPubKey == NULL) { |
michael@0 | 153 | SSL_DBG(("%d: SSL[%d]: Pub or priv key(s) is NULL.", |
michael@0 | 154 | SSL_GETPID(), ss->fd)); |
michael@0 | 155 | goto loser; |
michael@0 | 156 | } |
michael@0 | 157 | |
michael@0 | 158 | /* Get a copy of the session keys from shared memory. */ |
michael@0 | 159 | PORT_Memcpy(key_name, SESS_TICKET_KEY_NAME_PREFIX, |
michael@0 | 160 | sizeof(SESS_TICKET_KEY_NAME_PREFIX)); |
michael@0 | 161 | if (!ssl_GetSessionTicketKeysPKCS11(svrPrivKey, svrPubKey, |
michael@0 | 162 | ss->pkcs11PinArg, &key_name[SESS_TICKET_KEY_NAME_PREFIX_LEN], |
michael@0 | 163 | &session_ticket_enc_key_pkcs11, &session_ticket_mac_key_pkcs11)) |
michael@0 | 164 | return PR_FAILURE; |
michael@0 | 165 | |
michael@0 | 166 | rv = NSS_RegisterShutdown(ssl3_SessionTicketShutdown, NULL); |
michael@0 | 167 | if (rv != SECSuccess) |
michael@0 | 168 | goto loser; |
michael@0 | 169 | |
michael@0 | 170 | return PR_SUCCESS; |
michael@0 | 171 | |
michael@0 | 172 | loser: |
michael@0 | 173 | ssl3_SessionTicketShutdown(NULL, NULL); |
michael@0 | 174 | return PR_FAILURE; |
michael@0 | 175 | } |
michael@0 | 176 | |
michael@0 | 177 | static SECStatus |
michael@0 | 178 | ssl3_GetSessionTicketKeysPKCS11(sslSocket *ss, PK11SymKey **aes_key, |
michael@0 | 179 | PK11SymKey **mac_key) |
michael@0 | 180 | { |
michael@0 | 181 | if (PR_CallOnceWithArg(&generate_session_keys_once, |
michael@0 | 182 | ssl3_GenerateSessionTicketKeysPKCS11, ss) != PR_SUCCESS) |
michael@0 | 183 | return SECFailure; |
michael@0 | 184 | |
michael@0 | 185 | if (session_ticket_enc_key_pkcs11 == NULL || |
michael@0 | 186 | session_ticket_mac_key_pkcs11 == NULL) |
michael@0 | 187 | return SECFailure; |
michael@0 | 188 | |
michael@0 | 189 | *aes_key = session_ticket_enc_key_pkcs11; |
michael@0 | 190 | *mac_key = session_ticket_mac_key_pkcs11; |
michael@0 | 191 | return SECSuccess; |
michael@0 | 192 | } |
michael@0 | 193 | |
michael@0 | 194 | #ifndef NO_PKCS11_BYPASS |
michael@0 | 195 | static PRStatus |
michael@0 | 196 | ssl3_GenerateSessionTicketKeys(void) |
michael@0 | 197 | { |
michael@0 | 198 | PORT_Memcpy(key_name, SESS_TICKET_KEY_NAME_PREFIX, |
michael@0 | 199 | sizeof(SESS_TICKET_KEY_NAME_PREFIX)); |
michael@0 | 200 | |
michael@0 | 201 | if (!ssl_GetSessionTicketKeys(&key_name[SESS_TICKET_KEY_NAME_PREFIX_LEN], |
michael@0 | 202 | session_ticket_enc_key, session_ticket_mac_key)) |
michael@0 | 203 | return PR_FAILURE; |
michael@0 | 204 | |
michael@0 | 205 | session_ticket_keys_initialized = PR_TRUE; |
michael@0 | 206 | return PR_SUCCESS; |
michael@0 | 207 | } |
michael@0 | 208 | |
michael@0 | 209 | static SECStatus |
michael@0 | 210 | ssl3_GetSessionTicketKeys(const unsigned char **aes_key, |
michael@0 | 211 | PRUint32 *aes_key_length, const unsigned char **mac_key, |
michael@0 | 212 | PRUint32 *mac_key_length) |
michael@0 | 213 | { |
michael@0 | 214 | if (PR_CallOnce(&generate_session_keys_once, |
michael@0 | 215 | ssl3_GenerateSessionTicketKeys) != PR_SUCCESS) |
michael@0 | 216 | return SECFailure; |
michael@0 | 217 | |
michael@0 | 218 | if (!session_ticket_keys_initialized) |
michael@0 | 219 | return SECFailure; |
michael@0 | 220 | |
michael@0 | 221 | *aes_key = session_ticket_enc_key; |
michael@0 | 222 | *aes_key_length = sizeof(session_ticket_enc_key); |
michael@0 | 223 | *mac_key = session_ticket_mac_key; |
michael@0 | 224 | *mac_key_length = sizeof(session_ticket_mac_key); |
michael@0 | 225 | |
michael@0 | 226 | return SECSuccess; |
michael@0 | 227 | } |
michael@0 | 228 | #endif |
michael@0 | 229 | |
michael@0 | 230 | /* Table of handlers for received TLS hello extensions, one per extension. |
michael@0 | 231 | * In the second generation, this table will be dynamic, and functions |
michael@0 | 232 | * will be registered here. |
michael@0 | 233 | */ |
michael@0 | 234 | /* This table is used by the server, to handle client hello extensions. */ |
michael@0 | 235 | static const ssl3HelloExtensionHandler clientHelloHandlers[] = { |
michael@0 | 236 | { ssl_server_name_xtn, &ssl3_HandleServerNameXtn }, |
michael@0 | 237 | #ifndef NSS_DISABLE_ECC |
michael@0 | 238 | { ssl_elliptic_curves_xtn, &ssl3_HandleSupportedCurvesXtn }, |
michael@0 | 239 | { ssl_ec_point_formats_xtn, &ssl3_HandleSupportedPointFormatsXtn }, |
michael@0 | 240 | #endif |
michael@0 | 241 | { ssl_session_ticket_xtn, &ssl3_ServerHandleSessionTicketXtn }, |
michael@0 | 242 | { ssl_renegotiation_info_xtn, &ssl3_HandleRenegotiationInfoXtn }, |
michael@0 | 243 | { ssl_next_proto_nego_xtn, &ssl3_ServerHandleNextProtoNegoXtn }, |
michael@0 | 244 | { ssl_app_layer_protocol_xtn, &ssl3_ServerHandleAppProtoXtn }, |
michael@0 | 245 | { ssl_use_srtp_xtn, &ssl3_HandleUseSRTPXtn }, |
michael@0 | 246 | { ssl_cert_status_xtn, &ssl3_ServerHandleStatusRequestXtn }, |
michael@0 | 247 | { ssl_signature_algorithms_xtn, &ssl3_ServerHandleSigAlgsXtn }, |
michael@0 | 248 | { -1, NULL } |
michael@0 | 249 | }; |
michael@0 | 250 | |
michael@0 | 251 | /* These two tables are used by the client, to handle server hello |
michael@0 | 252 | * extensions. */ |
michael@0 | 253 | static const ssl3HelloExtensionHandler serverHelloHandlersTLS[] = { |
michael@0 | 254 | { ssl_server_name_xtn, &ssl3_HandleServerNameXtn }, |
michael@0 | 255 | /* TODO: add a handler for ssl_ec_point_formats_xtn */ |
michael@0 | 256 | { ssl_session_ticket_xtn, &ssl3_ClientHandleSessionTicketXtn }, |
michael@0 | 257 | { ssl_renegotiation_info_xtn, &ssl3_HandleRenegotiationInfoXtn }, |
michael@0 | 258 | { ssl_next_proto_nego_xtn, &ssl3_ClientHandleNextProtoNegoXtn }, |
michael@0 | 259 | { ssl_app_layer_protocol_xtn, &ssl3_ClientHandleAppProtoXtn }, |
michael@0 | 260 | { ssl_use_srtp_xtn, &ssl3_HandleUseSRTPXtn }, |
michael@0 | 261 | { ssl_cert_status_xtn, &ssl3_ClientHandleStatusRequestXtn }, |
michael@0 | 262 | { -1, NULL } |
michael@0 | 263 | }; |
michael@0 | 264 | |
michael@0 | 265 | static const ssl3HelloExtensionHandler serverHelloHandlersSSL3[] = { |
michael@0 | 266 | { ssl_renegotiation_info_xtn, &ssl3_HandleRenegotiationInfoXtn }, |
michael@0 | 267 | { -1, NULL } |
michael@0 | 268 | }; |
michael@0 | 269 | |
michael@0 | 270 | /* Tables of functions to format TLS hello extensions, one function per |
michael@0 | 271 | * extension. |
michael@0 | 272 | * These static tables are for the formatting of client hello extensions. |
michael@0 | 273 | * The server's table of hello senders is dynamic, in the socket struct, |
michael@0 | 274 | * and sender functions are registered there. |
michael@0 | 275 | */ |
michael@0 | 276 | static const |
michael@0 | 277 | ssl3HelloExtensionSender clientHelloSendersTLS[SSL_MAX_EXTENSIONS] = { |
michael@0 | 278 | { ssl_server_name_xtn, &ssl3_SendServerNameXtn }, |
michael@0 | 279 | { ssl_renegotiation_info_xtn, &ssl3_SendRenegotiationInfoXtn }, |
michael@0 | 280 | #ifndef NSS_DISABLE_ECC |
michael@0 | 281 | { ssl_elliptic_curves_xtn, &ssl3_SendSupportedCurvesXtn }, |
michael@0 | 282 | { ssl_ec_point_formats_xtn, &ssl3_SendSupportedPointFormatsXtn }, |
michael@0 | 283 | #endif |
michael@0 | 284 | { ssl_session_ticket_xtn, &ssl3_SendSessionTicketXtn }, |
michael@0 | 285 | { ssl_next_proto_nego_xtn, &ssl3_ClientSendNextProtoNegoXtn }, |
michael@0 | 286 | { ssl_app_layer_protocol_xtn, &ssl3_ClientSendAppProtoXtn }, |
michael@0 | 287 | { ssl_use_srtp_xtn, &ssl3_SendUseSRTPXtn }, |
michael@0 | 288 | { ssl_cert_status_xtn, &ssl3_ClientSendStatusRequestXtn }, |
michael@0 | 289 | { ssl_signature_algorithms_xtn, &ssl3_ClientSendSigAlgsXtn } |
michael@0 | 290 | /* any extra entries will appear as { 0, NULL } */ |
michael@0 | 291 | }; |
michael@0 | 292 | |
michael@0 | 293 | static const |
michael@0 | 294 | ssl3HelloExtensionSender clientHelloSendersSSL3[SSL_MAX_EXTENSIONS] = { |
michael@0 | 295 | { ssl_renegotiation_info_xtn, &ssl3_SendRenegotiationInfoXtn } |
michael@0 | 296 | /* any extra entries will appear as { 0, NULL } */ |
michael@0 | 297 | }; |
michael@0 | 298 | |
michael@0 | 299 | static PRBool |
michael@0 | 300 | arrayContainsExtension(const PRUint16 *array, PRUint32 len, PRUint16 ex_type) |
michael@0 | 301 | { |
michael@0 | 302 | int i; |
michael@0 | 303 | for (i = 0; i < len; i++) { |
michael@0 | 304 | if (ex_type == array[i]) |
michael@0 | 305 | return PR_TRUE; |
michael@0 | 306 | } |
michael@0 | 307 | return PR_FALSE; |
michael@0 | 308 | } |
michael@0 | 309 | |
michael@0 | 310 | PRBool |
michael@0 | 311 | ssl3_ExtensionNegotiated(sslSocket *ss, PRUint16 ex_type) { |
michael@0 | 312 | TLSExtensionData *xtnData = &ss->xtnData; |
michael@0 | 313 | return arrayContainsExtension(xtnData->negotiated, |
michael@0 | 314 | xtnData->numNegotiated, ex_type); |
michael@0 | 315 | } |
michael@0 | 316 | |
michael@0 | 317 | static PRBool |
michael@0 | 318 | ssl3_ClientExtensionAdvertised(sslSocket *ss, PRUint16 ex_type) { |
michael@0 | 319 | TLSExtensionData *xtnData = &ss->xtnData; |
michael@0 | 320 | return arrayContainsExtension(xtnData->advertised, |
michael@0 | 321 | xtnData->numAdvertised, ex_type); |
michael@0 | 322 | } |
michael@0 | 323 | |
michael@0 | 324 | /* Format an SNI extension, using the name from the socket's URL, |
michael@0 | 325 | * unless that name is a dotted decimal string. |
michael@0 | 326 | * Used by client and server. |
michael@0 | 327 | */ |
michael@0 | 328 | PRInt32 |
michael@0 | 329 | ssl3_SendServerNameXtn(sslSocket * ss, PRBool append, |
michael@0 | 330 | PRUint32 maxBytes) |
michael@0 | 331 | { |
michael@0 | 332 | SECStatus rv; |
michael@0 | 333 | if (!ss) |
michael@0 | 334 | return 0; |
michael@0 | 335 | if (!ss->sec.isServer) { |
michael@0 | 336 | PRUint32 len; |
michael@0 | 337 | PRNetAddr netAddr; |
michael@0 | 338 | |
michael@0 | 339 | /* must have a hostname */ |
michael@0 | 340 | if (!ss->url || !ss->url[0]) |
michael@0 | 341 | return 0; |
michael@0 | 342 | /* must not be an IPv4 or IPv6 address */ |
michael@0 | 343 | if (PR_SUCCESS == PR_StringToNetAddr(ss->url, &netAddr)) { |
michael@0 | 344 | /* is an IP address (v4 or v6) */ |
michael@0 | 345 | return 0; |
michael@0 | 346 | } |
michael@0 | 347 | len = PORT_Strlen(ss->url); |
michael@0 | 348 | if (append && maxBytes >= len + 9) { |
michael@0 | 349 | /* extension_type */ |
michael@0 | 350 | rv = ssl3_AppendHandshakeNumber(ss, ssl_server_name_xtn, 2); |
michael@0 | 351 | if (rv != SECSuccess) return -1; |
michael@0 | 352 | /* length of extension_data */ |
michael@0 | 353 | rv = ssl3_AppendHandshakeNumber(ss, len + 5, 2); |
michael@0 | 354 | if (rv != SECSuccess) return -1; |
michael@0 | 355 | /* length of server_name_list */ |
michael@0 | 356 | rv = ssl3_AppendHandshakeNumber(ss, len + 3, 2); |
michael@0 | 357 | if (rv != SECSuccess) return -1; |
michael@0 | 358 | /* Name Type (sni_host_name) */ |
michael@0 | 359 | rv = ssl3_AppendHandshake(ss, "\0", 1); |
michael@0 | 360 | if (rv != SECSuccess) return -1; |
michael@0 | 361 | /* HostName (length and value) */ |
michael@0 | 362 | rv = ssl3_AppendHandshakeVariable(ss, (PRUint8 *)ss->url, len, 2); |
michael@0 | 363 | if (rv != SECSuccess) return -1; |
michael@0 | 364 | if (!ss->sec.isServer) { |
michael@0 | 365 | TLSExtensionData *xtnData = &ss->xtnData; |
michael@0 | 366 | xtnData->advertised[xtnData->numAdvertised++] = |
michael@0 | 367 | ssl_server_name_xtn; |
michael@0 | 368 | } |
michael@0 | 369 | } |
michael@0 | 370 | return len + 9; |
michael@0 | 371 | } |
michael@0 | 372 | /* Server side */ |
michael@0 | 373 | if (append && maxBytes >= 4) { |
michael@0 | 374 | rv = ssl3_AppendHandshakeNumber(ss, ssl_server_name_xtn, 2); |
michael@0 | 375 | if (rv != SECSuccess) return -1; |
michael@0 | 376 | /* length of extension_data */ |
michael@0 | 377 | rv = ssl3_AppendHandshakeNumber(ss, 0, 2); |
michael@0 | 378 | if (rv != SECSuccess) return -1; |
michael@0 | 379 | } |
michael@0 | 380 | return 4; |
michael@0 | 381 | } |
michael@0 | 382 | |
michael@0 | 383 | /* handle an incoming SNI extension, by ignoring it. */ |
michael@0 | 384 | SECStatus |
michael@0 | 385 | ssl3_HandleServerNameXtn(sslSocket * ss, PRUint16 ex_type, SECItem *data) |
michael@0 | 386 | { |
michael@0 | 387 | SECItem *names = NULL; |
michael@0 | 388 | PRUint32 listCount = 0, namesPos = 0, i; |
michael@0 | 389 | TLSExtensionData *xtnData = &ss->xtnData; |
michael@0 | 390 | SECItem ldata; |
michael@0 | 391 | PRInt32 listLenBytes = 0; |
michael@0 | 392 | |
michael@0 | 393 | if (!ss->sec.isServer) { |
michael@0 | 394 | /* Verify extension_data is empty. */ |
michael@0 | 395 | if (data->data || data->len || |
michael@0 | 396 | !ssl3_ExtensionNegotiated(ss, ssl_server_name_xtn)) { |
michael@0 | 397 | /* malformed or was not initiated by the client.*/ |
michael@0 | 398 | return SECFailure; |
michael@0 | 399 | } |
michael@0 | 400 | return SECSuccess; |
michael@0 | 401 | } |
michael@0 | 402 | |
michael@0 | 403 | /* Server side - consume client data and register server sender. */ |
michael@0 | 404 | /* do not parse the data if don't have user extension handling function. */ |
michael@0 | 405 | if (!ss->sniSocketConfig) { |
michael@0 | 406 | return SECSuccess; |
michael@0 | 407 | } |
michael@0 | 408 | /* length of server_name_list */ |
michael@0 | 409 | listLenBytes = ssl3_ConsumeHandshakeNumber(ss, 2, &data->data, &data->len); |
michael@0 | 410 | if (listLenBytes == 0 || listLenBytes != data->len) { |
michael@0 | 411 | return SECFailure; |
michael@0 | 412 | } |
michael@0 | 413 | ldata = *data; |
michael@0 | 414 | /* Calculate the size of the array.*/ |
michael@0 | 415 | while (listLenBytes > 0) { |
michael@0 | 416 | SECItem litem; |
michael@0 | 417 | SECStatus rv; |
michael@0 | 418 | PRInt32 type; |
michael@0 | 419 | /* Name Type (sni_host_name) */ |
michael@0 | 420 | type = ssl3_ConsumeHandshakeNumber(ss, 1, &ldata.data, &ldata.len); |
michael@0 | 421 | if (!ldata.len) { |
michael@0 | 422 | return SECFailure; |
michael@0 | 423 | } |
michael@0 | 424 | rv = ssl3_ConsumeHandshakeVariable(ss, &litem, 2, &ldata.data, &ldata.len); |
michael@0 | 425 | if (rv != SECSuccess) { |
michael@0 | 426 | return SECFailure; |
michael@0 | 427 | } |
michael@0 | 428 | /* Adjust total length for cunsumed item, item len and type.*/ |
michael@0 | 429 | listLenBytes -= litem.len + 3; |
michael@0 | 430 | if (listLenBytes > 0 && !ldata.len) { |
michael@0 | 431 | return SECFailure; |
michael@0 | 432 | } |
michael@0 | 433 | listCount += 1; |
michael@0 | 434 | } |
michael@0 | 435 | if (!listCount) { |
michael@0 | 436 | return SECFailure; |
michael@0 | 437 | } |
michael@0 | 438 | names = PORT_ZNewArray(SECItem, listCount); |
michael@0 | 439 | if (!names) { |
michael@0 | 440 | return SECFailure; |
michael@0 | 441 | } |
michael@0 | 442 | for (i = 0;i < listCount;i++) { |
michael@0 | 443 | int j; |
michael@0 | 444 | PRInt32 type; |
michael@0 | 445 | SECStatus rv; |
michael@0 | 446 | PRBool nametypePresent = PR_FALSE; |
michael@0 | 447 | /* Name Type (sni_host_name) */ |
michael@0 | 448 | type = ssl3_ConsumeHandshakeNumber(ss, 1, &data->data, &data->len); |
michael@0 | 449 | /* Check if we have such type in the list */ |
michael@0 | 450 | for (j = 0;j < listCount && names[j].data;j++) { |
michael@0 | 451 | if (names[j].type == type) { |
michael@0 | 452 | nametypePresent = PR_TRUE; |
michael@0 | 453 | break; |
michael@0 | 454 | } |
michael@0 | 455 | } |
michael@0 | 456 | /* HostName (length and value) */ |
michael@0 | 457 | rv = ssl3_ConsumeHandshakeVariable(ss, &names[namesPos], 2, |
michael@0 | 458 | &data->data, &data->len); |
michael@0 | 459 | if (rv != SECSuccess) { |
michael@0 | 460 | goto loser; |
michael@0 | 461 | } |
michael@0 | 462 | if (nametypePresent == PR_FALSE) { |
michael@0 | 463 | namesPos += 1; |
michael@0 | 464 | } |
michael@0 | 465 | } |
michael@0 | 466 | /* Free old and set the new data. */ |
michael@0 | 467 | if (xtnData->sniNameArr) { |
michael@0 | 468 | PORT_Free(ss->xtnData.sniNameArr); |
michael@0 | 469 | } |
michael@0 | 470 | xtnData->sniNameArr = names; |
michael@0 | 471 | xtnData->sniNameArrSize = namesPos; |
michael@0 | 472 | xtnData->negotiated[xtnData->numNegotiated++] = ssl_server_name_xtn; |
michael@0 | 473 | |
michael@0 | 474 | return SECSuccess; |
michael@0 | 475 | |
michael@0 | 476 | loser: |
michael@0 | 477 | PORT_Free(names); |
michael@0 | 478 | return SECFailure; |
michael@0 | 479 | } |
michael@0 | 480 | |
michael@0 | 481 | /* Called by both clients and servers. |
michael@0 | 482 | * Clients sends a filled in session ticket if one is available, and otherwise |
michael@0 | 483 | * sends an empty ticket. Servers always send empty tickets. |
michael@0 | 484 | */ |
michael@0 | 485 | PRInt32 |
michael@0 | 486 | ssl3_SendSessionTicketXtn( |
michael@0 | 487 | sslSocket * ss, |
michael@0 | 488 | PRBool append, |
michael@0 | 489 | PRUint32 maxBytes) |
michael@0 | 490 | { |
michael@0 | 491 | PRInt32 extension_length; |
michael@0 | 492 | NewSessionTicket *session_ticket = NULL; |
michael@0 | 493 | sslSessionID *sid = ss->sec.ci.sid; |
michael@0 | 494 | |
michael@0 | 495 | /* Ignore the SessionTicket extension if processing is disabled. */ |
michael@0 | 496 | if (!ss->opt.enableSessionTickets) |
michael@0 | 497 | return 0; |
michael@0 | 498 | |
michael@0 | 499 | /* Empty extension length = extension_type (2-bytes) + |
michael@0 | 500 | * length(extension_data) (2-bytes) |
michael@0 | 501 | */ |
michael@0 | 502 | extension_length = 4; |
michael@0 | 503 | |
michael@0 | 504 | /* If we are a client then send a session ticket if one is availble. |
michael@0 | 505 | * Servers that support the extension and are willing to negotiate the |
michael@0 | 506 | * the extension always respond with an empty extension. |
michael@0 | 507 | */ |
michael@0 | 508 | if (!ss->sec.isServer) { |
michael@0 | 509 | /* The caller must be holding sid->u.ssl3.lock for reading. We cannot |
michael@0 | 510 | * just acquire and release the lock within this function because the |
michael@0 | 511 | * caller will call this function twice, and we need the inputs to be |
michael@0 | 512 | * consistent between the two calls. Note that currently the caller |
michael@0 | 513 | * will only be holding the lock when we are the client and when we're |
michael@0 | 514 | * attempting to resume an existing session. |
michael@0 | 515 | */ |
michael@0 | 516 | |
michael@0 | 517 | session_ticket = &sid->u.ssl3.locked.sessionTicket; |
michael@0 | 518 | if (session_ticket->ticket.data) { |
michael@0 | 519 | if (ss->xtnData.ticketTimestampVerified) { |
michael@0 | 520 | extension_length += session_ticket->ticket.len; |
michael@0 | 521 | } else if (!append && |
michael@0 | 522 | (session_ticket->ticket_lifetime_hint == 0 || |
michael@0 | 523 | (session_ticket->ticket_lifetime_hint + |
michael@0 | 524 | session_ticket->received_timestamp > ssl_Time()))) { |
michael@0 | 525 | extension_length += session_ticket->ticket.len; |
michael@0 | 526 | ss->xtnData.ticketTimestampVerified = PR_TRUE; |
michael@0 | 527 | } |
michael@0 | 528 | } |
michael@0 | 529 | } |
michael@0 | 530 | |
michael@0 | 531 | if (append && maxBytes >= extension_length) { |
michael@0 | 532 | SECStatus rv; |
michael@0 | 533 | /* extension_type */ |
michael@0 | 534 | rv = ssl3_AppendHandshakeNumber(ss, ssl_session_ticket_xtn, 2); |
michael@0 | 535 | if (rv != SECSuccess) |
michael@0 | 536 | goto loser; |
michael@0 | 537 | if (session_ticket && session_ticket->ticket.data && |
michael@0 | 538 | ss->xtnData.ticketTimestampVerified) { |
michael@0 | 539 | rv = ssl3_AppendHandshakeVariable(ss, session_ticket->ticket.data, |
michael@0 | 540 | session_ticket->ticket.len, 2); |
michael@0 | 541 | ss->xtnData.ticketTimestampVerified = PR_FALSE; |
michael@0 | 542 | ss->xtnData.sentSessionTicketInClientHello = PR_TRUE; |
michael@0 | 543 | } else { |
michael@0 | 544 | rv = ssl3_AppendHandshakeNumber(ss, 0, 2); |
michael@0 | 545 | } |
michael@0 | 546 | if (rv != SECSuccess) |
michael@0 | 547 | goto loser; |
michael@0 | 548 | |
michael@0 | 549 | if (!ss->sec.isServer) { |
michael@0 | 550 | TLSExtensionData *xtnData = &ss->xtnData; |
michael@0 | 551 | xtnData->advertised[xtnData->numAdvertised++] = |
michael@0 | 552 | ssl_session_ticket_xtn; |
michael@0 | 553 | } |
michael@0 | 554 | } else if (maxBytes < extension_length) { |
michael@0 | 555 | PORT_Assert(0); |
michael@0 | 556 | return 0; |
michael@0 | 557 | } |
michael@0 | 558 | return extension_length; |
michael@0 | 559 | |
michael@0 | 560 | loser: |
michael@0 | 561 | ss->xtnData.ticketTimestampVerified = PR_FALSE; |
michael@0 | 562 | return -1; |
michael@0 | 563 | } |
michael@0 | 564 | |
michael@0 | 565 | /* handle an incoming Next Protocol Negotiation extension. */ |
michael@0 | 566 | static SECStatus |
michael@0 | 567 | ssl3_ServerHandleNextProtoNegoXtn(sslSocket * ss, PRUint16 ex_type, |
michael@0 | 568 | SECItem *data) |
michael@0 | 569 | { |
michael@0 | 570 | if (ss->firstHsDone || data->len != 0) { |
michael@0 | 571 | /* Clients MUST send an empty NPN extension, if any. */ |
michael@0 | 572 | PORT_SetError(SSL_ERROR_NEXT_PROTOCOL_DATA_INVALID); |
michael@0 | 573 | return SECFailure; |
michael@0 | 574 | } |
michael@0 | 575 | |
michael@0 | 576 | ss->xtnData.negotiated[ss->xtnData.numNegotiated++] = ex_type; |
michael@0 | 577 | |
michael@0 | 578 | /* TODO: server side NPN support would require calling |
michael@0 | 579 | * ssl3_RegisterServerHelloExtensionSender here in order to echo the |
michael@0 | 580 | * extension back to the client. */ |
michael@0 | 581 | |
michael@0 | 582 | return SECSuccess; |
michael@0 | 583 | } |
michael@0 | 584 | |
michael@0 | 585 | /* ssl3_ValidateNextProtoNego checks that the given block of data is valid: none |
michael@0 | 586 | * of the lengths may be 0 and the sum of the lengths must equal the length of |
michael@0 | 587 | * the block. */ |
michael@0 | 588 | SECStatus |
michael@0 | 589 | ssl3_ValidateNextProtoNego(const unsigned char* data, unsigned int length) |
michael@0 | 590 | { |
michael@0 | 591 | unsigned int offset = 0; |
michael@0 | 592 | |
michael@0 | 593 | while (offset < length) { |
michael@0 | 594 | unsigned int newOffset = offset + 1 + (unsigned int) data[offset]; |
michael@0 | 595 | /* Reject embedded nulls to protect against buggy applications that |
michael@0 | 596 | * store protocol identifiers in null-terminated strings. |
michael@0 | 597 | */ |
michael@0 | 598 | if (newOffset > length || data[offset] == 0) { |
michael@0 | 599 | PORT_SetError(SSL_ERROR_NEXT_PROTOCOL_DATA_INVALID); |
michael@0 | 600 | return SECFailure; |
michael@0 | 601 | } |
michael@0 | 602 | offset = newOffset; |
michael@0 | 603 | } |
michael@0 | 604 | |
michael@0 | 605 | if (offset > length) { |
michael@0 | 606 | PORT_SetError(SSL_ERROR_NEXT_PROTOCOL_DATA_INVALID); |
michael@0 | 607 | return SECFailure; |
michael@0 | 608 | } |
michael@0 | 609 | |
michael@0 | 610 | return SECSuccess; |
michael@0 | 611 | } |
michael@0 | 612 | |
michael@0 | 613 | /* protocol selection handler for ALPN (server side) and NPN (client side) */ |
michael@0 | 614 | static SECStatus |
michael@0 | 615 | ssl3_SelectAppProtocol(sslSocket *ss, PRUint16 ex_type, SECItem *data) |
michael@0 | 616 | { |
michael@0 | 617 | SECStatus rv; |
michael@0 | 618 | unsigned char resultBuffer[255]; |
michael@0 | 619 | SECItem result = { siBuffer, resultBuffer, 0 }; |
michael@0 | 620 | |
michael@0 | 621 | rv = ssl3_ValidateNextProtoNego(data->data, data->len); |
michael@0 | 622 | if (rv != SECSuccess) |
michael@0 | 623 | return rv; |
michael@0 | 624 | |
michael@0 | 625 | PORT_Assert(ss->nextProtoCallback); |
michael@0 | 626 | rv = ss->nextProtoCallback(ss->nextProtoArg, ss->fd, data->data, data->len, |
michael@0 | 627 | result.data, &result.len, sizeof resultBuffer); |
michael@0 | 628 | if (rv != SECSuccess) |
michael@0 | 629 | return rv; |
michael@0 | 630 | /* If the callback wrote more than allowed to |result| it has corrupted our |
michael@0 | 631 | * stack. */ |
michael@0 | 632 | if (result.len > sizeof resultBuffer) { |
michael@0 | 633 | PORT_SetError(SEC_ERROR_OUTPUT_LEN); |
michael@0 | 634 | return SECFailure; |
michael@0 | 635 | } |
michael@0 | 636 | |
michael@0 | 637 | if (ex_type == ssl_app_layer_protocol_xtn && |
michael@0 | 638 | ss->ssl3.nextProtoState != SSL_NEXT_PROTO_NEGOTIATED) { |
michael@0 | 639 | /* The callback might say OK, but then it's picked a default. |
michael@0 | 640 | * That's OK for NPN, but not ALPN. */ |
michael@0 | 641 | SECITEM_FreeItem(&ss->ssl3.nextProto, PR_FALSE); |
michael@0 | 642 | PORT_SetError(SSL_ERROR_NEXT_PROTOCOL_NO_PROTOCOL); |
michael@0 | 643 | (void)SSL3_SendAlert(ss, alert_fatal, no_application_protocol); |
michael@0 | 644 | return SECFailure; |
michael@0 | 645 | } |
michael@0 | 646 | |
michael@0 | 647 | ss->xtnData.negotiated[ss->xtnData.numNegotiated++] = ex_type; |
michael@0 | 648 | |
michael@0 | 649 | SECITEM_FreeItem(&ss->ssl3.nextProto, PR_FALSE); |
michael@0 | 650 | return SECITEM_CopyItem(NULL, &ss->ssl3.nextProto, &result); |
michael@0 | 651 | } |
michael@0 | 652 | |
michael@0 | 653 | /* handle an incoming ALPN extension at the server */ |
michael@0 | 654 | static SECStatus |
michael@0 | 655 | ssl3_ServerHandleAppProtoXtn(sslSocket *ss, PRUint16 ex_type, SECItem *data) |
michael@0 | 656 | { |
michael@0 | 657 | int count; |
michael@0 | 658 | SECStatus rv; |
michael@0 | 659 | |
michael@0 | 660 | /* We expressly don't want to allow ALPN on renegotiation, |
michael@0 | 661 | * despite it being permitted by the spec. */ |
michael@0 | 662 | if (ss->firstHsDone || data->len == 0) { |
michael@0 | 663 | /* Clients MUST send a non-empty ALPN extension. */ |
michael@0 | 664 | PORT_SetError(SSL_ERROR_NEXT_PROTOCOL_DATA_INVALID); |
michael@0 | 665 | return SECFailure; |
michael@0 | 666 | } |
michael@0 | 667 | |
michael@0 | 668 | /* unlike NPN, ALPN has extra redundant length information so that |
michael@0 | 669 | * the extension is the same in both ClientHello and ServerHello */ |
michael@0 | 670 | count = ssl3_ConsumeHandshakeNumber(ss, 2, &data->data, &data->len); |
michael@0 | 671 | if (count < 0) { |
michael@0 | 672 | return SECFailure; /* fatal alert was sent */ |
michael@0 | 673 | } |
michael@0 | 674 | if (count != data->len) { |
michael@0 | 675 | return ssl3_DecodeError(ss); |
michael@0 | 676 | } |
michael@0 | 677 | |
michael@0 | 678 | if (!ss->nextProtoCallback) { |
michael@0 | 679 | /* we're not configured for it */ |
michael@0 | 680 | return SECSuccess; |
michael@0 | 681 | } |
michael@0 | 682 | |
michael@0 | 683 | rv = ssl3_SelectAppProtocol(ss, ex_type, data); |
michael@0 | 684 | if (rv != SECSuccess) { |
michael@0 | 685 | return rv; |
michael@0 | 686 | } |
michael@0 | 687 | |
michael@0 | 688 | /* prepare to send back a response, if we negotiated */ |
michael@0 | 689 | if (ss->ssl3.nextProtoState == SSL_NEXT_PROTO_NEGOTIATED) { |
michael@0 | 690 | return ssl3_RegisterServerHelloExtensionSender( |
michael@0 | 691 | ss, ex_type, ssl3_ServerSendAppProtoXtn); |
michael@0 | 692 | } |
michael@0 | 693 | return SECSuccess; |
michael@0 | 694 | } |
michael@0 | 695 | |
michael@0 | 696 | static SECStatus |
michael@0 | 697 | ssl3_ClientHandleNextProtoNegoXtn(sslSocket *ss, PRUint16 ex_type, |
michael@0 | 698 | SECItem *data) |
michael@0 | 699 | { |
michael@0 | 700 | PORT_Assert(!ss->firstHsDone); |
michael@0 | 701 | |
michael@0 | 702 | if (ssl3_ExtensionNegotiated(ss, ssl_app_layer_protocol_xtn)) { |
michael@0 | 703 | /* If the server negotiated ALPN then it has already told us what |
michael@0 | 704 | * protocol to use, so it doesn't make sense for us to try to negotiate |
michael@0 | 705 | * a different one by sending the NPN handshake message. However, if |
michael@0 | 706 | * we've negotiated NPN then we're required to send the NPN handshake |
michael@0 | 707 | * message. Thus, these two extensions cannot both be negotiated on the |
michael@0 | 708 | * same connection. */ |
michael@0 | 709 | PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); |
michael@0 | 710 | return SECFailure; |
michael@0 | 711 | } |
michael@0 | 712 | |
michael@0 | 713 | /* We should only get this call if we sent the extension, so |
michael@0 | 714 | * ss->nextProtoCallback needs to be non-NULL. However, it is possible |
michael@0 | 715 | * that an application erroneously cleared the callback between the time |
michael@0 | 716 | * we sent the ClientHello and now. */ |
michael@0 | 717 | if (!ss->nextProtoCallback) { |
michael@0 | 718 | PORT_SetError(SSL_ERROR_NEXT_PROTOCOL_NO_CALLBACK); |
michael@0 | 719 | return SECFailure; |
michael@0 | 720 | } |
michael@0 | 721 | |
michael@0 | 722 | return ssl3_SelectAppProtocol(ss, ex_type, data); |
michael@0 | 723 | } |
michael@0 | 724 | |
michael@0 | 725 | static SECStatus |
michael@0 | 726 | ssl3_ClientHandleAppProtoXtn(sslSocket *ss, PRUint16 ex_type, SECItem *data) |
michael@0 | 727 | { |
michael@0 | 728 | const unsigned char* d = data->data; |
michael@0 | 729 | PRUint16 name_list_len; |
michael@0 | 730 | SECItem protocol_name; |
michael@0 | 731 | |
michael@0 | 732 | if (ssl3_ExtensionNegotiated(ss, ssl_next_proto_nego_xtn)) { |
michael@0 | 733 | PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); |
michael@0 | 734 | return SECFailure; |
michael@0 | 735 | } |
michael@0 | 736 | |
michael@0 | 737 | /* The extension data from the server has the following format: |
michael@0 | 738 | * uint16 name_list_len; |
michael@0 | 739 | * uint8 len; |
michael@0 | 740 | * uint8 protocol_name[len]; */ |
michael@0 | 741 | if (data->len < 4 || data->len > 2 + 1 + 255) { |
michael@0 | 742 | PORT_SetError(SSL_ERROR_NEXT_PROTOCOL_DATA_INVALID); |
michael@0 | 743 | return SECFailure; |
michael@0 | 744 | } |
michael@0 | 745 | |
michael@0 | 746 | name_list_len = ((PRUint16) d[0]) << 8 | |
michael@0 | 747 | ((PRUint16) d[1]); |
michael@0 | 748 | if (name_list_len != data->len - 2 || d[2] != data->len - 3) { |
michael@0 | 749 | PORT_SetError(SSL_ERROR_NEXT_PROTOCOL_DATA_INVALID); |
michael@0 | 750 | return SECFailure; |
michael@0 | 751 | } |
michael@0 | 752 | |
michael@0 | 753 | protocol_name.data = data->data + 3; |
michael@0 | 754 | protocol_name.len = data->len - 3; |
michael@0 | 755 | |
michael@0 | 756 | SECITEM_FreeItem(&ss->ssl3.nextProto, PR_FALSE); |
michael@0 | 757 | ss->ssl3.nextProtoState = SSL_NEXT_PROTO_SELECTED; |
michael@0 | 758 | ss->xtnData.negotiated[ss->xtnData.numNegotiated++] = ex_type; |
michael@0 | 759 | return SECITEM_CopyItem(NULL, &ss->ssl3.nextProto, &protocol_name); |
michael@0 | 760 | } |
michael@0 | 761 | |
michael@0 | 762 | static PRInt32 |
michael@0 | 763 | ssl3_ClientSendNextProtoNegoXtn(sslSocket * ss, PRBool append, |
michael@0 | 764 | PRUint32 maxBytes) |
michael@0 | 765 | { |
michael@0 | 766 | PRInt32 extension_length; |
michael@0 | 767 | |
michael@0 | 768 | /* Renegotiations do not send this extension. */ |
michael@0 | 769 | if (!ss->opt.enableNPN || !ss->nextProtoCallback || ss->firstHsDone) { |
michael@0 | 770 | return 0; |
michael@0 | 771 | } |
michael@0 | 772 | |
michael@0 | 773 | extension_length = 4; |
michael@0 | 774 | |
michael@0 | 775 | if (append && maxBytes >= extension_length) { |
michael@0 | 776 | SECStatus rv; |
michael@0 | 777 | rv = ssl3_AppendHandshakeNumber(ss, ssl_next_proto_nego_xtn, 2); |
michael@0 | 778 | if (rv != SECSuccess) |
michael@0 | 779 | goto loser; |
michael@0 | 780 | rv = ssl3_AppendHandshakeNumber(ss, 0, 2); |
michael@0 | 781 | if (rv != SECSuccess) |
michael@0 | 782 | goto loser; |
michael@0 | 783 | ss->xtnData.advertised[ss->xtnData.numAdvertised++] = |
michael@0 | 784 | ssl_next_proto_nego_xtn; |
michael@0 | 785 | } else if (maxBytes < extension_length) { |
michael@0 | 786 | return 0; |
michael@0 | 787 | } |
michael@0 | 788 | |
michael@0 | 789 | return extension_length; |
michael@0 | 790 | |
michael@0 | 791 | loser: |
michael@0 | 792 | return -1; |
michael@0 | 793 | } |
michael@0 | 794 | |
michael@0 | 795 | static PRInt32 |
michael@0 | 796 | ssl3_ClientSendAppProtoXtn(sslSocket * ss, PRBool append, PRUint32 maxBytes) |
michael@0 | 797 | { |
michael@0 | 798 | PRInt32 extension_length; |
michael@0 | 799 | unsigned char *alpn_protos = NULL; |
michael@0 | 800 | |
michael@0 | 801 | /* Renegotiations do not send this extension. */ |
michael@0 | 802 | if (!ss->opt.enableALPN || !ss->opt.nextProtoNego.data || ss->firstHsDone) { |
michael@0 | 803 | return 0; |
michael@0 | 804 | } |
michael@0 | 805 | |
michael@0 | 806 | extension_length = 2 /* extension type */ + 2 /* extension length */ + |
michael@0 | 807 | 2 /* protocol name list length */ + |
michael@0 | 808 | ss->opt.nextProtoNego.len; |
michael@0 | 809 | |
michael@0 | 810 | if (append && maxBytes >= extension_length) { |
michael@0 | 811 | /* NPN requires that the client's fallback protocol is first in the |
michael@0 | 812 | * list. However, ALPN sends protocols in preference order. So we |
michael@0 | 813 | * allocate a buffer and move the first protocol to the end of the |
michael@0 | 814 | * list. */ |
michael@0 | 815 | SECStatus rv; |
michael@0 | 816 | const unsigned int len = ss->opt.nextProtoNego.len; |
michael@0 | 817 | |
michael@0 | 818 | alpn_protos = PORT_Alloc(len); |
michael@0 | 819 | if (alpn_protos == NULL) { |
michael@0 | 820 | return SECFailure; |
michael@0 | 821 | } |
michael@0 | 822 | if (len > 0) { |
michael@0 | 823 | /* Each protocol string is prefixed with a single byte length. */ |
michael@0 | 824 | unsigned int i = ss->opt.nextProtoNego.data[0] + 1; |
michael@0 | 825 | if (i <= len) { |
michael@0 | 826 | memcpy(alpn_protos, &ss->opt.nextProtoNego.data[i], len - i); |
michael@0 | 827 | memcpy(alpn_protos + len - i, ss->opt.nextProtoNego.data, i); |
michael@0 | 828 | } else { |
michael@0 | 829 | /* This seems to be invalid data so we'll send as-is. */ |
michael@0 | 830 | memcpy(alpn_protos, ss->opt.nextProtoNego.data, len); |
michael@0 | 831 | } |
michael@0 | 832 | } |
michael@0 | 833 | |
michael@0 | 834 | rv = ssl3_AppendHandshakeNumber(ss, ssl_app_layer_protocol_xtn, 2); |
michael@0 | 835 | if (rv != SECSuccess) { |
michael@0 | 836 | goto loser; |
michael@0 | 837 | } |
michael@0 | 838 | rv = ssl3_AppendHandshakeNumber(ss, extension_length - 4, 2); |
michael@0 | 839 | if (rv != SECSuccess) { |
michael@0 | 840 | goto loser; |
michael@0 | 841 | } |
michael@0 | 842 | rv = ssl3_AppendHandshakeVariable(ss, alpn_protos, len, 2); |
michael@0 | 843 | PORT_Free(alpn_protos); |
michael@0 | 844 | alpn_protos = NULL; |
michael@0 | 845 | if (rv != SECSuccess) { |
michael@0 | 846 | goto loser; |
michael@0 | 847 | } |
michael@0 | 848 | ss->xtnData.advertised[ss->xtnData.numAdvertised++] = |
michael@0 | 849 | ssl_app_layer_protocol_xtn; |
michael@0 | 850 | } else if (maxBytes < extension_length) { |
michael@0 | 851 | return 0; |
michael@0 | 852 | } |
michael@0 | 853 | |
michael@0 | 854 | return extension_length; |
michael@0 | 855 | |
michael@0 | 856 | loser: |
michael@0 | 857 | if (alpn_protos) { |
michael@0 | 858 | PORT_Free(alpn_protos); |
michael@0 | 859 | } |
michael@0 | 860 | return -1; |
michael@0 | 861 | } |
michael@0 | 862 | |
michael@0 | 863 | static PRInt32 |
michael@0 | 864 | ssl3_ServerSendAppProtoXtn(sslSocket * ss, PRBool append, PRUint32 maxBytes) |
michael@0 | 865 | { |
michael@0 | 866 | PRInt32 extension_length; |
michael@0 | 867 | |
michael@0 | 868 | /* we're in over our heads if any of these fail */ |
michael@0 | 869 | PORT_Assert(ss->opt.enableALPN); |
michael@0 | 870 | PORT_Assert(ss->ssl3.nextProto.data); |
michael@0 | 871 | PORT_Assert(ss->ssl3.nextProto.len > 0); |
michael@0 | 872 | PORT_Assert(ss->ssl3.nextProtoState == SSL_NEXT_PROTO_NEGOTIATED); |
michael@0 | 873 | PORT_Assert(!ss->firstHsDone); |
michael@0 | 874 | |
michael@0 | 875 | extension_length = 2 /* extension type */ + 2 /* extension length */ + |
michael@0 | 876 | 2 /* protocol name list */ + 1 /* name length */ + |
michael@0 | 877 | ss->ssl3.nextProto.len; |
michael@0 | 878 | |
michael@0 | 879 | if (append && maxBytes >= extension_length) { |
michael@0 | 880 | SECStatus rv; |
michael@0 | 881 | rv = ssl3_AppendHandshakeNumber(ss, ssl_app_layer_protocol_xtn, 2); |
michael@0 | 882 | if (rv != SECSuccess) { |
michael@0 | 883 | return -1; |
michael@0 | 884 | } |
michael@0 | 885 | rv = ssl3_AppendHandshakeNumber(ss, extension_length - 4, 2); |
michael@0 | 886 | if (rv != SECSuccess) { |
michael@0 | 887 | return -1; |
michael@0 | 888 | } |
michael@0 | 889 | rv = ssl3_AppendHandshakeNumber(ss, ss->ssl3.nextProto.len + 1, 2); |
michael@0 | 890 | if (rv != SECSuccess) { |
michael@0 | 891 | return -1; |
michael@0 | 892 | } |
michael@0 | 893 | rv = ssl3_AppendHandshakeVariable(ss, ss->ssl3.nextProto.data, |
michael@0 | 894 | ss->ssl3.nextProto.len, 1); |
michael@0 | 895 | if (rv != SECSuccess) { |
michael@0 | 896 | return -1; |
michael@0 | 897 | } |
michael@0 | 898 | } else if (maxBytes < extension_length) { |
michael@0 | 899 | return 0; |
michael@0 | 900 | } |
michael@0 | 901 | |
michael@0 | 902 | return extension_length; |
michael@0 | 903 | } |
michael@0 | 904 | |
michael@0 | 905 | static SECStatus |
michael@0 | 906 | ssl3_ClientHandleStatusRequestXtn(sslSocket *ss, PRUint16 ex_type, |
michael@0 | 907 | SECItem *data) |
michael@0 | 908 | { |
michael@0 | 909 | /* The echoed extension must be empty. */ |
michael@0 | 910 | if (data->len != 0) |
michael@0 | 911 | return SECFailure; |
michael@0 | 912 | |
michael@0 | 913 | /* Keep track of negotiated extensions. */ |
michael@0 | 914 | ss->xtnData.negotiated[ss->xtnData.numNegotiated++] = ex_type; |
michael@0 | 915 | |
michael@0 | 916 | return SECSuccess; |
michael@0 | 917 | } |
michael@0 | 918 | |
michael@0 | 919 | static PRInt32 |
michael@0 | 920 | ssl3_ServerSendStatusRequestXtn( |
michael@0 | 921 | sslSocket * ss, |
michael@0 | 922 | PRBool append, |
michael@0 | 923 | PRUint32 maxBytes) |
michael@0 | 924 | { |
michael@0 | 925 | PRInt32 extension_length; |
michael@0 | 926 | SECStatus rv; |
michael@0 | 927 | int i; |
michael@0 | 928 | PRBool haveStatus = PR_FALSE; |
michael@0 | 929 | |
michael@0 | 930 | for (i = kt_null; i < kt_kea_size; i++) { |
michael@0 | 931 | /* TODO: This is a temporary workaround. |
michael@0 | 932 | * The correct code needs to see if we have an OCSP response for |
michael@0 | 933 | * the server certificate being used, rather than if we have any |
michael@0 | 934 | * OCSP response. See also ssl3_SendCertificateStatus. |
michael@0 | 935 | */ |
michael@0 | 936 | if (ss->certStatusArray[i] && ss->certStatusArray[i]->len) { |
michael@0 | 937 | haveStatus = PR_TRUE; |
michael@0 | 938 | break; |
michael@0 | 939 | } |
michael@0 | 940 | } |
michael@0 | 941 | if (!haveStatus) |
michael@0 | 942 | return 0; |
michael@0 | 943 | |
michael@0 | 944 | extension_length = 2 + 2; |
michael@0 | 945 | if (append && maxBytes >= extension_length) { |
michael@0 | 946 | /* extension_type */ |
michael@0 | 947 | rv = ssl3_AppendHandshakeNumber(ss, ssl_cert_status_xtn, 2); |
michael@0 | 948 | if (rv != SECSuccess) |
michael@0 | 949 | return -1; |
michael@0 | 950 | /* length of extension_data */ |
michael@0 | 951 | rv = ssl3_AppendHandshakeNumber(ss, 0, 2); |
michael@0 | 952 | if (rv != SECSuccess) |
michael@0 | 953 | return -1; |
michael@0 | 954 | } |
michael@0 | 955 | |
michael@0 | 956 | return extension_length; |
michael@0 | 957 | } |
michael@0 | 958 | |
michael@0 | 959 | /* ssl3_ClientSendStatusRequestXtn builds the status_request extension on the |
michael@0 | 960 | * client side. See RFC 4366 section 3.6. */ |
michael@0 | 961 | static PRInt32 |
michael@0 | 962 | ssl3_ClientSendStatusRequestXtn(sslSocket * ss, PRBool append, |
michael@0 | 963 | PRUint32 maxBytes) |
michael@0 | 964 | { |
michael@0 | 965 | PRInt32 extension_length; |
michael@0 | 966 | |
michael@0 | 967 | if (!ss->opt.enableOCSPStapling) |
michael@0 | 968 | return 0; |
michael@0 | 969 | |
michael@0 | 970 | /* extension_type (2-bytes) + |
michael@0 | 971 | * length(extension_data) (2-bytes) + |
michael@0 | 972 | * status_type (1) + |
michael@0 | 973 | * responder_id_list length (2) + |
michael@0 | 974 | * request_extensions length (2) |
michael@0 | 975 | */ |
michael@0 | 976 | extension_length = 9; |
michael@0 | 977 | |
michael@0 | 978 | if (append && maxBytes >= extension_length) { |
michael@0 | 979 | SECStatus rv; |
michael@0 | 980 | TLSExtensionData *xtnData; |
michael@0 | 981 | |
michael@0 | 982 | /* extension_type */ |
michael@0 | 983 | rv = ssl3_AppendHandshakeNumber(ss, ssl_cert_status_xtn, 2); |
michael@0 | 984 | if (rv != SECSuccess) |
michael@0 | 985 | return -1; |
michael@0 | 986 | rv = ssl3_AppendHandshakeNumber(ss, extension_length - 4, 2); |
michael@0 | 987 | if (rv != SECSuccess) |
michael@0 | 988 | return -1; |
michael@0 | 989 | rv = ssl3_AppendHandshakeNumber(ss, 1 /* status_type ocsp */, 1); |
michael@0 | 990 | if (rv != SECSuccess) |
michael@0 | 991 | return -1; |
michael@0 | 992 | /* A zero length responder_id_list means that the responders are |
michael@0 | 993 | * implicitly known to the server. */ |
michael@0 | 994 | rv = ssl3_AppendHandshakeNumber(ss, 0, 2); |
michael@0 | 995 | if (rv != SECSuccess) |
michael@0 | 996 | return -1; |
michael@0 | 997 | /* A zero length request_extensions means that there are no extensions. |
michael@0 | 998 | * Specifically, we don't set the id-pkix-ocsp-nonce extension. This |
michael@0 | 999 | * means that the server can replay a cached OCSP response to us. */ |
michael@0 | 1000 | rv = ssl3_AppendHandshakeNumber(ss, 0, 2); |
michael@0 | 1001 | if (rv != SECSuccess) |
michael@0 | 1002 | return -1; |
michael@0 | 1003 | |
michael@0 | 1004 | xtnData = &ss->xtnData; |
michael@0 | 1005 | xtnData->advertised[xtnData->numAdvertised++] = ssl_cert_status_xtn; |
michael@0 | 1006 | } else if (maxBytes < extension_length) { |
michael@0 | 1007 | PORT_Assert(0); |
michael@0 | 1008 | return 0; |
michael@0 | 1009 | } |
michael@0 | 1010 | return extension_length; |
michael@0 | 1011 | } |
michael@0 | 1012 | |
michael@0 | 1013 | /* |
michael@0 | 1014 | * NewSessionTicket |
michael@0 | 1015 | * Called from ssl3_HandleFinished |
michael@0 | 1016 | */ |
michael@0 | 1017 | SECStatus |
michael@0 | 1018 | ssl3_SendNewSessionTicket(sslSocket *ss) |
michael@0 | 1019 | { |
michael@0 | 1020 | int i; |
michael@0 | 1021 | SECStatus rv; |
michael@0 | 1022 | NewSessionTicket ticket; |
michael@0 | 1023 | SECItem plaintext; |
michael@0 | 1024 | SECItem plaintext_item = {0, NULL, 0}; |
michael@0 | 1025 | SECItem ciphertext = {0, NULL, 0}; |
michael@0 | 1026 | PRUint32 ciphertext_length; |
michael@0 | 1027 | PRBool ms_is_wrapped; |
michael@0 | 1028 | unsigned char wrapped_ms[SSL3_MASTER_SECRET_LENGTH]; |
michael@0 | 1029 | SECItem ms_item = {0, NULL, 0}; |
michael@0 | 1030 | SSL3KEAType effectiveExchKeyType = ssl_kea_null; |
michael@0 | 1031 | PRUint32 padding_length; |
michael@0 | 1032 | PRUint32 message_length; |
michael@0 | 1033 | PRUint32 cert_length; |
michael@0 | 1034 | PRUint8 length_buf[4]; |
michael@0 | 1035 | PRUint32 now; |
michael@0 | 1036 | PK11SymKey *aes_key_pkcs11; |
michael@0 | 1037 | PK11SymKey *mac_key_pkcs11; |
michael@0 | 1038 | #ifndef NO_PKCS11_BYPASS |
michael@0 | 1039 | const unsigned char *aes_key; |
michael@0 | 1040 | const unsigned char *mac_key; |
michael@0 | 1041 | PRUint32 aes_key_length; |
michael@0 | 1042 | PRUint32 mac_key_length; |
michael@0 | 1043 | PRUint64 aes_ctx_buf[MAX_CIPHER_CONTEXT_LLONGS]; |
michael@0 | 1044 | AESContext *aes_ctx; |
michael@0 | 1045 | const SECHashObject *hashObj = NULL; |
michael@0 | 1046 | PRUint64 hmac_ctx_buf[MAX_MAC_CONTEXT_LLONGS]; |
michael@0 | 1047 | HMACContext *hmac_ctx; |
michael@0 | 1048 | #endif |
michael@0 | 1049 | CK_MECHANISM_TYPE cipherMech = CKM_AES_CBC; |
michael@0 | 1050 | PK11Context *aes_ctx_pkcs11; |
michael@0 | 1051 | CK_MECHANISM_TYPE macMech = CKM_SHA256_HMAC; |
michael@0 | 1052 | PK11Context *hmac_ctx_pkcs11; |
michael@0 | 1053 | unsigned char computed_mac[TLS_EX_SESS_TICKET_MAC_LENGTH]; |
michael@0 | 1054 | unsigned int computed_mac_length; |
michael@0 | 1055 | unsigned char iv[AES_BLOCK_SIZE]; |
michael@0 | 1056 | SECItem ivItem; |
michael@0 | 1057 | SECItem *srvName = NULL; |
michael@0 | 1058 | PRUint32 srvNameLen = 0; |
michael@0 | 1059 | CK_MECHANISM_TYPE msWrapMech = 0; /* dummy default value, |
michael@0 | 1060 | * must be >= 0 */ |
michael@0 | 1061 | |
michael@0 | 1062 | SSL_TRC(3, ("%d: SSL3[%d]: send session_ticket handshake", |
michael@0 | 1063 | SSL_GETPID(), ss->fd)); |
michael@0 | 1064 | |
michael@0 | 1065 | PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss)); |
michael@0 | 1066 | PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss)); |
michael@0 | 1067 | |
michael@0 | 1068 | ticket.ticket_lifetime_hint = TLS_EX_SESS_TICKET_LIFETIME_HINT; |
michael@0 | 1069 | cert_length = (ss->opt.requestCertificate && ss->sec.ci.sid->peerCert) ? |
michael@0 | 1070 | 3 + ss->sec.ci.sid->peerCert->derCert.len : 0; |
michael@0 | 1071 | |
michael@0 | 1072 | /* Get IV and encryption keys */ |
michael@0 | 1073 | ivItem.data = iv; |
michael@0 | 1074 | ivItem.len = sizeof(iv); |
michael@0 | 1075 | rv = PK11_GenerateRandom(iv, sizeof(iv)); |
michael@0 | 1076 | if (rv != SECSuccess) goto loser; |
michael@0 | 1077 | |
michael@0 | 1078 | #ifndef NO_PKCS11_BYPASS |
michael@0 | 1079 | if (ss->opt.bypassPKCS11) { |
michael@0 | 1080 | rv = ssl3_GetSessionTicketKeys(&aes_key, &aes_key_length, |
michael@0 | 1081 | &mac_key, &mac_key_length); |
michael@0 | 1082 | } else |
michael@0 | 1083 | #endif |
michael@0 | 1084 | { |
michael@0 | 1085 | rv = ssl3_GetSessionTicketKeysPKCS11(ss, &aes_key_pkcs11, |
michael@0 | 1086 | &mac_key_pkcs11); |
michael@0 | 1087 | } |
michael@0 | 1088 | if (rv != SECSuccess) goto loser; |
michael@0 | 1089 | |
michael@0 | 1090 | if (ss->ssl3.pwSpec->msItem.len && ss->ssl3.pwSpec->msItem.data) { |
michael@0 | 1091 | /* The master secret is available unwrapped. */ |
michael@0 | 1092 | ms_item.data = ss->ssl3.pwSpec->msItem.data; |
michael@0 | 1093 | ms_item.len = ss->ssl3.pwSpec->msItem.len; |
michael@0 | 1094 | ms_is_wrapped = PR_FALSE; |
michael@0 | 1095 | } else { |
michael@0 | 1096 | /* Extract the master secret wrapped. */ |
michael@0 | 1097 | sslSessionID sid; |
michael@0 | 1098 | PORT_Memset(&sid, 0, sizeof(sslSessionID)); |
michael@0 | 1099 | |
michael@0 | 1100 | if (ss->ssl3.hs.kea_def->kea == kea_ecdhe_rsa) { |
michael@0 | 1101 | effectiveExchKeyType = kt_rsa; |
michael@0 | 1102 | } else { |
michael@0 | 1103 | effectiveExchKeyType = ss->ssl3.hs.kea_def->exchKeyType; |
michael@0 | 1104 | } |
michael@0 | 1105 | |
michael@0 | 1106 | rv = ssl3_CacheWrappedMasterSecret(ss, &sid, ss->ssl3.pwSpec, |
michael@0 | 1107 | effectiveExchKeyType); |
michael@0 | 1108 | if (rv == SECSuccess) { |
michael@0 | 1109 | if (sid.u.ssl3.keys.wrapped_master_secret_len > sizeof(wrapped_ms)) |
michael@0 | 1110 | goto loser; |
michael@0 | 1111 | memcpy(wrapped_ms, sid.u.ssl3.keys.wrapped_master_secret, |
michael@0 | 1112 | sid.u.ssl3.keys.wrapped_master_secret_len); |
michael@0 | 1113 | ms_item.data = wrapped_ms; |
michael@0 | 1114 | ms_item.len = sid.u.ssl3.keys.wrapped_master_secret_len; |
michael@0 | 1115 | msWrapMech = sid.u.ssl3.masterWrapMech; |
michael@0 | 1116 | } else { |
michael@0 | 1117 | /* TODO: else send an empty ticket. */ |
michael@0 | 1118 | goto loser; |
michael@0 | 1119 | } |
michael@0 | 1120 | ms_is_wrapped = PR_TRUE; |
michael@0 | 1121 | } |
michael@0 | 1122 | /* Prep to send negotiated name */ |
michael@0 | 1123 | srvName = &ss->ssl3.pwSpec->srvVirtName; |
michael@0 | 1124 | if (srvName->data && srvName->len) { |
michael@0 | 1125 | srvNameLen = 2 + srvName->len; /* len bytes + name len */ |
michael@0 | 1126 | } |
michael@0 | 1127 | |
michael@0 | 1128 | ciphertext_length = |
michael@0 | 1129 | sizeof(PRUint16) /* ticket_version */ |
michael@0 | 1130 | + sizeof(SSL3ProtocolVersion) /* ssl_version */ |
michael@0 | 1131 | + sizeof(ssl3CipherSuite) /* ciphersuite */ |
michael@0 | 1132 | + 1 /* compression */ |
michael@0 | 1133 | + 10 /* cipher spec parameters */ |
michael@0 | 1134 | + 1 /* SessionTicket.ms_is_wrapped */ |
michael@0 | 1135 | + 1 /* effectiveExchKeyType */ |
michael@0 | 1136 | + 4 /* msWrapMech */ |
michael@0 | 1137 | + 2 /* master_secret.length */ |
michael@0 | 1138 | + ms_item.len /* master_secret */ |
michael@0 | 1139 | + 1 /* client_auth_type */ |
michael@0 | 1140 | + cert_length /* cert */ |
michael@0 | 1141 | + 1 /* server name type */ |
michael@0 | 1142 | + srvNameLen /* name len + length field */ |
michael@0 | 1143 | + sizeof(ticket.ticket_lifetime_hint); |
michael@0 | 1144 | padding_length = AES_BLOCK_SIZE - |
michael@0 | 1145 | (ciphertext_length % AES_BLOCK_SIZE); |
michael@0 | 1146 | ciphertext_length += padding_length; |
michael@0 | 1147 | |
michael@0 | 1148 | message_length = |
michael@0 | 1149 | sizeof(ticket.ticket_lifetime_hint) /* ticket_lifetime_hint */ |
michael@0 | 1150 | + 2 /* length field for NewSessionTicket.ticket */ |
michael@0 | 1151 | + SESS_TICKET_KEY_NAME_LEN /* key_name */ |
michael@0 | 1152 | + AES_BLOCK_SIZE /* iv */ |
michael@0 | 1153 | + 2 /* length field for NewSessionTicket.ticket.encrypted_state */ |
michael@0 | 1154 | + ciphertext_length /* encrypted_state */ |
michael@0 | 1155 | + TLS_EX_SESS_TICKET_MAC_LENGTH; /* mac */ |
michael@0 | 1156 | |
michael@0 | 1157 | if (SECITEM_AllocItem(NULL, &plaintext_item, ciphertext_length) == NULL) |
michael@0 | 1158 | goto loser; |
michael@0 | 1159 | |
michael@0 | 1160 | plaintext = plaintext_item; |
michael@0 | 1161 | |
michael@0 | 1162 | /* ticket_version */ |
michael@0 | 1163 | rv = ssl3_AppendNumberToItem(&plaintext, TLS_EX_SESS_TICKET_VERSION, |
michael@0 | 1164 | sizeof(PRUint16)); |
michael@0 | 1165 | if (rv != SECSuccess) goto loser; |
michael@0 | 1166 | |
michael@0 | 1167 | /* ssl_version */ |
michael@0 | 1168 | rv = ssl3_AppendNumberToItem(&plaintext, ss->version, |
michael@0 | 1169 | sizeof(SSL3ProtocolVersion)); |
michael@0 | 1170 | if (rv != SECSuccess) goto loser; |
michael@0 | 1171 | |
michael@0 | 1172 | /* ciphersuite */ |
michael@0 | 1173 | rv = ssl3_AppendNumberToItem(&plaintext, ss->ssl3.hs.cipher_suite, |
michael@0 | 1174 | sizeof(ssl3CipherSuite)); |
michael@0 | 1175 | if (rv != SECSuccess) goto loser; |
michael@0 | 1176 | |
michael@0 | 1177 | /* compression */ |
michael@0 | 1178 | rv = ssl3_AppendNumberToItem(&plaintext, ss->ssl3.hs.compression, 1); |
michael@0 | 1179 | if (rv != SECSuccess) goto loser; |
michael@0 | 1180 | |
michael@0 | 1181 | /* cipher spec parameters */ |
michael@0 | 1182 | rv = ssl3_AppendNumberToItem(&plaintext, ss->sec.authAlgorithm, 1); |
michael@0 | 1183 | if (rv != SECSuccess) goto loser; |
michael@0 | 1184 | rv = ssl3_AppendNumberToItem(&plaintext, ss->sec.authKeyBits, 4); |
michael@0 | 1185 | if (rv != SECSuccess) goto loser; |
michael@0 | 1186 | rv = ssl3_AppendNumberToItem(&plaintext, ss->sec.keaType, 1); |
michael@0 | 1187 | if (rv != SECSuccess) goto loser; |
michael@0 | 1188 | rv = ssl3_AppendNumberToItem(&plaintext, ss->sec.keaKeyBits, 4); |
michael@0 | 1189 | if (rv != SECSuccess) goto loser; |
michael@0 | 1190 | |
michael@0 | 1191 | /* master_secret */ |
michael@0 | 1192 | rv = ssl3_AppendNumberToItem(&plaintext, ms_is_wrapped, 1); |
michael@0 | 1193 | if (rv != SECSuccess) goto loser; |
michael@0 | 1194 | rv = ssl3_AppendNumberToItem(&plaintext, effectiveExchKeyType, 1); |
michael@0 | 1195 | if (rv != SECSuccess) goto loser; |
michael@0 | 1196 | rv = ssl3_AppendNumberToItem(&plaintext, msWrapMech, 4); |
michael@0 | 1197 | if (rv != SECSuccess) goto loser; |
michael@0 | 1198 | rv = ssl3_AppendNumberToItem(&plaintext, ms_item.len, 2); |
michael@0 | 1199 | if (rv != SECSuccess) goto loser; |
michael@0 | 1200 | rv = ssl3_AppendToItem(&plaintext, ms_item.data, ms_item.len); |
michael@0 | 1201 | if (rv != SECSuccess) goto loser; |
michael@0 | 1202 | |
michael@0 | 1203 | /* client_identity */ |
michael@0 | 1204 | if (ss->opt.requestCertificate && ss->sec.ci.sid->peerCert) { |
michael@0 | 1205 | rv = ssl3_AppendNumberToItem(&plaintext, CLIENT_AUTH_CERTIFICATE, 1); |
michael@0 | 1206 | if (rv != SECSuccess) goto loser; |
michael@0 | 1207 | rv = ssl3_AppendNumberToItem(&plaintext, |
michael@0 | 1208 | ss->sec.ci.sid->peerCert->derCert.len, 3); |
michael@0 | 1209 | if (rv != SECSuccess) goto loser; |
michael@0 | 1210 | rv = ssl3_AppendToItem(&plaintext, |
michael@0 | 1211 | ss->sec.ci.sid->peerCert->derCert.data, |
michael@0 | 1212 | ss->sec.ci.sid->peerCert->derCert.len); |
michael@0 | 1213 | if (rv != SECSuccess) goto loser; |
michael@0 | 1214 | } else { |
michael@0 | 1215 | rv = ssl3_AppendNumberToItem(&plaintext, 0, 1); |
michael@0 | 1216 | if (rv != SECSuccess) goto loser; |
michael@0 | 1217 | } |
michael@0 | 1218 | |
michael@0 | 1219 | /* timestamp */ |
michael@0 | 1220 | now = ssl_Time(); |
michael@0 | 1221 | rv = ssl3_AppendNumberToItem(&plaintext, now, |
michael@0 | 1222 | sizeof(ticket.ticket_lifetime_hint)); |
michael@0 | 1223 | if (rv != SECSuccess) goto loser; |
michael@0 | 1224 | |
michael@0 | 1225 | if (srvNameLen) { |
michael@0 | 1226 | /* Name Type (sni_host_name) */ |
michael@0 | 1227 | rv = ssl3_AppendNumberToItem(&plaintext, srvName->type, 1); |
michael@0 | 1228 | if (rv != SECSuccess) goto loser; |
michael@0 | 1229 | /* HostName (length and value) */ |
michael@0 | 1230 | rv = ssl3_AppendNumberToItem(&plaintext, srvName->len, 2); |
michael@0 | 1231 | if (rv != SECSuccess) goto loser; |
michael@0 | 1232 | rv = ssl3_AppendToItem(&plaintext, srvName->data, srvName->len); |
michael@0 | 1233 | if (rv != SECSuccess) goto loser; |
michael@0 | 1234 | } else { |
michael@0 | 1235 | /* No Name */ |
michael@0 | 1236 | rv = ssl3_AppendNumberToItem(&plaintext, (char)TLS_STE_NO_SERVER_NAME, |
michael@0 | 1237 | 1); |
michael@0 | 1238 | if (rv != SECSuccess) goto loser; |
michael@0 | 1239 | } |
michael@0 | 1240 | |
michael@0 | 1241 | PORT_Assert(plaintext.len == padding_length); |
michael@0 | 1242 | for (i = 0; i < padding_length; i++) |
michael@0 | 1243 | plaintext.data[i] = (unsigned char)padding_length; |
michael@0 | 1244 | |
michael@0 | 1245 | if (SECITEM_AllocItem(NULL, &ciphertext, ciphertext_length) == NULL) { |
michael@0 | 1246 | rv = SECFailure; |
michael@0 | 1247 | goto loser; |
michael@0 | 1248 | } |
michael@0 | 1249 | |
michael@0 | 1250 | /* Generate encrypted portion of ticket. */ |
michael@0 | 1251 | #ifndef NO_PKCS11_BYPASS |
michael@0 | 1252 | if (ss->opt.bypassPKCS11) { |
michael@0 | 1253 | aes_ctx = (AESContext *)aes_ctx_buf; |
michael@0 | 1254 | rv = AES_InitContext(aes_ctx, aes_key, aes_key_length, iv, |
michael@0 | 1255 | NSS_AES_CBC, 1, AES_BLOCK_SIZE); |
michael@0 | 1256 | if (rv != SECSuccess) goto loser; |
michael@0 | 1257 | |
michael@0 | 1258 | rv = AES_Encrypt(aes_ctx, ciphertext.data, &ciphertext.len, |
michael@0 | 1259 | ciphertext.len, plaintext_item.data, |
michael@0 | 1260 | plaintext_item.len); |
michael@0 | 1261 | if (rv != SECSuccess) goto loser; |
michael@0 | 1262 | } else |
michael@0 | 1263 | #endif |
michael@0 | 1264 | { |
michael@0 | 1265 | aes_ctx_pkcs11 = PK11_CreateContextBySymKey(cipherMech, |
michael@0 | 1266 | CKA_ENCRYPT, aes_key_pkcs11, &ivItem); |
michael@0 | 1267 | if (!aes_ctx_pkcs11) |
michael@0 | 1268 | goto loser; |
michael@0 | 1269 | |
michael@0 | 1270 | rv = PK11_CipherOp(aes_ctx_pkcs11, ciphertext.data, |
michael@0 | 1271 | (int *)&ciphertext.len, ciphertext.len, |
michael@0 | 1272 | plaintext_item.data, plaintext_item.len); |
michael@0 | 1273 | PK11_Finalize(aes_ctx_pkcs11); |
michael@0 | 1274 | PK11_DestroyContext(aes_ctx_pkcs11, PR_TRUE); |
michael@0 | 1275 | if (rv != SECSuccess) goto loser; |
michael@0 | 1276 | } |
michael@0 | 1277 | |
michael@0 | 1278 | /* Convert ciphertext length to network order. */ |
michael@0 | 1279 | length_buf[0] = (ciphertext.len >> 8) & 0xff; |
michael@0 | 1280 | length_buf[1] = (ciphertext.len ) & 0xff; |
michael@0 | 1281 | |
michael@0 | 1282 | /* Compute MAC. */ |
michael@0 | 1283 | #ifndef NO_PKCS11_BYPASS |
michael@0 | 1284 | if (ss->opt.bypassPKCS11) { |
michael@0 | 1285 | hmac_ctx = (HMACContext *)hmac_ctx_buf; |
michael@0 | 1286 | hashObj = HASH_GetRawHashObject(HASH_AlgSHA256); |
michael@0 | 1287 | if (HMAC_Init(hmac_ctx, hashObj, mac_key, |
michael@0 | 1288 | mac_key_length, PR_FALSE) != SECSuccess) |
michael@0 | 1289 | goto loser; |
michael@0 | 1290 | |
michael@0 | 1291 | HMAC_Begin(hmac_ctx); |
michael@0 | 1292 | HMAC_Update(hmac_ctx, key_name, SESS_TICKET_KEY_NAME_LEN); |
michael@0 | 1293 | HMAC_Update(hmac_ctx, iv, sizeof(iv)); |
michael@0 | 1294 | HMAC_Update(hmac_ctx, (unsigned char *)length_buf, 2); |
michael@0 | 1295 | HMAC_Update(hmac_ctx, ciphertext.data, ciphertext.len); |
michael@0 | 1296 | HMAC_Finish(hmac_ctx, computed_mac, &computed_mac_length, |
michael@0 | 1297 | sizeof(computed_mac)); |
michael@0 | 1298 | } else |
michael@0 | 1299 | #endif |
michael@0 | 1300 | { |
michael@0 | 1301 | SECItem macParam; |
michael@0 | 1302 | macParam.data = NULL; |
michael@0 | 1303 | macParam.len = 0; |
michael@0 | 1304 | hmac_ctx_pkcs11 = PK11_CreateContextBySymKey(macMech, |
michael@0 | 1305 | CKA_SIGN, mac_key_pkcs11, &macParam); |
michael@0 | 1306 | if (!hmac_ctx_pkcs11) |
michael@0 | 1307 | goto loser; |
michael@0 | 1308 | |
michael@0 | 1309 | rv = PK11_DigestBegin(hmac_ctx_pkcs11); |
michael@0 | 1310 | rv = PK11_DigestOp(hmac_ctx_pkcs11, key_name, |
michael@0 | 1311 | SESS_TICKET_KEY_NAME_LEN); |
michael@0 | 1312 | rv = PK11_DigestOp(hmac_ctx_pkcs11, iv, sizeof(iv)); |
michael@0 | 1313 | rv = PK11_DigestOp(hmac_ctx_pkcs11, (unsigned char *)length_buf, 2); |
michael@0 | 1314 | rv = PK11_DigestOp(hmac_ctx_pkcs11, ciphertext.data, ciphertext.len); |
michael@0 | 1315 | rv = PK11_DigestFinal(hmac_ctx_pkcs11, computed_mac, |
michael@0 | 1316 | &computed_mac_length, sizeof(computed_mac)); |
michael@0 | 1317 | PK11_DestroyContext(hmac_ctx_pkcs11, PR_TRUE); |
michael@0 | 1318 | if (rv != SECSuccess) goto loser; |
michael@0 | 1319 | } |
michael@0 | 1320 | |
michael@0 | 1321 | /* Serialize the handshake message. */ |
michael@0 | 1322 | rv = ssl3_AppendHandshakeHeader(ss, new_session_ticket, message_length); |
michael@0 | 1323 | if (rv != SECSuccess) goto loser; |
michael@0 | 1324 | |
michael@0 | 1325 | rv = ssl3_AppendHandshakeNumber(ss, ticket.ticket_lifetime_hint, |
michael@0 | 1326 | sizeof(ticket.ticket_lifetime_hint)); |
michael@0 | 1327 | if (rv != SECSuccess) goto loser; |
michael@0 | 1328 | |
michael@0 | 1329 | rv = ssl3_AppendHandshakeNumber(ss, |
michael@0 | 1330 | message_length - sizeof(ticket.ticket_lifetime_hint) - 2, 2); |
michael@0 | 1331 | if (rv != SECSuccess) goto loser; |
michael@0 | 1332 | |
michael@0 | 1333 | rv = ssl3_AppendHandshake(ss, key_name, SESS_TICKET_KEY_NAME_LEN); |
michael@0 | 1334 | if (rv != SECSuccess) goto loser; |
michael@0 | 1335 | |
michael@0 | 1336 | rv = ssl3_AppendHandshake(ss, iv, sizeof(iv)); |
michael@0 | 1337 | if (rv != SECSuccess) goto loser; |
michael@0 | 1338 | |
michael@0 | 1339 | rv = ssl3_AppendHandshakeVariable(ss, ciphertext.data, ciphertext.len, 2); |
michael@0 | 1340 | if (rv != SECSuccess) goto loser; |
michael@0 | 1341 | |
michael@0 | 1342 | rv = ssl3_AppendHandshake(ss, computed_mac, computed_mac_length); |
michael@0 | 1343 | if (rv != SECSuccess) goto loser; |
michael@0 | 1344 | |
michael@0 | 1345 | loser: |
michael@0 | 1346 | if (plaintext_item.data) |
michael@0 | 1347 | SECITEM_FreeItem(&plaintext_item, PR_FALSE); |
michael@0 | 1348 | if (ciphertext.data) |
michael@0 | 1349 | SECITEM_FreeItem(&ciphertext, PR_FALSE); |
michael@0 | 1350 | |
michael@0 | 1351 | return rv; |
michael@0 | 1352 | } |
michael@0 | 1353 | |
michael@0 | 1354 | /* When a client receives a SessionTicket extension a NewSessionTicket |
michael@0 | 1355 | * message is expected during the handshake. |
michael@0 | 1356 | */ |
michael@0 | 1357 | SECStatus |
michael@0 | 1358 | ssl3_ClientHandleSessionTicketXtn(sslSocket *ss, PRUint16 ex_type, |
michael@0 | 1359 | SECItem *data) |
michael@0 | 1360 | { |
michael@0 | 1361 | if (data->len != 0) |
michael@0 | 1362 | return SECFailure; |
michael@0 | 1363 | |
michael@0 | 1364 | /* Keep track of negotiated extensions. */ |
michael@0 | 1365 | ss->xtnData.negotiated[ss->xtnData.numNegotiated++] = ex_type; |
michael@0 | 1366 | return SECSuccess; |
michael@0 | 1367 | } |
michael@0 | 1368 | |
michael@0 | 1369 | SECStatus |
michael@0 | 1370 | ssl3_ServerHandleSessionTicketXtn(sslSocket *ss, PRUint16 ex_type, |
michael@0 | 1371 | SECItem *data) |
michael@0 | 1372 | { |
michael@0 | 1373 | SECStatus rv; |
michael@0 | 1374 | SECItem *decrypted_state = NULL; |
michael@0 | 1375 | SessionTicket *parsed_session_ticket = NULL; |
michael@0 | 1376 | sslSessionID *sid = NULL; |
michael@0 | 1377 | SSL3Statistics *ssl3stats; |
michael@0 | 1378 | |
michael@0 | 1379 | /* Ignore the SessionTicket extension if processing is disabled. */ |
michael@0 | 1380 | if (!ss->opt.enableSessionTickets) |
michael@0 | 1381 | return SECSuccess; |
michael@0 | 1382 | |
michael@0 | 1383 | /* Keep track of negotiated extensions. */ |
michael@0 | 1384 | ss->xtnData.negotiated[ss->xtnData.numNegotiated++] = ex_type; |
michael@0 | 1385 | |
michael@0 | 1386 | /* Parse the received ticket sent in by the client. We are |
michael@0 | 1387 | * lenient about some parse errors, falling back to a fullshake |
michael@0 | 1388 | * instead of terminating the current connection. |
michael@0 | 1389 | */ |
michael@0 | 1390 | if (data->len == 0) { |
michael@0 | 1391 | ss->xtnData.emptySessionTicket = PR_TRUE; |
michael@0 | 1392 | } else { |
michael@0 | 1393 | int i; |
michael@0 | 1394 | SECItem extension_data; |
michael@0 | 1395 | EncryptedSessionTicket enc_session_ticket; |
michael@0 | 1396 | unsigned char computed_mac[TLS_EX_SESS_TICKET_MAC_LENGTH]; |
michael@0 | 1397 | unsigned int computed_mac_length; |
michael@0 | 1398 | #ifndef NO_PKCS11_BYPASS |
michael@0 | 1399 | const SECHashObject *hashObj; |
michael@0 | 1400 | const unsigned char *aes_key; |
michael@0 | 1401 | const unsigned char *mac_key; |
michael@0 | 1402 | PRUint32 aes_key_length; |
michael@0 | 1403 | PRUint32 mac_key_length; |
michael@0 | 1404 | PRUint64 hmac_ctx_buf[MAX_MAC_CONTEXT_LLONGS]; |
michael@0 | 1405 | HMACContext *hmac_ctx; |
michael@0 | 1406 | PRUint64 aes_ctx_buf[MAX_CIPHER_CONTEXT_LLONGS]; |
michael@0 | 1407 | AESContext *aes_ctx; |
michael@0 | 1408 | #endif |
michael@0 | 1409 | PK11SymKey *aes_key_pkcs11; |
michael@0 | 1410 | PK11SymKey *mac_key_pkcs11; |
michael@0 | 1411 | PK11Context *hmac_ctx_pkcs11; |
michael@0 | 1412 | CK_MECHANISM_TYPE macMech = CKM_SHA256_HMAC; |
michael@0 | 1413 | PK11Context *aes_ctx_pkcs11; |
michael@0 | 1414 | CK_MECHANISM_TYPE cipherMech = CKM_AES_CBC; |
michael@0 | 1415 | unsigned char * padding; |
michael@0 | 1416 | PRUint32 padding_length; |
michael@0 | 1417 | unsigned char *buffer; |
michael@0 | 1418 | unsigned int buffer_len; |
michael@0 | 1419 | PRInt32 temp; |
michael@0 | 1420 | SECItem cert_item; |
michael@0 | 1421 | PRInt8 nameType = TLS_STE_NO_SERVER_NAME; |
michael@0 | 1422 | |
michael@0 | 1423 | /* Turn off stateless session resumption if the client sends a |
michael@0 | 1424 | * SessionTicket extension, even if the extension turns out to be |
michael@0 | 1425 | * malformed (ss->sec.ci.sid is non-NULL when doing session |
michael@0 | 1426 | * renegotiation.) |
michael@0 | 1427 | */ |
michael@0 | 1428 | if (ss->sec.ci.sid != NULL) { |
michael@0 | 1429 | if (ss->sec.uncache) |
michael@0 | 1430 | ss->sec.uncache(ss->sec.ci.sid); |
michael@0 | 1431 | ssl_FreeSID(ss->sec.ci.sid); |
michael@0 | 1432 | ss->sec.ci.sid = NULL; |
michael@0 | 1433 | } |
michael@0 | 1434 | |
michael@0 | 1435 | extension_data.data = data->data; /* Keep a copy for future use. */ |
michael@0 | 1436 | extension_data.len = data->len; |
michael@0 | 1437 | |
michael@0 | 1438 | if (ssl3_ParseEncryptedSessionTicket(ss, data, &enc_session_ticket) |
michael@0 | 1439 | != SECSuccess) |
michael@0 | 1440 | return SECFailure; |
michael@0 | 1441 | |
michael@0 | 1442 | /* Get session ticket keys. */ |
michael@0 | 1443 | #ifndef NO_PKCS11_BYPASS |
michael@0 | 1444 | if (ss->opt.bypassPKCS11) { |
michael@0 | 1445 | rv = ssl3_GetSessionTicketKeys(&aes_key, &aes_key_length, |
michael@0 | 1446 | &mac_key, &mac_key_length); |
michael@0 | 1447 | } else |
michael@0 | 1448 | #endif |
michael@0 | 1449 | { |
michael@0 | 1450 | rv = ssl3_GetSessionTicketKeysPKCS11(ss, &aes_key_pkcs11, |
michael@0 | 1451 | &mac_key_pkcs11); |
michael@0 | 1452 | } |
michael@0 | 1453 | if (rv != SECSuccess) { |
michael@0 | 1454 | SSL_DBG(("%d: SSL[%d]: Unable to get/generate session ticket keys.", |
michael@0 | 1455 | SSL_GETPID(), ss->fd)); |
michael@0 | 1456 | goto loser; |
michael@0 | 1457 | } |
michael@0 | 1458 | |
michael@0 | 1459 | /* If the ticket sent by the client was generated under a key different |
michael@0 | 1460 | * from the one we have, bypass ticket processing. |
michael@0 | 1461 | */ |
michael@0 | 1462 | if (PORT_Memcmp(enc_session_ticket.key_name, key_name, |
michael@0 | 1463 | SESS_TICKET_KEY_NAME_LEN) != 0) { |
michael@0 | 1464 | SSL_DBG(("%d: SSL[%d]: Session ticket key_name sent mismatch.", |
michael@0 | 1465 | SSL_GETPID(), ss->fd)); |
michael@0 | 1466 | goto no_ticket; |
michael@0 | 1467 | } |
michael@0 | 1468 | |
michael@0 | 1469 | /* Verify the MAC on the ticket. MAC verification may also |
michael@0 | 1470 | * fail if the MAC key has been recently refreshed. |
michael@0 | 1471 | */ |
michael@0 | 1472 | #ifndef NO_PKCS11_BYPASS |
michael@0 | 1473 | if (ss->opt.bypassPKCS11) { |
michael@0 | 1474 | hmac_ctx = (HMACContext *)hmac_ctx_buf; |
michael@0 | 1475 | hashObj = HASH_GetRawHashObject(HASH_AlgSHA256); |
michael@0 | 1476 | if (HMAC_Init(hmac_ctx, hashObj, mac_key, |
michael@0 | 1477 | sizeof(session_ticket_mac_key), PR_FALSE) != SECSuccess) |
michael@0 | 1478 | goto no_ticket; |
michael@0 | 1479 | HMAC_Begin(hmac_ctx); |
michael@0 | 1480 | HMAC_Update(hmac_ctx, extension_data.data, |
michael@0 | 1481 | extension_data.len - TLS_EX_SESS_TICKET_MAC_LENGTH); |
michael@0 | 1482 | if (HMAC_Finish(hmac_ctx, computed_mac, &computed_mac_length, |
michael@0 | 1483 | sizeof(computed_mac)) != SECSuccess) |
michael@0 | 1484 | goto no_ticket; |
michael@0 | 1485 | } else |
michael@0 | 1486 | #endif |
michael@0 | 1487 | { |
michael@0 | 1488 | SECItem macParam; |
michael@0 | 1489 | macParam.data = NULL; |
michael@0 | 1490 | macParam.len = 0; |
michael@0 | 1491 | hmac_ctx_pkcs11 = PK11_CreateContextBySymKey(macMech, |
michael@0 | 1492 | CKA_SIGN, mac_key_pkcs11, &macParam); |
michael@0 | 1493 | if (!hmac_ctx_pkcs11) { |
michael@0 | 1494 | SSL_DBG(("%d: SSL[%d]: Unable to create HMAC context: %d.", |
michael@0 | 1495 | SSL_GETPID(), ss->fd, PORT_GetError())); |
michael@0 | 1496 | goto no_ticket; |
michael@0 | 1497 | } else { |
michael@0 | 1498 | SSL_DBG(("%d: SSL[%d]: Successfully created HMAC context.", |
michael@0 | 1499 | SSL_GETPID(), ss->fd)); |
michael@0 | 1500 | } |
michael@0 | 1501 | rv = PK11_DigestBegin(hmac_ctx_pkcs11); |
michael@0 | 1502 | rv = PK11_DigestOp(hmac_ctx_pkcs11, extension_data.data, |
michael@0 | 1503 | extension_data.len - TLS_EX_SESS_TICKET_MAC_LENGTH); |
michael@0 | 1504 | if (rv != SECSuccess) { |
michael@0 | 1505 | PK11_DestroyContext(hmac_ctx_pkcs11, PR_TRUE); |
michael@0 | 1506 | goto no_ticket; |
michael@0 | 1507 | } |
michael@0 | 1508 | rv = PK11_DigestFinal(hmac_ctx_pkcs11, computed_mac, |
michael@0 | 1509 | &computed_mac_length, sizeof(computed_mac)); |
michael@0 | 1510 | PK11_DestroyContext(hmac_ctx_pkcs11, PR_TRUE); |
michael@0 | 1511 | if (rv != SECSuccess) |
michael@0 | 1512 | goto no_ticket; |
michael@0 | 1513 | } |
michael@0 | 1514 | if (NSS_SecureMemcmp(computed_mac, enc_session_ticket.mac, |
michael@0 | 1515 | computed_mac_length) != 0) { |
michael@0 | 1516 | SSL_DBG(("%d: SSL[%d]: Session ticket MAC mismatch.", |
michael@0 | 1517 | SSL_GETPID(), ss->fd)); |
michael@0 | 1518 | goto no_ticket; |
michael@0 | 1519 | } |
michael@0 | 1520 | |
michael@0 | 1521 | /* We ignore key_name for now. |
michael@0 | 1522 | * This is ok as MAC verification succeeded. |
michael@0 | 1523 | */ |
michael@0 | 1524 | |
michael@0 | 1525 | /* Decrypt the ticket. */ |
michael@0 | 1526 | |
michael@0 | 1527 | /* Plaintext is shorter than the ciphertext due to padding. */ |
michael@0 | 1528 | decrypted_state = SECITEM_AllocItem(NULL, NULL, |
michael@0 | 1529 | enc_session_ticket.encrypted_state.len); |
michael@0 | 1530 | |
michael@0 | 1531 | #ifndef NO_PKCS11_BYPASS |
michael@0 | 1532 | if (ss->opt.bypassPKCS11) { |
michael@0 | 1533 | aes_ctx = (AESContext *)aes_ctx_buf; |
michael@0 | 1534 | rv = AES_InitContext(aes_ctx, aes_key, |
michael@0 | 1535 | sizeof(session_ticket_enc_key), enc_session_ticket.iv, |
michael@0 | 1536 | NSS_AES_CBC, 0,AES_BLOCK_SIZE); |
michael@0 | 1537 | if (rv != SECSuccess) { |
michael@0 | 1538 | SSL_DBG(("%d: SSL[%d]: Unable to create AES context.", |
michael@0 | 1539 | SSL_GETPID(), ss->fd)); |
michael@0 | 1540 | goto no_ticket; |
michael@0 | 1541 | } |
michael@0 | 1542 | |
michael@0 | 1543 | rv = AES_Decrypt(aes_ctx, decrypted_state->data, |
michael@0 | 1544 | &decrypted_state->len, decrypted_state->len, |
michael@0 | 1545 | enc_session_ticket.encrypted_state.data, |
michael@0 | 1546 | enc_session_ticket.encrypted_state.len); |
michael@0 | 1547 | if (rv != SECSuccess) |
michael@0 | 1548 | goto no_ticket; |
michael@0 | 1549 | } else |
michael@0 | 1550 | #endif |
michael@0 | 1551 | { |
michael@0 | 1552 | SECItem ivItem; |
michael@0 | 1553 | ivItem.data = enc_session_ticket.iv; |
michael@0 | 1554 | ivItem.len = AES_BLOCK_SIZE; |
michael@0 | 1555 | aes_ctx_pkcs11 = PK11_CreateContextBySymKey(cipherMech, |
michael@0 | 1556 | CKA_DECRYPT, aes_key_pkcs11, &ivItem); |
michael@0 | 1557 | if (!aes_ctx_pkcs11) { |
michael@0 | 1558 | SSL_DBG(("%d: SSL[%d]: Unable to create AES context.", |
michael@0 | 1559 | SSL_GETPID(), ss->fd)); |
michael@0 | 1560 | goto no_ticket; |
michael@0 | 1561 | } |
michael@0 | 1562 | |
michael@0 | 1563 | rv = PK11_CipherOp(aes_ctx_pkcs11, decrypted_state->data, |
michael@0 | 1564 | (int *)&decrypted_state->len, decrypted_state->len, |
michael@0 | 1565 | enc_session_ticket.encrypted_state.data, |
michael@0 | 1566 | enc_session_ticket.encrypted_state.len); |
michael@0 | 1567 | PK11_Finalize(aes_ctx_pkcs11); |
michael@0 | 1568 | PK11_DestroyContext(aes_ctx_pkcs11, PR_TRUE); |
michael@0 | 1569 | if (rv != SECSuccess) |
michael@0 | 1570 | goto no_ticket; |
michael@0 | 1571 | } |
michael@0 | 1572 | |
michael@0 | 1573 | /* Check padding. */ |
michael@0 | 1574 | padding_length = |
michael@0 | 1575 | (PRUint32)decrypted_state->data[decrypted_state->len - 1]; |
michael@0 | 1576 | if (padding_length == 0 || padding_length > AES_BLOCK_SIZE) |
michael@0 | 1577 | goto no_ticket; |
michael@0 | 1578 | |
michael@0 | 1579 | padding = &decrypted_state->data[decrypted_state->len - padding_length]; |
michael@0 | 1580 | for (i = 0; i < padding_length; i++, padding++) { |
michael@0 | 1581 | if (padding_length != (PRUint32)*padding) |
michael@0 | 1582 | goto no_ticket; |
michael@0 | 1583 | } |
michael@0 | 1584 | |
michael@0 | 1585 | /* Deserialize session state. */ |
michael@0 | 1586 | buffer = decrypted_state->data; |
michael@0 | 1587 | buffer_len = decrypted_state->len; |
michael@0 | 1588 | |
michael@0 | 1589 | parsed_session_ticket = PORT_ZAlloc(sizeof(SessionTicket)); |
michael@0 | 1590 | if (parsed_session_ticket == NULL) { |
michael@0 | 1591 | rv = SECFailure; |
michael@0 | 1592 | goto loser; |
michael@0 | 1593 | } |
michael@0 | 1594 | |
michael@0 | 1595 | /* Read ticket_version (which is ignored for now.) */ |
michael@0 | 1596 | temp = ssl3_ConsumeHandshakeNumber(ss, 2, &buffer, &buffer_len); |
michael@0 | 1597 | if (temp < 0) goto no_ticket; |
michael@0 | 1598 | parsed_session_ticket->ticket_version = (SSL3ProtocolVersion)temp; |
michael@0 | 1599 | |
michael@0 | 1600 | /* Read SSLVersion. */ |
michael@0 | 1601 | temp = ssl3_ConsumeHandshakeNumber(ss, 2, &buffer, &buffer_len); |
michael@0 | 1602 | if (temp < 0) goto no_ticket; |
michael@0 | 1603 | parsed_session_ticket->ssl_version = (SSL3ProtocolVersion)temp; |
michael@0 | 1604 | |
michael@0 | 1605 | /* Read cipher_suite. */ |
michael@0 | 1606 | temp = ssl3_ConsumeHandshakeNumber(ss, 2, &buffer, &buffer_len); |
michael@0 | 1607 | if (temp < 0) goto no_ticket; |
michael@0 | 1608 | parsed_session_ticket->cipher_suite = (ssl3CipherSuite)temp; |
michael@0 | 1609 | |
michael@0 | 1610 | /* Read compression_method. */ |
michael@0 | 1611 | temp = ssl3_ConsumeHandshakeNumber(ss, 1, &buffer, &buffer_len); |
michael@0 | 1612 | if (temp < 0) goto no_ticket; |
michael@0 | 1613 | parsed_session_ticket->compression_method = (SSLCompressionMethod)temp; |
michael@0 | 1614 | |
michael@0 | 1615 | /* Read cipher spec parameters. */ |
michael@0 | 1616 | temp = ssl3_ConsumeHandshakeNumber(ss, 1, &buffer, &buffer_len); |
michael@0 | 1617 | if (temp < 0) goto no_ticket; |
michael@0 | 1618 | parsed_session_ticket->authAlgorithm = (SSLSignType)temp; |
michael@0 | 1619 | temp = ssl3_ConsumeHandshakeNumber(ss, 4, &buffer, &buffer_len); |
michael@0 | 1620 | if (temp < 0) goto no_ticket; |
michael@0 | 1621 | parsed_session_ticket->authKeyBits = (PRUint32)temp; |
michael@0 | 1622 | temp = ssl3_ConsumeHandshakeNumber(ss, 1, &buffer, &buffer_len); |
michael@0 | 1623 | if (temp < 0) goto no_ticket; |
michael@0 | 1624 | parsed_session_ticket->keaType = (SSLKEAType)temp; |
michael@0 | 1625 | temp = ssl3_ConsumeHandshakeNumber(ss, 4, &buffer, &buffer_len); |
michael@0 | 1626 | if (temp < 0) goto no_ticket; |
michael@0 | 1627 | parsed_session_ticket->keaKeyBits = (PRUint32)temp; |
michael@0 | 1628 | |
michael@0 | 1629 | /* Read wrapped master_secret. */ |
michael@0 | 1630 | temp = ssl3_ConsumeHandshakeNumber(ss, 1, &buffer, &buffer_len); |
michael@0 | 1631 | if (temp < 0) goto no_ticket; |
michael@0 | 1632 | parsed_session_ticket->ms_is_wrapped = (PRBool)temp; |
michael@0 | 1633 | |
michael@0 | 1634 | temp = ssl3_ConsumeHandshakeNumber(ss, 1, &buffer, &buffer_len); |
michael@0 | 1635 | if (temp < 0) goto no_ticket; |
michael@0 | 1636 | parsed_session_ticket->exchKeyType = (SSL3KEAType)temp; |
michael@0 | 1637 | |
michael@0 | 1638 | temp = ssl3_ConsumeHandshakeNumber(ss, 4, &buffer, &buffer_len); |
michael@0 | 1639 | if (temp < 0) goto no_ticket; |
michael@0 | 1640 | parsed_session_ticket->msWrapMech = (CK_MECHANISM_TYPE)temp; |
michael@0 | 1641 | |
michael@0 | 1642 | temp = ssl3_ConsumeHandshakeNumber(ss, 2, &buffer, &buffer_len); |
michael@0 | 1643 | if (temp < 0) goto no_ticket; |
michael@0 | 1644 | parsed_session_ticket->ms_length = (PRUint16)temp; |
michael@0 | 1645 | if (parsed_session_ticket->ms_length == 0 || /* sanity check MS. */ |
michael@0 | 1646 | parsed_session_ticket->ms_length > |
michael@0 | 1647 | sizeof(parsed_session_ticket->master_secret)) |
michael@0 | 1648 | goto no_ticket; |
michael@0 | 1649 | |
michael@0 | 1650 | /* Allow for the wrapped master secret to be longer. */ |
michael@0 | 1651 | if (buffer_len < parsed_session_ticket->ms_length) |
michael@0 | 1652 | goto no_ticket; |
michael@0 | 1653 | PORT_Memcpy(parsed_session_ticket->master_secret, buffer, |
michael@0 | 1654 | parsed_session_ticket->ms_length); |
michael@0 | 1655 | buffer += parsed_session_ticket->ms_length; |
michael@0 | 1656 | buffer_len -= parsed_session_ticket->ms_length; |
michael@0 | 1657 | |
michael@0 | 1658 | /* Read client_identity */ |
michael@0 | 1659 | temp = ssl3_ConsumeHandshakeNumber(ss, 1, &buffer, &buffer_len); |
michael@0 | 1660 | if (temp < 0) |
michael@0 | 1661 | goto no_ticket; |
michael@0 | 1662 | parsed_session_ticket->client_identity.client_auth_type = |
michael@0 | 1663 | (ClientAuthenticationType)temp; |
michael@0 | 1664 | switch(parsed_session_ticket->client_identity.client_auth_type) { |
michael@0 | 1665 | case CLIENT_AUTH_ANONYMOUS: |
michael@0 | 1666 | break; |
michael@0 | 1667 | case CLIENT_AUTH_CERTIFICATE: |
michael@0 | 1668 | rv = ssl3_ConsumeHandshakeVariable(ss, &cert_item, 3, |
michael@0 | 1669 | &buffer, &buffer_len); |
michael@0 | 1670 | if (rv != SECSuccess) goto no_ticket; |
michael@0 | 1671 | rv = SECITEM_CopyItem(NULL, &parsed_session_ticket->peer_cert, |
michael@0 | 1672 | &cert_item); |
michael@0 | 1673 | if (rv != SECSuccess) goto no_ticket; |
michael@0 | 1674 | break; |
michael@0 | 1675 | default: |
michael@0 | 1676 | goto no_ticket; |
michael@0 | 1677 | } |
michael@0 | 1678 | /* Read timestamp. */ |
michael@0 | 1679 | temp = ssl3_ConsumeHandshakeNumber(ss, 4, &buffer, &buffer_len); |
michael@0 | 1680 | if (temp < 0) |
michael@0 | 1681 | goto no_ticket; |
michael@0 | 1682 | parsed_session_ticket->timestamp = (PRUint32)temp; |
michael@0 | 1683 | |
michael@0 | 1684 | /* Read server name */ |
michael@0 | 1685 | nameType = |
michael@0 | 1686 | ssl3_ConsumeHandshakeNumber(ss, 1, &buffer, &buffer_len); |
michael@0 | 1687 | if (nameType != TLS_STE_NO_SERVER_NAME) { |
michael@0 | 1688 | SECItem name_item; |
michael@0 | 1689 | rv = ssl3_ConsumeHandshakeVariable(ss, &name_item, 2, &buffer, |
michael@0 | 1690 | &buffer_len); |
michael@0 | 1691 | if (rv != SECSuccess) goto no_ticket; |
michael@0 | 1692 | rv = SECITEM_CopyItem(NULL, &parsed_session_ticket->srvName, |
michael@0 | 1693 | &name_item); |
michael@0 | 1694 | if (rv != SECSuccess) goto no_ticket; |
michael@0 | 1695 | parsed_session_ticket->srvName.type = nameType; |
michael@0 | 1696 | } |
michael@0 | 1697 | |
michael@0 | 1698 | /* Done parsing. Check that all bytes have been consumed. */ |
michael@0 | 1699 | if (buffer_len != padding_length) |
michael@0 | 1700 | goto no_ticket; |
michael@0 | 1701 | |
michael@0 | 1702 | /* Use the ticket if it has not expired, otherwise free the allocated |
michael@0 | 1703 | * memory since the ticket is of no use. |
michael@0 | 1704 | */ |
michael@0 | 1705 | if (parsed_session_ticket->timestamp != 0 && |
michael@0 | 1706 | parsed_session_ticket->timestamp + |
michael@0 | 1707 | TLS_EX_SESS_TICKET_LIFETIME_HINT > ssl_Time()) { |
michael@0 | 1708 | |
michael@0 | 1709 | sid = ssl3_NewSessionID(ss, PR_TRUE); |
michael@0 | 1710 | if (sid == NULL) { |
michael@0 | 1711 | rv = SECFailure; |
michael@0 | 1712 | goto loser; |
michael@0 | 1713 | } |
michael@0 | 1714 | |
michael@0 | 1715 | /* Copy over parameters. */ |
michael@0 | 1716 | sid->version = parsed_session_ticket->ssl_version; |
michael@0 | 1717 | sid->u.ssl3.cipherSuite = parsed_session_ticket->cipher_suite; |
michael@0 | 1718 | sid->u.ssl3.compression = parsed_session_ticket->compression_method; |
michael@0 | 1719 | sid->authAlgorithm = parsed_session_ticket->authAlgorithm; |
michael@0 | 1720 | sid->authKeyBits = parsed_session_ticket->authKeyBits; |
michael@0 | 1721 | sid->keaType = parsed_session_ticket->keaType; |
michael@0 | 1722 | sid->keaKeyBits = parsed_session_ticket->keaKeyBits; |
michael@0 | 1723 | |
michael@0 | 1724 | /* Copy master secret. */ |
michael@0 | 1725 | #ifndef NO_PKCS11_BYPASS |
michael@0 | 1726 | if (ss->opt.bypassPKCS11 && |
michael@0 | 1727 | parsed_session_ticket->ms_is_wrapped) |
michael@0 | 1728 | goto no_ticket; |
michael@0 | 1729 | #endif |
michael@0 | 1730 | if (parsed_session_ticket->ms_length > |
michael@0 | 1731 | sizeof(sid->u.ssl3.keys.wrapped_master_secret)) |
michael@0 | 1732 | goto no_ticket; |
michael@0 | 1733 | PORT_Memcpy(sid->u.ssl3.keys.wrapped_master_secret, |
michael@0 | 1734 | parsed_session_ticket->master_secret, |
michael@0 | 1735 | parsed_session_ticket->ms_length); |
michael@0 | 1736 | sid->u.ssl3.keys.wrapped_master_secret_len = |
michael@0 | 1737 | parsed_session_ticket->ms_length; |
michael@0 | 1738 | sid->u.ssl3.exchKeyType = parsed_session_ticket->exchKeyType; |
michael@0 | 1739 | sid->u.ssl3.masterWrapMech = parsed_session_ticket->msWrapMech; |
michael@0 | 1740 | sid->u.ssl3.keys.msIsWrapped = |
michael@0 | 1741 | parsed_session_ticket->ms_is_wrapped; |
michael@0 | 1742 | sid->u.ssl3.masterValid = PR_TRUE; |
michael@0 | 1743 | sid->u.ssl3.keys.resumable = PR_TRUE; |
michael@0 | 1744 | |
michael@0 | 1745 | /* Copy over client cert from session ticket if there is one. */ |
michael@0 | 1746 | if (parsed_session_ticket->peer_cert.data != NULL) { |
michael@0 | 1747 | if (sid->peerCert != NULL) |
michael@0 | 1748 | CERT_DestroyCertificate(sid->peerCert); |
michael@0 | 1749 | sid->peerCert = CERT_NewTempCertificate(ss->dbHandle, |
michael@0 | 1750 | &parsed_session_ticket->peer_cert, NULL, PR_FALSE, PR_TRUE); |
michael@0 | 1751 | if (sid->peerCert == NULL) { |
michael@0 | 1752 | rv = SECFailure; |
michael@0 | 1753 | goto loser; |
michael@0 | 1754 | } |
michael@0 | 1755 | } |
michael@0 | 1756 | if (parsed_session_ticket->srvName.data != NULL) { |
michael@0 | 1757 | sid->u.ssl3.srvName = parsed_session_ticket->srvName; |
michael@0 | 1758 | } |
michael@0 | 1759 | ss->statelessResume = PR_TRUE; |
michael@0 | 1760 | ss->sec.ci.sid = sid; |
michael@0 | 1761 | } |
michael@0 | 1762 | } |
michael@0 | 1763 | |
michael@0 | 1764 | if (0) { |
michael@0 | 1765 | no_ticket: |
michael@0 | 1766 | SSL_DBG(("%d: SSL[%d]: Session ticket parsing failed.", |
michael@0 | 1767 | SSL_GETPID(), ss->fd)); |
michael@0 | 1768 | ssl3stats = SSL_GetStatistics(); |
michael@0 | 1769 | SSL_AtomicIncrementLong(& ssl3stats->hch_sid_ticket_parse_failures ); |
michael@0 | 1770 | } |
michael@0 | 1771 | rv = SECSuccess; |
michael@0 | 1772 | |
michael@0 | 1773 | loser: |
michael@0 | 1774 | /* ss->sec.ci.sid == sid if it did NOT come here via goto statement |
michael@0 | 1775 | * in that case do not free sid |
michael@0 | 1776 | */ |
michael@0 | 1777 | if (sid && (ss->sec.ci.sid != sid)) { |
michael@0 | 1778 | ssl_FreeSID(sid); |
michael@0 | 1779 | sid = NULL; |
michael@0 | 1780 | } |
michael@0 | 1781 | if (decrypted_state != NULL) { |
michael@0 | 1782 | SECITEM_FreeItem(decrypted_state, PR_TRUE); |
michael@0 | 1783 | decrypted_state = NULL; |
michael@0 | 1784 | } |
michael@0 | 1785 | |
michael@0 | 1786 | if (parsed_session_ticket != NULL) { |
michael@0 | 1787 | if (parsed_session_ticket->peer_cert.data) { |
michael@0 | 1788 | SECITEM_FreeItem(&parsed_session_ticket->peer_cert, PR_FALSE); |
michael@0 | 1789 | } |
michael@0 | 1790 | PORT_ZFree(parsed_session_ticket, sizeof(SessionTicket)); |
michael@0 | 1791 | } |
michael@0 | 1792 | |
michael@0 | 1793 | return rv; |
michael@0 | 1794 | } |
michael@0 | 1795 | |
michael@0 | 1796 | /* |
michael@0 | 1797 | * Read bytes. Using this function means the SECItem structure |
michael@0 | 1798 | * cannot be freed. The caller is expected to call this function |
michael@0 | 1799 | * on a shallow copy of the structure. |
michael@0 | 1800 | */ |
michael@0 | 1801 | static SECStatus |
michael@0 | 1802 | ssl3_ConsumeFromItem(SECItem *item, unsigned char **buf, PRUint32 bytes) |
michael@0 | 1803 | { |
michael@0 | 1804 | if (bytes > item->len) |
michael@0 | 1805 | return SECFailure; |
michael@0 | 1806 | |
michael@0 | 1807 | *buf = item->data; |
michael@0 | 1808 | item->data += bytes; |
michael@0 | 1809 | item->len -= bytes; |
michael@0 | 1810 | return SECSuccess; |
michael@0 | 1811 | } |
michael@0 | 1812 | |
michael@0 | 1813 | static SECStatus |
michael@0 | 1814 | ssl3_ParseEncryptedSessionTicket(sslSocket *ss, SECItem *data, |
michael@0 | 1815 | EncryptedSessionTicket *enc_session_ticket) |
michael@0 | 1816 | { |
michael@0 | 1817 | if (ssl3_ConsumeFromItem(data, &enc_session_ticket->key_name, |
michael@0 | 1818 | SESS_TICKET_KEY_NAME_LEN) != SECSuccess) |
michael@0 | 1819 | return SECFailure; |
michael@0 | 1820 | if (ssl3_ConsumeFromItem(data, &enc_session_ticket->iv, |
michael@0 | 1821 | AES_BLOCK_SIZE) != SECSuccess) |
michael@0 | 1822 | return SECFailure; |
michael@0 | 1823 | if (ssl3_ConsumeHandshakeVariable(ss, &enc_session_ticket->encrypted_state, |
michael@0 | 1824 | 2, &data->data, &data->len) != SECSuccess) |
michael@0 | 1825 | return SECFailure; |
michael@0 | 1826 | if (ssl3_ConsumeFromItem(data, &enc_session_ticket->mac, |
michael@0 | 1827 | TLS_EX_SESS_TICKET_MAC_LENGTH) != SECSuccess) |
michael@0 | 1828 | return SECFailure; |
michael@0 | 1829 | if (data->len != 0) /* Make sure that we have consumed all bytes. */ |
michael@0 | 1830 | return SECFailure; |
michael@0 | 1831 | |
michael@0 | 1832 | return SECSuccess; |
michael@0 | 1833 | } |
michael@0 | 1834 | |
michael@0 | 1835 | /* go through hello extensions in buffer "b". |
michael@0 | 1836 | * For each one, find the extension handler in the table, and |
michael@0 | 1837 | * if present, invoke that handler. |
michael@0 | 1838 | * Servers ignore any extensions with unknown extension types. |
michael@0 | 1839 | * Clients reject any extensions with unadvertised extension types. |
michael@0 | 1840 | */ |
michael@0 | 1841 | SECStatus |
michael@0 | 1842 | ssl3_HandleHelloExtensions(sslSocket *ss, SSL3Opaque **b, PRUint32 *length) |
michael@0 | 1843 | { |
michael@0 | 1844 | const ssl3HelloExtensionHandler * handlers; |
michael@0 | 1845 | |
michael@0 | 1846 | if (ss->sec.isServer) { |
michael@0 | 1847 | handlers = clientHelloHandlers; |
michael@0 | 1848 | } else if (ss->version > SSL_LIBRARY_VERSION_3_0) { |
michael@0 | 1849 | handlers = serverHelloHandlersTLS; |
michael@0 | 1850 | } else { |
michael@0 | 1851 | handlers = serverHelloHandlersSSL3; |
michael@0 | 1852 | } |
michael@0 | 1853 | |
michael@0 | 1854 | while (*length) { |
michael@0 | 1855 | const ssl3HelloExtensionHandler * handler; |
michael@0 | 1856 | SECStatus rv; |
michael@0 | 1857 | PRInt32 extension_type; |
michael@0 | 1858 | SECItem extension_data; |
michael@0 | 1859 | |
michael@0 | 1860 | /* Get the extension's type field */ |
michael@0 | 1861 | extension_type = ssl3_ConsumeHandshakeNumber(ss, 2, b, length); |
michael@0 | 1862 | if (extension_type < 0) /* failure to decode extension_type */ |
michael@0 | 1863 | return SECFailure; /* alert already sent */ |
michael@0 | 1864 | |
michael@0 | 1865 | /* get the data for this extension, so we can pass it or skip it. */ |
michael@0 | 1866 | rv = ssl3_ConsumeHandshakeVariable(ss, &extension_data, 2, b, length); |
michael@0 | 1867 | if (rv != SECSuccess) |
michael@0 | 1868 | return rv; |
michael@0 | 1869 | |
michael@0 | 1870 | /* Check whether the server sent an extension which was not advertised |
michael@0 | 1871 | * in the ClientHello. |
michael@0 | 1872 | */ |
michael@0 | 1873 | if (!ss->sec.isServer && |
michael@0 | 1874 | !ssl3_ClientExtensionAdvertised(ss, extension_type)) |
michael@0 | 1875 | return SECFailure; /* TODO: send unsupported_extension alert */ |
michael@0 | 1876 | |
michael@0 | 1877 | /* Check whether an extension has been sent multiple times. */ |
michael@0 | 1878 | if (ssl3_ExtensionNegotiated(ss, extension_type)) |
michael@0 | 1879 | return SECFailure; |
michael@0 | 1880 | |
michael@0 | 1881 | /* find extension_type in table of Hello Extension Handlers */ |
michael@0 | 1882 | for (handler = handlers; handler->ex_type >= 0; handler++) { |
michael@0 | 1883 | /* if found, call this handler */ |
michael@0 | 1884 | if (handler->ex_type == extension_type) { |
michael@0 | 1885 | rv = (*handler->ex_handler)(ss, (PRUint16)extension_type, |
michael@0 | 1886 | &extension_data); |
michael@0 | 1887 | /* Ignore this result */ |
michael@0 | 1888 | /* Treat all bad extensions as unrecognized types. */ |
michael@0 | 1889 | break; |
michael@0 | 1890 | } |
michael@0 | 1891 | } |
michael@0 | 1892 | } |
michael@0 | 1893 | return SECSuccess; |
michael@0 | 1894 | } |
michael@0 | 1895 | |
michael@0 | 1896 | /* Add a callback function to the table of senders of server hello extensions. |
michael@0 | 1897 | */ |
michael@0 | 1898 | SECStatus |
michael@0 | 1899 | ssl3_RegisterServerHelloExtensionSender(sslSocket *ss, PRUint16 ex_type, |
michael@0 | 1900 | ssl3HelloExtensionSenderFunc cb) |
michael@0 | 1901 | { |
michael@0 | 1902 | int i; |
michael@0 | 1903 | ssl3HelloExtensionSender *sender = &ss->xtnData.serverSenders[0]; |
michael@0 | 1904 | |
michael@0 | 1905 | for (i = 0; i < SSL_MAX_EXTENSIONS; ++i, ++sender) { |
michael@0 | 1906 | if (!sender->ex_sender) { |
michael@0 | 1907 | sender->ex_type = ex_type; |
michael@0 | 1908 | sender->ex_sender = cb; |
michael@0 | 1909 | return SECSuccess; |
michael@0 | 1910 | } |
michael@0 | 1911 | /* detect duplicate senders */ |
michael@0 | 1912 | PORT_Assert(sender->ex_type != ex_type); |
michael@0 | 1913 | if (sender->ex_type == ex_type) { |
michael@0 | 1914 | /* duplicate */ |
michael@0 | 1915 | break; |
michael@0 | 1916 | } |
michael@0 | 1917 | } |
michael@0 | 1918 | PORT_Assert(i < SSL_MAX_EXTENSIONS); /* table needs to grow */ |
michael@0 | 1919 | PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); |
michael@0 | 1920 | return SECFailure; |
michael@0 | 1921 | } |
michael@0 | 1922 | |
michael@0 | 1923 | /* call each of the extension senders and return the accumulated length */ |
michael@0 | 1924 | PRInt32 |
michael@0 | 1925 | ssl3_CallHelloExtensionSenders(sslSocket *ss, PRBool append, PRUint32 maxBytes, |
michael@0 | 1926 | const ssl3HelloExtensionSender *sender) |
michael@0 | 1927 | { |
michael@0 | 1928 | PRInt32 total_exten_len = 0; |
michael@0 | 1929 | int i; |
michael@0 | 1930 | |
michael@0 | 1931 | if (!sender) { |
michael@0 | 1932 | sender = ss->version > SSL_LIBRARY_VERSION_3_0 ? |
michael@0 | 1933 | &clientHelloSendersTLS[0] : &clientHelloSendersSSL3[0]; |
michael@0 | 1934 | } |
michael@0 | 1935 | |
michael@0 | 1936 | for (i = 0; i < SSL_MAX_EXTENSIONS; ++i, ++sender) { |
michael@0 | 1937 | if (sender->ex_sender) { |
michael@0 | 1938 | PRInt32 extLen = (*sender->ex_sender)(ss, append, maxBytes); |
michael@0 | 1939 | if (extLen < 0) |
michael@0 | 1940 | return -1; |
michael@0 | 1941 | maxBytes -= extLen; |
michael@0 | 1942 | total_exten_len += extLen; |
michael@0 | 1943 | } |
michael@0 | 1944 | } |
michael@0 | 1945 | return total_exten_len; |
michael@0 | 1946 | } |
michael@0 | 1947 | |
michael@0 | 1948 | |
michael@0 | 1949 | /* Extension format: |
michael@0 | 1950 | * Extension number: 2 bytes |
michael@0 | 1951 | * Extension length: 2 bytes |
michael@0 | 1952 | * Verify Data Length: 1 byte |
michael@0 | 1953 | * Verify Data (TLS): 12 bytes (client) or 24 bytes (server) |
michael@0 | 1954 | * Verify Data (SSL): 36 bytes (client) or 72 bytes (server) |
michael@0 | 1955 | */ |
michael@0 | 1956 | static PRInt32 |
michael@0 | 1957 | ssl3_SendRenegotiationInfoXtn( |
michael@0 | 1958 | sslSocket * ss, |
michael@0 | 1959 | PRBool append, |
michael@0 | 1960 | PRUint32 maxBytes) |
michael@0 | 1961 | { |
michael@0 | 1962 | PRInt32 len, needed; |
michael@0 | 1963 | |
michael@0 | 1964 | /* In draft-ietf-tls-renegotiation-03, it is NOT RECOMMENDED to send |
michael@0 | 1965 | * both the SCSV and the empty RI, so when we send SCSV in |
michael@0 | 1966 | * the initial handshake, we don't also send RI. |
michael@0 | 1967 | */ |
michael@0 | 1968 | if (!ss || ss->ssl3.hs.sendingSCSV) |
michael@0 | 1969 | return 0; |
michael@0 | 1970 | len = !ss->firstHsDone ? 0 : |
michael@0 | 1971 | (ss->sec.isServer ? ss->ssl3.hs.finishedBytes * 2 |
michael@0 | 1972 | : ss->ssl3.hs.finishedBytes); |
michael@0 | 1973 | needed = 5 + len; |
michael@0 | 1974 | if (append && maxBytes >= needed) { |
michael@0 | 1975 | SECStatus rv; |
michael@0 | 1976 | /* extension_type */ |
michael@0 | 1977 | rv = ssl3_AppendHandshakeNumber(ss, ssl_renegotiation_info_xtn, 2); |
michael@0 | 1978 | if (rv != SECSuccess) return -1; |
michael@0 | 1979 | /* length of extension_data */ |
michael@0 | 1980 | rv = ssl3_AppendHandshakeNumber(ss, len + 1, 2); |
michael@0 | 1981 | if (rv != SECSuccess) return -1; |
michael@0 | 1982 | /* verify_Data from previous Finished message(s) */ |
michael@0 | 1983 | rv = ssl3_AppendHandshakeVariable(ss, |
michael@0 | 1984 | ss->ssl3.hs.finishedMsgs.data, len, 1); |
michael@0 | 1985 | if (rv != SECSuccess) return -1; |
michael@0 | 1986 | if (!ss->sec.isServer) { |
michael@0 | 1987 | TLSExtensionData *xtnData = &ss->xtnData; |
michael@0 | 1988 | xtnData->advertised[xtnData->numAdvertised++] = |
michael@0 | 1989 | ssl_renegotiation_info_xtn; |
michael@0 | 1990 | } |
michael@0 | 1991 | } |
michael@0 | 1992 | return needed; |
michael@0 | 1993 | } |
michael@0 | 1994 | |
michael@0 | 1995 | static SECStatus |
michael@0 | 1996 | ssl3_ServerHandleStatusRequestXtn(sslSocket *ss, PRUint16 ex_type, |
michael@0 | 1997 | SECItem *data) |
michael@0 | 1998 | { |
michael@0 | 1999 | SECStatus rv = SECSuccess; |
michael@0 | 2000 | |
michael@0 | 2001 | /* remember that we got this extension. */ |
michael@0 | 2002 | ss->xtnData.negotiated[ss->xtnData.numNegotiated++] = ex_type; |
michael@0 | 2003 | PORT_Assert(ss->sec.isServer); |
michael@0 | 2004 | /* prepare to send back the appropriate response */ |
michael@0 | 2005 | rv = ssl3_RegisterServerHelloExtensionSender(ss, ex_type, |
michael@0 | 2006 | ssl3_ServerSendStatusRequestXtn); |
michael@0 | 2007 | return rv; |
michael@0 | 2008 | } |
michael@0 | 2009 | |
michael@0 | 2010 | /* This function runs in both the client and server. */ |
michael@0 | 2011 | static SECStatus |
michael@0 | 2012 | ssl3_HandleRenegotiationInfoXtn(sslSocket *ss, PRUint16 ex_type, SECItem *data) |
michael@0 | 2013 | { |
michael@0 | 2014 | SECStatus rv = SECSuccess; |
michael@0 | 2015 | PRUint32 len = 0; |
michael@0 | 2016 | |
michael@0 | 2017 | if (ss->firstHsDone) { |
michael@0 | 2018 | len = ss->sec.isServer ? ss->ssl3.hs.finishedBytes |
michael@0 | 2019 | : ss->ssl3.hs.finishedBytes * 2; |
michael@0 | 2020 | } |
michael@0 | 2021 | if (data->len != 1 + len || |
michael@0 | 2022 | data->data[0] != len || (len && |
michael@0 | 2023 | NSS_SecureMemcmp(ss->ssl3.hs.finishedMsgs.data, |
michael@0 | 2024 | data->data + 1, len))) { |
michael@0 | 2025 | /* Can we do this here? Or, must we arrange for the caller to do it? */ |
michael@0 | 2026 | (void)SSL3_SendAlert(ss, alert_fatal, handshake_failure); |
michael@0 | 2027 | PORT_SetError(SSL_ERROR_BAD_HANDSHAKE_HASH_VALUE); |
michael@0 | 2028 | return SECFailure; |
michael@0 | 2029 | } |
michael@0 | 2030 | /* remember that we got this extension and it was correct. */ |
michael@0 | 2031 | ss->peerRequestedProtection = 1; |
michael@0 | 2032 | ss->xtnData.negotiated[ss->xtnData.numNegotiated++] = ex_type; |
michael@0 | 2033 | if (ss->sec.isServer) { |
michael@0 | 2034 | /* prepare to send back the appropriate response */ |
michael@0 | 2035 | rv = ssl3_RegisterServerHelloExtensionSender(ss, ex_type, |
michael@0 | 2036 | ssl3_SendRenegotiationInfoXtn); |
michael@0 | 2037 | } |
michael@0 | 2038 | return rv; |
michael@0 | 2039 | } |
michael@0 | 2040 | |
michael@0 | 2041 | static PRInt32 |
michael@0 | 2042 | ssl3_SendUseSRTPXtn(sslSocket *ss, PRBool append, PRUint32 maxBytes) |
michael@0 | 2043 | { |
michael@0 | 2044 | PRUint32 ext_data_len; |
michael@0 | 2045 | PRInt16 i; |
michael@0 | 2046 | SECStatus rv; |
michael@0 | 2047 | |
michael@0 | 2048 | if (!ss) |
michael@0 | 2049 | return 0; |
michael@0 | 2050 | |
michael@0 | 2051 | if (!ss->sec.isServer) { |
michael@0 | 2052 | /* Client side */ |
michael@0 | 2053 | |
michael@0 | 2054 | if (!IS_DTLS(ss) || !ss->ssl3.dtlsSRTPCipherCount) |
michael@0 | 2055 | return 0; /* Not relevant */ |
michael@0 | 2056 | |
michael@0 | 2057 | ext_data_len = 2 + 2 * ss->ssl3.dtlsSRTPCipherCount + 1; |
michael@0 | 2058 | |
michael@0 | 2059 | if (append && maxBytes >= 4 + ext_data_len) { |
michael@0 | 2060 | /* Extension type */ |
michael@0 | 2061 | rv = ssl3_AppendHandshakeNumber(ss, ssl_use_srtp_xtn, 2); |
michael@0 | 2062 | if (rv != SECSuccess) return -1; |
michael@0 | 2063 | /* Length of extension data */ |
michael@0 | 2064 | rv = ssl3_AppendHandshakeNumber(ss, ext_data_len, 2); |
michael@0 | 2065 | if (rv != SECSuccess) return -1; |
michael@0 | 2066 | /* Length of the SRTP cipher list */ |
michael@0 | 2067 | rv = ssl3_AppendHandshakeNumber(ss, |
michael@0 | 2068 | 2 * ss->ssl3.dtlsSRTPCipherCount, |
michael@0 | 2069 | 2); |
michael@0 | 2070 | if (rv != SECSuccess) return -1; |
michael@0 | 2071 | /* The SRTP ciphers */ |
michael@0 | 2072 | for (i = 0; i < ss->ssl3.dtlsSRTPCipherCount; i++) { |
michael@0 | 2073 | rv = ssl3_AppendHandshakeNumber(ss, |
michael@0 | 2074 | ss->ssl3.dtlsSRTPCiphers[i], |
michael@0 | 2075 | 2); |
michael@0 | 2076 | } |
michael@0 | 2077 | /* Empty MKI value */ |
michael@0 | 2078 | ssl3_AppendHandshakeVariable(ss, NULL, 0, 1); |
michael@0 | 2079 | |
michael@0 | 2080 | ss->xtnData.advertised[ss->xtnData.numAdvertised++] = |
michael@0 | 2081 | ssl_use_srtp_xtn; |
michael@0 | 2082 | } |
michael@0 | 2083 | |
michael@0 | 2084 | return 4 + ext_data_len; |
michael@0 | 2085 | } |
michael@0 | 2086 | |
michael@0 | 2087 | /* Server side */ |
michael@0 | 2088 | if (append && maxBytes >= 9) { |
michael@0 | 2089 | /* Extension type */ |
michael@0 | 2090 | rv = ssl3_AppendHandshakeNumber(ss, ssl_use_srtp_xtn, 2); |
michael@0 | 2091 | if (rv != SECSuccess) return -1; |
michael@0 | 2092 | /* Length of extension data */ |
michael@0 | 2093 | rv = ssl3_AppendHandshakeNumber(ss, 5, 2); |
michael@0 | 2094 | if (rv != SECSuccess) return -1; |
michael@0 | 2095 | /* Length of the SRTP cipher list */ |
michael@0 | 2096 | rv = ssl3_AppendHandshakeNumber(ss, 2, 2); |
michael@0 | 2097 | if (rv != SECSuccess) return -1; |
michael@0 | 2098 | /* The selected cipher */ |
michael@0 | 2099 | rv = ssl3_AppendHandshakeNumber(ss, ss->ssl3.dtlsSRTPCipherSuite, 2); |
michael@0 | 2100 | if (rv != SECSuccess) return -1; |
michael@0 | 2101 | /* Empty MKI value */ |
michael@0 | 2102 | ssl3_AppendHandshakeVariable(ss, NULL, 0, 1); |
michael@0 | 2103 | } |
michael@0 | 2104 | |
michael@0 | 2105 | return 9; |
michael@0 | 2106 | } |
michael@0 | 2107 | |
michael@0 | 2108 | static SECStatus |
michael@0 | 2109 | ssl3_HandleUseSRTPXtn(sslSocket * ss, PRUint16 ex_type, SECItem *data) |
michael@0 | 2110 | { |
michael@0 | 2111 | SECStatus rv; |
michael@0 | 2112 | SECItem ciphers = {siBuffer, NULL, 0}; |
michael@0 | 2113 | PRUint16 i; |
michael@0 | 2114 | unsigned int j; |
michael@0 | 2115 | PRUint16 cipher = 0; |
michael@0 | 2116 | PRBool found = PR_FALSE; |
michael@0 | 2117 | SECItem litem; |
michael@0 | 2118 | |
michael@0 | 2119 | if (!ss->sec.isServer) { |
michael@0 | 2120 | /* Client side */ |
michael@0 | 2121 | if (!data->data || !data->len) { |
michael@0 | 2122 | /* malformed */ |
michael@0 | 2123 | return SECFailure; |
michael@0 | 2124 | } |
michael@0 | 2125 | |
michael@0 | 2126 | /* Get the cipher list */ |
michael@0 | 2127 | rv = ssl3_ConsumeHandshakeVariable(ss, &ciphers, 2, |
michael@0 | 2128 | &data->data, &data->len); |
michael@0 | 2129 | if (rv != SECSuccess) { |
michael@0 | 2130 | return SECFailure; |
michael@0 | 2131 | } |
michael@0 | 2132 | /* Now check that the number of ciphers listed is 1 (len = 2) */ |
michael@0 | 2133 | if (ciphers.len != 2) { |
michael@0 | 2134 | return SECFailure; |
michael@0 | 2135 | } |
michael@0 | 2136 | |
michael@0 | 2137 | /* Get the selected cipher */ |
michael@0 | 2138 | cipher = (ciphers.data[0] << 8) | ciphers.data[1]; |
michael@0 | 2139 | |
michael@0 | 2140 | /* Now check that this is one of the ciphers we offered */ |
michael@0 | 2141 | for (i = 0; i < ss->ssl3.dtlsSRTPCipherCount; i++) { |
michael@0 | 2142 | if (cipher == ss->ssl3.dtlsSRTPCiphers[i]) { |
michael@0 | 2143 | found = PR_TRUE; |
michael@0 | 2144 | break; |
michael@0 | 2145 | } |
michael@0 | 2146 | } |
michael@0 | 2147 | |
michael@0 | 2148 | if (!found) { |
michael@0 | 2149 | return SECFailure; |
michael@0 | 2150 | } |
michael@0 | 2151 | |
michael@0 | 2152 | /* Get the srtp_mki value */ |
michael@0 | 2153 | rv = ssl3_ConsumeHandshakeVariable(ss, &litem, 1, |
michael@0 | 2154 | &data->data, &data->len); |
michael@0 | 2155 | if (rv != SECSuccess) { |
michael@0 | 2156 | return SECFailure; |
michael@0 | 2157 | } |
michael@0 | 2158 | |
michael@0 | 2159 | /* We didn't offer an MKI, so this must be 0 length */ |
michael@0 | 2160 | /* XXX RFC 5764 Section 4.1.3 says: |
michael@0 | 2161 | * If the client detects a nonzero-length MKI in the server's |
michael@0 | 2162 | * response that is different than the one the client offered, |
michael@0 | 2163 | * then the client MUST abort the handshake and SHOULD send an |
michael@0 | 2164 | * invalid_parameter alert. |
michael@0 | 2165 | * |
michael@0 | 2166 | * Due to a limitation of the ssl3_HandleHelloExtensions function, |
michael@0 | 2167 | * returning SECFailure here won't abort the handshake. It will |
michael@0 | 2168 | * merely cause the use_srtp extension to be not negotiated. We |
michael@0 | 2169 | * should fix this. See NSS bug 753136. |
michael@0 | 2170 | */ |
michael@0 | 2171 | if (litem.len != 0) { |
michael@0 | 2172 | return SECFailure; |
michael@0 | 2173 | } |
michael@0 | 2174 | |
michael@0 | 2175 | if (data->len != 0) { |
michael@0 | 2176 | /* malformed */ |
michael@0 | 2177 | return SECFailure; |
michael@0 | 2178 | } |
michael@0 | 2179 | |
michael@0 | 2180 | /* OK, this looks fine. */ |
michael@0 | 2181 | ss->xtnData.negotiated[ss->xtnData.numNegotiated++] = ssl_use_srtp_xtn; |
michael@0 | 2182 | ss->ssl3.dtlsSRTPCipherSuite = cipher; |
michael@0 | 2183 | return SECSuccess; |
michael@0 | 2184 | } |
michael@0 | 2185 | |
michael@0 | 2186 | /* Server side */ |
michael@0 | 2187 | if (!IS_DTLS(ss) || !ss->ssl3.dtlsSRTPCipherCount) { |
michael@0 | 2188 | /* Ignore the extension if we aren't doing DTLS or no DTLS-SRTP |
michael@0 | 2189 | * preferences have been set. */ |
michael@0 | 2190 | return SECSuccess; |
michael@0 | 2191 | } |
michael@0 | 2192 | |
michael@0 | 2193 | if (!data->data || data->len < 5) { |
michael@0 | 2194 | /* malformed */ |
michael@0 | 2195 | return SECFailure; |
michael@0 | 2196 | } |
michael@0 | 2197 | |
michael@0 | 2198 | /* Get the cipher list */ |
michael@0 | 2199 | rv = ssl3_ConsumeHandshakeVariable(ss, &ciphers, 2, |
michael@0 | 2200 | &data->data, &data->len); |
michael@0 | 2201 | if (rv != SECSuccess) { |
michael@0 | 2202 | return SECFailure; |
michael@0 | 2203 | } |
michael@0 | 2204 | /* Check that the list is even length */ |
michael@0 | 2205 | if (ciphers.len % 2) { |
michael@0 | 2206 | return SECFailure; |
michael@0 | 2207 | } |
michael@0 | 2208 | |
michael@0 | 2209 | /* Walk through the offered list and pick the most preferred of our |
michael@0 | 2210 | * ciphers, if any */ |
michael@0 | 2211 | for (i = 0; !found && i < ss->ssl3.dtlsSRTPCipherCount; i++) { |
michael@0 | 2212 | for (j = 0; j + 1 < ciphers.len; j += 2) { |
michael@0 | 2213 | cipher = (ciphers.data[j] << 8) | ciphers.data[j + 1]; |
michael@0 | 2214 | if (cipher == ss->ssl3.dtlsSRTPCiphers[i]) { |
michael@0 | 2215 | found = PR_TRUE; |
michael@0 | 2216 | break; |
michael@0 | 2217 | } |
michael@0 | 2218 | } |
michael@0 | 2219 | } |
michael@0 | 2220 | |
michael@0 | 2221 | /* Get the srtp_mki value */ |
michael@0 | 2222 | rv = ssl3_ConsumeHandshakeVariable(ss, &litem, 1, &data->data, &data->len); |
michael@0 | 2223 | if (rv != SECSuccess) { |
michael@0 | 2224 | return SECFailure; |
michael@0 | 2225 | } |
michael@0 | 2226 | |
michael@0 | 2227 | if (data->len != 0) { |
michael@0 | 2228 | return SECFailure; /* Malformed */ |
michael@0 | 2229 | } |
michael@0 | 2230 | |
michael@0 | 2231 | /* Now figure out what to do */ |
michael@0 | 2232 | if (!found) { |
michael@0 | 2233 | /* No matching ciphers */ |
michael@0 | 2234 | return SECSuccess; |
michael@0 | 2235 | } |
michael@0 | 2236 | |
michael@0 | 2237 | /* OK, we have a valid cipher and we've selected it */ |
michael@0 | 2238 | ss->ssl3.dtlsSRTPCipherSuite = cipher; |
michael@0 | 2239 | ss->xtnData.negotiated[ss->xtnData.numNegotiated++] = ssl_use_srtp_xtn; |
michael@0 | 2240 | |
michael@0 | 2241 | return ssl3_RegisterServerHelloExtensionSender(ss, ssl_use_srtp_xtn, |
michael@0 | 2242 | ssl3_SendUseSRTPXtn); |
michael@0 | 2243 | } |
michael@0 | 2244 | |
michael@0 | 2245 | /* ssl3_ServerHandleSigAlgsXtn handles the signature_algorithms extension |
michael@0 | 2246 | * from a client. |
michael@0 | 2247 | * See https://tools.ietf.org/html/rfc5246#section-7.4.1.4.1 */ |
michael@0 | 2248 | static SECStatus |
michael@0 | 2249 | ssl3_ServerHandleSigAlgsXtn(sslSocket * ss, PRUint16 ex_type, SECItem *data) |
michael@0 | 2250 | { |
michael@0 | 2251 | SECStatus rv; |
michael@0 | 2252 | SECItem algorithms; |
michael@0 | 2253 | const unsigned char *b; |
michael@0 | 2254 | unsigned int numAlgorithms, i; |
michael@0 | 2255 | |
michael@0 | 2256 | /* Ignore this extension if we aren't doing TLS 1.2 or greater. */ |
michael@0 | 2257 | if (ss->version < SSL_LIBRARY_VERSION_TLS_1_2) { |
michael@0 | 2258 | return SECSuccess; |
michael@0 | 2259 | } |
michael@0 | 2260 | |
michael@0 | 2261 | /* Keep track of negotiated extensions. */ |
michael@0 | 2262 | ss->xtnData.negotiated[ss->xtnData.numNegotiated++] = ex_type; |
michael@0 | 2263 | |
michael@0 | 2264 | rv = ssl3_ConsumeHandshakeVariable(ss, &algorithms, 2, &data->data, |
michael@0 | 2265 | &data->len); |
michael@0 | 2266 | if (rv != SECSuccess) { |
michael@0 | 2267 | return SECFailure; |
michael@0 | 2268 | } |
michael@0 | 2269 | /* Trailing data, empty value, or odd-length value is invalid. */ |
michael@0 | 2270 | if (data->len != 0 || algorithms.len == 0 || (algorithms.len & 1) != 0) { |
michael@0 | 2271 | PORT_SetError(SSL_ERROR_RX_MALFORMED_CLIENT_HELLO); |
michael@0 | 2272 | return SECFailure; |
michael@0 | 2273 | } |
michael@0 | 2274 | |
michael@0 | 2275 | numAlgorithms = algorithms.len/2; |
michael@0 | 2276 | |
michael@0 | 2277 | /* We don't care to process excessive numbers of algorithms. */ |
michael@0 | 2278 | if (numAlgorithms > 512) { |
michael@0 | 2279 | numAlgorithms = 512; |
michael@0 | 2280 | } |
michael@0 | 2281 | |
michael@0 | 2282 | ss->ssl3.hs.clientSigAndHash = |
michael@0 | 2283 | PORT_NewArray(SSL3SignatureAndHashAlgorithm, numAlgorithms); |
michael@0 | 2284 | if (!ss->ssl3.hs.clientSigAndHash) { |
michael@0 | 2285 | return SECFailure; |
michael@0 | 2286 | } |
michael@0 | 2287 | ss->ssl3.hs.numClientSigAndHash = 0; |
michael@0 | 2288 | |
michael@0 | 2289 | b = algorithms.data; |
michael@0 | 2290 | for (i = 0; i < numAlgorithms; i++) { |
michael@0 | 2291 | unsigned char tls_hash = *(b++); |
michael@0 | 2292 | unsigned char tls_sig = *(b++); |
michael@0 | 2293 | SECOidTag hash = ssl3_TLSHashAlgorithmToOID(tls_hash); |
michael@0 | 2294 | |
michael@0 | 2295 | if (hash == SEC_OID_UNKNOWN) { |
michael@0 | 2296 | /* We ignore formats that we don't understand. */ |
michael@0 | 2297 | continue; |
michael@0 | 2298 | } |
michael@0 | 2299 | /* tls_sig support will be checked later in |
michael@0 | 2300 | * ssl3_PickSignatureHashAlgorithm. */ |
michael@0 | 2301 | ss->ssl3.hs.clientSigAndHash[i].hashAlg = hash; |
michael@0 | 2302 | ss->ssl3.hs.clientSigAndHash[i].sigAlg = tls_sig; |
michael@0 | 2303 | ss->ssl3.hs.numClientSigAndHash++; |
michael@0 | 2304 | } |
michael@0 | 2305 | |
michael@0 | 2306 | if (!ss->ssl3.hs.numClientSigAndHash) { |
michael@0 | 2307 | /* We didn't understand any of the client's requested signature |
michael@0 | 2308 | * formats. We'll use the defaults. */ |
michael@0 | 2309 | PORT_Free(ss->ssl3.hs.clientSigAndHash); |
michael@0 | 2310 | ss->ssl3.hs.clientSigAndHash = NULL; |
michael@0 | 2311 | } |
michael@0 | 2312 | |
michael@0 | 2313 | return SECSuccess; |
michael@0 | 2314 | } |
michael@0 | 2315 | |
michael@0 | 2316 | /* ssl3_ClientSendSigAlgsXtn sends the signature_algorithm extension for TLS |
michael@0 | 2317 | * 1.2 ClientHellos. */ |
michael@0 | 2318 | static PRInt32 |
michael@0 | 2319 | ssl3_ClientSendSigAlgsXtn(sslSocket * ss, PRBool append, PRUint32 maxBytes) |
michael@0 | 2320 | { |
michael@0 | 2321 | static const unsigned char signatureAlgorithms[] = { |
michael@0 | 2322 | /* This block is the contents of our signature_algorithms extension, in |
michael@0 | 2323 | * wire format. See |
michael@0 | 2324 | * https://tools.ietf.org/html/rfc5246#section-7.4.1.4.1 */ |
michael@0 | 2325 | tls_hash_sha256, tls_sig_rsa, |
michael@0 | 2326 | tls_hash_sha384, tls_sig_rsa, |
michael@0 | 2327 | tls_hash_sha1, tls_sig_rsa, |
michael@0 | 2328 | #ifndef NSS_DISABLE_ECC |
michael@0 | 2329 | tls_hash_sha256, tls_sig_ecdsa, |
michael@0 | 2330 | tls_hash_sha384, tls_sig_ecdsa, |
michael@0 | 2331 | tls_hash_sha1, tls_sig_ecdsa, |
michael@0 | 2332 | #endif |
michael@0 | 2333 | tls_hash_sha256, tls_sig_dsa, |
michael@0 | 2334 | tls_hash_sha1, tls_sig_dsa, |
michael@0 | 2335 | }; |
michael@0 | 2336 | PRInt32 extension_length; |
michael@0 | 2337 | |
michael@0 | 2338 | if (ss->version < SSL_LIBRARY_VERSION_TLS_1_2) { |
michael@0 | 2339 | return 0; |
michael@0 | 2340 | } |
michael@0 | 2341 | |
michael@0 | 2342 | extension_length = |
michael@0 | 2343 | 2 /* extension type */ + |
michael@0 | 2344 | 2 /* extension length */ + |
michael@0 | 2345 | 2 /* supported_signature_algorithms length */ + |
michael@0 | 2346 | sizeof(signatureAlgorithms); |
michael@0 | 2347 | |
michael@0 | 2348 | if (append && maxBytes >= extension_length) { |
michael@0 | 2349 | SECStatus rv; |
michael@0 | 2350 | rv = ssl3_AppendHandshakeNumber(ss, ssl_signature_algorithms_xtn, 2); |
michael@0 | 2351 | if (rv != SECSuccess) |
michael@0 | 2352 | goto loser; |
michael@0 | 2353 | rv = ssl3_AppendHandshakeNumber(ss, extension_length - 4, 2); |
michael@0 | 2354 | if (rv != SECSuccess) |
michael@0 | 2355 | goto loser; |
michael@0 | 2356 | rv = ssl3_AppendHandshakeVariable(ss, signatureAlgorithms, |
michael@0 | 2357 | sizeof(signatureAlgorithms), 2); |
michael@0 | 2358 | if (rv != SECSuccess) |
michael@0 | 2359 | goto loser; |
michael@0 | 2360 | ss->xtnData.advertised[ss->xtnData.numAdvertised++] = |
michael@0 | 2361 | ssl_signature_algorithms_xtn; |
michael@0 | 2362 | } else if (maxBytes < extension_length) { |
michael@0 | 2363 | PORT_Assert(0); |
michael@0 | 2364 | return 0; |
michael@0 | 2365 | } |
michael@0 | 2366 | |
michael@0 | 2367 | return extension_length; |
michael@0 | 2368 | |
michael@0 | 2369 | loser: |
michael@0 | 2370 | return -1; |
michael@0 | 2371 | } |
michael@0 | 2372 | |
michael@0 | 2373 | unsigned int |
michael@0 | 2374 | ssl3_CalculatePaddingExtensionLength(unsigned int clientHelloLength) |
michael@0 | 2375 | { |
michael@0 | 2376 | unsigned int recordLength = 1 /* handshake message type */ + |
michael@0 | 2377 | 3 /* handshake message length */ + |
michael@0 | 2378 | clientHelloLength; |
michael@0 | 2379 | unsigned int extensionLength; |
michael@0 | 2380 | |
michael@0 | 2381 | if (recordLength < 256 || recordLength >= 512) { |
michael@0 | 2382 | return 0; |
michael@0 | 2383 | } |
michael@0 | 2384 | |
michael@0 | 2385 | extensionLength = 512 - recordLength; |
michael@0 | 2386 | /* Extensions take at least four bytes to encode. */ |
michael@0 | 2387 | if (extensionLength < 4) { |
michael@0 | 2388 | extensionLength = 4; |
michael@0 | 2389 | } |
michael@0 | 2390 | |
michael@0 | 2391 | return extensionLength; |
michael@0 | 2392 | } |
michael@0 | 2393 | |
michael@0 | 2394 | /* ssl3_AppendPaddingExtension possibly adds an extension which ensures that a |
michael@0 | 2395 | * ClientHello record is either < 256 bytes or is >= 512 bytes. This ensures |
michael@0 | 2396 | * that we don't trigger bugs in F5 products. */ |
michael@0 | 2397 | PRInt32 |
michael@0 | 2398 | ssl3_AppendPaddingExtension(sslSocket *ss, unsigned int extensionLen, |
michael@0 | 2399 | PRUint32 maxBytes) |
michael@0 | 2400 | { |
michael@0 | 2401 | unsigned int paddingLen = extensionLen - 4; |
michael@0 | 2402 | static unsigned char padding[256]; |
michael@0 | 2403 | |
michael@0 | 2404 | if (extensionLen == 0) { |
michael@0 | 2405 | return 0; |
michael@0 | 2406 | } |
michael@0 | 2407 | |
michael@0 | 2408 | if (extensionLen < 4 || |
michael@0 | 2409 | extensionLen > maxBytes || |
michael@0 | 2410 | paddingLen > sizeof(padding)) { |
michael@0 | 2411 | PORT_Assert(0); |
michael@0 | 2412 | return -1; |
michael@0 | 2413 | } |
michael@0 | 2414 | |
michael@0 | 2415 | if (SECSuccess != ssl3_AppendHandshakeNumber(ss, ssl_padding_xtn, 2)) |
michael@0 | 2416 | return -1; |
michael@0 | 2417 | if (SECSuccess != ssl3_AppendHandshakeNumber(ss, paddingLen, 2)) |
michael@0 | 2418 | return -1; |
michael@0 | 2419 | if (SECSuccess != ssl3_AppendHandshake(ss, padding, paddingLen)) |
michael@0 | 2420 | return -1; |
michael@0 | 2421 | |
michael@0 | 2422 | return extensionLen; |
michael@0 | 2423 | } |