10#include <botan/internal/sp800_108.h> 
   12#include <botan/exceptn.h> 
   13#include <botan/internal/bit_ops.h> 
   14#include <botan/internal/fmt.h> 
   15#include <botan/internal/loadstor.h> 
   16#include <botan/internal/stl_util.h> 
   26      constexpr static void validate_bit_lengths(
size_t counter_bits, 
size_t output_length_bits) {
 
   28                         "SP.800-108 counter length may be one of {8, 16, 24, 32} only");
 
   29         BOTAN_ARG_CHECK(output_length_bits % 8 == 0 && output_length_bits <= 32,
 
   30                         "SP.800-108 output length encoding may be one of {8, 16, 24, 32} only");
 
   33      static CounterParams create_or_throw(
size_t output_bytes,
 
   34                                           size_t output_length_bits,
 
   36                                           size_t prf_output_bytes) {
 
   39         BOTAN_ARG_CHECK(
static_cast<uint64_t
>(output_bytes) * 8 <= std::numeric_limits<uint32_t>::max(),
 
   40                         "SP.800-108 output size in bits does not fit into 32-bits");
 
   41         const auto output_bits = 
static_cast<uint32_t
>(output_bytes * 8);
 
   42         const auto max_output_bits = (uint64_t(1) << output_length_bits) - 1;
 
   44                         "SP.800-108 output size does not fit into the requested field length");
 
   47         const auto blocks_required = 
ceil_division<uint64_t >(output_bytes, prf_output_bytes);
 
   52         const auto max_blocks = (uint64_t(1) << counter_bits) - 1;
 
   53         BOTAN_ARG_CHECK(blocks_required < max_blocks, 
"SP.800-108 output size too large");
 
   56            output_bits, output_length_bits / 8, counter_bits / 8, 
static_cast<uint32_t
>(blocks_required));
 
   59      template <std::invocable<std::span<const u
