mod authenticated;
mod default;
mod unauthenticated;
pub use authenticated::Authenticated;
pub use default::CardIoDefault;
pub use unauthenticated::Unauthenticated;
use crate::io;
macro_rules! command {
($slf:expr, $out:expr, { $( $field_name:ident: $field_type:ty = $field_value:expr ),* }, [ $( $body:ident ),* ]) => {{
let header: &[u8] = $crate::client::command_header!({
$( $field_name: $field_type = $field_value ),*
});
$slf.default_exchange_multi($out, header, &[ $( $body ),* ]).await?
}};
}
pub(super) use command;
macro_rules! command_cmac {
($slf:expr, $out:expr, { $( $field_name:ident: $field_type:ty = $field_value:expr ),* }, [ $( $body:ident ),* ]) => {{
let header: &[u8] = $crate::client::command_header!({
$( $field_name: $field_type = $field_value ),*
});
match &mut $slf.authentication.session {
$crate::client::Session::Aes { keying, .. } => {
$crate::io::cmac_out_cmac_in(&$slf.card, keying, $out, &header, &[ $( $body ),* ]).await?
},
$crate::client::Session::Des { keying, .. } => {
$crate::io::cmac_out_cmac_in(&$slf.card, keying, $out, &header, &[ $( $body ),* ]).await?
},
}
}};
}
pub(super) use command_cmac;
macro_rules! command_encrypted_request {
($slf:expr, $out:expr, { $( $field_name:ident: $field_type:ty = $field_value:expr ),* }, [ $( $body:ident ),* ]) => {{
let header: &[u8] = $crate::client::command_header!({
$( $field_name: $field_type = $field_value ),*
});
match &mut $slf.authentication.session {
$crate::client::Session::Aes { keying, .. } => {
$crate::io::encrypted_out_plain_in(&$slf.card, keying, $out, &header, &[ $( $body ),* ]).await?
},
$crate::client::Session::Des { keying, .. } => {
$crate::io::encrypted_out_plain_in(&$slf.card, keying, $out, &header, &[ $( $body ),* ]).await?
},
}
}};
}
pub(super) use command_encrypted_request;
macro_rules! command_encrypted_response {
($slf:expr, $out:expr, { $( $field_name:ident: $field_type:ty = $field_value:expr ),* }, [ $( $body:ident ),* ]) => {{
let header: &[u8] = $crate::client::command_header!({
$( $field_name: $field_type = $field_value ),*
});
match &mut $slf.authentication.session {
$crate::client::Session::Aes { keying, .. } => {
$crate::io::plain_out_encrypted_in(&$slf.card, keying, $out, &header, &[ $( $body ),* ]).await?
},
$crate::client::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_header {
({ $( $field_name:ident: $field_type:ty = $field_value:expr ),* }) => {{
#[repr(C, packed)]
#[allow(dead_code)]
struct Command {
$( $field_name: $field_type ),*
}
let header = Command {
$( $field_name: $field_value ),*
};
#[allow(unsafe_code)]
#[allow(trivial_casts)]
unsafe { $crate::std::slice::from_raw_parts(&header as *const Command as *const u8, size_of::<Command>()) }
}};
}
pub(super) use command_header;
pub trait AuthenticationState {}
pub struct Card<'card, IoBackendT, AuthenticationStateT>
where
AuthenticationStateT: AuthenticationState,
IoBackendT: io::Backend,
{
pub(super) buf: [u8; 0xff],
pub(super) card: &'card IoBackendT,
pub(super) authentication: AuthenticationStateT,
}
impl<'card, AuthenticationStateT, IoBackendT> AsRef<IoBackendT>
for Card<'card, IoBackendT, AuthenticationStateT>
where
AuthenticationStateT: AuthenticationState,
IoBackendT: io::Backend,
{
fn as_ref(&self) -> &IoBackendT {
self.card
}
}
impl<'card, AuthenticationStateT, IoBackendT> Card<'card, IoBackendT, AuthenticationStateT>
where
AuthenticationStateT: AuthenticationState,
IoBackendT: io::Backend,
{
pub fn authentication_state(&self) -> &AuthenticationStateT {
&self.authentication
}
}