prs_lib/crypto/backend/rpgpie/
context.rs1use std::ops::Deref;
4
5use anyhow::Result;
6use thiserror::Error;
7
8use crate::crypto::{Config, IsContext, Key, Proto};
9use crate::{Ciphertext, Plaintext, Recipients};
10use rpgpie_certificate_store::{Error as StoreError, Store};
11
12use super::raw;
13
14pub fn context(_config: &Config) -> Result<Context, Error> {
16 let store = Store::new()?;
17 Ok(Context::from(store))
18}
19
20pub struct Context {
22 pub(super) store: rpgpie_certificate_store::Store,
24}
25
26impl Context {
27 pub fn from(store: Store) -> Self {
28 Self { store }
29 }
30}
31
32impl IsContext for Context {
33 fn encrypt(&mut self, recipients: &Recipients, plaintext: Plaintext) -> Result<Ciphertext> {
34 let fps = recipients
35 .keys()
36 .iter()
37 .map(|k| k.fingerprint(false))
38 .collect::<Vec<_>>();
39 raw::encrypt(&mut *self, fps.deref(), plaintext.unsecure_ref())
40 }
41
42 fn decrypt(&mut self, ciphertext: Ciphertext) -> Result<Plaintext> {
43 Ok(raw::decrypt(&mut *self, ciphertext.unsecure_ref())?)
44 }
45
46 fn can_decrypt(&mut self, ciphertext: Ciphertext) -> Result<bool> {
47 let res = raw::decrypt(&mut *self, ciphertext.unsecure_ref());
48 match res {
49 Ok(_) => Ok(true),
50 Err(Error::NoSecretKey) => Ok(false),
51 Err(err) => Err(err.into()),
52 }
53 }
54
55 fn keys_public(&mut self) -> Result<Vec<Key>> {
56 let certs = self.store.search_like_user_id("%")?;
57
58 Ok(certs
59 .into_iter()
60 .map(|c| raw::metadata_for_cert(&c))
61 .collect())
62 }
63
64 fn keys_private(&mut self) -> Result<Vec<Key>> {
65 let store = rpgpie_certificate_store::Store::new()?;
67
68 let mut keys = Vec::new();
70 let cards = raw::cards()?;
71
72 for mut card in cards {
73 let fingerprint = card
74 .transaction()?
75 .fingerprint(openpgp_card::ocard::KeyType::Decryption)?;
76
77 if let Some(fp) = fingerprint {
78 let certs = store.search_by_fingerprint(&fp.to_hex())?;
79 for cert in certs {
80 keys.push(raw::metadata_for_cert(&cert));
81 }
82 }
83 }
84
85 Ok(keys)
86 }
87
88 fn import_key(&mut self, key: &[u8]) -> Result<()> {
89 let certs = rpgpie::certificate::Certificate::load(&mut std::io::Cursor::new(key))?;
90 for cert in certs {
91 let existing = self
92 .store
93 .get_by_primary_fingerprint(&raw::format_fingerprint(cert.fingerprint()))?;
94
95 if existing.is_none() {
96 self.store.insert(&cert)?;
97 }
98 }
99
100 Ok(())
101 }
102
103 fn export_key(&mut self, key: Key) -> Result<Vec<u8>> {
104 let mut certs = self
105 .store
106 .get_by_primary_fingerprint(&key.fingerprint(false))?
107 .into_iter()
108 .chain(self.store.search_by_fingerprint(&key.fingerprint(false))?);
109
110 if let Some(cert) = certs.next() {
111 let mut data = Vec::new();
112 cert.save(true, &mut data)?;
113 Ok(data)
114 } else {
115 Err(Error::CertificateMissing.into())
116 }
117 }
118
119 fn supports_proto(&self, proto: Proto) -> bool {
120 proto == Proto::Gpg
121 }
122}
123
124#[derive(Debug, Error)]
126pub enum Error {
127 #[error("Certificate store: {0:?}")]
129 CertificateStore(#[from] StoreError),
130 #[error("Smartcard error: {0}")]
131 Smartcard(#[from] openpgp_card::Error),
132 #[error("PGP error: {0}")]
133 Pgp(#[from] pgp::errors::Error),
134 #[error("No secret key to decrypt message")]
135 NoSecretKey,
136 #[error("No public key to encrypt message")]
137 NoPublicKey,
138 #[error("Unimplemented ({0})")]
139 Unimplemented(String),
140 #[error("Malformed OpenPGP message data")]
141 MalformedMessage,
142 #[error("No usable public keys")]
143 NoUsablePublicKeys,
144 #[error("Certificate missing from key store")]
145 CertificateMissing,
146 #[error("{0}")]
147 Any(#[from] anyhow::Error),
148}