Botan 3.11.0
Crypto and TLS for C&
prf_x942.cpp
Go to the documentation of this file.
1/*
2* X9.42 PRF
3* (C) 1999-2007 Jack Lloyd
4* (C) 2024 René Meusel, Rohde & Schwarz Cybersecurity
5*
6* Botan is released under the Simplified BSD License (see license.txt)
7*/
8
9#include <botan/internal/prf_x942.h>
10
11#include <botan/der_enc.h>
12#include <botan/hash.h>
13#include <botan/internal/bit_ops.h>
14#include <botan/internal/buffer_stuffer.h>
15#include <botan/internal/concat_util.h>
16#include <botan/internal/loadstor.h>
17
18namespace Botan {
19
20namespace {
21
22/*
23* Encode an integer as an OCTET STRING
24*/
25std::vector<uint8_t> encode_x942_int(uint32_t n) {
26 const auto n_buf = store_be(n);
27
28 std::vector<uint8_t> output;
29 DER_Encoder(output).encode(n_buf.data(), n_buf.size(), ASN1_Type::OctetString);
30 return output;
31}
32
33} // namespace
34
35void X942_PRF::perform_kdf(std::span<uint8_t> key,
36 std::span<const uint8_t> secret,
37 std::span<const uint8_t> salt,
38 std::span<const uint8_t> label) const {
39 if(key.empty()) {
40 return;
41 }
42
43 constexpr size_t sha1_output_bytes = 20; // Fixed to use SHA-1
44 const auto blocks_required = ceil_division<uint64_t /* for 32bit systems */>(key.size(), sha1_output_bytes);
45
46 // This KDF uses a 32-bit counter for the hash blocks, initialized at 1.
47 // It will wrap around after 2^32 - 1 iterations limiting the theoretically
48 // possible output to 2^32 - 1 blocks.
49 BOTAN_ARG_CHECK(blocks_required <= 0xFFFFFFFE, "X942_PRF maximum output length exceeded");
50
51 auto hash = HashFunction::create("SHA-1");
52 const auto in = concat<secure_vector<uint8_t>>(label, salt);
53
54 BufferStuffer k(key);
55 for(uint32_t counter = 1; !k.full(); ++counter) {
56 BOTAN_ASSERT_NOMSG(counter != 0); // overflow check
57
58 hash->update(secret);
59 hash->update(
60 DER_Encoder()
61 .start_sequence()
62
63 .start_sequence()
64 .encode(m_key_wrap_oid)
65 .raw_bytes(encode_x942_int(counter))
66 .end_cons()
67
68 .encode_if(!salt.empty(), DER_Encoder().start_explicit(0).encode(in, ASN1_Type::OctetString).end_explicit())
69
70 .start_explicit(2)
71 .raw_bytes(encode_x942_int(static_cast<uint32_t>(8 * key.size())))
72 .end_explicit()
73
74 .end_cons()
75 .get_contents());
76
77 // Write straight into the output buffer, except if the hash output needs
78 // a truncation in the final iteration.
79 if(k.remaining_capacity() >= sha1_output_bytes) {
80 hash->final(k.next(sha1_output_bytes));
81 } else {
82 std::array<uint8_t, sha1_output_bytes> h{};
83 hash->final(h);
84 k.append(std::span{h}.first(k.remaining_capacity()));
85 }
86 }
87}
88
89std::string X942_PRF::name() const {
90 return "X9.42-PRF(" + m_key_wrap_oid.to_formatted_string() + ")";
91}
92
93} // namespace Botan
#define BOTAN_ASSERT_NOMSG(expr)
Definition assert.h:75
#define BOTAN_ARG_CHECK(expr, msg)
Definition assert.h:33
DER_Encoder & encode(bool b)
Definition der_enc.cpp:252
static std::unique_ptr< HashFunction > create(std::string_view algo_spec, std::string_view provider="")
Definition hash.cpp:111
std::string name() const override
Definition prf_x942.cpp:89
std::string encode(const uint8_t der[], size_t length, std::string_view label, size_t width)
Definition pem.cpp:39
BOTAN_FORCE_INLINE constexpr T ceil_division(T a, T b)
Definition bit_ops.h:167
constexpr auto concat(Rs &&... ranges)
Definition concat_util.h:90
constexpr auto store_be(ParamTs &&... params)
Definition loadstor.h:745