1 diff -pu a/nss/lib/ssl/ssl3con.c b/nss/lib/ssl/ssl3con.c
2 --- a/nss/lib/ssl/ssl3con.c 2014-01-03 19:03:55.547150312 -0800
3 +++ b/nss/lib/ssl/ssl3con.c 2014-01-03 19:04:31.257733748 -0800
4 @@ -6681,10 +6681,22 @@ ssl3_HandleServerHello(sslSocket *ss, SS
5 sid->u.ssl3.sessionIDLength = sidBytes.len;
6 PORT_Memcpy(sid->u.ssl3.sessionID, sidBytes.data, sidBytes.len);
8 + /* Copy Signed Certificate Timestamps, if any. */
9 + if (ss->xtnData.signedCertTimestamps.data) {
10 + rv = SECITEM_CopyItem(NULL, &sid->u.ssl3.signedCertTimestamps,
11 + &ss->xtnData.signedCertTimestamps);
12 + if (rv != SECSuccess)
16 ss->ssl3.hs.isResuming = PR_FALSE;
17 ss->ssl3.hs.ws = wait_server_cert;
20 + /* Clean up the temporary pointer to the handshake buffer. */
21 + ss->xtnData.signedCertTimestamps.data = NULL;
22 + ss->xtnData.signedCertTimestamps.len = 0;
24 /* If we will need a ChannelID key then we make the callback now. This
25 * allows the handshake to be restarted cleanly if the callback returns
27 @@ -6710,6 +6722,9 @@ alert_loser:
28 (void)SSL3_SendAlert(ss, alert_fatal, desc);
31 + /* Clean up the temporary pointer to the handshake buffer. */
32 + ss->xtnData.signedCertTimestamps.data = NULL;
33 + ss->xtnData.signedCertTimestamps.len = 0;
34 errCode = ssl_MapLowLevelError(errCode);
37 diff -pu a/nss/lib/ssl/ssl3ext.c b/nss/lib/ssl/ssl3ext.c
38 --- a/nss/lib/ssl/ssl3ext.c 2014-01-03 19:04:20.207553209 -0800
39 +++ b/nss/lib/ssl/ssl3ext.c 2014-01-03 19:04:31.257733748 -0800
40 @@ -81,6 +81,12 @@ static PRInt32 ssl3_ClientSendSigAlgsXtn
42 static SECStatus ssl3_ServerHandleSigAlgsXtn(sslSocket *ss, PRUint16 ex_type,
44 +static PRInt32 ssl3_ClientSendSignedCertTimestampXtn(sslSocket *ss,
47 +static SECStatus ssl3_ClientHandleSignedCertTimestampXtn(sslSocket *ss,
52 * Write bytes. Using this function means the SECItem structure
53 @@ -259,6 +265,8 @@ static const ssl3HelloExtensionHandler s
54 { ssl_use_srtp_xtn, &ssl3_HandleUseSRTPXtn },
55 { ssl_channel_id_xtn, &ssl3_ClientHandleChannelIDXtn },
56 { ssl_cert_status_xtn, &ssl3_ClientHandleStatusRequestXtn },
57 + { ssl_signed_certificate_timestamp_xtn,
58 + &ssl3_ClientHandleSignedCertTimestampXtn },
62 @@ -287,7 +295,9 @@ ssl3HelloExtensionSender clientHelloSend
63 { ssl_use_srtp_xtn, &ssl3_SendUseSRTPXtn },
64 { ssl_channel_id_xtn, &ssl3_ClientSendChannelIDXtn },
65 { ssl_cert_status_xtn, &ssl3_ClientSendStatusRequestXtn },
66 - { ssl_signature_algorithms_xtn, &ssl3_ClientSendSigAlgsXtn }
67 + { ssl_signature_algorithms_xtn, &ssl3_ClientSendSigAlgsXtn },
68 + { ssl_signed_certificate_timestamp_xtn,
69 + &ssl3_ClientSendSignedCertTimestampXtn }
70 /* any extra entries will appear as { 0, NULL } */
73 @@ -2372,3 +2382,65 @@ ssl3_AppendPaddingExtension(sslSocket *s
78 +/* ssl3_ClientSendSignedCertTimestampXtn sends the signed_certificate_timestamp
79 + * extension for TLS ClientHellos. */
81 +ssl3_ClientSendSignedCertTimestampXtn(sslSocket *ss, PRBool append,
84 + PRInt32 extension_length = 2 /* extension_type */ +
85 + 2 /* length(extension_data) */;
87 + /* Only send the extension if processing is enabled. */
88 + if (!ss->opt.enableSignedCertTimestamps)
91 + if (append && maxBytes >= extension_length) {
93 + /* extension_type */
94 + rv = ssl3_AppendHandshakeNumber(ss,
95 + ssl_signed_certificate_timestamp_xtn,
97 + if (rv != SECSuccess)
100 + rv = ssl3_AppendHandshakeNumber(ss, 0, 2);
101 + if (rv != SECSuccess)
103 + ss->xtnData.advertised[ss->xtnData.numAdvertised++] =
104 + ssl_signed_certificate_timestamp_xtn;
105 + } else if (maxBytes < extension_length) {
110 + return extension_length;
116 +ssl3_ClientHandleSignedCertTimestampXtn(sslSocket *ss, PRUint16 ex_type,
119 + /* We do not yet know whether we'll be resuming a session or creating
120 + * a new one, so we keep a pointer to the data in the TLSExtensionData
121 + * structure. This pointer is only valid in the scope of
122 + * ssl3_HandleServerHello, and, if not resuming a session, the data is
123 + * copied once a new session structure has been set up.
124 + * All parsing is currently left to the application and we accept
125 + * everything, including empty data.
127 + SECItem *scts = &ss->xtnData.signedCertTimestamps;
128 + PORT_Assert(!scts->data && !scts->len);
131 + /* Empty extension data: RFC 6962 mandates non-empty contents. */
135 + /* Keep track of negotiated extensions. */
136 + ss->xtnData.negotiated[ss->xtnData.numNegotiated++] = ex_type;
139 diff -pu a/nss/lib/ssl/ssl.h b/nss/lib/ssl/ssl.h
140 --- a/nss/lib/ssl/ssl.h 2014-01-03 18:58:03.661401846 -0800
141 +++ b/nss/lib/ssl/ssl.h 2014-01-03 19:04:31.257733748 -0800
142 @@ -161,6 +161,8 @@ SSL_IMPORT PRFileDesc *DTLS_ImportFD(PRF
144 #define SSL_CBC_RANDOM_IV 23
145 #define SSL_ENABLE_OCSP_STAPLING 24 /* Request OCSP stapling (client) */
146 +/* Request Signed Certificate Timestamps via TLS extension (client) */
147 +#define SSL_ENABLE_SIGNED_CERT_TIMESTAMPS 25
149 #ifdef SSL_DEPRECATED_FUNCTION
150 /* Old deprecated function names */
151 @@ -464,6 +466,23 @@ SSL_IMPORT CERTCertList *SSL_PeerCertifi
153 SSL_IMPORT const SECItemArray * SSL_PeerStapledOCSPResponses(PRFileDesc *fd);
155 +/* SSL_PeerSignedCertTimestamps returns the signed_certificate_timestamp
156 + * extension data provided by the TLS server. The return value is a pointer
157 + * to an internal SECItem that contains the returned response (as a serialized
158 + * SignedCertificateTimestampList, see RFC 6962). The returned pointer is only
159 + * valid until the callback function that calls SSL_PeerSignedCertTimestamps
160 + * (e.g. the authenticate certificate hook, or the handshake callback) returns.
162 + * If no Signed Certificate Timestamps were given by the server then the result
163 + * will be empty. If there was an error, then the result will be NULL.
165 + * You must set the SSL_ENABLE_SIGNED_CERT_TIMESTAMPS option to indicate support
166 + * for Signed Certificate Timestamps to a server.
168 + * libssl does not do any parsing or validation of the response itself.
170 +SSL_IMPORT const SECItem * SSL_PeerSignedCertTimestamps(PRFileDesc *fd);
172 /* SSL_SetStapledOCSPResponses stores an array of one or multiple OCSP responses
173 * in the fd's data, which may be sent as part of a server side cert_status
174 * handshake message. Parameter |responses| is for the server certificate of
175 diff -pu a/nss/lib/ssl/sslimpl.h b/nss/lib/ssl/sslimpl.h
176 --- a/nss/lib/ssl/sslimpl.h 2014-01-03 19:03:55.557150476 -0800
177 +++ b/nss/lib/ssl/sslimpl.h 2014-01-03 19:04:31.257733748 -0800
178 @@ -312,29 +312,30 @@ typedef struct sslOptionsStr {
179 * list of supported protocols. */
180 SECItem nextProtoNego;
182 - unsigned int useSecurity : 1; /* 1 */
183 - unsigned int useSocks : 1; /* 2 */
184 - unsigned int requestCertificate : 1; /* 3 */
185 - unsigned int requireCertificate : 2; /* 4-5 */
186 - unsigned int handshakeAsClient : 1; /* 6 */
187 - unsigned int handshakeAsServer : 1; /* 7 */
188 - unsigned int enableSSL2 : 1; /* 8 */
189 - unsigned int unusedBit9 : 1; /* 9 */
190 - unsigned int unusedBit10 : 1; /* 10 */
191 - unsigned int noCache : 1; /* 11 */
192 - unsigned int fdx : 1; /* 12 */
193 - unsigned int v2CompatibleHello : 1; /* 13 */
194 - unsigned int detectRollBack : 1; /* 14 */
195 - unsigned int noStepDown : 1; /* 15 */
196 - unsigned int bypassPKCS11 : 1; /* 16 */
197 - unsigned int noLocks : 1; /* 17 */
198 - unsigned int enableSessionTickets : 1; /* 18 */
199 - unsigned int enableDeflate : 1; /* 19 */
200 - unsigned int enableRenegotiation : 2; /* 20-21 */
201 - unsigned int requireSafeNegotiation : 1; /* 22 */
202 - unsigned int enableFalseStart : 1; /* 23 */
203 - unsigned int cbcRandomIV : 1; /* 24 */
204 - unsigned int enableOCSPStapling : 1; /* 25 */
205 + unsigned int useSecurity : 1; /* 1 */
206 + unsigned int useSocks : 1; /* 2 */
207 + unsigned int requestCertificate : 1; /* 3 */
208 + unsigned int requireCertificate : 2; /* 4-5 */
209 + unsigned int handshakeAsClient : 1; /* 6 */
210 + unsigned int handshakeAsServer : 1; /* 7 */
211 + unsigned int enableSSL2 : 1; /* 8 */
212 + unsigned int unusedBit9 : 1; /* 9 */
213 + unsigned int unusedBit10 : 1; /* 10 */
214 + unsigned int noCache : 1; /* 11 */
215 + unsigned int fdx : 1; /* 12 */
216 + unsigned int v2CompatibleHello : 1; /* 13 */
217 + unsigned int detectRollBack : 1; /* 14 */
218 + unsigned int noStepDown : 1; /* 15 */
219 + unsigned int bypassPKCS11 : 1; /* 16 */
220 + unsigned int noLocks : 1; /* 17 */
221 + unsigned int enableSessionTickets : 1; /* 18 */
222 + unsigned int enableDeflate : 1; /* 19 */
223 + unsigned int enableRenegotiation : 2; /* 20-21 */
224 + unsigned int requireSafeNegotiation : 1; /* 22 */
225 + unsigned int enableFalseStart : 1; /* 23 */
226 + unsigned int cbcRandomIV : 1; /* 24 */
227 + unsigned int enableOCSPStapling : 1; /* 25 */
228 + unsigned int enableSignedCertTimestamps : 1; /* 26 */
231 typedef enum { sslHandshakingUndetermined = 0,
232 @@ -717,6 +718,11 @@ struct sslSessionIDStr {
233 * resumption handshake to the original handshake. */
234 SECItem originalHandshakeHash;
236 + /* Signed certificate timestamps received in a TLS extension.
237 + ** (used only in client).
239 + SECItem signedCertTimestamps;
241 /* This lock is lazily initialized by CacheSID when a sid is first
242 * cached. Before then, there is no need to lock anything because
243 * the sid isn't being shared by anything.
244 @@ -825,6 +831,18 @@ struct TLSExtensionDataStr {
245 * is beyond ssl3_HandleClientHello function. */
247 PRUint32 sniNameArrSize;
249 + /* Signed Certificate Timestamps extracted from the TLS extension.
251 + * This container holds a temporary pointer to the extension data,
252 + * until a session structure (the sec.ci.sid of an sslSocket) is setup
253 + * that can hold a permanent copy of the data
254 + * (in sec.ci.sid.u.ssl3.signedCertTimestamps).
255 + * The data pointed to by this structure is neither explicitly allocated
256 + * nor copied: the pointer points to the handshake message buffer and is
257 + * only valid in the scope of ssl3_HandleServerHello.
259 + SECItem signedCertTimestamps;
262 typedef SECStatus (*sslRestartTarget)(sslSocket *);
263 diff -pu a/nss/lib/ssl/sslnonce.c b/nss/lib/ssl/sslnonce.c
264 --- a/nss/lib/ssl/sslnonce.c 2014-01-03 19:03:25.356657071 -0800
265 +++ b/nss/lib/ssl/sslnonce.c 2014-01-03 19:05:48.568996889 -0800
266 @@ -133,6 +133,9 @@ ssl_DestroySID(sslSessionID *sid)
267 if (sid->u.ssl3.originalHandshakeHash.data) {
268 SECITEM_FreeItem(&sid->u.ssl3.originalHandshakeHash, PR_FALSE);
270 + if (sid->u.ssl3.signedCertTimestamps.data) {
271 + SECITEM_FreeItem(&sid->u.ssl3.signedCertTimestamps, PR_FALSE);
274 if (sid->u.ssl3.lock) {
275 PR_DestroyRWLock(sid->u.ssl3.lock);
276 diff -pu a/nss/lib/ssl/sslsock.c b/nss/lib/ssl/sslsock.c
277 --- a/nss/lib/ssl/sslsock.c 2014-01-03 18:57:38.240986619 -0800
278 +++ b/nss/lib/ssl/sslsock.c 2014-01-03 19:06:53.560058775 -0800
279 @@ -85,7 +85,8 @@ static sslOptions ssl_defaults = {
280 PR_FALSE, /* requireSafeNegotiation */
281 PR_FALSE, /* enableFalseStart */
282 PR_TRUE, /* cbcRandomIV */
283 - PR_FALSE /* enableOCSPStapling */
284 + PR_FALSE, /* enableOCSPStapling */
285 + PR_FALSE /* enableSignedCertTimestamps */
289 @@ -777,6 +778,10 @@ SSL_OptionSet(PRFileDesc *fd, PRInt32 wh
290 ss->opt.enableOCSPStapling = on;
293 + case SSL_ENABLE_SIGNED_CERT_TIMESTAMPS:
294 + ss->opt.enableSignedCertTimestamps = on;
298 PORT_SetError(SEC_ERROR_INVALID_ARGS);
300 @@ -847,6 +852,9 @@ SSL_OptionGet(PRFileDesc *fd, PRInt32 wh
301 case SSL_ENABLE_FALSE_START: on = ss->opt.enableFalseStart; break;
302 case SSL_CBC_RANDOM_IV: on = ss->opt.cbcRandomIV; break;
303 case SSL_ENABLE_OCSP_STAPLING: on = ss->opt.enableOCSPStapling; break;
304 + case SSL_ENABLE_SIGNED_CERT_TIMESTAMPS:
305 + on = ss->opt.enableSignedCertTimestamps;
309 PORT_SetError(SEC_ERROR_INVALID_ARGS);
310 @@ -908,6 +916,9 @@ SSL_OptionGetDefault(PRInt32 which, PRBo
311 case SSL_ENABLE_OCSP_STAPLING:
312 on = ssl_defaults.enableOCSPStapling;
314 + case SSL_ENABLE_SIGNED_CERT_TIMESTAMPS:
315 + on = ssl_defaults.enableSignedCertTimestamps;
319 PORT_SetError(SEC_ERROR_INVALID_ARGS);
320 @@ -1075,6 +1086,10 @@ SSL_OptionSetDefault(PRInt32 which, PRBo
321 ssl_defaults.enableOCSPStapling = on;
324 + case SSL_ENABLE_SIGNED_CERT_TIMESTAMPS:
325 + ssl_defaults.enableSignedCertTimestamps = on;
329 PORT_SetError(SEC_ERROR_INVALID_ARGS);
331 @@ -1899,6 +1914,29 @@ SSL_PeerStapledOCSPResponses(PRFileDesc
332 return &ss->sec.ci.sid->peerCertStatus;
336 +SSL_PeerSignedCertTimestamps(PRFileDesc *fd)
338 + sslSocket *ss = ssl_FindSocket(fd);
341 + SSL_DBG(("%d: SSL[%d]: bad socket in SSL_PeerSignedCertTimestamps",
342 + SSL_GETPID(), fd));
346 + if (!ss->sec.ci.sid) {
347 + PORT_SetError(SEC_ERROR_NOT_INITIALIZED);
351 + if (ss->sec.ci.sid->version < SSL_LIBRARY_VERSION_3_0) {
352 + PORT_SetError(SSL_ERROR_FEATURE_NOT_SUPPORTED_FOR_SSL2);
355 + return &ss->sec.ci.sid->u.ssl3.signedCertTimestamps;
359 SSL_HandshakeResumedSession(PRFileDesc *fd, PRBool *handshake_resumed) {
360 sslSocket *ss = ssl_FindSocket(fd);
361 diff -pu a/nss/lib/ssl/sslt.h b/nss/lib/ssl/sslt.h
362 --- a/nss/lib/ssl/sslt.h 2014-01-03 19:03:55.557150476 -0800
363 +++ b/nss/lib/ssl/sslt.h 2014-01-03 19:04:31.257733748 -0800
364 @@ -202,6 +202,7 @@ typedef enum {
365 ssl_signature_algorithms_xtn = 13,
366 ssl_use_srtp_xtn = 14,
367 ssl_app_layer_protocol_xtn = 16,
368 + ssl_signed_certificate_timestamp_xtn = 18, /* RFC 6962 */
369 ssl_session_ticket_xtn = 35,
370 ssl_next_proto_nego_xtn = 13172,
371 ssl_channel_id_xtn = 30032,
372 @@ -209,6 +210,6 @@ typedef enum {
373 ssl_renegotiation_info_xtn = 0xff01 /* experimental number */
376 -#define SSL_MAX_EXTENSIONS 11 /* doesn't include ssl_padding_xtn. */
377 +#define SSL_MAX_EXTENSIONS 12 /* doesn't include ssl_padding_xtn. */
379 #endif /* __sslt_h_ */