HashManager.h 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. /*
  2. * Copyright (c) 2020, Ali Mohammad Pur <mpfard@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #pragma once
  7. #include <AK/Optional.h>
  8. #include <AK/OwnPtr.h>
  9. #include <AK/Variant.h>
  10. #include <LibCrypto/Hash/HashFunction.h>
  11. #include <LibCrypto/Hash/MD5.h>
  12. #include <LibCrypto/Hash/SHA1.h>
  13. #include <LibCrypto/Hash/SHA2.h>
  14. namespace Crypto {
  15. namespace Hash {
  16. enum class HashKind {
  17. Unknown,
  18. None,
  19. SHA1,
  20. SHA256,
  21. SHA384,
  22. SHA512,
  23. MD5,
  24. };
  25. struct MultiHashDigestVariant {
  26. constexpr static size_t Size = 0;
  27. MultiHashDigestVariant(Empty digest)
  28. : m_digest(move(digest))
  29. {
  30. }
  31. MultiHashDigestVariant(MD5::DigestType digest)
  32. : m_digest(move(digest))
  33. {
  34. }
  35. MultiHashDigestVariant(SHA1::DigestType digest)
  36. : m_digest(move(digest))
  37. {
  38. }
  39. MultiHashDigestVariant(SHA256::DigestType digest)
  40. : m_digest(move(digest))
  41. {
  42. }
  43. MultiHashDigestVariant(SHA384::DigestType digest)
  44. : m_digest(move(digest))
  45. {
  46. }
  47. MultiHashDigestVariant(SHA512::DigestType digest)
  48. : m_digest(move(digest))
  49. {
  50. }
  51. [[nodiscard]] u8 const* immutable_data() const
  52. {
  53. return m_digest.visit(
  54. [&](Empty const&) -> u8 const* { VERIFY_NOT_REACHED(); },
  55. [&](auto const& value) { return value.immutable_data(); });
  56. }
  57. [[nodiscard]] size_t data_length() const
  58. {
  59. return m_digest.visit(
  60. [&](Empty const&) -> size_t { VERIFY_NOT_REACHED(); },
  61. [&](auto const& value) { return value.data_length(); });
  62. }
  63. [[nodiscard]] ReadonlyBytes bytes() const
  64. {
  65. return m_digest.visit(
  66. [&](Empty const&) -> ReadonlyBytes { VERIFY_NOT_REACHED(); },
  67. [&](auto const& value) { return value.bytes(); });
  68. }
  69. using DigestVariant = Variant<Empty, MD5::DigestType, SHA1::DigestType, SHA256::DigestType, SHA384::DigestType, SHA512::DigestType>;
  70. DigestVariant m_digest {};
  71. };
  72. class Manager final : public HashFunction<0, 0, MultiHashDigestVariant> {
  73. public:
  74. using HashFunction::update;
  75. Manager()
  76. {
  77. m_pre_init_buffer = ByteBuffer();
  78. }
  79. Manager(Manager const& other) // NOT a copy constructor!
  80. {
  81. m_pre_init_buffer = ByteBuffer(); // will not be used
  82. initialize(other.m_kind);
  83. }
  84. Manager(HashKind kind)
  85. {
  86. m_pre_init_buffer = ByteBuffer();
  87. initialize(kind);
  88. }
  89. ~Manager()
  90. {
  91. m_algorithm = Empty {};
  92. }
  93. inline size_t digest_size() const
  94. {
  95. return m_algorithm.visit(
  96. [&](Empty const&) -> size_t { return 0; },
  97. [&](auto const& hash) { return hash.digest_size(); });
  98. }
  99. inline size_t block_size() const
  100. {
  101. return m_algorithm.visit(
  102. [&](Empty const&) -> size_t { return 0; },
  103. [&](auto const& hash) { return hash.block_size(); });
  104. }
  105. inline void initialize(HashKind kind)
  106. {
  107. if (!m_algorithm.has<Empty>()) {
  108. VERIFY_NOT_REACHED();
  109. }
  110. m_kind = kind;
  111. switch (kind) {
  112. case HashKind::MD5:
  113. m_algorithm = MD5();
  114. break;
  115. case HashKind::SHA1:
  116. m_algorithm = SHA1();
  117. break;
  118. case HashKind::SHA256:
  119. m_algorithm = SHA256();
  120. break;
  121. case HashKind::SHA384:
  122. m_algorithm = SHA384();
  123. break;
  124. case HashKind::SHA512:
  125. m_algorithm = SHA512();
  126. break;
  127. default:
  128. case HashKind::None:
  129. m_algorithm = Empty {};
  130. break;
  131. }
  132. }
  133. virtual void update(u8 const* data, size_t length) override
  134. {
  135. auto size = m_pre_init_buffer.size();
  136. if (size) {
  137. m_algorithm.visit(
  138. [&](Empty&) {},
  139. [&](auto& hash) { hash.update(m_pre_init_buffer); });
  140. }
  141. m_algorithm.visit(
  142. [&](Empty&) { m_pre_init_buffer.append(data, length); },
  143. [&](auto& hash) { hash.update(data, length); });
  144. if (size && m_kind != HashKind::None)
  145. m_pre_init_buffer.clear();
  146. }
  147. virtual DigestType peek() override
  148. {
  149. return m_algorithm.visit(
  150. [&](Empty&) -> DigestType { VERIFY_NOT_REACHED(); },
  151. [&](auto& hash) -> DigestType { return hash.peek(); });
  152. }
  153. virtual DigestType digest() override
  154. {
  155. auto digest = peek();
  156. reset();
  157. return digest;
  158. }
  159. virtual void reset() override
  160. {
  161. m_pre_init_buffer.clear();
  162. m_algorithm.visit(
  163. [&](Empty&) {},
  164. [&](auto& hash) { hash.reset(); });
  165. }
  166. #ifndef KERNEL
  167. virtual DeprecatedString class_name() const override
  168. {
  169. return m_algorithm.visit(
  170. [&](Empty const&) -> DeprecatedString { return "UninitializedHashManager"; },
  171. [&](auto const& hash) { return hash.class_name(); });
  172. }
  173. #endif
  174. inline HashKind kind() const
  175. {
  176. return m_kind;
  177. }
  178. inline bool is(HashKind kind) const
  179. {
  180. return m_kind == kind;
  181. }
  182. private:
  183. using AlgorithmVariant = Variant<Empty, MD5, SHA1, SHA256, SHA384, SHA512>;
  184. AlgorithmVariant m_algorithm {};
  185. HashKind m_kind { HashKind::None };
  186. ByteBuffer m_pre_init_buffer;
  187. };
  188. }
  189. }