Skip to content

Commit 0921608

Browse files
committed
LibCrypto: Replace all hashes implementation with OpenSSL
This required multiple changes: - Make hashes non-copiable because they contain a heap allocated pointer - Reference classes via `NonnullOwnPtr` only (they are non-copiable) - Drop all existing hashes implementations - Use the `OpenSSLHashFunction` base class to implement the same hashes I was not able to come up with a way to divide this commit into multiple without increasing the amount of changes. Nothing breaks with this commit!
1 parent 6ebc7d6 commit 0921608

File tree

15 files changed

+164
-1346
lines changed

15 files changed

+164
-1346
lines changed

Libraries/LibCrypto/Authentication/HMAC.h

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,12 @@ class HMAC {
2424
using HashType = HashT;
2525
using TagType = typename HashType::DigestType;
2626

27-
constexpr size_t digest_size() const { return m_inner_hasher.digest_size(); }
27+
size_t digest_size() const { return m_inner_hasher->digest_size(); }
2828

2929
template<typename KeyBufferType, typename... Args>
3030
HMAC(KeyBufferType key, Args... args)
31-
: m_inner_hasher(args...)
32-
, m_outer_hasher(args...)
31+
: m_inner_hasher(move(HashT::create(args...)))
32+
, m_outer_hasher(move(HashT::create(args...)))
3333
{
3434
derive_key(key);
3535
reset();
@@ -44,7 +44,7 @@ class HMAC {
4444

4545
void update(u8 const* message, size_t length)
4646
{
47-
m_inner_hasher.update(message, length);
47+
m_inner_hasher->update(message, length);
4848
}
4949

5050
TagType process(ReadonlyBytes span) { return process(span.data(), span.size()); }
@@ -55,32 +55,32 @@ class HMAC {
5555

5656
TagType digest()
5757
{
58-
m_outer_hasher.update(m_inner_hasher.digest().immutable_data(), m_inner_hasher.digest_size());
59-
auto result = m_outer_hasher.digest();
58+
m_outer_hasher->update(m_inner_hasher->digest().immutable_data(), m_inner_hasher->digest_size());
59+
auto result = m_outer_hasher->digest();
6060
reset();
6161
return result;
6262
}
6363

6464
void reset()
6565
{
66-
m_inner_hasher.reset();
67-
m_outer_hasher.reset();
68-
m_inner_hasher.update(m_key_data, m_inner_hasher.block_size());
69-
m_outer_hasher.update(m_key_data + m_inner_hasher.block_size(), m_outer_hasher.block_size());
66+
m_inner_hasher->reset();
67+
m_outer_hasher->reset();
68+
m_inner_hasher->update(m_key_data, m_inner_hasher->block_size());
69+
m_outer_hasher->update(m_key_data + m_inner_hasher->block_size(), m_outer_hasher->block_size());
7070
}
7171

7272
ByteString class_name() const
7373
{
7474
StringBuilder builder;
7575
builder.append("HMAC-"sv);
76-
builder.append(m_inner_hasher.class_name());
76+
builder.append(m_inner_hasher->class_name());
7777
return builder.to_byte_string();
7878
}
7979

8080
private:
8181
void derive_key(u8 const* key, size_t length)
8282
{
83-
auto block_size = m_inner_hasher.block_size();
83+
auto block_size = m_inner_hasher->block_size();
8484
// Note: The block size of all the current hash functions is 512 bits.
8585
Vector<u8, 64> v_key;
8686
v_key.resize(block_size);
@@ -89,10 +89,10 @@ class HMAC {
8989
// the first few bytes leaves the rest zero, which
9090
// is exactly what we want (zero padding)
9191
if (length > block_size) {
92-
m_inner_hasher.update(key, length);
93-
auto digest = m_inner_hasher.digest();
92+
m_inner_hasher->update(key, length);
93+
auto digest = m_inner_hasher->digest();
9494
// FIXME: should we check if the hash function creates more data than its block size?
95-
key_buffer.overwrite(0, digest.immutable_data(), m_inner_hasher.digest_size());
95+
key_buffer.overwrite(0, digest.immutable_data(), m_inner_hasher->digest_size());
9696
} else if (length > 0) {
9797
key_buffer.overwrite(0, key, length);
9898
}
@@ -110,7 +110,7 @@ class HMAC {
110110
void derive_key(ReadonlyBytes key) { derive_key(key.data(), key.size()); }
111111
void derive_key(StringView key) { derive_key(key.bytes()); }
112112

113-
HashType m_inner_hasher, m_outer_hasher;
113+
NonnullOwnPtr<HashType> m_inner_hasher, m_outer_hasher;
114114
u8 m_key_data[2048];
115115
};
116116

Libraries/LibCrypto/Curves/Ed25519.cpp

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -79,15 +79,15 @@ ErrorOr<ByteBuffer> Ed25519::sign(ReadonlyBytes public_key, ReadonlyBytes privat
7979
memcpy(p, h.data + 32, 32);
8080

8181
// 2. Compute SHA-512(dom2(F, C) || p || PH(M)), where M is the message to be signed.
82-
Crypto::Hash::SHA512 hash;
82+
auto hash = Hash::SHA512::create();
8383
// NOTE: dom2(F, C) is a blank octet string when signing or verifying Ed25519
84-
hash.update(p, 32);
84+
hash->update(p, 32);
8585
// NOTE: PH(M) = M
86-
hash.update(message.data(), message.size());
86+
hash->update(message.data(), message.size());
8787

8888
// Interpret the 64-octet digest as a little-endian integer r.
8989
// For efficiency, do this by first reducing r modulo L, the group order of B.
90-
auto digest = hash.digest();
90+
auto digest = hash->digest();
9191
barrett_reduce(r, digest.data);
9292

9393
// 3. Compute the point [r]B.
@@ -100,13 +100,13 @@ ErrorOr<ByteBuffer> Ed25519::sign(ReadonlyBytes public_key, ReadonlyBytes privat
100100
// 4. Compute SHA512(dom2(F, C) || R || A || PH(M)),
101101
// NOTE: We can reuse hash here, since digest() calls reset()
102102
// NOTE: dom2(F, C) is a blank octet string when signing or verifying Ed25519
103-
hash.update(R.data(), R.size());
103+
hash->update(R.data(), R.size());
104104
// NOTE: A == public_key
105-
hash.update(public_key.data(), public_key.size());
105+
hash->update(public_key.data(), public_key.size());
106106
// NOTE: PH(M) = M
107-
hash.update(message.data(), message.size());
107+
hash->update(message.data(), message.size());
108108

109-
digest = hash.digest();
109+
digest = hash->digest();
110110
// and interpret the 64-octet digest as a little-endian integer k.
111111
memcpy(k, digest.data, 64);
112112

@@ -160,15 +160,15 @@ bool Ed25519::verify(ReadonlyBytes public_key, ReadonlyBytes signature, Readonly
160160
not_valid |= decode_point(&ka, public_key.data());
161161

162162
// 2. Compute SHA512(dom2(F, C) || R || A || PH(M)), and interpret the 64-octet digest as a little-endian integer k.
163-
Crypto::Hash::SHA512 hash;
163+
auto hash = Hash::SHA512::create();
164164
// NOTE: dom2(F, C) is a blank octet string when signing or verifying Ed25519
165-
hash.update(r, half_signature_size);
165+
hash->update(r, half_signature_size);
166166
// NOTE: A == public_key
167-
hash.update(public_key.data(), key_size());
167+
hash->update(public_key.data(), key_size());
168168
// NOTE: PH(M) = M
169-
hash.update(message.data(), message.size());
169+
hash->update(message.data(), message.size());
170170

171-
auto digest = hash.digest();
171+
auto digest = hash->digest();
172172
auto k = digest.data;
173173

174174
// 3. Check the group equation [8][S]B = [8]R + [8][k]A'.

Libraries/LibCrypto/Hash/BLAKE2b.cpp

Lines changed: 0 additions & 126 deletions
This file was deleted.

Libraries/LibCrypto/Hash/BLAKE2b.h

Lines changed: 5 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -7,82 +7,23 @@
77
#pragma once
88

99
#include <AK/ByteString.h>
10-
#include <LibCrypto/Hash/HashFunction.h>
11-
#include <LibCrypto/Hash/SHA2.h>
10+
#include <LibCrypto/Hash/OpenSSLHashFunction.h>
1211

1312
namespace Crypto::Hash {
1413

15-
namespace BLAKE2bConstants {
16-
static constexpr auto blockbytes { 128 };
17-
static constexpr auto hash_length { 64 };
18-
};
14+
class BLAKE2b final : public OpenSSLHashFunction<BLAKE2b, 1024, 512> {
15+
AK_MAKE_NONCOPYABLE(BLAKE2b);
1916

20-
class BLAKE2b final : public HashFunction<1024, 512> {
2117
public:
22-
using HashFunction::update;
23-
24-
BLAKE2b()
18+
BLAKE2b(EVP_MD_CTX* context)
19+
: OpenSSLHashFunction(EVP_blake2b512(), context)
2520
{
26-
reset();
2721
}
2822

29-
virtual void update(u8 const*, size_t) override;
30-
virtual DigestType digest() override;
31-
virtual DigestType peek() override;
32-
33-
static DigestType hash(u8 const* data, size_t length)
34-
{
35-
BLAKE2b blake2b;
36-
blake2b.update(data, length);
37-
return blake2b.digest();
38-
}
39-
40-
static DigestType hash(ByteBuffer const& buffer) { return hash(buffer.data(), buffer.size()); }
41-
static DigestType hash(StringView buffer) { return hash((u8 const*)buffer.characters_without_null_termination(), buffer.length()); }
42-
4323
virtual ByteString class_name() const override
4424
{
4525
return "BLAKE2b";
4626
}
47-
48-
virtual void reset() override
49-
{
50-
m_internal_state = {};
51-
// BLAKE2b uses the same initialization vector as SHA512.
52-
for (size_t i = 0; i < 8; ++i)
53-
m_internal_state.hash_state[i] = SHA512Constants::InitializationHashes[i];
54-
m_internal_state.hash_state[0] ^= 0x01010000 ^ (0 << 8) ^ BLAKE2bConstants::hash_length;
55-
}
56-
57-
private:
58-
static constexpr u8 BLAKE2bSigma[12][16] = {
59-
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
60-
{ 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 },
61-
{ 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 },
62-
{ 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 },
63-
{ 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 },
64-
{ 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 },
65-
{ 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 },
66-
{ 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 },
67-
{ 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 },
68-
{ 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0 },
69-
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
70-
{ 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 }
71-
};
72-
73-
struct BLAKE2bState {
74-
u64 hash_state[8] {};
75-
u64 message_byte_offset[2] {};
76-
u64 is_at_last_block { 0 };
77-
u8 buffer[BLAKE2bConstants::blockbytes] = {};
78-
size_t buffer_length { 0 };
79-
};
80-
81-
BLAKE2bState m_internal_state {};
82-
83-
void mix(u64* work_vector, u64 a, u64 b, u64 c, u64 d, u64 x, u64 y);
84-
void increment_counter_by(u64 const amount);
85-
void transform(u8 const*);
8627
};
8728

8829
};

0 commit comments

Comments
 (0)