Coverage Report

Created: 2025-08-28 06:59

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