Chromium Code Reviews| Index: net/third_party/nss/ssl/ssl3ext.c |
| =================================================================== |
| --- net/third_party/nss/ssl/ssl3ext.c (revision 199250) |
| +++ 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,135 @@ |
| 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; |
| + } |
| + /* XXX Should we check if we support tls_sig? */ |
|
agl
2013/05/28 20:21:13
Hmm, probably yes although it's just an optimisati
wtc
2013/05/28 23:22:19
Because we will check tls_sig later in ssl3_PickSi
agl
2013/05/28 23:36:36
Right. This filtering is just removing the options
|
| + 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. */ |
| + /* XXX Should we fail the handshake in this case? */ |
|
wtc
2013/05/28 17:50:25
agl: these two XXX comments are also questions for
agl
2013/05/28 20:21:13
The handshake may not need to sign anything, in wh
|
| + 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, |
|
wtc
2013/05/28 17:50:25
Should we add tls_hash_sha512 entries to this arra
agl
2013/05/28 20:21:13
I was just trying to cover Suite-B. I think SHA-51
wtc
2013/05/28 23:22:19
OK, I replaced tls_hash_sha384 with tls_hash_sha22
|
| + 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_sha384, 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; |
| +} |