/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 192 bytes in order to avoid allocation of overly |
42 | | // large memory stretches when client code works with the maximal key length. We chose a |
43 | | // boundary that contains the length of the default_salt of the one-step KDM with KMAC128 |
44 | | // of 164 bytes. (see NIST SP 800-56C Rev. 2, Section 4.1, Implementation-Dependent Parameters 3.). |
45 | 0 | return Key_Length_Specification(0, 192); |
46 | 0 | } |
47 | | |
48 | 0 | bool KMAC::has_keying_material() const { |
49 | 0 | return !m_encoded_key.empty(); |
50 | 0 | } |
51 | | |
52 | 0 | std::string KMAC::provider() const { |
53 | 0 | return m_cshake->provider(); |
54 | 0 | } |
55 | | |
56 | 0 | void KMAC::start_msg(std::span<const uint8_t> nonce) { |
57 | 0 | assert_key_material_set(); |
58 | 0 | m_cshake->start(nonce); |
59 | 0 | m_cshake->update(m_encoded_key); |
60 | 0 | m_message_started = true; |
61 | 0 | } |
62 | | |
63 | 0 | void KMAC::add_data(std::span<const uint8_t> data) { |
64 | 0 | assert_key_material_set(!m_encoded_key.empty()); |
65 | 0 | if(!m_message_started) { |
66 | 0 | start(); |
67 | 0 | } |
68 | 0 | m_cshake->update(data); |
69 | 0 | } |
70 | | |
71 | 0 | void KMAC::final_result(std::span<uint8_t> output) { |
72 | 0 | assert_key_material_set(); |
73 | 0 | std::array<uint8_t, keccak_max_int_encoding_size()> encoded_output_length_buffer; |
74 | 0 | m_cshake->update(keccak_int_right_encode(encoded_output_length_buffer, m_output_bit_length)); |
75 | 0 | m_cshake->output(output.first(output_length())); |
76 | 0 | m_cshake->clear(); |
77 | 0 | m_message_started = false; |
78 | 0 | } |
79 | | |
80 | 0 | void KMAC::key_schedule(std::span<const uint8_t> key) { |
81 | 0 | clear(); |
82 | 0 | keccak_absorb_padded_strings_encoding(m_encoded_key, m_cshake->block_size(), key); |
83 | 0 | } |
84 | | |
85 | | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
86 | | |
87 | 0 | KMAC128::KMAC128(size_t output_bit_length) : KMAC(std::make_unique<cSHAKE_128_XOF>("KMAC"), output_bit_length) {} |
88 | | |
89 | 0 | std::string KMAC128::name() const { |
90 | 0 | return fmt("KMAC-128({})", output_length() * 8); |
91 | 0 | } |
92 | | |
93 | 0 | std::unique_ptr<MessageAuthenticationCode> KMAC128::new_object() const { |
94 | 0 | return std::make_unique<KMAC128>(output_length() * 8); |
95 | 0 | } |
96 | | |
97 | 0 | KMAC256::KMAC256(size_t output_bit_length) : KMAC(std::make_unique<cSHAKE_256_XOF>("KMAC"), output_bit_length) {} |
98 | | |
99 | 0 | std::string KMAC256::name() const { |
100 | 0 | return fmt("KMAC-256({})", output_length() * 8); |
101 | 0 | } |
102 | | |
103 | 0 | std::unique_ptr<MessageAuthenticationCode> KMAC256::new_object() const { |
104 | 0 | return std::make_unique<KMAC256>(output_length() * 8); |
105 | 0 | } |
106 | | |
107 | | } // namespace Botan |