1use std::io::Read;
2
3use sequoia_openpgp as openpgp;
4
5use openpgp::Cert;
6use openpgp::Fingerprint;
7use openpgp::Result;
8use openpgp::crypto::Password;
9use openpgp::crypto::mpi;
10use openpgp::crypto;
11use openpgp::packet::Key;
12use openpgp::packet::Packet;
13use openpgp::packet::key::PublicParts;
14use openpgp::packet::key::UnspecifiedRole;
15use openpgp::packet::signature::SignatureBuilder;
16use openpgp::parse::PacketParser;
17use openpgp::parse::PacketParserResult;
18use openpgp::parse::Parse;
19use openpgp::parse::stream::GoodChecksum;
20use openpgp::parse::stream::MessageLayer;
21use openpgp::parse::stream::MessageStructure;
22use openpgp::parse::stream::VerificationHelper;
23use openpgp::parse::stream::VerifierBuilder;
24use openpgp::serialize::stream::LiteralWriter;
25use openpgp::serialize::stream::Message;
26use openpgp::serialize::stream::Signer;
27use openpgp::types::HashAlgorithm;
28use openpgp::types::SignatureType;
29
30use anyhow::Context;
31
32pub mod data;
34
35use crate as backend;
36
37use crate::Backend;
38use crate::utils::run_async;
39
40pub struct TestSigner(
42 Box<dyn crate::KeyHandle + Send + Sync>,
43 Key<PublicParts, UnspecifiedRole>);
44
45impl From<Box<dyn backend::KeyHandle + Send + Sync>> for TestSigner {
46 fn from(kh: Box<dyn backend::KeyHandle + Send + Sync>) -> Self {
47 let key = run_async(async {
48 kh.public_key().await
49 }).expect("ok"); Self(kh, key)
51 }
52}
53
54impl crypto::Signer for TestSigner {
55 fn public(&self) -> &Key<PublicParts, UnspecifiedRole>
56 {
57 &self.1
58 }
59
60 fn sign(&mut self, hash_algo: HashAlgorithm, digest: &[u8])
61 -> Result<mpi::Signature>
62 {
63 run_async(async {
64 self.0.sign(hash_algo, digest).await.map(|(_pk_algo, sig)| sig)
65 })?
66 }
67}
68
69pub struct VerifyHelper {
70 pub keyring: Vec<Cert>,
72 pub signers: Vec<Fingerprint>,
74}
75
76impl VerifyHelper {
77 pub fn new(keyring: &[ Cert ]) -> Self {
78 Self {
79 keyring: keyring.to_vec(),
80 signers: Vec::new(),
81 }
82 }
83}
84
85impl VerificationHelper for &mut VerifyHelper {
86 fn get_certs(&mut self, ids: &[openpgp::KeyHandle]) -> Result<Vec<Cert>> {
87 Ok(self.keyring
88 .iter()
89 .filter(|cert| {
90 cert.keys().any(|k| {
91 ids.iter().any(|id| {
92 id.aliases(openpgp::KeyHandle::from(k.key().fingerprint()))
93 })
94 })
95 })
96 .cloned()
97 .collect::<Vec<_>>())
98 }
99 fn check(&mut self, structure: MessageStructure) -> Result<()> {
100 for (i, layer) in structure.into_iter().enumerate() {
101 match layer {
102 MessageLayer::Encryption { .. } if i == 0 => (),
103 MessageLayer::Compression { .. } if i == 1 => (),
104 MessageLayer::SignatureGroup { ref results } => {
105 for r in results {
106 if let Ok(GoodChecksum { ka, .. }) = r {
107 self.signers.push(ka.key().fingerprint());
108 } else {
109 log::info!("Bad signature: {:?}", r);
110 }
111 }
112 }
113 _ => return Err(anyhow::anyhow!(
114 "Unexpected message structure")),
115 }
116 }
117
118 Ok(())
119 }
120}
121
122pub fn sign_verify(signers: Vec<TestSigner>,
126 keyring: Vec<Cert>,
127 signing_keys: Option<&[ Fingerprint ]>) -> Result<()>
128{
129 let p = &openpgp::policy::StandardPolicy::new();
130
131 let mut output = Vec::new();
132 let message = Message::new(&mut output);
133
134 let builder = SignatureBuilder::new(SignatureType::Binary);
135
136 let mut signers = signers.into_iter();
137 let mut signer = Signer::with_template(
138 message, signers.next().expect("a signer"), builder)?;
139 for s in signers {
140 signer = signer.add_signer(s)?;
141 }
142 let signer = signer.build().context("Failed to create signer")?;
143 let mut writer = LiteralWriter::new(signer).build()
144 .context("Failed to create literal writer")?;
145
146 std::io::copy(&mut std::io::Cursor::new(b"hello"), &mut writer)
147 .context("Failed to sign")?;
148 if let Err(err) = writer.finalize().context("Failed to sign") {
149 if signing_keys.is_none() {
150 return Ok(());
152 } else {
153 panic!("Failed to finalize writer: {}", err);
154 }
155 }
156
157 let mut h = VerifyHelper::new(&keyring);
158 let mut v = VerifierBuilder::from_bytes(&output[..])?
159 .with_policy(p, None, &mut h)?;
160
161 let mut message = Vec::new();
162 let r = v.read_to_end(&mut message);
163
164 if let Some(signing_keys) = signing_keys {
165 assert!(r.is_ok());
166 assert_eq!(message, b"hello");
167 assert_eq!(&h.signers, signing_keys);
168 } else {
169 assert!(r.is_err());
170 }
171
172 Ok(())
173}
174
175pub async fn try_decrypt<B>(backend: &mut B,
186 ciphertext: &[u8], plaintext: Option<&[u8]>,
187 recipient: openpgp::KeyHandle,
188 password: Option<Password>)
189 -> Result<()>
190where B: Backend
191{
192 let mut good = false;
193
194 let mut session_key = None;
195 let mut ppr = PacketParser::from_bytes(ciphertext)?;
196 while let PacketParserResult::Some(mut pp) = ppr {
197 match pp.packet {
198 Packet::PKESK(ref pkesk)
199 if pkesk.recipient().as_ref() == Some(&recipient) =>
200 {
201 log::debug!("Considering PKESK for {}",
203 pkesk.recipient().unwrap());
204
205 'done: for device in backend.list().await {
206 for mut key in device.list().await {
207 log::debug!("Considering key {}", key.fingerprint());
208
209 let key_handle =
210 openpgp::KeyHandle::from(key.fingerprint());
211 if pkesk.recipient()
212 .map(|r| ! r.aliases(&key_handle))
213 .unwrap_or(false)
214 {
215 log::debug!("Wrong key for PKESK {}", key.fingerprint());
216 continue;
217 }
218
219 if let Some(password) = password.as_ref() {
220 key.lock().await?;
222
223 if let Err(e) = key.unlock(Some(password)).await {
224 eprintln!("Failed to unlock key: {}", e);
225 continue;
228 }
229 }
230
231 if let Some((algo, sk))
232 = key.decrypt_pkesk(&pkesk).await
233 {
234 session_key = Some((algo, sk));
235 break 'done;
236 }
237 }
238 if session_key.is_none() {
239 return Err(anyhow::anyhow!(
240 "Decryption failed".to_string()));
241 }
242 }
243 }
244 Packet::PKESK(ref pkesk) => {
245 log::debug!("Ignoring PKESK for {:?}", pkesk.recipient());
247 }
248 Packet::SEIP(_) => {
249 if let Some(session_key) = session_key.take() {
250 let (algo, sk) = session_key;
251 log::debug!("Decrypting PKESK");
252 pp.decrypt(algo, &sk)?;
253 log::debug!("Decrypting PKESK succeeded");
254 } else {
255 return Err(anyhow::anyhow!(
256 "Could not decrypt a PKESK".to_string()));
257 }
258 }
259 Packet::Literal(_) => {
260 pp.buffer_unread_content()?;
261 if let Packet::Literal(l) = &pp.packet {
262 if let Some(plaintext) = plaintext {
263 if plaintext != l.body() {
264 return Err(anyhow::anyhow!(format!(
265 "Plaintext does not match:\n\
266 got: {:?},\n\
267 expected: {:?}",
268 l.body(), plaintext)));
269 }
270 }
271 good = true;
272 }
273 }
274 _ => (),
275 }
276
277 let (_packet, next_ppr) = pp.recurse()?;
278 ppr = next_ppr;
279 }
280
281 if let PacketParserResult::EOF(ppr) = ppr {
282 assert!(ppr.is_message().is_ok());
283 assert!(good);
286 }
287
288 Ok(())
289}
290
291#[macro_export]
314macro_rules! generate_tests {
315 ($preinit: expr, $serialize_tests: expr,
316 $backend: ty, $init_backend: expr,
317 $import_cert: expr, $can_import_encrypted_secret_key_material: expr,
318 $key_sets: expr, $default_password: expr,
319 $can_export: expr,
320 $can_change_password: expr,
321 $can_delete: expr) => {
322 static SERIALIZE: std::sync::Mutex<()> = std::sync::Mutex::new(());
323
324 fn serialize_maybe() -> Option<std::sync::MutexGuard<'static, ()>> {
325 let serialize_tests: bool = $serialize_tests;
326 if serialize_tests {
327 loop {
328 match SERIALIZE.lock() {
329 Ok(guard) => return Some(guard),
330 Err(_err) => {
331 SERIALIZE.clear_poison();
334 }
335 }
336 }
337 } else {
338 None
339 }
340 }
341
342 fn strip_primary_secret(cert: Cert) -> Cert {
347 if cert.primary_key().key().has_secret() {
348 let mut pk = cert.primary_key().key().clone();
349 pk.steal_secret();
350
351 let cert = cert.insert_packets(pk).expect("can merge").0;
352 assert!(! cert.primary_key().key().has_secret());
353 cert
354 } else {
355 cert
356 }
357 }
358
359 #[tokio::test]
361 pub async fn import_cert_helper() -> Result<()> {
362 let _ = env_logger::Builder::from_default_env().try_init();
363
364 let _serialized = serialize_maybe();
365
366 if ! $preinit() {
367 eprintln!("preinit returned false, skipping test.");
368 return Ok(());
369 }
370
371 let mut backend = $init_backend().await;
375 let mut cert = Cert::from_bytes(
376 $crate::test_framework::data::key("no-password.asc"))
377 .expect("valid cert");
378
379 let key_sets: Option<usize> = $key_sets;
380 if key_sets.is_some() {
381 cert = strip_primary_secret(cert);
382 }
383
384 $import_cert(&mut backend, &cert).await;
385
386 let mut imported_keys = Vec::new();
387 for device in backend.list().await {
388 for key in device.list().await {
389 imported_keys.push(key.fingerprint());
390 }
391 }
392 imported_keys.sort();
393
394 let mut expected_keys = Vec::new();
395 for ka in cert.keys().secret() {
396 expected_keys.push(ka.key().fingerprint());
397 }
398 expected_keys.sort();
399
400 if imported_keys != expected_keys {
401 eprintln!(
402 "Imported keys:{}",
403 imported_keys.iter()
404 .map(|fpr| fpr.to_string())
405 .collect::<Vec<String>>()
406 .join("\n "));
407 eprintln!(
408 "Expected keys:{}",
409 expected_keys.iter()
410 .map(|fpr| fpr.to_string())
411 .collect::<Vec<String>>()
412 .join("\n "));
413
414 panic!("Importing keys is broken");
415 }
416
417 Ok(())
418 }
419
420 #[tokio::test]
422 pub async fn backend_import_cert() -> Result<()> {
423 let _ = env_logger::Builder::from_default_env().try_init();
424
425 let _serialized = serialize_maybe();
426
427 if ! $preinit() {
428 eprintln!("preinit returned false, skipping test.");
429 return Ok(());
430 }
431
432 let mut backend = $init_backend().await;
436
437 let cert = Cert::from_bytes(
438 $crate::test_framework::data::key("carol-subkeys-a.asc"))
439 .expect("valid cert");
440
441 let mut expected_keys = Vec::new();
442 for ka in cert.keys().secret() {
443 expected_keys.push(ka.key().fingerprint());
444 }
445 expected_keys.sort();
446
447 for expected_status in [ImportStatus::New, ImportStatus::Unchanged] {
448 eprintln!("expected_status: {:?}", expected_status);
449 match backend.import(cert.clone()).await {
450 Err(err) => {
451 if let Some(Error::ExternalImportRequired(_))
452 = err.downcast_ref()
453 {
454 return Ok(());
457 } else {
458 return Err(err);
459 }
460 }
461 Ok(results) => {
462 let mut imported_keys = results
463 .into_iter()
464 .map(|(import_status, key)| {
465 assert_eq!(import_status, expected_status);
466 key.fingerprint()
467 })
468 .collect::<Vec<Fingerprint>>();
469 imported_keys.sort();
470
471 if imported_keys != expected_keys {
472 eprintln!(
473 "Imported keys:{}",
474 imported_keys.iter()
475 .map(|fpr| fpr.to_string())
476 .collect::<Vec<String>>()
477 .join("\n "));
478 eprintln!(
479 "Expected keys:{}",
480 expected_keys.iter()
481 .map(|fpr| fpr.to_string())
482 .collect::<Vec<String>>()
483 .join("\n "));
484
485 panic!("Importing keys is broken");
486 }
487
488 let mut listed_keys = Vec::new();
489 for device in backend.list().await {
490 for key in device.list().await {
491 listed_keys.push(key.fingerprint());
492 }
493 }
494 listed_keys.sort();
495
496 if listed_keys != expected_keys {
497 eprintln!(
498 "Listed keys:{}",
499 listed_keys.iter()
500 .map(|fpr| fpr.to_string())
501 .collect::<Vec<String>>()
502 .join("\n "));
503 eprintln!(
504 "Expected keys:{}",
505 expected_keys.iter()
506 .map(|fpr| fpr.to_string())
507 .collect::<Vec<String>>()
508 .join("\n "));
509
510 panic!("Listing keys is broken");
511 }
512 }
513 }
514 }
515
516 Ok(())
517 }
518
519 #[tokio::test]
520 pub async fn decrypt_simple() -> Result<()> {
521 let _ = env_logger::Builder::from_default_env().try_init();
522
523 let _serialized = serialize_maybe();
524
525 if ! $preinit() {
526 eprintln!("preinit returned false, skipping test.");
527 return Ok(());
528 }
529
530 let mut backend = $init_backend().await;
534 let cert = Cert::from_bytes(
535 $crate::test_framework::data::key("no-password.asc"))
536 .expect("valid cert");
537
538 $import_cert(&mut backend, &cert).await;
539
540 let msg: &[u8] = $crate::test_framework::data::message("no-password.asc");
541 let keyid = KeyHandle::KeyID("AA5BFAC1E4A121A0".parse()?);
542
543 let default_password: Option<&str> = $default_password;
544 let default_password: Option<Password>
545 = default_password.map(|p| Password::from(p));
546 if let Err(err) = $crate::test_framework::try_decrypt(
547 &mut backend, msg, Some(b"foo\n"), keyid, default_password).await
548 {
549 eprintln!("Decrypting: {}", err);
550 Err(err)
551 } else {
552 Ok(())
553 }
554 }
555
556 #[tokio::test]
557 pub async fn decrypt_missing_password() -> Result<()> {
558 let _ = env_logger::Builder::from_default_env().try_init();
559
560 let can_import_encrypted_secret_key_material: bool
561 = $can_import_encrypted_secret_key_material;
562 if ! can_import_encrypted_secret_key_material {
563 log::debug!("Backend doesn't support importing encrypt secret \
564 material. Skipping test.");
565 return Ok(());
566 }
567
568 let _serialized = serialize_maybe();
569
570 if ! $preinit() {
571 eprintln!("preinit returned false, skipping test.");
572 return Ok(());
573 }
574
575 let mut backend = $init_backend().await;
581
582 let cert = Cert::from_bytes(
583 $crate::test_framework::data::key("bob-password-bob.asc"))
584 .expect("valid cert");
585 $import_cert(&mut backend, &cert).await;
586
587 let cert = Cert::from_bytes(
588 $crate::test_framework::data::key("bob-password-smithy.asc"))
589 .expect("valid cert");
590 $import_cert(&mut backend, &cert).await;
591
592 let msg: &[u8] = $crate::test_framework::data::message("bob.asc");
593 let keyid = KeyHandle::KeyID("0A4BA2249168D779".parse()?);
594
595 assert!(
596 $crate::test_framework::try_decrypt(
597 &mut backend, msg, Some(b"hi bob\n"), keyid, None)
598 .await.is_err());
599
600 Ok(())
601 }
602
603 #[tokio::test]
604 pub async fn decrypt_with_password() -> Result<()> {
605 let _ = env_logger::Builder::from_default_env().try_init();
606
607 let can_import_encrypted_secret_key_material: bool
608 = $can_import_encrypted_secret_key_material;
609 if ! can_import_encrypted_secret_key_material {
610 log::debug!("Backend doesn't support importing encrypt secret \
611 material. Skipping test.");
612 return Ok(());
613 }
614
615 let _serialized = serialize_maybe();
616
617 if ! $preinit() {
618 eprintln!("preinit returned false, skipping test.");
619 return Ok(());
620 }
621
622 let mut backend = $init_backend().await;
631
632 let msg: &[u8] = $crate::test_framework::data::message("bob.asc");
633 let keyid = KeyHandle::KeyID("0A4BA2249168D779".parse()?);
634
635 log::info!("Importing certificate variant #1");
639 let cert = Cert::from_bytes(
640 $crate::test_framework::data::key("bob-password-bob.asc"))
641 .expect("valid cert");
642 $import_cert(&mut backend, &cert).await;
643
644 log::info!("Decrypting with wrong password:");
645 assert!(
646 $crate::test_framework::try_decrypt(
647 &mut backend, msg, Some(b"hi bob\n"),
648 keyid.clone(), Some(Password::from("sup3r s3cur3")))
649 .await.is_err());
650
651 log::info!("Decrypting with right password:");
652 $crate::test_framework::try_decrypt(
653 &mut backend, msg, Some(b"hi bob\n"),
654 keyid.clone(), Some(Password::from("bob"))).await.unwrap();
655
656 log::info!("Importing certificate variant #2");
660 let cert2 = Cert::from_bytes(
661 $crate::test_framework::data::key("bob-password-smithy.asc"))
662 .expect("valid cert");
663 assert_eq!(cert.fingerprint(), cert2.fingerprint());
664 $import_cert(&mut backend, &cert2).await;
665
666 log::info!("Decrypting with wrong password:");
667 assert!($crate::test_framework::try_decrypt(
668 &mut backend, msg, Some(b"hi bob\n"),
669 keyid.clone(), Some(Password::from("sup3r s3cur3"))).await.is_err());
670 log::info!("Decrypting with right password:");
671 $crate::test_framework::try_decrypt(
672 &mut backend, msg, Some(b"hi bob\n"),
673 keyid.clone(), Some(Password::from("smithy"))).await.unwrap();
674
675 log::info!("Importing certificate variant #3");
678 let cert3 = Cert::from_bytes(
679 $crate::test_framework::data::key("bob-no-password.asc"))
680 .expect("valid cert");
681 assert_eq!(cert.fingerprint(), cert3.fingerprint());
682 $import_cert(&mut backend, &cert3).await;
683
684 log::info!("Decrypting with right password:");
691 $crate::test_framework::try_decrypt(
692 &mut backend, msg, Some(b"hi bob\n"),
693 keyid.clone(), None).await.unwrap();
694
695 Ok(())
696 }
697
698 #[tokio::test]
699 pub async fn verify() -> Result<()> {
700 let _ = env_logger::Builder::from_default_env().try_init();
701
702 let _serialized = serialize_maybe();
703
704 if ! $preinit() {
705 eprintln!("preinit returned false, skipping test.");
706 return Ok(());
707 }
708
709 async fn test(filename: &str, signing_key: &str,
710 password: Option<&str>,
711 success: bool)
712 -> Result<()>
713 {
714 let mut backend = $init_backend().await;
715
716 let cert = Cert::from_bytes(
717 $crate::test_framework::data::key(filename))
718 .expect("valid cert");
719 $import_cert(&mut backend, &cert).await;
720
721 let mut signer = backend.find_key(&signing_key).await?;
722 if let Some(password) = password {
723 if let Err(err) = signer.unlock(Some(&password.into())).await {
724 log::warn!("Failed to unlock key: {}", err);
725 }
726 } else {
727 let default_password: Option<&str> = $default_password;
729 if let Some(default_password) = default_password {
730 let default_password = Password::from(default_password);
731 if let Err(err) = signer.unlock(Some(&default_password)).await {
732 log::warn!("Failed to unlock key: {}", err);
733 }
734 }
735 }
736
737 let signing_fpr = Fingerprint::from_hex(signing_key)
738 .expect("valid");
739
740 let expected_signers_;
741 let expected_signers: Option<&[ Fingerprint ]> = if success {
742 expected_signers_ = vec![ signing_fpr ];
743 Some(&expected_signers_[..])
744 } else {
745 None
746 };
747
748 $crate::test_framework::sign_verify(
749 vec![ signer.into() ],
750 vec![ cert.clone() ],
751 expected_signers)?;
752
753 Ok(())
754 }
755
756 test("no-password.asc", "8D46B2975890A615AF4109CB6BA1BF391DF802C8",
758 None, true).await.expect("should pass");
759
760 let can_import_encrypted_secret_key_material: bool
761 = $can_import_encrypted_secret_key_material;
762 if ! can_import_encrypted_secret_key_material {
763 log::debug!("Backend doesn't support importing encrypt secret \
764 material. Skipping the rest of the test.");
765 return Ok(());
766 }
767
768 test("bob-password-bob.asc", "9410E96E68643821794608269CB5006116833EE7",
771 None, false).await.expect("should pass");
772
773 test("bob-password-bob.asc", "9410E96E68643821794608269CB5006116833EE7",
775 Some("bob"), true).await.expect("should pass");
776
777 test("bob-password-bob.asc", "9410E96E68643821794608269CB5006116833EE7",
779 Some("wrong password"), false).await.expect("should pass");
780
781 Ok(())
782 }
783
784 #[tokio::test]
785 pub async fn list_keys() -> Result<()> {
786 let _ = env_logger::Builder::from_default_env().try_init();
787
788 let _serialized = serialize_maybe();
789
790 if ! $preinit() {
791 eprintln!("preinit returned false, skipping test.");
792 return Ok(());
793 }
794
795 let key_sets: Option<usize> = $key_sets;
796
797 let _ = env_logger::Builder::from_default_env().try_init();
798
799 {
801 let mut backend = init_backend().await;
802
803 let mut got = Vec::new();
804 for device in backend.list().await {
805 for mut key in device.list().await {
806 got.push(key.fingerprint().to_string());
807 }
808 }
809 assert!(got.is_empty());
810 }
811
812 let keyring_a: &[u8] = $crate::test_framework::data::key(
817 "carol-subkeys-a.asc");
818 let mut cert_a = Cert::from_bytes(keyring_a)
819 .expect("valid cert");
820 if key_sets.is_some() {
821 cert_a = strip_primary_secret(cert_a);
823 }
824 let keys_a = cert_a.keys().secret().map(|k| k.key().fingerprint())
825 .collect::<Vec<Fingerprint>>();
826
827 let keyring_b: &[u8] = $crate::test_framework::data::key(
828 "carol-subkeys-b.asc");
829 let mut cert_b = Cert::from_bytes(keyring_b)
830 .expect("valid cert");
831 if key_sets.is_some() {
832 cert_b = strip_primary_secret(cert_b);
834 }
835 let keys_b = cert_b.keys().secret().map(|k| k.key().fingerprint())
836 .collect::<Vec<Fingerprint>>();
837
838 assert_eq!(cert_a.fingerprint(), cert_b.fingerprint());
841 assert_ne!(keys_a, keys_b);
842
843 let mut all_keys = keys_a.clone();
844 all_keys.extend_from_slice(&keys_b);
845 all_keys.sort();
846 all_keys.dedup();
847
848 for (a, b) in [(true, false), (false, true), (true, true)].iter() {
850 if *a && *b {
851 eprintln!("Loading a and b: {:?} {:?}", keys_a, keys_b);
852 } else if *a {
853 eprintln!("Loading a: {:?}", keys_a);
854 } else if *b {
855 eprintln!("Loading b: {:?}", keys_b);
856 }
857
858 let mut keyring: Vec<&Cert> = Vec::new();
859 let mut keys: Vec<Fingerprint> = Vec::new();
860
861 if *a {
862 keyring.push(&cert_a);
863 keys.extend_from_slice(&keys_a);
864 }
865 if *b {
866 keyring.push(&cert_b);
867 keys.extend_from_slice(&keys_b);
868 }
869
870 let mut backend = init_backend().await;
871
872 for cert in keyring {
873 $import_cert(&mut backend, cert).await;
874 }
875
876 let mut got = Vec::new();
878 for device in backend.list().await {
879 for mut key in device.list().await {
880 got.push(key.fingerprint());
881 }
882 }
883 got.sort();
884
885 keys.sort();
886 keys.dedup();
887
888 assert_eq!(keys, got,
889 "Expected: {:?}\nGot: {:?}", keys, got);
890
891 for k in all_keys.iter() {
893 let expected = keys.contains(k);
894 eprintln!("Checking find_key({}) => {}",
895 k.to_string(), expected);
896 match (expected, backend.find_key(&k.to_string()).await) {
897 (true, Ok(_)) => {
898 }
899 (true, Err(err)) => {
900 panic!("Didn't find {}, but should have. \
901 Error message is: {}",
902 k, err);
903 }
904 (false, Ok(_)) => {
905 panic!("Found {}, but shouldn't have", k);
906 }
907 (false, Err(_err)) => {
908 }
909 }
910 }
911 }
912
913 Ok(())
914 }
915
916 #[tokio::test]
917 pub async fn list_only_returns_secret_keys() -> Result<()> {
918 let _ = env_logger::Builder::from_default_env().try_init();
919
920 let _serialized = serialize_maybe();
921
922 if ! $preinit() {
923 eprintln!("preinit returned false, skipping test.");
924 return Ok(());
925 }
926
927 let cert_bytes: &[u8] = test_framework::data::key(
930 "dave-not-all-keys-have-secrets.asc");
931 let cert = Cert::from_bytes(cert_bytes)
932 .expect("valid cert");
933
934 let (keys, public_keys): (Vec<(Fingerprint, bool)> , _) = cert
935 .keys()
936 .map(|k| (k.key().fingerprint(), k.key().has_secret()))
937 .partition(|(_fpr, has_secret)| *has_secret);
938
939 let keys = keys.into_iter().map(|(fpr, _)| fpr)
940 .collect::<Vec<Fingerprint>>();
941 let public_keys = public_keys.into_iter().map(|(fpr, _)| fpr)
942 .collect::<Vec<Fingerprint>>();
943
944 assert!(! keys.is_empty());
945 assert!(! public_keys.is_empty());
946
947 let mut backend = init_backend().await;
948
949 $import_cert(&mut backend, &cert).await;
950
951 let mut got = Vec::new();
953 for device in backend.list().await {
954 for key in device.list().await {
955 got.push(key.fingerprint());
956 }
957 }
958 got.sort();
959
960 assert_eq!(keys, got);
961
962 for k in keys.iter() {
964 assert!(backend.find_key(&k.to_string()).await.is_ok());
965 }
966 for k in public_keys.iter() {
968 assert!(backend.find_key(&k.to_string()).await.is_err());
969 }
970
971 Ok(())
972 }
973
974 #[tokio::test]
976 pub async fn key_export() -> Result<()> {
977 let _ = env_logger::Builder::from_default_env().try_init();
978
979 let can_export: bool = $can_export;
980 if ! can_export {
981 log::debug!("Backend doesn't support exporting secret key \
982 material. Skipping test.");
983 return Ok(());
984 }
985
986 let _serialized = serialize_maybe();
987
988 if ! $preinit() {
989 eprintln!("preinit returned false, skipping test.");
990 return Ok(());
991 }
992
993 let mut backend = $init_backend().await;
997
998 let cert = Cert::from_bytes(
999 $crate::test_framework::data::key("carol-subkeys-a.asc"))
1000 .expect("valid cert");
1001
1002 $import_cert(&mut backend, &cert).await;
1003
1004 let mut count = 0;
1005 for key in cert.keys().secret() {
1006 count += 1;
1007
1008 let mut found = false;
1009 'find: for mut d in backend.list().await {
1010 for mut k in d.list().await {
1011 if k.fingerprint() == key.key().fingerprint() {
1012 let exported_key
1013 = k.export().await.expect("can export");
1014 assert_eq!(&exported_key, key.key());
1015
1016 found = true;
1017 break 'find;
1018 }
1019 }
1020 }
1021
1022 assert!(found, "{} was not imported", key.key().fingerprint());
1023 }
1024
1025 assert!(count > 0);
1027
1028 Ok(())
1029 }
1030
1031 #[tokio::test]
1032 pub async fn change_password() -> Result<()> {
1033 let _ = env_logger::Builder::from_default_env().try_init();
1034
1035 let can_change_password: bool = $can_change_password;
1036 if ! can_change_password {
1037 log::debug!("Backend doesn't support changing passwords. \
1038 Skipping test.");
1039 return Ok(());
1040 }
1041
1042 let _serialized = serialize_maybe();
1043
1044 if ! $preinit() {
1045 eprintln!("preinit returned false, skipping test.");
1046 return Ok(());
1047 }
1048
1049 let mut backend = $init_backend().await;
1056
1057 let msg: &[u8] = $crate::test_framework::data::message("bob.asc");
1058 let fpr_str = "86353DE523CB334DC0B1F0F00A4BA2249168D779";
1059 let fpr: sequoia_openpgp::Fingerprint
1060 = fpr_str.parse().expect("valid");
1061 let keyid = KeyHandle::KeyID(fpr.into());
1062
1063 log::info!("Importing certificate variant #1");
1067 let cert = Cert::from_bytes(
1068 $crate::test_framework::data::key("bob-password-bob.asc"))
1069 .expect("valid cert");
1070 $import_cert(&mut backend, &cert).await;
1071
1072 log::info!("Decrypting with wrong password:");
1073 assert!(
1074 $crate::test_framework::try_decrypt(
1075 &mut backend, msg, Some(b"hi bob\n"),
1076 keyid.clone(), Some(Password::from("sup3r s3cur3")))
1077 .await.is_err());
1078
1079 log::info!("Decrypting with right password:");
1080 $crate::test_framework::try_decrypt(
1081 &mut backend, msg, Some(b"hi bob\n"),
1082 keyid.clone(), Some(Password::from("bob"))).await.unwrap();
1083
1084 let mut key = backend.find_key(fpr_str)
1086 .await.expect("key is present");
1087
1088 if let Err(err) = key.change_password(Some(&"new password".into())).await {
1089 if let Some($crate::Error::NoInlinePassword(msg))
1090 = err.downcast_ref()
1091 {
1092 eprintln!("Changing passwords not supported by \
1093 backend: {:?}",
1094 msg);
1095 return Ok(());
1096 } else {
1097 panic!("Failed to change password");
1098 }
1099 }
1100
1101 key.lock().await.expect("can lock key");
1103
1104 log::info!("Decrypting with wrong password:");
1105 assert!($crate::test_framework::try_decrypt(
1106 &mut backend, msg, Some(b"hi bob\n"),
1107 keyid.clone(), Some(Password::from("sup3r s3cur3"))).await.is_err());
1108 log::info!("Decrypting with old password:");
1109 assert!($crate::test_framework::try_decrypt(
1110 &mut backend, msg, Some(b"hi bob\n"),
1111 keyid.clone(), Some(Password::from("smithy"))).await.is_err());
1112 log::info!("Decrypting with new password:");
1113 $crate::test_framework::try_decrypt(
1114 &mut backend, msg, Some(b"hi bob\n"),
1115 keyid.clone(), Some(Password::from("new password"))).await.unwrap();
1116
1117 Ok(())
1118 }
1119
1120
1121 #[tokio::test]
1122 pub async fn delete_secret_key_material() -> Result<()> {
1123 let _ = env_logger::Builder::from_default_env().try_init();
1124
1125 let can_delete: bool = $can_delete;
1126 if ! can_delete {
1127 log::debug!("Backend doesn't support deleting secret key \
1128 material. Skipping test.");
1129 return Ok(());
1130 }
1131
1132 let _serialized = serialize_maybe();
1133
1134 if ! $preinit() {
1135 eprintln!("preinit returned false, skipping test.");
1136 return Ok(());
1137 }
1138
1139 let mut backend = $init_backend().await;
1146
1147 let msg: &[u8] = $crate::test_framework::data::message("bob.asc");
1148
1149 let fpr_str = "86353DE523CB334DC0B1F0F00A4BA2249168D779";
1150 let fpr: sequoia_openpgp::Fingerprint
1151 = fpr_str.parse().expect("valid");
1152 let keyid = KeyHandle::KeyID(fpr.into());
1153
1154 log::info!("Importing certificate variant #1");
1158 let cert = Cert::from_bytes(
1159 $crate::test_framework::data::key("bob-password-bob.asc"))
1160 .expect("valid cert");
1161 $import_cert(&mut backend, &cert).await;
1162
1163 log::info!("Decrypting with wrong password:");
1164 assert!(
1165 $crate::test_framework::try_decrypt(
1166 &mut backend, msg, Some(b"hi bob\n"),
1167 keyid.clone(), Some(Password::from("sup3r s3cur3")))
1168 .await.is_err());
1169
1170 log::info!("Decrypting with right password:");
1171 $crate::test_framework::try_decrypt(
1172 &mut backend, msg, Some(b"hi bob\n"),
1173 keyid.clone(), Some(Password::from("bob"))).await.unwrap();
1174
1175 log::info!("Deleting primary key:");
1177 let primary = cert.fingerprint().to_string();
1178 let mut key = backend.find_key(&primary)
1179 .await.expect("key is present");
1180
1181 if key.password_source().await.is_external_source() {
1182 eprintln!("Skipping test: backend requires that the user \
1183 confirm key deletion");
1184 return Ok(());
1185 }
1186
1187 if let Err(err) = key.delete_secret_key_material().await {
1188 panic!("Failed to delete {}", primary);
1189 }
1190
1191 assert!(backend.find_key(&primary).await.is_err());
1193
1194 log::info!("Decrypting with right password:");
1195 $crate::test_framework::try_decrypt(
1196 &mut backend, msg, Some(b"hi bob\n"),
1197 keyid.clone(), Some(Password::from("bob"))).await.unwrap();
1198
1199 log::info!("Deleting decryption key:");
1200 let mut key = backend.find_key(&fpr_str)
1201 .await.expect("key is present");
1202
1203 if let Err(err) = key.delete_secret_key_material().await {
1204 panic!("Failed to delete {}", primary);
1205 }
1206
1207 assert!(
1208 $crate::test_framework::try_decrypt(
1209 &mut backend, msg, Some(b"hi bob\n"),
1210 keyid.clone(), Some(Password::from("bob")))
1211 .await.is_err());
1212
1213 assert!(backend.find_key(&fpr_str).await.is_err());
1215
1216 Ok(())
1217 }
1218 };
1219}