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