11#include <botan/internal/sp800_56c_one_step.h>
13#include <botan/exceptn.h>
14#include <botan/internal/bit_ops.h>
15#include <botan/internal/fmt.h>
16#include <botan/internal/kmac.h>
24concept hash_or_mac_type = std::is_same_v<T, HashFunction> || std::is_same_v<T, MessageAuthenticationCode>;
29template <hash_or_mac_type HashOrMacType>
30void kdm_internal(std::span<uint8_t> output_buffer,
31 std::span<const uint8_t> z,
32 std::span<const uint8_t> fixed_info,
33 HashOrMacType& hash_or_mac,
34 const std::function<
void(HashOrMacType&)>& init_h_callback) {
35 size_t l = output_buffer.size() * 8;
40 size_t reps =
ceil_division(l, hash_or_mac.output_length() * 8);
62 for(
size_t i = 1; i <= reps; i++) {
67 init_h_callback(hash_or_mac);
70 hash_or_mac.update_be(counter);
71 hash_or_mac.update(z);
72 hash_or_mac.update(fixed_info);
73 auto k_i = hash_or_mac.final();
76 result.insert(result.end(), k_i.begin(), k_i.end());
80 copy_mem(output_buffer, std::span(result).subspan(0, output_buffer.size()));
87 const uint8_t secret[],
91 const uint8_t label[],
92 size_t label_len)
const {
94 BOTAN_ARG_CHECK(salt_len == 0,
"SP800_56A_Hash does not support a non-empty salt");
96 kdm_internal<HashFunction>(
97 {key, key_len}, {secret, secret_len}, {label, label_len}, *m_hash, [](
HashFunction&) { });
101 return fmt(
"SP800-56A({})", m_hash->name());
105 return std::make_unique<SP800_56C_One_Step_Hash>(m_hash->new_object());
109 m_mac(std::move(mac)) {
111 if(!m_mac->name().starts_with(
"HMAC(")) {
112 throw Algorithm_Not_Found(
"Only HMAC can be used with SP800_56A_HMAC");
118 const uint8_t secret[],
120 const uint8_t salt[],
122 const uint8_t label[],
123 size_t label_len)
const {
124 kdm_internal<MessageAuthenticationCode>(
134 kdf_mac.set_key(std::span{salt, salt_len});
139 return fmt(
"SP800-56A({})", m_mac->name());
143 return std::make_unique<SP800_56C_One_Step_HMAC>(m_mac->new_object());
149 const uint8_t secret[],
151 const uint8_t salt[],
153 const uint8_t label[],
154 size_t label_len)
const {
156 kdm_internal<MessageAuthenticationCode>(
169 kdf_mac.set_key(std::span{salt, salt_len});
175 kdf_mac.start(std::array<uint8_t, 3>{
'K',
'D',
'F'});
179std::unique_ptr<MessageAuthenticationCode> SP800_56C_One_Step_KMAC128::create_kmac_instance(
180 size_t output_byte_len)
const {
181 return std::make_unique<KMAC128>(output_byte_len * 8);
184std::unique_ptr<MessageAuthenticationCode> SP800_56C_One_Step_KMAC256::create_kmac_instance(
185 size_t output_byte_len)
const {
186 return std::make_unique<KMAC256>(output_byte_len * 8);
#define BOTAN_ARG_CHECK(expr, msg)
virtual std::unique_ptr< MessageAuthenticationCode > create_kmac_instance(size_t output_byte_len) const =0
void kdf(uint8_t key[], size_t key_len, const uint8_t secret[], size_t secret_len, const uint8_t salt[], size_t salt_len, const uint8_t label[], size_t label_len) const override
virtual size_t default_salt_length() const =0
See SP800-56C Section 4.1 - Implementation-Dependent Parameters 3.
SP800_56C_One_Step_HMAC(std::unique_ptr< MessageAuthenticationCode > mac)
void kdf(uint8_t key[], size_t key_len, const uint8_t secret[], size_t secret_len, const uint8_t salt[], size_t salt_len, const uint8_t label[], size_t label_len) const override
std::string name() const override
std::unique_ptr< KDF > new_object() const override
std::string name() const override
std::unique_ptr< KDF > new_object() const override
void kdf(uint8_t key[], size_t key_len, const uint8_t secret[], size_t secret_len, const uint8_t salt[], size_t salt_len, const uint8_t label[], size_t label_len) const override
std::string fmt(std::string_view format, const T &... args)
constexpr T ceil_division(T a, T b)
std::vector< T, secure_allocator< T > > secure_vector
constexpr void copy_mem(T *out, const T *in, size_t n)