blob: 43ea7fcdde43ffe49811b6d02cf308d5fee8214f [file] [log] [blame]
// 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_