| 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 04157701e9028e670098fa47469960ffc05513c9..068223ddd7451e4de7aee59cb7dbd73a98480f2e 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 }    */
 | 
|  };
 | 
|  
 | 
| @@ -2297,3 +2307,60 @@ ssl3_ClientSendSigAlgsXtn(sslSocket * ss, PRBool append, PRUint32 maxBytes)
 | 
|  loser:
 | 
|      return -1;
 | 
|  }
 | 
| +
 | 
| +/* 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);
 | 
| +    *scts = *data;
 | 
| +    /* Keep track of negotiated extensions. */
 | 
| +    ss->xtnData.negotiated[ss->xtnData.numNegotiated++] = ex_type;
 | 
| +    return SECSuccess;
 | 
| +}
 | 
| 
 |