1use std::convert::{TryFrom, TryInto};
7
8use card_backend::{CardBackend, CardCaps, CardTransaction, PinType, SmartcardError};
9use secrecy::{ExposeSecret, SecretVec};
10
11use crate::ocard::algorithm::{AlgorithmAttributes, AlgorithmInformation};
12use crate::ocard::apdu::command::Command;
13use crate::ocard::apdu::response::RawResponse;
14use crate::ocard::crypto::{CardUploadableKey, Cryptogram, Hash, PublicKeyMaterial};
15use crate::ocard::data::{
16 ApplicationIdentifier, ApplicationRelatedData, CardholderRelatedData, ExtendedCapabilities,
17 ExtendedLengthInfo, Fingerprint, HistoricalBytes, KdfDo, KeyGenerationTime, Lang,
18 PWStatusBytes, SecuritySupportTemplate, Sex, UserInteractionFlag,
19};
20use crate::ocard::tags::{ShortTag, Tags};
21use crate::ocard::tlv::value::Value;
22use crate::ocard::tlv::Tlv;
23use crate::Error;
24
25pub mod algorithm;
26pub(crate) mod apdu;
27mod commands;
28pub mod crypto;
29pub mod data;
30pub mod kdf;
31mod keys;
32pub(crate) mod oid;
33pub(crate) mod tags;
34pub(crate) mod tlv;
35
36pub(crate) const OPENPGP_APPLICATION: &[u8] = &[0xD2, 0x76, 0x00, 0x01, 0x24, 0x01];
37
38#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
40pub enum KeyType {
41 Signing,
42 Decryption,
43 Authentication,
44
45 Attestation,
47}
48
49impl KeyType {
50 pub(crate) fn algorithm_tag(&self) -> ShortTag {
52 match self {
53 Self::Signing => Tags::AlgorithmAttributesSignature,
54 Self::Decryption => Tags::AlgorithmAttributesDecryption,
55 Self::Authentication => Tags::AlgorithmAttributesAuthentication,
56 Self::Attestation => Tags::AlgorithmAttributesAttestation,
57 }
58 .into()
59 }
60
61 fn fingerprint_put_tag(&self) -> ShortTag {
66 match self {
67 Self::Signing => Tags::FingerprintSignature,
68 Self::Decryption => Tags::FingerprintDecryption,
69 Self::Authentication => Tags::FingerprintAuthentication,
70 Self::Attestation => Tags::FingerprintAttestation,
71 }
72 .into()
73 }
74
75 fn timestamp_put_tag(&self) -> ShortTag {
80 match self {
81 Self::Signing => Tags::GenerationTimeSignature,
82 Self::Decryption => Tags::GenerationTimeDecryption,
83 Self::Authentication => Tags::GenerationTimeAuthentication,
84 Self::Attestation => Tags::GenerationTimeAttestation,
85 }
86 .into()
87 }
88}
89
90#[derive(Debug)]
94struct CardImmutable {
95 aid: ApplicationIdentifier,
96 ec: ExtendedCapabilities,
97 hb: Option<HistoricalBytes>, eli: Option<ExtendedLengthInfo>, ai: Option<Option<AlgorithmInformation>>, }
104
105pub struct OpenPGP {
112 card: Box<dyn CardBackend + Send + Sync>,
114
115 card_caps: Option<CardCaps>,
118
119 immutable: Option<CardImmutable>,
123}
124
125impl OpenPGP {
126 pub fn new<B>(backend: B) -> Result<Self, Error>
131 where
132 B: Into<Box<dyn CardBackend + Send + Sync>>,
133 {
134 let card: Box<dyn CardBackend + Send + Sync> = backend.into();
135
136 let mut op = Self {
137 card,
138 card_caps: None,
139 immutable: None,
140 };
141
142 let (caps, imm) = {
143 let mut tx = op.transaction()?;
144 tx.select()?;
145
146 let ard = tx.application_related_data()?;
148
149 let mut ext_support = false;
153 let mut chaining_support = false;
154
155 if let Ok(hist) = ard.historical_bytes() {
156 if let Some(cc) = hist.card_capabilities() {
157 chaining_support = cc.command_chaining();
158 ext_support = cc.extended_lc_le();
159 }
160 }
161
162 let ext_cap = ard.extended_capabilities()?;
163
164 let (max_cmd_bytes, max_rsp_bytes) = if let Ok(Some(eli)) =
166 ard.extended_length_information()
167 {
168 (eli.max_command_bytes(), eli.max_response_bytes())
170 } else if let (Some(cmd), Some(rsp)) = (ext_cap.max_cmd_len(), ext_cap.max_resp_len()) {
171 (cmd, rsp)
173 } else {
174 (255, 255)
176 };
177
178 let pw_status = ard.pw_status_bytes()?;
179 let pw1_max = pw_status.pw1_max_len();
180 let pw3_max = pw_status.pw3_max_len();
181
182 let caps = CardCaps::new(
183 ext_support,
184 chaining_support,
185 max_cmd_bytes,
186 max_rsp_bytes,
187 pw1_max,
188 pw3_max,
189 );
190
191 let imm = CardImmutable {
192 aid: ard.application_id()?,
193 ec: ard.extended_capabilities()?,
194 hb: Some(ard.historical_bytes()?),
195 eli: ard.extended_length_information()?,
196 ai: None, };
198
199 drop(tx);
200
201 let caps = op.card.limit_card_caps(caps);
206
207 (caps, imm)
208 };
209
210 log::trace!("set card_caps to: {:x?}", caps);
211 op.card_caps = Some(caps);
212
213 log::trace!("set immutable card state to: {:x?}", imm);
214 op.immutable = Some(imm);
215
216 Ok(op)
217 }
218
219 pub fn into_card(self) -> Box<dyn CardBackend + Send + Sync> {
224 self.card
225 }
226
227 pub fn transaction(&mut self) -> Result<Transaction, Error> {
233 let card_caps = &mut self.card_caps;
234 let immutable = &mut self.immutable; let tx = self.card.transaction(Some(OPENPGP_APPLICATION))?;
237
238 if tx.was_reset() {
239 }
242
243 Ok(Transaction {
244 tx,
245 card_caps,
246 immutable,
247 })
248 }
249}
250
251pub struct Transaction<'a> {
261 tx: Box<dyn CardTransaction + Send + Sync + 'a>,
262 card_caps: &'a Option<CardCaps>,
263 immutable: &'a mut Option<CardImmutable>,
264}
265
266impl Transaction<'_> {
267 pub(crate) fn tx(&mut self) -> &mut dyn CardTransaction {
268 self.tx.as_mut()
269 }
270
271 pub(crate) fn send_command(
272 &mut self,
273 cmd: Command,
274 expect_reply: bool,
275 ) -> Result<RawResponse, Error> {
276 apdu::send_command(&mut *self.tx, cmd, *self.card_caps, expect_reply)
277 }
278
279 pub fn select(&mut self) -> Result<Vec<u8>, Error> {
283 log::info!("OpenPgpTransaction: select");
284
285 self.send_command(commands::select_openpgp()?, false)?
286 .try_into()
287 }
288
289 pub fn terminate_df(&mut self) -> Result<(), Error> {
293 log::info!("OpenPgpTransaction: terminate_df");
294
295 self.send_command(commands::terminate_df()?, false)?;
296 Ok(())
297 }
298
299 pub fn activate_file(&mut self) -> Result<(), Error> {
303 log::info!("OpenPgpTransaction: activate_file");
304
305 self.send_command(commands::activate_file()?, false)?;
306 Ok(())
307 }
308
309 pub fn feature_pinpad_verify(&self) -> bool {
313 self.tx.feature_pinpad_verify()
314 }
315
316 pub fn feature_pinpad_modify(&self) -> bool {
318 self.tx.feature_pinpad_modify()
319 }
320
321 pub fn application_related_data(&mut self) -> Result<ApplicationRelatedData, Error> {
329 log::info!("OpenPgpTransaction: application_related_data");
330
331 let resp = self.send_command(commands::application_related_data()?, true)?;
332 let value = Value::from(resp.data()?, true)?;
333
334 log::trace!(" ARD value: {:02x?}", value);
335
336 Ok(ApplicationRelatedData(Tlv::new(
337 Tags::ApplicationRelatedData,
338 value,
339 )))
340 }
341
342 fn card_immutable(&self) -> Result<&CardImmutable, Error> {
346 if let Some(imm) = &self.immutable {
347 Ok(imm)
348 } else {
349 Err(Error::InternalError(
351 "Unexpected state of immutable cache".to_string(),
352 ))
353 }
354 }
355
356 pub fn application_identifier(&self) -> Result<ApplicationIdentifier, Error> {
361 Ok(self.card_immutable()?.aid)
362 }
363
364 pub fn extended_capabilities(&self) -> Result<ExtendedCapabilities, Error> {
369 Ok(self.card_immutable()?.ec)
370 }
371
372 pub fn historical_bytes(&self) -> Result<Option<HistoricalBytes>, Error> {
377 Ok(self.card_immutable()?.hb)
378 }
379
380 pub fn extended_length_info(&self) -> Result<Option<ExtendedLengthInfo>, Error> {
385 Ok(self.card_immutable()?.eli)
386 }
387
388 #[allow(dead_code)]
389 pub(crate) fn algorithm_information_cached(
390 &mut self,
391 ) -> Result<Option<AlgorithmInformation>, Error> {
392 match &self.immutable {
396 Some(ci) => {
397 if let Some(ai) = &ci.ai {
399 return Ok(ai.clone());
400 }
401 }
402 None => {
403 return Err(Error::InternalError(
404 "Unexpected state of immutable cache".to_string(),
405 ))
406 }
407 }
408
409 let ai = self.algorithm_information()?;
411
412 match self.immutable {
413 Some(ci) => {
414 ci.ai = Some(ai.clone());
415 Ok(ai)
416 }
417 None => Err(Error::InternalError(
418 "Unexpected state of immutable cache".to_string(),
419 )),
420 }
421 }
422
423 pub fn url(&mut self) -> Result<Vec<u8>, Error> {
427 log::info!("OpenPgpTransaction: url");
428
429 self.send_command(commands::url()?, true)?.try_into()
430 }
431
432 pub fn login_data(&mut self) -> Result<Vec<u8>, Error> {
434 log::info!("OpenPgpTransaction: login_data");
435
436 self.send_command(commands::login_data()?, true)?.try_into()
437 }
438
439 pub fn cardholder_related_data(&mut self) -> Result<CardholderRelatedData, Error> {
441 log::info!("OpenPgpTransaction: cardholder_related_data");
442
443 let resp = self.send_command(commands::cardholder_related_data()?, true)?;
444
445 resp.data()?.try_into()
446 }
447
448 pub fn security_support_template(&mut self) -> Result<SecuritySupportTemplate, Error> {
450 log::info!("OpenPgpTransaction: security_support_template");
451
452 let resp = self.send_command(commands::security_support_template()?, true)?;
453
454 let tlv = Tlv::try_from(resp.data()?)?;
455
456 let dst = tlv.find(Tags::DigitalSignatureCounter).ok_or_else(|| {
457 Error::NotFound("Couldn't get DigitalSignatureCounter DO".to_string())
458 })?;
459
460 if let Value::S(data) = dst {
461 let data = match &data[..] {
462 [a, b, c] => [0, *a, *b, *c],
464 _ => {
465 return Err(Error::ParseError(format!(
466 "Unexpected length {} for DigitalSignatureCounter DO",
467 data.len()
468 )))
469 }
470 };
471
472 let dsc: u32 = u32::from_be_bytes(data);
473 Ok(SecuritySupportTemplate { dsc })
474 } else {
475 Err(Error::NotFound(
476 "Failed to process SecuritySupportTemplate".to_string(),
477 ))
478 }
479 }
480
481 #[allow(dead_code)]
496 pub fn cardholder_certificate(&mut self) -> Result<Vec<u8>, Error> {
497 log::info!("OpenPgpTransaction: cardholder_certificate");
498
499 self.send_command(commands::cardholder_certificate()?, true)?
500 .try_into()
501 }
502
503 pub fn next_cardholder_certificate(&mut self) -> Result<Vec<u8>, Error> {
508 log::info!("OpenPgpTransaction: next_cardholder_certificate");
509
510 self.send_command(commands::get_next_cardholder_certificate()?, true)?
511 .try_into()
512 }
513
514 pub fn kdf_do(&mut self) -> Result<KdfDo, Error> {
516 log::info!("OpenPgpTransaction: kdf_do");
517
518 let kdf_do = self
519 .send_command(commands::kdf_do()?, true)?
520 .data()?
521 .try_into()?;
522
523 log::trace!(" KDF DO value: {:02x?}", kdf_do);
524
525 Ok(kdf_do)
526 }
527
528 pub fn algorithm_information(&mut self) -> Result<Option<AlgorithmInformation>, Error> {
530 log::info!("OpenPgpTransaction: algorithm_information");
531
532 let resp = self.send_command(commands::algo_info()?, true)?;
533
534 let ai = resp.data()?.try_into()?;
535 Ok(Some(ai))
536 }
537
538 pub fn attestation_certificate(&mut self) -> Result<Vec<u8>, Error> {
540 log::info!("OpenPgpTransaction: attestation_certificate");
541
542 self.send_command(commands::attestation_certificate()?, true)?
543 .try_into()
544 }
545
546 pub fn firmware_version(&mut self) -> Result<Vec<u8>, Error> {
548 log::info!("OpenPgpTransaction: firmware_version");
549
550 self.send_command(commands::firmware_version()?, true)?
551 .try_into()
552 }
553
554 pub fn set_identity(&mut self, id: u8) -> Result<Vec<u8>, Error> {
559 log::info!("OpenPgpTransaction: set_identity");
560
561 let resp = self.send_command(commands::set_identity(id)?, false);
562
563 if let Err(Error::Smartcard(SmartcardError::NotTransacted)) = resp {
566 Ok(vec![])
567 } else {
568 resp?.try_into()
569 }
570 }
571
572 pub fn select_data(&mut self, num: u8, tag: &[u8]) -> Result<(), Error> {
588 log::info!("OpenPgpTransaction: select_data");
589
590 let tlv = Tlv::new(
591 Tags::GeneralReference,
592 Value::C(vec![Tlv::new(Tags::TagList, Value::S(tag.to_vec()))]),
593 );
594
595 let mut data = tlv.serialize();
596
597 if let Ok(version) = self.firmware_version() {
606 if version.len() == 3
607 && version[0] == 5
608 && (version[1] < 4 || (version[1] == 4 && version[2] <= 3))
609 {
610 if data.len() > 255 {
616 return Err(Error::InternalError(format!(
617 "select_data: exceedingly long data: {}",
618 data.len()
619 )));
620 }
621
622 data.insert(0, data.len() as u8);
623 }
624 }
625
626 let cmd = commands::select_data(num, data)?;
627
628 self.send_command(cmd, true)?.check_ok()?;
631
632 Ok(())
633 }
634
635 pub fn private_use_do(&mut self, num: u8) -> Result<Vec<u8>, Error> {
641 log::info!("OpenPgpTransaction: private_use_do");
642
643 let tag = match num {
644 1 => Tags::PrivateUse1,
645 2 => Tags::PrivateUse2,
646 3 => Tags::PrivateUse3,
647 4 => Tags::PrivateUse4,
648 _ => {
649 return Err(Error::UnsupportedFeature(format!(
650 "Illegal Private Use DO num '{}'",
651 num,
652 )))
653 }
654 };
655
656 let cmd = commands::get_data(tag)?;
657 self.send_command(cmd, true)?.try_into()
658 }
659
660 pub fn factory_reset(&mut self) -> Result<(), Error> {
678 log::info!("OpenPgpTransaction: factory_reset");
679
680 let mut bad_pw_len = 8;
681
682 if let Ok(kdf_do) = self.kdf_do() {
686 if kdf_do.hash_algo() == Some(0x08) {
687 bad_pw_len = 0x20;
688 } else if kdf_do.hash_algo() == Some(0x0a) {
689 bad_pw_len = 0x40;
690 }
691 }
692
693 let bad_pw: Vec<_> = std::iter::repeat(0x40).take(bad_pw_len).collect();
694
695 for _ in 0..4 {
697 let resp = self.verify_pw1_sign(bad_pw.clone().into());
698
699 if !(matches!(
700 resp,
701 Err(Error::CardStatus(StatusBytes::SecurityStatusNotSatisfied))
702 | Err(Error::CardStatus(StatusBytes::AuthenticationMethodBlocked))
703 | Err(Error::CardStatus(
704 StatusBytes::ExecutionErrorNonVolatileMemoryUnchanged
705 ))
706 | Err(Error::CardStatus(StatusBytes::PasswordNotChecked(_)))
707 | Err(Error::CardStatus(StatusBytes::ConditionOfUseNotSatisfied))
708 )) {
709 return Err(Error::InternalError(
710 "Unexpected status for reset, at pw1.".into(),
711 ));
712 }
713 }
714
715 for _ in 0..4 {
717 let resp = self.verify_pw3(bad_pw.clone().into());
718
719 if !(matches!(
720 resp,
721 Err(Error::CardStatus(StatusBytes::SecurityStatusNotSatisfied))
722 | Err(Error::CardStatus(StatusBytes::AuthenticationMethodBlocked))
723 | Err(Error::CardStatus(
724 StatusBytes::ExecutionErrorNonVolatileMemoryUnchanged
725 ))
726 | Err(Error::CardStatus(StatusBytes::PasswordNotChecked(_)))
727 | Err(Error::CardStatus(StatusBytes::ConditionOfUseNotSatisfied))
728 )) {
729 return Err(Error::InternalError(
730 "Unexpected status for reset, at pw3.".into(),
731 ));
732 }
733 }
734
735 self.terminate_df()?;
736 self.activate_file()?;
737
738 Ok(())
739 }
740
741 pub fn verify_pw1_sign(&mut self, pin: SecretVec<u8>) -> Result<(), Error> {
749 log::info!("OpenPgpTransaction: verify_pw1_sign");
750
751 let cmd = commands::verify_pw1_81(pin)?;
752
753 self.send_command(cmd, false)?.try_into()
754 }
755
756 pub fn verify_pw1_sign_pinpad(&mut self) -> Result<(), Error> {
764 log::info!("OpenPgpTransaction: verify_pw1_sign_pinpad");
765
766 let cc = *self.card_caps;
767
768 let res = self.tx().pinpad_verify(PinType::Sign, &cc)?;
769 RawResponse::try_from(res)?.try_into()
770 }
771
772 pub fn check_pw1_sign(&mut self) -> Result<(), Error> {
781 log::info!("OpenPgpTransaction: check_pw1_sign");
782
783 let verify = commands::verify_pw1_81(vec![].into())?;
784 self.send_command(verify, false)?.try_into()
785 }
786
787 pub fn verify_pw1_user(&mut self, pin: SecretVec<u8>) -> Result<(), Error> {
790 log::info!("OpenPgpTransaction: verify_pw1_user");
791
792 let verify = commands::verify_pw1_82(pin)?;
793 self.send_command(verify, false)?.try_into()
794 }
795
796 pub fn verify_pw1_user_pinpad(&mut self) -> Result<(), Error> {
800 log::info!("OpenPgpTransaction: verify_pw1_user_pinpad");
801
802 let cc = *self.card_caps;
803
804 let res = self.tx().pinpad_verify(PinType::User, &cc)?;
805 RawResponse::try_from(res)?.try_into()
806 }
807
808 pub fn check_pw1_user(&mut self) -> Result<(), Error> {
818 log::info!("OpenPgpTransaction: check_pw1_user");
819
820 let verify = commands::verify_pw1_82(vec![].into())?;
821 self.send_command(verify, false)?.try_into()
822 }
823
824 pub fn verify_pw3(&mut self, pin: SecretVec<u8>) -> Result<(), Error> {
826 log::info!("OpenPgpTransaction: verify_pw3");
827
828 let verify = commands::verify_pw3(pin)?;
829 self.send_command(verify, false)?.try_into()
830 }
831
832 pub fn verify_pw3_pinpad(&mut self) -> Result<(), Error> {
835 log::info!("OpenPgpTransaction: verify_pw3_pinpad");
836
837 let cc = *self.card_caps;
838
839 let res = self.tx().pinpad_verify(PinType::Admin, &cc)?;
840 RawResponse::try_from(res)?.try_into()
841 }
842
843 pub fn check_pw3(&mut self) -> Result<(), Error> {
852 log::info!("OpenPgpTransaction: check_pw3");
853
854 let verify = commands::verify_pw3(vec![].into())?;
855 self.send_command(verify, false)?.try_into()
856 }
857
858 pub fn change_pw1(&mut self, old: SecretVec<u8>, new: SecretVec<u8>) -> Result<(), Error> {
862 log::info!("OpenPgpTransaction: change_pw1");
863
864 let mut data = vec![];
865 data.extend(old.expose_secret());
866 data.extend(new.expose_secret());
867
868 let change = commands::change_pw1(data.into())?;
869 self.send_command(change, false)?.try_into()
870 }
871
872 pub fn change_pw1_pinpad(&mut self) -> Result<(), Error> {
875 log::info!("OpenPgpTransaction: change_pw1_pinpad");
876
877 let cc = *self.card_caps;
878
879 let res = self.tx().pinpad_modify(PinType::Sign, &cc)?;
882 RawResponse::try_from(res)?.try_into()
883 }
884
885 pub fn change_pw3(&mut self, old: SecretVec<u8>, new: SecretVec<u8>) -> Result<(), Error> {
889 log::info!("OpenPgpTransaction: change_pw3");
890
891 let mut data = vec![];
892 data.extend(old.expose_secret());
893 data.extend(new.expose_secret());
894
895 let change = commands::change_pw3(data.into())?;
896 self.send_command(change, false)?.try_into()
897 }
898
899 pub fn change_pw3_pinpad(&mut self) -> Result<(), Error> {
902 log::info!("OpenPgpTransaction: change_pw3_pinpad");
903
904 let cc = *self.card_caps;
905
906 let res = self.tx().pinpad_modify(PinType::Admin, &cc)?;
907 RawResponse::try_from(res)?.try_into()
908 }
909
910 pub fn reset_retry_counter_pw1(
918 &mut self,
919 new_pw1: SecretVec<u8>,
920 resetting_code: Option<SecretVec<u8>>,
921 ) -> Result<(), Error> {
922 log::info!("OpenPgpTransaction: reset_retry_counter_pw1");
923
924 let cmd = commands::reset_retry_counter_pw1(resetting_code, new_pw1)?;
925 self.send_command(cmd, false)?.try_into()
926 }
927
928 pub fn decipher(&mut self, dm: Cryptogram) -> Result<Vec<u8>, Error> {
935 match dm {
936 Cryptogram::RSA(message) => {
937 let mut data = vec![0x0];
939 data.extend_from_slice(message);
940
941 self.pso_decipher(data)
943 }
944 Cryptogram::ECDH(eph) => {
945 let epk = Tlv::new(Tags::ExternalPublicKey, Value::S(eph.to_vec()));
953
954 let pkdo = Tlv::new(Tags::PublicKey, Value::C(vec![epk]));
956
957 let cdo = Tlv::new(Tags::Cipher, Value::C(vec![pkdo]));
959
960 self.pso_decipher(cdo.serialize())
961 }
962 }
963 }
964
965 pub fn pso_decipher(&mut self, data: Vec<u8>) -> Result<Vec<u8>, Error> {
971 log::info!("OpenPgpTransaction: pso_decipher");
972
973 let dec_cmd = commands::decryption(data)?;
975 let resp = self.send_command(dec_cmd, true)?;
976
977 Ok(resp.data()?.to_vec())
978 }
979
980 pub fn manage_security_environment(
996 &mut self,
997 for_operation: KeyType,
998 key_ref: KeyType,
999 ) -> Result<(), Error> {
1000 log::info!("OpenPgpTransaction: manage_security_environment");
1001
1002 if !matches!(for_operation, KeyType::Authentication | KeyType::Decryption)
1003 || !matches!(key_ref, KeyType::Authentication | KeyType::Decryption)
1004 {
1005 return Err(Error::UnsupportedAlgo("Only Decryption and Authentication keys can be manipulated by manage_security_environment".to_string()));
1006 }
1007
1008 let cmd = commands::manage_security_environment(for_operation, key_ref)?;
1009 let resp = self.send_command(cmd, false)?;
1010 resp.check_ok()?;
1011 Ok(())
1012 }
1013
1014 pub fn signature_for_hash(&mut self, hash: Hash) -> Result<Vec<u8>, Error> {
1028 self.pso_compute_digital_signature(digestinfo(hash)?)
1029 }
1030
1031 pub fn pso_compute_digital_signature(&mut self, data: Vec<u8>) -> Result<Vec<u8>, Error> {
1037 log::info!("OpenPgpTransaction: pso_compute_digital_signature");
1038
1039 let cds_cmd = commands::signature(data)?;
1040 let resp = self.send_command(cds_cmd, true)?;
1041
1042 Ok(resp.data().map(|d| d.to_vec())?)
1043 }
1044
1045 pub fn authenticate_for_hash(&mut self, hash: Hash) -> Result<Vec<u8>, Error> {
1058 self.internal_authenticate(digestinfo(hash)?)
1059 }
1060
1061 pub fn internal_authenticate(&mut self, data: Vec<u8>) -> Result<Vec<u8>, Error> {
1067 log::info!("OpenPgpTransaction: internal_authenticate");
1068
1069 let ia_cmd = commands::internal_authenticate(data)?;
1070 let resp = self.send_command(ia_cmd, true)?;
1071
1072 Ok(resp.data().map(|d| d.to_vec())?)
1073 }
1074
1075 pub fn set_private_use_do(&mut self, num: u8, data: Vec<u8>) -> Result<(), Error> {
1085 log::info!("OpenPgpTransaction: set_private_use_do");
1086
1087 let tag = match num {
1088 1 => Tags::PrivateUse1,
1089 2 => Tags::PrivateUse2,
1090 3 => Tags::PrivateUse3,
1091 4 => Tags::PrivateUse4,
1092 _ => {
1093 return Err(Error::UnsupportedFeature(format!(
1094 "Illegal Private Use DO num '{}'",
1095 num,
1096 )))
1097 }
1098 };
1099
1100 let cmd = commands::put_data(tag, data)?;
1101 self.send_command(cmd, true)?.try_into()
1102 }
1103
1104 pub fn set_login(&mut self, login: &[u8]) -> Result<(), Error> {
1105 log::info!("OpenPgpTransaction: set_login");
1106
1107 let cmd = commands::put_login_data(login.to_vec())?;
1108 self.send_command(cmd, false)?.try_into()
1109 }
1110
1111 pub fn set_name(&mut self, name: &[u8]) -> Result<(), Error> {
1112 log::info!("OpenPgpTransaction: set_name");
1113
1114 let cmd = commands::put_name(name.to_vec())?;
1115 self.send_command(cmd, false)?.try_into()
1116 }
1117
1118 pub fn set_lang(&mut self, lang: &[Lang]) -> Result<(), Error> {
1119 log::info!("OpenPgpTransaction: set_lang");
1120
1121 let bytes: Vec<_> = lang.iter().flat_map(|&l| Vec::<u8>::from(l)).collect();
1122
1123 let cmd = commands::put_lang(bytes)?;
1124 self.send_command(cmd, false)?.try_into()
1125 }
1126
1127 pub fn set_sex(&mut self, sex: Sex) -> Result<(), Error> {
1128 log::info!("OpenPgpTransaction: set_sex");
1129
1130 let cmd = commands::put_sex((&sex).into())?;
1131 self.send_command(cmd, false)?.try_into()
1132 }
1133
1134 pub fn set_url(&mut self, url: &[u8]) -> Result<(), Error> {
1135 log::info!("OpenPgpTransaction: set_url");
1136
1137 let cmd = commands::put_url(url.to_vec())?;
1138 self.send_command(cmd, false)?.try_into()
1139 }
1140
1141 pub fn set_cardholder_certificate(&mut self, data: Vec<u8>) -> Result<(), Error> {
1146 log::info!("OpenPgpTransaction: set_cardholder_certificate");
1147
1148 let cmd = commands::put_cardholder_certificate(data)?;
1149 self.send_command(cmd, false)?.try_into()
1150 }
1151
1152 pub fn set_algorithm_attributes(
1158 &mut self,
1159 key_type: KeyType,
1160 algorithm_attributes: &AlgorithmAttributes,
1161 ) -> Result<(), Error> {
1162 log::info!("OpenPgpTransaction: set_algorithm_attributes");
1163
1164 let ecap = self.extended_capabilities()?;
1166 if !ecap.algo_attrs_changeable() {
1167 return Ok(());
1171 }
1172
1173 let cmd = commands::put_data(
1175 key_type.algorithm_tag(),
1176 algorithm_attributes.to_data_object()?,
1177 )?;
1178
1179 self.send_command(cmd, false)?.try_into()
1180 }
1181
1182 pub fn set_pw_status_bytes(
1194 &mut self,
1195 pw_status: &PWStatusBytes,
1196 long: bool,
1197 ) -> Result<(), Error> {
1198 log::info!("OpenPgpTransaction: set_pw_status_bytes");
1199
1200 let data = pw_status.serialize_for_put(long);
1201
1202 let cmd = commands::put_pw_status(data)?;
1203 self.send_command(cmd, false)?.try_into()
1204 }
1205
1206 pub fn set_fingerprint(&mut self, fp: Fingerprint, key_type: KeyType) -> Result<(), Error> {
1207 log::info!("OpenPgpTransaction: set_fingerprint");
1208
1209 let cmd = commands::put_data(key_type.fingerprint_put_tag(), fp.as_bytes().to_vec())?;
1210
1211 self.send_command(cmd, false)?.try_into()
1212 }
1213
1214 pub fn set_ca_fingerprint_1(&mut self, fp: Fingerprint) -> Result<(), Error> {
1215 log::info!("OpenPgpTransaction: set_ca_fingerprint_1");
1216
1217 let cmd = commands::put_data(Tags::CaFingerprint1, fp.as_bytes().to_vec())?;
1218 self.send_command(cmd, false)?.try_into()
1219 }
1220
1221 pub fn set_ca_fingerprint_2(&mut self, fp: Fingerprint) -> Result<(), Error> {
1222 log::info!("OpenPgpTransaction: set_ca_fingerprint_2");
1223
1224 let cmd = commands::put_data(Tags::CaFingerprint2, fp.as_bytes().to_vec())?;
1225 self.send_command(cmd, false)?.try_into()
1226 }
1227
1228 pub fn set_ca_fingerprint_3(&mut self, fp: Fingerprint) -> Result<(), Error> {
1229 log::info!("OpenPgpTransaction: set_ca_fingerprint_3");
1230
1231 let cmd = commands::put_data(Tags::CaFingerprint3, fp.as_bytes().to_vec())?;
1232 self.send_command(cmd, false)?.try_into()
1233 }
1234
1235 pub fn set_creation_time(
1236 &mut self,
1237 time: KeyGenerationTime,
1238 key_type: KeyType,
1239 ) -> Result<(), Error> {
1240 log::info!("OpenPgpTransaction: set_creation_time");
1241
1242 let time_value: Vec<u8> = time.get().to_be_bytes().to_vec();
1244
1245 let cmd = commands::put_data(key_type.timestamp_put_tag(), time_value)?;
1246
1247 self.send_command(cmd, false)?.try_into()
1248 }
1249
1250 pub fn set_resetting_code(&mut self, resetting_code: SecretVec<u8>) -> Result<(), Error> {
1257 log::info!("OpenPgpTransaction: set_resetting_code");
1258
1259 let cmd = commands::put_data(Tags::ResettingCode, resetting_code)?;
1260 self.send_command(cmd, false)?.try_into()
1261 }
1262
1263 pub fn set_pso_enc_dec_key(&mut self, key: &[u8]) -> Result<(), Error> {
1269 log::info!("OpenPgpTransaction: set_pso_enc_dec_key");
1270
1271 let cmd = commands::put_data(Tags::PsoEncDecKey, key.to_vec())?;
1272 self.send_command(cmd, false)?.try_into()
1273 }
1274
1275 pub fn set_uif_pso_cds(&mut self, uif: &UserInteractionFlag) -> Result<(), Error> {
1277 log::info!("OpenPgpTransaction: set_uif_pso_cds");
1278
1279 let cmd = commands::put_data(Tags::UifSig, uif.as_bytes().to_vec())?;
1280 self.send_command(cmd, false)?.try_into()
1281 }
1282
1283 pub fn set_uif_pso_dec(&mut self, uif: &UserInteractionFlag) -> Result<(), Error> {
1285 log::info!("OpenPgpTransaction: set_uif_pso_dec");
1286
1287 let cmd = commands::put_data(Tags::UifDec, uif.as_bytes().to_vec())?;
1288 self.send_command(cmd, false)?.try_into()
1289 }
1290
1291 pub fn set_uif_pso_aut(&mut self, uif: &UserInteractionFlag) -> Result<(), Error> {
1293 log::info!("OpenPgpTransaction: set_uif_pso_aut");
1294
1295 let cmd = commands::put_data(Tags::UifAuth, uif.as_bytes().to_vec())?;
1296 self.send_command(cmd, false)?.try_into()
1297 }
1298
1299 pub fn set_uif_attestation(&mut self, uif: &UserInteractionFlag) -> Result<(), Error> {
1312 log::info!("OpenPgpTransaction: set_uif_attestation");
1313
1314 let cmd = commands::put_data(Tags::UifAttestation, uif.as_bytes().to_vec())?;
1315 self.send_command(cmd, false)?.try_into()
1316 }
1317
1318 pub fn generate_attestation(&mut self, key_type: KeyType) -> Result<(), Error> {
1320 log::info!("OpenPgpTransaction: generate_attestation");
1321
1322 let key = match key_type {
1323 KeyType::Signing => 0x01,
1324 KeyType::Decryption => 0x02,
1325 KeyType::Authentication => 0x03,
1326 _ => return Err(Error::InternalError("Unexpected KeyType".to_string())),
1327 };
1328
1329 let cmd = commands::generate_attestation(key)?;
1330 self.send_command(cmd, false)?.try_into()
1331 }
1332
1333 pub fn set_kdf_do(&mut self, kdf_do: &KdfDo) -> Result<(), Error> {
1339 log::info!("OpenPgpTransaction: set_kdf_do");
1340
1341 let cmd = commands::put_data(Tags::KdfDo, kdf_do.serialize())?;
1342 self.send_command(cmd, false)?.try_into()
1343 }
1344
1345 pub fn key_import(
1354 &mut self,
1355 key: Box<dyn CardUploadableKey>,
1356 key_type: KeyType,
1357 ) -> Result<(), Error> {
1358 keys::key_import(self, key, key_type)
1359 }
1360
1361 pub fn generate_key(
1364 &mut self,
1365 fp_from_pub: fn(
1366 &PublicKeyMaterial,
1367 KeyGenerationTime,
1368 KeyType,
1369 ) -> Result<Fingerprint, Error>,
1370 key_type: KeyType,
1371 ) -> Result<(PublicKeyMaterial, KeyGenerationTime), Error> {
1372 let ard = self.application_related_data()?; let cur_algo = ard.algorithm_attributes(key_type)?;
1375
1376 keys::gen_key_set_metadata(self, fp_from_pub, &cur_algo, key_type)
1377 }
1378
1379 pub fn public_key(&mut self, key_type: KeyType) -> Result<PublicKeyMaterial, Error> {
1388 keys::public_key(self, key_type)
1389 }
1390}
1391
1392fn digestinfo(hash: Hash) -> Result<Vec<u8>, Error> {
1393 match hash {
1394 Hash::SHA1(_) | Hash::SHA256(_) | Hash::SHA384(_) | Hash::SHA512(_) => {
1395 let tlv = Tlv::new(
1396 Tags::Sequence,
1397 Value::C(vec![
1398 Tlv::new(
1399 Tags::Sequence,
1400 Value::C(vec![
1401 Tlv::new(
1402 Tags::ObjectIdentifier,
1403 Value::S(hash.oid()?.to_vec()),
1405 ),
1406 Tlv::new(Tags::Null, Value::S(vec![])),
1407 ]),
1408 ),
1409 Tlv::new(Tags::OctetString, Value::S(hash.digest().to_vec())),
1410 ]),
1411 );
1412
1413 Ok(tlv.serialize())
1414 }
1415 Hash::EdDSA(d) => Ok(d.to_vec()),
1416 Hash::ECDSA(d) => Ok(d.to_vec()),
1417 }
1418}
1419
1420#[derive(thiserror::Error, Debug, PartialEq, Eq, Copy, Clone)]
1422#[non_exhaustive]
1423pub enum StatusBytes {
1424 #[error("Command correct")]
1425 Ok,
1426
1427 #[error("Command correct, [{0}] bytes available in response")]
1428 OkBytesAvailable(u8),
1429
1430 #[error("Selected file or DO in termination state")]
1431 TerminationState,
1432
1433 #[error("Password not checked, {0} allowed retries")]
1434 PasswordNotChecked(u8),
1435
1436 #[error("Execution error with non-volatile memory unchanged")]
1437 ExecutionErrorNonVolatileMemoryUnchanged,
1438
1439 #[error("Triggering by the card {0}")]
1440 TriggeringByCard(u8),
1441
1442 #[error("Memory failure")]
1443 MemoryFailure,
1444
1445 #[error("Security-related issues (reserved for UIF in this application)")]
1446 SecurityRelatedIssues,
1447
1448 #[error("Wrong length (Lc and/or Le)")]
1449 WrongLength,
1450
1451 #[error("Logical channel not supported")]
1452 LogicalChannelNotSupported,
1453
1454 #[error("Secure messaging not supported")]
1455 SecureMessagingNotSupported,
1456
1457 #[error("Last command of the chain expected")]
1458 LastCommandOfChainExpected,
1459
1460 #[error("Command chaining not supported")]
1461 CommandChainingNotSupported,
1462
1463 #[error("Security status not satisfied")]
1464 SecurityStatusNotSatisfied,
1465
1466 #[error("Authentication method blocked")]
1467 AuthenticationMethodBlocked,
1468
1469 #[error("Condition of use not satisfied")]
1470 ConditionOfUseNotSatisfied,
1471
1472 #[error("Expected secure messaging DOs missing (e. g. SM-key)")]
1473 ExpectedSecureMessagingDOsMissing,
1474
1475 #[error("SM data objects incorrect (e. g. wrong TLV-structure in command data)")]
1476 SMDataObjectsIncorrect,
1477
1478 #[error("Incorrect parameters in the command data field")]
1479 IncorrectParametersCommandDataField,
1480
1481 #[error("File or application not found")]
1482 FileOrApplicationNotFound,
1483
1484 #[error("Referenced data, reference data or DO not found")]
1485 ReferencedDataNotFound,
1486
1487 #[error("Wrong parameters P1-P2")]
1488 WrongParametersP1P2,
1489
1490 #[error("Instruction code (INS) not supported or invalid")]
1491 INSNotSupported,
1492
1493 #[error("Class (CLA) not supported")]
1494 CLANotSupported,
1495
1496 #[error("No precise diagnosis")]
1497 NoPreciseDiagnosis,
1498
1499 #[error("Unknown OpenPGP card status: [{0:x}, {1:x}]")]
1500 UnknownStatus(u8, u8),
1501}
1502
1503impl From<(u8, u8)> for StatusBytes {
1504 fn from(status: (u8, u8)) -> Self {
1505 match (status.0, status.1) {
1506 (0x90, 0x00) => StatusBytes::Ok,
1507 (0x61, bytes) => StatusBytes::OkBytesAvailable(bytes),
1508
1509 (0x62, 0x85) => StatusBytes::TerminationState,
1510 (0x63, 0xC0..=0xCF) => StatusBytes::PasswordNotChecked(status.1 & 0xf),
1511 (0x64, 0x00) => StatusBytes::ExecutionErrorNonVolatileMemoryUnchanged,
1512 (0x64, 0x02..=0x80) => StatusBytes::TriggeringByCard(status.1),
1513 (0x65, 0x01) => StatusBytes::MemoryFailure,
1514 (0x66, 0x00) => StatusBytes::SecurityRelatedIssues,
1515 (0x67, 0x00) => StatusBytes::WrongLength,
1516 (0x68, 0x81) => StatusBytes::LogicalChannelNotSupported,
1517 (0x68, 0x82) => StatusBytes::SecureMessagingNotSupported,
1518 (0x68, 0x83) => StatusBytes::LastCommandOfChainExpected,
1519 (0x68, 0x84) => StatusBytes::CommandChainingNotSupported,
1520 (0x69, 0x82) => StatusBytes::SecurityStatusNotSatisfied,
1521 (0x69, 0x83) => StatusBytes::AuthenticationMethodBlocked,
1522 (0x69, 0x85) => StatusBytes::ConditionOfUseNotSatisfied,
1523 (0x69, 0x87) => StatusBytes::ExpectedSecureMessagingDOsMissing,
1524 (0x69, 0x88) => StatusBytes::SMDataObjectsIncorrect,
1525 (0x6A, 0x80) => StatusBytes::IncorrectParametersCommandDataField,
1526 (0x6A, 0x82) => StatusBytes::FileOrApplicationNotFound,
1527 (0x6A, 0x88) => StatusBytes::ReferencedDataNotFound,
1528 (0x6B, 0x00) => StatusBytes::WrongParametersP1P2,
1529 (0x6D, 0x00) => StatusBytes::INSNotSupported,
1530 (0x6E, 0x00) => StatusBytes::CLANotSupported,
1531 (0x6F, 0x00) => StatusBytes::NoPreciseDiagnosis,
1532 _ => StatusBytes::UnknownStatus(status.0, status.1),
1533 }
1534 }
1535}