| // Copyright 2023 The BoringSSL Authors | |
| // | |
| // Licensed under the Apache License, Version 2.0 (the "License"); | |
| // you may not use this file except in compliance with the License. | |
| // You may obtain a copy of the License at | |
| // | |
| // https://www.apache.org/licenses/LICENSE-2.0 | |
| // | |
| // Unless required by applicable law or agreed to in writing, software | |
| // distributed under the License is distributed on an "AS IS" BASIS, | |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| // See the License for the specific language governing permissions and | |
| // limitations under the License. | |
| #include <optional> | |
| #include <string_view> | |
| #include <openssl/pki/certificate.h> | |
| #include <openssl/pool.h> | |
| #include "cert_errors.h" | |
| #include "encode_values.h" | |
| #include "parsed_certificate.h" | |
| #include "pem.h" | |
| #include "parse_values.h" | |
| BSSL_NAMESPACE_BEGIN | |
| namespace { | |
| std::shared_ptr<const bssl::ParsedCertificate> ParseCertificateFromDer( | |
| bssl::Span<const uint8_t>cert, std::string *out_diagnostic) { | |
| bssl::ParseCertificateOptions default_options{}; | |
| // TODO(crbug.com/533048005): Remove this option. It now only controls serials | |
| // that aren't even valid integers. Historically, people needed to set it to | |
| // tolerate length over 20, but this is now always enabled. | |
| default_options.allow_invalid_serial_numbers = true; | |
| bssl::UniquePtr<CRYPTO_BUFFER> buffer( | |
| CRYPTO_BUFFER_new(cert.data(), cert.size(), nullptr)); | |
| bssl::CertErrors errors; | |
| std::shared_ptr<const bssl::ParsedCertificate> parsed_cert( | |
| bssl::ParsedCertificate::Create(std::move(buffer), default_options, &errors)); | |
| if (!parsed_cert) { | |
| *out_diagnostic = errors.ToDebugString(); | |
| return nullptr; | |
| } | |
| return parsed_cert; | |
| } | |
| } // namespace | |
| struct CertificateInternals { | |
| std::shared_ptr<const bssl::ParsedCertificate> cert; | |
| }; | |
| Certificate::Certificate(std::unique_ptr<CertificateInternals> internals) | |
| : internals_(std::move(internals)) {} | |
| Certificate::~Certificate() = default; | |
| Certificate::Certificate(Certificate&& other) = default; | |
| std::unique_ptr<Certificate> Certificate::FromDER(bssl::Span<const uint8_t> der, | |
| std::string *out_diagnostic) { | |
| std::shared_ptr<const bssl::ParsedCertificate> result = | |
| ParseCertificateFromDer(der, out_diagnostic); | |
| if (result == nullptr) { | |
| return nullptr; | |
| } | |
| auto internals = std::make_unique<CertificateInternals>(); | |
| internals->cert = std::move(result); | |
| std::unique_ptr<Certificate> ret(new Certificate(std::move(internals))); | |
| return ret; | |
| } | |
| std::unique_ptr<Certificate> Certificate::FromPEM(std::string_view pem, | |
| std::string *out_diagnostic) { | |
| bssl::PEMTokenizer tokenizer(pem, {"CERTIFICATE"}); | |
| if (!tokenizer.GetNext()) { | |
| return nullptr; | |
| } | |
| return FromDER(StringAsBytes(tokenizer.data()), out_diagnostic); | |
| } | |
| bool Certificate::IsSelfIssued() const { | |
| return internals_->cert->normalized_subject() == | |
| internals_->cert->normalized_issuer(); | |
| } | |
| Certificate::Validity Certificate::GetValidity() const { | |
| Certificate::Validity validity; | |
| // As this is a previously parsed certificate, we know the not_before | |
| // and not after are valid, so these conversions can not fail. | |
| (void) GeneralizedTimeToPosixTime( | |
| internals_->cert->tbs().validity_not_before, &validity.not_before); | |
| (void) GeneralizedTimeToPosixTime( | |
| internals_->cert->tbs().validity_not_after, &validity.not_after); | |
| return validity; | |
| } | |
| bssl::Span<const uint8_t> Certificate::GetSerialNumber() const { | |
| return internals_->cert->tbs().serial_number; | |
| } | |
| BSSL_NAMESPACE_END |