OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "net/cert/ct_objects_extractor.h" | 5 #include "net/cert/ct_objects_extractor.h" |
6 | 6 |
7 #include <cert.h> | 7 #include <cert.h> |
8 #include <secasn1.h> | 8 #include <secasn1.h> |
9 #include <secitem.h> | 9 #include <secitem.h> |
10 #include <secoid.h> | 10 #include <secoid.h> |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
69 "X.509v3 Certificate Transparency Embedded Signed Certificate Timestamp " | 69 "X.509v3 Certificate Transparency Embedded Signed Certificate Timestamp " |
70 "List"; | 70 "List"; |
71 | 71 |
72 // The wire form of the OID 1.3.6.1.4.1.11129.2.4.5 - OCSP SingleExtension for | 72 // The wire form of the OID 1.3.6.1.4.1.11129.2.4.5 - OCSP SingleExtension for |
73 // X.509v3 Certificate Transparency Signed Certificate Timestamp List, see | 73 // X.509v3 Certificate Transparency Signed Certificate Timestamp List, see |
74 // Section 3.3 of RFC6962. | 74 // Section 3.3 of RFC6962. |
75 const unsigned char kOCSPExtensionOid[] = {0x2B, 0x06, 0x01, 0x04, 0x01, | 75 const unsigned char kOCSPExtensionOid[] = {0x2B, 0x06, 0x01, 0x04, 0x01, |
76 0xD6, 0x79, 0x02, 0x04, 0x05}; | 76 0xD6, 0x79, 0x02, 0x04, 0x05}; |
77 | 77 |
78 const SECItem kOCSPExtensionOidItem = { | 78 const SECItem kOCSPExtensionOidItem = { |
79 siBuffer, const_cast<unsigned char*>(kOCSPExtensionOid), | 79 siBuffer, const_cast<unsigned char*>(kOCSPExtensionOid), |
80 sizeof(kOCSPExtensionOid) | 80 sizeof(kOCSPExtensionOid)}; |
81 }; | |
82 | 81 |
83 // id-ad-ocsp: 1.3.6.1.5.5.7.48.1.1 | 82 // id-ad-ocsp: 1.3.6.1.5.5.7.48.1.1 |
84 const unsigned char kBasicOCSPResponseOid[] = {0x2B, 0x06, 0x01, 0x05, 0x05, | 83 const unsigned char kBasicOCSPResponseOid[] = {0x2B, 0x06, 0x01, 0x05, 0x05, |
85 0x07, 0x30, 0x01, 0x01}; | 84 0x07, 0x30, 0x01, 0x01}; |
86 | 85 |
87 const SECItem kBasicOCSPResponseOidItem = { | 86 const SECItem kBasicOCSPResponseOidItem = { |
88 siBuffer, const_cast<unsigned char*>(kBasicOCSPResponseOid), | 87 siBuffer, const_cast<unsigned char*>(kBasicOCSPResponseOid), |
89 sizeof(kBasicOCSPResponseOid) | 88 sizeof(kBasicOCSPResponseOid)}; |
90 }; | |
91 | |
92 | 89 |
93 // Initializes the necessary NSS internals for use with Certificate | 90 // Initializes the necessary NSS internals for use with Certificate |
94 // Transparency. | 91 // Transparency. |
95 class CTInitSingleton { | 92 class CTInitSingleton { |
96 public: | 93 public: |
97 SECOidTag embedded_oid() const { return embedded_oid_; } | 94 SECOidTag embedded_oid() const { return embedded_oid_; } |
98 | 95 |
99 private: | 96 private: |
100 friend struct base::DefaultLazyInstanceTraits<CTInitSingleton>; | 97 friend struct base::DefaultLazyInstanceTraits<CTInitSingleton>; |
101 | 98 |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
144 std::string* extension_data) { | 141 std::string* extension_data) { |
145 SECItem extension; | 142 SECItem extension; |
146 SECStatus rv = CERT_FindCertExtension(cert, oid, &extension); | 143 SECStatus rv = CERT_FindCertExtension(cert, oid, &extension); |
147 if (rv != SECSuccess) | 144 if (rv != SECSuccess) |
148 return false; | 145 return false; |
149 | 146 |
150 base::StringPiece raw_data(reinterpret_cast<char*>(extension.data), | 147 base::StringPiece raw_data(reinterpret_cast<char*>(extension.data), |
151 extension.len); | 148 extension.len); |
152 base::StringPiece parsed_data; | 149 base::StringPiece parsed_data; |
153 if (!asn1::GetElement(&raw_data, asn1::kOCTETSTRING, &parsed_data) || | 150 if (!asn1::GetElement(&raw_data, asn1::kOCTETSTRING, &parsed_data) || |
154 raw_data.size() > 0) { // Decoding failure or raw data left | 151 raw_data.size() > 0) { // Decoding failure or raw data left |
155 rv = SECFailure; | 152 rv = SECFailure; |
156 } else { | 153 } else { |
157 parsed_data.CopyToString(extension_data); | 154 parsed_data.CopyToString(extension_data); |
158 } | 155 } |
159 | 156 |
160 SECITEM_FreeItem(&extension, PR_FALSE); | 157 SECITEM_FreeItem(&extension, PR_FALSE); |
161 return rv == SECSuccess; | 158 return rv == SECSuccess; |
162 } | 159 } |
163 | 160 |
164 // NSS offers CERT_FindCertExtension for certificates, but that only accepts | 161 // NSS offers CERT_FindCertExtension for certificates, but that only accepts |
(...skipping 19 matching lines...) Expand all Loading... |
184 break; | 181 break; |
185 } | 182 } |
186 } | 183 } |
187 | 184 |
188 if (!match) | 185 if (!match) |
189 return false; | 186 return false; |
190 | 187 |
191 SECItem contents; | 188 SECItem contents; |
192 // SEC_QuickDERDecodeItem sets |contents| to point to |match|, so it is not | 189 // SEC_QuickDERDecodeItem sets |contents| to point to |match|, so it is not |
193 // necessary to free the contents of |contents|. | 190 // necessary to free the contents of |contents|. |
194 SECStatus rv = SEC_QuickDERDecodeItem(arena, &contents, | 191 SECStatus rv = SEC_QuickDERDecodeItem( |
195 SEC_ASN1_GET(SEC_OctetStringTemplate), | 192 arena, &contents, SEC_ASN1_GET(SEC_OctetStringTemplate), &match->value); |
196 &match->value); | |
197 if (rv != SECSuccess) | 193 if (rv != SECSuccess) |
198 return false; | 194 return false; |
199 | 195 |
200 base::StringPiece parsed_data(reinterpret_cast<char*>(contents.data), | 196 base::StringPiece parsed_data(reinterpret_cast<char*>(contents.data), |
201 contents.len); | 197 contents.len); |
202 parsed_data.CopyToString(extension_data); | 198 parsed_data.CopyToString(extension_data); |
203 return true; | 199 return true; |
204 } | 200 } |
205 | 201 |
206 // Given a |cert|, extract the TBSCertificate from this certificate, also | 202 // Given a |cert|, extract the TBSCertificate from this certificate, also |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
255 | 251 |
256 // ResponseBytes ::= SEQUENCE { | 252 // ResponseBytes ::= SEQUENCE { |
257 // responseType OBJECT IDENTIFIER, | 253 // responseType OBJECT IDENTIFIER, |
258 // response OCTET STRING } | 254 // response OCTET STRING } |
259 struct ResponseBytes { | 255 struct ResponseBytes { |
260 SECItem response_type; | 256 SECItem response_type; |
261 SECItem der_response; | 257 SECItem der_response; |
262 }; | 258 }; |
263 | 259 |
264 const SEC_ASN1Template kResponseBytesTemplate[] = { | 260 const SEC_ASN1Template kResponseBytesTemplate[] = { |
265 { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(ResponseBytes) }, | 261 {SEC_ASN1_SEQUENCE, 0, NULL, sizeof(ResponseBytes)}, |
266 { SEC_ASN1_OBJECT_ID, offsetof(ResponseBytes, response_type) }, | 262 {SEC_ASN1_OBJECT_ID, offsetof(ResponseBytes, response_type)}, |
267 { SEC_ASN1_OCTET_STRING, offsetof(ResponseBytes, der_response) }, | 263 {SEC_ASN1_OCTET_STRING, offsetof(ResponseBytes, der_response)}, |
268 { 0 } | 264 {0}}; |
269 }; | |
270 | 265 |
271 // OCSPResponse ::= SEQUENCE { | 266 // OCSPResponse ::= SEQUENCE { |
272 // responseStatus OCSPResponseStatus, | 267 // responseStatus OCSPResponseStatus, |
273 // responseBytes [0] EXPLICIT ResponseBytes OPTIONAL } | 268 // responseBytes [0] EXPLICIT ResponseBytes OPTIONAL } |
274 struct OCSPResponse { | 269 struct OCSPResponse { |
275 SECItem response_status; | 270 SECItem response_status; |
276 // This indirection is needed because |response_bytes| is an optional | 271 // This indirection is needed because |response_bytes| is an optional |
277 // component and we need a way to determine if it is missing. | 272 // component and we need a way to determine if it is missing. |
278 ResponseBytes* response_bytes; | 273 ResponseBytes* response_bytes; |
279 }; | 274 }; |
280 | 275 |
281 const SEC_ASN1Template kPointerToResponseBytesTemplate[] = { | 276 const SEC_ASN1Template kPointerToResponseBytesTemplate[] = { |
282 { SEC_ASN1_POINTER, 0, kResponseBytesTemplate } | 277 {SEC_ASN1_POINTER, 0, kResponseBytesTemplate}}; |
283 }; | |
284 | 278 |
285 const SEC_ASN1Template kOCSPResponseTemplate[] = { | 279 const SEC_ASN1Template kOCSPResponseTemplate[] = { |
286 { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(OCSPResponse) }, | 280 {SEC_ASN1_SEQUENCE, 0, NULL, sizeof(OCSPResponse)}, |
287 { SEC_ASN1_ENUMERATED, offsetof(OCSPResponse, response_status) }, | 281 {SEC_ASN1_ENUMERATED, offsetof(OCSPResponse, response_status)}, |
288 { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT | SEC_ASN1_CONSTRUCTED | | 282 {SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT | SEC_ASN1_CONSTRUCTED | |
289 SEC_ASN1_CONTEXT_SPECIFIC | 0, offsetof(OCSPResponse, response_bytes), | 283 SEC_ASN1_CONTEXT_SPECIFIC | 0, |
290 kPointerToResponseBytesTemplate }, | 284 offsetof(OCSPResponse, response_bytes), kPointerToResponseBytesTemplate}, |
291 { 0 } | 285 {0}}; |
292 }; | |
293 | 286 |
294 // CertID ::= SEQUENCE { | 287 // CertID ::= SEQUENCE { |
295 // hashAlgorithm AlgorithmIdentifier, | 288 // hashAlgorithm AlgorithmIdentifier, |
296 // issuerNameHash OCTET STRING, -- Hash of Issuer's DN | 289 // issuerNameHash OCTET STRING, -- Hash of Issuer's DN |
297 // issuerKeyHash OCTET STRING, -- Hash of Issuers public key | 290 // issuerKeyHash OCTET STRING, -- Hash of Issuers public key |
298 // serialNumber CertificateSerialNumber } | 291 // serialNumber CertificateSerialNumber } |
299 struct CertID { | 292 struct CertID { |
300 SECAlgorithmID hash_algorithm; | 293 SECAlgorithmID hash_algorithm; |
301 SECItem issuer_name_hash; | 294 SECItem issuer_name_hash; |
302 SECItem issuer_key_hash; | 295 SECItem issuer_key_hash; |
303 SECItem serial_number; | 296 SECItem serial_number; |
304 }; | 297 }; |
305 | 298 |
306 const SEC_ASN1Template kCertIDTemplate[] = { | 299 const SEC_ASN1Template kCertIDTemplate[] = { |
307 { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(CertID) }, | 300 {SEC_ASN1_SEQUENCE, 0, NULL, sizeof(CertID)}, |
308 { SEC_ASN1_INLINE | SEC_ASN1_XTRN, offsetof(CertID, hash_algorithm), | 301 {SEC_ASN1_INLINE | SEC_ASN1_XTRN, offsetof(CertID, hash_algorithm), |
309 SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) }, | 302 SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate)}, |
310 { SEC_ASN1_OCTET_STRING, offsetof(CertID, issuer_name_hash) }, | 303 {SEC_ASN1_OCTET_STRING, offsetof(CertID, issuer_name_hash)}, |
311 { SEC_ASN1_OCTET_STRING, offsetof(CertID, issuer_key_hash) }, | 304 {SEC_ASN1_OCTET_STRING, offsetof(CertID, issuer_key_hash)}, |
312 { SEC_ASN1_INTEGER, offsetof(CertID, serial_number) }, | 305 {SEC_ASN1_INTEGER, offsetof(CertID, serial_number)}, |
313 { 0 } | 306 {0}}; |
314 }; | |
315 | 307 |
316 // SingleResponse ::= SEQUENCE { | 308 // SingleResponse ::= SEQUENCE { |
317 // certID CertID, | 309 // certID CertID, |
318 // certStatus CertStatus, | 310 // certStatus CertStatus, |
319 // thisUpdate GeneralizedTime, | 311 // thisUpdate GeneralizedTime, |
320 // nextUpdate [0] EXPLICIT GeneralizedTime OPTIONAL, | 312 // nextUpdate [0] EXPLICIT GeneralizedTime OPTIONAL, |
321 // singleExtensions [1] EXPLICIT Extensions OPTIONAL } | 313 // singleExtensions [1] EXPLICIT Extensions OPTIONAL } |
322 struct SingleResponse { | 314 struct SingleResponse { |
323 CertID cert_id; | 315 CertID cert_id; |
324 // The following three fields are not used. | 316 // The following three fields are not used. |
325 SECItem der_cert_status; | 317 SECItem der_cert_status; |
326 SECItem this_update; | 318 SECItem this_update; |
327 SECItem next_update; | 319 SECItem next_update; |
328 CERTCertExtension** single_extensions; | 320 CERTCertExtension** single_extensions; |
329 }; | 321 }; |
330 | 322 |
331 const SEC_ASN1Template kSingleResponseTemplate[] = { | 323 const SEC_ASN1Template kSingleResponseTemplate[] = { |
332 { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SingleResponse) }, | 324 {SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SingleResponse)}, |
333 { SEC_ASN1_INLINE, offsetof(SingleResponse, cert_id), kCertIDTemplate }, | 325 {SEC_ASN1_INLINE, offsetof(SingleResponse, cert_id), kCertIDTemplate}, |
334 // Really a CHOICE but we make it an ANY because we don't care about the | 326 // Really a CHOICE but we make it an ANY because we don't care about the |
335 // contents of this field. | 327 // contents of this field. |
336 // TODO(ekasper): use SEC_ASN1_CHOICE. | 328 // TODO(ekasper): use SEC_ASN1_CHOICE. |
337 { SEC_ASN1_ANY, offsetof(SingleResponse, der_cert_status) }, | 329 {SEC_ASN1_ANY, offsetof(SingleResponse, der_cert_status)}, |
338 { SEC_ASN1_GENERALIZED_TIME, offsetof(SingleResponse, this_update) }, | 330 {SEC_ASN1_GENERALIZED_TIME, offsetof(SingleResponse, this_update)}, |
339 { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT | | 331 {SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT | SEC_ASN1_CONSTRUCTED | |
340 SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 0, | 332 SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 0, |
341 offsetof(SingleResponse, next_update), | 333 offsetof(SingleResponse, next_update), |
342 SEC_ASN1_SUB(SEC_GeneralizedTimeTemplate) }, | 334 SEC_ASN1_SUB(SEC_GeneralizedTimeTemplate)}, |
343 { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT | SEC_ASN1_CONSTRUCTED | | 335 {SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT | SEC_ASN1_CONSTRUCTED | |
344 SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 1, | 336 SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 1, |
345 offsetof(SingleResponse, single_extensions), | 337 offsetof(SingleResponse, single_extensions), |
346 SEC_ASN1_SUB(CERT_SequenceOfCertExtensionTemplate) }, | 338 SEC_ASN1_SUB(CERT_SequenceOfCertExtensionTemplate)}, |
347 { 0 } | 339 {0}}; |
348 }; | |
349 | 340 |
350 // ResponseData ::= SEQUENCE { | 341 // ResponseData ::= SEQUENCE { |
351 // version [0] EXPLICIT Version DEFAULT v1, | 342 // version [0] EXPLICIT Version DEFAULT v1, |
352 // responderID ResponderID, | 343 // responderID ResponderID, |
353 // producedAt GeneralizedTime, | 344 // producedAt GeneralizedTime, |
354 // responses SEQUENCE OF SingleResponse, | 345 // responses SEQUENCE OF SingleResponse, |
355 // responseExtensions [1] EXPLICIT Extensions OPTIONAL } | 346 // responseExtensions [1] EXPLICIT Extensions OPTIONAL } |
356 struct ResponseData { | 347 struct ResponseData { |
357 // The first three fields are not used. | 348 // The first three fields are not used. |
358 SECItem version; | 349 SECItem version; |
359 SECItem der_responder_id; | 350 SECItem der_responder_id; |
360 SECItem produced_at; | 351 SECItem produced_at; |
361 SingleResponse** single_responses; | 352 SingleResponse** single_responses; |
362 // Skip extensions. | 353 // Skip extensions. |
363 }; | 354 }; |
364 | 355 |
365 const SEC_ASN1Template kResponseDataTemplate[] = { | 356 const SEC_ASN1Template kResponseDataTemplate[] = { |
366 { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(ResponseData) }, | 357 {SEC_ASN1_SEQUENCE, 0, NULL, sizeof(ResponseData)}, |
367 { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT | SEC_ASN1_CONSTRUCTED | | 358 {SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT | SEC_ASN1_CONSTRUCTED | |
368 SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 0, | 359 SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 0, |
369 offsetof(ResponseData, version), SEC_ASN1_SUB(SEC_IntegerTemplate) }, | 360 offsetof(ResponseData, version), SEC_ASN1_SUB(SEC_IntegerTemplate)}, |
370 // Really a CHOICE but we make it an ANY because we don't care about the | 361 // Really a CHOICE but we make it an ANY because we don't care about the |
371 // contents of this field. | 362 // contents of this field. |
372 // TODO(ekasper): use SEC_ASN1_CHOICE. | 363 // TODO(ekasper): use SEC_ASN1_CHOICE. |
373 { SEC_ASN1_ANY, offsetof(ResponseData, der_responder_id) }, | 364 {SEC_ASN1_ANY, offsetof(ResponseData, der_responder_id)}, |
374 { SEC_ASN1_GENERALIZED_TIME, offsetof(ResponseData, produced_at) }, | 365 {SEC_ASN1_GENERALIZED_TIME, offsetof(ResponseData, produced_at)}, |
375 { SEC_ASN1_SEQUENCE_OF, offsetof(ResponseData, single_responses), | 366 {SEC_ASN1_SEQUENCE_OF, offsetof(ResponseData, single_responses), |
376 kSingleResponseTemplate }, | 367 kSingleResponseTemplate}, |
377 { SEC_ASN1_SKIP_REST }, | 368 {SEC_ASN1_SKIP_REST}, |
378 { 0 } | 369 {0}}; |
379 }; | |
380 | 370 |
381 // BasicOCSPResponse ::= SEQUENCE { | 371 // BasicOCSPResponse ::= SEQUENCE { |
382 // tbsResponseData ResponseData, | 372 // tbsResponseData ResponseData, |
383 // signatureAlgorithm AlgorithmIdentifier, | 373 // signatureAlgorithm AlgorithmIdentifier, |
384 // signature BIT STRING, | 374 // signature BIT STRING, |
385 // certs [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL } | 375 // certs [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL } |
386 struct BasicOCSPResponse { | 376 struct BasicOCSPResponse { |
387 ResponseData tbs_response_data; | 377 ResponseData tbs_response_data; |
388 // We do not care about the rest. | 378 // We do not care about the rest. |
389 }; | 379 }; |
390 | 380 |
391 const SEC_ASN1Template kBasicOCSPResponseTemplate[] = { | 381 const SEC_ASN1Template kBasicOCSPResponseTemplate[] = { |
392 { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(BasicOCSPResponse) }, | 382 {SEC_ASN1_SEQUENCE, 0, NULL, sizeof(BasicOCSPResponse)}, |
393 { SEC_ASN1_INLINE, offsetof(BasicOCSPResponse, tbs_response_data), | 383 {SEC_ASN1_INLINE, offsetof(BasicOCSPResponse, tbs_response_data), |
394 kResponseDataTemplate }, | 384 kResponseDataTemplate}, |
395 { SEC_ASN1_SKIP_REST }, | 385 {SEC_ASN1_SKIP_REST}, |
396 { 0 } | 386 {0}}; |
397 }; | |
398 | 387 |
399 bool StringEqualToSECItem(const std::string& value1, const SECItem& value2) { | 388 bool StringEqualToSECItem(const std::string& value1, const SECItem& value2) { |
400 if (value1.size() != value2.len) | 389 if (value1.size() != value2.len) |
401 return false; | 390 return false; |
402 return memcmp(value1.data(), value2.data, value2.len) == 0; | 391 return memcmp(value1.data(), value2.data, value2.len) == 0; |
403 } | 392 } |
404 | 393 |
405 // TODO(ekasper): also use the issuer name hash in matching. | 394 // TODO(ekasper): also use the issuer name hash in matching. |
406 bool CertIDMatches(const CertID& cert_id, | 395 bool CertIDMatches(const CertID& cert_id, |
407 const std::string& serial_number, | 396 const std::string& serial_number, |
(...skipping 18 matching lines...) Expand all Loading... |
426 } // namespace | 415 } // namespace |
427 | 416 |
428 bool ExtractEmbeddedSCTList(X509Certificate::OSCertHandle cert, | 417 bool ExtractEmbeddedSCTList(X509Certificate::OSCertHandle cert, |
429 std::string* sct_list) { | 418 std::string* sct_list) { |
430 DCHECK(cert); | 419 DCHECK(cert); |
431 | 420 |
432 NSSCertWrapper leaf_cert(cert); | 421 NSSCertWrapper leaf_cert(cert); |
433 if (!leaf_cert.cert) | 422 if (!leaf_cert.cert) |
434 return false; | 423 return false; |
435 | 424 |
436 return GetCertOctetStringExtension(leaf_cert.cert.get(), | 425 return GetCertOctetStringExtension( |
437 g_ct_singleton.Get().embedded_oid(), | 426 leaf_cert.cert.get(), g_ct_singleton.Get().embedded_oid(), sct_list); |
438 sct_list); | |
439 } | 427 } |
440 | 428 |
441 bool GetPrecertLogEntry(X509Certificate::OSCertHandle leaf, | 429 bool GetPrecertLogEntry(X509Certificate::OSCertHandle leaf, |
442 X509Certificate::OSCertHandle issuer, | 430 X509Certificate::OSCertHandle issuer, |
443 LogEntry* result) { | 431 LogEntry* result) { |
444 DCHECK(leaf); | 432 DCHECK(leaf); |
445 DCHECK(issuer); | 433 DCHECK(issuer); |
446 | 434 |
447 NSSCertWrapper leaf_cert(leaf); | 435 NSSCertWrapper leaf_cert(leaf); |
448 NSSCertWrapper issuer_cert(issuer); | 436 NSSCertWrapper issuer_cert(issuer); |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
523 // only uses stapled OCSP responses which have this limit imposed by the TLS | 511 // only uses stapled OCSP responses which have this limit imposed by the TLS |
524 // protocol. | 512 // protocol. |
525 if (ocsp_response.size() > 0xffffff) | 513 if (ocsp_response.size() > 0xffffff) |
526 return false; | 514 return false; |
527 | 515 |
528 crypto::ScopedPLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE)); | 516 crypto::ScopedPLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE)); |
529 | 517 |
530 OCSPResponse response; | 518 OCSPResponse response; |
531 memset(&response, 0, sizeof(response)); | 519 memset(&response, 0, sizeof(response)); |
532 | 520 |
533 SECItem src = { siBuffer, | 521 SECItem src = {siBuffer, reinterpret_cast<unsigned char*>( |
534 reinterpret_cast<unsigned char*>(const_cast<char*>( | 522 const_cast<char*>(ocsp_response.data())), |
535 ocsp_response.data())), | 523 static_cast<unsigned int>(ocsp_response.size())}; |
536 static_cast<unsigned int>(ocsp_response.size()) }; | |
537 | 524 |
538 // |response| will point directly into |src|, so it's not necessary to | 525 // |response| will point directly into |src|, so it's not necessary to |
539 // free the |response| contents, but they may only be used while |src| | 526 // free the |response| contents, but they may only be used while |src| |
540 // is valid (i.e., in this method). | 527 // is valid (i.e., in this method). |
541 SECStatus rv = SEC_QuickDERDecodeItem(arena.get(), &response, | 528 SECStatus rv = SEC_QuickDERDecodeItem( |
542 kOCSPResponseTemplate, &src); | 529 arena.get(), &response, kOCSPResponseTemplate, &src); |
543 if (rv != SECSuccess) | 530 if (rv != SECSuccess) |
544 return false; | 531 return false; |
545 | 532 |
546 if (!response.response_bytes) | 533 if (!response.response_bytes) |
547 return false; | 534 return false; |
548 | 535 |
549 if (!SECITEM_ItemsAreEqual(&kBasicOCSPResponseOidItem, | 536 if (!SECITEM_ItemsAreEqual(&kBasicOCSPResponseOidItem, |
550 &response.response_bytes->response_type)) { | 537 &response.response_bytes->response_type)) { |
551 return false; | 538 return false; |
552 } | 539 } |
553 | 540 |
554 BasicOCSPResponse basic_response; | 541 BasicOCSPResponse basic_response; |
555 memset(&basic_response, 0, sizeof(basic_response)); | 542 memset(&basic_response, 0, sizeof(basic_response)); |
556 | 543 |
557 rv = SEC_QuickDERDecodeItem(arena.get(), &basic_response, | 544 rv = SEC_QuickDERDecodeItem(arena.get(), |
| 545 &basic_response, |
558 kBasicOCSPResponseTemplate, | 546 kBasicOCSPResponseTemplate, |
559 &response.response_bytes->der_response); | 547 &response.response_bytes->der_response); |
560 if (rv != SECSuccess) | 548 if (rv != SECSuccess) |
561 return false; | 549 return false; |
562 | 550 |
563 SingleResponse** responses = | 551 SingleResponse** responses = |
564 basic_response.tbs_response_data.single_responses; | 552 basic_response.tbs_response_data.single_responses; |
565 if (!responses) | 553 if (!responses) |
566 return false; | 554 return false; |
567 | 555 |
(...skipping 17 matching lines...) Expand all Loading... |
585 return false; | 573 return false; |
586 issuer_spk.remove_prefix(1); | 574 issuer_spk.remove_prefix(1); |
587 | 575 |
588 // NSS OCSP lib recognizes SHA1, MD5 and MD2; MD5 and MD2 are dead but | 576 // NSS OCSP lib recognizes SHA1, MD5 and MD2; MD5 and MD2 are dead but |
589 // https://bugzilla.mozilla.org/show_bug.cgi?id=663315 will add SHA-256 | 577 // https://bugzilla.mozilla.org/show_bug.cgi?id=663315 will add SHA-256 |
590 // and SHA-384. | 578 // and SHA-384. |
591 // TODO(ekasper): add SHA-384 to crypto/sha2.h and here if it proves | 579 // TODO(ekasper): add SHA-384 to crypto/sha2.h and here if it proves |
592 // necessary. | 580 // necessary. |
593 // TODO(ekasper): only compute the hashes on demand. | 581 // TODO(ekasper): only compute the hashes on demand. |
594 std::string issuer_key_sha256_hash = crypto::SHA256HashString(issuer_spk); | 582 std::string issuer_key_sha256_hash = crypto::SHA256HashString(issuer_spk); |
595 std::string issuer_key_sha1_hash = base::SHA1HashString( | 583 std::string issuer_key_sha1_hash = |
596 issuer_spk.as_string()); | 584 base::SHA1HashString(issuer_spk.as_string()); |
597 | 585 |
598 const SingleResponse* match = NULL; | 586 const SingleResponse* match = NULL; |
599 for (const SingleResponse* const* resps = responses; *resps; ++resps) { | 587 for (const SingleResponse* const* resps = responses; *resps; ++resps) { |
600 const SingleResponse* resp = *resps; | 588 const SingleResponse* resp = *resps; |
601 if (CertIDMatches(resp->cert_id, cert_serial_number, | 589 if (CertIDMatches(resp->cert_id, |
602 issuer_key_sha1_hash, issuer_key_sha256_hash)) { | 590 cert_serial_number, |
| 591 issuer_key_sha1_hash, |
| 592 issuer_key_sha256_hash)) { |
603 match = resp; | 593 match = resp; |
604 break; | 594 break; |
605 } | 595 } |
606 } | 596 } |
607 | 597 |
608 if (!match) | 598 if (!match) |
609 return false; | 599 return false; |
610 | 600 |
611 return GetSCTListFromOCSPExtension(arena.get(), match->single_extensions, | 601 return GetSCTListFromOCSPExtension( |
612 sct_list); | 602 arena.get(), match->single_extensions, sct_list); |
613 } | 603 } |
614 | 604 |
615 } // namespace ct | 605 } // namespace ct |
616 | 606 |
617 } // namespace net | 607 } // namespace net |
OLD | NEW |