|  | // Copyright 2016 The Chromium Authors | 
|  | // Use of this source code is governed by a BSD-style license that can be | 
|  | // found in the LICENSE file. | 
|  |  | 
|  | // ---------------------------- | 
|  | // Overview of error design | 
|  | // ---------------------------- | 
|  | // | 
|  | // Certificate path building/validation/parsing may emit a sequence of errors | 
|  | // and warnings. | 
|  | // | 
|  | // Each individual error/warning entry (CertError) is comprised of: | 
|  | // | 
|  | //   * A unique identifier. | 
|  | // | 
|  | //     This serves similarly to an error code, and is used to query if a | 
|  | //     particular error/warning occurred. | 
|  | // | 
|  | //   * [optional] A parameters object. | 
|  | // | 
|  | //     Nodes may attach a heap-allocated subclass of CertErrorParams to carry | 
|  | //     extra information that is used when reporting the error. For instance | 
|  | //     a parsing error may describe where in the DER the failure happened, or | 
|  | //     what the unexpected value was. | 
|  | // | 
|  | // A collection of errors is represented by the CertErrors object. This may be | 
|  | // used to group errors that have a common context, such as all the | 
|  | // errors/warnings that apply to a specific certificate. | 
|  | // | 
|  | // Lastly, CertPathErrors composes multiple CertErrors -- one for each | 
|  | // certificate in the verified chain. | 
|  | // | 
|  | // ---------------------------- | 
|  | // Defining new errors | 
|  | // ---------------------------- | 
|  | // | 
|  | // The error IDs are extensible and do not need to be centrally defined. | 
|  | // | 
|  | // To define a new error use the macro DEFINE_CERT_ERROR_ID() in a .cc file. | 
|  | // If consumers are to be able to query for this error then the symbol should | 
|  | // also be exposed in a header file. | 
|  | // | 
|  | // Error IDs are in truth string literals, whose pointer value will be unique | 
|  | // per process. | 
|  |  | 
|  | #ifndef BSSL_PKI_CERT_ERRORS_H_ | 
|  | #define BSSL_PKI_CERT_ERRORS_H_ | 
|  |  | 
|  | #include <memory> | 
|  | #include <vector> | 
|  |  | 
|  | #include <openssl/base.h> | 
|  |  | 
|  | #include "cert_error_id.h" | 
|  | #include "parsed_certificate.h" | 
|  |  | 
|  | namespace bssl { | 
|  |  | 
|  | class CertErrorParams; | 
|  | class CertPathErrors; | 
|  |  | 
|  | // CertError represents either an error or a warning. | 
|  | struct OPENSSL_EXPORT CertError { | 
|  | enum Severity { | 
|  | SEVERITY_HIGH, | 
|  | SEVERITY_WARNING, | 
|  | }; | 
|  |  | 
|  | CertError(); | 
|  | CertError(Severity severity, CertErrorId id, | 
|  | std::unique_ptr<CertErrorParams> params); | 
|  | CertError(CertError &&other); | 
|  | CertError &operator=(CertError &&); | 
|  | ~CertError(); | 
|  |  | 
|  | // Pretty-prints the error and its parameters. | 
|  | std::string ToDebugString() const; | 
|  |  | 
|  | Severity severity; | 
|  | CertErrorId id; | 
|  | std::unique_ptr<CertErrorParams> params; | 
|  | }; | 
|  |  | 
|  | // CertErrors is a collection of CertError, along with convenience methods to | 
|  | // add and inspect errors. | 
|  | class OPENSSL_EXPORT CertErrors { | 
|  | public: | 
|  | CertErrors(); | 
|  | CertErrors(CertErrors &&other); | 
|  | CertErrors &operator=(CertErrors &&); | 
|  | ~CertErrors(); | 
|  |  | 
|  | // Adds an error/warning. |params| may be null. | 
|  | void Add(CertError::Severity severity, CertErrorId id, | 
|  | std::unique_ptr<CertErrorParams> params); | 
|  |  | 
|  | // Adds a high severity error. | 
|  | void AddError(CertErrorId id, std::unique_ptr<CertErrorParams> params); | 
|  | void AddError(CertErrorId id); | 
|  |  | 
|  | // Adds a low severity error. | 
|  | void AddWarning(CertErrorId id, std::unique_ptr<CertErrorParams> params); | 
|  | void AddWarning(CertErrorId id); | 
|  |  | 
|  | // Dumps a textual representation of the errors for debugging purposes. | 
|  | std::string ToDebugString() const; | 
|  |  | 
|  | // Returns true if the error |id| was added to this CertErrors at | 
|  | // severity |severity| | 
|  | bool ContainsErrorWithSeverity(CertErrorId id, | 
|  | CertError::Severity severity) const; | 
|  |  | 
|  | // Returns true if the error |id| was added to this CertErrors at | 
|  | // high serverity. | 
|  | bool ContainsError(CertErrorId id) const; | 
|  |  | 
|  | // Returns true if this contains any errors of the given severity level. | 
|  | bool ContainsAnyErrorWithSeverity(CertError::Severity severity) const; | 
|  |  | 
|  | private: | 
|  | friend CertPathErrors; | 
|  | std::vector<CertError> nodes_; | 
|  | }; | 
|  |  | 
|  | // CertPathErrors is a collection of CertErrors, to group errors into different | 
|  | // buckets for different certificates. The "index" should correspond with that | 
|  | // of the certificate relative to its chain. | 
|  | class OPENSSL_EXPORT CertPathErrors { | 
|  | public: | 
|  | CertPathErrors(); | 
|  | CertPathErrors(CertPathErrors &&other); | 
|  | CertPathErrors &operator=(CertPathErrors &&); | 
|  | ~CertPathErrors(); | 
|  |  | 
|  | // Gets a bucket to put errors in for |cert_index|. This will lookup and | 
|  | // return the existing error bucket if one exists, or create a new one for the | 
|  | // specified index. It is expected that |cert_index| is the corresponding | 
|  | // index in a certificate chain (with 0 being the target). | 
|  | CertErrors *GetErrorsForCert(size_t cert_index); | 
|  |  | 
|  | // Const version of the above, with the difference that if there is no | 
|  | // existing bucket for |cert_index| returns nullptr rather than lazyily | 
|  | // creating one. | 
|  | const CertErrors *GetErrorsForCert(size_t cert_index) const; | 
|  |  | 
|  | // Returns a bucket to put errors that are not associated with a particular | 
|  | // certificate. | 
|  | CertErrors *GetOtherErrors(); | 
|  | const CertErrors *GetOtherErrors() const; | 
|  |  | 
|  | // Returns true if CertPathErrors contains the specified error (of any | 
|  | // severity). | 
|  | bool ContainsError(CertErrorId id) const; | 
|  |  | 
|  | // Returns true if this contains any errors of the given severity level. | 
|  | bool ContainsAnyErrorWithSeverity(CertError::Severity severity) const; | 
|  |  | 
|  | // If the path contains only one unique high severity error, return the | 
|  | // error id and sets |out_depth| to the depth at which the error was | 
|  | // first seen. A depth of -1 means the error is not associated with | 
|  | // a single certificate of the path. | 
|  | std::optional<CertErrorId> FindSingleHighSeverityError( | 
|  | ptrdiff_t &out_depth) const; | 
|  |  | 
|  | // Shortcut for ContainsAnyErrorWithSeverity(CertError::SEVERITY_HIGH). | 
|  | bool ContainsHighSeverityErrors() const { | 
|  | return ContainsAnyErrorWithSeverity(CertError::SEVERITY_HIGH); | 
|  | } | 
|  |  | 
|  | // Pretty-prints all the errors in the CertPathErrors. If there were no | 
|  | // errors/warnings, returns an empty string. | 
|  | std::string ToDebugString(const ParsedCertificateList &certs) const; | 
|  |  | 
|  | private: | 
|  | std::vector<CertErrors> cert_errors_; | 
|  | CertErrors other_errors_; | 
|  | }; | 
|  |  | 
|  | }  // namespace bssl | 
|  |  | 
|  | #endif  // BSSL_PKI_CERT_ERRORS_H_ |