HashManager.h 8.4 KB

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