Embedded SDK
Embedded SDK
ledger_ble.c
Go to the documentation of this file.
1 
2 /*******************************************************************************
3  * Ledger Nano S - Secure firmware
4  * (c) 2022 Ledger
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  ********************************************************************************/
18 
19 /* Includes ------------------------------------------------------------------*/
20 #include "os.h"
21 #include "os_settings.h"
22 #include "os_io_seproxyhal.h"
23 
24 #include "ble_hci_le.h"
25 #include "ble_hal_aci.h"
26 #include "ble_gap_aci.h"
27 #include "ble_l2cap_aci.h"
28 #include "ble_gatt_aci.h"
29 #include "ble_legacy.h"
30 
31 #include "lcx_rng.h"
32 
33 #include "ledger_protocol.h"
34 #include "ledger_ble.h"
35 
36 /* Private enumerations ------------------------------------------------------*/
37 typedef enum {
44 } ble_state_t;
45 
46 typedef enum {
62 
63 typedef enum {
71 
72 /* Private types, structures, unions -----------------------------------------*/
73 typedef struct {
77  uint8_t peer_address[6];
90 
91 typedef struct {
92  // General
94  char device_name[20 + 1];
96  uint8_t random_address[CONFIG_DATA_RANDOM_ADDRESS_LEN];
97 
98  // Init
100 
101  // Advertising configuration
104 
105  // HCI
107 
108  // GAP
116 
117  // L2CAP
119 
120  // ATT/GATT
126 
127  // PAIRING
129 
130  // APDU
133  uint8_t apdu_buffer[IO_APDU_BUFFER_SIZE];
134 
135  // TRANSFER MODE
138  uint8_t resp[2];
139 
141 
142 /* Private defines------------------------------------------------------------*/
143 #define MAX_MTU_SIZE 156
144 
145 #define BLE_SLAVE_CONN_INTERVAL_MIN 12 // 15ms
146 #define BLE_SLAVE_CONN_INTERVAL_MAX 24 // 30ms
147 
148 #define BLE_ADVERTISING_INTERVAL_MIN 48 // 30ms
149 #define BLE_ADVERTISING_INTERVAL_MAX 96 // 60ms
150 
151 #ifdef HAVE_PRINTF
152 #define LOG_BLE PRINTF
153 #else // !HAVE_PRINTF
154 #define LOG_BLE(...)
155 #endif // !HAVE_PRINTF
156 
157 /* Private macros-------------------------------------------------------------*/
158 
159 /* Private functions prototypes ----------------------------------------------*/
160 static void get_device_name(void);
161 static void configure_advertising_mngr(uint16_t opcode);
162 static void init_mngr(uint16_t opcode, const uint8_t *buffer, uint16_t length);
163 static void hci_evt_cmd_complete(const uint8_t *buffer, uint16_t length);
164 static void hci_evt_le_meta_evt(const uint8_t *buffer, uint16_t length);
165 static void hci_evt_vendor(const uint8_t *buffer, uint16_t length);
166 #ifdef HAVE_INAPP_BLE_PAIRING
167 static void end_pairing_ux(uint8_t pairing_ok);
168 static void ask_user_pairing_numeric_comparison(uint32_t code);
169 static void rsp_user_pairing_numeric_comparison(unsigned int status);
170 static void ask_user_pairing_passkey(void);
171 static void rsp_user_pairing_passkey(unsigned int status);
172 #endif // HAVE_INAPP_BLE_PAIRING
173 static void attribute_modified(const uint8_t *buffer, uint16_t length);
174 static void write_permit_request(const uint8_t *buffer, uint16_t length);
175 static void advertising_enable(uint8_t enable);
176 static void start_advertising(void);
177 static void notify_chunk(void);
178 static void check_transfer_mode(uint8_t enable);
179 
180 /* Exported variables --------------------------------------------------------*/
181 
182 /* Private variables ---------------------------------------------------------*/
183 // clang-format off
184 #ifdef TARGET_FLEX
185 const uint8_t service_uuid[16] = {0x72,0x65,0x67,0x64,0x65,0x4c,0x00,0x00,0x04,0x30,0x97,0x2C,0x00,0x34,0xD6,0x13,};
186 const uint8_t charUuidTX[16] = {0x72,0x65,0x67,0x64,0x65,0x4c,0x01,0x00,0x04,0x30,0x97,0x2C,0x00,0x34,0xD6,0x13,};
187 const uint8_t charUuidRX[16] = {0x72,0x65,0x67,0x64,0x65,0x4c,0x02,0x00,0x04,0x30,0x97,0x2C,0x00,0x34,0xD6,0x13,};
188 const uint8_t charUuidRX2[16] = {0x72,0x65,0x67,0x64,0x65,0x4c,0x03,0x00,0x04,0x30,0x97,0x2C,0x00,0x34,0xD6,0x13,};
189 #endif
190 
191 #ifdef TARGET_STAX
192 const uint8_t service_uuid[16] = {0x72,0x65,0x67,0x64,0x65,0x4c,0x00,0x00,0x04,0x60,0x97,0x2C,0x00,0x34,0xD6,0x13,};
193 const uint8_t charUuidTX[16] = {0x72,0x65,0x67,0x64,0x65,0x4c,0x01,0x00,0x04,0x60,0x97,0x2C,0x00,0x34,0xD6,0x13,};
194 const uint8_t charUuidRX[16] = {0x72,0x65,0x67,0x64,0x65,0x4c,0x02,0x00,0x04,0x60,0x97,0x2C,0x00,0x34,0xD6,0x13,};
195 const uint8_t charUuidRX2[16] = {0x72,0x65,0x67,0x64,0x65,0x4c,0x03,0x00,0x04,0x60,0x97,0x2C,0x00,0x34,0xD6,0x13,};
196 #endif
197 
198 #ifdef TARGET_NANOX
199 const uint8_t service_uuid[16] = {0x72,0x65,0x67,0x64,0x65,0x4c,0x00,0x00,0x04,0x00,0x97,0x2C,0x00,0x34,0xD6,0x13,};
200 const uint8_t charUuidTX[16] = {0x72,0x65,0x67,0x64,0x65,0x4c,0x01,0x00,0x04,0x00,0x97,0x2C,0x00,0x34,0xD6,0x13,};
201 const uint8_t charUuidRX[16] = {0x72,0x65,0x67,0x64,0x65,0x4c,0x02,0x00,0x04,0x00,0x97,0x2C,0x00,0x34,0xD6,0x13,};
202 const uint8_t charUuidRX2[16] = {0x72,0x65,0x67,0x64,0x65,0x4c,0x03,0x00,0x04,0x00,0x97,0x2C,0x00,0x34,0xD6,0x13,};
203 #endif
204 // clang-format on
205 
206 static ledger_protocol_t ledger_protocol_data;
207 static ledger_ble_data_t ledger_ble_data;
208 
209 /* Private functions ---------------------------------------------------------*/
210 static void copy_apdu_to_app(bool update_wait_status)
211 {
212  // `rx_apdu_length` is already checked to be less than
213  // `rx_apdu_buffer_max_length` in `process_apdu_chunk()`
214  memcpy(ledger_protocol_data.rx_dst_buffer,
215  ledger_protocol_data.rx_apdu_buffer,
216  ledger_protocol_data.rx_apdu_length);
217  G_io_app.apdu_length = ledger_protocol_data.rx_apdu_length;
218  G_io_app.apdu_state = APDU_BLE;
219  G_io_app.apdu_media = IO_APDU_MEDIA_BLE;
220  ledger_protocol_data.rx_apdu_length = 0;
221  if (update_wait_status) {
222  ledger_protocol_data.rx_apdu_status = APDU_STATUS_WAITING;
223  }
224 }
225 
226 static void get_device_name(void)
227 {
228  memset(ledger_ble_data.device_name, 0, sizeof(ledger_ble_data.device_name));
229  ledger_ble_data.device_name_length = os_setting_get(OS_SETTING_DEVICENAME,
230  (uint8_t *) ledger_ble_data.device_name,
231  sizeof(ledger_ble_data.device_name) - 1);
232 }
233 
234 static void configure_advertising_mngr(uint16_t opcode)
235 {
236  if ((ledger_ble_data.hci_cmd_opcode != 0xFFFF) && (opcode != ledger_ble_data.hci_cmd_opcode)) {
237  // Unexpected event => BLE_TODO
238  return;
239  }
240 
241  uint8_t buffer[31];
242  uint8_t index = 0;
243 
244  if (ledger_ble_data.adv_step == BLE_CONFIG_ADV_STEP_IDLE) {
245  ledger_ble_data.connection.connection_handle = 0xFFFF;
246  ledger_ble_data.advertising_enabled = 0;
247  LOG_BLE("CONFIGURE ADVERTISING START\n");
248  }
249  else if (ledger_ble_data.adv_step == (BLE_CONFIG_ADV_STEP_END - 1)) {
250  ledger_ble_data.advertising_enabled = 1;
251  }
252 
253  ledger_ble_data.adv_step++;
254  if ((ledger_ble_data.adv_step == (BLE_CONFIG_ADV_STEP_END - 1))
255  && (!ledger_ble_data.adv_enable)) {
256  ledger_ble_data.adv_step++;
257  }
258 
259  switch (ledger_ble_data.adv_step) {
261  // Flags
262  buffer[index++] = 2;
263  buffer[index++] = AD_TYPE_FLAGS;
264  buffer[index++] = FLAG_BIT_BR_EDR_NOT_SUPPORTED | FLAG_BIT_LE_GENERAL_DISCOVERABLE_MODE;
265 
266  // Complete Local Name
267  get_device_name();
268  buffer[index++] = ledger_ble_data.device_name_length + 1;
269  buffer[index++] = AD_TYPE_COMPLETE_LOCAL_NAME;
270  memcpy(&buffer[index], ledger_ble_data.device_name, ledger_ble_data.device_name_length);
271  index += ledger_ble_data.device_name_length;
272 
273  ledger_ble_data.hci_cmd_opcode = 0xfc8e;
274  aci_gap_update_adv_data(index, buffer);
275  break;
276 
278  // Incomplete List of 128-bit Service UUIDs
279  buffer[index++] = sizeof(service_uuid) + 1;
280  buffer[index++] = AD_TYPE_128_BIT_SERV_UUID;
281  memcpy(&buffer[index], service_uuid, sizeof(service_uuid));
282  index += sizeof(service_uuid);
283 
284  // Slave Connection Interval Range
285  buffer[index++] = 5;
286  buffer[index++] = AD_TYPE_SLAVE_CONN_INTERVAL;
287  buffer[index++] = BLE_SLAVE_CONN_INTERVAL_MIN;
288  buffer[index++] = 0;
289  buffer[index++] = BLE_SLAVE_CONN_INTERVAL_MAX;
290  buffer[index++] = 0;
291 
292  ledger_ble_data.hci_cmd_opcode = 0x2009;
293  hci_le_set_scan_response_data(index, buffer);
294  break;
295 
297  ledger_ble_data.hci_cmd_opcode = 0xfd06;
298  aci_gatt_update_char_value(ledger_ble_data.gap_service_handle,
300  0,
301  ledger_ble_data.device_name_length,
302  (uint8_t *) ledger_ble_data.device_name);
303  break;
304 
306  ledger_ble_data.hci_cmd_opcode = 0xfc83;
307  advertising_enable(1);
308  break;
309 
310  default:
311  LOG_BLE("CONFIGURE ADVERTISING END\n");
312  if (ledger_ble_data.state == BLE_STATE_CONFIGURE_ADVERTISING) {
313  ledger_ble_data.state = BLE_STATE_INITIALIZED;
314  }
315  break;
316  }
317 }
318 
319 static void init_mngr(uint16_t opcode, const uint8_t *buffer, uint16_t length)
320 {
321  UNUSED(length);
322 
323  if ((ledger_ble_data.hci_cmd_opcode != 0xFFFF) && (opcode != ledger_ble_data.hci_cmd_opcode)) {
324  // Unexpected event => BLE_TODO
325  return;
326  }
327 
328  if (ledger_ble_data.init_step == BLE_INIT_STEP_IDLE) {
329  LOG_BLE("INIT START\n");
330  }
331  else if ((length >= 6) && (ledger_ble_data.init_step == BLE_INIT_STEP_GAP_INIT)) {
332  ledger_ble_data.gap_service_handle = U2LE(buffer, 1);
333  ledger_ble_data.gap_device_name_characteristic_handle = U2LE(buffer, 3);
334  ledger_ble_data.gap_appearance_characteristic_handle = U2LE(buffer, 5);
335  }
336  else if ((length >= 2) && (ledger_ble_data.init_step == BLE_INIT_STEP_ADD_SERVICE)) {
337  ledger_ble_data.ledger_gatt_service_handle = U2LE(buffer, 1);
338  }
339  else if ((length >= 2)
341  ledger_ble_data.ledger_gatt_notification_characteristic_handle = U2LE(buffer, 1);
342  }
343  else if ((length >= 2)
344  && (ledger_ble_data.init_step == BLE_INIT_STEP_ADD_WRITE_CHARACTERISTIC)) {
345  ledger_ble_data.ledger_gatt_write_characteristic_handle = U2LE(buffer, 1);
346  }
347  else if ((length >= 2)
349  ledger_ble_data.ledger_gatt_write_cmd_characteristic_handle = U2LE(buffer, 1);
350  }
351  else if (ledger_ble_data.init_step == BLE_INIT_STEP_CONFIGURE_ADVERTISING) {
352  ledger_ble_data.adv_enable = !os_setting_get(OS_SETTING_PLANEMODE, NULL, 0);
353  configure_advertising_mngr(opcode);
354  if (ledger_ble_data.adv_step != BLE_CONFIG_ADV_STEP_END) {
355  return;
356  }
357  }
358 
359  ledger_ble_data.init_step++;
360 
361  switch (ledger_ble_data.init_step) {
362  case BLE_INIT_STEP_RESET:
363  hci_reset();
364  break;
365 
367  ledger_ble_data.hci_cmd_opcode = 0xfc0c;
368  aci_hal_write_config_data(CONFIG_DATA_RANDOM_ADDRESS_OFFSET,
369  CONFIG_DATA_RANDOM_ADDRESS_LEN,
370  ledger_ble_data.random_address);
371  break;
372 
374  ledger_ble_data.hci_cmd_opcode = 0xfd01;
375  aci_gatt_init();
376  break;
377 
379  ledger_ble_data.hci_cmd_opcode = 0xfc8a;
380  aci_gap_init(GAP_PERIPHERAL_ROLE,
381  PRIVACY_DISABLED,
382  sizeof(ledger_ble_data.device_name) - 1,
383  &ledger_ble_data.gap_service_handle,
384  &ledger_ble_data.gap_device_name_characteristic_handle,
385  &ledger_ble_data.gap_appearance_characteristic_handle);
386  break;
387 
389  ledger_ble_data.hci_cmd_opcode = 0xfc85;
390  aci_gap_set_io_capability(IO_CAP_DISPLAY_YES_NO);
391  break;
392 
394  ledger_ble_data.hci_cmd_opcode = 0xfc86;
395  aci_gap_set_authentication_requirement(
396  BONDING,
397  MITM_PROTECTION_REQUIRED,
398  0x01, // LE Secure connections pairing supported but optional
399  KEYPRESS_NOT_SUPPORTED,
400  MIN_ENCRY_KEY_SIZE + 1,
401  MAX_ENCRY_KEY_SIZE,
402  DONOT_USE_FIXED_PIN_FOR_PAIRING,
403  0,
404  STATIC_RANDOM_ADDR);
405  break;
406 
408  ledger_ble_data.hci_cmd_opcode = 0xfd02;
409  aci_gatt_add_service(UUID_TYPE_128,
410  (const Service_UUID_t *) service_uuid,
411  PRIMARY_SERVICE,
412  9,
413  &ledger_ble_data.ledger_gatt_service_handle);
414  break;
415 
417  ledger_ble_data.hci_cmd_opcode = 0xfd04;
418  aci_gatt_add_char(ledger_ble_data.ledger_gatt_service_handle,
419  UUID_TYPE_128,
420  (const Char_UUID_t *) charUuidTX,
421  MAX_MTU_SIZE,
422  CHAR_PROP_NOTIFY,
423  ATTR_PERMISSION_AUTHEN_WRITE,
424  GATT_DONT_NOTIFY_EVENTS,
425  MAX_ENCRY_KEY_SIZE,
426  CHAR_VALUE_LEN_VARIABLE,
428  break;
429 
431  ledger_ble_data.hci_cmd_opcode = 0xfd04;
432  aci_gatt_add_char(ledger_ble_data.ledger_gatt_service_handle,
433  UUID_TYPE_128,
434  (const Char_UUID_t *) charUuidRX,
435  MAX_MTU_SIZE,
436  CHAR_PROP_WRITE,
437  ATTR_PERMISSION_AUTHEN_WRITE,
438  GATT_NOTIFY_WRITE_REQ_AND_WAIT_FOR_APPL_RESP,
439  MAX_ENCRY_KEY_SIZE,
440  CHAR_VALUE_LEN_VARIABLE,
441  &ledger_ble_data.ledger_gatt_write_characteristic_handle);
442  break;
443 
445  ledger_ble_data.hci_cmd_opcode = 0xfd04;
446  aci_gatt_add_char(ledger_ble_data.ledger_gatt_service_handle,
447  UUID_TYPE_128,
448  (const Char_UUID_t *) charUuidRX2,
449  MAX_MTU_SIZE,
450  CHAR_PROP_WRITE_WITHOUT_RESP,
451  ATTR_PERMISSION_AUTHEN_WRITE,
452  GATT_NOTIFY_ATTRIBUTE_WRITE,
453  MAX_ENCRY_KEY_SIZE,
454  CHAR_VALUE_LEN_VARIABLE,
456  break;
457 
459  ledger_ble_data.hci_cmd_opcode = 0xfc0f;
460  aci_hal_set_tx_power_level(1, // High power (ignored)
461 #if defined(TARGET_STAX) || defined(TARGET_FLEX)
462  0x19); // 0 dBm
463 #else // !TARGET_STAX
464  0x07); // -14.1 dBm
465 #endif // !TARGET_STAX
466  break;
467 
469  ledger_ble_data.hci_cmd_opcode = 0xFFFF;
470  ledger_ble_data.adv_step = BLE_CONFIG_ADV_STEP_IDLE;
471  ledger_ble_data.adv_enable = !os_setting_get(OS_SETTING_PLANEMODE, NULL, 0);
472  configure_advertising_mngr(0);
473  break;
474 
475  case BLE_INIT_STEP_END:
476  LOG_BLE("INIT END\n");
477  if (ledger_ble_data.clear_pairing == 0xC1) {
478  ledger_ble_data.clear_pairing = 0;
479  aci_gap_clear_security_db();
480  }
481  G_io_app.ble_ready = 1;
482  ledger_ble_data.state = BLE_STATE_INITIALIZED;
483  break;
484 
485  default:
486  break;
487  }
488 }
489 
490 static void hci_evt_cmd_complete(const uint8_t *buffer, uint16_t length)
491 {
492  if (length < 3) {
493  return;
494  }
495 
496  uint16_t opcode = U2LE(buffer, 1);
497 
498  if (ledger_ble_data.state == BLE_STATE_INITIALIZING) {
499  init_mngr(opcode, &buffer[3], length);
500  }
501  else if (ledger_ble_data.state == BLE_STATE_CONFIGURE_ADVERTISING) {
502  configure_advertising_mngr(opcode);
503  }
504  else if (opcode == 0xfd26) {
505  // ACI_GATT_WRITE_RESP
506  if (ledger_ble_data.wait_write_resp_ack != 0) {
507  ledger_ble_data.wait_write_resp_ack = 0;
508  if (ledger_protocol_data.tx_chunk_length >= 2) {
509  G_io_app.ble_xfer_timeout = 2000;
510  notify_chunk();
511  }
512  }
513  }
514  else if (opcode == 0xfd06) {
515  // ACI_GATT_UPDATE_CHAR_VALUE
516  ledger_protocol_data.tx_chunk_length = 0;
517  if (ledger_ble_data.transfer_mode_enable) {
518  if ((ledger_protocol_data.rx_apdu_length)
519  && (ledger_protocol_data.rx_apdu_status == APDU_STATUS_COMPLETE)) {
520  copy_apdu_to_app(false);
521  }
522  }
523  else {
524  if (ledger_protocol_data.tx_apdu_buffer) {
525  LEDGER_PROTOCOL_tx(&ledger_protocol_data, NULL, 0);
526  notify_chunk();
527  }
528  if (!ledger_protocol_data.tx_apdu_buffer) {
529  ledger_protocol_data.tx_chunk_length = 0;
530  G_io_app.ble_xfer_timeout = 0;
531  G_io_app.apdu_state = APDU_IDLE;
532  if ((!ledger_ble_data.connection_updated)
533  && (ledger_ble_data.connection.conn_interval > BLE_SLAVE_CONN_INTERVAL_MIN)) {
534  ledger_ble_data.connection_updated = 1;
535  aci_l2cap_connection_parameter_update_req(
536  ledger_ble_data.connection.connection_handle,
539  ledger_ble_data.connection.conn_latency,
540  ledger_ble_data.connection.supervision_timeout);
541  }
542  }
543  }
544  }
545  else if ((opcode == 0xfc81) || (opcode == 0xfc83)) {
546  LOG_BLE("HCI_LE_SET_ADVERTISE_ENABLE %04X %d %d\n",
547  ledger_ble_data.connection.connection_handle,
548  G_io_app.disabling_advertising,
549  G_io_app.enabling_advertising);
550  if (ledger_ble_data.connection.connection_handle != 0xFFFF) {
551  if (G_io_app.disabling_advertising) {
552  // Connected & ordered to disable ble, force disconnection
553 #ifdef HAVE_INAPP_BLE_PAIRING
554  end_pairing_ux(BOLOS_UX_ASYNCHMODAL_PAIRING_STATUS_FAILED);
555 #endif // HAVE_INAPP_BLE_PAIRING
556  LEDGER_BLE_init();
557  }
558  }
559  else if (G_io_app.disabling_advertising) {
560  ledger_ble_data.advertising_enabled = 0;
561  if (G_io_app.name_changed) {
562  start_advertising();
563  }
564  }
565  else if (G_io_app.enabling_advertising) {
566  ledger_ble_data.advertising_enabled = 1;
567  }
568  else {
569  ledger_ble_data.advertising_enabled = 1;
570  }
571  G_io_app.disabling_advertising = 0;
572  G_io_app.enabling_advertising = 0;
573  }
574  else if (opcode == 0xfca5) {
575  LOG_BLE("ACI_GAP_NUMERIC_COMPARISON_VALUE_CONFIRM_YESNO\n");
576  }
577  else if (opcode == 0xfc94) {
578  LOG_BLE("ACI_GAP_CLEAR_SECURITY_DB\n");
579  }
580  else if (opcode == 0xfd25) {
581  LOG_BLE("ACI_GATT_CONFIRM_INDICATION\n");
582  }
583  else {
584  LOG_BLE("HCI EVT CMD COMPLETE 0x%04X\n", opcode);
585  }
586 }
587 
588 static void hci_evt_le_meta_evt(const uint8_t *buffer, uint16_t length)
589 {
590  if (!length) {
591  return;
592  }
593 
594  switch (buffer[0]) {
595  case HCI_LE_CONNECTION_COMPLETE_SUBEVT_CODE:
596  ledger_ble_data.connection.connection_handle = U2LE(buffer, 2);
597  ledger_ble_data.connection.role_slave = buffer[4];
598  ledger_ble_data.connection.peer_address_random = buffer[5];
599  memcpy(ledger_ble_data.connection.peer_address, &buffer[6], 6);
600  ledger_ble_data.connection.conn_interval = U2LE(buffer, 12);
601  ledger_ble_data.connection.conn_latency = U2LE(buffer, 14);
602  ledger_ble_data.connection.supervision_timeout = U2LE(buffer, 16);
603  ledger_ble_data.connection.master_clock_accuracy = buffer[18];
604  ledger_ble_data.connection.encrypted = 0;
605  ledger_ble_data.transfer_mode_enable = 0;
606  LOG_BLE("LE CONNECTION COMPLETE %04X - %04X- %04X- %04X\n",
607  ledger_ble_data.connection.connection_handle,
608  ledger_ble_data.connection.conn_interval,
609  ledger_ble_data.connection.conn_latency,
610  ledger_ble_data.connection.supervision_timeout);
611  ledger_protocol_data.mtu = ATT_MTU - 3 + 2;
612  ledger_ble_data.notifications_enabled = 0;
613  ledger_ble_data.advertising_enabled = 0;
614  ledger_protocol_data.mtu_negotiated = 0;
615  ledger_ble_data.connection_updated = 0;
616  break;
617 
618  case HCI_LE_CONNECTION_UPDATE_COMPLETE_SUBEVT_CODE:
619  ledger_ble_data.connection.connection_handle = U2LE(buffer, 2);
620  ledger_ble_data.connection.conn_interval = U2LE(buffer, 4);
621  ledger_ble_data.connection.conn_latency = U2LE(buffer, 6);
622  ledger_ble_data.connection.supervision_timeout = U2LE(buffer, 8);
623  LOG_BLE("LE CONNECTION UPDATE %04X - %04X- %04X- %04X\n",
624  ledger_ble_data.connection.connection_handle,
625  ledger_ble_data.connection.conn_interval,
626  ledger_ble_data.connection.conn_latency,
627  ledger_ble_data.connection.supervision_timeout);
628  break;
629 
630  case HCI_LE_DATA_LENGTH_CHANGE_SUBEVT_CODE:
631  if (U2LE(buffer, 1) == ledger_ble_data.connection.connection_handle) {
632  ledger_ble_data.connection.max_tx_octets = U2LE(buffer, 3);
633  ledger_ble_data.connection.max_tx_time = U2LE(buffer, 5);
634  ledger_ble_data.connection.max_rx_octets = U2LE(buffer, 7);
635  ledger_ble_data.connection.max_rx_time = U2LE(buffer, 9);
636  LOG_BLE("LE DATA LENGTH CHANGE %04X - %04X- %04X- %04X\n",
637  ledger_ble_data.connection.max_tx_octets,
638  ledger_ble_data.connection.max_tx_time,
639  ledger_ble_data.connection.max_rx_octets,
640  ledger_ble_data.connection.max_rx_time);
641  }
642  break;
643 
644  case HCI_LE_PHY_UPDATE_COMPLETE_SUBEVT_CODE:
645  if (U2LE(buffer, 2) == ledger_ble_data.connection.connection_handle) {
646  ledger_ble_data.connection.tx_phy = buffer[4];
647  ledger_ble_data.connection.rx_phy = buffer[5];
648  LOG_BLE("LE PHY UPDATE %02X - %02X\n",
649  ledger_ble_data.connection.tx_phy,
650  ledger_ble_data.connection.rx_phy);
651  }
652  break;
653 
654  default:
655  LOG_BLE("HCI LE META 0x%02X\n", buffer[0]);
656  break;
657  }
658 }
659 
660 static void hci_evt_vendor(const uint8_t *buffer, uint16_t length)
661 {
662  if (length < 4) {
663  return;
664  }
665 
666  uint16_t opcode = U2LE(buffer, 0);
667 
668  if (U2LE(buffer, 2) != ledger_ble_data.connection.connection_handle) {
669  return;
670  }
671 
672  switch (opcode) {
673 #ifdef HAVE_INAPP_BLE_PAIRING
674  case ACI_GAP_PAIRING_COMPLETE_VSEVT_CODE:
675  LOG_BLE("PAIRING");
676  switch (buffer[4]) {
677  case SMP_PAIRING_STATUS_SUCCESS:
678  LOG_BLE(" SUCCESS\n");
679  end_pairing_ux(BOLOS_UX_ASYNCHMODAL_PAIRING_STATUS_SUCCESS);
680  break;
681 
682  case SMP_PAIRING_STATUS_SMP_TIMEOUT:
683  LOG_BLE(" TIMEOUT\n");
684  end_pairing_ux(BOLOS_UX_ASYNCHMODAL_PAIRING_STATUS_TIMEOUT);
685  break;
686 
687  case SMP_PAIRING_STATUS_PAIRING_FAILED:
688  LOG_BLE(" FAILED : %02X\n", buffer[5]);
689  if (buffer[5] == 0x08) { // UNSPECIFIED_REASON
690  end_pairing_ux(BOLOS_UX_ASYNCHMODAL_PAIRING_STATUS_CANCELLED_FROM_REMOTE);
691  }
692  else {
693  end_pairing_ux(BOLOS_UX_ASYNCHMODAL_PAIRING_STATUS_FAILED);
694  }
695  break;
696 
697  default:
698  end_pairing_ux(BOLOS_UX_ASYNCHMODAL_PAIRING_STATUS_FAILED);
699  break;
700  }
701  ledger_ble_data.pairing_in_progress = 0;
702  break;
703 
704  case ACI_GAP_PASS_KEY_REQ_VSEVT_CODE:
705  LOG_BLE("PASSKEY REQ\n");
706  ask_user_pairing_passkey();
707  break;
708 
709  case ACI_GAP_NUMERIC_COMPARISON_VALUE_VSEVT_CODE:
710  LOG_BLE("NUMERIC COMP : %d\n", U4LE(buffer, 4));
711  ask_user_pairing_numeric_comparison(U4LE(buffer, 4));
712  break;
713 #endif // HAVE_INAPP_BLE_PAIRING
714 
715  case ACI_GATT_ATTRIBUTE_MODIFIED_VSEVT_CODE:
716  attribute_modified(&buffer[4], length - 4);
717  break;
718 
719  case ACI_ATT_EXCHANGE_MTU_RESP_VSEVT_CODE:
720  ledger_protocol_data.mtu = U2LE(buffer, 4) - 3 + 2;
721  ledger_protocol_data.mtu_negotiated = 1;
722  LOG_BLE("MTU : %d\n", U2LE(buffer, 4));
723  break;
724 
725  case ACI_L2CAP_CONNECTION_UPDATE_RESP_VSEVT_CODE:
726  LOG_BLE("CONNECTION UPDATE RESP %d\n", buffer[4]);
727  break;
728 
729  case ACI_GATT_WRITE_PERMIT_REQ_VSEVT_CODE:
730  write_permit_request(&buffer[4], length - 4);
731  break;
732 
733  case ACI_GATT_INDICATION_VSEVT_CODE:
734  LOG_BLE("INDICATION EVT\n");
735  aci_gatt_confirm_indication(ledger_ble_data.connection.connection_handle);
736  break;
737 
738  case ACI_GATT_PROC_COMPLETE_VSEVT_CODE:
739  LOG_BLE("PROCEDURE COMPLETE\n");
740  break;
741 
742  case ACI_GATT_PROC_TIMEOUT_VSEVT_CODE:
743  LOG_BLE("PROCEDURE TIMEOUT\n");
744 #ifdef HAVE_INAPP_BLE_PAIRING
745  end_pairing_ux(BOLOS_UX_ASYNCHMODAL_PAIRING_STATUS_FAILED);
746 #endif // HAVE_INAPP_BLE_PAIRING
747  LEDGER_BLE_init();
748  break;
749 
750  default:
751  LOG_BLE("HCI VENDOR 0x%04X\n", opcode);
752  break;
753  }
754 }
755 
756 #ifdef HAVE_INAPP_BLE_PAIRING
757 static void end_pairing_ux(uint8_t pairing_ok)
758 {
759  bolos_ux_params_t ux_params;
760 
761  LOG_BLE("end_pairing_ux : %d (%d)\n", pairing_ok, ledger_ble_data.pairing_in_progress);
762  if (ledger_ble_data.pairing_in_progress) {
763  ux_params.ux_id = BOLOS_UX_ASYNCHMODAL_PAIRING_CANCEL;
764  ux_params.u.pairing_status.pairing_ok = pairing_ok;
765  ux_params.len = sizeof(ux_params.u.pairing_status);
766  G_io_asynch_ux_callback.asynchmodal_end_callback = NULL;
767  os_ux(&ux_params);
768  }
769 }
770 
771 static void ask_user_pairing_numeric_comparison(uint32_t code)
772 {
773  bolos_ux_params_t ux_params;
774 
775  ux_params.u.pairing_request.type = BOLOS_UX_ASYNCHMODAL_PAIRING_REQUEST_NUMCOMP;
776  ux_params.ux_id = BOLOS_UX_ASYNCHMODAL_PAIRING_REQUEST;
777  ux_params.len = sizeof(ux_params.u.pairing_request);
778  ledger_ble_data.pairing_in_progress = 1;
779  ux_params.u.pairing_request.pairing_info_len = 6;
780  SPRINTF(ux_params.u.pairing_request.pairing_info, "%06d", (unsigned int) code);
781 #if defined(TARGET_STAX) || defined(TARGET_FLEX)
782  G_io_asynch_ux_callback.asynchmodal_end_callback = NULL;
783 #else // !TARGET_STAX
784  G_io_asynch_ux_callback.asynchmodal_end_callback = rsp_user_pairing_numeric_comparison;
785 #endif // !TARGET_STAX
786  os_ux(&ux_params);
787 }
788 
789 static void rsp_user_pairing_numeric_comparison(unsigned int status)
790 {
791  if (status == BOLOS_UX_OK) {
792  end_pairing_ux(BOLOS_UX_ASYNCHMODAL_PAIRING_STATUS_CONFIRM_CODE_YES);
793  aci_gap_numeric_comparison_value_confirm_yesno(ledger_ble_data.connection.connection_handle,
794  1);
795  }
796  else if (status == BOLOS_UX_IGNORE) {
797  ledger_ble_data.pairing_in_progress = 0;
798  aci_gap_numeric_comparison_value_confirm_yesno(ledger_ble_data.connection.connection_handle,
799  0);
800  }
801  else {
802  end_pairing_ux(BOLOS_UX_ASYNCHMODAL_PAIRING_STATUS_CONFIRM_CODE_NO);
803  aci_gap_numeric_comparison_value_confirm_yesno(ledger_ble_data.connection.connection_handle,
804  0);
805  }
806 }
807 
808 static void ask_user_pairing_passkey(void)
809 {
810  bolos_ux_params_t ux_params;
811 
812  ux_params.u.pairing_request.type = BOLOS_UX_ASYNCHMODAL_PAIRING_REQUEST_PASSKEY;
813  ux_params.ux_id = BOLOS_UX_ASYNCHMODAL_PAIRING_REQUEST;
814  ux_params.len = sizeof(ux_params.u.pairing_request);
815  ledger_ble_data.pairing_in_progress = 1;
816  ledger_ble_data.pairing_code = cx_rng_u32_range_func(0, 1000000, cx_rng_u32);
817  ux_params.u.pairing_request.pairing_info_len = 6;
818  SPRINTF(ux_params.u.pairing_request.pairing_info, "%06d", ledger_ble_data.pairing_code);
819 #if defined(TARGET_STAX) || defined(TARGET_FLEX)
820  G_io_asynch_ux_callback.asynchmodal_end_callback = NULL;
821 #else // !TARGET_STAX
822  G_io_asynch_ux_callback.asynchmodal_end_callback = rsp_user_pairing_passkey;
823 #endif // !TARGET_STAX
824  os_ux(&ux_params);
825 }
826 
827 static void rsp_user_pairing_passkey(unsigned int status)
828 {
829  if (status == BOLOS_UX_OK) {
830  end_pairing_ux(BOLOS_UX_ASYNCHMODAL_PAIRING_STATUS_ACCEPT_PASSKEY);
831  ledger_ble_data.pairing_code = cx_rng_u32_range_func(0, 1000000, cx_rng_u32);
832  aci_gap_pass_key_resp(ledger_ble_data.connection.connection_handle,
833  ledger_ble_data.pairing_code);
834  }
835  else if (status == BOLOS_UX_IGNORE) {
836  ledger_ble_data.pairing_in_progress = 0;
837  }
838  else {
839  end_pairing_ux(BOLOS_UX_ASYNCHMODAL_PAIRING_STATUS_CANCEL_PASSKEY);
840  }
841 }
842 #endif // HAVE_INAPP_BLE_PAIRING
843 
844 static void attribute_modified(const uint8_t *buffer, uint16_t length)
845 {
846  if (length < 6) {
847  return;
848  }
849 
850  uint16_t att_handle = U2LE(buffer, 0);
851  uint16_t offset = U2LE(buffer, 2);
852  uint16_t att_data_length = U2LE(buffer, 4);
853 
854  if ((att_handle == ledger_ble_data.ledger_gatt_notification_characteristic_handle + 2)
855  && (att_data_length == 2) && (offset == 0)) {
856  // Peer device registering/unregistering for notifications
857  if (U2LE(buffer, 6) != 0) {
858  LOG_BLE("REGISTERED FOR NOTIFICATIONS\n");
859  ledger_ble_data.notifications_enabled = 1;
860  if (!ledger_protocol_data.mtu_negotiated) {
861  aci_gatt_exchange_config(ledger_ble_data.connection.connection_handle);
862  }
863  }
864  else {
865  LOG_BLE("NOT REGISTERED FOR NOTIFICATIONS\n");
866  ledger_ble_data.notifications_enabled = 0;
867  }
868  }
869  else if ((att_handle == ledger_ble_data.ledger_gatt_write_cmd_characteristic_handle + 1)
870  && (ledger_ble_data.notifications_enabled) && (ledger_ble_data.connection.encrypted)
871  && (att_data_length)) {
872  LOG_BLE("WRITE CMD %d\n", length - 4);
873  LEDGER_PROTOCOL_rx(&ledger_protocol_data, &buffer[4], length - 4);
874 
875  if (ledger_protocol_data.rx_apdu_status == APDU_STATUS_COMPLETE) {
876  check_transfer_mode(G_io_app.transfer_mode);
877  if (ledger_ble_data.transfer_mode_enable) {
878  if (U2BE(ledger_ble_data.resp, 0) != SWO_SUCCESS) {
879  LOG_BLE("Transfer failed 0x%04x\n", U2BE(ledger_ble_data.resp, 0));
880  G_io_app.transfer_mode = 0;
881  check_transfer_mode(G_io_app.transfer_mode);
882  copy_apdu_to_app(true);
883  }
884  else if (ledger_ble_data.resp_length) {
885  LEDGER_PROTOCOL_tx(
886  &ledger_protocol_data, ledger_ble_data.resp, ledger_ble_data.resp_length);
887  ledger_ble_data.resp_length = 0;
888  notify_chunk();
889  }
890  }
891  else {
892  copy_apdu_to_app(true);
893  }
894  }
895  else if (ledger_protocol_data.tx_chunk_length >= 2) {
896  G_io_app.ble_xfer_timeout = 2000;
897  notify_chunk();
898  G_io_app.apdu_state = APDU_BLE;
899  }
900  }
901  else {
902  LOG_BLE("ATT MODIFIED %04X %d bytes at offset %d\n", att_handle, att_data_length, offset);
903  }
904 }
905 
906 static void write_permit_request(const uint8_t *buffer, uint16_t length)
907 {
908  if (length < 3) {
909  return;
910  }
911 
912  uint16_t att_handle = U2LE(buffer, 0);
913  uint8_t data_length = buffer[2];
914 
915  ledger_ble_data.wait_write_resp_ack = 1;
916 
917  if ((att_handle == ledger_ble_data.ledger_gatt_write_characteristic_handle + 1)
918  && (ledger_ble_data.notifications_enabled) && (ledger_ble_data.connection.encrypted)
919  && (data_length)) {
920  LEDGER_PROTOCOL_rx(&ledger_protocol_data, &buffer[1], length - 1);
921  aci_gatt_write_resp(ledger_ble_data.connection.connection_handle,
922  att_handle,
923  0,
924  HCI_SUCCESS_ERR_CODE,
925  data_length,
926  &buffer[3]);
927  if (ledger_protocol_data.rx_apdu_status == APDU_STATUS_COMPLETE) {
928  copy_apdu_to_app(true);
929  }
930  }
931  else {
932  LOG_BLE("ATT WRITE %04X %d bytes\n", att_handle, data_length);
933  ledger_protocol_data.tx_chunk_length = 0;
934  aci_gatt_write_resp(ledger_ble_data.connection.connection_handle,
935  att_handle,
936  0,
937  HCI_SUCCESS_ERR_CODE,
938  data_length,
939  &buffer[3]);
940  }
941 }
942 
943 static void advertising_enable(uint8_t enable)
944 {
945  if (enable) {
946  uint8_t buffer[31];
947 
948  get_device_name();
949  buffer[0] = AD_TYPE_COMPLETE_LOCAL_NAME;
950  memcpy(&buffer[1], ledger_ble_data.device_name, ledger_ble_data.device_name_length);
951  aci_gap_set_discoverable(ADV_IND,
954  RANDOM_ADDR,
955  NO_WHITE_LIST_USE,
956  ledger_ble_data.device_name_length + 1,
957  buffer,
958  0,
959  NULL,
960  0,
961  0);
962  }
963  else {
964  aci_gap_set_non_discoverable();
965  }
966 }
967 
968 static void start_advertising(void)
969 {
970  if (G_io_app.name_changed) {
971  G_io_app.name_changed = 0;
972  ledger_ble_data.state = BLE_STATE_CONFIGURE_ADVERTISING;
973  ledger_ble_data.adv_step = BLE_CONFIG_ADV_STEP_IDLE;
974  }
975  else {
976  ledger_ble_data.state = BLE_STATE_CONFIGURE_ADVERTISING;
977  ledger_ble_data.adv_step = BLE_CONFIG_ADV_STEP_START - 1;
978  }
979  ledger_ble_data.hci_cmd_opcode = 0xFFFF;
980  ledger_ble_data.adv_enable = !os_setting_get(OS_SETTING_PLANEMODE, NULL, 0);
981  configure_advertising_mngr(0);
982 }
983 
984 static void notify_chunk(void)
985 {
986  if (ledger_protocol_data.tx_chunk_length >= 2) {
987  aci_gatt_update_char_value(ledger_ble_data.ledger_gatt_service_handle,
989  0,
990  ledger_protocol_data.tx_chunk_length - 2,
991  &ledger_protocol_data.tx_chunk[2]);
992  }
993 }
994 
995 static void check_transfer_mode(uint8_t enable)
996 {
997  if (ledger_ble_data.transfer_mode_enable != enable) {
998  LOG_BLE("LEDGER_BLE_set_transfer_mode %d\n", enable);
999  }
1000 
1001  if ((ledger_ble_data.transfer_mode_enable == 0) && (enable != 0)) {
1002  ledger_ble_data.resp_length = 2;
1003  U2BE_ENCODE(ledger_ble_data.resp, 0, SWO_SUCCESS);
1004  }
1005 
1006  ledger_ble_data.transfer_mode_enable = enable;
1007 }
1008 
1009 /* Exported functions --------------------------------------------------------*/
1011 {
1012  G_io_app.enabling_advertising = 0;
1013  G_io_app.disabling_advertising = 0;
1014 
1015  if (ledger_ble_data.clear_pairing == 0xC1) {
1016  memset(&ledger_ble_data, 0, sizeof(ledger_ble_data));
1017  ledger_ble_data.clear_pairing = 0xC1;
1018  }
1019  else {
1020  memset(&ledger_ble_data, 0, sizeof(ledger_ble_data));
1021  }
1022 
1023  LEDGER_BLE_get_mac_address(ledger_ble_data.random_address);
1024  ledger_ble_data.hci_cmd_opcode = 0xFFFF;
1025  ledger_ble_data.state = BLE_STATE_INITIALIZING;
1026  ledger_ble_data.init_step = BLE_INIT_STEP_IDLE;
1027 
1028  memset(&ledger_protocol_data, 0, sizeof(ledger_protocol_data));
1029  ledger_protocol_data.rx_apdu_buffer = ledger_ble_data.apdu_buffer;
1030  ledger_protocol_data.rx_apdu_buffer_max_length = sizeof(ledger_ble_data.apdu_buffer);
1031 #ifdef HAVE_LOCAL_APDU_BUFFER
1032  ledger_protocol_data.rx_dst_buffer = NULL;
1033 #else
1034  ledger_protocol_data.rx_dst_buffer = G_io_apdu_buffer;
1035 #endif
1036  LEDGER_PROTOCOL_init(&ledger_protocol_data);
1037 
1038  init_mngr(0, NULL, 0);
1039 }
1040 
1041 void LEDGER_BLE_set_recv_buffer(uint8_t *buffer, uint16_t buffer_length)
1042 {
1043  ledger_protocol_data.rx_dst_buffer = buffer;
1044  ledger_protocol_data.rx_apdu_buffer_max_length
1045  = MIN(buffer_length, sizeof(ledger_ble_data.apdu_buffer));
1046 }
1047 
1048 void LEDGER_BLE_send(const uint8_t *packet, uint16_t packet_length)
1049 {
1050  if ((ledger_ble_data.transfer_mode_enable != 0) && (packet_length == 2)) {
1051  G_io_app.apdu_state = APDU_IDLE;
1052  ledger_ble_data.resp_length = 2;
1053  ledger_ble_data.resp[0] = packet[0];
1054  ledger_ble_data.resp[1] = packet[1];
1055  if (ledger_protocol_data.rx_apdu_length) {
1056  LEDGER_PROTOCOL_tx(&ledger_protocol_data, packet, packet_length);
1057  notify_chunk();
1058  }
1059  }
1060  else {
1061  if ((ledger_ble_data.resp_length != 0) && (U2BE(ledger_ble_data.resp, 0) != SWO_SUCCESS)) {
1062  LEDGER_PROTOCOL_tx(
1063  &ledger_protocol_data, ledger_ble_data.resp, ledger_ble_data.resp_length);
1064  }
1065  else {
1066  LEDGER_PROTOCOL_tx(&ledger_protocol_data, packet, packet_length);
1067  }
1068  ledger_ble_data.resp_length = 0;
1069 
1070  if (ledger_ble_data.wait_write_resp_ack == 0) {
1071  notify_chunk();
1072  }
1073  }
1074 }
1075 
1076 void LEDGER_BLE_receive(const uint8_t *spi_buffer)
1077 {
1078  if (spi_buffer[3] == HCI_EVENT_PKT_TYPE) {
1079  switch (spi_buffer[4]) {
1080  case HCI_DISCONNECTION_COMPLETE_EVT_CODE:
1081  LOG_BLE("HCI DISCONNECTION COMPLETE code %02X\n", spi_buffer[9]);
1082  ledger_ble_data.connection.connection_handle = 0xFFFF;
1083  ledger_ble_data.advertising_enabled = 0;
1084  ledger_ble_data.connection.encrypted = 0;
1085  ledger_ble_data.transfer_mode_enable = 0;
1086  G_io_app.transfer_mode = 0;
1087 #ifdef HAVE_INAPP_BLE_PAIRING
1088  end_pairing_ux(BOLOS_UX_ASYNCHMODAL_PAIRING_STATUS_FAILED);
1089 #endif // HAVE_INAPP_BLE_PAIRING
1090  if (spi_buffer[9] != 0x28) { // Error code : Instant Passed
1091  start_advertising();
1092  }
1093  else {
1094  // Workaround to avoid unexpected start advertising event in loop (seems to be a
1095  // bug in the stack)
1096  LEDGER_BLE_init();
1097  }
1098  break;
1099 
1100  case HCI_ENCRYPTION_CHANGE_EVT_CODE:
1101  if (U2LE(spi_buffer, 7) == ledger_ble_data.connection.connection_handle) {
1102  if (spi_buffer[9]) {
1103  LOG_BLE("Link encrypted\n");
1104  ledger_ble_data.connection.encrypted = 1;
1105  }
1106  else {
1107  LOG_BLE("Link not encrypted\n");
1108  ledger_ble_data.connection.encrypted = 0;
1109  }
1110  }
1111  else {
1112  LOG_BLE("HCI ENCRYPTION CHANGE EVT %d on connection handle \n",
1113  spi_buffer[9],
1114  U2LE(spi_buffer, 7));
1115  }
1116  break;
1117 
1118  case HCI_COMMAND_COMPLETE_EVT_CODE:
1119  hci_evt_cmd_complete(&spi_buffer[6], spi_buffer[5]);
1120  break;
1121 
1122  case HCI_COMMAND_STATUS_EVT_CODE:
1123  LOG_BLE("HCI COMMAND_STATUS\n");
1124  break;
1125 
1126  case HCI_ENCRYPTION_KEY_REFRESH_COMPLETE_EVT_CODE:
1127  LOG_BLE("HCI KEY_REFRESH_COMPLETE\n");
1128  break;
1129 
1130  case HCI_LE_META_EVT_CODE:
1131  hci_evt_le_meta_evt(&spi_buffer[6], spi_buffer[5]);
1132  break;
1133 
1134  case HCI_VENDOR_SPECIFIC_DEBUG_EVT_CODE:
1135  hci_evt_vendor(&spi_buffer[6], spi_buffer[5]);
1136  break;
1137 
1138  default:
1139  break;
1140  }
1141  }
1142 }
1143 
1145 {
1146  if ((G_io_app.name_changed) && (G_io_app.ble_ready) && (!enable)
1147  && (ledger_ble_data.connection.connection_handle != 0xFFFF)) {
1148  G_io_app.name_changed = 0;
1149  }
1150  else if (G_io_app.ble_ready) {
1151  if (enable) {
1152  G_io_app.enabling_advertising = 1;
1153  G_io_app.disabling_advertising = 0;
1154  }
1155  else {
1156  G_io_app.enabling_advertising = 0;
1157  G_io_app.disabling_advertising = 1;
1158  }
1159  advertising_enable(enable);
1160  }
1161 }
1162 
1164 {
1165  if (G_io_app.ble_ready) {
1166  if (ledger_ble_data.connection.connection_handle != 0xFFFF) {
1167  // Connected => force disconnection before clearing
1168  ledger_ble_data.clear_pairing = 0xC1;
1169  LEDGER_BLE_init();
1170  }
1171  else {
1172  aci_gap_clear_security_db();
1173  }
1174  }
1175 }
1176 
1178 {
1179  if (ledger_ble_data.pairing_in_progress == 1) {
1180  rsp_user_pairing_numeric_comparison(status);
1181  }
1182  else if (ledger_ble_data.pairing_in_progress == 2) {
1183  rsp_user_pairing_passkey(status);
1184  }
1185 }
1186 
1187 int hci_send_req(struct hci_request *p_cmd, uint8_t async)
1188 {
1189  UNUSED(async);
1190 
1191  uint16_t opcode = ((p_cmd->ocf) & 0x03ff) | ((p_cmd->ogf) << 10);
1192 
1193  uint8_t tag_buffer[5];
1194  tag_buffer[0] = SEPROXYHAL_TAG_BLE_SEND;
1195  tag_buffer[1] = (p_cmd->clen + 2) >> 8;
1196  tag_buffer[2] = (p_cmd->clen + 2);
1197  tag_buffer[3] = opcode >> 8;
1198  tag_buffer[4] = opcode;
1199  io_seproxyhal_spi_send(tag_buffer, 5);
1200  io_seproxyhal_spi_send(p_cmd->cparam, p_cmd->clen);
1201  return 0;
1202 }
1203 
1204 void BLE_power(unsigned char powered, const char *discovered_name)
1205 {
1206  UNUSED(discovered_name);
1207 
1208  LOG_BLE("BLE_power %d\n", powered);
1209  if (powered) {
1210  LEDGER_BLE_init();
1211  }
1212 }
Random Number Generation.
#define BLE_ADVERTISING_INTERVAL_MIN
Definition: ledger_ble.c:148
ble_config_adv_step_t
Definition: ledger_ble.c:63
@ BLE_CONFIG_ADV_STEP_START
Definition: ledger_ble.c:68
@ BLE_CONFIG_ADV_STEP_SET_ADV_DATAS
Definition: ledger_ble.c:65
@ BLE_CONFIG_ADV_STEP_SET_GAP_DEVICE_NAME
Definition: ledger_ble.c:67
@ BLE_CONFIG_ADV_STEP_SET_SCAN_RSP_DATAS
Definition: ledger_ble.c:66
@ BLE_CONFIG_ADV_STEP_END
Definition: ledger_ble.c:69
@ BLE_CONFIG_ADV_STEP_IDLE
Definition: ledger_ble.c:64
#define LOG_BLE(...)
Definition: ledger_ble.c:154
#define BLE_ADVERTISING_INTERVAL_MAX
Definition: ledger_ble.c:149
void LEDGER_BLE_receive(const uint8_t *spi_buffer)
Definition: ledger_ble.c:1076
void BLE_power(unsigned char powered, const char *discovered_name)
Definition: ledger_ble.c:1204
void LEDGER_BLE_reset_pairings(void)
Definition: ledger_ble.c:1163
int hci_send_req(struct hci_request *p_cmd, uint8_t async)
Definition: ledger_ble.c:1187
ble_state_t
Definition: ledger_ble.c:37
@ BLE_STATE_DISCONNECTING
Definition: ledger_ble.c:43
@ BLE_STATE_CONFIGURE_ADVERTISING
Definition: ledger_ble.c:40
@ BLE_STATE_INITIALIZING
Definition: ledger_ble.c:38
@ BLE_STATE_CONNECTED
Definition: ledger_ble.c:42
@ BLE_STATE_INITIALIZED
Definition: ledger_ble.c:39
@ BLE_STATE_CONNECTING
Definition: ledger_ble.c:41
#define MAX_MTU_SIZE
Definition: ledger_ble.c:143
void LEDGER_BLE_enable_advertising(uint8_t enable)
Definition: ledger_ble.c:1144
ble_init_step_t
Definition: ledger_ble.c:46
@ BLE_INIT_STEP_SET_IO_CAPABILITIES
Definition: ledger_ble.c:52
@ BLE_INIT_STEP_ADD_NOTIFICATION_CHARACTERISTIC
Definition: ledger_ble.c:55
@ BLE_INIT_STEP_SET_AUTH_REQUIREMENTS
Definition: ledger_ble.c:53
@ BLE_INIT_STEP_CONFIGURE_ADVERTISING
Definition: ledger_ble.c:59
@ BLE_INIT_STEP_ADD_WRITE_CHARACTERISTIC
Definition: ledger_ble.c:56
@ BLE_INIT_STEP_SET_TX_POWER_LEVEL
Definition: ledger_ble.c:58
@ BLE_INIT_STEP_END
Definition: ledger_ble.c:60
@ BLE_INIT_STEP_IDLE
Definition: ledger_ble.c:47
@ BLE_INIT_STEP_STATIC_ADDRESS
Definition: ledger_ble.c:49
@ BLE_INIT_STEP_GAP_INIT
Definition: ledger_ble.c:51
@ BLE_INIT_STEP_ADD_WRITE_COMMAND_CHARACTERISTIC
Definition: ledger_ble.c:57
@ BLE_INIT_STEP_ADD_SERVICE
Definition: ledger_ble.c:54
@ BLE_INIT_STEP_GATT_INIT
Definition: ledger_ble.c:50
@ BLE_INIT_STEP_RESET
Definition: ledger_ble.c:48
void LEDGER_BLE_set_recv_buffer(uint8_t *buffer, uint16_t buffer_length)
Definition: ledger_ble.c:1041
#define BLE_SLAVE_CONN_INTERVAL_MIN
Definition: ledger_ble.c:145
void LEDGER_BLE_send(const uint8_t *packet, uint16_t packet_length)
Definition: ledger_ble.c:1048
void LEDGER_BLE_accept_pairing(uint8_t status)
Definition: ledger_ble.c:1177
void LEDGER_BLE_init(void)
Definition: ledger_ble.c:1010
#define BLE_SLAVE_CONN_INTERVAL_MAX
Definition: ledger_ble.c:146
#define LEDGER_BLE_get_mac_address(address)
Definition: ledger_ble.h:45
#define MIN(x, y)
Definition: nbgl_types.h:79
uint8_t peer_address_random
Definition: ledger_ble.c:76
uint16_t max_rx_time
Definition: ledger_ble.c:87
uint8_t tx_phy
Definition: ledger_ble.c:82
uint16_t connection_handle
Definition: ledger_ble.c:74
uint8_t encrypted
Definition: ledger_ble.c:88
uint8_t peer_address[6]
Definition: ledger_ble.c:77
uint16_t supervision_timeout
Definition: ledger_ble.c:80
uint16_t conn_interval
Definition: ledger_ble.c:78
uint16_t max_tx_octets
Definition: ledger_ble.c:84
uint16_t max_tx_time
Definition: ledger_ble.c:85
uint16_t max_rx_octets
Definition: ledger_ble.c:86
uint8_t master_clock_accuracy
Definition: ledger_ble.c:81
uint16_t conn_latency
Definition: ledger_ble.c:79
uint8_t role_slave
Definition: ledger_ble.c:75
uint8_t rx_phy
Definition: ledger_ble.c:83
uint8_t random_address[CONFIG_DATA_RANDOM_ADDRESS_LEN]
Definition: ledger_ble.c:96
uint8_t pairing_in_progress
Definition: ledger_ble.c:115
uint8_t apdu_buffer[IO_APDU_BUFFER_SIZE]
Definition: ledger_ble.c:133
ble_state_t state
Definition: ledger_ble.c:93
uint8_t wait_write_resp_ack
Definition: ledger_ble.c:131
uint8_t adv_enable
Definition: ledger_ble.c:103
uint16_t gap_device_name_characteristic_handle
Definition: ledger_ble.c:110
uint8_t transfer_mode_enable
Definition: ledger_ble.c:136
ble_connection_t connection
Definition: ledger_ble.c:113
uint16_t ledger_gatt_notification_characteristic_handle
Definition: ledger_ble.c:122
uint8_t resp_length
Definition: ledger_ble.c:137
uint8_t advertising_enabled
Definition: ledger_ble.c:112
uint16_t pairing_code
Definition: ledger_ble.c:114
uint16_t ledger_gatt_write_characteristic_handle
Definition: ledger_ble.c:123
ble_config_adv_step_t adv_step
Definition: ledger_ble.c:102
uint16_t gap_appearance_characteristic_handle
Definition: ledger_ble.c:111
uint16_t ledger_gatt_service_handle
Definition: ledger_ble.c:121
uint16_t apdu_buffer_length
Definition: ledger_ble.c:132
uint16_t hci_cmd_opcode
Definition: ledger_ble.c:106
uint8_t resp[2]
Definition: ledger_ble.c:138
uint8_t connection_updated
Definition: ledger_ble.c:118
uint16_t ledger_gatt_write_cmd_characteristic_handle
Definition: ledger_ble.c:124
char device_name[20+1]
Definition: ledger_ble.c:94
char device_name_length
Definition: ledger_ble.c:95
uint8_t clear_pairing
Definition: ledger_ble.c:128
uint8_t notifications_enabled
Definition: ledger_ble.c:125
ble_init_step_t init_step
Definition: ledger_ble.c:99
uint16_t gap_service_handle
Definition: ledger_ble.c:109
unsigned short uint16_t
Definition: usbd_conf.h:54
unsigned char uint8_t
Definition: usbd_conf.h:53