secure_messaging.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349
  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. SecureMessaging* secure_messaging_alloc(AuthParameters* params) {
  6. SecureMessaging* secure_messaging = malloc(sizeof(SecureMessaging));
  7. memset(secure_messaging, 0, sizeof(SecureMessaging));
  8. secure_messaging->cipher = params->cipher;
  9. if(params->cipher == AES_128_CBC) {
  10. memcpy(secure_messaging->aesContext, params->rndICC, 8);
  11. memcpy(secure_messaging->aesContext + 8, params->UID, 8);
  12. } else if(params->cipher == TWO_KEY_3DES_CBC_MODE) {
  13. memcpy(secure_messaging->desContext, params->rndICC, 4);
  14. memcpy(secure_messaging->desContext + 4, params->UID, 4);
  15. } else {
  16. FURI_LOG_W(TAG, "Cipher not matched");
  17. }
  18. size_t index = 0;
  19. uint8_t buffer[38];
  20. memset(buffer, 0, sizeof(buffer));
  21. index += 4; // skip 4 bytes where iteration will be put
  22. memcpy(buffer + index, params->cNonce, 8);
  23. index += 8;
  24. memcpy(buffer + index, params->rNonce, 8);
  25. index += 8;
  26. buffer[index++] = params->cipher;
  27. buffer[index++] = params->cipher;
  28. memcpy(buffer + index, params->rndICC, 8);
  29. index += 8;
  30. memcpy(buffer + index, params->UID, 8);
  31. index += 8;
  32. size_t iterations = 1;
  33. size_t unit = 0;
  34. if(params->hash == SHA1) {
  35. unit = 160 / 8;
  36. } else if(params->hash == SHA256) {
  37. unit = 256 / 8;
  38. }
  39. // FURI_LOG_D(TAG, "secure_messaging_alloc hash %d unit %d", hash, unit);
  40. // More than enough space for the hash
  41. uint8_t accumulator[64];
  42. memset(accumulator, 0, sizeof(accumulator));
  43. for(size_t i = 0; i < 32; i += unit) {
  44. buffer[3] = iterations++;
  45. if(params->hash == SHA1) {
  46. mbedtls_sha1_context ctx;
  47. mbedtls_sha1_init(&ctx);
  48. mbedtls_sha1_starts(&ctx);
  49. mbedtls_sha1_update(&ctx, buffer, index);
  50. mbedtls_sha1_finish(&ctx, accumulator + i);
  51. mbedtls_sha1_free(&ctx);
  52. } else if(params->hash == SHA256) {
  53. mbedtls_sha256_context ctx;
  54. mbedtls_sha256_init(&ctx);
  55. mbedtls_sha256_starts(&ctx, 0);
  56. mbedtls_sha256_update(&ctx, buffer, index);
  57. mbedtls_sha256_finish(&ctx, accumulator + i);
  58. mbedtls_sha256_free(&ctx);
  59. } else {
  60. FURI_LOG_W(TAG, "Could not match hash algorithm");
  61. }
  62. }
  63. memcpy(secure_messaging->PrivacyKey, accumulator, 16);
  64. memcpy(secure_messaging->CMACKey, accumulator + 16, 16);
  65. return secure_messaging;
  66. }
  67. void secure_messaging_free(SecureMessaging* secure_messaging) {
  68. furi_assert(secure_messaging);
  69. // Nothing to free;
  70. free(secure_messaging);
  71. }
  72. void secure_messaging_increment_context(SecureMessaging* secure_messaging) {
  73. uint8_t* context = NULL;
  74. size_t context_len = 0;
  75. if(secure_messaging->cipher == AES_128_CBC) {
  76. context = secure_messaging->aesContext;
  77. context_len = sizeof(secure_messaging->aesContext);
  78. } else if(secure_messaging->cipher == TWO_KEY_3DES_CBC_MODE) {
  79. context = secure_messaging->desContext;
  80. context_len = sizeof(secure_messaging->desContext);
  81. } else {
  82. FURI_LOG_W(TAG, "Cipher not matched");
  83. return;
  84. }
  85. do {
  86. } while(++context[--context_len] == 0 && context_len > 0);
  87. }
  88. void secure_messaging_wrap_apdu(
  89. SecureMessaging* secure_messaging,
  90. uint8_t* message,
  91. size_t message_len,
  92. BitBuffer* tx_buffer) {
  93. secure_messaging_increment_context(secure_messaging);
  94. uint8_t cipher = secure_messaging->cipher;
  95. if(message_len > SECURE_MESSAGING_MAX_SIZE) {
  96. FURI_LOG_W(TAG, "Message too long to wrap");
  97. return;
  98. }
  99. uint8_t clear[SECURE_MESSAGING_MAX_SIZE];
  100. memset(clear, 0, sizeof(clear));
  101. memcpy(clear, message, message_len);
  102. clear[message_len] = 0x80;
  103. uint8_t block_size = cipher == AES_128_CBC ? 16 : 8;
  104. uint8_t block_count = (message_len + block_size - 1) / block_size;
  105. size_t clear_len = block_count * block_size;
  106. uint8_t encrypted[SECURE_MESSAGING_MAX_SIZE];
  107. if(cipher == AES_128_CBC) {
  108. seos_worker_aes_encrypt(secure_messaging->PrivacyKey, clear_len, clear, encrypted);
  109. } else if(cipher == TWO_KEY_3DES_CBC_MODE) {
  110. seos_worker_des_encrypt(secure_messaging->PrivacyKey, clear_len, clear, encrypted);
  111. } else {
  112. FURI_LOG_W(TAG, "Cipher not matched");
  113. }
  114. uint8_t header[] = {0x0c, 0xcb, 0x3f, 0xff};
  115. uint8_t encrypted_prefix[] = {0x85, clear_len};
  116. uint8_t no_something[] = {0x97, 0x00};
  117. uint8_t cmac[16];
  118. BitBuffer* cmacInput = bit_buffer_alloc(256);
  119. bit_buffer_reset(cmacInput);
  120. if(cipher == AES_128_CBC) {
  121. uint8_t* context = secure_messaging->aesContext;
  122. bit_buffer_append_bytes(cmacInput, context, block_size);
  123. bit_buffer_append_bytes(cmacInput, header, sizeof(header));
  124. bit_buffer_append_bytes(cmacInput, padding, block_size - sizeof(header));
  125. bit_buffer_append_bytes(cmacInput, encrypted_prefix, sizeof(encrypted_prefix));
  126. bit_buffer_append_bytes(cmacInput, encrypted, clear_len);
  127. bit_buffer_append_bytes(cmacInput, no_something, sizeof(no_something));
  128. // Need to pad [encrypted_prefix, encrypted, no_something], and encrypted is by definition block_size units,so we just need to pad to align the other 4.
  129. bit_buffer_append_bytes(cmacInput, padding, block_size - 4);
  130. aes_cmac(
  131. secure_messaging->CMACKey,
  132. sizeof(secure_messaging->CMACKey),
  133. (uint8_t*)bit_buffer_get_data(cmacInput),
  134. bit_buffer_get_size_bytes(cmacInput),
  135. cmac);
  136. } else if(cipher == TWO_KEY_3DES_CBC_MODE) {
  137. uint8_t* context = secure_messaging->desContext;
  138. bit_buffer_append_bytes(cmacInput, context, block_size);
  139. bit_buffer_append_bytes(cmacInput, header, sizeof(header));
  140. bit_buffer_append_bytes(cmacInput, padding, block_size - sizeof(header));
  141. bit_buffer_append_bytes(cmacInput, encrypted_prefix, sizeof(encrypted_prefix));
  142. bit_buffer_append_bytes(cmacInput, encrypted, clear_len);
  143. bit_buffer_append_bytes(cmacInput, no_something, sizeof(no_something));
  144. // Need to pad [encrypted_prefix, encrypted, no_something], and encrypted is by definition block_size units,so we just need to pad to align the other 4.
  145. bit_buffer_append_bytes(cmacInput, padding, block_size - 4);
  146. des_cmac(
  147. secure_messaging->CMACKey,
  148. sizeof(secure_messaging->CMACKey),
  149. (uint8_t*)bit_buffer_get_data(cmacInput),
  150. bit_buffer_get_size_bytes(cmacInput),
  151. cmac);
  152. } else {
  153. FURI_LOG_W(TAG, "Cipher not matched");
  154. }
  155. bit_buffer_free(cmacInput);
  156. uint8_t apdu_len[] = {2 + clear_len + 2 + 2 + 8};
  157. uint8_t cmac_prefix[] = {0x8e, 0x08};
  158. uint8_t Le[] = {0x00};
  159. bit_buffer_reset(tx_buffer);
  160. bit_buffer_append_bytes(tx_buffer, header, sizeof(header));
  161. bit_buffer_append_bytes(tx_buffer, apdu_len, sizeof(apdu_len));
  162. bit_buffer_append_bytes(tx_buffer, encrypted_prefix, sizeof(encrypted_prefix));
  163. bit_buffer_append_bytes(tx_buffer, encrypted, clear_len);
  164. bit_buffer_append_bytes(tx_buffer, no_something, sizeof(no_something));
  165. bit_buffer_append_bytes(tx_buffer, cmac_prefix, sizeof(cmac_prefix));
  166. bit_buffer_append_bytes(tx_buffer, cmac, 8);
  167. bit_buffer_append_bytes(tx_buffer, Le, sizeof(Le));
  168. }
  169. void secure_messaging_unwrap_rapdu(SecureMessaging* secure_messaging, BitBuffer* rx_buffer) {
  170. secure_messaging_increment_context(secure_messaging);
  171. // 8540 <encrypted> 99029000 8e08 <cmac>
  172. size_t encrypted_len = bit_buffer_get_byte(rx_buffer, 1);
  173. const uint8_t* encrypted = bit_buffer_get_data(rx_buffer) + 2;
  174. // const uint8_t *cmac = bit_buffer_get_data(rx_buffer) + 2 + encrypted_len + 6;
  175. uint8_t clear[SECURE_MESSAGING_MAX_SIZE];
  176. memset(clear, 0, sizeof(clear));
  177. // TODO: check cmac
  178. if(secure_messaging->cipher == AES_128_CBC) {
  179. seos_worker_aes_decrypt(secure_messaging->PrivacyKey, encrypted_len, encrypted, clear);
  180. } else if(secure_messaging->cipher == TWO_KEY_3DES_CBC_MODE) {
  181. seos_worker_des_decrypt(secure_messaging->PrivacyKey, encrypted_len, encrypted, clear);
  182. } else {
  183. FURI_LOG_W(TAG, "Cipher not matched");
  184. }
  185. size_t clear_len = encrypted_len;
  186. do {
  187. } while(clear[--clear_len] == 0 && clear_len > 0);
  188. bit_buffer_reset(rx_buffer);
  189. bit_buffer_append_bytes(rx_buffer, clear, clear_len);
  190. }
  191. // Assumes it is an iso14443a-4 and doesn't have framing bytes
  192. /*
  193. 0ccb3fff
  194. 16
  195. 8508
  196. 4088b37ca72bc7ae
  197. 9700
  198. 8e08
  199. 85345f0f5c44b980
  200. 00
  201. */
  202. void secure_messaging_unwrap_apdu(SecureMessaging* secure_messaging, BitBuffer* rx_buffer) {
  203. secure_messaging_increment_context(secure_messaging);
  204. // TODO: check cmac
  205. const uint8_t* encrypted = bit_buffer_get_data(rx_buffer) + 7;
  206. size_t encrypted_len = bit_buffer_get_byte(rx_buffer, 6);
  207. if(encrypted_len > SECURE_MESSAGING_MAX_SIZE) {
  208. FURI_LOG_W(TAG, "message too large (%d) to unwrap", encrypted_len);
  209. return;
  210. }
  211. uint8_t clear[SECURE_MESSAGING_MAX_SIZE];
  212. memset(clear, 0, sizeof(clear));
  213. if(secure_messaging->cipher == AES_128_CBC) {
  214. seos_worker_aes_decrypt(secure_messaging->PrivacyKey, encrypted_len, encrypted, clear);
  215. } else if(secure_messaging->cipher == TWO_KEY_3DES_CBC_MODE) {
  216. seos_worker_des_decrypt(secure_messaging->PrivacyKey, encrypted_len, encrypted, clear);
  217. } else {
  218. FURI_LOG_W(TAG, "Cipher not matched");
  219. }
  220. do {
  221. } while(clear[--encrypted_len] == 0 && encrypted_len > 0);
  222. bit_buffer_reset(rx_buffer);
  223. bit_buffer_append_bytes(rx_buffer, clear, encrypted_len);
  224. }
  225. void secure_messaging_wrap_rapdu(
  226. SecureMessaging* secure_messaging,
  227. uint8_t* message,
  228. size_t message_len,
  229. BitBuffer* tx_buffer) {
  230. secure_messaging_increment_context(secure_messaging);
  231. uint8_t cipher = secure_messaging->cipher;
  232. if(message_len > SECURE_MESSAGING_MAX_SIZE) {
  233. FURI_LOG_W(TAG, "Message too long to wrap");
  234. return;
  235. }
  236. // Copy into clear so we can pad it.
  237. uint8_t clear[SECURE_MESSAGING_MAX_SIZE];
  238. memset(clear, 0, sizeof(clear));
  239. memcpy(clear, message, message_len);
  240. clear[message_len] = 0x80;
  241. uint8_t block_size = cipher == AES_128_CBC ? 16 : 8;
  242. uint8_t block_count = (message_len + block_size - 1) / block_size;
  243. size_t clear_len = block_count * block_size;
  244. uint8_t encrypted[SECURE_MESSAGING_MAX_SIZE];
  245. if(cipher == AES_128_CBC) {
  246. seos_worker_aes_encrypt(secure_messaging->PrivacyKey, clear_len, clear, encrypted);
  247. } else if(cipher == TWO_KEY_3DES_CBC_MODE) {
  248. seos_worker_des_encrypt(secure_messaging->PrivacyKey, clear_len, clear, encrypted);
  249. } else {
  250. FURI_LOG_W(TAG, "Cipher not matched");
  251. }
  252. uint8_t encrypted_prefix[] = {0x85, clear_len};
  253. uint8_t cmac_prefix[] = {0x8e, 0x08};
  254. uint8_t something[] = {0x99, 0x02, 0x90, 0x00};
  255. uint8_t cmac[16];
  256. BitBuffer* cmacInput = bit_buffer_alloc(256);
  257. bit_buffer_reset(cmacInput);
  258. if(cipher == AES_128_CBC) {
  259. uint8_t* context = secure_messaging->aesContext;
  260. bit_buffer_append_bytes(cmacInput, context, block_size);
  261. bit_buffer_append_bytes(cmacInput, encrypted_prefix, sizeof(encrypted_prefix));
  262. bit_buffer_append_bytes(cmacInput, encrypted, clear_len);
  263. bit_buffer_append_bytes(cmacInput, something, sizeof(something));
  264. // Need to pad to multiple of block size, but context and encrypted are already block size.
  265. bit_buffer_append_bytes(
  266. cmacInput, padding, block_size - sizeof(encrypted_prefix) - sizeof(something));
  267. aes_cmac(
  268. secure_messaging->CMACKey,
  269. sizeof(secure_messaging->CMACKey),
  270. (uint8_t*)bit_buffer_get_data(cmacInput),
  271. bit_buffer_get_size_bytes(cmacInput),
  272. cmac);
  273. } else if(cipher == TWO_KEY_3DES_CBC_MODE) {
  274. uint8_t* context = secure_messaging->desContext;
  275. bit_buffer_append_bytes(cmacInput, context, block_size);
  276. bit_buffer_append_bytes(cmacInput, encrypted_prefix, sizeof(encrypted_prefix));
  277. bit_buffer_append_bytes(cmacInput, encrypted, clear_len);
  278. bit_buffer_append_bytes(cmacInput, something, sizeof(something));
  279. // Need to pad to multiple of block size, but context and encrypted are already block size.
  280. bit_buffer_append_bytes(
  281. cmacInput, padding, block_size - sizeof(encrypted_prefix) - sizeof(something));
  282. des_cmac(
  283. secure_messaging->CMACKey,
  284. sizeof(secure_messaging->CMACKey),
  285. (uint8_t*)bit_buffer_get_data(cmacInput),
  286. bit_buffer_get_size_bytes(cmacInput),
  287. cmac);
  288. } else {
  289. FURI_LOG_W(TAG, "Cipher not matched");
  290. }
  291. bit_buffer_free(cmacInput);
  292. bit_buffer_append_bytes(tx_buffer, encrypted_prefix, sizeof(encrypted_prefix));
  293. bit_buffer_append_bytes(tx_buffer, encrypted, clear_len);
  294. bit_buffer_append_bytes(tx_buffer, something, sizeof(something));
  295. bit_buffer_append_bytes(tx_buffer, cmac_prefix, sizeof(cmac_prefix));
  296. bit_buffer_append_bytes(tx_buffer, cmac, 8);
  297. // Success (9000) is appended by common code before transmission
  298. /*
  299. 8540
  300. 2b4f4e5598193e71cc94ff6dc2b24d1e9feae4182d7315b8b11a8a034670fe8c369f2a98c256dd6f4decf28277a180ea1c4ce515812abfa683e1e004bc66d757
  301. 9902
  302. 9000
  303. 8e08
  304. a860944446f6d53d
  305. 9000
  306. */
  307. }