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