Embedded SDK
Embedded SDK
Loading...
Searching...
No Matches
io.c
Go to the documentation of this file.
1/*****************************************************************************
2 * (c) 2021 Ledger SAS.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *****************************************************************************/
16
17#include <stdint.h>
18#include <string.h>
19
20#include "os.h"
21#include "os_io_legacy_types.h"
22#include "os_io_seph_cmd.h"
23#include "os_io_seph_ux.h"
24#include "os_io_default_apdu.h"
25#include "seproxyhal_protocol.h"
26#include "write.h"
27#include "offsets.h"
28#include "io.h"
29
30#ifdef HAVE_IO_USB
31#include "usbd_ledger.h"
32#endif // HAVE_IO_USB
33
34#ifdef HAVE_BLE
35#include "ble_ledger.h"
36#endif // HAVE_BLE
37
38#ifdef HAVE_NFC_READER
39#include "nfc_ledger.h"
40#endif // HAVE_NFC_READER
41
42#ifdef HAVE_SWAP
43#include "swap.h"
44#endif
45
46// TODO: Temporary workaround, at some point all status words should be defined by the SDK and
47// removed from the application
48#define SW_OK 0x9000
49#define SW_WRONG_RESPONSE_LENGTH 0xB000
50
51static uint8_t need_to_start_io;
52
53uint8_t G_io_seproxyhal_spi_buffer[OS_IO_SEPH_BUFFER_SIZE];
54
55#ifdef HAVE_BAGL
56WEAK void io_seproxyhal_display(const bagl_element_t *element)
57{
58 io_seph_ux_display_bagl_element(element);
59}
60#endif // HAVE_BAGL
61
62// This function can be used to declare a callback to SEPROXYHAL_TAG_TICKER_EVENT in the application
64
65WEAK unsigned char io_event(unsigned char channel)
66{
67 UNUSED(channel);
68 switch (G_io_seproxyhal_spi_buffer[0]) {
69 case SEPROXYHAL_TAG_BUTTON_PUSH_EVENT:
71 break;
72#ifdef HAVE_SE_TOUCH
73 case SEPROXYHAL_TAG_FINGER_EVENT:
75 break;
76#endif // HAVE_SE_TOUCH
77 case SEPROXYHAL_TAG_TICKER_EVENT:
80#ifdef HAVE_NFC_READER
81 io_nfc_ticker();
82 io_nfc_process_events();
83#endif // HAVE_NFC_READER
84 break;
85#ifdef HAVE_NFC_READER
86 case SEPROXYHAL_TAG_NFC_EVENT:
87 io_nfc_event();
88 io_nfc_process_events();
89 break;
90#endif // HAVE_NFC_READER
91
92 default:
94 break;
95 }
96
97 return 1;
98}
99
101{
102 need_to_start_io = 1;
103}
104
106{
107 int status = 0;
108
109 if (need_to_start_io) {
110#ifndef USE_OS_IO_STACK
111 io_seproxyhal_io_heartbeat();
112 io_seproxyhal_io_heartbeat();
113 io_seproxyhal_io_heartbeat();
114#endif // USE_OS_IO_STACK
115 os_io_start();
116 need_to_start_io = 0;
117 }
118
119#ifdef FUZZING
120 for (uint8_t retries = 5; retries && status <= 0; retries--) {
121#else
122 while (status <= 0) {
123#endif
124 status = io_legacy_apdu_rx(1);
125 }
126
127 return status;
128}
129
130WEAK int io_send_response_buffers(const buffer_t *rdatalist, size_t count, uint16_t sw)
131{
132 int status = 0;
133 size_t length = 0;
134
135 if (rdatalist && count > 0) {
136 for (size_t i = 0; i < count; i++) {
137 const buffer_t *rdata = &rdatalist[i];
138
139 if (!buffer_copy(rdata, G_io_tx_buffer + length, sizeof(G_io_tx_buffer) - length - 2)) {
140 return io_send_sw(SW_WRONG_RESPONSE_LENGTH);
141 }
142 length += rdata->size - rdata->offset;
143 if (count > 1) {
144 PRINTF("<= FRAG (%u/%u) RData=%.*H\n", i + 1, count, rdata->size, rdata->ptr);
145 }
146 }
147 PRINTF("<= SW=%04X | RData=%.*H\n", sw, length, G_io_tx_buffer);
148 }
149 else {
150 PRINTF("<= SW=%04X | RData=\n", sw);
151 }
152
153 write_u16_be(G_io_tx_buffer, length, sw);
154 length += 2;
155
156#ifdef HAVE_SWAP
157 // If we are in swap mode and have validated a TX, we send it and immediately quit
159 PRINTF("Swap answer is processed. Send it\n");
160
161 if (io_legacy_apdu_tx(G_io_tx_buffer, length) >= 0) {
162 PRINTF("Returning to Exchange with status %d\n", (sw == SW_OK));
164 PRINTF("os_lib_end\n");
165 os_lib_end();
166 }
167 else {
168 PRINTF("Unrecoverable\n");
169 os_sched_exit(-1);
170 }
171 }
172#endif // HAVE_SWAP
173
174 status = io_legacy_apdu_tx(G_io_tx_buffer, length);
175
176 if (status < 0) {
177 status = -1;
178 }
179
180 return status;
181}
182
183#ifdef STANDARD_APP_SYNC_RAPDU
184WEAK bool io_recv_and_process_event(void)
185{
186 int status = io_legacy_apdu_rx(1);
187 if (status > 0) {
188 return true;
189 }
190
191 return false;
192}
193#endif
bool buffer_copy(const buffer_t *buffer, uint8_t *out, size_t out_len)
Definition buffer.c:153
uint8_t G_io_seproxyhal_spi_buffer[OS_IO_SEPH_BUFFER_SIZE]
Definition io.c:53
WEAK unsigned char io_event(unsigned char channel)
Definition io.c:65
#define SW_WRONG_RESPONSE_LENGTH
Definition io.c:49
#define SW_OK
Definition io.c:48
WEAK int io_send_response_buffers(const buffer_t *rdatalist, size_t count, uint16_t sw)
Definition io.c:130
WEAK void io_init()
Definition io.c:100
WEAK int io_recv_command()
Definition io.c:105
WEAK void app_ticker_event_callback(void)
Definition io.c:63
#define WEAK
Definition macros.h:8
const uint8_t * ptr
Definition buffer.h:19
size_t size
Pointer to byte buffer.
Definition buffer.h:20
size_t offset
Size of byte buffer.
Definition buffer.h:21
volatile bool G_called_from_swap
volatile bool G_swap_response_ready
volatile uint8_t * G_swap_signing_return_value_address
#define UX_TICKER_EVENT(seph_packet, callback)
Definition ux_bagl.h:517
#define UX_FINGER_EVENT(seph_packet)
Definition ux_bagl.h:512
void io_seproxyhal_display(const bagl_element_t *element)
#define UX_DEFAULT_EVENT()
Definition ux_bagl.h:544
#define UX_BUTTON_PUSH_EVENT(seph_packet)
Definition ux_bagl.h:501
void write_u16_be(uint8_t *ptr, size_t offset, uint16_t value)
Definition write.c:20