BLAKE2b.cpp 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. /*
  2. * Copyright (c) 2023, the SerenityOS developers
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <AK/ByteReader.h>
  7. #include <LibCrypto/Hash/BLAKE2b.h>
  8. namespace Crypto::Hash {
  9. constexpr static auto ROTRIGHT(u64 a, size_t b) { return (a >> b) | (a << (64 - b)); }
  10. void BLAKE2b::update(u8 const* in, size_t inlen)
  11. {
  12. if (inlen > 0) {
  13. size_t left = m_internal_state.buffer_length;
  14. size_t fill = BLAKE2bConstants::blockbytes - left;
  15. if (inlen > fill) {
  16. m_internal_state.buffer_length = 0;
  17. // Fill the buffer.
  18. __builtin_memcpy(m_internal_state.buffer + left, in, fill);
  19. increment_counter_by(BLAKE2bConstants::blockbytes);
  20. transform(m_internal_state.buffer);
  21. in += fill;
  22. inlen -= fill;
  23. while (inlen > BLAKE2bConstants::blockbytes) {
  24. increment_counter_by(BLAKE2bConstants::blockbytes);
  25. transform(in);
  26. in += BLAKE2bConstants::blockbytes;
  27. inlen -= BLAKE2bConstants::blockbytes;
  28. }
  29. }
  30. __builtin_memcpy(m_internal_state.buffer + m_internal_state.buffer_length, in, inlen);
  31. m_internal_state.buffer_length += inlen;
  32. }
  33. }
  34. BLAKE2b::DigestType BLAKE2b::peek()
  35. {
  36. DigestType digest;
  37. increment_counter_by(m_internal_state.buffer_length);
  38. // Set this as the last block
  39. m_internal_state.is_at_last_block = UINT64_MAX;
  40. // Pad the buffer with zeros
  41. __builtin_memset(m_internal_state.buffer + m_internal_state.buffer_length, 0, BLAKE2bConstants::blockbytes - m_internal_state.buffer_length);
  42. transform(m_internal_state.buffer);
  43. for (size_t i = 0; i < 8; ++i)
  44. __builtin_memcpy(&digest.data[0] + sizeof(m_internal_state.hash_state[i]) * i, &m_internal_state.hash_state[i], sizeof(m_internal_state.hash_state[i]));
  45. return digest;
  46. }
  47. BLAKE2b::DigestType BLAKE2b::digest()
  48. {
  49. auto digest = peek();
  50. reset();
  51. return digest;
  52. }
  53. void BLAKE2b::increment_counter_by(const u64 amount)
  54. {
  55. m_internal_state.message_byte_offset[0] += amount;
  56. m_internal_state.message_byte_offset[1] += (m_internal_state.message_byte_offset[0] < amount);
  57. }
  58. void BLAKE2b::mix(u64* work_array, u64 a, u64 b, u64 c, u64 d, u64 x, u64 y)
  59. {
  60. constexpr auto rotation_constant_1 = 32;
  61. constexpr auto rotation_constant_2 = 24;
  62. constexpr auto rotation_constant_3 = 16;
  63. constexpr auto rotation_constant_4 = 63;
  64. work_array[a] = work_array[a] + work_array[b] + x;
  65. work_array[d] = ROTRIGHT(work_array[d] ^ work_array[a], rotation_constant_1);
  66. work_array[c] = work_array[c] + work_array[d];
  67. work_array[b] = ROTRIGHT(work_array[b] ^ work_array[c], rotation_constant_2);
  68. work_array[a] = work_array[a] + work_array[b] + y;
  69. work_array[d] = ROTRIGHT(work_array[d] ^ work_array[a], rotation_constant_3);
  70. work_array[c] = work_array[c] + work_array[d];
  71. work_array[b] = ROTRIGHT(work_array[b] ^ work_array[c], rotation_constant_4);
  72. }
  73. void BLAKE2b::transform(u8 const* block)
  74. {
  75. u64 m[16];
  76. u64 v[16];
  77. for (size_t i = 0; i < 16; ++i)
  78. m[i] = ByteReader::load64(block + i * sizeof(m[i]));
  79. for (size_t i = 0; i < 8; ++i)
  80. v[i] = m_internal_state.hash_state[i];
  81. v[8] = SHA512Constants::InitializationHashes[0];
  82. v[9] = SHA512Constants::InitializationHashes[1];
  83. v[10] = SHA512Constants::InitializationHashes[2];
  84. v[11] = SHA512Constants::InitializationHashes[3];
  85. v[12] = SHA512Constants::InitializationHashes[4] ^ m_internal_state.message_byte_offset[0];
  86. v[13] = SHA512Constants::InitializationHashes[5] ^ m_internal_state.message_byte_offset[1];
  87. v[14] = SHA512Constants::InitializationHashes[6] ^ m_internal_state.is_at_last_block;
  88. v[15] = SHA512Constants::InitializationHashes[7];
  89. for (size_t i = 0; i < 12; ++i) {
  90. u64 sigma_selection[16];
  91. for (size_t j = 0; j < 16; ++j)
  92. sigma_selection[j] = BLAKE2bSigma[i % 10][j];
  93. mix(v, 0, 4, 8, 12, m[sigma_selection[0]], m[sigma_selection[1]]);
  94. mix(v, 1, 5, 9, 13, m[sigma_selection[2]], m[sigma_selection[3]]);
  95. mix(v, 2, 6, 10, 14, m[sigma_selection[4]], m[sigma_selection[5]]);
  96. mix(v, 3, 7, 11, 15, m[sigma_selection[6]], m[sigma_selection[7]]);
  97. mix(v, 0, 5, 10, 15, m[sigma_selection[8]], m[sigma_selection[9]]);
  98. mix(v, 1, 6, 11, 12, m[sigma_selection[10]], m[sigma_selection[11]]);
  99. mix(v, 2, 7, 8, 13, m[sigma_selection[12]], m[sigma_selection[13]]);
  100. mix(v, 3, 4, 9, 14, m[sigma_selection[14]], m[sigma_selection[15]]);
  101. }
  102. for (size_t i = 0; i < 8; ++i)
  103. m_internal_state.hash_state[i] = m_internal_state.hash_state[i] ^ v[i] ^ v[i + 8];
  104. }
  105. }