/src/botan/build/include/internal/botan/internal/kyber_helpers.h
Line | Count | Source (jump to first uncovered line) |
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 | | |
19 | | namespace Botan::Kyber_Algos { |
20 | | |
21 | | /** |
22 | | * Special load_le<> that takes 3 bytes and returns a 32-bit integer. |
23 | | */ |
24 | 0 | inline uint32_t load_le3(std::span<const uint8_t, 3> in) { |
25 | 0 | return Botan::load_le(std::array<uint8_t, 4>{in[0], in[1], in[2], 0}); |
26 | 0 | } |
27 | | |
28 | | /** |
29 | | * NIST FIPS 203, Formula 4.7 (Compress) |
30 | | */ |
31 | | template <size_t d> |
32 | | requires(d > 0 && d < 12) |
33 | 0 | constexpr std::make_unsigned_t<KyberConstants::T> compress(KyberConstants::T x) { |
34 | 0 | BOTAN_DEBUG_ASSERT(x >= 0 && x < KyberConstants::Q); |
35 | 0 | 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 | 0 | BOTAN_DEBUG_ASSERT(n < (1 << 23)); |
50 | 0 | static_assert(KyberConstants::Q == 3329); |
51 | 0 | using unsigned_T = std::make_unsigned_t<KyberConstants::T>; |
52 | |
|
53 | 0 | constexpr uint64_t m = 2580335; |
54 | 0 | constexpr size_t p = 33; |
55 | 0 | constexpr unsigned_T mask = (1 << d) - 1; |
56 | 0 | return static_cast<unsigned_T>((n * m) >> p) & mask; |
57 | 0 | } Unexecuted instantiation: _ZN5Botan11Kyber_Algos8compressILm10EQaagtT_Li0EltT_Li12EEEts Unexecuted instantiation: _ZN5Botan11Kyber_Algos8compressILm11EQaagtT_Li0EltT_Li12EEEts Unexecuted instantiation: _ZN5Botan11Kyber_Algos8compressILm4EQaagtT_Li0EltT_Li12EEEts Unexecuted instantiation: _ZN5Botan11Kyber_Algos8compressILm5EQaagtT_Li0EltT_Li12EEEts Unexecuted instantiation: _ZN5Botan11Kyber_Algos8compressILm1EQaagtT_Li0EltT_Li12EEEts |
58 | | |
59 | | /** |
60 | | * NIST FIPS 203, Formula 4.8 (Decompress) |
61 | | */ |
62 | | template <size_t d> |
63 | | requires(d > 0 && d < 12) |
64 | 0 | constexpr KyberConstants::T decompress(std::make_unsigned_t<KyberConstants::T> x) { |
65 | 0 | BOTAN_DEBUG_ASSERT(x >= 0 && x < (1 << d)); |
66 | |
|
67 | 0 | constexpr uint32_t offset = 1 << (d - 1); |
68 | 0 | constexpr uint32_t mask = (1 << d) - 1; |
69 | 0 | return static_cast<KyberConstants::T>(((static_cast<uint32_t>(x) & mask) * KyberConstants::Q + offset) >> d); |
70 | 0 | } Unexecuted instantiation: _ZN5Botan11Kyber_Algos10decompressILm10EQaagtT_Li0EltT_Li12EEEst Unexecuted instantiation: _ZN5Botan11Kyber_Algos10decompressILm11EQaagtT_Li0EltT_Li12EEEst Unexecuted instantiation: _ZN5Botan11Kyber_Algos10decompressILm4EQaagtT_Li0EltT_Li12EEEst Unexecuted instantiation: _ZN5Botan11Kyber_Algos10decompressILm5EQaagtT_Li0EltT_Li12EEEst Unexecuted instantiation: _ZN5Botan11Kyber_Algos10decompressILm1EQaagtT_Li0EltT_Li12EEEst |
71 | | |
72 | | } // namespace Botan::Kyber_Algos |
73 | | |
74 | | #endif |