1 //! Certificate tests
2 use const_oid::AssociatedOid;
3 use der::asn1::{Ia5StringRef, OctetString, PrintableStringRef, Utf8StringRef};
4 use der::{Decode, Encode, ErrorKind, Length, Tag, Tagged};
5 use hex_literal::hex;
6 use x509_cert::ext::pkix::crl::dp::{DistributionPoint, ReasonFlags, Reasons};
7 use x509_cert::ext::pkix::name::{DistributionPointName, GeneralName, GeneralNames};
8 use x509_cert::ext::pkix::*;
9 use x509_cert::ext::Extensions;
10 use x509_cert::name::Name;
11 use x509_cert::{serial_number::SerialNumber, Certificate, Version};
12
13 use const_oid::db::rfc5280::*;
14 use const_oid::db::rfc5912::ID_CE_CERTIFICATE_POLICIES;
15
spin_over_exts(exts: Extensions)16 fn spin_over_exts(exts: Extensions) {
17 for ext in exts {
18 match ext.extn_id {
19 SubjectDirectoryAttributes::OID => {
20 let decoded =
21 SubjectDirectoryAttributes::from_der(ext.extn_value.as_bytes()).unwrap();
22 assert_eq!(
23 ext.extn_value,
24 decoded.to_der().and_then(OctetString::new).unwrap()
25 );
26 }
27
28 SubjectKeyIdentifier::OID => {
29 let decoded = SubjectKeyIdentifier::from_der(ext.extn_value.as_bytes()).unwrap();
30 assert_eq!(
31 ext.extn_value,
32 decoded.to_der().and_then(OctetString::new).unwrap()
33 );
34 }
35
36 KeyUsage::OID => {
37 let decoded = KeyUsage::from_der(ext.extn_value.as_bytes()).unwrap();
38 assert_eq!(
39 ext.extn_value,
40 decoded.to_der().and_then(OctetString::new).unwrap()
41 );
42 }
43
44 PrivateKeyUsagePeriod::OID => {
45 let decoded = PrivateKeyUsagePeriod::from_der(ext.extn_value.as_bytes()).unwrap();
46 assert_eq!(
47 ext.extn_value,
48 decoded.to_der().and_then(OctetString::new).unwrap()
49 );
50 }
51
52 SubjectAltName::OID => {
53 let decoded = SubjectAltName::from_der(ext.extn_value.as_bytes()).unwrap();
54 assert_eq!(
55 ext.extn_value,
56 decoded.to_der().and_then(OctetString::new).unwrap()
57 );
58 }
59
60 IssuerAltName::OID => {
61 let decoded = IssuerAltName::from_der(ext.extn_value.as_bytes()).unwrap();
62 assert_eq!(
63 ext.extn_value,
64 decoded.to_der().and_then(OctetString::new).unwrap()
65 );
66 }
67
68 BasicConstraints::OID => {
69 let decoded = BasicConstraints::from_der(ext.extn_value.as_bytes()).unwrap();
70 assert_eq!(
71 ext.extn_value,
72 decoded.to_der().and_then(OctetString::new).unwrap()
73 );
74 }
75
76 NameConstraints::OID => {
77 let decoded = NameConstraints::from_der(ext.extn_value.as_bytes()).unwrap();
78 assert_eq!(
79 ext.extn_value,
80 decoded.to_der().and_then(OctetString::new).unwrap()
81 );
82 }
83
84 CrlDistributionPoints::OID => {
85 let decoded = CrlDistributionPoints::from_der(ext.extn_value.as_bytes()).unwrap();
86 assert_eq!(
87 ext.extn_value,
88 decoded.to_der().and_then(OctetString::new).unwrap()
89 );
90 }
91
92 CertificatePolicies::OID => {
93 let decoded = CertificatePolicies::from_der(ext.extn_value.as_bytes()).unwrap();
94 assert_eq!(
95 ext.extn_value,
96 decoded.to_der().and_then(OctetString::new).unwrap()
97 );
98 }
99
100 PolicyMappings::OID => {
101 let decoded = PolicyMappings::from_der(ext.extn_value.as_bytes()).unwrap();
102 assert_eq!(
103 ext.extn_value,
104 decoded.to_der().and_then(OctetString::new).unwrap()
105 );
106 }
107
108 AuthorityKeyIdentifier::OID => {
109 let decoded = AuthorityKeyIdentifier::from_der(ext.extn_value.as_bytes()).unwrap();
110 assert_eq!(
111 ext.extn_value,
112 decoded.to_der().and_then(OctetString::new).unwrap()
113 );
114 }
115
116 PolicyConstraints::OID => {
117 let decoded = PolicyConstraints::from_der(ext.extn_value.as_bytes()).unwrap();
118 assert_eq!(
119 ext.extn_value,
120 decoded.to_der().and_then(OctetString::new).unwrap()
121 );
122 }
123
124 ExtendedKeyUsage::OID => {
125 let decoded = ExtendedKeyUsage::from_der(ext.extn_value.as_bytes()).unwrap();
126 assert_eq!(
127 ext.extn_value,
128 decoded.to_der().and_then(OctetString::new).unwrap()
129 );
130 }
131
132 FreshestCrl::OID => {
133 let decoded = FreshestCrl::from_der(ext.extn_value.as_bytes()).unwrap();
134 assert_eq!(
135 ext.extn_value,
136 decoded.to_der().and_then(OctetString::new).unwrap()
137 );
138 }
139
140 InhibitAnyPolicy::OID => {
141 let decoded = InhibitAnyPolicy::from_der(ext.extn_value.as_bytes()).unwrap();
142 assert_eq!(
143 ext.extn_value,
144 decoded.to_der().and_then(OctetString::new).unwrap()
145 );
146 }
147
148 AuthorityInfoAccessSyntax::OID => {
149 let decoded =
150 AuthorityInfoAccessSyntax::from_der(ext.extn_value.as_bytes()).unwrap();
151 assert_eq!(
152 ext.extn_value,
153 decoded.to_der().and_then(OctetString::new).unwrap()
154 );
155 }
156
157 SubjectInfoAccessSyntax::OID => {
158 let decoded = SubjectInfoAccessSyntax::from_der(ext.extn_value.as_bytes()).unwrap();
159 assert_eq!(
160 ext.extn_value,
161 decoded.to_der().and_then(OctetString::new).unwrap()
162 );
163 }
164
165 _ => {
166 eprintln!("ignoring {} with criticality {}", ext.extn_id, ext.critical);
167 }
168 }
169 }
170 }
171
172 #[test]
decode_general_name()173 fn decode_general_name() {
174 // DnsName
175 let dns_name = GeneralName::from_der(&hex!("820C616D617A6F6E2E636F2E756B")[..]).unwrap();
176 match dns_name {
177 GeneralName::DnsName(dns_name) => assert_eq!(dns_name.to_string(), "amazon.co.uk"),
178 _ => panic!("Failed to parse DnsName from GeneralName"),
179 }
180
181 // Rfc822Name
182 let rfc822 = GeneralName::from_der(
183 &hex!("811B456D61696C5F38303837323037343440746D612E6F73642E6D696C")[..],
184 )
185 .unwrap();
186 match rfc822 {
187 GeneralName::Rfc822Name(rfc822) => {
188 assert_eq!(rfc822.to_string(), "Email_808720744@tma.osd.mil")
189 }
190 _ => panic!("Failed to parse Rfc822Name from GeneralName"),
191 }
192
193 // OtherName
194 let bytes = hex!("A021060A2B060104018237140203A0130C1155706E5F323134393530313330406D696C");
195 match GeneralName::from_der(&bytes).unwrap() {
196 GeneralName::OtherName(other_name) => {
197 let onval = Utf8StringRef::try_from(&other_name.value).unwrap();
198 assert_eq!(onval.to_string(), "Upn_214950130@mil");
199 }
200 _ => panic!("Failed to parse OtherName from GeneralName"),
201 }
202 }
203
204 #[test]
decode_cert()205 fn decode_cert() {
206 // cloned cert with variety of interesting bits, including subject DN encoded backwards, large
207 // policy mapping set, large policy set (including one with qualifiers), fairly typical set of
208 // extensions otherwise
209 let der_encoded_cert =
210 include_bytes!("examples/026EDA6FA1EDFA8C253936C75B5EEBD954BFF452.fake.der");
211 let result = Certificate::from_der(der_encoded_cert);
212 let cert: Certificate = result.unwrap();
213 let exts = cert.tbs_certificate.extensions.unwrap();
214 let i = exts.iter();
215 let mut counter = 0;
216 for ext in i {
217 if 0 == counter {
218 assert_eq!(ext.extn_id.to_string(), ID_CE_KEY_USAGE.to_string());
219 assert_eq!(ext.critical, true);
220
221 let ku = KeyUsage::from_der(ext.extn_value.as_bytes()).unwrap();
222 assert_eq!(KeyUsages::KeyCertSign | KeyUsages::CRLSign, ku);
223
224 let reencoded = ku.to_der().and_then(OctetString::new).unwrap();
225 assert_eq!(ext.extn_value, reencoded);
226 } else if 1 == counter {
227 assert_eq!(ext.extn_id.to_string(), ID_CE_BASIC_CONSTRAINTS.to_string());
228 assert_eq!(ext.critical, true);
229 let bc = BasicConstraints::from_der(ext.extn_value.as_bytes()).unwrap();
230 assert_eq!(true, bc.ca);
231 assert!(bc.path_len_constraint.is_none());
232
233 let reencoded = bc.to_der().and_then(OctetString::new).unwrap();
234 assert_eq!(ext.extn_value, reencoded);
235 } else if 2 == counter {
236 assert_eq!(ext.extn_id.to_string(), ID_CE_POLICY_MAPPINGS.to_string());
237 assert_eq!(ext.critical, false);
238 let pm = PolicyMappings::from_der(ext.extn_value.as_bytes()).unwrap();
239 assert_eq!(19, pm.0.len());
240
241 let reencoded = pm.to_der().and_then(OctetString::new).unwrap();
242 assert_eq!(ext.extn_value, reencoded);
243
244 let subject_domain_policy: [&str; 19] = [
245 "2.16.840.1.101.3.2.1.48.2",
246 "2.16.840.1.101.3.2.1.48.2",
247 "2.16.840.1.101.3.2.1.48.3",
248 "2.16.840.1.101.3.2.1.48.3",
249 "2.16.840.1.101.3.2.1.48.5",
250 "2.16.840.1.101.3.2.1.48.5",
251 "2.16.840.1.101.3.2.1.48.4",
252 "2.16.840.1.101.3.2.1.48.4",
253 "2.16.840.1.101.3.2.1.48.6",
254 "2.16.840.1.101.3.2.1.48.6",
255 "2.16.840.1.101.3.2.1.48.78",
256 "2.16.840.1.101.3.2.1.48.78",
257 "2.16.840.1.101.3.2.1.48.78",
258 "2.16.840.1.101.3.2.1.48.79",
259 "2.16.840.1.101.3.2.1.48.80",
260 "2.16.840.1.101.3.2.1.48.99",
261 "2.16.840.1.101.3.2.1.48.99",
262 "2.16.840.1.101.3.2.1.48.100",
263 "2.16.840.1.101.3.2.1.48.100",
264 ];
265
266 let issuer_domain_policy: [&str; 19] = [
267 "2.16.840.1.113839.0.100.2.1",
268 "2.16.840.1.113839.0.100.2.2",
269 "2.16.840.1.113839.0.100.3.1",
270 "2.16.840.1.113839.0.100.3.2",
271 "2.16.840.1.113839.0.100.14.1",
272 "2.16.840.1.113839.0.100.14.2",
273 "2.16.840.1.113839.0.100.12.1",
274 "2.16.840.1.113839.0.100.12.2",
275 "2.16.840.1.113839.0.100.15.1",
276 "2.16.840.1.113839.0.100.15.2",
277 "2.16.840.1.113839.0.100.18.0",
278 "2.16.840.1.113839.0.100.18.1",
279 "2.16.840.1.113839.0.100.18.2",
280 "2.16.840.1.113839.0.100.19.1",
281 "2.16.840.1.113839.0.100.20.1",
282 "2.16.840.1.113839.0.100.37.1",
283 "2.16.840.1.113839.0.100.37.2",
284 "2.16.840.1.113839.0.100.38.1",
285 "2.16.840.1.113839.0.100.38.2",
286 ];
287
288 let mut counter_pm = 0;
289 for mapping in pm.0 {
290 assert_eq!(
291 issuer_domain_policy[counter_pm],
292 mapping.issuer_domain_policy.to_string()
293 );
294 assert_eq!(
295 subject_domain_policy[counter_pm],
296 mapping.subject_domain_policy.to_string()
297 );
298 counter_pm += 1;
299 }
300 } else if 3 == counter {
301 assert_eq!(
302 ext.extn_id.to_string(),
303 ID_CE_CERTIFICATE_POLICIES.to_string()
304 );
305 assert_eq!(ext.critical, false);
306 let cps = CertificatePolicies::from_der(ext.extn_value.as_bytes()).unwrap();
307 assert_eq!(19, cps.0.len());
308
309 let reencoded = cps.to_der().and_then(OctetString::new).unwrap();
310 assert_eq!(ext.extn_value, reencoded);
311
312 let ids: [&str; 19] = [
313 "2.16.840.1.113839.0.100.2.1",
314 "2.16.840.1.113839.0.100.2.2",
315 "2.16.840.1.113839.0.100.3.1",
316 "2.16.840.1.113839.0.100.3.2",
317 "2.16.840.1.113839.0.100.14.1",
318 "2.16.840.1.113839.0.100.14.2",
319 "2.16.840.1.113839.0.100.12.1",
320 "2.16.840.1.113839.0.100.12.2",
321 "2.16.840.1.113839.0.100.15.1",
322 "2.16.840.1.113839.0.100.15.2",
323 "2.16.840.1.113839.0.100.18.0",
324 "2.16.840.1.113839.0.100.18.1",
325 "2.16.840.1.113839.0.100.18.2",
326 "2.16.840.1.113839.0.100.19.1",
327 "2.16.840.1.113839.0.100.20.1",
328 "2.16.840.1.113839.0.100.37.1",
329 "2.16.840.1.113839.0.100.37.2",
330 "2.16.840.1.113839.0.100.38.1",
331 "2.16.840.1.113839.0.100.38.2",
332 ];
333
334 let mut cp_counter = 0;
335 for cp in cps.0 {
336 assert_eq!(ids[cp_counter], cp.policy_identifier.to_string());
337 if 18 == cp_counter {
338 assert!(cp.policy_qualifiers.is_some());
339 let pq = cp.policy_qualifiers.unwrap();
340 let mut counter_pq = 0;
341 for pqi in pq.iter() {
342 if 0 == counter_pq {
343 assert_eq!("1.3.6.1.5.5.7.2.1", pqi.policy_qualifier_id.to_string());
344 let cpsval =
345 Ia5StringRef::try_from(pqi.qualifier.as_ref().unwrap()).unwrap();
346 assert_eq!(
347 "https://secure.identrust.com/certificates/policy/IGC/index.html",
348 cpsval.to_string()
349 );
350 } else if 1 == counter_pq {
351 assert_eq!("1.3.6.1.5.5.7.2.2", pqi.policy_qualifier_id.to_string());
352 // TODO VisibleString
353 }
354 counter_pq += 1;
355 }
356 } else {
357 assert!(cp.policy_qualifiers.is_none())
358 }
359
360 cp_counter += 1;
361 }
362 } else if 4 == counter {
363 assert_eq!(
364 ext.extn_id.to_string(),
365 ID_CE_SUBJECT_KEY_IDENTIFIER.to_string()
366 );
367 assert_eq!(ext.critical, false);
368 let skid = SubjectKeyIdentifier::from_der(ext.extn_value.as_bytes()).unwrap();
369 assert_eq!(Length::new(21), skid.0.len());
370 assert_eq!(
371 &hex!("DBD3DEBF0D7B615B32803BC0206CD7AADD39B8ACFF"),
372 skid.0.as_bytes()
373 );
374
375 let reencoded = skid.to_der().and_then(OctetString::new).unwrap();
376 assert_eq!(ext.extn_value, reencoded);
377 } else if 5 == counter {
378 assert_eq!(
379 ext.extn_id.to_string(),
380 ID_CE_CRL_DISTRIBUTION_POINTS.to_string()
381 );
382 assert_eq!(ext.critical, false);
383 let crl_dps = CrlDistributionPoints::from_der(ext.extn_value.as_bytes()).unwrap();
384 assert_eq!(2, crl_dps.0.len());
385
386 let reencoded = crl_dps.to_der().and_then(OctetString::new).unwrap();
387 assert_eq!(ext.extn_value, reencoded);
388
389 let mut crldp_counter = 0;
390 for crldp in crl_dps.0 {
391 let dpn = crldp.distribution_point.unwrap();
392 if 0 == crldp_counter {
393 match dpn {
394 DistributionPointName::FullName(gns) => {
395 assert_eq!(1, gns.len());
396 let gn = gns.get(0).unwrap();
397 match gn {
398 GeneralName::UniformResourceIdentifier(uri) => {
399 assert_eq!(
400 "http://crl-pte.identrust.com.test/crl/IGCRootca1.crl",
401 uri.to_string()
402 );
403 }
404 _ => {
405 panic!("Expected UniformResourceIdentifier");
406 }
407 }
408 }
409 _ => {
410 panic!("Expected FullName");
411 }
412 }
413 } else if 1 == crldp_counter {
414 match dpn {
415 DistributionPointName::FullName(gns) => {
416 assert_eq!(1, gns.len());
417 let gn = gns.get(0).unwrap();
418 match gn {
419 GeneralName::UniformResourceIdentifier(uri) => {
420 assert_eq!("ldap://ldap-pte.identrust.com.test/cn%3DIGC%20Root%20CA1%2Co%3DIdenTrust%2Cc%3DUS%3FcertificateRevocationList%3Bbinary", uri.to_string());
421 }
422 _ => {
423 panic!("Expected UniformResourceIdentifier");
424 }
425 }
426 }
427 _ => {
428 panic!("Expected UniformResourceIdentifier");
429 }
430 }
431 }
432
433 crldp_counter += 1;
434 }
435 } else if 6 == counter {
436 assert_eq!(
437 ext.extn_id.to_string(),
438 ID_PE_SUBJECT_INFO_ACCESS.to_string()
439 );
440 assert_eq!(ext.critical, false);
441 let sias = SubjectInfoAccessSyntax::from_der(ext.extn_value.as_bytes()).unwrap();
442 assert_eq!(1, sias.0.len());
443
444 let reencoded = sias.to_der().and_then(OctetString::new).unwrap();
445 assert_eq!(ext.extn_value, reencoded);
446
447 for sia in sias.0 {
448 assert_eq!("1.3.6.1.5.5.7.48.5", sia.access_method.to_string());
449 let gn = sia.access_location;
450 match gn {
451 GeneralName::UniformResourceIdentifier(gn) => {
452 assert_eq!(
453 "http://http.cite.fpki-lab.gov.test/bridge/caCertsIssuedBytestFBCA.p7c",
454 gn.to_string()
455 );
456 }
457 _ => {
458 panic!("Expected UniformResourceIdentifier");
459 }
460 }
461 }
462 } else if 7 == counter {
463 assert_eq!(
464 ext.extn_id.to_string(),
465 ID_PE_AUTHORITY_INFO_ACCESS.to_string()
466 );
467 assert_eq!(ext.critical, false);
468 let aias = AuthorityInfoAccessSyntax::from_der(ext.extn_value.as_bytes()).unwrap();
469 assert_eq!(2, aias.0.len());
470 let mut aia_counter = 0;
471
472 let reencoded = aias.to_der().and_then(OctetString::new).unwrap();
473 assert_eq!(ext.extn_value, reencoded);
474
475 for aia in aias.0 {
476 if 0 == aia_counter {
477 assert_eq!("1.3.6.1.5.5.7.48.2", aia.access_method.to_string());
478 let gn = aia.access_location;
479 match gn {
480 GeneralName::UniformResourceIdentifier(gn) => {
481 assert_eq!(
482 "http://apps-stg.identrust.com.test/roots/IGCRootca1.p7c",
483 gn.to_string()
484 );
485 }
486 _ => {
487 panic!("Expected UniformResourceIdentifier");
488 }
489 }
490 } else if 1 == aia_counter {
491 assert_eq!("1.3.6.1.5.5.7.48.1", aia.access_method.to_string());
492 let gn = aia.access_location;
493 match gn {
494 GeneralName::UniformResourceIdentifier(gn) => {
495 assert_eq!(
496 "http://igcrootpte.ocsp.identrust.com.test:8125",
497 gn.to_string()
498 );
499 }
500 _ => {
501 panic!("Expected UniformResourceIdentifier");
502 }
503 }
504 }
505
506 aia_counter += 1;
507 }
508 } else if 8 == counter {
509 assert_eq!(
510 ext.extn_id.to_string(),
511 ID_CE_INHIBIT_ANY_POLICY.to_string()
512 );
513 assert_eq!(ext.critical, false);
514 let iap = InhibitAnyPolicy::from_der(ext.extn_value.as_bytes()).unwrap();
515 assert_eq!(0, iap.0);
516
517 let reencoded = iap.to_der().and_then(OctetString::new).unwrap();
518 assert_eq!(ext.extn_value, reencoded);
519 } else if 9 == counter {
520 assert_eq!(
521 ext.extn_id.to_string(),
522 ID_CE_AUTHORITY_KEY_IDENTIFIER.to_string()
523 );
524 assert_eq!(ext.critical, false);
525 let akid = AuthorityKeyIdentifier::from_der(ext.extn_value.as_bytes()).unwrap();
526 assert_eq!(
527 &hex!("7C4C863AB80BD589870BEDB7E11BBD2A08BB3D23FF"),
528 akid.key_identifier.as_ref().unwrap().as_bytes()
529 );
530
531 let reencoded = akid.to_der().and_then(OctetString::new).unwrap();
532 assert_eq!(ext.extn_value, reencoded);
533 }
534
535 counter += 1;
536 }
537
538 let der_encoded_cert = include_bytes!("examples/GoodCACert.crt");
539 let result = Certificate::from_der(der_encoded_cert);
540 let cert: Certificate = result.unwrap();
541
542 assert_eq!(cert.tbs_certificate.version, Version::V3);
543 let target_serial: [u8; 1] = [2];
544 assert_eq!(
545 cert.tbs_certificate.serial_number,
546 SerialNumber::new(&target_serial).unwrap()
547 );
548 assert_eq!(
549 cert.tbs_certificate.signature.oid.to_string(),
550 "1.2.840.113549.1.1.11"
551 );
552 assert_eq!(
553 cert.tbs_certificate
554 .signature
555 .parameters
556 .as_ref()
557 .unwrap()
558 .tag(),
559 Tag::Null
560 );
561 assert_eq!(
562 cert.tbs_certificate
563 .signature
564 .parameters
565 .as_ref()
566 .unwrap()
567 .is_null(),
568 true
569 );
570
571 let mut counter = 0;
572 let i = cert.tbs_certificate.issuer.0.iter();
573 for rdn in i {
574 let i1 = rdn.0.iter();
575 for atav in i1 {
576 if 0 == counter {
577 assert_eq!(atav.oid.to_string(), "2.5.4.6");
578 assert_eq!(
579 PrintableStringRef::try_from(&atav.value)
580 .unwrap()
581 .to_string(),
582 "US"
583 );
584 } else if 1 == counter {
585 assert_eq!(atav.oid.to_string(), "2.5.4.10");
586 assert_eq!(
587 PrintableStringRef::try_from(&atav.value)
588 .unwrap()
589 .to_string(),
590 "Test Certificates 2011"
591 );
592 } else if 2 == counter {
593 assert_eq!(atav.oid.to_string(), "2.5.4.3");
594 assert_eq!(
595 PrintableStringRef::try_from(&atav.value)
596 .unwrap()
597 .to_string(),
598 "Trust Anchor"
599 );
600 }
601 counter += 1;
602 }
603 }
604
605 assert_eq!(
606 cert.tbs_certificate
607 .validity
608 .not_before
609 .to_unix_duration()
610 .as_secs(),
611 1262334600
612 );
613 assert_eq!(
614 cert.tbs_certificate
615 .validity
616 .not_after
617 .to_unix_duration()
618 .as_secs(),
619 1924936200
620 );
621
622 counter = 0;
623 let i = cert.tbs_certificate.subject.0.iter();
624 for rdn in i {
625 let i1 = rdn.0.iter();
626 for atav in i1 {
627 if 0 == counter {
628 assert_eq!(atav.oid.to_string(), "2.5.4.6");
629 assert_eq!(
630 PrintableStringRef::try_from(&atav.value)
631 .unwrap()
632 .to_string(),
633 "US"
634 );
635 } else if 1 == counter {
636 assert_eq!(atav.oid.to_string(), "2.5.4.10");
637 assert_eq!(
638 PrintableStringRef::try_from(&atav.value)
639 .unwrap()
640 .to_string(),
641 "Test Certificates 2011"
642 );
643 } else if 2 == counter {
644 assert_eq!(atav.oid.to_string(), "2.5.4.3");
645 assert_eq!(
646 PrintableStringRef::try_from(&atav.value)
647 .unwrap()
648 .to_string(),
649 "Good CA"
650 );
651 }
652 counter += 1;
653 }
654 }
655
656 assert_eq!(
657 cert.tbs_certificate
658 .subject_public_key_info
659 .algorithm
660 .oid
661 .to_string(),
662 "1.2.840.113549.1.1.1"
663 );
664 assert_eq!(
665 cert.tbs_certificate
666 .subject_public_key_info
667 .algorithm
668 .parameters
669 .as_ref()
670 .unwrap()
671 .tag(),
672 Tag::Null
673 );
674 assert_eq!(
675 cert.tbs_certificate
676 .subject_public_key_info
677 .algorithm
678 .parameters
679 .as_ref()
680 .unwrap()
681 .is_null(),
682 true
683 );
684
685 // TODO - parse and compare public key
686
687 counter = 0;
688 let exts = cert.tbs_certificate.extensions.unwrap();
689 let i = exts.iter();
690 for ext in i {
691 if 0 == counter {
692 assert_eq!(
693 ext.extn_id.to_string(),
694 ID_CE_AUTHORITY_KEY_IDENTIFIER.to_string()
695 );
696 assert_eq!(ext.critical, false);
697 let akid = AuthorityKeyIdentifier::from_der(ext.extn_value.as_bytes()).unwrap();
698 assert_eq!(
699 akid.key_identifier.unwrap().as_bytes(),
700 &hex!("E47D5FD15C9586082C05AEBE75B665A7D95DA866")[..]
701 );
702 } else if 1 == counter {
703 assert_eq!(
704 ext.extn_id.to_string(),
705 ID_CE_SUBJECT_KEY_IDENTIFIER.to_string()
706 );
707 assert_eq!(ext.critical, false);
708 let skid = SubjectKeyIdentifier::from_der(ext.extn_value.as_bytes()).unwrap();
709 assert_eq!(
710 skid.0.as_bytes(),
711 &hex!("580184241BBC2B52944A3DA510721451F5AF3AC9")[..]
712 );
713 } else if 2 == counter {
714 assert_eq!(ext.extn_id.to_string(), ID_CE_KEY_USAGE.to_string());
715 assert_eq!(ext.critical, true);
716 let ku = KeyUsage::from_der(ext.extn_value.as_bytes()).unwrap();
717 assert_eq!(KeyUsages::KeyCertSign | KeyUsages::CRLSign, ku);
718 } else if 3 == counter {
719 assert_eq!(
720 ext.extn_id.to_string(),
721 ID_CE_CERTIFICATE_POLICIES.to_string()
722 );
723 assert_eq!(ext.critical, false);
724 let r = CertificatePolicies::from_der(ext.extn_value.as_bytes());
725 let cp = r.unwrap();
726 let i = cp.0.iter();
727 for p in i {
728 assert_eq!(p.policy_identifier.to_string(), "2.16.840.1.101.3.2.1.48.1");
729 }
730 } else if 4 == counter {
731 assert_eq!(ext.extn_id.to_string(), ID_CE_BASIC_CONSTRAINTS.to_string());
732 assert_eq!(ext.critical, true);
733 let bc = BasicConstraints::from_der(ext.extn_value.as_bytes()).unwrap();
734 assert_eq!(bc.ca, true);
735 assert_eq!(bc.path_len_constraint, Option::None);
736 }
737
738 counter += 1;
739 }
740 assert_eq!(
741 cert.signature_algorithm.oid.to_string(),
742 "1.2.840.113549.1.1.11"
743 );
744 assert_eq!(
745 cert.signature_algorithm.parameters.as_ref().unwrap().tag(),
746 Tag::Null
747 );
748 assert_eq!(cert.signature_algorithm.parameters.unwrap().is_null(), true);
749
750 // TODO - parse and compare signature value
751
752 // This cert adds extended key usage and netscape cert type vs above samples
753 let der_encoded_cert = include_bytes!("examples/0954e2343dd5efe0a7f0967d69caf33e5f893720.der");
754 let result = Certificate::from_der(der_encoded_cert);
755 let cert: Certificate = result.unwrap();
756 let exts = cert.tbs_certificate.extensions.unwrap();
757 spin_over_exts(exts);
758
759 // This cert adds extended key usage and name constraints vs above samples
760 let der_encoded_cert = include_bytes!("examples/0fcc78fbbca9f32b08b19b032b84f2c86a128f35.der");
761 let result = Certificate::from_der(der_encoded_cert);
762 let cert: Certificate = result.unwrap();
763 let exts = cert.tbs_certificate.extensions.unwrap();
764 spin_over_exts(exts);
765
766 // This cert adds logotype (which is unrecognized) vs above samples
767 let der_encoded_cert = include_bytes!("examples/15b05c4865410c6b3ff76a4e8f3d87276756bd0c.der");
768 let result = Certificate::from_der(der_encoded_cert);
769 let cert: Certificate = result.unwrap();
770 let exts = cert.tbs_certificate.extensions.unwrap();
771 spin_over_exts(exts);
772
773 // This cert features an EC key unlike the above samples
774 let der_encoded_cert = include_bytes!("examples/16ee54e48c76eaa1052e09010d8faefee95e5ebb.der");
775 let result = Certificate::from_der(der_encoded_cert);
776 let cert: Certificate = result.unwrap();
777 let exts = cert.tbs_certificate.extensions.unwrap();
778 spin_over_exts(exts);
779
780 // This cert adds issuer alt name vs above samples
781 let der_encoded_cert = include_bytes!("examples/342cd9d3062da48c346965297f081ebc2ef68fdc.der");
782 let result = Certificate::from_der(der_encoded_cert);
783 let cert: Certificate = result.unwrap();
784 let exts = cert.tbs_certificate.extensions.unwrap();
785 spin_over_exts(exts);
786
787 // This cert adds policy constraints vs above samples
788 let der_encoded_cert = include_bytes!("examples/2049a5b28f104b2c6e1a08546f9cfc0353d6fd30.der");
789 let result = Certificate::from_der(der_encoded_cert);
790 let cert: Certificate = result.unwrap();
791 let exts = cert.tbs_certificate.extensions.unwrap();
792 spin_over_exts(exts);
793
794 // This cert adds subject alt name vs above samples
795 let der_encoded_cert = include_bytes!("examples/21723e7a0fb61a0bd4a29879b82a02b2fb4ad096.der");
796 let result = Certificate::from_der(der_encoded_cert);
797 let cert: Certificate = result.unwrap();
798 let exts = cert.tbs_certificate.extensions.unwrap();
799 spin_over_exts(exts);
800
801 // This cert adds subject directory attributes vs above samples
802 let der_encoded_cert =
803 include_bytes!("examples/085B1E2F40254F9C7A2387BE9FF4EC116C326E10.fake.der");
804 let result = Certificate::from_der(der_encoded_cert);
805 let cert: Certificate = result.unwrap();
806 let exts = cert.tbs_certificate.extensions.unwrap();
807 spin_over_exts(exts);
808
809 // This cert adds private key usage period (and an unprocessed Entrust extension) vs above samples
810 let der_encoded_cert =
811 include_bytes!("examples/554D5FF11DA613A155584D8D4AA07F67724D8077.fake.der");
812 let result = Certificate::from_der(der_encoded_cert);
813 let cert: Certificate = result.unwrap();
814 let exts = cert.tbs_certificate.extensions.unwrap();
815 spin_over_exts(exts);
816
817 // This cert adds OCSP no check vs above samples
818 let der_encoded_cert =
819 include_bytes!("examples/28879DABB0FD11618FB74E47BE049D2933866D53.fake.der");
820 let result = Certificate::from_der(der_encoded_cert);
821 let cert: Certificate = result.unwrap();
822 let exts = cert.tbs_certificate.extensions.unwrap();
823 spin_over_exts(exts);
824
825 // This cert adds PIV NACI indicator vs above samples
826 let der_encoded_cert =
827 include_bytes!("examples/288C8BCFEE6B89D110DAE2C9873897BF7FF53382.fake.der");
828 let result = Certificate::from_der(der_encoded_cert);
829 let cert: Certificate = result.unwrap();
830 let exts = cert.tbs_certificate.extensions.unwrap();
831 spin_over_exts(exts);
832 }
833
834 #[test]
decode_idp()835 fn decode_idp() {
836 use der::TagNumber;
837
838 // IDP from 04A8739769B3C090A11DCDFABA3CF33F4BEF21F3.crl in PKITS 2048 in ficam-scvp-testing repo
839 let idp = IssuingDistributionPoint::from_der(&hex!("30038201FF")).unwrap();
840 assert_eq!(idp.only_contains_ca_certs, true);
841 assert_eq!(idp.only_contains_attribute_certs, false);
842 assert_eq!(idp.only_contains_user_certs, false);
843 assert_eq!(idp.indirect_crl, false);
844 assert!(idp.only_some_reasons.is_none());
845 assert!(idp.distribution_point.is_none());
846
847 let n =
848 Name::from_der(&hex!("305A310B3009060355040613025553311F301D060355040A131654657374204365727469666963617465732032303137311C301A060355040B13136F6E6C79536F6D65526561736F6E7320434133310C300A0603550403130343524C")).unwrap();
849 assert_eq!(4, n.0.len());
850
851 let gn =
852 GeneralName::from_der(&hex!("A45C305A310B3009060355040613025553311F301D060355040A131654657374204365727469666963617465732032303137311C301A060355040B13136F6E6C79536F6D65526561736F6E7320434133310C300A0603550403130343524C")).unwrap();
853 match gn {
854 GeneralName::DirectoryName(gn) => {
855 assert_eq!(4, gn.0.len());
856 }
857 _ => {}
858 }
859
860 let gns =
861 GeneralNames::from_der(&hex!("305EA45C305A310B3009060355040613025553311F301D060355040A131654657374204365727469666963617465732032303137311C301A060355040B13136F6E6C79536F6D65526561736F6E7320434133310C300A0603550403130343524C")).unwrap();
862 assert_eq!(1, gns.len());
863 let gn = gns.get(0).unwrap();
864 match gn {
865 GeneralName::DirectoryName(gn) => {
866 assert_eq!(4, gn.0.len());
867 }
868 _ => {}
869 }
870
871 //TODO - fix decode impl (expecting a SEQUENCE despite this being a CHOICE). Sort out FixedTag implementation.
872 // let dpn =
873 // DistributionPointName::from_der(&hex!("A05EA45C305A310B3009060355040613025553311F301D060355040A131654657374204365727469666963617465732032303137311C301A060355040B13136F6E6C79536F6D65526561736F6E7320434133310C300A0603550403130343524C")).unwrap();
874 // match dpn {
875 // DistributionPointName::FullName(dpn) => {
876 // assert_eq!(1, dpn.len());
877 // let gn = dpn.get(0).unwrap();
878 // match gn {
879 // GeneralName::DirectoryName(gn) => {
880 // assert_eq!(4, gn.len());
881 // }
882 // _ => {}
883 // }
884 // }
885 // _ => {}
886 // }
887
888 let dp =
889 DistributionPoint::from_der(&hex!("3062A060A05EA45C305A310B3009060355040613025553311F301D060355040A131654657374204365727469666963617465732032303137311C301A060355040B13136F6E6C79536F6D65526561736F6E7320434133310C300A0603550403130343524C")).unwrap();
890 let dpn = dp.distribution_point.unwrap();
891 match dpn {
892 DistributionPointName::FullName(dpn) => {
893 assert_eq!(1, dpn.len());
894 let gn = dpn.get(0).unwrap();
895 match gn {
896 GeneralName::DirectoryName(gn) => {
897 assert_eq!(4, gn.0.len());
898 }
899 _ => {}
900 }
901 }
902 _ => {}
903 }
904 assert!(dp.crl_issuer.is_none());
905 assert!(dp.reasons.is_none());
906
907 // 0 103: SEQUENCE {
908 // 2 96: [0] {
909 // 4 94: [0] {
910 // 6 92: [4] {
911 // 8 90: SEQUENCE {
912 // 10 11: SET {
913 // 12 9: SEQUENCE {
914 // 14 3: OBJECT IDENTIFIER countryName (2 5 4 6)
915 // 19 2: PrintableString 'US'
916 // : }
917 // : }
918 // 23 31: SET {
919 // 25 29: SEQUENCE {
920 // 27 3: OBJECT IDENTIFIER organizationName (2 5 4 10)
921 // 32 22: PrintableString 'Test Certificates 2017'
922 // : }
923 // : }
924 // 56 28: SET {
925 // 58 26: SEQUENCE {
926 // 60 3: OBJECT IDENTIFIER organizationalUnitName (2 5 4 11)
927 // 65 19: PrintableString 'onlySomeReasons CA3'
928 // : }
929 // : }
930 // 86 12: SET {
931 // 88 10: SEQUENCE {
932 // 90 3: OBJECT IDENTIFIER commonName (2 5 4 3)
933 // 95 3: PrintableString 'CRL'
934 // : }
935 // : }
936 // : }
937 // : }
938 // : }
939 // : }
940 // 100 3: [3] 07 9F 80
941 // : }
942 // IDP from 54B0D2A6F6AA4780771CC4F9F076F623CEB0F57E.crl in PKITS 2048 in ficam-scvp-testing repo
943 let idp =
944 IssuingDistributionPoint::from_der(&hex!("3067A060A05EA45C305A310B3009060355040613025553311F301D060355040A131654657374204365727469666963617465732032303137311C301A060355040B13136F6E6C79536F6D65526561736F6E7320434133310C300A0603550403130343524C8303079F80")).unwrap();
945 assert_eq!(idp.only_contains_ca_certs, false);
946 assert_eq!(idp.only_contains_attribute_certs, false);
947 assert_eq!(idp.only_contains_user_certs, false);
948 assert_eq!(idp.indirect_crl, false);
949 assert!(idp.only_some_reasons.is_some());
950 assert!(idp.distribution_point.is_some());
951
952 assert_eq!(
953 Reasons::Unused
954 | Reasons::AffiliationChanged
955 | Reasons::Superseded
956 | Reasons::CessationOfOperation
957 | Reasons::CertificateHold
958 | Reasons::PrivilegeWithdrawn
959 | Reasons::AaCompromise,
960 idp.only_some_reasons.unwrap()
961 );
962
963 // 930 360: SEQUENCE {
964 // 934 353: [0] {
965 // 938 349: [0] {
966 // 942 117: [4] {
967 // 944 115: SEQUENCE {
968 // 946 11: SET {
969 // 948 9: SEQUENCE {
970 // 950 3: OBJECT IDENTIFIER countryName (2 5 4 6)
971 // 955 2: PrintableString 'US'
972 // : }
973 // : }
974 // 959 31: SET {
975 // 961 29: SEQUENCE {
976 // 963 3: OBJECT IDENTIFIER
977 // : organizationName (2 5 4 10)
978 // 968 22: PrintableString 'Test Certificates 2017'
979 // : }
980 // : }
981 // 992 24: SET {
982 // 994 22: SEQUENCE {
983 // 996 3: OBJECT IDENTIFIER
984 // : organizationalUnitName (2 5 4 11)
985 // 1001 15: PrintableString 'indirectCRL CA5'
986 // : }
987 // : }
988 // 1018 41: SET {
989 // 1020 39: SEQUENCE {
990 // 1022 3: OBJECT IDENTIFIER commonName (2 5 4 3)
991 // 1027 32: PrintableString 'indirect CRL for indirectCRL CA6'
992 // : }
993 // : }
994 // : }
995 // : }
996 // 1061 117: [4] {
997 // 1063 115: SEQUENCE {
998 // 1065 11: SET {
999 // 1067 9: SEQUENCE {
1000 // 1069 3: OBJECT IDENTIFIER countryName (2 5 4 6)
1001 // 1074 2: PrintableString 'US'
1002 // : }
1003 // : }
1004 // 1078 31: SET {
1005 // 1080 29: SEQUENCE {
1006 // 1082 3: OBJECT IDENTIFIER
1007 // : organizationName (2 5 4 10)
1008 // 1087 22: PrintableString 'Test Certificates 2017'
1009 // : }
1010 // : }
1011 // 1111 24: SET {
1012 // 1113 22: SEQUENCE {
1013 // 1115 3: OBJECT IDENTIFIER
1014 // : organizationalUnitName (2 5 4 11)
1015 // 1120 15: PrintableString 'indirectCRL CA5'
1016 // : }
1017 // : }
1018 // 1137 41: SET {
1019 // 1139 39: SEQUENCE {
1020 // 1141 3: OBJECT IDENTIFIER commonName (2 5 4 3)
1021 // 1146 32: PrintableString 'indirect CRL for indirectCRL CA7'
1022 // : }
1023 // : }
1024 // : }
1025 // : }
1026 // 1180 109: [4] {
1027 // 1182 107: SEQUENCE {
1028 // 1184 11: SET {
1029 // 1186 9: SEQUENCE {
1030 // 1188 3: OBJECT IDENTIFIER countryName (2 5 4 6)
1031 // 1193 2: PrintableString 'US'
1032 // : }
1033 // : }
1034 // 1197 31: SET {
1035 // 1199 29: SEQUENCE {
1036 // 1201 3: OBJECT IDENTIFIER
1037 // : organizationName (2 5 4 10)
1038 // 1206 22: PrintableString 'Test Certificates 2017'
1039 // : }
1040 // : }
1041 // 1230 24: SET {
1042 // 1232 22: SEQUENCE {
1043 // 1234 3: OBJECT IDENTIFIER
1044 // : organizationalUnitName (2 5 4 11)
1045 // 1239 15: PrintableString 'indirectCRL CA5'
1046 // : }
1047 // : }
1048 // 1256 33: SET {
1049 // 1258 31: SEQUENCE {
1050 // 1260 3: OBJECT IDENTIFIER commonName (2 5 4 3)
1051 // 1265 24: PrintableString 'CRL1 for indirectCRL CA5'
1052 // : }
1053 // : }
1054 // : }
1055 // : }
1056 // : }
1057 // : }
1058 // 1291 1: [4] FF
1059 // : }
1060 // : }
1061 // : }
1062 // IDP from 959528526E54B646AF895E2362D3AD20F4B3284D.crl in PKITS 2048 in ficam-scvp-testing repo
1063 let idp =
1064 IssuingDistributionPoint::from_der(&hex!("30820168A0820161A082015DA4753073310B3009060355040613025553311F301D060355040A13165465737420436572746966696361746573203230313731183016060355040B130F696E64697265637443524C204341353129302706035504031320696E6469726563742043524C20666F7220696E64697265637443524C20434136A4753073310B3009060355040613025553311F301D060355040A13165465737420436572746966696361746573203230313731183016060355040B130F696E64697265637443524C204341353129302706035504031320696E6469726563742043524C20666F7220696E64697265637443524C20434137A46D306B310B3009060355040613025553311F301D060355040A13165465737420436572746966696361746573203230313731183016060355040B130F696E64697265637443524C204341353121301F0603550403131843524C3120666F7220696E64697265637443524C204341358401FF")).unwrap();
1065 assert_eq!(idp.only_contains_ca_certs, false);
1066 assert_eq!(idp.only_contains_attribute_certs, false);
1067 assert_eq!(idp.only_contains_user_certs, false);
1068 assert_eq!(idp.indirect_crl, true);
1069 assert!(idp.only_some_reasons.is_none());
1070 assert!(idp.distribution_point.is_some());
1071 let dp = idp.distribution_point.unwrap();
1072 match dp {
1073 DistributionPointName::FullName(dp) => {
1074 assert_eq!(3, dp.len());
1075 for gn in dp {
1076 match gn {
1077 GeneralName::DirectoryName(gn) => {
1078 assert_eq!(4, gn.0.len());
1079 }
1080 _ => {
1081 panic!("Expected DirectoryName")
1082 }
1083 }
1084 }
1085 }
1086 _ => {
1087 panic!("Expected FullName")
1088 }
1089 }
1090
1091 // Tag on second RDN in first name is TeletexString (20) instead of PrintableString (19)
1092 let idp =
1093 IssuingDistributionPoint::from_der(&hex!("30820168A0820161A082015DA4753073310B3009060355040613025553311F301D060355040A14165465737420436572746966696361746573203230313731183016060355040B130F696E64697265637443524C204341353129302706035504031320696E6469726563742043524C20666F7220696E64697265637443524C20434136A4753073310B3009060355040613025553311F301D060355040A13165465737420436572746966696361746573203230313731183016060355040B130F696E64697265637443524C204341353129302706035504031320696E6469726563742043524C20666F7220696E64697265637443524C20434137A46D306B310B3009060355040613025553311F301D060355040A13165465737420436572746966696361746573203230313731183016060355040B130F696E64697265637443524C204341353121301F0603550403131843524C3120666F7220696E64697265637443524C204341358401FF")).unwrap();
1094 assert_eq!(idp.only_contains_ca_certs, false);
1095 assert_eq!(idp.only_contains_attribute_certs, false);
1096 assert_eq!(idp.only_contains_user_certs, false);
1097 assert_eq!(idp.indirect_crl, true);
1098 assert!(idp.only_some_reasons.is_none());
1099 assert!(idp.distribution_point.is_some());
1100 let dp = idp.distribution_point.unwrap();
1101 match dp {
1102 DistributionPointName::FullName(dp) => {
1103 assert_eq!(3, dp.len());
1104 for gn in dp {
1105 match gn {
1106 GeneralName::DirectoryName(gn) => {
1107 assert_eq!(4, gn.0.len());
1108 }
1109 _ => {
1110 panic!("Expected DirectoryName")
1111 }
1112 }
1113 }
1114 }
1115 _ => {
1116 panic!("Expected FullName")
1117 }
1118 }
1119
1120 //---------------------------------
1121 // Negative tests
1122 //---------------------------------
1123 // Value contains more than length value indicates
1124 let reason_flags = ReasonFlags::from_der(&hex!("0302079F80"));
1125 let err = reason_flags.err().unwrap();
1126 assert_eq!(
1127 ErrorKind::TrailingData {
1128 decoded: 4u8.into(),
1129 remaining: 1u8.into()
1130 },
1131 err.kind()
1132 );
1133
1134 // Value incomplete relative to length value
1135 let reason_flags = ReasonFlags::from_der(&hex!("0304079F80"));
1136 let err = reason_flags.err().unwrap();
1137 assert_eq!(
1138 ErrorKind::Incomplete {
1139 expected_len: 6u8.into(),
1140 actual_len: 5u8.into()
1141 },
1142 err.kind()
1143 );
1144
1145 // Value incomplete relative to length value
1146 let idp =
1147 IssuingDistributionPoint::from_der(&hex!("3067A060A05EA45C305A310B3009060355040613025553311F301D060355040A131654657374204365727469666963617465732032303137311C301A060355040B13136F6E6C79536F6D65526561736F6E7320434133310C300A0603550403130343524C8304079F80"));
1148 let err = idp.err().unwrap();
1149 assert_eq!(err.position().unwrap(), 103u8.into());
1150 assert_eq!(
1151 ErrorKind::Incomplete {
1152 expected_len: 106u8.into(),
1153 actual_len: 105u8.into()
1154 },
1155 err.kind()
1156 );
1157
1158 // Truncated
1159 let reason_flags = ReasonFlags::from_der(&hex!("0303079F"));
1160 let err = reason_flags.err().unwrap();
1161 assert_eq!(
1162 ErrorKind::Incomplete {
1163 expected_len: 5u8.into(),
1164 actual_len: 4u8.into()
1165 },
1166 err.kind()
1167 );
1168
1169 // Nonsensical tag where BIT STRING tag should be
1170 let reason_flags = ReasonFlags::from_der(&hex!("FF03079F80"));
1171 let err = reason_flags.err().unwrap();
1172 assert_eq!(ErrorKind::TagNumberInvalid, err.kind());
1173
1174 // INTEGER tag where BIT STRING expected
1175 let reason_flags = ReasonFlags::from_der(&hex!("0203079F80"));
1176 let err = reason_flags.err().unwrap();
1177 assert_eq!(
1178 ErrorKind::TagUnexpected {
1179 expected: Some(Tag::BitString),
1180 actual: Tag::Integer
1181 },
1182 err.kind()
1183 );
1184
1185 // Context specific tag that should be primitive is constructed
1186 let idp = IssuingDistributionPoint::from_der(&hex!("3003A201FF"));
1187 let err = idp.err().unwrap();
1188 assert_eq!(
1189 ErrorKind::Noncanonical {
1190 tag: Tag::ContextSpecific {
1191 constructed: true,
1192 number: TagNumber::new(2)
1193 }
1194 },
1195 err.kind()
1196 );
1197
1198 // Boolean value is two bytes long
1199 let idp =
1200 IssuingDistributionPoint::from_der(&hex!("30820168A0820161A082015DA4753073310B3009060355040613025553311F301D060355040A13165465737420436572746966696361746573203230313731183016060355040B130F696E64697265637443524C204341353129302706035504031320696E6469726563742043524C20666F7220696E64697265637443524C20434136A4753073310B3009060355040613025553311F301D060355040A13165465737420436572746966696361746573203230313731183016060355040B130F696E64697265637443524C204341353129302706035504031320696E6469726563742043524C20666F7220696E64697265637443524C20434137A46D306B310B3009060355040613025553311F301D060355040A13165465737420436572746966696361746573203230313731183016060355040B130F696E64697265637443524C204341353121301F0603550403131843524C3120666F7220696E64697265637443524C204341358402FFFF"));
1201 let err = idp.err().unwrap();
1202 assert_eq!(ErrorKind::Length { tag: Tag::Boolean }, err.kind());
1203
1204 // Boolean value is neither 0x00 nor 0xFF
1205 let idp =
1206 IssuingDistributionPoint::from_der(&hex!("30820168A0820161A082015DA4753073310B3009060355040613025553311F301D060355040A13165465737420436572746966696361746573203230313731183016060355040B130F696E64697265637443524C204341353129302706035504031320696E6469726563742043524C20666F7220696E64697265637443524C20434136A4753073310B3009060355040613025553311F301D060355040A13165465737420436572746966696361746573203230313731183016060355040B130F696E64697265637443524C204341353129302706035504031320696E6469726563742043524C20666F7220696E64697265637443524C20434137A46D306B310B3009060355040613025553311F301D060355040A13165465737420436572746966696361746573203230313731183016060355040B130F696E64697265637443524C204341353121301F0603550403131843524C3120666F7220696E64697265637443524C20434135840175"));
1207 let err = idp.err().unwrap();
1208 assert_eq!(ErrorKind::Noncanonical { tag: Tag::Boolean }, err.kind());
1209
1210 // Length on second RDN in first name indicates more bytes than are present
1211 let idp =
1212 IssuingDistributionPoint::from_der(&hex!("30820168A0820161A082015DA4753073310B3009060355040613025553311F301D060355040A13995465737420436572746966696361746573203230313731183016060355040B130F696E64697265637443524C204341353129302706035504031320696E6469726563742043524C20666F7220696E64697265637443524C20434136A4753073310B3009060355040613025553311F301D060355040A13165465737420436572746966696361746573203230313731183016060355040B130F696E64697265637443524C204341353129302706035504031320696E6469726563742043524C20666F7220696E64697265637443524C20434137A46D306B310B3009060355040613025553311F301D060355040A13165465737420436572746966696361746573203230313731183016060355040B130F696E64697265637443524C204341353121301F0603550403131843524C3120666F7220696E64697265637443524C204341358401FF"));
1213 let err = idp.err().unwrap();
1214 assert_eq!(
1215 ErrorKind::Length {
1216 tag: Tag::PrintableString
1217 },
1218 err.kind()
1219 );
1220 }
1221