use core::fmt;
use heapless::{String, Vec};
use crate::limits::MAX_APPLETS;
use crate::aid::Aid;
use crate::command::install::PrivLen;
use crate::limits::{
ATR_ATS_MAX, CIN_MAX, GETDATA_RAW_MAX, IIN_MAX, MAX_CIPHERS, MAX_ELFS, MAX_KEYSETS,
MAX_KEYS_PER_SET, MAX_MODULES_PER_ELF, MAX_PRIVILEGE_BYTES, MAX_QUIRKS, MAX_SCP_VARIANTS,
MAX_SDS, MAX_WARNINGS, OTHER_DETAIL_MAX,
};
use crate::transport::TransportProtocol;
pub struct CardInfo {
pub isd_aid: Aid,
pub atr_or_ats: Vec<u8, ATR_ATS_MAX>,
pub transport_protocol: TransportProtocol,
pub scp_supported: Vec<ScpVariant, MAX_SCP_VARIANTS>, pub scp_default: ScpVariant,
pub isd_keysets: Vec<Keyset, MAX_KEYSETS>, pub isd_key_template_format: KeyTemplateFormat,
pub capabilities: CardCapabilities,
pub card_recognition_data_raw: Vec<u8, GETDATA_RAW_MAX>,
pub iin: Option<Vec<u8, IIN_MAX>>, pub cin: Option<Vec<u8, CIN_MAX>>, pub card_image_number: Option<Vec<u8, CIN_MAX>>, pub jc_platform_version: Option<(u8, u8, u8)>,
pub privilege_encoding: PrivLen,
pub quirks_detected: Vec<String<OTHER_DETAIL_MAX>, MAX_QUIRKS>,
pub discovery_warnings: Vec<DiscoveryWarning, MAX_WARNINGS>,
}
#[derive(Debug)]
pub struct CardInventory {
pub security_domains: Vec<SecurityDomainEntry, MAX_SDS>,
pub applets: Vec<ApplicationEntry, MAX_APPLETS>,
pub elfs: Vec<ExecutableLoadFileEntry, MAX_ELFS>,
}
#[derive(Clone, Copy, PartialEq, Eq)]
pub enum ScpVariant {
Scp02 { i_param: u8 }, Scp03 { i_param: u8 }, }
impl fmt::Debug for ScpVariant {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let (name, i) = match self {
ScpVariant::Scp02 { i_param } => ("Scp02", i_param),
ScpVariant::Scp03 { i_param } => ("Scp03", i_param),
};
f.debug_struct(name)
.field("i_param", &format_args!("{i:#04x}"))
.finish()
}
}
pub struct Keyset {
pub kvn: u8,
pub keys: Vec<KeyInfo, MAX_KEYS_PER_SET>, }
impl fmt::Debug for Keyset {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Keyset")
.field("kvn", &format_args!("{:#04x}", self.kvn))
.field("keys", &self.keys)
.finish()
}
}
pub struct KeyInfo {
pub kid: u8,
pub key_type: KeyType,
pub key_length: u8,
}
impl fmt::Debug for KeyInfo {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("KeyInfo")
.field("kid", &format_args!("{:#04x}", self.kid))
.field("key_type", &self.key_type)
.field("key_length", &self.key_length)
.finish()
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum KeyType {
Des, Aes, RsaPublic, RsaPrivateCrt, RsaPrivateExponent, EccPublic, EccPrivate, EccParametersRef, Other(u8),
}
#[derive(Debug)]
pub enum KeyTemplateFormat {
Basic, Extended, }
pub struct CardCapabilities {
pub max_logical_channels: u8, pub ciphers_supported: Vec<CipherAlg, MAX_CIPHERS>,
pub privileges_supported: Vec<u8, MAX_PRIVILEGE_BYTES>,
pub memory_total_bytes: Option<u32>,
pub memory_free_bytes: Option<u32>,
pub cci_raw: Vec<u8, GETDATA_RAW_MAX>, }
#[non_exhaustive]
#[derive(Debug)]
pub enum CipherAlg {
Aes128,
Aes192,
Aes256,
TripleDes,
Rsa1024,
Rsa2048,
Rsa3072,
Rsa4096,
EccP256,
EccP384,
EccP521,
Sha1,
Sha256,
Sha384,
Sha512,
Other(String<OTHER_DETAIL_MAX>),
}
pub struct SecurityDomainEntry {
pub aid: Aid,
pub life_cycle_state: u8, pub privileges: [u8; 3],
pub associated_sd_aid: Option<Aid>, }
pub struct ApplicationEntry {
pub aid: Aid,
pub life_cycle_state: u8,
pub privileges: [u8; 3],
pub associated_sd_aid: Aid, pub associated_elf_aid: Option<Aid>, }
#[derive(Debug)]
pub struct ExecutableLoadFileEntry {
pub aid: Aid,
pub life_cycle_state: u8,
pub associated_sd_aid: Aid,
pub modules: Vec<Aid, MAX_MODULES_PER_ELF>, }
#[non_exhaustive]
#[derive(Debug)]
pub enum DiscoveryWarning {
CardRecognitionDataMissing,
KeyInformationTemplateMissing,
CardCapabilityInfoMissing,
UnknownLifecycleByte(u8),
GetStatusParseFailed,
Other(String<OTHER_DETAIL_MAX>),
}
impl core::fmt::Debug for CardInfo {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("CardInfo")
.field("isd_aid", &self.isd_aid)
.field(
"atr_or_ats",
&crate::hexfmt::HexBytes(self.atr_or_ats.as_slice()),
)
.field("transport_protocol", &self.transport_protocol)
.field("scp_supported", &self.scp_supported)
.field("scp_default", &self.scp_default)
.field("isd_keysets", &self.isd_keysets)
.field("isd_key_template_format", &self.isd_key_template_format)
.field("capabilities", &self.capabilities)
.field(
"card_recognition_data_raw",
&crate::hexfmt::HexBytes(self.card_recognition_data_raw.as_slice()),
)
.field("iin", &self.iin.as_deref().map(crate::hexfmt::HexBytes))
.field("cin", &self.cin.as_deref().map(crate::hexfmt::HexBytes))
.field(
"card_image_number",
&self
.card_image_number
.as_deref()
.map(crate::hexfmt::HexBytes),
)
.field("jc_platform_version", &self.jc_platform_version)
.field("privilege_encoding", &self.privilege_encoding)
.field("quirks_detected", &self.quirks_detected)
.field("discovery_warnings", &self.discovery_warnings)
.finish()
}
}
impl core::fmt::Debug for CardCapabilities {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("CardCapabilities")
.field("max_logical_channels", &self.max_logical_channels)
.field("ciphers_supported", &self.ciphers_supported)
.field(
"privileges_supported",
&crate::hexfmt::HexBytes(self.privileges_supported.as_slice()),
)
.field("memory_total_bytes", &self.memory_total_bytes)
.field("memory_free_bytes", &self.memory_free_bytes)
.field("cci_raw", &crate::hexfmt::HexBytes(self.cci_raw.as_slice()))
.finish()
}
}
impl core::fmt::Debug for SecurityDomainEntry {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("SecurityDomainEntry")
.field("aid", &self.aid)
.field("life_cycle_state", &self.life_cycle_state)
.field("privileges", &crate::hexfmt::HexBytes(&self.privileges[..]))
.field("associated_sd_aid", &self.associated_sd_aid)
.finish()
}
}
impl core::fmt::Debug for ApplicationEntry {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("ApplicationEntry")
.field("aid", &self.aid)
.field("life_cycle_state", &self.life_cycle_state)
.field("privileges", &crate::hexfmt::HexBytes(&self.privileges[..]))
.field("associated_sd_aid", &self.associated_sd_aid)
.field("associated_elf_aid", &self.associated_elf_aid)
.finish()
}
}