use heapless::Vec;
use crate::backend::key::{KeyBackend, KeyHandle};
use crate::error::BackendError;
use crate::limits::{CAPDU_MAX, ENC_KEY_BLOCK_MAX, RAPDU_MAX, SCP03_S16_MAX};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ScpMode {
S8,
S16,
}
impl ScpMode {
#[must_use]
pub const fn from_i(i_param: u8) -> Self {
if i_param & 0x08 != 0 {
Self::S16
} else {
Self::S8
}
}
#[must_use]
pub const fn field_len(self) -> usize {
match self {
Self::S8 => 8,
Self::S16 => 16,
}
}
#[must_use]
pub const fn mac_len(self) -> usize {
self.field_len()
}
#[must_use]
pub const fn l_bits(self) -> u16 {
match self {
Self::S8 => 0x0040,
Self::S16 => 0x0080,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Scp03Session(u16);
impl Scp03Session {
#[must_use]
pub const fn new(index: u16) -> Self {
Self(index)
}
#[must_use]
pub const fn index(self) -> u16 {
self.0
}
}
pub trait Scp03Backend: KeyBackend {
fn scp03_derive_session(
&self,
static_enc: &KeyHandle,
static_mac: &KeyHandle,
mode: ScpMode,
host_challenge: &[u8],
card_challenge: &[u8],
) -> Result<Scp03Session, BackendError>;
fn scp03_card_cryptogram(
&self,
s: &Scp03Session,
host_ch: &[u8],
card_ch: &[u8],
) -> Result<Vec<u8, SCP03_S16_MAX>, BackendError>;
fn scp03_host_cryptogram(
&self,
s: &Scp03Session,
host_ch: &[u8],
card_ch: &[u8],
) -> Result<Vec<u8, SCP03_S16_MAX>, BackendError>;
fn scp03_pseudo_card_challenge(
&self,
static_enc: &KeyHandle,
mode: ScpMode,
seq_counter: &[u8; 3],
invoker_aid: &[u8],
) -> Result<Vec<u8, SCP03_S16_MAX>, BackendError>;
fn scp03_wrap_command(
&self,
s: &mut Scp03Session,
capdu: &[u8],
) -> Result<Vec<u8, CAPDU_MAX>, BackendError>;
fn scp03_unwrap_response(
&self,
s: &mut Scp03Session,
rapdu: &[u8],
) -> Result<Vec<u8, RAPDU_MAX>, BackendError>;
fn scp03_encrypt_put_key_payload(
&self,
dek: &KeyHandle,
new_key: &KeyHandle,
) -> Result<Vec<u8, ENC_KEY_BLOCK_MAX>, BackendError>;
fn scp03_close_session(&self, _s: Scp03Session) {}
}