diff --git a/src/lib/pubkey/hss_lms/hss.cpp b/src/lib/pubkey/hss_lms/hss.cpp
index fc2bd38223c..a6b24efae96 100644
--- a/src/lib/pubkey/hss_lms/hss.cpp
+++ b/src/lib/pubkey/hss_lms/hss.cpp
@@ -101,18 +101,18 @@ HSS_LMS_Params::HSS_LMS_Params(std::string_view algo_params) {
 }
 
 HSS_Sig_Idx HSS_LMS_Params::calc_max_sig_count() const {
-   uint32_t total_hight_counter = 0;
+   uint32_t total_height_counter = 0;
    for(HSS_Level level(0); level < L(); level++) {
-      total_hight_counter += params_at_level(level).lms_params().h();
+      total_height_counter += params_at_level(level).lms_params().h();
    }
-   if(total_hight_counter >= sizeof(HSS_Sig_Idx) * 8) {
+   if(total_height_counter >= sizeof(HSS_Sig_Idx) * 8) {
       return HSS_Sig_Idx(std::numeric_limits<HSS_Sig_Idx::wrapped_type>::max());
    }
-   return HSS_Sig_Idx(1) << total_hight_counter;
+   return HSS_Sig_Idx(1) << total_height_counter;
 }
 
 HSS_LMS_PrivateKeyInternal::HSS_LMS_PrivateKeyInternal(const HSS_LMS_Params& hss_params, RandomNumberGenerator& rng) :
-      m_hss_params(hss_params), m_current_idx(0) {
+      m_hss_params(hss_params), m_current_idx(0), m_sig_size(HSS_Signature::size(m_hss_params)) {
    m_hss_seed = rng.random_vec<LMS_Seed>(m_hss_params.params_at_level(HSS_Level(0)).lms_params().m());
    m_identifier = rng.random_vec<LMS_Identifier>(LMS_IDENTIFIER_LEN);
 }
@@ -211,7 +211,8 @@ HSS_LMS_PrivateKeyInternal::HSS_LMS_PrivateKeyInternal(HSS_LMS_Params hss_params
       m_hss_params(std::move(hss_params)),
       m_hss_seed(std::move(hss_seed)),
       m_identifier(std::move(identifier)),
-      m_current_idx(0) {
+      m_current_idx(0),
+      m_sig_size(HSS_Signature::size(m_hss_params)) {
    BOTAN_ARG_CHECK(m_hss_seed.size() == m_hss_params.params_at_level(HSS_Level(0)).lms_params().m(),
                    "Invalid seed size");
    BOTAN_ARG_CHECK(m_identifier.size() == LMS_IDENTIFIER_LEN, "Invalid identifier size");
diff --git a/src/lib/pubkey/hss_lms/hss.h b/src/lib/pubkey/hss_lms/hss.h
index d37b00ce339..f927a781cd0 100644
--- a/src/lib/pubkey/hss_lms/hss.h
+++ b/src/lib/pubkey/hss_lms/hss.h
@@ -188,6 +188,11 @@ class BOTAN_TEST_API HSS_LMS_PrivateKeyInternal final {
        */
       LMS_PrivateKey hss_derive_root_lms_private_key() const;
 
+      /**
+       * @brief Returns the size in bytes of a signature created by this key.
+       */
+      size_t signature_size() const { return m_sig_size; };
+
    private:
       HSS_LMS_PrivateKeyInternal(HSS_LMS_Params hss_params, LMS_Seed hss_seed, LMS_Identifier identifier);
 
@@ -221,6 +226,7 @@ class BOTAN_TEST_API HSS_LMS_PrivateKeyInternal final {
       LMS_Seed m_hss_seed;
       LMS_Identifier m_identifier;
       HSS_Sig_Idx m_current_idx;
+      const size_t m_sig_size;
 };
 
 class HSS_Signature;
diff --git a/src/lib/pubkey/hss_lms/hss_lms.cpp b/src/lib/pubkey/hss_lms/hss_lms.cpp
index 48a9cc76d85..08b8eaf89d5 100644
--- a/src/lib/pubkey/hss_lms/hss_lms.cpp
+++ b/src/lib/pubkey/hss_lms/hss_lms.cpp
@@ -169,7 +169,7 @@ class HSS_LMS_Signature_Operation final : public PK_Ops::Signature {
          return m_private->sign(message_to_sign);
       }
 
-      size_t signature_length() const override { return HSS_Signature::size(m_private->hss_params()); }
+      size_t signature_length() const override { return m_private->signature_size(); }
 
       AlgorithmIdentifier algorithm_identifier() const override { return m_public->algorithm_identifier(); }
 
diff --git a/src/lib/pubkey/hss_lms/hss_lms.h b/src/lib/pubkey/hss_lms/hss_lms.h
index fd3e5140596..8b6f3bb5b3c 100644
--- a/src/lib/pubkey/hss_lms/hss_lms.h
+++ b/src/lib/pubkey/hss_lms/hss_lms.h
@@ -31,7 +31,7 @@ class HSS_LMS_PrivateKeyInternal;
  * To derive seeds for single LMS trees in the HSS-multitree, the method (SECRET_METHOD 2)
  * of the reference implementation (https://github.com/cisco/hash-sigs) is used.
  */
-class BOTAN_PUBLIC_API(3, 2) HSS_LMS_PublicKey : public virtual Public_Key {
+class BOTAN_PUBLIC_API(3, 4) HSS_LMS_PublicKey : public virtual Public_Key {
    public:
       /**
        * @brief Load an existing public key using its bytes.
@@ -112,7 +112,7 @@ BOTAN_DIAGNOSTIC_IGNORE_INHERITED_VIA_DOMINANCE
  *
  * Note: The selected hash function is also used for seed derivation.
  */
-class BOTAN_PUBLIC_API(3, 2) HSS_LMS_PrivateKey final : public virtual HSS_LMS_PublicKey,
+class BOTAN_PUBLIC_API(3, 4) HSS_LMS_PrivateKey final : public virtual HSS_LMS_PublicKey,
                                                         public virtual Private_Key {
    public:
       /**
diff --git a/src/lib/pubkey/hss_lms/lm_ots.cpp b/src/lib/pubkey/hss_lms/lm_ots.cpp
index 87ab8b0db53..42bd1f455cc 100644
--- a/src/lib/pubkey/hss_lms/lm_ots.cpp
+++ b/src/lib/pubkey/hss_lms/lm_ots.cpp
@@ -57,8 +57,11 @@ uint8_t byte(std::span<const uint8_t> S, uint32_t i) {
 
 // RFC 8554 3.1.3
 uint8_t coef(std::span<const uint8_t> S, uint32_t i, const LMOTS_Params& params) {
-   return params.coef_max() &
-          (byte(S, (i * params.w()) / 8) >> (8 - (params.w() * (i % (8 / params.w())) + params.w())));
+   const uint8_t w_bit_mask = params.coef_max();
+   const uint8_t coef_byte = byte(S, (i * params.w()) / 8);
+   const uint8_t shift = 8 - (params.w() * (i % (8 / params.w())) + params.w());
+
+   return w_bit_mask & (coef_byte >> shift);
 }
 
 // RFC 8554 4.4
@@ -77,7 +80,7 @@ std::vector<uint8_t> gen_Q_with_cksm(const LMOTS_Params& params,
                                      const LMS_Message& msg) {
    std::vector<uint8_t> Q_with_cksm(params.n() + sizeof(uint16_t));
    BufferStuffer qwc_stuffer(Q_with_cksm);
-   const auto hash = HashFunction::create_or_throw(params.hash_name());
+   const auto hash = params.hash();
    hash->update(identifier);
    hash->update(store_be(q));
    hash->update(store_be(D_MESG));
@@ -258,7 +261,7 @@ LMOTS_Private_Key::LMOTS_Private_Key(const LMOTS_Params& params,
                                      const LMS_Seed& seed) :
       OTS_Instance(params, identifier, q), m_seed(seed) {
    PseudorandomKeyGeneration gen(identifier);
-   const auto hash = HashFunction::create_or_throw(params.hash_name());
+   const auto hash = params.hash();
 
    gen.set_q(q.get());
    gen.set_j(0xff);
@@ -272,7 +275,7 @@ LMOTS_Private_Key::LMOTS_Private_Key(const LMOTS_Params& params,
 void LMOTS_Private_Key::sign(StrongSpan<LMOTS_Signature_Bytes> out_sig, const LMS_Message& msg) const {
    BOTAN_ARG_CHECK(out_sig.size() == LMOTS_Signature::size(params()), "Invalid output buffer size");
    BufferStuffer sig_stuffer(out_sig);
-   const auto hash = HashFunction::create_or_throw(params().hash_name());
+   const auto hash = params().hash();
    sig_stuffer.append(store_be(params().algorithm_type()));
    const auto C = sig_stuffer.next(params().n());
 
@@ -303,13 +306,13 @@ void LMOTS_Private_Key::derive_random_C(std::span<uint8_t> out, HashFunction& ha
 }
 
 LMOTS_Public_Key::LMOTS_Public_Key(const LMOTS_Private_Key& lmots_sk) : OTS_Instance(lmots_sk) {
-   const auto pk_hash = HashFunction::create_or_throw(lmots_sk.params().hash_name());
+   const auto pk_hash = lmots_sk.params().hash();
    pk_hash->update(lmots_sk.identifier());
    pk_hash->update(store_be(lmots_sk.q()));
    pk_hash->update(store_be(D_PBLC));
 
    Chain_Generator chain_gen(lmots_sk.identifier(), lmots_sk.q());
-   const auto hash = HashFunction::create_or_throw(lmots_sk.params().hash_name());
+   const auto hash = lmots_sk.params().hash();
    LMOTS_Node tmp(lmots_sk.params().n());
    for(uint16_t i = 0; i < lmots_sk.params().p(); ++i) {
       chain_gen.process(*hash, i, 0, lmots_sk.params().coef_max(), lmots_sk.chain_input(i), tmp);
@@ -330,13 +333,13 @@ LMOTS_K lmots_compute_pubkey_from_sig(const LMOTS_Signature& sig,
    const auto Q_with_cksm = gen_Q_with_cksm(params, identifier, q, sig.C(), msg);
 
    // Prefill the final hash object
-   const auto pk_hash = HashFunction::create_or_throw(params.hash_name());
+   const auto pk_hash = params.hash();
    pk_hash->update(identifier);
    pk_hash->update(store_be(q));
    pk_hash->update(store_be(D_PBLC));
 
    Chain_Generator chain_gen(identifier, q);
-   const auto hash = HashFunction::create_or_throw(params.hash_name());
+   const auto hash = params.hash();
    LMOTS_Node tmp(params.n());
    for(uint16_t i = 0; i < params.p(); ++i) {
       const uint8_t a = coef(Q_with_cksm, i, params);
diff --git a/src/lib/pubkey/hss_lms/lm_ots.h b/src/lib/pubkey/hss_lms/lm_ots.h
index f781c4178b6..596f4ec3d19 100644
--- a/src/lib/pubkey/hss_lms/lm_ots.h
+++ b/src/lib/pubkey/hss_lms/lm_ots.h
@@ -149,6 +149,11 @@ class BOTAN_TEST_API LMOTS_Params {
        */
       const std::string& hash_name() const { return m_hash_name; }
 
+      /**
+       * @brief Construct a new hash instance for the OTS instance.
+       */
+      std::unique_ptr<HashFunction> hash() const { return HashFunction::create_or_throw(hash_name()); }
+
    private:
       /**
        * @brief Construct a new LM-OTS parameter object.
diff --git a/src/lib/pubkey/hss_lms/lms.cpp b/src/lib/pubkey/hss_lms/lms.cpp
index d05a32cc4eb..a955c41cf09 100644
--- a/src/lib/pubkey/hss_lms/lms.cpp
+++ b/src/lib/pubkey/hss_lms/lms.cpp
@@ -55,11 +55,10 @@ class TreeAddress final {
 };
 
 auto get_hash_pair_func_for_identifier(const LMS_Params& lms_params, LMS_Identifier identifier) {
-   return [hash = HashFunction::create_or_throw(lms_params.hash_name()), I = std::move(identifier)](
-             StrongSpan<LMS_Tree_Node> out,
-             const TreeAddress& address,
-             StrongSpan<const LMS_Tree_Node> left,
-             StrongSpan<const LMS_Tree_Node> right) {
+   return [hash = lms_params.hash(), I = std::move(identifier)](StrongSpan<LMS_Tree_Node> out,
+                                                                const TreeAddress& address,
+                                                                StrongSpan<const LMS_Tree_Node> left,
+                                                                StrongSpan<const LMS_Tree_Node> right) {
       auto lms_address = dynamic_cast<const TreeAddress&>(address);
 
       hash->update(I);
@@ -83,8 +82,7 @@ void lms_gen_leaf(StrongSpan<LMS_Tree_Node> out,
 }
 
 auto lms_gen_leaf_func(const LMS_PrivateKey& lms_sk) {
-   return [hash = HashFunction::create_or_throw(lms_sk.lms_params().hash_name()), lms_sk](
-             StrongSpan<LMS_Tree_Node> out, const TreeAddress& tree_address) {
+   return [hash = lms_sk.lms_params().hash(), lms_sk](StrongSpan<LMS_Tree_Node> out, const TreeAddress& tree_address) {
       auto lmots_sk = LMOTS_Private_Key(lms_sk.lmots_params(), lms_sk.identifier(), tree_address.q(), lms_sk.seed());
       auto lmots_pk = LMOTS_Public_Key(lmots_sk);
       lms_gen_leaf(out, lmots_pk, tree_address, *hash);
@@ -165,9 +163,6 @@ LMS_Params LMS_Params::create_or_throw(LMS_Algorithm_Type type) {
 }
 
 LMS_Params LMS_Params::create_or_throw(std::string_view hash_name, uint8_t height) {
-   if(height != 5 && height != 10 && height != 15 && height != 20 && height != 25) {
-      throw Decoding_Error("Invalid height");
-   }
    LMS_Algorithm_Type type = [](std::string_view hash, uint8_t h) -> LMS_Algorithm_Type {
       if(hash == "SHA-256") {
          switch(h) {
@@ -278,7 +273,7 @@ LMS_PublicKey LMS_PublicKey::from_bytes_or_throw(BufferSlicer& slicer) {
    // Alg. 6. 2.c.
    auto lms_params = LMS_Params::create_or_throw(lms_type);
    // Alg. 6. 2.d.
-   if(total_remaining_bytes < size(lms_params)) {
+   if(total_remaining_bytes < LMS_PublicKey::size(lms_params)) {
       throw Decoding_Error("Too few bytes while parsing LMS public key.");
    }
    // Alg. 6. 2.b.
@@ -397,7 +392,7 @@ std::optional<LMS_Tree_Node> LMS_PublicKey::lms_compute_root_from_sig(const LMS_
       const LMOTS_Signature& lmots_sig = sig.lmots_sig();
       const LMOTS_Params lmots_params = LMOTS_Params::create_or_throw(lmots_sig.algorithm_type());
       const LMOTS_K Kc = lmots_compute_pubkey_from_sig(lmots_sig, msg, identifier(), sig.q());
-      const auto hash = HashFunction::create_or_throw(lms_params.hash_name());
+      const auto hash = lms_params.hash();
 
       auto hash_pair_func = get_hash_pair_func_for_identifier(lms_params, identifier());
 
diff --git a/src/lib/pubkey/hss_lms/lms.h b/src/lib/pubkey/hss_lms/lms.h
index 468bcace615..52587e46f6a 100644
--- a/src/lib/pubkey/hss_lms/lms.h
+++ b/src/lib/pubkey/hss_lms/lms.h
@@ -122,6 +122,11 @@ class BOTAN_TEST_API LMS_Params {
        */
       const std::string& hash_name() const { return m_hash_name; }
 
+      /**
+       * @brief Construct a new hash instance for the LMS instance.
+       */
+      std::unique_ptr<HashFunction> hash() const { return HashFunction::create_or_throw(hash_name()); }
+
    private:
       /**
        * @brief Construct a new LMS parameter object.