HashManager.h 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317
  1. /*
  2. * Copyright (c) 2020, Ali Mohammad Pur <ali.mpfard@gmail.com>
  3. * All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions are met:
  7. *
  8. * 1. Redistributions of source code must retain the above copyright notice, this
  9. * list of conditions and the following disclaimer.
  10. *
  11. * 2. Redistributions in binary form must reproduce the above copyright notice,
  12. * this list of conditions and the following disclaimer in the documentation
  13. * and/or other materials provided with the distribution.
  14. *
  15. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  16. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  17. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  18. * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
  19. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  20. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  21. * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  22. * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  23. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  24. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  25. */
  26. #pragma once
  27. #include <AK/Optional.h>
  28. #include <AK/OwnPtr.h>
  29. #include <LibCrypto/Hash/HashFunction.h>
  30. #include <LibCrypto/Hash/MD5.h>
  31. #include <LibCrypto/Hash/SHA1.h>
  32. #include <LibCrypto/Hash/SHA2.h>
  33. namespace Crypto {
  34. namespace Hash {
  35. enum class HashKind {
  36. None,
  37. SHA1,
  38. SHA256,
  39. SHA512,
  40. MD5,
  41. };
  42. struct MultiHashDigestVariant {
  43. constexpr static size_t Size = 0;
  44. MultiHashDigestVariant(SHA1::DigestType digest)
  45. : sha1(digest)
  46. , kind(HashKind::SHA1)
  47. {
  48. }
  49. MultiHashDigestVariant(SHA256::DigestType digest)
  50. : sha256(digest)
  51. , kind(HashKind::SHA256)
  52. {
  53. }
  54. MultiHashDigestVariant(SHA512::DigestType digest)
  55. : sha512(digest)
  56. , kind(HashKind::SHA512)
  57. {
  58. }
  59. MultiHashDigestVariant(MD5::DigestType digest)
  60. : md5(digest)
  61. , kind(HashKind::MD5)
  62. {
  63. }
  64. const u8* immutable_data() const
  65. {
  66. switch (kind) {
  67. case HashKind::MD5:
  68. return md5.value().immutable_data();
  69. case HashKind::SHA1:
  70. return sha1.value().immutable_data();
  71. case HashKind::SHA256:
  72. return sha256.value().immutable_data();
  73. case HashKind::SHA512:
  74. return sha512.value().immutable_data();
  75. default:
  76. case HashKind::None:
  77. ASSERT_NOT_REACHED();
  78. break;
  79. }
  80. }
  81. size_t data_length()
  82. {
  83. switch (kind) {
  84. case HashKind::MD5:
  85. return md5.value().data_length();
  86. case HashKind::SHA1:
  87. return sha1.value().data_length();
  88. case HashKind::SHA256:
  89. return sha256.value().data_length();
  90. case HashKind::SHA512:
  91. return sha512.value().data_length();
  92. default:
  93. case HashKind::None:
  94. ASSERT_NOT_REACHED();
  95. break;
  96. }
  97. }
  98. Optional<SHA1::DigestType> sha1;
  99. Optional<SHA256::DigestType> sha256;
  100. Optional<SHA512::DigestType> sha512;
  101. Optional<MD5::DigestType> md5;
  102. HashKind kind { HashKind::None };
  103. };
  104. class Manager final : public HashFunction<0, MultiHashDigestVariant> {
  105. public:
  106. Manager()
  107. {
  108. m_pre_init_buffer = ByteBuffer::create_zeroed(0);
  109. }
  110. Manager(const Manager& other) // NOT a copy constructor!
  111. {
  112. m_pre_init_buffer = ByteBuffer::create_zeroed(0); // will not be used
  113. initialize(other.m_kind);
  114. }
  115. Manager(HashKind kind)
  116. {
  117. m_pre_init_buffer = ByteBuffer::create_zeroed(0);
  118. initialize(kind);
  119. }
  120. ~Manager()
  121. {
  122. m_sha1 = nullptr;
  123. m_sha256 = nullptr;
  124. m_sha512 = nullptr;
  125. m_md5 = nullptr;
  126. }
  127. virtual void update(const ByteBuffer& buffer) override { update(buffer.data(), buffer.size()); };
  128. virtual void update(const StringView& string) override { update((const u8*)string.characters_without_null_termination(), string.length()); };
  129. inline size_t digest_size() const
  130. {
  131. switch (m_kind) {
  132. case HashKind::MD5:
  133. return m_md5->digest_size();
  134. case HashKind::SHA1:
  135. return m_sha1->digest_size();
  136. case HashKind::SHA256:
  137. return m_sha256->digest_size();
  138. case HashKind::SHA512:
  139. return m_sha512->digest_size();
  140. default:
  141. case HashKind::None:
  142. return 0;
  143. }
  144. }
  145. inline size_t block_size() const
  146. {
  147. switch (m_kind) {
  148. case HashKind::MD5:
  149. return m_md5->block_size();
  150. case HashKind::SHA1:
  151. return m_sha1->block_size();
  152. case HashKind::SHA256:
  153. return m_sha256->block_size();
  154. case HashKind::SHA512:
  155. return m_sha512->block_size();
  156. default:
  157. case HashKind::None:
  158. return 0;
  159. }
  160. }
  161. inline void initialize(HashKind kind)
  162. {
  163. if (m_kind != HashKind::None) {
  164. ASSERT_NOT_REACHED();
  165. }
  166. m_kind = kind;
  167. switch (kind) {
  168. case HashKind::MD5:
  169. m_md5 = make<MD5>();
  170. break;
  171. case HashKind::SHA1:
  172. m_sha1 = make<SHA1>();
  173. break;
  174. case HashKind::SHA256:
  175. m_sha256 = make<SHA256>();
  176. break;
  177. case HashKind::SHA512:
  178. m_sha512 = make<SHA512>();
  179. break;
  180. default:
  181. case HashKind::None:
  182. break;
  183. }
  184. }
  185. virtual void update(const u8* data, size_t length) override
  186. {
  187. auto size = m_pre_init_buffer.size();
  188. switch (m_kind) {
  189. case HashKind::MD5:
  190. if (size)
  191. m_md5->update(m_pre_init_buffer);
  192. m_md5->update(data, length);
  193. break;
  194. case HashKind::SHA1:
  195. if (size)
  196. m_sha1->update(m_pre_init_buffer);
  197. m_sha1->update(data, length);
  198. break;
  199. case HashKind::SHA256:
  200. if (size)
  201. m_sha256->update(m_pre_init_buffer);
  202. m_sha256->update(data, length);
  203. break;
  204. case HashKind::SHA512:
  205. if (size)
  206. m_sha512->update(m_pre_init_buffer);
  207. m_sha512->update(data, length);
  208. break;
  209. default:
  210. case HashKind::None:
  211. m_pre_init_buffer.append(data, length);
  212. return;
  213. }
  214. if (size)
  215. m_pre_init_buffer.clear();
  216. }
  217. virtual DigestType peek() override
  218. {
  219. switch (m_kind) {
  220. case HashKind::MD5:
  221. return { m_md5->peek() };
  222. case HashKind::SHA1:
  223. return { m_sha1->peek() };
  224. case HashKind::SHA256:
  225. return { m_sha256->peek() };
  226. case HashKind::SHA512:
  227. return { m_sha512->peek() };
  228. default:
  229. case HashKind::None:
  230. ASSERT_NOT_REACHED();
  231. break;
  232. }
  233. }
  234. virtual DigestType digest() override
  235. {
  236. auto digest = peek();
  237. reset();
  238. return digest;
  239. }
  240. virtual void reset() override
  241. {
  242. m_pre_init_buffer.clear();
  243. switch (m_kind) {
  244. case HashKind::MD5:
  245. m_md5->reset();
  246. break;
  247. case HashKind::SHA1:
  248. m_sha1->reset();
  249. break;
  250. case HashKind::SHA256:
  251. m_sha256->reset();
  252. break;
  253. case HashKind::SHA512:
  254. m_sha512->reset();
  255. break;
  256. default:
  257. case HashKind::None:
  258. break;
  259. }
  260. }
  261. virtual String class_name() const override
  262. {
  263. switch (m_kind) {
  264. case HashKind::MD5:
  265. return m_md5->class_name();
  266. case HashKind::SHA1:
  267. return m_sha1->class_name();
  268. case HashKind::SHA256:
  269. return m_sha256->class_name();
  270. case HashKind::SHA512:
  271. return m_sha512->class_name();
  272. default:
  273. case HashKind::None:
  274. return "UninitializedHashManager";
  275. }
  276. }
  277. inline bool is(HashKind kind) const
  278. {
  279. return m_kind == kind;
  280. }
  281. private:
  282. OwnPtr<SHA1> m_sha1;
  283. OwnPtr<SHA256> m_sha256;
  284. OwnPtr<SHA512> m_sha512;
  285. OwnPtr<MD5> m_md5;
  286. HashKind m_kind { HashKind::None };
  287. ByteBuffer m_pre_init_buffer;
  288. };
  289. }
  290. }