Botan 3.6.1
Crypto and TLS for C&
sp_hash_sha2.h
Go to the documentation of this file.
1/*
2 * SLH-DSA Hash Implementation for SHA-256
3 * (C) 2023 Jack Lloyd
4 * 2023 Fabian Albert, René Meusel, Amos Treiber - Rohde & Schwarz Cybersecurity
5 *
6 * Botan is released under the Simplified BSD License (see license.txt)
7 */
8
9#ifndef BOTAN_SP_HASH_SHA2_H_
10#define BOTAN_SP_HASH_SHA2_H_
11
12#include <botan/internal/sp_hash.h>
13
14#include <botan/internal/hmac.h>
15#include <botan/internal/mgf1.h>
16#include <botan/internal/sha2_32.h>
17#include <botan/internal/sha2_64.h>
18#include <botan/internal/stl_util.h>
19#include <botan/internal/trunc_hash.h>
20
21namespace Botan {
22
23/**
24 * Implementation of SLH-DSA hash function abstraction for SHA2
25 */
27 private:
28 HashFunction& tweak_hash(const Sphincs_Address& address, size_t input_length) override {
29 // Depending on the input length we decide to use SHA-256 (Function F
30 // in the spec) or SHA-X (Function T_l and H in the spec).
31 //
32 // All hashed values share a common prefix. Hence we could reuse the
33 // hash state after this prefix was consumed as an optimization.
34 //
35 // TODO: Currently, the `copy_state()` method would force us to perform
36 // a re-allocation whenever we want to do that.
37 auto& hash = (input_length > m_sphincs_params.n()) ? *m_sha_x : *m_sha_256;
38 const auto& padded_pub_seed =
39 (input_length > m_sphincs_params.n()) ? m_padded_pub_seed_x : m_padded_pub_seed_256;
40 hash.update(padded_pub_seed);
41 hash.update(address.to_bytes_compressed());
42 return hash;
43 }
44
45 std::vector<uint8_t> H_msg_digest(StrongSpan<const SphincsMessageRandomness> r,
46 const SphincsTreeNode& root,
47 const SphincsMessageInternal& message) override {
48 m_sha_x_full->update(r);
49 m_sha_x_full->update(m_pub_seed);
50 m_sha_x_full->update(root);
51 m_sha_x_full->update(message.prefix);
52 m_sha_x_full->update(message.message);
53
54 auto r_pk_buffer = m_sha_x_full->final();
55 std::vector<uint8_t> mgf1_input = concat<std::vector<uint8_t>>(r, m_pub_seed, r_pk_buffer);
56
57 std::vector<uint8_t> digest(m_sphincs_params.h_msg_digest_bytes());
58 mgf1_mask(*m_sha_x_full, mgf1_input.data(), mgf1_input.size(), digest.data(), digest.size());
59
60 return digest;
61 }
62
63 public:
64 Sphincs_Hash_Functions_Sha2(const Sphincs_Parameters& sphincs_params, const SphincsPublicSeed& pub_seed) :
65 Sphincs_Hash_Functions(sphincs_params, pub_seed), m_sphincs_params(sphincs_params) {
66 m_padded_pub_seed_256 = std::vector<uint8_t>(64, '\0');
67 BOTAN_ASSERT_NOMSG(pub_seed.size() <= m_padded_pub_seed_256.size());
68 std::copy(pub_seed.begin(), pub_seed.end(), m_padded_pub_seed_256.begin());
69
70 if(sphincs_params.n() == 16) {
71 m_sha_x = std::make_unique<Truncated_Hash>(std::make_unique<SHA_256>(), sphincs_params.n() * 8);
72 m_sha_x_full = std::make_unique<SHA_256>();
73 m_padded_pub_seed_x = m_padded_pub_seed_256;
74 } else {
75 BOTAN_ASSERT_NOMSG(sphincs_params.n() <= 128);
76 m_sha_x = std::make_unique<Truncated_Hash>(std::make_unique<SHA_512>(), sphincs_params.n() * 8);
77 m_sha_x_full = std::make_unique<SHA_512>();
78
79 m_padded_pub_seed_x = std::vector<uint8_t>(128, '\0');
80 BOTAN_ASSERT_NOMSG(pub_seed.size() <= m_padded_pub_seed_x.size());
81 std::copy(pub_seed.begin(), pub_seed.end(), m_padded_pub_seed_x.begin());
82 }
83
84 if(m_sphincs_params.n() < 32) {
85 m_sha_256 = std::make_unique<Truncated_Hash>(std::make_unique<SHA_256>(), m_sphincs_params.n() * 8);
86 } else {
87 m_sha_256 = std::make_unique<SHA_256>();
88 }
89 }
90
94 const SphincsMessageInternal& msg) override {
95 HMAC hmac_sha_x(m_sha_x_full->new_object());
96 hmac_sha_x.set_key(sk_prf);
97 hmac_sha_x.update(opt_rand);
98 hmac_sha_x.update(msg.prefix);
99 hmac_sha_x.update(msg.message);
100
101 const auto prf = hmac_sha_x.final();
102 std::copy(prf.begin(), prf.begin() + out.size(), out.begin());
103 }
104
105 std::string msg_hash_function_name() const override { return m_sha_x_full->name(); }
106
107 private:
108 const Sphincs_Parameters& m_sphincs_params;
109 std::unique_ptr<HashFunction> m_sha_256;
110 std::unique_ptr<HashFunction> m_sha_x;
111 /// Non truncated SHA-X hash
112 std::unique_ptr<HashFunction> m_sha_x_full;
113
114 std::vector<uint8_t> m_padded_pub_seed_256;
115 std::vector<uint8_t> m_padded_pub_seed_x;
116};
117
118} // namespace Botan
119
120#endif
#define BOTAN_ASSERT_NOMSG(expr)
Definition assert.h:59
void update(const uint8_t in[], size_t length)
Definition buf_comp.h:35
void final(uint8_t out[])
Definition buf_comp.h:70
std::array< uint8_t, 22 > to_bytes_compressed() const
Definition sp_address.h:147
void PRF_msg(StrongSpan< SphincsMessageRandomness > out, StrongSpan< const SphincsSecretPRF > sk_prf, StrongSpan< const SphincsOptionalRandomness > opt_rand, const SphincsMessageInternal &msg) override
Sphincs_Hash_Functions_Sha2(const Sphincs_Parameters &sphincs_params, const SphincsPublicSeed &pub_seed)
std::string msg_hash_function_name() const override
const SphincsPublicSeed & m_pub_seed
Definition sp_hash.h:103
uint32_t h_msg_digest_bytes() const
decltype(auto) begin() noexcept(noexcept(this->m_span.begin()))
decltype(auto) size() const noexcept(noexcept(this->m_span.size()))
void set_key(const SymmetricKey &key)
Definition sym_algo.h:113
void mgf1_mask(HashFunction &hash, const uint8_t in[], size_t in_len, uint8_t out[], size_t out_len)
Definition mgf1.cpp:15
Gf448Elem root(const Gf448Elem &elem)
Compute the root of elem in the field.
constexpr auto concat(Rs &&... ranges)
Definition stl_util.h:263
M' representation of FIPS 205 (the input to slh_sign_internal and slh_verify_internal)
Definition sp_types.h:52
SphincsInputMessage message
Definition sp_types.h:54
SphincsMessagePrefix prefix
Definition sp_types.h:53