Botan 3.11.0
Crypto and TLS for C&
Botan::HSS_LMS_PrivateKeyInternal Class Referencefinal

The internal HSS-LMS private key. More...

#include <hss.h>

Public Member Functions

void _const_time_poison () const
void _const_time_unpoison () const
LMS_PrivateKey hss_derive_root_lms_private_key () const
 Create the HSS root LMS tree's LMS_PrivateKey using the HSS-LMS private key.
 HSS_LMS_PrivateKeyInternal (const HSS_LMS_Params &hss_params, RandomNumberGenerator &rng)
 Create an internal HSS-LMS private key.
const HSS_LMS_Paramshss_params () const
 Returns the used HSS-LMS parameters.
HSS_Sig_Idx remaining_operations (HSS_Sig_Idx idx) const
 Get the idx of the next signature to generate.
void set_idx (HSS_Sig_Idx idx)
 Set the idx of the next signature to generate.
std::vector< uint8_t > sign (std::span< const uint8_t > msg)
 Create a HSS-LMS signature.
size_t signature_size () const
 Returns the size in bytes of a signature created by this key.
secure_vector< uint8_t > to_bytes () const
 Returns the key in its encoded format.

Static Public Member Functions

static std::shared_ptr< HSS_LMS_PrivateKeyInternalfrom_bytes_or_throw (std::span< const uint8_t > key_bytes)
 Parse a private HSS-LMS key.

Detailed Description

The internal HSS-LMS private key.

Note that the format is not specified in the RFC 8554, and is Botan specific.

Definition at line 127 of file hss.h.

Constructor & Destructor Documentation

◆ HSS_LMS_PrivateKeyInternal()

Botan::HSS_LMS_PrivateKeyInternal::HSS_LMS_PrivateKeyInternal ( const HSS_LMS_Params & hss_params,
RandomNumberGenerator & rng )

Create an internal HSS-LMS private key.

Parameters
hss_paramsThe HSS-LMS parameters for the key.
rngThe rng to use.

Definition at line 123 of file hss.cpp.

123 :
124 m_hss_params(hss_params),
125 m_hss_seed(rng.random_vec<LMS_Seed>(m_hss_params.params_at_level(HSS_Level(0)).lms_params().m())),
126 m_identifier(rng.random_vec<LMS_Identifier>(LMS_IDENTIFIER_LEN)),
127 // LMS doesn't have a single unique parameter code that we can easily use,
128 // so algo_params is left as 0
129 m_keyid("HSS-LMS", 0, m_hss_seed, m_identifier),
130 m_sig_size(HSS_Signature::size(m_hss_params)) {}
const HSS_LMS_Params & hss_params() const
Returns the used HSS-LMS parameters.
Definition hss.h:149
static size_t size(const HSS_LMS_Params &params)
Returns the size a signature would have in its encoded format.
Definition hss.cpp:418
constexpr size_t LMS_IDENTIFIER_LEN
The length in bytes of the LMS identifier (I).
Definition lms.h:69
Strong< std::vector< uint8_t >, struct LMS_Identifier_ > LMS_Identifier
The identifier of an LMS tree (I in RFC 8554).
Definition lm_ots.h:53
Strong< secure_vector< uint8_t >, struct LMS_SEED_ > LMS_Seed
Seed of the LMS tree, used to generate the LM-OTS private keys.
Definition lm_ots.h:28
Strong< uint32_t, struct HSS_Level_, EnableArithmeticWithPlainNumber > HSS_Level
The HSS layer in the HSS multi tree starting at 0 from the root.
Definition hss.h:35

References hss_params(), and Botan::LMS_IDENTIFIER_LEN.

Referenced by from_bytes_or_throw().

Member Function Documentation

◆ _const_time_poison()

void Botan::HSS_LMS_PrivateKeyInternal::_const_time_poison ( ) const
inline

Definition at line 199 of file hss.h.

199{ CT::poison(m_hss_seed); }
constexpr void poison(const T *p, size_t n)
Definition ct_utils.h:56

References Botan::CT::poison().

◆ _const_time_unpoison()

void Botan::HSS_LMS_PrivateKeyInternal::_const_time_unpoison ( ) const
inline

Definition at line 201 of file hss.h.

201{ CT::unpoison(m_hss_seed); }
constexpr void unpoison(const T *p, size_t n)
Definition ct_utils.h:67

References Botan::CT::unpoison().

◆ from_bytes_or_throw()

std::shared_ptr< HSS_LMS_PrivateKeyInternal > Botan::HSS_LMS_PrivateKeyInternal::from_bytes_or_throw ( std::span< const uint8_t > key_bytes)
static

Parse a private HSS-LMS key.

