• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2015 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 <algorithm>
6 
7 #include "certificate_policies.h"
8 
9 #include "cert_error_params.h"
10 #include "cert_errors.h"
11 #include "input.h"
12 #include "parse_values.h"
13 #include "parser.h"
14 #include "tag.h"
15 #include <openssl/base.h>
16 
17 namespace bssl {
18 
19 namespace {
20 
21 // ---------------------------------------------------------------
22 // Errors
23 // ---------------------------------------------------------------
24 
25 DEFINE_CERT_ERROR_ID(kPolicyQualifiersEmptySequence,
26                      "The policy qualifiers SEQUENCE is empty");
27 DEFINE_CERT_ERROR_ID(kUnknownPolicyQualifierOid,
28                      "Unknown policy qualifier OID (not CPS or User Notice)");
29 DEFINE_CERT_ERROR_ID(kPoliciesEmptySequence, "Policies is an empty SEQUENCE");
30 DEFINE_CERT_ERROR_ID(kPoliciesDuplicateOid, "Policies contains duplicate OIDs");
31 DEFINE_CERT_ERROR_ID(kPolicyInformationTrailingData,
32                      "PolicyInformation has trailing data");
33 DEFINE_CERT_ERROR_ID(kFailedParsingPolicyQualifiers,
34                      "Failed parsing policy qualifiers");
35 DEFINE_CERT_ERROR_ID(kMissingQualifier,
36                      "PolicyQualifierInfo is missing qualifier");
37 DEFINE_CERT_ERROR_ID(kPolicyQualifierInfoTrailingData,
38                      "PolicyQualifierInfo has trailing data");
39 
40 // Minimally parse policyQualifiers, storing in |policy_qualifiers| if non-null.
41 // If a policy qualifier other than User Notice/CPS is present, parsing
42 // will fail if |restrict_to_known_qualifiers| was set to true.
ParsePolicyQualifiers(bool restrict_to_known_qualifiers,der::Parser * policy_qualifiers_sequence_parser,std::vector<PolicyQualifierInfo> * policy_qualifiers,CertErrors * errors)43 bool ParsePolicyQualifiers(bool restrict_to_known_qualifiers,
44                            der::Parser* policy_qualifiers_sequence_parser,
45                            std::vector<PolicyQualifierInfo>* policy_qualifiers,
46                            CertErrors* errors) {
47   BSSL_CHECK(errors);
48 
49   // If it is present, the policyQualifiers sequence should have at least 1
50   // element.
51   //
52   //      policyQualifiers   SEQUENCE SIZE (1..MAX) OF
53   //                              PolicyQualifierInfo OPTIONAL }
54   if (!policy_qualifiers_sequence_parser->HasMore()) {
55     errors->AddError(kPolicyQualifiersEmptySequence);
56     return false;
57   }
58   while (policy_qualifiers_sequence_parser->HasMore()) {
59     // PolicyQualifierInfo ::= SEQUENCE {
60     der::Parser policy_information_parser;
61     if (!policy_qualifiers_sequence_parser->ReadSequence(
62             &policy_information_parser)) {
63       return false;
64     }
65     //      policyQualifierId  PolicyQualifierId,
66     der::Input qualifier_oid;
67     if (!policy_information_parser.ReadTag(der::kOid, &qualifier_oid))
68       return false;
69     if (restrict_to_known_qualifiers &&
70         qualifier_oid != der::Input(kCpsPointerId) &&
71         qualifier_oid != der::Input(kUserNoticeId)) {
72       errors->AddError(kUnknownPolicyQualifierOid,
73                        CreateCertErrorParams1Der("oid", qualifier_oid));
74       return false;
75     }
76     //      qualifier          ANY DEFINED BY policyQualifierId }
77     der::Input qualifier_tlv;
78     if (!policy_information_parser.ReadRawTLV(&qualifier_tlv)) {
79       errors->AddError(kMissingQualifier);
80       return false;
81     }
82     // Should not have trailing data after qualifier.
83     if (policy_information_parser.HasMore()) {
84       errors->AddError(kPolicyQualifierInfoTrailingData);
85       return false;
86     }
87 
88     if (policy_qualifiers)
89       policy_qualifiers->push_back({qualifier_oid, qualifier_tlv});
90   }
91   return true;
92 }
93 
94 // RFC 5280 section 4.2.1.4.  Certificate Policies:
95 //
96 // certificatePolicies ::= SEQUENCE SIZE (1..MAX) OF PolicyInformation
97 //
98 // PolicyInformation ::= SEQUENCE {
99 //      policyIdentifier   CertPolicyId,
100 //      policyQualifiers   SEQUENCE SIZE (1..MAX) OF
101 //                              PolicyQualifierInfo OPTIONAL }
102 //
103 // CertPolicyId ::= OBJECT IDENTIFIER
104 //
105 // PolicyQualifierInfo ::= SEQUENCE {
106 //      policyQualifierId  PolicyQualifierId,
107 //      qualifier          ANY DEFINED BY policyQualifierId }
108 //
109 // PolicyQualifierId ::= OBJECT IDENTIFIER ( id-qt-cps | id-qt-unotice )
110 //
111 // Qualifier ::= CHOICE {
112 //      cPSuri           CPSuri,
113 //      userNotice       UserNotice }
114 //
115 // CPSuri ::= IA5String
116 //
117 // UserNotice ::= SEQUENCE {
118 //      noticeRef        NoticeReference OPTIONAL,
119 //      explicitText     DisplayText OPTIONAL }
120 //
121 // NoticeReference ::= SEQUENCE {
122 //      organization     DisplayText,
123 //      noticeNumbers    SEQUENCE OF INTEGER }
124 //
125 // DisplayText ::= CHOICE {
126 //      ia5String        IA5String      (SIZE (1..200)),
127 //      visibleString    VisibleString  (SIZE (1..200)),
128 //      bmpString        BMPString      (SIZE (1..200)),
129 //      utf8String       UTF8String     (SIZE (1..200)) }
ParseCertificatePoliciesExtensionImpl(const der::Input & extension_value,bool fail_parsing_unknown_qualifier_oids,std::vector<der::Input> * policy_oids,std::vector<PolicyInformation> * policy_informations,CertErrors * errors)130 bool ParseCertificatePoliciesExtensionImpl(
131     const der::Input& extension_value,
132     bool fail_parsing_unknown_qualifier_oids,
133     std::vector<der::Input>* policy_oids,
134     std::vector<PolicyInformation>* policy_informations,
135     CertErrors* errors) {
136   BSSL_CHECK(policy_oids);
137   BSSL_CHECK(errors);
138   // certificatePolicies ::= SEQUENCE SIZE (1..MAX) OF PolicyInformation
139   der::Parser extension_parser(extension_value);
140   der::Parser policies_sequence_parser;
141   if (!extension_parser.ReadSequence(&policies_sequence_parser))
142     return false;
143   // Should not have trailing data after certificatePolicies sequence.
144   if (extension_parser.HasMore())
145     return false;
146   // The certificatePolicies sequence should have at least 1 element.
147   if (!policies_sequence_parser.HasMore()) {
148     errors->AddError(kPoliciesEmptySequence);
149     return false;
150   }
151 
152   policy_oids->clear();
153   if (policy_informations)
154     policy_informations->clear();
155 
156   while (policies_sequence_parser.HasMore()) {
157     // PolicyInformation ::= SEQUENCE {
158     der::Parser policy_information_parser;
159     if (!policies_sequence_parser.ReadSequence(&policy_information_parser))
160       return false;
161     //      policyIdentifier   CertPolicyId,
162     der::Input policy_oid;
163     if (!policy_information_parser.ReadTag(der::kOid, &policy_oid))
164       return false;
165 
166     policy_oids->push_back(policy_oid);
167 
168     std::vector<PolicyQualifierInfo>* policy_qualifiers = nullptr;
169     if (policy_informations) {
170       policy_informations->emplace_back();
171       policy_informations->back().policy_oid = policy_oid;
172       policy_qualifiers = &policy_informations->back().policy_qualifiers;
173     }
174 
175     if (!policy_information_parser.HasMore())
176       continue;
177 
178     //      policyQualifiers   SEQUENCE SIZE (1..MAX) OF
179     //                              PolicyQualifierInfo OPTIONAL }
180     der::Parser policy_qualifiers_sequence_parser;
181     if (!policy_information_parser.ReadSequence(
182             &policy_qualifiers_sequence_parser)) {
183       return false;
184     }
185     // Should not have trailing data after policyQualifiers sequence.
186     if (policy_information_parser.HasMore()) {
187       errors->AddError(kPolicyInformationTrailingData);
188       return false;
189     }
190 
191     // RFC 5280 section 4.2.1.4: When qualifiers are used with the special
192     // policy anyPolicy, they MUST be limited to the qualifiers identified in
193     // this section.
194     if (!ParsePolicyQualifiers(fail_parsing_unknown_qualifier_oids ||
195                                    policy_oid == der::Input(kAnyPolicyOid),
196                                &policy_qualifiers_sequence_parser,
197                                policy_qualifiers, errors)) {
198       errors->AddError(kFailedParsingPolicyQualifiers);
199       return false;
200     }
201   }
202 
203   // RFC 5280 section 4.2.1.4: A certificate policy OID MUST NOT appear more
204   // than once in a certificate policies extension.
205   std::sort(policy_oids->begin(), policy_oids->end());
206   auto dupe_policy_iter =
207       std::adjacent_find(policy_oids->begin(), policy_oids->end());
208   if (dupe_policy_iter != policy_oids->end()) {
209     errors->AddError(kPoliciesDuplicateOid,
210                      CreateCertErrorParams1Der("oid", *dupe_policy_iter));
211     return false;
212   }
213 
214   return true;
215 }
216 
217 }  // namespace
218 
219 PolicyInformation::PolicyInformation() = default;
220 PolicyInformation::~PolicyInformation() = default;
221 PolicyInformation::PolicyInformation(const PolicyInformation&) = default;
222 PolicyInformation::PolicyInformation(PolicyInformation&&) = default;
223 
ParseCertificatePoliciesExtension(const der::Input & extension_value,std::vector<PolicyInformation> * policies,CertErrors * errors)224 bool ParseCertificatePoliciesExtension(const der::Input& extension_value,
225                                        std::vector<PolicyInformation>* policies,
226                                        CertErrors* errors) {
227   std::vector<der::Input> unused_policy_oids;
228   return ParseCertificatePoliciesExtensionImpl(
229       extension_value, /*fail_parsing_unknown_qualifier_oids=*/false,
230       &unused_policy_oids, policies, errors);
231 }
232 
ParseCertificatePoliciesExtensionOids(const der::Input & extension_value,bool fail_parsing_unknown_qualifier_oids,std::vector<der::Input> * policy_oids,CertErrors * errors)233 bool ParseCertificatePoliciesExtensionOids(
234     const der::Input& extension_value,
235     bool fail_parsing_unknown_qualifier_oids,
236     std::vector<der::Input>* policy_oids,
237     CertErrors* errors) {
238   return ParseCertificatePoliciesExtensionImpl(
239       extension_value, fail_parsing_unknown_qualifier_oids, policy_oids,
240       nullptr, errors);
241 }
242 
243 // From RFC 5280:
244 //
245 //   PolicyConstraints ::= SEQUENCE {
246 //        requireExplicitPolicy           [0] SkipCerts OPTIONAL,
247 //        inhibitPolicyMapping            [1] SkipCerts OPTIONAL }
248 //
249 //   SkipCerts ::= INTEGER (0..MAX)
ParsePolicyConstraints(const der::Input & policy_constraints_tlv,ParsedPolicyConstraints * out)250 bool ParsePolicyConstraints(const der::Input& policy_constraints_tlv,
251                             ParsedPolicyConstraints* out) {
252   der::Parser parser(policy_constraints_tlv);
253 
254   //   PolicyConstraints ::= SEQUENCE {
255   der::Parser sequence_parser;
256   if (!parser.ReadSequence(&sequence_parser))
257     return false;
258 
259   // RFC 5280 prohibits CAs from issuing PolicyConstraints as an empty sequence:
260   //
261   //   Conforming CAs MUST NOT issue certificates where policy constraints
262   //   is an empty sequence.  That is, either the inhibitPolicyMapping field
263   //   or the requireExplicitPolicy field MUST be present.  The behavior of
264   //   clients that encounter an empty policy constraints field is not
265   //   addressed in this profile.
266   if (!sequence_parser.HasMore())
267     return false;
268 
269   std::optional<der::Input> require_value;
270   if (!sequence_parser.ReadOptionalTag(der::ContextSpecificPrimitive(0),
271                                        &require_value)) {
272     return false;
273   }
274 
275   if (require_value) {
276     uint8_t require_explicit_policy;
277     if (!ParseUint8(require_value.value(), &require_explicit_policy)) {
278       // TODO(eroman): Surface reason for failure if length was longer than
279       // uint8.
280       return false;
281     }
282     out->require_explicit_policy = require_explicit_policy;
283   }
284 
285   std::optional<der::Input> inhibit_value;
286   if (!sequence_parser.ReadOptionalTag(der::ContextSpecificPrimitive(1),
287                                        &inhibit_value)) {
288     return false;
289   }
290 
291   if (inhibit_value) {
292     uint8_t inhibit_policy_mapping;
293     if (!ParseUint8(inhibit_value.value(), &inhibit_policy_mapping)) {
294       // TODO(eroman): Surface reason for failure if length was longer than
295       // uint8.
296       return false;
297     }
298     out->inhibit_policy_mapping = inhibit_policy_mapping;
299   }
300 
301   // There should be no remaining data.
302   if (sequence_parser.HasMore() || parser.HasMore())
303     return false;
304 
305   return true;
306 }
307 
308 // From RFC 5280:
309 //
310 //   InhibitAnyPolicy ::= SkipCerts
311 //
312 //   SkipCerts ::= INTEGER (0..MAX)
ParseInhibitAnyPolicy(const der::Input & inhibit_any_policy_tlv)313 std::optional<uint8_t> ParseInhibitAnyPolicy(
314     const der::Input& inhibit_any_policy_tlv) {
315   der::Parser parser(inhibit_any_policy_tlv);
316   std::optional<uint8_t> num_certs = std::make_optional<uint8_t>();
317 
318   // TODO(eroman): Surface reason for failure if length was longer than uint8.
319   if (!parser.ReadUint8(&num_certs.value())) {
320     return std::nullopt;
321   }
322 
323   // There should be no remaining data.
324   if (parser.HasMore()) {
325     return std::nullopt;
326   }
327 
328   return num_certs;
329 }
330 
331 // From RFC 5280:
332 //
333 //   PolicyMappings ::= SEQUENCE SIZE (1..MAX) OF SEQUENCE {
334 //        issuerDomainPolicy      CertPolicyId,
335 //        subjectDomainPolicy     CertPolicyId }
ParsePolicyMappings(const der::Input & policy_mappings_tlv,std::vector<ParsedPolicyMapping> * mappings)336 bool ParsePolicyMappings(const der::Input& policy_mappings_tlv,
337                          std::vector<ParsedPolicyMapping>* mappings) {
338   mappings->clear();
339 
340   der::Parser parser(policy_mappings_tlv);
341 
342   //   PolicyMappings ::= SEQUENCE SIZE (1..MAX) OF SEQUENCE {
343   der::Parser sequence_parser;
344   if (!parser.ReadSequence(&sequence_parser))
345     return false;
346 
347   // Must be at least 1 mapping.
348   if (!sequence_parser.HasMore())
349     return false;
350 
351   while (sequence_parser.HasMore()) {
352     der::Parser mapping_parser;
353     if (!sequence_parser.ReadSequence(&mapping_parser))
354       return false;
355 
356     ParsedPolicyMapping mapping;
357     if (!mapping_parser.ReadTag(der::kOid, &mapping.issuer_domain_policy))
358       return false;
359     if (!mapping_parser.ReadTag(der::kOid, &mapping.subject_domain_policy))
360       return false;
361 
362     // There shouldn't be extra unconsumed data.
363     if (mapping_parser.HasMore())
364       return false;
365 
366     mappings->push_back(mapping);
367   }
368 
369   // There shouldn't be extra unconsumed data.
370   if (parser.HasMore())
371     return false;
372 
373   return true;
374 }
375 
376 }  // namespace net
377