| 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 |