Coverage Report

Created: 2025-04-11 06:34

/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