Botan 3.13.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 () const
 Get the number of remaining signatures for this key.
void set_idx (HSS_Sig_Idx idx) const
 Set the idx of the next signature to generate.
std::vector< uint8_t > sign (std::span< const uint8_t > msg) const
 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.
Random Number GeneratorsThe rng to use.

Definition at line 143 of file hss.cpp.

143 :
144 m_hss_params(hss_params),
145 m_hss_seed(rng.random_vec<LMS_Seed>(m_hss_params.params_at_level(HSS_Level(0)).lms_params().m())),
146 m_identifier(rng.random_vec<LMS_Identifier>(LMS_IDENTIFIER_LEN)),
147 m_keyid(
148 "HSS-LMS", hss_param_encoding(m_hss_params), m_hss_params.max_sig_count().get(), m_hss_seed, m_identifier),
149 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:441
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 204 of file hss.h.

204{ 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 206 of file hss.h.

206{ 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 165 of file hss.cpp.

166 {
167 if(key_bytes.size() < sizeof(HSS_Level) + sizeof(HSS_Sig_Idx)) {
168 throw Decoding_Error("Too few private key bytes.");
169 }
170 BufferSlicer slicer(key_bytes);
171
172 const auto L = load_be<HSS_Level>(slicer.take<sizeof(HSS_Level)>());
173 if(L == 0U || L > HSS_MAX_LEVELS) {
174 throw Decoding_Error("Invalid number of HSS layers in private HSS-LMS key.");
175 }
176
177 const auto sig_idx = load_be<HSS_Sig_Idx>(slicer.take<sizeof(HSS_Sig_Idx)>());
178
179 std::vector<HSS_LMS_Params::LMS_LMOTS_Params_Pair> params;
180 for(size_t layer = 1; layer <= L; ++layer) {
181 if(slicer.remaining() < sizeof(LMS_Algorithm_Type) + sizeof(LMOTS_Algorithm_Type)) {
182 throw Decoding_Error("Out of bytes while parsing private HSS-LMS key.");
183 }
184 const auto lms_type = load_be<LMS_Algorithm_Type>(slicer.take<sizeof(LMS_Algorithm_Type)>());
185 const auto lmots_type = load_be<LMOTS_Algorithm_Type>(slicer.take<sizeof(LMOTS_Algorithm_Type)>());
186 params.push_back({LMS_Params::create_or_throw(lms_type), LMOTS_Params::create_or_throw(lmots_type)});
187 }
188 const auto& hash_name = params.at(0).lms_params().hash_name();
189
190 for(const auto& param : params) {
191 const bool invalid_lmots_hash = param.lmots_params().hash_name() != hash_name;
192 const bool invalid_lms_hash = param.lms_params().hash_name() != hash_name;
193 if(invalid_lmots_hash || invalid_lms_hash) {
194 throw Decoding_Error("Inconsistent hash functions are not allowed.");
195 }
196 }
197
198 if(slicer.remaining() < params.at(0).lms_params().m() + LMS_IDENTIFIER_LEN) {
199 throw Decoding_Error("Out of bytes while parsing private HSS-LMS key.");
200 }
201 auto hss_seed = slicer.copy<LMS_Seed>(params.at(0).lms_params().m());
202 auto identifier = slicer.copy<LMS_Identifier>(LMS_IDENTIFIER_LEN);
203
204 if(!slicer.empty()) {
205 throw Decoding_Error("Private HSS-LMS key contains more bytes than expected.");
206 }
207 auto sk = std::shared_ptr<HSS_LMS_PrivateKeyInternal>(
208 new HSS_LMS_PrivateKeyInternal(HSS_LMS_Params(std::move(params)), std::move(hss_seed), std::move(identifier)));
209
210 sk->set_idx(sig_idx);
211 return sk;
212}
HSS_LMS_PrivateKeyInternal(const HSS_LMS_Params &hss_params, RandomNumberGenerator &rng)
Create an internal HSS-LMS private key.
Definition hss.cpp:143
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 310 of file hss.cpp.

310 {
311 const auto& top_params = hss_params().params_at_level(HSS_Level(0));
312 return LMS_PrivateKey(top_params.lms_params(), top_params.lmots_params(), m_identifier, m_hss_seed);
313}
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 ( ) const

Get the number of remaining signatures for this key.

Definition at line 235 of file hss.cpp.

235 {
237}
HSS_Sig_Idx remaining_operations() const
Get the number of remaining signatures for this key.
Definition hss.cpp:235
static Stateful_Key_Index_Registry & global()

References 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) const

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 or equal to hss_params().max_sig_count(), with an index == max indicating the key is completely exhausted. The index will never go backward (highest value wins).

The signing state lives in the process-wide Stateful_Key_Index_Registry keyed by the key identity, not in this object, so this leaves *this unchanged and is therefore const.

Definition at line 239 of file hss.cpp.

239 {
240 // An index equal to max_sig_count is valid and denotes an exhausted key
241 if(idx > m_hss_params.max_sig_count()) {
242 throw Decoding_Error("HSS-LMS private key index out of bounds");
243 }
245}
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) const

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 263 of file hss.cpp.

