Skip to content

Commit 6ebc7d6

Browse files
committed
LibCrypto: Introduce utility class for OpenSSL backed hashes
This abstract class allows implementing hashes backed by OpenSSL with very few lines of code, see next commit.
1 parent 199c663 commit 6ebc7d6

File tree

1 file changed

+101
-0
lines changed

1 file changed

+101
-0
lines changed
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
/*
2+
* Copyright (c) 2024, Altomani Gianluca <altomanigianluca@gmail.com>
3+
*
4+
* SPDX-License-Identifier: BSD-2-Clause
5+
*/
6+
7+
#pragma once
8+
9+
#include <AK/ByteString.h>
10+
#include <AK/NonnullOwnPtr.h>
11+
#include <AK/Types.h>
12+
#include <LibCrypto/Hash/HashFunction.h>
13+
14+
#include <openssl/evp.h>
15+
16+
namespace Crypto::Hash {
17+
18+
template<typename T, size_t BlockS, size_t DigestS, typename DigestT = Digest<DigestS>>
19+
class OpenSSLHashFunction : public HashFunction<BlockS, DigestS, DigestT> {
20+
AK_MAKE_NONCOPYABLE(OpenSSLHashFunction);
21+
22+
public:
23+
using HashFunction<BlockS, DigestS, DigestT>::update;
24+
25+
static NonnullOwnPtr<T> create()
26+
{
27+
auto* context = EVP_MD_CTX_new();
28+
return make<T>(context);
29+
}
30+
31+
explicit OpenSSLHashFunction(EVP_MD const* type, EVP_MD_CTX* context)
32+
: m_type(type)
33+
, m_context(context)
34+
{
35+
OpenSSLHashFunction::reset();
36+
}
37+
38+
virtual ~OpenSSLHashFunction() override
39+
{
40+
EVP_MD_CTX_free(m_context);
41+
}
42+
43+
virtual ByteString class_name() const override = 0;
44+
45+
void update(u8 const* input, size_t length) override
46+
{
47+
if (EVP_DigestUpdate(m_context, input, length) != 1) {
48+
VERIFY_NOT_REACHED();
49+
}
50+
}
51+
52+
DigestT digest() override
53+
{
54+
DigestT digest;
55+
if (EVP_DigestFinal_ex(m_context, digest.data, nullptr) != 1) {
56+
VERIFY_NOT_REACHED();
57+
}
58+
59+
reset();
60+
return digest;
61+
}
62+
63+
DigestT peek() override
64+
{
65+
auto c = copy();
66+
return c->digest();
67+
}
68+
69+
void reset() override
70+
{
71+
if (EVP_DigestInit_ex(m_context, m_type, nullptr) != 1) {
72+
VERIFY_NOT_REACHED();
73+
}
74+
}
75+
76+
virtual NonnullOwnPtr<T> copy() const
77+
{
78+
auto context = create();
79+
if (EVP_MD_CTX_copy_ex(context->m_context, m_context) != 1) {
80+
VERIFY_NOT_REACHED();
81+
}
82+
83+
return context;
84+
}
85+
86+
static DigestT hash(u8 const* data, size_t length)
87+
{
88+
auto hasher = create();
89+
hasher->update(data, length);
90+
return hasher->digest();
91+
}
92+
93+
static DigestT hash(ByteBuffer const& buffer) { return hash(buffer.data(), buffer.size()); }
94+
static DigestT hash(StringView buffer) { return hash(reinterpret_cast<u8 const*>(buffer.characters_without_null_termination()), buffer.length()); }
95+
96+
private:
97+
EVP_MD const* m_type;
98+
EVP_MD_CTX* m_context;
99+
};
100+
101+
}

0 commit comments

Comments
 (0)