crypto1.h 7.8 KB

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