1use std::collections::HashMap;
2use std::collections::hash_map::Entry;
3use std::path::Path;
4use std::sync::Arc;
5use std::sync::Weak;
6use std::time::Duration;
7use std::time::SystemTime;
8
9use futures::lock::Mutex;
10
11use card_backend_pcsc;
12
13use openpgp_card::ocard::crypto::Cryptogram;
14use openpgp_card::ocard::data::KeyStatus;
15use openpgp_card::ocard::KeyType;
16use openpgp_card::ocard::Transaction;
17
18use sequoia_openpgp as openpgp;
19use openpgp::Cert;
20use openpgp::Fingerprint;
21use openpgp::Result;
22use openpgp::crypto::mem::Protected;
23use openpgp::crypto::ecdh;
24use openpgp::crypto::mpi;
25use openpgp::crypto::Password;
26use openpgp::crypto::SessionKey;
27use openpgp::packet;
28use openpgp::types::Curve;
29use openpgp::types::HashAlgorithm;
30use openpgp::types::PublicKeyAlgorithm;
31
32use sequoia_keystore_backend as backend;
33use backend::Error;
34use backend::ImportStatus;
35use backend::PasswordSource;
36use backend::Protection;
37use backend::utils::Directory;
38
39mod certd;
40
41#[cfg(test)]
44mod privkey;
45
46#[derive(Clone)]
47pub struct Backend {
48 inner: Arc<Mutex<BackendInternal>>,
49}
50
51struct BackendInternal {
52 home: Directory,
53
54 enabled: bool,
56
57 certd: Arc<certd::CertD>,
63
64 devices: Vec<Device>,
67
68 last_scan: Option<SystemTime>,
69}
70
71#[derive(Clone)]
77pub struct Device {
78 id: String,
80 inner: Arc<Mutex<DeviceInternal>>
81}
82
83impl Device {
84 fn downgrade(&self) -> WeakDevice {
86 WeakDevice {
87 id: self.id.clone(),
88 inner: Arc::downgrade(&self.inner),
89 }
90 }
91}
92
93#[derive(Clone)]
97pub struct WeakDevice {
98 id: String,
99 inner: Weak<Mutex<DeviceInternal>>,
100}
101
102impl WeakDevice {
103 fn upgrade(&self) -> Option<Device> {
105 Some(Device {
106 id: self.id.clone(),
107 inner: self.inner.upgrade()?,
108 })
109 }
110}
111
112struct DeviceInternal {
113 id: String,
118
119 card: openpgp_card::Card<openpgp_card::state::Open>,
124
125 pinpad: bool,
127
128 keys: HashMap<Fingerprint, Key>,
130}
131
132#[derive(Clone)]
133pub struct Key {
134 fpr: Fingerprint,
136 inner: Arc<Mutex<KeyInternal>>,
137}
138
139struct KeyInternal {
141 device: WeakDevice,
142
143 fingerprint: Fingerprint,
144 public_key: packet::Key<packet::key::PublicParts,
145 packet::key::UnspecifiedRole>,
146
147 password: Option<Password>,
162
163 slot: openpgp_card::ocard::KeyType,
165}
166
167impl Backend {
168 pub async fn init<P: AsRef<Path>>(home: P, default: bool)
176 -> Result<Self>
177 {
178 log::trace!("Backend::init");
179
180 let home = Directory::from(home.as_ref());
181
182 let certd = Arc::new(certd::CertD::new()?);
183
184 Ok(Backend {
185 inner: Arc::new(Mutex::new(BackendInternal {
186 home,
187 enabled: default,
188 certd,
189 devices: vec![],
190 last_scan: None,
191 }))
192 })
193 }
194
195 pub async fn init_ephemeral() -> Result<Self> {
199 log::trace!("Backend::init_ephemeral");
200
201 let home = Directory::ephemeral()?;
202 Self::init(home, true).await
204 }
205}
206
207impl BackendInternal {
208 async fn scan_internal(&mut self, force: bool) -> Result<()> {
209 log::trace!("Backend::scan");
210
211 if ! self.enabled {
212 log::debug!("OpenPGP Card backend is disabled");
213 return Ok(());
214 }
215
216 if ! force {
217 if let Some(last_scan) = self.last_scan {
219 if let Ok(duration) = SystemTime::now().duration_since(last_scan) {
220 if duration < Duration::new(3, 0) {
221 return Ok(())
222 }
223 }
224 }
225 }
226
227 let certd = Arc::clone(&self.certd);
228
229 let card_backends = match card_backend_pcsc::PcscBackend::cards(None) {
230 Ok(card_backends) => card_backends.collect(),
231 Err(err) => {
232 log::debug!("Listing openpgp cards using PC/SC: {}", err);
233 Vec::new()
234 }
235 };
236
237 for card_backend in card_backends.into_iter() {
240 let card_backend = match card_backend {
241 Ok(card_backend) => card_backend,
242 Err(err) => {
243 log::debug!("Opening openpgp card backend: {}", err);
244 continue;
245 }
246 };
247
248 let mut card = match openpgp_card::Card::new(card_backend) {
249 Ok(card) => card,
250 Err(err) => {
251 log::debug!("Opening openpgp card: {}", err);
252 continue;
253 }
254 };
255
256 let mut tx = match card.transaction() {
257 Ok(tx) => tx,
258 Err(err) => {
259 log::debug!("Starting transaction on openpgp card: {}", err);
260 continue;
261 }
262 };
263
264 let id = match tx.application_identifier() {
266 Ok(id) => id,
267 Err(err) => {
268 log::debug!("Getting application id from openpgp card: {}", err);
269 continue;
270 }
271 };
272 let id = id.ident();
273
274 let keyinfo = match tx.key_information() {
276 Ok(keyinfo) => keyinfo,
277 Err(err) => {
278 log::debug!("Getting key information from openpgp card: {}", err);
279 continue;
280 }
281 };
282
283 let present = if let Some(keyinfo) = keyinfo {
284 [
285 keyinfo.sig_status() != KeyStatus::NotPresent,
286 keyinfo.dec_status() != KeyStatus::NotPresent,
287 keyinfo.aut_status() != KeyStatus::NotPresent
288 ]
289 } else {
290 [false, false, false]
291 };
292
293 let fprs = match tx.fingerprints() {
294 Ok(tx) => tx,
295 Err(err) => {
296 log::debug!("Getting fingerprints from openpgp card: {}", err);
297 continue;
298 }
299 };
300
301 let pinpad = tx.feature_pinpad_verify();
302
303 drop(tx);
304
305 let mut device = None;
307 for d in self.devices.iter_mut() {
308 if d.id == id {
309 device = Some(d);
310 }
311 }
312
313 let device = if let Some(device) = device {
314 device
316 } else {
317 let device = Device {
319 id: id.clone(),
320 inner: Arc::new(Mutex::new(DeviceInternal {
321 id: id.clone(),
322 keys: HashMap::new(),
323 card: card,
324 pinpad,
325 })),
326 };
327
328 self.devices.push(device);
329
330 self.devices.last_mut().unwrap()
331 };
332
333 let mut device_internal = device.inner.lock().await;
334
335 let fprs = &[
336 (fprs.signature(), KeyType::Signing),
337 (fprs.decryption(), KeyType::Decryption),
338 (fprs.authentication(), KeyType::Authentication),
339 ][..];
340
341 for ((fpr, slot), present) in fprs.into_iter().zip(present.into_iter()) {
342 let Some(fpr) = fpr else { continue };
343 let fpr = Fingerprint::from_bytes(4, fpr.as_bytes())?;
347 log::trace!("{}: {}present",
348 fpr, if present { "" } else { "NOT " });
349
350 match device_internal.keys.entry(fpr.clone()) {
351 Entry::Occupied(_oe) => {
352 }
354 Entry::Vacant(ve) => {
355 log::debug!("Found key {}", fpr);
357
358 if let Some(pk) = certd.find_one(&fpr).await {
359 let key = Key {
360 fpr: fpr.clone(),
361 inner: Arc::new(Mutex::new(KeyInternal {
362 device: device.downgrade(),
363 fingerprint: fpr,
364 public_key: pk,
366 password: None,
367 slot: slot.clone(),
368 })),
369 };
370
371 ve.insert(key);
372 } else {
373 log::debug!("Ignoring {}: no public key available",
374 fpr);
375 }
376 }
377 }
378 }
379 }
380
381 self.last_scan = Some(SystemTime::now());
382
383 Ok(())
384 }
385}
386
387#[async_trait::async_trait]
388impl backend::Backend for Backend {
389 fn id(&self) -> String {
390 "openpgp-card".into()
391 }
392
393 async fn scan(&mut self) -> Result<()> {
394 let mut backend = self.inner.lock().await;
395 backend.scan_internal(false).await
396 }
397
398 async fn list<'a>(&'a self)
399 -> Box<dyn Iterator<Item=Box<dyn backend::DeviceHandle + Send + Sync + 'a>>
400 + Send + Sync + 'a>
401 {
402 log::trace!("Backend::list");
403
404 let mut backend = self.inner.lock().await;
405
406 if let Err(err) = backend.scan_internal(false).await {
407 log::debug!("Scanning OpenPGP Cards: {}", err);
408 }
409
410 Box::new(
411 backend.devices.iter()
412 .map(|device| {
413 Box::new(device.clone())
414 as Box<dyn backend::DeviceHandle + Send + Sync>
415 })
416 .collect::<Vec<_>>()
417 .into_iter())
418 }
419
420 async fn find_device<'a>(&self, id: &str)
421 -> Result<Box<dyn backend::DeviceHandle + Send + Sync + 'a>>
422 {
423 log::trace!("Backend::find_device");
424
425 let mut backend = self.inner.lock().await;
426
427 for scan in [false, true] {
430 if scan {
431 log::trace!("Rescanning");
432 if let Err(err) = backend.scan_internal(true).await {
433 log::debug!("Scanning OpenPGP Cards: {}", err);
434 }
435 }
436
437 for device in backend.devices.iter() {
438 if device.id == id {
439 return Ok(Box::new(device.clone())
440 as Box<dyn backend::DeviceHandle + Send + Sync>);
441 }
442 }
443 }
444
445 Err(Error::NotFound(id.into()).into())
446 }
447
448 async fn find_key<'a>(&self, id: &str)
449 -> Result<Box<dyn backend::KeyHandle + Send + Sync + 'a>>
450 {
451 log::trace!("Backend::find_key");
452
453 let mut backend = self.inner.lock().await;
454
455 for scan in [false, true] {
458 if scan {
459 log::trace!("Rescanning");
460 if let Err(err) = backend.scan_internal(true).await {
461 log::debug!("Scanning OpenPGP Cards: {}", err);
462 }
463 }
464
465 for device in backend.devices.iter() {
466 let device = device.inner.lock().await;
467
468 for (key_id, key) in device.keys.iter() {
469 if &key_id.to_string() == id {
470 return Ok(Box::new(key.clone())
471 as Box<dyn backend::KeyHandle + Send + Sync>);
472 }
473 }
474 }
475 }
476
477 Err(Error::NotFound(id.into()).into())
478 }
479
480 async fn import<'a>(&self, _cert: Cert)
481 -> Result<Vec<(ImportStatus,
482 Box<dyn backend::KeyHandle + Send + Sync + 'a>)>>
483 {
484 log::trace!("Backend::import");
485
486 Err(Error::ExternalImportRequired(Some(
487 "To import a key into an OpenPGP Card, use something like: \
488 oct admin --card ABCD:01234567 import key.priv".into())).into())
489 }
490}
491
492#[async_trait::async_trait]
493impl backend::DeviceHandle for Device {
494 fn id(&self) -> String {
495 log::trace!("Device::id");
496
497 self.id.clone()
498 }
499
500 async fn available(&self) -> bool {
501 log::trace!("Device::available");
502
503 true
506 }
507
508 async fn configured(&self) -> bool {
509 log::trace!("Device::configured");
510
511 true
514 }
515
516 async fn registered(&self) -> bool {
517 log::trace!("Device::registered");
518
519
520 true
523 }
524
525 async fn lock(&mut self) -> Result<()> {
526 log::trace!("Device::lock");
527
528 let device = self.inner.lock().await;
530 for key in device.keys.values() {
531 let mut key_internal = key.inner.lock().await;
532 key_internal.password = None;
533 }
534
535 Ok(())
536 }
537
538 async fn list<'a>(&'a self)
539 -> Box<dyn Iterator<Item=Box<dyn backend::KeyHandle + Send + Sync + 'a>>
540 + Send + Sync + 'a>
541 {
542 log::trace!("Device::list");
543
544 let device = self.inner.lock().await;
545 let keys = device.keys.values()
546 .map(|key| {
547 Box::new(key.clone())
548 as Box<dyn backend::KeyHandle + Send + Sync>
549 })
550 .collect::<Vec<_>>();
551
552 Box::new(keys.into_iter())
553 }
554}
555
556#[async_trait::async_trait]
557impl backend::KeyHandle for Key {
558 fn id(&self) -> String {
559 log::trace!("Key::id");
560
561 self.fpr.to_string()
562 }
563
564 fn fingerprint(&self) -> Fingerprint {
565 log::trace!("Key::fingerprint");
566
567 self.fpr.clone()
568 }
569
570 async fn device<'a>(&self)
571 -> Box<dyn backend::DeviceHandle + Send + Sync + 'a>
572 {
573 log::trace!("Key::device");
574
575 let key_internal = self.inner.lock().await;
576
577 let device = match key_internal.device.upgrade() {
579 Some(device) => device,
580 None => panic!("Device disappeared"),
581 };
582
583 Box::new(device)
584 }
585
586 async fn available(&self) -> bool {
594 log::trace!("Key::available");
595
596 true
599 }
600
601 async fn locked(&self) -> Protection {
602 log::trace!("Key::locked");
603
604 let key_internal = self.inner.lock().await;
616 let slot = key_internal.slot;
617
618 let slot_str = || {
619 match slot {
620 KeyType::Signing => "signing".to_string(),
621 KeyType::Decryption => "decryption".to_string(),
622 KeyType::Authentication => "authentication".to_string(),
623 s => format!("{:?}", s),
624 }
625 };
626
627 if key_internal.password.is_some() {
628 return Protection::Unlocked;
629 }
630
631 let device = match key_internal.device.upgrade() {
633 Some(device) => device,
634 None => {
635 return Protection::ExternalOther(
636 Some("Card disappeared".into()));
637 }
638 };
639 drop(key_internal);
641 let mut device_internal = device.inner.lock().await;
642
643 if device_internal.pinpad {
644 return Protection::ExternalPassword(None);
645 }
646
647 let mut tx = match device_internal.card.transaction() {
648 Ok(tx) => tx,
649 Err(err) => {
650 log::debug!("Starting transaction on openpgp card: {}", err);
651 return Protection::ExternalOther(Some(
652 "Communication with card failed".into()));
653 }
654 };
655
656 match tx.user_interaction_flag(slot) {
657 Ok(uif) => {
658 if let Some(uif) = uif {
659 if uif.touch_policy().touch_required() {
660 return Protection::Password(Some(
671 format!("Enter PIN and touch the OpenPGP card \
672 to unlock the {} key", slot_str())))
673 }
674 }
675 }
676 Err(err) => {
677 log::debug!("Getting user interaction flags: {}", err);
678 }
679 }
680
681 Protection::Password(Some(
682 format!("Enter PIN to unlock the {} key", slot_str())))
683 }
684
685 async fn password_source(&self) -> PasswordSource {
686 log::trace!("Key::password_source");
687
688 let key_internal = self.inner.lock().await;
691
692 let device = match key_internal.device.upgrade() {
694 Some(device) => device,
695 None => {
696 return PasswordSource::ExternalSideEffect;
698 }
699 };
700 drop(key_internal);
702 let mut device_internal = device.inner.lock().await;
703 let key_internal = self.inner.lock().await;
705
706 if device_internal.pinpad {
707 return PasswordSource::ExternalSideEffect;
709 }
710
711 let mut tx = match device_internal.card.transaction() {
712 Ok(tx) => tx,
713 Err(err) => {
714 log::debug!("Starting transaction on openpgp card: {}", err);
715 return PasswordSource::ExternalSideEffect;
717 }
718 };
719
720 match tx.user_interaction_flag(key_internal.slot) {
721 Ok(uif) => {
722 if let Some(uif) = uif {
723 if uif.touch_policy().touch_required() {
724 return PasswordSource::InlineWithConfirmation;
725 }
726 }
727 }
728 Err(err) => {
729 log::debug!("Getting user interaction flags: {}", err);
730 }
731 }
732
733 PasswordSource::Inline
734 }
735
736 async fn decryption_capable(&self) -> bool {
737 log::trace!("Key::decryption_capable");
738
739 let key_internal = self.inner.lock().await;
740 match key_internal.slot {
741 KeyType::Signing => false,
742 KeyType::Decryption => true,
743 KeyType::Authentication => false,
744 _ => false,
745 }
746 }
747
748 async fn signing_capable(&self) -> bool {
749 log::trace!("Key::signing_capable");
750
751 let key_internal = self.inner.lock().await;
752 match key_internal.slot {
753 KeyType::Signing => true,
754 KeyType::Decryption => false,
755 KeyType::Authentication => true,
756 _ => false,
757 }
758 }
759
760 async fn unlock(&mut self, password: Option<&Password>) -> Result<()> {
761 log::trace!("Key::unlock");
762
763 let key_internal = self.inner.lock().await;
766
767 if key_internal.password.is_some() {
768 return Err(Error::AlreadyUnlocked(
769 "Key is already unlocked".into()).into());
770 }
771
772 let device = match key_internal.device.upgrade() {
774 Some(device) => device,
775 None => {
776 return Err(anyhow::anyhow!("Card disappeared"));
777 }
778 };
779 drop(key_internal);
781 let mut device_internal = device.inner.lock().await;
782 let mut key_internal = self.inner.lock().await;
784
785 let pinpad = device_internal.pinpad;
788
789 let mut tx = match device_internal.card.transaction() {
790 Ok(tx) => tx,
791 Err(err) => {
792 log::debug!("Starting transaction on openpgp card: {}", err);
793 return Err(err.into());
795 }
796 };
797
798 if let Some(password) = password {
799 if pinpad {
802 return Err(Error::NoInlinePassword(None).into());
805 }
806
807 let p = password.map(|p| String::from_utf8(p.to_vec()))?;
808
809 if key_internal.slot == KeyType::Signing {
810 tx.verify_user_signing_pin(p.into())?;
811 } else {
812 tx.verify_user_pin(p.into())?;
813 }
814 key_internal.password = Some(password.clone());
815 } else {
816 if ! pinpad {
820 return Err(Error::NoExternalPassword(
821 Some("Cannot prompt user for password".into())).into());
822 }
823
824 fn cb() {}
825 if key_internal.slot == KeyType::Signing {
826 tx.verify_user_signing_pinpad(&cb)?;
827 } else {
828 tx.verify_user_pinpad(&cb)?;
829 }
830 }
831
832 Ok(())
833 }
834
835 async fn lock(&mut self) -> Result<()> {
836 log::trace!("Key::lock");
837
838 let mut key_internal = self.inner.lock().await;
839
840 key_internal.password = None;
841
842 Ok(())
846 }
847
848 async fn public_key(&self)
849 -> packet::Key<packet::key::PublicParts,
850 packet::key::UnspecifiedRole>
851 {
852 log::trace!("Key::public_key");
853
854 let key = self.inner.lock().await;
855 key.public_key.clone()
856 }
857
858 async fn decrypt_ciphertext(&mut self,
860 ciphertext: &mpi::Ciphertext,
861 _plaintext_len: Option<usize>)
862 -> Result<SessionKey>
863 {
864 log::trace!("Key::decrypt_ciphertext");
865
866 let key_internal = self.inner.lock().await;
870
871 let public_key = key_internal.public_key.clone();
873 let password = key_internal.password.clone();
874
875 let device = match key_internal.device.upgrade() {
877 Some(device) => device,
878 None => {
879 return Err(anyhow::anyhow!("Card disappeared"));
880 }
881 };
882 drop(key_internal);
884 let mut device_internal = device.inner.lock().await;
885
886 let mut tx = match device_internal.card.transaction() {
887 Ok(tx) => tx,
888 Err(err) => {
889 log::debug!("Starting transaction on openpgp card: {}", err);
890 return Err(err.into());
892 }
893 };
894
895 let unlock = || -> Result<()> {
906 if let Some(password) = password {
907 let password = password.map(|p| String::from_utf8(p.to_vec()))?;
908 tx.verify_user_pin(password.into())?;
909 }
910
911 Ok(())
912 };
913
914 match (ciphertext, public_key.mpis()) {
921 (mpi::Ciphertext::RSA { c: ct }, mpi::PublicKey::RSA { .. }) => {
922 let dm = Cryptogram::RSA(ct.value());
923
924 unlock()?;
925 let dec = tx.card().decipher(dm)?;
926
927 let sk = SessionKey::from(&dec[..]);
928 Ok(sk)
929 }
930 (mpi::Ciphertext::ECDH { ref e, .. }, mpi::PublicKey::ECDH { ref curve, .. }) => {
931 let dm = if curve == &Curve::Cv25519 {
932 assert_eq!(
933 e.value()[0],
934 0x40,
935 "Unexpected shape of decrypted Cv25519 data"
936 );
937
938 Cryptogram::ECDH(&e.value()[1..])
940 } else {
941 Cryptogram::ECDH(e.value())
943 };
944
945 unlock()?;
947 let mut dec = tx.card().decipher(dm)?;
948
949 if curve == &Curve::NistP256 && dec.len() == 65 {
953 assert_eq!(dec[0], 0x04, "Unexpected shape of decrypted NistP256 data");
954
955 dec = dec[1..33].to_vec();
957 }
958
959 #[allow(non_snake_case)]
960 let S: Protected = dec.into();
961
962 Ok(ecdh::decrypt_unwrap(&public_key, &S, ciphertext, None )?)
963 }
964
965 (ciphertext, public) => Err(anyhow::anyhow!(
966 "Unsupported combination of ciphertext {:?} \
967 and public key {:?} ",
968 ciphertext,
969 public
970 )),
971 }
972 }
973
974 async fn sign(&mut self, hash_algo: HashAlgorithm, digest: &[u8])
975 -> Result<(PublicKeyAlgorithm, mpi::Signature)>
976 {
977 log::trace!("Key::sign");
978
979 let key_internal = self.inner.lock().await;
983
984 let public_key = key_internal.public_key.clone();
986 let password = key_internal.password.clone();
987 let slot = key_internal.slot;
988
989 let device = match key_internal.device.upgrade() {
991 Some(device) => device,
992 None => {
993 return Err(anyhow::anyhow!("Card disappeared"));
994 }
995 };
996 drop(key_internal);
998 let mut device_internal = device.inner.lock().await;
999
1000 let mut tx = match device_internal.card.transaction() {
1001 Ok(tx) => tx,
1002 Err(err) => {
1003 log::debug!("Starting transaction on openpgp card: {}", err);
1004 return Err(err.into());
1006 }
1007 };
1008
1009 let unlock = || -> Result<()> {
1010 if let Some(password) = password {
1011 log::trace!("Unlocking key with password");
1012 let password = password.map(|p| String::from_utf8(p.to_vec()))?;
1013 tx.verify_user_signing_pin(password.into())?;
1014 log::trace!("Successfully unlocked slot");
1015 } else {
1016 log::debug!("Not unlocking slot; no password cached");
1017 }
1018
1019 Ok(())
1020 };
1021
1022 let sig_fn = if slot == KeyType::Signing {
1033 Transaction::signature_for_hash
1034 } else {
1035 Transaction::authenticate_for_hash
1036 };
1037 use openpgp_card::ocard::crypto::Hash;
1045 let sig = match (public_key.pk_algo(), public_key.mpis()) {
1046 #[allow(deprecated)]
1047 (PublicKeyAlgorithm::RSASign, mpi::PublicKey::RSA { .. })
1048 | (PublicKeyAlgorithm::RSAEncryptSign, mpi::PublicKey::RSA { .. }) => {
1049 let hash = match hash_algo {
1050 sequoia_openpgp::types::HashAlgorithm::SHA256 => Hash::SHA256(
1051 digest
1052 .try_into()
1053 .map_err(|_| anyhow::anyhow!("invalid slice length"))?,
1054 ),
1055 sequoia_openpgp::types::HashAlgorithm::SHA384 => Hash::SHA384(
1056 digest
1057 .try_into()
1058 .map_err(|_| anyhow::anyhow!("invalid slice length"))?,
1059 ),
1060 sequoia_openpgp::types::HashAlgorithm::SHA512 => Hash::SHA512(
1061 digest
1062 .try_into()
1063 .map_err(|_| anyhow::anyhow!("invalid slice length"))?,
1064 ),
1065 _ => {
1066 return Err(anyhow::anyhow!(
1067 "Unsupported hash algorithm for RSA {:?}",
1068 hash_algo
1069 ));
1070 }
1071 };
1072 unlock()?;
1073 let sig = sig_fn(tx.card(), hash)?;
1074 let mpi = mpi::MPI::new(&sig[..]);
1075 mpi::Signature::RSA { s: mpi }
1076 }
1077 (PublicKeyAlgorithm::EdDSA, mpi::PublicKey::EdDSA { .. }) => {
1078 let hash = Hash::EdDSA(digest);
1079 unlock()?;
1080 let sig = sig_fn(tx.card(), hash)?;
1081 let r = mpi::MPI::new(&sig[..32]);
1082 let s = mpi::MPI::new(&sig[32..]);
1083 mpi::Signature::EdDSA { r, s }
1084 }
1085 (PublicKeyAlgorithm::ECDSA, mpi::PublicKey::ECDSA { curve, .. }) => {
1086 let hash = match curve {
1087 Curve::NistP256 => Hash::ECDSA(&digest[..32]),
1088 Curve::NistP384 => Hash::ECDSA(&digest[..48]),
1089 Curve::NistP521 => Hash::ECDSA(&digest[..64]),
1090 _ => Hash::ECDSA(digest),
1091 };
1092 unlock()?;
1093 let sig = sig_fn(tx.card(), hash)?;
1094 let len_2 = sig.len() / 2;
1095 let r = mpi::MPI::new(&sig[..len_2]);
1096 let s = mpi::MPI::new(&sig[len_2..]);
1097 mpi::Signature::ECDSA { r, s }
1098 }
1099 (pk_algo, _) => return Err(anyhow::anyhow!(
1101 "Unsupported combination of algorithm {:?} and pubkey {:?}",
1102 pk_algo,
1103 public_key
1104 )),
1105 };
1106
1107 log::trace!("Returned a {} signature", public_key.pk_algo());
1108 Ok((public_key.pk_algo(), sig))
1109 }
1110
1111 async fn export(&mut self)
1112 -> Result<openpgp::packet::Key<
1113 openpgp::packet::key::SecretParts,
1114 openpgp::packet::key::UnspecifiedRole>>
1115 {
1116 Err(Error::OperationNotSupported(
1117 "Keys cannot be exported from OpenPGP cards.".into()).into())
1118 }
1119
1120 async fn change_password(&mut self, password: Option<&Password>)
1121 -> Result<()>
1122 {
1123 log::trace!("KeyHandle::change_password({}, {})",
1124 self.fingerprint(),
1125 if let Some(password) = password {
1126 if password.map(|p| p.is_empty()) {
1127 "clear password"
1128 } else {
1129 "set password"
1130 }
1131 } else {
1132 "ask for password"
1133 });
1134
1135 Err(Error::OperationNotSupported(
1136 "Use an external tool to manage OpenPGP cards.".into()).into())
1137 }
1138
1139 async fn delete_secret_key_material(&mut self)
1140 -> Result<()>
1141 {
1142 log::trace!("KeyHandle::delete_secret_key_material");
1143
1144 Err(Error::OperationNotSupported(
1145 "Use an external tool to manage OpenPGP cards.".into()).into())
1146 }
1147}
1148
1149#[cfg(test)]
1150mod tests {
1151 use super::*;
1152
1153 use openpgp::KeyHandle;
1154 use openpgp::cert::amalgamation::key::ValidKeyAmalgamation;
1155 use openpgp::parse::Parse;
1156 use openpgp::policy::StandardPolicy;
1157 use openpgp::serialize::Serialize;
1158
1159 const P: &StandardPolicy = &StandardPolicy::new();
1160
1161 use backend::test_framework;
1162
1163 use backend::Backend as _;
1164
1165 const TEST_CARD_ID: &str = "0000:00000000";
1167 const TEST_CARD_ADMIN_PIN: &str = "12345678";
1168 const TEST_CARD_USER_PIN: &str = "123456";
1169
1170 fn get_test_card() -> Option<openpgp_card::Card<openpgp_card::state::Open>>
1171 {
1172 let card_backends = match card_backend_pcsc::PcscBackend::cards(None) {
1173 Ok(card_backends) => card_backends.collect(),
1174 Err(err) => {
1175 log::debug!("Listing openpgp cards using PC/SC: {}", err);
1176 Vec::new()
1177 }
1178 };
1179
1180 let mut test_card = None;
1181 for card_backend in card_backends.into_iter() {
1182 let card_backend = match card_backend {
1183 Ok(card_backend) => card_backend,
1184 Err(err) => {
1185 log::debug!("Opening openpgp card backend: {}", err);
1186 continue;
1187 }
1188 };
1189
1190 let mut card = match openpgp_card::Card::new(card_backend) {
1191 Ok(card) => card,
1192 Err(err) => {
1193 log::debug!("Opening openpgp card: {}", err);
1194 continue;
1195 }
1196 };
1197
1198 let tx = match card.transaction() {
1199 Ok(tx) => tx,
1200 Err(err) => {
1201 log::debug!("Starting transaction on openpgp card: {}", err);
1202 continue;
1203 }
1204 };
1205
1206 let id = match tx.application_identifier() {
1207 Ok(id) => id,
1208 Err(err) => {
1209 log::debug!("Getting application id from openpgp card: {}", err);
1210 continue;
1211 }
1212 };
1213 let id = id.ident();
1214
1215 if id == TEST_CARD_ID {
1216 drop(tx);
1217 test_card = Some(card);
1218 break;
1219 } else {
1220 eprintln!("Found card {}", id);
1221 }
1222 }
1223
1224 test_card
1225 }
1226
1227 fn preinit() -> bool {
1228 get_test_card().is_some()
1230 }
1231
1232 async fn init_backend() -> Backend {
1233 let backend = Backend::init_ephemeral().await.expect("can init backend");
1234
1235 let mut card = if let Some(card) = get_test_card() {
1236 card
1237 } else {
1238 panic!("Test card ({}) not available", TEST_CARD_ID);
1239 };
1240
1241 let mut tx = card.transaction().expect("can start a transaction");
1243 tx.factory_reset().expect("can factory reset");
1244
1245 backend
1246 }
1247
1248 async fn import_cert(backend: &mut Backend, cert: &Cert) {
1249 let vc = cert.with_policy(P, None).expect("valid cert");
1250
1251 eprintln!("Importing cert {}'s subkeys", cert.fingerprint());
1252 for ka in vc.keys().subkeys() {
1253 eprintln!(" - {}, secret: {}, key flags: {:?}",
1254 ka.key().fingerprint(), ka.key().has_secret(), ka.key_flags());
1255 }
1256
1257 let signing_key
1258 = vc.keys().subkeys().for_signing().secret().next();
1259 let auth_key
1260 = vc.keys().subkeys().for_authentication().secret().next();
1261 let encryption_key
1262 = vc.keys().subkeys().for_transport_encryption().secret().next();
1263
1264 assert!(signing_key.is_some()
1265 || auth_key.is_some()
1266 || encryption_key.is_some(),
1267 "Expect at least one subkey with secret key material");
1268
1269 let mut card = if let Some(card) = get_test_card() {
1270 card
1271 } else {
1272 panic!("Test card ({}) not available", TEST_CARD_ID);
1273 };
1274
1275 let mut tx = card.transaction().expect("can start a transaction");
1276
1277 tx.verify_admin_pin(TEST_CARD_ADMIN_PIN.to_string().into())
1278 .expect("can use admin pin");
1279
1280 let mut admin = tx.to_admin_card(None)
1281 .expect("can access admin functionality");
1282
1283 let mut import_key = |key: Option<ValidKeyAmalgamation<_, _, ()>>, slot: KeyType| {
1285 if let Some(key) = key {
1286 eprintln!("Importing key {} to {:?} slot",
1287 key.key().fingerprint(), slot);
1288
1289 assert!(key.key().has_unencrypted_secret());
1290 let key = Box::new(privkey::SequoiaKey::new(key.into(), None));
1291 admin.import_key(key, slot)
1294 .expect("can import key");
1295 } else {
1296 eprintln!("No {:?} key to import", slot);
1297 }
1298 };
1299
1300 import_key(signing_key, KeyType::Signing);
1301 import_key(auth_key, KeyType::Authentication);
1302 import_key(encryption_key, KeyType::Decryption);
1303
1304 backend.inner.lock().await.certd.certd().insert(
1307 &cert.fingerprint().to_string(),
1308 (), false,
1309 |(), disk| {
1310 let cert_;
1311 let cert = if let Some(disk) = disk {
1312 let disk = Cert::from_bytes(disk).expect("valid cert");
1314 cert_ = cert.clone().merge_public(disk).expect("can merge");
1315 &cert_
1316 } else {
1317 cert
1319 };
1320
1321 let mut bytes = Vec::new();
1322 cert.serialize(&mut bytes).expect("can serialize to a vec");
1323 Ok(bytes.into())
1324 })
1325 .expect("inserted");
1326 }
1327
1328 sequoia_keystore_backend::generate_tests!(
1329 preinit,
1330 true, Backend, init_backend,
1332 import_cert,
1333 false, Some(1), Some(TEST_CARD_USER_PIN), false, false, false );
1340}