| Index: net/third_party/nss/ssl/ssl3ext.c
|
| diff --git a/net/third_party/nss/ssl/ssl3ext.c b/net/third_party/nss/ssl/ssl3ext.c
|
| index 9214a2e6b3bdc2e923d0beba0245b6ba71bf5838..eb3fb70f2805c444317ee87ee55760b36fa31660 100644
|
| --- a/net/third_party/nss/ssl/ssl3ext.c
|
| +++ b/net/third_party/nss/ssl/ssl3ext.c
|
| @@ -101,6 +101,12 @@ static PRInt32 ssl3_ClientSendDraftVersionXtn(sslSocket *ss, PRBool append,
|
| PRUint32 maxBytes);
|
| static SECStatus ssl3_ServerHandleDraftVersionXtn(sslSocket *ss, PRUint16 ex_type,
|
| SECItem *data);
|
| +static PRInt32 ssl3_SendExtendedMasterSecretXtn(sslSocket *ss, PRBool append,
|
| + PRUint32 maxBytes);
|
| +static SECStatus ssl3_HandleExtendedMasterSecretXtn(sslSocket *ss,
|
| + PRUint16 ex_type,
|
| + SECItem *data);
|
| +
|
|
|
| /*
|
| * Write bytes. Using this function means the SECItem structure
|
| @@ -266,6 +272,7 @@ static const ssl3HelloExtensionHandler clientHelloHandlers[] = {
|
| { ssl_cert_status_xtn, &ssl3_ServerHandleStatusRequestXtn },
|
| { ssl_signature_algorithms_xtn, &ssl3_ServerHandleSigAlgsXtn },
|
| { ssl_tls13_draft_version_xtn, &ssl3_ServerHandleDraftVersionXtn },
|
| + { ssl_extended_master_secret_xtn, &ssl3_HandleExtendedMasterSecretXtn },
|
| { -1, NULL }
|
| };
|
|
|
| @@ -281,6 +288,7 @@ static const ssl3HelloExtensionHandler serverHelloHandlersTLS[] = {
|
| { ssl_use_srtp_xtn, &ssl3_ClientHandleUseSRTPXtn },
|
| { ssl_channel_id_xtn, &ssl3_ClientHandleChannelIDXtn },
|
| { ssl_cert_status_xtn, &ssl3_ClientHandleStatusRequestXtn },
|
| + { ssl_extended_master_secret_xtn, &ssl3_HandleExtendedMasterSecretXtn },
|
| { ssl_signed_certificate_timestamp_xtn,
|
| &ssl3_ClientHandleSignedCertTimestampXtn },
|
| { -1, NULL }
|
| @@ -319,6 +327,7 @@ ssl3HelloExtensionSender clientHelloSendersTLS[SSL_MAX_EXTENSIONS] = {
|
| * extension. */
|
| { ssl_signature_algorithms_xtn, &ssl3_ClientSendSigAlgsXtn },
|
| { ssl_tls13_draft_version_xtn, &ssl3_ClientSendDraftVersionXtn },
|
| + { ssl_extended_master_secret_xtn, &ssl3_SendExtendedMasterSecretXtn},
|
| /* any extra entries will appear as { 0, NULL } */
|
| };
|
|
|
| @@ -331,7 +340,7 @@ ssl3HelloExtensionSender clientHelloSendersSSL3[SSL_MAX_EXTENSIONS] = {
|
| static PRBool
|
| arrayContainsExtension(const PRUint16 *array, PRUint32 len, PRUint16 ex_type)
|
| {
|
| - int i;
|
| + unsigned int i;
|
| for (i = 0; i < len; i++) {
|
| if (ex_type == array[i])
|
| return PR_TRUE;
|
| @@ -433,12 +442,12 @@ ssl3_HandleServerNameXtn(sslSocket * ss, PRUint16 ex_type, SECItem *data)
|
| }
|
| /* length of server_name_list */
|
| listLenBytes = ssl3_ConsumeHandshakeNumber(ss, 2, &data->data, &data->len);
|
| - if (listLenBytes < 0 || listLenBytes != data->len) {
|
| - (void)ssl3_DecodeError(ss);
|
| + if (listLenBytes < 0) {
|
| return SECFailure;
|
| }
|
| - if (listLenBytes == 0) {
|
| - return SECSuccess; /* ignore an empty extension */
|
| + if (listLenBytes == 0 || listLenBytes != data->len) {
|
| + (void)ssl3_DecodeError(ss);
|
| + return SECFailure;
|
| }
|
| ldata = *data;
|
| /* Calculate the size of the array.*/
|
| @@ -463,15 +472,12 @@ ssl3_HandleServerNameXtn(sslSocket * ss, PRUint16 ex_type, SECItem *data)
|
| }
|
| listCount += 1;
|
| }
|
| - if (!listCount) {
|
| - return SECFailure; /* nothing we can act on */
|
| - }
|
| names = PORT_ZNewArray(SECItem, listCount);
|
| if (!names) {
|
| return SECFailure;
|
| }
|
| for (i = 0;i < listCount;i++) {
|
| - int j;
|
| + unsigned int j;
|
| PRInt32 type;
|
| SECStatus rv;
|
| PRBool nametypePresent = PR_FALSE;
|
| @@ -559,7 +565,11 @@ ssl3_SendSessionTicketXtn(
|
| }
|
| }
|
|
|
| - if (append && maxBytes >= extension_length) {
|
| + if (maxBytes < (PRUint32)extension_length) {
|
| + PORT_Assert(0);
|
| + return 0;
|
| + }
|
| + if (append) {
|
| SECStatus rv;
|
| /* extension_type */
|
| rv = ssl3_AppendHandshakeNumber(ss, ssl_session_ticket_xtn, 2);
|
| @@ -582,9 +592,6 @@ ssl3_SendSessionTicketXtn(
|
| xtnData->advertised[xtnData->numAdvertised++] =
|
| ssl_session_ticket_xtn;
|
| }
|
| - } else if (maxBytes < extension_length) {
|
| - PORT_Assert(0);
|
| - return 0;
|
| }
|
| return extension_length;
|
|
|
| @@ -645,12 +652,17 @@ ssl3_SelectAppProtocol(sslSocket *ss, PRUint16 ex_type, SECItem *data)
|
|
|
| rv = ssl3_ValidateNextProtoNego(data->data, data->len);
|
| if (rv != SECSuccess) {
|
| - PORT_SetError(SSL_ERROR_NEXT_PROTOCOL_DATA_INVALID);
|
| (void)SSL3_SendAlert(ss, alert_fatal, decode_error);
|
| + PORT_SetError(SSL_ERROR_NEXT_PROTOCOL_DATA_INVALID);
|
| return rv;
|
| }
|
|
|
| PORT_Assert(ss->nextProtoCallback);
|
| + /* For ALPN, the cipher suite isn't selected yet. Note that extensions
|
| + * sometimes affect what cipher suite is selected, e.g., for ECC. */
|
| + PORT_Assert((ss->ssl3.hs.preliminaryInfo &
|
| + ssl_preinfo_all & ~ssl_preinfo_cipher_suite) ==
|
| + (ssl_preinfo_all & ~ssl_preinfo_cipher_suite));
|
| rv = ss->nextProtoCallback(ss->nextProtoArg, ss->fd, data->data, data->len,
|
| result.data, &result.len, sizeof(resultBuffer));
|
| if (rv != SECSuccess) {
|
| @@ -673,8 +685,8 @@ ssl3_SelectAppProtocol(sslSocket *ss, PRUint16 ex_type, SECItem *data)
|
| ss->ssl3.nextProtoState != SSL_NEXT_PROTO_NEGOTIATED) {
|
| /* The callback might say OK, but then it picks a default value - one
|
| * that was not listed. That's OK for NPN, but not ALPN. */
|
| - PORT_SetError(SSL_ERROR_NEXT_PROTOCOL_NO_PROTOCOL);
|
| (void)SSL3_SendAlert(ss, alert_fatal, no_application_protocol);
|
| + PORT_SetError(SSL_ERROR_NEXT_PROTOCOL_NO_PROTOCOL);
|
| return SECFailure;
|
| }
|
|
|
| @@ -693,8 +705,8 @@ ssl3_ServerHandleAppProtoXtn(sslSocket *ss, PRUint16 ex_type, SECItem *data)
|
| * despite it being permitted by the spec. */
|
| if (ss->firstHsDone || data->len == 0) {
|
| /* Clients MUST send a non-empty ALPN extension. */
|
| - PORT_SetError(SSL_ERROR_NEXT_PROTOCOL_DATA_INVALID);
|
| (void)SSL3_SendAlert(ss, alert_fatal, illegal_parameter);
|
| + PORT_SetError(SSL_ERROR_NEXT_PROTOCOL_DATA_INVALID);
|
| return SECFailure;
|
| }
|
|
|
| @@ -721,8 +733,8 @@ ssl3_ServerHandleAppProtoXtn(sslSocket *ss, PRUint16 ex_type, SECItem *data)
|
| rv = ssl3_RegisterServerHelloExtensionSender(
|
| ss, ex_type, ssl3_ServerSendAppProtoXtn);
|
| if (rv != SECSuccess) {
|
| - PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
|
| (void)SSL3_SendAlert(ss, alert_fatal, internal_error);
|
| + PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
|
| return rv;
|
| }
|
| }
|
| @@ -742,8 +754,8 @@ ssl3_ClientHandleNextProtoNegoXtn(sslSocket *ss, PRUint16 ex_type,
|
| * we've negotiated NPN then we're required to send the NPN handshake
|
| * message. Thus, these two extensions cannot both be negotiated on the
|
| * same connection. */
|
| - PORT_SetError(SSL_ERROR_BAD_SERVER);
|
| (void)SSL3_SendAlert(ss, alert_fatal, illegal_parameter);
|
| + PORT_SetError(SSL_ERROR_BAD_SERVER);
|
| return SECFailure;
|
| }
|
|
|
| @@ -753,8 +765,8 @@ ssl3_ClientHandleNextProtoNegoXtn(sslSocket *ss, PRUint16 ex_type,
|
| * we sent the ClientHello and now. */
|
| if (!ss->nextProtoCallback) {
|
| PORT_Assert(0);
|
| - PORT_SetError(SSL_ERROR_NEXT_PROTOCOL_NO_CALLBACK);
|
| (void)SSL3_SendAlert(ss, alert_fatal, internal_error);
|
| + PORT_SetError(SSL_ERROR_NEXT_PROTOCOL_NO_CALLBACK);
|
| return SECFailure;
|
| }
|
|
|
| @@ -778,16 +790,16 @@ ssl3_ClientHandleAppProtoXtn(sslSocket *ss, PRUint16 ex_type, SECItem *data)
|
| * uint8 len; // where len >= 1
|
| * uint8 protocol_name[len]; */
|
| if (data->len < 4 || data->len > 2 + 1 + 255) {
|
| - PORT_SetError(SSL_ERROR_NEXT_PROTOCOL_DATA_INVALID);
|
| (void)SSL3_SendAlert(ss, alert_fatal, decode_error);
|
| + PORT_SetError(SSL_ERROR_NEXT_PROTOCOL_DATA_INVALID);
|
| return SECFailure;
|
| }
|
|
|
| list_len = ssl3_ConsumeHandshakeNumber(ss, 2, &data->data, &data->len);
|
| /* The list has to be the entire extension. */
|
| if (list_len != data->len) {
|
| - PORT_SetError(SSL_ERROR_NEXT_PROTOCOL_DATA_INVALID);
|
| (void)SSL3_SendAlert(ss, alert_fatal, decode_error);
|
| + PORT_SetError(SSL_ERROR_NEXT_PROTOCOL_DATA_INVALID);
|
| return SECFailure;
|
| }
|
|
|
| @@ -795,8 +807,8 @@ ssl3_ClientHandleAppProtoXtn(sslSocket *ss, PRUint16 ex_type, SECItem *data)
|
| &data->data, &data->len);
|
| /* The list must have exactly one value. */
|
| if (rv != SECSuccess || data->len != 0) {
|
| - PORT_SetError(SSL_ERROR_NEXT_PROTOCOL_DATA_INVALID);
|
| (void)SSL3_SendAlert(ss, alert_fatal, decode_error);
|
| + PORT_SetError(SSL_ERROR_NEXT_PROTOCOL_DATA_INVALID);
|
| return SECFailure;
|
| }
|
|
|
| @@ -819,7 +831,10 @@ ssl3_ClientSendNextProtoNegoXtn(sslSocket * ss, PRBool append,
|
|
|
| extension_length = 4;
|
|
|
| - if (append && maxBytes >= extension_length) {
|
| + if (maxBytes < (PRUint32)extension_length) {
|
| + return 0;
|
| + }
|
| + if (append) {
|
| SECStatus rv;
|
| rv = ssl3_AppendHandshakeNumber(ss, ssl_next_proto_nego_xtn, 2);
|
| if (rv != SECSuccess)
|
| @@ -829,8 +844,6 @@ ssl3_ClientSendNextProtoNegoXtn(sslSocket * ss, PRBool append,
|
| goto loser;
|
| ss->xtnData.advertised[ss->xtnData.numAdvertised++] =
|
| ssl_next_proto_nego_xtn;
|
| - } else if (maxBytes < extension_length) {
|
| - return 0;
|
| }
|
|
|
| return extension_length;
|
| @@ -854,7 +867,10 @@ ssl3_ClientSendAppProtoXtn(sslSocket * ss, PRBool append, PRUint32 maxBytes)
|
| 2 /* protocol name list length */ +
|
| ss->opt.nextProtoNego.len;
|
|
|
| - if (append && maxBytes >= extension_length) {
|
| + if (maxBytes < (PRUint32)extension_length) {
|
| + return 0;
|
| + }
|
| + if (append) {
|
| /* NPN requires that the client's fallback protocol is first in the
|
| * list. However, ALPN sends protocols in preference order. So we
|
| * allocate a buffer and move the first protocol to the end of the
|
| @@ -894,8 +910,6 @@ ssl3_ClientSendAppProtoXtn(sslSocket * ss, PRBool append, PRUint32 maxBytes)
|
| }
|
| ss->xtnData.advertised[ss->xtnData.numAdvertised++] =
|
| ssl_app_layer_protocol_xtn;
|
| - } else if (maxBytes < extension_length) {
|
| - return 0;
|
| }
|
|
|
| return extension_length;
|
| @@ -923,7 +937,10 @@ ssl3_ServerSendAppProtoXtn(sslSocket * ss, PRBool append, PRUint32 maxBytes)
|
| 2 /* protocol name list */ + 1 /* name length */ +
|
| ss->ssl3.nextProto.len;
|
|
|
| - if (append && maxBytes >= extension_length) {
|
| + if (maxBytes < (PRUint32)extension_length) {
|
| + return 0;
|
| + }
|
| + if (append) {
|
| SECStatus rv;
|
| rv = ssl3_AppendHandshakeNumber(ss, ssl_app_layer_protocol_xtn, 2);
|
| if (rv != SECSuccess) {
|
| @@ -942,8 +959,6 @@ ssl3_ServerSendAppProtoXtn(sslSocket * ss, PRBool append, PRUint32 maxBytes)
|
| if (rv != SECSuccess) {
|
| return -1;
|
| }
|
| - } else if (maxBytes < extension_length) {
|
| - return 0;
|
| }
|
|
|
| return extension_length;
|
| @@ -1045,7 +1060,10 @@ ssl3_ServerSendStatusRequestXtn(
|
| return 0;
|
|
|
| extension_length = 2 + 2;
|
| - if (append && maxBytes >= extension_length) {
|
| + if (maxBytes < (PRUint32)extension_length) {
|
| + return 0;
|
| + }
|
| + if (append) {
|
| /* extension_type */
|
| rv = ssl3_AppendHandshakeNumber(ss, ssl_cert_status_xtn, 2);
|
| if (rv != SECSuccess)
|
| @@ -1078,7 +1096,11 @@ ssl3_ClientSendStatusRequestXtn(sslSocket * ss, PRBool append,
|
| */
|
| extension_length = 9;
|
|
|
| - if (append && maxBytes >= extension_length) {
|
| + if (maxBytes < (PRUint32)extension_length) {
|
| + PORT_Assert(0);
|
| + return 0;
|
| + }
|
| + if (append) {
|
| SECStatus rv;
|
| TLSExtensionData *xtnData;
|
|
|
| @@ -1106,9 +1128,6 @@ ssl3_ClientSendStatusRequestXtn(sslSocket * ss, PRBool append,
|
|
|
| xtnData = &ss->xtnData;
|
| xtnData->advertised[xtnData->numAdvertised++] = ssl_cert_status_xtn;
|
| - } else if (maxBytes < extension_length) {
|
| - PORT_Assert(0);
|
| - return 0;
|
| }
|
| return extension_length;
|
| }
|
| @@ -1120,7 +1139,7 @@ ssl3_ClientSendStatusRequestXtn(sslSocket * ss, PRBool append,
|
| SECStatus
|
| ssl3_SendNewSessionTicket(sslSocket *ss)
|
| {
|
| - int i;
|
| + PRUint32 i;
|
| SECStatus rv;
|
| NewSessionTicket ticket;
|
| SECItem plaintext;
|
| @@ -1152,7 +1171,7 @@ ssl3_SendNewSessionTicket(sslSocket *ss)
|
| CK_MECHANISM_TYPE cipherMech = CKM_AES_CBC;
|
| PK11Context *aes_ctx_pkcs11;
|
| CK_MECHANISM_TYPE macMech = CKM_SHA256_HMAC;
|
| - PK11Context *hmac_ctx_pkcs11;
|
| + PK11Context *hmac_ctx_pkcs11 = NULL;
|
| unsigned char computed_mac[TLS_EX_SESS_TICKET_MAC_LENGTH];
|
| unsigned int computed_mac_length;
|
| unsigned char iv[AES_BLOCK_SIZE];
|
| @@ -1200,7 +1219,8 @@ ssl3_SendNewSessionTicket(sslSocket *ss)
|
| sslSessionID sid;
|
| PORT_Memset(&sid, 0, sizeof(sslSessionID));
|
|
|
| - if (ss->ssl3.hs.kea_def->kea == kea_ecdhe_rsa) {
|
| + if (ss->ssl3.hs.kea_def->kea == kea_ecdhe_rsa ||
|
| + ss->ssl3.hs.kea_def->kea == kea_dhe_rsa) {
|
| effectiveExchKeyType = kt_rsa;
|
| } else {
|
| effectiveExchKeyType = ss->ssl3.hs.kea_def->exchKeyType;
|
| @@ -1243,6 +1263,7 @@ ssl3_SendNewSessionTicket(sslSocket *ss)
|
| + cert_length /* cert */
|
| + 1 /* server name type */
|
| + srvNameLen /* name len + length field */
|
| + + 1 /* extendedMasterSecretUsed */
|
| + sizeof(ticket.ticket_lifetime_hint);
|
| padding_length = AES_BLOCK_SIZE -
|
| (ciphertext_length % AES_BLOCK_SIZE);
|
| @@ -1341,6 +1362,11 @@ ssl3_SendNewSessionTicket(sslSocket *ss)
|
| if (rv != SECSuccess) goto loser;
|
| }
|
|
|
| + /* extendedMasterSecretUsed */
|
| + rv = ssl3_AppendNumberToItem(
|
| + &plaintext, ss->sec.ci.sid->u.ssl3.keys.extendedMasterSecretUsed, 1);
|
| + if (rv != SECSuccess) goto loser;
|
| +
|
| PORT_Assert(plaintext.len == padding_length);
|
| for (i = 0; i < padding_length; i++)
|
| plaintext.data[i] = (unsigned char)padding_length;
|
| @@ -1410,14 +1436,18 @@ ssl3_SendNewSessionTicket(sslSocket *ss)
|
| goto loser;
|
|
|
| rv = PK11_DigestBegin(hmac_ctx_pkcs11);
|
| + if (rv != SECSuccess) goto loser;
|
| rv = PK11_DigestOp(hmac_ctx_pkcs11, key_name,
|
| SESS_TICKET_KEY_NAME_LEN);
|
| + if (rv != SECSuccess) goto loser;
|
| rv = PK11_DigestOp(hmac_ctx_pkcs11, iv, sizeof(iv));
|
| + if (rv != SECSuccess) goto loser;
|
| rv = PK11_DigestOp(hmac_ctx_pkcs11, (unsigned char *)length_buf, 2);
|
| + if (rv != SECSuccess) goto loser;
|
| rv = PK11_DigestOp(hmac_ctx_pkcs11, ciphertext.data, ciphertext.len);
|
| + if (rv != SECSuccess) goto loser;
|
| rv = PK11_DigestFinal(hmac_ctx_pkcs11, computed_mac,
|
| &computed_mac_length, sizeof(computed_mac));
|
| - PK11_DestroyContext(hmac_ctx_pkcs11, PR_TRUE);
|
| if (rv != SECSuccess) goto loser;
|
| }
|
|
|
| @@ -1446,6 +1476,8 @@ ssl3_SendNewSessionTicket(sslSocket *ss)
|
| if (rv != SECSuccess) goto loser;
|
|
|
| loser:
|
| + if (hmac_ctx_pkcs11)
|
| + PK11_DestroyContext(hmac_ctx_pkcs11, PR_TRUE);
|
| if (plaintext_item.data)
|
| SECITEM_FreeItem(&plaintext_item, PR_FALSE);
|
| if (ciphertext.data)
|
| @@ -1495,7 +1527,7 @@ ssl3_ServerHandleSessionTicketXtn(sslSocket *ss, PRUint16 ex_type,
|
| if (data->len == 0) {
|
| ss->xtnData.emptySessionTicket = PR_TRUE;
|
| } else {
|
| - int i;
|
| + PRUint32 i;
|
| SECItem extension_data;
|
| EncryptedSessionTicket enc_session_ticket;
|
| unsigned char computed_mac[TLS_EX_SESS_TICKET_MAC_LENGTH];
|
| @@ -1698,9 +1730,10 @@ ssl3_ServerHandleSessionTicketXtn(sslSocket *ss, PRUint16 ex_type,
|
| goto loser;
|
| }
|
|
|
| - /* Read ticket_version (which is ignored for now.) */
|
| + /* Read ticket_version and reject if the version is wrong */
|
| temp = ssl3_ConsumeHandshakeNumber(ss, 2, &buffer, &buffer_len);
|
| - if (temp < 0) goto no_ticket;
|
| + if (temp != TLS_EX_SESS_TICKET_VERSION) goto no_ticket;
|
| +
|
| parsed_session_ticket->ticket_version = (SSL3ProtocolVersion)temp;
|
|
|
| /* Read SSLVersion. */
|
| @@ -1801,6 +1834,13 @@ ssl3_ServerHandleSessionTicketXtn(sslSocket *ss, PRUint16 ex_type,
|
| parsed_session_ticket->srvName.type = nameType;
|
| }
|
|
|
| + /* Read extendedMasterSecretUsed */
|
| + temp = ssl3_ConsumeHandshakeNumber(ss, 1, &buffer, &buffer_len);
|
| + if (temp < 0)
|
| + goto no_ticket;
|
| + PORT_Assert(temp == PR_TRUE || temp == PR_FALSE);
|
| + parsed_session_ticket->extendedMasterSecretUsed = (PRBool)temp;
|
| +
|
| /* Done parsing. Check that all bytes have been consumed. */
|
| if (buffer_len != padding_length)
|
| goto no_ticket;
|
| @@ -1847,6 +1887,8 @@ ssl3_ServerHandleSessionTicketXtn(sslSocket *ss, PRUint16 ex_type,
|
| parsed_session_ticket->ms_is_wrapped;
|
| sid->u.ssl3.masterValid = PR_TRUE;
|
| sid->u.ssl3.keys.resumable = PR_TRUE;
|
| + sid->u.ssl3.keys.extendedMasterSecretUsed = parsed_session_ticket->
|
| + extendedMasterSecretUsed;
|
|
|
| /* Copy over client cert from session ticket if there is one. */
|
| if (parsed_session_ticket->peer_cert.data != NULL) {
|
| @@ -2085,7 +2127,10 @@ ssl3_SendRenegotiationInfoXtn(
|
| (ss->sec.isServer ? ss->ssl3.hs.finishedBytes * 2
|
| : ss->ssl3.hs.finishedBytes);
|
| needed = 5 + len;
|
| - if (append && maxBytes >= needed) {
|
| + if (maxBytes < (PRUint32)needed) {
|
| + return 0;
|
| + }
|
| + if (append) {
|
| SECStatus rv;
|
| /* extension_type */
|
| rv = ssl3_AppendHandshakeNumber(ss, ssl_renegotiation_info_xtn, 2);
|
| @@ -2138,8 +2183,8 @@ ssl3_HandleRenegotiationInfoXtn(sslSocket *ss, PRUint16 ex_type, SECItem *data)
|
| }
|
| if (len && NSS_SecureMemcmp(ss->ssl3.hs.finishedMsgs.data,
|
| data->data + 1, len)) {
|
| - PORT_SetError(SSL_ERROR_BAD_HANDSHAKE_HASH_VALUE);
|
| (void)SSL3_SendAlert(ss, alert_fatal, handshake_failure);
|
| + PORT_SetError(SSL_ERROR_BAD_HANDSHAKE_HASH_VALUE);
|
| return SECFailure;
|
| }
|
| /* remember that we got this extension and it was correct. */
|
| @@ -2263,8 +2308,8 @@ ssl3_ClientHandleUseSRTPXtn(sslSocket * ss, PRUint16 ex_type, SECItem *data)
|
| }
|
|
|
| if (!found) {
|
| - PORT_SetError(SSL_ERROR_RX_MALFORMED_SERVER_HELLO);
|
| (void)SSL3_SendAlert(ss, alert_fatal, illegal_parameter);
|
| + PORT_SetError(SSL_ERROR_RX_MALFORMED_SERVER_HELLO);
|
| return SECFailure;
|
| }
|
|
|
| @@ -2277,8 +2322,8 @@ ssl3_ClientHandleUseSRTPXtn(sslSocket * ss, PRUint16 ex_type, SECItem *data)
|
|
|
| /* We didn't offer an MKI, so this must be 0 length */
|
| if (litem.len != 0) {
|
| - PORT_SetError(SSL_ERROR_RX_MALFORMED_SERVER_HELLO);
|
| (void)SSL3_SendAlert(ss, alert_fatal, illegal_parameter);
|
| + PORT_SetError(SSL_ERROR_RX_MALFORMED_SERVER_HELLO);
|
| return SECFailure;
|
| }
|
|
|
| @@ -2374,7 +2419,7 @@ ssl3_ServerHandleSigAlgsXtn(sslSocket * ss, PRUint16 ex_type, SECItem *data)
|
| SECStatus rv;
|
| SECItem algorithms;
|
| const unsigned char *b;
|
| - unsigned int numAlgorithms, i, j;
|
| + unsigned int numAlgorithms, i;
|
|
|
| /* Ignore this extension if we aren't doing TLS 1.2 or greater. */
|
| if (ss->version < SSL_LIBRARY_VERSION_TLS_1_2) {
|
| @@ -2388,8 +2433,8 @@ ssl3_ServerHandleSigAlgsXtn(sslSocket * ss, PRUint16 ex_type, SECItem *data)
|
| }
|
| /* Trailing data, empty value, or odd-length value is invalid. */
|
| if (data->len != 0 || algorithms.len == 0 || (algorithms.len & 1) != 0) {
|
| - PORT_SetError(SSL_ERROR_RX_MALFORMED_CLIENT_HELLO);
|
| (void)SSL3_SendAlert(ss, alert_fatal, decode_error);
|
| + PORT_SetError(SSL_ERROR_RX_MALFORMED_CLIENT_HELLO);
|
| return SECFailure;
|
| }
|
|
|
| @@ -2401,30 +2446,24 @@ ssl3_ServerHandleSigAlgsXtn(sslSocket * ss, PRUint16 ex_type, SECItem *data)
|
| }
|
|
|
| ss->ssl3.hs.clientSigAndHash =
|
| - PORT_NewArray(SSL3SignatureAndHashAlgorithm, numAlgorithms);
|
| + PORT_NewArray(SSLSignatureAndHashAlg, numAlgorithms);
|
| if (!ss->ssl3.hs.clientSigAndHash) {
|
| - PORT_SetError(SSL_ERROR_RX_MALFORMED_CLIENT_HELLO);
|
| (void)SSL3_SendAlert(ss, alert_fatal, internal_error);
|
| + PORT_SetError(SSL_ERROR_RX_MALFORMED_CLIENT_HELLO);
|
| return SECFailure;
|
| }
|
| ss->ssl3.hs.numClientSigAndHash = 0;
|
|
|
| b = algorithms.data;
|
| - for (i = j = 0; i < numAlgorithms; i++) {
|
| - unsigned char tls_hash = *(b++);
|
| - unsigned char tls_sig = *(b++);
|
| - SECOidTag hash = ssl3_TLSHashAlgorithmToOID(tls_hash);
|
| -
|
| - if (hash == SEC_OID_UNKNOWN) {
|
| - /* We ignore formats that we don't understand. */
|
| - continue;
|
| + ss->ssl3.hs.numClientSigAndHash = 0;
|
| + for (i = 0; i < numAlgorithms; i++) {
|
| + SSLSignatureAndHashAlg *sigAndHash =
|
| + &ss->ssl3.hs.clientSigAndHash[ss->ssl3.hs.numClientSigAndHash];
|
| + sigAndHash->hashAlg = (SSLHashType)*(b++);
|
| + sigAndHash->sigAlg = (SSLSignType)*(b++);
|
| + if (ssl3_IsSupportedSignatureAlgorithm(sigAndHash)) {
|
| + ++ss->ssl3.hs.numClientSigAndHash;
|
| }
|
| - /* tls_sig support will be checked later in
|
| - * ssl3_PickSignatureHashAlgorithm. */
|
| - ss->ssl3.hs.clientSigAndHash[j].hashAlg = hash;
|
| - ss->ssl3.hs.clientSigAndHash[j].sigAlg = tls_sig;
|
| - ++j;
|
| - ++ss->ssl3.hs.numClientSigAndHash;
|
| }
|
|
|
| if (!ss->ssl3.hs.numClientSigAndHash) {
|
| @@ -2442,60 +2481,60 @@ ssl3_ServerHandleSigAlgsXtn(sslSocket * ss, PRUint16 ex_type, SECItem *data)
|
| /* ssl3_ClientSendSigAlgsXtn sends the signature_algorithm extension for TLS
|
| * 1.2 ClientHellos. */
|
| static PRInt32
|
| -ssl3_ClientSendSigAlgsXtn(sslSocket * ss, PRBool append, PRUint32 maxBytes)
|
| +ssl3_ClientSendSigAlgsXtn(sslSocket *ss, PRBool append, PRUint32 maxBytes)
|
| {
|
| - static const unsigned char signatureAlgorithms[] = {
|
| - /* This block is the contents of our signature_algorithms extension, in
|
| - * wire format. See
|
| - * https://tools.ietf.org/html/rfc5246#section-7.4.1.4.1 */
|
| - tls_hash_sha256, tls_sig_rsa,
|
| - tls_hash_sha384, tls_sig_rsa,
|
| - tls_hash_sha512, tls_sig_rsa,
|
| - tls_hash_sha1, tls_sig_rsa,
|
| -#ifndef NSS_DISABLE_ECC
|
| - tls_hash_sha256, tls_sig_ecdsa,
|
| - tls_hash_sha384, tls_sig_ecdsa,
|
| - tls_hash_sha512, tls_sig_ecdsa,
|
| - tls_hash_sha1, tls_sig_ecdsa,
|
| -#endif
|
| - tls_hash_sha256, tls_sig_dsa,
|
| - tls_hash_sha1, tls_sig_dsa,
|
| - };
|
| PRInt32 extension_length;
|
| + unsigned int i;
|
| + PRInt32 pos=0;
|
| + PRUint32 policy;
|
| + PRUint8 buf[MAX_SIGNATURE_ALGORITHMS * 2];
|
|
|
| if (ss->version < SSL_LIBRARY_VERSION_TLS_1_2) {
|
| return 0;
|
| }
|
|
|
| + for (i=0; i < ss->ssl3.signatureAlgorithmCount; i++) {
|
| + SECOidTag hashOID = ssl3_TLSHashAlgorithmToOID(
|
| + ss->ssl3.signatureAlgorithms[i].hashAlg);
|
| + if ((NSS_GetAlgorithmPolicy(hashOID, & policy) != SECSuccess) ||
|
| + (policy & NSS_USE_ALG_IN_SSL_KX)) {
|
| + buf[pos++] = ss->ssl3.signatureAlgorithms[i].hashAlg;
|
| + buf[pos++] = ss->ssl3.signatureAlgorithms[i].sigAlg;
|
| + }
|
| + }
|
| +
|
| extension_length =
|
| 2 /* extension type */ +
|
| 2 /* extension length */ +
|
| 2 /* supported_signature_algorithms length */ +
|
| - sizeof(signatureAlgorithms);
|
| + pos;
|
| +
|
| + if (maxBytes < extension_length) {
|
| + PORT_Assert(0);
|
| + return 0;
|
| + }
|
|
|
| - if (append && maxBytes >= extension_length) {
|
| + if (append) {
|
| SECStatus rv;
|
| rv = ssl3_AppendHandshakeNumber(ss, ssl_signature_algorithms_xtn, 2);
|
| - if (rv != SECSuccess)
|
| - goto loser;
|
| + if (rv != SECSuccess) {
|
| + return -1;
|
| + }
|
| rv = ssl3_AppendHandshakeNumber(ss, extension_length - 4, 2);
|
| - if (rv != SECSuccess)
|
| - goto loser;
|
| - rv = ssl3_AppendHandshakeVariable(ss, signatureAlgorithms,
|
| - sizeof(signatureAlgorithms), 2);
|
| - if (rv != SECSuccess)
|
| - goto loser;
|
| + if (rv != SECSuccess) {
|
| + return -1;
|
| + }
|
| +
|
| + rv = ssl3_AppendHandshakeVariable(ss, buf, extension_length - 6, 2);
|
| + if (rv != SECSuccess) {
|
| + return -1;
|
| + }
|
| +
|
| ss->xtnData.advertised[ss->xtnData.numAdvertised++] =
|
| ssl_signature_algorithms_xtn;
|
| - } else if (maxBytes < extension_length) {
|
| - PORT_Assert(0);
|
| - return 0;
|
| }
|
|
|
| return extension_length;
|
| -
|
| -loser:
|
| - return -1;
|
| }
|
|
|
| unsigned int
|
| @@ -2565,7 +2604,11 @@ ssl3_ClientSendDraftVersionXtn(sslSocket * ss, PRBool append, PRUint32 maxBytes)
|
| }
|
|
|
| extension_length = 6; /* Type + length + number */
|
| - if (append && maxBytes >= extension_length) {
|
| + if (maxBytes < (PRUint32)extension_length) {
|
| + PORT_Assert(0);
|
| + return 0;
|
| + }
|
| + if (append) {
|
| SECStatus rv;
|
| rv = ssl3_AppendHandshakeNumber(ss, ssl_tls13_draft_version_xtn, 2);
|
| if (rv != SECSuccess)
|
| @@ -2578,9 +2621,6 @@ ssl3_ClientSendDraftVersionXtn(sslSocket * ss, PRBool append, PRUint32 maxBytes)
|
| goto loser;
|
| ss->xtnData.advertised[ss->xtnData.numAdvertised++] =
|
| ssl_tls13_draft_version_xtn;
|
| - } else if (maxBytes < extension_length) {
|
| - PORT_Assert(0);
|
| - return 0;
|
| }
|
|
|
| return extension_length;
|
| @@ -2633,6 +2673,51 @@ ssl3_ServerHandleDraftVersionXtn(sslSocket * ss, PRUint16 ex_type,
|
| return SECSuccess;
|
| }
|
|
|
| +static PRInt32
|
| +ssl3_SendExtendedMasterSecretXtn(sslSocket * ss, PRBool append,
|
| + PRUint32 maxBytes)
|
| +{
|
| + PRInt32 extension_length;
|
| +
|
| + if (!ss->opt.enableExtendedMS) {
|
| + return 0;
|
| + }
|
| +
|
| +#ifndef NO_PKCS11_BYPASS
|
| + /* Extended MS can only be used w/o bypass mode */
|
| + if (ss->opt.bypassPKCS11) {
|
| + PORT_Assert(0);
|
| + PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
|
| + return -1;
|
| + }
|
| +#endif
|
| +
|
| + /* Always send the extension in this function, since the
|
| + * client always sends it and this function is only called on
|
| + * the server if we negotiated the extension. */
|
| + extension_length = 4; /* Type + length (0) */
|
| + if (maxBytes < extension_length) {
|
| + PORT_Assert(0);
|
| + return 0;
|
| + }
|
| +
|
| + if (append) {
|
| + SECStatus rv;
|
| + rv = ssl3_AppendHandshakeNumber(ss, ssl_extended_master_secret_xtn, 2);
|
| + if (rv != SECSuccess)
|
| + goto loser;
|
| + rv = ssl3_AppendHandshakeNumber(ss, 0, 2);
|
| + if (rv != SECSuccess)
|
| + goto loser;
|
| + ss->xtnData.advertised[ss->xtnData.numAdvertised++] =
|
| + ssl_extended_master_secret_xtn;
|
| + }
|
| +
|
| + return extension_length;
|
| +loser:
|
| + return -1;
|
| +}
|
| +
|
| /* ssl3_ClientSendSignedCertTimestampXtn sends the signed_certificate_timestamp
|
| * extension for TLS ClientHellos. */
|
| static PRInt32
|
| @@ -2646,7 +2731,12 @@ ssl3_ClientSendSignedCertTimestampXtn(sslSocket *ss, PRBool append,
|
| if (!ss->opt.enableSignedCertTimestamps)
|
| return 0;
|
|
|
| - if (append && maxBytes >= extension_length) {
|
| + if (maxBytes < extension_length) {
|
| + PORT_Assert(0);
|
| + return 0;
|
| + }
|
| +
|
| + if (append) {
|
| SECStatus rv;
|
| /* extension_type */
|
| rv = ssl3_AppendHandshakeNumber(ss,
|
| @@ -2660,9 +2750,6 @@ ssl3_ClientSendSignedCertTimestampXtn(sslSocket *ss, PRBool append,
|
| goto loser;
|
| ss->xtnData.advertised[ss->xtnData.numAdvertised++] =
|
| ssl_signed_certificate_timestamp_xtn;
|
| - } else if (maxBytes < extension_length) {
|
| - PORT_Assert(0);
|
| - return 0;
|
| }
|
|
|
| return extension_length;
|
| @@ -2671,6 +2758,46 @@ loser:
|
| }
|
|
|
| static SECStatus
|
| +ssl3_HandleExtendedMasterSecretXtn(sslSocket * ss, PRUint16 ex_type,
|
| + SECItem *data)
|
| +{
|
| + if (ss->version < SSL_LIBRARY_VERSION_TLS_1_0) {
|
| + return SECSuccess;
|
| + }
|
| +
|
| + if (!ss->opt.enableExtendedMS) {
|
| + return SECSuccess;
|
| + }
|
| +
|
| +#ifndef NO_PKCS11_BYPASS
|
| + /* Extended MS can only be used w/o bypass mode */
|
| + if (ss->opt.bypassPKCS11) {
|
| + PORT_Assert(0);
|
| + PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
|
| + return SECFailure;
|
| + }
|
| +#endif
|
| +
|
| + if (data->len != 0) {
|
| + SSL_TRC(30, ("%d: SSL3[%d]: Bogus extended master secret extension",
|
| + SSL_GETPID(), ss->fd));
|
| + return SECFailure;
|
| + }
|
| +
|
| + SSL_DBG(("%d: SSL[%d]: Negotiated extended master secret extension.",
|
| + SSL_GETPID(), ss->fd));
|
| +
|
| + /* Keep track of negotiated extensions. */
|
| + ss->xtnData.negotiated[ss->xtnData.numNegotiated++] = ex_type;
|
| +
|
| + if (ss->sec.isServer) {
|
| + return ssl3_RegisterServerHelloExtensionSender(
|
| + ss, ex_type, ssl3_SendExtendedMasterSecretXtn);
|
| + }
|
| + return SECSuccess;
|
| +}
|
| +
|
| +static SECStatus
|
| ssl3_ClientHandleSignedCertTimestampXtn(sslSocket *ss, PRUint16 ex_type,
|
| SECItem *data)
|
| {
|
|
|