• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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