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