secure_messaging.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393
  1. #include "secure_messaging.h"
  2. #define TAG "SecureMessaging"
  3. uint8_t padding[16] =
  4. {0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
  5. void secure_messaging_adjust_parity(uint8_t key[16]) {
  6. for(size_t i = 0; i < 16; i++) {
  7. // Set the parity bit to 1 if the number of 1 bits is even
  8. for(size_t j = 0; j < 8; j++) {
  9. if((key[i] >> j) & 0x01) {
  10. key[i] ^= 0x01;
  11. }
  12. }
  13. key[i] ^= 0x01;
  14. }
  15. }
  16. void secure_messaging_key_diversification(uint8_t input[20], uint8_t* output) {
  17. uint8_t sha[20];
  18. mbedtls_sha1_context ctx;
  19. mbedtls_sha1_init(&ctx);
  20. mbedtls_sha1_starts(&ctx);
  21. mbedtls_sha1_update(&ctx, input, 20);
  22. mbedtls_sha1_finish(&ctx, sha);
  23. memcpy(output, sha, 16);
  24. secure_messaging_adjust_parity(output);
  25. }
  26. SecureMessaging* secure_messaging_alloc(
  27. uint8_t* passport_number,
  28. uint8_t* date_of_birth,
  29. uint8_t* date_of_expiry) {
  30. SecureMessaging* secure_messaging = malloc(sizeof(SecureMessaging));
  31. memset(secure_messaging, 0, sizeof(SecureMessaging));
  32. mbedtls_sha1_context ctx;
  33. memset(secure_messaging->rndIFD, 0x00, sizeof(secure_messaging->rndIFD));
  34. memset(secure_messaging->Kifd, 0x00, sizeof(secure_messaging->Kifd));
  35. uint8_t mrz[SECURE_MESSAGING_MAX_SIZE];
  36. size_t mrz_index = 0;
  37. strncpy((char*)mrz, (char*)passport_number, 12);
  38. mrz_index += strlen((char*)passport_number);
  39. strncpy((char*)mrz + mrz_index, (char*)date_of_birth, 8);
  40. mrz_index += strlen((char*)date_of_birth);
  41. strncpy((char*)mrz + mrz_index, (char*)date_of_expiry, 8);
  42. mrz_index += strlen((char*)date_of_expiry);
  43. FURI_LOG_D(TAG, "secure_messaging_alloc mrz %s", mrz);
  44. uint8_t sha[20];
  45. mbedtls_sha1_init(&ctx);
  46. mbedtls_sha1_starts(&ctx);
  47. mbedtls_sha1_update(&ctx, mrz, mrz_index);
  48. mbedtls_sha1_finish(&ctx, sha);
  49. passy_log_buffer(TAG, "secure_messaging_alloc sha", sha, sizeof(sha));
  50. uint8_t D[20];
  51. memset(D, 0, sizeof(D));
  52. memcpy(D, sha, 16);
  53. D[19] = 0x01;
  54. mbedtls_sha1_init(&ctx);
  55. mbedtls_sha1_starts(&ctx);
  56. mbedtls_sha1_update(&ctx, D, sizeof(D));
  57. mbedtls_sha1_finish(&ctx, sha);
  58. memcpy(secure_messaging->KENC, sha, 16);
  59. passy_log_buffer(
  60. TAG, "secure_messaging_alloc KENC", secure_messaging->KENC, sizeof(secure_messaging->KENC));
  61. // Adjust the parity bits
  62. secure_messaging_adjust_parity(secure_messaging->KENC);
  63. passy_log_buffer(
  64. TAG, "secure_messaging_alloc KENC", secure_messaging->KENC, sizeof(secure_messaging->KENC));
  65. D[19] = 0x02;
  66. mbedtls_sha1_init(&ctx);
  67. mbedtls_sha1_starts(&ctx);
  68. mbedtls_sha1_update(&ctx, D, sizeof(D));
  69. mbedtls_sha1_finish(&ctx, sha);
  70. memcpy(secure_messaging->KMAC, sha, 16);
  71. passy_log_buffer(
  72. TAG, "secure_messaging_alloc KMAC", secure_messaging->KMAC, sizeof(secure_messaging->KMAC));
  73. secure_messaging_adjust_parity(secure_messaging->KMAC);
  74. passy_log_buffer(
  75. TAG, "secure_messaging_alloc KMAC", secure_messaging->KMAC, sizeof(secure_messaging->KMAC));
  76. mbedtls_sha1_free(&ctx);
  77. return secure_messaging;
  78. }
  79. void secure_messaging_free(SecureMessaging* secure_messaging) {
  80. furi_assert(secure_messaging);
  81. // Nothing to free;
  82. free(secure_messaging);
  83. }
  84. void secure_messaging_calculate_session_keys(SecureMessaging* secure_messaging) {
  85. uint8_t Kseed[16];
  86. for(size_t i = 0; i < sizeof(Kseed); i++) {
  87. Kseed[i] = secure_messaging->Kifd[i] ^ secure_messaging->Kicc[i];
  88. }
  89. passy_log_buffer(TAG, "secure_messaging_calculate_session_keys Kseed", Kseed, sizeof(Kseed));
  90. mbedtls_sha1_context ctx;
  91. uint8_t D[20];
  92. uint8_t sha[20];
  93. memset(D, 0, sizeof(D));
  94. memcpy(D, Kseed, sizeof(Kseed));
  95. D[19] = 0x01;
  96. mbedtls_sha1_init(&ctx);
  97. mbedtls_sha1_starts(&ctx);
  98. mbedtls_sha1_update(&ctx, D, sizeof(D));
  99. mbedtls_sha1_finish(&ctx, sha);
  100. memcpy(secure_messaging->KSenc, sha, 16);
  101. secure_messaging_adjust_parity(secure_messaging->KSenc);
  102. passy_log_buffer(
  103. TAG,
  104. "secure_messaging_calculate_session_keys KSenc",
  105. secure_messaging->KSenc,
  106. sizeof(secure_messaging->KSenc));
  107. memset(D, 0, sizeof(D));
  108. memcpy(D, Kseed, sizeof(Kseed));
  109. D[19] = 0x02;
  110. mbedtls_sha1_init(&ctx);
  111. mbedtls_sha1_starts(&ctx);
  112. mbedtls_sha1_update(&ctx, D, sizeof(D));
  113. mbedtls_sha1_finish(&ctx, sha);
  114. memcpy(secure_messaging->KSmac, sha, 16);
  115. secure_messaging_adjust_parity(secure_messaging->KSmac);
  116. passy_log_buffer(
  117. TAG,
  118. "secure_messaging_calculate_session_keys KSmac",
  119. secure_messaging->KSmac,
  120. sizeof(secure_messaging->KSmac));
  121. }
  122. void secure_messaging_increment_context(SecureMessaging* secure_messaging) {
  123. uint8_t* context = secure_messaging->SSC;
  124. size_t context_len = sizeof(secure_messaging->SSC);
  125. do {
  126. } while(++context[--context_len] == 0 && context_len > 0);
  127. }
  128. void secure_messaging_wrap_apdu(
  129. SecureMessaging* secure_messaging,
  130. uint8_t* message,
  131. size_t message_len,
  132. BitBuffer* tx_buffer) {
  133. furi_assert(secure_messaging);
  134. secure_messaging_increment_context(secure_messaging);
  135. uint8_t payload_length = 0;
  136. bool has_le = false;
  137. if(message_len == 5) { // APDU with no payload and Le
  138. has_le = true;
  139. } else {
  140. payload_length = message[4];
  141. }
  142. if(has_le) {
  143. FURI_LOG_I(TAG, "secure_messaging_wrap_apdu has_le %d", message[message_len - 1]);
  144. }
  145. uint8_t cmd_header[8];
  146. memset(cmd_header, 0, sizeof(cmd_header));
  147. memcpy(cmd_header, message, 4);
  148. cmd_header[0] |= 0x0c;
  149. cmd_header[4] = 0x80;
  150. uint8_t D087[3 + 8];
  151. if(payload_length > 0) {
  152. uint8_t* payload = message + 5;
  153. if(payload_length > 7) {
  154. FURI_LOG_W(TAG, "secure_messaging_wrap_apdu payload length too large to handle");
  155. return;
  156. }
  157. uint8_t padded_payload[8];
  158. memset(padded_payload, 0, sizeof(padded_payload));
  159. memcpy(padded_payload, payload, payload_length);
  160. padded_payload[payload_length] = 0x80;
  161. passy_log_buffer(
  162. TAG,
  163. "secure_messaging_wrap_apdu padded_payload",
  164. padded_payload,
  165. sizeof(padded_payload));
  166. uint8_t encrypted_payload[8];
  167. uint8_t iv[8];
  168. memset(iv, 0, sizeof(iv));
  169. mbedtls_des3_context ctx;
  170. mbedtls_des3_init(&ctx);
  171. mbedtls_des3_set2key_enc(&ctx, secure_messaging->KSenc);
  172. mbedtls_des3_crypt_cbc(
  173. &ctx,
  174. MBEDTLS_DES_ENCRYPT,
  175. sizeof(padded_payload),
  176. iv,
  177. padded_payload,
  178. encrypted_payload);
  179. mbedtls_des3_free(&ctx);
  180. memset(D087, 0, sizeof(D087));
  181. D087[0] = 0x87;
  182. D087[1] = 1 + sizeof(encrypted_payload);
  183. D087[2] = 0x01; // TODO: look into the meaning of this
  184. memcpy(D087 + 3, encrypted_payload, sizeof(encrypted_payload));
  185. }
  186. uint8_t D097[3];
  187. memset(D097, 0, sizeof(D097));
  188. if(has_le) {
  189. D097[0] = 0x97;
  190. D097[1] = 0x01;
  191. D097[2] = message[message_len - 1];
  192. }
  193. uint8_t M[8 + 3 + 8 /* + 2*/];
  194. uint8_t M_index = 0;
  195. memset(M, 0, sizeof(M));
  196. memcpy(M, cmd_header, sizeof(cmd_header));
  197. M_index += sizeof(cmd_header);
  198. if(payload_length > 0) {
  199. memcpy(M + M_index, D087, sizeof(D087));
  200. M_index += sizeof(D087);
  201. }
  202. if(has_le) {
  203. memcpy(M + M_index, D097, sizeof(D097));
  204. M_index += sizeof(D097);
  205. }
  206. passy_log_buffer(TAG, "secure_messaging_wrap_apdu M", M, M_index);
  207. uint8_t N[32];
  208. uint8_t N_index = 0;
  209. memset(N, 0, sizeof(N));
  210. memcpy(N, secure_messaging->SSC, sizeof(secure_messaging->SSC));
  211. N_index += sizeof(secure_messaging->SSC);
  212. memcpy(N + N_index, M, M_index);
  213. N_index += M_index;
  214. N[N_index++] = 0x80;
  215. // Align to 8 bytes
  216. uint8_t block_count = (N_index + 7) / 8;
  217. N_index = block_count * 8;
  218. passy_log_buffer(TAG, "secure_messaging_wrap_apdu N", N, N_index);
  219. uint8_t mac[8];
  220. passy_mac(secure_messaging->KSmac, N, N_index, mac, true);
  221. passy_log_buffer(TAG, "secure_messaging_wrap_apdu mac", mac, sizeof(mac));
  222. uint8_t D08E[2 + 8];
  223. memset(D08E, 0, sizeof(D08E));
  224. D08E[0] = 0x8E;
  225. D08E[1] = sizeof(mac);
  226. memcpy(D08E + 2, mac, sizeof(mac));
  227. bit_buffer_append_bytes(tx_buffer, cmd_header, 4);
  228. uint8_t protected_payload_length = 0;
  229. protected_payload_length += sizeof(D08E);
  230. if(payload_length > 0) {
  231. protected_payload_length += sizeof(D087);
  232. }
  233. if(has_le) {
  234. protected_payload_length += sizeof(D097);
  235. }
  236. // Lc
  237. bit_buffer_append_byte(tx_buffer, protected_payload_length);
  238. if(payload_length > 0) {
  239. bit_buffer_append_bytes(tx_buffer, D087, sizeof(D087));
  240. }
  241. if(has_le) {
  242. bit_buffer_append_bytes(tx_buffer, D097, sizeof(D097));
  243. }
  244. bit_buffer_append_bytes(tx_buffer, D08E, sizeof(D08E));
  245. bit_buffer_append_byte(tx_buffer, 0x00); // Le
  246. }
  247. void secure_messaging_unwrap_rapdu(SecureMessaging* secure_messaging, BitBuffer* rx_buffer) {
  248. secure_messaging_increment_context(secure_messaging);
  249. size_t length = bit_buffer_get_size_bytes(rx_buffer);
  250. const uint8_t* data = bit_buffer_get_data(rx_buffer);
  251. uint8_t status_word[2];
  252. uint8_t* mac = NULL;
  253. uint8_t* encrypted = NULL;
  254. uint8_t encrypted_len = 0;
  255. // Look for mac
  256. uint8_t i = 0;
  257. do {
  258. uint8_t type = data[i++];
  259. uint8_t len = data[i++];
  260. switch(type) {
  261. case 0x87:
  262. // Encrypted data always starts with a 0x01
  263. encrypted = (uint8_t*)data + i + 1;
  264. encrypted_len = len - 1;
  265. break;
  266. case 0x8E:
  267. mac = (uint8_t*)data + i;
  268. break;
  269. case 0x99:
  270. status_word[0] = data[i + 0];
  271. status_word[1] = data[i + 1];
  272. break;
  273. default:
  274. FURI_LOG_W(TAG, "Unknown type %02x", type);
  275. break;
  276. }
  277. i += len;
  278. } while(i < length - 2);
  279. if(mac) {
  280. uint8_t K[SECURE_MESSAGING_MAX_SIZE];
  281. memset(K, 0, sizeof(K));
  282. uint8_t K_index = 0;
  283. memcpy(K, secure_messaging->SSC, sizeof(secure_messaging->SSC));
  284. K_index += sizeof(secure_messaging->SSC);
  285. if(encrypted) {
  286. K[K_index++] = 0x87;
  287. K[K_index++] = encrypted_len + 1;
  288. K[K_index++] = 0x01;
  289. memcpy(K + K_index, encrypted, encrypted_len);
  290. K_index += encrypted_len;
  291. }
  292. // Assume the status word is always present
  293. K[K_index++] = 0x99;
  294. K[K_index++] = 0x02;
  295. memcpy(K + K_index, status_word, 2);
  296. K_index += 2;
  297. K[K_index++] = 0x80;
  298. // Align to 8 bytes
  299. uint8_t block_count = (K_index + 7) / 8;
  300. K_index = block_count * 8;
  301. passy_log_buffer(TAG, "secure_messaging_unwrap_rapdu K", K, K_index);
  302. uint8_t calculated_mac[8];
  303. passy_mac(secure_messaging->KSmac, K, K_index, calculated_mac, true);
  304. passy_log_buffer(
  305. TAG,
  306. "secure_messaging_unwrap_rapdu calculated_mac",
  307. calculated_mac,
  308. sizeof(calculated_mac));
  309. if(memcmp(mac, calculated_mac, sizeof(calculated_mac)) != 0) {
  310. FURI_LOG_W(TAG, "Invalid MAC");
  311. return;
  312. }
  313. }
  314. uint8_t decrypted[SECURE_MESSAGING_MAX_SIZE];
  315. uint8_t decrypted_len = encrypted_len;
  316. if(encrypted) {
  317. if(encrypted_len > sizeof(decrypted)) {
  318. FURI_LOG_W(TAG, "secure_messaging_unwrap_rapdu encrypted length too large to handle");
  319. return;
  320. }
  321. uint8_t iv[8];
  322. memset(iv, 0, sizeof(iv));
  323. mbedtls_des3_context ctx;
  324. mbedtls_des3_init(&ctx);
  325. mbedtls_des3_set2key_dec(&ctx, secure_messaging->KSenc);
  326. mbedtls_des3_crypt_cbc(&ctx, MBEDTLS_DES_DECRYPT, encrypted_len, iv, encrypted, decrypted);
  327. mbedtls_des3_free(&ctx);
  328. // Remove padding
  329. do {
  330. } while(decrypted[--decrypted_len] == 0 && decrypted_len > 0);
  331. passy_log_buffer(TAG, "secure_messaging_unwrap_rapdu decrypted", decrypted, decrypted_len);
  332. }
  333. // Don't reset until after data has been decrypted
  334. bit_buffer_reset(rx_buffer);
  335. if(encrypted) {
  336. bit_buffer_append_bytes(rx_buffer, decrypted, decrypted_len);
  337. }
  338. bit_buffer_append_bytes(rx_buffer, status_word, 2);
  339. }