seos_reader.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487
  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. memset(credential->adf_response, 0, sizeof(credential->adf_response));
  224. memcpy(
  225. credential->adf_response,
  226. rx_data,
  227. bit_buffer_get_size_bytes(rx_buffer) - offset - sizeof(success));
  228. size_t bufLen = 0;
  229. uint8_t clear[0x40];
  230. if(params->cipher == AES_128_CBC) {
  231. size_t ivLen = 16;
  232. bufLen = rx_data[5] - ivLen;
  233. uint8_t* iv = (uint8_t*)rx_data + 6;
  234. uint8_t* enc = (uint8_t*)rx_data + 6 + ivLen;
  235. mbedtls_aes_context ctx;
  236. mbedtls_aes_init(&ctx);
  237. mbedtls_aes_setkey_dec(&ctx, SEOS_ADF1_PRIV_ENC, sizeof(SEOS_ADF1_PRIV_ENC) * 8);
  238. mbedtls_aes_crypt_cbc(&ctx, MBEDTLS_AES_DECRYPT, bufLen, iv, enc, clear);
  239. mbedtls_aes_free(&ctx);
  240. } else if(params->cipher == TWO_KEY_3DES_CBC_MODE) {
  241. size_t ivLen = 8;
  242. bufLen = rx_data[5] - ivLen;
  243. uint8_t* iv = (uint8_t*)rx_data + 6;
  244. uint8_t* enc = (uint8_t*)rx_data + 6 + ivLen;
  245. mbedtls_des3_context ctx;
  246. mbedtls_des3_init(&ctx);
  247. mbedtls_des3_set2key_dec(&ctx, SEOS_ADF1_PRIV_ENC);
  248. mbedtls_des3_crypt_cbc(&ctx, MBEDTLS_DES_DECRYPT, bufLen, iv, enc, clear);
  249. mbedtls_des3_free(&ctx);
  250. }
  251. // 06112b0601040181e438010102011801010202 cf 07 3d4c010c71cfa7 e2d0b41a00cc5e494c8d52b6e562592399fe614a
  252. if(clear[0] != 0x06) {
  253. FURI_LOG_W(TAG, "Missing expected 0x06 at start of clear");
  254. return false;
  255. }
  256. size_t oidLen = clear[1];
  257. if(clear[2 + oidLen] != 0xCF) {
  258. FURI_LOG_W(TAG, "Missing expected 0xCF after OID");
  259. return false;
  260. }
  261. credential->diversifier_len = clear[2 + oidLen + 1];
  262. if(credential->diversifier_len > sizeof(credential->diversifier)) {
  263. FURI_LOG_W(TAG, "diversifier too large");
  264. return false;
  265. }
  266. uint8_t* diversifier = clear + 2 + oidLen + 2;
  267. memcpy(credential->diversifier, diversifier, credential->diversifier_len);
  268. char display[SEOS_WORKER_MAX_BUFFER_SIZE * 2 + 1];
  269. memset(display, 0, sizeof(display));
  270. for(uint8_t i = 0; i < credential->diversifier_len; i++) {
  271. snprintf(display + (i * 2), sizeof(display), "%02x", diversifier[i]);
  272. }
  273. FURI_LOG_D(TAG, "diversifier: %s", display);
  274. return true;
  275. }
  276. NfcCommand seos_reader_general_authenticate_1(SeosReader* seos_reader) {
  277. Iso14443_4aPoller* iso14443_4a_poller = seos_reader->iso14443_4a_poller;
  278. BitBuffer* tx_buffer = seos_reader->tx_buffer;
  279. BitBuffer* rx_buffer = seos_reader->rx_buffer;
  280. NfcCommand ret = NfcCommandContinue;
  281. Iso14443_4aError error;
  282. general_authenticate_1[3] = seos_reader->params.key_no;
  283. bit_buffer_append_bytes(tx_buffer, general_authenticate_1, sizeof(general_authenticate_1));
  284. seos_log_bitbuffer(TAG, "NFC transmit", tx_buffer);
  285. error = iso14443_4a_poller_send_block(iso14443_4a_poller, tx_buffer, rx_buffer);
  286. if(error != Iso14443_4aErrorNone) {
  287. FURI_LOG_W(TAG, "iso14443_4a_poller_send_block error %d", error);
  288. return NfcCommandStop;
  289. }
  290. bit_buffer_reset(tx_buffer);
  291. seos_log_bitbuffer(TAG, "NFC response", rx_buffer);
  292. // 7c0a8108018cde7d6049edb09000
  293. uint8_t expected_header[] = {0x7c, 0x0a, 0x81, 0x08};
  294. const uint8_t* rx_data = bit_buffer_get_data(rx_buffer);
  295. if(memcmp(rx_data, expected_header, sizeof(expected_header)) != 0) {
  296. FURI_LOG_W(TAG, "Invalid response");
  297. return NfcCommandStop;
  298. }
  299. memcpy(seos_reader->params.rndICC, rx_data + 4, 8);
  300. return ret;
  301. }
  302. NfcCommand seos_reader_general_authenticate_2(SeosReader* seos_reader) {
  303. Iso14443_4aPoller* iso14443_4a_poller = seos_reader->iso14443_4a_poller;
  304. BitBuffer* tx_buffer = seos_reader->tx_buffer;
  305. BitBuffer* rx_buffer = seos_reader->rx_buffer;
  306. NfcCommand ret = NfcCommandContinue;
  307. Iso14443_4aError error;
  308. uint8_t cryptogram[32 + 8];
  309. memset(cryptogram, 0, sizeof(cryptogram));
  310. seos_reader_generate_cryptogram(seos_reader->credential, &seos_reader->params, cryptogram);
  311. uint8_t ga_header[] = {
  312. 0x00, 0x87, 0x00, seos_reader->params.key_no, 0x2c, 0x7c, 0x2a, 0x82, 0x28};
  313. bit_buffer_append_bytes(tx_buffer, ga_header, sizeof(ga_header));
  314. bit_buffer_append_bytes(tx_buffer, cryptogram, sizeof(cryptogram));
  315. seos_log_bitbuffer(TAG, "NFC transmit", tx_buffer);
  316. error = iso14443_4a_poller_send_block(iso14443_4a_poller, tx_buffer, rx_buffer);
  317. if(error != Iso14443_4aErrorNone) {
  318. FURI_LOG_W(TAG, "iso14443_4a_poller_send_block error %d", error);
  319. return NfcCommandStop;
  320. }
  321. bit_buffer_reset(tx_buffer);
  322. seos_log_bitbuffer(TAG, "NFC response", rx_buffer);
  323. const uint8_t* rx_data = bit_buffer_get_data(rx_buffer);
  324. if(rx_data[0] != 0x7C || rx_data[2] != 0x82) {
  325. FURI_LOG_W(TAG, "Invalid rx_data");
  326. return NfcCommandStop;
  327. }
  328. if(rx_data[3] == 40) {
  329. if(!seos_reader_verify_cryptogram(&seos_reader->params, rx_data + 4)) {
  330. FURI_LOG_W(TAG, "Card cryptogram failed verification");
  331. return NfcCommandStop;
  332. }
  333. FURI_LOG_I(TAG, "Authenticated");
  334. } else {
  335. FURI_LOG_W(TAG, "Unhandled card cryptogram size %d", rx_data[3]);
  336. }
  337. seos_reader->secure_messaging = secure_messaging_alloc(&seos_reader->params);
  338. return ret;
  339. }
  340. NfcCommand seos_state_machine(Seos* seos, Iso14443_4aPoller* iso14443_4a_poller) {
  341. furi_assert(seos);
  342. NfcCommand ret = NfcCommandContinue;
  343. SeosReader* seos_reader = seos_reader_alloc(&seos->credential, iso14443_4a_poller);
  344. seos->seos_reader = seos_reader;
  345. do {
  346. ret = seos_reader_select_aid(seos_reader);
  347. if(ret == NfcCommandStop) break;
  348. ret = seos_reader_select_adf(seos_reader);
  349. if(ret == NfcCommandStop) break;
  350. if(!seos_reader_select_adf_response(
  351. seos_reader->rx_buffer, 0, seos_reader->credential, &seos_reader->params)) {
  352. break;
  353. }
  354. ret = seos_reader_general_authenticate_1(seos_reader);
  355. if(ret == NfcCommandStop) break;
  356. ret = seos_reader_general_authenticate_2(seos_reader);
  357. if(ret == NfcCommandStop) break;
  358. if(seos_reader_request_sio(seos_reader)) {
  359. SeosCredential* credential = seos_reader->credential;
  360. credential->adf_oid_len = SEOS_ADF_OID_LEN;
  361. memcpy(credential->adf_oid, SEOS_ADF_OID, sizeof(credential->adf_oid));
  362. view_dispatcher_send_custom_event(seos->view_dispatcher, SeosCustomEventReaderSuccess);
  363. }
  364. } while(false);
  365. // An error occurred
  366. if(ret == NfcCommandStop) {
  367. view_dispatcher_send_custom_event(seos->view_dispatcher, SeosCustomEventReaderError);
  368. }
  369. seos_reader_free(seos_reader);
  370. return NfcCommandStop;
  371. }
  372. NfcCommand seos_worker_poller_callback(NfcGenericEvent event, void* context) {
  373. furi_assert(event.protocol == NfcProtocolIso14443_4a);
  374. NfcCommand ret = NfcCommandContinue;
  375. Seos* seos = context;
  376. const Iso14443_4aPollerEvent* iso14443_4a_event = event.event_data;
  377. Iso14443_4aPoller* iso14443_4a_poller = event.instance;
  378. if(iso14443_4a_event->type == Iso14443_4aPollerEventTypeReady) {
  379. // view_dispatcher_send_custom_event(seos->view_dispatcher, SeosCustomEventPollerDetect);
  380. nfc_device_set_data(
  381. seos->nfc_device, NfcProtocolIso14443_4a, nfc_poller_get_data(seos->poller));
  382. ret = seos_state_machine(seos, iso14443_4a_poller);
  383. // furi_thread_set_current_priority(FuriThreadPriorityLowest);
  384. } else if(iso14443_4a_event->type == Iso14443_4aPollerEventTypeError) {
  385. Iso14443_4aPollerEventData* data = iso14443_4a_event->data;
  386. Iso14443_4aError error = data->error;
  387. FURI_LOG_W(TAG, "Iso14443_4aError %i", error);
  388. // I was hoping to catch MFC here, but it seems to be treated the same (None) as no card being present.
  389. switch(error) {
  390. case Iso14443_4aErrorNone:
  391. break;
  392. case Iso14443_4aErrorNotPresent:
  393. break;
  394. case Iso14443_4aErrorProtocol:
  395. ret = NfcCommandStop;
  396. break;
  397. case Iso14443_4aErrorTimeout:
  398. break;
  399. }
  400. }
  401. return ret;
  402. }