seos_reader.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479
  1. #include "seos_reader_i.h"
  2. #define TAG "SeosReader"
  3. static uint8_t success[] = {0x90, 0x00};
  4. static uint8_t select[] =
  5. {0x00, 0xa4, 0x04, 0x00, 0x0a, 0xa0, 0x00, 0x00, 0x04, 0x40, 0x00, 0x01, 0x01, 0x00, 0x01, 0x00};
  6. static uint8_t SEOS_APPLET_FCI[] =
  7. {0x6F, 0x0C, 0x84, 0x0A, 0xA0, 0x00, 0x00, 0x04, 0x40, 0x00, 0x01, 0x01, 0x00, 0x01};
  8. static uint8_t general_authenticate_1[] =
  9. {0x00, 0x87, 0x00, 0x01, 0x04, 0x7c, 0x02, 0x81, 0x00, 0x00};
  10. SeosReader* seos_reader_alloc(SeosCredential* credential, Iso14443_4aPoller* iso14443_4a_poller) {
  11. SeosReader* seos_reader = malloc(sizeof(SeosReader));
  12. memset(seos_reader, 0, sizeof(SeosReader));
  13. seos_reader->params.key_no = 1;
  14. seos_reader->secure_messaging = NULL;
  15. memset(seos_reader->params.cNonce, 0x0c, sizeof(seos_reader->params.cNonce));
  16. memset(seos_reader->params.UID, 0x0d, sizeof(seos_reader->params.UID));
  17. seos_reader->credential = credential;
  18. seos_reader->iso14443_4a_poller = iso14443_4a_poller;
  19. seos_reader->tx_buffer = bit_buffer_alloc(SEOS_WORKER_MAX_BUFFER_SIZE);
  20. seos_reader->rx_buffer = bit_buffer_alloc(SEOS_WORKER_MAX_BUFFER_SIZE);
  21. return seos_reader;
  22. }
  23. void seos_reader_free(SeosReader* seos_reader) {
  24. furi_assert(seos_reader);
  25. bit_buffer_free(seos_reader->tx_buffer);
  26. bit_buffer_free(seos_reader->rx_buffer);
  27. if(seos_reader->secure_messaging) {
  28. secure_messaging_free(seos_reader->secure_messaging);
  29. }
  30. free(seos_reader);
  31. }
  32. bool seos_reader_request_sio(SeosReader* seos_reader) {
  33. SecureMessaging* secure_messaging = seos_reader->secure_messaging;
  34. furi_assert(secure_messaging);
  35. Iso14443_4aPoller* iso14443_4a_poller = seos_reader->iso14443_4a_poller;
  36. BitBuffer* tx_buffer = seos_reader->tx_buffer;
  37. BitBuffer* rx_buffer = seos_reader->rx_buffer;
  38. Iso14443_4aError error;
  39. uint8_t message[] = {0x5c, 0x02, 0xff, 0x00};
  40. secure_messaging_wrap_apdu(secure_messaging, message, sizeof(message), tx_buffer);
  41. seos_log_bitbuffer(TAG, "NFC transmit", tx_buffer);
  42. error = iso14443_4a_poller_send_block(iso14443_4a_poller, tx_buffer, rx_buffer);
  43. if(error != Iso14443_4aErrorNone) {
  44. FURI_LOG_W(TAG, "iso14443_4a_poller_send_block error %d", error);
  45. return false;
  46. }
  47. bit_buffer_reset(tx_buffer);
  48. seos_log_bitbuffer(TAG, "NFC response(wrapped)", rx_buffer);
  49. secure_messaging_unwrap_rapdu(secure_messaging, rx_buffer);
  50. seos_log_bitbuffer(TAG, "NFC response(clear)", rx_buffer);
  51. // Skip fileId
  52. seos_reader->credential->sio_len = bit_buffer_get_byte(rx_buffer, 2);
  53. if(seos_reader->credential->sio_len > sizeof(seos_reader->credential->sio)) {
  54. FURI_LOG_W(TAG, "SIO too long to save");
  55. return false;
  56. }
  57. memcpy(
  58. seos_reader->credential->sio,
  59. bit_buffer_get_data(rx_buffer) + 3,
  60. seos_reader->credential->sio_len);
  61. return true;
  62. }
  63. void seos_reader_generate_cryptogram(
  64. SeosCredential* credential,
  65. AuthParameters* params,
  66. uint8_t* cryptogram) {
  67. seos_worker_diversify_key(
  68. SEOS_ADF1_READ,
  69. credential->diversifier,
  70. credential->diversifier_len,
  71. SEOS_ADF_OID,
  72. SEOS_ADF_OID_LEN,
  73. params->cipher,
  74. params->hash,
  75. params->key_no,
  76. true,
  77. params->priv_key);
  78. seos_worker_diversify_key(
  79. SEOS_ADF1_READ,
  80. credential->diversifier,
  81. credential->diversifier_len,
  82. SEOS_ADF_OID,
  83. SEOS_ADF_OID_LEN,
  84. params->cipher,
  85. params->hash,
  86. params->key_no,
  87. false,
  88. params->auth_key);
  89. uint8_t clear[32];
  90. memset(clear, 0, sizeof(clear));
  91. size_t index = 0;
  92. memcpy(clear + index, params->UID, sizeof(params->UID));
  93. index += sizeof(params->UID);
  94. memcpy(clear + index, params->rndICC, sizeof(params->rndICC));
  95. index += sizeof(params->rndICC);
  96. memcpy(clear + index, params->cNonce, sizeof(params->cNonce));
  97. index += sizeof(params->cNonce);
  98. uint8_t cmac[16];
  99. if(params->cipher == AES_128_CBC) {
  100. seos_worker_aes_encrypt(params->priv_key, sizeof(clear), clear, cryptogram);
  101. aes_cmac(params->auth_key, sizeof(params->auth_key), cryptogram, index, cmac);
  102. } else if(params->cipher == TWO_KEY_3DES_CBC_MODE) {
  103. seos_worker_des_encrypt(params->priv_key, sizeof(clear), clear, cryptogram);
  104. des_cmac(params->auth_key, sizeof(params->auth_key), cryptogram, index, cmac);
  105. } else {
  106. FURI_LOG_W(TAG, "Cipher not matched");
  107. }
  108. memcpy(cryptogram + sizeof(clear), cmac, SEOS_WORKER_CMAC_SIZE);
  109. }
  110. bool seos_reader_verify_cryptogram(AuthParameters* params, const uint8_t* cryptogram) {
  111. // cryptogram is 40 bytes: 32 byte encrypted + 8 byte cmac
  112. size_t encrypted_len = 32;
  113. uint8_t* mac = (uint8_t*)cryptogram + encrypted_len;
  114. uint8_t cmac[16];
  115. if(params->cipher == AES_128_CBC) {
  116. aes_cmac(
  117. params->auth_key, sizeof(params->auth_key), (uint8_t*)cryptogram, encrypted_len, cmac);
  118. } else if(params->cipher == TWO_KEY_3DES_CBC_MODE) {
  119. des_cmac(
  120. params->auth_key, sizeof(params->auth_key), (uint8_t*)cryptogram, encrypted_len, cmac);
  121. } else {
  122. FURI_LOG_W(TAG, "Cipher not matched");
  123. }
  124. if(memcmp(cmac, mac, SEOS_WORKER_CMAC_SIZE) != 0) {
  125. FURI_LOG_W(TAG, "Incorrect cryptogram mac %02x... vs %02x...", cmac[0], mac[0]);
  126. return false;
  127. }
  128. uint8_t clear[32];
  129. memset(clear, 0, sizeof(clear));
  130. if(params->cipher == AES_128_CBC) {
  131. seos_worker_aes_decrypt(params->priv_key, encrypted_len, cryptogram, clear);
  132. } else if(params->cipher == TWO_KEY_3DES_CBC_MODE) {
  133. seos_worker_des_decrypt(params->priv_key, encrypted_len, cryptogram, clear);
  134. } else {
  135. FURI_LOG_W(TAG, "Cipher not matched");
  136. }
  137. // rndICC[8], UID[8], rNonce[16]
  138. uint8_t* rndICC = clear;
  139. if(memcmp(rndICC, params->rndICC, sizeof(params->rndICC)) != 0) {
  140. FURI_LOG_W(TAG, "Incorrect rndICC returned");
  141. return false;
  142. }
  143. uint8_t* UID = clear + 8;
  144. if(memcmp(UID, params->UID, sizeof(params->UID)) != 0) {
  145. FURI_LOG_W(TAG, "Incorrect UID returned");
  146. return false;
  147. }
  148. memcpy(params->rNonce, clear + 8 + 8, sizeof(params->rNonce));
  149. return true;
  150. }
  151. NfcCommand seos_reader_select_aid(SeosReader* seos_reader) {
  152. Iso14443_4aPoller* iso14443_4a_poller = seos_reader->iso14443_4a_poller;
  153. BitBuffer* tx_buffer = seos_reader->tx_buffer;
  154. BitBuffer* rx_buffer = seos_reader->rx_buffer;
  155. NfcCommand ret = NfcCommandContinue;
  156. Iso14443_4aError error;
  157. bit_buffer_append_bytes(tx_buffer, select, sizeof(select));
  158. seos_log_bitbuffer(TAG, "NFC transmit", tx_buffer);
  159. error = iso14443_4a_poller_send_block(iso14443_4a_poller, tx_buffer, rx_buffer);
  160. if(error != Iso14443_4aErrorNone) {
  161. FURI_LOG_W(TAG, "iso14443_4a_poller_send_block error %d", error);
  162. return NfcCommandStop;
  163. }
  164. bit_buffer_reset(tx_buffer);
  165. seos_log_bitbuffer(TAG, "NFC response", rx_buffer);
  166. // TODO: validate response
  167. if(memcmp(
  168. bit_buffer_get_data(rx_buffer) + bit_buffer_get_size_bytes(rx_buffer) - sizeof(success),
  169. success,
  170. sizeof(success)) != 0) {
  171. FURI_LOG_W(TAG, "Non-success response");
  172. return NfcCommandStop;
  173. }
  174. if(memcmp(bit_buffer_get_data(rx_buffer), SEOS_APPLET_FCI, sizeof(SEOS_APPLET_FCI)) != 0) {
  175. FURI_LOG_W(TAG, "Unexpected select AID response");
  176. return NfcCommandStop;
  177. }
  178. return ret;
  179. }
  180. NfcCommand seos_reader_select_adf(SeosReader* seos_reader) {
  181. Iso14443_4aPoller* iso14443_4a_poller = seos_reader->iso14443_4a_poller;
  182. BitBuffer* tx_buffer = seos_reader->tx_buffer;
  183. BitBuffer* rx_buffer = seos_reader->rx_buffer;
  184. NfcCommand ret = NfcCommandContinue;
  185. Iso14443_4aError error;
  186. uint8_t select_adf_header[] = {
  187. 0x80, 0xa5, 0x04, 0x00, (uint8_t)SEOS_ADF_OID_LEN + 2, 0x06, (uint8_t)SEOS_ADF_OID_LEN};
  188. bit_buffer_append_bytes(tx_buffer, select_adf_header, sizeof(select_adf_header));
  189. bit_buffer_append_bytes(tx_buffer, SEOS_ADF_OID, SEOS_ADF_OID_LEN);
  190. bit_buffer_append_byte(tx_buffer, 0x00); // Le
  191. seos_log_bitbuffer(TAG, "NFC transmit", tx_buffer);
  192. error = iso14443_4a_poller_send_block(iso14443_4a_poller, tx_buffer, rx_buffer);
  193. if(error != Iso14443_4aErrorNone) {
  194. FURI_LOG_W(TAG, "iso14443_4a_poller_send_block error %d", error);
  195. return NfcCommandStop;
  196. }
  197. seos_log_bitbuffer(TAG, "NFC response", rx_buffer);
  198. bit_buffer_reset(tx_buffer);
  199. return ret;
  200. }
  201. bool seos_reader_select_adf_response(
  202. BitBuffer* rx_buffer,
  203. size_t offset,
  204. SeosCredential* credential,
  205. AuthParameters* params) {
  206. seos_log_bitbuffer(TAG, "response", rx_buffer);
  207. // cd 02 0206
  208. // 85 38 41c01a89db89aecf 4b35b4f18dc4045b2a3d65cdd1c1944e8c8548f786e6c51128a5c8546a27120a7e44ba0f4cd7218a026ea1a73a9211a9
  209. // 8e 08 20f830009042cb85
  210. uint8_t expected_header[] = {0xcd, 0x02};
  211. if(bit_buffer_get_size_bytes(rx_buffer) < sizeof(expected_header)) {
  212. FURI_LOG_W(TAG, "Invalid response length");
  213. return false;
  214. }
  215. // handle when the buffer starts with other stuff
  216. const uint8_t* rx_data = bit_buffer_get_data(rx_buffer) + offset;
  217. if(memcmp(rx_data, expected_header, sizeof(expected_header)) != 0) {
  218. FURI_LOG_W(TAG, "Invalid response");
  219. return false;
  220. }
  221. params->cipher = rx_data[2];
  222. params->hash = rx_data[3];
  223. size_t bufLen = 0;
  224. uint8_t clear[0x40];
  225. if(params->cipher == AES_128_CBC) {
  226. size_t ivLen = 16;
  227. bufLen = rx_data[5] - ivLen;
  228. uint8_t* iv = (uint8_t*)rx_data + 6;
  229. uint8_t* enc = (uint8_t*)rx_data + 6 + ivLen;
  230. mbedtls_aes_context ctx;
  231. mbedtls_aes_init(&ctx);
  232. mbedtls_aes_setkey_dec(&ctx, SEOS_ADF1_PRIV_ENC, sizeof(SEOS_ADF1_PRIV_ENC) * 8);
  233. mbedtls_aes_crypt_cbc(&ctx, MBEDTLS_AES_DECRYPT, bufLen, iv, enc, clear);
  234. mbedtls_aes_free(&ctx);
  235. } else if(params->cipher == TWO_KEY_3DES_CBC_MODE) {
  236. size_t ivLen = 8;
  237. bufLen = rx_data[5] - ivLen;
  238. uint8_t* iv = (uint8_t*)rx_data + 6;
  239. uint8_t* enc = (uint8_t*)rx_data + 6 + ivLen;
  240. mbedtls_des3_context ctx;
  241. mbedtls_des3_init(&ctx);
  242. mbedtls_des3_set2key_dec(&ctx, SEOS_ADF1_PRIV_ENC);
  243. mbedtls_des3_crypt_cbc(&ctx, MBEDTLS_DES_DECRYPT, bufLen, iv, enc, clear);
  244. mbedtls_des3_free(&ctx);
  245. }
  246. // 06112b0601040181e438010102011801010202 cf 07 3d4c010c71cfa7 e2d0b41a00cc5e494c8d52b6e562592399fe614a
  247. if(clear[0] != 0x06) {
  248. FURI_LOG_W(TAG, "Missing expected 0x06 at start of clear");
  249. return false;
  250. }
  251. size_t oidLen = clear[1];
  252. if(clear[2 + oidLen] != 0xCF) {
  253. FURI_LOG_W(TAG, "Missing expected 0xCF after OID");
  254. return false;
  255. }
  256. credential->diversifier_len = clear[2 + oidLen + 1];
  257. if(credential->diversifier_len > sizeof(credential->diversifier)) {
  258. FURI_LOG_W(TAG, "diversifier too large");
  259. return false;
  260. }
  261. uint8_t* diversifier = clear + 2 + oidLen + 2;
  262. memcpy(credential->diversifier, diversifier, credential->diversifier_len);
  263. char display[SEOS_WORKER_MAX_BUFFER_SIZE * 2 + 1];
  264. memset(display, 0, sizeof(display));
  265. for(uint8_t i = 0; i < credential->diversifier_len; i++) {
  266. snprintf(display + (i * 2), sizeof(display), "%02x", diversifier[i]);
  267. }
  268. FURI_LOG_D(TAG, "diversifier: %s", display);
  269. return true;
  270. }
  271. NfcCommand seos_reader_general_authenticate_1(SeosReader* seos_reader) {
  272. Iso14443_4aPoller* iso14443_4a_poller = seos_reader->iso14443_4a_poller;
  273. BitBuffer* tx_buffer = seos_reader->tx_buffer;
  274. BitBuffer* rx_buffer = seos_reader->rx_buffer;
  275. NfcCommand ret = NfcCommandContinue;
  276. Iso14443_4aError error;
  277. general_authenticate_1[3] = seos_reader->params.key_no;
  278. bit_buffer_append_bytes(tx_buffer, general_authenticate_1, sizeof(general_authenticate_1));
  279. seos_log_bitbuffer(TAG, "NFC transmit", tx_buffer);
  280. error = iso14443_4a_poller_send_block(iso14443_4a_poller, tx_buffer, rx_buffer);
  281. if(error != Iso14443_4aErrorNone) {
  282. FURI_LOG_W(TAG, "iso14443_4a_poller_send_block error %d", error);
  283. return NfcCommandStop;
  284. }
  285. bit_buffer_reset(tx_buffer);
  286. seos_log_bitbuffer(TAG, "NFC response", rx_buffer);
  287. // 7c0a8108018cde7d6049edb09000
  288. uint8_t expected_header[] = {0x7c, 0x0a, 0x81, 0x08};
  289. const uint8_t* rx_data = bit_buffer_get_data(rx_buffer);
  290. if(memcmp(rx_data, expected_header, sizeof(expected_header)) != 0) {
  291. FURI_LOG_W(TAG, "Invalid response");
  292. return NfcCommandStop;
  293. }
  294. memcpy(seos_reader->params.rndICC, rx_data + 4, 8);
  295. return ret;
  296. }
  297. NfcCommand seos_reader_general_authenticate_2(SeosReader* seos_reader) {
  298. Iso14443_4aPoller* iso14443_4a_poller = seos_reader->iso14443_4a_poller;
  299. BitBuffer* tx_buffer = seos_reader->tx_buffer;
  300. BitBuffer* rx_buffer = seos_reader->rx_buffer;
  301. NfcCommand ret = NfcCommandContinue;
  302. Iso14443_4aError error;
  303. uint8_t cryptogram[32 + 8];
  304. memset(cryptogram, 0, sizeof(cryptogram));
  305. seos_reader_generate_cryptogram(seos_reader->credential, &seos_reader->params, cryptogram);
  306. uint8_t ga_header[] = {
  307. 0x00, 0x87, 0x00, seos_reader->params.key_no, 0x2c, 0x7c, 0x2a, 0x82, 0x28};
  308. bit_buffer_append_bytes(tx_buffer, ga_header, sizeof(ga_header));
  309. bit_buffer_append_bytes(tx_buffer, cryptogram, sizeof(cryptogram));
  310. seos_log_bitbuffer(TAG, "NFC transmit", tx_buffer);
  311. error = iso14443_4a_poller_send_block(iso14443_4a_poller, tx_buffer, rx_buffer);
  312. if(error != Iso14443_4aErrorNone) {
  313. FURI_LOG_W(TAG, "iso14443_4a_poller_send_block error %d", error);
  314. return NfcCommandStop;
  315. }
  316. bit_buffer_reset(tx_buffer);
  317. seos_log_bitbuffer(TAG, "NFC response", rx_buffer);
  318. const uint8_t* rx_data = bit_buffer_get_data(rx_buffer);
  319. if(rx_data[0] != 0x7C || rx_data[2] != 0x82) {
  320. FURI_LOG_W(TAG, "Invalid rx_data");
  321. return NfcCommandStop;
  322. }
  323. if(rx_data[3] == 40) {
  324. if(!seos_reader_verify_cryptogram(&seos_reader->params, rx_data + 4)) {
  325. FURI_LOG_W(TAG, "Card cryptogram failed verification");
  326. return NfcCommandStop;
  327. }
  328. FURI_LOG_I(TAG, "Authenticated");
  329. } else {
  330. FURI_LOG_W(TAG, "Unhandled card cryptogram size %d", rx_data[3]);
  331. }
  332. seos_reader->secure_messaging = secure_messaging_alloc(&seos_reader->params);
  333. return ret;
  334. }
  335. NfcCommand seos_state_machine(Seos* seos, Iso14443_4aPoller* iso14443_4a_poller) {
  336. furi_assert(seos);
  337. NfcCommand ret = NfcCommandContinue;
  338. SeosReader* seos_reader = seos_reader_alloc(&seos->credential, iso14443_4a_poller);
  339. seos->seos_reader = seos_reader;
  340. do {
  341. ret = seos_reader_select_aid(seos_reader);
  342. if(ret == NfcCommandStop) break;
  343. ret = seos_reader_select_adf(seos_reader);
  344. if(ret == NfcCommandStop) break;
  345. if(!seos_reader_select_adf_response(
  346. seos_reader->rx_buffer, 0, seos_reader->credential, &seos_reader->params)) {
  347. break;
  348. }
  349. ret = seos_reader_general_authenticate_1(seos_reader);
  350. if(ret == NfcCommandStop) break;
  351. ret = seos_reader_general_authenticate_2(seos_reader);
  352. if(ret == NfcCommandStop) break;
  353. if(seos_reader_request_sio(seos_reader)) {
  354. view_dispatcher_send_custom_event(seos->view_dispatcher, SeosCustomEventReaderSuccess);
  355. }
  356. } while(false);
  357. // An error occurred
  358. if(ret == NfcCommandStop) {
  359. view_dispatcher_send_custom_event(seos->view_dispatcher, SeosCustomEventReaderError);
  360. }
  361. seos_reader_free(seos_reader);
  362. return NfcCommandStop;
  363. }
  364. NfcCommand seos_worker_poller_callback(NfcGenericEvent event, void* context) {
  365. furi_assert(event.protocol == NfcProtocolIso14443_4a);
  366. NfcCommand ret = NfcCommandContinue;
  367. Seos* seos = context;
  368. const Iso14443_4aPollerEvent* iso14443_4a_event = event.event_data;
  369. Iso14443_4aPoller* iso14443_4a_poller = event.instance;
  370. if(iso14443_4a_event->type == Iso14443_4aPollerEventTypeReady) {
  371. // view_dispatcher_send_custom_event(seos->view_dispatcher, SeosCustomEventPollerDetect);
  372. nfc_device_set_data(
  373. seos->nfc_device, NfcProtocolIso14443_4a, nfc_poller_get_data(seos->poller));
  374. ret = seos_state_machine(seos, iso14443_4a_poller);
  375. // furi_thread_set_current_priority(FuriThreadPriorityLowest);
  376. } else if(iso14443_4a_event->type == Iso14443_4aPollerEventTypeError) {
  377. Iso14443_4aPollerEventData* data = iso14443_4a_event->data;
  378. Iso14443_4aError error = data->error;
  379. FURI_LOG_W(TAG, "Iso14443_4aError %i", error);
  380. // I was hoping to catch MFC here, but it seems to be treated the same (None) as no card being present.
  381. switch(error) {
  382. case Iso14443_4aErrorNone:
  383. break;
  384. case Iso14443_4aErrorNotPresent:
  385. break;
  386. case Iso14443_4aErrorProtocol:
  387. ret = NfcCommandStop;
  388. break;
  389. case Iso14443_4aErrorTimeout:
  390. break;
  391. }
  392. }
  393. return ret;
  394. }