Botan 3.4.0
Crypto and TLS for C&
sp_hash_sha2.h
Go to the documentation of this file.
1/*
2 * SPHINCS+ 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 SPHINCS+ 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 std::span<const uint8_t> 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);
52
53 auto r_pk_buffer = m_sha_x_full->final();
54 std::vector<uint8_t> mgf1_input = concat_as<std::vector<uint8_t>>(r, m_pub_seed, r_pk_buffer);
55
56 std::vector<uint8_t> digest(m_sphincs_params.h_msg_digest_bytes());
57 mgf1_mask(*m_sha_x_full, mgf1_input.data(), mgf1_input.size(), digest.data(), digest.size());
58
59 return digest;
60 }
61
62 public:
63 Sphincs_Hash_Functions_Sha2(const Sphincs_Parameters& sphincs_params, const SphincsPublicSeed& pub_seed) :
64 Sphincs_Hash_Functions(sphincs_params, pub_seed), m_sphincs_params(sphincs_params) {
65 m_padded_pub_seed_256 = std::vector<uint8_t>(64, '\0');
66 BOTAN_ASSERT_NOMSG(pub_seed.size() <= m_padded_pub_seed_256.size());
67 std::copy(pub_seed.begin(), pub_seed.end(), m_padded_pub_seed_256.begin());
68
69 if(sphincs_params.n() == 16) {
70 m_sha_x = std::make_unique<Truncated_Hash>(std::make_unique<SHA_256>(), sphincs_params.n() * 8);
71 m_sha_x_full = std::make_unique<SHA_256>();
72 m_padded_pub_seed_x = m_padded_pub_seed_256;
73 } else {
74 BOTAN_ASSERT_NOMSG(sphincs_params.n() <= 128);
75 m_sha_x = std::make_unique<Truncated_Hash>(std::make_unique<SHA_512>(), sphincs_params.n() * 8);
76 m_sha_x_full = std::make_unique<SHA_512>();
77
78 m_padded_pub_seed_x = std::vector<uint8_t>(128, '\0');
79 BOTAN_ASSERT_NOMSG(pub_seed.size() <= m_padded_pub_seed_x.size());
80 std::copy(pub_seed.begin(), pub_seed.end(), m_padded_pub_seed_x.begin());
81 }
82
83 if(m_sphincs_params.n() < 32) {
84 m_sha_256 = std::make_unique<Truncated_Hash>(std::make_unique<SHA_256>(), m_sphincs_params.n() * 8);
85 } else {
86 m_sha_256 = std::make_unique<SHA_256>();
87 }
88 }
89
91 const SphincsSecretPRF& sk_prf,
92 const SphincsOptionalRandomness& opt_rand,
93 std::span<const uint8_t> in) override {
94 HMAC hmac_sha_x(m_sha_x_full->new_object());
95 hmac_sha_x.set_key(sk_prf);
96 hmac_sha_x.update(opt_rand);
97 hmac_sha_x.update(in);
98
99 const auto prf = hmac_sha_x.final();
100 std::copy(prf.begin(), prf.begin() + out.size(), out.begin());
101 }
102
103 std::string msg_hash_function_name() const override { return m_sha_x_full->name(); }
104
105 private:
106 const Sphincs_Parameters& m_sphincs_params;
107 std::unique_ptr<HashFunction> m_sha_256;
108 std::unique_ptr<HashFunction> m_sha_x;
109 /// Non truncated SHA-X hash
110 std::unique_ptr<HashFunction> m_sha_x_full;
111
112 std::vector<uint8_t> m_padded_pub_seed_256;
113 std::vector<uint8_t> m_padded_pub_seed_x;
114};
115
116} // namespace Botan
117
118#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:142
void PRF_msg(StrongSpan< SphincsMessageRandomness > out, const SphincsSecretPRF &sk_prf, const SphincsOptionalRandomness &opt_rand, std::span< const uint8_t > in) 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:102
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.