Parameters
key_bytesThe private key bytes to parse.
Returns
The internal HSS-LMS private key.
Exceptions
Decoding_ErrorIf parsing the private key fails.

Definition at line 146 of file hss.cpp.

147 {
148 if(key_bytes.size() < sizeof(HSS_Level) + sizeof(HSS_Sig_Idx)) {
149 throw Decoding_Error("Too few private key bytes.");
150 }
151 BufferSlicer slicer(key_bytes);
152
153 const auto L = load_be<HSS_Level>(slicer.take<sizeof(HSS_Level)>());
154 if(L == 0U || L > HSS_MAX_LEVELS) {
155 throw Decoding_Error("Invalid number of HSS layers in private HSS-LMS key.");
156 }
157
158 const auto sig_idx = load_be<HSS_Sig_Idx>(slicer.take<sizeof(HSS_Sig_Idx)>());
159
160 std::vector<HSS_LMS_Params::LMS_LMOTS_Params_Pair> params;
161 for(size_t layer = 1; layer <= L; ++layer) {
162 if(slicer.remaining() < sizeof(LMS_Algorithm_Type) + sizeof(LMOTS_Algorithm_Type)) {
163 throw Decoding_Error("Out of bytes while parsing private HSS-LMS key.");
164 }
165 const auto lms_type = load_be<LMS_Algorithm_Type>(slicer.take<sizeof(LMS_Algorithm_Type)>());
166 const auto lmots_type = load_be<LMOTS_Algorithm_Type>(slicer.take<sizeof(LMOTS_Algorithm_Type)>());
167 params.push_back({LMS_Params::create_or_throw(lms_type), LMOTS_Params::create_or_throw(lmots_type)});
168 }
169 const auto& hash_name = params.at(0).lms_params().hash_name();
170
171 for(const auto& param : params) {
172 const bool invalid_lmots_hash = param.lmots_params().hash_name() != hash_name;
173 const bool invalid_lms_hash = param.lms_params().hash_name() != hash_name;
174 if(invalid_lmots_hash || invalid_lms_hash) {
175 throw Decoding_Error("Inconsistent hash functions are not allowed.");
176 }
177 }
178
179 if(slicer.remaining() < params.at(0).lms_params().m() + LMS_IDENTIFIER_LEN) {
180 throw Decoding_Error("Out of bytes while parsing private HSS-LMS key.");
181 }
182 auto hss_seed = slicer.copy<LMS_Seed>(params.at(0).lms_params().m());
183 auto identifier = slicer.copy<LMS_Identifier>(LMS_IDENTIFIER_LEN);
184
185 if(!slicer.empty()) {
186 throw Decoding_Error("Private HSS-LMS key contains more bytes than expected.");
187 }
188 auto sk = std::shared_ptr<HSS_LMS_PrivateKeyInternal>(
189 new HSS_LMS_PrivateKeyInternal(HSS_LMS_Params(std::move(params)), std::move(hss_seed), std::move(identifier)));
190
191 sk->set_idx(sig_idx);
192 return sk;
193}
HSS_LMS_PrivateKeyInternal(const HSS_LMS_Params &hss_params, RandomNumberGenerator &rng)
Create an internal HSS-LMS private key.
Definition hss.cpp:123
static LMOTS_Params create_or_throw(LMOTS_Algorithm_Type type)
Create the LM-OTS parameters from a known algorithm type.
Definition lm_ots.cpp:106
static LMS_Params create_or_throw(LMS_Algorithm_Type type)
Create the LMS parameters from a known algorithm type.
Definition lms.cpp:120
LMS_Algorithm_Type
Enum of available LMS algorithm types.
Definition lms.h:32
Strong< uint64_t, struct HSS_Sig_Idx_, EnableArithmeticWithPlainNumber > HSS_Sig_Idx
The index of a node within a specific LMS tree layer.
Definition hss.h:30
LMOTS_Algorithm_Type
Enum of available LM-OTS algorithm types.
Definition lm_ots.h:68
constexpr auto load_be(ParamTs &&... params)
Definition loadstor.h:504

References Botan::BufferSlicer::copy(), Botan::LMOTS_Params::create_or_throw(), Botan::LMS_Params::create_or_throw(), Botan::BufferSlicer::empty(), HSS_LMS_PrivateKeyInternal(), Botan::LMS_IDENTIFIER_LEN, Botan::load_be(), Botan::BufferSlicer::remaining(), and Botan::BufferSlicer::take().

Referenced by Botan::HSS_LMS_PrivateKey::HSS_LMS_PrivateKey().

◆ hss_derive_root_lms_private_key()

LMS_PrivateKey Botan::HSS_LMS_PrivateKeyInternal::hss_derive_root_lms_private_key ( ) const

