• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 use der::{
2     asn1::{Ia5StringRef, PrintableStringRef},
3     Decode, Encode, SliceReader,
4 };
5 use hex_literal::hex;
6 use x509_cert::anchor::{CertPolicies, TrustAnchorChoice};
7 use x509_cert::ext::pkix::name::GeneralName;
8 
9 #[test]
decode_ta1()10 fn decode_ta1() {
11     // features an ECA cert wrapped in a TrustAnchorInfo that contains a pile of certificate policies
12     // in the cert path controls field
13     let der_encoded_tac = include_bytes!("examples/eca_policies.ta");
14     let der_encoded_cert = include_bytes!("examples/eca.der");
15 
16     let mut decoder = SliceReader::new(der_encoded_tac).unwrap();
17     let tac = TrustAnchorChoice::decode(&mut decoder).unwrap();
18     let reencoded_tac = tac.to_der().unwrap();
19     println!("Original : {:02X?}", der_encoded_cert);
20     println!("Reencoded: {:02X?}", reencoded_tac);
21     assert_eq!(der_encoded_tac, reencoded_tac.as_slice());
22 
23     match tac {
24         TrustAnchorChoice::TaInfo(tai) => {
25             assert_eq!(
26                 tai.pub_key.algorithm.oid.to_string(),
27                 "1.2.840.113549.1.1.1"
28             );
29 
30             assert_eq!(
31                 &hex!("335BA56F7A55602B814B2614CC79BF4ABA8B32BD"),
32                 tai.key_id.as_bytes()
33             );
34 
35             let policy_ids: [&str; 42] = [
36                 "1.2.36.1.334.1.2.1.2",
37                 "1.2.840.113549.5.6.1.3.1.12",
38                 "1.2.840.113549.5.6.1.3.1.18",
39                 "1.3.6.1.4.1.103.100.1.1.3.1",
40                 "1.3.6.1.4.1.13948.1.1.1.2",
41                 "1.3.6.1.4.1.13948.1.1.1.6",
42                 "1.3.6.1.4.1.1569.10.1.1",
43                 "1.3.6.1.4.1.1569.10.1.2",
44                 "1.3.6.1.4.1.16304.3.6.2.12",
45                 "1.3.6.1.4.1.16304.3.6.2.20",
46                 "1.3.6.1.4.1.16334.509.2.6",
47                 "1.3.6.1.4.1.23337.1.1.10",
48                 "1.3.6.1.4.1.23337.1.1.8",
49                 "1.3.6.1.4.1.2396.2.1.2",
50                 "1.3.6.1.4.1.2396.2.1.7",
51                 "1.3.6.1.4.1.24019.1.1.1.18",
52                 "1.3.6.1.4.1.24019.1.1.1.19",
53                 "1.3.6.1.4.1.24019.1.1.1.2",
54                 "1.3.6.1.4.1.24019.1.1.1.7",
55                 "1.3.6.1.4.1.73.15.3.1.12",
56                 "1.3.6.1.4.1.73.15.3.1.5",
57                 "2.16.528.1.1003.1.2.5.1",
58                 "2.16.528.1.1003.1.2.5.2",
59                 "2.16.840.1.101.2.1.11.19",
60                 "2.16.840.1.101.3.2.1.12.2",
61                 "2.16.840.1.101.3.2.1.12.3",
62                 "2.16.840.1.101.3.2.1.3.12",
63                 "2.16.840.1.101.3.2.1.3.13",
64                 "2.16.840.1.101.3.2.1.3.16",
65                 "2.16.840.1.101.3.2.1.3.18",
66                 "2.16.840.1.101.3.2.1.3.24",
67                 "2.16.840.1.101.3.2.1.3.4",
68                 "2.16.840.1.101.3.2.1.3.7",
69                 "2.16.840.1.101.3.2.1.5.4",
70                 "2.16.840.1.101.3.2.1.5.5",
71                 "2.16.840.1.101.3.2.1.6.12",
72                 "2.16.840.1.101.3.2.1.6.4",
73                 "2.16.840.1.113733.1.7.23.3.1.18",
74                 "2.16.840.1.113733.1.7.23.3.1.7",
75                 "2.16.840.1.114027.200.3.10.7.2",
76                 "2.16.840.1.114027.200.3.10.7.4",
77                 "2.16.840.1.114027.200.3.10.7.6",
78             ];
79 
80             let cert_path = tai.cert_path.as_ref().unwrap();
81             let mut counter = 0;
82             let exts = cert_path.policy_set.as_ref().unwrap();
83             let i = exts.0.iter();
84             for ext in i {
85                 assert_eq!(policy_ids[counter], ext.policy_identifier.to_string());
86                 counter += 1;
87             }
88 
89             counter = 0;
90             let i = cert_path.ta_name.0.iter();
91             for rdn in i {
92                 let i1 = rdn.0.iter();
93                 for atav in i1 {
94                     if 0 == counter {
95                         assert_eq!(atav.oid.to_string(), "2.5.4.6");
96                         assert_eq!(
97                             PrintableStringRef::try_from(&atav.value)
98                                 .unwrap()
99                                 .to_string(),
100                             "US"
101                         );
102                     } else if 1 == counter {
103                         assert_eq!(atav.oid.to_string(), "2.5.4.10");
104                         assert_eq!(
105                             PrintableStringRef::try_from(&atav.value)
106                                 .unwrap()
107                                 .to_string(),
108                             "U.S. Government"
109                         );
110                     } else if 2 == counter {
111                         assert_eq!(atav.oid.to_string(), "2.5.4.11");
112                         assert_eq!(
113                             PrintableStringRef::try_from(&atav.value)
114                                 .unwrap()
115                                 .to_string(),
116                             "ECA"
117                         );
118                     } else if 3 == counter {
119                         assert_eq!(atav.oid.to_string(), "2.5.4.3");
120                         assert_eq!(
121                             PrintableStringRef::try_from(&atav.value)
122                                 .unwrap()
123                                 .to_string(),
124                             "ECA Root CA 4"
125                         );
126                     }
127                     counter += 1;
128                 }
129             }
130 
131             let reencoded_cert = cert_path.certificate.to_der().unwrap();
132             assert_eq!(der_encoded_cert, reencoded_cert.as_slice());
133         }
134         _ => panic!("Unexpected TrustAnchorChoice contents"),
135     }
136 }
137 
138 #[test]
decode_ta2()139 fn decode_ta2() {
140     // features an Entrust cert wrapped in a TrustAnchorInfo that contains an excluded subtree in the
141     // name constraint in the cert path controls field
142     let der_encoded_tac = include_bytes!("examples/entrust_dnConstraint.ta");
143     let der_encoded_cert = include_bytes!("examples/entrust.der");
144 
145     let mut decoder = SliceReader::new(der_encoded_tac).unwrap();
146     let tac = TrustAnchorChoice::decode(&mut decoder).unwrap();
147     let reencoded_tac = tac.to_der().unwrap();
148     println!("Original : {:02X?}", der_encoded_cert);
149     println!("Reencoded: {:02X?}", reencoded_tac);
150     assert_eq!(der_encoded_tac, reencoded_tac.as_slice());
151 
152     match tac {
153         TrustAnchorChoice::TaInfo(tai) => {
154             assert_eq!(
155                 tai.pub_key.algorithm.oid.to_string(),
156                 "1.2.840.113549.1.1.1"
157             );
158 
159             assert_eq!(
160                 &hex!("1A74551E8A85089F505D3E8A46018A819CF99E1E"),
161                 tai.key_id.as_bytes()
162             );
163 
164             let cert_path = tai.cert_path.as_ref().unwrap();
165 
166             let mut counter = 0;
167             let i = cert_path.ta_name.0.iter();
168             for rdn in i {
169                 let i1 = rdn.0.iter();
170                 for atav in i1 {
171                     if 0 == counter {
172                         assert_eq!(atav.oid.to_string(), "2.5.4.6");
173                         assert_eq!(
174                             PrintableStringRef::try_from(&atav.value)
175                                 .unwrap()
176                                 .to_string(),
177                             "US"
178                         );
179                     } else if 1 == counter {
180                         assert_eq!(atav.oid.to_string(), "2.5.4.10");
181                         assert_eq!(
182                             PrintableStringRef::try_from(&atav.value)
183                                 .unwrap()
184                                 .to_string(),
185                             "Entrust"
186                         );
187                     } else if 2 == counter {
188                         assert_eq!(atav.oid.to_string(), "2.5.4.11");
189                         assert_eq!(
190                             PrintableStringRef::try_from(&atav.value)
191                                 .unwrap()
192                                 .to_string(),
193                             "Certification Authorities"
194                         );
195                     } else if 3 == counter {
196                         assert_eq!(atav.oid.to_string(), "2.5.4.11");
197                         assert_eq!(
198                             PrintableStringRef::try_from(&atav.value)
199                                 .unwrap()
200                                 .to_string(),
201                             "Entrust Managed Services NFI Root CA"
202                         );
203                     }
204                     counter += 1;
205                 }
206             }
207 
208             let nc = cert_path.name_constr.as_ref().unwrap();
209             counter = 0;
210             let gsi = nc.excluded_subtrees.as_ref().unwrap().iter();
211             for gs in gsi {
212                 match &gs.base {
213                     GeneralName::DirectoryName(dn) => {
214                         let i = dn.0.iter();
215                         for rdn in i {
216                             let i1 = rdn.0.iter();
217                             for atav in i1 {
218                                 if 0 == counter {
219                                     assert_eq!(atav.oid.to_string(), "2.5.4.6");
220                                     assert_eq!(
221                                         PrintableStringRef::try_from(&atav.value)
222                                             .unwrap()
223                                             .to_string(),
224                                         "US"
225                                     );
226                                 } else if 1 == counter {
227                                     assert_eq!(atav.oid.to_string(), "2.5.4.10");
228                                     assert_eq!(
229                                         PrintableStringRef::try_from(&atav.value)
230                                             .unwrap()
231                                             .to_string(),
232                                         "U.S. Government"
233                                     );
234                                 } else if 2 == counter {
235                                     assert_eq!(atav.oid.to_string(), "2.5.4.11");
236                                     assert_eq!(
237                                         PrintableStringRef::try_from(&atav.value)
238                                             .unwrap()
239                                             .to_string(),
240                                         "DoD"
241                                     );
242                                 }
243                                 counter += 1;
244                             }
245                         }
246                     }
247                     _ => panic!("Unexpected GeneralSubtree type"),
248                 }
249             }
250 
251             let reencoded_cert = cert_path.certificate.to_der().unwrap();
252             assert_eq!(der_encoded_cert, reencoded_cert.as_slice());
253         }
254         _ => panic!("Unexpected TrustAnchorChoice contents"),
255     }
256 }
257 
258 #[test]
decode_ta3()259 fn decode_ta3() {
260     // features an Exostar cert wrapped in a TrustAnchorInfo that contains an excluded subtree in the
261     // name constraint and policy flags in the cert path controls field
262     let der_encoded_tac = include_bytes!("examples/exostar_policyFlags.ta");
263     let der_encoded_cert = include_bytes!("examples/exostar.der");
264 
265     let mut decoder = SliceReader::new(der_encoded_tac).unwrap();
266     let tac = TrustAnchorChoice::decode(&mut decoder).unwrap();
267     let reencoded_tac = tac.to_der().unwrap();
268     println!("Original : {:02X?}", der_encoded_cert);
269     println!("Reencoded: {:02X?}", reencoded_tac);
270     assert_eq!(der_encoded_tac, reencoded_tac.as_slice());
271 
272     match tac {
273         TrustAnchorChoice::TaInfo(tai) => {
274             assert_eq!(
275                 tai.pub_key.algorithm.oid.to_string(),
276                 "1.2.840.113549.1.1.1"
277             );
278 
279             assert_eq!(
280                 &hex!("2EBE91A6776A373CF5FD1DB6DD78C9A6E5F42220"),
281                 tai.key_id.as_bytes()
282             );
283 
284             let cert_path = tai.cert_path.as_ref().unwrap();
285 
286             assert_eq!(
287                 CertPolicies::InhibitPolicyMapping
288                     | CertPolicies::RequireExplicitPolicy
289                     | CertPolicies::InhibitAnyPolicy,
290                 cert_path.policy_flags.unwrap()
291             );
292 
293             let mut counter = 0;
294             let i = cert_path.ta_name.0.iter();
295             for rdn in i {
296                 let i1 = rdn.0.iter();
297                 for atav in i1 {
298                     if 0 == counter {
299                         assert_eq!(atav.oid.to_string(), "2.5.4.6");
300                         assert_eq!(
301                             PrintableStringRef::try_from(&atav.value)
302                                 .unwrap()
303                                 .to_string(),
304                             "US"
305                         );
306                     } else if 1 == counter {
307                         assert_eq!(atav.oid.to_string(), "2.5.4.10");
308                         assert_eq!(
309                             PrintableStringRef::try_from(&atav.value)
310                                 .unwrap()
311                                 .to_string(),
312                             "Exostar LLC"
313                         );
314                     } else if 2 == counter {
315                         assert_eq!(atav.oid.to_string(), "2.5.4.11");
316                         assert_eq!(
317                             PrintableStringRef::try_from(&atav.value)
318                                 .unwrap()
319                                 .to_string(),
320                             "Certification Authorities"
321                         );
322                     } else if 3 == counter {
323                         assert_eq!(atav.oid.to_string(), "2.5.4.3");
324                         assert_eq!(
325                             PrintableStringRef::try_from(&atav.value)
326                                 .unwrap()
327                                 .to_string(),
328                             "Exostar Federated Identity Service Root CA 1"
329                         );
330                     }
331                     counter += 1;
332                 }
333             }
334 
335             let nc = cert_path.name_constr.as_ref().unwrap();
336             counter = 0;
337             let gsi = nc.excluded_subtrees.as_ref().unwrap().iter();
338             for gs in gsi {
339                 match &gs.base {
340                     GeneralName::DirectoryName(dn) => {
341                         let i = dn.0.iter();
342                         for rdn in i {
343                             let i1 = rdn.0.iter();
344                             for atav in i1 {
345                                 if 0 == counter {
346                                     assert_eq!(atav.oid.to_string(), "2.5.4.6");
347                                     assert_eq!(
348                                         PrintableStringRef::try_from(&atav.value)
349                                             .unwrap()
350                                             .to_string(),
351                                         "US"
352                                     );
353                                 } else if 1 == counter {
354                                     assert_eq!(atav.oid.to_string(), "2.5.4.10");
355                                     assert_eq!(
356                                         PrintableStringRef::try_from(&atav.value)
357                                             .unwrap()
358                                             .to_string(),
359                                         "U.S. Government"
360                                     );
361                                 } else if 2 == counter {
362                                     assert_eq!(atav.oid.to_string(), "2.5.4.11");
363                                     assert_eq!(
364                                         PrintableStringRef::try_from(&atav.value)
365                                             .unwrap()
366                                             .to_string(),
367                                         "DoD"
368                                     );
369                                 }
370                                 counter += 1;
371                             }
372                         }
373                     }
374                     _ => panic!("Unexpected GeneralSubtree type"),
375                 }
376             }
377 
378             let reencoded_cert = cert_path.certificate.to_der().unwrap();
379             assert_eq!(der_encoded_cert, reencoded_cert.as_slice());
380         }
381         _ => panic!("Unexpected TrustAnchorChoice contents"),
382     }
383 }
384 
385 #[test]
decode_ta4()386 fn decode_ta4() {
387     // features an Exostar cert wrapped in a TrustAnchorInfo that contains path length constraint in
388     // the cert path controls field
389     let der_encoded_tac = include_bytes!("examples/raytheon_pathLenConstraint.ta");
390     let der_encoded_cert = include_bytes!("examples/raytheon.der");
391 
392     let mut decoder = SliceReader::new(der_encoded_tac).unwrap();
393     let tac = TrustAnchorChoice::decode(&mut decoder).unwrap();
394     let reencoded_tac = tac.to_der().unwrap();
395     println!("Original : {:02X?}", der_encoded_cert);
396     println!("Reencoded: {:02X?}", reencoded_tac);
397     assert_eq!(der_encoded_tac, reencoded_tac.as_slice());
398 
399     match tac {
400         TrustAnchorChoice::TaInfo(tai) => {
401             assert_eq!(
402                 tai.pub_key.algorithm.oid.to_string(),
403                 "1.2.840.113549.1.1.1"
404             );
405 
406             assert_eq!(
407                 &hex!("283086D556154210425CF07B1C11B28389D47920"),
408                 tai.key_id.as_bytes()
409             );
410 
411             let cert_path = tai.cert_path.as_ref().unwrap();
412 
413             let mut counter = 0;
414             let i = cert_path.ta_name.0.iter();
415             for rdn in i {
416                 let i1 = rdn.0.iter();
417                 for atav in i1 {
418                     if 0 == counter {
419                         assert_eq!(atav.oid.to_string(), "0.9.2342.19200300.100.1.25");
420                         assert_eq!(
421                             Ia5StringRef::try_from(&atav.value).unwrap().to_string(),
422                             "com"
423                         );
424                     } else if 1 == counter {
425                         assert_eq!(atav.oid.to_string(), "0.9.2342.19200300.100.1.25");
426                         assert_eq!(
427                             Ia5StringRef::try_from(&atav.value).unwrap().to_string(),
428                             "raytheon"
429                         );
430                     } else if 2 == counter {
431                         assert_eq!(atav.oid.to_string(), "2.5.4.10");
432                         assert_eq!(
433                             PrintableStringRef::try_from(&atav.value)
434                                 .unwrap()
435                                 .to_string(),
436                             "CAs"
437                         );
438                     } else if 3 == counter {
439                         assert_eq!(atav.oid.to_string(), "2.5.4.11");
440                         assert_eq!(
441                             PrintableStringRef::try_from(&atav.value)
442                                 .unwrap()
443                                 .to_string(),
444                             "RaytheonRoot"
445                         );
446                     }
447                     counter += 1;
448                 }
449             }
450 
451             let pl = cert_path.path_len_constraint.unwrap();
452             if 2 != pl {
453                 panic!("Wrong path length constraint");
454             }
455 
456             let reencoded_cert = cert_path.certificate.to_der().unwrap();
457             assert_eq!(der_encoded_cert, reencoded_cert.as_slice());
458         }
459         _ => panic!("Unexpected TrustAnchorChoice contents"),
460     }
461 }
462