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_PATH_BUILDER_H_ 16 #define BSSL_PKI_PATH_BUILDER_H_ 17 18 #include <memory> 19 #include <vector> 20 21 #include <openssl/base.h> 22 #include <openssl/pki/verify_error.h> 23 24 #include "cert_errors.h" 25 #include "input.h" 26 #include "parse_values.h" 27 #include "parsed_certificate.h" 28 #include "trust_store.h" 29 #include "verify_certificate_chain.h" 30 31 BSSL_NAMESPACE_BEGIN 32 33 namespace der { 34 struct GeneralizedTime; 35 } 36 37 class CertPathBuilder; 38 class CertPathIter; 39 class CertIssuerSource; 40 41 // Base class for custom data that CertPathBuilderDelegate can attach to paths. 42 class OPENSSL_EXPORT CertPathBuilderDelegateData { 43 public: 44 virtual ~CertPathBuilderDelegateData() = default; 45 }; 46 47 // Represents a single candidate path that was built or is being processed. 48 // 49 // This is used both to represent valid paths, as well as invalid/partial ones. 50 // 51 // Consumers must use |IsValid()| to test whether the 52 // CertPathBuilderResultPath is the result of a successful certificate 53 // verification. 54 struct OPENSSL_EXPORT CertPathBuilderResultPath { 55 CertPathBuilderResultPath(); 56 ~CertPathBuilderResultPath(); 57 58 // Returns true if the candidate path is valid. A "valid" path is one which 59 // chains to a trusted root, and did not have any high severity errors added 60 // to it during certificate verification. 61 bool IsValid() const; 62 63 // Public verify error result for this candidate path. 64 VerifyError GetVerifyError() const; 65 66 // Returns the chain's root certificate or nullptr if the chain doesn't 67 // chain to a trust anchor. 68 const ParsedCertificate *GetTrustedCert() const; 69 70 // Path in the forward direction: 71 // 72 // certs[0] is the target certificate 73 // certs[i] was issued by certs[i+1] 74 // certs.back() is the root certificate (which may or may not be trusted). 75 ParsedCertificateList certs; 76 77 // Describes the trustedness of the final certificate in the chain, 78 // |certs.back()| 79 // 80 // For result paths where |IsValid()|, the final certificate is trusted. 81 // However for failed or partially constructed paths the final certificate may 82 // not be a trust anchor. 83 CertificateTrust last_cert_trust; 84 85 // The set of policies that the certificate is valid for (of the 86 // subset of policies user requested during verification). 87 std::set<der::Input> user_constrained_policy_set; 88 89 // Slot for per-path data that may set by CertPathBuilderDelegate. The 90 // specific type is chosen by the delegate. Can be nullptr when unused. 91 std::unique_ptr<CertPathBuilderDelegateData> delegate_data; 92 93 // The set of errors and warnings associated with this path (bucketed 94 // per-certificate). Note that consumers should always use |IsValid()| to 95 // determine validity of the CertPathBuilderResultPath, and not just inspect 96 // |errors|. 97 CertPathErrors errors; 98 }; 99 100 // CertPathBuilderDelegate controls policies for certificate verification and 101 // path building. 102 class OPENSSL_EXPORT CertPathBuilderDelegate 103 : public VerifyCertificateChainDelegate { 104 public: 105 // This is called during path building on candidate paths. These are either 106 // paths which have already been run through RFC 5280 verification, or 107 // partial paths that the path builder cannot continue either due to not 108 // finding a matching issuer or reaching a configured pathbuilding limit. 109 // |path| may already have errors and warnings set on it. Delegates can 110 // "reject" a candidate path from path building by adding high severity 111 // errors. 112 virtual void CheckPathAfterVerification(const CertPathBuilder &path_builder, 113 CertPathBuilderResultPath *path) = 0; 114 115 // This is called during path building in between attempts to build candidate 116 // paths. Delegates can cause path building to stop and return indicating 117 // the deadline was exceeded by returning true from this function. 118 virtual bool IsDeadlineExpired() = 0; 119 120 // This is called during path building to decide if debug logs will be 121 // sent to the delegate rom the path builder. No calls to DebugLog (below) 122 // will be made unless this returns true. 123 virtual bool IsDebugLogEnabled() = 0; 124 125 // This is called to send a debug log string |msg| to the delegate. These are 126 // only called if IsDebugLogEnabled (above) returns true. 127 virtual void DebugLog(std::string_view msg) = 0; 128 }; 129 130 // Checks whether a certificate is trusted by building candidate paths to trust 131 // anchors and verifying those paths according to RFC 5280. Each instance of 132 // CertPathBuilder is used for a single verification. 133 // 134 // WARNING: This implementation is currently experimental. Consult an OWNER 135 // before using it. 136 class OPENSSL_EXPORT CertPathBuilder { 137 public: 138 // Provides the overall result of path building. This includes the paths that 139 // were attempted. 140 struct OPENSSL_EXPORT Result { 141 Result(); 142 Result(Result &&); 143 144 Result(const Result &) = delete; 145 Result &operator=(const Result &) = delete; 146 147 ~Result(); 148 Result &operator=(Result &&); 149 150 // Returns true if there was a valid path. 151 bool HasValidPath() const; 152 153 // Returns true if any of the attempted paths contain |error_id|. 154 bool AnyPathContainsError(CertErrorId error_id) const; 155 156 // Returns the best single error from result, using the best path found. 157 const VerifyError GetBestPathVerifyError() const; 158 159 // Returns the CertPathBuilderResultPath for the best valid path, or nullptr 160 // if there was none. 161 const CertPathBuilderResultPath *GetBestValidPath() const; 162 163 // Returns the best CertPathBuilderResultPath or nullptr if there was none. 164 const CertPathBuilderResultPath *GetBestPathPossiblyInvalid() const; 165 166 // List of paths that were attempted and the result for each. 167 std::vector<std::unique_ptr<CertPathBuilderResultPath>> paths; 168 169 // Index into |paths|. Before use, |paths.empty()| must be checked. 170 // NOTE: currently the definition of "best" is fairly limited. Valid is 171 // better than invalid, but otherwise nothing is guaranteed. 172 size_t best_result_index = 0; 173 174 // The iteration count reached by path building. 175 uint32_t iteration_count = 0; 176 177 // The max depth seen while path building. 178 uint32_t max_depth_seen = 0; 179 180 // True if the search stopped because it exceeded the iteration limit 181 // configured with |SetIterationLimit|. 182 bool exceeded_iteration_limit = false; 183 184 // True if the search stopped because delegate->IsDeadlineExpired() returned 185 // true. 186 bool exceeded_deadline = false; 187 }; 188 189 // Creates a CertPathBuilder that attempts to find a path from |cert| to a 190 // trust anchor in |trust_store| and is valid at |time|. 191 // 192 // The caller must keep |trust_store| and |delegate| valid for the lifetime 193 // of the CertPathBuilder. 194 // 195 // See VerifyCertificateChain() for a more detailed explanation of the 196 // same-named parameters not defined below. 197 // 198 // * |delegate|: Must be non-null. The delegate is called at various points in 199 // path building to verify specific parts of certificates or the 200 // final chain. See CertPathBuilderDelegate and 201 // VerifyCertificateChainDelegate for more information. 202 CertPathBuilder(std::shared_ptr<const ParsedCertificate> cert, 203 TrustStore *trust_store, CertPathBuilderDelegate *delegate, 204 const der::GeneralizedTime &time, KeyPurpose key_purpose, 205 InitialExplicitPolicy initial_explicit_policy, 206 const std::set<der::Input> &user_initial_policy_set, 207 InitialPolicyMappingInhibit initial_policy_mapping_inhibit, 208 InitialAnyPolicyInhibit initial_any_policy_inhibit); 209 210 CertPathBuilder(const CertPathBuilder &) = delete; 211 CertPathBuilder &operator=(const CertPathBuilder &) = delete; 212 213 ~CertPathBuilder(); 214 215 // Adds a CertIssuerSource to provide intermediates for use in path building. 216 // Multiple sources may be added. Must not be called after Run is called. 217 // The |*cert_issuer_source| must remain valid for the lifetime of the 218 // CertPathBuilder. 219 // 220 // (If no issuer sources are added, the target certificate will only verify if 221 // it is a trust anchor or is directly signed by a trust anchor.) 222 void AddCertIssuerSource(CertIssuerSource *cert_issuer_source); 223 224 // Sets a limit to the number of times to repeat the process of considering a 225 // new intermediate over all potential paths. Setting |limit| to 0 disables 226 // the iteration limit, which is the default. 227 void SetIterationLimit(uint32_t limit); 228 229 // Sets a limit to the number of certificates to be added in a path from leaf 230 // to root. Setting |limit| to 0 disables this limit, which is the default. 231 void SetDepthLimit(uint32_t limit); 232 233 // Set the limit of valid paths returned by the path builder to |limit|. If 234 // |limit| is non zero, path building will stop once |limit| valid paths have 235 // been found. Setting |limit| to 0 disables the limit, meaning path building 236 // will continue until all possible paths have been exhausted (or iteration 237 // limit / deadline is exceeded). The default limit is 1. 238 void SetValidPathLimit(size_t limit); 239 240 // If |explore_all_paths| is false, this is equivalent to calling 241 // SetValidPathLimit(1). If |explore_all_paths| is true, this is equivalent to 242 // calling SetValidPathLimit(0). 243 void SetExploreAllPaths(bool explore_all_paths); 244 245 // Executes verification of the target certificate. 246 // 247 // Run must not be called more than once on each CertPathBuilder instance. 248 Result Run(); 249 250 private: 251 void AddResultPath(std::unique_ptr<CertPathBuilderResultPath> result_path); 252 253 // |out_result_| may be referenced by other members, so should be initialized 254 // first. 255 Result out_result_; 256 257 std::unique_ptr<CertPathIter> cert_path_iter_; 258 CertPathBuilderDelegate *delegate_; 259 const der::GeneralizedTime time_; 260 const KeyPurpose key_purpose_; 261 const InitialExplicitPolicy initial_explicit_policy_; 262 const std::set<der::Input> user_initial_policy_set_; 263 const InitialPolicyMappingInhibit initial_policy_mapping_inhibit_; 264 const InitialAnyPolicyInhibit initial_any_policy_inhibit_; 265 uint32_t max_iteration_count_ = 0; 266 uint32_t max_path_building_depth_ = 0; 267 size_t valid_path_limit_ = 1; 268 size_t valid_path_count_ = 0; 269 }; 270 271 BSSL_NAMESPACE_END 272 273 #endif // BSSL_PKI_PATH_BUILDER_H_ 274