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; |
+} |