seos_central.c 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. #include "seos_central_i.h"
  2. #define TAG "SeosCentral"
  3. static uint8_t success[] = {0x90, 0x00};
  4. static uint8_t file_not_found[] = {0x6A, 0x82};
  5. static uint8_t select_header[] = {0x00, 0xa4, 0x04, 0x00};
  6. static uint8_t standard_seos_aid[] = {0xa0, 0x00, 0x00, 0x04, 0x40, 0x00, 0x01, 0x01, 0x00, 0x01};
  7. static uint8_t select_adf_header[] = {0x80, 0xa5, 0x04, 0x00};
  8. static uint8_t general_authenticate_1[] =
  9. {0x00, 0x87, 0x00, 0x01, 0x04, 0x7c, 0x02, 0x81, 0x00, 0x00};
  10. static uint8_t general_authenticate_2_header[] = {0x00, 0x87, 0x00, 0x01};
  11. static uint8_t secure_messaging_header[] = {0x0c, 0xcb, 0x3f, 0xff};
  12. SeosCentral* seos_central_alloc(Seos* seos) {
  13. SeosCentral* seos_central = malloc(sizeof(SeosCentral));
  14. memset(seos_central, 0, sizeof(SeosCentral));
  15. seos_central->seos = seos;
  16. seos_central->credential = &seos->credential;
  17. seos_central->phase = SELECT_AID;
  18. // Using DES for greater compatibilty
  19. seos_central->params.cipher = TWO_KEY_3DES_CBC_MODE;
  20. seos_central->params.hash = SHA1;
  21. memset(seos_central->params.rndICC, 0x0d, sizeof(seos_central->params.rndICC));
  22. memset(seos_central->params.rNonce, 0x0c, sizeof(seos_central->params.rNonce));
  23. seos_central->secure_messaging = NULL;
  24. seos_central->seos_att = seos_att_alloc(seos);
  25. seos_att_set_notify_callback(seos_central->seos_att, seos_central_notify, seos_central);
  26. return seos_central;
  27. }
  28. void seos_central_free(SeosCentral* seos_central) {
  29. furi_assert(seos_central);
  30. seos_att_free(seos_central->seos_att);
  31. free(seos_central);
  32. }
  33. void seos_central_start(SeosCentral* seos_central, FlowMode mode) {
  34. seos_att_start(seos_central->seos_att, BLE_CENTRAL, mode);
  35. }
  36. void seos_central_stop(SeosCentral* seos_central) {
  37. seos_att_stop(seos_central->seos_att);
  38. }
  39. void seos_central_notify(void* context, const uint8_t* buffer, size_t buffer_len) {
  40. SeosCentral* seos_central = (SeosCentral*)context;
  41. seos_log_buffer(TAG, "notify", (uint8_t*)buffer, buffer_len);
  42. const uint8_t* data = buffer;
  43. if(data[0] == 0xe1) {
  44. FURI_LOG_W(TAG, "Reader BLE Error code: %02x", data[1]);
  45. return;
  46. }
  47. BitBuffer* response = bit_buffer_alloc(128);
  48. if(data[0] != BLE_START) {
  49. FURI_LOG_W(TAG, "Unexpected start of BLE packet");
  50. }
  51. const uint8_t* apdu = data + 1; // Match name to nfc version for easier copying
  52. if(memcmp(apdu, select_header, sizeof(select_header)) == 0) {
  53. if(memcmp(apdu + sizeof(select_header) + 1, standard_seos_aid, sizeof(standard_seos_aid)) ==
  54. 0) {
  55. bit_buffer_append_byte(response, BLE_START);
  56. seos_emulator_select_aid(response);
  57. bit_buffer_append_bytes(response, (uint8_t*)success, sizeof(success));
  58. seos_central->phase = SELECT_ADF;
  59. } else {
  60. bit_buffer_append_byte(response, BLE_START);
  61. bit_buffer_append_bytes(response, (uint8_t*)file_not_found, sizeof(file_not_found));
  62. }
  63. } else if(memcmp(apdu, select_adf_header, sizeof(select_adf_header)) == 0) {
  64. // is our adf in the list?
  65. // +1 to skip APDU length byte
  66. void* p = memmem(
  67. apdu + sizeof(select_adf_header) + 1,
  68. apdu[sizeof(select_adf_header)],
  69. SEOS_ADF_OID,
  70. SEOS_ADF_OID_LEN);
  71. if(p) {
  72. seos_log_buffer(TAG, "Matched ADF", p, SEOS_ADF_OID_LEN);
  73. bit_buffer_append_byte(response, BLE_START);
  74. seos_emulator_select_adf(&seos_central->params, seos_central->credential, response);
  75. bit_buffer_append_bytes(response, (uint8_t*)success, sizeof(success));
  76. seos_central->phase = GENERAL_AUTHENTICATION_1;
  77. } else {
  78. FURI_LOG_W(TAG, "Failed to match any ADF OID");
  79. }
  80. } else if(memcmp(apdu, general_authenticate_1, sizeof(general_authenticate_1)) == 0) {
  81. bit_buffer_append_byte(response, BLE_START);
  82. seos_emulator_general_authenticate_1(response, seos_central->params);
  83. bit_buffer_append_bytes(response, (uint8_t*)success, sizeof(success));
  84. seos_central->phase = GENERAL_AUTHENTICATION_2;
  85. } else if(memcmp(apdu, general_authenticate_2_header, sizeof(general_authenticate_2_header)) == 0) {
  86. bit_buffer_append_byte(response, BLE_START);
  87. if(seos_emulator_general_authenticate_2(
  88. apdu, buffer_len - 1, seos_central->credential, &seos_central->params, response)) {
  89. FURI_LOG_I(TAG, "Authenticated");
  90. view_dispatcher_send_custom_event(
  91. seos_central->seos->view_dispatcher, SeosCustomEventAuthenticated);
  92. seos_central->secure_messaging = secure_messaging_alloc(&seos_central->params);
  93. bit_buffer_append_bytes(response, (uint8_t*)success, sizeof(success));
  94. } else {
  95. bit_buffer_reset(response);
  96. }
  97. seos_central->phase = REQUEST_SIO;
  98. } else if(memcmp(apdu, secure_messaging_header, sizeof(secure_messaging_header)) == 0) {
  99. uint8_t request_sio[] = {0x5c, 0x02, 0xff, 0x00};
  100. bit_buffer_append_byte(response, BLE_START);
  101. if(seos_central->secure_messaging) {
  102. FURI_LOG_D(TAG, "Unwrap secure message");
  103. // c0 0ccb3fff 16 8508fa8395d30de4e8e097008e085da7edbd833b002d00
  104. // Ignore 1 BLE_START byte
  105. size_t bytes_to_ignore = 1;
  106. BitBuffer* tmp = bit_buffer_alloc(buffer_len);
  107. bit_buffer_append_bytes(tmp, buffer + bytes_to_ignore, buffer_len - bytes_to_ignore);
  108. seos_log_bitbuffer(TAG, "NFC received(wrapped)", tmp);
  109. secure_messaging_unwrap_apdu(seos_central->secure_messaging, tmp);
  110. seos_log_bitbuffer(TAG, "NFC received(clear)", tmp);
  111. const uint8_t* message = bit_buffer_get_data(tmp);
  112. if(memcmp(message, request_sio, sizeof(request_sio)) == 0) {
  113. view_dispatcher_send_custom_event(
  114. seos_central->seos->view_dispatcher, SeosCustomEventSIORequested);
  115. BitBuffer* sio_file = bit_buffer_alloc(128);
  116. bit_buffer_append_bytes(sio_file, message + 2, 2); // fileId
  117. bit_buffer_append_byte(sio_file, seos_central->credential->sio_len);
  118. bit_buffer_append_bytes(
  119. sio_file, seos_central->credential->sio, seos_central->credential->sio_len);
  120. seos_log_bitbuffer(TAG, "sio_file", sio_file);
  121. secure_messaging_wrap_rapdu(
  122. seos_central->secure_messaging,
  123. (uint8_t*)bit_buffer_get_data(sio_file),
  124. bit_buffer_get_size_bytes(sio_file),
  125. response);
  126. bit_buffer_free(sio_file);
  127. } else {
  128. FURI_LOG_W(TAG, "Did not match the cleartext request");
  129. }
  130. bit_buffer_append_bytes(response, (uint8_t*)success, sizeof(success));
  131. bit_buffer_free(tmp);
  132. } else {
  133. uint8_t no_sm[] = {0x69, 0x88};
  134. bit_buffer_append_bytes(response, no_sm, sizeof(no_sm));
  135. }
  136. } else {
  137. FURI_LOG_W(TAG, "no match for attribute_value");
  138. }
  139. if(bit_buffer_get_size_bytes(response) > 0) {
  140. seos_att_write_request(seos_central->seos_att, response);
  141. }
  142. bit_buffer_free(response);
  143. }