/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_ |