Skip to content

Commit

Permalink
Use ledger protocol to split NFC APDUs
Browse files Browse the repository at this point in the history
  • Loading branch information
yrichard-ledger committed May 16, 2024
1 parent b2a5789 commit 3187eaf
Show file tree
Hide file tree
Showing 4 changed files with 145 additions and 25 deletions.
26 changes: 26 additions & 0 deletions include/os_io_nfc.h
Original file line number Diff line number Diff line change
@@ -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
2 changes: 1 addition & 1 deletion include/os_io_seproxyhal.h
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
107 changes: 107 additions & 0 deletions src/os_io_nfc.c
Original file line number Diff line number Diff line change
@@ -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 <string.h>


#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


35 changes: 11 additions & 24 deletions src/os_io_seproxyhal.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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

Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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;
Expand Down

0 comments on commit 3187eaf

Please sign in to comment.