Bob Beck | bc97b7a | 2023-04-18 08:35:15 -0600 | [diff] [blame] | 1 | // Copyright 2015 The Chromium Authors |
| 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
| 5 | #ifndef BSSL_PKI_VERIFY_CERTIFICATE_CHAIN_H_ |
| 6 | #define BSSL_PKI_VERIFY_CERTIFICATE_CHAIN_H_ |
| 7 | |
| 8 | #include "fillins/openssl_util.h" |
| 9 | #include <set> |
| 10 | |
| 11 | |
| 12 | #include "cert_errors.h" |
| 13 | #include "parsed_certificate.h" |
| 14 | #include "signature_verify_cache.h" |
| 15 | #include "input.h" |
| 16 | #include <openssl/evp.h> |
| 17 | |
| 18 | namespace bssl { |
| 19 | |
| 20 | namespace der { |
| 21 | struct GeneralizedTime; |
| 22 | } |
| 23 | |
| 24 | struct CertificateTrust; |
| 25 | |
| 26 | // The key purpose (extended key usage) to check for during verification. |
| 27 | enum class KeyPurpose { |
| 28 | ANY_EKU, |
| 29 | SERVER_AUTH, |
| 30 | CLIENT_AUTH, |
| 31 | SERVER_AUTH_STRICT, // Skip ANY_EKU when checking, require EKU present in |
| 32 | // certificate. |
| 33 | CLIENT_AUTH_STRICT, // Skip ANY_EKU when checking, require EKU present in |
| 34 | // certificate. |
| 35 | }; |
| 36 | |
| 37 | enum class InitialExplicitPolicy { |
| 38 | kFalse, |
| 39 | kTrue, |
| 40 | }; |
| 41 | |
| 42 | enum class InitialPolicyMappingInhibit { |
| 43 | kFalse, |
| 44 | kTrue, |
| 45 | }; |
| 46 | |
| 47 | enum class InitialAnyPolicyInhibit { |
| 48 | kFalse, |
| 49 | kTrue, |
| 50 | }; |
| 51 | |
| 52 | // VerifyCertificateChainDelegate exposes delegate methods used when verifying a |
| 53 | // chain. |
| 54 | class OPENSSL_EXPORT VerifyCertificateChainDelegate { |
| 55 | public: |
| 56 | // Implementations should return true if |signature_algorithm| is allowed for |
| 57 | // certificate signing, false otherwise. When returning false implementations |
| 58 | // can optionally add high-severity errors to |errors| with details on why it |
| 59 | // was rejected. |
| 60 | virtual bool IsSignatureAlgorithmAcceptable( |
| 61 | SignatureAlgorithm signature_algorithm, |
| 62 | CertErrors* errors) = 0; |
| 63 | |
| 64 | // Implementations should return true if |public_key| is acceptable. This is |
| 65 | // called for each certificate in the chain, including the target certificate. |
| 66 | // When returning false implementations can optionally add high-severity |
| 67 | // errors to |errors| with details on why it was rejected. |
| 68 | // |
| 69 | // |public_key| can be assumed to be non-null. |
| 70 | virtual bool IsPublicKeyAcceptable(EVP_PKEY* public_key, |
| 71 | CertErrors* errors) = 0; |
| 72 | |
| 73 | // This is called during verification to obtain a pointer to a signature |
| 74 | // verification cache if one exists. nullptr may be returned indicating there |
| 75 | // is no verification cache. |
| 76 | virtual SignatureVerifyCache* GetVerifyCache() = 0; |
| 77 | |
| 78 | virtual ~VerifyCertificateChainDelegate(); |
| 79 | }; |
| 80 | |
| 81 | // VerifyCertificateChain() verifies an ordered certificate path in accordance |
| 82 | // with RFC 5280's "Certification Path Validation" algorithm (section 6). |
| 83 | // |
| 84 | // ----------------------------------------- |
| 85 | // Deviations from RFC 5280 |
| 86 | // ----------------------------------------- |
| 87 | // |
| 88 | // * If Extended Key Usage appears on intermediates, it is treated as |
| 89 | // a restriction on subordinate certificates. |
| 90 | // * No revocation checking is performed. |
| 91 | // |
| 92 | // ----------------------------------------- |
| 93 | // Additional responsibilities of the caller |
| 94 | // ----------------------------------------- |
| 95 | // |
| 96 | // After successful path verification, the caller is responsible for |
| 97 | // subsequently checking: |
| 98 | // |
| 99 | // * The end-entity's KeyUsage before using its SPKI. |
| 100 | // * The end-entity's name/subjectAltName. Name constraints from intermediates |
| 101 | // will have already been applied, so it is sufficient to check the |
| 102 | // end-entity for a match. The caller MUST NOT check hostnames on the |
| 103 | // commonName field because this implementation does not apply dnsName |
| 104 | // constraints on commonName. |
| 105 | // |
| 106 | // --------- |
| 107 | // Inputs |
| 108 | // --------- |
| 109 | // |
| 110 | // certs: |
| 111 | // A non-empty chain of DER-encoded certificates, listed in the |
| 112 | // "forward" direction. The first certificate is the target |
| 113 | // certificate to verify, and the last certificate has trustedness |
| 114 | // given by |last_cert_trust| (generally a trust anchor). |
| 115 | // |
| 116 | // * certs[0] is the target certificate to verify. |
| 117 | // * certs[i+1] holds the certificate that issued cert_chain[i]. |
| 118 | // * certs[N-1] the root certificate |
| 119 | // |
| 120 | // Note that THIS IS NOT identical in meaning to the same named |
| 121 | // "certs" input defined in RFC 5280 section 6.1.1.a. The differences |
| 122 | // are: |
| 123 | // |
| 124 | // * The order of certificates is reversed |
| 125 | // * In RFC 5280 "certs" DOES NOT include the trust anchor |
| 126 | // |
| 127 | // last_cert_trust: |
| 128 | // Trustedness of |certs.back()|. The trustedness of |certs.back()| |
| 129 | // MUST BE decided by the caller -- this function takes it purely as |
| 130 | // an input. Moreover, the CertificateTrust can be used to specify |
| 131 | // trust anchor constraints. |
| 132 | // |
| 133 | // This combined with |certs.back()| (the root certificate) fills a |
| 134 | // similar role to "trust anchor information" defined in RFC 5280 |
| 135 | // section 6.1.1.d. |
| 136 | // |
| 137 | // delegate: |
| 138 | // |delegate| must be non-null. It is used to answer policy questions such |
| 139 | // as whether a signature algorithm is acceptable, or a public key is strong |
| 140 | // enough. |
| 141 | // |
| 142 | // time: |
| 143 | // The UTC time to use for expiration checks. This is equivalent to |
| 144 | // the input from RFC 5280 section 6.1.1: |
| 145 | // |
| 146 | // (b) the current date/time. |
| 147 | // |
| 148 | // required_key_purpose: |
| 149 | // The key purpose that the target certificate needs to be valid for. |
| 150 | // |
| 151 | // user_initial_policy_set: |
| 152 | // This is equivalent to the same named input in RFC 5280 section |
| 153 | // 6.1.1: |
| 154 | // |
| 155 | // (c) user-initial-policy-set: A set of certificate policy |
| 156 | // identifiers naming the policies that are acceptable to the |
| 157 | // certificate user. The user-initial-policy-set contains the |
| 158 | // special value any-policy if the user is not concerned about |
| 159 | // certificate policy. |
| 160 | // |
| 161 | // initial_policy_mapping_inhibit: |
| 162 | // This is equivalent to the same named input in RFC 5280 section |
| 163 | // 6.1.1: |
| 164 | // |
| 165 | // (e) initial-policy-mapping-inhibit, which indicates if policy |
| 166 | // mapping is allowed in the certification path. |
| 167 | // |
| 168 | // initial_explicit_policy: |
| 169 | // This is equivalent to the same named input in RFC 5280 section |
| 170 | // 6.1.1: |
| 171 | // |
| 172 | // (f) initial-explicit-policy, which indicates if the path must be |
| 173 | // valid for at least one of the certificate policies in the |
| 174 | // user-initial-policy-set. |
| 175 | // |
| 176 | // initial_any_policy_inhibit: |
| 177 | // This is equivalent to the same named input in RFC 5280 section |
| 178 | // 6.1.1: |
| 179 | // |
| 180 | // (g) initial-any-policy-inhibit, which indicates whether the |
| 181 | // anyPolicy OID should be processed if it is included in a |
| 182 | // certificate. |
| 183 | // |
| 184 | // --------- |
| 185 | // Outputs |
| 186 | // --------- |
| 187 | // |
| 188 | // user_constrained_policy_set: |
| 189 | // Can be null. If non-null, |user_constrained_policy_set| will be filled |
| 190 | // with the matching policies (intersected with user_initial_policy_set). |
| 191 | // This is equivalent to the same named output in X.509 section 10.2. |
| 192 | // Note that it is OK for this to point to input user_initial_policy_set. |
| 193 | // |
| 194 | // errors: |
| 195 | // Must be non-null. The set of errors/warnings encountered while |
| 196 | // validating the path are appended to this structure. If verification |
| 197 | // failed, then there is guaranteed to be at least 1 high severity error |
| 198 | // written to |errors|. |
| 199 | // |
| 200 | // ------------------------- |
| 201 | // Trust Anchor constraints |
| 202 | // ------------------------- |
| 203 | // |
| 204 | // Conceptually, VerifyCertificateChain() sets RFC 5937's |
| 205 | // "enforceTrustAnchorConstraints" to true. |
| 206 | // |
| 207 | // One specifies trust anchor constraints using the |last_cert_trust| |
| 208 | // parameter in conjunction with extensions appearing in |certs.back()|. |
| 209 | // |
| 210 | // The trust anchor |certs.back()| is always passed as a certificate to |
| 211 | // this function, however the manner in which that certificate is |
| 212 | // interpreted depends on |last_cert_trust|: |
| 213 | // |
| 214 | // TRUSTED_ANCHOR: |
| 215 | // |
| 216 | // No properties from the root certificate, other than its Subject and |
| 217 | // SPKI, are checked during verification. This is the usual |
| 218 | // interpretation for a "trust anchor". |
| 219 | // |
| 220 | // enforce_anchor_expiry=true: |
| 221 | // |
| 222 | // The validity period of the root is checked, in addition to Subject and SPKI. |
| 223 | // |
| 224 | // enforce_anchor_constraints=true: |
| 225 | // |
| 226 | // Only a subset of extensions and properties from the certificate are checked. |
| 227 | // In general, constraints encoded by extensions are only enforced if the |
| 228 | // extension is present. |
| 229 | // |
| 230 | // * Signature: No |
| 231 | // * Validity (expiration): No |
| 232 | // * Key usage: Yes |
| 233 | // * Extended key usage: Yes (required if required_key_purpose is STRICT) |
| 234 | // * Basic constraints: Yes |
| 235 | // * Name constraints: Yes |
| 236 | // * Certificate policies: Yes |
| 237 | // * Policy Mappings: Yes |
| 238 | // * inhibitAnyPolicy: Yes |
| 239 | // * PolicyConstraints: Yes |
| 240 | // |
| 241 | // The presence of any other unrecognized extension marked as critical fails |
| 242 | // validation. |
| 243 | OPENSSL_EXPORT void VerifyCertificateChain( |
| 244 | const ParsedCertificateList& certs, |
| 245 | const CertificateTrust& last_cert_trust, |
| 246 | VerifyCertificateChainDelegate* delegate, |
| 247 | const der::GeneralizedTime& time, |
| 248 | KeyPurpose required_key_purpose, |
| 249 | InitialExplicitPolicy initial_explicit_policy, |
| 250 | const std::set<der::Input>& user_initial_policy_set, |
| 251 | InitialPolicyMappingInhibit initial_policy_mapping_inhibit, |
| 252 | InitialAnyPolicyInhibit initial_any_policy_inhibit, |
| 253 | std::set<der::Input>* user_constrained_policy_set, |
| 254 | CertPathErrors* errors); |
| 255 | |
| 256 | // Returns true if `cert` is self-signed. Returns false `cert` is not |
| 257 | // self-signed or there was an error. If `errors` is non-null, it will contain |
| 258 | // additional information about the problem. If `cache` is non-null, it will be |
| 259 | // used to cache the signature verification step. |
| 260 | OPENSSL_EXPORT bool VerifyCertificateIsSelfSigned(const ParsedCertificate& cert, |
| 261 | SignatureVerifyCache* cache, |
| 262 | CertErrors* errors); |
| 263 | |
| 264 | } // namespace net |
| 265 | |
| 266 | #endif // BSSL_PKI_VERIFY_CERTIFICATE_CHAIN_H_ |