| 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 <string.h> | 7 #include <string.h> |
| 8 | 8 |
| 9 #include <openssl/bytestring.h> | 9 #include <openssl/bytestring.h> |
| 10 #include <openssl/obj.h> | 10 #include <openssl/obj.h> |
| (...skipping 16 matching lines...) Expand all Loading... |
| 27 | 27 |
| 28 void FreeX509_EXTENSIONS(X509_EXTENSIONS* ptr) { | 28 void FreeX509_EXTENSIONS(X509_EXTENSIONS* ptr) { |
| 29 sk_X509_EXTENSION_pop_free(ptr, X509_EXTENSION_free); | 29 sk_X509_EXTENSION_pop_free(ptr, X509_EXTENSION_free); |
| 30 } | 30 } |
| 31 | 31 |
| 32 using ScopedX509_EXTENSIONS = | 32 using ScopedX509_EXTENSIONS = |
| 33 crypto::ScopedOpenSSL<X509_EXTENSIONS, FreeX509_EXTENSIONS>; | 33 crypto::ScopedOpenSSL<X509_EXTENSIONS, FreeX509_EXTENSIONS>; |
| 34 | 34 |
| 35 // The wire form of the OID 1.3.6.1.4.1.11129.2.4.2. See Section 3.3 of | 35 // The wire form of the OID 1.3.6.1.4.1.11129.2.4.2. See Section 3.3 of |
| 36 // RFC6962. | 36 // RFC6962. |
| 37 const uint8_t kEmbeddedSCTOid[] = {0x2B, 0x06, 0x01, 0x04, 0x01, 0xD6, 0x79, | 37 const uint8_t kEmbeddedSCTOid[] = {0x2B, 0x06, 0x01, 0x04, 0x01, |
| 38 0x02, 0x04, 0x02}; | 38 0xD6, 0x79, 0x02, 0x04, 0x02}; |
| 39 | 39 |
| 40 // The wire form of the OID 1.3.6.1.4.1.11129.2.4.5 - OCSP SingleExtension for | 40 // The wire form of the OID 1.3.6.1.4.1.11129.2.4.5 - OCSP SingleExtension for |
| 41 // X.509v3 Certificate Transparency Signed Certificate Timestamp List, see | 41 // X.509v3 Certificate Transparency Signed Certificate Timestamp List, see |
| 42 // Section 3.3 of RFC6962. | 42 // Section 3.3 of RFC6962. |
| 43 const uint8_t kOCSPExtensionOid[] = {0x2B, 0x06, 0x01, 0x04, 0x01, 0xD6, 0x79, | 43 const uint8_t kOCSPExtensionOid[] = {0x2B, 0x06, 0x01, 0x04, 0x01, |
| 44 0x02, 0x04, 0x05}; | 44 0xD6, 0x79, 0x02, 0x04, 0x05}; |
| 45 | 45 |
| 46 bool StringEqualToCBS(const std::string& value1, const CBS* value2) { | 46 bool StringEqualToCBS(const std::string& value1, const CBS* value2) { |
| 47 if (CBS_len(value2) != value1.size()) | 47 if (CBS_len(value2) != value1.size()) |
| 48 return false; | 48 return false; |
| 49 return memcmp(value1.data(), CBS_data(value2), CBS_len(value2)) == 0; | 49 return memcmp(value1.data(), CBS_data(value2), CBS_len(value2)) == 0; |
| 50 } | 50 } |
| 51 | 51 |
| 52 ScopedX509 OSCertHandleToOpenSSL(X509Certificate::OSCertHandle os_handle) { | 52 ScopedX509 OSCertHandleToOpenSSL(X509Certificate::OSCertHandle os_handle) { |
| 53 #if defined(USE_OPENSSL_CERTS) | 53 #if defined(USE_OPENSSL_CERTS) |
| 54 return ScopedX509(X509Certificate::DupOSCertHandle(os_handle)); | 54 return ScopedX509(X509Certificate::DupOSCertHandle(os_handle)); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 73 if (static_cast<size_t>(x509_ext->object->length) == oid_len && | 73 if (static_cast<size_t>(x509_ext->object->length) == oid_len && |
| 74 memcmp(x509_ext->object->data, oid, oid_len) == 0) { | 74 memcmp(x509_ext->object->data, oid, oid_len) == 0) { |
| 75 // The SCT list is an OCTET STRING inside the extension. | 75 // The SCT list is an OCTET STRING inside the extension. |
| 76 CBS ext_value, sct_list; | 76 CBS ext_value, sct_list; |
| 77 CBS_init(&ext_value, x509_ext->value->data, x509_ext->value->length); | 77 CBS_init(&ext_value, x509_ext->value->data, x509_ext->value->length); |
| 78 if (!CBS_get_asn1(&ext_value, &sct_list, CBS_ASN1_OCTETSTRING) || | 78 if (!CBS_get_asn1(&ext_value, &sct_list, CBS_ASN1_OCTETSTRING) || |
| 79 CBS_len(&ext_value) != 0) { | 79 CBS_len(&ext_value) != 0) { |
| 80 return false; | 80 return false; |
| 81 } | 81 } |
| 82 if (out_sct_list) { | 82 if (out_sct_list) { |
| 83 *out_sct_list = std::string( | 83 *out_sct_list = |
| 84 reinterpret_cast<const char*>(CBS_data(&sct_list)), | 84 std::string(reinterpret_cast<const char*>(CBS_data(&sct_list)), |
| 85 CBS_len(&sct_list)); | 85 CBS_len(&sct_list)); |
| 86 } | 86 } |
| 87 return true; | 87 return true; |
| 88 } | 88 } |
| 89 } | 89 } |
| 90 return false; | 90 return false; |
| 91 } | 91 } |
| 92 | 92 |
| 93 // Finds the SingleResponse in |responses| which matches |issuer| and | 93 // Finds the SingleResponse in |responses| which matches |issuer| and |
| 94 // |cert_serial_number|. On success, returns true and sets | 94 // |cert_serial_number|. On success, returns true and sets |
| 95 // |*out_single_response| to the body of the SingleResponse starting at the | 95 // |*out_single_response| to the body of the SingleResponse starting at the |
| (...skipping 19 matching lines...) Expand all Loading... |
| 115 // number of unused bits in the ASN.1 BIT STRING so we do it here. For public | 115 // number of unused bits in the ASN.1 BIT STRING so we do it here. For public |
| 116 // keys, the bitstring is in practice always byte-aligned. | 116 // keys, the bitstring is in practice always byte-aligned. |
| 117 if (issuer_spk.empty() || issuer_spk[0] != 0) | 117 if (issuer_spk.empty() || issuer_spk[0] != 0) |
| 118 return false; | 118 return false; |
| 119 issuer_spk.remove_prefix(1); | 119 issuer_spk.remove_prefix(1); |
| 120 | 120 |
| 121 // TODO(ekasper): add SHA-384 to crypto/sha2.h and here if it proves | 121 // TODO(ekasper): add SHA-384 to crypto/sha2.h and here if it proves |
| 122 // necessary. | 122 // necessary. |
| 123 // TODO(ekasper): only compute the hashes on demand. | 123 // TODO(ekasper): only compute the hashes on demand. |
| 124 std::string issuer_key_sha256_hash = crypto::SHA256HashString(issuer_spk); | 124 std::string issuer_key_sha256_hash = crypto::SHA256HashString(issuer_spk); |
| 125 std::string issuer_key_sha1_hash = base::SHA1HashString( | 125 std::string issuer_key_sha1_hash = |
| 126 issuer_spk.as_string()); | 126 base::SHA1HashString(issuer_spk.as_string()); |
| 127 | 127 |
| 128 while (CBS_len(responses) > 0) { | 128 while (CBS_len(responses) > 0) { |
| 129 CBS single_response, cert_id; | 129 CBS single_response, cert_id; |
| 130 if (!CBS_get_asn1(responses, &single_response, CBS_ASN1_SEQUENCE) || | 130 if (!CBS_get_asn1(responses, &single_response, CBS_ASN1_SEQUENCE) || |
| 131 !CBS_get_asn1(&single_response, &cert_id, CBS_ASN1_SEQUENCE)) { | 131 !CBS_get_asn1(&single_response, &cert_id, CBS_ASN1_SEQUENCE)) { |
| 132 return false; | 132 return false; |
| 133 } | 133 } |
| 134 | 134 |
| 135 CBS hash_algorithm, hash, serial_number, issuer_name_hash, issuer_key_hash; | 135 CBS hash_algorithm, hash, serial_number, issuer_name_hash, issuer_key_hash; |
| 136 if (!CBS_get_asn1(&cert_id, &hash_algorithm, CBS_ASN1_SEQUENCE) || | 136 if (!CBS_get_asn1(&cert_id, &hash_algorithm, CBS_ASN1_SEQUENCE) || |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 170 } // namespace | 170 } // namespace |
| 171 | 171 |
| 172 bool ExtractEmbeddedSCTList(X509Certificate::OSCertHandle cert, | 172 bool ExtractEmbeddedSCTList(X509Certificate::OSCertHandle cert, |
| 173 std::string* sct_list) { | 173 std::string* sct_list) { |
| 174 ScopedX509 x509(OSCertHandleToOpenSSL(cert)); | 174 ScopedX509 x509(OSCertHandleToOpenSSL(cert)); |
| 175 if (!x509) | 175 if (!x509) |
| 176 return false; | 176 return false; |
| 177 X509_EXTENSIONS* x509_exts = x509->cert_info->extensions; | 177 X509_EXTENSIONS* x509_exts = x509->cert_info->extensions; |
| 178 if (!x509_exts) | 178 if (!x509_exts) |
| 179 return false; | 179 return false; |
| 180 return GetSCTListFromX509_EXTENSIONS( | 180 return GetSCTListFromX509_EXTENSIONS(x509->cert_info->extensions, |
| 181 x509->cert_info->extensions, kEmbeddedSCTOid, sizeof(kEmbeddedSCTOid), | 181 kEmbeddedSCTOid, sizeof(kEmbeddedSCTOid), |
| 182 sct_list); | 182 sct_list); |
| 183 } | 183 } |
| 184 | 184 |
| 185 bool GetPrecertLogEntry(X509Certificate::OSCertHandle leaf, | 185 bool GetPrecertLogEntry(X509Certificate::OSCertHandle leaf, |
| 186 X509Certificate::OSCertHandle issuer, | 186 X509Certificate::OSCertHandle issuer, |
| 187 LogEntry* result) { | 187 LogEntry* result) { |
| 188 result->Reset(); | 188 result->Reset(); |
| 189 | 189 |
| 190 ScopedX509 leaf_x509(OSCertHandleToOpenSSL(leaf)); | 190 ScopedX509 leaf_x509(OSCertHandleToOpenSSL(leaf)); |
| 191 if (!leaf_x509) | 191 if (!leaf_x509) |
| 192 return false; | 192 return false; |
| (...skipping 12 matching lines...) Expand all Loading... |
| 205 // without the SCT extension (RFC6962, section 3.2). | 205 // without the SCT extension (RFC6962, section 3.2). |
| 206 ScopedX509 leaf_copy(X509_dup(leaf_x509.get())); | 206 ScopedX509 leaf_copy(X509_dup(leaf_x509.get())); |
| 207 if (!leaf_copy || !leaf_copy->cert_info->extensions) { | 207 if (!leaf_copy || !leaf_copy->cert_info->extensions) { |
| 208 NOTREACHED(); | 208 NOTREACHED(); |
| 209 return false; | 209 return false; |
| 210 } | 210 } |
| 211 X509_EXTENSIONS* leaf_copy_exts = leaf_copy->cert_info->extensions; | 211 X509_EXTENSIONS* leaf_copy_exts = leaf_copy->cert_info->extensions; |
| 212 for (size_t i = 0; i < sk_X509_EXTENSION_num(leaf_copy_exts); i++) { | 212 for (size_t i = 0; i < sk_X509_EXTENSION_num(leaf_copy_exts); i++) { |
| 213 X509_EXTENSION* ext = sk_X509_EXTENSION_value(leaf_copy_exts, i); | 213 X509_EXTENSION* ext = sk_X509_EXTENSION_value(leaf_copy_exts, i); |
| 214 if (static_cast<size_t>(ext->object->length) == sizeof(kEmbeddedSCTOid) && | 214 if (static_cast<size_t>(ext->object->length) == sizeof(kEmbeddedSCTOid) && |
| 215 memcmp(ext->object->data, | 215 memcmp(ext->object->data, kEmbeddedSCTOid, sizeof(kEmbeddedSCTOid)) == |
| 216 kEmbeddedSCTOid, sizeof(kEmbeddedSCTOid)) == 0) { | 216 0) { |
| 217 X509_EXTENSION_free(sk_X509_EXTENSION_delete(leaf_copy_exts, i)); | 217 X509_EXTENSION_free(sk_X509_EXTENSION_delete(leaf_copy_exts, i)); |
| 218 X509_CINF_set_modified(leaf_copy->cert_info); | 218 X509_CINF_set_modified(leaf_copy->cert_info); |
| 219 break; | 219 break; |
| 220 } | 220 } |
| 221 } | 221 } |
| 222 | 222 |
| 223 std::string to_be_signed; | 223 std::string to_be_signed; |
| 224 int len = i2d_X509_CINF(leaf_copy->cert_info, NULL); | 224 int len = i2d_X509_CINF(leaf_copy->cert_info, NULL); |
| 225 if (len < 0) | 225 if (len < 0) |
| 226 return false; | 226 return false; |
| 227 uint8_t* ptr = | 227 uint8_t* ptr = |
| 228 reinterpret_cast<uint8_t*>(base::WriteInto(&to_be_signed, len + 1)); | 228 reinterpret_cast<uint8_t*>(base::WriteInto(&to_be_signed, len + 1)); |
| 229 if (i2d_X509_CINF(leaf_copy->cert_info, &ptr) < 0) | 229 if (i2d_X509_CINF(leaf_copy->cert_info, &ptr) < 0) |
| 230 return false; | 230 return false; |
| 231 | 231 |
| 232 // Extract the issuer's public key. | 232 // Extract the issuer's public key. |
| 233 std::string issuer_der; | 233 std::string issuer_der; |
| 234 if (!X509Certificate::GetDEREncoded(issuer, &issuer_der)) | 234 if (!X509Certificate::GetDEREncoded(issuer, &issuer_der)) |
| 235 return false; | 235 return false; |
| 236 base::StringPiece issuer_key; | 236 base::StringPiece issuer_key; |
| 237 if (!asn1::ExtractSPKIFromDERCert(issuer_der, &issuer_key)) | 237 if (!asn1::ExtractSPKIFromDERCert(issuer_der, &issuer_key)) |
| 238 return false; | 238 return false; |
| 239 | 239 |
| 240 // Fill in the LogEntry. | 240 // Fill in the LogEntry. |
| 241 result->type = ct::LogEntry::LOG_ENTRY_TYPE_PRECERT; | 241 result->type = ct::LogEntry::LOG_ENTRY_TYPE_PRECERT; |
| 242 result->tbs_certificate.swap(to_be_signed); | 242 result->tbs_certificate.swap(to_be_signed); |
| 243 crypto::SHA256HashString(issuer_key, | 243 crypto::SHA256HashString(issuer_key, result->issuer_key_hash.data, |
| 244 result->issuer_key_hash.data, | |
| 245 sizeof(result->issuer_key_hash.data)); | 244 sizeof(result->issuer_key_hash.data)); |
| 246 | 245 |
| 247 return true; | 246 return true; |
| 248 } | 247 } |
| 249 | 248 |
| 250 bool GetX509LogEntry(X509Certificate::OSCertHandle leaf, LogEntry* result) { | 249 bool GetX509LogEntry(X509Certificate::OSCertHandle leaf, LogEntry* result) { |
| 251 DCHECK(leaf); | 250 DCHECK(leaf); |
| 252 | 251 |
| 253 std::string encoded; | 252 std::string encoded; |
| 254 if (!X509Certificate::GetDEREncoded(leaf, &encoded)) | 253 if (!X509Certificate::GetDEREncoded(leaf, &encoded)) |
| 255 return false; | 254 return false; |
| 256 | 255 |
| 257 result->Reset(); | 256 result->Reset(); |
| 258 result->type = ct::LogEntry::LOG_ENTRY_TYPE_X509; | 257 result->type = ct::LogEntry::LOG_ENTRY_TYPE_X509; |
| 259 result->leaf_certificate.swap(encoded); | 258 result->leaf_certificate.swap(encoded); |
| 260 return true; | 259 return true; |
| 261 } | 260 } |
| 262 | 261 |
| 263 bool ExtractSCTListFromOCSPResponse(X509Certificate::OSCertHandle issuer, | 262 bool ExtractSCTListFromOCSPResponse(X509Certificate::OSCertHandle issuer, |
| 264 const std::string& cert_serial_number, | 263 const std::string& cert_serial_number, |
| 265 const std::string& ocsp_response, | 264 const std::string& ocsp_response, |
| 266 std::string* sct_list) { | 265 std::string* sct_list) { |
| 267 // The input is an OCSPResponse. See RFC2560, section 4.2.1. The SCT list is | 266 // The input is an OCSPResponse. See RFC2560, section 4.2.1. The SCT list is |
| 268 // in the extensions field of the SingleResponse which matches the input | 267 // in the extensions field of the SingleResponse which matches the input |
| 269 // certificate. | 268 // certificate. |
| 270 CBS cbs; | 269 CBS cbs; |
| 271 CBS_init(&cbs, | 270 CBS_init(&cbs, reinterpret_cast<const uint8_t*>(ocsp_response.data()), |
| 272 reinterpret_cast<const uint8_t*>(ocsp_response.data()), | |
| 273 ocsp_response.size()); | 271 ocsp_response.size()); |
| 274 | 272 |
| 275 // Parse down to the ResponseBytes. The ResponseBytes is optional, but if it's | 273 // Parse down to the ResponseBytes. The ResponseBytes is optional, but if it's |
| 276 // missing, this can't include an SCT list. | 274 // missing, this can't include an SCT list. |
| 277 CBS sequence, response_status, tagged_response_bytes, response_bytes; | 275 CBS sequence, response_status, tagged_response_bytes, response_bytes; |
| 278 CBS response_type, response; | 276 CBS response_type, response; |
| 279 if (!CBS_get_asn1(&cbs, &sequence, CBS_ASN1_SEQUENCE) || | 277 if (!CBS_get_asn1(&cbs, &sequence, CBS_ASN1_SEQUENCE) || CBS_len(&cbs) != 0 || |
| 280 CBS_len(&cbs) != 0 || | |
| 281 !CBS_get_asn1(&sequence, &response_status, CBS_ASN1_ENUMERATED) || | 278 !CBS_get_asn1(&sequence, &response_status, CBS_ASN1_ENUMERATED) || |
| 282 !CBS_get_asn1(&sequence, &tagged_response_bytes, | 279 !CBS_get_asn1(&sequence, &tagged_response_bytes, |
| 283 CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0) || | 280 CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0) || |
| 284 CBS_len(&sequence) != 0 || | 281 CBS_len(&sequence) != 0 || |
| 285 !CBS_get_asn1(&tagged_response_bytes, &response_bytes, | 282 !CBS_get_asn1(&tagged_response_bytes, &response_bytes, |
| 286 CBS_ASN1_SEQUENCE) || | 283 CBS_ASN1_SEQUENCE) || |
| 287 CBS_len(&tagged_response_bytes) != 0 || | 284 CBS_len(&tagged_response_bytes) != 0 || |
| 288 !CBS_get_asn1(&response_bytes, &response_type, CBS_ASN1_OBJECT) || | 285 !CBS_get_asn1(&response_bytes, &response_type, CBS_ASN1_OBJECT) || |
| 289 !CBS_get_asn1(&response_bytes, &response, CBS_ASN1_OCTETSTRING) || | 286 !CBS_get_asn1(&response_bytes, &response, CBS_ASN1_OCTETSTRING) || |
| 290 CBS_len(&response_bytes) != 0) { | 287 CBS_len(&response_bytes) != 0) { |
| 291 return false; | 288 return false; |
| 292 } | 289 } |
| 293 | 290 |
| 294 // The only relevant ResponseType is id-pkix-ocsp-basic. | 291 // The only relevant ResponseType is id-pkix-ocsp-basic. |
| 295 if (OBJ_cbs2nid(&response_type) != NID_id_pkix_OCSP_basic) | 292 if (OBJ_cbs2nid(&response_type) != NID_id_pkix_OCSP_basic) |
| 296 return false; | 293 return false; |
| 297 | 294 |
| 298 // Parse the ResponseData out of the BasicOCSPResponse. Ignore the rest. | 295 // Parse the ResponseData out of the BasicOCSPResponse. Ignore the rest. |
| 299 CBS basic_response, response_data, responses; | 296 CBS basic_response, response_data, responses; |
| 300 if (!CBS_get_asn1(&response, &basic_response, CBS_ASN1_SEQUENCE) || | 297 if (!CBS_get_asn1(&response, &basic_response, CBS_ASN1_SEQUENCE) || |
| 301 CBS_len(&response) != 0 || | 298 CBS_len(&response) != 0 || |
| 302 !CBS_get_asn1(&basic_response, &response_data, CBS_ASN1_SEQUENCE)) { | 299 !CBS_get_asn1(&basic_response, &response_data, CBS_ASN1_SEQUENCE)) { |
| 303 } | 300 } |
| 304 | 301 |
| 305 // Skip the optional version. | 302 // Skip the optional version. |
| 306 const int kVersionTag = | 303 const int kVersionTag = CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0; |
| 307 CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0; | |
| 308 if (CBS_len(&response_data) > 0 && | 304 if (CBS_len(&response_data) > 0 && |
| 309 CBS_data(&response_data)[0] == kVersionTag && | 305 CBS_data(&response_data)[0] == kVersionTag && |
| 310 !CBS_get_asn1(&response_data, NULL /* version */, kVersionTag)) { | 306 !CBS_get_asn1(&response_data, NULL /* version */, kVersionTag)) { |
| 311 return false; | 307 return false; |
| 312 } | 308 } |
| 313 | 309 |
| 314 // Extract the list of SingleResponses. | 310 // Extract the list of SingleResponses. |
| 315 if (!CBS_get_any_asn1_element(&response_data, | 311 if (!CBS_get_any_asn1_element(&response_data, NULL /* responderID */, NULL, |
| 316 NULL /* responderID */, NULL, NULL) || | 312 NULL) || |
| 317 !CBS_get_any_asn1_element(&response_data, | 313 !CBS_get_any_asn1_element(&response_data, NULL /* producedAt */, NULL, |
| 318 NULL /* producedAt */, NULL, NULL) || | 314 NULL) || |
| 319 !CBS_get_asn1(&response_data, &responses, CBS_ASN1_SEQUENCE)) { | 315 !CBS_get_asn1(&response_data, &responses, CBS_ASN1_SEQUENCE)) { |
| 320 return false; | 316 return false; |
| 321 } | 317 } |
| 322 | 318 |
| 323 CBS single_response; | 319 CBS single_response; |
| 324 if (!FindMatchingSingleResponse(&responses, issuer, cert_serial_number, | 320 if (!FindMatchingSingleResponse(&responses, issuer, cert_serial_number, |
| 325 &single_response)) { | 321 &single_response)) { |
| 326 return false; | 322 return false; |
| 327 } | 323 } |
| 328 | 324 |
| 329 // Skip the certStatus and thisUpdate fields. | 325 // Skip the certStatus and thisUpdate fields. |
| 330 if (!CBS_get_any_asn1_element(&single_response, | 326 if (!CBS_get_any_asn1_element(&single_response, NULL /* certStatus */, NULL, |
| 331 NULL /* certStatus */, NULL, NULL) || | 327 NULL) || |
| 332 !CBS_get_any_asn1_element(&single_response, | 328 !CBS_get_any_asn1_element(&single_response, NULL /* thisUpdate */, NULL, |
| 333 NULL /* thisUpdate */, NULL, NULL)) { | 329 NULL)) { |
| 334 return false; | 330 return false; |
| 335 } | 331 } |
| 336 | 332 |
| 337 const int kNextUpdateTag = | 333 const int kNextUpdateTag = |
| 338 CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0; | 334 CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0; |
| 339 const int kSingleExtensionsTag = | 335 const int kSingleExtensionsTag = |
| 340 CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 1; | 336 CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 1; |
| 341 | 337 |
| 342 // Skip the optional nextUpdate field. | 338 // Skip the optional nextUpdate field. |
| 343 if (CBS_len(&single_response) > 0 && | 339 if (CBS_len(&single_response) > 0 && |
| 344 CBS_data(&single_response)[0] == kNextUpdateTag && | 340 CBS_data(&single_response)[0] == kNextUpdateTag && |
| 345 !CBS_get_asn1(&single_response, NULL /* nextUpdate */, kNextUpdateTag)) { | 341 !CBS_get_asn1(&single_response, NULL /* nextUpdate */, kNextUpdateTag)) { |
| 346 return false; | 342 return false; |
| 347 } | 343 } |
| 348 | 344 |
| 349 CBS extensions; | 345 CBS extensions; |
| 350 if (!CBS_get_asn1(&single_response, &extensions, kSingleExtensionsTag)) | 346 if (!CBS_get_asn1(&single_response, &extensions, kSingleExtensionsTag)) |
| 351 return false; | 347 return false; |
| 352 const uint8_t* ptr = CBS_data(&extensions); | 348 const uint8_t* ptr = CBS_data(&extensions); |
| 353 ScopedX509_EXTENSIONS x509_exts( | 349 ScopedX509_EXTENSIONS x509_exts( |
| 354 d2i_X509_EXTENSIONS(NULL, &ptr, CBS_len(&extensions))); | 350 d2i_X509_EXTENSIONS(NULL, &ptr, CBS_len(&extensions))); |
| 355 if (!x509_exts || ptr != CBS_data(&extensions) + CBS_len(&extensions)) | 351 if (!x509_exts || ptr != CBS_data(&extensions) + CBS_len(&extensions)) |
| 356 return false; | 352 return false; |
| 357 | 353 |
| 358 return GetSCTListFromX509_EXTENSIONS( | 354 return GetSCTListFromX509_EXTENSIONS(x509_exts.get(), kOCSPExtensionOid, |
| 359 x509_exts.get(), kOCSPExtensionOid, sizeof(kOCSPExtensionOid), sct_list); | 355 sizeof(kOCSPExtensionOid), sct_list); |
| 360 } | 356 } |
| 361 | 357 |
| 362 } // namespace ct | 358 } // namespace ct |
| 363 | 359 |
| 364 } // namespace net | 360 } // namespace net |
| OLD | NEW |