Botan 3.7.1
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/loadstor.h>
15#include <botan/internal/stl_util.h>
16
17namespace Botan {
18
19namespace {
20
21/*
22* Encode an integer as an OCTET STRING
23*/
24std::vector<uint8_t> encode_x942_int(uint32_t n) {
25 const auto n_buf = store_be(n);
26
27 std::vector<uint8_t> output;
28 DER_Encoder(output).encode(n_buf.data(), n_buf.size(), ASN1_Type::OctetString);
29 return output;
30}
31
32} // namespace
33
34void X942_PRF::perform_kdf(std::span<uint8_t> key,
35 std::span<const uint8_t> secret,
36 std::span<const uint8_t> salt,
37 std::span<const uint8_t> label) const {
38 if(key.empty()) {
39 return;
40 }
41
42 constexpr size_t sha1_output_bytes = 20; // Fixed to use SHA-1
43 const auto blocks_required = ceil_division<uint64_t /* for 32bit systems */>(key.size(), sha1_output_bytes);
44
45 // This KDF uses a 32-bit counter for the hash blocks, initialized at 1.
46 // It will wrap around after 2^32 - 1 iterations limiting the theoretically
47 // possible output to 2^32 - 1 blocks.
48 BOTAN_ARG_CHECK(blocks_required <= 0xFFFFFFFE, "X942_PRF maximum output length exceeeded");
49
50 auto hash = HashFunction::create("SHA-1");
51 const auto in = concat<secure_vector<uint8_t>>(label, salt);
52
53 BufferStuffer k(key);
54 for(uint32_t counter = 1; !k.full(); ++counter) {
55 BOTAN_ASSERT_NOMSG(counter != 0); // overflow check
56
57 hash->update(secret);
58 hash->update(
59 DER_Encoder()
60 .start_sequence()
61
62 .start_sequence()
63 .encode(m_key_wrap_oid)
64 .raw_bytes(encode_x942_int(counter))
65 .end_cons()
66
67 .encode_if(!salt.empty(), DER_Encoder().start_explicit(0).encode(in, ASN1_Type::OctetString).end_explicit())
68
69 .start_explicit(2)
70 .raw_bytes(encode_x942_int(static_cast<uint32_t>(8 * key.size())))
71 .end_explicit()
72
73 .end_cons()
74 .get_contents());
75
76 // Write straight into the output buffer, except if the hash output needs
77 // a truncation in the final iteration.
78 if(k.remaining_capacity() >= sha1_output_bytes) {
79 hash->final(k.next(sha1_output_bytes));
80 } else {
81 std::array<uint8_t, sha1_output_bytes> h;
82 hash->final(h);
83 k.append(std::span{h}.first(k.remaining_capacity()));
84 }
85 }
86}
87
88std::string X942_PRF::name() const {
89 return "X9.42-PRF(" + m_key_wrap_oid.to_formatted_string() + ")";
90}
91
92} // namespace Botan
#define BOTAN_ASSERT_NOMSG(expr)
Definition assert.h:59
#define BOTAN_ARG_CHECK(expr, msg)
Definition assert.h:29
static std::unique_ptr< HashFunction > create(std::string_view algo_spec, std::string_view provider="")
Definition hash.cpp:107
std::string to_formatted_string() const
Definition asn1_oid.cpp:139
std::string name() const override
Definition prf_x942.cpp:88
std::string encode(const uint8_t der[], size_t length, std::string_view label, size_t width)
Definition pem.cpp:39
constexpr T ceil_division(T a, T b)
Definition bit_ops.h:160
constexpr auto concat(Rs &&... ranges)
Definition stl_util.h:263
constexpr auto store_be(ParamTs &&... params)
Definition loadstor.h:773