int8_t>, std::span<const u
int8_t>> Fn>
 
   60      constexpr void generate_blocks(Fn fn)
 const {
 
   61         const auto outlen_encoded = 
store_be(m_output_length_bits);
 
   62         for(uint32_t counter = 1; counter <= m_blocks_required; ++counter) {
 
   63            const auto counter_encoded = 
store_be(counter);
 
   64            fn(std::span{counter_encoded}.last(m_counter_bytes),
 
   65               std::span{outlen_encoded}.last(m_output_length_encoding_bytes));
 
   70      CounterParams(uint32_t output_length_bits,
 
   71                    size_t output_length_encoding_bytes,
 
   73                    uint32_t blocks_required) :
 
   74            m_output_length_bits(output_length_bits),
 
   75            m_output_length_encoding_bytes(output_length_encoding_bytes),
 
   76            m_counter_bytes(counter_bytes),
 
   77            m_blocks_required(blocks_required) {}
 
   80      uint32_t m_output_length_bits;
 
   81      size_t m_output_length_encoding_bytes;
 
   82      size_t m_counter_bytes;
 
   83      uint32_t m_blocks_required;
 
   89      m_prf(std::move(mac)), m_counter_bits(r), m_output_length_bits(L) {
 
   90   CounterParams::validate_bit_lengths(m_counter_bits, m_output_length_bits);
 
 
   95   return (m_counter_bits == 32 && m_output_length_bits == 32)
 
   96             ? 
fmt(
"SP800-108-Counter({})", m_prf->name())  
 
   97             : 
fmt(
"SP800-108-Counter({},{},{})", m_prf->name(), m_counter_bits, m_output_length_bits);
 
 
  101   return std::make_unique<SP800_108_Counter>(m_prf->new_object(), m_counter_bits, m_output_length_bits);
 
 
  104void SP800_108_Counter::perform_kdf(std::span<uint8_t> key,
 
  105                                    std::span<const uint8_t> secret,
 
  106                                    std::span<const uint8_t> salt,
 
  107                                    std::span<const uint8_t> label)
 const {
 
  112   const auto prf_len = m_prf->output_length();
 
  113   const auto params = CounterParams::create_or_throw(key.size(), m_output_length_bits, m_counter_bits, prf_len);
 
  115   constexpr uint8_t delim = 0;
 
  117   BufferStuffer k(key);
 
  118   m_prf->set_key(secret);
 
  120   params.generate_blocks([&](
auto counter_encoded, 
auto outlen_encoded) {
 
  121      m_prf->update(counter_encoded);
 
  122      m_prf->update(label);
 
  123      m_prf->update(delim);
 
  125      m_prf->update(outlen_encoded);
 
  129      if(k.remaining_capacity() >= prf_len) {
 
  130         m_prf->final(k.next(prf_len));
 
  132         const auto h = m_prf->final();
 
  133         k.append(std::span{h}.first(k.remaining_capacity()));
 
  141      m_prf(std::move(mac)), m_counter_bits(r), m_output_length_bits(L) {
 
  142   CounterParams::validate_bit_lengths(m_counter_bits, m_output_length_bits);
 
 
  147   return (m_counter_bits == 32 && m_output_length_bits == 32)
 
  148             ? 
fmt(
"SP800-108-Feedback({})", m_prf->name())  
 
  149             : 
fmt(
"SP800-108-Feedback({},{},{})", m_prf->name(), m_counter_bits, m_output_length_bits);
 
 
  153   return std::make_unique<SP800_108_Feedback>(m_prf->new_object(), m_counter_bits, m_output_length_bits);
 
 
  156void SP800_108_Feedback::perform_kdf(std::span<uint8_t> key,
 
  157                                     std::span<const uint8_t> secret,
 
  158                                     std::span<const uint8_t> salt,
 
  159                                     std::span<const uint8_t> label)
 const {
 
  164   const auto prf_len = m_prf->output_length();
 
  165   const auto iv_len = (salt.size() >= prf_len ? prf_len : 0);
 
  166   constexpr uint8_t delim = 0;
 
  167   const auto params = CounterParams::create_or_throw(key.size(), m_output_length_bits, m_counter_bits, prf_len);
 
  169   BufferSlicer s(salt);
 
  170   auto prev = s.copy_as_secure_vector(iv_len);
 
  171   const auto ctx = s.take(s.remaining());
 
  174   BufferStuffer k(key);
 
  175   m_prf->set_key(secret);
 
  177   params.generate_blocks([&](
auto counter_encoded, 
auto outlen_encoded) {
 
  179      m_prf->update(counter_encoded);
 
  180      m_prf->update(label);
 
  181      m_prf->update(delim);
 
  183      m_prf->update(outlen_encoded);
 
  186      const auto bytes_to_write = std::min(prev.size(), k.remaining_capacity());
 
  187      k.append(std::span{prev}.first(bytes_to_write));
 
  194      m_prf(std::move(mac)), m_counter_bits(r), m_output_length_bits(L) {
 
  195   CounterParams::validate_bit_lengths(m_counter_bits, m_output_length_bits);
 
 
  200   return (m_counter_bits == 32 && m_output_length_bits == 32)
 
  201             ? 
fmt(
"SP800-108-Pipeline({})", m_prf->name())  
 
  202             : 
fmt(
"SP800-108-Pipeline({},{},{})", m_prf->name(), m_counter_bits, m_output_length_bits);
 
 
  206   return std::make_unique<SP800_108_Pipeline>(m_prf->new_object(), m_counter_bits, m_output_length_bits);
 
 
  209void SP800_108_Pipeline::perform_kdf(std::span<uint8_t> key,
 
  210                                     std::span<const uint8_t> secret,
 
  211                                     std::span<const uint8_t> salt,
 
  212                                     std::span<const uint8_t> label)
 const {
 
  217   const auto prf_len = m_prf->output_length();
 
  218   constexpr uint8_t delim = 0;
 
  219   const auto params = CounterParams::create_or_throw(key.size(), m_output_length_bits, m_counter_bits, prf_len);
 
  221   BufferStuffer k(key);
 
  222   m_prf->set_key(secret);
 
  225   params.generate_blocks([&](
auto counter_encoded, 
auto outlen_encoded) {
 
  226      auto incorporate_constant_input = [label, salt, outlen_encoded](MessageAuthenticationCode* prf) {
 
  230         prf->update(outlen_encoded);
 
  233      if(scratch.empty()) {
 
  235         incorporate_constant_input(m_prf.get());
 
  236         scratch = m_prf->final();
 
  239         m_prf->update(scratch);
 
  240         m_prf->final(scratch);
 
  243      m_prf->update(scratch);
 
  244      m_prf->update(counter_encoded);
 
  245      incorporate_constant_input(m_prf.get());
 
  249      if(k.remaining_capacity() >= prf_len) {
 
  250         m_prf->final(k.next(prf_len));
 
  254         m_prf->final(scratch);
 
  255         k.append(std::span{scratch}.first(k.remaining_capacity()));
 
#define BOTAN_ASSERT_NOMSG(expr)
 
#define BOTAN_ARG_CHECK(expr, msg)
 
SP800_108_Counter(std::unique_ptr< MessageAuthenticationCode > mac, size_t r, size_t L)
 
std::string name() const override
 
std::unique_ptr< KDF > new_object() const override
 
std::string name() const override
 
SP800_108_Feedback(std::unique_ptr< MessageAuthenticationCode > mac, size_t r, size_t L)
 
std::unique_ptr< KDF > new_object() const override
 
std::unique_ptr< KDF > new_object() const override
 
std::string name() const override
 
SP800_108_Pipeline(std::unique_ptr< MessageAuthenticationCode > mac, size_t r, size_t L)
 
std::string fmt(std::string_view format, const T &... args)
 
BOTAN_FORCE_INLINE constexpr T ceil_division(T a, T b)
 
std::vector< T, secure_allocator< T > > secure_vector
 
constexpr auto store_be(ParamTs &&... params)