From 3187eafbc8d9a8a8648104fcdddeb79559da8c2b Mon Sep 17 00:00:00 2001 From: Yves Richard Date: Wed, 15 May 2024 23:02:43 +0200 Subject: [PATCH] Use ledger protocol to split NFC APDUs --- include/os_io_nfc.h | 26 +++++++++ include/os_io_seproxyhal.h | 2 +- src/os_io_nfc.c | 107 +++++++++++++++++++++++++++++++++++++ src/os_io_seproxyhal.c | 35 ++++-------- 4 files changed, 145 insertions(+), 25 deletions(-) create mode 100644 include/os_io_nfc.h create mode 100644 src/os_io_nfc.c diff --git a/include/os_io_nfc.h b/include/os_io_nfc.h new file mode 100644 index 000000000..b8602c25f --- /dev/null +++ b/include/os_io_nfc.h @@ -0,0 +1,26 @@ + +/******************************************************************************* + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ + +#ifndef OS_IO_NFC_H +#define OS_IO_NFC_H + +void io_nfc_init(void); +void io_nfc_recv_event(void); +void io_nfc_send_response(const uint8_t *packet, uint16_t packet_length); + +#endif diff --git a/include/os_io_seproxyhal.h b/include/os_io_seproxyhal.h index 23c86f39c..e39528d54 100644 --- a/include/os_io_seproxyhal.h +++ b/include/os_io_seproxyhal.h @@ -136,7 +136,7 @@ void io_set_timeout(unsigned int timeout); #ifdef HAVE_NFC // Needs to be aligned with RFAL_FEATURE_ISO_DEP_IBLOCK_MAX_LEN defined on mcu side in platform.h -#define NFC_APDU_MAX_SIZE 256 +#define NFC_APDU_MAX_SIZE 1024 void io_seproxyhal_nfc_power(bool forceInit); #endif diff --git a/src/os_io_nfc.c b/src/os_io_nfc.c new file mode 100644 index 000000000..91fe72ebe --- /dev/null +++ b/src/os_io_nfc.c @@ -0,0 +1,107 @@ + +/******************************************************************************* + * Ledger Nano S - Secure firmware + * (c) 2022 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ +#include "bolos_target.h" +#include "errors.h" +#include "exceptions.h" +#ifdef HAVE_NFC + +#if defined(DEBUG_OS_STACK_CONSUMPTION) +#include "os_debug.h" +#endif // DEBUG_OS_STACK_CONSUMPTION + +#include "os_io.h" +#include "os_utils.h" +#include "os_io_seproxyhal.h" +#include + + +#ifdef DEBUG +#define LOG printf +#else +#define LOG(...) +#endif + +#include "os.h" +#include "ledger_protocol.h" + +static uint8_t rx_apdu_buffer[IO_APDU_BUFFER_SIZE]; +static ledger_protocol_t ledger_protocol_data; + +void io_nfc_init(void){ + memset(&rx_apdu_buffer, 0, sizeof(rx_apdu_buffer)); + memset(&ledger_protocol_data, 0, sizeof(ledger_protocol_data)); + ledger_protocol_data.rx_apdu_buffer = rx_apdu_buffer; + ledger_protocol_data.rx_apdu_buffer_max_length = sizeof(rx_apdu_buffer); + ledger_protocol_data.mtu = MIN(sizeof(ledger_protocol_data.tx_chunk), sizeof(G_io_seproxyhal_spi_buffer) - 3); +#ifdef HAVE_LOCAL_APDU_BUFFER + ledger_protocol_data.rx_dst_buffer = NULL; +#else + ledger_protocol_data.rx_dst_buffer = G_io_apdu_buffer; +#endif + LEDGER_PROTOCOL_init(&ledger_protocol_data); +} + +void io_nfc_recv_event(void) +{ + size_t size = U2BE(G_io_seproxyhal_spi_buffer, 1); + + //TODO check max size + LEDGER_PROTOCOL_rx(&ledger_protocol_data, G_io_seproxyhal_spi_buffer+3, size); + + if (ledger_protocol_data.rx_apdu_status == APDU_STATUS_COMPLETE) { + memcpy(ledger_protocol_data.rx_dst_buffer, + ledger_protocol_data.rx_apdu_buffer, + ledger_protocol_data.rx_apdu_length); + G_io_app.apdu_length = ledger_protocol_data.rx_apdu_length; + G_io_app.apdu_state = APDU_NFC; + G_io_app.apdu_media = IO_APDU_MEDIA_NFC; + ledger_protocol_data.rx_apdu_length = 0; + ledger_protocol_data.rx_apdu_status = APDU_STATUS_WAITING; + } +} + + + +void io_nfc_send_response(const uint8_t *packet, uint16_t packet_length){ + + LEDGER_PROTOCOL_tx(&ledger_protocol_data, packet, packet_length); + if (ledger_protocol_data.tx_chunk_length >= 2) { + // reply the NFC APDU over SEPROXYHAL protocol + G_io_seproxyhal_spi_buffer[0] = SEPROXYHAL_TAG_NFC_RAPDU; + G_io_seproxyhal_spi_buffer[1] = (ledger_protocol_data.tx_chunk_length) >> 8; + G_io_seproxyhal_spi_buffer[2] = (ledger_protocol_data.tx_chunk_length); + memcpy(G_io_seproxyhal_spi_buffer+3, ledger_protocol_data.tx_chunk, ledger_protocol_data.tx_chunk_length); + io_seproxyhal_spi_send(G_io_seproxyhal_spi_buffer, 3+ledger_protocol_data.tx_chunk_length); + } + + while (ledger_protocol_data.tx_apdu_buffer) { + LEDGER_PROTOCOL_tx(&ledger_protocol_data, NULL, 0); + if (ledger_protocol_data.tx_chunk_length >= 2) { + // reply the NFC APDU over SEPROXYHAL protocol + G_io_seproxyhal_spi_buffer[0] = SEPROXYHAL_TAG_NFC_RAPDU; + G_io_seproxyhal_spi_buffer[1] = (ledger_protocol_data.tx_chunk_length) >> 8; + G_io_seproxyhal_spi_buffer[2] = (ledger_protocol_data.tx_chunk_length); + memcpy(G_io_seproxyhal_spi_buffer+3, ledger_protocol_data.tx_chunk, ledger_protocol_data.tx_chunk_length); + io_seproxyhal_spi_send(G_io_seproxyhal_spi_buffer, 3+ledger_protocol_data.tx_chunk_length); + } + } +} + +#endif // HAVE_NFC + + diff --git a/src/os_io_seproxyhal.c b/src/os_io_seproxyhal.c index 34286cca3..2ea7649dd 100644 --- a/src/os_io_seproxyhal.c +++ b/src/os_io_seproxyhal.c @@ -87,6 +87,10 @@ extern USBD_HandleTypeDef USBD_Device; #endif #include "os.h" +#ifdef HAVE_NFC +#include "os_io_nfc.h" +#endif + #ifdef HAVE_SERIALIZED_NBGL #include "nbgl_serialize.h" #endif @@ -243,21 +247,6 @@ void io_seproxyhal_handle_capdu_event(void) } } -#ifdef HAVE_NFC -void io_seproxyhal_handle_nfc_recv_event(void) -{ - if (G_io_app.apdu_state == APDU_IDLE) { - size_t max = MIN(sizeof(G_io_apdu_buffer), sizeof(G_io_seproxyhal_spi_buffer) - 3); - size_t size = U2BE(G_io_seproxyhal_spi_buffer, 1); - - G_io_app.apdu_media = IO_APDU_MEDIA_NFC; - G_io_app.apdu_state = APDU_NFC; - G_io_app.apdu_length = MIN(size, max); - - memcpy(G_io_apdu_buffer, &G_io_seproxyhal_spi_buffer[3], G_io_app.apdu_length); - } -} -#endif unsigned int io_seproxyhal_handle_event(void) { #ifdef HAVE_IO_USB @@ -290,7 +279,8 @@ unsigned int io_seproxyhal_handle_event(void) #ifdef HAVE_NFC case SEPROXYHAL_TAG_NFC_APDU_EVENT: - io_seproxyhal_handle_nfc_recv_event(); + // TODO chack APDU_IDLE || APDU_NFC + io_nfc_recv_event(); return 1; #endif @@ -462,6 +452,10 @@ void io_seproxyhal_init(void) io_usb_hid_init(); #endif // HAVE_USB_APDU +#ifdef HAVE_NFC + io_nfc_init(); +#endif // HAVE_NFC + #ifdef HAVE_BAGL io_seproxyhal_init_ux(); @@ -1358,14 +1352,7 @@ unsigned short io_exchange(unsigned char channel, unsigned short tx_len) || (tx_len > NFC_APDU_MAX_SIZE)) { THROW(INVALID_PARAMETER); } - // reply the NFC APDU over SEPROXYHAL protocol - G_io_seproxyhal_spi_buffer[0] = SEPROXYHAL_TAG_NFC_RAPDU; - G_io_seproxyhal_spi_buffer[1] = (tx_len) >> 8; - G_io_seproxyhal_spi_buffer[2] = (tx_len); - io_seproxyhal_spi_send(G_io_seproxyhal_spi_buffer, 3); - io_seproxyhal_spi_send(G_io_apdu_buffer, tx_len); - - // isngle packet reply, mark immediate idle + io_nfc_send_response(G_io_apdu_buffer, tx_len); G_io_app.apdu_state = APDU_IDLE; G_io_app.apdu_media = IO_APDU_MEDIA_NONE; goto break_send;