1 // Copyright 2016 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 // ---------------------------- 6 // Overview of error design 7 // ---------------------------- 8 // 9 // Certificate path building/validation/parsing may emit a sequence of errors 10 // and warnings. 11 // 12 // Each individual error/warning entry (CertError) is comprised of: 13 // 14 // * A unique identifier. 15 // 16 // This serves similarly to an error code, and is used to query if a 17 // particular error/warning occurred. 18 // 19 // * [optional] A parameters object. 20 // 21 // Nodes may attach a heap-allocated subclass of CertErrorParams to carry 22 // extra information that is used when reporting the error. For instance 23 // a parsing error may describe where in the DER the failure happened, or 24 // what the unexpected value was. 25 // 26 // A collection of errors is represented by the CertErrors object. This may be 27 // used to group errors that have a common context, such as all the 28 // errors/warnings that apply to a specific certificate. 29 // 30 // Lastly, CertPathErrors composes multiple CertErrors -- one for each 31 // certificate in the verified chain. 32 // 33 // ---------------------------- 34 // Defining new errors 35 // ---------------------------- 36 // 37 // The error IDs are extensible and do not need to be centrally defined. 38 // 39 // To define a new error use the macro DEFINE_CERT_ERROR_ID() in a .cc file. 40 // If consumers are to be able to query for this error then the symbol should 41 // also be exposed in a header file. 42 // 43 // Error IDs are in truth string literals, whose pointer value will be unique 44 // per process. 45 46 #ifndef BSSL_PKI_CERT_ERRORS_H_ 47 #define BSSL_PKI_CERT_ERRORS_H_ 48 49 #include <memory> 50 #include <vector> 51 52 #include <openssl/base.h> 53 54 #include "cert_error_id.h" 55 #include "parsed_certificate.h" 56 57 namespace bssl { 58 59 class CertErrorParams; 60 class CertPathErrors; 61 62 // CertError represents either an error or a warning. 63 struct OPENSSL_EXPORT CertError { 64 enum Severity { 65 SEVERITY_HIGH, 66 SEVERITY_WARNING, 67 }; 68 69 CertError(); 70 CertError(Severity severity, CertErrorId id, 71 std::unique_ptr<CertErrorParams> params); 72 CertError(CertError &&other); 73 CertError &operator=(CertError &&); 74 ~CertError(); 75 76 // Pretty-prints the error and its parameters. 77 std::string ToDebugString() const; 78 79 Severity severity; 80 CertErrorId id; 81 std::unique_ptr<CertErrorParams> params; 82 }; 83 84 // CertErrors is a collection of CertError, along with convenience methods to 85 // add and inspect errors. 86 class OPENSSL_EXPORT CertErrors { 87 public: 88 CertErrors(); 89 CertErrors(CertErrors &&other); 90 CertErrors &operator=(CertErrors &&); 91 ~CertErrors(); 92 93 // Adds an error/warning. |params| may be null. 94 void Add(CertError::Severity severity, CertErrorId id, 95 std::unique_ptr<CertErrorParams> params); 96 97 // Adds a high severity error. 98 void AddError(CertErrorId id, std::unique_ptr<CertErrorParams> params); 99 void AddError(CertErrorId id); 100 101 // Adds a low severity error. 102 void AddWarning(CertErrorId id, std::unique_ptr<CertErrorParams> params); 103 void AddWarning(CertErrorId id); 104 105 // Dumps a textual representation of the errors for debugging purposes. 106 std::string ToDebugString() const; 107 108 // Returns true if the error |id| was added to this CertErrors at 109 // severity |severity| 110 bool ContainsErrorWithSeverity(CertErrorId id, 111 CertError::Severity severity) const; 112 113 // Returns true if the error |id| was added to this CertErrors at 114 // high serverity. 115 bool ContainsError(CertErrorId id) const; 116 117 // Returns true if this contains any errors of the given severity level. 118 bool ContainsAnyErrorWithSeverity(CertError::Severity severity) const; 119 120 private: 121 friend CertPathErrors; 122 std::vector<CertError> nodes_; 123 }; 124 125 // CertPathErrors is a collection of CertErrors, to group errors into different 126 // buckets for different certificates. The "index" should correspond with that 127 // of the certificate relative to its chain. 128 class OPENSSL_EXPORT CertPathErrors { 129 public: 130 CertPathErrors(); 131 CertPathErrors(CertPathErrors &&other); 132 CertPathErrors &operator=(CertPathErrors &&); 133 ~CertPathErrors(); 134 135 // Gets a bucket to put errors in for |cert_index|. This will lookup and 136 // return the existing error bucket if one exists, or create a new one for the 137 // specified index. It is expected that |cert_index| is the corresponding 138 // index in a certificate chain (with 0 being the target). 139 CertErrors *GetErrorsForCert(size_t cert_index); 140 141 // Const version of the above, with the difference that if there is no 142 // existing bucket for |cert_index| returns nullptr rather than lazyily 143 // creating one. 144 const CertErrors *GetErrorsForCert(size_t cert_index) const; 145 146 // Returns a bucket to put errors that are not associated with a particular 147 // certificate. 148 CertErrors *GetOtherErrors(); 149 const CertErrors *GetOtherErrors() const; 150 151 // Returns true if CertPathErrors contains the specified error (of any 152 // severity). 153 bool ContainsError(CertErrorId id) const; 154 155 // Returns true if this contains any errors of the given severity level. 156 bool ContainsAnyErrorWithSeverity(CertError::Severity severity) const; 157 158 // If the path contains only one unique high severity error, return the 159 // error id and sets |out_depth| to the depth at which the error was 160 // first seen. A depth of -1 means the error is not associated with 161 // a single certificate of the path. 162 std::optional<CertErrorId> FindSingleHighSeverityError( 163 ptrdiff_t &out_depth) const; 164 165 // Shortcut for ContainsAnyErrorWithSeverity(CertError::SEVERITY_HIGH). ContainsHighSeverityErrors()166 bool ContainsHighSeverityErrors() const { 167 return ContainsAnyErrorWithSeverity(CertError::SEVERITY_HIGH); 168 } 169 170 // Pretty-prints all the errors in the CertPathErrors. If there were no 171 // errors/warnings, returns an empty string. 172 std::string ToDebugString(const ParsedCertificateList &certs) const; 173 174 private: 175 std::vector<CertErrors> cert_errors_; 176 CertErrors other_errors_; 177 }; 178 179 } // namespace bssl 180 181 #endif // BSSL_PKI_CERT_ERRORS_H_ 182