Botan 3.11.0
Crypto and TLS for C&
kyber_symmetric_primitives.h
Go to the documentation of this file.
1/*
2 * Symmetric primitives for Kyber (modern)
3 * (C) 2022 Jack Lloyd
4 * (C) 2022 Hannes Rantzsch, René Meusel, neXenio GmbH
5 * (C) 2024 René Meusel, Rohde & Schwarz Cybersecurity
6 *
7 * Botan is released under the Simplified BSD License (see license.txt)
8 */
9
10#ifndef BOTAN_KYBER_SYMMETRIC_PRIMITIVES_H_
11#define BOTAN_KYBER_SYMMETRIC_PRIMITIVES_H_
12
13#include <botan/hash.h>
14#include <botan/xof.h>
15#include <botan/internal/buffer_slicer.h>
16#include <botan/internal/kyber_constants.h>
17#include <botan/internal/kyber_types.h>
18
19#include <span>
20#include <tuple>
21
22namespace Botan {
23
24/**
25 * Adapter class that uses polymorphy to distinguish
26 * Kyber "modern" from Kyber "90s" modes.
27 */
28class Kyber_Symmetric_Primitives /* NOLINT(*-special-member-functions) */ {
29 public:
30 virtual ~Kyber_Symmetric_Primitives() = default;
31
32 // TODO: remove this once Kyber-R3 is removed
34
35 // TODO: remove this once Kyber-R3 is removed
39
43
44 std::pair<KyberSeedRho, KyberSeedSigma> G(StrongSpan<const KyberSeedRandomness> seed,
45 const KyberConstants& mode) const {
46 if(auto domsep = seed_expansion_domain_separator(mode)) {
47 return G_split<KyberSeedRho, KyberSeedSigma>(seed, *domsep);
48 } else {
49 return G_split<KyberSeedRho, KyberSeedSigma>(seed);
50 }
51 }
52
53 std::pair<KyberSharedSecret, KyberEncryptionRandomness> G(
55 return G_split<KyberSharedSecret, KyberEncryptionRandomness>(msg, pubkey_hash);
56 }
57
60 auto j = create_J();
61 j->update(rejection_value);
62 j->update(ciphertext);
63 return j->final<KyberSharedSecret>();
64 }
65
66 // TODO: remove this once Kyber-R3 is removed
69 StrongSpan<const KyberHashedCiphertext> hashed_ciphertext) const {
70 auto kdf = create_KDF();
71 kdf->update(shared_secret);
72 kdf->update(hashed_ciphertext);
73 kdf->final(out);
74 }
75
77 const uint8_t nonce,
78 const size_t outlen) const {
79 auto bare_seed_span = std::visit([&](const auto s) { return s.get(); }, seed);
80 return create_PRF(bare_seed_span, nonce)->output<KyberSamplingRandomness>(outlen);
81 }
82
83 /// Setup an XOF object for matrix sampling
84 void setup_XOF(std::unique_ptr<Botan::XOF>& xof,
86 std::tuple<uint8_t, uint8_t> matrix_position) const {
87 if(!xof) {
88 xof = create_XOF(seed, matrix_position);
89 } else {
90 init_XOF(*xof, seed, matrix_position);
91 }
92 }
93
94 /// Setup a seeded PRF XOF for polynomial sampling
95 void setup_PRF(std::unique_ptr<Botan::XOF>& xof, std::span<const uint8_t> seed, uint8_t nonce) const {
96 if(!xof) {
97 xof = create_PRF(seed, nonce);
98 } else {
99 init_PRF(*xof, seed, nonce);
100 }
101 }
102
103 private:
106 ranges::contiguous_range... InputTs>
107 std::pair<T1, T2> G_split(const InputTs&... inputs) const {
108 auto g = create_G();
109 (g->update(inputs), ...);
110 const auto s = g->final();
111
112 BufferSlicer bs(s);
113 std::pair<T1, T2> result;
114 result.first = bs.copy<T1>(KyberConstants::SEED_BYTES);
115 result.second = bs.copy<T2>(KyberConstants::SEED_BYTES);
116 BOTAN_ASSERT_NOMSG(bs.empty());
117 return result;
118 }
119
120 protected:
121 virtual std::optional<std::array<uint8_t, 1>> seed_expansion_domain_separator(
122 const KyberConstants& mode) const = 0;
123
124 virtual std::unique_ptr<HashFunction> create_G() const = 0;
125 virtual std::unique_ptr<HashFunction> create_H() const = 0;
126 virtual std::unique_ptr<HashFunction> create_J() const = 0;
127 virtual std::unique_ptr<HashFunction> create_KDF() const = 0;
128
129 virtual std::unique_ptr<Botan::XOF> create_PRF(std::span<const uint8_t> seed, uint8_t nonce) const = 0;
130 virtual void init_PRF(Botan::XOF& xof, std::span<const uint8_t> seed, uint8_t nonce) const = 0;
131
132 virtual std::unique_ptr<Botan::XOF> create_XOF(std::span<const uint8_t> seed,
133 std::tuple<uint8_t, uint8_t> matrix_position) const = 0;
134 virtual void init_XOF(Botan::XOF& xof,
135 std::span<const uint8_t> seed,
136 std::tuple<uint8_t, uint8_t> matrix_position) const = 0;
137};
138
139} // namespace Botan
140
141#endif
#define BOTAN_ASSERT_NOMSG(expr)
Definition assert.h:75
static constexpr size_t SEED_BYTES
virtual ~Kyber_Symmetric_Primitives()=default
KyberMessage H(StrongSpan< const KyberMessage > m) const
void setup_XOF(std::unique_ptr< Botan::XOF > &xof, StrongSpan< const KyberSeedRho > seed, std::tuple< uint8_t, uint8_t > matrix_position) const
Setup an XOF object for matrix sampling.
virtual void init_XOF(Botan::XOF &xof, std::span< const uint8_t > seed, std::tuple< uint8_t, uint8_t > matrix_position) const =0
KyberHashedCiphertext H(StrongSpan< const KyberCompressedCiphertext > r) const
void setup_PRF(std::unique_ptr< Botan::XOF > &xof, std::span< const uint8_t > seed, uint8_t nonce) const
Setup a seeded PRF XOF for polynomial sampling.
virtual std::unique_ptr< Botan::XOF > create_XOF(std::span< const uint8_t > seed, std::tuple< uint8_t, uint8_t > matrix_position) const =0
void KDF(StrongSpan< KyberSharedSecret > out, StrongSpan< const KyberSharedSecret > shared_secret, StrongSpan< const KyberHashedCiphertext > hashed_ciphertext) const
KyberSamplingRandomness PRF(KyberSigmaOrEncryptionRandomness seed, const uint8_t nonce, const size_t outlen) const
virtual std::unique_ptr< Botan::XOF > create_PRF(std::span< const uint8_t > seed, uint8_t nonce) const =0
virtual std::unique_ptr< HashFunction > create_G() const =0
virtual std::unique_ptr< HashFunction > create_H() const =0
std::pair< KyberSharedSecret, KyberEncryptionRandomness > G(StrongSpan< const KyberMessage > msg, StrongSpan< const KyberHashedPublicKey > pubkey_hash) const
KyberSharedSecret J(StrongSpan< const KyberImplicitRejectionValue > rejection_value, StrongSpan< const KyberCompressedCiphertext > ciphertext) const
virtual std::unique_ptr< HashFunction > create_J() const =0
std::pair< KyberSeedRho, KyberSeedSigma > G(StrongSpan< const KyberSeedRandomness > seed, const KyberConstants &mode) const
virtual void init_PRF(Botan::XOF &xof, std::span< const uint8_t > seed, uint8_t nonce) const =0
KyberHashedPublicKey H(StrongSpan< const KyberSerializedPublicKey > pk) const
virtual std::unique_ptr< HashFunction > create_KDF() const =0
virtual std::optional< std::array< uint8_t, 1 > > seed_expansion_domain_separator(const KyberConstants &mode) const =0
Strong< secure_vector< uint8_t >, struct KyberMessage_ > KyberMessage
Random message value to be encrypted by the CPA-secure Kyber encryption scheme.
Definition kyber_types.h:45
Strong< secure_vector< uint8_t >, struct KyberSamplingRandomness_ > KyberSamplingRandomness
PRF value used for sampling of error polynomials.
Definition kyber_types.h:51
Strong< std::vector< uint8_t >, struct KyberHashedCiphertext_ > KyberHashedCiphertext
Definition kyber_types.h:67
std::variant< StrongSpan< const KyberSeedSigma >, StrongSpan< const KyberEncryptionRandomness > > KyberSigmaOrEncryptionRandomness
Variant value of either a KyberSeedSigma or a KyberEncryptionRandomness.
Definition kyber_types.h:70
Strong< secure_vector< uint8_t >, struct KyberSharedSecret_ > KyberSharedSecret
Shared secret value generated during encapsulation and recovered during decapsulation.
Definition kyber_types.h:54
Strong< std::vector< uint8_t >, struct KyberHashedPublicKey_ > KyberHashedPublicKey
Hash value of the serialized public key.
Definition kyber_types.h:60