Coverage Report

Created: 2026-10-19 07:10

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/boringssl/pki/trust_store.h
Line
Count
Source
1
// Copyright 2016 The Chromium Authors
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
// you may not use this file except in compliance with the License.
5
// You may obtain a copy of the License at
6
//
7
//     https://www.apache.org/licenses/LICENSE-2.0
8
//
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14
15
#ifndef BSSL_PKI_TRUST_STORE_H_
16
#define BSSL_PKI_TRUST_STORE_H_
17
18
#include <array>
19
#include <memory>
20
#include <optional>
21
22
#include <openssl/base.h>
23
#include <openssl/pool.h>
24
#include <openssl/sha2.h>
25
26
#include "cert_issuer_source.h"
27
#include "merkle_tree.h"
28
#include "parsed_certificate.h"
29
#include "signature_algorithm.h"
30
31
BSSL_NAMESPACE_BEGIN
32
33
enum class CertificateTrustType {
34
  // This certificate is explicitly blocked (distrusted).
35
  DISTRUSTED,
36
37
  // The trustedness of this certificate is unknown (inherits trust from
38
  // its issuer).
39
  UNSPECIFIED,
40
41
  // This certificate is a trust anchor (as defined by RFC 5280).
42
  TRUSTED_ANCHOR,
43
44
  // This certificate can be used as a trust anchor (as defined by RFC 5280) or
45
  // a trusted leaf, depending on context.
46
  TRUSTED_ANCHOR_OR_LEAF,
47
48
  // This certificate is a directly trusted leaf.
49
  TRUSTED_LEAF,
50
51
  LAST = TRUSTED_ANCHOR
52
};
53
54
struct OPENSSL_EXPORT TrustedSubtree {
55
  Subtree range;
56
  std::array<uint8_t, SHA256_DIGEST_LENGTH> hash;
57
};
58
59
struct OPENSSL_EXPORT LogTrustedSubtrees {
60
  uint16_t log_number;
61
  std::vector<TrustedSubtree> trusted_subtrees;
62
};
63
64
// Describes the level of trust in a certificate.
65
struct OPENSSL_EXPORT CertificateTrust {
66
0
  static constexpr CertificateTrust ForTrustAnchor() {
67
0
    CertificateTrust result;
68
0
    result.type = CertificateTrustType::TRUSTED_ANCHOR;
69
0
    return result;
70
0
  }
71
72
0
  static constexpr CertificateTrust ForTrustAnchorOrLeaf() {
73
0
    CertificateTrust result;
74
0
    result.type = CertificateTrustType::TRUSTED_ANCHOR_OR_LEAF;
75
0
    return result;
76
0
  }
77
78
0
  static constexpr CertificateTrust ForTrustedLeaf() {
79
0
    CertificateTrust result;
80
0
    result.type = CertificateTrustType::TRUSTED_LEAF;
81
0
    return result;
82
0
  }
83
84
0
  static constexpr CertificateTrust ForUnspecified() {
85
0
    CertificateTrust result;
86
0
    return result;
87
0
  }
88
89
0
  static constexpr CertificateTrust ForDistrusted() {
90
0
    CertificateTrust result;
91
0
    result.type = CertificateTrustType::DISTRUSTED;
92
0
    return result;
93
0
  }
94
95
0
  constexpr CertificateTrust WithEnforceAnchorExpiry(bool value = true) const {
96
0
    CertificateTrust result = *this;
97
0
    result.enforce_anchor_expiry = value;
98
0
    return result;
99
0
  }
100
101
  constexpr CertificateTrust WithEnforceAnchorConstraints(
102
0
      bool value = true) const {
103
0
    CertificateTrust result = *this;
104
0
    result.enforce_anchor_constraints = value;
105
0
    return result;
106
0
  }
107
108
  constexpr CertificateTrust WithRequireAnchorBasicConstraints(
109
0
      bool value = true) const {
110
0
    CertificateTrust result = *this;
111
0
    result.require_anchor_basic_constraints = value;
112
0
    return result;
113
0
  }
114
115
  constexpr CertificateTrust WithRequireLeafSelfSigned(
116
0
      bool value = true) const {
117
0
    CertificateTrust result = *this;
118
0
    result.require_leaf_selfsigned = value;
119
0
    return result;
120
0
  }
121
122
  bool IsTrustAnchor() const;
123
  bool IsTrustLeaf() const;
124
  bool IsDistrusted() const;
125
  bool HasUnspecifiedTrust() const;
126
127
  std::string ToDebugString() const;
128
129
  static std::optional<CertificateTrust> FromDebugString(
130
      const std::string &trust_string);
131
132
  // The overall type of trust.
133
  CertificateTrustType type = CertificateTrustType::UNSPECIFIED;
134
135
  // Optionally, enforce extra bits on trust anchors. If these are false, the
136
  // only fields in a trust anchor certificate that are meaningful are its
137
  // name and SPKI.
138
  bool enforce_anchor_expiry = false;
139
  bool enforce_anchor_constraints = false;
140
  // Require that X.509v3 trust anchors have a basicConstraints extension.
141
  // X.509v1 and X.509v2 trust anchors do not support basicConstraints and are
142
  // not affected.
143
  // Additionally, this setting only has effect if `enforce_anchor_constraints`
144
  // is true, which also requires that the extension assert CA=true.
145
  bool require_anchor_basic_constraints = false;
146
147
  // Optionally, require trusted leafs to be self-signed to be trusted.
148
  bool require_leaf_selfsigned = false;
149
};
150
151
class OPENSSL_EXPORT MTCAnchor {
152
 public:
153
  enum MtcSpecVersion {
154
    // draft-ietf-plants-merkle-tree-certs-04
155
    kPlants04,
156
157
    // draft-ietf-plants-merkle-tree-certs-07
158
    kPlants07
159
  };
160
161
  class Token {
162
   private:
163
    explicit Token() = default;
164
    friend MTCAnchor;
165
  };
166
167
  // Create an MTCAnchor with spec version kPlants04 for a trusted CA with
168
  // `ca_id` containing the DER encoding of the relative OID of the CA's ID.
169
  // `ca_signature_algorithm` and `ca_key` configure the CA cosigner key.
170
  // `ca_key` should be a DER-encoded SubjectPublicKeyInfo.
171
  // The `log_trusted_subtrees` must be sorted by log number, and each
172
  // `trusted_subtrees` within must be sorted by their subtree ranges.
173
  MTCAnchor(Span<const uint8_t> ca_id,
174
            SignatureAlgorithm ca_signature_algorithm,
175
            UniquePtr<CRYPTO_BUFFER> ca_key,
176
            std::vector<LogTrustedSubtrees> log_trusted_subtrees);
177
178
  // Create an MTCAnchor with spec version kPlants07 for a trusted CA with
179
  // `ca_id` containing the DER encoding of the relative OID of the CA's ID.
180
  // `ca_signature_algorithm` and `ca_key` configure the CA cosigner key.
181
  // `ca_key` should be a DER-encoded SubjectPublicKeyInfo.
182
  // The `log_trusted_subtrees` must be sorted by log number, and each
183
  // `trusted_subtrees` within must be sorted by their subtree ranges.
184
  // Returns nullptr on error.
185
  static std::shared_ptr<const MTCAnchor> CreatePlants07(
186
      Span<const uint8_t> ca_id, SignatureAlgorithm ca_signature_algorithm,
187
      UniquePtr<CRYPTO_BUFFER> ca_key,
188
      std::vector<LogTrustedSubtrees> log_trusted_subtrees);
189
190
  // This constructor is conceptually private, but needs to be public for
191
  // make_shared to work. Uses the "passkey idiom" to prevent callers outside
192
  // of the class from calling it.
193
  // Outside callers should use the Create* static method(s).
194
  MTCAnchor(Token, MtcSpecVersion spec_version, Span<const uint8_t> ca_id,
195
            SignatureAlgorithm ca_signature_algorithm,
196
            UniquePtr<CRYPTO_BUFFER> ca_key,
197
            std::vector<LogTrustedSubtrees> log_trusted_subtrees);
198
199
  // Returns whether this MTCAnchor represents a valid anchor. This function
200
  // exists because the c'tor inputs could be invalid.
201
  // TODO(mattm): remove public constructor and remove or private the IsValid
202
  // method.
203
  bool IsValid() const;
204
205
0
  MtcSpecVersion spec_version() const { return spec_version_; }
206
0
  Span<const uint8_t> ca_id() const { return ca_id_; }
207
0
  SignatureAlgorithm ca_signature_algorithm() const {
208
0
    return ca_signature_algorithm_;
209
0
  }
210
0
  const CRYPTO_BUFFER *ca_key() const { return ca_key_.get(); }
211
  // TODO(nharper): Move this function to TrustAnchor.
212
  der::Input NormalizedSubject() const;
213
  // TODO(nharper): Remove this function in favor of TrustAnchor's version.
214
  CertificateTrust CertTrust() const;
215
  // TODO(nharper): Move this function to TrustAnchor.
216
  std::shared_ptr<const ParsedCertificate> AsCert() const;
217
218
  std::optional<TreeHashConstSpan> SubtreeHash(uint16_t log_number,
219
                                               Subtree target_range) const;
220
  std::string TrustedSubtreesDebugString() const;
221
222
 private:
223
  void CreateSyntheticCert(Span<const uint8_t> ca_id);
224
225
  MtcSpecVersion spec_version_;
226
  std::vector<uint8_t> ca_id_;
227
  SignatureAlgorithm ca_signature_algorithm_;
228
  UniquePtr<CRYPTO_BUFFER> ca_key_;
229
  std::shared_ptr<const ParsedCertificate> synthetic_cert_;
230
  std::vector<LogTrustedSubtrees> trusted_subtrees_;
231
};
232
233
// A TrustAnchor contains information about how a trust anchor is trusted and
234
// what is trusted. It should be used in place of a (ParsedCertificate,
235
// CertificateTrust) tuple as some trust information, e.g. MTC anchors, is not
236
// representable by such a tuple.
237
//
238
// TODO(nharper): This class is the first step of a large refactor to stop
239
// representing TrustAnchors as ParsedCertificates. Prior to the introduction of
240
// Merkle Tree Certs, the information about a trust anchor was split between
241
// a ParsedCertificate (containing the anchor's Subject name and public key) and
242
// a CertificateTrust struct (informing when/how the trust anchor is trusted, as
243
// well as whether any additional constraints should be applied). With the
244
// introduction of Merkle Tree Certs, some of this information about how to use
245
// an MTC trust anchor fits in neither place. The eventual goal is that the
246
// TrustAnchor class is the single place that contains all information about a
247
// trust anchor, rather than that information being split across multiple
248
// objects. This will allow a further goal of removing the dependency of
249
// requiring that a trust anchor be representable as a ParsedCertificate: MTC
250
// trust anchors only have a ParsedCertificate accessor for compatibility
251
// reasons, and while draft-ietf-lamps-x509-alg-none improves the efficiency of
252
// storing trust anchors in X.509 certs, this refactor will allow further
253
// improvements for classical (non-MTC) roots.
254
//
255
// See also internal design doc:
256
// https://docs.google.com/document/d/1wqHAmZqtF8oJzNObFBm41lzDt2JWRhjM32A3z6ampJE/edit
257
class OPENSSL_EXPORT TrustAnchor {
258
 public:
259
  // Creates a default TrustAnchor with an unspecified CertificateTrust.
260
  TrustAnchor() = default;
261
262
  // Creates a TrustAnchor with no associated MTCAnchor.
263
0
  explicit TrustAnchor(CertificateTrust trust) : TrustAnchor(trust, nullptr) {}
264
  TrustAnchor(CertificateTrust trust,
265
              std::shared_ptr<const MTCAnchor> mtc_anchor)
266
0
      : trust_(trust), mtc_anchor_(std::move(mtc_anchor)) {}
267
268
  // TODO(nharper): Temporarily add ParsedCertificate member and accessor.
269
270
  // TODO(nharper): Add accessors to get information about the trust anchor that
271
  // is currently found in the ParsedCertificate:
272
  // - `der::Input NormalizedSubject() const;`
273
  // - `UniquePtr<EVP_PKEY> PublicKey() const;`
274
275
  // Modifies the CertificateTrust for this TrustAnchor. Should only be called
276
  // by path_builder.cc.
277
  //
278
  // TODO(nharper): Remove this function as part of the larger TrustAnchor
279
  // refactor.
280
  void OverrideCertTrust(CertificateTrust new_trust);
281
  CertificateTrust CertTrust() const;
282
  std::shared_ptr<const bssl::MTCAnchor> MTCAnchor() const;
283
284
 private:
285
  CertificateTrust trust_;
286
  std::shared_ptr<const bssl::MTCAnchor> mtc_anchor_ = nullptr;
287
};
288
289
// Interface for finding intermediates / trust anchors, and testing the
290
// trustedness of certificates.
291
class OPENSSL_EXPORT TrustStore : public CertIssuerSource {
292
 public:
293
  TrustStore() = default;
294
295
  TrustStore(const TrustStore &) = delete;
296
  TrustStore &operator=(const TrustStore &) = delete;
297
298
  // Returns the trusted of `cert`, which must be non-null.
299
  virtual CertificateTrust GetTrust(const ParsedCertificate *cert) = 0;
300
301
  // Returns the TrustAnchor that issued `cert`, if one exists.
302
  //
303
  // TODO(nharper): Make this a pure virtual function once all TrustStore
304
  // implementations have implemented this.
305
  virtual std::shared_ptr<const MTCAnchor> GetTrustedMTCIssuerOf(
306
      const ParsedCertificate *cert);
307
308
  // Disable async issuers for TrustStore, as it isn't needed.
309
  void AsyncGetIssuersOf(const ParsedCertificate *cert,
310
                         std::unique_ptr<Request> *out_req) final;
311
};
312
313
BSSL_NAMESPACE_END
314
315
#endif  // BSSL_PKI_TRUST_STORE_H_