/src/botan/src/lib/pubkey/xmss/xmss_signature_operation.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * XMSS Signature Operation |
3 | | * Signature generation operation for Extended Hash-Based Signatures (XMSS) as |
4 | | * defined in: |
5 | | * |
6 | | * [1] XMSS: Extended Hash-Based Signatures, |
7 | | * Request for Comments: 8391 |
8 | | * Release: May 2018. |
9 | | * https://datatracker.ietf.org/doc/rfc8391/ |
10 | | * |
11 | | * (C) 2016,2017,2018 Matthias Gierlings |
12 | | * |
13 | | * Botan is released under the Simplified BSD License (see license.txt) |
14 | | **/ |
15 | | |
16 | | #include <botan/internal/xmss_signature_operation.h> |
17 | | |
18 | | #include <botan/internal/xmss_tools.h> |
19 | | |
20 | | namespace Botan { |
21 | | |
22 | | XMSS_Signature_Operation::XMSS_Signature_Operation(const XMSS_PrivateKey& private_key) : |
23 | 0 | m_priv_key(private_key), |
24 | 0 | m_hash(private_key.xmss_parameters()), |
25 | 0 | m_randomness(0), |
26 | 0 | m_leaf_idx(0), |
27 | 0 | m_is_initialized(false) {} Unexecuted instantiation: Botan::XMSS_Signature_Operation::XMSS_Signature_Operation(Botan::XMSS_PrivateKey const&) Unexecuted instantiation: Botan::XMSS_Signature_Operation::XMSS_Signature_Operation(Botan::XMSS_PrivateKey const&) |
28 | | |
29 | | XMSS_Signature::TreeSignature XMSS_Signature_Operation::generate_tree_signature(const secure_vector<uint8_t>& msg, |
30 | | XMSS_PrivateKey& xmss_priv_key, |
31 | 0 | XMSS_Address& adrs) { |
32 | 0 | XMSS_Signature::TreeSignature result; |
33 | |
|
34 | 0 | result.authentication_path = build_auth_path(xmss_priv_key, adrs); |
35 | 0 | adrs.set_type(XMSS_Address::Type::OTS_Hash_Address); |
36 | 0 | adrs.set_ots_address(m_leaf_idx); |
37 | |
|
38 | 0 | result.ots_signature = |
39 | 0 | xmss_priv_key.wots_private_key_for(adrs, m_hash).sign(msg, xmss_priv_key.public_seed(), adrs, m_hash); |
40 | |
|
41 | 0 | return result; |
42 | 0 | } |
43 | | |
44 | 0 | XMSS_Signature XMSS_Signature_Operation::sign(const secure_vector<uint8_t>& msg_hash, XMSS_PrivateKey& xmss_priv_key) { |
45 | 0 | XMSS_Address adrs; |
46 | 0 | XMSS_Signature sig(m_leaf_idx, m_randomness, generate_tree_signature(msg_hash, xmss_priv_key, adrs)); |
47 | 0 | return sig; |
48 | 0 | } |
49 | | |
50 | 0 | size_t XMSS_Signature_Operation::signature_length() const { |
51 | 0 | const auto& params = m_priv_key.xmss_parameters(); |
52 | 0 | return sizeof(uint64_t) + // size of leaf index |
53 | 0 | params.element_size() + params.len() * params.element_size() + params.tree_height() * params.element_size(); |
54 | 0 | } |
55 | | |
56 | 0 | wots_keysig_t XMSS_Signature_Operation::build_auth_path(XMSS_PrivateKey& priv_key, XMSS_Address& adrs) { |
57 | 0 | const auto& params = m_priv_key.xmss_parameters(); |
58 | 0 | wots_keysig_t auth_path(params.tree_height()); |
59 | 0 | adrs.set_type(XMSS_Address::Type::Hash_Tree_Address); |
60 | |
|
61 | 0 | for(size_t j = 0; j < params.tree_height(); j++) { |
62 | 0 | size_t k = (m_leaf_idx / (static_cast<size_t>(1) << j)) ^ 0x01; |
63 | 0 | auth_path[j] = priv_key.tree_hash(k * (static_cast<size_t>(1) << j), j, adrs); |
64 | 0 | } |
65 | |
|
66 | 0 | return auth_path; |
67 | 0 | } |
68 | | |
69 | 0 | void XMSS_Signature_Operation::update(std::span<const uint8_t> input) { |
70 | 0 | initialize(); |
71 | 0 | m_hash.h_msg_update(input); |
72 | 0 | } |
73 | | |
74 | 0 | std::vector<uint8_t> XMSS_Signature_Operation::sign(RandomNumberGenerator& /*rng*/) { |
75 | 0 | initialize(); |
76 | 0 | auto sig = sign(m_hash.h_msg_final(), m_priv_key).bytes(); |
77 | 0 | m_is_initialized = false; |
78 | 0 | return sig; |
79 | 0 | } |
80 | | |
81 | 0 | void XMSS_Signature_Operation::initialize() { |
82 | | // return if we already initialized and reserved a leaf index for signing. |
83 | 0 | if(m_is_initialized) { |
84 | 0 | return; |
85 | 0 | } |
86 | | |
87 | 0 | secure_vector<uint8_t> index_bytes; |
88 | | // reserve leaf index so it can not be reused by another signature |
89 | | // operation using the same private key. |
90 | 0 | m_leaf_idx = static_cast<uint32_t>(m_priv_key.reserve_unused_leaf_index()); |
91 | | |
92 | | // write prefix for message hashing into buffer. |
93 | 0 | XMSS_Tools::concat(index_bytes, m_leaf_idx, 32); |
94 | 0 | m_hash.prf(m_randomness, m_priv_key.prf_value(), index_bytes); |
95 | 0 | index_bytes.clear(); |
96 | 0 | XMSS_Tools::concat(index_bytes, m_leaf_idx, m_priv_key.xmss_parameters().element_size()); |
97 | 0 | m_hash.h_msg_init(m_randomness, m_priv_key.root(), index_bytes); |
98 | 0 | m_is_initialized = true; |
99 | 0 | } |
100 | | |
101 | 0 | AlgorithmIdentifier XMSS_Signature_Operation::algorithm_identifier() const { |
102 | 0 | return AlgorithmIdentifier(OID::from_string("XMSS"), AlgorithmIdentifier::USE_EMPTY_PARAM); |
103 | 0 | } |
104 | | |
105 | | } // namespace Botan |