Botan 3.6.1
Crypto and TLS for C&
Botan::CRYSTALS Namespace Reference

Namespaces

namespace  detail
 

Classes

struct  BitPackingTrait
 
class  Polynomial
 
class  PolynomialMatrix
 
class  PolynomialVector
 
class  Trait_Base
 

Concepts

concept  crystals_constants
 
concept  crystals_trait
 
concept  byte_source
 
concept  coeff_map_fn
 
concept  coeff_unmap_fn
 

Enumerations

enum class  Domain { Normal , NTT }
 

Functions

template<crystals_trait Trait>
Polynomial< Trait, Domain::Normalinverse_ntt (Polynomial< Trait, Domain::NTT > p_ntt)
 
template<crystals_trait Trait>
PolynomialVector< Trait, Domain::Normalinverse_ntt (PolynomialVector< Trait, Domain::NTT > polyvec_ntt)
 
template<crystals_trait Trait, Domain D>
Polynomial< Trait, D > montgomery (Polynomial< Trait, D > p)
 
template<crystals_trait Trait, Domain D>
PolynomialVector< Trait, D > montgomery (PolynomialVector< Trait, D > polyvec)
 
template<crystals_trait Trait>
Polynomial< Trait, Domain::NTTntt (Polynomial< Trait, Domain::Normal > p)
 
template<crystals_trait Trait>
PolynomialVector< Trait, Domain::NTTntt (PolynomialVector< Trait, Domain::Normal > polyvec)
 
template<crystals_trait Trait>
Polynomial< Trait, Domain::NTToperator* (const Polynomial< Trait, Domain::NTT > &a, const Polynomial< Trait, Domain::NTT > &b)
 
template<crystals_trait Trait>
PolynomialVector< Trait, Domain::NTToperator* (const Polynomial< Trait, Domain::NTT > &p, const PolynomialVector< Trait, Domain::NTT > &pv)
 
template<crystals_trait Trait>
PolynomialVector< Trait, Domain::NTToperator* (const PolynomialMatrix< Trait > &mat, const PolynomialVector< Trait, Domain::NTT > &vec)
 
template<crystals_trait Trait>
Polynomial< Trait, Domain::NTToperator* (const PolynomialVector< Trait, Domain::NTT > &a, const PolynomialVector< Trait, Domain::NTT > &b)
 
template<crystals_trait Trait>
PolynomialVector< Trait, Domain::Normaloperator+ (const PolynomialVector< Trait, Domain::Normal > &a, const PolynomialVector< Trait, Domain::Normal > &b)
 
template<crystals_trait Trait>
PolynomialVector< Trait, Domain::Normaloperator<< (const PolynomialVector< Trait, Domain::Normal > &pv, size_t shift)
 
template<int32_t range, crystals_trait PolyTrait, Domain D>
constexpr void pack (const Polynomial< PolyTrait, D > &p, BufferStuffer &stuffer)
 Overload for packing polynomials with a NOOP map function.
 
template<int32_t range, crystals_trait PolyTrait, Domain D, coeff_map_fn< typename PolyTrait::T > MapFnT>
constexpr void pack (const Polynomial< PolyTrait, D > &p, BufferStuffer &stuffer, MapFnT map)
 
template<int32_t range, byte_source ByteSourceT, crystals_trait PolyTrait, Domain D>
constexpr void unpack (Polynomial< PolyTrait, D > &p, ByteSourceT &byte_source)
 Overload for unpacking polynomials with a NOOP unmap function.
 
template<int32_t range, byte_source ByteSourceT, crystals_trait PolyTrait, Domain D, coeff_unmap_fn< typename PolyTrait::T > UnmapFnT>
constexpr void unpack (Polynomial< PolyTrait, D > &p, ByteSourceT &byte_source, UnmapFnT unmap)
 

Enumeration Type Documentation

◆ Domain

enum class Botan::CRYSTALS::Domain
strong
Enumerator
Normal 
NTT 

Definition at line 28 of file pqcrystals.h.

Function Documentation

◆ inverse_ntt() [1/2]

template<crystals_trait Trait>
Polynomial< Trait, Domain::Normal > Botan::CRYSTALS::inverse_ntt ( Polynomial< Trait, Domain::NTT > p_ntt)

Definition at line 564 of file pqcrystals.h.

