sequoia_keystore_backend/
test_framework.rs

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
32/// Test data.
33pub mod data;
34
35use crate as backend;
36
37use crate::Backend;
38use crate::utils::run_async;
39
40// A wrapper for KeyHandle, which implements crypto::Signer.
41pub 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"); // XXX: don't unwrap
50        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    // The certificates.
71    pub keyring: Vec<Cert>,
72    // The good signatures.
73    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
122/// Sign a message and verify that the signature is good.
123///
124/// If signing_keys is None, this is expected to fail.
125pub 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            // Expected failure.
151            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
175/// Try to decrypt a message.
176///
177/// `ciphertext` is the well-formed encrypted message.
178/// plaintext is the expected plaintext.  If it is not `None`,
179/// then it must match what is decrypted.
180///
181/// `password` is an optional password.  If supplied, then it
182/// must be used to unlock the key.
183///
184/// This function tries to decrypt all of the keys with the password.
185pub 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                // Manual search.
202                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                            // Relock, just in case.
221                            key.lock().await?;
222
223                            if let Err(e) = key.unlock(Some(password)).await {
224                                eprintln!("Failed to unlock key: {}", e);
225                                // There may be another key that we
226                                // can unlock with this password.
227                                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                // Catch-all for packets that failed the manual search.
246                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        // A possible reason this may fail is if the message uses
284        // compression, but compression support is not enabled.
285        assert!(good);
286    }
287
288    Ok(())
289}
290
291/// Preinit is a function that is called at the start of every
292/// test.  If it returns `true`, the test should be run.  If it
293/// returns `false`, then the test should be skipped.  This is useful
294/// when the required test infrastructure is not detected.
295///
296/// `$serialize_tests` is whether to serialize the tests for this
297/// backend.  If `false`, the tests are run concurrently.
298///
299/// `$import_cert` imports a certificate into the backend.
300///
301/// `$can_import_encrypted_secret_key_material` is whether
302/// `$import_cert` can import encrypted secret key material.
303///
304/// If `$key_sets` is `Some`, then the backend can only load standard
305/// keys consisting of (up to) an encrypt key, a signing key and an
306/// authentication key.  The integer indicates the number of key sets
307/// that the backend can load simultaneously.  If `$key_sets` is
308/// `None`, then the backend can load an infinite number of keys.
309///
310/// Some backends always protect keys by default.  If
311/// `$default_password` is `Some` that's the password for keys when
312/// they are imported.
313#[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                            // Another test panicked.  Don't let that
332                            // stop us.
333                            SERIALIZE.clear_poison();
334                        }
335                    }
336                }
337            } else {
338                None
339            }
340        }
341
342        /// strip the primary key's secret key material, if any.
343        ///
344        /// This is useful when `$key_sets` is `Some` and the backend
345        /// doesn't have space for the primary key.
346        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        // Make sure $import_cert works.
360        #[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            // A simple test: import a certificate.  Make sure the
372            // keys are actually imported.
373
374            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        // Check backend.import_cert.
421        #[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            // A simple test: import a certificate.  Make sure the
433            // keys are actually imported.
434
435            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                            // The backend does not support import_cert.
455                            // That's okay.  Skip the test.
456                            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            // A simple test: given a secret key and a message encrypted to
531            // the key, can we use the backend to decrypt it?
532
533            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            // Load a few variants of a certificate: one where the
576            // keys are encrypted with the password "bob", one where
577            // they are encrypted with the password "smithy", and one
578            // that is not encrypted.
579
580            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            // Load a certificate where the keys are encrypted with
623            // the password "bob".  Make sure we can decrypt the
624            // message.  Load a variant of the certificate where the
625            // passwords have been changed.  Make sure we can decrypt
626            // the message with the new password.  Finally, load a
627            // variant of the certificate where the keys are not
628            // encrypted.
629
630            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            // Import Bob's certificate.  The keys are password
636            // protected.  Make sure we can use them with the right
637            // password, and can't with the wrong one.
638            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            // Import a new version of Bob's certificate in which the
657            // keys are still encrypted, but with a different
658            // password.
659            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            // Import a third version of Bob's certificate in which
676            // the keys are not encrypt.
677            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            // Note: using the wrong password does not always fail
685            // with a key that is not password protected.  For
686            // instance, the gpg-agent backend only provides the
687            // cached password on demand.  Since the key is not
688            // password protected, it won't ask for a password.
689
690            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                    // Use the default password (if configured).
728                    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            // A simple test: sign a message using a key with no password.
757            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            // Sign a message using a key that is password protected,
769            // but don't provide the password.  Make sure it fails.
770            test("bob-password-bob.asc", "9410E96E68643821794608269CB5006116833EE7",
771                 None, false).await.expect("should pass");
772
773            // Now provide the password.
774            test("bob-password-bob.asc", "9410E96E68643821794608269CB5006116833EE7",
775                 Some("bob"), true).await.expect("should pass");
776
777            // And now provide the wrong password.
778            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            // We first make sure that we can list the empty backend.
800            {
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            // We have two variants of a certificate with disjoint
813            // subkeys.  When we load both certificates, make sure both
814            // sets of variants appear.
815
816            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                // Strip the primary.
822                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                // Strip the primary.
833                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            // We expect the same certificate, but with different
839            // subkeys.
840            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            // Try with just a, then just b, then both variants.
849            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                // Check that we can find the cert by iterating.
877                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                // Check that Backend::find_key returns all of the keys.
892                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            // Make sure only keys with secret key material are returned.
928
929            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            // List the keys.
952            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            // Check that Backend::find_key returns all of the keys.
963            for k in keys.iter() {
964                assert!(backend.find_key(&k.to_string()).await.is_ok());
965            }
966            // And doesn't return the public keys.
967            for k in public_keys.iter() {
968                assert!(backend.find_key(&k.to_string()).await.is_err());
969            }
970
971            Ok(())
972        }
973
974        // Check key.export
975        #[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            // A simple test: import a certificate.  Make sure the
994            // keys are actually imported.
995
996            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            // Make sure we tested something.
1026            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            // Load a certificate where the keys are encrypted with
1050            // the password "bob".  Make sure we can use it to decrypt
1051            // a message.  Change the key's password, and relock it.
1052            // Make sure we can't decrypt the message with the old
1053            // password, but can decrypt it with the new password.
1054
1055            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            // Import Bob's certificate.  They keys are password
1064            // protected.  Make sure we can use them with the right
1065            // password, and can't with the wrong one.
1066            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            // Change the password.
1085            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            // Relock the key.
1102            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            // Load a certificate where the keys are encrypted with
1140            // the password "bob".  Make sure we can use it to decrypt
1141            // a message.  Delete the primary key.  Make sure we can
1142            // still decrypt the message.  Delete the decryption key.
1143            // Make sure we can't decrypt the message anymore.
1144
1145            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            // Import Bob's certificate.  They keys are password
1155            // protected.  Make sure we can use them with the right
1156            // password, and can't with the wrong one.
1157            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            // Delete the primary key.
1176            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            // Make sure we can't find the primary key any more.
1192            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            // Make sure we can't find the decryption key any more.
1214            assert!(backend.find_key(&fpr_str).await.is_err());
1215
1216            Ok(())
1217        }
1218    };
1219}