1use std::cmp::Ordering;
2
3use crate::asn1::{Asn1Object, Asn1OctetString, Asn1Time};
4use crate::bn::{BigNum, MsbOption};
5use crate::hash::MessageDigest;
6use crate::nid::Nid;
7use crate::pkey::{PKey, Private};
8use crate::rsa::Rsa;
9#[cfg(not(boringssl))]
10use crate::ssl::SslFiletype;
11use crate::stack::Stack;
12use crate::x509::extension::{
13    AuthorityKeyIdentifier, BasicConstraints, ExtendedKeyUsage, KeyUsage, SubjectAlternativeName,
14    SubjectKeyIdentifier,
15};
16#[cfg(not(boringssl))]
17use crate::x509::store::X509Lookup;
18use crate::x509::store::X509StoreBuilder;
19#[cfg(any(ossl102, libressl261))]
20use crate::x509::verify::{X509VerifyFlags, X509VerifyParam};
21#[cfg(ossl102)]
22use crate::x509::X509PurposeId;
23#[cfg(any(ossl102, libressl261))]
24use crate::x509::X509PurposeRef;
25#[cfg(ossl110)]
26use crate::x509::{CrlReason, X509Builder};
27use crate::x509::{
28    CrlStatus, X509Crl, X509Extension, X509Name, X509Req, X509StoreContext, X509VerifyResult, X509,
29};
30
31#[cfg(ossl110)]
32use foreign_types::ForeignType;
33use hex::{self, FromHex};
34#[cfg(any(ossl102, libressl261))]
35use libc::time_t;
36
37use super::{CertificateIssuer, ReasonCode};
38
39fn pkey() -> PKey<Private> {
40    let rsa = Rsa::generate(2048).unwrap();
41    PKey::from_rsa(rsa).unwrap()
42}
43
44#[test]
45fn test_cert_loading() {
46    let cert = include_bytes!("../../test/cert.pem");
47    let cert = X509::from_pem(cert).unwrap();
48    let fingerprint = cert.digest(MessageDigest::sha1()).unwrap();
49
50    let hash_str = "59172d9313e84459bcff27f967e79e6e9217e584";
51    let hash_vec = Vec::from_hex(hash_str).unwrap();
52
53    assert_eq!(hash_vec, &*fingerprint);
54}
55
56#[test]
57fn test_debug() {
58    let cert = include_bytes!("../../test/cert.pem");
59    let cert = X509::from_pem(cert).unwrap();
60    let debugged = format!("{:#?}", cert);
61    #[cfg(boringssl)]
62    assert!(debugged.contains(r#"serial_number: "8771f7bdee982fa5""#));
63    #[cfg(not(boringssl))]
64    assert!(debugged.contains(r#"serial_number: "8771F7BDEE982FA5""#));
65    assert!(debugged.contains(r#"signature_algorithm: sha256WithRSAEncryption"#));
66    assert!(debugged.contains(r#"countryName = "AU""#));
67    assert!(debugged.contains(r#"stateOrProvinceName = "Some-State""#));
68    assert!(debugged.contains(r#"not_before: Aug 14 17:00:03 2016 GMT"#));
69    assert!(debugged.contains(r#"not_after: Aug 12 17:00:03 2026 GMT"#));
70}
71
72#[test]
73fn test_cert_issue_validity() {
74    let cert = include_bytes!("../../test/cert.pem");
75    let cert = X509::from_pem(cert).unwrap();
76    let not_before = cert.not_before().to_string();
77    let not_after = cert.not_after().to_string();
78
79    assert_eq!(not_before, "Aug 14 17:00:03 2016 GMT");
80    assert_eq!(not_after, "Aug 12 17:00:03 2026 GMT");
81}
82
83#[test]
84fn test_save_der() {
85    let cert = include_bytes!("../../test/cert.pem");
86    let cert = X509::from_pem(cert).unwrap();
87
88    let der = cert.to_der().unwrap();
89    assert!(!der.is_empty());
90}
91
92#[test]
93fn test_subject_read_cn() {
94    let cert = include_bytes!("../../test/cert.pem");
95    let cert = X509::from_pem(cert).unwrap();
96    let subject = cert.subject_name();
97    let cn = subject.entries_by_nid(Nid::COMMONNAME).next().unwrap();
98    assert_eq!(cn.data().as_slice(), b"foobar.com")
99}
100
101#[test]
102fn test_nid_values() {
103    let cert = include_bytes!("../../test/nid_test_cert.pem");
104    let cert = X509::from_pem(cert).unwrap();
105    let subject = cert.subject_name();
106
107    let cn = subject.entries_by_nid(Nid::COMMONNAME).next().unwrap();
108    assert_eq!(cn.data().as_slice(), b"example.com");
109
110    let email = subject
111        .entries_by_nid(Nid::PKCS9_EMAILADDRESS)
112        .next()
113        .unwrap();
114    assert_eq!(email.data().as_slice(), b"test@example.com");
115
116    let friendly = subject.entries_by_nid(Nid::FRIENDLYNAME).next().unwrap();
117    assert_eq!(&**friendly.data().as_utf8().unwrap(), "Example");
118}
119
120#[test]
121fn test_nameref_iterator() {
122    let cert = include_bytes!("../../test/nid_test_cert.pem");
123    let cert = X509::from_pem(cert).unwrap();
124    let subject = cert.subject_name();
125    let mut all_entries = subject.entries();
126
127    let email = all_entries.next().unwrap();
128    assert_eq!(
129        email.object().nid().as_raw(),
130        Nid::PKCS9_EMAILADDRESS.as_raw()
131    );
132    assert_eq!(email.data().as_slice(), b"test@example.com");
133
134    let cn = all_entries.next().unwrap();
135    assert_eq!(cn.object().nid().as_raw(), Nid::COMMONNAME.as_raw());
136    assert_eq!(cn.data().as_slice(), b"example.com");
137
138    let friendly = all_entries.next().unwrap();
139    assert_eq!(friendly.object().nid().as_raw(), Nid::FRIENDLYNAME.as_raw());
140    assert_eq!(&**friendly.data().as_utf8().unwrap(), "Example");
141
142    if all_entries.next().is_some() {
143        panic!();
144    }
145}
146
147#[test]
148fn test_nid_uid_value() {
149    let cert = include_bytes!("../../test/nid_uid_test_cert.pem");
150    let cert = X509::from_pem(cert).unwrap();
151    let subject = cert.subject_name();
152
153    let cn = subject.entries_by_nid(Nid::USERID).next().unwrap();
154    assert_eq!(cn.data().as_slice(), b"this is the userId");
155}
156
157#[test]
158fn test_subject_alt_name() {
159    let cert = include_bytes!("../../test/alt_name_cert.pem");
160    let cert = X509::from_pem(cert).unwrap();
161
162    let subject_alt_names = cert.subject_alt_names().unwrap();
163    assert_eq!(5, subject_alt_names.len());
164    assert_eq!(Some("example.com"), subject_alt_names[0].dnsname());
165    assert_eq!(subject_alt_names[1].ipaddress(), Some(&[127, 0, 0, 1][..]));
166    assert_eq!(
167        subject_alt_names[2].ipaddress(),
168        Some(&b"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01"[..])
169    );
170    assert_eq!(Some("test@example.com"), subject_alt_names[3].email());
171    assert_eq!(Some("http://www.example.com"), subject_alt_names[4].uri());
172}
173
174#[test]
175#[cfg(ossl110)]
176fn test_retrieve_pathlen() {
177    let cert = include_bytes!("../../test/root-ca.pem");
178    let cert = X509::from_pem(cert).unwrap();
179    assert_eq!(cert.pathlen(), None);
180
181    let cert = include_bytes!("../../test/intermediate-ca.pem");
182    let cert = X509::from_pem(cert).unwrap();
183    assert_eq!(cert.pathlen(), Some(0));
184
185    let cert = include_bytes!("../../test/alt_name_cert.pem");
186    let cert = X509::from_pem(cert).unwrap();
187    assert_eq!(cert.pathlen(), None);
188}
189
190#[test]
191#[cfg(ossl110)]
192fn test_subject_key_id() {
193    let cert = include_bytes!("../../test/certv3.pem");
194    let cert = X509::from_pem(cert).unwrap();
195
196    let subject_key_id = cert.subject_key_id().unwrap();
197    assert_eq!(
198        subject_key_id.as_slice(),
199        &b"\xB6\x73\x2F\x61\xA5\x4B\xA1\xEF\x48\x2C\x15\xB1\x9F\xF3\xDC\x34\x2F\xBC\xAC\x30"[..]
200    );
201}
202
203#[test]
204#[cfg(ossl110)]
205fn test_authority_key_id() {
206    let cert = include_bytes!("../../test/certv3.pem");
207    let cert = X509::from_pem(cert).unwrap();
208
209    let authority_key_id = cert.authority_key_id().unwrap();
210    assert_eq!(
211        authority_key_id.as_slice(),
212        &b"\x6C\xD3\xA5\x03\xAB\x0D\x5F\x2C\xC9\x8D\x8A\x9C\x88\xA7\x88\x77\xB8\x37\xFD\x9A"[..]
213    );
214}
215
216#[test]
217#[cfg(ossl111d)]
218fn test_authority_issuer_and_serial() {
219    let cert = include_bytes!("../../test/authority_key_identifier.pem");
220    let cert = X509::from_pem(cert).unwrap();
221
222    let authority_issuer = cert.authority_issuer().unwrap();
223    assert_eq!(1, authority_issuer.len());
224    let dn = authority_issuer[0].directory_name().unwrap();
225    let mut o = dn.entries_by_nid(Nid::ORGANIZATIONNAME);
226    let o = o.next().unwrap().data().as_utf8().unwrap();
227    assert_eq!(o.as_bytes(), b"PyCA");
228    let mut cn = dn.entries_by_nid(Nid::COMMONNAME);
229    let cn = cn.next().unwrap().data().as_utf8().unwrap();
230    assert_eq!(cn.as_bytes(), b"cryptography.io");
231
232    let authority_serial = cert.authority_serial().unwrap();
233    let serial = authority_serial.to_bn().unwrap();
234    let expected = BigNum::from_u32(3).unwrap();
235    assert_eq!(serial, expected);
236}
237
238#[test]
239fn test_subject_alt_name_iter() {
240    let cert = include_bytes!("../../test/alt_name_cert.pem");
241    let cert = X509::from_pem(cert).unwrap();
242
243    let subject_alt_names = cert.subject_alt_names().unwrap();
244    let mut subject_alt_names_iter = subject_alt_names.iter();
245    assert_eq!(
246        subject_alt_names_iter.next().unwrap().dnsname(),
247        Some("example.com")
248    );
249    assert_eq!(
250        subject_alt_names_iter.next().unwrap().ipaddress(),
251        Some(&[127, 0, 0, 1][..])
252    );
253    assert_eq!(
254        subject_alt_names_iter.next().unwrap().ipaddress(),
255        Some(&b"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01"[..])
256    );
257    assert_eq!(
258        subject_alt_names_iter.next().unwrap().email(),
259        Some("test@example.com")
260    );
261    assert_eq!(
262        subject_alt_names_iter.next().unwrap().uri(),
263        Some("http://www.example.com")
264    );
265    assert!(subject_alt_names_iter.next().is_none());
266}
267
268#[test]
269fn test_aia_ca_issuer() {
270    // With AIA
271    let cert = include_bytes!("../../test/aia_test_cert.pem");
272    let cert = X509::from_pem(cert).unwrap();
273    let authority_info = cert.authority_info().unwrap();
274    assert_eq!(authority_info.len(), 1);
275    assert_eq!(authority_info[0].method().to_string(), "CA Issuers");
276    assert_eq!(
277        authority_info[0].location().uri(),
278        Some("http://www.example.com/cert.pem")
279    );
280    // Without AIA
281    let cert = include_bytes!("../../test/cert.pem");
282    let cert = X509::from_pem(cert).unwrap();
283    assert!(cert.authority_info().is_none());
284}
285
286#[test]
287fn x509_builder() {
288    let pkey = pkey();
289
290    let mut name = X509Name::builder().unwrap();
291    name.append_entry_by_nid(Nid::COMMONNAME, "foobar.com")
292        .unwrap();
293    let name = name.build();
294
295    let mut builder = X509::builder().unwrap();
296    builder.set_version(2).unwrap();
297    builder.set_subject_name(&name).unwrap();
298    builder.set_issuer_name(&name).unwrap();
299    builder
300        .set_not_before(&Asn1Time::days_from_now(0).unwrap())
301        .unwrap();
302    builder
303        .set_not_after(&Asn1Time::days_from_now(365).unwrap())
304        .unwrap();
305    builder.set_pubkey(&pkey).unwrap();
306
307    let mut serial = BigNum::new().unwrap();
308    serial.rand(128, MsbOption::MAYBE_ZERO, false).unwrap();
309    builder
310        .set_serial_number(&serial.to_asn1_integer().unwrap())
311        .unwrap();
312
313    let basic_constraints = BasicConstraints::new().critical().ca().build().unwrap();
314    builder.append_extension(basic_constraints).unwrap();
315    let key_usage = KeyUsage::new()
316        .digital_signature()
317        .key_encipherment()
318        .build()
319        .unwrap();
320    builder.append_extension(key_usage).unwrap();
321    let ext_key_usage = ExtendedKeyUsage::new()
322        .client_auth()
323        .server_auth()
324        .other("2.999.1")
325        .build()
326        .unwrap();
327    builder.append_extension(ext_key_usage).unwrap();
328    let subject_key_identifier = SubjectKeyIdentifier::new()
329        .build(&builder.x509v3_context(None, None))
330        .unwrap();
331    builder.append_extension(subject_key_identifier).unwrap();
332    let authority_key_identifier = AuthorityKeyIdentifier::new()
333        .keyid(true)
334        .build(&builder.x509v3_context(None, None))
335        .unwrap();
336    builder.append_extension(authority_key_identifier).unwrap();
337    let subject_alternative_name = SubjectAlternativeName::new()
338        .dns("example.com")
339        .build(&builder.x509v3_context(None, None))
340        .unwrap();
341    builder.append_extension(subject_alternative_name).unwrap();
342
343    builder.sign(&pkey, MessageDigest::sha256()).unwrap();
344
345    let x509 = builder.build();
346
347    assert!(pkey.public_eq(&x509.public_key().unwrap()));
348    assert!(x509.verify(&pkey).unwrap());
349
350    let cn = x509
351        .subject_name()
352        .entries_by_nid(Nid::COMMONNAME)
353        .next()
354        .unwrap();
355    assert_eq!(cn.data().as_slice(), b"foobar.com");
356    assert_eq!(serial, x509.serial_number().to_bn().unwrap());
357}
358
359#[test]
360// This tests `X509Extension::new`, even though its deprecated.
361#[allow(deprecated)]
362fn x509_extension_new() {
363    assert!(X509Extension::new(None, None, "crlDistributionPoints", "section").is_err());
364    assert!(X509Extension::new(None, None, "proxyCertInfo", "").is_err());
365    assert!(X509Extension::new(None, None, "certificatePolicies", "").is_err());
366    assert!(X509Extension::new(None, None, "subjectAltName", "dirName:section").is_err());
367}
368
369#[test]
370fn x509_extension_new_from_der() {
371    let ext = X509Extension::new_from_der(
372        &Asn1Object::from_str("2.5.29.19").unwrap(),
373        true,
374        &Asn1OctetString::new_from_bytes(b"\x30\x03\x01\x01\xff").unwrap(),
375    )
376    .unwrap();
377    assert_eq!(
378        ext.to_der().unwrap(),
379        b"0\x0f\x06\x03U\x1d\x13\x01\x01\xff\x04\x050\x03\x01\x01\xff"
380    );
381}
382
383#[test]
384fn x509_extension_to_der() {
385    let builder = X509::builder().unwrap();
386
387    for (ext, expected) in [
388        (
389            BasicConstraints::new().critical().ca().build().unwrap(),
390            b"0\x0f\x06\x03U\x1d\x13\x01\x01\xff\x04\x050\x03\x01\x01\xff" as &[u8],
391        ),
392        (
393            SubjectAlternativeName::new()
394                .dns("example.com,DNS:example2.com")
395                .build(&builder.x509v3_context(None, None))
396                .unwrap(),
397            b"0'\x06\x03U\x1d\x11\x04 0\x1e\x82\x1cexample.com,DNS:example2.com",
398        ),
399        (
400            SubjectAlternativeName::new()
401                .rid("1.2.3.4")
402                .uri("https://example.com")
403                .build(&builder.x509v3_context(None, None))
404                .unwrap(),
405            b"0#\x06\x03U\x1d\x11\x04\x1c0\x1a\x88\x03*\x03\x04\x86\x13https://example.com",
406        ),
407        (
408            ExtendedKeyUsage::new()
409                .server_auth()
410                .other("2.999.1")
411                .other("clientAuth")
412                .build()
413                .unwrap(),
414            b"0\x22\x06\x03U\x1d%\x04\x1b0\x19\x06\x08+\x06\x01\x05\x05\x07\x03\x01\x06\x03\x887\x01\x06\x08+\x06\x01\x05\x05\x07\x03\x02",
415        ),
416    ] {
417        assert_eq!(&ext.to_der().unwrap(), expected);
418    }
419}
420
421#[test]
422fn eku_invalid_other() {
423    assert!(ExtendedKeyUsage::new()
424        .other("1.1.1.1.1,2.2.2.2.2")
425        .build()
426        .is_err());
427}
428
429#[test]
430fn x509_req_builder() {
431    let pkey = pkey();
432
433    let mut name = X509Name::builder().unwrap();
434    name.append_entry_by_nid(Nid::COMMONNAME, "foobar.com")
435        .unwrap();
436    let name = name.build();
437
438    let mut builder = X509Req::builder().unwrap();
439    builder.set_version(0).unwrap();
440    builder.set_subject_name(&name).unwrap();
441    builder.set_pubkey(&pkey).unwrap();
442
443    let mut extensions = Stack::new().unwrap();
444    let key_usage = KeyUsage::new()
445        .digital_signature()
446        .key_encipherment()
447        .build()
448        .unwrap();
449    extensions.push(key_usage).unwrap();
450    let subject_alternative_name = SubjectAlternativeName::new()
451        .dns("example.com")
452        .build(&builder.x509v3_context(None))
453        .unwrap();
454    extensions.push(subject_alternative_name).unwrap();
455    builder.add_extensions(&extensions).unwrap();
456
457    builder.sign(&pkey, MessageDigest::sha256()).unwrap();
458
459    let req = builder.build();
460    assert!(req.public_key().unwrap().public_eq(&pkey));
461    assert_eq!(req.extensions().unwrap().len(), extensions.len());
462    assert!(req.verify(&pkey).unwrap());
463}
464
465#[test]
466fn test_stack_from_pem() {
467    let certs = include_bytes!("../../test/certs.pem");
468    let certs = X509::stack_from_pem(certs).unwrap();
469
470    assert_eq!(certs.len(), 2);
471    assert_eq!(
472        hex::encode(certs[0].digest(MessageDigest::sha1()).unwrap()),
473        "59172d9313e84459bcff27f967e79e6e9217e584"
474    );
475    assert_eq!(
476        hex::encode(certs[1].digest(MessageDigest::sha1()).unwrap()),
477        "c0cbdf7cdd03c9773e5468e1f6d2da7d5cbb1875"
478    );
479}
480
481#[test]
482fn issued() {
483    let cert = include_bytes!("../../test/cert.pem");
484    let cert = X509::from_pem(cert).unwrap();
485    let ca = include_bytes!("../../test/root-ca.pem");
486    let ca = X509::from_pem(ca).unwrap();
487
488    assert_eq!(ca.issued(&cert), X509VerifyResult::OK);
489    assert_ne!(cert.issued(&cert), X509VerifyResult::OK);
490}
491
492#[test]
493fn signature() {
494    let cert = include_bytes!("../../test/cert.pem");
495    let cert = X509::from_pem(cert).unwrap();
496    let signature = cert.signature();
497    assert_eq!(
498        hex::encode(signature.as_slice()),
499        "4af607b889790b43470442cfa551cdb8b6d0b0340d2958f76b9e3ef6ad4992230cead6842587f0ecad5\
500         78e6e11a221521e940187e3d6652de14e84e82f6671f097cc47932e022add3c0cb54a26bf27fa84c107\
501         4971caa6bee2e42d34a5b066c427f2d452038082b8073993399548088429de034fdd589dcfb0dd33be7\
502         ebdfdf698a28d628a89568881d658151276bde333600969502c4e62e1d3470a683364dfb241f78d310a\
503         89c119297df093eb36b7fd7540224f488806780305d1e79ffc938fe2275441726522ab36d88348e6c51\
504         f13dcc46b5e1cdac23c974fd5ef86aa41e91c9311655090a52333bc79687c748d833595d4c5f987508f\
505         e121997410d37c"
506    );
507    let algorithm = cert.signature_algorithm();
508    assert_eq!(algorithm.object().nid(), Nid::SHA256WITHRSAENCRYPTION);
509    assert_eq!(algorithm.object().to_string(), "sha256WithRSAEncryption");
510}
511
512#[test]
513#[allow(clippy::redundant_clone)]
514fn clone_x509() {
515    let cert = include_bytes!("../../test/cert.pem");
516    let cert = X509::from_pem(cert).unwrap();
517    drop(cert.clone());
518}
519
520#[test]
521fn test_verify_cert() {
522    let cert = include_bytes!("../../test/cert.pem");
523    let cert = X509::from_pem(cert).unwrap();
524    let ca = include_bytes!("../../test/root-ca.pem");
525    let ca = X509::from_pem(ca).unwrap();
526    let chain = Stack::new().unwrap();
527
528    let mut store_bldr = X509StoreBuilder::new().unwrap();
529    store_bldr.add_cert(ca).unwrap();
530    let store = store_bldr.build();
531
532    let mut context = X509StoreContext::new().unwrap();
533    assert!(context
534        .init(&store, &cert, &chain, |c| c.verify_cert())
535        .unwrap());
536    assert!(context
537        .init(&store, &cert, &chain, |c| c.verify_cert())
538        .unwrap());
539}
540
541#[test]
542fn test_verify_fails() {
543    let cert = include_bytes!("../../test/cert.pem");
544    let cert = X509::from_pem(cert).unwrap();
545    let ca = include_bytes!("../../test/alt_name_cert.pem");
546    let ca = X509::from_pem(ca).unwrap();
547    let chain = Stack::new().unwrap();
548
549    let mut store_bldr = X509StoreBuilder::new().unwrap();
550    store_bldr.add_cert(ca).unwrap();
551    let store = store_bldr.build();
552
553    let mut context = X509StoreContext::new().unwrap();
554    assert!(!context
555        .init(&store, &cert, &chain, |c| c.verify_cert())
556        .unwrap());
557}
558
559#[test]
560#[cfg(any(ossl102, libressl261))]
561fn test_verify_fails_with_crl_flag_set_and_no_crl() {
562    let cert = include_bytes!("../../test/cert.pem");
563    let cert = X509::from_pem(cert).unwrap();
564    let ca = include_bytes!("../../test/root-ca.pem");
565    let ca = X509::from_pem(ca).unwrap();
566    let chain = Stack::new().unwrap();
567
568    let mut store_bldr = X509StoreBuilder::new().unwrap();
569    store_bldr.add_cert(ca).unwrap();
570    store_bldr.set_flags(X509VerifyFlags::CRL_CHECK).unwrap();
571    let store = store_bldr.build();
572
573    let mut context = X509StoreContext::new().unwrap();
574    assert_eq!(
575        context
576            .init(&store, &cert, &chain, |c| {
577                c.verify_cert()?;
578                Ok(c.error())
579            })
580            .unwrap()
581            .error_string(),
582        "unable to get certificate CRL"
583    )
584}
585
586#[test]
587#[cfg(any(ossl102, libressl261))]
588fn test_verify_cert_with_purpose() {
589    let cert = include_bytes!("../../test/cert.pem");
590    let cert = X509::from_pem(cert).unwrap();
591    let ca = include_bytes!("../../test/root-ca.pem");
592    let ca = X509::from_pem(ca).unwrap();
593    let chain = Stack::new().unwrap();
594
595    let mut store_bldr = X509StoreBuilder::new().unwrap();
596    let purpose_idx = X509PurposeRef::get_by_sname("sslserver")
597        .expect("Getting certificate purpose 'sslserver' failed");
598    let x509_purposeref =
599        X509PurposeRef::from_idx(purpose_idx).expect("Getting certificate purpose failed");
600    store_bldr
601        .set_purpose(x509_purposeref.purpose())
602        .expect("Setting certificate purpose failed");
603    store_bldr.add_cert(ca).unwrap();
604
605    let store = store_bldr.build();
606
607    let mut context = X509StoreContext::new().unwrap();
608    assert!(context
609        .init(&store, &cert, &chain, |c| c.verify_cert())
610        .unwrap());
611}
612
613#[test]
614#[cfg(any(ossl102, libressl261))]
615fn test_verify_cert_with_wrong_purpose_fails() {
616    let cert = include_bytes!("../../test/cert.pem");
617    let cert = X509::from_pem(cert).unwrap();
618    let ca = include_bytes!("../../test/root-ca.pem");
619    let ca = X509::from_pem(ca).unwrap();
620    let chain = Stack::new().unwrap();
621
622    let mut store_bldr = X509StoreBuilder::new().unwrap();
623    let purpose_idx = X509PurposeRef::get_by_sname("timestampsign")
624        .expect("Getting certificate purpose 'timestampsign' failed");
625    let x509_purpose =
626        X509PurposeRef::from_idx(purpose_idx).expect("Getting certificate purpose failed");
627    store_bldr
628        .set_purpose(x509_purpose.purpose())
629        .expect("Setting certificate purpose failed");
630    store_bldr.add_cert(ca).unwrap();
631
632    let store = store_bldr.build();
633
634    let expected_error = ffi::X509_V_ERR_INVALID_PURPOSE;
635    let mut context = X509StoreContext::new().unwrap();
636    assert_eq!(
637        context
638            .init(&store, &cert, &chain, |c| {
639                c.verify_cert()?;
640                Ok(c.error())
641            })
642            .unwrap()
643            .as_raw(),
644        expected_error
645    )
646}
647
648#[cfg(ossl110)]
649#[test]
650fn x509_ref_version() {
651    let mut builder = X509Builder::new().unwrap();
652    let expected_version = 2;
653    builder
654        .set_version(expected_version)
655        .expect("Failed to set certificate version");
656    let cert = builder.build();
657    let actual_version = cert.version();
658    assert_eq!(
659        expected_version, actual_version,
660        "Obtained certificate version is incorrect",
661    );
662}
663
664#[cfg(ossl110)]
665#[test]
666fn x509_ref_version_no_version_set() {
667    let cert = X509Builder::new().unwrap().build();
668    let actual_version = cert.version();
669    assert_eq!(
670        0, actual_version,
671        "Default certificate version is incorrect",
672    );
673}
674
675#[test]
676fn test_load_crl() {
677    let ca = include_bytes!("../../test/crl-ca.crt");
678    let ca = X509::from_pem(ca).unwrap();
679
680    let crl = include_bytes!("../../test/test.crl");
681    let crl = X509Crl::from_der(crl).unwrap();
682    assert!(crl.verify(&ca.public_key().unwrap()).unwrap());
683
684    let cert = include_bytes!("../../test/subca.crt");
685    let cert = X509::from_pem(cert).unwrap();
686
687    let revoked = match crl.get_by_cert(&cert) {
688        CrlStatus::Revoked(revoked) => revoked,
689        _ => panic!("cert should be revoked"),
690    };
691
692    assert_eq!(
693        revoked.serial_number().to_bn().unwrap(),
694        cert.serial_number().to_bn().unwrap(),
695        "revoked and cert serial numbers should match"
696    );
697}
698
699#[test]
700fn test_crl_entry_extensions() {
701    let crl = include_bytes!("../../test/entry_extensions.crl");
702    let crl = X509Crl::from_pem(crl).unwrap();
703
704    let revoked_certs = crl.get_revoked().unwrap();
705    let entry = &revoked_certs[0];
706
707    let (critical, issuer) = entry
708        .extension::<CertificateIssuer>()
709        .unwrap()
710        .expect("Certificate issuer extension should be present");
711    assert!(critical, "Certificate issuer extension is critical");
712    assert_eq!(issuer.len(), 1, "Certificate issuer should have one entry");
713    let issuer = issuer[0]
714        .directory_name()
715        .expect("Issuer should be a directory name");
716    assert_eq!(
717        format!("{:?}", issuer),
718        r#"[countryName = "GB", commonName = "Test CA"]"#
719    );
720
721    // reason_code can't be inspected without ossl110
722    #[allow(unused_variables)]
723    let (critical, reason_code) = entry
724        .extension::<ReasonCode>()
725        .unwrap()
726        .expect("Reason code extension should be present");
727    assert!(!critical, "Reason code extension is not critical");
728    #[cfg(ossl110)]
729    assert_eq!(
730        CrlReason::KEY_COMPROMISE,
731        CrlReason::from_raw(reason_code.get_i64().unwrap() as ffi::c_int)
732    );
733}
734
735#[test]
736fn test_save_subject_der() {
737    let cert = include_bytes!("../../test/cert.pem");
738    let cert = X509::from_pem(cert).unwrap();
739
740    let der = cert.subject_name().to_der().unwrap();
741    println!("der: {:?}", der);
742    assert!(!der.is_empty());
743}
744
745#[test]
746fn test_load_subject_der() {
747    // The subject from ../../test/cert.pem
748    const SUBJECT_DER: &[u8] = &[
749        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,
750        10, 83, 111, 109, 101, 45, 83, 116, 97, 116, 101, 49, 33, 48, 31, 6, 3, 85, 4, 10, 12, 24,
751        73, 110, 116, 101, 114, 110, 101, 116, 32, 87, 105, 100, 103, 105, 116, 115, 32, 80, 116,
752        121, 32, 76, 116, 100, 49, 19, 48, 17, 6, 3, 85, 4, 3, 12, 10, 102, 111, 111, 98, 97, 114,
753        46, 99, 111, 109,
754    ];
755    X509Name::from_der(SUBJECT_DER).unwrap();
756}
757
758#[test]
759fn test_convert_to_text() {
760    let cert = include_bytes!("../../test/cert.pem");
761    let cert = X509::from_pem(cert).unwrap();
762
763    const SUBSTRINGS: &[&str] = &[
764        "Certificate:\n",
765        "Serial Number:",
766        "Signature Algorithm:",
767        "Issuer: C=AU, ST=Some-State, O=Internet Widgits Pty Ltd\n",
768        "Subject: C=AU, ST=Some-State, O=Internet Widgits Pty Ltd, CN=foobar.com\n",
769        "Subject Public Key Info:",
770    ];
771
772    let text = String::from_utf8(cert.to_text().unwrap()).unwrap();
773
774    for substring in SUBSTRINGS {
775        assert!(
776            text.contains(substring),
777            "{:?} not found inside {}",
778            substring,
779            text
780        );
781    }
782}
783
784#[test]
785fn test_convert_req_to_text() {
786    let csr = include_bytes!("../../test/csr.pem");
787    let csr = X509Req::from_pem(csr).unwrap();
788
789    const SUBSTRINGS: &[&str] = &[
790        "Certificate Request:\n",
791        "Version:",
792        "Subject: C=AU, ST=Some-State, O=Internet Widgits Pty Ltd, CN=foobar.com\n",
793        "Subject Public Key Info:",
794        "Signature Algorithm:",
795    ];
796
797    let text = String::from_utf8(csr.to_text().unwrap()).unwrap();
798
799    for substring in SUBSTRINGS {
800        assert!(
801            text.contains(substring),
802            "{:?} not found inside {}",
803            substring,
804            text
805        );
806    }
807}
808
809#[test]
810fn test_name_cmp() {
811    let cert = include_bytes!("../../test/cert.pem");
812    let cert = X509::from_pem(cert).unwrap();
813
814    let subject = cert.subject_name();
815    let issuer = cert.issuer_name();
816    assert_eq!(Ordering::Equal, subject.try_cmp(subject).unwrap());
817    assert_eq!(Ordering::Greater, subject.try_cmp(issuer).unwrap());
818}
819
820#[test]
821#[cfg(any(boringssl, ossl110, libressl270))]
822fn test_name_to_owned() {
823    let cert = include_bytes!("../../test/cert.pem");
824    let cert = X509::from_pem(cert).unwrap();
825    let name = cert.subject_name();
826    let copied_name = name.to_owned().unwrap();
827    assert_eq!(Ordering::Equal, name.try_cmp(&copied_name).unwrap());
828}
829
830#[test]
831#[cfg(any(ossl102, libressl261))]
832fn test_verify_param_set_time_fails_verification() {
833    const TEST_T_2030: time_t = 1893456000;
834
835    let cert = include_bytes!("../../test/cert.pem");
836    let cert = X509::from_pem(cert).unwrap();
837    let ca = include_bytes!("../../test/root-ca.pem");
838    let ca = X509::from_pem(ca).unwrap();
839    let chain = Stack::new().unwrap();
840
841    let mut store_bldr = X509StoreBuilder::new().unwrap();
842    store_bldr.add_cert(ca).unwrap();
843    let mut verify_params = X509VerifyParam::new().unwrap();
844    verify_params.set_time(TEST_T_2030);
845    store_bldr.set_param(&verify_params).unwrap();
846    let store = store_bldr.build();
847
848    let mut context = X509StoreContext::new().unwrap();
849    assert_eq!(
850        context
851            .init(&store, &cert, &chain, |c| {
852                c.verify_cert()?;
853                Ok(c.error())
854            })
855            .unwrap()
856            .error_string(),
857        "certificate has expired"
858    )
859}
860
861#[test]
862#[cfg(any(ossl102, libressl261))]
863fn test_verify_param_set_time() {
864    const TEST_T_2020: time_t = 1577836800;
865
866    let cert = include_bytes!("../../test/cert.pem");
867    let cert = X509::from_pem(cert).unwrap();
868    let ca = include_bytes!("../../test/root-ca.pem");
869    let ca = X509::from_pem(ca).unwrap();
870    let chain = Stack::new().unwrap();
871
872    let mut store_bldr = X509StoreBuilder::new().unwrap();
873    store_bldr.add_cert(ca).unwrap();
874    let mut verify_params = X509VerifyParam::new().unwrap();
875    verify_params.set_time(TEST_T_2020);
876    store_bldr.set_param(&verify_params).unwrap();
877    let store = store_bldr.build();
878
879    let mut context = X509StoreContext::new().unwrap();
880    assert!(context
881        .init(&store, &cert, &chain, |c| c.verify_cert())
882        .unwrap());
883}
884
885#[test]
886#[cfg(any(ossl102, libressl261))]
887fn test_verify_param_set_depth() {
888    let cert = include_bytes!("../../test/leaf.pem");
889    let cert = X509::from_pem(cert).unwrap();
890    let intermediate_ca = include_bytes!("../../test/intermediate-ca.pem");
891    let intermediate_ca = X509::from_pem(intermediate_ca).unwrap();
892    let ca = include_bytes!("../../test/root-ca.pem");
893    let ca = X509::from_pem(ca).unwrap();
894    let mut chain = Stack::new().unwrap();
895    chain.push(intermediate_ca).unwrap();
896
897    let mut store_bldr = X509StoreBuilder::new().unwrap();
898    store_bldr.add_cert(ca).unwrap();
899    let mut verify_params = X509VerifyParam::new().unwrap();
900    // OpenSSL 1.1.0+ considers the root certificate to not be part of the chain, while 1.0.2 and LibreSSL do
901    let expected_depth = if cfg!(any(ossl110)) { 1 } else { 2 };
902    verify_params.set_depth(expected_depth);
903    store_bldr.set_param(&verify_params).unwrap();
904    let store = store_bldr.build();
905
906    let mut context = X509StoreContext::new().unwrap();
907    assert!(context
908        .init(&store, &cert, &chain, |c| c.verify_cert())
909        .unwrap());
910}
911
912#[test]
913#[cfg(any(ossl102, libressl261))]
914#[allow(clippy::bool_to_int_with_if)]
915fn test_verify_param_set_depth_fails_verification() {
916    let cert = include_bytes!("../../test/leaf.pem");
917    let cert = X509::from_pem(cert).unwrap();
918    let intermediate_ca = include_bytes!("../../test/intermediate-ca.pem");
919    let intermediate_ca = X509::from_pem(intermediate_ca).unwrap();
920    let ca = include_bytes!("../../test/root-ca.pem");
921    let ca = X509::from_pem(ca).unwrap();
922    let mut chain = Stack::new().unwrap();
923    chain.push(intermediate_ca).unwrap();
924
925    let mut store_bldr = X509StoreBuilder::new().unwrap();
926    store_bldr.add_cert(ca).unwrap();
927    let mut verify_params = X509VerifyParam::new().unwrap();
928    // OpenSSL 1.1.0+ considers the root certificate to not be part of the chain, while 1.0.2 and LibreSSL do
929    let expected_depth = if cfg!(any(ossl110)) { 0 } else { 1 };
930    verify_params.set_depth(expected_depth);
931    store_bldr.set_param(&verify_params).unwrap();
932    let store = store_bldr.build();
933
934    // OpenSSL 1.1.0+ added support for X509_V_ERR_CERT_CHAIN_TOO_LONG, while 1.0.2 simply ignores the intermediate
935    let expected_error = if cfg!(any(ossl110, libressl261)) {
936        "certificate chain too long"
937    } else {
938        "unable to get local issuer certificate"
939    };
940
941    let mut context = X509StoreContext::new().unwrap();
942    assert_eq!(
943        context
944            .init(&store, &cert, &chain, |c| {
945                c.verify_cert()?;
946                Ok(c.error())
947            })
948            .unwrap()
949            .error_string(),
950        expected_error
951    )
952}
953
954#[test]
955#[cfg(not(boringssl))]
956fn test_load_cert_file() {
957    let cert = include_bytes!("../../test/cert.pem");
958    let cert = X509::from_pem(cert).unwrap();
959    let chain = Stack::new().unwrap();
960
961    let mut store_bldr = X509StoreBuilder::new().unwrap();
962    let lookup = store_bldr.add_lookup(X509Lookup::file()).unwrap();
963    lookup
964        .load_cert_file("test/root-ca.pem", SslFiletype::PEM)
965        .unwrap();
966    let store = store_bldr.build();
967
968    let mut context = X509StoreContext::new().unwrap();
969    assert!(context
970        .init(&store, &cert, &chain, |c| c.verify_cert())
971        .unwrap());
972}
973
974#[test]
975#[cfg(ossl110)]
976fn test_verify_param_auth_level() {
977    let mut param = X509VerifyParam::new().unwrap();
978    let auth_lvl = 2;
979    let auth_lvl_default = -1;
980
981    assert_eq!(param.auth_level(), auth_lvl_default);
982
983    param.set_auth_level(auth_lvl);
984    assert_eq!(param.auth_level(), auth_lvl);
985}
986
987#[test]
988#[cfg(ossl102)]
989fn test_set_purpose() {
990    let cert = include_bytes!("../../test/leaf.pem");
991    let cert = X509::from_pem(cert).unwrap();
992    let intermediate_ca = include_bytes!("../../test/intermediate-ca.pem");
993    let intermediate_ca = X509::from_pem(intermediate_ca).unwrap();
994    let ca = include_bytes!("../../test/root-ca.pem");
995    let ca = X509::from_pem(ca).unwrap();
996    let mut chain = Stack::new().unwrap();
997    chain.push(intermediate_ca).unwrap();
998
999    let mut store_bldr = X509StoreBuilder::new().unwrap();
1000    store_bldr.add_cert(ca).unwrap();
1001    let mut verify_params = X509VerifyParam::new().unwrap();
1002    verify_params.set_purpose(X509PurposeId::ANY).unwrap();
1003    store_bldr.set_param(&verify_params).unwrap();
1004    let store = store_bldr.build();
1005    let mut context = X509StoreContext::new().unwrap();
1006
1007    assert!(context
1008        .init(&store, &cert, &chain, |c| c.verify_cert())
1009        .unwrap());
1010}
1011
1012#[test]
1013#[cfg(ossl102)]
1014fn test_set_purpose_fails_verification() {
1015    let cert = include_bytes!("../../test/leaf.pem");
1016    let cert = X509::from_pem(cert).unwrap();
1017    let intermediate_ca = include_bytes!("../../test/intermediate-ca.pem");
1018    let intermediate_ca = X509::from_pem(intermediate_ca).unwrap();
1019    let ca = include_bytes!("../../test/root-ca.pem");
1020    let ca = X509::from_pem(ca).unwrap();
1021    let mut chain = Stack::new().unwrap();
1022    chain.push(intermediate_ca).unwrap();
1023
1024    let mut store_bldr = X509StoreBuilder::new().unwrap();
1025    store_bldr.add_cert(ca).unwrap();
1026    let mut verify_params = X509VerifyParam::new().unwrap();
1027    verify_params
1028        .set_purpose(X509PurposeId::TIMESTAMP_SIGN)
1029        .unwrap();
1030    store_bldr.set_param(&verify_params).unwrap();
1031    let store = store_bldr.build();
1032
1033    let expected_error = ffi::X509_V_ERR_INVALID_PURPOSE;
1034    let mut context = X509StoreContext::new().unwrap();
1035    assert_eq!(
1036        context
1037            .init(&store, &cert, &chain, |c| {
1038                c.verify_cert()?;
1039                Ok(c.error())
1040            })
1041            .unwrap()
1042            .as_raw(),
1043        expected_error
1044    )
1045}
1046
1047#[test]
1048#[cfg(any(ossl101, libressl350))]
1049fn test_add_name_entry() {
1050    let cert = include_bytes!("../../test/cert.pem");
1051    let cert = X509::from_pem(cert).unwrap();
1052    let inp_name = cert.subject_name().entries().next().unwrap();
1053
1054    let mut names = X509Name::builder().unwrap();
1055    names.append_entry(inp_name).unwrap();
1056    let names = names.build();
1057
1058    let mut entries = names.entries();
1059    let outp_name = entries.next().unwrap();
1060    assert_eq!(outp_name.object().nid(), inp_name.object().nid());
1061    assert_eq!(outp_name.data().as_slice(), inp_name.data().as_slice());
1062    assert!(entries.next().is_none());
1063}
1064
1065#[test]
1066#[cfg(not(boringssl))]
1067fn test_load_crl_file_fail() {
1068    let mut store_bldr = X509StoreBuilder::new().unwrap();
1069    let lookup = store_bldr.add_lookup(X509Lookup::file()).unwrap();
1070    let res = lookup.load_crl_file("test/root-ca.pem", SslFiletype::PEM);
1071    assert!(res.is_err());
1072}
1073
1074#[cfg(ossl110)]
1075fn ipaddress_as_subject_alternative_name_is_formatted_in_debug<T>(expected_ip: T)
1076where
1077    T: Into<std::net::IpAddr>,
1078{
1079    let expected_ip = format!("{:?}", expected_ip.into());
1080    let mut builder = X509Builder::new().unwrap();
1081    let san = SubjectAlternativeName::new()
1082        .ip(&expected_ip)
1083        .build(&builder.x509v3_context(None, None))
1084        .unwrap();
1085    builder.append_extension(san).unwrap();
1086    let cert = builder.build();
1087    let actual_ip = cert
1088        .subject_alt_names()
1089        .into_iter()
1090        .flatten()
1091        .map(|n| format!("{:?}", *n))
1092        .next()
1093        .unwrap();
1094    assert_eq!(actual_ip, expected_ip);
1095}
1096
1097#[cfg(ossl110)]
1098#[test]
1099fn ipv4_as_subject_alternative_name_is_formatted_in_debug() {
1100    ipaddress_as_subject_alternative_name_is_formatted_in_debug([8u8, 8, 8, 128]);
1101}
1102
1103#[cfg(ossl110)]
1104#[test]
1105fn ipv6_as_subject_alternative_name_is_formatted_in_debug() {
1106    ipaddress_as_subject_alternative_name_is_formatted_in_debug([
1107        8u8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 128,
1108    ]);
1109}
1110
1111#[test]
1112#[cfg(ossl300)]
1113fn test_store_all_certificates() {
1114    let cert = include_bytes!("../../test/cert.pem");
1115    let cert = X509::from_pem(cert).unwrap();
1116
1117    let store = {
1118        let mut b = X509StoreBuilder::new().unwrap();
1119        b.add_cert(cert).unwrap();
1120        b.build()
1121    };
1122
1123    assert_eq!(store.all_certificates().len(), 1);
1124}
1125
1126#[cfg(ossl110)]
1127#[test]
1128fn other_name_as_subject_alternative_name() {
1129    let oid = Asn1Object::from_str("1.3.6.1.5.5.7.8.11").unwrap();
1130    // this is the hex representation of "test" encoded as a ia5string
1131    let content = [0x16, 0x04, 0x74, 0x65, 0x73, 0x74];
1132
1133    let mut builder = X509Builder::new().unwrap();
1134    let san = SubjectAlternativeName::new()
1135        .other_name2(oid, &content)
1136        .build(&builder.x509v3_context(None, None))
1137        .unwrap();
1138    builder.append_extension(san).unwrap();
1139    let cert = builder.build();
1140    let general_name = cert
1141        .subject_alt_names()
1142        .into_iter()
1143        .flatten()
1144        .next()
1145        .unwrap();
1146    unsafe {
1147        assert_eq!((*general_name.as_ptr()).type_, 0);
1148    }
1149}
1150
1151#[test]
1152fn test_dist_point() {
1153    let cert = include_bytes!("../../test/certv3.pem");
1154    let cert = X509::from_pem(cert).unwrap();
1155
1156    let dps = cert.crl_distribution_points().unwrap();
1157    let dp = dps.get(0).unwrap();
1158    let dp_nm = dp.distpoint().unwrap();
1159    let dp_gns = dp_nm.fullname().unwrap();
1160    let dp_gn = dp_gns.get(0).unwrap();
1161    assert_eq!(dp_gn.uri().unwrap(), "http://example.com/crl.pem");
1162
1163    let dp = dps.get(1).unwrap();
1164    let dp_nm = dp.distpoint().unwrap();
1165    let dp_gns = dp_nm.fullname().unwrap();
1166    let dp_gn = dp_gns.get(0).unwrap();
1167    assert_eq!(dp_gn.uri().unwrap(), "http://example.com/crl2.pem");
1168    assert!(dps.get(2).is_none())
1169}
1170
1171#[test]
1172fn test_dist_point_null() {
1173    let cert = include_bytes!("../../test/cert.pem");
1174    let cert = X509::from_pem(cert).unwrap();
1175    assert!(cert.crl_distribution_points().is_none());
1176}
1177