Botan 3.6.0
Crypto and TLS for C&
kyber_helpers.h
Go to the documentation of this file.
1/*
2 * Crystals Kyber Internal 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_KYBER_HELPERS_H_
12#define BOTAN_KYBER_HELPERS_H_
13
14#include <botan/internal/ct_utils.h>
15#include <botan/internal/kyber_constants.h>
16#include <botan/internal/loadstor.h>
17#include <botan/internal/pqcrystals_helpers.h>
18
19namespace Botan::Kyber_Algos {
20
21/**
22 * Special load_le<> that takes 3 bytes and returns a 32-bit integer.
23 */
24inline uint32_t load_le3(std::span<const uint8_t, 3> in) {
25 return Botan::load_le(std::array<uint8_t, 4>{in[0], in[1], in[2], 0});
26}
27
28/**
29 * NIST FIPS 203, Formula 4.7 (Compress)
30 */
31template <size_t d>
32 requires(d > 0 && d < 12)
33constexpr std::make_unsigned_t<KyberConstants::T> compress(KyberConstants::T x) {
35 const uint32_t n = (static_cast<uint32_t>(x) << d) + KyberConstants::Q / 2;
36
37 // This is a mitigation for a potential side channel called "KyberSlash".
38 //
39 // It implements the division by Q using a multiplication and a shift. Most
40 // compilers would generate similar code for such a division by a constant.
41 // Though, in some cases, compilers might use a variable-time int division,
42 // resulting in a potential side channel.
43 //
44 // The constants below work for all values that appear in Kyber with the
45 // greatest being 3328 * 2^11 + Q // 2 = 6,817,408 < 2**23 = 8,388,608.
46 //
47 // See "Hacker's Delight" (Second Edition) by Henry S. Warren, Jr.
48 // Chapter 10-9 "Unsigned Division by Divisors >= 1"
49 BOTAN_DEBUG_ASSERT(n < (1 << 23));
50 static_assert(KyberConstants::Q == 3329);
51 using unsigned_T = std::make_unsigned_t<KyberConstants::T>;
52
53 constexpr uint64_t m = 2580335;
54 constexpr size_t p = 33;
55 constexpr unsigned_T mask = (1 << d) - 1;
56 return static_cast<unsigned_T>((n * m) >> p) & mask;
57};
58
59/**
60 * NIST FIPS 203, Formula 4.8 (Decompress)
61 */
62template <size_t d>
63 requires(d > 0 && d < 12)
64constexpr KyberConstants::T decompress(std::make_unsigned_t<KyberConstants::T> x) {
65 BOTAN_DEBUG_ASSERT(x >= 0 && x < (1 << d));
66
67 constexpr uint32_t offset = 1 << (d - 1);
68 constexpr uint32_t mask = (1 << d) - 1;
69 return static_cast<KyberConstants::T>(((static_cast<uint32_t>(x) & mask) * KyberConstants::Q + offset) >> d);
70}
71
72} // namespace Botan::Kyber_Algos
73
74#endif
#define BOTAN_DEBUG_ASSERT(expr)
Definition assert.h:98
static constexpr T Q
modulus
int16_t T
base data type for most calculations
constexpr std::make_unsigned_t< KyberConstants::T > compress(KyberConstants::T x)
uint32_t load_le3(std::span< const uint8_t, 3 > in)
constexpr KyberConstants::T decompress(std::make_unsigned_t< KyberConstants::T > x)
constexpr auto load_le(ParamTs &&... params)
Definition loadstor.h:521