t_1.c 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. #include "t_1.h"
  2. #define TAG "Seader:T=1"
  3. // http://www.sat-digest.com/SatXpress/SmartCard/ISO7816-4.htm
  4. /* I know my T=1 is terrible, but I'm also only targetting one specific 'card' */
  5. #define MORE_BIT 0x20
  6. #define IFSD_VALUE 0xfe
  7. #define IFSC_VALUE 0xfe // Fom the SAM ATR
  8. #define R_BLOCK 0x80
  9. #define R_SEQUENCE_NUMBER_MASK 0x10
  10. // TODO: T1 struct
  11. uint8_t NAD = 0x00;
  12. uint8_t dPCB = 0x40; // Init to 0x40 so first call to next_pcb will return 0x00
  13. uint8_t cPCB = 0x00; // Init to 0x40 so first call to next_pcb will return 0x00
  14. uint8_t seader_next_dpcb() {
  15. uint8_t next_pcb = dPCB ^ 0x40;
  16. //FURI_LOG_D(TAG, "dPCB was: %02X, current dPCB: %02X", dPCB, next_pcb);
  17. dPCB = next_pcb;
  18. return dPCB;
  19. }
  20. uint8_t seader_next_cpcb() {
  21. uint8_t next_pcb = cPCB ^ 0x40;
  22. //FURI_LOG_D(TAG, "cPCB was: %02X, current cPCB: %02X", cPCB, next_pcb);
  23. cPCB = next_pcb;
  24. return cPCB;
  25. }
  26. void seader_t_1_set_IFSD(Seader* seader) {
  27. SeaderWorker* seader_worker = seader->worker;
  28. SeaderUartBridge* seader_uart = seader_worker->uart;
  29. uint8_t frame[5];
  30. uint8_t frame_len = 0;
  31. frame[0] = NAD;
  32. frame[1] = 0xC1; // S(IFS request)
  33. frame[2] = 0x01;
  34. frame[3] = IFSD_VALUE;
  35. frame_len = 4;
  36. frame_len = seader_add_lrc(frame, frame_len);
  37. seader_ccid_XfrBlock(seader_uart, frame, frame_len);
  38. }
  39. void seader_t_1_send_ack(Seader* seader) {
  40. SeaderWorker* seader_worker = seader->worker;
  41. SeaderUartBridge* seader_uart = seader_worker->uart;
  42. uint8_t frame[4];
  43. uint8_t frame_len = 0;
  44. frame[0] = NAD;
  45. frame[1] = R_BLOCK | (seader_next_cpcb() >> 2);
  46. frame[2] = 0x00;
  47. frame_len = 3;
  48. frame_len = seader_add_lrc(frame, frame_len);
  49. //FURI_LOG_D(TAG, "Sending R-Block ACK: PCB: %02x", frame[1]);
  50. seader_ccid_XfrBlock(seader_uart, frame, frame_len);
  51. }
  52. BitBuffer* seader_t_1_tx_buffer;
  53. size_t seader_t_1_tx_buffer_offset = 0;
  54. void seader_send_t1(SeaderUartBridge* seader_uart, uint8_t* apdu, size_t len) {
  55. uint8_t frame[SEADER_UART_RX_BUF_SIZE];
  56. uint8_t frame_len = 0;
  57. if(len > IFSC_VALUE) {
  58. if(seader_t_1_tx_buffer == NULL) {
  59. seader_t_1_tx_buffer = bit_buffer_alloc(768);
  60. bit_buffer_copy_bytes(seader_t_1_tx_buffer, apdu, len);
  61. }
  62. size_t remaining =
  63. (bit_buffer_get_size_bytes(seader_t_1_tx_buffer) - seader_t_1_tx_buffer_offset);
  64. size_t copy_length = remaining > IFSC_VALUE ? IFSC_VALUE : remaining;
  65. frame[0] = NAD;
  66. if(remaining > IFSC_VALUE) {
  67. frame[1] = seader_next_dpcb() | MORE_BIT;
  68. } else {
  69. frame[1] = seader_next_dpcb();
  70. }
  71. frame[2] = copy_length;
  72. frame_len = 3;
  73. memcpy(
  74. frame + frame_len,
  75. bit_buffer_get_data(seader_t_1_tx_buffer) + seader_t_1_tx_buffer_offset,
  76. copy_length);
  77. frame_len += copy_length;
  78. frame_len = seader_add_lrc(frame, frame_len);
  79. /*
  80. FURI_LOG_D(
  81. TAG,
  82. "Sending T=1 frame %s more bit set. Remaining: %d, Copy Length: %d",
  83. (remaining > IFSC_VALUE) ? "with" : "without",
  84. remaining,
  85. copy_length);
  86. */
  87. seader_ccid_XfrBlock(seader_uart, frame, frame_len);
  88. seader_t_1_tx_buffer_offset += copy_length;
  89. if(seader_t_1_tx_buffer_offset >= bit_buffer_get_size_bytes(seader_t_1_tx_buffer)) {
  90. bit_buffer_free(seader_t_1_tx_buffer);
  91. seader_t_1_tx_buffer = NULL;
  92. seader_t_1_tx_buffer_offset = 0;
  93. }
  94. return;
  95. }
  96. frame[0] = NAD;
  97. frame[1] = seader_next_dpcb();
  98. frame[2] = len;
  99. frame_len = 3;
  100. if(len > 0) {
  101. memcpy(frame + frame_len, apdu, len);
  102. frame_len += len;
  103. }
  104. frame_len = seader_add_lrc(frame, frame_len);
  105. seader_ccid_XfrBlock(seader_uart, frame, frame_len);
  106. }
  107. BitBuffer* seader_t_1_rx_buffer;
  108. bool seader_recv_t1(Seader* seader, CCID_Message* message) {
  109. // remove/validate NAD, PCB, LEN, LRC
  110. if(message->dwLength < 4) {
  111. FURI_LOG_W(TAG, "Invalid T=1 frame: too short");
  112. return false;
  113. }
  114. //uint8_t NAD = message->payload[0];
  115. uint8_t rPCB = message->payload[1];
  116. uint8_t LEN = message->payload[2];
  117. //uint8_t LRC = message->payload[3 + LEN];
  118. //FURI_LOG_D(TAG, "NAD: %02X, rPCB: %02X, LEN: %02X, LRC: %02X", NAD, rPCB, LEN, LRC);
  119. if(rPCB == 0xE1) {
  120. // S(IFS response)
  121. seader_worker_send_version(seader);
  122. SeaderWorker* seader_worker = seader->worker;
  123. if(seader_worker->callback) {
  124. seader_worker->callback(SeaderWorkerEventSamPresent, seader_worker->context);
  125. }
  126. return false;
  127. }
  128. if(rPCB == cPCB) {
  129. seader_next_cpcb();
  130. if(seader_t_1_rx_buffer != NULL) {
  131. bit_buffer_append_bytes(seader_t_1_rx_buffer, message->payload + 3, LEN);
  132. // TODO: validate LRC
  133. seader_worker_process_sam_message(
  134. seader,
  135. (uint8_t*)bit_buffer_get_data(seader_t_1_rx_buffer),
  136. bit_buffer_get_size_bytes(seader_t_1_rx_buffer));
  137. bit_buffer_free(seader_t_1_rx_buffer);
  138. seader_t_1_rx_buffer = NULL;
  139. return true;
  140. }
  141. if(seader_validate_lrc(message->payload, message->dwLength) == false) {
  142. return false;
  143. }
  144. // Skip NAD, PCB, LEN
  145. message->payload = message->payload + 3;
  146. message->dwLength = LEN;
  147. if(message->dwLength == 0) {
  148. //FURI_LOG_D(TAG, "Received T=1 frame with no data");
  149. return true;
  150. }
  151. return seader_worker_process_sam_message(seader, message->payload, message->dwLength);
  152. } else if(rPCB == (cPCB | MORE_BIT)) {
  153. //FURI_LOG_D(TAG, "Received T=1 frame with more bit set");
  154. if(seader_t_1_rx_buffer == NULL) {
  155. seader_t_1_rx_buffer = bit_buffer_alloc(512);
  156. }
  157. bit_buffer_append_bytes(seader_t_1_rx_buffer, message->payload + 3, LEN);
  158. seader_t_1_send_ack(seader);
  159. return false;
  160. } else if((rPCB & R_BLOCK) == R_BLOCK) {
  161. uint8_t R_SEQ = (rPCB & R_SEQUENCE_NUMBER_MASK) >> 4;
  162. uint8_t I_SEQ = (dPCB ^ 0x40) >> 6;
  163. if(R_SEQ != I_SEQ) {
  164. /*
  165. FURI_LOG_D(
  166. TAG,
  167. "Received R-Block: Incorrect sequence. Expected: %02X, Received: %02X",
  168. I_SEQ,
  169. R_SEQ);
  170. */
  171. // When this happens, the flipper freezes if it is doing NFC and my attempts to do events to stop that have failed
  172. return false;
  173. }
  174. if(seader_t_1_tx_buffer != NULL) {
  175. // Send more data, re-using the buffer to trigger the code path that sends the next block
  176. SeaderWorker* seader_worker = seader->worker;
  177. SeaderUartBridge* seader_uart = seader_worker->uart;
  178. seader_send_t1(
  179. seader_uart,
  180. (uint8_t*)bit_buffer_get_data(seader_t_1_tx_buffer),
  181. bit_buffer_get_size_bytes(seader_t_1_tx_buffer));
  182. return false;
  183. }
  184. } else {
  185. FURI_LOG_W(
  186. TAG, "Invalid T=1 frame: PCB mismatch. Expected: %02X, Received: %02X", cPCB, rPCB);
  187. }
  188. return false;
  189. }