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