Index: net/third_party/nss/ssl/ssl3ext.c |
=================================================================== |
--- net/third_party/nss/ssl/ssl3ext.c (revision 202696) |
+++ net/third_party/nss/ssl/ssl3ext.c (working copy) |
@@ -74,6 +74,10 @@ |
SECItem *data); |
static PRInt32 ssl3_ClientSendStatusRequestXtn(sslSocket * ss, PRBool append, |
PRUint32 maxBytes); |
+static PRInt32 ssl3_ClientSendSigAlgsXtn(sslSocket *ss, PRBool append, |
+ PRUint32 maxBytes); |
+static SECStatus ssl3_ServerHandleSigAlgsXtn(sslSocket *ss, PRUint16 ex_type, |
+ SECItem *data); |
/* |
* Write bytes. Using this function means the SECItem structure |
@@ -236,6 +240,7 @@ |
{ ssl_next_proto_nego_xtn, &ssl3_ServerHandleNextProtoNegoXtn }, |
{ ssl_use_srtp_xtn, &ssl3_HandleUseSRTPXtn }, |
{ ssl_cert_status_xtn, &ssl3_ServerHandleStatusRequestXtn }, |
+ { ssl_signature_algorithms_xtn, &ssl3_ServerHandleSigAlgsXtn }, |
{ -1, NULL } |
}; |
@@ -276,7 +281,8 @@ |
{ ssl_next_proto_nego_xtn, &ssl3_ClientSendNextProtoNegoXtn }, |
{ ssl_use_srtp_xtn, &ssl3_SendUseSRTPXtn }, |
{ ssl_channel_id_xtn, &ssl3_ClientSendChannelIDXtn }, |
- { ssl_cert_status_xtn, &ssl3_ClientSendStatusRequestXtn } |
+ { ssl_cert_status_xtn, &ssl3_ClientSendStatusRequestXtn }, |
+ { ssl_signature_algorithms_xtn, &ssl3_ClientSendSigAlgsXtn } |
/* any extra entries will appear as { 0, NULL } */ |
}; |
@@ -2039,3 +2045,134 @@ |
return ssl3_RegisterServerHelloExtensionSender(ss, ssl_use_srtp_xtn, |
ssl3_SendUseSRTPXtn); |
} |
+ |
+/* ssl3_ServerHandleSigAlgsXtn handles the signature_algorithms extension |
+ * from a client. |
+ * See https://tools.ietf.org/html/rfc5246#section-7.4.1.4.1 */ |
+static SECStatus |
+ssl3_ServerHandleSigAlgsXtn(sslSocket * ss, PRUint16 ex_type, SECItem *data) |
+{ |
+ SECStatus rv; |
+ SECItem algorithms; |
+ const unsigned char *b; |
+ 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) { |
+ return SECSuccess; |
+ } |
+ |
+ /* Keep track of negotiated extensions. */ |
+ ss->xtnData.negotiated[ss->xtnData.numNegotiated++] = ex_type; |
+ |
+ rv = ssl3_ConsumeHandshakeVariable(ss, &algorithms, 2, &data->data, |
+ &data->len); |
+ if (rv != SECSuccess) { |
+ return SECFailure; |
+ } |
+ /* Trailing data or odd-length parameters is invalid. */ |
+ if (data->len != 0 || (algorithms.len & 1) != 0) { |
+ PORT_SetError(SSL_ERROR_RX_MALFORMED_CLIENT_HELLO); |
+ return SECFailure; |
+ } |
+ |
+ numAlgorithms = algorithms.len/2; |
+ |
+ if (numAlgorithms == 0) { |
+ return SECSuccess; |
+ } |
+ /* We don't care to process excessive numbers of algorithms. */ |
+ if (numAlgorithms > 512) { |
+ numAlgorithms = 512; |
+ } |
+ |
+ ss->ssl3.hs.clientSigAndHash = |
+ PORT_NewArray(SSL3SignatureAndHashAlgorithm, numAlgorithms); |
+ if (!ss->ssl3.hs.clientSigAndHash) { |
+ return SECFailure; |
+ } |
+ ss->ssl3.hs.numClientSigAndHash = 0; |
+ |
+ b = algorithms.data; |
+ for (i = 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; |
+ } |
+ /* tls_sig support will be checked later in |
+ * ssl3_PickSignatureHashAlgorithm. */ |
+ ss->ssl3.hs.clientSigAndHash[i].hashAlg = hash; |
+ ss->ssl3.hs.clientSigAndHash[i].sigAlg = tls_sig; |
+ ss->ssl3.hs.numClientSigAndHash++; |
+ } |
+ |
+ if (!ss->ssl3.hs.numClientSigAndHash) { |
+ /* We didn't understand any of the client's requested signature |
+ * formats. We'll use the defaults. */ |
+ PORT_Free(ss->ssl3.hs.clientSigAndHash); |
+ ss->ssl3.hs.clientSigAndHash = NULL; |
+ } |
+ |
+ return SECSuccess; |
+} |
+ |
+/* ssl3_ClientSendSigAlgsXtn sends the signature_algorithm extension for TLS |
+ * 1.2 ClientHellos. */ |
+static PRInt32 |
+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_sha1, tls_sig_rsa, |
+#ifdef NSS_ENABLE_ECC |
+ tls_hash_sha256, tls_sig_ecdsa, |
+ tls_hash_sha384, 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; |
+ |
+ if (ss->version < SSL_LIBRARY_VERSION_TLS_1_2) { |
+ return 0; |
+ } |
+ |
+ extension_length = |
+ 2 /* extension type */ + |
+ 2 /* extension length */ + |
+ 2 /* supported_signature_algorithms length */ + |
+ sizeof(signatureAlgorithms); |
+ |
+ if (append && maxBytes >= extension_length) { |
+ SECStatus rv; |
+ rv = ssl3_AppendHandshakeNumber(ss, ssl_signature_algorithms_xtn, 2); |
+ if (rv != SECSuccess) |
+ goto loser; |
+ 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; |
+ 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; |
+} |