Refactor trait

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