1 //! Certificate tests
2 
3 use der::{
4     asn1::{BitStringRef, ContextSpecific, ObjectIdentifier, PrintableStringRef, Utf8StringRef},
5     Decode, DecodeValue, Encode, FixedTag, Header, Reader, Tag, Tagged,
6 };
7 use hex_literal::hex;
8 use spki::AlgorithmIdentifierRef;
9 use x509_cert::serial_number::SerialNumber;
10 use x509_cert::Certificate;
11 use x509_cert::*;
12 
13 #[cfg(feature = "pem")]
14 use der::DecodePem;
15 
16 // TODO - parse and compare extension values
17 const EXTENSIONS: &[(&str, bool)] = &[
18     ("2.5.29.15", true),
19     ("2.5.29.19", true),
20     ("2.5.29.33", false),
21     ("2.5.29.32", false),
22     ("2.5.29.14", false),
23     ("2.5.29.31", false),
24     ("1.3.6.1.5.5.7.1.11", false),
25     ("1.3.6.1.5.5.7.1.1", false),
26     ("2.5.29.54", false),
27     ("2.5.29.35", false),
28 ];
29 
30 ///Structure supporting deferred decoding of fields in the Certificate SEQUENCE
31 pub struct DeferDecodeCertificate<'a> {
32     /// tbsCertificate       TBSCertificate,
33     pub tbs_certificate: &'a [u8],
34     /// signatureAlgorithm   AlgorithmIdentifier,
35     pub signature_algorithm: &'a [u8],
36     /// signature            BIT STRING
37     pub signature: &'a [u8],
38 }
39 
40 impl<'a> DecodeValue<'a> for DeferDecodeCertificate<'a> {
decode_value<R: Reader<'a>>( reader: &mut R, header: Header, ) -> der::Result<DeferDecodeCertificate<'a>>41     fn decode_value<R: Reader<'a>>(
42         reader: &mut R,
43         header: Header,
44     ) -> der::Result<DeferDecodeCertificate<'a>> {
45         reader.read_nested(header.length, |reader| {
46             Ok(Self {
47                 tbs_certificate: reader.tlv_bytes()?,
48                 signature_algorithm: reader.tlv_bytes()?,
49                 signature: reader.tlv_bytes()?,
50             })
51         })
52     }
53 }
54 
55 impl FixedTag for DeferDecodeCertificate<'_> {
56     const TAG: Tag = Tag::Sequence;
57 }
58 
59 ///Structure supporting deferred decoding of fields in the TBSCertificate SEQUENCE
60 pub struct DeferDecodeTbsCertificate<'a> {
61     /// Decoded field
62     pub version: u8,
63     /// Defer decoded field
64     pub serial_number: &'a [u8],
65     /// Defer decoded field
66     pub signature: &'a [u8],
67     /// Defer decoded field
68     pub issuer: &'a [u8],
69     /// Defer decoded field
70     pub validity: &'a [u8],
71     /// Defer decoded field
72     pub subject: &'a [u8],
73     /// Defer decoded field
74     pub subject_public_key_info: &'a [u8],
75     /// Decoded field (never present)
76     pub issuer_unique_id: Option<BitStringRef<'a>>,
77     /// Decoded field (never present)
78     pub subject_unique_id: Option<BitStringRef<'a>>,
79     /// Defer decoded field
80     pub extensions: &'a [u8],
81 }
82 
83 impl<'a> DecodeValue<'a> for DeferDecodeTbsCertificate<'a> {
decode_value<R: Reader<'a>>( reader: &mut R, header: Header, ) -> der::Result<DeferDecodeTbsCertificate<'a>>84     fn decode_value<R: Reader<'a>>(
85         reader: &mut R,
86         header: Header,
87     ) -> der::Result<DeferDecodeTbsCertificate<'a>> {
88         reader.read_nested(header.length, |reader| {
89             let version = ContextSpecific::decode_explicit(reader, ::der::TagNumber::N0)?
90                 .map(|cs| cs.value)
91                 .unwrap_or_else(Default::default);
92 
93             Ok(Self {
94                 version,
95                 serial_number: reader.tlv_bytes()?,
96                 signature: reader.tlv_bytes()?,
97                 issuer: reader.tlv_bytes()?,
98                 validity: reader.tlv_bytes()?,
99                 subject: reader.tlv_bytes()?,
100                 subject_public_key_info: reader.tlv_bytes()?,
101                 issuer_unique_id: reader.decode()?,
102                 subject_unique_id: reader.decode()?,
103                 extensions: reader.tlv_bytes()?,
104             })
105         })
106     }
107 }
108 
109 impl FixedTag for DeferDecodeTbsCertificate<'_> {
110     const TAG: Tag = Tag::Sequence;
111 }
112 
113 #[test]
reencode_cert()114 fn reencode_cert() {
115     let der_encoded_cert =
116         include_bytes!("examples/026EDA6FA1EDFA8C253936C75B5EEBD954BFF452.fake.der");
117     let defer_cert = DeferDecodeCertificate::from_der(der_encoded_cert).unwrap();
118 
119     let parsed_tbs = TbsCertificate::from_der(defer_cert.tbs_certificate).unwrap();
120     let reencoded_tbs = parsed_tbs.to_der().unwrap();
121     assert_eq!(defer_cert.tbs_certificate, reencoded_tbs);
122 
123     let parsed_sigalg = AlgorithmIdentifierRef::from_der(defer_cert.signature_algorithm).unwrap();
124     let reencoded_sigalg = parsed_sigalg.to_der().unwrap();
125     assert_eq!(defer_cert.signature_algorithm, reencoded_sigalg);
126 
127     let parsed_sig = BitStringRef::from_der(defer_cert.signature).unwrap();
128     let reencoded_sig = parsed_sig.to_der().unwrap();
129     assert_eq!(defer_cert.signature, reencoded_sig);
130 
131     let parsed_coverage_tbs =
132         DeferDecodeTbsCertificate::from_der(defer_cert.tbs_certificate).unwrap();
133 
134     // TODO - defer decode then re-encode version field
135 
136     let encoded_serial = parsed_tbs.serial_number.to_der().unwrap();
137     assert_eq!(parsed_coverage_tbs.serial_number, encoded_serial);
138 
139     let encoded_signature = parsed_tbs.signature.to_der().unwrap();
140     assert_eq!(parsed_coverage_tbs.signature, encoded_signature);
141 
142     let encoded_issuer = parsed_tbs.issuer.to_der().unwrap();
143     assert_eq!(parsed_coverage_tbs.issuer, encoded_issuer);
144 
145     let encoded_validity = parsed_tbs.validity.to_der().unwrap();
146     assert_eq!(parsed_coverage_tbs.validity, encoded_validity);
147 
148     let encoded_subject = parsed_tbs.subject.to_der().unwrap();
149     assert_eq!(parsed_coverage_tbs.subject, encoded_subject);
150 
151     let encoded_subject_public_key_info = parsed_tbs.subject_public_key_info.to_der().unwrap();
152     assert_eq!(
153         parsed_coverage_tbs.subject_public_key_info,
154         encoded_subject_public_key_info
155     );
156 
157     // TODO - either encode as context specific or decode to sequence. for know lop off context
158     // specific tag and length
159     let encoded_extensions = parsed_tbs.extensions.to_der().unwrap();
160     assert_eq!(&parsed_coverage_tbs.extensions[4..], encoded_extensions);
161 }
162 
163 #[test]
decode_oversized_oids()164 fn decode_oversized_oids() {
165     let o1parse = ObjectIdentifier::from_der(&hex!(
166         "06252B060104018237150885C8B86B87AFF00383A99F3C96C34081ADE6494D82B0E91D85B2873D"
167     ))
168     .unwrap();
169     let o1str = o1parse.to_string();
170     assert_eq!(
171         o1str,
172         "1.3.6.1.4.1.311.21.8.11672683.15464451.6967228.369088.2847561.77.4994205.11305917"
173     );
174     let o1 = ObjectIdentifier::new_unwrap(
175         "1.3.6.1.4.1.311.21.8.11672683.15464451.6967228.369088.2847561.77.4994205.11305917",
176     );
177     assert_eq!(
178         o1.to_string(),
179         "1.3.6.1.4.1.311.21.8.11672683.15464451.6967228.369088.2847561.77.4994205.11305917"
180     );
181     let enc_oid = o1.to_der().unwrap();
182     assert_eq!(
183         &hex!("06252B060104018237150885C8B86B87AFF00383A99F3C96C34081ADE6494D82B0E91D85B2873D"),
184         enc_oid.as_slice()
185     );
186 }
187 
188 #[test]
decode_cert()189 fn decode_cert() {
190     // cloned cert with variety of interesting bits, including subject DN encoded backwards, large
191     // policy mapping set, large policy set (including one with qualifiers), fairly typical set of
192     // extensions otherwise
193     let der_encoded_cert =
194         include_bytes!("examples/026EDA6FA1EDFA8C253936C75B5EEBD954BFF452.fake.der");
195     let result = Certificate::from_der(der_encoded_cert);
196     let cert: Certificate = result.unwrap();
197     println!("{:?}", cert);
198     let exts = cert.tbs_certificate.extensions.unwrap();
199     for (ext, (oid, crit)) in exts.iter().zip(EXTENSIONS) {
200         assert_eq!(ext.extn_id.to_string(), *oid);
201         assert_eq!(ext.critical, *crit);
202     }
203 
204     let result = Certificate::from_der(der_encoded_cert);
205     let cert: Certificate = result.unwrap();
206 
207     assert_eq!(cert.tbs_certificate.version, Version::V3);
208     let target_serial: [u8; 16] = [
209         0x7F, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x49, 0xCF, 0x70, 0x66, 0x4D, 0x00, 0x00, 0x00,
210         0x02,
211     ];
212     assert_eq!(
213         cert.tbs_certificate.serial_number,
214         SerialNumber::new(&target_serial).unwrap()
215     );
216     assert_eq!(
217         cert.tbs_certificate.signature.oid.to_string(),
218         "1.2.840.113549.1.1.11"
219     );
220     assert_eq!(
221         cert.tbs_certificate
222             .signature
223             .parameters
224             .as_ref()
225             .unwrap()
226             .tag(),
227         Tag::Null
228     );
229     assert!(cert
230         .tbs_certificate
231         .signature
232         .parameters
233         .as_ref()
234         .unwrap()
235         .is_null());
236 
237     let mut counter = 0;
238     let i = cert.tbs_certificate.issuer.0.iter();
239     for rdn in i {
240         let i1 = rdn.0.iter();
241         for atav in i1 {
242             if 0 == counter {
243                 assert_eq!(atav.oid.to_string(), "2.5.4.6");
244                 assert_eq!(
245                     PrintableStringRef::try_from(&atav.value)
246                         .unwrap()
247                         .to_string(),
248                     "US"
249                 );
250             } else if 1 == counter {
251                 assert_eq!(atav.oid.to_string(), "2.5.4.10");
252                 assert_eq!(
253                     PrintableStringRef::try_from(&atav.value)
254                         .unwrap()
255                         .to_string(),
256                     "Mock"
257                 );
258             } else if 2 == counter {
259                 assert_eq!(atav.oid.to_string(), "2.5.4.10");
260                 assert_eq!(
261                     Utf8StringRef::try_from(&atav.value).unwrap().to_string(),
262                     "IdenTrust Services LLC"
263                 );
264             } else if 3 == counter {
265                 assert_eq!(atav.oid.to_string(), "2.5.4.3");
266                 assert_eq!(
267                     Utf8StringRef::try_from(&atav.value).unwrap().to_string(),
268                     "PTE IdenTrust Global Common Root CA 1"
269                 );
270             }
271             counter += 1;
272         }
273     }
274 
275     assert_eq!(
276         cert.tbs_certificate
277             .validity
278             .not_before
279             .to_unix_duration()
280             .as_secs(),
281         1416524490
282     );
283     assert_eq!(
284         cert.tbs_certificate
285             .validity
286             .not_after
287             .to_unix_duration()
288             .as_secs(),
289         1516628593
290     );
291 
292     counter = 0;
293     let i = cert.tbs_certificate.subject.0.iter();
294     for rdn in i {
295         let i1 = rdn.0.iter();
296         for atav in i1 {
297             // Yes, this cert features RDNs encoded in reverse order
298             if 0 == counter {
299                 assert_eq!(atav.oid.to_string(), "2.5.4.3");
300                 assert_eq!(
301                     PrintableStringRef::try_from(&atav.value)
302                         .unwrap()
303                         .to_string(),
304                     "Test Federal Bridge CA"
305                 );
306             } else if 1 == counter {
307                 assert_eq!(atav.oid.to_string(), "2.5.4.11");
308                 assert_eq!(
309                     PrintableStringRef::try_from(&atav.value)
310                         .unwrap()
311                         .to_string(),
312                     "TestFPKI"
313                 );
314             } else if 2 == counter {
315                 assert_eq!(atav.oid.to_string(), "2.5.4.10");
316                 assert_eq!(
317                     PrintableStringRef::try_from(&atav.value)
318                         .unwrap()
319                         .to_string(),
320                     "U.S. Government"
321                 );
322             } else if 3 == counter {
323                 assert_eq!(atav.oid.to_string(), "2.5.4.6");
324                 assert_eq!(
325                     PrintableStringRef::try_from(&atav.value)
326                         .unwrap()
327                         .to_string(),
328                     "US"
329                 );
330             }
331             counter += 1;
332         }
333     }
334 
335     assert_eq!(
336         cert.tbs_certificate
337             .subject_public_key_info
338             .algorithm
339             .oid
340             .to_string(),
341         "1.2.840.113549.1.1.1"
342     );
343     assert_eq!(
344         cert.tbs_certificate
345             .subject_public_key_info
346             .algorithm
347             .parameters
348             .as_ref()
349             .unwrap()
350             .tag(),
351         Tag::Null
352     );
353     assert!(cert
354         .tbs_certificate
355         .subject_public_key_info
356         .algorithm
357         .parameters
358         .as_ref()
359         .unwrap()
360         .is_null());
361 
362     // TODO - parse and compare public key
363 
364     let exts = cert.tbs_certificate.extensions.as_ref().unwrap();
365     for (ext, (oid, crit)) in exts.iter().zip(EXTENSIONS) {
366         assert_eq!(ext.extn_id.to_string(), *oid);
367         assert_eq!(ext.critical, *crit);
368     }
369 
370     assert_eq!(
371         cert.signature_algorithm.oid.to_string(),
372         "1.2.840.113549.1.1.11"
373     );
374     assert_eq!(
375         cert.signature_algorithm.parameters.as_ref().unwrap().tag(),
376         Tag::Null
377     );
378     assert!(cert
379         .signature_algorithm
380         .parameters
381         .as_ref()
382         .unwrap()
383         .is_null());
384 
385     assert_eq!(
386         &hex!("2A892F357BF3EF19E1211986106803FA18E66237802F1B1B0C6756CE678DB01D72CD0A4EB7171C2CDDF110ACD38AA65C35699E869C219AD7550AA4F287BB784F72EF8C9EA0E3DD103EFE5BF182EA36FFBCB45AAE65840263680534789C4F3215AF5454AD48CBC4B7A881E0135401A0BD5A849C11101DD1C66178E762C00DF59DD50F8DE9ED46FC6A0D742AE5697D87DD08DAC5291A75FB13C82FF2865C9E36799EA726137E1814E6A878C9532E8FC3D0A2A942D1CCC668FFCEAC255E6002FDE5ACDF2CE47556BB141C3A797A4BFDB673F6F1C229D7914FFEEF1505EE36F8038137D1B8F90106994BAB3E6FF0F60360A2E32F7A30B7ECEC1502DF3CC725BD6E436BA8F96A1847C9CEBB3F5A5906472292501D59BE1A98475BB1F30B677FAA8A45E351640C85B1B22661D33BD23EC6C0CA33DDD79E1120C7FC869EC4D0175ADB4A258AEAC5E8D2F0F578B8BF4B2C5DCC3269768AAA5B9E26D0592C5BB09C702C72E0A60F66D3EEB2B4983279634D59B0A2011B0E26AE796CC95D3243DF49615434E5CC06C374C3F936C005D360CAE6101F3AE7E97E29A157F5020770D4648D7877EBF8248CF3F3E68F9957A36F92D50616F2C60D3842327EF9BC0312CFF03A48C78E97254C2ADEADCA05069168443D833831FF66295A2EED685F164F1DBE01F8C897E1F63D42851682CBEE7B5A64D7BA2923D33644DBF1F7B3EDCE996F9928F043"),
387         cert.signature.raw_bytes()
388     );
389 
390     #[cfg(feature = "pem")]
391     {
392         let pem_encoded_cert =
393             include_bytes!("examples/026EDA6FA1EDFA8C253936C75B5EEBD954BFF452.fake.pem");
394         let result = Certificate::from_pem(pem_encoded_cert);
395         let pem_cert: Certificate = result.unwrap();
396 
397         assert_eq!(pem_cert, cert);
398     }
399 }
400 
401 #[test]
decode_cert_negative_serial_number()402 fn decode_cert_negative_serial_number() {
403     let der_encoded_cert = include_bytes!("examples/28903a635b5280fae6774c0b6da7d6baa64af2e8.der");
404 
405     let cert = Certificate::from_der(der_encoded_cert).unwrap();
406     assert_eq!(
407         cert.tbs_certificate.serial_number.as_bytes(),
408         // INTEGER (125 bit) -2.370157924795571e+37
409         &[238, 43, 61, 235, 212, 33, 222, 20, 168, 98, 172, 4, 243, 221, 196, 1]
410     );
411 
412     let reencoded = cert.to_der().unwrap();
413     assert_eq!(der_encoded_cert, reencoded.as_slice());
414 }
415 
416 #[cfg(all(feature = "pem", feature = "hazmat"))]
417 #[test]
decode_cert_overlength_serial_number()418 fn decode_cert_overlength_serial_number() {
419     use der::{pem::LineEnding, DecodePem, EncodePem};
420     use x509_cert::certificate::CertificateInner;
421 
422     let pem_encoded_cert = include_bytes!("examples/qualcomm.pem");
423 
424     assert!(Certificate::from_pem(pem_encoded_cert).is_err());
425 
426     let cert = CertificateInner::<x509_cert::certificate::Raw>::from_pem(pem_encoded_cert).unwrap();
427     assert_eq!(
428         cert.tbs_certificate.serial_number.as_bytes(),
429         &[
430             0, 132, 206, 11, 246, 160, 254, 130, 78, 229, 229, 6, 202, 168, 157, 120, 198, 21, 1,
431             98, 87, 113
432         ]
433     );
434     assert_eq!(cert.tbs_certificate.serial_number.as_bytes().len(), 22);
435 
436     let reencoded = cert.to_pem(LineEnding::LF).unwrap();
437     assert_eq!(pem_encoded_cert, reencoded.as_bytes());
438 }
439 
440 #[cfg(all(feature = "pem"))]
441 #[test]
load_certificate_chains()442 fn load_certificate_chains() {
443     let pem_encoded_chain = include_bytes!("examples/crates.io-chain.pem");
444 
445     let chain = Certificate::load_pem_chain(pem_encoded_chain).expect("parse certificate chain");
446 
447     assert_eq!(chain.len(), 4, "4 certificates are expected in this chain");
448 }
449 
450 #[cfg(feature = "arbitrary")]
451 #[test]
452 // Purpose of this check is to ensure the arbitraty trait is provided for certificate variants
453 #[allow(unused)]
certificate_arbitrary()454 fn certificate_arbitrary() {
455     fn check_arbitrary<'a>(_arbitrary: impl arbitrary::Arbitrary<'a>) {}
456 
457     fn check_certificate(certificate: x509_cert::Certificate) {
458         check_arbitrary(certificate);
459     }
460 
461     #[cfg(feature = "hazmat")]
462     fn check_raw_certificate(
463         certificate: x509_cert::certificate::CertificateInner<x509_cert::certificate::Raw>,
464     ) {
465         check_arbitrary(certificate);
466     }
467 }
468