564 {
565 auto p = detail::domain_cast<Domain::Normal>(std::move(p_ntt));
566 Trait::inverse_ntt(p.coefficients());
567 return p;
568}

References Botan::CRYSTALS::detail::domain_cast().

◆ inverse_ntt() [2/2]

template<crystals_trait Trait>
PolynomialVector< Trait, Domain::Normal > Botan::CRYSTALS::inverse_ntt ( PolynomialVector< Trait, Domain::NTT > polyvec_ntt)

Definition at line 580 of file pqcrystals.h.

580 {
581 auto polyvec = detail::domain_cast<Domain::Normal>(std::move(polyvec_ntt));
582 for(auto& poly : polyvec) {
583 Trait::inverse_ntt(poly.coefficients());
584 }
585 return polyvec;
586}

References Botan::CRYSTALS::detail::domain_cast().

◆ montgomery() [1/2]

template<crystals_trait Trait, Domain D>
Polynomial< Trait, D > Botan::CRYSTALS::montgomery ( Polynomial< Trait, D > p)

Definition at line 589 of file pqcrystals.h.

589 {
590 detail::montgomery(p);
591 return p;
592}

References Botan::CRYSTALS::detail::montgomery().

◆ montgomery() [2/2]

template<crystals_trait Trait, Domain D>
PolynomialVector< Trait, D > Botan::CRYSTALS::montgomery ( PolynomialVector< Trait, D > polyvec)

Definition at line 595 of file pqcrystals.h.

595 {
596 for(auto& p : polyvec) {
597 detail::montgomery(p);
598 }
599 return polyvec;
600}

References Botan::CRYSTALS::detail::montgomery().

◆ ntt() [1/2]

template<crystals_trait Trait>
Polynomial< Trait, Domain::NTT > Botan::CRYSTALS::ntt ( Polynomial< Trait, Domain::Normal > p)

Definition at line 557 of file pqcrystals.h.

557 {
558 auto p_ntt = detail::domain_cast<Domain::NTT>(std::move(p));
559 Trait::ntt(p_ntt.coefficients());
560 return p_ntt;
561}

References Botan::CRYSTALS::detail::domain_cast().

◆ ntt() [2/2]

template<crystals_trait Trait>
PolynomialVector< Trait, Domain::NTT > Botan::CRYSTALS::ntt ( PolynomialVector< Trait, Domain::Normal > polyvec)

Definition at line 571 of file pqcrystals.h.

571 {
572 auto polyvec_ntt = detail::domain_cast<Domain::NTT>(std::move(polyvec));
573 for(auto& poly : polyvec_ntt) {
574 Trait::ntt(poly.coefficients());
575 }
576 return polyvec_ntt;
577}

References Botan::CRYSTALS::detail::domain_cast().

◆ operator*() [1/4]

template<crystals_trait Trait>
Polynomial< Trait, Domain::NTT > Botan::CRYSTALS::operator* ( const Polynomial< Trait, Domain::NTT > & a,
const Polynomial< Trait, Domain::NTT > & b )

Definition at line 642 of file pqcrystals.h.

643 {
645 Trait::poly_pointwise_montgomery(result.coefficients(), a.coefficients(), b.coefficients());
646 return result;
647}
std::span< T, Trait::N > coefficients()
Definition pqcrystals.h:300
const SIMD_8x32 & b

References Botan::b, and Botan::CRYSTALS::Polynomial< Trait, D >::coefficients().

◆ operator*() [2/4]

template<crystals_trait Trait>
PolynomialVector< Trait, Domain::NTT > Botan::CRYSTALS::operator* ( const Polynomial< Trait, Domain::NTT > & p,
const PolynomialVector< Trait, Domain::NTT > & pv )

Definition at line 632 of file pqcrystals.h.

633 {
635 for(size_t i = 0; i < pv.size(); ++i) {
636 Trait::poly_pointwise_montgomery(result[i].coefficients(), p.coefficients(), pv[i].coefficients());
637 }
638 return result;
639}

References Botan::CRYSTALS::Polynomial< Trait, D >::coefficients(), Botan::CRYSTALS::PolynomialVector< Trait, D >::coefficients(), and Botan::CRYSTALS::PolynomialVector< Trait, D >::size().

◆ operator*() [3/4]

