Chromium Code Reviews| 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 adb81ed8a46a76fe5bb9aa68a315e2c92ed79222..02e104d700510570e24bdde3e9e4b98dae2566c6 100644 | 
| --- a/net/third_party/nss/ssl/ssl3ext.c | 
| +++ b/net/third_party/nss/ssl/ssl3ext.c | 
| @@ -81,6 +81,12 @@ static PRInt32 ssl3_ClientSendSigAlgsXtn(sslSocket *ss, PRBool append, | 
| PRUint32 maxBytes); | 
| static SECStatus ssl3_ServerHandleSigAlgsXtn(sslSocket *ss, PRUint16 ex_type, | 
| SECItem *data); | 
| +static PRInt32 ssl3_ClientSendSignedCertTimestampXtn(sslSocket *ss, | 
| + PRBool append, | 
| + PRUint32 maxBytes); | 
| +static SECStatus ssl3_ClientHandleSignedCertTimestampXtn(sslSocket *ss, | 
| + PRUint16 ex_type, | 
| + SECItem *data); | 
| /* | 
| * Write bytes. Using this function means the SECItem structure | 
| @@ -259,6 +265,8 @@ static const ssl3HelloExtensionHandler serverHelloHandlersTLS[] = { | 
| { ssl_use_srtp_xtn, &ssl3_HandleUseSRTPXtn }, | 
| { ssl_channel_id_xtn, &ssl3_ClientHandleChannelIDXtn }, | 
| { ssl_cert_status_xtn, &ssl3_ClientHandleStatusRequestXtn }, | 
| + { ssl_signed_certificate_timestamp_xtn, | 
| + &ssl3_ClientHandleSignedCertTimestampXtn }, | 
| { -1, NULL } | 
| }; | 
| @@ -287,7 +295,9 @@ ssl3HelloExtensionSender clientHelloSendersTLS[SSL_MAX_EXTENSIONS] = { | 
| { ssl_use_srtp_xtn, &ssl3_SendUseSRTPXtn }, | 
| { ssl_channel_id_xtn, &ssl3_ClientSendChannelIDXtn }, | 
| { ssl_cert_status_xtn, &ssl3_ClientSendStatusRequestXtn }, | 
| - { ssl_signature_algorithms_xtn, &ssl3_ClientSendSigAlgsXtn } | 
| + { ssl_signature_algorithms_xtn, &ssl3_ClientSendSigAlgsXtn }, | 
| + { ssl_signed_certificate_timestamp_xtn, | 
| + &ssl3_ClientSendSignedCertTimestampXtn } | 
| /* any extra entries will appear as { 0, NULL } */ | 
| }; | 
| @@ -2364,3 +2374,65 @@ ssl3_AppendPaddingExtension(sslSocket *ss, unsigned int extensionLen, | 
| return extensionLen; | 
| } | 
| + | 
| +/* ssl3_ClientSendSignedCertTimestampXtn sends the signed_certificate_timestamp | 
| + * extension for TLS ClientHellos. */ | 
| +static PRInt32 | 
| +ssl3_ClientSendSignedCertTimestampXtn(sslSocket *ss, PRBool append, | 
| + PRUint32 maxBytes) | 
| +{ | 
| + PRInt32 extension_length = 2 /* extension_type */ + | 
| + 2 /* length(extension_data) */; | 
| + | 
| + /* Only send the extension if processing is enabled. */ | 
| + if (!ss->opt.enableSignedCertTimestamps) | 
| + return 0; | 
| + | 
| + if (append && maxBytes >= extension_length) { | 
| + SECStatus rv; | 
| + /* extension_type */ | 
| + rv = ssl3_AppendHandshakeNumber(ss, | 
| + ssl_signed_certificate_timestamp_xtn, | 
| + 2); | 
| + if (rv != SECSuccess) | 
| + goto loser; | 
| + /* zero length */ | 
| + rv = ssl3_AppendHandshakeNumber(ss, 0, 2); | 
| + if (rv != SECSuccess) | 
| + 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; | 
| +loser: | 
| + return -1; | 
| +} | 
| + | 
| +static SECStatus | 
| +ssl3_ClientHandleSignedCertTimestampXtn(sslSocket *ss, PRUint16 ex_type, | 
| + SECItem *data) | 
| +{ | 
| + /* We do not yet know whether we'll be resuming a session or creating | 
| + * a new one, so we keep a pointer to the data in the TLSExtensionData | 
| + * structure. This pointer is only valid in the scope of | 
| + * ssl3_HandleServerHello, and, if not resuming a session, the data is | 
| + * copied once a new session structure has been set up. | 
| + * All parsing is currently left to the application and we accept | 
| + * everything, including empty data. | 
| + */ | 
| + SECItem *scts = &ss->xtnData.signedCertTimestamps; | 
| + PORT_Assert(!scts->data && !scts->len); | 
| + | 
| + if (!data->len) { | 
| + /* Empty extension data: RFC 6962 mandates non-empty contents. */ | 
| 
 
wtc
2013/11/20 23:05:55
Ideally we should call PORT_SetError(). But I can'
 
 | 
| + return SECFailure; | 
| + } | 
| + *scts = *data; | 
| + /* Keep track of negotiated extensions. */ | 
| + ss->xtnData.negotiated[ss->xtnData.numNegotiated++] = ex_type; | 
| + return SECSuccess; | 
| +} |