crypto1.c 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. #include "crypto1.h"
  2. #include <nfc/helpers/nfc_util.h>
  3. #include <bit_lib/bit_lib.h>
  4. #include <furi.h>
  5. // Algorithm from https://github.com/RfidResearchGroup/proxmark3.git
  6. #define SWAPENDIAN(x) \
  7. ((x) = ((x) >> 8 & 0xff00ff) | ((x) & 0xff00ff) << 8, (x) = (x) >> 16 | (x) << 16)
  8. #define LF_POLY_ODD (0x29CE5C)
  9. #define LF_POLY_EVEN (0x870804)
  10. #define BEBIT(x, n) FURI_BIT(x, (n) ^ 24)
  11. Crypto1* crypto1_alloc() {
  12. Crypto1* instance = malloc(sizeof(Crypto1));
  13. return instance;
  14. }
  15. void crypto1_free(Crypto1* instance) {
  16. furi_assert(instance);
  17. free(instance);
  18. }
  19. void crypto1_reset(Crypto1* crypto1) {
  20. furi_assert(crypto1);
  21. crypto1->even = 0;
  22. crypto1->odd = 0;
  23. }
  24. void crypto1_init(Crypto1* crypto1, uint64_t key) {
  25. furi_assert(crypto1);
  26. crypto1->even = 0;
  27. crypto1->odd = 0;
  28. for(int8_t i = 47; i > 0; i -= 2) {
  29. crypto1->odd = crypto1->odd << 1 | FURI_BIT(key, (i - 1) ^ 7);
  30. crypto1->even = crypto1->even << 1 | FURI_BIT(key, i ^ 7);
  31. }
  32. }
  33. static uint32_t crypto1_filter(uint32_t in) {
  34. uint32_t out = 0;
  35. out = 0xf22c0 >> (in & 0xf) & 16;
  36. out |= 0x6c9c0 >> (in >> 4 & 0xf) & 8;
  37. out |= 0x3c8b0 >> (in >> 8 & 0xf) & 4;
  38. out |= 0x1e458 >> (in >> 12 & 0xf) & 2;
  39. out |= 0x0d938 >> (in >> 16 & 0xf) & 1;
  40. return FURI_BIT(0xEC57E80A, out);
  41. }
  42. uint8_t crypto1_bit(Crypto1* crypto1, uint8_t in, int is_encrypted) {
  43. furi_assert(crypto1);
  44. uint8_t out = crypto1_filter(crypto1->odd);
  45. uint32_t feed = out & (!!is_encrypted);
  46. feed ^= !!in;
  47. feed ^= LF_POLY_ODD & crypto1->odd;
  48. feed ^= LF_POLY_EVEN & crypto1->even;
  49. crypto1->even = crypto1->even << 1 | (nfc_util_even_parity32(feed));
  50. FURI_SWAP(crypto1->odd, crypto1->even);
  51. return out;
  52. }
  53. uint8_t crypto1_byte(Crypto1* crypto1, uint8_t in, int is_encrypted) {
  54. furi_assert(crypto1);
  55. uint8_t out = 0;
  56. for(uint8_t i = 0; i < 8; i++) {
  57. out |= crypto1_bit(crypto1, FURI_BIT(in, i), is_encrypted) << i;
  58. }
  59. return out;
  60. }
  61. uint32_t crypto1_word(Crypto1* crypto1, uint32_t in, int is_encrypted) {
  62. furi_assert(crypto1);
  63. uint32_t out = 0;
  64. for(uint8_t i = 0; i < 32; i++) {
  65. out |= (uint32_t)crypto1_bit(crypto1, BEBIT(in, i), is_encrypted) << (24 ^ i);
  66. }
  67. return out;
  68. }
  69. uint32_t prng_successor(uint32_t x, uint32_t n) {
  70. SWAPENDIAN(x);
  71. while(n--) x = x >> 1 | (x >> 16 ^ x >> 18 ^ x >> 19 ^ x >> 21) << 31;
  72. return SWAPENDIAN(x);
  73. }
  74. void crypto1_decrypt(Crypto1* crypto, const BitBuffer* buff, BitBuffer* out) {
  75. furi_assert(crypto);
  76. furi_assert(buff);
  77. furi_assert(out);
  78. size_t bits = bit_buffer_get_size(buff);
  79. bit_buffer_set_size(out, bits);
  80. const uint8_t* encrypted_data = bit_buffer_get_data(buff);
  81. if(bits < 8) {
  82. uint8_t decrypted_byte = 0;
  83. uint8_t encrypted_byte = encrypted_data[0];
  84. decrypted_byte |= (crypto1_bit(crypto, 0, 0) ^ FURI_BIT(encrypted_byte, 0)) << 0;
  85. decrypted_byte |= (crypto1_bit(crypto, 0, 0) ^ FURI_BIT(encrypted_byte, 1)) << 1;
  86. decrypted_byte |= (crypto1_bit(crypto, 0, 0) ^ FURI_BIT(encrypted_byte, 2)) << 2;
  87. decrypted_byte |= (crypto1_bit(crypto, 0, 0) ^ FURI_BIT(encrypted_byte, 3)) << 3;
  88. bit_buffer_set_byte(out, 0, decrypted_byte);
  89. } else {
  90. for(size_t i = 0; i < bits / 8; i++) {
  91. uint8_t decrypted_byte = crypto1_byte(crypto, 0, 0) ^ encrypted_data[i];
  92. bit_buffer_set_byte(out, i, decrypted_byte);
  93. }
  94. }
  95. }
  96. void crypto1_encrypt(Crypto1* crypto, uint8_t* keystream, const BitBuffer* buff, BitBuffer* out) {
  97. furi_assert(crypto);
  98. furi_assert(buff);
  99. furi_assert(out);
  100. size_t bits = bit_buffer_get_size(buff);
  101. bit_buffer_set_size(out, bits);
  102. const uint8_t* plain_data = bit_buffer_get_data(buff);
  103. if(bits < 8) {
  104. uint8_t encrypted_byte = 0;
  105. for(size_t i = 0; i < bits; i++) {
  106. encrypted_byte |= (crypto1_bit(crypto, 0, 0) ^ FURI_BIT(plain_data[0], i)) << i;
  107. }
  108. bit_buffer_set_byte(out, 0, encrypted_byte);
  109. } else {
  110. for(size_t i = 0; i < bits / 8; i++) {
  111. uint8_t encrypted_byte = crypto1_byte(crypto, keystream ? keystream[i] : 0, 0) ^
  112. plain_data[i];
  113. bool parity_bit =
  114. ((crypto1_filter(crypto->odd) ^ nfc_util_odd_parity8(plain_data[i])) & 0x01);
  115. bit_buffer_set_byte_with_parity(out, i, encrypted_byte, parity_bit);
  116. }
  117. }
  118. }
  119. void crypto1_encrypt_reader_nonce(
  120. Crypto1* crypto,
  121. uint64_t key,
  122. uint32_t cuid,
  123. uint8_t* nt,
  124. uint8_t* nr,
  125. BitBuffer* out,
  126. bool is_nested) {
  127. furi_assert(crypto);
  128. furi_assert(nt);
  129. furi_assert(nr);
  130. furi_assert(out);
  131. bit_buffer_set_size_bytes(out, 8);
  132. uint32_t nt_num = bit_lib_bytes_to_num_be(nt, sizeof(uint32_t));
  133. crypto1_init(crypto, key);
  134. if(is_nested) {
  135. nt_num = crypto1_word(crypto, nt_num ^ cuid, 1) ^ nt_num;
  136. } else {
  137. crypto1_word(crypto, nt_num ^ cuid, 0);
  138. }
  139. for(size_t i = 0; i < 4; i++) {
  140. uint8_t byte = crypto1_byte(crypto, nr[i], 0) ^ nr[i];
  141. bool parity_bit = ((crypto1_filter(crypto->odd) ^ nfc_util_odd_parity8(nr[i])) & 0x01);
  142. bit_buffer_set_byte_with_parity(out, i, byte, parity_bit);
  143. nr[i] = byte;
  144. }
  145. nt_num = prng_successor(nt_num, 32);
  146. for(size_t i = 4; i < 8; i++) {
  147. nt_num = prng_successor(nt_num, 8);
  148. uint8_t byte = crypto1_byte(crypto, 0, 0) ^ (uint8_t)(nt_num);
  149. bool parity_bit = ((crypto1_filter(crypto->odd) ^ nfc_util_odd_parity8(nt_num)) & 0x01);
  150. bit_buffer_set_byte_with_parity(out, i, byte, parity_bit);
  151. }
  152. }