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]);
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])
}
}
+25 -23
View File
@@ -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)
}
}
+20 -18
View File
@@ -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,
+24 -12
View File
@@ -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 {}
+8 -25
View File
@@ -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)]