HashManager.h 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297
  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 <LibCrypto/Hash/HashFunction.h>
  10. #include <LibCrypto/Hash/MD5.h>
  11. #include <LibCrypto/Hash/SHA1.h>
  12. #include <LibCrypto/Hash/SHA2.h>
  13. namespace Crypto {
  14. namespace Hash {
  15. enum class HashKind {
  16. None,
  17. SHA1,
  18. SHA256,
  19. SHA512,
  20. MD5,
  21. };
  22. struct MultiHashDigestVariant {
  23. constexpr static size_t Size = 0;
  24. MultiHashDigestVariant(SHA1::DigestType digest)
  25. : sha1(digest)
  26. , kind(HashKind::SHA1)
  27. {
  28. }
  29. MultiHashDigestVariant(SHA256::DigestType digest)
  30. : sha256(digest)
  31. , kind(HashKind::SHA256)
  32. {
  33. }
  34. MultiHashDigestVariant(SHA512::DigestType digest)
  35. : sha512(digest)
  36. , kind(HashKind::SHA512)
  37. {
  38. }
  39. MultiHashDigestVariant(MD5::DigestType digest)
  40. : md5(digest)
  41. , kind(HashKind::MD5)
  42. {
  43. }
  44. const u8* immutable_data() const
  45. {
  46. switch (kind) {
  47. case HashKind::MD5:
  48. return md5.value().immutable_data();
  49. case HashKind::SHA1:
  50. return sha1.value().immutable_data();
  51. case HashKind::SHA256:
  52. return sha256.value().immutable_data();
  53. case HashKind::SHA512:
  54. return sha512.value().immutable_data();
  55. default:
  56. case HashKind::None:
  57. VERIFY_NOT_REACHED();
  58. break;
  59. }
  60. }
  61. size_t data_length()
  62. {
  63. switch (kind) {
  64. case HashKind::MD5:
  65. return md5.value().data_length();
  66. case HashKind::SHA1:
  67. return sha1.value().data_length();
  68. case HashKind::SHA256:
  69. return sha256.value().data_length();
  70. case HashKind::SHA512:
  71. return sha512.value().data_length();
  72. default:
  73. case HashKind::None:
  74. VERIFY_NOT_REACHED();
  75. break;
  76. }
  77. }
  78. Optional<SHA1::DigestType> sha1;
  79. Optional<SHA256::DigestType> sha256;
  80. Optional<SHA512::DigestType> sha512;
  81. Optional<MD5::DigestType> md5;
  82. HashKind kind { HashKind::None };
  83. };
  84. class Manager final : public HashFunction<0, MultiHashDigestVariant> {
  85. public:
  86. using HashFunction::update;
  87. Manager()
  88. {
  89. m_pre_init_buffer = ByteBuffer::create_zeroed(0);
  90. }
  91. Manager(const Manager& other) // NOT a copy constructor!
  92. {
  93. m_pre_init_buffer = ByteBuffer::create_zeroed(0); // will not be used
  94. initialize(other.m_kind);
  95. }
  96. Manager(HashKind kind)
  97. {
  98. m_pre_init_buffer = ByteBuffer::create_zeroed(0);
  99. initialize(kind);
  100. }
  101. ~Manager()
  102. {
  103. m_sha1 = nullptr;
  104. m_sha256 = nullptr;
  105. m_sha512 = nullptr;
  106. m_md5 = nullptr;
  107. }
  108. inline size_t digest_size() const
  109. {
  110. switch (m_kind) {
  111. case HashKind::MD5:
  112. return m_md5->digest_size();
  113. case HashKind::SHA1:
  114. return m_sha1->digest_size();
  115. case HashKind::SHA256:
  116. return m_sha256->digest_size();
  117. case HashKind::SHA512:
  118. return m_sha512->digest_size();
  119. default:
  120. case HashKind::None:
  121. return 0;
  122. }
  123. }
  124. inline size_t block_size() const
  125. {
  126. switch (m_kind) {
  127. case HashKind::MD5:
  128. return m_md5->block_size();
  129. case HashKind::SHA1:
  130. return m_sha1->block_size();
  131. case HashKind::SHA256:
  132. return m_sha256->block_size();
  133. case HashKind::SHA512:
  134. return m_sha512->block_size();
  135. default:
  136. case HashKind::None:
  137. return 0;
  138. }
  139. }
  140. inline void initialize(HashKind kind)
  141. {
  142. if (m_kind != HashKind::None) {
  143. VERIFY_NOT_REACHED();
  144. }
  145. m_kind = kind;
  146. switch (kind) {
  147. case HashKind::MD5:
  148. m_md5 = make<MD5>();
  149. break;
  150. case HashKind::SHA1:
  151. m_sha1 = make<SHA1>();
  152. break;
  153. case HashKind::SHA256:
  154. m_sha256 = make<SHA256>();
  155. break;
  156. case HashKind::SHA512:
  157. m_sha512 = make<SHA512>();
  158. break;
  159. default:
  160. case HashKind::None:
  161. break;
  162. }
  163. }
  164. virtual void update(const u8* data, size_t length) override
  165. {
  166. auto size = m_pre_init_buffer.size();
  167. switch (m_kind) {
  168. case HashKind::MD5:
  169. if (size)
  170. m_md5->update(m_pre_init_buffer);
  171. m_md5->update(data, length);
  172. break;
  173. case HashKind::SHA1:
  174. if (size)
  175. m_sha1->update(m_pre_init_buffer);
  176. m_sha1->update(data, length);
  177. break;
  178. case HashKind::SHA256:
  179. if (size)
  180. m_sha256->update(m_pre_init_buffer);
  181. m_sha256->update(data, length);
  182. break;
  183. case HashKind::SHA512:
  184. if (size)
  185. m_sha512->update(m_pre_init_buffer);
  186. m_sha512->update(data, length);
  187. break;
  188. default:
  189. case HashKind::None:
  190. m_pre_init_buffer.append(data, length);
  191. return;
  192. }
  193. if (size)
  194. m_pre_init_buffer.clear();
  195. }
  196. virtual DigestType peek() override
  197. {
  198. switch (m_kind) {
  199. case HashKind::MD5:
  200. return { m_md5->peek() };
  201. case HashKind::SHA1:
  202. return { m_sha1->peek() };
  203. case HashKind::SHA256:
  204. return { m_sha256->peek() };
  205. case HashKind::SHA512:
  206. return { m_sha512->peek() };
  207. default:
  208. case HashKind::None:
  209. VERIFY_NOT_REACHED();
  210. break;
  211. }
  212. }
  213. virtual DigestType digest() override
  214. {
  215. auto digest = peek();
  216. reset();
  217. return digest;
  218. }
  219. virtual void reset() override
  220. {
  221. m_pre_init_buffer.clear();
  222. switch (m_kind) {
  223. case HashKind::MD5:
  224. m_md5->reset();
  225. break;
  226. case HashKind::SHA1:
  227. m_sha1->reset();
  228. break;
  229. case HashKind::SHA256:
  230. m_sha256->reset();
  231. break;
  232. case HashKind::SHA512:
  233. m_sha512->reset();
  234. break;
  235. default:
  236. case HashKind::None:
  237. break;
  238. }
  239. }
  240. virtual String class_name() const override
  241. {
  242. switch (m_kind) {
  243. case HashKind::MD5:
  244. return m_md5->class_name();
  245. case HashKind::SHA1:
  246. return m_sha1->class_name();
  247. case HashKind::SHA256:
  248. return m_sha256->class_name();
  249. case HashKind::SHA512:
  250. return m_sha512->class_name();
  251. default:
  252. case HashKind::None:
  253. return "UninitializedHashManager";
  254. }
  255. }
  256. inline bool is(HashKind kind) const
  257. {
  258. return m_kind == kind;
  259. }
  260. private:
  261. OwnPtr<SHA1> m_sha1;
  262. OwnPtr<SHA256> m_sha256;
  263. OwnPtr<SHA512> m_sha512;
  264. OwnPtr<MD5> m_md5;
  265. HashKind m_kind { HashKind::None };
  266. ByteBuffer m_pre_init_buffer;
  267. };
  268. }
  269. }