/src/botan/src/lib/mac/kmac/kmac.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * KMAC |
3 | | * (C) 2023 Jack Lloyd |
4 | | * (C) 2023 Falko Strenzke |
5 | | * (C) 2023 René Meusel - Rohde & Schwarz Cybersecurity |
6 | | * |
7 | | * Botan is released under the Simplified BSD License (see license.txt) |
8 | | */ |
9 | | |
10 | | #include <botan/internal/kmac.h> |
11 | | |
12 | | #include <botan/internal/cshake_xof.h> |
13 | | #include <botan/internal/fmt.h> |
14 | | #include <botan/internal/keccak_helpers.h> |
15 | | |
16 | | namespace Botan { |
17 | | |
18 | | KMAC::KMAC(std::unique_ptr<cSHAKE_XOF> cshake, size_t output_bit_length) : |
19 | 0 | m_output_bit_length(output_bit_length), m_message_started(false), m_cshake(std::move(cshake)) { |
20 | 0 | BOTAN_ARG_CHECK(m_output_bit_length % 8 == 0, "KMAC output length must be full bytes"); |
21 | 0 | BOTAN_ARG_CHECK(m_output_bit_length > 0, "KMAC output length must be at least one byte"); |
22 | 0 | BOTAN_ASSERT_NONNULL(m_cshake); |
23 | 0 | } |
24 | | |
25 | 0 | KMAC::~KMAC() = default; |
26 | | |
27 | 0 | void KMAC::clear() { |
28 | 0 | zap(m_encoded_key); |
29 | 0 | m_message_started = false; |
30 | 0 | m_cshake->clear(); |
31 | 0 | } |
32 | | |
33 | 0 | size_t KMAC::output_length() const { |
34 | 0 | return m_output_bit_length / 8; |
35 | 0 | } |
36 | | |
37 | 0 | Key_Length_Specification KMAC::key_spec() const { |
38 | | // KMAC supports key lengths from zero up to 2²⁰⁴⁰ (2^(2040)) bits: |
39 | | // https://nvlpubs.nist.gov/nistpubs/specialpublications/nist.sp.800-185.pdf#page=28 |
40 | | // |
41 | | // However, we restrict the key length to 64 bytes in order to avoid allocation of overly |
42 | | // large memory stretches when client code works with the maximal key length. |
43 | 0 | return Key_Length_Specification(0, 64); |
44 | 0 | } |
45 | | |
46 | 0 | bool KMAC::has_keying_material() const { |
47 | 0 | return !m_encoded_key.empty(); |
48 | 0 | } |
49 | | |
50 | 0 | std::string KMAC::provider() const { |
51 | 0 | return m_cshake->provider(); |
52 | 0 | } |
53 | | |
54 | 0 | void KMAC::start_msg(const uint8_t nonce[], size_t nonce_len) { |
55 | 0 | assert_key_material_set(); |
56 | 0 | m_cshake->start({nonce, nonce_len}, {}); |
57 | 0 | m_cshake->update(m_encoded_key); |
58 | 0 | m_message_started = true; |
59 | 0 | } |
60 | | |
61 | 0 | void KMAC::add_data(std::span<const uint8_t> data) { |
62 | 0 | assert_key_material_set(!m_encoded_key.empty()); |
63 | 0 | if(!m_message_started) { |
64 | 0 | start(); |
65 | 0 | } |
66 | 0 | m_cshake->update(data); |
67 | 0 | } |
68 | | |
69 | 0 | void KMAC::final_result(std::span<uint8_t> output) { |
70 | 0 | assert_key_material_set(); |
71 | 0 | std::array<uint8_t, keccak_max_int_encoding_size()> encoded_output_length_buffer; |
72 | 0 | m_cshake->update(keccak_int_right_encode(encoded_output_length_buffer, m_output_bit_length)); |
73 | 0 | m_cshake->output(output.first(output_length())); |
74 | 0 | m_cshake->clear(); |
75 | 0 | m_message_started = false; |
76 | 0 | } |
77 | | |
78 | 0 | void KMAC::key_schedule(std::span<const uint8_t> key) { |
79 | 0 | clear(); |
80 | 0 | keccak_absorb_padded_strings_encoding(m_encoded_key, m_cshake->block_size(), key); |
81 | 0 | } |
82 | | |
83 | | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
84 | | |
85 | 0 | KMAC128::KMAC128(size_t output_bit_length) : KMAC(std::make_unique<cSHAKE_128_XOF>("KMAC"), output_bit_length) {} |
86 | | |
87 | 0 | std::string KMAC128::name() const { |
88 | 0 | return fmt("KMAC-128({})", output_length() * 8); |
89 | 0 | } |
90 | | |
91 | 0 | std::unique_ptr<MessageAuthenticationCode> KMAC128::new_object() const { |
92 | 0 | return std::make_unique<KMAC128>(output_length() * 8); |
93 | 0 | } |
94 | | |
95 | 0 | KMAC256::KMAC256(size_t output_bit_length) : KMAC(std::make_unique<cSHAKE_256_XOF>("KMAC"), output_bit_length) {} |
96 | | |
97 | 0 | std::string KMAC256::name() const { |
98 | 0 | return fmt("KMAC-256({})", output_length() * 8); |
99 | 0 | } |
100 | | |
101 | 0 | std::unique_ptr<MessageAuthenticationCode> KMAC256::new_object() const { |
102 | 0 | return std::make_unique<KMAC256>(output_length() * 8); |
103 | 0 | } |
104 | | |
105 | | } // namespace Botan |