Coverage Report

Created: 2025-03-04 07:22

/src/serenity/Userland/Libraries/LibCrypto/Hash/MGF.h
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright (c) 2024, stelar7 <dudedbz@gmail.com>
3
 *
4
 * SPDX-License-Identifier: BSD-2-Clause
5
 */
6
7
#pragma once
8
9
#include <AK/ByteBuffer.h>
10
#include <AK/ByteReader.h>
11
#include <AK/Endian.h>
12
13
namespace Crypto::Hash {
14
15
class MGF {
16
public:
17
    // https://datatracker.ietf.org/doc/html/rfc2437#section-10.2.1
18
    template<typename HashFunction>
19
    static ErrorOr<ByteBuffer> mgf1(ReadonlyBytes seed, size_t length)
20
    requires requires { HashFunction::digest_size(); }
21
0
    {
22
0
        HashFunction hash;
23
24
0
        size_t h_len = hash.digest_size();
25
26
        // 1. If length > 2^32(hLen), output "mask too long" and stop.
27
        if constexpr (sizeof(size_t) > 32) {
28
            if (length > (h_len << 32))
29
                return Error::from_string_literal("mask too long");
30
        }
31
32
        // 2. Let T be the empty octet string.
33
0
        auto t = TRY(ByteBuffer::create_uninitialized(0));
34
35
        // 3. For counter from 0 to ceil(length / hLen) - 1, do the following:
36
0
        auto counter = 0u;
37
0
        auto iterations = AK::ceil_div(length, h_len) - 1;
38
39
0
        auto c = TRY(ByteBuffer::create_uninitialized(4));
40
0
        for (; counter <= iterations; ++counter) {
41
            // a. Convert counter to an octet string C of length 4 with the primitive I2OSP: C = I2OSP(counter, 4)
42
0
            ByteReader::store(static_cast<u8*>(c.data()), AK::convert_between_host_and_big_endian(static_cast<u32>(counter)));
43
44
            // b. Concatenate the hash of the seed Z and C to the octet string T: T = T || Hash (Z || C)
45
0
            hash.update(seed);
46
0
            hash.update(c);
47
0
            auto digest = hash.digest();
48
49
0
            TRY(t.try_append(digest.bytes()));
50
0
        }
51
52
        // 4. Output the leading l octets of T as the octet string mask.
53
0
        return t.slice(0, length);
54
0
    }
Unexecuted instantiation: _ZN6Crypto4Hash3MGF4mgf1INS0_4SHA1EEEN2AK7ErrorOrINS4_6Detail10ByteBufferILm32EEENS4_5ErrorEEENS4_4SpanIKhEEmQrqXclsrT_11digest_sizeEE
Unexecuted instantiation: _ZN6Crypto4Hash3MGF4mgf1INS0_6SHA256EEEN2AK7ErrorOrINS4_6Detail10ByteBufferILm32EEENS4_5ErrorEEENS4_4SpanIKhEEmQrqXclsrT_11digest_sizeEE
Unexecuted instantiation: _ZN6Crypto4Hash3MGF4mgf1INS0_6SHA384EEEN2AK7ErrorOrINS4_6Detail10ByteBufferILm32EEENS4_5ErrorEEENS4_4SpanIKhEEmQrqXclsrT_11digest_sizeEE
Unexecuted instantiation: _ZN6Crypto4Hash3MGF4mgf1INS0_6SHA512EEEN2AK7ErrorOrINS4_6Detail10ByteBufferILm32EEENS4_5ErrorEEENS4_4SpanIKhEEmQrqXclsrT_11digest_sizeEE
55
};
56
57
}