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