Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "net/cert/internal/parsed_certificate.h" | |
| 6 | |
| 7 #include "net/cert/internal/name_constraints.h" | |
| 8 #include "net/cert/internal/signature_algorithm.h" | |
| 9 #include "net/cert/internal/verify_name_match.h" | |
| 10 #include "net/der/parser.h" | |
| 11 | |
| 12 namespace net { | |
| 13 | |
| 14 namespace { | |
| 15 | |
| 16 WARN_UNUSED_RESULT bool GetSequenceValue(const der::Input& tlv, | |
| 17 der::Input* value) { | |
| 18 der::Parser parser(tlv); | |
| 19 return parser.ReadTag(der::kSequence, value) && !parser.HasMore(); | |
| 20 } | |
| 21 | |
| 22 } // namespace | |
| 23 | |
| 24 ParsedCertificate::ParsedCertificate() {} | |
| 25 ParsedCertificate::~ParsedCertificate() {} | |
| 26 | |
| 27 scoped_refptr<ParsedCertificate> ParsedCertificate::CreateFromCertificateData( | |
| 28 const uint8_t* data, | |
| 29 size_t length, | |
| 30 DataSource source) { | |
| 31 scoped_refptr<ParsedCertificate> result(new ParsedCertificate); | |
| 32 | |
| 33 switch (source) { | |
| 34 case DataSource::INTERNAL_COPY: | |
| 35 result->cert_data_.assign(data, data + length); | |
| 36 result->cert_ = | |
| 37 der::Input(result->cert_data_.data(), result->cert_data_.size()); | |
| 38 break; | |
| 39 case DataSource::EXTERNAL_REFERENCE: | |
| 40 result->cert_ = der::Input(data, length); | |
| 41 break; | |
| 42 } | |
| 43 | |
| 44 if (!ParseCertificate(result->cert_, &result->tbs_certificate_tlv_, | |
| 45 &result->signature_algorithm_tlv_, | |
| 46 &result->signature_value_)) | |
| 47 return nullptr; | |
|
eroman
2016/05/12 18:12:29
nit: curly braces?
mattm
2016/05/13 02:17:36
Done.
| |
| 48 | |
| 49 if (!ParseTbsCertificate(result->tbs_certificate_tlv_, &result->parsed_tbs_)) | |
| 50 return nullptr; | |
| 51 | |
| 52 // Attempt to parse the signature algorithm contained in the Certificate. | |
| 53 // Do not give up on failure here, since SignatureAlgorithm::CreateFromDer | |
| 54 // will fail on valid but unsupported signature algorithms. | |
|
eroman
2016/05/12 18:12:29
What current consumer is this allowance made for?
mattm
2016/05/13 02:17:36
There are several in tests (PKITS and ours), they
| |
| 55 // TODO(mattm): should distinguish between unsupported algorithms and parsing | |
| 56 // errors. | |
| 57 result->signature_algorithm_ = | |
| 58 SignatureAlgorithm::CreateFromDer(result->signature_algorithm_tlv_); | |
| 59 | |
| 60 der::Input subject_value; | |
| 61 if (!GetSequenceValue(result->parsed_tbs_.subject_tlv, &subject_value) || | |
| 62 !NormalizeName(subject_value, &result->normalized_subject_)) | |
| 63 return nullptr; | |
| 64 der::Input issuer_value; | |
| 65 if (!GetSequenceValue(result->parsed_tbs_.issuer_tlv, &issuer_value) || | |
| 66 !NormalizeName(issuer_value, &result->normalized_issuer_)) | |
| 67 return nullptr; | |
|
eroman
2016/05/12 18:12:29
Same question throughout -- if we consider these m
mattm
2016/05/13 02:17:36
yeah, I always forget that. done.
| |
| 68 | |
| 69 // Parse the standard X.509 extensions and remove them from | |
| 70 // |unconsumed_extensions|. | |
| 71 if (result->parsed_tbs_.has_extensions) { | |
| 72 // ParseExtensions() ensures there are no duplicates, and maps the (unique) | |
| 73 // OID to the extension value. | |
| 74 if (!ParseExtensions(result->parsed_tbs_.extensions_tlv, | |
| 75 &result->unconsumed_extensions_)) | |
| 76 return nullptr; | |
| 77 | |
| 78 ParsedExtension extension; | |
| 79 | |
| 80 // Basic constraints. | |
| 81 if (ConsumeExtension(BasicConstraintsOid(), &result->unconsumed_extensions_, | |
| 82 &extension)) { | |
| 83 result->has_basic_constraints_ = true; | |
| 84 if (!ParseBasicConstraints(extension.value, &result->basic_constraints_)) | |
| 85 return nullptr; | |
| 86 } | |
| 87 | |
| 88 // KeyUsage. | |
| 89 if (ConsumeExtension(KeyUsageOid(), &result->unconsumed_extensions_, | |
| 90 &extension)) { | |
| 91 result->has_key_usage_ = true; | |
| 92 if (!ParseKeyUsage(extension.value, &result->key_usage_)) | |
| 93 return nullptr; | |
| 94 } | |
| 95 | |
| 96 // Subject alternative name. | |
| 97 if (ConsumeExtension(SubjectAltNameOid(), &result->unconsumed_extensions_, | |
| 98 &result->subject_alt_names_extension_)) { | |
| 99 // RFC 5280 section 4.2.1.6: | |
| 100 // SubjectAltName ::= GeneralNames | |
| 101 result->subject_alt_names_ = GeneralNames::CreateFromDer( | |
| 102 result->subject_alt_names_extension_.value); | |
| 103 if (!result->subject_alt_names_) | |
| 104 return nullptr; | |
| 105 // RFC 5280 section 4.1.2.6: | |
| 106 // If subject naming information is present only in the subjectAltName | |
| 107 // extension (e.g., a key bound only to an email address or URI), then the | |
| 108 // subject name MUST be an empty sequence and the subjectAltName extension | |
| 109 // MUST be critical. | |
| 110 if (subject_value.Length() == 0 && | |
| 111 !result->subject_alt_names_extension_.critical) | |
| 112 return nullptr; | |
| 113 } | |
| 114 | |
| 115 // Name constraints. | |
| 116 if (ConsumeExtension(NameConstraintsOid(), &result->unconsumed_extensions_, | |
| 117 &extension)) { | |
| 118 result->name_constraints_ = | |
| 119 NameConstraints::CreateFromDer(extension.value, extension.critical); | |
| 120 if (!result->name_constraints_) | |
| 121 return nullptr; | |
| 122 } | |
| 123 } | |
| 124 | |
| 125 return result; | |
| 126 } | |
| 127 | |
| 128 scoped_refptr<ParsedCertificate> ParsedCertificate::CreateFromCertificateCopy( | |
| 129 const base::StringPiece& data) { | |
| 130 return ParsedCertificate::CreateFromCertificateData( | |
| 131 reinterpret_cast<const uint8_t*>(data.data()), data.size(), | |
| 132 DataSource::INTERNAL_COPY); | |
| 133 } | |
| 134 | |
| 135 } // namespace net | |
| OLD | NEW |