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