/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 | | } |