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