crypto1.h 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  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 const uint8_t lookup1[256] = {
  22. 0, 0, 16, 16, 0, 16, 0, 0, 0, 16, 0, 0, 16, 16, 16, 16, 0, 0, 16, 16, 0, 16, 0, 0,
  23. 0, 16, 0, 0, 16, 16, 16, 16, 0, 0, 16, 16, 0, 16, 0, 0, 0, 16, 0, 0, 16, 16, 16, 16,
  24. 8, 8, 24, 24, 8, 24, 8, 8, 8, 24, 8, 8, 24, 24, 24, 24, 8, 8, 24, 24, 8, 24, 8, 8,
  25. 8, 24, 8, 8, 24, 24, 24, 24, 8, 8, 24, 24, 8, 24, 8, 8, 8, 24, 8, 8, 24, 24, 24, 24,
  26. 0, 0, 16, 16, 0, 16, 0, 0, 0, 16, 0, 0, 16, 16, 16, 16, 0, 0, 16, 16, 0, 16, 0, 0,
  27. 0, 16, 0, 0, 16, 16, 16, 16, 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. 8, 8, 24, 24, 8, 24, 8, 8, 8, 24, 8, 8, 24, 24, 24, 24, 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};
  33. static const uint8_t lookup2[256] = {
  34. 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,
  35. 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,
  36. 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,
  37. 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,
  38. 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,
  39. 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,
  40. 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,
  41. 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,
  42. 2, 6, 2, 2, 6, 6, 6, 6, 2, 2, 6, 6, 2, 6, 2, 2, 2, 6, 2, 2, 6, 6, 6, 6};
  43. static inline int filter(uint32_t const x) {
  44. uint32_t f;
  45. f = lookup1[x & 0xff] | lookup2[(x >> 8) & 0xff];
  46. f |= 0x0d938 >> (x >> 16 & 0xf) & 1;
  47. return BIT(0xEC57E80A, f);
  48. }
  49. #ifndef __ARM_ARCH_7EM__
  50. static inline uint8_t evenparity32(uint32_t x) {
  51. return __builtin_parity(x);
  52. }
  53. #endif
  54. #ifdef __ARM_ARCH_7EM__
  55. static inline uint8_t evenparity32(uint32_t x) {
  56. uint32_t result;
  57. __asm__ volatile("eor r1, %[x], %[x], lsr #16 \n\t" // r1 = x ^ (x >> 16)
  58. "eor r1, r1, r1, lsr #8 \n\t" // r1 = r1 ^ (r1 >> 8)
  59. "eor r1, r1, r1, lsr #4 \n\t" // r1 = r1 ^ (r1 >> 4)
  60. "eor r1, r1, r1, lsr #2 \n\t" // r1 = r1 ^ (r1 >> 2)
  61. "eor r1, r1, r1, lsr #1 \n\t" // r1 = r1 ^ (r1 >> 1)
  62. "and %[result], r1, #1 \n\t" // result = r1 & 1
  63. : [result] "=r"(result)
  64. : [x] "r"(x)
  65. : "r1");
  66. return result;
  67. }
  68. #endif
  69. static inline void update_contribution(unsigned int data[], int item, int mask1, int mask2) {
  70. int p = data[item] >> 25;
  71. p = p << 1 | evenparity32(data[item] & mask1);
  72. p = p << 1 | evenparity32(data[item] & mask2);
  73. data[item] = p << 24 | (data[item] & 0xffffff);
  74. }
  75. static inline uint32_t crypt_word(struct Crypto1State* s) {
  76. // "in" and "x" are always 0 (last iteration)
  77. uint32_t res_ret = 0;
  78. uint32_t feedin, t;
  79. for(int i = 0; i <= 31; i++) {
  80. res_ret |= (filter(s->odd) << (24 ^ i)); //-V629
  81. feedin = LF_POLY_EVEN & s->even;
  82. feedin ^= LF_POLY_ODD & s->odd;
  83. s->even = s->even << 1 | (evenparity32(feedin));
  84. t = s->odd, s->odd = s->even, s->even = t;
  85. }
  86. return res_ret;
  87. }
  88. static inline void crypt_word_noret(struct Crypto1State* s, uint32_t in, int x) {
  89. uint8_t ret;
  90. uint32_t feedin, t, next_in;
  91. for(int i = 0; i <= 31; i++) {
  92. next_in = BEBIT(in, i);
  93. ret = filter(s->odd);
  94. feedin = ret & (!!x);
  95. feedin ^= LF_POLY_EVEN & s->even;
  96. feedin ^= LF_POLY_ODD & s->odd;
  97. feedin ^= !!next_in;
  98. s->even = s->even << 1 | (evenparity32(feedin));
  99. t = s->odd, s->odd = s->even, s->even = t;
  100. }
  101. return;
  102. }
  103. static inline uint32_t crypt_word_ret(struct Crypto1State* s, uint32_t in, int x) {
  104. uint32_t ret = 0;
  105. uint32_t feedin, t, next_in;
  106. uint8_t next_ret;
  107. for(int i = 0; i <= 31; i++) {
  108. next_in = BEBIT(in, i);
  109. next_ret = filter(s->odd);
  110. feedin = next_ret & (!!x);
  111. feedin ^= LF_POLY_EVEN & s->even;
  112. feedin ^= LF_POLY_ODD & s->odd;
  113. feedin ^= !!next_in;
  114. s->even = s->even << 1 | (evenparity32(feedin));
  115. t = s->odd, s->odd = s->even, s->even = t;
  116. ret |= next_ret << (24 ^ i);
  117. }
  118. return ret;
  119. }
  120. static inline void rollback_word_noret(struct Crypto1State* s, uint32_t in, int x) {
  121. uint8_t ret;
  122. uint32_t feedin, t, next_in;
  123. for(int i = 31; i >= 0; i--) {
  124. next_in = BEBIT(in, i);
  125. s->odd &= 0xffffff;
  126. t = s->odd, s->odd = s->even, s->even = t;
  127. ret = filter(s->odd);
  128. feedin = ret & (!!x);
  129. feedin ^= s->even & 1;
  130. feedin ^= LF_POLY_EVEN & (s->even >>= 1);
  131. feedin ^= LF_POLY_ODD & s->odd;
  132. feedin ^= !!next_in;
  133. s->even |= (evenparity32(feedin)) << 23;
  134. }
  135. return;
  136. }
  137. static inline uint32_t prng_successor(uint32_t x, uint32_t n) {
  138. SWAPENDIAN(x);
  139. while(n--) x = x >> 1 | (x >> 16 ^ x >> 18 ^ x >> 19 ^ x >> 21) << 31;
  140. return SWAPENDIAN(x);
  141. }
  142. #endif // CRYPTO1_H