template<crystals_trait Trait>
PolynomialVector< Trait, Domain::NTT > Botan::CRYSTALS::operator* ( const PolynomialMatrix< Trait > & mat,
const PolynomialVector< Trait, Domain::NTT > & vec )

Definition at line 614 of file pqcrystals.h.

615 {
617 for(size_t i = 0; i < mat.size(); ++i) {
618 Trait::polyvec_pointwise_acc_montgomery(result[i].coefficients(), mat[i].coefficients(), vec.coefficients());
619 }
620 return result;
621}

References Botan::CRYSTALS::PolynomialVector< Trait, D >::coefficients(), and Botan::CRYSTALS::PolynomialMatrix< Trait >::size().

◆ operator*() [4/4]

template<crystals_trait Trait>
Polynomial< Trait, Domain::NTT > Botan::CRYSTALS::operator* ( const PolynomialVector< Trait, Domain::NTT > & a,
const PolynomialVector< Trait, Domain::NTT > & b )

Definition at line 624 of file pqcrystals.h.

625 {
627 detail::dot_product(result, a, b);
628 return result;
629}

References Botan::b, and Botan::CRYSTALS::detail::dot_product().

◆ operator+()

template<crystals_trait Trait>
PolynomialVector< Trait, Domain::Normal > Botan::CRYSTALS::operator+ ( const PolynomialVector< Trait, Domain::Normal > & a,
const PolynomialVector< Trait, Domain::Normal > & b )

Definition at line 603 of file pqcrystals.h.

604 {
605 BOTAN_DEBUG_ASSERT(a.size() == b.size());
607 for(size_t i = 0; i < a.size(); ++i) {
608 Trait::poly_add(result[i].coefficients(), a[i].coefficients(), b[i].coefficients());
609 }
610 return result;
611}
#define BOTAN_DEBUG_ASSERT(expr)
Definition assert.h:98

References Botan::b, BOTAN_DEBUG_ASSERT, and Botan::CRYSTALS::PolynomialVector< Trait, D >::size().

◆ operator<<()

template<crystals_trait Trait>
PolynomialVector< Trait, Domain::Normal > Botan::CRYSTALS::operator<< ( const PolynomialVector< Trait, Domain::Normal > & pv,
size_t shift )

Definition at line 642 of file pqcrystals.h.

650 {
651 BOTAN_ASSERT_NOMSG(shift < sizeof(typename Trait::T) * 8);
653 for(size_t i = 0; i < pv.size(); ++i) {
654 for(size_t j = 0; j < Trait::N; ++j) {
655 result[i][j] = pv[i][j] << shift;
656 }
657 }
658 return result;
659}
#define BOTAN_ASSERT_NOMSG(expr)
Definition assert.h:59

◆ pack() [1/2]

template<int32_t range, crystals_trait PolyTrait, Domain D>
void Botan::CRYSTALS::pack ( const Polynomial< PolyTrait, D > & p,
BufferStuffer & stuffer )
constexpr

Overload for packing polynomials with a NOOP map function.

Definition at line 222 of file pqcrystals_encoding.h.

222 {
223 using unsigned_T = std::make_unsigned_t<typename PolyTrait::T>;
224 pack<range>(p, stuffer, [](typename PolyTrait::T x) { return static_cast<unsigned_T>(x); });
225}

References pack().

◆ pack() [2/2]

template<int32_t range, crystals_trait PolyTrait, Domain D, coeff_map_fn< typename PolyTrait::T > MapFnT>
void Botan::CRYSTALS::pack ( const Polynomial< PolyTrait, D > & p,
BufferStuffer & stuffer,
MapFnT map )
constexpr

Base implementation of NIST FIPS 203 Algorithm 5 (ByteEncode) and NIST FIPS 204 Algorithms 16 (SimpleBitPack) and 17 (BitPack).

This takes a polynomial p and packs its coefficients into the buffer represented by stuffer. Optionally, the coefficients can be transformed using the map function before packing them. Kyber uses map to compress the coefficients as needed, Dilithium to transform coefficients to unsigned.

The implementation assumes that the values returned from the custom map transformation are in the range [0, range]. No assumption is made about the value range of the coefficients in the polynomial p.

