Mirror of BoringSSL (grpc依赖)
https://boringssl.googlesource.com/boringssl
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
295 lines
11 KiB
295 lines
11 KiB
// Copyright 2016 The Chromium Authors |
|
// Use of this source code is governed by a BSD-style license that can be |
|
// found in the LICENSE file. |
|
|
|
#include "parsed_certificate.h" |
|
|
|
#include "cert_errors.h" |
|
#include "certificate_policies.h" |
|
#include "extended_key_usage.h" |
|
#include "name_constraints.h" |
|
#include "signature_algorithm.h" |
|
#include "verify_name_match.h" |
|
#include "parser.h" |
|
#include <openssl/pool.h> |
|
|
|
namespace bssl { |
|
|
|
namespace { |
|
|
|
DEFINE_CERT_ERROR_ID(kFailedParsingCertificate, "Failed parsing Certificate"); |
|
DEFINE_CERT_ERROR_ID(kFailedParsingTbsCertificate, |
|
"Failed parsing TBSCertificate"); |
|
DEFINE_CERT_ERROR_ID(kFailedReadingIssuerOrSubject, |
|
"Failed reading issuer or subject"); |
|
DEFINE_CERT_ERROR_ID(kFailedNormalizingSubject, "Failed normalizing subject"); |
|
DEFINE_CERT_ERROR_ID(kFailedNormalizingIssuer, "Failed normalizing issuer"); |
|
DEFINE_CERT_ERROR_ID(kFailedParsingExtensions, "Failed parsing extensions"); |
|
DEFINE_CERT_ERROR_ID(kFailedParsingBasicConstraints, |
|
"Failed parsing basic constraints"); |
|
DEFINE_CERT_ERROR_ID(kFailedParsingKeyUsage, "Failed parsing key usage"); |
|
DEFINE_CERT_ERROR_ID(kFailedParsingEku, "Failed parsing extended key usage"); |
|
DEFINE_CERT_ERROR_ID(kFailedParsingSubjectAltName, |
|
"Failed parsing subjectAltName"); |
|
DEFINE_CERT_ERROR_ID(kSubjectAltNameNotCritical, |
|
"Empty subject and subjectAltName is not critical"); |
|
DEFINE_CERT_ERROR_ID(kFailedParsingNameConstraints, |
|
"Failed parsing name constraints"); |
|
DEFINE_CERT_ERROR_ID(kFailedParsingAia, "Failed parsing authority info access"); |
|
DEFINE_CERT_ERROR_ID(kFailedParsingPolicies, |
|
"Failed parsing certificate policies"); |
|
DEFINE_CERT_ERROR_ID(kFailedParsingPolicyConstraints, |
|
"Failed parsing policy constraints"); |
|
DEFINE_CERT_ERROR_ID(kFailedParsingPolicyMappings, |
|
"Failed parsing policy mappings"); |
|
DEFINE_CERT_ERROR_ID(kFailedParsingInhibitAnyPolicy, |
|
"Failed parsing inhibit any policy"); |
|
DEFINE_CERT_ERROR_ID(kFailedParsingAuthorityKeyIdentifier, |
|
"Failed parsing authority key identifier"); |
|
DEFINE_CERT_ERROR_ID(kFailedParsingSubjectKeyIdentifier, |
|
"Failed parsing subject key identifier"); |
|
|
|
[[nodiscard]] bool GetSequenceValue(const der::Input& tlv, der::Input* value) { |
|
der::Parser parser(tlv); |
|
return parser.ReadTag(der::kSequence, value) && !parser.HasMore(); |
|
} |
|
|
|
} // namespace |
|
|
|
bool ParsedCertificate::GetExtension(const der::Input& extension_oid, |
|
ParsedExtension* parsed_extension) const { |
|
if (!tbs_.extensions_tlv) |
|
return false; |
|
|
|
auto it = extensions_.find(extension_oid); |
|
if (it == extensions_.end()) { |
|
*parsed_extension = ParsedExtension(); |
|
return false; |
|
} |
|
|
|
*parsed_extension = it->second; |
|
return true; |
|
} |
|
|
|
ParsedCertificate::ParsedCertificate(PrivateConstructor) {} |
|
ParsedCertificate::~ParsedCertificate() = default; |
|
|
|
// static |
|
std::shared_ptr<const ParsedCertificate> ParsedCertificate::Create( |
|
bssl::UniquePtr<CRYPTO_BUFFER> backing_data, |
|
const ParseCertificateOptions& options, |
|
CertErrors* errors) { |
|
// |errors| is an optional parameter, but to keep the code simpler, use a |
|
// dummy object when one wasn't provided. |
|
CertErrors unused_errors; |
|
if (!errors) |
|
errors = &unused_errors; |
|
|
|
auto result = std::make_shared<ParsedCertificate>(PrivateConstructor{}); |
|
result->cert_data_ = std::move(backing_data); |
|
result->cert_ = der::Input(CRYPTO_BUFFER_data(result->cert_data_.get()), |
|
CRYPTO_BUFFER_len(result->cert_data_.get())); |
|
|
|
if (!ParseCertificate(result->cert_, &result->tbs_certificate_tlv_, |
|
&result->signature_algorithm_tlv_, |
|
&result->signature_value_, errors)) { |
|
errors->AddError(kFailedParsingCertificate); |
|
return nullptr; |
|
} |
|
|
|
if (!ParseTbsCertificate(result->tbs_certificate_tlv_, options, &result->tbs_, |
|
errors)) { |
|
errors->AddError(kFailedParsingTbsCertificate); |
|
return nullptr; |
|
} |
|
|
|
// Attempt to parse the signature algorithm contained in the Certificate. |
|
result->signature_algorithm_ = |
|
ParseSignatureAlgorithm(result->signature_algorithm_tlv_); |
|
|
|
der::Input subject_value; |
|
if (!GetSequenceValue(result->tbs_.subject_tlv, &subject_value)) { |
|
errors->AddError(kFailedReadingIssuerOrSubject); |
|
return nullptr; |
|
} |
|
if (!NormalizeName(subject_value, &result->normalized_subject_, errors)) { |
|
errors->AddError(kFailedNormalizingSubject); |
|
return nullptr; |
|
} |
|
der::Input issuer_value; |
|
if (!GetSequenceValue(result->tbs_.issuer_tlv, &issuer_value)) { |
|
errors->AddError(kFailedReadingIssuerOrSubject); |
|
return nullptr; |
|
} |
|
if (!NormalizeName(issuer_value, &result->normalized_issuer_, errors)) { |
|
errors->AddError(kFailedNormalizingIssuer); |
|
return nullptr; |
|
} |
|
|
|
// Parse the standard X.509 extensions. |
|
if (result->tbs_.extensions_tlv) { |
|
// ParseExtensions() ensures there are no duplicates, and maps the (unique) |
|
// OID to the extension value. |
|
if (!ParseExtensions(result->tbs_.extensions_tlv.value(), |
|
&result->extensions_)) { |
|
errors->AddError(kFailedParsingExtensions); |
|
return nullptr; |
|
} |
|
|
|
ParsedExtension extension; |
|
|
|
// Basic constraints. |
|
if (result->GetExtension(der::Input(kBasicConstraintsOid), &extension)) { |
|
result->has_basic_constraints_ = true; |
|
if (!ParseBasicConstraints(extension.value, |
|
&result->basic_constraints_)) { |
|
errors->AddError(kFailedParsingBasicConstraints); |
|
return nullptr; |
|
} |
|
} |
|
|
|
// Key Usage. |
|
if (result->GetExtension(der::Input(kKeyUsageOid), &extension)) { |
|
result->has_key_usage_ = true; |
|
if (!ParseKeyUsage(extension.value, &result->key_usage_)) { |
|
errors->AddError(kFailedParsingKeyUsage); |
|
return nullptr; |
|
} |
|
} |
|
|
|
// Extended Key Usage. |
|
if (result->GetExtension(der::Input(kExtKeyUsageOid), &extension)) { |
|
result->has_extended_key_usage_ = true; |
|
if (!ParseEKUExtension(extension.value, &result->extended_key_usage_)) { |
|
errors->AddError(kFailedParsingEku); |
|
return nullptr; |
|
} |
|
} |
|
|
|
// Subject alternative name. |
|
if (result->GetExtension(der::Input(kSubjectAltNameOid), |
|
&result->subject_alt_names_extension_)) { |
|
// RFC 5280 section 4.2.1.6: |
|
// SubjectAltName ::= GeneralNames |
|
result->subject_alt_names_ = GeneralNames::Create( |
|
result->subject_alt_names_extension_.value, errors); |
|
if (!result->subject_alt_names_) { |
|
errors->AddError(kFailedParsingSubjectAltName); |
|
return nullptr; |
|
} |
|
// RFC 5280 section 4.1.2.6: |
|
// If subject naming information is present only in the subjectAltName |
|
// extension (e.g., a key bound only to an email address or URI), then the |
|
// subject name MUST be an empty sequence and the subjectAltName extension |
|
// MUST be critical. |
|
if (subject_value.Length() == 0 && |
|
!result->subject_alt_names_extension_.critical) { |
|
errors->AddError(kSubjectAltNameNotCritical); |
|
return nullptr; |
|
} |
|
} |
|
|
|
// Name constraints. |
|
if (result->GetExtension(der::Input(kNameConstraintsOid), &extension)) { |
|
result->name_constraints_ = |
|
NameConstraints::Create(extension.value, extension.critical, errors); |
|
if (!result->name_constraints_) { |
|
errors->AddError(kFailedParsingNameConstraints); |
|
return nullptr; |
|
} |
|
} |
|
|
|
// Authority information access. |
|
if (result->GetExtension(der::Input(kAuthorityInfoAccessOid), |
|
&result->authority_info_access_extension_)) { |
|
result->has_authority_info_access_ = true; |
|
if (!ParseAuthorityInfoAccessURIs( |
|
result->authority_info_access_extension_.value, |
|
&result->ca_issuers_uris_, &result->ocsp_uris_)) { |
|
errors->AddError(kFailedParsingAia); |
|
return nullptr; |
|
} |
|
} |
|
|
|
// Policies. |
|
if (result->GetExtension(der::Input(kCertificatePoliciesOid), &extension)) { |
|
result->has_policy_oids_ = true; |
|
if (!ParseCertificatePoliciesExtensionOids( |
|
extension.value, false /*fail_parsing_unknown_qualifier_oids*/, |
|
&result->policy_oids_, errors)) { |
|
errors->AddError(kFailedParsingPolicies); |
|
return nullptr; |
|
} |
|
} |
|
|
|
// Policy constraints. |
|
if (result->GetExtension(der::Input(kPolicyConstraintsOid), &extension)) { |
|
result->has_policy_constraints_ = true; |
|
if (!ParsePolicyConstraints(extension.value, |
|
&result->policy_constraints_)) { |
|
errors->AddError(kFailedParsingPolicyConstraints); |
|
return nullptr; |
|
} |
|
} |
|
|
|
// Policy mappings. |
|
if (result->GetExtension(der::Input(kPolicyMappingsOid), &extension)) { |
|
result->has_policy_mappings_ = true; |
|
if (!ParsePolicyMappings(extension.value, &result->policy_mappings_)) { |
|
errors->AddError(kFailedParsingPolicyMappings); |
|
return nullptr; |
|
} |
|
} |
|
|
|
// Inhibit Any Policy. |
|
if (result->GetExtension(der::Input(kInhibitAnyPolicyOid), &extension)) { |
|
result->has_inhibit_any_policy_ = true; |
|
if (!ParseInhibitAnyPolicy(extension.value, |
|
&result->inhibit_any_policy_)) { |
|
errors->AddError(kFailedParsingInhibitAnyPolicy); |
|
return nullptr; |
|
} |
|
} |
|
|
|
// Subject Key Identifier. |
|
if (result->GetExtension(der::Input(kSubjectKeyIdentifierOid), |
|
&extension)) { |
|
result->subject_key_identifier_ = std::make_optional<der::Input>(); |
|
if (!ParseSubjectKeyIdentifier( |
|
extension.value, &result->subject_key_identifier_.value())) { |
|
errors->AddError(kFailedParsingSubjectKeyIdentifier); |
|
return nullptr; |
|
} |
|
} |
|
|
|
// Authority Key Identifier. |
|
if (result->GetExtension(der::Input(kAuthorityKeyIdentifierOid), |
|
&extension)) { |
|
result->authority_key_identifier_ = |
|
std::make_optional<ParsedAuthorityKeyIdentifier>(); |
|
if (!ParseAuthorityKeyIdentifier( |
|
extension.value, &result->authority_key_identifier_.value())) { |
|
errors->AddError(kFailedParsingAuthorityKeyIdentifier); |
|
return nullptr; |
|
} |
|
} |
|
} |
|
|
|
return result; |
|
} |
|
|
|
// static |
|
bool ParsedCertificate::CreateAndAddToVector( |
|
bssl::UniquePtr<CRYPTO_BUFFER> cert_data, |
|
const ParseCertificateOptions& options, |
|
std::vector<std::shared_ptr<const bssl::ParsedCertificate>>* chain, |
|
CertErrors* errors) { |
|
std::shared_ptr<const ParsedCertificate> cert( |
|
Create(std::move(cert_data), options, errors)); |
|
if (!cert) |
|
return false; |
|
chain->push_back(std::move(cert)); |
|
return true; |
|
} |
|
|
|
} // namespace net
|
|
|