diff --git a/Libraries/LibCrypto/Hash/OpenSSLHashFunction.h b/Libraries/LibCrypto/Hash/OpenSSLHashFunction.h new file mode 100644 index 00000000000..903b51502b3 --- /dev/null +++ b/Libraries/LibCrypto/Hash/OpenSSLHashFunction.h @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2024, Altomani Gianluca + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include +#include +#include +#include + +#include + +namespace Crypto::Hash { + +template> +class OpenSSLHashFunction : public HashFunction { + AK_MAKE_NONCOPYABLE(OpenSSLHashFunction); + +public: + using HashFunction::update; + + static NonnullOwnPtr create() + { + auto* context = EVP_MD_CTX_new(); + return make(context); + } + + OpenSSLHashFunction(EVP_MD const* type, EVP_MD_CTX* context) + : m_type(type) + , m_context(context) + { + OpenSSLHashFunction::reset(); + } + + virtual ~OpenSSLHashFunction() override + { + EVP_MD_CTX_free(m_context); + } + + virtual ByteString class_name() const override = 0; + + void update(u8 const* input, size_t length) override + { + if (EVP_DigestUpdate(m_context, input, length) != 1) { + VERIFY_NOT_REACHED(); + } + } + + DigestT digest() override + { + DigestT digest; + if (EVP_DigestFinal_ex(m_context, digest.data, nullptr) != 1) { + VERIFY_NOT_REACHED(); + } + + reset(); + return digest; + } + + DigestT peek() override + { + auto c = copy(); + return c->digest(); + } + + void reset() override + { + if (EVP_DigestInit_ex(m_context, m_type, nullptr) != 1) { + VERIFY_NOT_REACHED(); + } + } + + virtual NonnullOwnPtr copy() const + { + auto context = create(); + if (EVP_MD_CTX_copy_ex(context->m_context, m_context) != 1) { + VERIFY_NOT_REACHED(); + } + + return context; + } + + static DigestT hash(u8 const* data, size_t length) + { + auto hasher = create(); + hasher->update(data, length); + return hasher->digest(); + } + + static DigestT hash(ByteBuffer const& buffer) { return hash(buffer.data(), buffer.size()); } + static DigestT hash(StringView buffer) { return hash(reinterpret_cast(buffer.characters_without_null_termination()), buffer.length()); } + +private: + EVP_MD const* m_type; + EVP_MD_CTX* m_context; +}; + +}