Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions include/seproxyhal_protocol.h
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,9 @@ enum seph_protocol_evt_usb_mask {
SEPROXYHAL_TAG_USB_EP_XFER_OUT = 0x04,
};

// EVT : USB IAP2 DATA
#define SEPROXYHAL_TAG_USB_IAP_EVENT (0x11)

// EVT : MCU CHUNK READ RSP
#define SEPROXYHAL_TAG_UNSEC_CHUNK_EVENT (0x12)

Expand Down Expand Up @@ -265,6 +268,9 @@ enum seph_protocol_cmd_usb_prepare_type {
SEPROXYHAL_TAG_USB_EP_PREPARE_DIR_UNSTALL = 0x80,
};

// CMD : USB SEND IAP2 DATA
#define SEPROXYHAL_TAG_USB_IAP_SEND (0x51)

// CMD : REQUEST STATUS
#define SEPROXYHAL_TAG_REQUEST_STATUS (0x52)

Expand Down
2 changes: 2 additions & 0 deletions io/include/os_io.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ typedef enum {
OS_IO_PACKET_TYPE_USB_U2F_HID_CANCEL = 0x25,
OS_IO_PACKET_TYPE_USB_U2F_HID_RAW = 0x26,
OS_IO_PACKET_TYPE_USB_CDC_RAW = 0x29,
OS_IO_PACKET_TYPE_USB_IAP_APDU = 0x2A,

OS_IO_PACKET_TYPE_BLE_MASK = 0x30,
OS_IO_PACKET_TYPE_BLE_APDU = 0x30,
Expand All @@ -69,6 +70,7 @@ typedef enum {
APDU_TYPE_USB_U2F_CANCEL = OS_IO_PACKET_TYPE_USB_U2F_HID_CANCEL,
APDU_TYPE_BLE = OS_IO_PACKET_TYPE_BLE_APDU,
APDU_TYPE_NFC = OS_IO_PACKET_TYPE_NFC_APDU,
APDU_TYPE_IAP = OS_IO_PACKET_TYPE_USB_IAP_APDU,
} apdu_type_t;

typedef enum {
Expand Down
20 changes: 20 additions & 0 deletions io/src/os_io.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@
#ifndef HAVE_CDCUSB
#include "usbd_ledger_hid_u2f.h"
#endif // HAVE_CDCUSB
#ifdef HAVE_IAPUSB
#include "usb_iap.h"
#endif // HAVE_IAPUSB
#endif // HAVE_IO_USB

#ifdef HAVE_BLE
Expand Down Expand Up @@ -177,6 +180,9 @@ int os_io_init(os_io_init_t *init)

#ifdef HAVE_IO_USB
USBD_LEDGER_init(&init->usb, force_restart);
#ifdef HAVE_IAPUSB
USB_LEDGER_IAP_init();
#endif // HAVE_IAPUSB
#endif // HAVE_IO_USB

#ifdef HAVE_BLE
Expand Down Expand Up @@ -282,6 +288,13 @@ int os_io_rx_evt(unsigned char *buffer,
case SEPROXYHAL_TAG_USB_EP_XFER_EVENT:
status = USBD_LEDGER_rx_seph_evt(G_io_seph_buffer, length, buffer, buffer_max_length);
break;

#ifdef HAVE_IAPUSB
case SEPROXYHAL_TAG_USB_IAP_EVENT:
status
= USB_LEDGER_iap_rx_seph_evt(G_io_seph_buffer, length, buffer, buffer_max_length);
break;
#endif // HAVE_IAPUSB
#endif // HAVE_IO_USB

#ifdef HAVE_BLE
Expand Down Expand Up @@ -354,6 +367,12 @@ int os_io_tx_cmd(uint8_t type,
// TODO_IO test error code
USBD_LEDGER_send(USBD_LEDGER_CLASS_HID, type, buffer, length, 0);
break;

#ifdef HAVE_IAPUSB
case OS_IO_PACKET_TYPE_USB_IAP_APDU:
USB_LEDGER_IAP_send_apdu(buffer, length);
break;
#endif // HAVE_IAPUSB
#ifdef HAVE_WEBUSB
case OS_IO_PACKET_TYPE_USB_WEBUSB_APDU:
USBD_LEDGER_send(USBD_LEDGER_CLASS_WEBUSB, type, buffer, length, 0);
Expand Down Expand Up @@ -473,6 +492,7 @@ unsigned int os_io_handle_ux_event_reject_apdu(void)
case OS_IO_PACKET_TYPE_USB_CCID_APDU:
case OS_IO_PACKET_TYPE_BLE_APDU:
case OS_IO_PACKET_TYPE_NFC_APDU:
case OS_IO_PACKET_TYPE_USB_IAP_APDU:
os_io_tx_cmd(G_io_tx_buffer[0], err_buffer, sizeof(err_buffer), 0);
break;

Expand Down
1 change: 1 addition & 0 deletions io_legacy/include/os_io_legacy_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ typedef enum {
IO_APDU_MEDIA_RAW,
IO_APDU_MEDIA_U2F,
IO_APDU_MEDIA_CDC,
IO_APDU_MEDIA_IAP,
} io_apdu_media_t;

typedef enum {
Expand Down
5 changes: 5 additions & 0 deletions io_legacy/src/os_io_legacy.c
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,9 @@ static io_apdu_media_t get_media_from_apdu_type(apdu_type_t apdu_type)
if (apdu_type == APDU_TYPE_NFC) {
return IO_APDU_MEDIA_NFC;
}
if (apdu_type == APDU_TYPE_IAP) {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't it be under ifdef ?

return IO_APDU_MEDIA_IAP;
}
return IO_APDU_MEDIA_NONE;
}

Expand Down Expand Up @@ -153,6 +156,7 @@ void io_seproxyhal_io_heartbeat(void)
case OS_IO_PACKET_TYPE_USB_U2F_HID_APDU:
case OS_IO_PACKET_TYPE_BLE_APDU:
case OS_IO_PACKET_TYPE_NFC_APDU:
case OS_IO_PACKET_TYPE_USB_IAP_APDU:
os_io_tx_cmd(G_io_rx_buffer[0], err_buffer, sizeof(err_buffer), 0);
break;

Expand Down Expand Up @@ -392,6 +396,7 @@ int io_legacy_apdu_rx(uint8_t handle_ux_events)
case OS_IO_PACKET_TYPE_USB_U2F_HID_RAW:
case OS_IO_PACKET_TYPE_BLE_APDU:
case OS_IO_PACKET_TYPE_NFC_APDU:
case OS_IO_PACKET_TYPE_USB_IAP_APDU:
io_os_legacy_apdu_type = G_io_rx_buffer[0];
if (os_perso_is_pin_set() == BOLOS_TRUE
&& os_global_pin_is_validated() != BOLOS_TRUE) {
Expand Down
46 changes: 46 additions & 0 deletions lib_stusb/include/usb_iap.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*****************************************************************************
* (c) 2025 Ledger SAS.
*
* 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 USB_LEDGER_IAP_H
#define USB_LEDGER_IAP_H

/* Includes ------------------------------------------------------------------*/
#include <stdint.h>
#include "usbd_def.h"
#include "usbd_ledger_types.h"

/* Exported enumerations -----------------------------------------------------*/

/* Exported defines --------------------------------------------------------*/

/* Exported types, structures, unions ----------------------------------------*/

/* Exported macros------------------------------------------------------------*/

/* Exported variables --------------------------------------------------------*/

/* Exported functions --------------------------------------------------------*/

void USB_LEDGER_IAP_init(void);

int USB_LEDGER_iap_rx_seph_evt(uint8_t *seph_buffer,
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor: harmonize function naming

USB_LEDGER_iap_rx_seph_evt -> USB_LEDGER_IAP_rx_seph_evt

uint16_t seph_buffer_length,
uint8_t *apdu_buffer,
uint16_t apdu_buffer_max_length);

int USB_LEDGER_IAP_send_apdu(const uint8_t *apdu_buf, uint16_t apdu_buf_length);

#endif // USBD_LEDGER_WEBUSB_H
145 changes: 145 additions & 0 deletions lib_stusb/src/usb_iap.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
/*****************************************************************************
* (c) 2025 Ledger SAS.
*
* 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.
*****************************************************************************/

/* Includes ------------------------------------------------------------------*/
#include "ledger_protocol.h"
#include "usbd_ledger.h"
#include "usb_iap.h"
#include "seproxyhal_protocol.h"

/* Private enumerations ------------------------------------------------------*/

/* Private defines------------------------------------------------------------*/

/* Private types, structures, unions -----------------------------------------*/

/* Private macros-------------------------------------------------------------*/

/* Private functions prototypes ----------------------------------------------*/

/* Private variables ---------------------------------------------------------*/
static ledger_protocol_t protocol_data = {};

/* Exported variables --------------------------------------------------------*/

/* Private functions ---------------------------------------------------------*/
static void USB_LEDGER_IAP_send_packet(uint8_t *buffer, uint16_t length)
{
if (length) {
unsigned char hdr[3];
hdr[0] = SEPROXYHAL_TAG_USB_IAP_SEND;
hdr[1] = length >> 8;
hdr[2] = length;
os_io_tx_cmd(OS_IO_PACKET_TYPE_SEPH, hdr, 3, NULL);
os_io_tx_cmd(OS_IO_PACKET_TYPE_SEPH, buffer, length, NULL);
}
}

/* Exported functions --------------------------------------------------------*/

void USB_LEDGER_IAP_init(void)
{
memset(&protocol_data, 0, sizeof(protocol_data));
protocol_data.mtu = sizeof(USBD_LEDGER_protocol_chunk_buffer);

LEDGER_PROTOCOL_init(&protocol_data, OS_IO_PACKET_TYPE_USB_IAP_APDU);
}

int USB_LEDGER_IAP_send_apdu(const uint8_t *apdu_buf, uint16_t apdu_buf_length)
{
uint32_t status = -1;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be an int. Even better if the function could return int32_t instead !


ledger_protocol_result_t result = LEDGER_PROTOCOL_tx(&protocol_data,
apdu_buf,
apdu_buf_length,
USBD_LEDGER_protocol_chunk_buffer,
sizeof(USBD_LEDGER_protocol_chunk_buffer),
0);

if (result != LP_SUCCESS) {
goto error;
}
if (protocol_data.tx_chunk_length >= 2) {
USB_LEDGER_IAP_send_packet(USBD_LEDGER_protocol_chunk_buffer,
protocol_data.tx_chunk_length);
}

while (protocol_data.tx_apdu_buffer) {
result = LEDGER_PROTOCOL_tx(&protocol_data,
NULL,
0,
USBD_LEDGER_protocol_chunk_buffer,
sizeof(USBD_LEDGER_protocol_chunk_buffer),
0);
if (result != LP_SUCCESS) {
goto error;
}
if (protocol_data.tx_chunk_length >= 2) {
USB_LEDGER_IAP_send_packet(USBD_LEDGER_protocol_chunk_buffer,
protocol_data.tx_chunk_length);
}
}
status = 0;

error:
return status;
}

int USB_LEDGER_iap_rx_seph_evt(uint8_t *seph_buffer,
uint16_t seph_buffer_length,
uint8_t *apdu_buffer,
uint16_t apdu_buffer_max_length)
{
int status = -1;

if (seph_buffer[1] != SEPROXYHAL_TAG_USB_IAP_EVENT || seph_buffer_length < 4) {
goto error;
}

ledger_protocol_result_t result = LEDGER_PROTOCOL_rx(&protocol_data,
&seph_buffer[4],
seph_buffer_length - 4,
USBD_LEDGER_protocol_chunk_buffer,
sizeof(USBD_LEDGER_protocol_chunk_buffer),
apdu_buffer,
apdu_buffer_max_length,
0);
if (result != LP_SUCCESS) {
goto error;
}

if (protocol_data.tx_chunk_length > 0) {
// Tx chunck was generated while processing rx
// For example MTU request -> MTU response
USB_LEDGER_IAP_send_packet(USBD_LEDGER_protocol_chunk_buffer,
protocol_data.tx_chunk_length);
protocol_data.tx_chunk_length = 0;
}

if (protocol_data.rx_apdu_status == APDU_STATUS_COMPLETE) {
// Should not happen as it is verified by LEDGER_PROTOCOL_rx() already
if (apdu_buffer_max_length < protocol_data.rx_apdu_length) {
status = -1;
}
else {
status = protocol_data.rx_apdu_length;
}
protocol_data.rx_apdu_status = APDU_STATUS_WAITING;
}

error:
return status;
}