1 use crate::asn1::Asn1Time;
2 use crate::bn::{BigNum, MsbOption};
3 use crate::hash::MessageDigest;
4 use crate::nid::Nid;
5 use crate::pkey::{PKey, Private};
6 use crate::rsa::Rsa;
7 use crate::stack::Stack;
8 use crate::x509::extension::{
9     AuthorityKeyIdentifier, BasicConstraints, ExtendedKeyUsage, KeyUsage, SubjectAlternativeName,
10     SubjectKeyIdentifier,
11 };
12 use crate::x509::store::X509StoreBuilder;
13 #[cfg(any(ossl102, libressl261))]
14 use crate::x509::verify::X509VerifyFlags;
15 #[cfg(ossl110)]
16 use crate::x509::X509Builder;
17 use crate::x509::{X509Name, X509Req, X509StoreContext, X509VerifyResult, X509};
18 use hex::{self, FromHex};
19 
pkey() -> PKey<Private>20 fn pkey() -> PKey<Private> {
21     let rsa = Rsa::generate(2048).unwrap();
22     PKey::from_rsa(rsa).unwrap()
23 }
24 
25 #[test]
test_cert_loading()26 fn test_cert_loading() {
27     let cert = include_bytes!("../../test/cert.pem");
28     let cert = X509::from_pem(cert).unwrap();
29     let fingerprint = cert.digest(MessageDigest::sha1()).unwrap();
30 
31     let hash_str = "59172d9313e84459bcff27f967e79e6e9217e584";
32     let hash_vec = Vec::from_hex(hash_str).unwrap();
33 
34     assert_eq!(hash_vec, &*fingerprint);
35 }
36 
37 #[test]
test_debug()38 fn test_debug() {
39     let cert = include_bytes!("../../test/cert.pem");
40     let cert = X509::from_pem(cert).unwrap();
41     let debugged = format!("{:#?}", cert);
42     assert!(debugged.contains(r#"serial_number: "8771F7BDEE982FA5""#));
43     assert!(debugged.contains(r#"signature_algorithm: sha256WithRSAEncryption"#));
44     assert!(debugged.contains(r#"countryName = "AU""#));
45     assert!(debugged.contains(r#"stateOrProvinceName = "Some-State""#));
46     assert!(debugged.contains(r#"not_before: Aug 14 17:00:03 2016 GMT"#));
47     assert!(debugged.contains(r#"not_after: Aug 12 17:00:03 2026 GMT"#));
48 }
49 
50 #[test]
test_cert_issue_validity()51 fn test_cert_issue_validity() {
52     let cert = include_bytes!("../../test/cert.pem");
53     let cert = X509::from_pem(cert).unwrap();
54     let not_before = cert.not_before().to_string();
55     let not_after = cert.not_after().to_string();
56 
57     assert_eq!(not_before, "Aug 14 17:00:03 2016 GMT");
58     assert_eq!(not_after, "Aug 12 17:00:03 2026 GMT");
59 }
60 
61 #[test]
test_save_der()62 fn test_save_der() {
63     let cert = include_bytes!("../../test/cert.pem");
64     let cert = X509::from_pem(cert).unwrap();
65 
66     let der = cert.to_der().unwrap();
67     assert!(!der.is_empty());
68 }
69 
70 #[test]
test_subject_read_cn()71 fn test_subject_read_cn() {
72     let cert = include_bytes!("../../test/cert.pem");
73     let cert = X509::from_pem(cert).unwrap();
74     let subject = cert.subject_name();
75     let cn = subject.entries_by_nid(Nid::COMMONNAME).next().unwrap();
76     assert_eq!(cn.data().as_slice(), b"foobar.com")
77 }
78 
79 #[test]
test_nid_values()80 fn test_nid_values() {
81     let cert = include_bytes!("../../test/nid_test_cert.pem");
82     let cert = X509::from_pem(cert).unwrap();
83     let subject = cert.subject_name();
84 
85     let cn = subject.entries_by_nid(Nid::COMMONNAME).next().unwrap();
86     assert_eq!(cn.data().as_slice(), b"example.com");
87 
88     let email = subject
89         .entries_by_nid(Nid::PKCS9_EMAILADDRESS)
90         .next()
91         .unwrap();
92     assert_eq!(email.data().as_slice(), b"test@example.com");
93 
94     let friendly = subject.entries_by_nid(Nid::FRIENDLYNAME).next().unwrap();
95     assert_eq!(&**friendly.data().as_utf8().unwrap(), "Example");
96 }
97 
98 #[test]
test_nameref_iterator()99 fn test_nameref_iterator() {
100     let cert = include_bytes!("../../test/nid_test_cert.pem");
101     let cert = X509::from_pem(cert).unwrap();
102     let subject = cert.subject_name();
103     let mut all_entries = subject.entries();
104 
105     let email = all_entries.next().unwrap();
106     assert_eq!(
107         email.object().nid().as_raw(),
108         Nid::PKCS9_EMAILADDRESS.as_raw()
109     );
110     assert_eq!(email.data().as_slice(), b"test@example.com");
111 
112     let cn = all_entries.next().unwrap();
113     assert_eq!(cn.object().nid().as_raw(), Nid::COMMONNAME.as_raw());
114     assert_eq!(cn.data().as_slice(), b"example.com");
115 
116     let friendly = all_entries.next().unwrap();
117     assert_eq!(friendly.object().nid().as_raw(), Nid::FRIENDLYNAME.as_raw());
118     assert_eq!(&**friendly.data().as_utf8().unwrap(), "Example");
119 
120     if all_entries.next().is_some() {
121         panic!();
122     }
123 }
124 
125 #[test]
test_nid_uid_value()126 fn test_nid_uid_value() {
127     let cert = include_bytes!("../../test/nid_uid_test_cert.pem");
128     let cert = X509::from_pem(cert).unwrap();
129     let subject = cert.subject_name();
130 
131     let cn = subject.entries_by_nid(Nid::USERID).next().unwrap();
132     assert_eq!(cn.data().as_slice(), b"this is the userId");
133 }
134 
135 #[test]
test_subject_alt_name()136 fn test_subject_alt_name() {
137     let cert = include_bytes!("../../test/alt_name_cert.pem");
138     let cert = X509::from_pem(cert).unwrap();
139 
140     let subject_alt_names = cert.subject_alt_names().unwrap();
141     assert_eq!(5, subject_alt_names.len());
142     assert_eq!(Some("example.com"), subject_alt_names[0].dnsname());
143     assert_eq!(subject_alt_names[1].ipaddress(), Some(&[127, 0, 0, 1][..]));
144     assert_eq!(
145         subject_alt_names[2].ipaddress(),
146         Some(&b"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01"[..])
147     );
148     assert_eq!(Some("test@example.com"), subject_alt_names[3].email());
149     assert_eq!(Some("http://www.example.com"), subject_alt_names[4].uri());
150 }
151 
152 #[test]
test_subject_alt_name_iter()153 fn test_subject_alt_name_iter() {
154     let cert = include_bytes!("../../test/alt_name_cert.pem");
155     let cert = X509::from_pem(cert).unwrap();
156 
157     let subject_alt_names = cert.subject_alt_names().unwrap();
158     let mut subject_alt_names_iter = subject_alt_names.iter();
159     assert_eq!(
160         subject_alt_names_iter.next().unwrap().dnsname(),
161         Some("example.com")
162     );
163     assert_eq!(
164         subject_alt_names_iter.next().unwrap().ipaddress(),
165         Some(&[127, 0, 0, 1][..])
166     );
167     assert_eq!(
168         subject_alt_names_iter.next().unwrap().ipaddress(),
169         Some(&b"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01"[..])
170     );
171     assert_eq!(
172         subject_alt_names_iter.next().unwrap().email(),
173         Some("test@example.com")
174     );
175     assert_eq!(
176         subject_alt_names_iter.next().unwrap().uri(),
177         Some("http://www.example.com")
178     );
179     assert!(subject_alt_names_iter.next().is_none());
180 }
181 
182 #[test]
test_aia_ca_issuer()183 fn test_aia_ca_issuer() {
184     // With AIA
185     let cert = include_bytes!("../../test/aia_test_cert.pem");
186     let cert = X509::from_pem(cert).unwrap();
187     let authority_info = cert.authority_info().unwrap();
188     assert_eq!(authority_info.len(), 1);
189     assert_eq!(authority_info[0].method().to_string(), "CA Issuers");
190     assert_eq!(
191         authority_info[0].location().uri(),
192         Some("http://www.example.com/cert.pem")
193     );
194     // Without AIA
195     let cert = include_bytes!("../../test/cert.pem");
196     let cert = X509::from_pem(cert).unwrap();
197     assert!(cert.authority_info().is_none());
198 }
199 
200 #[test]
x509_builder()201 fn x509_builder() {
202     let pkey = pkey();
203 
204     let mut name = X509Name::builder().unwrap();
205     name.append_entry_by_nid(Nid::COMMONNAME, "foobar.com")
206         .unwrap();
207     let name = name.build();
208 
209     let mut builder = X509::builder().unwrap();
210     builder.set_version(2).unwrap();
211     builder.set_subject_name(&name).unwrap();
212     builder.set_issuer_name(&name).unwrap();
213     builder
214         .set_not_before(&Asn1Time::days_from_now(0).unwrap())
215         .unwrap();
216     builder
217         .set_not_after(&Asn1Time::days_from_now(365).unwrap())
218         .unwrap();
219     builder.set_pubkey(&pkey).unwrap();
220 
221     let mut serial = BigNum::new().unwrap();
222     serial.rand(128, MsbOption::MAYBE_ZERO, false).unwrap();
223     builder
224         .set_serial_number(&serial.to_asn1_integer().unwrap())
225         .unwrap();
226 
227     let basic_constraints = BasicConstraints::new().critical().ca().build().unwrap();
228     builder.append_extension(basic_constraints).unwrap();
229     let key_usage = KeyUsage::new()
230         .digital_signature()
231         .key_encipherment()
232         .build()
233         .unwrap();
234     builder.append_extension(key_usage).unwrap();
235     let ext_key_usage = ExtendedKeyUsage::new()
236         .client_auth()
237         .server_auth()
238         .other("2.999.1")
239         .build()
240         .unwrap();
241     builder.append_extension(ext_key_usage).unwrap();
242     let subject_key_identifier = SubjectKeyIdentifier::new()
243         .build(&builder.x509v3_context(None, None))
244         .unwrap();
245     builder.append_extension(subject_key_identifier).unwrap();
246     let authority_key_identifier = AuthorityKeyIdentifier::new()
247         .keyid(true)
248         .build(&builder.x509v3_context(None, None))
249         .unwrap();
250     builder.append_extension(authority_key_identifier).unwrap();
251     let subject_alternative_name = SubjectAlternativeName::new()
252         .dns("example.com")
253         .build(&builder.x509v3_context(None, None))
254         .unwrap();
255     builder.append_extension(subject_alternative_name).unwrap();
256 
257     builder.sign(&pkey, MessageDigest::sha256()).unwrap();
258 
259     let x509 = builder.build();
260 
261     assert!(pkey.public_eq(&x509.public_key().unwrap()));
262     assert!(x509.verify(&pkey).unwrap());
263 
264     let cn = x509
265         .subject_name()
266         .entries_by_nid(Nid::COMMONNAME)
267         .next()
268         .unwrap();
269     assert_eq!(cn.data().as_slice(), b"foobar.com");
270     assert_eq!(serial, x509.serial_number().to_bn().unwrap());
271 }
272 
273 #[test]
x509_req_builder()274 fn x509_req_builder() {
275     let pkey = pkey();
276 
277     let mut name = X509Name::builder().unwrap();
278     name.append_entry_by_nid(Nid::COMMONNAME, "foobar.com")
279         .unwrap();
280     let name = name.build();
281 
282     let mut builder = X509Req::builder().unwrap();
283     builder.set_version(2).unwrap();
284     builder.set_subject_name(&name).unwrap();
285     builder.set_pubkey(&pkey).unwrap();
286 
287     let mut extensions = Stack::new().unwrap();
288     let key_usage = KeyUsage::new()
289         .digital_signature()
290         .key_encipherment()
291         .build()
292         .unwrap();
293     extensions.push(key_usage).unwrap();
294     let subject_alternative_name = SubjectAlternativeName::new()
295         .dns("example.com")
296         .build(&builder.x509v3_context(None))
297         .unwrap();
298     extensions.push(subject_alternative_name).unwrap();
299     builder.add_extensions(&extensions).unwrap();
300 
301     builder.sign(&pkey, MessageDigest::sha256()).unwrap();
302 
303     let req = builder.build();
304     assert!(req.public_key().unwrap().public_eq(&pkey));
305     assert_eq!(req.extensions().unwrap().len(), extensions.len());
306     assert!(req.verify(&pkey).unwrap());
307 }
308 
309 #[test]
test_stack_from_pem()310 fn test_stack_from_pem() {
311     let certs = include_bytes!("../../test/certs.pem");
312     let certs = X509::stack_from_pem(certs).unwrap();
313 
314     assert_eq!(certs.len(), 2);
315     assert_eq!(
316         hex::encode(certs[0].digest(MessageDigest::sha1()).unwrap()),
317         "59172d9313e84459bcff27f967e79e6e9217e584"
318     );
319     assert_eq!(
320         hex::encode(certs[1].digest(MessageDigest::sha1()).unwrap()),
321         "c0cbdf7cdd03c9773e5468e1f6d2da7d5cbb1875"
322     );
323 }
324 
325 #[test]
issued()326 fn issued() {
327     let cert = include_bytes!("../../test/cert.pem");
328     let cert = X509::from_pem(cert).unwrap();
329     let ca = include_bytes!("../../test/root-ca.pem");
330     let ca = X509::from_pem(ca).unwrap();
331 
332     assert_eq!(ca.issued(&cert), X509VerifyResult::OK);
333     assert_ne!(cert.issued(&cert), X509VerifyResult::OK);
334 }
335 
336 #[test]
signature()337 fn signature() {
338     let cert = include_bytes!("../../test/cert.pem");
339     let cert = X509::from_pem(cert).unwrap();
340     let signature = cert.signature();
341     assert_eq!(
342         hex::encode(signature.as_slice()),
343         "4af607b889790b43470442cfa551cdb8b6d0b0340d2958f76b9e3ef6ad4992230cead6842587f0ecad5\
344          78e6e11a221521e940187e3d6652de14e84e82f6671f097cc47932e022add3c0cb54a26bf27fa84c107\
345          4971caa6bee2e42d34a5b066c427f2d452038082b8073993399548088429de034fdd589dcfb0dd33be7\
346          ebdfdf698a28d628a89568881d658151276bde333600969502c4e62e1d3470a683364dfb241f78d310a\
347          89c119297df093eb36b7fd7540224f488806780305d1e79ffc938fe2275441726522ab36d88348e6c51\
348          f13dcc46b5e1cdac23c974fd5ef86aa41e91c9311655090a52333bc79687c748d833595d4c5f987508f\
349          e121997410d37c"
350     );
351     let algorithm = cert.signature_algorithm();
352     assert_eq!(algorithm.object().nid(), Nid::SHA256WITHRSAENCRYPTION);
353     assert_eq!(algorithm.object().to_string(), "sha256WithRSAEncryption");
354 }
355 
356 #[test]
357 #[allow(clippy::redundant_clone)]
clone_x509()358 fn clone_x509() {
359     let cert = include_bytes!("../../test/cert.pem");
360     let cert = X509::from_pem(cert).unwrap();
361     drop(cert.clone());
362 }
363 
364 #[test]
test_verify_cert()365 fn test_verify_cert() {
366     let cert = include_bytes!("../../test/cert.pem");
367     let cert = X509::from_pem(cert).unwrap();
368     let ca = include_bytes!("../../test/root-ca.pem");
369     let ca = X509::from_pem(ca).unwrap();
370     let chain = Stack::new().unwrap();
371 
372     let mut store_bldr = X509StoreBuilder::new().unwrap();
373     store_bldr.add_cert(ca).unwrap();
374     let store = store_bldr.build();
375 
376     let mut context = X509StoreContext::new().unwrap();
377     assert!(context
378         .init(&store, &cert, &chain, |c| c.verify_cert())
379         .unwrap());
380     assert!(context
381         .init(&store, &cert, &chain, |c| c.verify_cert())
382         .unwrap());
383 }
384 
385 #[test]
test_verify_fails()386 fn test_verify_fails() {
387     let cert = include_bytes!("../../test/cert.pem");
388     let cert = X509::from_pem(cert).unwrap();
389     let ca = include_bytes!("../../test/alt_name_cert.pem");
390     let ca = X509::from_pem(ca).unwrap();
391     let chain = Stack::new().unwrap();
392 
393     let mut store_bldr = X509StoreBuilder::new().unwrap();
394     store_bldr.add_cert(ca).unwrap();
395     let store = store_bldr.build();
396 
397     let mut context = X509StoreContext::new().unwrap();
398     assert!(!context
399         .init(&store, &cert, &chain, |c| c.verify_cert())
400         .unwrap());
401 }
402 
403 #[test]
404 #[cfg(any(ossl102, libressl261))]
test_verify_fails_with_crl_flag_set_and_no_crl()405 fn test_verify_fails_with_crl_flag_set_and_no_crl() {
406     let cert = include_bytes!("../../test/cert.pem");
407     let cert = X509::from_pem(cert).unwrap();
408     let ca = include_bytes!("../../test/root-ca.pem");
409     let ca = X509::from_pem(ca).unwrap();
410     let chain = Stack::new().unwrap();
411 
412     let mut store_bldr = X509StoreBuilder::new().unwrap();
413     store_bldr.add_cert(ca).unwrap();
414     store_bldr.set_flags(X509VerifyFlags::CRL_CHECK).unwrap();
415     let store = store_bldr.build();
416 
417     let mut context = X509StoreContext::new().unwrap();
418     assert_eq!(
419         context
420             .init(&store, &cert, &chain, |c| {
421                 c.verify_cert()?;
422                 Ok(c.error())
423             })
424             .unwrap()
425             .error_string(),
426         "unable to get certificate CRL"
427     )
428 }
429 
430 #[cfg(ossl110)]
431 #[test]
x509_ref_version()432 fn x509_ref_version() {
433     let mut builder = X509Builder::new().unwrap();
434     let expected_version = 2;
435     builder
436         .set_version(expected_version)
437         .expect("Failed to set certificate version");
438     let cert = builder.build();
439     let actual_version = cert.version();
440     assert_eq!(
441         expected_version, actual_version,
442         "Obtained certificate version is incorrect",
443     );
444 }
445 
446 #[cfg(ossl110)]
447 #[test]
x509_ref_version_no_version_set()448 fn x509_ref_version_no_version_set() {
449     let cert = X509Builder::new().unwrap().build();
450     let actual_version = cert.version();
451     assert_eq!(
452         0, actual_version,
453         "Default certificate version is incorrect",
454     );
455 }
456 
457 #[test]
test_save_subject_der()458 fn test_save_subject_der() {
459     let cert = include_bytes!("../../test/cert.pem");
460     let cert = X509::from_pem(cert).unwrap();
461 
462     let der = cert.subject_name().to_der().unwrap();
463     println!("der: {:?}", der);
464     assert!(!der.is_empty());
465 }
466 
467 #[test]
test_load_subject_der()468 fn test_load_subject_der() {
469     // The subject from ../../test/cert.pem
470     const SUBJECT_DER: &[u8] = &[
471         48, 90, 49, 11, 48, 9, 6, 3, 85, 4, 6, 19, 2, 65, 85, 49, 19, 48, 17, 6, 3, 85, 4, 8, 12,
472         10, 83, 111, 109, 101, 45, 83, 116, 97, 116, 101, 49, 33, 48, 31, 6, 3, 85, 4, 10, 12, 24,
473         73, 110, 116, 101, 114, 110, 101, 116, 32, 87, 105, 100, 103, 105, 116, 115, 32, 80, 116,
474         121, 32, 76, 116, 100, 49, 19, 48, 17, 6, 3, 85, 4, 3, 12, 10, 102, 111, 111, 98, 97, 114,
475         46, 99, 111, 109,
476     ];
477     X509Name::from_der(SUBJECT_DER).unwrap();
478 }
479