implement MAC auth for felica

This commit is contained in:
2026-08-28 21:56:37 +08:00
parent f523b7d394
commit 494f4b92eb
20 changed files with 562 additions and 233 deletions
+52 -24
View File
@@ -1,22 +1,20 @@
use crate::types::{LoraPublisher, SharedI2c};
use core::sync::atomic::{AtomicPtr, Ordering};
use defmt::Debug2Format;
use embassy_sync::once_lock::OnceLock;
use embassy_time::{Delay, Timer};
use esp_hal::gpio;
use esp_hal::rng::Trng;
use lorawan_device::RngCore;
use pn532::felica::{FelicaBlock, FelicaPollingRequestCode, FelicaServiceCode};
use pn532::felica::types::{FelicaPollingRequestCode};
use pn532::{BaudRate, Pn532};
static CARD_KEY: OnceLock<heapless::Vec<u8, 16>> = OnceLock::new();
static CARD_KEY: OnceLock<[u8; 16]> = OnceLock::new();
const CARD_KEY_STR: &str = env!("CARD_KEY");
fn get_card_key() -> &'static heapless::Vec<u8, 16> {
fn get_card_key() -> &'static [u8; 16] {
CARD_KEY.get_or_init(|| {
let hex_string = env!("CARD_KEY");
let mut buffer = [0u8; 16];
hex::decode_to_slice(hex_string, &mut buffer).unwrap();
heapless::Vec::from_array(buffer)
hex::decode_to_slice(CARD_KEY_STR, &mut buffer).unwrap();
buffer
})
}
@@ -41,19 +39,17 @@ impl<'a> CardReader<'a> {
#[embassy_executor::task]
pub async fn start_card_reader(
mut card_reader: CardReader<'static>,
mut publisher: LoraPublisher<'static>,
_publisher: LoraPublisher<'static>,
mut trng: Trng
) -> () {
let card_key = get_card_key();
let mut rc = [0u8; 16];
trng.fill_bytes(&mut rc);
defmt::trace!("card_key: {}", hex::encode_upper(card_key));
loop {
Timer::after_millis(50).await;
let Some(response) = (match card_reader.driver.felica_polling(
None,
BaudRate::Felica424kbps,
BaudRate::Felica212kbps,
FelicaPollingRequestCode::SystemCode,
core::time::Duration::from_secs(1),
) {
@@ -67,25 +63,57 @@ pub async fn start_card_reader(
continue;
};
defmt::info!("Polling card: {}", Debug2Format(&response));
// if let Err(e) = card_reader.driver.felica_write_without_encryption(
// &response.idm, &response.pmm,
// &[FelicaLiteSServiceCode::Write],
// &[FelicaLiteSBlock::CK],
// &[*card_key]
// ) {
// defmt::error!("card_reader write ck error: {}", e);
// continue;
// }
let mut data = [[0u8; 16]; 3];
// user blocks 0x0000..0x000D via the raw u16 AsBlock impl; a single read
// is capped at 3 blocks by the 64-byte packet buffer (response = 14 + 16n).
let blocks: [u16; 3] = [0x0000, 0x0001, 0x0002];
match card_reader.driver.felica_read_without_encryption(
let (rc1, rc2) = match card_reader.driver.set_random_challenge(
&response.idm,
&response.pmm,
&[FelicaServiceCode::Read],
&blocks,
&mut data,
&mut trng
) {
Ok(_) => {},
Ok(rc) => rc,
Err(e) => {
defmt::error!("unable to read blocks: {}", e);
defmt::error!("card_reader rc error: {}", e);
continue;
}
}
defmt::debug!("Blocks: {:?}", data);
};
defmt::info!("RC: rc1: {:02X}, rc2: {:02X}", rc1, rc2);
let mut rc = [0u8; 16];
rc[..8].copy_from_slice(&rc1);
rc[8..].copy_from_slice(&rc2);
let (sk1, sk2) = match card_reader.driver.get_session_keys(&rc, card_key) {
Ok(v) => v,
Err(e) => {
defmt::error!("card_reader sk error: {}", e);
continue;
}
};
defmt::info!("sk1: {:02X} sk2: {:02X}", sk1, sk2);
let mac = match card_reader.driver.check_mac(
&response.idm,
&response.pmm,
&sk1,
&sk2,
&rc1
) {
Ok(v) => v,
Err(e) => {
defmt::error!("card_driver mac check error: {}", e);
continue;
}
};
defmt::info!("mac check: {}", mac);
match card_reader.driver.release() {
Ok(_) => {},