Note that this bit-packing algorithm is inefficient if the bit-length of the coefficients is a multiple of 8. In that case, a byte-level encoding (that might need to take endianess into account) would be more efficient. However, neither Kyber nor Dilithium instantiate bit-packings with such a value range.

Template Parameters
rangethe upper bound of the coefficient range.

Definition at line 116 of file pqcrystals_encoding.h.

116 {
118
119 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 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 typename trait::collector_array collectors = {0};
138 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 const typename trait::unsigned_T mapped_coeff = map(p[i + j]);
141 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 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 collectors[c] |= coeff_value << bit_offset;
151 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 if(bit_offset > trait::bits_in_collector) {
157 bit_offset = bit_offset - trait::bits_in_collector;
158 collectors[++c] = coeff_value >> (trait::bits_per_coeff - bit_offset);
159 }
160 }
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 const auto bytes = store_le(collectors);
166 stuffer.append(std::span{bytes}.template first<trait::bytes_per_pack>());
167 }
168}
constexpr void append(std::span< const uint8_t > buffer)
Definition stl_util.h:177
constexpr size_t remaining_capacity() const
Definition stl_util.h:189
constexpr size_t size() const
Definition pqcrystals.h:274
constexpr auto store_le(ParamTs &&... params)
Definition loadstor.h:764

References Botan::BufferStuffer::append(), BOTAN_DEBUG_ASSERT, Botan::BufferStuffer::remaining_capacity(), Botan::CRYSTALS::Polynomial< Trait, D >::size(), and Botan::store_le().

Referenced by pack().

◆ unpack() [1/2]

template<int32_t range, byte_source ByteSourceT, crystals_trait PolyTrait, Domain D>
void Botan::CRYSTALS::unpack ( Polynomial< PolyTrait, D > & p,
ByteSourceT & byte_source )
constexpr

Overload for unpacking polynomials with a NOOP unmap function.

Definition at line 229 of file pqcrystals_encoding.h.

229 {
230 using unsigned_T = std::make_unsigned_t<typename PolyTrait::T>;
231 unpack<range>(p, byte_source, [](unsigned_T x) { return static_cast<typename PolyTrait::T>(x); });
232}

References unpack().

◆ unpack() [2/2]

template<int32_t range, byte_source ByteSourceT, crystals_trait PolyTrait, Domain D, coeff_unmap_fn< typename PolyTrait::T > UnmapFnT>
void Botan::CRYSTALS::unpack ( Polynomial< PolyTrait, D > & p,
ByteSourceT & byte_source,
UnmapFnT unmap )
constexpr

Base implementation of NIST FIPS 203 Algorithm 6 (ByteDecode) and NIST FIPS 204 Algorithms 18 (SimpleBitUnpack) and 19 (BitUnpack).

This takes a byte sequence represented by byte_source and unpacks its coefficients into the polynomial p. Optionally, the coefficients can be transformed using the unmap function after unpacking them. Note that the unmap function must be able to deal with out-of-range values, as the input to unpack() may be untrusted data.

Kyber uses unmap to decompress the coefficients as needed, Dilithium uses it to convert the coefficients back to signed integers.

Template Parameters
rangethe upper bound of the coefficient range.

Definition at line 190 of file pqcrystals_encoding.h.

190 {
192
193 auto get_bytes = detail::as_byte_source(byte_source);
194 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 for(size_t i = 0; i < p.size(); i += trait::coeffs_per_pack) {
199 get_bytes(std::span{bytes}.template first<trait::bytes_per_pack>());
200 const auto collectors = load_le<typename trait::collector_array>(bytes);
201
202 for(size_t j = 0, bit_offset = 0, c = 0; j < trait::coeffs_per_pack; ++j) {
203 typename trait::sink_t coeff_value = collectors[c] >> bit_offset;
204 bit_offset += trait::bits_per_coeff;
205 if(bit_offset > trait::bits_in_collector) {
206 bit_offset = bit_offset - trait::bits_in_collector;
207 coeff_value |= collectors[++c] << (trait::bits_per_coeff - bit_offset);
208 }
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 p[i + j] = unmap(static_cast<typename trait::unsigned_T>(coeff_value & trait::value_mask));
216 }
217 }
218}

References Botan::CRYSTALS::detail::as_byte_source(), Botan::load_le(), and Botan::CRYSTALS::Polynomial< Trait, D >::size().

Referenced by unpack().