Coverage Report

Created: 2025-08-28 06:26

/src/serenity/Userland/Libraries/LibCrypto/Hash/BLAKE2b.cpp
Line
Count
Source
1
/*
2
 * Copyright (c) 2023, the SerenityOS developers
3
 *
4
 * SPDX-License-Identifier: BSD-2-Clause
5
 */
6
7
#include <AK/ByteReader.h>
8
#include <LibCrypto/Hash/BLAKE2b.h>
9
10
namespace Crypto::Hash {
11
53.7M
constexpr static auto ROTRIGHT(u64 a, size_t b) { return (a >> b) | (a << (64 - b)); }
12
13
void BLAKE2b::update(u8 const* in, size_t inlen)
14
104
{
15
104
    if (inlen > 0) {
16
104
        size_t left = m_internal_state.buffer_length;
17
104
        size_t fill = BLAKE2bConstants::blockbytes - left;
18
104
        if (inlen > fill) {
19
91
            m_internal_state.buffer_length = 0;
20
            // Fill the buffer.
21
91
            __builtin_memcpy(m_internal_state.buffer + left, in, fill);
22
23
91
            increment_counter_by(BLAKE2bConstants::blockbytes);
24
91
            transform(m_internal_state.buffer);
25
91
            in += fill;
26
91
            inlen -= fill;
27
139k
            while (inlen > BLAKE2bConstants::blockbytes) {
28
139k
                increment_counter_by(BLAKE2bConstants::blockbytes);
29
139k
                transform(in);
30
139k
                in += BLAKE2bConstants::blockbytes;
31
139k
                inlen -= BLAKE2bConstants::blockbytes;
32
139k
            }
33
91
        }
34
104
        __builtin_memcpy(m_internal_state.buffer + m_internal_state.buffer_length, in, inlen);
35
104
        m_internal_state.buffer_length += inlen;
36
104
    }
37
104
}
38
39
BLAKE2b::DigestType BLAKE2b::peek()
40
104
{
41
104
    DigestType digest;
42
104
    increment_counter_by(m_internal_state.buffer_length);
43
44
    // Set this as the last block
45
104
    m_internal_state.is_at_last_block = UINT64_MAX;
46
47
    // Pad the buffer with zeros
48
104
    __builtin_memset(m_internal_state.buffer + m_internal_state.buffer_length, 0, BLAKE2bConstants::blockbytes - m_internal_state.buffer_length);
49
104
    transform(m_internal_state.buffer);
50
51
936
    for (size_t i = 0; i < 8; ++i)
52
832
        __builtin_memcpy(&digest.data[0] + sizeof(m_internal_state.hash_state[i]) * i, &m_internal_state.hash_state[i], sizeof(m_internal_state.hash_state[i]));
53
54
104
    return digest;
55
104
}
56
57
BLAKE2b::DigestType BLAKE2b::digest()
58
104
{
59
104
    auto digest = peek();
60
104
    reset();
61
104
    return digest;
62
104
}
63
64
void BLAKE2b::increment_counter_by(u64 const amount)
65
139k
{
66
139k
    m_internal_state.message_byte_offset[0] += amount;
67
139k
    m_internal_state.message_byte_offset[1] += (m_internal_state.message_byte_offset[0] < amount);
68
139k
}
69
70
void BLAKE2b::mix(u64* work_array, u64 a, u64 b, u64 c, u64 d, u64 x, u64 y)
71
13.4M
{
72
13.4M
    constexpr auto rotation_constant_1 = 32;
73
13.4M
    constexpr auto rotation_constant_2 = 24;
74
13.4M
    constexpr auto rotation_constant_3 = 16;
75
13.4M
    constexpr auto rotation_constant_4 = 63;
76
77
13.4M
    work_array[a] = work_array[a] + work_array[b] + x;
78
13.4M
    work_array[d] = ROTRIGHT(work_array[d] ^ work_array[a], rotation_constant_1);
79
13.4M
    work_array[c] = work_array[c] + work_array[d];
80
13.4M
    work_array[b] = ROTRIGHT(work_array[b] ^ work_array[c], rotation_constant_2);
81
13.4M
    work_array[a] = work_array[a] + work_array[b] + y;
82
13.4M
    work_array[d] = ROTRIGHT(work_array[d] ^ work_array[a], rotation_constant_3);
83
13.4M
    work_array[c] = work_array[c] + work_array[d];
84
13.4M
    work_array[b] = ROTRIGHT(work_array[b] ^ work_array[c], rotation_constant_4);
85
13.4M
}
86
87
void BLAKE2b::transform(u8 const* block)
88
139k
{
89
139k
    u64 m[16];
90
139k
    u64 v[16];
91
92
2.37M
    for (size_t i = 0; i < 16; ++i)
93
2.23M
        m[i] = ByteReader::load64(block + i * sizeof(m[i]));
94
95
1.25M
    for (size_t i = 0; i < 8; ++i)
96
1.11M
        v[i] = m_internal_state.hash_state[i];
97
98
139k
    v[8] = SHA512Constants::InitializationHashes[0];
99
139k
    v[9] = SHA512Constants::InitializationHashes[1];
100
139k
    v[10] = SHA512Constants::InitializationHashes[2];
101
139k
    v[11] = SHA512Constants::InitializationHashes[3];
102
139k
    v[12] = SHA512Constants::InitializationHashes[4] ^ m_internal_state.message_byte_offset[0];
103
139k
    v[13] = SHA512Constants::InitializationHashes[5] ^ m_internal_state.message_byte_offset[1];
104
139k
    v[14] = SHA512Constants::InitializationHashes[6] ^ m_internal_state.is_at_last_block;
105
139k
    v[15] = SHA512Constants::InitializationHashes[7];
106
107
1.81M
    for (size_t i = 0; i < 12; ++i) {
108
1.67M
        u64 sigma_selection[16];
109
28.5M
        for (size_t j = 0; j < 16; ++j)
110
26.8M
            sigma_selection[j] = BLAKE2bSigma[i % 10][j];
111
1.67M
        mix(v, 0, 4, 8, 12, m[sigma_selection[0]], m[sigma_selection[1]]);
112
1.67M
        mix(v, 1, 5, 9, 13, m[sigma_selection[2]], m[sigma_selection[3]]);
113
1.67M
        mix(v, 2, 6, 10, 14, m[sigma_selection[4]], m[sigma_selection[5]]);
114
1.67M
        mix(v, 3, 7, 11, 15, m[sigma_selection[6]], m[sigma_selection[7]]);
115
116
1.67M
        mix(v, 0, 5, 10, 15, m[sigma_selection[8]], m[sigma_selection[9]]);
117
1.67M
        mix(v, 1, 6, 11, 12, m[sigma_selection[10]], m[sigma_selection[11]]);
118
1.67M
        mix(v, 2, 7, 8, 13, m[sigma_selection[12]], m[sigma_selection[13]]);
119
1.67M
        mix(v, 3, 4, 9, 14, m[sigma_selection[14]], m[sigma_selection[15]]);
120
1.67M
    }
121
122
1.25M
    for (size_t i = 0; i < 8; ++i)
123
1.11M
        m_internal_state.hash_state[i] = m_internal_state.hash_state[i] ^ v[i] ^ v[i + 8];
124
139k
}
125
126
}