1 use std::cmp::Ordering;
2
3 use crate::asn1::{Asn1Object, Asn1OctetString, Asn1Time};
4 use crate::bn::{BigNum, MsbOption};
5 use crate::hash::MessageDigest;
6 use crate::nid::Nid;
7 use crate::pkey::{PKey, Private};
8 use crate::rsa::Rsa;
9 #[cfg(not(boringssl))]
10 use crate::ssl::SslFiletype;
11 use crate::stack::Stack;
12 use crate::x509::extension::{
13 AuthorityKeyIdentifier, BasicConstraints, ExtendedKeyUsage, KeyUsage, SubjectAlternativeName,
14 SubjectKeyIdentifier,
15 };
16 #[cfg(not(boringssl))]
17 use crate::x509::store::X509Lookup;
18 use crate::x509::store::X509StoreBuilder;
19 #[cfg(any(ossl102, libressl261))]
20 use crate::x509::verify::{X509VerifyFlags, X509VerifyParam};
21 #[cfg(ossl102)]
22 use crate::x509::X509PurposeId;
23 #[cfg(any(ossl102, libressl261))]
24 use crate::x509::X509PurposeRef;
25 #[cfg(ossl110)]
26 use crate::x509::{CrlReason, X509Builder};
27 use crate::x509::{
28 CrlStatus, X509Crl, X509Extension, X509Name, X509Req, X509StoreContext, X509VerifyResult, X509,
29 };
30
31 #[cfg(ossl110)]
32 use foreign_types::ForeignType;
33 use hex::{self, FromHex};
34 #[cfg(any(ossl102, libressl261))]
35 use libc::time_t;
36
37 use super::{CertificateIssuer, ReasonCode};
38
pkey() -> PKey<Private>39 fn pkey() -> PKey<Private> {
40 let rsa = Rsa::generate(2048).unwrap();
41 PKey::from_rsa(rsa).unwrap()
42 }
43
44 #[test]
test_cert_loading()45 fn 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]
test_debug()57 fn 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]
test_cert_issue_validity()73 fn 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]
test_save_der()84 fn 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]
test_subject_read_cn()93 fn 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]
test_nid_values()102 fn 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]
test_nameref_iterator()121 fn 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]
test_nid_uid_value()148 fn 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]
test_subject_alt_name()158 fn 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)]
test_retrieve_pathlen()176 fn 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)]
test_subject_key_id()192 fn 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)]
test_authority_key_id()205 fn 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)]
test_authority_issuer_and_serial()218 fn 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]
test_subject_alt_name_iter()239 fn 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]
test_aia_ca_issuer()269 fn 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]
x509_builder()287 fn 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)]
x509_extension_new()362 fn 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]
x509_extension_new_from_der()370 fn 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]
x509_extension_to_der()384 fn 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]
eku_invalid_other()422 fn 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]
x509_req_builder()430 fn 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]
test_stack_from_pem()466 fn 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]
issued()482 fn 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]
signature()493 fn 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)]
clone_x509()514 fn 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]
test_verify_cert()521 fn 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]
test_verify_fails()542 fn 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))]
test_verify_fails_with_crl_flag_set_and_no_crl()561 fn 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))]
test_verify_cert_with_purpose()588 fn 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))]
test_verify_cert_with_wrong_purpose_fails()615 fn 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]
x509_ref_version()650 fn 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]
x509_ref_version_no_version_set()666 fn 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]
test_load_crl()676 fn 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]
test_crl_entry_extensions()700 fn 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]
test_save_subject_der()736 fn 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]
test_load_subject_der()746 fn 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]
test_convert_to_text()759 fn 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]
test_convert_req_to_text()785 fn 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]
test_name_cmp()810 fn 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))]
test_name_to_owned()822 fn 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))]
test_verify_param_set_time_fails_verification()832 fn 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))]
test_verify_param_set_time()863 fn 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))]
test_verify_param_set_depth()887 fn 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)]
test_verify_param_set_depth_fails_verification()915 fn 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))]
test_load_cert_file()956 fn 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)]
test_verify_param_auth_level()976 fn 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)]
test_set_purpose()989 fn 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)]
test_set_purpose_fails_verification()1014 fn 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))]
test_add_name_entry()1049 fn 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))]
test_load_crl_file_fail()1067 fn 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)]
ipaddress_as_subject_alternative_name_is_formatted_in_debug<T>(expected_ip: T) where T: Into<std::net::IpAddr>,1075 fn ipaddress_as_subject_alternative_name_is_formatted_in_debug<T>(expected_ip: T)
1076 where
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]
ipv4_as_subject_alternative_name_is_formatted_in_debug()1099 fn 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]
ipv6_as_subject_alternative_name_is_formatted_in_debug()1105 fn 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)]
test_store_all_certificates()1113 fn 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]
other_name_as_subject_alternative_name()1128 fn 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]
test_dist_point()1152 fn 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]
test_dist_point_null()1172 fn 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