1 /* Copyright (c) 2023, Google Inc.
2 *
3 * Permission to use, copy, modify, and/or distribute this software for any
4 * purpose with or without fee is hereby granted, provided that the above
5 * copyright notice and this permission notice appear in all copies.
6 *
7 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
10 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
12 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
13 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
14
15 #include <optional>
16 #include <string_view>
17
18 #include <openssl/pki/certificate.h>
19 #include <openssl/pool.h>
20
21 #include "cert_errors.h"
22 #include "encode_values.h"
23 #include "parsed_certificate.h"
24 #include "pem.h"
25 #include "parse_values.h"
26
27 namespace bssl {
28
29 namespace {
30
ParseCertificateFromDer(bssl::Span<const uint8_t> cert,std::string * out_diagnostic)31 std::shared_ptr<const bssl::ParsedCertificate> ParseCertificateFromDer(
32 bssl::Span<const uint8_t>cert, std::string *out_diagnostic) {
33 bssl::ParseCertificateOptions default_options{};
34 // We follow Chromium in setting |allow_invalid_serial_numbers| in order to
35 // not choke on 21-byte serial numbers, which are common. davidben explains
36 // why:
37 //
38 // The reason for the discrepancy is that unsigned numbers with the high bit
39 // otherwise set get an extra 0 byte in front to keep them positive. So if you
40 // do:
41 // var num [20]byte
42 // fillWithRandom(num[:])
43 // serialNumber := new(big.Int).SetBytes(num[:])
44 // encodeASN1Integer(serialNumber)
45 //
46 // Then half of your serial numbers will be encoded with 21 bytes. (And
47 // 1/512th will have 19 bytes instead of 20.)
48 default_options.allow_invalid_serial_numbers = true;
49
50 bssl::UniquePtr<CRYPTO_BUFFER> buffer(
51 CRYPTO_BUFFER_new(cert.data(), cert.size(), nullptr));
52 bssl::CertErrors errors;
53 std::shared_ptr<const bssl::ParsedCertificate> parsed_cert(
54 bssl::ParsedCertificate::Create(std::move(buffer), default_options, &errors));
55 if (!parsed_cert) {
56 *out_diagnostic = errors.ToDebugString();
57 return nullptr;
58 }
59 return parsed_cert;
60 }
61
62 } // namespace
63
64 struct CertificateInternals {
65 std::shared_ptr<const bssl::ParsedCertificate> cert;
66 };
67
Certificate(std::unique_ptr<CertificateInternals> internals)68 Certificate::Certificate(std::unique_ptr<CertificateInternals> internals)
69 : internals_(std::move(internals)) {}
70 Certificate::~Certificate() = default;
71 Certificate::Certificate(Certificate&& other) = default;
72
FromDER(bssl::Span<const uint8_t> der,std::string * out_diagnostic)73 std::unique_ptr<Certificate> Certificate::FromDER(bssl::Span<const uint8_t> der,
74 std::string *out_diagnostic) {
75 std::shared_ptr<const bssl::ParsedCertificate> result =
76 ParseCertificateFromDer(der, out_diagnostic);
77 if (result == nullptr) {
78 return nullptr;
79 }
80
81 auto internals = std::make_unique<CertificateInternals>();
82 internals->cert = std::move(result);
83 std::unique_ptr<Certificate> ret(new Certificate(std::move(internals)));
84 return ret;
85 }
86
FromPEM(std::string_view pem,std::string * out_diagnostic)87 std::unique_ptr<Certificate> Certificate::FromPEM(std::string_view pem,
88 std::string *out_diagnostic) {
89 bssl::PEMTokenizer tokenizer(pem, {"CERTIFICATE"});
90 if (!tokenizer.GetNext()) {
91 return nullptr;
92 }
93 return FromDER(StringAsBytes(tokenizer.data()), out_diagnostic);
94 }
95
IsSelfIssued() const96 bool Certificate::IsSelfIssued() const {
97 return internals_->cert->normalized_subject() ==
98 internals_->cert->normalized_issuer();
99 }
100
GetValidity() const101 Certificate::Validity Certificate::GetValidity() const {
102 Certificate::Validity validity;
103
104 // As this is a previously parsed certificate, we know the not_before
105 // and not after are valid, so these conversions can not fail.
106 (void) GeneralizedTimeToPosixTime(
107 internals_->cert->tbs().validity_not_before, &validity.not_before);
108 (void) GeneralizedTimeToPosixTime(
109 internals_->cert->tbs().validity_not_after, &validity.not_after);
110 return validity;
111 }
112
GetSerialNumber() const113 bssl::Span<const uint8_t> Certificate::GetSerialNumber() const {
114 return internals_->cert->tbs().serial_number;
115 }
116
117 } // namespace boringssl
118