263 {
264 std::vector<uint8_t> sig(HSS_Signature::size(hss_params()));
265 BufferStuffer sig_stuffer(sig);
266 sig_stuffer.append(store_be(hss_params().L() - 1));
267
268 std::vector<LMS_Tree_Node_Idx> q = derive_lms_leaf_indices_from_hss_index(reserve_next_idx(), hss_params());
269
270 // Derive LMS private keys and compute buffers
271 std::vector<LMS_PrivateKey> lms_key_at_layer;
272 std::vector<StrongSpan<LMS_Signature_Bytes>> out_lms_sig_buffer_at_layer;
273 std::vector<std::span<uint8_t>> out_child_pk_buffer_at_layer;
274 for(HSS_Level layer(0); layer < hss_params().L(); ++layer) {
275 // Generate key for current layer
276 const HSS_LMS_Params::LMS_LMOTS_Params_Pair& layer_params = hss_params().params_at_level(layer);
277 if(layer == HSS_Level(0)) {
278 lms_key_at_layer.push_back(hss_derive_root_lms_private_key());
279 } else {
280 lms_key_at_layer.push_back(
281 hss_derive_child_lms_private_key(layer_params, lms_key_at_layer.back(), q.at(layer.get() - 1)));
282 out_child_pk_buffer_at_layer.push_back(sig_stuffer.next(LMS_PublicKey::size(layer_params.lms_params())));
283 }
284 out_lms_sig_buffer_at_layer.push_back(sig_stuffer.next<LMS_Signature_Bytes>(
285 LMS_Signature::size(layer_params.lms_params(), layer_params.lmots_params())));
286 }
287 BOTAN_ASSERT_NOMSG(sig_stuffer.full());
288
289 // Sign and write the signature from bottom layer to root layer
290 std::vector<uint8_t> current_pk;
291 for(int32_t layer_it = hss_params().L().get() - 1; layer_it >= 0; --layer_it) {
292 HSS_Level layer(layer_it);
293 if(layer == hss_params().L() - 1) {
294 current_pk =
295 lms_key_at_layer.at(layer.get())
296 .sign_and_get_pk(out_lms_sig_buffer_at_layer.at(layer.get()), q.at(layer.get()), LMS_Message(msg))
297 .to_bytes();
298 } else {
299 copy_mem(out_child_pk_buffer_at_layer.at(layer.get()), current_pk);
300 current_pk =
301 lms_key_at_layer.at(layer.get())
302 .sign_and_get_pk(out_lms_sig_buffer_at_layer.at(layer.get()), q.at(layer.get()), LMS_Message(current_pk))
303 .to_bytes();
304 }
305 }
306
307 return sig;
308}
#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:310
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
Strong< std::vector< uint8_t >, struct LMS_Signature_Bytes_ > LMS_Signature_Bytes
Raw bytes of an LMS signature.
Definition lms.h:84
constexpr void copy_mem(T *out, const T *in, size_t n)
Definition mem_ops.h:144
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 202 of file hss.h.

202{ 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 214 of file hss.cpp.

214 {
215 secure_vector<uint8_t> sk_bytes(size());
216 BufferStuffer stuffer(sk_bytes);
217
218 const uint64_t current_index = Stateful_Key_Index_Registry::global().current_index(m_keyid);
219
220 stuffer.append(store_be(hss_params().L()));
221 stuffer.append(store_be(current_index));
222
223 for(HSS_Level layer(1); layer <= hss_params().L(); ++layer) {
224 const auto& params = hss_params().params_at_level(layer - 1);
225 stuffer.append(store_be(params.lms_params().algorithm_type()));
226 stuffer.append(store_be(params.lmots_params().algorithm_type()));
227 }
228 stuffer.append(m_hss_seed);
229 stuffer.append(m_identifier);
230 BOTAN_ASSERT_NOMSG(stuffer.full());
231
232 return sk_bytes;
233}
std::vector< T, secure_allocator< T > > secure_vector
Definition secmem.h:128

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: