optimized_elite.c 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. //-----------------------------------------------------------------------------
  2. // Borrowed initially from https://github.com/holiman/loclass
  3. // Copyright (C) 2014 Martin Holst Swende
  4. // Copyright (C) Proxmark3 contributors. See AUTHORS.md for details.
  5. //
  6. // This program is free software: you can redistribute it and/or modify
  7. // it under the terms of the GNU General Public License as published by
  8. // the Free Software Foundation, either version 3 of the License, or
  9. // (at your option) any later version.
  10. //
  11. // This program is distributed in the hope that it will be useful,
  12. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. // GNU General Public License for more details.
  15. //
  16. // See LICENSE.txt for the text of the license.
  17. //-----------------------------------------------------------------------------
  18. // WARNING
  19. //
  20. // THIS CODE IS CREATED FOR EXPERIMENTATION AND EDUCATIONAL USE ONLY.
  21. //
  22. // USAGE OF THIS CODE IN OTHER WAYS MAY INFRINGE UPON THE INTELLECTUAL
  23. // PROPERTY OF OTHER PARTIES, SUCH AS INSIDE SECURE AND HID GLOBAL,
  24. // AND MAY EXPOSE YOU TO AN INFRINGEMENT ACTION FROM THOSE PARTIES.
  25. //
  26. // THIS CODE SHOULD NEVER BE USED TO INFRINGE PATENTS OR INTELLECTUAL PROPERTY RIGHTS.
  27. //-----------------------------------------------------------------------------
  28. // It is a reconstruction of the cipher engine used in iClass, and RFID techology.
  29. //
  30. // The implementation is based on the work performed by
  31. // Flavio D. Garcia, Gerhard de Koning Gans, Roel Verdult and
  32. // Milosch Meriac in the paper "Dismantling IClass".
  33. //-----------------------------------------------------------------------------
  34. #include "optimized_elite.h"
  35. #include <stdint.h>
  36. #include <stdbool.h>
  37. #include <string.h>
  38. #include <mbedtls/des.h>
  39. #include "optimized_ikeys.h"
  40. /**
  41. * @brief Permutes a key from standard NIST format to Iclass specific format
  42. * from http://www.proxmark.org/forum/viewtopic.php?pid=11220#p11220
  43. *
  44. * If you permute [6c 8d 44 f9 2a 2d 01 bf] you get [8a 0d b9 88 bb a7 90 ea] as shown below.
  45. *
  46. * 1 0 1 1 1 1 1 1 bf
  47. * 0 0 0 0 0 0 0 1 01
  48. * 0 0 1 0 1 1 0 1 2d
  49. * 0 0 1 0 1 0 1 0 2a
  50. * 1 1 1 1 1 0 0 1 f9
  51. * 0 1 0 0 0 1 0 0 44
  52. * 1 0 0 0 1 1 0 1 8d
  53. * 0 1 1 0 1 1 0 0 6c
  54. *
  55. * 8 0 b 8 b a 9 e
  56. * a d 9 8 b 7 0 a
  57. *
  58. * @param key
  59. * @param dest
  60. */
  61. void permutekey(const uint8_t key[8], uint8_t dest[8]) {
  62. int i;
  63. for (i = 0 ; i < 8 ; i++) {
  64. dest[i] = (((key[7] & (0x80 >> i)) >> (7 - i)) << 7) |
  65. (((key[6] & (0x80 >> i)) >> (7 - i)) << 6) |
  66. (((key[5] & (0x80 >> i)) >> (7 - i)) << 5) |
  67. (((key[4] & (0x80 >> i)) >> (7 - i)) << 4) |
  68. (((key[3] & (0x80 >> i)) >> (7 - i)) << 3) |
  69. (((key[2] & (0x80 >> i)) >> (7 - i)) << 2) |
  70. (((key[1] & (0x80 >> i)) >> (7 - i)) << 1) |
  71. (((key[0] & (0x80 >> i)) >> (7 - i)) << 0);
  72. }
  73. }
  74. /**
  75. * Permutes a key from iclass specific format to NIST format
  76. * @brief permutekey_rev
  77. * @param key
  78. * @param dest
  79. */
  80. void permutekey_rev(const uint8_t key[8], uint8_t dest[8]) {
  81. int i;
  82. for (i = 0 ; i < 8 ; i++) {
  83. dest[7 - i] = (((key[0] & (0x80 >> i)) >> (7 - i)) << 7) |
  84. (((key[1] & (0x80 >> i)) >> (7 - i)) << 6) |
  85. (((key[2] & (0x80 >> i)) >> (7 - i)) << 5) |
  86. (((key[3] & (0x80 >> i)) >> (7 - i)) << 4) |
  87. (((key[4] & (0x80 >> i)) >> (7 - i)) << 3) |
  88. (((key[5] & (0x80 >> i)) >> (7 - i)) << 2) |
  89. (((key[6] & (0x80 >> i)) >> (7 - i)) << 1) |
  90. (((key[7] & (0x80 >> i)) >> (7 - i)) << 0);
  91. }
  92. }
  93. /**
  94. * Helper function for hash1
  95. * @brief rr
  96. * @param val
  97. * @return
  98. */
  99. static uint8_t rr(uint8_t val) {
  100. return val >> 1 | ((val & 1) << 7);
  101. }
  102. /**
  103. * Helper function for hash1
  104. * @brief rl
  105. * @param val
  106. * @return
  107. */
  108. static uint8_t rl(uint8_t val) {
  109. return val << 1 | ((val & 0x80) >> 7);
  110. }
  111. /**
  112. * Helper function for hash1
  113. * @brief swap
  114. * @param val
  115. * @return
  116. */
  117. static uint8_t swap(uint8_t val) {
  118. return ((val >> 4) & 0xFF) | ((val & 0xFF) << 4);
  119. }
  120. /**
  121. * Hash1 takes CSN as input, and determines what bytes in the keytable will be used
  122. * when constructing the K_sel.
  123. * @param csn the CSN used
  124. * @param k output
  125. */
  126. void hash1(const uint8_t csn[], uint8_t k[]) {
  127. k[0] = csn[0] ^ csn[1] ^ csn[2] ^ csn[3] ^ csn[4] ^ csn[5] ^ csn[6] ^ csn[7];
  128. k[1] = csn[0] + csn[1] + csn[2] + csn[3] + csn[4] + csn[5] + csn[6] + csn[7];
  129. k[2] = rr(swap(csn[2] + k[1]));
  130. k[3] = rl(swap(csn[3] + k[0]));
  131. k[4] = ~rr(csn[4] + k[2]) + 1;
  132. k[5] = ~rl(csn[5] + k[3]) + 1;
  133. k[6] = rr(csn[6] + (k[4] ^ 0x3c));
  134. k[7] = rl(csn[7] + (k[5] ^ 0xc3));
  135. k[7] &= 0x7F;
  136. k[6] &= 0x7F;
  137. k[5] &= 0x7F;
  138. k[4] &= 0x7F;
  139. k[3] &= 0x7F;
  140. k[2] &= 0x7F;
  141. k[1] &= 0x7F;
  142. k[0] &= 0x7F;
  143. }
  144. /**
  145. Definition 14. Define the rotate key function rk : (F 82 ) 8 × N → (F 82 ) 8 as
  146. rk(x [0] . . . x [7] , 0) = x [0] . . . x [7]
  147. rk(x [0] . . . x [7] , n + 1) = rk(rl(x [0] ) . . . rl(x [7] ), n)
  148. **/
  149. static void rk(uint8_t *key, uint8_t n, uint8_t *outp_key) {
  150. memcpy(outp_key, key, 8);
  151. uint8_t j;
  152. while (n-- > 0) {
  153. for (j = 0; j < 8 ; j++)
  154. outp_key[j] = rl(outp_key[j]);
  155. }
  156. return;
  157. }
  158. static mbedtls_des_context ctx_enc;
  159. static mbedtls_des_context ctx_dec;
  160. static void desdecrypt_iclass(uint8_t *iclass_key, uint8_t *input, uint8_t *output) {
  161. uint8_t key_std_format[8] = {0};
  162. permutekey_rev(iclass_key, key_std_format);
  163. mbedtls_des_setkey_dec(&ctx_dec, key_std_format);
  164. mbedtls_des_crypt_ecb(&ctx_dec, input, output);
  165. }
  166. static void desencrypt_iclass(uint8_t *iclass_key, uint8_t *input, uint8_t *output) {
  167. uint8_t key_std_format[8] = {0};
  168. permutekey_rev(iclass_key, key_std_format);
  169. mbedtls_des_setkey_enc(&ctx_enc, key_std_format);
  170. mbedtls_des_crypt_ecb(&ctx_enc, input, output);
  171. }
  172. /**
  173. * @brief Insert uint8_t[8] custom master key to calculate hash2 and return key_select.
  174. * @param key unpermuted custom key
  175. * @param hash1 hash1
  176. * @param key_sel output key_sel=h[hash1[i]]
  177. */
  178. void hash2(uint8_t *key64, uint8_t *outp_keytable) {
  179. /**
  180. *Expected:
  181. * High Security Key Table
  182. 00 F1 35 59 A1 0D 5A 26 7F 18 60 0B 96 8A C0 25 C1
  183. 10 BF A1 3B B0 FF 85 28 75 F2 1F C6 8F 0E 74 8F 21
  184. 20 14 7A 55 16 C8 A9 7D B3 13 0C 5D C9 31 8D A9 B2
  185. 30 A3 56 83 0F 55 7E DE 45 71 21 D2 6D C1 57 1C 9C
  186. 40 78 2F 64 51 42 7B 64 30 FA 26 51 76 D3 E0 FB B6
  187. 50 31 9F BF 2F 7E 4F 94 B4 BD 4F 75 91 E3 1B EB 42
  188. 60 3F 88 6F B8 6C 2C 93 0D 69 2C D5 20 3C C1 61 95
  189. 70 43 08 A0 2F FE B3 26 D7 98 0B 34 7B 47 70 A0 AB
  190. **** The 64-bit HS Custom Key Value = 5B7C62C491C11B39 ******/
  191. uint8_t key64_negated[8] = {0};
  192. uint8_t z[8][8] = {{0}, {0}};
  193. uint8_t temp_output[8] = {0};
  194. //calculate complement of key
  195. int i;
  196. for (i = 0; i < 8; i++)
  197. key64_negated[i] = ~key64[i];
  198. // Once again, key is on iclass-format
  199. desencrypt_iclass(key64, key64_negated, z[0]);
  200. uint8_t y[8][8] = {{0}, {0}};
  201. // y[0]=DES_dec(z[0],~key)
  202. // Once again, key is on iclass-format
  203. desdecrypt_iclass(z[0], key64_negated, y[0]);
  204. for (i = 1; i < 8; i++) {
  205. rk(key64, i, temp_output);
  206. desdecrypt_iclass(temp_output, z[i - 1], z[i]);
  207. desencrypt_iclass(temp_output, y[i - 1], y[i]);
  208. }
  209. if (outp_keytable != NULL) {
  210. for (i = 0 ; i < 8 ; i++) {
  211. memcpy(outp_keytable + i * 16, y[i], 8);
  212. memcpy(outp_keytable + 8 + i * 16, z[i], 8);
  213. }
  214. }
  215. }