CsCrypto  1.0.1
hash.h
1 /***********************************************************************
2 *
3 * Copyright (c) 2021-2024 Tim van Deurzen
4 * Copyright (c) 2021-2024 Barbara Geller
5 * Copyright (c) 2021-2024 Ansel Sermersheim
6 *
7 * This file is part of CsCrypto.
8 *
9 * CsCrypto is free software, released under the BSD 2-Clause license.
10 * For license details refer to LICENSE provided with this project.
11 *
12 * CsCrypto is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
15 *
16 * https://opensource.org/licenses/BSD-2-Clause
17 *
18 ***********************************************************************/
19 
20 #ifndef CS_CRYPTO_DRIVERS_BOTAN_HASH_H
21 #define CS_CRYPTO_DRIVERS_BOTAN_HASH_H
22 
23 #ifdef CSCRYPTO_HAVE_BOTAN
24 
25 #include <drivers/base/hash.h>
26 #include <util/conversions/byte.h>
27 #include <util/tools/span.h>
28 
29 #include <array>
30 #include <optional>
31 #include <cstddef>
32 #include <type_traits>
33 
34 #include <botan/md4.h>
35 #include <botan/md5.h>
36 #include <botan/sha160.h>
37 #include <botan/sha2_32.h>
38 #include <botan/sha2_64.h>
39 #include <botan/sha3.h>
40 
41 namespace cs_crypto::drivers::botan {
42 
43 template <typename BotanContext, std::size_t SIZE>
44 struct hasher_interface {
45  public:
46  constexpr static const std::size_t digest_size = SIZE;
47 
48  hasher_interface(const hasher_interface & other)
49  {
50  if (this == &other) {
51  return;
52  }
53 
54  this->m_context = other.m_context->copy_state();
55  };
56 
57  hasher_interface &operator=(const hasher_interface & other) &
58  {
59  if (this == &other) {
60  return *this;
61  }
62 
63  hasher_interface tmp = other;
64  std::swap(*this, tmp);
65 
66  return *this;
67  }
68 
69  hasher_interface(hasher_interface &&) = default;
70  hasher_interface &operator=(hasher_interface &&) & = default;
71 
72  static std::optional<hasher_interface> make_context()
73  {
74  auto retval = hasher_interface();
75 
76  if (retval.m_context == nullptr) {
77  return std::nullopt;
78  }
79 
80  return retval;
81  }
82 
83  void update(cs_crypto::util::span<std::byte> bytes) &
84  {
85  m_context->update(cs_crypto::util::from_byte_ptr(bytes.data()), bytes.size());
86  }
87 
88  auto finalize() &&
89  {
90  std::array<std::byte, digest_size> md = {};
91  m_context->final(cs_crypto::util::from_byte_ptr(md.data()));
92 
93  return md;
94  }
95 
96  private:
97  std::unique_ptr<Botan::HashFunction> m_context;
98 
99  hasher_interface()
100  : m_context(std::make_unique<BotanContext>())
101  {
102  }
103 };
104 
105 struct hash : cs_crypto::drivers::basic_hash {
106  using md4 = hasher_interface<Botan::MD4, 16>;
107 
108  using md5 = hasher_interface<Botan::MD5, 16>;
109 
110  using sha1 = hasher_interface<Botan::SHA_160, 20>;
111 
112  using sha2_224 = hasher_interface<Botan::SHA_224, 28>;
113  using sha2_256 = hasher_interface<Botan::SHA_256, 32>;
114  using sha2_384 = hasher_interface<Botan::SHA_384, 48>;
115  using sha2_512 = hasher_interface<Botan::SHA_512, 64>;
116 
117  using sha3_224 = hasher_interface<Botan::SHA_3_224, 28>;
118  using sha3_256 = hasher_interface<Botan::SHA_3_256, 32>;
119  using sha3_384 = hasher_interface<Botan::SHA_3_384, 48>;
120  using sha3_512 = hasher_interface<Botan::SHA_3_512, 64>;
121 };
122 
123 } // namespace cs_crypto::drivers::botan
124 
125 #endif // CSCRYPTO_HAVE_BOTAN
126 
127 #endif