use crate::{ApplicationId, io};
macro_rules! command {
($slf:expr, $out:expr, { $( $field_name:ident: $field_type:ty = $field_value:expr ),* }, $size:literal, [ $( $body:expr ),* ]) => {{
let header: [u8; $size] = $crate::command_header!({
$( $field_name: $field_type = $field_value ),*
}, $size);
$slf.default_exchange_multi($out, &header, &[ $( $body ),* ]).await?
}};
}
pub(super) use command;
macro_rules! command_de_minimis {
($slf:expr, { $( $field_name:ident: $field_type:ty = $field_value:expr ),* }, $size:literal, [ $( $body:expr ),* ]) => {{
let header: [u8; $size] = $crate::command_header!({
$( $field_name: $field_type = $field_value ),*
}, $size);
$slf.default_exchange_multi_de_minimis(&header, &[ $( $body ),* ]).await?
}};
}
pub(super) use command_de_minimis;
macro_rules! command_cmac_de_minimis {
($slf:expr, { $( $field_name:ident: $field_type:ty = $field_value:expr ),* }, $size:literal, [ $( $body:expr ),* ]) => {{
let header: [u8; $size] = $crate::command_header!({
$( $field_name: $field_type = $field_value ),*
}, $size);
match &mut $slf.authentication.session {
$crate::Session::Aes { keying, .. } => {
$crate::io::cmac_out_cmac_in(&$slf.card, keying, &mut $slf.buf, &header, &[ $( $body ),* ]).await?
},
$crate::Session::Des { keying, .. } => {
$crate::io::cmac_out_cmac_in(&$slf.card, keying, &mut $slf.buf, &header, &[ $( $body ),* ]).await?
},
}
}};
}
pub(super) use command_cmac_de_minimis;
macro_rules! command_encrypted_request_de_minimis {
($slf:expr, { $( $field_name:ident: $field_type:ty = $field_value:expr ),* }, $size:literal, [ $( $body:expr ),* ]) => {{
let header: [u8; $size] = $crate::command_header!({
$( $field_name: $field_type = $field_value ),*
}, $size);
let crc = $crate::crc32(&header, &[ $( $body ),* ]).to_le_bytes();
match &mut $slf.authentication.session {
$crate::Session::Aes { keying, .. } => {
$crate::io::encrypted_out_cmac_in(&$slf.card, keying, &mut $slf.buf, &header, &[ $( $body, )* &crc ]).await?
},
$crate::Session::Des { keying, .. } => {
$crate::io::encrypted_out_cmac_in(&$slf.card, keying, &mut $slf.buf, &header, &[ $( $body, )* &crc ]).await?
},
}
}};
}
pub(super) use command_encrypted_request_de_minimis;
macro_rules! command_encrypted_response {
($slf:expr, $out:expr, { $( $field_name:ident: $field_type:ty = $field_value:expr ),* }, $size:literal, [ $( $body:expr ),* ]) => {{
let header: [u8; $size] = $crate::command_header!({
$( $field_name: $field_type = $field_value ),*
}, $size);
match &mut $slf.authentication.session {
$crate::Session::Aes { keying, .. } => {
$crate::io::plain_out_encrypted_in(&$slf.card, keying, $out, &header, &[ $( $body ),* ]).await?
},
$crate::Session::Des { keying, .. } => {
$crate::io::plain_out_encrypted_in(&$slf.card, keying, $out, &header, &[ $( $body ),* ]).await?
},
}
}};
}
pub(super) use command_encrypted_response;
macro_rules! command_encrypted_response_de_minimis {
($slf:expr, { $( $field_name:ident: $field_type:ty = $field_value:expr ),* }, $size:literal, [ $( $body:expr ),* ]) => {{
let header: [u8; $size] = $crate::command_header!({
$( $field_name: $field_type = $field_value ),*
}, $size);
match &mut $slf.authentication.session {
$crate::Session::Aes { keying, .. } => {
$crate::io::plain_out_encrypted_in(&$slf.card, keying, &mut $slf.buf, &header, &[ $( $body ),* ]).await?
},
$crate::Session::Des { keying, .. } => {
$crate::io::plain_out_encrypted_in(&$slf.card, keying, &mut $slf.buf, &header, &[ $( $body ),* ]).await?
},
}
}};
}
pub(super) use command_encrypted_response_de_minimis;
macro_rules! command_header {
({ $( $field_name:ident: $field_type:ty = $field_value:expr ),* }, $size:literal) => {{
#[repr(C, packed)]
#[allow(dead_code)]
#[derive(Debug)]
struct Command {
$( $field_name: $field_type ),*
}
let header = Command {
$( $field_name: $field_value ),*
};
#[allow(unsafe_code)]
unsafe { $crate::std::mem::transmute::<Command, [u8; $size]>(header) }
}};
}
pub(super) use command_header;
pub trait AuthenticationState {}
pub struct Card<IoBackendT, AuthenticationStateT>
where
AuthenticationStateT: AuthenticationState,
IoBackendT: io::Backend,
{
pub(super) buf: [u8; 60],
pub(super) application_id: ApplicationId,
pub(super) card: IoBackendT,
pub(super) authentication: AuthenticationStateT,
}
impl<AuthenticationStateT, IoBackendT> AsRef<IoBackendT> for Card<IoBackendT, AuthenticationStateT>
where
AuthenticationStateT: AuthenticationState,
IoBackendT: io::Backend,
{
fn as_ref(&self) -> &IoBackendT {
&self.card
}
}
impl<AuthenticationStateT, IoBackendT> Card<IoBackendT, AuthenticationStateT>
where
AuthenticationStateT: AuthenticationState,
IoBackendT: io::Backend,
{
pub fn authentication_state(&self) -> &AuthenticationStateT {
&self.authentication
}
}