Coverage Report

Created: 2022-01-14 08:07

/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