Coverage Report

Created: 2025-04-11 06:34

/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