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