/src/botan/build/include/internal/botan/internal/pqcrystals_encoding.h
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * PQ CRYSTALS Encoding Helpers |
3 | | * |
4 | | * Further changes |
5 | | * (C) 2024 Jack Lloyd |
6 | | * (C) 2024 René Meusel, Rohde & Schwarz Cybersecurity |
7 | | * |
8 | | * Botan is released under the Simplified BSD License (see license.txt) |
9 | | */ |
10 | | |
11 | | #ifndef BOTAN_PQ_CRYSTALS_ENCODING_H_ |
12 | | #define BOTAN_PQ_CRYSTALS_ENCODING_H_ |
13 | | |
14 | | #include <limits> |
15 | | #include <numeric> |
16 | | #include <span> |
17 | | |
18 | | #include <botan/internal/loadstor.h> |
19 | | #include <botan/internal/pqcrystals.h> |
20 | | #include <botan/internal/pqcrystals_helpers.h> |
21 | | #include <botan/internal/stl_util.h> |
22 | | |
23 | | #if defined(BOTAN_HAS_XOF) |
24 | | #include <botan/xof.h> |
25 | | #endif |
26 | | namespace Botan::CRYSTALS { |
27 | | |
28 | | namespace detail { |
29 | | |
30 | 0 | constexpr auto as_byte_source(BufferSlicer& slicer) { |
31 | 0 | return [&](std::span<uint8_t> out) { slicer.copy_into(out); }; |
32 | 0 | } |
33 | | |
34 | | #if defined(BOTAN_HAS_XOF) |
35 | 0 | constexpr auto as_byte_source(Botan::XOF& xof) { |
36 | 0 | return [&](std::span<uint8_t> out) { xof.output(out); }; |
37 | 0 | } |
38 | | #endif |
39 | | |
40 | | } // namespace detail |
41 | | |
42 | | template <typename T> |
43 | | concept byte_source = |
44 | | requires(T& t) { requires std::invocable<decltype(detail::as_byte_source(t)), std::span<uint8_t>>; }; |
45 | | |
46 | | template <typename T, typename PolyCoeffT> |
47 | | concept coeff_map_fn = std::signed_integral<PolyCoeffT> && requires(T fn, PolyCoeffT coeff) { |
48 | | { fn(coeff) } -> std::same_as<std::make_unsigned_t<PolyCoeffT>>; |
49 | | }; |
50 | | |
51 | | template <typename T, typename PolyCoeffT> |
52 | | concept coeff_unmap_fn = |
53 | | std::signed_integral<PolyCoeffT> && requires(T fn, std::make_unsigned_t<PolyCoeffT> coeff_value) { |
54 | | { fn(coeff_value) } -> std::same_as<PolyCoeffT>; |
55 | | }; |
56 | | |
57 | | /** |
58 | | * Helper for base implementations of NIST FIPS 204, Algorithms 16-19 and |
59 | | * NIST FIPS 203 Algorithms 5-6. It pre-computes generic values to bit-(un)pack |
60 | | * polynomial coefficients at compile-time. |
61 | | * |
62 | | * The base implementations are also templated with the @p range parameter |
63 | | * forcing the compiler to generate specialized code for each supported range. |
64 | | */ |
65 | | template <int32_t range, crystals_trait PolyTrait> |
66 | | struct BitPackingTrait final { |
67 | | using T = typename PolyTrait::T; |
68 | | using unsigned_T = std::make_unsigned_t<T>; |
69 | | using sink_t = uint64_t; |
70 | | |
71 | | static_assert(range <= std::numeric_limits<T>::max()); |
72 | | |
73 | | constexpr static size_t bits_in_collector = sizeof(sink_t) * 8; |
74 | | constexpr static size_t bits_per_coeff = bitlen(range); |
75 | | constexpr static size_t bits_per_pack = [] { |
76 | | // Ensure that the bit-packing is byte-aligned and scale it |
77 | | // to utilize the collector's bit-width as much as possible. |
78 | | size_t smallest_aligned_pack = std::lcm(bits_per_coeff, size_t(8)); |
79 | | return (smallest_aligned_pack < bits_in_collector) |
80 | | ? (bits_in_collector / smallest_aligned_pack) * smallest_aligned_pack |
81 | | : smallest_aligned_pack; |
82 | | }(); |
83 | | constexpr static size_t bytes_per_pack = bits_per_pack / 8; |
84 | | constexpr static size_t coeffs_per_pack = bits_per_pack / bits_per_coeff; |
85 | | constexpr static size_t collectors_per_pack = (bytes_per_pack + sizeof(sink_t) - 1) / sizeof(sink_t); |
86 | | constexpr static size_t collector_bytes_per_pack = collectors_per_pack * sizeof(sink_t); |
87 | | constexpr static sink_t value_mask = (1 << bits_per_coeff) - 1; |
88 | | |
89 | | using collector_array = std::array<sink_t, collectors_per_pack>; |
90 | | using collector_bytearray = std::array<uint8_t, collector_bytes_per_pack>; |
91 | | |
92 | | static_assert(PolyTrait::N % coeffs_per_pack == 0); |
93 | | }; |
94 | | |
95 | | /** |
96 | | * Base implementation of NIST FIPS 203 Algorithm 5 (ByteEncode) and NIST |
97 | | * FIPS 204 Algorithms 16 (SimpleBitPack) and 17 (BitPack). |
98 | | * |
99 | | * This takes a polynomial @p p and packs its coefficients into the buffer |
100 | | * represented by @p stuffer. Optionally, the coefficients can be transformed |
101 | | * using the @p map function before packing them. Kyber uses @p map to compress |
102 | | * the coefficients as needed, Dilithium to transform coefficients to unsigned. |
103 | | * |
104 | | * The implementation assumes that the values returned from the custom @p map |
105 | | * transformation are in the range [0, range]. No assumption is made about the |
106 | | * value range of the coefficients in the polynomial @p p. |
107 | | * |
108 | | * Note that this bit-packing algorithm is inefficient if the bit-length of the |
109 | | * coefficients is a multiple of 8. In that case, a byte-level encoding (that |
110 | | * might need to take endianess into account) would be more efficient. However, |
111 | | * neither Kyber nor Dilithium instantiate bit-packings with such a value range. |
112 | | * |
113 | | * @tparam range the upper bound of the coefficient range. |
114 | | */ |
115 | | template <int32_t range, crystals_trait PolyTrait, Domain D, coeff_map_fn<typename PolyTrait::T> MapFnT> |
116 | 0 | constexpr void pack(const Polynomial<PolyTrait, D>& p, BufferStuffer& stuffer, MapFnT map) { |
117 | 0 | using trait = BitPackingTrait<range, PolyTrait>; |
118 | |
|
119 | 0 | BOTAN_DEBUG_ASSERT(stuffer.remaining_capacity() >= p.size() * trait::bits_per_coeff / 8); |
120 | | |
121 | | // Bit-packing example that shows a coefficients' bit-pack that spills across |
122 | | // more than one 64-bit collectors. This illustrates the algorithm below. |
123 | | // |
124 | | // 0 64 128 |
125 | | // Collectors (64 bits): | collectors[0] | collectors[1] | |
126 | | // | | | |
127 | | // Coefficients (11 bits): | c[0] | c[1] | c[2] | c[3] | c[4] | c[5] | c[6] | c[7] | | | | | ... |
128 | | // | | | |
129 | | // | < byte-aligned coefficient pack > | < byte-aligned pad. > | |
130 | | // | (one inner loop iteration) | |
131 | | // 0 88 (divisible by 8) |
132 | |
|
133 | 0 | for(size_t i = 0; i < p.size(); i += trait::coeffs_per_pack) { |
134 | | // The collectors array is filled with bit-packed coefficients to produce |
135 | | // a byte-aligned pack of coefficients. When coefficients fall onto the |
136 | | // boundary of two collectors, their bits must be split. |
137 | 0 | typename trait::collector_array collectors = {0}; |
138 | 0 | for(size_t j = 0, bit_offset = 0, c = 0; j < trait::coeffs_per_pack; ++j) { |
139 | | // Transform p[i] via a custom map function (that may be a NOOP). |
140 | 0 | const typename trait::unsigned_T mapped_coeff = map(p[i + j]); |
141 | 0 | const auto coeff_value = static_cast<typename trait::sink_t>(mapped_coeff); |
142 | | |
143 | | // pack() is called only on data produced by us. If the values returned |
144 | | // by the map function are not in the range [0, range] we have a bug. |
145 | 0 | BOTAN_DEBUG_ASSERT(coeff_value <= range); |
146 | | |
147 | | // Bit-pack the coefficient into the collectors array and keep track of |
148 | | // the bit-offset within the current collector. Note that this might |
149 | | // shift some high-bits of the coefficient out of the current collector. |
150 | 0 | collectors[c] |= coeff_value << bit_offset; |
151 | 0 | bit_offset += trait::bits_per_coeff; |
152 | | |
153 | | // If the bit-offset now exceeds the collector's bit-width, we fill the |
154 | | // next collector with the high-bits that didn't fit into the previous. |
155 | | // The bit-offset is adjusted to now point into the new collector. |
156 | 0 | if(bit_offset > trait::bits_in_collector) { |
157 | 0 | bit_offset = bit_offset - trait::bits_in_collector; |
158 | 0 | collectors[++c] = coeff_value >> (trait::bits_per_coeff - bit_offset); |
159 | 0 | } |
160 | 0 | } |
161 | | |
162 | | // One byte-aligned pack of bit-packed coefficients is now stored in the |
163 | | // collectors and can be written to an output buffer. Note that we might |
164 | | // have to remove some padding bytes of unused collector space. |
165 | 0 | const auto bytes = store_le(collectors); |
166 | 0 | stuffer.append(std::span{bytes}.template first<trait::bytes_per_pack>()); |
167 | 0 | } |
168 | 0 | } Unexecuted instantiation: _ZN5Botan8CRYSTALS4packILi1023ETkNS0_14crystals_traitENS_19DilithiumPolyTraitsELNS0_6DomainE0ETkNS0_12coeff_map_fnINT0_1TEEEZNS0_4packILi1023ETkNS0_14crystals_traitES2_LS3_0EEEvRKNS0_10PolynomialIS5_XT1_EEERNS_13BufferStufferEEUliE_EEvSB_SD_T2_ Unexecuted instantiation: _ZN5Botan8CRYSTALS4packILi4ETkNS0_14crystals_traitENS_19DilithiumPolyTraitsELNS0_6DomainE0ETkNS0_12coeff_map_fnINT0_1TEEEPFjiEEEvRKNS0_10PolynomialIS5_XT1_EEERNS_13BufferStufferET2_ Unexecuted instantiation: _ZN5Botan8CRYSTALS4packILi8ETkNS0_14crystals_traitENS_19DilithiumPolyTraitsELNS0_6DomainE0ETkNS0_12coeff_map_fnINT0_1TEEEPFjiEEEvRKNS0_10PolynomialIS5_XT1_EEERNS_13BufferStufferET2_ Unexecuted instantiation: _ZN5Botan8CRYSTALS4packILi8191ETkNS0_14crystals_traitENS_19DilithiumPolyTraitsELNS0_6DomainE0ETkNS0_12coeff_map_fnINT0_1TEEEPFjiEEEvRKNS0_10PolynomialIS5_XT1_EEERNS_13BufferStufferET2_ Unexecuted instantiation: _ZN5Botan8CRYSTALS4packILi262143ETkNS0_14crystals_traitENS_19DilithiumPolyTraitsELNS0_6DomainE0ETkNS0_12coeff_map_fnINT0_1TEEEPFjiEEEvRKNS0_10PolynomialIS5_XT1_EEERNS_13BufferStufferET2_ Unexecuted instantiation: _ZN5Botan8CRYSTALS4packILi1048575ETkNS0_14crystals_traitENS_19DilithiumPolyTraitsELNS0_6DomainE0ETkNS0_12coeff_map_fnINT0_1TEEEPFjiEEEvRKNS0_10PolynomialIS5_XT1_EEERNS_13BufferStufferET2_ Unexecuted instantiation: _ZN5Botan8CRYSTALS4packILi43ETkNS0_14crystals_traitENS_19DilithiumPolyTraitsELNS0_6DomainE0ETkNS0_12coeff_map_fnINT0_1TEEEZNS0_4packILi43ETkNS0_14crystals_traitES2_LS3_0EEEvRKNS0_10PolynomialIS5_XT1_EEERNS_13BufferStufferEEUliE_EEvSB_SD_T2_ Unexecuted instantiation: _ZN5Botan8CRYSTALS4packILi15ETkNS0_14crystals_traitENS_19DilithiumPolyTraitsELNS0_6DomainE0ETkNS0_12coeff_map_fnINT0_1TEEEZNS0_4packILi15ETkNS0_14crystals_traitES2_LS3_0EEEvRKNS0_10PolynomialIS5_XT1_EEERNS_13BufferStufferEEUliE_EEvSB_SD_T2_ Unexecuted instantiation: _ZN5Botan8CRYSTALS4packILi3328ETkNS0_14crystals_traitENS_15KyberPolyTraitsELNS0_6DomainE1ETkNS0_12coeff_map_fnINT0_1TEEEZNS0_4packILi3328ETkNS0_14crystals_traitES2_LS3_1EEEvRKNS0_10PolynomialIS5_XT1_EEERNS_13BufferStufferEEUlsE_EEvSB_SD_T2_ Unexecuted instantiation: _ZN5Botan8CRYSTALS4packILi1023ETkNS0_14crystals_traitENS_15KyberPolyTraitsELNS0_6DomainE0ETkNS0_12coeff_map_fnINT0_1TEEEPFtsEEEvRKNS0_10PolynomialIS5_XT1_EEERNS_13BufferStufferET2_ Unexecuted instantiation: _ZN5Botan8CRYSTALS4packILi2047ETkNS0_14crystals_traitENS_15KyberPolyTraitsELNS0_6DomainE0ETkNS0_12coeff_map_fnINT0_1TEEEPFtsEEEvRKNS0_10PolynomialIS5_XT1_EEERNS_13BufferStufferET2_ Unexecuted instantiation: _ZN5Botan8CRYSTALS4packILi15ETkNS0_14crystals_traitENS_15KyberPolyTraitsELNS0_6DomainE0ETkNS0_12coeff_map_fnINT0_1TEEEPFtsEEEvRKNS0_10PolynomialIS5_XT1_EEERNS_13BufferStufferET2_ Unexecuted instantiation: _ZN5Botan8CRYSTALS4packILi31ETkNS0_14crystals_traitENS_15KyberPolyTraitsELNS0_6DomainE0ETkNS0_12coeff_map_fnINT0_1TEEEPFtsEEEvRKNS0_10PolynomialIS5_XT1_EEERNS_13BufferStufferET2_ Unexecuted instantiation: _ZN5Botan8CRYSTALS4packILi1ETkNS0_14crystals_traitENS_15KyberPolyTraitsELNS0_6DomainE0ETkNS0_12coeff_map_fnINT0_1TEEEPFtsEEEvRKNS0_10PolynomialIS5_XT1_EEERNS_13BufferStufferET2_ |
169 | | |
170 | | /** |
171 | | * Base implementation of NIST FIPS 203 Algorithm 6 (ByteDecode) and NIST |
172 | | * FIPS 204 Algorithms 18 (SimpleBitUnpack) and 19 (BitUnpack). |
173 | | * |
174 | | * This takes a byte sequence represented by @p byte_source and unpacks its |
175 | | * coefficients into the polynomial @p p. Optionally, the coefficients can be |
176 | | * transformed using the @p unmap function after unpacking them. Note that |
177 | | * the @p unmap function must be able to deal with out-of-range values, as the |
178 | | * input to `unpack()` may be untrusted data. |
179 | | * |
180 | | * Kyber uses @p unmap to decompress the coefficients as needed, Dilithium uses |
181 | | * it to convert the coefficients back to signed integers. |
182 | | * |
183 | | * @tparam range the upper bound of the coefficient range. |
184 | | */ |
185 | | template <int32_t range, |
186 | | byte_source ByteSourceT, |
187 | | crystals_trait PolyTrait, |
188 | | Domain D, |
189 | | coeff_unmap_fn<typename PolyTrait::T> UnmapFnT> |
190 | 0 | constexpr void unpack(Polynomial<PolyTrait, D>& p, ByteSourceT& byte_source, UnmapFnT unmap) { |
191 | 0 | using trait = BitPackingTrait<range, PolyTrait>; |
192 | |
|
193 | 0 | auto get_bytes = detail::as_byte_source(byte_source); |
194 | 0 | typename trait::collector_bytearray bytes = {0}; |
195 | | |
196 | | // This is the inverse operation of the bit-packing algorithm above. Please |
197 | | // refer to the comments there for a detailed explanation of the algorithm. |
198 | 0 | for(size_t i = 0; i < p.size(); i += trait::coeffs_per_pack) { |
199 | 0 | get_bytes(std::span{bytes}.template first<trait::bytes_per_pack>()); |
200 | 0 | const auto collectors = load_le<typename trait::collector_array>(bytes); |
201 | |
|
202 | 0 | for(size_t j = 0, bit_offset = 0, c = 0; j < trait::coeffs_per_pack; ++j) { |
203 | 0 | typename trait::sink_t coeff_value = collectors[c] >> bit_offset; |
204 | 0 | bit_offset += trait::bits_per_coeff; |
205 | 0 | if(bit_offset > trait::bits_in_collector) { |
206 | 0 | bit_offset = bit_offset - trait::bits_in_collector; |
207 | 0 | coeff_value |= collectors[++c] << (trait::bits_per_coeff - bit_offset); |
208 | 0 | } |
209 | | |
210 | | // unpack() may be called on data produced by an untrusted party. |
211 | | // The values passed into the unmap function may be out of range, hence |
212 | | // it is acceptable for unmap to return an out-of-range value then. |
213 | | // |
214 | | // For that reason we cannot use BOTAN_ASSERT[_DEBUG] on the values. |
215 | 0 | p[i + j] = unmap(static_cast<typename trait::unsigned_T>(coeff_value & trait::value_mask)); |
216 | 0 | } |
217 | 0 | } |
218 | 0 | } Unexecuted instantiation: _ZN5Botan8CRYSTALS6unpackILi1023ETkNS0_11byte_sourceENS_12BufferSlicerETkNS0_14crystals_traitENS_19DilithiumPolyTraitsELNS0_6DomainE0ETkNS0_14coeff_unmap_fnINT1_1TEEEZNS0_6unpackILi1023ETkNS0_11byte_sourceES2_TkNS0_14crystals_traitES3_LS4_0EEEvRNS0_10PolynomialIS6_XT2_EEERT0_EUljE_EEvSB_SD_T3_ Unexecuted instantiation: _ZN5Botan8CRYSTALS6unpackILi4ETkNS0_11byte_sourceENS_12BufferSlicerETkNS0_14crystals_traitENS_19DilithiumPolyTraitsELNS0_6DomainE0ETkNS0_14coeff_unmap_fnINT1_1TEEEPFijEEEvRNS0_10PolynomialIS6_XT2_EEERT0_T3_ Unexecuted instantiation: _ZN5Botan8CRYSTALS6unpackILi8ETkNS0_11byte_sourceENS_12BufferSlicerETkNS0_14crystals_traitENS_19DilithiumPolyTraitsELNS0_6DomainE0ETkNS0_14coeff_unmap_fnINT1_1TEEEPFijEEEvRNS0_10PolynomialIS6_XT2_EEERT0_T3_ Unexecuted instantiation: _ZN5Botan8CRYSTALS6unpackILi8191ETkNS0_11byte_sourceENS_12BufferSlicerETkNS0_14crystals_traitENS_19DilithiumPolyTraitsELNS0_6DomainE0ETkNS0_14coeff_unmap_fnINT1_1TEEEPFijEEEvRNS0_10PolynomialIS6_XT2_EEERT0_T3_ Unexecuted instantiation: _ZN5Botan8CRYSTALS6unpackILi262143ETkNS0_11byte_sourceENS_12BufferSlicerETkNS0_14crystals_traitENS_19DilithiumPolyTraitsELNS0_6DomainE0ETkNS0_14coeff_unmap_fnINT1_1TEEEPFijEEEvRNS0_10PolynomialIS6_XT2_EEERT0_T3_ Unexecuted instantiation: _ZN5Botan8CRYSTALS6unpackILi1048575ETkNS0_11byte_sourceENS_12BufferSlicerETkNS0_14crystals_traitENS_19DilithiumPolyTraitsELNS0_6DomainE0ETkNS0_14coeff_unmap_fnINT1_1TEEEPFijEEEvRNS0_10PolynomialIS6_XT2_EEERT0_T3_ Unexecuted instantiation: _ZN5Botan8CRYSTALS6unpackILi262143ETkNS0_11byte_sourceENS_3XOFETkNS0_14crystals_traitENS_19DilithiumPolyTraitsELNS0_6DomainE0ETkNS0_14coeff_unmap_fnINT1_1TEEEPFijEEEvRNS0_10PolynomialIS6_XT2_EEERT0_T3_ Unexecuted instantiation: _ZN5Botan8CRYSTALS6unpackILi1048575ETkNS0_11byte_sourceENS_3XOFETkNS0_14crystals_traitENS_19DilithiumPolyTraitsELNS0_6DomainE0ETkNS0_14coeff_unmap_fnINT1_1TEEEPFijEEEvRNS0_10PolynomialIS6_XT2_EEERT0_T3_ Unexecuted instantiation: _ZN5Botan8CRYSTALS6unpackILi3328ETkNS0_11byte_sourceENS_12BufferSlicerETkNS0_14crystals_traitENS_15KyberPolyTraitsELNS0_6DomainE1ETkNS0_14coeff_unmap_fnINT1_1TEEEZNS0_6unpackILi3328ETkNS0_11byte_sourceES2_TkNS0_14crystals_traitES3_LS4_1EEEvRNS0_10PolynomialIS6_XT2_EEERT0_EUltE_EEvSB_SD_T3_ Unexecuted instantiation: _ZN5Botan8CRYSTALS6unpackILi1023ETkNS0_11byte_sourceENS_12BufferSlicerETkNS0_14crystals_traitENS_15KyberPolyTraitsELNS0_6DomainE0ETkNS0_14coeff_unmap_fnINT1_1TEEEPFstEEEvRNS0_10PolynomialIS6_XT2_EEERT0_T3_ Unexecuted instantiation: _ZN5Botan8CRYSTALS6unpackILi2047ETkNS0_11byte_sourceENS_12BufferSlicerETkNS0_14crystals_traitENS_15KyberPolyTraitsELNS0_6DomainE0ETkNS0_14coeff_unmap_fnINT1_1TEEEPFstEEEvRNS0_10PolynomialIS6_XT2_EEERT0_T3_ Unexecuted instantiation: _ZN5Botan8CRYSTALS6unpackILi15ETkNS0_11byte_sourceENS_12BufferSlicerETkNS0_14crystals_traitENS_15KyberPolyTraitsELNS0_6DomainE0ETkNS0_14coeff_unmap_fnINT1_1TEEEPFstEEEvRNS0_10PolynomialIS6_XT2_EEERT0_T3_ Unexecuted instantiation: _ZN5Botan8CRYSTALS6unpackILi31ETkNS0_11byte_sourceENS_12BufferSlicerETkNS0_14crystals_traitENS_15KyberPolyTraitsELNS0_6DomainE0ETkNS0_14coeff_unmap_fnINT1_1TEEEPFstEEEvRNS0_10PolynomialIS6_XT2_EEERT0_T3_ Unexecuted instantiation: _ZN5Botan8CRYSTALS6unpackILi1ETkNS0_11byte_sourceENS_12BufferSlicerETkNS0_14crystals_traitENS_15KyberPolyTraitsELNS0_6DomainE0ETkNS0_14coeff_unmap_fnINT1_1TEEEPFstEEEvRNS0_10PolynomialIS6_XT2_EEERT0_T3_ |
219 | | |
220 | | /// Overload for packing polynomials with a NOOP map function |
221 | | template <int32_t range, crystals_trait PolyTrait, Domain D> |
222 | 0 | constexpr void pack(const Polynomial<PolyTrait, D>& p, BufferStuffer& stuffer) { |
223 | 0 | using unsigned_T = std::make_unsigned_t<typename PolyTrait::T>; |
224 | 0 | pack<range>(p, stuffer, [](typename PolyTrait::T x) { return static_cast<unsigned_T>(x); }); Unexecuted instantiation: _ZZN5Botan8CRYSTALS4packILi1023ETkNS0_14crystals_traitENS_19DilithiumPolyTraitsELNS0_6DomainE0EEEvRKNS0_10PolynomialIT0_XT1_EEERNS_13BufferStufferEENKUliE_clEi Unexecuted instantiation: _ZZN5Botan8CRYSTALS4packILi43ETkNS0_14crystals_traitENS_19DilithiumPolyTraitsELNS0_6DomainE0EEEvRKNS0_10PolynomialIT0_XT1_EEERNS_13BufferStufferEENKUliE_clEi Unexecuted instantiation: _ZZN5Botan8CRYSTALS4packILi15ETkNS0_14crystals_traitENS_19DilithiumPolyTraitsELNS0_6DomainE0EEEvRKNS0_10PolynomialIT0_XT1_EEERNS_13BufferStufferEENKUliE_clEi Unexecuted instantiation: _ZZN5Botan8CRYSTALS4packILi3328ETkNS0_14crystals_traitENS_15KyberPolyTraitsELNS0_6DomainE1EEEvRKNS0_10PolynomialIT0_XT1_EEERNS_13BufferStufferEENKUlsE_clEs |
225 | 0 | } Unexecuted instantiation: _ZN5Botan8CRYSTALS4packILi1023ETkNS0_14crystals_traitENS_19DilithiumPolyTraitsELNS0_6DomainE0EEEvRKNS0_10PolynomialIT0_XT1_EEERNS_13BufferStufferE Unexecuted instantiation: _ZN5Botan8CRYSTALS4packILi43ETkNS0_14crystals_traitENS_19DilithiumPolyTraitsELNS0_6DomainE0EEEvRKNS0_10PolynomialIT0_XT1_EEERNS_13BufferStufferE Unexecuted instantiation: _ZN5Botan8CRYSTALS4packILi15ETkNS0_14crystals_traitENS_19DilithiumPolyTraitsELNS0_6DomainE0EEEvRKNS0_10PolynomialIT0_XT1_EEERNS_13BufferStufferE Unexecuted instantiation: _ZN5Botan8CRYSTALS4packILi3328ETkNS0_14crystals_traitENS_15KyberPolyTraitsELNS0_6DomainE1EEEvRKNS0_10PolynomialIT0_XT1_EEERNS_13BufferStufferE |
226 | | |
227 | | /// Overload for unpacking polynomials with a NOOP unmap function |
228 | | template <int32_t range, byte_source ByteSourceT, crystals_trait PolyTrait, Domain D> |
229 | 0 | constexpr void unpack(Polynomial<PolyTrait, D>& p, ByteSourceT& byte_source) { |
230 | 0 | using unsigned_T = std::make_unsigned_t<typename PolyTrait::T>; |
231 | 0 | unpack<range>(p, byte_source, [](unsigned_T x) { return static_cast<typename PolyTrait::T>(x); }); Unexecuted instantiation: _ZZN5Botan8CRYSTALS6unpackILi1023ETkNS0_11byte_sourceENS_12BufferSlicerETkNS0_14crystals_traitENS_19DilithiumPolyTraitsELNS0_6DomainE0EEEvRNS0_10PolynomialIT1_XT2_EEERT0_ENKUljE_clEj Unexecuted instantiation: _ZZN5Botan8CRYSTALS6unpackILi3328ETkNS0_11byte_sourceENS_12BufferSlicerETkNS0_14crystals_traitENS_15KyberPolyTraitsELNS0_6DomainE1EEEvRNS0_10PolynomialIT1_XT2_EEERT0_ENKUltE_clEt |
232 | 0 | } Unexecuted instantiation: _ZN5Botan8CRYSTALS6unpackILi1023ETkNS0_11byte_sourceENS_12BufferSlicerETkNS0_14crystals_traitENS_19DilithiumPolyTraitsELNS0_6DomainE0EEEvRNS0_10PolynomialIT1_XT2_EEERT0_ Unexecuted instantiation: _ZN5Botan8CRYSTALS6unpackILi3328ETkNS0_11byte_sourceENS_12BufferSlicerETkNS0_14crystals_traitENS_15KyberPolyTraitsELNS0_6DomainE1EEEvRNS0_10PolynomialIT1_XT2_EEERT0_ |
233 | | |
234 | | } // namespace Botan::CRYSTALS |
235 | | |
236 | | #endif |