Refactor trait
This commit is contained in:
@@ -26,8 +26,8 @@ where
|
||||
rng.fill_bytes(&mut data[0]);
|
||||
self.felica_write_without_encryption(
|
||||
card,
|
||||
&[FelicaLiteSServiceCode::Write],
|
||||
&[FelicaLiteSBlock::RC],
|
||||
[FelicaLiteSServiceCode::Write],
|
||||
[FelicaLiteSBlock::RC],
|
||||
&data,
|
||||
)?;
|
||||
let rc = RandomChallenge::from(data[0]);
|
||||
@@ -95,7 +95,7 @@ where
|
||||
}
|
||||
|
||||
/// Compute the MAC_A value for a Write With MAC operation.
|
||||
pub(crate) fn compute_write_mac(&mut self, session: &AuthSession, plain: &[u8; 24]) -> [u8; 8] {
|
||||
pub(crate) fn compute_write_mac(&mut self, session: &AuthSession, plain: [u8; 24]) -> [u8; 8] {
|
||||
let mut header = [0u8; 8];
|
||||
header.copy_from_slice(&plain[0..8]);
|
||||
Self::compute_mac(session, session.sk.as_des_write(), &header, &plain[8..24])
|
||||
@@ -110,15 +110,15 @@ where
|
||||
let mut data = [[0u8; 16]; 3];
|
||||
self.felica_read_without_encryption(
|
||||
card,
|
||||
&[FelicaLiteSServiceCode::Read],
|
||||
&[
|
||||
[FelicaLiteSServiceCode::Read],
|
||||
[
|
||||
FelicaLiteSBlock::ID,
|
||||
FelicaLiteSBlock::CKV,
|
||||
FelicaLiteSBlock::MACA,
|
||||
],
|
||||
&mut data,
|
||||
)?;
|
||||
let block_list = &[
|
||||
let block_list = [
|
||||
FelicaLiteSBlock::ID,
|
||||
FelicaLiteSBlock::CKV,
|
||||
FelicaLiteSBlock::MACA,
|
||||
|
||||
@@ -24,13 +24,13 @@ where
|
||||
block[8] = dfc[0];
|
||||
block[9] = dfc[1];
|
||||
block[10..16].copy_from_slice(&arbitrary);
|
||||
self.write_block(card, &[FelicaLiteSBlock::ID], &[block])
|
||||
self.write_block(card, [FelicaLiteSBlock::ID], &[block])
|
||||
}
|
||||
|
||||
/// get value for [`FelicaLiteSBlock::ID`]
|
||||
pub fn get_id(&mut self, card: &CardSession) -> Result<[u8; 16], Error<B::TransportError>> {
|
||||
let mut block = [[0u8; 16]];
|
||||
self.read_block(card, &[FelicaLiteSBlock::ID], &mut block)?;
|
||||
self.read_block(card, [FelicaLiteSBlock::ID], &mut block)?;
|
||||
crate::trace!("ID block: {:02X}", block);
|
||||
Ok(block[0])
|
||||
}
|
||||
@@ -41,7 +41,7 @@ where
|
||||
card: &CardSession,
|
||||
key: &CardKey,
|
||||
) -> Result<(), Error<B::TransportError>> {
|
||||
self.write_block(card, &[FelicaLiteSBlock::CK], &[**key])
|
||||
self.write_block(card, [FelicaLiteSBlock::CK], &[**key])
|
||||
}
|
||||
|
||||
/// set value for [`FelicaLiteSBlock::CK`] with MAC
|
||||
@@ -62,7 +62,7 @@ where
|
||||
card: &CardSession,
|
||||
version: &CardKeyVersion,
|
||||
) -> Result<(), Error<B::TransportError>> {
|
||||
self.write_block(card, &[FelicaLiteSBlock::CKV], &[version.as_block()])
|
||||
self.write_block(card, [FelicaLiteSBlock::CKV], &[version.as_block()])
|
||||
}
|
||||
|
||||
/// set value for [`FelicaLiteSBlock::CKV`] with MAC
|
||||
@@ -82,14 +82,14 @@ where
|
||||
card: &CardSession,
|
||||
) -> Result<CardKeyVersion, Error<B::TransportError>> {
|
||||
let mut block = [[0u8; 16]];
|
||||
self.read_block(card, &[FelicaLiteSBlock::CKV], &mut block)?;
|
||||
self.read_block(card, [FelicaLiteSBlock::CKV], &mut block)?;
|
||||
crate::trace!("CKV block: {:02X}", block);
|
||||
Ok(CardKeyVersion::from(block[0]))
|
||||
}
|
||||
|
||||
pub fn get_mc(&mut self, card: &CardSession) -> Result<MemoryConfig, Error<B::TransportError>> {
|
||||
let mut block = [[0u8; 16]];
|
||||
self.read_block(card, &[FelicaLiteSBlock::MemoryConfig], &mut block)?;
|
||||
self.read_block(card, [FelicaLiteSBlock::MemoryConfig], &mut block)?;
|
||||
crate::trace!("MC block: {:02X}", block[0]);
|
||||
Ok(MemoryConfig::from(block[0]))
|
||||
}
|
||||
@@ -100,6 +100,6 @@ where
|
||||
config: MemoryConfig,
|
||||
) -> Result<(), Error<B::TransportError>> {
|
||||
let block: [u8; 16] = config.into();
|
||||
self.write_block(card, &[FelicaLiteSBlock::MemoryConfig], &[block])
|
||||
self.write_block(card, [FelicaLiteSBlock::MemoryConfig], &[block])
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ pub mod issuance;
|
||||
|
||||
use crate::protocol::felica::error::Error;
|
||||
use crate::types::felica::felica_lite_s::auth::{AuthSession, CardKey, MacInput};
|
||||
use crate::types::felica::{AsBlock, CardSession, FelicaLiteSBlock, FelicaLiteSServiceCode};
|
||||
use crate::types::felica::{CardSession, FelicaLiteSBlock, FelicaLiteSServiceCode, IntoBlockCode};
|
||||
use crate::{Interface, Pn532};
|
||||
use embedded_hal::delay::DelayNs;
|
||||
use embedded_hal::digital::{InputPin, OutputPin};
|
||||
@@ -42,12 +42,12 @@ where
|
||||
&mut self,
|
||||
card: &CardSession,
|
||||
session: &AuthSession,
|
||||
block: impl AsBlock,
|
||||
block_code: impl IntoBlockCode,
|
||||
) -> Result<[u8; 16], crate::Error<B::TransportError>> {
|
||||
let mut block_data = [[0u8; 16]; 2];
|
||||
let block_list = [block.as_block(), FelicaLiteSBlock::MACA as u16];
|
||||
self.read_block(card, &block_list, &mut block_data)?;
|
||||
let input = MacInput::new(&block_data, &block_list);
|
||||
let block_codes = [block_code.into(), FelicaLiteSBlock::MACA as u16];
|
||||
self.read_block(card, block_codes, &mut block_data)?;
|
||||
let input = MacInput::new(&block_data, block_codes);
|
||||
let mac = Self::compute_mac(
|
||||
session,
|
||||
session.sk.as_des(),
|
||||
@@ -68,29 +68,31 @@ where
|
||||
&mut self,
|
||||
card: &CardSession,
|
||||
session: &AuthSession,
|
||||
block: impl AsBlock,
|
||||
block_code: impl IntoBlockCode,
|
||||
data: &[u8; 16],
|
||||
) -> Result<(), crate::Error<B::TransportError>> {
|
||||
let mut wcnt_block = [[0u8; 16]];
|
||||
self.read_block(card, &[FelicaLiteSBlock::WCNT], &mut wcnt_block)?;
|
||||
self.read_block(card, [FelicaLiteSBlock::WCNT], &mut wcnt_block)?;
|
||||
let mut wcnt = [0u8; 3];
|
||||
wcnt.copy_from_slice(&wcnt_block[0][0..3]);
|
||||
|
||||
let mut plain = [0u8; 24];
|
||||
plain[0..3].copy_from_slice(&wcnt);
|
||||
plain[4] = block.as_block() as u8;
|
||||
plain[6] = FelicaLiteSBlock::MACA.as_block() as u8;
|
||||
plain[8..24].copy_from_slice(data);
|
||||
let maca_block_code: u16 = FelicaLiteSBlock::MACA.clone().into();
|
||||
|
||||
let mac = self.compute_write_mac(session, &plain);
|
||||
let mut plain = heapless::Vec::<u8, 24>::new();
|
||||
plain.extend(wcnt);
|
||||
plain.push(block_code.clone().into() as u8).unwrap();
|
||||
plain.push(maca_block_code as u8).unwrap();
|
||||
plain.extend(*data);
|
||||
|
||||
let mut mac_a = [0u8; 16];
|
||||
mac_a[0..8].copy_from_slice(&mac);
|
||||
mac_a[8..11].copy_from_slice(&wcnt);
|
||||
let mac = self.compute_write_mac(session, plain.into_array().unwrap());
|
||||
|
||||
let block_list = [block.as_block(), FelicaLiteSBlock::MACA as u16];
|
||||
let block_data = [*data, mac_a];
|
||||
self.write_block(card, &block_list, &block_data)
|
||||
let mut mac_a = heapless::Vec::<u8, 16>::new();
|
||||
mac_a.extend(mac);
|
||||
mac_a.extend(wcnt);
|
||||
|
||||
let block_list = [block_code.into(), FelicaLiteSBlock::MACA as u16];
|
||||
let block_data = [*data, mac_a.into_array().unwrap()];
|
||||
self.write_block(card, block_list, &block_data)
|
||||
}
|
||||
|
||||
/// Complete External Authentication (manual §5.4.2, Figure 5-10).
|
||||
@@ -110,10 +112,10 @@ where
|
||||
pub fn read_block<const U: usize>(
|
||||
&mut self,
|
||||
card: &CardSession,
|
||||
list: &[impl AsBlock; U],
|
||||
list: [impl IntoBlockCode; U],
|
||||
data: &mut [[u8; 16]; U],
|
||||
) -> Result<(), crate::Error<B::TransportError>> {
|
||||
self.felica_read_without_encryption(card, &[FelicaLiteSServiceCode::Read], list, data)
|
||||
self.felica_read_without_encryption(card, [FelicaLiteSServiceCode::Read], list, data)
|
||||
}
|
||||
|
||||
/// write a raw block
|
||||
@@ -122,9 +124,9 @@ where
|
||||
pub fn write_block<const U: usize>(
|
||||
&mut self,
|
||||
card: &CardSession,
|
||||
list: &[impl AsBlock; U],
|
||||
list: [impl IntoBlockCode; U],
|
||||
data: &[[u8; 16]; U],
|
||||
) -> Result<(), crate::Error<B::TransportError>> {
|
||||
self.felica_write_without_encryption(card, &[FelicaLiteSServiceCode::Write], list, data)
|
||||
self.felica_write_without_encryption(card, [FelicaLiteSServiceCode::Write], list, data)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -156,11 +156,11 @@ where
|
||||
/// Send a FeliCa "Read Without Encryption" command.
|
||||
///
|
||||
/// Note: the number of blocks is limited by the 64-byte response buffer.
|
||||
pub(crate) fn felica_read_without_encryption<const U: usize>(
|
||||
pub(crate) fn felica_read_without_encryption<const U: usize, const S: usize>(
|
||||
&mut self,
|
||||
card: &CardSession,
|
||||
service_code_list: &[impl AsServiceCode],
|
||||
block_list: &[impl AsBlock; U],
|
||||
service_code_list: [impl IntoServiceCode; S],
|
||||
block_list: [impl IntoBlockCode; U],
|
||||
block_data: &mut [[u8; 16]; U],
|
||||
) -> Result<(), Error<B::TransportError>> {
|
||||
const COMMAND_SIZE: usize = 1 // command code (0x06)
|
||||
@@ -177,8 +177,7 @@ where
|
||||
+ 16 * FELICA_READ_MAX_BLOCK_NUM; // block data
|
||||
|
||||
// validate
|
||||
let num_service = service_code_list.len();
|
||||
if num_service > FELICA_READ_MAX_SERVICE_NUM || U > FELICA_READ_MAX_BLOCK_NUM {
|
||||
if S > FELICA_READ_MAX_SERVICE_NUM || U > FELICA_READ_MAX_BLOCK_NUM {
|
||||
return Err(Error::InvalidParam);
|
||||
}
|
||||
|
||||
@@ -187,15 +186,17 @@ where
|
||||
cmd.push(FelicaCommand::ReadWithoutEncryption.into_bits())
|
||||
.unwrap();
|
||||
cmd.extend_from_slice(&card.idm.into_bytes()).unwrap();
|
||||
cmd.push(num_service as u8).unwrap();
|
||||
cmd.push(S as u8).unwrap();
|
||||
for sc in service_code_list {
|
||||
let sc: [u8; 2] = sc.as_service_code().to_le_bytes();
|
||||
let sc = sc.into();
|
||||
let sc: [u8; 2] = sc.to_le_bytes();
|
||||
cmd.extend_from_slice(&sc).unwrap();
|
||||
}
|
||||
cmd.push(U as u8).unwrap();
|
||||
for bl in block_list {
|
||||
let bl: [u8; 2] = bl.as_block().to_be_bytes();
|
||||
cmd.extend_from_slice(&bl).unwrap();
|
||||
for block in block_list {
|
||||
let block: u16 = block.into();
|
||||
let block: [u8; 2] = block.to_be_bytes();
|
||||
cmd.extend_from_slice(&block).unwrap();
|
||||
}
|
||||
|
||||
// response
|
||||
@@ -219,11 +220,11 @@ where
|
||||
}
|
||||
|
||||
/// Send a FeliCa "Write Without Encryption" command.
|
||||
pub(crate) fn felica_write_without_encryption<const U: usize>(
|
||||
pub(crate) fn felica_write_without_encryption<const U: usize, const S: usize>(
|
||||
&mut self,
|
||||
card: &CardSession,
|
||||
service_code_list: &[impl AsServiceCode],
|
||||
block_list: &[impl AsBlock; U],
|
||||
service_code_list: [impl IntoServiceCode; S],
|
||||
block_list: [impl IntoBlockCode; U],
|
||||
block_data: &[[u8; 16]; U],
|
||||
) -> Result<(), Error<B::TransportError>> {
|
||||
const COMMAND_SIZE: usize = 1 // command code
|
||||
@@ -239,8 +240,7 @@ where
|
||||
+ 1; // status[1]
|
||||
|
||||
// validate
|
||||
let num_service = service_code_list.len();
|
||||
if num_service > FELICA_WRITE_MAX_SERVICE_NUM || U > FELICA_WRITE_MAX_BLOCK_NUM {
|
||||
if S > FELICA_WRITE_MAX_SERVICE_NUM || U > FELICA_WRITE_MAX_BLOCK_NUM {
|
||||
return Err(Error::InvalidParam);
|
||||
}
|
||||
|
||||
@@ -248,14 +248,16 @@ where
|
||||
let mut cmd = heapless::Vec::<u8, COMMAND_SIZE>::new();
|
||||
cmd.push(FelicaCommand::WriteWithEncryption as u8).unwrap();
|
||||
cmd.extend_from_slice(&card.idm.into_bytes()).unwrap();
|
||||
cmd.push(num_service as u8).unwrap();
|
||||
cmd.push(S as u8).unwrap();
|
||||
for sc in service_code_list {
|
||||
let sc = sc.as_service_code().to_le_bytes();
|
||||
let sc: u16 = sc.into();
|
||||
let sc = sc.to_le_bytes();
|
||||
cmd.extend_from_slice(&sc).unwrap();
|
||||
}
|
||||
cmd.push(U as u8).unwrap();
|
||||
for block in block_list {
|
||||
let block = block.as_block().to_be_bytes();
|
||||
let block: u16 = block.into();
|
||||
let block = block.to_be_bytes();
|
||||
cmd.extend_from_slice(&block).unwrap();
|
||||
}
|
||||
for block in block_data.iter().take(U) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use crate::types::felica::constants::FELICA_READ_MAX_BLOCK_NUM;
|
||||
use crate::types::felica::AsBlock;
|
||||
use crate::types::felica::IntoBlockCode;
|
||||
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
@@ -9,7 +9,7 @@ pub struct MacInput<const N: usize> {
|
||||
}
|
||||
|
||||
impl<const N: usize> MacInput<N> {
|
||||
pub fn new(block_data: &[[u8; 16]; N], blocks_list: &[impl AsBlock; N]) -> MacInput<N> {
|
||||
pub fn new(block_data: &[[u8; 16]; N], blocks_list: [impl IntoBlockCode; N]) -> MacInput<N> {
|
||||
if N > FELICA_READ_MAX_BLOCK_NUM {
|
||||
panic!("too many blocks");
|
||||
}
|
||||
@@ -17,8 +17,9 @@ impl<const N: usize> MacInput<N> {
|
||||
panic!("block should have at least 2 blocks");
|
||||
}
|
||||
let mut block_nums = [0u8; N];
|
||||
for (i, block) in blocks_list.iter().enumerate() {
|
||||
block_nums[i] = block.as_block() as u8;
|
||||
for (i, block) in blocks_list.into_iter().enumerate() {
|
||||
let block: u16 = block.into();
|
||||
block_nums[i] = block as u8;
|
||||
}
|
||||
Self {
|
||||
block_data: *block_data,
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
pub mod auth;
|
||||
pub mod config;
|
||||
|
||||
use super::AsBlock;
|
||||
use super::AsServiceCode;
|
||||
use super::IntoBlockCode;
|
||||
use super::IntoServiceCode;
|
||||
use bitfields::bitflag;
|
||||
|
||||
/// Service Code
|
||||
@@ -20,16 +20,20 @@ pub enum ServiceCode {
|
||||
Write = 0x0009,
|
||||
}
|
||||
|
||||
impl AsServiceCode for ServiceCode {
|
||||
fn as_service_code(&self) -> u16 {
|
||||
*self as u16
|
||||
}
|
||||
|
||||
fn from_service_code(val: u16) -> Self {
|
||||
Self::from_bits(val)
|
||||
impl From<u16> for ServiceCode {
|
||||
fn from(value: u16) -> Self {
|
||||
Self::from_bits(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<u16> for ServiceCode {
|
||||
fn into(self) -> u16 {
|
||||
self as u16
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoServiceCode for ServiceCode {}
|
||||
|
||||
/// FeliCa Lite system block numbers.
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
@@ -73,8 +77,16 @@ pub enum Block {
|
||||
STATE = 0x8092,
|
||||
}
|
||||
|
||||
impl AsBlock for Block {
|
||||
fn as_block(&self) -> u16 {
|
||||
*self as u16
|
||||
impl From<u16> for Block {
|
||||
fn from(value: u16) -> Self {
|
||||
Self::from_bits(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<u16> for Block {
|
||||
fn into(self) -> u16 {
|
||||
self as u16
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoBlockCode for Block {}
|
||||
|
||||
@@ -15,33 +15,16 @@ pub use polling::PollingConfig as FelicaPollingConfig;
|
||||
pub use polling::PollingRequestCode as FelicaPollingRequestCode;
|
||||
pub use polling::PollingResponse as FelicaPollingResponse;
|
||||
|
||||
pub trait AsServiceCode {
|
||||
fn as_service_code(&self) -> u16;
|
||||
fn from_service_code(val: u16) -> Self;
|
||||
}
|
||||
|
||||
pub trait AsBlock {
|
||||
fn as_block(&self) -> u16;
|
||||
}
|
||||
|
||||
impl AsBlock for u16 {
|
||||
fn as_block(&self) -> u16 {
|
||||
*self
|
||||
}
|
||||
}
|
||||
|
||||
impl AsServiceCode for u16 {
|
||||
fn as_service_code(&self) -> u16 {
|
||||
*self
|
||||
}
|
||||
|
||||
fn from_service_code(val: u16) -> Self {
|
||||
val
|
||||
}
|
||||
}
|
||||
|
||||
use bitfields::bitflag;
|
||||
|
||||
pub trait IntoServiceCode: From<u16> + Into<u16> + Clone {}
|
||||
|
||||
pub trait IntoBlockCode: From<u16> + Into<u16> + Clone {}
|
||||
|
||||
impl IntoBlockCode for u16 {}
|
||||
|
||||
impl IntoServiceCode for u16 {}
|
||||
|
||||
/// NDEF URI record identifier codes
|
||||
/// (see NFC Forum "URI Record Type Definition").
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
|
||||
Reference in New Issue
Block a user