crypto1.h 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  1. #ifndef CRYPTO1_H
  2. #define CRYPTO1_H
  3. #include <inttypes.h>
  4. #include "mfkey.h"
  5. #include <nfc/helpers/nfc_util.h>
  6. #include <nfc/protocols/mf_classic/mf_classic.h>
  7. #define LF_POLY_ODD (0x29CE5C)
  8. #define LF_POLY_EVEN (0x870804)
  9. #define BIT(x, n) ((x) >> (n) & 1)
  10. #define BEBIT(x, n) BIT(x, (n) ^ 24)
  11. #define SWAPENDIAN(x) \
  12. ((x) = ((x) >> 8 & 0xff00ff) | ((x) & 0xff00ff) << 8, (x) = (x) >> 16 | (x) << 16)
  13. static inline uint32_t prng_successor(uint32_t x, uint32_t n);
  14. static inline int filter(uint32_t const x);
  15. static inline uint8_t evenparity32(uint32_t x);
  16. static inline void update_contribution(unsigned int data[], int item, int mask1, int mask2);
  17. void crypto1_get_lfsr(struct Crypto1State* state, MfClassicKey* lfsr);
  18. static inline uint32_t crypt_word(struct Crypto1State* s);
  19. static inline void crypt_word_noret(struct Crypto1State* s, uint32_t in, int x);
  20. static inline uint32_t crypt_word_ret(struct Crypto1State* s, uint32_t in, int x);
  21. static uint32_t crypt_word_par(
  22. struct Crypto1State* s,
  23. uint32_t in,
  24. int is_encrypted,
  25. uint32_t nt_plain,
  26. uint8_t* parity_keystream_bits);
  27. static inline void rollback_word_noret(struct Crypto1State* s, uint32_t in, int x);
  28. static inline uint8_t napi_lfsr_rollback_bit(struct Crypto1State* s, uint32_t in, int fb);
  29. static inline uint32_t napi_lfsr_rollback_word(struct Crypto1State* s, uint32_t in, int fb);
  30. static const uint8_t lookup1[256] = {
  31. 0, 0, 16, 16, 0, 16, 0, 0, 0, 16, 0, 0, 16, 16, 16, 16, 0, 0, 16, 16, 0, 16, 0, 0,
  32. 0, 16, 0, 0, 16, 16, 16, 16, 0, 0, 16, 16, 0, 16, 0, 0, 0, 16, 0, 0, 16, 16, 16, 16,
  33. 8, 8, 24, 24, 8, 24, 8, 8, 8, 24, 8, 8, 24, 24, 24, 24, 8, 8, 24, 24, 8, 24, 8, 8,
  34. 8, 24, 8, 8, 24, 24, 24, 24, 8, 8, 24, 24, 8, 24, 8, 8, 8, 24, 8, 8, 24, 24, 24, 24,
  35. 0, 0, 16, 16, 0, 16, 0, 0, 0, 16, 0, 0, 16, 16, 16, 16, 0, 0, 16, 16, 0, 16, 0, 0,
  36. 0, 16, 0, 0, 16, 16, 16, 16, 8, 8, 24, 24, 8, 24, 8, 8, 8, 24, 8, 8, 24, 24, 24, 24,
  37. 0, 0, 16, 16, 0, 16, 0, 0, 0, 16, 0, 0, 16, 16, 16, 16, 0, 0, 16, 16, 0, 16, 0, 0,
  38. 0, 16, 0, 0, 16, 16, 16, 16, 8, 8, 24, 24, 8, 24, 8, 8, 8, 24, 8, 8, 24, 24, 24, 24,
  39. 8, 8, 24, 24, 8, 24, 8, 8, 8, 24, 8, 8, 24, 24, 24, 24, 0, 0, 16, 16, 0, 16, 0, 0,
  40. 0, 16, 0, 0, 16, 16, 16, 16, 8, 8, 24, 24, 8, 24, 8, 8, 8, 24, 8, 8, 24, 24, 24, 24,
  41. 8, 8, 24, 24, 8, 24, 8, 8, 8, 24, 8, 8, 24, 24, 24, 24};
  42. static const uint8_t lookup2[256] = {
  43. 0, 0, 4, 4, 0, 4, 0, 0, 0, 4, 0, 0, 4, 4, 4, 4, 0, 0, 4, 4, 0, 4, 0, 0, 0, 4, 0, 0, 4,
  44. 4, 4, 4, 2, 2, 6, 6, 2, 6, 2, 2, 2, 6, 2, 2, 6, 6, 6, 6, 2, 2, 6, 6, 2, 6, 2, 2, 2, 6,
  45. 2, 2, 6, 6, 6, 6, 0, 0, 4, 4, 0, 4, 0, 0, 0, 4, 0, 0, 4, 4, 4, 4, 2, 2, 6, 6, 2, 6, 2,
  46. 2, 2, 6, 2, 2, 6, 6, 6, 6, 0, 0, 4, 4, 0, 4, 0, 0, 0, 4, 0, 0, 4, 4, 4, 4, 0, 0, 4, 4,
  47. 0, 4, 0, 0, 0, 4, 0, 0, 4, 4, 4, 4, 0, 0, 4, 4, 0, 4, 0, 0, 0, 4, 0, 0, 4, 4, 4, 4, 2,
  48. 2, 6, 6, 2, 6, 2, 2, 2, 6, 2, 2, 6, 6, 6, 6, 0, 0, 4, 4, 0, 4, 0, 0, 0, 4, 0, 0, 4, 4,
  49. 4, 4, 0, 0, 4, 4, 0, 4, 0, 0, 0, 4, 0, 0, 4, 4, 4, 4, 2, 2, 6, 6, 2, 6, 2, 2, 2, 6, 2,
  50. 2, 6, 6, 6, 6, 2, 2, 6, 6, 2, 6, 2, 2, 2, 6, 2, 2, 6, 6, 6, 6, 2, 2, 6, 6, 2, 6, 2, 2,
  51. 2, 6, 2, 2, 6, 6, 6, 6, 2, 2, 6, 6, 2, 6, 2, 2, 2, 6, 2, 2, 6, 6, 6, 6};
  52. static inline int filter(uint32_t const x) {
  53. uint32_t f;
  54. f = lookup1[x & 0xff] | lookup2[(x >> 8) & 0xff];
  55. f |= 0x0d938 >> (x >> 16 & 0xf) & 1;
  56. return BIT(0xEC57E80A, f);
  57. }
  58. #ifndef __ARM_ARCH_7EM__
  59. static inline uint8_t evenparity32(uint32_t x) {
  60. return __builtin_parity(x);
  61. }
  62. #endif
  63. #ifdef __ARM_ARCH_7EM__
  64. static inline uint8_t evenparity32(uint32_t x) {
  65. uint32_t result;
  66. __asm__ volatile("eor r1, %[x], %[x], lsr #16 \n\t" // r1 = x ^ (x >> 16)
  67. "eor r1, r1, r1, lsr #8 \n\t" // r1 = r1 ^ (r1 >> 8)
  68. "eor r1, r1, r1, lsr #4 \n\t" // r1 = r1 ^ (r1 >> 4)
  69. "eor r1, r1, r1, lsr #2 \n\t" // r1 = r1 ^ (r1 >> 2)
  70. "eor r1, r1, r1, lsr #1 \n\t" // r1 = r1 ^ (r1 >> 1)
  71. "and %[result], r1, #1 \n\t" // result = r1 & 1
  72. : [result] "=r"(result)
  73. : [x] "r"(x)
  74. : "r1");
  75. return result;
  76. }
  77. #endif
  78. static inline void update_contribution(unsigned int data[], int item, int mask1, int mask2) {
  79. int p = data[item] >> 25;
  80. p = p << 1 | evenparity32(data[item] & mask1);
  81. p = p << 1 | evenparity32(data[item] & mask2);
  82. data[item] = p << 24 | (data[item] & 0xffffff);
  83. }
  84. static inline uint32_t crypt_word(struct Crypto1State* s) {
  85. // "in" and "x" are always 0 (last iteration)
  86. uint32_t res_ret = 0;
  87. uint32_t feedin, t;
  88. for(int i = 0; i <= 31; i++) {
  89. res_ret |= (filter(s->odd) << (24 ^ i)); //-V629
  90. feedin = LF_POLY_EVEN & s->even;
  91. feedin ^= LF_POLY_ODD & s->odd;
  92. s->even = s->even << 1 | (evenparity32(feedin));
  93. t = s->odd, s->odd = s->even, s->even = t;
  94. }
  95. return res_ret;
  96. }
  97. static inline void crypt_word_noret(struct Crypto1State* s, uint32_t in, int x) {
  98. uint8_t ret;
  99. uint32_t feedin, t, next_in;
  100. for(int i = 0; i <= 31; i++) {
  101. next_in = BEBIT(in, i);
  102. ret = filter(s->odd);
  103. feedin = ret & (!!x);
  104. feedin ^= LF_POLY_EVEN & s->even;
  105. feedin ^= LF_POLY_ODD & s->odd;
  106. feedin ^= !!next_in;
  107. s->even = s->even << 1 | (evenparity32(feedin));
  108. t = s->odd, s->odd = s->even, s->even = t;
  109. }
  110. return;
  111. }
  112. static inline uint32_t crypt_word_ret(struct Crypto1State* s, uint32_t in, int x) {
  113. uint32_t ret = 0;
  114. uint32_t feedin, t, next_in;
  115. uint8_t next_ret;
  116. for(int i = 0; i <= 31; i++) {
  117. next_in = BEBIT(in, i);
  118. next_ret = filter(s->odd);
  119. feedin = next_ret & (!!x);
  120. feedin ^= LF_POLY_EVEN & s->even;
  121. feedin ^= LF_POLY_ODD & s->odd;
  122. feedin ^= !!next_in;
  123. s->even = s->even << 1 | (evenparity32(feedin));
  124. t = s->odd, s->odd = s->even, s->even = t;
  125. ret |= next_ret << (24 ^ i);
  126. }
  127. return ret;
  128. }
  129. static uint8_t get_nth_byte(uint32_t value, int n) {
  130. if(n < 0 || n > 3) {
  131. // Handle invalid input
  132. return 0;
  133. }
  134. return (value >> (8 * (3 - n))) & 0xFF;
  135. }
  136. static uint8_t crypt_bit(struct Crypto1State* s, uint8_t in, int is_encrypted) {
  137. uint32_t feedin, t;
  138. uint8_t ret = filter(s->odd);
  139. feedin = ret & !!is_encrypted;
  140. feedin ^= !!in;
  141. feedin ^= LF_POLY_ODD & s->odd;
  142. feedin ^= LF_POLY_EVEN & s->even;
  143. s->even = s->even << 1 | evenparity32(feedin);
  144. t = s->odd, s->odd = s->even, s->even = t;
  145. return ret;
  146. }
  147. static inline uint32_t crypt_word_par(
  148. struct Crypto1State* s,
  149. uint32_t in,
  150. int is_encrypted,
  151. uint32_t nt_plain,
  152. uint8_t* parity_keystream_bits) {
  153. uint32_t ret = 0;
  154. *parity_keystream_bits = 0; // Reset parity keystream bits
  155. for(int i = 0; i < 32; i++) {
  156. uint8_t bit = crypt_bit(s, BEBIT(in, i), is_encrypted);
  157. ret |= bit << (24 ^ i);
  158. // Save keystream parity bit
  159. if((i + 1) % 8 == 0) {
  160. *parity_keystream_bits |=
  161. (filter(s->odd) ^ nfc_util_even_parity8(get_nth_byte(nt_plain, i / 8)))
  162. << (3 - (i / 8));
  163. }
  164. }
  165. return ret;
  166. }
  167. static inline void rollback_word_noret(struct Crypto1State* s, uint32_t in, int x) {
  168. uint8_t ret;
  169. uint32_t feedin, t, next_in;
  170. for(int i = 31; i >= 0; i--) {
  171. next_in = BEBIT(in, i);
  172. s->odd &= 0xffffff;
  173. t = s->odd, s->odd = s->even, s->even = t;
  174. ret = filter(s->odd);
  175. feedin = ret & (!!x);
  176. feedin ^= s->even & 1;
  177. feedin ^= LF_POLY_EVEN & (s->even >>= 1);
  178. feedin ^= LF_POLY_ODD & s->odd;
  179. feedin ^= !!next_in;
  180. s->even |= (evenparity32(feedin)) << 23;
  181. }
  182. return;
  183. }
  184. // TODO:
  185. /*
  186. uint32_t rollback_word(struct Crypto1State *s, uint32_t in, int x) {
  187. uint32_t res_ret = 0;
  188. uint8_t ret;
  189. uint32_t feedin, t, next_in;
  190. for (int i = 31; i >= 0; i--) {
  191. next_in = BEBIT(in, i);
  192. s->odd &= 0xffffff;
  193. t = s->odd, s->odd = s->even, s->even = t;
  194. ret = filter(s->odd);
  195. feedin = ret & (!!x);
  196. feedin ^= s->even & 1;
  197. feedin ^= LF_POLY_EVEN & (s->even >>= 1);
  198. feedin ^= LF_POLY_ODD & s->odd;
  199. feedin ^= !!next_in;
  200. s->even |= (evenparity32(feedin)) << 23;
  201. res_ret |= (ret << (24 ^ i));
  202. }
  203. return res_ret;
  204. }
  205. */
  206. uint8_t napi_lfsr_rollback_bit(struct Crypto1State* s, uint32_t in, int fb) {
  207. int out;
  208. uint8_t ret;
  209. uint32_t t;
  210. s->odd &= 0xffffff;
  211. t = s->odd, s->odd = s->even, s->even = t;
  212. out = s->even & 1;
  213. out ^= LF_POLY_EVEN & (s->even >>= 1);
  214. out ^= LF_POLY_ODD & s->odd;
  215. out ^= !!in;
  216. out ^= (ret = filter(s->odd)) & !!fb;
  217. s->even |= evenparity32(out) << 23;
  218. return ret;
  219. }
  220. uint32_t napi_lfsr_rollback_word(struct Crypto1State* s, uint32_t in, int fb) {
  221. int i;
  222. uint32_t ret = 0;
  223. for(i = 31; i >= 0; --i)
  224. ret |= napi_lfsr_rollback_bit(s, BEBIT(in, i), fb) << (i ^ 24);
  225. return ret;
  226. }
  227. static inline uint32_t prng_successor(uint32_t x, uint32_t n) {
  228. SWAPENDIAN(x);
  229. while(n--)
  230. x = x >> 1 | (x >> 16 ^ x >> 18 ^ x >> 19 ^ x >> 21) << 31;
  231. return SWAPENDIAN(x);
  232. }
  233. #endif // CRYPTO1_H