Create the HSS root LMS tree's LMS_PrivateKey using the HSS-LMS private key.

We use the same generation as the reference implementation (https://github.com/cisco/hash-sigs) with SECRET_METHOD==2.

Returns
The LMS private key

Definition at line 287 of file hss.cpp.

287 {
288 const auto& top_params = hss_params().params_at_level(HSS_Level(0));
289 return LMS_PrivateKey(top_params.lms_params(), top_params.lmots_params(), m_identifier, m_hss_seed);
290}
const LMS_LMOTS_Params_Pair & params_at_level(HSS_Level level) const
Returns the LMS an LM-OTS parameters at the specified level of the HSS tree.
Definition hss.h:99

References hss_params(), and Botan::HSS_LMS_Params::params_at_level().

Referenced by Botan::HSS_LMS_PublicKeyInternal::create(), and sign().

◆ hss_params()

const HSS_LMS_Params & Botan::HSS_LMS_PrivateKeyInternal::hss_params ( ) const
inline

Returns the used HSS-LMS parameters.

Definition at line 149 of file hss.h.

149{ return m_hss_params; }

Referenced by Botan::HSS_LMS_PublicKeyInternal::create(), hss_derive_root_lms_private_key(), HSS_LMS_PrivateKeyInternal(), sign(), and to_bytes().

◆ remaining_operations()

HSS_Sig_Idx Botan::HSS_LMS_PrivateKeyInternal::remaining_operations ( HSS_Sig_Idx idx) const

Get the idx of the next signature to generate.

Definition at line 216 of file hss.cpp.

216 {
218}
HSS_Sig_Idx remaining_operations(HSS_Sig_Idx idx) const
Get the idx of the next signature to generate.
Definition hss.cpp:216
static Stateful_Key_Index_Registry & global()

References Botan::detail::Strong_Base< T >::get(), Botan::Stateful_Key_Index_Registry::global(), and remaining_operations().

Referenced by remaining_operations().

◆ set_idx()

void Botan::HSS_LMS_PrivateKeyInternal::set_idx ( HSS_Sig_Idx idx)

Set the idx of the next signature to generate.

Note that creating two signatures with the same index is insecure. The index must be lower than hss_params().max_sig_count(). The index will never go backward (highest value wins).

Definition at line 220 of file hss.cpp.

220 {
222}
void set_index_lower_bound(const KeyId &key_id, uint64_t min)

References Botan::detail::Strong_Base< T >::get(), Botan::Stateful_Key_Index_Registry::global(), and Botan::Stateful_Key_Index_Registry::set_index_lower_bound().

◆ sign()

std::vector< uint8_t > Botan::HSS_LMS_PrivateKeyInternal::sign ( std::span< const uint8_t > msg)

Create a HSS-LMS signature.

See RFC 8554 6.2 - Algorithm 8.

For each signature creation the hypertree is computed once again, so no data is stored between multiple signatures. However, storing data between multiple signatures could be an optimization if applications create multiple signatures in one go.

Parameters
msgThe message to sign.

Definition at line 240 of file hss.cpp.

240 {
241 std::vector<uint8_t> sig(HSS_Signature::size(hss_params()));
242 BufferStuffer sig_stuffer(sig);
243 sig_stuffer.append(store_be(hss_params().L() - 1));
244
245 std::vector<LMS_Tree_Node_Idx> q = derive_lms_leaf_indices_from_hss_index(reserve_next_idx(), hss_params());
246
247 // Derive LMS private keys and compute buffers
248 std::vector<LMS_PrivateKey> lms_key_at_layer;
249 std::vector<StrongSpan<LMS_Signature_Bytes>> out_lms_sig_buffer_at_layer;
250 std::vector<std::span<uint8_t>> out_child_pk_buffer_at_layer;
251 for(HSS_Level layer(0); layer < hss_params().L(); ++layer) {
252 // Generate key for current layer
253 const HSS_LMS_Params::LMS_LMOTS_Params_Pair& layer_params = hss_params().params_at_level(layer);
254 if(layer == HSS_Level(0)) {
255 lms_key_at_layer.push_back(hss_derive_root_lms_private_key());
256 } else {
257 lms_key_at_layer.push_back(
258 hss_derive_child_lms_private_key(layer_params, lms_key_at_layer.back(), q.at(layer.get() - 1)));
259 out_child_pk_buffer_at_layer.push_back(sig_stuffer.next(LMS_PublicKey::size(layer_params.lms_params())));
260 }
261 out_lms_sig_buffer_at_layer.push_back(sig_stuffer.next<LMS_Signature_Bytes>(
262 LMS_Signature::size(layer_params.lms_params(), layer_params.lmots_params())));
263 }
264 BOTAN_ASSERT_NOMSG(sig_stuffer.full());
265
266 // Sign and write the signature from bottom layer to root layer
267 std::vector<uint8_t> current_pk;
268 for(int32_t layer_it = hss_params().L().get() - 1; layer_it >= 0; --layer_it) {
269 HSS_Level layer(layer_it);
270 if(layer == hss_params().L() - 1) {
271 current_pk =
272 lms_key_at_layer.at(layer.get())
273 .sign_and_get_pk(out_lms_sig_buffer_at_layer.at(layer.get()), q.at(layer.get()), LMS_Message(msg))
274 .to_bytes();
275 } else {
276 copy_mem(out_child_pk_buffer_at_layer.at(layer.get()), current_pk);
277 current_pk =
278 lms_key_at_layer.at(layer.get())
279 .sign_and_get_pk(out_lms_sig_buffer_at_layer.at(layer.get()), q.at(layer.get()), LMS_Message(current_pk))
280 .to_bytes();
281 }
282 }
283
284 return sig;
285}
#define BOTAN_ASSERT_NOMSG(expr)
Definition assert.h:75
HSS_Level L() const
Returns the number of layers the HSS tree has.
Definition hss.h:104
LMS_PrivateKey hss_derive_root_lms_private_key() const
Create the HSS root LMS tree's LMS_PrivateKey using the HSS-LMS private key.
Definition hss.cpp:287
static size_t size(const LMS_Params &lms_params)
The expected size of an LMS public key for given lms_params.
Definition lms.cpp:321
static size_t size(const LMS_Params &lms_params, const LMOTS_Params &lmots_params)
Definition lms.cpp:428
constexpr void copy_mem(T *out, const T *in, size_t n)
Definition mem_ops.h:144
Strong< std::vector< uint8_t >, struct LMS_Signature_Bytes_ > LMS_Signature_Bytes
Raw bytes of an LMS signature.
Definition lms.h:84
Strong< std::vector< uint8_t >, struct LMS_Message_ > LMS_Message
A message that is signed with an LMS tree.
Definition lm_ots.h:58
constexpr auto store_be(ParamTs &&... params)
Definition loadstor.h:745

References Botan::BufferStuffer::append(), BOTAN_ASSERT_NOMSG, Botan::copy_mem(), Botan::BufferStuffer::full(), Botan::detail::Strong_Base< T >::get(), hss_derive_root_lms_private_key(), hss_params(), Botan::HSS_LMS_Params::L(), Botan::HSS_LMS_Params::LMS_LMOTS_Params_Pair::lmots_params(), Botan::HSS_LMS_Params::LMS_LMOTS_Params_Pair::lms_params(), Botan::BufferStuffer::next(), Botan::HSS_LMS_Params::params_at_level(), Botan::HSS_Signature::size(), Botan::LMS_PublicKey::size(), Botan::LMS_Signature::size(), and Botan::store_be().

◆ signature_size()

size_t Botan::HSS_LMS_PrivateKeyInternal::signature_size ( ) const
inline

Returns the size in bytes of a signature created by this key.

Definition at line 197 of file hss.h.

197{ return m_sig_size; }

◆ to_bytes()

secure_vector< uint8_t > Botan::HSS_LMS_PrivateKeyInternal::to_bytes ( ) const

Returns the key in its encoded format.

Definition at line 195 of file hss.cpp.

195 {
196 secure_vector<uint8_t> sk_bytes(size());
197 BufferStuffer stuffer(sk_bytes);
198
199 const uint64_t current_index = Stateful_Key_Index_Registry::global().current_index(m_keyid);
200
201 stuffer.append(store_be(hss_params().L()));
202 stuffer.append(store_be(current_index));
203
204 for(HSS_Level layer(1); layer <= hss_params().L(); ++layer) {
205 const auto& params = hss_params().params_at_level(layer - 1);
206 stuffer.append(store_be(params.lms_params().algorithm_type()));
207 stuffer.append(store_be(params.lmots_params().algorithm_type()));
208 }
209 stuffer.append(m_hss_seed);
210 stuffer.append(m_identifier);
211 BOTAN_ASSERT_NOMSG(stuffer.full());
212
213 return sk_bytes;
214}
std::vector< T, secure_allocator< T > > secure_vector
Definition secmem.h:68

References Botan::BufferStuffer::append(), BOTAN_ASSERT_NOMSG, Botan::Stateful_Key_Index_Registry::current_index(), Botan::BufferStuffer::full(), Botan::Stateful_Key_Index_Registry::global(), hss_params(), Botan::HSS_LMS_Params::L(), Botan::HSS_LMS_Params::params_at_level(), and Botan::store_be().


The documentation for this class was generated from the following files: