xref: /aosp_15_r20/external/cronet/third_party/boringssl/src/pki/cert_errors.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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 #include "cert_errors.h"
6 
7 #include "cert_error_params.h"
8 #include "parse_name.h"
9 #include "parsed_certificate.h"
10 
11 #include <sstream>
12 
13 namespace bssl {
14 
15 namespace {
16 
AppendLinesWithIndentation(const std::string & text,const std::string & indentation,std::string * out)17 void AppendLinesWithIndentation(const std::string &text,
18                                 const std::string &indentation,
19                                 std::string *out) {
20   std::istringstream stream(text);
21   for (std::string line; std::getline(stream, line, '\n');) {
22     out->append(indentation);
23     out->append(line);
24     out->append("\n");
25   }
26 }
27 
28 }  // namespace
29 
30 CertError::CertError() = default;
31 
CertError(Severity in_severity,CertErrorId in_id,std::unique_ptr<CertErrorParams> in_params)32 CertError::CertError(Severity in_severity, CertErrorId in_id,
33                      std::unique_ptr<CertErrorParams> in_params)
34     : severity(in_severity), id(in_id), params(std::move(in_params)) {}
35 
36 CertError::CertError(CertError &&other) = default;
37 
38 CertError &CertError::operator=(CertError &&) = default;
39 
40 CertError::~CertError() = default;
41 
ToDebugString() const42 std::string CertError::ToDebugString() const {
43   std::string result;
44   switch (severity) {
45     case SEVERITY_WARNING:
46       result += "WARNING: ";
47       break;
48     case SEVERITY_HIGH:
49       result += "ERROR: ";
50       break;
51   }
52   result += CertErrorIdToDebugString(id);
53   result += +"\n";
54 
55   if (params) {
56     AppendLinesWithIndentation(params->ToDebugString(), "  ", &result);
57   }
58 
59   return result;
60 }
61 
62 CertErrors::CertErrors() = default;
63 CertErrors::CertErrors(CertErrors &&other) = default;
64 CertErrors &CertErrors::operator=(CertErrors &&) = default;
65 CertErrors::~CertErrors() = default;
66 
Add(CertError::Severity severity,CertErrorId id,std::unique_ptr<CertErrorParams> params)67 void CertErrors::Add(CertError::Severity severity, CertErrorId id,
68                      std::unique_ptr<CertErrorParams> params) {
69   nodes_.emplace_back(severity, id, std::move(params));
70 }
71 
AddError(CertErrorId id,std::unique_ptr<CertErrorParams> params)72 void CertErrors::AddError(CertErrorId id,
73                           std::unique_ptr<CertErrorParams> params) {
74   Add(CertError::SEVERITY_HIGH, id, std::move(params));
75 }
76 
AddError(CertErrorId id)77 void CertErrors::AddError(CertErrorId id) { AddError(id, nullptr); }
78 
AddWarning(CertErrorId id,std::unique_ptr<CertErrorParams> params)79 void CertErrors::AddWarning(CertErrorId id,
80                             std::unique_ptr<CertErrorParams> params) {
81   Add(CertError::SEVERITY_WARNING, id, std::move(params));
82 }
83 
AddWarning(CertErrorId id)84 void CertErrors::AddWarning(CertErrorId id) { AddWarning(id, nullptr); }
85 
ToDebugString() const86 std::string CertErrors::ToDebugString() const {
87   std::string result;
88   for (const CertError &node : nodes_) {
89     result += node.ToDebugString();
90   }
91 
92   return result;
93 }
94 
ContainsErrorWithSeverity(CertErrorId id,CertError::Severity severity) const95 bool CertErrors::ContainsErrorWithSeverity(CertErrorId id,
96                                            CertError::Severity severity) const {
97   for (const CertError &node : nodes_) {
98     if (node.id == id && node.severity == severity) {
99       return true;
100     }
101   }
102   return false;
103 }
104 
ContainsError(CertErrorId id) const105 bool CertErrors::ContainsError(CertErrorId id) const {
106   return ContainsErrorWithSeverity(id, CertError::SEVERITY_HIGH);
107 }
108 
ContainsAnyErrorWithSeverity(CertError::Severity severity) const109 bool CertErrors::ContainsAnyErrorWithSeverity(
110     CertError::Severity severity) const {
111   for (const CertError &node : nodes_) {
112     if (node.severity == severity) {
113       return true;
114     }
115   }
116   return false;
117 }
118 
119 CertPathErrors::CertPathErrors() = default;
120 
121 CertPathErrors::CertPathErrors(CertPathErrors &&other) = default;
122 CertPathErrors &CertPathErrors::operator=(CertPathErrors &&) = default;
123 
124 CertPathErrors::~CertPathErrors() = default;
125 
GetErrorsForCert(size_t cert_index)126 CertErrors *CertPathErrors::GetErrorsForCert(size_t cert_index) {
127   if (cert_index >= cert_errors_.size()) {
128     cert_errors_.resize(cert_index + 1);
129   }
130   return &cert_errors_[cert_index];
131 }
132 
GetErrorsForCert(size_t cert_index) const133 const CertErrors *CertPathErrors::GetErrorsForCert(size_t cert_index) const {
134   if (cert_index >= cert_errors_.size()) {
135     return nullptr;
136   }
137   return &cert_errors_[cert_index];
138 }
139 
GetOtherErrors()140 CertErrors *CertPathErrors::GetOtherErrors() { return &other_errors_; }
141 
GetOtherErrors() const142 const CertErrors *CertPathErrors::GetOtherErrors() const {
143   return &other_errors_;
144 }
145 
ContainsError(CertErrorId id) const146 bool CertPathErrors::ContainsError(CertErrorId id) const {
147   for (const CertErrors &errors : cert_errors_) {
148     if (errors.ContainsError(id)) {
149       return true;
150     }
151   }
152 
153   if (other_errors_.ContainsError(id)) {
154     return true;
155   }
156 
157   return false;
158 }
159 
ContainsAnyErrorWithSeverity(CertError::Severity severity) const160 bool CertPathErrors::ContainsAnyErrorWithSeverity(
161     CertError::Severity severity) const {
162   for (const CertErrors &errors : cert_errors_) {
163     if (errors.ContainsAnyErrorWithSeverity(severity)) {
164       return true;
165     }
166   }
167 
168   if (other_errors_.ContainsAnyErrorWithSeverity(severity)) {
169     return true;
170   }
171 
172   return false;
173 }
174 
FindSingleHighSeverityError(ptrdiff_t & out_depth) const175 std::optional<CertErrorId> CertPathErrors::FindSingleHighSeverityError(
176     ptrdiff_t &out_depth) const {
177   std::optional<CertErrorId> id_seen;
178   for (ptrdiff_t i = -1; i < (ptrdiff_t)cert_errors_.size(); ++i) {
179     const CertErrors *errors =
180         (i < 0) ? GetOtherErrors() : GetErrorsForCert(i);
181     for (const CertError &node : errors->nodes_) {
182       if (node.severity == CertError::SEVERITY_HIGH) {
183         if (!id_seen.has_value()) {
184           id_seen = node.id;
185           out_depth = i;
186         } else {
187           if (id_seen.value() != node.id) {
188             return {};
189           }
190         }
191       }
192     }
193   }
194   return id_seen;
195 }
196 
ToDebugString(const ParsedCertificateList & certs) const197 std::string CertPathErrors::ToDebugString(
198     const ParsedCertificateList &certs) const {
199   std::ostringstream result;
200 
201   for (size_t i = 0; i < cert_errors_.size(); ++i) {
202     // Pretty print the current CertErrors. If there were no errors/warnings,
203     // then continue.
204     const CertErrors &errors = cert_errors_[i];
205     std::string cert_errors_string = errors.ToDebugString();
206     if (cert_errors_string.empty()) {
207       continue;
208     }
209 
210     // Add a header that identifies which certificate this CertErrors pertains
211     // to.
212     std::string cert_name_debug_str;
213     if (i < certs.size() && certs[i]) {
214       RDNSequence subject;
215       if (ParseName(certs[i]->tbs().subject_tlv, &subject) &&
216           ConvertToRFC2253(subject, &cert_name_debug_str)) {
217         cert_name_debug_str = " (" + cert_name_debug_str + ")";
218       }
219     }
220     result << "----- Certificate i=" << i << cert_name_debug_str << " -----\n";
221     result << cert_errors_string << "\n";
222   }
223 
224   // Print any other errors that aren't associated with a particular certificate
225   // in the chain.
226   std::string other_errors = other_errors_.ToDebugString();
227   if (!other_errors.empty()) {
228     result << "----- Other errors (not certificate specific) -----\n";
229     result << other_errors << "\n";
230   }
231 
232   return result.str();
233 }
234 
235 }  // namespace bssl
236