Bring in the core of chromium certificate verifier as libpki
Initially this leaves the canonical source in chrome, Additions
and fillins are committed directly, the chrome files are coverted
using the IMPORT script run from the pki directory for the moment.
The intention here is to continue frequent automatic conversion
(and avoid wholesale cosmetic changes in here for now) until
chrome converts to use these files in place of it's versions.
At that point these will become the definiative files, and the
IMPORT script can be tossed out.
A middle step along the way will be to change google3's verify.cc
in third_party/chromium_certificate_verifier to use this instead
of it's own extracted copy.
Status (and what is not done yet) being roughly tracked in README.md
Bug: chromium:1322914
Change-Id: Ibdb5479bc68985fa61ce6b10f98f31f6b3a7cbdf
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/60285
Commit-Queue: Bob Beck <bbe@google.com>
Reviewed-by: Adam Langley <agl@google.com>
diff --git a/pki/cert_errors.cc b/pki/cert_errors.cc
new file mode 100644
index 0000000..12376b9
--- /dev/null
+++ b/pki/cert_errors.cc
@@ -0,0 +1,201 @@
+// 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.
+
+#include "cert_errors.h"
+
+#include "cert_error_params.h"
+#include "parse_name.h"
+#include "parsed_certificate.h"
+
+#include <sstream>
+
+namespace bssl {
+
+namespace {
+
+void AppendLinesWithIndentation(const std::string& text,
+ const std::string& indentation,
+ std::string* out) {
+ std::istringstream stream(text);
+ for (std::string line; std::getline(stream, line, '\n');) {
+ out->append(indentation);
+ out->append(line);
+ out->append("\n");
+ }
+}
+
+} // namespace
+
+CertError::CertError() = default;
+
+CertError::CertError(Severity in_severity,
+ CertErrorId in_id,
+ std::unique_ptr<CertErrorParams> in_params)
+ : severity(in_severity), id(in_id), params(std::move(in_params)) {}
+
+CertError::CertError(CertError&& other) = default;
+
+CertError& CertError::operator=(CertError&&) = default;
+
+CertError::~CertError() = default;
+
+std::string CertError::ToDebugString() const {
+ std::string result;
+ switch (severity) {
+ case SEVERITY_WARNING:
+ result += "WARNING: ";
+ break;
+ case SEVERITY_HIGH:
+ result += "ERROR: ";
+ break;
+ }
+ result += CertErrorIdToDebugString(id);
+ result += +"\n";
+
+ if (params)
+ AppendLinesWithIndentation(params->ToDebugString(), " ", &result);
+
+ return result;
+}
+
+CertErrors::CertErrors() = default;
+CertErrors::CertErrors(CertErrors&& other) = default;
+CertErrors& CertErrors::operator=(CertErrors&&) = default;
+CertErrors::~CertErrors() = default;
+
+void CertErrors::Add(CertError::Severity severity,
+ CertErrorId id,
+ std::unique_ptr<CertErrorParams> params) {
+ nodes_.emplace_back(severity, id, std::move(params));
+}
+
+void CertErrors::AddError(CertErrorId id,
+ std::unique_ptr<CertErrorParams> params) {
+ Add(CertError::SEVERITY_HIGH, id, std::move(params));
+}
+
+void CertErrors::AddError(CertErrorId id) {
+ AddError(id, nullptr);
+}
+
+void CertErrors::AddWarning(CertErrorId id,
+ std::unique_ptr<CertErrorParams> params) {
+ Add(CertError::SEVERITY_WARNING, id, std::move(params));
+}
+
+void CertErrors::AddWarning(CertErrorId id) {
+ AddWarning(id, nullptr);
+}
+
+std::string CertErrors::ToDebugString() const {
+ std::string result;
+ for (const CertError& node : nodes_)
+ result += node.ToDebugString();
+
+ return result;
+}
+
+bool CertErrors::ContainsError(CertErrorId id) const {
+ for (const CertError& node : nodes_) {
+ if (node.id == id)
+ return true;
+ }
+ return false;
+}
+
+bool CertErrors::ContainsAnyErrorWithSeverity(
+ CertError::Severity severity) const {
+ for (const CertError& node : nodes_) {
+ if (node.severity == severity)
+ return true;
+ }
+ return false;
+}
+
+CertPathErrors::CertPathErrors() = default;
+
+CertPathErrors::CertPathErrors(CertPathErrors&& other) = default;
+CertPathErrors& CertPathErrors::operator=(CertPathErrors&&) = default;
+
+CertPathErrors::~CertPathErrors() = default;
+
+CertErrors* CertPathErrors::GetErrorsForCert(size_t cert_index) {
+ if (cert_index >= cert_errors_.size())
+ cert_errors_.resize(cert_index + 1);
+ return &cert_errors_[cert_index];
+}
+
+const CertErrors* CertPathErrors::GetErrorsForCert(size_t cert_index) const {
+ if (cert_index >= cert_errors_.size())
+ return nullptr;
+ return &cert_errors_[cert_index];
+}
+
+CertErrors* CertPathErrors::GetOtherErrors() {
+ return &other_errors_;
+}
+
+bool CertPathErrors::ContainsError(CertErrorId id) const {
+ for (const CertErrors& errors : cert_errors_) {
+ if (errors.ContainsError(id))
+ return true;
+ }
+
+ if (other_errors_.ContainsError(id))
+ return true;
+
+ return false;
+}
+
+bool CertPathErrors::ContainsAnyErrorWithSeverity(
+ CertError::Severity severity) const {
+ for (const CertErrors& errors : cert_errors_) {
+ if (errors.ContainsAnyErrorWithSeverity(severity))
+ return true;
+ }
+
+ if (other_errors_.ContainsAnyErrorWithSeverity(severity))
+ return true;
+
+ return false;
+}
+
+std::string CertPathErrors::ToDebugString(
+ const ParsedCertificateList& certs) const {
+ std::ostringstream result;
+
+ for (size_t i = 0; i < cert_errors_.size(); ++i) {
+ // Pretty print the current CertErrors. If there were no errors/warnings,
+ // then continue.
+ const CertErrors& errors = cert_errors_[i];
+ std::string cert_errors_string = errors.ToDebugString();
+ if (cert_errors_string.empty())
+ continue;
+
+ // Add a header that identifies which certificate this CertErrors pertains
+ // to.
+ std::string cert_name_debug_str;
+ if (i < certs.size() && certs[i]) {
+ RDNSequence subject;
+ if (ParseName(certs[i]->tbs().subject_tlv, &subject) &&
+ ConvertToRFC2253(subject, &cert_name_debug_str)) {
+ cert_name_debug_str = " (" + cert_name_debug_str + ")";
+ }
+ }
+ result << "----- Certificate i=" << i << cert_name_debug_str << " -----\n";
+ result << cert_errors_string << "\n";
+ }
+
+ // Print any other errors that aren't associated with a particular certificate
+ // in the chain.
+ std::string other_errors = other_errors_.ToDebugString();
+ if (!other_errors.empty()) {
+ result << "----- Other errors (not certificate specific) -----\n";
+ result << other_errors << "\n";
+ }
+
+ return result.str();
+}
+
+} // namespace net