Coverage Report

Created: 2023-12-08 07:00

/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>) const
Unexecuted 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>) const
Unexecuted 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) const
Unexecuted 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