keeloq_common.c 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. #include "keeloq_common.h"
  2. #include <furi.h>
  3. #include <m-string.h>
  4. #include <m-array.h>
  5. #define bit(x, n) (((x) >> (n)) & 1)
  6. #define g5(x, a, b, c, d, e) \
  7. (bit(x, a) + bit(x, b) * 2 + bit(x, c) * 4 + bit(x, d) * 8 + bit(x, e) * 16)
  8. /** Simple Learning Encrypt
  9. * @param data - 0xBSSSCCCC, B(4bit) key, S(10bit) serial&0x3FF, C(16bit) counter
  10. * @param key - manufacture (64bit)
  11. * @return keeloq encrypt data
  12. */
  13. inline uint32_t subghz_protocol_keeloq_common_encrypt(const uint32_t data, const uint64_t key) {
  14. uint32_t x = data, r;
  15. for(r = 0; r < 528; r++)
  16. x = (x >> 1) ^ ((bit(x, 0) ^ bit(x, 16) ^ (uint32_t)bit(key, r & 63) ^
  17. bit(KEELOQ_NLF, g5(x, 1, 9, 20, 26, 31)))
  18. << 31);
  19. return x;
  20. }
  21. /** Simple Learning Decrypt
  22. * @param data - keelog encrypt data
  23. * @param key - manufacture (64bit)
  24. * @return 0xBSSSCCCC, B(4bit) key, S(10bit) serial&0x3FF, C(16bit) counter
  25. */
  26. inline uint32_t subghz_protocol_keeloq_common_decrypt(const uint32_t data, const uint64_t key) {
  27. uint32_t x = data, r;
  28. for(r = 0; r < 528; r++)
  29. x = (x << 1) ^ bit(x, 31) ^ bit(x, 15) ^ (uint32_t)bit(key, (15 - r) & 63) ^
  30. bit(KEELOQ_NLF, g5(x, 0, 8, 19, 25, 30));
  31. return x;
  32. }
  33. /** Normal Learning
  34. * @param data - serial number (28bit)
  35. * @param key - manufacture (64bit)
  36. * @return manufacture for this serial number (64bit)
  37. */
  38. inline uint64_t subghz_protocol_keeloq_common_normal_learning(uint32_t data, const uint64_t key) {
  39. uint32_t k1, k2;
  40. data &= 0x0FFFFFFF;
  41. data |= 0x20000000;
  42. k1 = subghz_protocol_keeloq_common_decrypt(data, key);
  43. data &= 0x0FFFFFFF;
  44. data |= 0x60000000;
  45. k2 = subghz_protocol_keeloq_common_decrypt(data, key);
  46. return ((uint64_t)k2 << 32) | k1; // key - shifrovanoya
  47. }
  48. /** Secure Learning
  49. * @param data - serial number (28bit)
  50. * @param seed - seed number (32bit)
  51. * @param key - manufacture (64bit)
  52. * @return manufacture for this serial number (64bit)
  53. */
  54. inline uint64_t subghz_protocol_keeloq_common_secure_learning(
  55. uint32_t data,
  56. uint32_t seed,
  57. const uint64_t key) {
  58. uint32_t k1, k2;
  59. data &= 0x0FFFFFFF;
  60. k1 = subghz_protocol_keeloq_common_decrypt(data, key);
  61. k2 = subghz_protocol_keeloq_common_decrypt(seed, key);
  62. return ((uint64_t)k1 << 32) | k2;
  63. }
  64. /** Magic_xor_type1 Learning
  65. * @param data - serial number (28bit)
  66. * @param xor - magic xor (64bit)
  67. * @return manufacture for this serial number (64bit)
  68. */
  69. inline uint64_t
  70. subghz_protocol_keeloq_common_magic_xor_type1_learning(uint32_t data, uint64_t xor) {
  71. data &= 0x0FFFFFFF;
  72. return (((uint64_t)data << 32) | data) ^ xor;
  73. }
  74. /** Magic_serial_type1 Learning
  75. * @param data - serial number (28bit)
  76. * @param man - magic man (64bit)
  77. * @return manufacture for this serial number (64bit)
  78. */
  79. inline uint64_t
  80. subghz_protocol_keeloq_common_magic_serial_type1_learning(uint32_t data, uint64_t man) {
  81. return man | ((uint64_t)data << 40) |
  82. ((uint64_t)(((data & 0xff) + ((data >> 8) & 0xFF)) & 0xFF) << 32);
  83. }