Botan 3.4.0
Crypto and TLS for C&
xmd.cpp
Go to the documentation of this file.
1/*
2* (C) 2019,2020,2021,2024 Jack Lloyd
3*
4* Botan is released under the Simplified BSD License (see license.txt)
5*/
6
7#include <botan/internal/xmd.h>
8
9#include <botan/exceptn.h>
10#include <botan/hash.h>
11#include <botan/internal/fmt.h>
12#include <vector>
13
14namespace Botan {
15
16void expand_message_xmd(std::string_view hash_fn,
17 std::span<uint8_t> output,
18 std::span<const uint8_t> input,
19 std::span<const uint8_t> domain_sep) {
20 if(domain_sep.size() > 0xFF) {
21 // RFC 9380 has a specification for handling this
22 throw Not_Implemented("XMD does not currently implement oversize DST handling");
23 }
24
25 const uint8_t domain_sep_len = static_cast<uint8_t>(domain_sep.size());
26
27 auto hash = HashFunction::create_or_throw(hash_fn);
28 const size_t block_size = hash->hash_block_size();
29 if(block_size == 0) {
30 throw Invalid_Argument(fmt("expand_message_xmd cannot be used with {}", hash_fn));
31 }
32
33 const size_t hash_output_size = hash->output_length();
34 if(output.size() > 255 * hash_output_size || output.size() > 0xFFFF) {
35 throw Invalid_Argument("expand_message_xmd requested output length too long");
36 }
37
38 // Compute b_0 = H(msg_prime) = H(Z_pad || msg || l_i_b_str || 0x00 || DST_prime)
39
40 hash->update(std::vector<uint8_t>(block_size));
41 hash->update(input);
42 hash->update_be(static_cast<uint16_t>(output.size()));
43 hash->update(0x00);
44 hash->update(domain_sep);
45 hash->update(domain_sep_len);
46
47 const secure_vector<uint8_t> b_0 = hash->final();
48
49 // Compute b_1 = H(b_0 || 0x01 || DST_prime)
50
51 hash->update(b_0);
52 hash->update(0x01);
53 hash->update(domain_sep);
54 hash->update(domain_sep_len);
55
56 secure_vector<uint8_t> b_i = hash->final();
57
58 uint8_t cnt = 2;
59 for(;;) {
60 const size_t produced = std::min(output.size(), hash_output_size);
61
62 copy_mem(&output[0], b_i.data(), produced);
63 output = output.subspan(produced);
64
65 if(output.empty()) {
66 break;
67 }
68
69 // Now compute the next b_i if needed
70
71 b_i ^= b_0;
72 hash->update(b_i);
73 hash->update(cnt);
74 hash->update(domain_sep);
75 hash->update(domain_sep_len);
76 hash->final(b_i);
77 cnt += 1;
78 }
79}
80
81} // namespace Botan
static std::unique_ptr< HashFunction > create_or_throw(std::string_view algo_spec, std::string_view provider="")
Definition hash.cpp:298
std::string fmt(std::string_view format, const T &... args)
Definition fmt.h:53
void expand_message_xmd(std::string_view hash_fn, std::span< uint8_t > output, std::span< const uint8_t > input, std::span< const uint8_t > domain_sep)
Definition xmd.cpp:16
std::vector< T, secure_allocator< T > > secure_vector
Definition secmem.h:61
constexpr void copy_mem(T *out, const T *in, size_t n)
Definition mem_ops.h:146