seos_central.c 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  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. const uint8_t* oid_list = apdu + sizeof(select_adf_header) + 1;
  65. size_t oid_list_len = apdu[sizeof(select_adf_header)];
  66. bit_buffer_append_byte(response, BLE_START);
  67. if(seos_emulator_select_adf(
  68. oid_list, oid_list_len, &seos_central->params, seos_central->credential, response)) {
  69. bit_buffer_append_bytes(response, (uint8_t*)success, sizeof(success));
  70. seos_central->phase = GENERAL_AUTHENTICATION_1;
  71. } else {
  72. FURI_LOG_W(TAG, "Failed to match any ADF OID");
  73. }
  74. } else if(memcmp(apdu, general_authenticate_1, sizeof(general_authenticate_1)) == 0) {
  75. bit_buffer_append_byte(response, BLE_START);
  76. seos_emulator_general_authenticate_1(response, seos_central->params);
  77. bit_buffer_append_bytes(response, (uint8_t*)success, sizeof(success));
  78. seos_central->phase = GENERAL_AUTHENTICATION_2;
  79. } else if(memcmp(apdu, general_authenticate_2_header, sizeof(general_authenticate_2_header)) == 0) {
  80. bit_buffer_append_byte(response, BLE_START);
  81. if(seos_emulator_general_authenticate_2(
  82. apdu, buffer_len - 1, seos_central->credential, &seos_central->params, response)) {
  83. FURI_LOG_I(TAG, "Authenticated");
  84. view_dispatcher_send_custom_event(
  85. seos_central->seos->view_dispatcher, SeosCustomEventAuthenticated);
  86. seos_central->secure_messaging = secure_messaging_alloc(&seos_central->params);
  87. bit_buffer_append_bytes(response, (uint8_t*)success, sizeof(success));
  88. } else {
  89. bit_buffer_reset(response);
  90. }
  91. seos_central->phase = REQUEST_SIO;
  92. } else if(memcmp(apdu, secure_messaging_header, sizeof(secure_messaging_header)) == 0) {
  93. uint8_t request_sio[] = {0x5c, 0x02, 0xff, 0x00};
  94. bit_buffer_append_byte(response, BLE_START);
  95. if(seos_central->secure_messaging) {
  96. FURI_LOG_D(TAG, "Unwrap secure message");
  97. // c0 0ccb3fff 16 8508fa8395d30de4e8e097008e085da7edbd833b002d00
  98. // Ignore 1 BLE_START byte
  99. size_t bytes_to_ignore = 1;
  100. BitBuffer* tmp = bit_buffer_alloc(buffer_len);
  101. bit_buffer_append_bytes(tmp, buffer + bytes_to_ignore, buffer_len - bytes_to_ignore);
  102. seos_log_bitbuffer(TAG, "NFC received(wrapped)", tmp);
  103. secure_messaging_unwrap_apdu(seos_central->secure_messaging, tmp);
  104. seos_log_bitbuffer(TAG, "NFC received(clear)", tmp);
  105. const uint8_t* message = bit_buffer_get_data(tmp);
  106. if(memcmp(message, request_sio, sizeof(request_sio)) == 0) {
  107. view_dispatcher_send_custom_event(
  108. seos_central->seos->view_dispatcher, SeosCustomEventSIORequested);
  109. BitBuffer* sio_file = bit_buffer_alloc(128);
  110. bit_buffer_append_bytes(sio_file, message + 2, 2); // fileId
  111. bit_buffer_append_byte(sio_file, seos_central->credential->sio_len);
  112. bit_buffer_append_bytes(
  113. sio_file, seos_central->credential->sio, seos_central->credential->sio_len);
  114. seos_log_bitbuffer(TAG, "sio_file", sio_file);
  115. secure_messaging_wrap_rapdu(
  116. seos_central->secure_messaging,
  117. (uint8_t*)bit_buffer_get_data(sio_file),
  118. bit_buffer_get_size_bytes(sio_file),
  119. response);
  120. bit_buffer_free(sio_file);
  121. } else {
  122. FURI_LOG_W(TAG, "Did not match the cleartext request");
  123. }
  124. bit_buffer_append_bytes(response, (uint8_t*)success, sizeof(success));
  125. bit_buffer_free(tmp);
  126. } else {
  127. uint8_t no_sm[] = {0x69, 0x88};
  128. bit_buffer_append_bytes(response, no_sm, sizeof(no_sm));
  129. }
  130. } else {
  131. FURI_LOG_W(TAG, "no match for attribute_value");
  132. }
  133. if(bit_buffer_get_size_bytes(response) > 0) {
  134. seos_att_write_request(seos_central->seos_att, response);
  135. }
  136. bit_buffer_free(response);
  137. }