OLD | NEW |
| (Empty) |
1 diff --git a/lib/ssl/ssl.h b/lib/ssl/ssl.h | |
2 index eb7f7ec..db09425 100644 | |
3 --- a/lib/ssl/ssl.h | |
4 +++ b/lib/ssl/ssl.h | |
5 @@ -203,6 +203,8 @@ SSL_IMPORT PRFileDesc *DTLS_ImportFD(PRFileDesc *model, PRFi
leDesc *fd); | |
6 */ | |
7 #define SSL_ENABLE_EXTENDED_MASTER_SECRET 30 | |
8 | |
9 +/* Request Signed Certificate Timestamps via TLS extension (client) */ | |
10 +#define SSL_ENABLE_SIGNED_CERT_TIMESTAMPS 31 | |
11 | |
12 #ifdef SSL_DEPRECATED_FUNCTION | |
13 /* Old deprecated function names */ | |
14 @@ -586,6 +588,23 @@ SSL_IMPORT CERTCertList *SSL_PeerCertificateChain(PRFileDes
c *fd); | |
15 */ | |
16 SSL_IMPORT const SECItemArray * SSL_PeerStapledOCSPResponses(PRFileDesc *fd); | |
17 | |
18 +/* SSL_PeerSignedCertTimestamps returns the signed_certificate_timestamp | |
19 + * extension data provided by the TLS server. The return value is a pointer | |
20 + * to an internal SECItem that contains the returned response (as a serialized | |
21 + * SignedCertificateTimestampList, see RFC 6962). The returned pointer is only | |
22 + * valid until the callback function that calls SSL_PeerSignedCertTimestamps | |
23 + * (e.g. the authenticate certificate hook, or the handshake callback) returns. | |
24 + * | |
25 + * If no Signed Certificate Timestamps were given by the server then the result | |
26 + * will be empty. If there was an error, then the result will be NULL. | |
27 + * | |
28 + * You must set the SSL_ENABLE_SIGNED_CERT_TIMESTAMPS option to indicate suppor
t | |
29 + * for Signed Certificate Timestamps to a server. | |
30 + * | |
31 + * libssl does not do any parsing or validation of the response itself. | |
32 + */ | |
33 +SSL_IMPORT const SECItem * SSL_PeerSignedCertTimestamps(PRFileDesc *fd); | |
34 + | |
35 /* SSL_SetStapledOCSPResponses stores an array of one or multiple OCSP response
s | |
36 * in the fd's data, which may be sent as part of a server side cert_status | |
37 * handshake message. Parameter |responses| is for the server certificate of | |
38 diff --git a/lib/ssl/ssl3con.c b/lib/ssl/ssl3con.c | |
39 index ba3d012..5c09f25 100644 | |
40 --- a/lib/ssl/ssl3con.c | |
41 +++ b/lib/ssl/ssl3con.c | |
42 @@ -6957,6 +6957,14 @@ ssl3_HandleServerHello(sslSocket *ss, SSL3Opaque *b, PRUi
nt32 length) | |
43 sid->u.ssl3.keys.extendedMasterSecretUsed = | |
44 ssl3_ExtensionNegotiated(ss, ssl_extended_master_secret_xtn); | |
45 | |
46 + /* Copy Signed Certificate Timestamps, if any. */ | |
47 + if (ss->xtnData.signedCertTimestamps.data) { | |
48 + rv = SECITEM_CopyItem(NULL, &sid->u.ssl3.signedCertTimestamps, | |
49 + &ss->xtnData.signedCertTimestamps); | |
50 + if (rv != SECSuccess) | |
51 + goto loser; | |
52 + } | |
53 + | |
54 ss->ssl3.hs.isResuming = PR_FALSE; | |
55 if (ss->ssl3.hs.kea_def->signKeyType != sign_null) { | |
56 /* All current cipher suites other than those with sign_null (i.e., | |
57 @@ -6971,6 +6979,10 @@ ssl3_HandleServerHello(sslSocket *ss, SSL3Opaque *b, PRUi
nt32 length) | |
58 } | |
59 | |
60 winner: | |
61 + /* Clean up the temporary pointer to the handshake buffer. */ | |
62 + ss->xtnData.signedCertTimestamps.data = NULL; | |
63 + ss->xtnData.signedCertTimestamps.len = 0; | |
64 + | |
65 /* If we will need a ChannelID key then we make the callback now. This | |
66 * allows the handshake to be restarted cleanly if the callback returns | |
67 * SECWouldBlock. */ | |
68 @@ -6996,6 +7008,9 @@ alert_loser: | |
69 (void)SSL3_SendAlert(ss, alert_fatal, desc); | |
70 | |
71 loser: | |
72 + /* Clean up the temporary pointer to the handshake buffer. */ | |
73 + ss->xtnData.signedCertTimestamps.data = NULL; | |
74 + ss->xtnData.signedCertTimestamps.len = 0; | |
75 errCode = ssl_MapLowLevelError(errCode); | |
76 return SECFailure; | |
77 } | |
78 diff --git a/lib/ssl/ssl3ext.c b/lib/ssl/ssl3ext.c | |
79 index 78825cb..9cfd541 100644 | |
80 --- a/lib/ssl/ssl3ext.c | |
81 +++ b/lib/ssl/ssl3ext.c | |
82 @@ -90,6 +90,12 @@ static PRInt32 ssl3_ClientSendSigAlgsXtn(sslSocket *ss, PRBoo
l append, | |
83 PRUint32 maxBytes); | |
84 static SECStatus ssl3_ServerHandleSigAlgsXtn(sslSocket *ss, PRUint16 ex_type, | |
85 SECItem *data); | |
86 +static PRInt32 ssl3_ClientSendSignedCertTimestampXtn(sslSocket *ss, | |
87 + PRBool append, | |
88 + PRUint32 maxBytes); | |
89 +static SECStatus ssl3_ClientHandleSignedCertTimestampXtn(sslSocket *ss, | |
90 + PRUint16 ex_type, | |
91 + SECItem *data); | |
92 | |
93 static PRInt32 ssl3_ClientSendDraftVersionXtn(sslSocket *ss, PRBool append, | |
94 PRUint32 maxBytes); | |
95 @@ -283,6 +289,8 @@ static const ssl3HelloExtensionHandler serverHelloHandlersTL
S[] = { | |
96 { ssl_channel_id_xtn, &ssl3_ClientHandleChannelIDXtn }, | |
97 { ssl_cert_status_xtn, &ssl3_ClientHandleStatusRequestXtn }, | |
98 { ssl_extended_master_secret_xtn, &ssl3_HandleExtendedMasterSecretXtn }, | |
99 + { ssl_signed_certificate_timestamp_xtn, | |
100 + &ssl3_ClientHandleSignedCertTimestampXtn }, | |
101 { -1, NULL } | |
102 }; | |
103 | |
104 @@ -311,6 +319,8 @@ ssl3HelloExtensionSender clientHelloSendersTLS[SSL_MAX_EXTEN
SIONS] = { | |
105 { ssl_use_srtp_xtn, &ssl3_ClientSendUseSRTPXtn }, | |
106 { ssl_channel_id_xtn, &ssl3_ClientSendChannelIDXtn }, | |
107 { ssl_cert_status_xtn, &ssl3_ClientSendStatusRequestXtn }, | |
108 + { ssl_signed_certificate_timestamp_xtn, | |
109 + &ssl3_ClientSendSignedCertTimestampXtn }, | |
110 { ssl_signature_algorithms_xtn, &ssl3_ClientSendSigAlgsXtn }, | |
111 { ssl_tls13_draft_version_xtn, &ssl3_ClientSendDraftVersionXtn }, | |
112 { ssl_extended_master_secret_xtn, &ssl3_SendExtendedMasterSecretXtn}, | |
113 @@ -2698,11 +2708,48 @@ ssl3_SendExtendedMasterSecretXtn(sslSocket * ss, PRBool
append, | |
114 } | |
115 | |
116 return extension_length; | |
117 - | |
118 loser: | |
119 return -1; | |
120 } | |
121 | |
122 +/* ssl3_ClientSendSignedCertTimestampXtn sends the signed_certificate_timestamp | |
123 + * extension for TLS ClientHellos. */ | |
124 +static PRInt32 | |
125 +ssl3_ClientSendSignedCertTimestampXtn(sslSocket *ss, PRBool append, | |
126 + PRUint32 maxBytes) | |
127 +{ | |
128 + PRInt32 extension_length = 2 /* extension_type */ + | |
129 + 2 /* length(extension_data) */; | |
130 + | |
131 + /* Only send the extension if processing is enabled. */ | |
132 + if (!ss->opt.enableSignedCertTimestamps) | |
133 + return 0; | |
134 + | |
135 + if (maxBytes < extension_length) { | |
136 + PORT_Assert(0); | |
137 + return 0; | |
138 + } | |
139 + | |
140 + if (append) { | |
141 + SECStatus rv; | |
142 + /* extension_type */ | |
143 + rv = ssl3_AppendHandshakeNumber(ss, | |
144 + ssl_signed_certificate_timestamp_xtn, | |
145 + 2); | |
146 + if (rv != SECSuccess) | |
147 + goto loser; | |
148 + /* zero length */ | |
149 + rv = ssl3_AppendHandshakeNumber(ss, 0, 2); | |
150 + if (rv != SECSuccess) | |
151 + goto loser; | |
152 + ss->xtnData.advertised[ss->xtnData.numAdvertised++] = | |
153 + ssl_signed_certificate_timestamp_xtn; | |
154 + } | |
155 + | |
156 + return extension_length; | |
157 +loser: | |
158 + return -1; | |
159 +} | |
160 | |
161 static SECStatus | |
162 ssl3_HandleExtendedMasterSecretXtn(sslSocket * ss, PRUint16 ex_type, | |
163 @@ -2743,3 +2790,28 @@ ssl3_HandleExtendedMasterSecretXtn(sslSocket * ss, PRUint
16 ex_type, | |
164 } | |
165 return SECSuccess; | |
166 } | |
167 + | |
168 +static SECStatus | |
169 +ssl3_ClientHandleSignedCertTimestampXtn(sslSocket *ss, PRUint16 ex_type, | |
170 + SECItem *data) | |
171 +{ | |
172 + /* We do not yet know whether we'll be resuming a session or creating | |
173 + * a new one, so we keep a pointer to the data in the TLSExtensionData | |
174 + * structure. This pointer is only valid in the scope of | |
175 + * ssl3_HandleServerHello, and, if not resuming a session, the data is | |
176 + * copied once a new session structure has been set up. | |
177 + * All parsing is currently left to the application and we accept | |
178 + * everything, including empty data. | |
179 + */ | |
180 + SECItem *scts = &ss->xtnData.signedCertTimestamps; | |
181 + PORT_Assert(!scts->data && !scts->len); | |
182 + | |
183 + if (!data->len) { | |
184 + /* Empty extension data: RFC 6962 mandates non-empty contents. */ | |
185 + return SECFailure; | |
186 + } | |
187 + *scts = *data; | |
188 + /* Keep track of negotiated extensions. */ | |
189 + ss->xtnData.negotiated[ss->xtnData.numNegotiated++] = ex_type; | |
190 + return SECSuccess; | |
191 +} | |
192 diff --git a/lib/ssl/sslimpl.h b/lib/ssl/sslimpl.h | |
193 index d53c446..080debe 100644 | |
194 --- a/lib/ssl/sslimpl.h | |
195 +++ b/lib/ssl/sslimpl.h | |
196 @@ -349,6 +349,7 @@ typedef struct sslOptionsStr { | |
197 unsigned int enableFallbackSCSV : 1; /* 29 */ | |
198 unsigned int enableServerDhe : 1; /* 30 */ | |
199 unsigned int enableExtendedMS : 1; /* 31 */ | |
200 + unsigned int enableSignedCertTimestamps : 1; /* 32 */ | |
201 } sslOptions; | |
202 | |
203 typedef enum { sslHandshakingUndetermined = 0, | |
204 @@ -732,6 +733,11 @@ struct sslSessionIDStr { | |
205 * resumption handshake to the original handshake. */ | |
206 SECItem originalHandshakeHash; | |
207 | |
208 + /* Signed certificate timestamps received in a TLS extension. | |
209 + ** (used only in client). | |
210 + */ | |
211 + SECItem signedCertTimestamps; | |
212 + | |
213 /* This lock is lazily initialized by CacheSID when a sid is first | |
214 * cached. Before then, there is no need to lock anything because | |
215 * the sid isn't being shared by anything. | |
216 @@ -846,6 +852,18 @@ struct TLSExtensionDataStr { | |
217 * is beyond ssl3_HandleClientHello function. */ | |
218 SECItem *sniNameArr; | |
219 PRUint32 sniNameArrSize; | |
220 + | |
221 + /* Signed Certificate Timestamps extracted from the TLS extension. | |
222 + * (client only). | |
223 + * This container holds a temporary pointer to the extension data, | |
224 + * until a session structure (the sec.ci.sid of an sslSocket) is setup | |
225 + * that can hold a permanent copy of the data | |
226 + * (in sec.ci.sid.u.ssl3.signedCertTimestamps). | |
227 + * The data pointed to by this structure is neither explicitly allocated | |
228 + * nor copied: the pointer points to the handshake message buffer and is | |
229 + * only valid in the scope of ssl3_HandleServerHello. | |
230 + */ | |
231 + SECItem signedCertTimestamps; | |
232 }; | |
233 | |
234 typedef SECStatus (*sslRestartTarget)(sslSocket *); | |
235 diff --git a/lib/ssl/sslnonce.c b/lib/ssl/sslnonce.c | |
236 index c45849d..cefdda6 100644 | |
237 --- a/lib/ssl/sslnonce.c | |
238 +++ b/lib/ssl/sslnonce.c | |
239 @@ -131,6 +131,9 @@ ssl_DestroySID(sslSessionID *sid) | |
240 if (sid->u.ssl3.originalHandshakeHash.data) { | |
241 SECITEM_FreeItem(&sid->u.ssl3.originalHandshakeHash, PR_FALSE); | |
242 } | |
243 + if (sid->u.ssl3.signedCertTimestamps.data) { | |
244 + SECITEM_FreeItem(&sid->u.ssl3.signedCertTimestamps, PR_FALSE); | |
245 + } | |
246 | |
247 if (sid->u.ssl3.lock) { | |
248 PR_DestroyRWLock(sid->u.ssl3.lock); | |
249 diff --git a/lib/ssl/sslsock.c b/lib/ssl/sslsock.c | |
250 index 6d700a7..28e3543 100644 | |
251 --- a/lib/ssl/sslsock.c | |
252 +++ b/lib/ssl/sslsock.c | |
253 @@ -92,7 +92,8 @@ static sslOptions ssl_defaults = { | |
254 PR_TRUE, /* reuseServerECDHEKey */ | |
255 PR_FALSE, /* enableFallbackSCSV */ | |
256 PR_TRUE, /* enableServerDhe */ | |
257 - PR_FALSE /* enableExtendedMS */ | |
258 + PR_FALSE, /* enableExtendedMS */ | |
259 + PR_FALSE, /* enableSignedCertTimestamps */ | |
260 }; | |
261 | |
262 /* | |
263 @@ -843,6 +844,10 @@ SSL_OptionSet(PRFileDesc *fd, PRInt32 which, PRBool on) | |
264 ss->opt.enableExtendedMS = on; | |
265 break; | |
266 | |
267 + case SSL_ENABLE_SIGNED_CERT_TIMESTAMPS: | |
268 + ss->opt.enableSignedCertTimestamps = on; | |
269 + break; | |
270 + | |
271 default: | |
272 PORT_SetError(SEC_ERROR_INVALID_ARGS); | |
273 rv = SECFailure; | |
274 @@ -921,6 +926,9 @@ SSL_OptionGet(PRFileDesc *fd, PRInt32 which, PRBool *pOn) | |
275 case SSL_ENABLE_SERVER_DHE: on = ss->opt.enableServerDhe; break; | |
276 case SSL_ENABLE_EXTENDED_MASTER_SECRET: | |
277 on = ss->opt.enableExtendedMS; break; | |
278 + case SSL_ENABLE_SIGNED_CERT_TIMESTAMPS: | |
279 + on = ss->opt.enableSignedCertTimestamps; | |
280 + break; | |
281 | |
282 default: | |
283 PORT_SetError(SEC_ERROR_INVALID_ARGS); | |
284 @@ -996,6 +1004,9 @@ SSL_OptionGetDefault(PRInt32 which, PRBool *pOn) | |
285 case SSL_ENABLE_EXTENDED_MASTER_SECRET: | |
286 on = ssl_defaults.enableExtendedMS; | |
287 break; | |
288 + case SSL_ENABLE_SIGNED_CERT_TIMESTAMPS: | |
289 + on = ssl_defaults.enableSignedCertTimestamps; | |
290 + break; | |
291 | |
292 default: | |
293 PORT_SetError(SEC_ERROR_INVALID_ARGS); | |
294 @@ -1187,6 +1198,10 @@ SSL_OptionSetDefault(PRInt32 which, PRBool on) | |
295 ssl_defaults.enableExtendedMS = on; | |
296 break; | |
297 | |
298 + case SSL_ENABLE_SIGNED_CERT_TIMESTAMPS: | |
299 + ssl_defaults.enableSignedCertTimestamps = on; | |
300 + break; | |
301 + | |
302 default: | |
303 PORT_SetError(SEC_ERROR_INVALID_ARGS); | |
304 return SECFailure; | |
305 @@ -2218,6 +2233,29 @@ SSL_PeerStapledOCSPResponses(PRFileDesc *fd) | |
306 return &ss->sec.ci.sid->peerCertStatus; | |
307 } | |
308 | |
309 +const SECItem * | |
310 +SSL_PeerSignedCertTimestamps(PRFileDesc *fd) | |
311 +{ | |
312 + sslSocket *ss = ssl_FindSocket(fd); | |
313 + | |
314 + if (!ss) { | |
315 + SSL_DBG(("%d: SSL[%d]: bad socket in SSL_PeerSignedCertTimestamps", | |
316 + SSL_GETPID(), fd)); | |
317 + return NULL; | |
318 + } | |
319 + | |
320 + if (!ss->sec.ci.sid) { | |
321 + PORT_SetError(SEC_ERROR_NOT_INITIALIZED); | |
322 + return NULL; | |
323 + } | |
324 + | |
325 + if (ss->sec.ci.sid->version < SSL_LIBRARY_VERSION_3_0) { | |
326 + PORT_SetError(SSL_ERROR_FEATURE_NOT_SUPPORTED_FOR_SSL2); | |
327 + return NULL; | |
328 + } | |
329 + return &ss->sec.ci.sid->u.ssl3.signedCertTimestamps; | |
330 +} | |
331 + | |
332 SECStatus | |
333 SSL_HandshakeResumedSession(PRFileDesc *fd, PRBool *handshake_resumed) { | |
334 sslSocket *ss = ssl_FindSocket(fd); | |
335 diff --git a/lib/ssl/sslt.h b/lib/ssl/sslt.h | |
336 index a2eff62..36e34df 100644 | |
337 --- a/lib/ssl/sslt.h | |
338 +++ b/lib/ssl/sslt.h | |
339 @@ -248,6 +248,7 @@ typedef enum { | |
340 ssl_signature_algorithms_xtn = 13, | |
341 ssl_use_srtp_xtn = 14, | |
342 ssl_app_layer_protocol_xtn = 16, | |
343 + ssl_signed_certificate_timestamp_xtn = 18, /* RFC 6962 */ | |
344 ssl_padding_xtn = 21, | |
345 ssl_extended_master_secret_xtn = 23, | |
346 ssl_session_ticket_xtn = 35, | |
347 @@ -257,7 +258,7 @@ typedef enum { | |
348 ssl_tls13_draft_version_xtn = 0xff02 /* experimental number */ | |
349 } SSLExtensionType; | |
350 | |
351 -#define SSL_MAX_EXTENSIONS 13 /* doesn't include ssl_padding_xtn. *
/ | |
352 +#define SSL_MAX_EXTENSIONS 14 /* doesn't include ssl_padding_xtn. *
/ | |
353 | |
354 typedef enum { | |
355 ssl_dhe_group_none = 0, | |
OLD | NEW |