1use std::convert::{TryFrom, TryInto};
7use std::fmt::{Display, Formatter, Write};
8
9use chrono::{DateTime, Utc};
10
11use crate::ocard::algorithm::AlgorithmAttributes;
12use crate::ocard::tags::Tags;
13use crate::ocard::tlv::length::tlv_encode_length;
14use crate::ocard::tlv::Tlv;
15use crate::ocard::KeyType;
16use crate::Error;
17
18mod algo_attrs;
19mod algo_info;
20mod application_id;
21mod cardholder;
22mod extended_cap;
23mod extended_length_info;
24mod fingerprint;
25mod historical;
26mod kdf_do;
27mod key_generation_times;
28mod pw_status;
29
30pub struct ApplicationRelatedData(pub(crate) Tlv);
39
40impl ApplicationRelatedData {
41 pub fn application_id(&self) -> Result<ApplicationIdentifier, Error> {
43 let aid = self.0.find(Tags::ApplicationIdentifier);
44
45 if let Some(aid) = aid {
46 Ok(ApplicationIdentifier::try_from(&aid.serialize()[..])?)
47 } else {
48 Err(Error::NotFound("Couldn't get Application ID.".to_string()))
49 }
50 }
51
52 pub fn historical_bytes(&self) -> Result<HistoricalBytes, Error> {
54 let hist = self.0.find(Tags::HistoricalBytes);
55
56 if let Some(hist) = hist {
57 log::trace!("Historical bytes: {:x?}", hist);
58 (hist.serialize().as_slice()).try_into()
59 } else {
60 Err(Error::NotFound(
61 "Failed to get historical bytes.".to_string(),
62 ))
63 }
64 }
65
66 pub fn extended_length_information(&self) -> Result<Option<ExtendedLengthInfo>, Error> {
69 let eli = self.0.find(Tags::ExtendedLengthInformation);
70
71 log::trace!("Extended length information: {:x?}", eli);
72
73 if let Some(eli) = eli {
74 Ok(Some((&eli.serialize()[..]).try_into()?))
76 } else {
77 Ok(None)
79 }
80 }
81
82 pub fn extended_capabilities(&self) -> Result<ExtendedCapabilities, Error> {
94 let app_id = self.application_id()?;
95 let version = app_id.version();
96
97 let ecap = self.0.find(Tags::ExtendedCapabilities);
99
100 if let Some(ecap) = ecap {
101 Ok(ExtendedCapabilities::try_from((
102 &ecap.serialize()[..],
103 version,
104 ))?)
105 } else {
106 Err(Error::NotFound(
107 "Failed to get extended capabilities.".to_string(),
108 ))
109 }
110 }
111
112 pub fn algorithm_attributes(&self, key_type: KeyType) -> Result<AlgorithmAttributes, Error> {
114 let aa = self.0.find(key_type.algorithm_tag());
115
116 if let Some(aa) = aa {
117 AlgorithmAttributes::try_from(&aa.serialize()[..])
118 } else {
119 Err(Error::NotFound(format!(
120 "Failed to get algorithm attributes for {key_type:?}."
121 )))
122 }
123 }
124
125 pub fn pw_status_bytes(&self) -> Result<PWStatusBytes, Error> {
127 let psb = self.0.find(Tags::PWStatusBytes);
128
129 if let Some(psb) = psb {
130 let pws = (&psb.serialize()[..]).try_into()?;
131
132 log::trace!("PW Status: {:x?}", pws);
133
134 Ok(pws)
135 } else {
136 Err(Error::NotFound(
137 "Failed to get PW status Bytes.".to_string(),
138 ))
139 }
140 }
141
142 pub fn fingerprints(&self) -> Result<KeySet<Fingerprint>, Error> {
145 let fp = self.0.find(Tags::Fingerprints);
146
147 if let Some(fp) = fp {
148 let fp: KeySet<Fingerprint> = (&fp.serialize()[..]).try_into()?;
149
150 log::trace!("Fp: {:x?}", fp);
151
152 Ok(fp)
153 } else {
154 Err(Error::NotFound("Failed to get fingerprints.".into()))
155 }
156 }
157
158 pub fn ca_fingerprints(&self) -> Result<[Option<Fingerprint>; 3], Error> {
159 let fp = self.0.find(Tags::CaFingerprints);
160
161 if let Some(fp) = fp {
162 let fp: KeySet<Fingerprint> = (&fp.serialize()[..]).try_into()?;
164
165 let fp = [fp.signature, fp.decryption, fp.authentication];
166
167 log::trace!("CA Fp: {:x?}", fp);
168
169 Ok(fp)
170 } else {
171 Err(Error::NotFound("Failed to get CA fingerprints.".into()))
172 }
173 }
174
175 pub fn key_generation_times(&self) -> Result<KeySet<KeyGenerationTime>, Error> {
177 let kg = self.0.find(Tags::GenerationTimes);
178
179 if let Some(kg) = kg {
180 let kg: KeySet<KeyGenerationTime> = (&kg.serialize()[..]).try_into()?;
181
182 log::trace!("Key generation: {:x?}", kg);
183
184 Ok(kg)
185 } else {
186 Err(Error::NotFound(
187 "Failed to get key generation times.".to_string(),
188 ))
189 }
190 }
191
192 pub fn key_information(&self) -> Result<Option<KeyInformation>, Error> {
193 let ki = self.0.find(Tags::KeyInformation);
194
195 Ok(ki.map(|v| v.serialize().into()))
198 }
199
200 pub fn uif_pso_cds(&self) -> Result<Option<UserInteractionFlag>, Error> {
201 let uif = self.0.find(Tags::UifSig);
202
203 match uif {
204 None => Ok(None),
205 Some(v) => Ok(Some(v.serialize().try_into()?)),
206 }
207 }
208
209 pub fn uif_pso_dec(&self) -> Result<Option<UserInteractionFlag>, Error> {
210 let uif = self.0.find(Tags::UifDec);
211
212 match uif {
213 None => Ok(None),
214 Some(v) => Ok(Some(v.serialize().try_into()?)),
215 }
216 }
217
218 pub fn uif_pso_aut(&self) -> Result<Option<UserInteractionFlag>, Error> {
219 let uif = self.0.find(Tags::UifAuth);
220
221 match uif {
222 None => Ok(None),
223 Some(v) => Ok(Some(v.serialize().try_into()?)),
224 }
225 }
226
227 pub fn attestation_key_fingerprint(&self) -> Result<Option<Fingerprint>, Error> {
229 match self.0.find(Tags::FingerprintAttestation) {
230 None => Ok(None),
231 Some(data) => {
232 if data.serialize().iter().any(|&b| b != 0) {
234 Ok(Some(Fingerprint::try_from(data.serialize().as_slice())?))
235 } else {
236 Ok(None)
237 }
238 }
239 }
240 }
241
242 pub fn attestation_key_algorithm_attributes(
244 &mut self,
245 ) -> Result<Option<AlgorithmAttributes>, Error> {
246 match self.0.find(Tags::AlgorithmAttributesAttestation) {
247 None => Ok(None),
248 Some(data) => Ok(Some(AlgorithmAttributes::try_from(
249 data.serialize().as_slice(),
250 )?)),
251 }
252 }
253
254 pub fn attestation_key_generation_time(&self) -> Result<Option<KeyGenerationTime>, Error> {
256 match self.0.find(Tags::GenerationTimeAttestation) {
257 None => Ok(None),
258 Some(data) => {
259 match &data.serialize()[..] {
261 [a, b, c, d] => {
262 match u32::from_be_bytes([*a, *b, *c, *d]) {
265 0 => Ok(None),
266 kgt => Ok(Some(kgt.into())),
267 }
268 }
269 data => Err(Error::ParseError(format!(
270 "attestation_key_generation_time unexpected length {}",
271 data.len()
272 ))),
273 }
274 }
275 }
276 }
277
278 pub fn uif_attestation(&self) -> Result<Option<UserInteractionFlag>, Error> {
279 let uif = self.0.find(Tags::UifAttestation);
280
281 match uif {
282 None => Ok(None),
283 Some(v) => Ok(Some(v.serialize().try_into()?)),
284 }
285 }
286}
287
288#[derive(Debug)]
290pub struct SecuritySupportTemplate {
291 pub(crate) dsc: u32,
294}
295
296impl SecuritySupportTemplate {
297 pub fn signature_count(&self) -> u32 {
298 self.dsc
299 }
300}
301
302#[derive(Clone, Copy, Eq, PartialEq, Debug)]
304pub struct KeyGenerationTime(u32);
305
306impl KeyGenerationTime {
307 pub fn get(&self) -> u32 {
308 self.0
309 }
310}
311
312impl Display for KeyGenerationTime {
313 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
314 write!(f, "{}", DateTime::<Utc>::from(self))
315 }
316}
317
318#[derive(Clone, Copy, Eq, PartialEq, Debug)]
320pub struct UserInteractionFlag([u8; 2]);
321
322impl TryFrom<Vec<u8>> for UserInteractionFlag {
323 type Error = Error;
324
325 fn try_from(v: Vec<u8>) -> Result<Self, Self::Error> {
326 match &v[..] {
327 [a, b] => Ok(UserInteractionFlag([*a, *b])),
328 _ => Err(Error::ParseError(format!("Can't get UIF from {v:x?}"))),
329 }
330 }
331}
332
333impl UserInteractionFlag {
334 pub fn touch_policy(&self) -> TouchPolicy {
335 self.0[0].into()
336 }
337
338 pub fn set_touch_policy(&mut self, tm: TouchPolicy) {
339 self.0[0] = tm.into();
340 }
341
342 pub fn features(&self) -> Features {
343 self.0[1].into()
344 }
345
346 pub(crate) fn as_bytes(&self) -> &[u8] {
347 &self.0[..]
348 }
349}
350
351impl Display for UserInteractionFlag {
352 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
353 write!(
354 f,
355 "Touch policy: {} [Features: {}]",
356 self.touch_policy(),
357 self.features()
358 )
359 }
360}
361
362#[derive(Debug, Eq, PartialEq, Clone, Copy)]
370pub enum TouchPolicy {
371 Off,
372 On,
373 Fixed,
374 Cached,
375 CachedFixed,
376 Unknown(u8),
377}
378
379impl TouchPolicy {
380 pub fn touch_required(&self) -> bool {
386 !matches!(self, Self::Off)
387 }
388}
389
390impl Display for TouchPolicy {
391 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
392 match self {
393 TouchPolicy::Off => write!(f, "Off"),
394 TouchPolicy::On => write!(f, "On"),
395 TouchPolicy::Fixed => write!(f, "Fixed"),
396 TouchPolicy::Cached => write!(f, "Cached"),
397 TouchPolicy::CachedFixed => write!(f, "CachedFixed"),
398 TouchPolicy::Unknown(i) => write!(f, "Unknown({i})"),
399 }
400 }
401}
402
403impl From<TouchPolicy> for u8 {
404 fn from(tm: TouchPolicy) -> Self {
405 match tm {
406 TouchPolicy::Off => 0,
407 TouchPolicy::On => 1,
408 TouchPolicy::Fixed => 2,
409 TouchPolicy::Cached => 3,
410 TouchPolicy::CachedFixed => 4,
411 TouchPolicy::Unknown(i) => i,
412 }
413 }
414}
415
416impl From<u8> for TouchPolicy {
417 fn from(i: u8) -> Self {
418 match i {
419 0 => TouchPolicy::Off,
420 1 => TouchPolicy::On,
421 2 => TouchPolicy::Fixed,
422 3 => TouchPolicy::Cached,
423 4 => TouchPolicy::CachedFixed,
424 _ => TouchPolicy::Unknown(i),
425 }
426 }
427}
428
429pub struct Features(u8);
432
433impl From<u8> for Features {
434 fn from(i: u8) -> Self {
435 Features(i)
436 }
437}
438
439impl Display for Features {
440 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
441 let mut ft = vec![];
442
443 if self.0 & 0x80 != 0 {
444 ft.push("Display")
445 }
446 if self.0 & 0x40 != 0 {
447 ft.push("Biometric input sensor")
448 }
449 if self.0 & 0x20 != 0 {
450 ft.push("Button")
451 }
452 if self.0 & 0x10 != 0 {
453 ft.push("Keypad")
454 }
455 if self.0 & 0x8 != 0 {
456 ft.push("LED")
457 }
458 if self.0 & 0x4 != 0 {
459 ft.push("Loudspeaker")
460 }
461 if self.0 & 0x2 != 0 {
462 ft.push("Microphone")
463 }
464 if self.0 & 0x1 != 0 {
465 ft.push("Touchscreen")
466 }
467
468 write!(f, "{}", ft.join(", "))
469 }
470}
471
472pub struct KeyInformation(Vec<u8>);
474
475impl From<Vec<u8>> for KeyInformation {
476 fn from(v: Vec<u8>) -> Self {
477 KeyInformation(v)
478 }
479}
480
481impl KeyInformation {
482 pub fn num_additional(&self) -> usize {
484 (self.0.len() - 6) / 2
485 }
486
487 fn get_ref(&self, n: usize) -> u8 {
488 self.0[n * 2]
489 }
490 fn get_status(&self, n: usize) -> KeyStatus {
491 self.0[n * 2 + 1].into()
492 }
493
494 pub fn sig_ref(&self) -> u8 {
495 self.get_ref(0)
496 }
497 pub fn sig_status(&self) -> KeyStatus {
498 self.get_status(0)
499 }
500
501 pub fn dec_ref(&self) -> u8 {
502 self.get_ref(1)
503 }
504 pub fn dec_status(&self) -> KeyStatus {
505 self.get_status(1)
506 }
507
508 pub fn aut_ref(&self) -> u8 {
509 self.get_ref(2)
510 }
511 pub fn aut_status(&self) -> KeyStatus {
512 self.get_status(2)
513 }
514
515 pub fn additional_ref(&self, num: usize) -> u8 {
516 self.get_ref(3 + num)
517 }
518 pub fn additional_status(&self, num: usize) -> KeyStatus {
519 self.get_status(3 + num)
520 }
521}
522
523impl Display for KeyInformation {
524 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
525 writeln!(
526 f,
527 "signature key (#{}): {}",
528 self.sig_ref(),
529 self.sig_status()
530 )?;
531 writeln!(
532 f,
533 "decryption key (#{}): {}",
534 self.dec_ref(),
535 self.dec_status()
536 )?;
537 writeln!(
538 f,
539 "authentication key (#{}): {}",
540 self.aut_ref(),
541 self.aut_status()
542 )?;
543
544 for i in 0..self.num_additional() {
545 writeln!(
546 f,
547 "additional key {} (#{}): {}",
548 i,
549 self.additional_ref(i),
550 self.additional_status(i)
551 )?;
552 }
553
554 Ok(())
555 }
556}
557
558#[derive(Debug, PartialEq, Eq, Clone, Copy)]
561pub enum KeyStatus {
562 NotPresent,
563 Generated,
564 Imported,
565 Unknown(u8),
566}
567
568impl From<u8> for KeyStatus {
569 fn from(i: u8) -> Self {
570 match i {
571 0 => KeyStatus::NotPresent,
572 1 => KeyStatus::Generated,
573 2 => KeyStatus::Imported,
574 _ => KeyStatus::Unknown(i),
575 }
576 }
577}
578
579impl Display for KeyStatus {
580 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
581 match self {
582 KeyStatus::NotPresent => write!(f, "not present"),
583 KeyStatus::Generated => write!(f, "generated"),
584 KeyStatus::Imported => write!(f, "imported"),
585 KeyStatus::Unknown(i) => write!(f, "unknown status ({i})"),
586 }
587 }
588}
589
590#[derive(Debug, Copy, Clone, Eq, PartialEq)]
592pub struct ApplicationIdentifier {
593 application: u8,
594 version: u16,
595 manufacturer: u16,
596 serial: u32,
597}
598
599impl Display for ApplicationIdentifier {
600 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
601 write!(
602 f,
603 "D276000124 {:02X} {:04X} {:04X} {:08X} 0000",
604 self.application, self.version, self.manufacturer, self.serial
605 )
606 }
607}
608
609#[derive(Debug, Clone, Copy, PartialEq, Eq)]
611pub struct HistoricalBytes {
612 cib: u8,
614
615 csd: Option<CardServiceData>,
617
618 cc: Option<CardCapabilities>,
620
621 sib: u8,
623}
624
625#[derive(Debug, Clone, Copy, PartialEq, Eq)]
627pub struct CardCapabilities {
628 command_chaining: bool,
629 extended_lc_le: bool,
630 extended_length_information: bool,
631}
632
633impl Display for CardCapabilities {
634 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
635 if self.command_chaining {
636 writeln!(f, "- command chaining")?;
637 }
638 if self.extended_lc_le {
639 writeln!(f, "- extended Lc and Le fields")?;
640 }
641 if self.extended_length_information {
642 writeln!(f, "- extended Length Information")?;
643 }
644
645 Ok(())
646 }
647}
648
649#[derive(Debug, Clone, Copy, PartialEq, Eq)]
651pub struct CardServiceData {
652 select_by_full_df_name: bool, select_by_partial_df_name: bool, dos_available_in_ef_dir: bool,
655 dos_available_in_ef_atr_info: bool, access_services: [bool; 3], mf: bool,
658}
659
660impl Display for CardServiceData {
661 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
662 if self.select_by_full_df_name {
663 writeln!(f, "- Application Selection by full DF name")?;
664 }
665 if self.select_by_partial_df_name {
666 writeln!(f, "- Application Selection by partial DF name")?;
667 }
668 if self.dos_available_in_ef_dir {
669 writeln!(f, "- DOs available in EF.DIR")?;
670 }
671 if self.dos_available_in_ef_atr_info {
672 writeln!(f, "- DOs available in EF.ATR/INFO")?;
673 }
674
675 write!(
676 f,
677 "- EF.DIR and EF.ATR/INFO access services by the GET DATA command (BER-TLV): "
678 )?;
679 for a in self.access_services {
680 if a {
681 write!(f, "1")?;
682 } else {
683 write!(f, "0")?;
684 }
685 }
686 writeln!(f)?;
687
688 if self.mf {
689 writeln!(f, "- Card with MF")?;
690 }
691
692 Ok(())
693 }
694}
695
696#[derive(Debug, Eq, Clone, Copy, PartialEq)]
698pub struct ExtendedCapabilities {
699 secure_messaging: bool,
700 get_challenge: bool,
701 key_import: bool,
702 pw_status_change: bool,
703 private_use_dos: bool,
704 algo_attrs_changeable: bool,
705 aes: bool,
706 kdf_do: bool,
707
708 sm_algo: u8,
709 max_len_challenge: u16,
710 max_len_cardholder_cert: u16,
711
712 max_cmd_len: Option<u16>, max_resp_len: Option<u16>, max_len_special_do: Option<u16>, pin_block_2_format_support: Option<bool>, mse_command_support: Option<bool>, }
719
720impl Display for ExtendedCapabilities {
721 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
722 if self.secure_messaging {
723 writeln!(f, "- secure messaging")?;
724 }
725 if self.get_challenge {
726 writeln!(f, "- get challenge")?;
727 }
728 if self.key_import {
729 writeln!(f, "- key import")?;
730 }
731 if self.pw_status_change {
732 writeln!(f, "- PW Status changeable")?;
733 }
734 if self.private_use_dos {
735 writeln!(f, "- private use DOs")?;
736 }
737 if self.algo_attrs_changeable {
738 writeln!(f, "- algorithm attributes changeable")?;
739 }
740 if self.aes {
741 writeln!(f, "- PSO:DEC/ENC with AES")?;
742 }
743 if self.kdf_do {
744 writeln!(f, "- KDF-DO")?;
745 }
746 if self.sm_algo != 0 {
747 writeln!(f, "- secure messaging algorithm: {:#02X}", self.sm_algo)?;
748 }
749
750 if self.max_len_challenge != 0 {
751 writeln!(
752 f,
753 "- maximum length of challenge: {}",
754 self.max_len_challenge
755 )?;
756 }
757 writeln!(
758 f,
759 "- maximum length cardholder certificates: {}",
760 self.max_len_cardholder_cert
761 )?;
762
763 if let Some(max_cmd_len) = self.max_cmd_len {
765 writeln!(f, "- maximum command length: {max_cmd_len}")?;
766 }
767 if let Some(max_resp_len) = self.max_resp_len {
768 writeln!(f, "- maximum response length: {max_resp_len}")?;
769 }
770
771 if let Some(max_len_special_do) = self.max_len_special_do {
773 writeln!(f, "- maximum length for special DOs: {max_len_special_do}")?;
774 }
775 if self.pin_block_2_format_support == Some(true) {
776 writeln!(f, "- PIN block 2 format supported")?;
777 }
778 if self.mse_command_support == Some(true) {
779 writeln!(f, "- MSE command (for DEC and AUT) supported")?;
780 }
781
782 Ok(())
783 }
784}
785
786#[derive(Debug, Eq, Clone, Copy, PartialEq)]
788pub struct ExtendedLengthInfo {
789 max_command_bytes: u16,
790 max_response_bytes: u16,
791}
792
793impl Display for ExtendedLengthInfo {
794 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
795 writeln!(f, "- max command length: {}", self.max_command_bytes)?;
796 writeln!(f, "- max response length: {}", self.max_response_bytes)?;
797 Ok(())
798 }
799}
800
801#[derive(Debug, PartialEq, Eq)]
803pub struct CardholderRelatedData {
804 name: Option<Vec<u8>>,
805 lang: Option<Vec<Lang>>,
806 sex: Option<Sex>,
807}
808
809impl Display for CardholderRelatedData {
810 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
811 if let Some(name) = &self.name {
812 writeln!(f, "Name: {}", Self::latin1_to_string(name))?;
813 }
814 if let Some(sex) = self.sex {
815 writeln!(f, "Sex: {sex}")?;
816 }
817 if let Some(lang) = &self.lang {
818 for (n, l) in lang.iter().enumerate() {
819 writeln!(f, "Lang {}: {}", n + 1, l)?;
820 }
821 }
822 Ok(())
823 }
824}
825
826#[derive(Debug, PartialEq, Eq, Clone, Copy)]
831pub enum Sex {
832 NotKnown,
833 Male,
834 Female,
835 NotApplicable,
836 UndefinedValue(u8), }
838
839impl Display for Sex {
840 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
841 match self {
842 Self::NotKnown => write!(f, "Not known"),
843 Self::Male => write!(f, "Male"),
844 Self::Female => write!(f, "Female"),
845 Self::NotApplicable => write!(f, "Not applicable"),
846 Self::UndefinedValue(v) => write!(f, "Undefined value {v:x?}"),
847 }
848 }
849}
850
851impl From<&Sex> for u8 {
852 fn from(sex: &Sex) -> u8 {
853 match sex {
854 Sex::NotKnown => 0x30,
855 Sex::Male => 0x31,
856 Sex::Female => 0x32,
857 Sex::NotApplicable => 0x39,
858 Sex::UndefinedValue(v) => *v,
859 }
860 }
861}
862
863impl From<u8> for Sex {
864 fn from(s: u8) -> Self {
865 match s {
866 0x30 => Self::NotKnown,
867 0x31 => Self::Male,
868 0x32 => Self::Female,
869 0x39 => Self::NotApplicable,
870 v => Self::UndefinedValue(v),
871 }
872 }
873}
874
875#[derive(Debug, PartialEq, Eq, Clone, Copy)]
880pub enum Lang {
881 Value([u8; 2]),
882 Invalid(u8),
883}
884
885impl Display for Lang {
886 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
887 match self {
888 Self::Value(v) => {
889 write!(f, "{}{}", v[0] as char, v[1] as char)
890 }
891 Self::Invalid(v) => {
892 write!(f, "{v:x?}")
893 }
894 }
895 }
896}
897
898impl From<(char, char)> for Lang {
899 fn from(c: (char, char)) -> Self {
900 Lang::Value([c.0 as u8, c.1 as u8])
901 }
902}
903
904impl From<[char; 2]> for Lang {
905 fn from(c: [char; 2]) -> Self {
906 Lang::Value([c[0] as u8, c[1] as u8])
907 }
908}
909
910impl From<Lang> for Vec<u8> {
911 fn from(lang: Lang) -> Self {
912 match lang {
913 Lang::Value(v) => vec![v[0], v[1]],
914 Lang::Invalid(v) => vec![v],
915 }
916 }
917}
918
919impl From<&[u8; 1]> for Lang {
920 fn from(data: &[u8; 1]) -> Self {
921 Lang::Invalid(data[0])
922 }
923}
924
925impl From<&[u8; 2]> for Lang {
926 fn from(data: &[u8; 2]) -> Self {
927 Lang::Value([data[0], data[1]])
928 }
929}
930
931#[derive(Debug, PartialEq, Eq)]
933pub struct PWStatusBytes {
934 pub(crate) pw1_cds_valid_once: bool,
935 pub(crate) pw1_pin_block: bool,
936 pub(crate) pw1_len_format: u8,
937 pub(crate) rc_len: u8,
938 pub(crate) pw3_pin_block: bool,
939 pub(crate) pw3_len_format: u8,
940 pub(crate) err_count_pw1: u8,
941 pub(crate) err_count_rst: u8,
942 pub(crate) err_count_pw3: u8,
943}
944
945impl PWStatusBytes {
946 pub fn set_pw1_pin_block(&mut self, val: bool) {
950 self.pw1_pin_block = val;
951 }
952
953 pub fn set_pw3_pin_block(&mut self, val: bool) {
957 self.pw3_pin_block = val;
958 }
959
960 pub fn pw1_cds_valid_once(&self) -> bool {
962 self.pw1_cds_valid_once
963 }
964
965 pub fn set_pw1_cds_valid_once(&mut self, val: bool) {
967 self.pw1_cds_valid_once = val;
968 }
969
970 pub fn pw1_max_len(&self) -> u8 {
972 self.pw1_len_format & 0x7f
973 }
974
975 pub fn rc_max_len(&self) -> u8 {
977 self.rc_len
978 }
979
980 pub fn pw3_max_len(&self) -> u8 {
982 self.pw3_len_format & 0x7f
983 }
984
985 pub fn err_count_pw1(&self) -> u8 {
987 self.err_count_pw1
988 }
989
990 pub fn err_count_rc(&self) -> u8 {
992 self.err_count_rst
993 }
994
995 pub fn err_count_pw3(&self) -> u8 {
997 self.err_count_pw3
998 }
999}
1000
1001#[derive(Clone, Eq, PartialEq)]
1003pub struct Fingerprint([u8; 20]);
1004
1005impl Fingerprint {
1006 pub fn to_hex(&self) -> String {
1007 self.0.map(|byte| format!("{:02x}", byte)).join("")
1008 }
1009
1010 pub fn to_spaced_hex(&self) -> String {
1011 let mut fp = String::new();
1012
1013 for i in 0..20 {
1014 let _ = write!(&mut fp, "{:02x}", self.0[i]);
1015
1016 if i < 19 && (i % 2 == 1) {
1017 fp.push(' ');
1018 }
1019 if i == 9 {
1020 fp.push(' ');
1021 }
1022 }
1023
1024 fp
1025 }
1026}
1027
1028#[derive(Debug, Clone)]
1031pub struct KdfDo {
1032 kdf_algo: u8,
1036
1037 hash_algo: Option<u8>,
1041
1042 iter_count: Option<u32>,
1044
1045 salt_pw1: Option<Vec<u8>>,
1047
1048 salt_rc: Option<Vec<u8>>,
1050
1051 salt_pw3: Option<Vec<u8>>,
1053
1054 initial_hash_pw1: Option<Vec<u8>>,
1056
1057 initial_hash_pw3: Option<Vec<u8>>,
1059}
1060
1061impl KdfDo {
1062 pub(crate) fn serialize(&self) -> Vec<u8> {
1063 let mut ser = vec![];
1068
1069 ser.push(0x81);
1070 ser.push(0x01);
1071 ser.push(self.kdf_algo);
1072
1073 if let Some(hash_algo) = self.hash_algo {
1074 ser.push(0x82);
1075 ser.push(0x01);
1076 ser.push(hash_algo);
1077 }
1078
1079 if let Some(iter_count) = self.iter_count {
1080 ser.push(0x83);
1081 ser.push(0x04);
1082 ser.extend_from_slice(&iter_count.to_be_bytes());
1083 }
1084
1085 if let Some(salt_pw1) = &self.salt_pw1 {
1086 ser.push(0x84);
1087 ser.extend_from_slice(&tlv_encode_length(salt_pw1.len() as u16));
1088 ser.extend_from_slice(salt_pw1);
1089 }
1090
1091 if let Some(salt_rc) = &self.salt_rc {
1092 ser.push(0x85);
1093 ser.extend_from_slice(&tlv_encode_length(salt_rc.len() as u16));
1094 ser.extend_from_slice(salt_rc);
1095 }
1096
1097 if let Some(salt_pw3) = &self.salt_pw3 {
1098 ser.push(0x86);
1099 ser.extend_from_slice(&tlv_encode_length(salt_pw3.len() as u16));
1100 ser.extend_from_slice(salt_pw3);
1101 }
1102
1103 if let Some(initial_hash_pw1) = &self.initial_hash_pw1 {
1104 ser.push(0x87);
1105 ser.extend_from_slice(&tlv_encode_length(initial_hash_pw1.len() as u16));
1106 ser.extend_from_slice(initial_hash_pw1);
1107 }
1108 if let Some(initial_hash_pw3) = &self.initial_hash_pw3 {
1109 ser.push(0x88);
1110 ser.extend_from_slice(&tlv_encode_length(initial_hash_pw3.len() as u16));
1111 ser.extend_from_slice(initial_hash_pw3);
1112 }
1113 ser
1114 }
1115
1116 pub fn iter_salted(
1117 hash_algo: u8,
1118 salt_pw1: Vec<u8>,
1119 salt_rc: Vec<u8>,
1120 salt_pw3: Vec<u8>,
1121 ) -> Result<Self, Error> {
1122 const PW1_INITIAL: &str = "123456";
1123 const PW3_INITIAL: &str = "12345678";
1124
1125 const ITER_COUNT: u32 = 0x03000000;
1126
1127 if hash_algo != 0x08 && hash_algo != 0x0a {
1130 return Err(Error::UnsupportedAlgo(
1131 "Unsupported hash algorithm".to_string(),
1132 ));
1133 }
1134
1135 let kdf_algo = 0x03; let hash_algo = Some(hash_algo);
1137 let iter_count = Some(ITER_COUNT);
1138
1139 let salt_pw1 = Some(salt_pw1);
1140 let salt_rc = Some(salt_rc);
1141 let salt_pw3 = Some(salt_pw3);
1142
1143 let initial_hash_pw1 = Some(crate::ocard::kdf::itersalt(
1144 PW1_INITIAL,
1145 hash_algo,
1146 iter_count,
1147 salt_pw1.as_deref(),
1148 )?);
1149
1150 let initial_hash_pw3 = Some(crate::ocard::kdf::itersalt(
1151 PW3_INITIAL,
1152 hash_algo,
1153 iter_count,
1154 salt_pw3.as_deref(),
1155 )?);
1156
1157 Ok(Self {
1158 kdf_algo,
1159 hash_algo,
1160 iter_count,
1161 salt_pw1,
1162 salt_rc,
1163 salt_pw3,
1164 initial_hash_pw1,
1165 initial_hash_pw3,
1166 })
1167 }
1168}
1169
1170pub(crate) fn complete<O>(result: nom::IResult<&[u8], O>) -> Result<O, Error> {
1172 let (rem, output) = result.map_err(|_err| Error::ParseError("Parsing failed".to_string()))?;
1173 if rem.is_empty() {
1174 Ok(output)
1175 } else {
1176 Err(Error::ParseError(format!(
1177 "Parsing incomplete, trailing data: {rem:x?}"
1178 )))
1179 }
1180}
1181
1182#[derive(Clone, Debug, Eq, PartialEq)]
1184pub struct KeySet<T> {
1185 signature: Option<T>,
1186 decryption: Option<T>,
1187 authentication: Option<T>,
1188}
1189
1190impl<T> From<(Option<T>, Option<T>, Option<T>)> for KeySet<T> {
1191 fn from(tuple: (Option<T>, Option<T>, Option<T>)) -> Self {
1192 Self {
1193 signature: tuple.0,
1194 decryption: tuple.1,
1195 authentication: tuple.2,
1196 }
1197 }
1198}
1199
1200impl<T> KeySet<T> {
1201 pub fn signature(&self) -> Option<&T> {
1202 self.signature.as_ref()
1203 }
1204
1205 pub fn decryption(&self) -> Option<&T> {
1206 self.decryption.as_ref()
1207 }
1208
1209 pub fn authentication(&self) -> Option<&T> {
1210 self.authentication.as_ref()
1211 }
1212}