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 break;
81 default:
83 break;
84 }
85
86 return 1;
87}
88
90{
91 need_to_start_io = 1;
92}
93
95{
96 int status = 0;
97
98 if (need_to_start_io) {
99#ifndef USE_OS_IO_STACK
100 io_seproxyhal_io_heartbeat();
101 io_seproxyhal_io_heartbeat();
102 io_seproxyhal_io_heartbeat();
103#endif // USE_OS_IO_STACK
104 os_io_start();
105 need_to_start_io = 0;
106 }
107
108#ifdef FUZZING
109 for (uint8_t retries = 5; retries && status <= 0; retries--) {
110#else
111 while (status <= 0) {
112#endif
113 status = io_legacy_apdu_rx(1);
114 }
115
116 return status;
117}
118
119WEAK int io_send_response_buffers(const buffer_t *rdatalist, size_t count, uint16_t sw)
120{
121 int status = 0;
122 size_t length = 0;
123
124 if (rdatalist && count > 0) {
125 for (size_t i = 0; i < count; i++) {
126 const buffer_t *rdata = &rdatalist[i];
127
128 if (!buffer_copy(rdata, G_io_tx_buffer + length, sizeof(G_io_tx_buffer) - length - 2)) {
129 return io_send_sw(SW_WRONG_RESPONSE_LENGTH);
130 }
131 length += rdata->size - rdata->offset;
132 if (count > 1) {
133 PRINTF("<= FRAG (%u/%u) RData=%.*H\n", i + 1, count, rdata->size, rdata->ptr);
134 }
135 }
136 PRINTF("<= SW=%04X | RData=%.*H\n", sw, length, G_io_tx_buffer);
137 }
138 else {
139 PRINTF("<= SW=%04X | RData=\n", sw);
140 }
141
142 write_u16_be(G_io_tx_buffer, length, sw);
143 length += 2;
144
145#ifdef HAVE_SWAP
146 // If we are in swap mode and have validated a TX, we send it and immediately quit
148 PRINTF("Swap answer is processed. Send it\n");
149
150 if (io_legacy_apdu_tx(G_io_tx_buffer, length) >= 0) {
151 PRINTF("Returning to Exchange with status %d\n", (sw == SW_OK));
153 PRINTF("os_lib_end\n");
154 os_lib_end();
155 }
156 else {
157 PRINTF("Unrecoverable\n");
158#ifndef USE_OS_IO_STACK
159 os_io_stop();
160#endif // USE_OS_IO_STACK
161 os_sched_exit(-1);
162 }
163 }
164#endif // HAVE_SWAP
165
166 status = io_legacy_apdu_tx(G_io_tx_buffer, length);
167
168 if (status < 0) {
169 status = -1;
170 }
171
172 return status;
173}
174
175#ifdef STANDARD_APP_SYNC_RAPDU
176WEAK bool io_recv_and_process_event(void)
177{
178 int status = io_legacy_apdu_rx(1);
179 if (status > 0) {
180 return true;
181 }
182
183 return false;
184}
185#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:119
WEAK void io_init()
Definition io.c:89
WEAK int io_recv_command()
Definition io.c:94
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