From d2ef3853e5191eb6497872004c4e7b315fb15af5 Mon Sep 17 00:00:00 2001 From: Mirna <29131616+MirnaMuhammad98@users.noreply.github.com> Date: Fri, 16 Oct 2020 09:29:23 +0200 Subject: [PATCH 1/5] Delete nfc.rs This branch is for the example application. --- third_party/libtock-drivers/src/nfc.rs | 117 ------------------------- 1 file changed, 117 deletions(-) delete mode 100644 third_party/libtock-drivers/src/nfc.rs diff --git a/third_party/libtock-drivers/src/nfc.rs b/third_party/libtock-drivers/src/nfc.rs deleted file mode 100644 index 977b49b..0000000 --- a/third_party/libtock-drivers/src/nfc.rs +++ /dev/null @@ -1,117 +0,0 @@ -use crate::util; -use core::cell::Cell; -use libtock_core::{callback, syscalls}; - -const DRIVER_NUMBER: usize = 0x30003; - -mod command_nr { - pub const TRANSMIT: usize = 1; - pub const RECEIVE: usize = 2; - pub const EMULATE: usize = 3; - pub const CONFIGURE: usize = 4; -} - -mod subscribe_nr { - pub const TRANSMIT: usize = 1; - pub const RECEIVE: usize = 2; - pub const SELECT: usize = 3; -} - -mod allow_nr { - pub const TRANSMIT: usize = 1; - pub const RECEIVE: usize = 2; -} - -pub fn enable_emulation() { - emulate(true); -} - -pub fn disable_emulation() { - emulate(false); -} - -pub fn emulate(enabled: bool) -> bool { - let result_code = syscalls::command(DRIVER_NUMBER, command_nr::EMULATE, enabled as usize, 0); - if result_code.is_err() { - return false; - } - - true -} - -pub fn selected() -> bool { - let is_selected = Cell::new(false); - let mut is_selected_alarm = || is_selected.set(true); - let subscription = syscalls::subscribe::( - DRIVER_NUMBER, - subscribe_nr::SELECT, - &mut is_selected_alarm, - ); - if subscription.is_err() { - return false; - } - - util::yieldk_for(|| is_selected.get()); - true -} - -pub fn configure(tag_type: u8) -> bool { - let result_code = syscalls::command(DRIVER_NUMBER, command_nr::CONFIGURE, tag_type as usize, 0); - if result_code.is_err() { - return false; - } - - true -} - -pub fn receive(buf: &mut [u8]) -> bool { - let result = syscalls::allow(DRIVER_NUMBER, allow_nr::RECEIVE, buf); - if result.is_err() { - return false; - } - - let done = Cell::new(false); - let mut alarm = || done.set(true); - let subscription = syscalls::subscribe::( - DRIVER_NUMBER, - subscribe_nr::RECEIVE, - &mut alarm, - ); - if subscription.is_err() { - return false; - } - - let result_code = syscalls::command(DRIVER_NUMBER, command_nr::RECEIVE, 0, 0); - if result_code.is_err() { - return false; - } - - util::yieldk_for(|| done.get()); - true -} - -pub fn transmit(buf: &mut [u8]) -> bool { - let result = syscalls::allow(DRIVER_NUMBER, allow_nr::TRANSMIT, buf); - if result.is_err() { - return false; - } - - let done = Cell::new(false); - let mut alarm = || done.set(true); - let subscription = syscalls::subscribe::( - DRIVER_NUMBER, - subscribe_nr::TRANSMIT, - &mut alarm, - ); - if subscription.is_err() { - return false; - } - - let result_code = syscalls::command(DRIVER_NUMBER, command_nr::TRANSMIT, 0, 0); - if result_code.is_err() { - return false; - } - - util::yieldk_for(|| done.get()); - true -} From c520095ab7c2ebaf6885a7e68ed63575b5317eaa Mon Sep 17 00:00:00 2001 From: Mirna <29131616+MirnaMuhammad98@users.noreply.github.com> Date: Fri, 16 Oct 2020 09:29:44 +0200 Subject: [PATCH 2/5] Update lib.rs This branch is for the example application. --- third_party/libtock-drivers/src/lib.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/third_party/libtock-drivers/src/lib.rs b/third_party/libtock-drivers/src/lib.rs index ec8a2d7..bf62d05 100644 --- a/third_party/libtock-drivers/src/lib.rs +++ b/third_party/libtock-drivers/src/lib.rs @@ -3,7 +3,6 @@ pub mod buttons; pub mod console; pub mod led; -pub mod nfc; pub mod result; pub mod rng; pub mod timer; From 16870d52c55c3e55344c2d4e2300157209c9a74f Mon Sep 17 00:00:00 2001 From: Mirna Date: Thu, 22 Oct 2020 12:15:24 +0200 Subject: [PATCH 3/5] Update the application logic --- examples/nfct_test.rs | 131 ++++++++++++++++++++++++++++++------------ 1 file changed, 95 insertions(+), 36 deletions(-) diff --git a/examples/nfct_test.rs b/examples/nfct_test.rs index 42176cd..f7ae3a4 100644 --- a/examples/nfct_test.rs +++ b/examples/nfct_test.rs @@ -6,6 +6,7 @@ extern crate lang_items; use core::fmt::Write; use libtock_drivers::console::Console; use libtock_drivers::nfc::NfcTag; +use libtock_drivers::nfc::RecvOp; #[allow(dead_code)] /// Helper function to write a slice into a fixed @@ -16,52 +17,110 @@ fn write_tx_buffer(buf: &mut [u8], slice: &[u8]) { } } +#[derive(PartialEq, Eq)] +enum State { + Enabled, + Disabled, +} + fn main() { let mut console = Console::new(); writeln!(console, "****************************************").unwrap(); writeln!(console, "nfct_test application is installed").unwrap(); - // 1. Configure Type 4 tag - if NfcTag::configure(4) { - writeln!(console, " -- TAG CONFIGURED").unwrap(); - } - // 2. Subscribe to a SELECTED CALLBACK - if NfcTag::selected() { - writeln!(console, " -- TAG SELECTED").unwrap(); - // 0xfffff results in 1048575 / 13.56e6 = 77ms - NfcTag::set_framedelaymax(0xfffff); - } - /* - [_.] TODO: Enable Tag emulation (currently the tag is always activated) - needs field detection support in the driver level. - */ - let mut rx_buf = [0; 64]; - let mut unknown_cmd_cntr = 0; + let mut state = State::Disabled; + let mut state_change_cntr = 0; loop { - NfcTag::receive(&mut rx_buf); - match rx_buf[0] { - 0xe0 /* RATS */=> { - let mut answer_to_select = [0x05, 0x78, 0x80, 0xB1, 0x00]; - let amount = answer_to_select.len(); - NfcTag::transmit(&mut answer_to_select, amount); + match state { + State::Enabled => { + let mut rx_buf = [0; 256]; + loop { + match NfcTag::receive(&mut rx_buf) { + Ok(RecvOp { + recv_amount: amount, + .. + }) => match amount { + 1 => writeln!(console, " -- RX Packet: {:02x?}", rx_buf[0],).unwrap(), + 2 => writeln!( + console, + " -- RX Packet: {:02x?} {:02x?}", + rx_buf[0], rx_buf[1], + ) + .unwrap(), + 3 => writeln!( + console, + " -- RX Packet: {:02x?} {:02x?} {:02x?}", + rx_buf[0], rx_buf[1], rx_buf[2], + ) + .unwrap(), + _ => writeln!( + console, + " -- RX Packet: {:02x?} {:02x?} {:02x?} {:02x?}", + rx_buf[0], rx_buf[1], rx_buf[2], rx_buf[3], + ) + .unwrap(), + }, + Err(_) => writeln!(console, " -- rx error!").unwrap(), + } + + match rx_buf[0] { + 0xe0 /* RATS */=> { + let mut answer_to_select = [0x05, 0x78, 0x80, 0xB1, 0x00]; + let amount = answer_to_select.len(); + match NfcTag::transmit(&mut answer_to_select, amount) { + Ok(_) => (), + Err(_) => writeln!(console, " -- tx error!").unwrap(), + } + } + 0xc2 /* DESELECT */ => { + // Ignore the request + let mut command_error = [0x6A, 0x81]; + let amount = command_error.len(); + match NfcTag::transmit(&mut command_error, amount) { + Ok(_) => (), + Err(_) => writeln!(console, " -- tx error!").unwrap(), + } + } + 0x02 | 0x03 /* APDU Prefix */ => { + let mut reply = [rx_buf[0], 0x90, 0x00]; + let amount = reply.len(); + match NfcTag::transmit(&mut reply, amount) { + Ok(_) => (), + Err(_) => writeln!(console, " -- tx error!").unwrap(), + } + } + 0x52 | 0x50 /* WUPA | Halt */ => { + if NfcTag::disable_emulation() { + writeln!(console, " -- TAG DISABLED").unwrap(); + } + state = State::Disabled; + break; + } + _ => { + } + } + } } - 0xc2 /* DESELECT */ => { - // Ignore the request - let mut command_error = [0x6A, 0x81]; - let amount = command_error.len(); - NfcTag::transmit(&mut command_error, amount); - } - 0x02 | 0x03 /* APDU Prefix */ => { - let mut reply = [rx_buf[0], 0x90, 0x00]; - let amount = reply.len(); - NfcTag::transmit(&mut reply, amount); - } - _ => { - unknown_cmd_cntr += 1; + State::Disabled => { + if NfcTag::enable_emulation() { + writeln!(console, " -- TAG ENABLED").unwrap(); + } + // 1. Configure Type 4 tag + if NfcTag::configure(4) { + writeln!(console, " -- TAG CONFIGURED").unwrap(); + } + // 2. Subscribe to a SELECTED CALLBACK + if NfcTag::selected() { + writeln!(console, " -- TAG SELECTED").unwrap(); + // 0xfffff results in 1048575 / 13.56e6 = 77ms + NfcTag::set_framedelaymax(0xfffff); + } + state = State::Enabled; } } - if unknown_cmd_cntr > 50 { + state_change_cntr += 1; + if state_change_cntr > 10 && state == State::Disabled { break; } } From 69194f3960c6b44ef881fa301b11511725f9da0e Mon Sep 17 00:00:00 2001 From: Mirna Date: Thu, 29 Oct 2020 23:07:23 +0200 Subject: [PATCH 4/5] Updates in the application logic --- examples/nfct_test.rs | 102 ++++++++++++++++++++++++------------------ 1 file changed, 58 insertions(+), 44 deletions(-) diff --git a/examples/nfct_test.rs b/examples/nfct_test.rs index f7ae3a4..82a1625 100644 --- a/examples/nfct_test.rs +++ b/examples/nfct_test.rs @@ -1,23 +1,44 @@ #![no_std] +#![allow(unused_imports)] extern crate alloc; extern crate lang_items; +extern crate libtock_drivers; use core::fmt::Write; +use libtock_core::result::CommandError; use libtock_drivers::console::Console; +#[cfg(feature = "with_nfc")] use libtock_drivers::nfc::NfcTag; +#[cfg(feature = "with_nfc")] use libtock_drivers::nfc::RecvOp; +use libtock_drivers::result::TockError; #[allow(dead_code)] -/// Helper function to write a slice into a fixed -/// length transmission buffer. +/// Helper function to write a slice into a transmission buffer. fn write_tx_buffer(buf: &mut [u8], slice: &[u8]) { for (i, &byte) in slice.iter().enumerate() { buf[i] = byte; } } +#[allow(dead_code)] +/// Helper function to write on console the received packet. +fn print_rx_buffer(buf: &mut [u8], amount: usize) { + if amount < 1 || amount > buf.len() { + return; + } + let mut console = Console::new(); + write!(console, " -- RX Packet:").unwrap(); + for byte in buf.iter().take(amount - 1) { + write!(console, " {:02x?}", byte).unwrap(); + } + writeln!(console, " {:02x?}", buf[amount - 1]).unwrap(); +} + +#[cfg(feature = "with_nfc")] #[derive(PartialEq, Eq)] +/// enum for reserving the NFC tag state. enum State { Enabled, Disabled, @@ -29,8 +50,11 @@ fn main() { writeln!(console, "****************************************").unwrap(); writeln!(console, "nfct_test application is installed").unwrap(); + #[cfg(feature = "with_nfc")] let mut state = State::Disabled; + #[cfg(feature = "with_nfc")] let mut state_change_cntr = 0; + #[cfg(feature = "with_nfc")] loop { match state { State::Enabled => { @@ -40,28 +64,15 @@ fn main() { Ok(RecvOp { recv_amount: amount, .. - }) => match amount { - 1 => writeln!(console, " -- RX Packet: {:02x?}", rx_buf[0],).unwrap(), - 2 => writeln!( - console, - " -- RX Packet: {:02x?} {:02x?}", - rx_buf[0], rx_buf[1], - ) - .unwrap(), - 3 => writeln!( - console, - " -- RX Packet: {:02x?} {:02x?} {:02x?}", - rx_buf[0], rx_buf[1], rx_buf[2], - ) - .unwrap(), - _ => writeln!( - console, - " -- RX Packet: {:02x?} {:02x?} {:02x?} {:02x?}", - rx_buf[0], rx_buf[1], rx_buf[2], rx_buf[3], - ) - .unwrap(), - }, - Err(_) => writeln!(console, " -- rx error!").unwrap(), + }) => print_rx_buffer(&mut rx_buf, amount), + Err(TockError::Command(CommandError { + return_code: -4, /* EOFF: Not Ready */ + .. + })) => (), + Err(TockError::Command(CommandError { + return_code: value, .. + })) => writeln!(console, " -- Err({})!", value).unwrap(), + Err(_) => writeln!(console, " -- RX ERROR").unwrap(), } match rx_buf[0] { @@ -83,11 +94,24 @@ fn main() { } } 0x02 | 0x03 /* APDU Prefix */ => { - let mut reply = [rx_buf[0], 0x90, 0x00]; - let amount = reply.len(); - match NfcTag::transmit(&mut reply, amount) { - Ok(_) => (), - Err(_) => writeln!(console, " -- tx error!").unwrap(), + // If the received packet is applet selection command (FIDO 2) + if rx_buf[1] == 0x00 && rx_buf[2] == 0xa4 && rx_buf[3] == 0x04 { + // Vesion: "U2F_V2" + // let mut reply = [rx_buf[0], 0x55, 0x32, 0x46, 0x5f, 0x56, 0x32, 0x90, 0x00,]; + // Vesion: "FIDO_2_0" + let mut reply = [rx_buf[0], 0x46, 0x49, 0x44, 0x4f, 0x5f, 0x32, 0x5f, 0x30, 0x90, 0x00,]; + let amount = reply.len(); + match NfcTag::transmit(&mut reply, amount) { + Ok(_) => (), + Err(_) => writeln!(console, " -- tx error!").unwrap(), + } + } else { + let mut reply = [rx_buf[0], 0x90, 0x00]; + let amount = reply.len(); + match NfcTag::transmit(&mut reply, amount) { + Ok(_) => (), + Err(_) => writeln!(console, " -- tx error!").unwrap(), + } } } 0x52 | 0x50 /* WUPA | Halt */ => { @@ -97,30 +121,20 @@ fn main() { state = State::Disabled; break; } - _ => { - } + _ => (), } } } State::Disabled => { - if NfcTag::enable_emulation() { - writeln!(console, " -- TAG ENABLED").unwrap(); - } - // 1. Configure Type 4 tag + NfcTag::enable_emulation(); + // Configure Type 4 tag if NfcTag::configure(4) { - writeln!(console, " -- TAG CONFIGURED").unwrap(); + state = State::Enabled; } - // 2. Subscribe to a SELECTED CALLBACK - if NfcTag::selected() { - writeln!(console, " -- TAG SELECTED").unwrap(); - // 0xfffff results in 1048575 / 13.56e6 = 77ms - NfcTag::set_framedelaymax(0xfffff); - } - state = State::Enabled; } } state_change_cntr += 1; - if state_change_cntr > 10 && state == State::Disabled { + if state_change_cntr > 100 && state == State::Disabled { break; } } From dd814b8ded7cbe8fa2bf00d8e8d970974feb5cd4 Mon Sep 17 00:00:00 2001 From: Mirna Date: Mon, 2 Nov 2020 10:49:00 +0200 Subject: [PATCH 5/5] Remove duplicate code --- examples/nfct_test.rs | 40 +++++++++++++++++----------------------- 1 file changed, 17 insertions(+), 23 deletions(-) diff --git a/examples/nfct_test.rs b/examples/nfct_test.rs index 82a1625..90d2dfa 100644 --- a/examples/nfct_test.rs +++ b/examples/nfct_test.rs @@ -36,6 +36,16 @@ fn print_rx_buffer(buf: &mut [u8], amount: usize) { writeln!(console, " {:02x?}", buf[amount - 1]).unwrap(); } +#[allow(dead_code)] +/// Helper function to write on console the received packet. +fn transmit_slice(buf: &mut [u8] { + let amount = buf.len(); + match NfcTag::transmit(&mut buf, amount) { + Ok(_) => (), + Err(_) => writeln!(console, " -- tx error!").unwrap(), + } +} + #[cfg(feature = "with_nfc")] #[derive(PartialEq, Eq)] /// enum for reserving the NFC tag state. @@ -72,46 +82,30 @@ fn main() { Err(TockError::Command(CommandError { return_code: value, .. })) => writeln!(console, " -- Err({})!", value).unwrap(), - Err(_) => writeln!(console, " -- RX ERROR").unwrap(), + Err(_) => writeln!(console, " -- RX Err").unwrap(), } match rx_buf[0] { 0xe0 /* RATS */=> { let mut answer_to_select = [0x05, 0x78, 0x80, 0xB1, 0x00]; - let amount = answer_to_select.len(); - match NfcTag::transmit(&mut answer_to_select, amount) { - Ok(_) => (), - Err(_) => writeln!(console, " -- tx error!").unwrap(), - } + transmit_slice(&mut answer_to_select); } 0xc2 /* DESELECT */ => { // Ignore the request let mut command_error = [0x6A, 0x81]; - let amount = command_error.len(); - match NfcTag::transmit(&mut command_error, amount) { - Ok(_) => (), - Err(_) => writeln!(console, " -- tx error!").unwrap(), - } + transmit_slice(&mut command_error); } 0x02 | 0x03 /* APDU Prefix */ => { // If the received packet is applet selection command (FIDO 2) if rx_buf[1] == 0x00 && rx_buf[2] == 0xa4 && rx_buf[3] == 0x04 { - // Vesion: "U2F_V2" + /// Vesion: "U2F_V2" // let mut reply = [rx_buf[0], 0x55, 0x32, 0x46, 0x5f, 0x56, 0x32, 0x90, 0x00,]; - // Vesion: "FIDO_2_0" + /// Vesion: "FIDO_2_0" let mut reply = [rx_buf[0], 0x46, 0x49, 0x44, 0x4f, 0x5f, 0x32, 0x5f, 0x30, 0x90, 0x00,]; - let amount = reply.len(); - match NfcTag::transmit(&mut reply, amount) { - Ok(_) => (), - Err(_) => writeln!(console, " -- tx error!").unwrap(), - } + transmit_slice(&mut reply); } else { let mut reply = [rx_buf[0], 0x90, 0x00]; - let amount = reply.len(); - match NfcTag::transmit(&mut reply, amount) { - Ok(_) => (), - Err(_) => writeln!(console, " -- tx error!").unwrap(), - } + transmit_slice(&mut reply); } } 0x52 | 0x50 /* WUPA | Halt */ => {