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