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