/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 | | #include <botan/internal/xmss_tools.h> |
18 | | |
19 | | namespace Botan { |
20 | | |
21 | | XMSS_Signature_Operation::XMSS_Signature_Operation( |
22 | | const XMSS_PrivateKey& private_key) : |
23 | | m_priv_key(private_key), |
24 | | m_xmss_params(private_key.xmss_oid()), |
25 | | m_hash(private_key.xmss_hash_function()), |
26 | | m_randomness(0), |
27 | | m_leaf_idx(0), |
28 | | m_is_initialized(false) |
29 | 0 | {} 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&) |
30 | | |
31 | | XMSS_WOTS_PublicKey::TreeSignature |
32 | | XMSS_Signature_Operation::generate_tree_signature(const secure_vector<uint8_t>& msg, |
33 | | XMSS_PrivateKey& xmss_priv_key, |
34 | | XMSS_Address& adrs) |
35 | 0 | { |
36 | |
|
37 | 0 | wots_keysig_t auth_path = build_auth_path(xmss_priv_key, adrs); |
38 | 0 | adrs.set_type(XMSS_Address::Type::OTS_Hash_Address); |
39 | 0 | adrs.set_ots_address(m_leaf_idx); |
40 | |
|
41 | 0 | wots_keysig_t sig_ots = xmss_priv_key.wots_private_key().sign(msg, adrs); |
42 | 0 | return XMSS_WOTS_PublicKey::TreeSignature(sig_ots, auth_path); |
43 | 0 | } |
44 | | |
45 | | XMSS_Signature |
46 | | XMSS_Signature_Operation::sign(const secure_vector<uint8_t>& msg_hash, |
47 | | XMSS_PrivateKey& xmss_priv_key) |
48 | 0 | { |
49 | 0 | XMSS_Address adrs; |
50 | 0 | XMSS_Signature sig(m_leaf_idx, |
51 | 0 | m_randomness, |
52 | 0 | generate_tree_signature(msg_hash, xmss_priv_key,adrs)); |
53 | 0 | return sig; |
54 | 0 | } |
55 | | |
56 | | size_t XMSS_Signature_Operation::signature_length() const |
57 | 0 | { |
58 | 0 | return sizeof(uint64_t) + // size of leaf index |
59 | 0 | m_xmss_params.element_size() + |
60 | 0 | m_xmss_params.len() * m_xmss_params.element_size() + |
61 | 0 | m_xmss_params.tree_height() * m_xmss_params.element_size(); |
62 | 0 | } |
63 | | |
64 | | wots_keysig_t |
65 | | XMSS_Signature_Operation::build_auth_path(XMSS_PrivateKey& priv_key, |
66 | | XMSS_Address& adrs) |
67 | 0 | { |
68 | 0 | wots_keysig_t auth_path(m_xmss_params.tree_height()); |
69 | 0 | adrs.set_type(XMSS_Address::Type::Hash_Tree_Address); |
70 | |
|
71 | 0 | for(size_t j = 0; j < m_xmss_params.tree_height(); j++) |
72 | 0 | { |
73 | 0 | size_t k = (m_leaf_idx / (static_cast<size_t>(1) << j)) ^ 0x01; |
74 | 0 | auth_path[j] = priv_key.tree_hash(k * (static_cast<size_t>(1) << j), j, adrs); |
75 | 0 | } |
76 | |
|
77 | 0 | return auth_path; |
78 | 0 | } |
79 | | |
80 | | void XMSS_Signature_Operation::update(const uint8_t msg[], size_t msg_len) |
81 | 0 | { |
82 | 0 | initialize(); |
83 | 0 | m_hash.h_msg_update(msg, msg_len); |
84 | 0 | } |
85 | | |
86 | | secure_vector<uint8_t> |
87 | | XMSS_Signature_Operation::sign(RandomNumberGenerator&) |
88 | 0 | { |
89 | 0 | initialize(); |
90 | 0 | secure_vector<uint8_t> signature(sign(m_hash.h_msg_final(), |
91 | 0 | m_priv_key).bytes()); |
92 | 0 | m_is_initialized = false; |
93 | 0 | return signature; |
94 | 0 | } |
95 | | |
96 | | void XMSS_Signature_Operation::initialize() |
97 | 0 | { |
98 | | // return if we already initialized and reserved a leaf index for signing. |
99 | 0 | if(m_is_initialized) |
100 | 0 | { return; } |
101 | | |
102 | 0 | secure_vector<uint8_t> index_bytes; |
103 | | // reserve leaf index so it can not be reused in by another signature |
104 | | // operation using the same private key. |
105 | 0 | m_leaf_idx = static_cast<uint32_t>(m_priv_key.reserve_unused_leaf_index()); |
106 | | |
107 | | // write prefix for message hashing into buffer. |
108 | 0 | XMSS_Tools::concat(index_bytes, m_leaf_idx, 32); |
109 | 0 | m_randomness = m_hash.prf(m_priv_key.prf(), index_bytes); |
110 | 0 | index_bytes.clear(); |
111 | 0 | XMSS_Tools::concat(index_bytes, m_leaf_idx, |
112 | 0 | m_priv_key.xmss_parameters().element_size()); |
113 | 0 | m_hash.h_msg_init(m_randomness, |
114 | 0 | m_priv_key.root(), |
115 | 0 | index_bytes); |
116 | 0 | m_is_initialized = true; |
117 | 0 | } |
118 | | |
119 | | } |
120 | | |