diff --git a/include/ml_kem/internals/k_pke.hpp b/include/ml_kem/internals/k_pke.hpp index c224fb8..3e82a6a 100644 --- a/include/ml_kem/internals/k_pke.hpp +++ b/include/ml_kem/internals/k_pke.hpp @@ -12,7 +12,7 @@ namespace k_pke { // K-PKE key generation algorithm, generating byte serialized public key and secret keym given a 32 -bytes input seed `d`. // See algorithm 12 of K-PKE specification https://doi.org/10.6028/NIST.FIPS.203.ipd. template -static inline constexpr void +constexpr void keygen(std::span d, std::span pubkey, std::span seckey) @@ -72,7 +72,7 @@ keygen(std::span d, // // See algorithm 13 of K-PKE specification https://doi.org/10.6028/NIST.FIPS.203.ipd. template -[[nodiscard("Use result of modulus check on public key")]] static inline constexpr bool +[[nodiscard("Use result of modulus check on public key")]] constexpr bool encrypt(std::span pubkey, std::span msg, std::span rcoin, @@ -149,7 +149,7 @@ encrypt(std::span pubkey // // See algorithm 14 defined in K-PKE specification https://doi.org/10.6028/NIST.FIPS.203.ipd. template -static inline constexpr void +constexpr void decrypt(std::span seckey, std::span enc, std::span dec) diff --git a/include/ml_kem/internals/math/field.hpp b/include/ml_kem/internals/math/field.hpp index e868c91..49a9c3b 100644 --- a/include/ml_kem/internals/math/field.hpp +++ b/include/ml_kem/internals/math/field.hpp @@ -1,15 +1,16 @@ #pragma once #include "ml_kem/internals/rng/prng.hpp" +#include "ml_kem/internals/utility/force_inline.hpp" #include #include namespace ml_kem_field { // Ml_kem Prime Field Modulus ( = 3329 ) -static constexpr uint32_t Q = (1u << 8) * 13 + 1; +inline constexpr uint32_t Q = (1u << 8) * 13 + 1; // Bit width of Ml_kem Prime Field Modulus ( = 12 ) -static constexpr size_t Q_BIT_WIDTH = std::bit_width(Q); +inline constexpr size_t Q_BIT_WIDTH = std::bit_width(Q); // Precomputed Barrett Reduction Constant // @@ -19,7 +20,7 @@ static constexpr size_t Q_BIT_WIDTH = std::bit_width(Q); // r = floor((1 << 2k) / Q) = 5039 // // See https://www.nayuki.io/page/barrett-reduction-algorithm. -static constexpr uint32_t R = (1u << (2 * Q_BIT_WIDTH)) / Q; +inline constexpr uint32_t R = (1u << (2 * Q_BIT_WIDTH)) / Q; // Prime field Zq | q = 3329, with arithmetic operations defined over it. // @@ -33,7 +34,7 @@ private: uint32_t v = 0u; // Given a 32 -bit unsigned integer `v` such that `v` ∈ [0, 2*Q), this routine can be invoked for reducing `v` modulo prime Q. - static inline constexpr uint32_t reduce_once(const uint32_t v) + static forceinline constexpr uint32_t reduce_once(const uint32_t v) { const uint32_t t0 = v - Q; const uint32_t t1 = -(t0 >> 31); @@ -45,7 +46,7 @@ private: // Given a 32 -bit unsigned integer `v` such that `v` ∈ [0, Q*Q), this routine can be invoked for reducing `v` modulo Q, using // barrett reduction technique, following algorithm description @ https://www.nayuki.io/page/barrett-reduction-algorithm. - static inline constexpr uint32_t barrett_reduce(const uint32_t v) + static forceinline constexpr uint32_t barrett_reduce(const uint32_t v) { const uint64_t t0 = static_cast(v) * static_cast(R); const uint32_t t1 = static_cast(t0 >> (2 * Q_BIT_WIDTH)); @@ -57,35 +58,35 @@ private: public: // Constructor(s) - inline constexpr zq_t() = default; - inline constexpr zq_t(const uint16_t a /* Expects a ∈ [0, Q) */) { this->v = a; } - static inline constexpr zq_t from_non_reduced(const uint16_t a /* Doesn't expect that a ∈ [0, Q) */) { return barrett_reduce(a); } + forceinline constexpr zq_t() = default; + forceinline constexpr zq_t(const uint16_t a /* Expects a ∈ [0, Q) */) { this->v = a; } + static forceinline constexpr zq_t from_non_reduced(const uint16_t a /* Doesn't expect that a ∈ [0, Q) */) { return barrett_reduce(a); } // Returns canonical value held under Zq type. Returned value must ∈ [0, Q). - inline constexpr uint32_t raw() const { return this->v; } + forceinline constexpr uint32_t raw() const { return this->v; } - static inline constexpr zq_t zero() { return zq_t(0u); } - static inline constexpr zq_t one() { return zq_t(1u); } + static forceinline constexpr zq_t zero() { return zq_t(0u); } + static forceinline constexpr zq_t one() { return zq_t(1u); } // Modulo addition of two Zq elements. - inline constexpr zq_t operator+(const zq_t& rhs) const { return reduce_once(this->v + rhs.v); } - inline constexpr void operator+=(const zq_t& rhs) { *this = *this + rhs; } + forceinline constexpr zq_t operator+(const zq_t& rhs) const { return reduce_once(this->v + rhs.v); } + forceinline constexpr void operator+=(const zq_t& rhs) { *this = *this + rhs; } // Modulo negation of a Zq element. - inline constexpr zq_t operator-() const { return zq_t(Q - this->v); } + forceinline constexpr zq_t operator-() const { return zq_t(Q - this->v); } // Modulo subtraction of one Zq element from another one. - inline constexpr zq_t operator-(const zq_t& rhs) const { return *this + (-rhs); } - inline constexpr void operator-=(const zq_t& rhs) { *this = *this - rhs; } + forceinline constexpr zq_t operator-(const zq_t& rhs) const { return *this + (-rhs); } + forceinline constexpr void operator-=(const zq_t& rhs) { *this = *this - rhs; } // Modulo multiplication of two Zq elements. - inline constexpr zq_t operator*(const zq_t& rhs) const { return barrett_reduce(this->v * rhs.v); } - inline constexpr void operator*=(const zq_t& rhs) { *this = *this * rhs; } + forceinline constexpr zq_t operator*(const zq_t& rhs) const { return barrett_reduce(this->v * rhs.v); } + forceinline constexpr void operator*=(const zq_t& rhs) { *this = *this * rhs; } // Modulo exponentiation of Zq element. // // Taken from https://github.com/itzmeanjan/dilithium/blob/3fe6ab61/include/field.hpp#L144-L167. - inline constexpr zq_t operator^(const size_t n) const + forceinline constexpr zq_t operator^(const size_t n) const { zq_t base = *this; @@ -108,15 +109,15 @@ public: // Multiplicative inverse of Zq element. Also division of one Zq element by another one. // // Note, if Zq element is 0, we can't compute multiplicative inverse and 0 is returned. - inline constexpr zq_t inv() const { return *this ^ static_cast((Q - 2)); } - inline constexpr zq_t operator/(const zq_t& rhs) const { return *this * rhs.inv(); } + forceinline constexpr zq_t inv() const { return *this ^ static_cast((Q - 2)); } + forceinline constexpr zq_t operator/(const zq_t& rhs) const { return *this * rhs.inv(); } // Comparison operators, see https://en.cppreference.com/w/cpp/language/default_comparisons - inline constexpr auto operator<=>(const zq_t&) const = default; + forceinline constexpr auto operator<=>(const zq_t&) const = default; // Samples a random Zq element, using pseudo random number generator. template - static inline zq_t random(ml_kem_prng::prng_t& prng) + static forceinline zq_t random(ml_kem_prng::prng_t& prng) { uint16_t res = 0; prng.read(std::span(reinterpret_cast(&res), sizeof(res))); diff --git a/include/ml_kem/internals/ml_kem.hpp b/include/ml_kem/internals/ml_kem.hpp index f5f60b0..8f76e5f 100644 --- a/include/ml_kem/internals/ml_kem.hpp +++ b/include/ml_kem/internals/ml_kem.hpp @@ -12,7 +12,7 @@ namespace ml_kem { // ML-KEM key generation algorithm, generating byte serialized public key and secret key, given 32 -bytes seed `d` and `z`. // See algorithm 15 defined in ML-KEM specification https://doi.org/10.6028/NIST.FIPS.203.ipd template -static inline constexpr void +constexpr void keygen(std::span d, // used in CPA-PKE std::span z, // used in CCA-KEM std::span pubkey, @@ -50,7 +50,7 @@ keygen(std::span d, // used in CPA-PKE // // See algorithm 16 defined in ML-KEM specification https://doi.org/10.6028/NIST.FIPS.203.ipd template -[[nodiscard("Use result, it might fail because of malformed input public key")]] static inline constexpr bool +[[nodiscard("Use result, it might fail because of malformed input public key")]] constexpr bool encapsulate(std::span m, std::span pubkey, std::span cipher, @@ -98,7 +98,7 @@ encapsulate(std::span m, // // See algorithm 17 defined in ML-KEM specification https://doi.org/10.6028/NIST.FIPS.203.ipd. template -static inline constexpr void +constexpr void decapsulate(std::span seckey, std::span cipher, std::span shared_secret) diff --git a/include/ml_kem/internals/poly/compression.hpp b/include/ml_kem/internals/poly/compression.hpp index e5978b2..dbf99a6 100644 --- a/include/ml_kem/internals/poly/compression.hpp +++ b/include/ml_kem/internals/poly/compression.hpp @@ -1,6 +1,7 @@ #pragma once #include "ml_kem/internals/math/field.hpp" #include "ml_kem/internals/poly/ntt.hpp" +#include "ml_kem/internals/utility/force_inline.hpp" #include "ml_kem/internals/utility/params.hpp" #include @@ -11,7 +12,7 @@ namespace ml_kem_utils { // See formula 4.5 on page 18 of ML-KEM specification https://doi.org/10.6028/NIST.FIPS.203.ipd. // Following implementation collects inspiration from https://github.com/FiloSottile/mlkem768/blob/cffbfb96/mlkem768.go#L395-L425. template -static inline constexpr ml_kem_field::zq_t +forceinline constexpr ml_kem_field::zq_t compress(const ml_kem_field::zq_t x) requires(ml_kem_params::check_d(d)) { @@ -31,7 +32,7 @@ compress(const ml_kem_field::zq_t x) // // See formula 4.6 on page 18 of ML-KEM specification https://doi.org/10.6028/NIST.FIPS.203.ipd. template -static inline constexpr ml_kem_field::zq_t +forceinline constexpr ml_kem_field::zq_t decompress(const ml_kem_field::zq_t x) requires(ml_kem_params::check_d(d)) { @@ -47,7 +48,7 @@ decompress(const ml_kem_field::zq_t x) // Utility function to compress each of 256 coefficients of a degree-255 polynomial while mutating the input. template -static inline constexpr void +constexpr void poly_compress(std::span poly) requires(ml_kem_params::check_d(d)) { @@ -58,7 +59,7 @@ poly_compress(std::span poly) // Utility function to decompress each of 256 coefficients of a degree-255 polynomial while mutating the input. template -static inline constexpr void +constexpr void poly_decompress(std::span poly) requires(ml_kem_params::check_d(d)) { diff --git a/include/ml_kem/internals/poly/ntt.hpp b/include/ml_kem/internals/poly/ntt.hpp index a5d8612..62778e0 100644 --- a/include/ml_kem/internals/poly/ntt.hpp +++ b/include/ml_kem/internals/poly/ntt.hpp @@ -1,27 +1,28 @@ #pragma once #include "ml_kem/internals/math/field.hpp" +#include "ml_kem/internals/utility/force_inline.hpp" namespace ml_kem_ntt { -static constexpr size_t LOG2N = 8; -static constexpr size_t N = 1 << LOG2N; +inline constexpr size_t LOG2N = 8; +inline constexpr size_t N = 1 << LOG2N; // First primitive 256 -th root of unity modulo q | q = 3329 // // Meaning, 17 ** 256 == 1 mod q -static constexpr auto ζ = ml_kem_field::zq_t(17); +inline constexpr auto ζ = ml_kem_field::zq_t(17); // Multiplicative inverse of N/ 2 over Z_q | q = 3329 and N = 256 // // Meaning (N/ 2) * INV_N = 1 mod q -static constexpr auto INV_N = ml_kem_field::zq_t(N / 2).inv(); +inline constexpr auto INV_N = ml_kem_field::zq_t(N / 2).inv(); // Given a 64 -bit unsigned integer, this routine extracts specified many contiguous bits from ( least significant bits ) LSB side // and reverses their bit order, returning bit reversed `mbw` -bit wide number. // // See https://github.com/itzmeanjan/falcon/blob/45b0593/include/ntt.hpp#L30-L38 for source of inspiration. template -static inline constexpr size_t +forceinline constexpr size_t bit_rev(const size_t v) { size_t v_rev = 0ul; @@ -35,7 +36,7 @@ bit_rev(const size_t v) } // Compile-time computed constants ( powers of ζ ), used for polynomial evaluation i.e. computation of NTT form. -static constexpr std::array NTT_ζ_EXP = []() -> auto { +inline constexpr std::array NTT_ζ_EXP = []() -> auto { std::array res{}; for (size_t i = 0; i < res.size(); i++) { @@ -46,7 +47,7 @@ static constexpr std::array NTT_ζ_EXP = []() -> auto }(); // Compile-time computed constants ( negated powers of ζ ), used for polynomial interpolation i.e. computation of iNTT form. -static constexpr std::array INTT_ζ_EXP = []() -> auto { +inline constexpr std::array INTT_ζ_EXP = []() -> auto { std::array res{}; for (size_t i = 0; i < res.size(); i++) { @@ -57,7 +58,7 @@ static constexpr std::array INTT_ζ_EXP = []() -> aut }(); // Compile-time computed constants ( powers of ζ ), used when multiplying two degree-255 polynomials in NTT domain. -static constexpr std::array POLY_MUL_ζ_EXP = []() -> auto { +inline constexpr std::array POLY_MUL_ζ_EXP = []() -> auto { std::array res{}; for (size_t i = 0; i < res.size(); i++) { @@ -74,7 +75,7 @@ static constexpr std::array POLY_MUL_ζ_EXP = []() -> // // Implementation inspired from https://github.com/itzmeanjan/falcon/blob/45b0593/include/ntt.hpp#L69-L144. // See algorithm 8 of ML-KEM specification https://doi.org/10.6028/NIST.FIPS.203.ipd. -static inline constexpr void +forceinline constexpr void ntt(std::span poly) { for (size_t l = LOG2N - 1; l >= 1; l--) { @@ -110,7 +111,7 @@ ntt(std::span poly) // // Implementation inspired from https://github.com/itzmeanjan/falcon/blob/45b0593/include/ntt.hpp#L146-L224. // See algorithm 9 of ML-KEM specification https://doi.org/10.6028/NIST.FIPS.203.ipd. -static inline constexpr void +forceinline constexpr void intt(std::span poly) { for (size_t l = 1; l < LOG2N; l++) { @@ -146,7 +147,7 @@ intt(std::span poly) // Given two degree-1 polynomials, this routine computes resulting degree-1 polynomial h. // See algorithm 11 of ML-KEM specification https://doi.org/10.6028/NIST.FIPS.203.ipd. -static inline constexpr void +forceinline constexpr void basemul(std::span f, std::span g, std::span h, const ml_kem_field::zq_t ζ) { ml_kem_field::zq_t f0 = f[0]; @@ -178,7 +179,7 @@ basemul(std::span f, std::span f, std::span g, std::span h) { using poly_t = std::span; diff --git a/include/ml_kem/internals/poly/poly_vec.hpp b/include/ml_kem/internals/poly/poly_vec.hpp index cf4a271..af1199d 100644 --- a/include/ml_kem/internals/poly/poly_vec.hpp +++ b/include/ml_kem/internals/poly/poly_vec.hpp @@ -3,6 +3,7 @@ #include "ml_kem/internals/poly/compression.hpp" #include "ml_kem/internals/poly/ntt.hpp" #include "ml_kem/internals/poly/serialize.hpp" +#include "ml_kem/internals/utility/force_inline.hpp" #include "ml_kem/internals/utility/params.hpp" namespace ml_kem_utils { @@ -10,7 +11,7 @@ namespace ml_kem_utils { // Given two matrices ( in NTT domain ) of compatible dimension, where each matrix element is a degree-255 polynomial over Z_q | q = 3329, // this routine multiplies them, computing a resulting matrix. template -static inline constexpr void +constexpr void matrix_multiply(std::span a, std::span b, std::span c) @@ -42,7 +43,7 @@ matrix_multiply(std::span -static inline constexpr void +constexpr void poly_vec_ntt(std::span vec) requires((k == 1) || ml_kem_params::check_k(k)) { @@ -57,7 +58,7 @@ poly_vec_ntt(std::span vec) // Given a vector ( of dimension `k x 1` ) of degree-255 polynomials ( where polynomial coefficients are in NTT form i.e. // they are placed in bit-reversed order ), this routine applies in-place polynomial iNTT over those `k` polynomials. template -static inline constexpr void +constexpr void poly_vec_intt(std::span vec) requires((k == 1) || ml_kem_params::check_k(k)) { @@ -71,7 +72,7 @@ poly_vec_intt(std::span vec) // Given a vector ( of dimension `k x 1` ) of degree-255 polynomials, this routine adds it to another polynomial vector of same dimension. template -static inline constexpr void +constexpr void poly_vec_add_to(std::span src, std::span dst) requires((k == 1) || ml_kem_params::check_k(k)) { @@ -84,7 +85,7 @@ poly_vec_add_to(std::span src, std: // Given a vector ( of dimension `k x 1` ) of degree-255 polynomials, this routine subtracts it to another polynomial vector of same dimension. template -static inline constexpr void +constexpr void poly_vec_sub_from(std::span src, std::span dst) requires((k == 1) || ml_kem_params::check_k(k)) { @@ -98,7 +99,7 @@ poly_vec_sub_from(std::span src, st // Given a vector ( of dimension `k x 1` ) of degree-255 polynomials, this routine encodes each of those polynomials into 32 x l -bytes, // writing to a (k x 32 x l) -bytes destination array. template -static inline constexpr void +constexpr void poly_vec_encode(std::span src, std::span dst) requires(ml_kem_params::check_k(k)) { @@ -116,7 +117,7 @@ poly_vec_encode(std::span src, std: // Given a byte array of length (k x 32 x l) -bytes, this routine decodes them into k degree-255 polynomials, writing them to a // column vector of dimension `k x 1`. template -static inline constexpr void +constexpr void poly_vec_decode(std::span src, std::span dst) requires(ml_kem_params::check_k(k)) { @@ -133,7 +134,7 @@ poly_vec_decode(std::span src, std::span -static inline constexpr void +constexpr void poly_vec_compress(std::span vec) requires(ml_kem_params::check_k(k)) { @@ -147,7 +148,7 @@ poly_vec_compress(std::span vec) // Given a vector ( of dimension `k x 1` ) of degree-255 polynomials, each of k * 256 coefficients are decompressed, while mutating input. template -static inline constexpr void +constexpr void poly_vec_decompress(std::span vec) requires(ml_kem_params::check_k(k)) { diff --git a/include/ml_kem/internals/poly/sampling.hpp b/include/ml_kem/internals/poly/sampling.hpp index 81e7464..a19c0e2 100644 --- a/include/ml_kem/internals/poly/sampling.hpp +++ b/include/ml_kem/internals/poly/sampling.hpp @@ -1,6 +1,7 @@ #pragma once #include "ml_kem/internals/math/field.hpp" #include "ml_kem/internals/poly/ntt.hpp" +#include "ml_kem/internals/utility/force_inline.hpp" #include "ml_kem/internals/utility/params.hpp" #include "shake128.hpp" #include "shake256.hpp" @@ -15,7 +16,7 @@ namespace ml_kem_utils { // statiscally close to randomly sampled elements of R_q. // // See algorithm 6 of ML-KEM specification https://doi.org/10.6028/NIST.FIPS.203.ipd. -inline constexpr void +forceinline constexpr void sample_ntt(shake128::shake128_t& hasher, std::span poly) { constexpr size_t n = poly.size(); @@ -48,7 +49,7 @@ sample_ntt(shake128::shake128_t& hasher, std::span -static inline constexpr void +constexpr void generate_matrix(std::span mat, std::span rho) requires(ml_kem_params::check_k(k)) { @@ -82,7 +83,7 @@ generate_matrix(std::span mat, std::s // // See algorithm 7 of ML-KEM specification https://doi.org/10.6028/NIST.FIPS.203.ipd. template -static inline constexpr void +constexpr void sample_poly_cbd(std::span prf, std::span poly) requires(ml_kem_params::check_eta(eta)) { @@ -132,7 +133,7 @@ sample_poly_cbd(std::span prf, std::span -static inline constexpr void +constexpr void generate_vector(std::span vec, std::span sigma, const uint8_t nonce) requires((k == 1) || ml_kem_params::check_k(k)) { diff --git a/include/ml_kem/internals/poly/serialize.hpp b/include/ml_kem/internals/poly/serialize.hpp index 38baf25..1d96c70 100644 --- a/include/ml_kem/internals/poly/serialize.hpp +++ b/include/ml_kem/internals/poly/serialize.hpp @@ -10,7 +10,7 @@ namespace ml_kem_utils { // // See algorithm 4 of ML-KEM specification https://doi.org/10.6028/NIST.FIPS.203.ipd. template -static inline constexpr void +constexpr void encode(std::span poly, std::span arr) requires(ml_kem_params::check_l(l)) { @@ -144,7 +144,7 @@ encode(std::span poly, std::span -static inline constexpr void +constexpr void decode(std::span arr, std::span poly) requires(ml_kem_params::check_l(l)) { diff --git a/include/ml_kem/internals/rng/prng.hpp b/include/ml_kem/internals/rng/prng.hpp index 301ee4d..a9eac63 100644 --- a/include/ml_kem/internals/rng/prng.hpp +++ b/include/ml_kem/internals/rng/prng.hpp @@ -1,4 +1,5 @@ #pragma once +#include "ml_kem/internals/utility/force_inline.hpp" #include "shake256.hpp" #include #include @@ -24,7 +25,7 @@ private: public: // Default constructor which seeds PRNG with system randomness. - inline prng_t() + forceinline prng_t() { std::array::digits> seed{}; auto _seed = std::span(seed); @@ -45,14 +46,14 @@ public: } // Explicit constructor which can be used for seeding PRNG. - inline explicit constexpr prng_t(std::span::digits> seed) + forceinline explicit constexpr prng_t(std::span::digits> seed) { state.absorb(seed); state.finalize(); } // Once PRNG is seeded i.e. PRNG object is constructed, you can request arbitrary many pseudo-random bytes from PRNG. - inline constexpr void read(std::span bytes) { state.squeeze(bytes); } + forceinline constexpr void read(std::span bytes) { state.squeeze(bytes); } }; } diff --git a/include/ml_kem/internals/utility/force_inline.hpp b/include/ml_kem/internals/utility/force_inline.hpp new file mode 100644 index 0000000..81c277e --- /dev/null +++ b/include/ml_kem/internals/utility/force_inline.hpp @@ -0,0 +1,29 @@ +#pragma once + +// Following content is taken from https://github.com/itzmeanjan/raccoon/blob/bfa45f9f22ea7b98f5d6588a8513ff4182af79ca/include/raccoon/internals/utility/force_inline.hpp + +#ifdef _MSC_VER +// MSVC +#define forceinline __forceinline + +#elif defined(__GNUC__) +// GCC +#if defined(__cplusplus) && __cplusplus >= 201103L +#define forceinline inline __attribute__((__always_inline__)) +#else +#define forceinline inline +#endif + +#elif defined(__CLANG__) +// Clang +#if __has_attribute(__always_inline__) +#define forceinline inline __attribute__((__always_inline__)) +#else +#define forceinline inline +#endif + +#else +// Others +#define forceinline inline + +#endif diff --git a/include/ml_kem/internals/utility/utils.hpp b/include/ml_kem/internals/utility/utils.hpp index 0be04e0..a0359a1 100644 --- a/include/ml_kem/internals/utility/utils.hpp +++ b/include/ml_kem/internals/utility/utils.hpp @@ -1,4 +1,5 @@ #pragma once +#include "ml_kem/internals/utility/force_inline.hpp" #include "subtle.hpp" #include @@ -7,7 +8,7 @@ namespace ml_kem_utils { // Given two byte arrays of equal length, this routine can be used for comparing them in constant-time, // producing truth value (0xffffffff) in case of equality, otherwise it returns false value (0x00000000). template -static inline constexpr uint32_t +forceinline constexpr uint32_t ct_memcmp(std::span bytes0, std::span bytes1) { uint32_t flag = -1u; @@ -24,7 +25,7 @@ ct_memcmp(std::span bytes0, std::span bytes1 // // In simple words, `sink = cond ? source0 ? source1` template -static inline constexpr void +forceinline constexpr void ct_cond_memcpy(const uint32_t cond, std::span sink, std::span source0, std::span source1) { for (size_t i = 0; i < n; i++) { @@ -33,42 +34,42 @@ ct_cond_memcpy(const uint32_t cond, std::span sink, std::span d, std::span z, std::span pubkey, @@ -45,7 +45,7 @@ keygen(std::span d, // Given seed `m` and a ML-KEM-1024 public key, this routine computes a ML-KEM-1024 cipher text and a fixed size shared secret. // If, input ML-KEM-1024 public key is malformed, encapsulation will fail, returning false. -[[nodiscard("If public key is malformed, encapsulation fails")]] inline constexpr bool +[[nodiscard("If public key is malformed, encapsulation fails")]] constexpr bool encapsulate(std::span m, std::span pubkey, std::span cipher, @@ -55,7 +55,7 @@ encapsulate(std::span m, } // Given a ML-KEM-1024 secret key and a cipher text, this routine computes a fixed size shared secret. -inline constexpr void +constexpr void decapsulate(std::span seckey, std::span cipher, std::span shared_secret) { ml_kem::decapsulate(seckey, cipher, shared_secret); diff --git a/include/ml_kem/ml_kem_512.hpp b/include/ml_kem/ml_kem_512.hpp index 7708a4f..ca851fb 100644 --- a/include/ml_kem/ml_kem_512.hpp +++ b/include/ml_kem/ml_kem_512.hpp @@ -6,35 +6,35 @@ namespace ml_kem_512 { // ML-KEM Key Encapsulation Mechanism instantiated with ML-KEM-512 parameters // See row 1 of table 2 of ML-KEM specification @ https://doi.org/10.6028/NIST.FIPS.203.ipd -static constexpr size_t k = 2; -static constexpr size_t η1 = 3; -static constexpr size_t η2 = 2; -static constexpr size_t du = 10; -static constexpr size_t dv = 4; +inline constexpr size_t k = 2; +inline constexpr size_t η1 = 3; +inline constexpr size_t η2 = 2; +inline constexpr size_t du = 10; +inline constexpr size_t dv = 4; // 32 -bytes seed `d`, used in underlying K-PKE key generation -static constexpr size_t SEED_D_BYTE_LEN = 32; +inline constexpr size_t SEED_D_BYTE_LEN = 32; // 32 -bytes seed `z`, used in ML-KEM key generation -static constexpr size_t SEED_Z_BYTE_LEN = 32; +inline constexpr size_t SEED_Z_BYTE_LEN = 32; // 800 -bytes ML-KEM-512 public key -static constexpr size_t PKEY_BYTE_LEN = ml_kem_utils::get_kem_public_key_len(k); +inline constexpr size_t PKEY_BYTE_LEN = ml_kem_utils::get_kem_public_key_len(k); // 1632 -bytes ML-KEM-512 secret key -static constexpr size_t SKEY_BYTE_LEN = ml_kem_utils::get_kem_secret_key_len(k); +inline constexpr size_t SKEY_BYTE_LEN = ml_kem_utils::get_kem_secret_key_len(k); // 32 -bytes seed `m`, used in ML-KEM encapsulation -static constexpr size_t SEED_M_BYTE_LEN = 32; +inline constexpr size_t SEED_M_BYTE_LEN = 32; // 768 -bytes ML-KEM-512 cipher text -static constexpr size_t CIPHER_TEXT_BYTE_LEN = ml_kem_utils::get_kem_cipher_text_len(k, du, dv); +inline constexpr size_t CIPHER_TEXT_BYTE_LEN = ml_kem_utils::get_kem_cipher_text_len(k, du, dv); // 32 -bytes ML-KEM-512 shared secret -static constexpr size_t SHARED_SECRET_BYTE_LEN = 32; +inline constexpr size_t SHARED_SECRET_BYTE_LEN = 32; // Computes a new ML-KEM-512 keypair, given seed `d` and `z`. -inline constexpr void +constexpr void keygen(std::span d, std::span z, std::span pubkey, @@ -45,7 +45,7 @@ keygen(std::span d, // Given seed `m` and a ML-KEM-512 public key, this routine computes a ML-KEM-512 cipher text and a fixed size shared secret. // If, input ML-KEM-512 public key is malformed, encapsulation will fail, returning false. -[[nodiscard("If public key is malformed, encapsulation fails")]] inline constexpr bool +[[nodiscard("If public key is malformed, encapsulation fails")]] constexpr bool encapsulate(std::span m, std::span pubkey, std::span cipher, @@ -55,7 +55,7 @@ encapsulate(std::span m, } // Given a ML-KEM-512 secret key and a cipher text, this routine computes a fixed size shared secret. -inline constexpr void +constexpr void decapsulate(std::span seckey, std::span cipher, std::span shared_secret) { ml_kem::decapsulate(seckey, cipher, shared_secret); diff --git a/include/ml_kem/ml_kem_768.hpp b/include/ml_kem/ml_kem_768.hpp index 15a9d5d..049944e 100644 --- a/include/ml_kem/ml_kem_768.hpp +++ b/include/ml_kem/ml_kem_768.hpp @@ -6,35 +6,35 @@ namespace ml_kem_768 { // ML-KEM Key Encapsulation Mechanism instantiated with ML-KEM-768 parameters // See row 2 of table 2 of ML-KEM specification @ https://doi.org/10.6028/NIST.FIPS.203.ipd -static constexpr size_t k = 3; -static constexpr size_t η1 = 2; -static constexpr size_t η2 = 2; -static constexpr size_t du = 10; -static constexpr size_t dv = 4; +inline constexpr size_t k = 3; +inline constexpr size_t η1 = 2; +inline constexpr size_t η2 = 2; +inline constexpr size_t du = 10; +inline constexpr size_t dv = 4; // 32 -bytes seed `d`, used in underlying K-PKE key generation -static constexpr size_t SEED_D_BYTE_LEN = 32; +inline constexpr size_t SEED_D_BYTE_LEN = 32; // 32 -bytes seed `z`, used in ML-KEM key generation -static constexpr size_t SEED_Z_BYTE_LEN = 32; +inline constexpr size_t SEED_Z_BYTE_LEN = 32; // 1184 -bytes ML-KEM-768 public key -static constexpr size_t PKEY_BYTE_LEN = ml_kem_utils::get_kem_public_key_len(k); +inline constexpr size_t PKEY_BYTE_LEN = ml_kem_utils::get_kem_public_key_len(k); // 2400 -bytes ML-KEM-768 secret key -static constexpr size_t SKEY_BYTE_LEN = ml_kem_utils::get_kem_secret_key_len(k); +inline constexpr size_t SKEY_BYTE_LEN = ml_kem_utils::get_kem_secret_key_len(k); // 32 -bytes seed `m`, used in ML-KEM encapsulation -static constexpr size_t SEED_M_BYTE_LEN = 32; +inline constexpr size_t SEED_M_BYTE_LEN = 32; // 1088 -bytes ML-KEM-768 cipher text -static constexpr size_t CIPHER_TEXT_BYTE_LEN = ml_kem_utils::get_kem_cipher_text_len(k, du, dv); +inline constexpr size_t CIPHER_TEXT_BYTE_LEN = ml_kem_utils::get_kem_cipher_text_len(k, du, dv); // 32 -bytes ML-KEM-768 shared secret -static constexpr size_t SHARED_SECRET_BYTE_LEN = 32; +inline constexpr size_t SHARED_SECRET_BYTE_LEN = 32; // Computes a new ML-KEM-768 keypair, given seed `d` and `z`. -inline constexpr void +constexpr void keygen(std::span d, std::span z, std::span pubkey, @@ -45,7 +45,7 @@ keygen(std::span d, // Given seed `m` and a ML-KEM-768 public key, this routine computes a ML-KEM-768 cipher text and a fixed size shared secret. // If, input ML-KEM-768 public key is malformed, encapsulation will fail, returning false. -[[nodiscard("If public key is malformed, encapsulation fails")]] inline constexpr bool +[[nodiscard("If public key is malformed, encapsulation fails")]] constexpr bool encapsulate(std::span m, std::span pubkey, std::span cipher, @@ -55,7 +55,7 @@ encapsulate(std::span m, } // Given a ML-KEM-768 secret key and a cipher text, this routine computes a fixed size shared secret. -inline constexpr void +constexpr void decapsulate(std::span seckey, std::span cipher, std::span shared_secret) { ml_kem::decapsulate(seckey, cipher, shared_secret);