20 #ifndef CS_CRYPTO_DRIVERS_OPENSSL_HASH_H
21 #define CS_CRYPTO_DRIVERS_OPENSSL_HASH_H
23 #ifdef CSCRYPTO_HAVE_OPENSSL
25 #include <drivers/base/hash.h>
26 #include <util/conversions/byte.h>
27 #include <util/tools/crypto_traits.h>
28 #include <util/tools/span.h>
36 #include <openssl/evp.h>
37 #include <openssl/md4.h>
38 #include <openssl/md5.h>
39 #include <openssl/sha.h>
41 namespace cs_crypto::drivers::openssl {
43 template <
typename OpenSSLContext, std::size_t SIZE,
auto doHash_Init,
auto doHash_Update,
auto doHash_Finalize>
44 struct hasher_interface {
46 constexpr static const std::size_t digest_size = SIZE;
48 ~hasher_interface() =
default;
50 hasher_interface(
const hasher_interface &other) =
default;
51 hasher_interface &operator=(
const hasher_interface &other) =
default;
53 hasher_interface(hasher_interface &&other) =
default;
54 hasher_interface &operator=(hasher_interface &&other) =
default;
56 static std::optional<hasher_interface> make_context()
61 if (doHash_Init(&ctx) != 1) {
65 return hasher_interface(std::move(ctx));
68 void update(cs_crypto::util::span<std::byte> bytes) &
71 doHash_Update(&m_context, bytes.data(), bytes.size());
76 std::array<std::byte, digest_size> md{};
79 doHash_Finalize(util::from_byte_ptr(md.data()), &m_context);
85 OpenSSLContext m_context;
87 explicit hasher_interface(OpenSSLContext &&context)
88 : m_context(std::move(context))
93 template <
auto DigestInitFn, std::size_t SIZE>
94 struct keccak_interface {
96 constexpr static const std::size_t digest_size = SIZE;
98 keccak_interface(keccak_interface
const &other)
101 if (
this == &other) {
105 EVP_MD_CTX_copy_ex(
this->m_context.get(), other.m_context.get());
108 ~keccak_interface() =
default;
110 keccak_interface &operator=(keccak_interface
const & other)
113 std::swap(
this->m_context, tmp.m_context);
118 keccak_interface(keccak_interface &&) =
default;
119 keccak_interface &operator=(keccak_interface &&) =
default;
121 static std::optional<keccak_interface> make_context()
123 keccak_interface retval = {};
125 if (retval.m_context ==
nullptr) {
132 void update(cs_crypto::util::span<std::byte> bytes) &
134 EVP_DigestUpdate(m_context.get(), bytes.data(), bytes.size());
139 std::array<std::byte, digest_size> result = {};
142 EVP_DigestFinal_ex(m_context.get(), util::from_byte_ptr(result.data()), &sz);
148 std::unique_ptr<EVP_MD_CTX,
decltype(&::EVP_MD_CTX_free)> m_context;
151 : m_context{EVP_MD_CTX_new(), ::EVP_MD_CTX_free}
153 if (m_context !=
nullptr && EVP_DigestInit_ex(m_context.get(), DigestInitFn(),
nullptr) != 1) {
154 EVP_MD_CTX_free(m_context.get());
160 struct hash : cs_crypto::drivers::basic_hash {
161 using md4 = hasher_interface<MD4_CTX, MD4_DIGEST_LENGTH, MD4_Init, MD4_Update, MD4_Final>;
162 using md5 = hasher_interface<MD5_CTX, MD5_DIGEST_LENGTH, MD5_Init, MD5_Update, MD5_Final>;
164 using sha1 = hasher_interface<SHA_CTX, SHA_DIGEST_LENGTH, SHA1_Init, SHA1_Update, SHA1_Final>;
166 using sha2_224 = hasher_interface<SHA256_CTX, SHA224_DIGEST_LENGTH, SHA224_Init, SHA224_Update, SHA224_Final>;
167 using sha2_256 = hasher_interface<SHA256_CTX, SHA256_DIGEST_LENGTH, SHA256_Init, SHA256_Update, SHA256_Final>;
168 using sha2_384 = hasher_interface<SHA512_CTX, SHA384_DIGEST_LENGTH, SHA384_Init, SHA384_Update, SHA384_Final>;
169 using sha2_512 = hasher_interface<SHA512_CTX, SHA512_DIGEST_LENGTH, SHA512_Init, SHA512_Update, SHA512_Final>;
171 using sha3_224 = keccak_interface<EVP_sha3_224, 28>;
172 using sha3_256 = keccak_interface<EVP_sha3_256, 32>;
173 using sha3_384 = keccak_interface<EVP_sha3_384, 48>;
174 using sha3_512 = keccak_interface<EVP_sha3_512, 64>;