xref: /aosp_15_r20/external/cronet/third_party/boringssl/src/pki/certificate.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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