Skip to content

Commit

Permalink
Apply review suggestions III
Browse files Browse the repository at this point in the history
  • Loading branch information
FAlbertDev committed Sep 20, 2024
1 parent 6f21276 commit 16a9a13
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 23 deletions.
24 changes: 18 additions & 6 deletions src/lib/pubkey/sphincsplus/sphincsplus_common/sp_fors.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,14 +32,26 @@ std::vector<TreeNodeIndex> fors_message_to_indices(std::span<const uint8_t> mess

uint32_t offset = 0;

// This is one of the few places where the logic of SPHINCS+ round 3.1 and SLH-DSA differs
auto update_idx = [&]() -> std::function<void(TreeNodeIndex&, uint32_t)> {
#if defined(BOTAN_HAS_SLH_DSA_WITH_SHA2) or defined(BOTAN_HAS_SLH_DSA_WITH_SHAKE)
if(params.is_slh_dsa()) {
return [&](TreeNodeIndex& idx, uint32_t i) {
idx ^= (((message[offset >> 3] >> (~offset & 0x7)) & 0x1) << (params.a() - 1 - i));
};
}
#endif
#if defined(BOTAN_HAS_SPHINCS_PLUS_WITH_SHA2) or defined(BOTAN_HAS_SPHINCS_PLUS_WITH_SHAKE)
if(!params.is_slh_dsa()) {
return [&](TreeNodeIndex& idx, uint32_t i) { idx ^= (((message[offset >> 3] >> (offset & 0x7)) & 0x1) << i); };
}
#endif
throw Internal_Error("Missing FORS index update logic for SPHINCS+ or SLH-DSA");
}();

for(auto& idx : indices) {
for(uint32_t i = 0; i < params.a(); ++i, ++offset) {
// This is one of the few places where SPHINCS+ round 3.1 and SLH-DSA differ
if(params.is_slh_dsa()) {
idx ^= (((message[offset >> 3] >> (~offset & 0x7)) & 0x1) << (params.a() - 1 - i));
} else {
idx ^= (((message[offset >> 3] >> (offset & 0x7)) & 0x1) << i);
}
update_idx(idx, i);
}
}

Expand Down
43 changes: 26 additions & 17 deletions src/lib/pubkey/sphincsplus/sphincsplus_common/sphincsplus.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,24 +33,27 @@ namespace Botan {

namespace {
// FIPS 205, Algorithm 22, line 8
SphincsMessageInternal prepare_message(SphincsInputMessage&& msg,
SphincsMessageInternal prepare_message(SphincsInputMessage msg,
const Sphincs_Parameters& params,
StrongSpan<const SphincsContext> context) {
BOTAN_ARG_CHECK(params.is_slh_dsa() || context.empty(), "Context is not supported for SPHINCS+");
SphincsMessageInternal msg_internal{.prefix = SphincsMessagePrefix(), .message = std::move(msg)};
[[maybe_unused]] SphincsMessageInternal msg_internal{.prefix = SphincsMessagePrefix(), .message = std::move(msg)};
#if defined(BOTAN_HAS_SLH_DSA_WITH_SHA2) or defined(BOTAN_HAS_SLH_DSA_WITH_SHAKE)
if(params.is_slh_dsa()) {
// prefix (no pre-hash mode): input mode byte + |ctx| + ctx
msg_internal.prefix = SphincsMessagePrefix(1 + 1 + context.size());
BufferStuffer prefix_stuffer(msg_internal.prefix);
const uint8_t input_mode_byte = 0x00; // Pure (TODO: pre-hash mode: 0x01)
prefix_stuffer.append(input_mode_byte);
prefix_stuffer.append(checked_cast_to<uint8_t>(context.size()));
prefix_stuffer.append(context);

BOTAN_ASSERT_NOMSG(prefix_stuffer.full());
msg_internal.prefix = concat<SphincsMessagePrefix>(
store_be(input_mode_byte), store_be(checked_cast_to<uint8_t>(context.size())), context);
return msg_internal;
}
#endif
#if defined(BOTAN_HAS_SPHINCS_PLUS_WITH_SHA2) or defined(BOTAN_HAS_SPHINCS_PLUS_WITH_SHAKE)
if(!params.is_slh_dsa()) {
// SPHINCS+ Round 3.1 uses the message without any prefix
return msg_internal;
}
// else: SPHINCS+ Round 3.1 uses the message without any prefix
return msg_internal;
#endif
throw Internal_Error("Missing message preparation logic for SLH-DSA or SPHINCS+");
}
} // namespace

Expand All @@ -63,7 +66,7 @@ class SphincsPlus_PublicKeyInternal final {

SphincsPlus_PublicKeyInternal(Sphincs_Parameters params, std::span<const uint8_t> key_bits) : m_params(params) {
if(key_bits.size() != m_params.public_key_bytes()) {
throw Decoding_Error("SLH-DSA(or SPHINCS+) Public Key doesn't have the expected length");
throw Decoding_Error("SLH-DSA (or SPHINCS+) Public Key doesn't have the expected length");
}

BufferSlicer s(key_bits);
Expand Down Expand Up @@ -94,7 +97,7 @@ class SphincsPlus_PrivateKeyInternal final {

SphincsPlus_PrivateKeyInternal(const Sphincs_Parameters& params, std::span<const uint8_t> key_bits) {
if(key_bits.size() != params.private_key_bytes() - params.public_key_bytes()) {
throw Decoding_Error("SLH-DSA(or SPHINCS+) Private Key doesn't have the expected length");
throw Decoding_Error("SLH-DSA (or SPHINCS+) Private Key doesn't have the expected length");
}

BufferSlicer s(key_bits);
Expand Down Expand Up @@ -175,7 +178,11 @@ class SphincsPlus_Verification_Operation final : public PK_Ops::Verification {
SphincsPlus_Verification_Operation(std::shared_ptr<SphincsPlus_PublicKeyInternal> pub_key) :
m_public(std::move(pub_key)),
m_hashes(Botan::Sphincs_Hash_Functions::create(m_public->parameters(), m_public->seed())),
m_context(/* TODO: Add API */ {}) {}
m_context(/* TODO: Add API */ {}) {
BOTAN_ARG_CHECK(m_context.size() <= 255, "Context must not exceed 255 bytes");
BOTAN_ARG_CHECK(m_public->parameters().is_available(),
"The selected SLH-DSA (or SPHINCS+) instance is not available in this build.");
}

/**
* Add more data to the message currently being signed
Expand Down Expand Up @@ -239,7 +246,7 @@ std::unique_ptr<PK_Ops::Verification> SphincsPlus_PublicKey::create_x509_verific
const AlgorithmIdentifier& signature_algorithm, std::string_view provider) const {
if(provider.empty() || provider == "base") {
if(signature_algorithm != this->algorithm_identifier()) {
throw Decoding_Error("Unexpected AlgorithmIdentifier for SLH-DSA(or SPHINCS+) signature");
throw Decoding_Error("Unexpected AlgorithmIdentifier for SLH-DSA (or SPHINCS+) signature");
}
return std::make_unique<SphincsPlus_Verification_Operation>(m_public);
}
Expand Down Expand Up @@ -332,6 +339,8 @@ class SphincsPlus_Signature_Operation final : public PK_Ops::Signature {
m_randomized(randomized),
m_context(/* TODO: add API for context */ {}) {
BOTAN_ARG_CHECK(m_context.size() <= 255, "Context must not exceed 255 bytes");
BOTAN_ARG_CHECK(m_public->parameters().is_available(),
"The selected SLH-DSA (or SPHINCS+) instance is not available in this build.");
}

void update(std::span<const uint8_t> msg) override {
Expand Down Expand Up @@ -368,7 +377,7 @@ class SphincsPlus_Signature_Operation final : public PK_Ops::Signature {

// Compute and append the digest randomization value (R of spec).
// Use addrng for the randomized variant. Use the public seed for the deterministic one.
auto opt_rand =
const auto opt_rand =
(addrnd.has_value()) ? addrnd.value() : StrongSpan<const SphincsOptionalRandomness>(m_public->seed());

auto msg_random_s = sphincs_sig.next<SphincsMessageRandomness>(p.n());
Expand Down Expand Up @@ -413,7 +422,7 @@ std::unique_ptr<PK_Ops::Signature> SphincsPlus_PrivateKey::create_signature_op(R
std::string_view provider) const {
BOTAN_UNUSED(rng);
BOTAN_ARG_CHECK(params.empty() || params == "Deterministic" || params == "Randomized",
"Unexpected parameters for signing with SLH-DSA(or SPHINCS+)");
"Unexpected parameters for signing with SLH-DSA (or SPHINCS+)");

const bool randomized = (params == "Randomized");
if(provider.empty() || provider == "base") {
Expand Down

0 comments on commit 16a9a13

Please sign in to comment.