SHA2.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394
  1. /*
  2. * Copyright (c) 2020, Ali Mohammad Pur <mpfard@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <AK/Types.h>
  7. #include <LibCrypto/Hash/SHA2.h>
  8. namespace Crypto::Hash {
  9. constexpr static auto ROTRIGHT(u32 a, size_t b) { return (a >> b) | (a << (32 - b)); }
  10. constexpr static auto CH(u32 x, u32 y, u32 z) { return (x & y) ^ (z & ~x); }
  11. constexpr static auto MAJ(u32 x, u32 y, u32 z) { return (x & y) ^ (x & z) ^ (y & z); }
  12. constexpr static auto EP0(u32 x) { return ROTRIGHT(x, 2) ^ ROTRIGHT(x, 13) ^ ROTRIGHT(x, 22); }
  13. constexpr static auto EP1(u32 x) { return ROTRIGHT(x, 6) ^ ROTRIGHT(x, 11) ^ ROTRIGHT(x, 25); }
  14. constexpr static auto SIGN0(u32 x) { return ROTRIGHT(x, 7) ^ ROTRIGHT(x, 18) ^ (x >> 3); }
  15. constexpr static auto SIGN1(u32 x) { return ROTRIGHT(x, 17) ^ ROTRIGHT(x, 19) ^ (x >> 10); }
  16. constexpr static auto ROTRIGHT(u64 a, size_t b) { return (a >> b) | (a << (64 - b)); }
  17. constexpr static auto CH(u64 x, u64 y, u64 z) { return (x & y) ^ (z & ~x); }
  18. constexpr static auto MAJ(u64 x, u64 y, u64 z) { return (x & y) ^ (x & z) ^ (y & z); }
  19. constexpr static auto EP0(u64 x) { return ROTRIGHT(x, 28) ^ ROTRIGHT(x, 34) ^ ROTRIGHT(x, 39); }
  20. constexpr static auto EP1(u64 x) { return ROTRIGHT(x, 14) ^ ROTRIGHT(x, 18) ^ ROTRIGHT(x, 41); }
  21. constexpr static auto SIGN0(u64 x) { return ROTRIGHT(x, 1) ^ ROTRIGHT(x, 8) ^ (x >> 7); }
  22. constexpr static auto SIGN1(u64 x) { return ROTRIGHT(x, 19) ^ ROTRIGHT(x, 61) ^ (x >> 6); }
  23. inline void SHA256::transform(u8 const* data)
  24. {
  25. u32 m[64];
  26. size_t i = 0;
  27. for (size_t j = 0; i < 16; ++i, j += 4) {
  28. m[i] = (data[j] << 24) | (data[j + 1] << 16) | (data[j + 2] << 8) | data[j + 3];
  29. }
  30. for (; i < BlockSize; ++i) {
  31. m[i] = SIGN1(m[i - 2]) + m[i - 7] + SIGN0(m[i - 15]) + m[i - 16];
  32. }
  33. auto a = m_state[0], b = m_state[1],
  34. c = m_state[2], d = m_state[3],
  35. e = m_state[4], f = m_state[5],
  36. g = m_state[6], h = m_state[7];
  37. for (size_t i = 0; i < Rounds; ++i) {
  38. auto temp0 = h + EP1(e) + CH(e, f, g) + SHA256Constants::RoundConstants[i] + m[i];
  39. auto temp1 = EP0(a) + MAJ(a, b, c);
  40. h = g;
  41. g = f;
  42. f = e;
  43. e = d + temp0;
  44. d = c;
  45. c = b;
  46. b = a;
  47. a = temp0 + temp1;
  48. }
  49. m_state[0] += a;
  50. m_state[1] += b;
  51. m_state[2] += c;
  52. m_state[3] += d;
  53. m_state[4] += e;
  54. m_state[5] += f;
  55. m_state[6] += g;
  56. m_state[7] += h;
  57. }
  58. void SHA256::update(u8 const* message, size_t length)
  59. {
  60. for (size_t i = 0; i < length; ++i) {
  61. if (m_data_length == BlockSize) {
  62. transform(m_data_buffer);
  63. m_bit_length += 512;
  64. m_data_length = 0;
  65. }
  66. m_data_buffer[m_data_length++] = message[i];
  67. }
  68. }
  69. SHA256::DigestType SHA256::digest()
  70. {
  71. auto digest = peek();
  72. reset();
  73. return digest;
  74. }
  75. SHA256::DigestType SHA256::peek()
  76. {
  77. DigestType digest;
  78. size_t i = m_data_length;
  79. if (BlockSize == m_data_length) {
  80. transform(m_data_buffer);
  81. m_bit_length += BlockSize * 8;
  82. m_data_length = 0;
  83. i = 0;
  84. }
  85. if (m_data_length < FinalBlockDataSize) {
  86. m_data_buffer[i++] = 0x80;
  87. while (i < FinalBlockDataSize)
  88. m_data_buffer[i++] = 0x00;
  89. } else {
  90. // First, complete a block with some padding.
  91. m_data_buffer[i++] = 0x80;
  92. while (i < BlockSize)
  93. m_data_buffer[i++] = 0x00;
  94. transform(m_data_buffer);
  95. // Then start another block with BlockSize - 8 bytes of zeros
  96. __builtin_memset(m_data_buffer, 0, FinalBlockDataSize);
  97. }
  98. // append total message length
  99. m_bit_length += m_data_length * 8;
  100. m_data_buffer[BlockSize - 1] = m_bit_length;
  101. m_data_buffer[BlockSize - 2] = m_bit_length >> 8;
  102. m_data_buffer[BlockSize - 3] = m_bit_length >> 16;
  103. m_data_buffer[BlockSize - 4] = m_bit_length >> 24;
  104. m_data_buffer[BlockSize - 5] = m_bit_length >> 32;
  105. m_data_buffer[BlockSize - 6] = m_bit_length >> 40;
  106. m_data_buffer[BlockSize - 7] = m_bit_length >> 48;
  107. m_data_buffer[BlockSize - 8] = m_bit_length >> 56;
  108. transform(m_data_buffer);
  109. // SHA uses big-endian and we assume little-endian
  110. // FIXME: looks like a thing for AK::NetworkOrdered,
  111. // but that doesn't support shifting operations
  112. for (size_t i = 0; i < 4; ++i) {
  113. digest.data[i + 0] = (m_state[0] >> (24 - i * 8)) & 0x000000ff;
  114. digest.data[i + 4] = (m_state[1] >> (24 - i * 8)) & 0x000000ff;
  115. digest.data[i + 8] = (m_state[2] >> (24 - i * 8)) & 0x000000ff;
  116. digest.data[i + 12] = (m_state[3] >> (24 - i * 8)) & 0x000000ff;
  117. digest.data[i + 16] = (m_state[4] >> (24 - i * 8)) & 0x000000ff;
  118. digest.data[i + 20] = (m_state[5] >> (24 - i * 8)) & 0x000000ff;
  119. digest.data[i + 24] = (m_state[6] >> (24 - i * 8)) & 0x000000ff;
  120. digest.data[i + 28] = (m_state[7] >> (24 - i * 8)) & 0x000000ff;
  121. }
  122. return digest;
  123. }
  124. inline void SHA384::transform(u8 const* data)
  125. {
  126. u64 m[80];
  127. size_t i = 0;
  128. for (size_t j = 0; i < 16; ++i, j += 8) {
  129. m[i] = ((u64)data[j] << 56) | ((u64)data[j + 1] << 48) | ((u64)data[j + 2] << 40) | ((u64)data[j + 3] << 32) | ((u64)data[j + 4] << 24) | ((u64)data[j + 5] << 16) | ((u64)data[j + 6] << 8) | (u64)data[j + 7];
  130. }
  131. for (; i < Rounds; ++i) {
  132. m[i] = SIGN1(m[i - 2]) + m[i - 7] + SIGN0(m[i - 15]) + m[i - 16];
  133. }
  134. auto a = m_state[0], b = m_state[1],
  135. c = m_state[2], d = m_state[3],
  136. e = m_state[4], f = m_state[5],
  137. g = m_state[6], h = m_state[7];
  138. for (size_t i = 0; i < Rounds; ++i) {
  139. // Note : SHA384 uses the SHA512 constants.
  140. auto temp0 = h + EP1(e) + CH(e, f, g) + SHA512Constants::RoundConstants[i] + m[i];
  141. auto temp1 = EP0(a) + MAJ(a, b, c);
  142. h = g;
  143. g = f;
  144. f = e;
  145. e = d + temp0;
  146. d = c;
  147. c = b;
  148. b = a;
  149. a = temp0 + temp1;
  150. }
  151. m_state[0] += a;
  152. m_state[1] += b;
  153. m_state[2] += c;
  154. m_state[3] += d;
  155. m_state[4] += e;
  156. m_state[5] += f;
  157. m_state[6] += g;
  158. m_state[7] += h;
  159. }
  160. void SHA384::update(u8 const* message, size_t length)
  161. {
  162. for (size_t i = 0; i < length; ++i) {
  163. if (m_data_length == BlockSize) {
  164. transform(m_data_buffer);
  165. m_bit_length += 1024;
  166. m_data_length = 0;
  167. }
  168. m_data_buffer[m_data_length++] = message[i];
  169. }
  170. }
  171. SHA384::DigestType SHA384::digest()
  172. {
  173. auto digest = peek();
  174. reset();
  175. return digest;
  176. }
  177. SHA384::DigestType SHA384::peek()
  178. {
  179. DigestType digest;
  180. size_t i = m_data_length;
  181. if (BlockSize == m_data_length) {
  182. transform(m_data_buffer);
  183. m_bit_length += BlockSize * 8;
  184. m_data_length = 0;
  185. i = 0;
  186. }
  187. if (m_data_length < FinalBlockDataSize) {
  188. m_data_buffer[i++] = 0x80;
  189. while (i < FinalBlockDataSize)
  190. m_data_buffer[i++] = 0x00;
  191. } else {
  192. // First, complete a block with some padding.
  193. m_data_buffer[i++] = 0x80;
  194. while (i < BlockSize)
  195. m_data_buffer[i++] = 0x00;
  196. transform(m_data_buffer);
  197. // Then start another block with BlockSize - 8 bytes of zeros
  198. __builtin_memset(m_data_buffer, 0, FinalBlockDataSize);
  199. }
  200. // append total message length
  201. m_bit_length += m_data_length * 8;
  202. m_data_buffer[BlockSize - 1] = m_bit_length;
  203. m_data_buffer[BlockSize - 2] = m_bit_length >> 8;
  204. m_data_buffer[BlockSize - 3] = m_bit_length >> 16;
  205. m_data_buffer[BlockSize - 4] = m_bit_length >> 24;
  206. m_data_buffer[BlockSize - 5] = m_bit_length >> 32;
  207. m_data_buffer[BlockSize - 6] = m_bit_length >> 40;
  208. m_data_buffer[BlockSize - 7] = m_bit_length >> 48;
  209. m_data_buffer[BlockSize - 8] = m_bit_length >> 56;
  210. // FIXME: Theoretically we should keep track of the number of bits as a u128, now we can only hash up to 2 EiB.
  211. m_data_buffer[BlockSize - 9] = 0;
  212. m_data_buffer[BlockSize - 10] = 0;
  213. m_data_buffer[BlockSize - 11] = 0;
  214. m_data_buffer[BlockSize - 12] = 0;
  215. m_data_buffer[BlockSize - 13] = 0;
  216. m_data_buffer[BlockSize - 14] = 0;
  217. m_data_buffer[BlockSize - 15] = 0;
  218. m_data_buffer[BlockSize - 16] = 0;
  219. transform(m_data_buffer);
  220. // SHA uses big-endian and we assume little-endian
  221. // FIXME: looks like a thing for AK::NetworkOrdered,
  222. // but that doesn't support shifting operations
  223. for (size_t i = 0; i < 8; ++i) {
  224. digest.data[i + 0] = (m_state[0] >> (56 - i * 8)) & 0x000000ff;
  225. digest.data[i + 8] = (m_state[1] >> (56 - i * 8)) & 0x000000ff;
  226. digest.data[i + 16] = (m_state[2] >> (56 - i * 8)) & 0x000000ff;
  227. digest.data[i + 24] = (m_state[3] >> (56 - i * 8)) & 0x000000ff;
  228. digest.data[i + 32] = (m_state[4] >> (56 - i * 8)) & 0x000000ff;
  229. digest.data[i + 40] = (m_state[5] >> (56 - i * 8)) & 0x000000ff;
  230. }
  231. return digest;
  232. }
  233. inline void SHA512::transform(u8 const* data)
  234. {
  235. u64 m[80];
  236. size_t i = 0;
  237. for (size_t j = 0; i < 16; ++i, j += 8) {
  238. m[i] = ((u64)data[j] << 56) | ((u64)data[j + 1] << 48) | ((u64)data[j + 2] << 40) | ((u64)data[j + 3] << 32) | ((u64)data[j + 4] << 24) | ((u64)data[j + 5] << 16) | ((u64)data[j + 6] << 8) | (u64)data[j + 7];
  239. }
  240. for (; i < Rounds; ++i) {
  241. m[i] = SIGN1(m[i - 2]) + m[i - 7] + SIGN0(m[i - 15]) + m[i - 16];
  242. }
  243. auto a = m_state[0], b = m_state[1],
  244. c = m_state[2], d = m_state[3],
  245. e = m_state[4], f = m_state[5],
  246. g = m_state[6], h = m_state[7];
  247. for (size_t i = 0; i < Rounds; ++i) {
  248. auto temp0 = h + EP1(e) + CH(e, f, g) + SHA512Constants::RoundConstants[i] + m[i];
  249. auto temp1 = EP0(a) + MAJ(a, b, c);
  250. h = g;
  251. g = f;
  252. f = e;
  253. e = d + temp0;
  254. d = c;
  255. c = b;
  256. b = a;
  257. a = temp0 + temp1;
  258. }
  259. m_state[0] += a;
  260. m_state[1] += b;
  261. m_state[2] += c;
  262. m_state[3] += d;
  263. m_state[4] += e;
  264. m_state[5] += f;
  265. m_state[6] += g;
  266. m_state[7] += h;
  267. }
  268. void SHA512::update(u8 const* message, size_t length)
  269. {
  270. for (size_t i = 0; i < length; ++i) {
  271. if (m_data_length == BlockSize) {
  272. transform(m_data_buffer);
  273. m_bit_length += 1024;
  274. m_data_length = 0;
  275. }
  276. m_data_buffer[m_data_length++] = message[i];
  277. }
  278. }
  279. SHA512::DigestType SHA512::digest()
  280. {
  281. auto digest = peek();
  282. reset();
  283. return digest;
  284. }
  285. SHA512::DigestType SHA512::peek()
  286. {
  287. DigestType digest;
  288. size_t i = m_data_length;
  289. if (BlockSize == m_data_length) {
  290. transform(m_data_buffer);
  291. m_bit_length += BlockSize * 8;
  292. m_data_length = 0;
  293. i = 0;
  294. }
  295. if (m_data_length < FinalBlockDataSize) {
  296. m_data_buffer[i++] = 0x80;
  297. while (i < FinalBlockDataSize)
  298. m_data_buffer[i++] = 0x00;
  299. } else {
  300. // First, complete a block with some padding.
  301. m_data_buffer[i++] = 0x80;
  302. while (i < BlockSize)
  303. m_data_buffer[i++] = 0x00;
  304. transform(m_data_buffer);
  305. // Then start another block with BlockSize - 8 bytes of zeros
  306. __builtin_memset(m_data_buffer, 0, FinalBlockDataSize);
  307. }
  308. // append total message length
  309. m_bit_length += m_data_length * 8;
  310. m_data_buffer[BlockSize - 1] = m_bit_length;
  311. m_data_buffer[BlockSize - 2] = m_bit_length >> 8;
  312. m_data_buffer[BlockSize - 3] = m_bit_length >> 16;
  313. m_data_buffer[BlockSize - 4] = m_bit_length >> 24;
  314. m_data_buffer[BlockSize - 5] = m_bit_length >> 32;
  315. m_data_buffer[BlockSize - 6] = m_bit_length >> 40;
  316. m_data_buffer[BlockSize - 7] = m_bit_length >> 48;
  317. m_data_buffer[BlockSize - 8] = m_bit_length >> 56;
  318. // FIXME: Theoretically we should keep track of the number of bits as a u128, now we can only hash up to 2 EiB.
  319. m_data_buffer[BlockSize - 9] = 0;
  320. m_data_buffer[BlockSize - 10] = 0;
  321. m_data_buffer[BlockSize - 11] = 0;
  322. m_data_buffer[BlockSize - 12] = 0;
  323. m_data_buffer[BlockSize - 13] = 0;
  324. m_data_buffer[BlockSize - 14] = 0;
  325. m_data_buffer[BlockSize - 15] = 0;
  326. m_data_buffer[BlockSize - 16] = 0;
  327. transform(m_data_buffer);
  328. // SHA uses big-endian and we assume little-endian
  329. // FIXME: looks like a thing for AK::NetworkOrdered,
  330. // but that doesn't support shifting operations
  331. for (size_t i = 0; i < 8; ++i) {
  332. digest.data[i + 0] = (m_state[0] >> (56 - i * 8)) & 0x000000ff;
  333. digest.data[i + 8] = (m_state[1] >> (56 - i * 8)) & 0x000000ff;
  334. digest.data[i + 16] = (m_state[2] >> (56 - i * 8)) & 0x000000ff;
  335. digest.data[i + 24] = (m_state[3] >> (56 - i * 8)) & 0x000000ff;
  336. digest.data[i + 32] = (m_state[4] >> (56 - i * 8)) & 0x000000ff;
  337. digest.data[i + 40] = (m_state[5] >> (56 - i * 8)) & 0x000000ff;
  338. digest.data[i + 48] = (m_state[6] >> (56 - i * 8)) & 0x000000ff;
  339. digest.data[i + 56] = (m_state[7] >> (56 - i * 8)) & 0x000000ff;
  340. }
  341. return digest;
  342. }
  343. }