u2f_hid.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311
  1. #include <furi.h>
  2. #include "u2f_hid.h"
  3. #include "u2f.h"
  4. #include <furi_hal.h>
  5. #include <gui/gui.h>
  6. #include <input/input.h>
  7. #include <lib/toolbox/args.h>
  8. #include <furi_hal_usb_hid_u2f.h>
  9. #include <storage/storage.h>
  10. #include <furi_hal_console.h>
  11. #define TAG "U2FHID"
  12. #define WORKER_TAG TAG "Worker"
  13. #define U2F_HID_MAX_PAYLOAD_LEN ((HID_U2F_PACKET_LEN - 7) + 128 * (HID_U2F_PACKET_LEN - 5))
  14. #define U2F_HID_TYPE_MASK 0x80 // Frame type mask
  15. #define U2F_HID_TYPE_INIT 0x80 // Initial frame identifier
  16. #define U2F_HID_TYPE_CONT 0x00 // Continuation frame identifier
  17. #define U2F_HID_PING (U2F_HID_TYPE_INIT | 0x01) // Echo data through local processor only
  18. #define U2F_HID_MSG (U2F_HID_TYPE_INIT | 0x03) // Send U2F message frame
  19. #define U2F_HID_LOCK (U2F_HID_TYPE_INIT | 0x04) // Send lock channel command
  20. #define U2F_HID_INIT (U2F_HID_TYPE_INIT | 0x06) // Channel initialization
  21. #define U2F_HID_WINK (U2F_HID_TYPE_INIT | 0x08) // Send device identification wink
  22. #define U2F_HID_ERROR (U2F_HID_TYPE_INIT | 0x3f) // Error response
  23. #define U2F_HID_ERR_NONE 0x00 // No error
  24. #define U2F_HID_ERR_INVALID_CMD 0x01 // Invalid command
  25. #define U2F_HID_ERR_INVALID_PAR 0x02 // Invalid parameter
  26. #define U2F_HID_ERR_INVALID_LEN 0x03 // Invalid message length
  27. #define U2F_HID_ERR_INVALID_SEQ 0x04 // Invalid message sequencing
  28. #define U2F_HID_ERR_MSG_TIMEOUT 0x05 // Message has timed out
  29. #define U2F_HID_ERR_CHANNEL_BUSY 0x06 // Channel busy
  30. #define U2F_HID_ERR_LOCK_REQUIRED 0x0a // Command requires channel lock
  31. #define U2F_HID_ERR_SYNC_FAIL 0x0b // SYNC command failed
  32. #define U2F_HID_ERR_OTHER 0x7f // Other unspecified error
  33. #define U2F_HID_BROADCAST_CID 0xFFFFFFFF
  34. typedef enum {
  35. WorkerEvtReserved = (1 << 0),
  36. WorkerEvtStop = (1 << 1),
  37. WorkerEvtConnect = (1 << 2),
  38. WorkerEvtDisconnect = (1 << 3),
  39. WorkerEvtRequest = (1 << 4),
  40. WorkerEvtUnlock = (1 << 5),
  41. } WorkerEvtFlags;
  42. struct U2fHid_packet {
  43. uint32_t cid;
  44. uint16_t len;
  45. uint8_t cmd;
  46. uint8_t payload[U2F_HID_MAX_PAYLOAD_LEN];
  47. };
  48. struct U2fHid {
  49. FuriThread* thread;
  50. FuriTimer* lock_timer;
  51. uint8_t seq_id_last;
  52. uint16_t req_buf_ptr;
  53. uint32_t req_len_left;
  54. uint32_t lock_cid;
  55. bool lock;
  56. U2fData* u2f_instance;
  57. struct U2fHid_packet packet;
  58. };
  59. static void u2f_hid_event_callback(HidU2fEvent ev, void* context) {
  60. furi_assert(context);
  61. U2fHid* u2f_hid = context;
  62. if(ev == HidU2fDisconnected)
  63. furi_thread_flags_set(furi_thread_get_id(u2f_hid->thread), WorkerEvtDisconnect);
  64. else if(ev == HidU2fConnected)
  65. furi_thread_flags_set(furi_thread_get_id(u2f_hid->thread), WorkerEvtConnect);
  66. else if(ev == HidU2fRequest)
  67. furi_thread_flags_set(furi_thread_get_id(u2f_hid->thread), WorkerEvtRequest);
  68. }
  69. static void u2f_hid_lock_timeout_callback(void* context) {
  70. furi_assert(context);
  71. U2fHid* u2f_hid = context;
  72. furi_thread_flags_set(furi_thread_get_id(u2f_hid->thread), WorkerEvtUnlock);
  73. }
  74. static void u2f_hid_send_response(U2fHid* u2f_hid) {
  75. uint8_t packet_buf[HID_U2F_PACKET_LEN];
  76. uint16_t len_remain = u2f_hid->packet.len;
  77. uint8_t len_cur = 0;
  78. uint8_t seq_cnt = 0;
  79. uint16_t data_ptr = 0;
  80. memset(packet_buf, 0, HID_U2F_PACKET_LEN);
  81. memcpy(packet_buf, &(u2f_hid->packet.cid), sizeof(uint32_t)); //-V1086
  82. // Init packet
  83. packet_buf[4] = u2f_hid->packet.cmd;
  84. packet_buf[5] = u2f_hid->packet.len >> 8;
  85. packet_buf[6] = (u2f_hid->packet.len & 0xFF);
  86. len_cur = (len_remain < (HID_U2F_PACKET_LEN - 7)) ? (len_remain) : (HID_U2F_PACKET_LEN - 7);
  87. if(len_cur > 0) memcpy(&packet_buf[7], u2f_hid->packet.payload, len_cur);
  88. furi_hal_hid_u2f_send_response(packet_buf, HID_U2F_PACKET_LEN);
  89. data_ptr = len_cur;
  90. len_remain -= len_cur;
  91. // Continuation packets
  92. while(len_remain > 0) {
  93. memset(&packet_buf[4], 0, HID_U2F_PACKET_LEN - 4);
  94. packet_buf[4] = seq_cnt;
  95. len_cur = (len_remain < (HID_U2F_PACKET_LEN - 5)) ? (len_remain) :
  96. (HID_U2F_PACKET_LEN - 5);
  97. memcpy(&packet_buf[5], &(u2f_hid->packet.payload[data_ptr]), len_cur);
  98. furi_hal_hid_u2f_send_response(packet_buf, HID_U2F_PACKET_LEN);
  99. seq_cnt++;
  100. len_remain -= len_cur;
  101. data_ptr += len_cur;
  102. }
  103. }
  104. static void u2f_hid_send_error(U2fHid* u2f_hid, uint8_t error) {
  105. u2f_hid->packet.len = 1;
  106. u2f_hid->packet.cmd = U2F_HID_ERROR;
  107. u2f_hid->packet.payload[0] = error;
  108. u2f_hid_send_response(u2f_hid);
  109. }
  110. static bool u2f_hid_parse_request(U2fHid* u2f_hid) {
  111. FURI_LOG_D(
  112. WORKER_TAG,
  113. "Req cid=%lX cmd=%x len=%u",
  114. u2f_hid->packet.cid,
  115. u2f_hid->packet.cmd,
  116. u2f_hid->packet.len);
  117. if(u2f_hid->packet.cmd == U2F_HID_PING) { // PING - echo request back
  118. u2f_hid_send_response(u2f_hid);
  119. } else if(u2f_hid->packet.cmd == U2F_HID_MSG) { // MSG - U2F message
  120. if((u2f_hid->lock == true) && (u2f_hid->packet.cid != u2f_hid->lock_cid)) return false;
  121. uint16_t resp_len =
  122. u2f_msg_parse(u2f_hid->u2f_instance, u2f_hid->packet.payload, u2f_hid->packet.len);
  123. if(resp_len > 0) {
  124. u2f_hid->packet.len = resp_len;
  125. u2f_hid_send_response(u2f_hid);
  126. } else
  127. return false;
  128. } else if(u2f_hid->packet.cmd == U2F_HID_LOCK) { // LOCK - lock all channels except current
  129. if(u2f_hid->packet.len != 1) return false;
  130. uint8_t lock_timeout = u2f_hid->packet.payload[0];
  131. if(lock_timeout == 0) { // Lock off
  132. u2f_hid->lock = false;
  133. u2f_hid->lock_cid = 0;
  134. } else { // Lock on
  135. u2f_hid->lock = true;
  136. u2f_hid->lock_cid = u2f_hid->packet.cid;
  137. furi_timer_start(u2f_hid->lock_timer, lock_timeout * 1000);
  138. }
  139. } else if(u2f_hid->packet.cmd == U2F_HID_INIT) { // INIT - channel initialization request
  140. if((u2f_hid->packet.len != 8) || (u2f_hid->packet.cid != U2F_HID_BROADCAST_CID) ||
  141. (u2f_hid->lock == true))
  142. return false;
  143. u2f_hid->packet.len = 17;
  144. uint32_t random_cid = furi_hal_random_get();
  145. memcpy(&(u2f_hid->packet.payload[8]), &random_cid, sizeof(uint32_t)); //-V1086
  146. u2f_hid->packet.payload[12] = 2; // Protocol version
  147. u2f_hid->packet.payload[13] = 1; // Device version major
  148. u2f_hid->packet.payload[14] = 0; // Device version minor
  149. u2f_hid->packet.payload[15] = 1; // Device build version
  150. u2f_hid->packet.payload[16] = 1; // Capabilities: wink
  151. u2f_hid_send_response(u2f_hid);
  152. } else if(u2f_hid->packet.cmd == U2F_HID_WINK) { // WINK - notify user
  153. if(u2f_hid->packet.len != 0) return false;
  154. u2f_wink(u2f_hid->u2f_instance);
  155. u2f_hid->packet.len = 0; //-V1048
  156. u2f_hid_send_response(u2f_hid);
  157. } else
  158. return false;
  159. return true;
  160. }
  161. static int32_t u2f_hid_worker(void* context) {
  162. U2fHid* u2f_hid = context;
  163. uint8_t packet_buf[HID_U2F_PACKET_LEN];
  164. FURI_LOG_D(WORKER_TAG, "Init");
  165. FuriHalUsbInterface* usb_mode_prev = furi_hal_usb_get_config();
  166. furi_check(furi_hal_usb_set_config(&usb_hid_u2f, NULL) == true);
  167. u2f_hid->lock_timer =
  168. furi_timer_alloc(u2f_hid_lock_timeout_callback, FuriTimerTypeOnce, u2f_hid);
  169. furi_hal_hid_u2f_set_callback(u2f_hid_event_callback, u2f_hid);
  170. while(1) {
  171. uint32_t flags = furi_thread_flags_wait(
  172. WorkerEvtStop | WorkerEvtConnect | WorkerEvtDisconnect | WorkerEvtRequest,
  173. FuriFlagWaitAny,
  174. FuriWaitForever);
  175. furi_check(!(flags & FuriFlagError));
  176. if(flags & WorkerEvtStop) break;
  177. if(flags & WorkerEvtConnect) {
  178. u2f_set_state(u2f_hid->u2f_instance, 1);
  179. FURI_LOG_D(WORKER_TAG, "Connect");
  180. }
  181. if(flags & WorkerEvtDisconnect) {
  182. u2f_set_state(u2f_hid->u2f_instance, 0);
  183. FURI_LOG_D(WORKER_TAG, "Disconnect");
  184. }
  185. if(flags & WorkerEvtRequest) {
  186. uint32_t len_cur = furi_hal_hid_u2f_get_request(packet_buf);
  187. do {
  188. if(len_cur == 0) {
  189. break;
  190. }
  191. if((packet_buf[4] & U2F_HID_TYPE_MASK) == U2F_HID_TYPE_INIT) {
  192. if(len_cur < 7) {
  193. u2f_hid->req_len_left = 0;
  194. break; // Wrong chunk len
  195. }
  196. // Init packet
  197. u2f_hid->packet.len = (packet_buf[5] << 8) | (packet_buf[6]);
  198. if(u2f_hid->packet.len > U2F_HID_MAX_PAYLOAD_LEN) {
  199. u2f_hid->req_len_left = 0;
  200. break; // Wrong packet len
  201. }
  202. if(u2f_hid->packet.len > (len_cur - 7)) {
  203. u2f_hid->req_len_left = u2f_hid->packet.len - (len_cur - 7);
  204. len_cur = len_cur - 7;
  205. } else {
  206. u2f_hid->req_len_left = 0;
  207. len_cur = u2f_hid->packet.len;
  208. }
  209. memcpy(&(u2f_hid->packet.cid), packet_buf, 4);
  210. u2f_hid->packet.cmd = packet_buf[4];
  211. u2f_hid->seq_id_last = 0;
  212. u2f_hid->req_buf_ptr = len_cur;
  213. if(len_cur > 0) memcpy(u2f_hid->packet.payload, &packet_buf[7], len_cur);
  214. } else {
  215. if(len_cur < 5) {
  216. u2f_hid->req_len_left = 0;
  217. break; // Wrong chunk len
  218. }
  219. // Continuation packet
  220. if(u2f_hid->req_len_left > 0) {
  221. uint32_t cid_temp = 0;
  222. memcpy(&cid_temp, packet_buf, 4);
  223. uint8_t seq_temp = packet_buf[4];
  224. if((cid_temp == u2f_hid->packet.cid) &&
  225. (seq_temp == u2f_hid->seq_id_last)) {
  226. if(u2f_hid->req_len_left > (len_cur - 5)) {
  227. len_cur = len_cur - 5;
  228. u2f_hid->req_len_left -= len_cur;
  229. } else {
  230. len_cur = u2f_hid->req_len_left;
  231. u2f_hid->req_len_left = 0;
  232. }
  233. memcpy(
  234. &(u2f_hid->packet.payload[u2f_hid->req_buf_ptr]),
  235. &packet_buf[5],
  236. len_cur);
  237. u2f_hid->req_buf_ptr += len_cur;
  238. u2f_hid->seq_id_last++;
  239. }
  240. }
  241. }
  242. if(u2f_hid->req_len_left == 0) {
  243. if(u2f_hid_parse_request(u2f_hid) == false) {
  244. u2f_hid_send_error(u2f_hid, U2F_HID_ERR_INVALID_CMD);
  245. }
  246. }
  247. } while(0);
  248. }
  249. if(flags & WorkerEvtUnlock) {
  250. u2f_hid->lock = false;
  251. u2f_hid->lock_cid = 0;
  252. }
  253. }
  254. furi_timer_stop(u2f_hid->lock_timer);
  255. furi_timer_free(u2f_hid->lock_timer);
  256. furi_hal_hid_u2f_set_callback(NULL, NULL);
  257. furi_hal_usb_set_config(usb_mode_prev, NULL);
  258. FURI_LOG_D(WORKER_TAG, "End");
  259. return 0;
  260. }
  261. U2fHid* u2f_hid_start(U2fData* u2f_inst) {
  262. U2fHid* u2f_hid = malloc(sizeof(U2fHid));
  263. u2f_hid->u2f_instance = u2f_inst;
  264. u2f_hid->thread = furi_thread_alloc_ex("U2fHidWorker", 2048, u2f_hid_worker, u2f_hid);
  265. furi_thread_start(u2f_hid->thread);
  266. return u2f_hid;
  267. }
  268. void u2f_hid_stop(U2fHid* u2f_hid) {
  269. furi_assert(u2f_hid);
  270. furi_thread_flags_set(furi_thread_get_id(u2f_hid->thread), WorkerEvtStop);
  271. furi_thread_join(u2f_hid->thread);
  272. furi_thread_free(u2f_hid->thread);
  273. free(u2f_hid);
  274. }