Audio plugin host https://kx.studio/carla
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

CarlaSha1Utils.hpp 5.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. /*
  2. * Carla sha1 utils
  3. * Copyright (C) 2023 Filipe Coelho <falktx@falktx.com>
  4. *
  5. * This program is free software; you can redistribute it and/or
  6. * modify it under the terms of the GNU General Public License as
  7. * published by the Free Software Foundation; either version 2 of
  8. * the License, or any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * For a full copy of the GNU General Public License see the doc/GPL.txt file.
  16. */
  17. #ifndef CARLA_SHA1_UTILS_HPP_INCLUDED
  18. #define CARLA_SHA1_UTILS_HPP_INCLUDED
  19. #include "CarlaUtils.hpp"
  20. #if defined(__BIG_ENDIAN__) || (defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__))
  21. # define CARLA_SHA1_BIG_ENDIAN
  22. #endif
  23. /*!
  24. * Simple, single-use SHA1 class.
  25. * Must be discarded after use.
  26. *
  27. * Based on libcrypt by Wei Dai and other contributors (originally in the public domain)
  28. */
  29. class CarlaSha1 {
  30. static constexpr const size_t BLOCK_LENGTH = 64;
  31. union {
  32. uint8_t u8[BLOCK_LENGTH];
  33. uint32_t u32[BLOCK_LENGTH/sizeof(uint32_t)];
  34. } buffer;
  35. uint32_t state[5];
  36. uint32_t byteCount;
  37. uint8_t bufferOffset;
  38. char resultstr[41];
  39. static_assert(sizeof(buffer.u8) == sizeof(buffer.u32), "valid size");
  40. public:
  41. /*
  42. * Constructor.
  43. */
  44. CarlaSha1() noexcept
  45. : byteCount(0),
  46. bufferOffset(0)
  47. {
  48. state[0] = 0x67452301;
  49. state[1] = 0xefcdab89;
  50. state[2] = 0x98badcfe;
  51. state[3] = 0x10325476;
  52. state[4] = 0xc3d2e1f0;
  53. }
  54. /*
  55. * Write a single byte of data.
  56. */
  57. void writeByte(const uint8_t data) noexcept
  58. {
  59. ++byteCount;
  60. _addUncounted(data);
  61. }
  62. /*
  63. * Write a custom blob of data.
  64. */
  65. void write(const void* const data, size_t len) noexcept
  66. {
  67. const uint8_t* u8data = static_cast<const uint8_t*>(data);
  68. while (len--)
  69. writeByte(*u8data++);
  70. }
  71. /*
  72. * Return hash result as byte array (20 characters).
  73. * @note must be called only once!
  74. */
  75. const uint8_t* resultAsHash() noexcept
  76. {
  77. // Pad to complete the last block
  78. _pad();
  79. #ifndef CARLA_SHA1_BIG_ENDIAN
  80. // Swap byte order back
  81. for (int i=0; i<5; ++i)
  82. {
  83. state[i] = ((state[i] << 24) & 0xff000000)
  84. | ((state[i] << 8) & 0x00ff0000)
  85. | ((state[i] >> 8) & 0x0000ff00)
  86. | ((state[i] >> 24) & 0x000000ff);
  87. }
  88. #endif
  89. return static_cast<uint8_t*>(static_cast<void*>(state));
  90. }
  91. /*
  92. * Return hash result as null-terminated string.
  93. * @note must be called only once!
  94. */
  95. const char* resultAsString() noexcept
  96. {
  97. const uint8_t* const hash = resultAsHash();
  98. for (int i=0; i<20; ++i)
  99. std::snprintf(resultstr + (i * 2), 3, "%02x", hash[i]);
  100. resultstr[40] = '\0';
  101. return resultstr;
  102. }
  103. private:
  104. void _addUncounted(const uint8_t data) noexcept
  105. {
  106. #ifdef CARLA_SHA1_BIG_ENDIAN
  107. buffer.u8[bufferOffset] = data;
  108. #else
  109. buffer.u8[bufferOffset ^ 3] = data;
  110. #endif
  111. if (++bufferOffset == BLOCK_LENGTH)
  112. {
  113. bufferOffset = 0;
  114. _hashBlock();
  115. }
  116. }
  117. void _hashBlock() noexcept
  118. {
  119. uint32_t a = state[0];
  120. uint32_t b = state[1];
  121. uint32_t c = state[2];
  122. uint32_t d = state[3];
  123. uint32_t e = state[4];
  124. uint32_t t;
  125. for (uint8_t i=0; i<80; ++i)
  126. {
  127. if (i >= 16)
  128. {
  129. t = buffer.u32[(i + 13) & 15]
  130. ^ buffer.u32[(i + 8) & 15]
  131. ^ buffer.u32[(i + 2) & 15]
  132. ^ buffer.u32[i & 15];
  133. buffer.u32[i & 15] = _rol32(t, 1);
  134. }
  135. if (i < 20)
  136. {
  137. t = (d ^ (b & (c ^ d))) + 0x5a827999;
  138. }
  139. else if (i < 40)
  140. {
  141. t = (b ^ c ^ d) + 0x6ed9eba1;
  142. }
  143. else if (i < 60)
  144. {
  145. t = ((b & c) | (d & (b | c))) + 0x8f1bbcdc;
  146. }
  147. else
  148. {
  149. t = (b ^ c ^ d) + 0xca62c1d6;
  150. }
  151. t += _rol32(a, 5) + e + buffer.u32[i & 15];
  152. e = d;
  153. d = c;
  154. c = _rol32(b, 30);
  155. b = a;
  156. a = t;
  157. }
  158. state[0] += a;
  159. state[1] += b;
  160. state[2] += c;
  161. state[3] += d;
  162. state[4] += e;
  163. }
  164. // Implement SHA-1 padding (fips180-2 ยง5.1.1)
  165. void _pad() noexcept
  166. {
  167. // Pad with 0x80 followed by 0x00 until the end of the block
  168. _addUncounted(0x80);
  169. while (bufferOffset != 56) _addUncounted(0x00);
  170. // Append length in the last 8 bytes
  171. _addUncounted(0); // We're only using 32 bit lengths
  172. _addUncounted(0); // But SHA-1 supports 64 bit lengths
  173. _addUncounted(0); // So zero pad the top bits
  174. _addUncounted(byteCount >> 29); // Shifting to multiply by 8
  175. _addUncounted(byteCount >> 21); // as SHA-1 supports bitstreams as well as
  176. _addUncounted(byteCount >> 13); // byte.
  177. _addUncounted(byteCount >> 5);
  178. _addUncounted(byteCount << 3);
  179. }
  180. static uint32_t _rol32(const uint32_t number, const uint8_t bits) noexcept
  181. {
  182. return (number << bits) | (number >> (32 - bits));
  183. }
  184. };
  185. #endif // CARLA_SHA1_UTILS_HPP_INCLUDED