1use std::convert::{TryFrom, TryInto};
7
8use card_backend::{CardBackend, CardCaps, CardTransaction, PinType, SmartcardError};
9use crypto::{HashAlgo, SigningAlgo};
10use secrecy::{ExposeSecret, SecretBox};
11
12use crate::{
13 Error,
14 ocard::{
15 algorithm::{AlgorithmAttributes, AlgorithmInformation},
16 apdu::{command::Command, response::RawResponse},
17 crypto::{CardUploadableKey, Cryptogram, PublicKeyMaterial},
18 data::{
19 ApplicationIdentifier,
20 ApplicationRelatedData,
21 CardholderRelatedData,
22 ExtendedCapabilities,
23 ExtendedLengthInfo,
24 Fingerprint,
25 HistoricalBytes,
26 KdfDo,
27 KeyGenerationTime,
28 Lang,
29 PWStatusBytes,
30 SecuritySupportTemplate,
31 Sex,
32 UserInteractionFlag,
33 },
34 tags::{ShortTag, Tags},
35 tlv::{Tlv, value::Value},
36 },
37};
38
39pub mod algorithm;
40pub(crate) mod apdu;
41mod commands;
42pub mod crypto;
43pub mod data;
44pub mod kdf;
45mod keys;
46pub(crate) mod oid;
47pub(crate) mod tags;
48pub(crate) mod tlv;
49
50pub(crate) const OPENPGP_APPLICATION: &[u8] = &[0xD2, 0x76, 0x00, 0x01, 0x24, 0x01];
51
52#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
54pub enum KeyType {
55 Signing,
56 Decryption,
57 Authentication,
58
59 Attestation,
61}
62
63impl KeyType {
64 pub(crate) fn algorithm_tag(&self) -> ShortTag {
66 match self {
67 Self::Signing => Tags::AlgorithmAttributesSignature,
68 Self::Decryption => Tags::AlgorithmAttributesDecryption,
69 Self::Authentication => Tags::AlgorithmAttributesAuthentication,
70 Self::Attestation => Tags::AlgorithmAttributesAttestation,
71 }
72 .into()
73 }
74
75 fn fingerprint_put_tag(&self) -> ShortTag {
80 match self {
81 Self::Signing => Tags::FingerprintSignature,
82 Self::Decryption => Tags::FingerprintDecryption,
83 Self::Authentication => Tags::FingerprintAuthentication,
84 Self::Attestation => Tags::FingerprintAttestation,
85 }
86 .into()
87 }
88
89 fn timestamp_put_tag(&self) -> ShortTag {
94 match self {
95 Self::Signing => Tags::GenerationTimeSignature,
96 Self::Decryption => Tags::GenerationTimeDecryption,
97 Self::Authentication => Tags::GenerationTimeAuthentication,
98 Self::Attestation => Tags::GenerationTimeAttestation,
99 }
100 .into()
101 }
102}
103
104#[derive(Debug)]
108struct CardImmutable {
109 aid: ApplicationIdentifier,
110 ec: ExtendedCapabilities,
111 hb: Option<HistoricalBytes>, eli: Option<ExtendedLengthInfo>, ai: Option<Option<AlgorithmInformation>>, }
118
119pub struct OpenPGP {
126 card: Box<dyn CardBackend + Send + Sync>,
128
129 card_caps: Option<CardCaps>,
132
133 immutable: Option<CardImmutable>,
137}
138
139impl OpenPGP {
140 pub fn new<B>(backend: B) -> Result<Self, Error>
145 where
146 B: Into<Box<dyn CardBackend + Send + Sync>>,
147 {
148 let card: Box<dyn CardBackend + Send + Sync> = backend.into();
149
150 let mut op = Self {
151 card,
152 card_caps: None,
153 immutable: None,
154 };
155
156 let (caps, imm) = {
157 let mut tx = op.transaction()?;
158 tx.select()?;
159
160 let ard = tx.application_related_data()?;
162
163 let mut ext_support = false;
167 let mut chaining_support = false;
168
169 if let Ok(hist) = ard.historical_bytes() {
170 if let Some(cc) = hist.card_capabilities() {
171 chaining_support = cc.command_chaining();
172 ext_support = cc.extended_lc_le();
173 }
174 }
175
176 let ext_cap = ard.extended_capabilities()?;
177
178 let (max_cmd_bytes, max_rsp_bytes) = if let Ok(Some(eli)) =
180 ard.extended_length_information()
181 {
182 (eli.max_command_bytes(), eli.max_response_bytes())
184 } else if let (Some(cmd), Some(rsp)) = (ext_cap.max_cmd_len(), ext_cap.max_resp_len()) {
185 (cmd, rsp)
187 } else {
188 (255, 255)
190 };
191
192 let pw_status = ard.pw_status_bytes()?;
193 let pw1_max = pw_status.pw1_max_len();
194 let pw3_max = pw_status.pw3_max_len();
195
196 let caps = CardCaps::new(
197 ext_support,
198 chaining_support,
199 max_cmd_bytes,
200 max_rsp_bytes,
201 pw1_max,
202 pw3_max,
203 );
204
205 let imm = CardImmutable {
206 aid: ard.application_id()?,
207 ec: ard.extended_capabilities()?,
208 hb: Some(ard.historical_bytes()?),
209 eli: ard.extended_length_information()?,
210 ai: None, };
212
213 drop(tx);
214
215 let caps = op.card.limit_card_caps(caps);
220
221 (caps, imm)
222 };
223
224 log::trace!("set card_caps to: {:x?}", caps);
225 op.card_caps = Some(caps);
226
227 log::trace!("set immutable card state to: {:x?}", imm);
228 op.immutable = Some(imm);
229
230 Ok(op)
231 }
232
233 pub fn into_card(self) -> Box<dyn CardBackend + Send + Sync> {
238 self.card
239 }
240
241 pub fn transaction(&mut self) -> Result<Transaction<'_>, Error> {
247 let card_caps = &mut self.card_caps;
248 let immutable = &mut self.immutable; let tx = self.card.transaction(Some(OPENPGP_APPLICATION))?;
251
252 if tx.was_reset() {
253 }
256
257 Ok(Transaction {
258 tx,
259 card_caps,
260 immutable,
261 })
262 }
263}
264
265pub struct Transaction<'a> {
275 tx: Box<dyn CardTransaction + Send + Sync + 'a>,
276 card_caps: &'a Option<CardCaps>,
277 immutable: &'a mut Option<CardImmutable>,
278}
279
280impl Transaction<'_> {
281 pub(crate) fn tx(&mut self) -> &mut dyn CardTransaction {
282 self.tx.as_mut()
283 }
284
285 pub(crate) fn send_command(
286 &mut self,
287 cmd: Command,
288 expect_reply: bool,
289 ) -> Result<RawResponse, Error> {
290 apdu::send_command(&mut *self.tx, cmd, *self.card_caps, expect_reply)
291 }
292
293 pub fn select(&mut self) -> Result<Vec<u8>, Error> {
297 log::info!("OpenPgpTransaction: select");
298
299 self.send_command(commands::select_openpgp()?, false)?
300 .try_into()
301 }
302
303 pub fn terminate_df(&mut self) -> Result<(), Error> {
307 log::info!("OpenPgpTransaction: terminate_df");
308
309 self.send_command(commands::terminate_df()?, false)?;
310 Ok(())
311 }
312
313 pub fn activate_file(&mut self) -> Result<(), Error> {
317 log::info!("OpenPgpTransaction: activate_file");
318
319 self.send_command(commands::activate_file()?, false)?;
320 Ok(())
321 }
322
323 pub fn feature_pinpad_verify(&self) -> bool {
327 self.tx.feature_pinpad_verify()
328 }
329
330 pub fn feature_pinpad_modify(&self) -> bool {
332 self.tx.feature_pinpad_modify()
333 }
334
335 pub fn application_related_data(&mut self) -> Result<ApplicationRelatedData, Error> {
343 log::info!("OpenPgpTransaction: application_related_data");
344
345 let resp = self.send_command(commands::application_related_data()?, true)?;
346 let value = Value::from(resp.data()?, true)?;
347
348 log::trace!(" ARD value: {:02x?}", value);
349
350 Ok(ApplicationRelatedData(Tlv::new(
351 Tags::ApplicationRelatedData,
352 value,
353 )))
354 }
355
356 fn card_immutable(&self) -> Result<&CardImmutable, Error> {
360 if let Some(imm) = &self.immutable {
361 Ok(imm)
362 } else {
363 Err(Error::InternalError(
365 "Unexpected state of immutable cache".to_string(),
366 ))
367 }
368 }
369
370 pub fn application_identifier(&self) -> Result<ApplicationIdentifier, Error> {
375 Ok(self.card_immutable()?.aid)
376 }
377
378 pub fn extended_capabilities(&self) -> Result<ExtendedCapabilities, Error> {
383 Ok(self.card_immutable()?.ec)
384 }
385
386 pub fn historical_bytes(&self) -> Result<Option<HistoricalBytes>, Error> {
391 Ok(self.card_immutable()?.hb)
392 }
393
394 pub fn extended_length_info(&self) -> Result<Option<ExtendedLengthInfo>, Error> {
399 Ok(self.card_immutable()?.eli)
400 }
401
402 #[allow(dead_code)]
403 pub(crate) fn algorithm_information_cached(
404 &mut self,
405 ) -> Result<Option<AlgorithmInformation>, Error> {
406 match &self.immutable {
410 Some(ci) => {
411 if let Some(ai) = &ci.ai {
413 return Ok(ai.clone());
414 }
415 }
416 None => {
417 return Err(Error::InternalError(
418 "Unexpected state of immutable cache".to_string(),
419 ));
420 }
421 }
422
423 let ai = self.algorithm_information()?;
425
426 match self.immutable {
427 Some(ci) => {
428 ci.ai = Some(ai.clone());
429 Ok(ai)
430 }
431 None => Err(Error::InternalError(
432 "Unexpected state of immutable cache".to_string(),
433 )),
434 }
435 }
436
437 pub fn url(&mut self) -> Result<Vec<u8>, Error> {
441 log::info!("OpenPgpTransaction: url");
442
443 self.send_command(commands::url()?, true)?.try_into()
444 }
445
446 pub fn login_data(&mut self) -> Result<Vec<u8>, Error> {
448 log::info!("OpenPgpTransaction: login_data");
449
450 self.send_command(commands::login_data()?, true)?.try_into()
451 }
452
453 pub fn cardholder_related_data(&mut self) -> Result<CardholderRelatedData, Error> {
455 log::info!("OpenPgpTransaction: cardholder_related_data");
456
457 let resp = self.send_command(commands::cardholder_related_data()?, true)?;
458
459 resp.data()?.try_into()
460 }
461
462 pub fn security_support_template(&mut self) -> Result<SecuritySupportTemplate, Error> {
464 log::info!("OpenPgpTransaction: security_support_template");
465
466 let resp = self.send_command(commands::security_support_template()?, true)?;
467
468 let tlv = Tlv::try_from(resp.data()?)?;
469
470 let dst = tlv.find(Tags::DigitalSignatureCounter).ok_or_else(|| {
471 Error::NotFound("Couldn't get DigitalSignatureCounter DO".to_string())
472 })?;
473
474 if let Value::S(data) = dst {
475 let data = match &data[..] {
476 [a, b, c] => [0, *a, *b, *c],
478 _ => {
479 return Err(Error::ParseError(format!(
480 "Unexpected length {} for DigitalSignatureCounter DO",
481 data.len()
482 )));
483 }
484 };
485
486 let dsc: u32 = u32::from_be_bytes(data);
487 Ok(SecuritySupportTemplate { dsc })
488 } else {
489 Err(Error::NotFound(
490 "Failed to process SecuritySupportTemplate".to_string(),
491 ))
492 }
493 }
494
495 #[allow(dead_code)]
510 pub fn cardholder_certificate(&mut self) -> Result<Vec<u8>, Error> {
511 log::info!("OpenPgpTransaction: cardholder_certificate");
512
513 self.send_command(commands::cardholder_certificate()?, true)?
514 .try_into()
515 }
516
517 pub fn next_cardholder_certificate(&mut self) -> Result<Vec<u8>, Error> {
522 log::info!("OpenPgpTransaction: next_cardholder_certificate");
523
524 self.send_command(commands::get_next_cardholder_certificate()?, true)?
525 .try_into()
526 }
527
528 pub fn kdf_do(&mut self) -> Result<KdfDo, Error> {
530 log::info!("OpenPgpTransaction: kdf_do");
531
532 let kdf_do = self
533 .send_command(commands::kdf_do()?, true)?
534 .data()?
535 .try_into()?;
536
537 log::trace!(" KDF DO value: {:02x?}", kdf_do);
538
539 Ok(kdf_do)
540 }
541
542 pub fn algorithm_information(&mut self) -> Result<Option<AlgorithmInformation>, Error> {
544 log::info!("OpenPgpTransaction: algorithm_information");
545
546 let resp = self.send_command(commands::algo_info()?, true)?;
547
548 let ai = resp.data()?.try_into()?;
549 Ok(Some(ai))
550 }
551
552 pub fn attestation_certificate(&mut self) -> Result<Vec<u8>, Error> {
554 log::info!("OpenPgpTransaction: attestation_certificate");
555
556 self.send_command(commands::attestation_certificate()?, true)?
557 .try_into()
558 }
559
560 pub fn firmware_version(&mut self) -> Result<Vec<u8>, Error> {
562 log::info!("OpenPgpTransaction: firmware_version");
563
564 self.send_command(commands::firmware_version()?, true)?
565 .try_into()
566 }
567
568 pub fn set_identity(&mut self, id: u8) -> Result<Vec<u8>, Error> {
573 log::info!("OpenPgpTransaction: set_identity");
574
575 let resp = self.send_command(commands::set_identity(id)?, false);
576
577 if let Err(Error::Smartcard(SmartcardError::NotTransacted)) = resp {
580 Ok(vec![])
581 } else {
582 resp?.try_into()
583 }
584 }
585
586 pub fn select_data(&mut self, num: u8, tag: &[u8]) -> Result<(), Error> {
602 log::info!("OpenPgpTransaction: select_data");
603
604 let tlv = Tlv::new(
605 Tags::GeneralReference,
606 Value::C(vec![Tlv::new(Tags::TagList, Value::S(tag.to_vec()))]),
607 );
608
609 let mut data = tlv.serialize();
610
611 if let Ok(version) = self.firmware_version() {
620 if version.len() == 3
621 && version[0] == 5
622 && (version[1] < 4 || (version[1] == 4 && version[2] <= 3))
623 {
624 if data.len() > 255 {
630 return Err(Error::InternalError(format!(
631 "select_data: exceedingly long data: {}",
632 data.len()
633 )));
634 }
635
636 data.insert(0, data.len() as u8);
637 }
638 }
639
640 let cmd = commands::select_data(num, data)?;
641
642 self.send_command(cmd, true)?.check_ok()?;
645
646 Ok(())
647 }
648
649 pub fn private_use_do(&mut self, num: u8) -> Result<Vec<u8>, Error> {
655 log::info!("OpenPgpTransaction: private_use_do");
656
657 let tag = match num {
658 1 => Tags::PrivateUse1,
659 2 => Tags::PrivateUse2,
660 3 => Tags::PrivateUse3,
661 4 => Tags::PrivateUse4,
662 _ => {
663 return Err(Error::UnsupportedFeature(format!(
664 "Illegal Private Use DO num '{}'",
665 num,
666 )));
667 }
668 };
669
670 let cmd = commands::get_data(tag)?;
671 self.send_command(cmd, true)?.try_into()
672 }
673
674 pub fn factory_reset(&mut self) -> Result<(), Error> {
692 log::info!("OpenPgpTransaction: factory_reset");
693
694 let mut bad_pw_len = 8;
695
696 if let Ok(kdf_do) = self.kdf_do() {
700 if kdf_do.hash_algo() == Some(0x08) {
701 bad_pw_len = 0x20;
702 } else if kdf_do.hash_algo() == Some(0x0a) {
703 bad_pw_len = 0x40;
704 }
705 }
706
707 let bad_pw: Vec<_> = std::iter::repeat_n(0x40, bad_pw_len).collect();
708
709 for _ in 0..4 {
711 let resp = self.verify_pw1_sign(bad_pw.clone().into());
712
713 if !(matches!(
714 resp,
715 Err(Error::CardStatus(StatusBytes::SecurityStatusNotSatisfied))
716 | Err(Error::CardStatus(StatusBytes::AuthenticationMethodBlocked))
717 | Err(Error::CardStatus(
718 StatusBytes::ExecutionErrorNonVolatileMemoryUnchanged
719 ))
720 | Err(Error::CardStatus(StatusBytes::PasswordNotChecked(_)))
721 | Err(Error::CardStatus(StatusBytes::ConditionOfUseNotSatisfied))
722 )) {
723 return Err(Error::InternalError(
724 "Unexpected status for reset, at pw1.".into(),
725 ));
726 }
727 }
728
729 for _ in 0..4 {
731 let resp = self.verify_pw3(bad_pw.clone().into());
732
733 if !(matches!(
734 resp,
735 Err(Error::CardStatus(StatusBytes::SecurityStatusNotSatisfied))
736 | Err(Error::CardStatus(StatusBytes::AuthenticationMethodBlocked))
737 | Err(Error::CardStatus(
738 StatusBytes::ExecutionErrorNonVolatileMemoryUnchanged
739 ))
740 | Err(Error::CardStatus(StatusBytes::PasswordNotChecked(_)))
741 | Err(Error::CardStatus(StatusBytes::ConditionOfUseNotSatisfied))
742 )) {
743 return Err(Error::InternalError(
744 "Unexpected status for reset, at pw3.".into(),
745 ));
746 }
747 }
748
749 self.terminate_df()?;
750 self.activate_file()?;
751
752 Ok(())
753 }
754
755 pub fn verify_pw1_sign(&mut self, pin: SecretBox<[u8]>) -> Result<(), Error> {
763 log::info!("OpenPgpTransaction: verify_pw1_sign");
764
765 let cmd = commands::verify_pw1_81(pin)?;
766
767 self.send_command(cmd, false)?.try_into()
768 }
769
770 pub fn verify_pw1_sign_pinpad(&mut self) -> Result<(), Error> {
778 log::info!("OpenPgpTransaction: verify_pw1_sign_pinpad");
779
780 let cc = *self.card_caps;
781
782 let res = self.tx().pinpad_verify(PinType::Sign, &cc)?;
783 RawResponse::try_from(res)?.try_into()
784 }
785
786 pub fn check_pw1_sign(&mut self) -> Result<(), Error> {
795 log::info!("OpenPgpTransaction: check_pw1_sign");
796
797 let verify = commands::verify_pw1_81(vec![].into())?;
798 self.send_command(verify, false)?.try_into()
799 }
800
801 pub fn verify_pw1_user(&mut self, pin: SecretBox<[u8]>) -> Result<(), Error> {
804 log::info!("OpenPgpTransaction: verify_pw1_user");
805
806 let verify = commands::verify_pw1_82(pin)?;
807 self.send_command(verify, false)?.try_into()
808 }
809
810 pub fn verify_pw1_user_pinpad(&mut self) -> Result<(), Error> {
814 log::info!("OpenPgpTransaction: verify_pw1_user_pinpad");
815
816 let cc = *self.card_caps;
817
818 let res = self.tx().pinpad_verify(PinType::User, &cc)?;
819 RawResponse::try_from(res)?.try_into()
820 }
821
822 pub fn check_pw1_user(&mut self) -> Result<(), Error> {
832 log::info!("OpenPgpTransaction: check_pw1_user");
833
834 let verify = commands::verify_pw1_82(vec![].into())?;
835 self.send_command(verify, false)?.try_into()
836 }
837
838 pub fn verify_pw3(&mut self, pin: SecretBox<[u8]>) -> Result<(), Error> {
840 log::info!("OpenPgpTransaction: verify_pw3");
841
842 let verify = commands::verify_pw3(pin)?;
843 self.send_command(verify, false)?.try_into()
844 }
845
846 pub fn verify_pw3_pinpad(&mut self) -> Result<(), Error> {
849 log::info!("OpenPgpTransaction: verify_pw3_pinpad");
850
851 let cc = *self.card_caps;
852
853 let res = self.tx().pinpad_verify(PinType::Admin, &cc)?;
854 RawResponse::try_from(res)?.try_into()
855 }
856
857 pub fn check_pw3(&mut self) -> Result<(), Error> {
866 log::info!("OpenPgpTransaction: check_pw3");
867
868 let verify = commands::verify_pw3(vec![].into())?;
869 self.send_command(verify, false)?.try_into()
870 }
871
872 pub fn change_pw1(&mut self, old: SecretBox<[u8]>, new: SecretBox<[u8]>) -> Result<(), Error> {
876 log::info!("OpenPgpTransaction: change_pw1");
877
878 let mut data = vec![];
879 data.extend(old.expose_secret());
880 data.extend(new.expose_secret());
881
882 let change = commands::change_pw1(data.into())?;
883 self.send_command(change, false)?.try_into()
884 }
885
886 pub fn change_pw1_pinpad(&mut self) -> Result<(), Error> {
889 log::info!("OpenPgpTransaction: change_pw1_pinpad");
890
891 let cc = *self.card_caps;
892
893 let res = self.tx().pinpad_modify(PinType::Sign, &cc)?;
896 RawResponse::try_from(res)?.try_into()
897 }
898
899 pub fn change_pw3(&mut self, old: SecretBox<[u8]>, new: SecretBox<[u8]>) -> Result<(), Error> {
903 log::info!("OpenPgpTransaction: change_pw3");
904
905 let mut data = vec![];
906 data.extend(old.expose_secret());
907 data.extend(new.expose_secret());
908
909 let change = commands::change_pw3(data.into())?;
910 self.send_command(change, false)?.try_into()
911 }
912
913 pub fn change_pw3_pinpad(&mut self) -> Result<(), Error> {
916 log::info!("OpenPgpTransaction: change_pw3_pinpad");
917
918 let cc = *self.card_caps;
919
920 let res = self.tx().pinpad_modify(PinType::Admin, &cc)?;
921 RawResponse::try_from(res)?.try_into()
922 }
923
924 pub fn reset_retry_counter_pw1(
932 &mut self,
933 new_pw1: SecretBox<[u8]>,
934 resetting_code: Option<SecretBox<[u8]>>,
935 ) -> Result<(), Error> {
936 log::info!("OpenPgpTransaction: reset_retry_counter_pw1");
937
938 let cmd = commands::reset_retry_counter_pw1(resetting_code, new_pw1)?;
939 self.send_command(cmd, false)?.try_into()
940 }
941
942 pub fn decipher(&mut self, dm: Cryptogram) -> Result<Vec<u8>, Error> {
949 match dm {
950 Cryptogram::RSA(message) => {
951 let mut data = vec![0x0];
953 data.extend_from_slice(message);
954
955 self.pso_decipher(data)
957 }
958 Cryptogram::ECDH(eph) => {
959 let epk = Tlv::new(Tags::ExternalPublicKey, Value::S(eph.to_vec()));
967
968 let pkdo = Tlv::new(Tags::PublicKey, Value::C(vec![epk]));
970
971 let cdo = Tlv::new(Tags::Cipher, Value::C(vec![pkdo]));
973
974 self.pso_decipher(cdo.serialize())
975 }
976 }
977 }
978
979 pub fn pso_decipher(&mut self, data: Vec<u8>) -> Result<Vec<u8>, Error> {
985 log::info!("OpenPgpTransaction: pso_decipher");
986
987 let dec_cmd = commands::decryption(data)?;
989 let resp = self.send_command(dec_cmd, true)?;
990
991 Ok(resp.data()?.to_vec())
992 }
993
994 pub fn manage_security_environment(
1011 &mut self,
1012 for_operation: KeyType,
1013 key_ref: KeyType,
1014 ) -> Result<(), Error> {
1015 log::info!("OpenPgpTransaction: manage_security_environment");
1016
1017 if !matches!(for_operation, KeyType::Authentication | KeyType::Decryption)
1018 || !matches!(key_ref, KeyType::Authentication | KeyType::Decryption)
1019 {
1020 return Err(Error::UnsupportedAlgo("Only Decryption and Authentication keys can be manipulated by manage_security_environment".to_string()));
1021 }
1022
1023 let cmd = commands::manage_security_environment(for_operation, key_ref)?;
1024 let resp = self.send_command(cmd, false)?;
1025 resp.check_ok()?;
1026 Ok(())
1027 }
1028
1029 pub fn signature_for_hash(
1043 &mut self,
1044 algo: SigningAlgo,
1045 digest: &[u8],
1046 ) -> Result<Vec<u8>, Error> {
1047 let data = match algo {
1048 SigningAlgo::ECC => digest.into(),
1049 SigningAlgo::RSA(hash_algo) => digestinfo(digest, hash_algo)?,
1050 };
1051
1052 self.pso_compute_digital_signature(data)
1053 }
1054
1055 pub fn pso_compute_digital_signature(&mut self, data: Vec<u8>) -> Result<Vec<u8>, Error> {
1061 log::info!("OpenPgpTransaction: pso_compute_digital_signature");
1062
1063 let cds_cmd = commands::signature(data)?;
1064 let resp = self.send_command(cds_cmd, true)?;
1065
1066 Ok(resp.data().map(|d| d.to_vec())?)
1067 }
1068
1069 pub fn authenticate_for_hash(
1082 &mut self,
1083 algo: SigningAlgo,
1084 digest: &[u8],
1085 ) -> Result<Vec<u8>, Error> {
1086 let data = match algo {
1087 SigningAlgo::ECC => digest.into(),
1088 SigningAlgo::RSA(hash_algo) => digestinfo(digest, hash_algo)?,
1089 };
1090
1091 self.internal_authenticate(data)
1092 }
1093
1094 pub fn internal_authenticate(&mut self, data: Vec<u8>) -> Result<Vec<u8>, Error> {
1100 log::info!("OpenPgpTransaction: internal_authenticate");
1101
1102 let ia_cmd = commands::internal_authenticate(data)?;
1103 let resp = self.send_command(ia_cmd, true)?;
1104
1105 Ok(resp.data().map(|d| d.to_vec())?)
1106 }
1107
1108 pub fn set_private_use_do(&mut self, num: u8, data: Vec<u8>) -> Result<(), Error> {
1118 log::info!("OpenPgpTransaction: set_private_use_do");
1119
1120 let tag = match num {
1121 1 => Tags::PrivateUse1,
1122 2 => Tags::PrivateUse2,
1123 3 => Tags::PrivateUse3,
1124 4 => Tags::PrivateUse4,
1125 _ => {
1126 return Err(Error::UnsupportedFeature(format!(
1127 "Illegal Private Use DO num '{}'",
1128 num,
1129 )));
1130 }
1131 };
1132
1133 let cmd = commands::put_data(tag, data)?;
1134 self.send_command(cmd, true)?.try_into()
1135 }
1136
1137 pub fn set_login(&mut self, login: &[u8]) -> Result<(), Error> {
1138 log::info!("OpenPgpTransaction: set_login");
1139
1140 let cmd = commands::put_login_data(login.to_vec())?;
1141 self.send_command(cmd, false)?.try_into()
1142 }
1143
1144 pub fn set_name(&mut self, name: &[u8]) -> Result<(), Error> {
1145 log::info!("OpenPgpTransaction: set_name");
1146
1147 let cmd = commands::put_name(name.to_vec())?;
1148 self.send_command(cmd, false)?.try_into()
1149 }
1150
1151 pub fn set_lang(&mut self, lang: &[Lang]) -> Result<(), Error> {
1152 log::info!("OpenPgpTransaction: set_lang");
1153
1154 let bytes: Vec<_> = lang.iter().flat_map(|&l| Vec::<u8>::from(l)).collect();
1155
1156 let cmd = commands::put_lang(bytes)?;
1157 self.send_command(cmd, false)?.try_into()
1158 }
1159
1160 pub fn set_sex(&mut self, sex: Sex) -> Result<(), Error> {
1161 log::info!("OpenPgpTransaction: set_sex");
1162
1163 let cmd = commands::put_sex((&sex).into())?;
1164 self.send_command(cmd, false)?.try_into()
1165 }
1166
1167 pub fn set_url(&mut self, url: &[u8]) -> Result<(), Error> {
1168 log::info!("OpenPgpTransaction: set_url");
1169
1170 let cmd = commands::put_url(url.to_vec())?;
1171 self.send_command(cmd, false)?.try_into()
1172 }
1173
1174 pub fn set_cardholder_certificate(&mut self, data: Vec<u8>) -> Result<(), Error> {
1179 log::info!("OpenPgpTransaction: set_cardholder_certificate");
1180
1181 let cmd = commands::put_cardholder_certificate(data)?;
1182 self.send_command(cmd, false)?.try_into()
1183 }
1184
1185 pub fn set_algorithm_attributes(
1191 &mut self,
1192 key_type: KeyType,
1193 algorithm_attributes: &AlgorithmAttributes,
1194 ) -> Result<(), Error> {
1195 log::info!("OpenPgpTransaction: set_algorithm_attributes");
1196
1197 let ecap = self.extended_capabilities()?;
1199 if !ecap.algo_attrs_changeable() {
1200 return Ok(());
1204 }
1205
1206 let cmd = commands::put_data(
1208 key_type.algorithm_tag(),
1209 algorithm_attributes.to_data_object()?,
1210 )?;
1211
1212 self.send_command(cmd, false)?.try_into()
1213 }
1214
1215 pub fn set_pw_status_bytes(
1227 &mut self,
1228 pw_status: &PWStatusBytes,
1229 long: bool,
1230 ) -> Result<(), Error> {
1231 log::info!("OpenPgpTransaction: set_pw_status_bytes");
1232
1233 let data = pw_status.serialize_for_put(long);
1234
1235 let cmd = commands::put_pw_status(data)?;
1236 self.send_command(cmd, false)?.try_into()
1237 }
1238
1239 pub fn set_fingerprint(&mut self, fp: Fingerprint, key_type: KeyType) -> Result<(), Error> {
1240 log::info!("OpenPgpTransaction: set_fingerprint");
1241
1242 let cmd = commands::put_data(key_type.fingerprint_put_tag(), fp.as_bytes().to_vec())?;
1243
1244 self.send_command(cmd, false)?.try_into()
1245 }
1246
1247 pub fn set_ca_fingerprint_1(&mut self, fp: Fingerprint) -> Result<(), Error> {
1248 log::info!("OpenPgpTransaction: set_ca_fingerprint_1");
1249
1250 let cmd = commands::put_data(Tags::CaFingerprint1, fp.as_bytes().to_vec())?;
1251 self.send_command(cmd, false)?.try_into()
1252 }
1253
1254 pub fn set_ca_fingerprint_2(&mut self, fp: Fingerprint) -> Result<(), Error> {
1255 log::info!("OpenPgpTransaction: set_ca_fingerprint_2");
1256
1257 let cmd = commands::put_data(Tags::CaFingerprint2, fp.as_bytes().to_vec())?;
1258 self.send_command(cmd, false)?.try_into()
1259 }
1260
1261 pub fn set_ca_fingerprint_3(&mut self, fp: Fingerprint) -> Result<(), Error> {
1262 log::info!("OpenPgpTransaction: set_ca_fingerprint_3");
1263
1264 let cmd = commands::put_data(Tags::CaFingerprint3, fp.as_bytes().to_vec())?;
1265 self.send_command(cmd, false)?.try_into()
1266 }
1267
1268 pub fn set_creation_time(
1269 &mut self,
1270 time: KeyGenerationTime,
1271 key_type: KeyType,
1272 ) -> Result<(), Error> {
1273 log::info!("OpenPgpTransaction: set_creation_time");
1274
1275 let time_value: Vec<u8> = time.get().to_be_bytes().to_vec();
1277
1278 let cmd = commands::put_data(key_type.timestamp_put_tag(), time_value)?;
1279
1280 self.send_command(cmd, false)?.try_into()
1281 }
1282
1283 pub fn set_resetting_code(&mut self, resetting_code: SecretBox<[u8]>) -> Result<(), Error> {
1290 log::info!("OpenPgpTransaction: set_resetting_code");
1291
1292 let cmd = commands::put_data(Tags::ResettingCode, resetting_code)?;
1293 self.send_command(cmd, false)?.try_into()
1294 }
1295
1296 pub fn set_pso_enc_dec_key(&mut self, key: &[u8]) -> Result<(), Error> {
1302 log::info!("OpenPgpTransaction: set_pso_enc_dec_key");
1303
1304 let cmd = commands::put_data(Tags::PsoEncDecKey, key.to_vec())?;
1305 self.send_command(cmd, false)?.try_into()
1306 }
1307
1308 pub fn set_uif_pso_cds(&mut self, uif: &UserInteractionFlag) -> Result<(), Error> {
1310 log::info!("OpenPgpTransaction: set_uif_pso_cds");
1311
1312 let cmd = commands::put_data(Tags::UifSig, uif.as_bytes().to_vec())?;
1313 self.send_command(cmd, false)?.try_into()
1314 }
1315
1316 pub fn set_uif_pso_dec(&mut self, uif: &UserInteractionFlag) -> Result<(), Error> {
1318 log::info!("OpenPgpTransaction: set_uif_pso_dec");
1319
1320 let cmd = commands::put_data(Tags::UifDec, uif.as_bytes().to_vec())?;
1321 self.send_command(cmd, false)?.try_into()
1322 }
1323
1324 pub fn set_uif_pso_aut(&mut self, uif: &UserInteractionFlag) -> Result<(), Error> {
1326 log::info!("OpenPgpTransaction: set_uif_pso_aut");
1327
1328 let cmd = commands::put_data(Tags::UifAuth, uif.as_bytes().to_vec())?;
1329 self.send_command(cmd, false)?.try_into()
1330 }
1331
1332 pub fn set_uif_attestation(&mut self, uif: &UserInteractionFlag) -> Result<(), Error> {
1345 log::info!("OpenPgpTransaction: set_uif_attestation");
1346
1347 let cmd = commands::put_data(Tags::UifAttestation, uif.as_bytes().to_vec())?;
1348 self.send_command(cmd, false)?.try_into()
1349 }
1350
1351 pub fn generate_attestation(&mut self, key_type: KeyType) -> Result<(), Error> {
1353 log::info!("OpenPgpTransaction: generate_attestation");
1354
1355 let key = match key_type {
1356 KeyType::Signing => 0x01,
1357 KeyType::Decryption => 0x02,
1358 KeyType::Authentication => 0x03,
1359 _ => return Err(Error::InternalError("Unexpected KeyType".to_string())),
1360 };
1361
1362 let cmd = commands::generate_attestation(key)?;
1363 self.send_command(cmd, false)?.try_into()
1364 }
1365
1366 pub fn set_kdf_do(&mut self, kdf_do: &KdfDo) -> Result<(), Error> {
1372 log::info!("OpenPgpTransaction: set_kdf_do");
1373
1374 let cmd = commands::put_data(Tags::KdfDo, kdf_do.serialize())?;
1375 self.send_command(cmd, false)?.try_into()
1376 }
1377
1378 pub fn key_import(
1387 &mut self,
1388 key: &dyn CardUploadableKey,
1389 key_type: KeyType,
1390 ) -> Result<(), Error> {
1391 keys::key_import(self, key, key_type)
1392 }
1393
1394 pub fn generate_key(
1397 &mut self,
1398 fp_from_pub: fn(
1399 &PublicKeyMaterial,
1400 KeyGenerationTime,
1401 KeyType,
1402 ) -> Result<Fingerprint, Error>,
1403 key_type: KeyType,
1404 ) -> Result<(PublicKeyMaterial, KeyGenerationTime), Error> {
1405 let ard = self.application_related_data()?; let cur_algo = ard.algorithm_attributes(key_type)?;
1408
1409 keys::gen_key_set_metadata(self, fp_from_pub, &cur_algo, key_type)
1410 }
1411
1412 pub fn public_key(&mut self, key_type: KeyType) -> Result<PublicKeyMaterial, Error> {
1421 keys::public_key(self, key_type)
1422 }
1423}
1424
1425fn digestinfo(digest: &[u8], hash_algo: HashAlgo) -> Result<Vec<u8>, Error> {
1429 if hash_algo.len() != digest.len() {
1430 return Err(Error::InternalError(format!(
1431 "Unexpected hash length {} for digestinfo with hash_algo {:?}",
1432 digest.len(),
1433 hash_algo
1434 )));
1435 }
1436
1437 let tlv = Tlv::new(
1438 Tags::Sequence,
1439 Value::C(vec![
1440 Tlv::new(
1441 Tags::Sequence,
1442 Value::C(vec![
1443 Tlv::new(Tags::ObjectIdentifier, Value::S(hash_algo.oid().to_vec())),
1444 Tlv::new(Tags::Null, Value::S(vec![])),
1445 ]),
1446 ),
1447 Tlv::new(Tags::OctetString, Value::S(digest.into())),
1448 ]),
1449 );
1450
1451 Ok(tlv.serialize())
1452}
1453
1454#[derive(thiserror::Error, Debug, PartialEq, Eq, Copy, Clone)]
1456#[non_exhaustive]
1457pub enum StatusBytes {
1458 #[error("Command correct")]
1459 Ok,
1460
1461 #[error("Command correct, [{0}] bytes available in response")]
1462 OkBytesAvailable(u8),
1463
1464 #[error("Selected file or DO in termination state")]
1465 TerminationState,
1466
1467 #[error("Password not checked, {0} allowed retries")]
1468 PasswordNotChecked(u8),
1469
1470 #[error("Execution error with non-volatile memory unchanged")]
1471 ExecutionErrorNonVolatileMemoryUnchanged,
1472
1473 #[error("Triggering by the card {0}")]
1474 TriggeringByCard(u8),
1475
1476 #[error("Memory failure")]
1477 MemoryFailure,
1478
1479 #[error("Security-related issues (reserved for UIF in this application)")]
1480 SecurityRelatedIssues,
1481
1482 #[error("Wrong length (Lc and/or Le)")]
1483 WrongLength,
1484
1485 #[error("Logical channel not supported")]
1486 LogicalChannelNotSupported,
1487
1488 #[error("Secure messaging not supported")]
1489 SecureMessagingNotSupported,
1490
1491 #[error("Last command of the chain expected")]
1492 LastCommandOfChainExpected,
1493
1494 #[error("Command chaining not supported")]
1495 CommandChainingNotSupported,
1496
1497 #[error("Security status not satisfied")]
1498 SecurityStatusNotSatisfied,
1499
1500 #[error("Authentication method blocked")]
1501 AuthenticationMethodBlocked,
1502
1503 #[error("Condition of use not satisfied")]
1504 ConditionOfUseNotSatisfied,
1505
1506 #[error("Expected secure messaging DOs missing (e. g. SM-key)")]
1507 ExpectedSecureMessagingDOsMissing,
1508
1509 #[error("SM data objects incorrect (e. g. wrong TLV-structure in command data)")]
1510 SMDataObjectsIncorrect,
1511
1512 #[error("Incorrect parameters in the command data field")]
1513 IncorrectParametersCommandDataField,
1514
1515 #[error("File or application not found")]
1516 FileOrApplicationNotFound,
1517
1518 #[error("Referenced data, reference data or DO not found")]
1519 ReferencedDataNotFound,
1520
1521 #[error("Wrong parameters P1-P2")]
1522 WrongParametersP1P2,
1523
1524 #[error("Instruction code (INS) not supported or invalid")]
1525 INSNotSupported,
1526
1527 #[error("Class (CLA) not supported")]
1528 CLANotSupported,
1529
1530 #[error("No precise diagnosis")]
1531 NoPreciseDiagnosis,
1532
1533 #[error("Unknown OpenPGP card status: [{0:x}, {1:x}]")]
1534 UnknownStatus(u8, u8),
1535}
1536
1537impl From<(u8, u8)> for StatusBytes {
1538 fn from(status: (u8, u8)) -> Self {
1539 match (status.0, status.1) {
1540 (0x90, 0x00) => StatusBytes::Ok,
1541 (0x61, bytes) => StatusBytes::OkBytesAvailable(bytes),
1542
1543 (0x62, 0x85) => StatusBytes::TerminationState,
1544 (0x63, 0xC0..=0xCF) => StatusBytes::PasswordNotChecked(status.1 & 0xf),
1545 (0x64, 0x00) => StatusBytes::ExecutionErrorNonVolatileMemoryUnchanged,
1546 (0x64, 0x02..=0x80) => StatusBytes::TriggeringByCard(status.1),
1547 (0x65, 0x01) => StatusBytes::MemoryFailure,
1548 (0x66, 0x00) => StatusBytes::SecurityRelatedIssues,
1549 (0x67, 0x00) => StatusBytes::WrongLength,
1550 (0x68, 0x81) => StatusBytes::LogicalChannelNotSupported,
1551 (0x68, 0x82) => StatusBytes::SecureMessagingNotSupported,
1552 (0x68, 0x83) => StatusBytes::LastCommandOfChainExpected,
1553 (0x68, 0x84) => StatusBytes::CommandChainingNotSupported,
1554 (0x69, 0x82) => StatusBytes::SecurityStatusNotSatisfied,
1555 (0x69, 0x83) => StatusBytes::AuthenticationMethodBlocked,
1556 (0x69, 0x85) => StatusBytes::ConditionOfUseNotSatisfied,
1557 (0x69, 0x87) => StatusBytes::ExpectedSecureMessagingDOsMissing,
1558 (0x69, 0x88) => StatusBytes::SMDataObjectsIncorrect,
1559 (0x6A, 0x80) => StatusBytes::IncorrectParametersCommandDataField,
1560 (0x6A, 0x82) => StatusBytes::FileOrApplicationNotFound,
1561 (0x6A, 0x88) => StatusBytes::ReferencedDataNotFound,
1562 (0x6B, 0x00) => StatusBytes::WrongParametersP1P2,
1563 (0x6D, 0x00) => StatusBytes::INSNotSupported,
1564 (0x6E, 0x00) => StatusBytes::CLANotSupported,
1565 (0x6F, 0x00) => StatusBytes::NoPreciseDiagnosis,
1566 _ => StatusBytes::UnknownStatus(status.0, status.1),
1567 }
1568 }
1569}