/src/botan/build/include/botan/internal/keccak_helpers.h
Line  | Count  | Source (jump to first uncovered line)  | 
1  |  | /*  | 
2  |  |  * Helper functions to implement Keccak-derived functions from NIST SP.800-185  | 
3  |  |  * (C) 2023 Jack Lloyd  | 
4  |  |  * (C) 2023 René Meusel - Rohde & Schwarz Cybersecurity  | 
5  |  |  *  | 
6  |  |  * Botan is released under the Simplified BSD License (see license.txt)  | 
7  |  |  */  | 
8  |  |  | 
9  |  | #ifndef BOTAN_KECCAK_HELPERS_H_  | 
10  |  | #define BOTAN_KECCAK_HELPERS_H_  | 
11  |  |  | 
12  |  | #include <array>  | 
13  |  | #include <cstdint>  | 
14  |  | #include <span>  | 
15  |  |  | 
16  |  | #include <botan/assert.h>  | 
17  |  | #include <botan/concepts.h>  | 
18  |  |  | 
19  |  | namespace Botan { | 
20  |  |  | 
21  |  | /**  | 
22  |  |  * Integer encoding defined in NIST SP.800-185 that can be unambiguously  | 
23  |  |  * parsed from the beginning of the string.  | 
24  |  |  *  | 
25  |  |  * This function does not allocate any memory and requires the caller to  | 
26  |  |  * provide a sufficiently large @p buffer. For a given @p x, this will  | 
27  |  |  * need exactly keccak_int_encoding_size() bytes. For an arbitrary @p x  | 
28  |  |  * it will generate keccak_max_int_encoding_size() bytes at most.  | 
29  |  |  *  | 
30  |  |  * @param buffer  buffer to write the left-encoding of @p x to.  | 
31  |  |  *                It is assumed that the buffer will hold at least  | 
32  |  |  *                keccak_int_encoding_size() bytes.  | 
33  |  |  * @param x       the integer to be left-encoded  | 
34  |  |  * @return        the byte span that represents the bytes written to @p buffer.  | 
35  |  |  */  | 
36  |  | BOTAN_TEST_API std::span<const uint8_t> keccak_int_left_encode(std::span<uint8_t> buffer, size_t x);  | 
37  |  |  | 
38  |  | /**  | 
39  |  |  * Integer encoding defined in NIST SP.800-185 that can be unambiguously  | 
40  |  |  * parsed from the end of the string.  | 
41  |  |  *  | 
42  |  |  * This function does not allocate any memory and requires the caller to  | 
43  |  |  * provide a sufficiently large @p buffer. For a given @p x, this will  | 
44  |  |  * need exactly keccak_int_encoding_size() bytes. For an arbitrary @p x  | 
45  |  |  * it will generate keccak_max_int_encoding_size() bytes at most.  | 
46  |  |  *  | 
47  |  |  * @param out  buffer to write the right-encoding of @p x to.  | 
48  |  |  *             It is assumed that the buffer will hold at least  | 
49  |  |  *             keccak_int_encoding_size() bytes.  | 
50  |  |  * @param x    the integer to be right-encoded  | 
51  |  |  * @return     the byte span that represents the bytes written to @p buffer.  | 
52  |  |  */  | 
53  |  | BOTAN_TEST_API std::span<const uint8_t> keccak_int_right_encode(std::span<uint8_t> out, size_t x);  | 
54  |  |  | 
55  |  | /**  | 
56  |  |  * @returns the required bytes for encodings of keccak_int_left_encode() or  | 
57  |  |  *          keccak_int_right_encode() given an integer @p x  | 
58  |  |  */  | 
59  |  | BOTAN_TEST_API size_t keccak_int_encoding_size(size_t x);  | 
60  |  |  | 
61  |  | /**  | 
62  |  |  * @returns the maximum required bytes for encodings of keccak_int_left_encode() or  | 
63  |  |  *          keccak_int_right_encode()  | 
64  |  |  */  | 
65  | 0  | constexpr size_t keccak_max_int_encoding_size() { | 
66  | 0  |    return sizeof(size_t) + 1 /* the length tag */;  | 
67  | 0  | }  | 
68  |  |  | 
69  |  | template <typename T>  | 
70  |  | concept updatable_object = requires(T& a, std::span<const uint8_t> span) { a.update(span); }; | 
71  |  |  | 
72  |  | template <typename T>  | 
73  |  | concept appendable_object = requires(T& a, std::span<const uint8_t> s) { a.insert(a.end(), s.begin(), s.end()); }; | 
74  |  |  | 
75  |  | template <typename T>  | 
76  |  | concept absorbing_object = updatable_object<T> || appendable_object<T>;  | 
77  |  |  | 
78  |  | /**  | 
79  |  |  * This is a combination of the functions encode_string() and bytepad() defined  | 
80  |  |  * in NIST SP.800-185 Section 2.3. Additionally, the result is directly streamed  | 
81  |  |  * into the provided XOF to avoid unneccessary memory allocation or a byte vector.  | 
82  |  |  *  | 
83  |  |  * @param sink         the XOF or byte vector to absorb the @p byte_strings into  | 
84  |  |  * @param padding_mod  the modulus value to create a padding for (NIST calls this 'w')  | 
85  |  |  * @param byte_strings a variable-length list of byte strings to be encoded and  | 
86  |  |  *                     absorbed into the given @p xof  | 
87  |  |  * @returns the number of bytes absorbed into the @p xof  | 
88  |  |  */  | 
89  |  | template <absorbing_object T, typename... Ts>  | 
90  |  |    requires(concepts::constructible_from<std::span<const uint8_t>, Ts> && ...)  | 
91  | 0  | size_t keccak_absorb_padded_strings_encoding(T& sink, size_t padding_mod, Ts... byte_strings) { | 
92  | 0  |    BOTAN_ASSERT_NOMSG(padding_mod > 0);  | 
93  |  |  | 
94  |  |    // used as temporary storage for all integer encodings in this function  | 
95  | 0  |    std::array<uint8_t, keccak_max_int_encoding_size()> int_encoding_buffer;  | 
96  |  |  | 
97  |  |    // absorbs byte strings and counts the number of absorbed bytes  | 
98  | 0  |    size_t bytes_absorbed = 0;  | 
99  | 0  |    auto absorb = [&](std::span<const uint8_t> bytes) { | 
100  | 0  |       if constexpr(updatable_object<T>) { | 
101  | 0  |          sink.update(bytes);  | 
102  | 0  |       } else if constexpr(appendable_object<T>) { | 
103  | 0  |          sink.insert(sink.end(), bytes.begin(), bytes.end());  | 
104  | 0  |       }  | 
105  | 0  |       bytes_absorbed += bytes.size();  | 
106  | 0  |    }; Unexecuted instantiation: Botan::keccak_absorb_padded_strings_encoding<std::__1::vector<unsigned char, Botan::secure_allocator<unsigned char> >, std::__1::span<unsigned char const, 18446744073709551615ul> >(std::__1::vector<unsigned char, Botan::secure_allocator<unsigned char> >&, unsigned long, std::__1::span<unsigned char const, 18446744073709551615ul>)::{lambda(std::__1::span<unsigned char const, 18446744073709551615ul>)#1}::operator()(std::__1::span<unsigned char const, 18446744073709551615ul>) constUnexecuted instantiation: Botan::keccak_absorb_padded_strings_encoding<Botan::cSHAKE_XOF, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >, std::__1::span<unsigned char const, 18446744073709551615ul> >(Botan::cSHAKE_XOF&, unsigned long, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >, std::__1::span<unsigned char const, 18446744073709551615ul>)::{lambda(std::__1::span<unsigned char const, 18446744073709551615ul>)#1}::operator()(std::__1::span<unsigned char const, 18446744073709551615ul>) const | 
107  |  |  | 
108  |  |    // encodes a given string and absorbs it into the XOF straight away  | 
109  | 0  |    auto encode_string_and_absorb = [&](std::span<const uint8_t> bytes) { | 
110  | 0  |       absorb(keccak_int_left_encode(int_encoding_buffer, bytes.size() * 8));  | 
111  | 0  |       absorb(bytes);  | 
112  | 0  |    }; Unexecuted instantiation: Botan::keccak_absorb_padded_strings_encoding<std::__1::vector<unsigned char, Botan::secure_allocator<unsigned char> >, std::__1::span<unsigned char const, 18446744073709551615ul> >(std::__1::vector<unsigned char, Botan::secure_allocator<unsigned char> >&, unsigned long, std::__1::span<unsigned char const, 18446744073709551615ul>)::{lambda(std::__1::span<unsigned char const, 18446744073709551615ul>)#2}::operator()(std::__1::span<unsigned char const, 18446744073709551615ul>) constUnexecuted instantiation: Botan::keccak_absorb_padded_strings_encoding<Botan::cSHAKE_XOF, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >, std::__1::span<unsigned char const, 18446744073709551615ul> >(Botan::cSHAKE_XOF&, unsigned long, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >, std::__1::span<unsigned char const, 18446744073709551615ul>)::{lambda(std::__1::span<unsigned char const, 18446744073709551615ul>)#2}::operator()(std::__1::span<unsigned char const, 18446744073709551615ul>) const | 
113  |  |  | 
114  |  |    // absorbs as many zero-bytes as requested into the XOF  | 
115  | 0  |    auto absorb_padding = [&](size_t padding_bytes) { | 
116  | 0  |       for(size_t i = 0; i < padding_bytes; ++i) { | 
117  | 0  |          const uint8_t zero_byte = 0;  | 
118  | 0  |          absorb({&zero_byte, 1}); | 
119  | 0  |       }  | 
120  | 0  |    }; Unexecuted instantiation: Botan::keccak_absorb_padded_strings_encoding<std::__1::vector<unsigned char, Botan::secure_allocator<unsigned char> >, std::__1::span<unsigned char const, 18446744073709551615ul> >(std::__1::vector<unsigned char, Botan::secure_allocator<unsigned char> >&, unsigned long, std::__1::span<unsigned char const, 18446744073709551615ul>)::{lambda(unsigned long)#1}::operator()(unsigned long) constUnexecuted instantiation: Botan::keccak_absorb_padded_strings_encoding<Botan::cSHAKE_XOF, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >, std::__1::span<unsigned char const, 18446744073709551615ul> >(Botan::cSHAKE_XOF&, unsigned long, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >, std::__1::span<unsigned char const, 18446744073709551615ul>)::{lambda(unsigned long)#1}::operator()(unsigned long) const | 
121  |  |  | 
122  |  |    // implementation of bytepad(encode_string(Ts) || ...) that absorbs the result  | 
123  |  |    // staight into the given xof  | 
124  | 0  |    absorb(keccak_int_left_encode(int_encoding_buffer, padding_mod));  | 
125  | 0  |    (encode_string_and_absorb(byte_strings), ...);  | 
126  | 0  |    absorb_padding(padding_mod - (bytes_absorbed % padding_mod));  | 
127  |  | 
  | 
128  | 0  |    return bytes_absorbed;  | 
129  | 0  | } Unexecuted instantiation: unsigned long Botan::keccak_absorb_padded_strings_encoding<std::__1::vector<unsigned char, Botan::secure_allocator<unsigned char> >, std::__1::span<unsigned char const, 18446744073709551615ul> >(std::__1::vector<unsigned char, Botan::secure_allocator<unsigned char> >&, unsigned long, std::__1::span<unsigned char const, 18446744073709551615ul>) Unexecuted instantiation: unsigned long Botan::keccak_absorb_padded_strings_encoding<Botan::cSHAKE_XOF, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >, std::__1::span<unsigned char const, 18446744073709551615ul> >(Botan::cSHAKE_XOF&, unsigned long, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >, std::__1::span<unsigned char const, 18446744073709551615ul>)  | 
130  |  |  | 
131  |  | }  // namespace Botan  | 
132  |  |  | 
133  |  | #endif  |