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 01/13] 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 02/13] 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 03/13] 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 04/13] 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 05/13] 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 */ => { From f9705d7c26ac4dfe507a0f0703cfb083a8d7dd3a Mon Sep 17 00:00:00 2001 From: Mirna Date: Mon, 2 Nov 2020 11:13:58 +0200 Subject: [PATCH 06/13] example app --- deploy.py | 7 +++ examples/nfct_test.rs | 136 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 143 insertions(+) create mode 100644 examples/nfct_test.rs diff --git a/deploy.py b/deploy.py index 358355d..e1ec38f 100755 --- a/deploy.py +++ b/deploy.py @@ -928,6 +928,13 @@ if __name__ == "__main__": const="console_test", help=("Compiles and installs the console_test example that tests the " "console driver with messages of various lengths.")) + apps_group.add_argument( + "--nfct_test", + dest="application", + action="store_const", + const="nfct_test", + help=("Compiles and installs the nfct_test example that tests the " + "NFC driver.")) main_parser.set_defaults(features=["with_ctap1"]) diff --git a/examples/nfct_test.rs b/examples/nfct_test.rs new file mode 100644 index 0000000..90d2dfa --- /dev/null +++ b/examples/nfct_test.rs @@ -0,0 +1,136 @@ +#![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 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(); +} + +#[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. +enum State { + Enabled, + Disabled, +} + +fn main() { + let mut console = Console::new(); + + 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 => { + let mut rx_buf = [0; 256]; + loop { + match NfcTag::receive(&mut rx_buf) { + Ok(RecvOp { + recv_amount: amount, + .. + }) => 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 Err").unwrap(), + } + + match rx_buf[0] { + 0xe0 /* RATS */=> { + let mut answer_to_select = [0x05, 0x78, 0x80, 0xB1, 0x00]; + transmit_slice(&mut answer_to_select); + } + 0xc2 /* DESELECT */ => { + // Ignore the request + let mut command_error = [0x6A, 0x81]; + 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" + // 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,]; + transmit_slice(&mut reply); + } else { + let mut reply = [rx_buf[0], 0x90, 0x00]; + transmit_slice(&mut reply); + } + } + 0x52 | 0x50 /* WUPA | Halt */ => { + if NfcTag::disable_emulation() { + writeln!(console, " -- TAG DISABLED").unwrap(); + } + state = State::Disabled; + break; + } + _ => (), + } + } + } + State::Disabled => { + NfcTag::enable_emulation(); + // Configure Type 4 tag + if NfcTag::configure(4) { + state = State::Enabled; + } + } + } + state_change_cntr += 1; + if state_change_cntr > 100 && state == State::Disabled { + break; + } + } + writeln!(console, "****************************************").unwrap(); +} From eb3187680701dba632759160407dbce3c55bc232 Mon Sep 17 00:00:00 2001 From: Mirna Date: Wed, 4 Nov 2020 17:48:50 +0200 Subject: [PATCH 07/13] Update to calculate elapsed time for transmission --- examples/nfct_test.rs | 94 +++++++++++++++++++++++++++++-------------- 1 file changed, 64 insertions(+), 30 deletions(-) diff --git a/examples/nfct_test.rs b/examples/nfct_test.rs index 90d2dfa..9da0312 100644 --- a/examples/nfct_test.rs +++ b/examples/nfct_test.rs @@ -1,5 +1,4 @@ #![no_std] -#![allow(unused_imports)] extern crate alloc; extern crate lang_items; @@ -8,19 +7,13 @@ 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::FlexUnwrap; use libtock_drivers::result::TockError; - -#[allow(dead_code)] -/// 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; - } -} +use libtock_drivers::timer; +use libtock_drivers::timer::Timer; +use libtock_drivers::timer::Timestamp; #[allow(dead_code)] /// Helper function to write on console the received packet. @@ -29,24 +22,37 @@ fn print_rx_buffer(buf: &mut [u8], amount: usize) { return; } let mut console = Console::new(); - write!(console, " -- RX Packet:").unwrap(); + write!(console, "RX:").unwrap(); for byte in buf.iter().take(amount - 1) { write!(console, " {:02x?}", byte).unwrap(); } writeln!(console, " {:02x?}", buf[amount - 1]).unwrap(); + console.flush(); } #[allow(dead_code)] -/// Helper function to write on console the received packet. -fn transmit_slice(buf: &mut [u8] { +/// Function to identify the time elapsed for a transmission request. +fn bench_transmit(console: &mut Console, timer: &Timer, title: &str, mut buf: &mut [u8]) { let amount = buf.len(); + let start = Timestamp::::from_clock_value(timer.get_current_clock().flex_unwrap()); match NfcTag::transmit(&mut buf, amount) { Ok(_) => (), - Err(_) => writeln!(console, " -- tx error!").unwrap(), + Err(_) => writeln!(Console::new(), " -- tx error!").unwrap(), } + let end = Timestamp::::from_clock_value(timer.get_current_clock().flex_unwrap()); + let elapsed = (end - start).ms(); + writeln!( + console, + "{}\n{:.2} ms elapsed for {} bytes ({:.2} kbit/s)", + title, + elapsed, + amount, + (amount as f64) / elapsed * 8. + ) + .unwrap(); + console.flush(); } -#[cfg(feature = "with_nfc")] #[derive(PartialEq, Eq)] /// enum for reserving the NFC tag state. enum State { @@ -56,15 +62,23 @@ enum State { fn main() { let mut console = Console::new(); + // Setup the timer with a dummy callback (we only care about reading the current time, but the + // API forces us to set an alarm callback too). + let mut with_callback = timer::with_callback(|_, _| {}); + let timer = with_callback.init().flex_unwrap(); writeln!(console, "****************************************").unwrap(); writeln!(console, "nfct_test application is installed").unwrap(); + writeln!( + console, + "Clock frequency: {} Hz", + timer.clock_frequency().hz() + ) + .unwrap(); - #[cfg(feature = "with_nfc")] let mut state = State::Disabled; - #[cfg(feature = "with_nfc")] + // Variable to count the change in the tag's state let mut state_change_cntr = 0; - #[cfg(feature = "with_nfc")] loop { match state { State::Enabled => { @@ -88,24 +102,44 @@ fn main() { match rx_buf[0] { 0xe0 /* RATS */=> { let mut answer_to_select = [0x05, 0x78, 0x80, 0xB1, 0x00]; - transmit_slice(&mut answer_to_select); + bench_transmit(&mut console, &timer, "TX: ATS", &mut answer_to_select); } 0xc2 /* DESELECT */ => { // Ignore the request let mut command_error = [0x6A, 0x81]; - transmit_slice(&mut command_error); + bench_transmit(&mut console, &timer, "TX: DESELECT", &mut command_error); } - 0x02 | 0x03 /* APDU Prefix */ => { + 0x02 | 0x03 /* APDU Prefix */ => match rx_buf[2] { // 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,]; - transmit_slice(&mut reply); - } else { + 0xa4 /* SELECT */ => if rx_buf[3] == 0x04 && rx_buf[5] == 0x08 && rx_buf[6] == 0xa0 { + // Vesion: "FIDO_2_0" + let mut reply = [rx_buf[0], 0x46, 0x49, 0x44, 0x4f, 0x5f, 0x32, 0x5f, 0x30, 0x90, 0x00,]; + bench_transmit(&mut console, &timer, "TX: Version Str", &mut reply); + } else { + let mut reply = [rx_buf[0], 0x90, 0x00]; + bench_transmit(&mut console, &timer, "TX: 0x9000", &mut reply); + } + 0xb0 /* READ */ => match rx_buf[5] { + 0x02 => { + let mut reply = [rx_buf[0], 0x12, 0x90, 0x00,]; + bench_transmit(&mut console, &timer, "TX: File Size", &mut reply); + } + 0x12 => { + let mut reply = [rx_buf[0], 0xd1, 0x01, 0x0e, 0x55, 0x77, 0x77, 0x77, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x73, 0x6b, 0x2e, 0x64, 0x65, 0x76, 0x90, 0x00,]; + bench_transmit(&mut console, &timer, "TX: NDEF", &mut reply); + } + 0x0f => { + let mut reply = [rx_buf[0], 0x00, 0x0f, 0x20, 0x00, 0x7f, 0x00, 0x7f, 0x04, 0x06, 0xe1, 0x04, 0x00, 0x7f, 0x00, 0x00, 0x90, 0x00,]; + bench_transmit(&mut console, &timer, "TX: CC", &mut reply); + } + _ => { + let mut reply = [rx_buf[0], 0x90, 0x00]; + bench_transmit(&mut console, &timer, "TX: 0x9000", &mut reply); + } + } + _ => { let mut reply = [rx_buf[0], 0x90, 0x00]; - transmit_slice(&mut reply); + bench_transmit(&mut console, &timer, "TX: 0x9000", &mut reply); } } 0x52 | 0x50 /* WUPA | Halt */ => { From aa47d1c278419cf329af99cffe5f65183b398bc7 Mon Sep 17 00:00:00 2001 From: Mirna Date: Wed, 4 Nov 2020 17:49:28 +0200 Subject: [PATCH 08/13] Supply NFC feature flag to desktop checks --- run_desktop_tests.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/run_desktop_tests.sh b/run_desktop_tests.sh index b22e1d8..696455f 100755 --- a/run_desktop_tests.sh +++ b/run_desktop_tests.sh @@ -31,7 +31,7 @@ cargo fmt --all -- --check cd ../.. echo "Running Clippy lints..." -cargo clippy --all-targets --features std -- -A clippy::new_without_default -D warnings +cargo clippy --all-targets --features std --features with_nfc -- -A clippy::new_without_default -D warnings echo "Building sha256sum tool..." cargo build --manifest-path third_party/tock/tools/sha256sum/Cargo.toml @@ -53,7 +53,7 @@ cargo check --release --target=thumbv7em-none-eabi --features debug_ctap,with_ct cargo check --release --target=thumbv7em-none-eabi --features debug_ctap,with_ctap1,panic_console,debug_allocations,verbose echo "Checking that examples build properly..." -cargo check --release --target=thumbv7em-none-eabi --examples +cargo check --release --target=thumbv7em-none-eabi --examples --features with_nfc echo "Checking that fuzz targets build properly..." cargo fuzz build From c232f2344c6232554d2a346660be1338aad2aacc Mon Sep 17 00:00:00 2001 From: Mirna Date: Wed, 4 Nov 2020 20:05:32 +0200 Subject: [PATCH 09/13] Resolve comments --- examples/nfct_test.rs | 326 +++++++++++++++++++++++------------------- run_desktop_tests.sh | 4 +- 2 files changed, 179 insertions(+), 151 deletions(-) diff --git a/examples/nfct_test.rs b/examples/nfct_test.rs index 9da0312..2e0df8a 100644 --- a/examples/nfct_test.rs +++ b/examples/nfct_test.rs @@ -5,166 +5,194 @@ extern crate lang_items; extern crate libtock_drivers; use core::fmt::Write; -use libtock_core::result::CommandError; use libtock_drivers::console::Console; -use libtock_drivers::nfc::NfcTag; -use libtock_drivers::nfc::RecvOp; -use libtock_drivers::result::FlexUnwrap; -use libtock_drivers::result::TockError; -use libtock_drivers::timer; -use libtock_drivers::timer::Timer; -use libtock_drivers::timer::Timestamp; -#[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; +#[cfg(not(feature = "with_nfc"))] +mod example { + use super::Console; + use super::Write; + + pub fn nfc(console: &mut Console) { + writeln!(console, "NFC feature flag is missing!").unwrap(); } - let mut console = Console::new(); - write!(console, "RX:").unwrap(); - for byte in buf.iter().take(amount - 1) { - write!(console, " {:02x?}", byte).unwrap(); - } - writeln!(console, " {:02x?}", buf[amount - 1]).unwrap(); - console.flush(); } -#[allow(dead_code)] -/// Function to identify the time elapsed for a transmission request. -fn bench_transmit(console: &mut Console, timer: &Timer, title: &str, mut buf: &mut [u8]) { - let amount = buf.len(); - let start = Timestamp::::from_clock_value(timer.get_current_clock().flex_unwrap()); - match NfcTag::transmit(&mut buf, amount) { - Ok(_) => (), - Err(_) => writeln!(Console::new(), " -- tx error!").unwrap(), - } - let end = Timestamp::::from_clock_value(timer.get_current_clock().flex_unwrap()); - let elapsed = (end - start).ms(); - writeln!( - console, - "{}\n{:.2} ms elapsed for {} bytes ({:.2} kbit/s)", - title, - elapsed, - amount, - (amount as f64) / elapsed * 8. - ) - .unwrap(); - console.flush(); -} +#[cfg(feature = "with_nfc")] +mod example { -#[derive(PartialEq, Eq)] -/// enum for reserving the NFC tag state. -enum State { - Enabled, - Disabled, + use super::Console; + use super::Write; + use libtock_core::result::CommandError; + use libtock_drivers::nfc::NfcTag; + use libtock_drivers::nfc::RecvOp; + use libtock_drivers::result::FlexUnwrap; + use libtock_drivers::result::TockError; + use libtock_drivers::timer; + use libtock_drivers::timer::Timer; + use libtock_drivers::timer::Timestamp; + + /// Helper function to write on console the received packet. + fn print_rx_buffer(buf: &mut [u8]) { + let mut console = Console::new(); + write!(console, "RX:").unwrap(); + if let Some((last, bytes)) = buf.split_last() { + for byte in bytes { + write!(console, " {:02x?}", byte).unwrap(); + } + writeln!(console, " {:02x?}", last).unwrap(); + } + console.flush(); + } + + /// Function to identify the time elapsed for a transmission request. + fn bench_transmit(console: &mut Console, timer: &Timer, title: &str, mut buf: &mut [u8]) { + let amount = buf.len(); + let start = Timestamp::::from_clock_value(timer.get_current_clock().flex_unwrap()); + match NfcTag::transmit(&mut buf, amount) { + Ok(_) => (), + Err(_) => writeln!(Console::new(), " -- tx error!").unwrap(), + } + let end = Timestamp::::from_clock_value(timer.get_current_clock().flex_unwrap()); + let elapsed = (end - start).ms(); + writeln!( + console, + "{}\n{:.2} ms elapsed for {} bytes ({:.2} kbit/s)", + title, + elapsed, + amount, + (amount as f64) / elapsed * 8. + ) + .unwrap(); + console.flush(); + } + + fn receive_packet(console: &mut Console, mut buf: &mut [u8; 256]) { + match NfcTag::receive(&mut buf) { + Ok(RecvOp { + recv_amount: amount, + .. + }) => { + if amount > 0 && amount <= buf.len() { + print_rx_buffer(&mut 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 Err").unwrap(), + } + } + + fn transmit_reply(mut console: &mut Console, timer: &Timer, buf: &[u8]) -> bool { + match buf[0] { + 0xe0 /* RATS */=> { + let mut answer_to_select = [0x05, 0x78, 0x80, 0xB1, 0x00]; + bench_transmit(&mut console, &timer, "TX: ATS", &mut answer_to_select); + } + 0xc2 /* DESELECT */ => { + // Ignore the request + let mut command_error = [0x6A, 0x81]; + bench_transmit(&mut console, &timer, "TX: DESELECT", &mut command_error); + } + 0x02 | 0x03 /* APDU Prefix */ => match buf[2] { + // If the received packet is applet selection command (FIDO 2) + 0xa4 /* SELECT */ => if buf[3] == 0x04 && buf[5] == 0x08 && buf[6] == 0xa0 { + // Vesion: "FIDO_2_0" + let mut reply = [buf[0], 0x46, 0x49, 0x44, 0x4f, 0x5f, 0x32, 0x5f, 0x30, 0x90, 0x00,]; + bench_transmit(&mut console, &timer, "TX: Version Str", &mut reply); + } else { + let mut reply = [buf[0], 0x90, 0x00]; + bench_transmit(&mut console, &timer, "TX: 0x9000", &mut reply); + } + 0xb0 /* READ */ => match buf[5] { + 0x02 => { + let mut reply = [buf[0], 0x12, 0x90, 0x00,]; + bench_transmit(&mut console, &timer, "TX: File Size", &mut reply); + } + 0x12 => { + let mut reply = [buf[0], 0xd1, 0x01, 0x0e, 0x55, 0x77, 0x77, 0x77, 0x2e, 0x6f, 0x70, 0x65, + 0x6e, 0x73, 0x6b, 0x2e, 0x64, 0x65, 0x76, 0x90, 0x00,]; + bench_transmit(&mut console, &timer, "TX: NDEF", &mut reply); + } + 0x0f => { + let mut reply = [buf[0], 0x00, 0x0f, 0x20, 0x00, 0x7f, 0x00, 0x7f, 0x04, 0x06, 0xe1, 0x04, + 0x00, 0x7f, 0x00, 0x00, 0x90, 0x00,]; + bench_transmit(&mut console, &timer, "TX: CC", &mut reply); + } + _ => { + let mut reply = [buf[0], 0x90, 0x00]; + bench_transmit(&mut console, &timer, "TX: 0x9000", &mut reply); + } + } + _ => { + let mut reply = [buf[0], 0x90, 0x00]; + bench_transmit(&mut console, &timer, "TX: 0x9000", &mut reply); + } + } + 0x26 | 0x52 | 0x50 /* REQA | WUPA | Halt */ => { + if NfcTag::disable_emulation() { + writeln!(console, " -- TAG DISABLED").unwrap(); + } + return false; + } + _ => (), + } + true + } + + pub fn nfc(mut console: &mut Console) { + // Setup the timer with a dummy callback (we only care about reading the current time, but the + // API forces us to set an alarm callback too). + let mut with_callback = timer::with_callback(|_, _| {}); + let timer = with_callback.init().flex_unwrap(); + + writeln!( + console, + "Clock frequency: {} Hz", + timer.clock_frequency().hz() + ) + .unwrap(); + + let mut is_enabled = false; + let mut state_change_counter = 0; + loop { + match is_enabled { + true => { + let mut rx_buf = [0; 256]; + loop { + receive_packet(&mut console, &mut rx_buf); + // If the reader restarts the communication and we can't + // reply to the received packet, then disable the tag. + if !transmit_reply(&mut console, &timer, &rx_buf) { + is_enabled = false; + break; + } + } + } + false => { + NfcTag::enable_emulation(); + // Configure Type 4 tag + if NfcTag::configure(4) { + is_enabled = true; + } + } + } + state_change_counter += 1; + if state_change_counter > 100 && is_enabled == false { + break; + } + } + } } fn main() { let mut console = Console::new(); - // Setup the timer with a dummy callback (we only care about reading the current time, but the - // API forces us to set an alarm callback too). - let mut with_callback = timer::with_callback(|_, _| {}); - let timer = with_callback.init().flex_unwrap(); - writeln!(console, "****************************************").unwrap(); writeln!(console, "nfct_test application is installed").unwrap(); - writeln!( - console, - "Clock frequency: {} Hz", - timer.clock_frequency().hz() - ) - .unwrap(); - - let mut state = State::Disabled; - // Variable to count the change in the tag's state - let mut state_change_cntr = 0; - loop { - match state { - State::Enabled => { - let mut rx_buf = [0; 256]; - loop { - match NfcTag::receive(&mut rx_buf) { - Ok(RecvOp { - recv_amount: amount, - .. - }) => 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 Err").unwrap(), - } - - match rx_buf[0] { - 0xe0 /* RATS */=> { - let mut answer_to_select = [0x05, 0x78, 0x80, 0xB1, 0x00]; - bench_transmit(&mut console, &timer, "TX: ATS", &mut answer_to_select); - } - 0xc2 /* DESELECT */ => { - // Ignore the request - let mut command_error = [0x6A, 0x81]; - bench_transmit(&mut console, &timer, "TX: DESELECT", &mut command_error); - } - 0x02 | 0x03 /* APDU Prefix */ => match rx_buf[2] { - // If the received packet is applet selection command (FIDO 2) - 0xa4 /* SELECT */ => if rx_buf[3] == 0x04 && rx_buf[5] == 0x08 && rx_buf[6] == 0xa0 { - // Vesion: "FIDO_2_0" - let mut reply = [rx_buf[0], 0x46, 0x49, 0x44, 0x4f, 0x5f, 0x32, 0x5f, 0x30, 0x90, 0x00,]; - bench_transmit(&mut console, &timer, "TX: Version Str", &mut reply); - } else { - let mut reply = [rx_buf[0], 0x90, 0x00]; - bench_transmit(&mut console, &timer, "TX: 0x9000", &mut reply); - } - 0xb0 /* READ */ => match rx_buf[5] { - 0x02 => { - let mut reply = [rx_buf[0], 0x12, 0x90, 0x00,]; - bench_transmit(&mut console, &timer, "TX: File Size", &mut reply); - } - 0x12 => { - let mut reply = [rx_buf[0], 0xd1, 0x01, 0x0e, 0x55, 0x77, 0x77, 0x77, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x73, 0x6b, 0x2e, 0x64, 0x65, 0x76, 0x90, 0x00,]; - bench_transmit(&mut console, &timer, "TX: NDEF", &mut reply); - } - 0x0f => { - let mut reply = [rx_buf[0], 0x00, 0x0f, 0x20, 0x00, 0x7f, 0x00, 0x7f, 0x04, 0x06, 0xe1, 0x04, 0x00, 0x7f, 0x00, 0x00, 0x90, 0x00,]; - bench_transmit(&mut console, &timer, "TX: CC", &mut reply); - } - _ => { - let mut reply = [rx_buf[0], 0x90, 0x00]; - bench_transmit(&mut console, &timer, "TX: 0x9000", &mut reply); - } - } - _ => { - let mut reply = [rx_buf[0], 0x90, 0x00]; - bench_transmit(&mut console, &timer, "TX: 0x9000", &mut reply); - } - } - 0x52 | 0x50 /* WUPA | Halt */ => { - if NfcTag::disable_emulation() { - writeln!(console, " -- TAG DISABLED").unwrap(); - } - state = State::Disabled; - break; - } - _ => (), - } - } - } - State::Disabled => { - NfcTag::enable_emulation(); - // Configure Type 4 tag - if NfcTag::configure(4) { - state = State::Enabled; - } - } - } - state_change_cntr += 1; - if state_change_cntr > 100 && state == State::Disabled { - break; - } - } + example::nfc(&mut console); writeln!(console, "****************************************").unwrap(); } diff --git a/run_desktop_tests.sh b/run_desktop_tests.sh index 696455f..b22e1d8 100755 --- a/run_desktop_tests.sh +++ b/run_desktop_tests.sh @@ -31,7 +31,7 @@ cargo fmt --all -- --check cd ../.. echo "Running Clippy lints..." -cargo clippy --all-targets --features std --features with_nfc -- -A clippy::new_without_default -D warnings +cargo clippy --all-targets --features std -- -A clippy::new_without_default -D warnings echo "Building sha256sum tool..." cargo build --manifest-path third_party/tock/tools/sha256sum/Cargo.toml @@ -53,7 +53,7 @@ cargo check --release --target=thumbv7em-none-eabi --features debug_ctap,with_ct cargo check --release --target=thumbv7em-none-eabi --features debug_ctap,with_ctap1,panic_console,debug_allocations,verbose echo "Checking that examples build properly..." -cargo check --release --target=thumbv7em-none-eabi --examples --features with_nfc +cargo check --release --target=thumbv7em-none-eabi --examples echo "Checking that fuzz targets build properly..." cargo fuzz build From 0eaa2b529103d743fe62ba5e25c7d05a7008f044 Mon Sep 17 00:00:00 2001 From: Mirna Date: Wed, 4 Nov 2020 20:25:30 +0200 Subject: [PATCH 10/13] Refactor a `match` expression --- examples/nfct_test.rs | 34 +++++++++++++++------------------- 1 file changed, 15 insertions(+), 19 deletions(-) diff --git a/examples/nfct_test.rs b/examples/nfct_test.rs index 2e0df8a..0a81751 100644 --- a/examples/nfct_test.rs +++ b/examples/nfct_test.rs @@ -19,7 +19,6 @@ mod example { #[cfg(feature = "with_nfc")] mod example { - use super::Console; use super::Write; use libtock_core::result::CommandError; @@ -160,29 +159,26 @@ mod example { let mut is_enabled = false; let mut state_change_counter = 0; loop { - match is_enabled { - true => { - let mut rx_buf = [0; 256]; - loop { - receive_packet(&mut console, &mut rx_buf); - // If the reader restarts the communication and we can't - // reply to the received packet, then disable the tag. - if !transmit_reply(&mut console, &timer, &rx_buf) { - is_enabled = false; - break; - } + if is_enabled { + let mut rx_buf = [0; 256]; + loop { + receive_packet(&mut console, &mut rx_buf); + // If the reader restarts the communication and we can't + // reply to the received packet, then disable the tag. + if !transmit_reply(&mut console, &timer, &rx_buf) { + is_enabled = false; + break; } } - false => { - NfcTag::enable_emulation(); - // Configure Type 4 tag - if NfcTag::configure(4) { - is_enabled = true; - } + } else { + NfcTag::enable_emulation(); + // Configure Type 4 tag + if NfcTag::configure(4) { + is_enabled = true; } } state_change_counter += 1; - if state_change_counter > 100 && is_enabled == false { + if !is_enabled && state_change_counter > 100 { break; } } From 203367b081b14ca6622c6dee2ca29e1194397cf7 Mon Sep 17 00:00:00 2001 From: Mirna Date: Thu, 5 Nov 2020 10:38:59 +0200 Subject: [PATCH 11/13] Updated control flow + cleaned some code --- examples/nfct_test.rs | 45 ++++++++++++++++++++----------------------- 1 file changed, 21 insertions(+), 24 deletions(-) diff --git a/examples/nfct_test.rs b/examples/nfct_test.rs index 0a81751..a43a059 100644 --- a/examples/nfct_test.rs +++ b/examples/nfct_test.rs @@ -32,15 +32,15 @@ mod example { /// Helper function to write on console the received packet. fn print_rx_buffer(buf: &mut [u8]) { - let mut console = Console::new(); - write!(console, "RX:").unwrap(); if let Some((last, bytes)) = buf.split_last() { + let mut console = Console::new(); + write!(console, "RX:").unwrap(); for byte in bytes { write!(console, " {:02x?}", byte).unwrap(); } writeln!(console, " {:02x?}", last).unwrap(); + console.flush(); } - console.flush(); } /// Function to identify the time elapsed for a transmission request. @@ -65,25 +65,27 @@ mod example { console.flush(); } - fn receive_packet(console: &mut Console, mut buf: &mut [u8; 256]) { + fn receive_packet(console: &mut Console, mut buf: &mut [u8; 256]) -> bool { match NfcTag::receive(&mut buf) { Ok(RecvOp { recv_amount: amount, .. }) => { - if amount > 0 && amount <= buf.len() { + if amount <= buf.len() { print_rx_buffer(&mut buf[..amount]); } } Err(TockError::Command(CommandError { return_code: -4, /* EOFF: Not Ready */ .. - })) => (), + })) => return false, + // For the example app, just print any other received error without handling. Err(TockError::Command(CommandError { return_code: value, .. })) => writeln!(console, " -- Err({})!", value).unwrap(), Err(_) => writeln!(console, " -- RX Err").unwrap(), } + true } fn transmit_reply(mut console: &mut Console, timer: &Timer, buf: &[u8]) -> bool { @@ -156,29 +158,24 @@ mod example { ) .unwrap(); - let mut is_enabled = false; let mut state_change_counter = 0; loop { - if is_enabled { + while !NfcTag::enable_emulation() {} + // Configure Type 4 tag + while !NfcTag::configure(4) {} + state_change_counter += 1; + loop { let mut rx_buf = [0; 256]; - loop { - receive_packet(&mut console, &mut rx_buf); - // If the reader restarts the communication and we can't - // reply to the received packet, then disable the tag. - if !transmit_reply(&mut console, &timer, &rx_buf) { - is_enabled = false; - break; - } - } - } else { - NfcTag::enable_emulation(); - // Configure Type 4 tag - if NfcTag::configure(4) { - is_enabled = true; + // Await a successful receive + while !receive_packet(&mut console, &mut rx_buf) {} + // If the reader restarts the communication and we can't + // reply to the received packet, then disable the tag. + if !transmit_reply(&mut console, &timer, &rx_buf) { + state_change_counter += 1; + break; } } - state_change_counter += 1; - if !is_enabled && state_change_counter > 100 { + if state_change_counter > 100 { break; } } From f48046d1e4cb3adde676c62c0c6b0db2f6f62e03 Mon Sep 17 00:00:00 2001 From: Mirna Date: Thu, 5 Nov 2020 10:39:51 +0200 Subject: [PATCH 12/13] Added checks using NFC feature flag --- run_desktop_tests.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/run_desktop_tests.sh b/run_desktop_tests.sh index b22e1d8..49c2990 100755 --- a/run_desktop_tests.sh +++ b/run_desktop_tests.sh @@ -32,6 +32,7 @@ cd ../.. echo "Running Clippy lints..." cargo clippy --all-targets --features std -- -A clippy::new_without_default -D warnings +cargo clippy --all-targets --features std,with_nfc -- -A clippy::new_without_default -D warnings echo "Building sha256sum tool..." cargo build --manifest-path third_party/tock/tools/sha256sum/Cargo.toml @@ -54,6 +55,7 @@ cargo check --release --target=thumbv7em-none-eabi --features debug_ctap,with_ct echo "Checking that examples build properly..." cargo check --release --target=thumbv7em-none-eabi --examples +cargo check --release --target=thumbv7em-none-eabi --examples --features with_nfc echo "Checking that fuzz targets build properly..." cargo fuzz build From 84dec3f636fa7c261135ff8b0930621990f98b71 Mon Sep 17 00:00:00 2001 From: Mirna Date: Tue, 10 Nov 2020 16:57:31 +0200 Subject: [PATCH 13/13] Update in the application's workflow --- examples/nfct_test.rs | 150 +++++++++++++++++++++++++++++------------- 1 file changed, 104 insertions(+), 46 deletions(-) diff --git a/examples/nfct_test.rs b/examples/nfct_test.rs index a43a059..924237d 100644 --- a/examples/nfct_test.rs +++ b/examples/nfct_test.rs @@ -30,6 +30,41 @@ mod example { use libtock_drivers::timer::Timer; use libtock_drivers::timer::Timestamp; + #[derive(Copy, Clone, Debug, PartialEq)] + enum ReturnCode { + /// Operation completed successfully + SUCCESS, + /// Generic failure condition + FAIL, + /// Underlying system is busy; retry + EBUSY, + /// The component is powered down + EOFF, + /// An invalid parameter was passed + EINVAL, + /// Operation canceled by a call + ECANCEL, + /// Memory required not available + ENOMEM, + /// Operation or command is unsupported + ENOSUPPORT, + } + + impl From for ReturnCode { + fn from(original: isize) -> ReturnCode { + match original { + 0 => ReturnCode::SUCCESS, + -1 => ReturnCode::FAIL, + -2 => ReturnCode::EBUSY, + -4 => ReturnCode::EOFF, + -6 => ReturnCode::EINVAL, + -8 => ReturnCode::ECANCEL, + -9 => ReturnCode::ENOMEM, + _ => ReturnCode::ENOSUPPORT, + } + } + } + /// Helper function to write on console the received packet. fn print_rx_buffer(buf: &mut [u8]) { if let Some((last, bytes)) = buf.split_last() { @@ -44,11 +79,20 @@ mod example { } /// Function to identify the time elapsed for a transmission request. - fn bench_transmit(console: &mut Console, timer: &Timer, title: &str, mut buf: &mut [u8]) { + fn bench_transmit( + console: &mut Console, + timer: &Timer, + title: &str, + mut buf: &mut [u8], + ) -> ReturnCode { let amount = buf.len(); let start = Timestamp::::from_clock_value(timer.get_current_clock().flex_unwrap()); match NfcTag::transmit(&mut buf, amount) { Ok(_) => (), + Err(TockError::Command(CommandError { + return_code: -8, /* ECANCEL: No Field*/ + .. + })) => return ReturnCode::ECANCEL, Err(_) => writeln!(Console::new(), " -- tx error!").unwrap(), } let end = Timestamp::::from_clock_value(timer.get_current_clock().flex_unwrap()); @@ -63,9 +107,10 @@ mod example { ) .unwrap(); console.flush(); + ReturnCode::SUCCESS } - fn receive_packet(console: &mut Console, mut buf: &mut [u8; 256]) -> bool { + fn receive_packet(console: &mut Console, mut buf: &mut [u8; 256]) -> ReturnCode { match NfcTag::receive(&mut buf) { Ok(RecvOp { recv_amount: amount, @@ -75,74 +120,71 @@ mod example { print_rx_buffer(&mut buf[..amount]); } } - Err(TockError::Command(CommandError { - return_code: -4, /* EOFF: Not Ready */ - .. - })) => return false, - // For the example app, just print any other received error without handling. - Err(TockError::Command(CommandError { - return_code: value, .. - })) => writeln!(console, " -- Err({})!", value).unwrap(), - Err(_) => writeln!(console, " -- RX Err").unwrap(), + Err(TockError::Command(CommandError { return_code, .. })) => return return_code.into(), + Err(_) => { + writeln!(console, " -- RX Err").unwrap(); + return ReturnCode::ECANCEL; + } } - true + ReturnCode::SUCCESS } - fn transmit_reply(mut console: &mut Console, timer: &Timer, buf: &[u8]) -> bool { + fn transmit_reply(mut console: &mut Console, timer: &Timer, buf: &[u8]) -> ReturnCode { + let mut return_code = ReturnCode::SUCCESS; match buf[0] { 0xe0 /* RATS */=> { let mut answer_to_select = [0x05, 0x78, 0x80, 0xB1, 0x00]; - bench_transmit(&mut console, &timer, "TX: ATS", &mut answer_to_select); + return_code = bench_transmit(&mut console, &timer, "TX: ATS", &mut answer_to_select); } 0xc2 /* DESELECT */ => { // Ignore the request let mut command_error = [0x6A, 0x81]; - bench_transmit(&mut console, &timer, "TX: DESELECT", &mut command_error); + return_code = bench_transmit(&mut console, &timer, "TX: DESELECT", &mut command_error); } 0x02 | 0x03 /* APDU Prefix */ => match buf[2] { // If the received packet is applet selection command (FIDO 2) 0xa4 /* SELECT */ => if buf[3] == 0x04 && buf[5] == 0x08 && buf[6] == 0xa0 { - // Vesion: "FIDO_2_0" - let mut reply = [buf[0], 0x46, 0x49, 0x44, 0x4f, 0x5f, 0x32, 0x5f, 0x30, 0x90, 0x00,]; - bench_transmit(&mut console, &timer, "TX: Version Str", &mut reply); - } else { - let mut reply = [buf[0], 0x90, 0x00]; - bench_transmit(&mut console, &timer, "TX: 0x9000", &mut reply); - } + // Vesion: "FIDO_2_0" + let mut reply = [buf[0], 0x46, 0x49, 0x44, 0x4f, 0x5f, 0x32, 0x5f, 0x30, 0x90, 0x00,]; + return_code = bench_transmit(&mut console, &timer, "TX: Version Str", &mut reply); + } else if (buf[6] == 0xd2 && buf[7] == 0x76) || (buf[6] == 0xe1 && (buf[7] == 0x03 || buf[7] == 0x04)){ + let mut reply = [buf[0], 0x90, 0x00]; + return_code = bench_transmit(&mut console, &timer, "TX: 0x9000", &mut reply); + } else /* Unknown file */ { + let mut reply = [buf[0], 0x6a, 0x82]; + return_code = bench_transmit(&mut console, &timer, "TX: 0x6A82", &mut reply); + } 0xb0 /* READ */ => match buf[5] { - 0x02 => { + 0x02 => { let mut reply = [buf[0], 0x12, 0x90, 0x00,]; - bench_transmit(&mut console, &timer, "TX: File Size", &mut reply); + return_code = bench_transmit(&mut console, &timer, "TX: File Size", &mut reply); } 0x12 => { let mut reply = [buf[0], 0xd1, 0x01, 0x0e, 0x55, 0x77, 0x77, 0x77, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x73, 0x6b, 0x2e, 0x64, 0x65, 0x76, 0x90, 0x00,]; - bench_transmit(&mut console, &timer, "TX: NDEF", &mut reply); + return_code = bench_transmit(&mut console, &timer, "TX: NDEF", &mut reply); } 0x0f => { let mut reply = [buf[0], 0x00, 0x0f, 0x20, 0x00, 0x7f, 0x00, 0x7f, 0x04, 0x06, 0xe1, 0x04, 0x00, 0x7f, 0x00, 0x00, 0x90, 0x00,]; - bench_transmit(&mut console, &timer, "TX: CC", &mut reply); + return_code = bench_transmit(&mut console, &timer, "TX: CC", &mut reply); } _ => { let mut reply = [buf[0], 0x90, 0x00]; - bench_transmit(&mut console, &timer, "TX: 0x9000", &mut reply); + return_code = bench_transmit(&mut console, &timer, "TX: 0x9000", &mut reply); } } _ => { let mut reply = [buf[0], 0x90, 0x00]; - bench_transmit(&mut console, &timer, "TX: 0x9000", &mut reply); + return_code = bench_transmit(&mut console, &timer, "TX: 0x9000", &mut reply); } } 0x26 | 0x52 | 0x50 /* REQA | WUPA | Halt */ => { - if NfcTag::disable_emulation() { - writeln!(console, " -- TAG DISABLED").unwrap(); - } - return false; + return ReturnCode::EOFF; } _ => (), } - true + return_code } pub fn nfc(mut console: &mut Console) { @@ -160,19 +202,35 @@ mod example { let mut state_change_counter = 0; loop { - while !NfcTag::enable_emulation() {} - // Configure Type 4 tag - while !NfcTag::configure(4) {} - state_change_counter += 1; - loop { - let mut rx_buf = [0; 256]; - // Await a successful receive - while !receive_packet(&mut console, &mut rx_buf) {} - // If the reader restarts the communication and we can't - // reply to the received packet, then disable the tag. - if !transmit_reply(&mut console, &timer, &rx_buf) { - state_change_counter += 1; - break; + let mut rx_buf = [0; 256]; + match receive_packet(&mut console, &mut rx_buf) { + ReturnCode::EOFF => { + // Not configured + while !NfcTag::enable_emulation() {} + // Configure Type 4 tag + while !NfcTag::configure(4) {} + } + ReturnCode::ECANCEL /* field lost */ => { + NfcTag::disable_emulation(); + } + ReturnCode::EBUSY /* awaiting select*/ => (), + ReturnCode::ENOMEM => { + writeln!(console, " -- Amount more than buffer limit").unwrap() + } + ReturnCode::FAIL => writeln!(console, " -- Invalid CRC").unwrap(), + ReturnCode::EINVAL /* covered in driver interface */ => (), + ReturnCode::ENOSUPPORT => (), + ReturnCode::SUCCESS => { + // If the reader restarts the communication then disable the tag. + match transmit_reply(&mut console, &timer, &rx_buf) { + ReturnCode::ECANCEL | ReturnCode::EOFF => { + if NfcTag::disable_emulation() { + writeln!(console, " -- TAG DISABLED").unwrap(); + } + state_change_counter += 1; + } + _ => (), + } } } if state_change_counter > 100 {