Skip to content

Commit

Permalink
Consumers can specify expectations of value availability
Browse files Browse the repository at this point in the history
  • Loading branch information
reneme committed Sep 11, 2024
1 parent 0b79910 commit 1be9081
Show file tree
Hide file tree
Showing 15 changed files with 110 additions and 65 deletions.
18 changes: 9 additions & 9 deletions src/lib/pk_pad/emsa.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@
namespace Botan {

std::unique_ptr<EMSA> EMSA::create_or_throw(PK_Signature_Options& options) {
const auto hash = options.maybe_hash_function();
const auto padding = options.padding();
const auto hash = options.hash_function().optional();
const auto padding = options.padding().optional();
const bool is_raw_hash = !hash.has_value() || hash.value() == "Raw";
const bool is_raw_padding = !padding.has_value() || padding.value() == "Raw";

Expand All @@ -43,9 +43,9 @@ std::unique_ptr<EMSA> EMSA::create_or_throw(PK_Signature_Options& options) {

#if defined(BOTAN_HAS_EMSA_RAW)
if(is_raw_hash) {
if(auto [using_prehash, prehash_fn] = options.prehash(); using_prehash && prehash_fn.has_value()) {
if(auto prehash = HashFunction::create(prehash_fn.value())) {
return std::make_unique<EMSA_Raw>(prehash->output_length());
if(auto prehash = options.prehash().optional(); prehash.has_value() && prehash->has_value()) {
if(auto prehash_fn = HashFunction::create(prehash->value())) {
return std::make_unique<EMSA_Raw>(prehash_fn->output_length());
}
} else {
return std::make_unique<EMSA_Raw>();
Expand All @@ -65,7 +65,7 @@ std::unique_ptr<EMSA> EMSA::create_or_throw(PK_Signature_Options& options) {
#if defined(BOTAN_HAS_EMSA_PKCS1)
if(padding == "PKCS1v15") {
if(is_raw_hash) {
return std::make_unique<EMSA_PKCS1v15_Raw>(options.prehash().second);
return std::make_unique<EMSA_PKCS1v15_Raw>(options.prehash().or_default(std::nullopt));
} else if(hash_fn) {
return std::make_unique<EMSA_PKCS1v15>(std::move(hash_fn));
}
Expand All @@ -74,18 +74,18 @@ std::unique_ptr<EMSA> EMSA::create_or_throw(PK_Signature_Options& options) {

#if defined(BOTAN_HAS_EMSA_PSSR)
if(padding == "PSS_Raw" && hash_fn) {
return std::make_unique<PSSR_Raw>(std::move(hash_fn), options.salt_size());
return std::make_unique<PSSR_Raw>(std::move(hash_fn), options.salt_size().optional());
}

if(padding == "PSS" && hash_fn) {
return std::make_unique<PSSR>(std::move(hash_fn), options.salt_size());
return std::make_unique<PSSR>(std::move(hash_fn), options.salt_size().optional());
}
#endif

#if defined(BOTAN_HAS_ISO_9796)
if(padding == "ISO_9796_DS2" && hash_fn) {
return std::make_unique<ISO_9796_DS2>(
std::move(hash_fn), !options.using_explicit_trailer_field(), options.salt_size());
std::move(hash_fn), !options.using_explicit_trailer_field(), options.salt_size().optional());
}

//ISO-9796-2 DS 3 is deterministic and DS2 without a salt
Expand Down
4 changes: 2 additions & 2 deletions src/lib/prov/pkcs11/p11_ecdsa.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ class PKCS11_ECDSA_Signature_Operation final : public PK_Ops::Signature {

public:
PKCS11_ECDSA_Signature_Operation(const PKCS11_ECDSA_PrivateKey& key, PK_Signature_Options& options) :
PKCS11_ECDSA_Signature_Operation(key, options.hash_function()) {}
PKCS11_ECDSA_Signature_Operation(key, options.hash_function().required()) {}

void update(std::span<const uint8_t> input) override {
if(!m_initialized) {
Expand Down Expand Up @@ -128,7 +128,7 @@ class PKCS11_ECDSA_Verification_Operation final : public PK_Ops::Verification {

public:
PKCS11_ECDSA_Verification_Operation(const PKCS11_ECDSA_PublicKey& key, PK_Signature_Options& options) :
PKCS11_ECDSA_Verification_Operation(key, options.hash_function()) {}
PKCS11_ECDSA_Verification_Operation(key, options.hash_function().required()) {}

void update(std::span<const uint8_t> input) override {
if(!m_initialized) {
Expand Down
4 changes: 2 additions & 2 deletions src/lib/prov/pkcs11/p11_mechanism.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -192,8 +192,8 @@ MechanismWrapper MechanismWrapper::create_rsa_crypt_mechanism(std::string_view p

MechanismWrapper MechanismWrapper::create_rsa_sign_mechanism(PK_Signature_Options& options) {
const std::string padding = [&]() {
const auto hash = options.maybe_hash_function();
const auto padding = options.padding();
const auto hash = options.hash_function().optional();
const auto padding = options.padding().optional();

if(hash && padding) {
return fmt("{}({})", padding.value(), hash.value());
Expand Down
8 changes: 4 additions & 4 deletions src/lib/pubkey/curve448/ed448/ed448.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -218,8 +218,8 @@ AlgorithmIdentifier Ed448_Sign_Operation::algorithm_identifier() const {
std::unique_ptr<PK_Ops::Verification> Ed448_PublicKey::_create_verification_op(PK_Signature_Options& options) const {
options.exclude_provider_for_algorithm(algo_name());

if(const auto [uses_prehash, prehash_fn] = options.prehash(); uses_prehash) {
return std::make_unique<Ed448_Verify_Operation>(*this, prehash_fn.value_or("SHAKE-256(512)"));
if(auto prehash = options.prehash().optional()) {
return std::make_unique<Ed448_Verify_Operation>(*this, prehash->value_or("SHAKE-256(512)"));
} else {
return std::make_unique<Ed448_Verify_Operation>(*this);
}
Expand All @@ -242,8 +242,8 @@ std::unique_ptr<PK_Ops::Signature> Ed448_PrivateKey::_create_signature_op(Random
BOTAN_UNUSED(rng);
options.exclude_provider_for_algorithm(algo_name());

if(const auto [uses_prehash, prehash_fn] = options.prehash(); uses_prehash) {
return std::make_unique<Ed448_Sign_Operation>(*this, prehash_fn.value_or("SHAKE-256(512)"));
if(auto prehash = options.prehash().optional()) {
return std::make_unique<Ed448_Sign_Operation>(*this, prehash->value_or("SHAKE-256(512)"));
} else {
return std::make_unique<Ed448_Sign_Operation>(*this);
}
Expand Down
5 changes: 4 additions & 1 deletion src/lib/pubkey/dilithium/dilithium_common/dilithium.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,10 @@ class Dilithium_Signature_Operation final : public PK_Ops::Signature {
m_s1(ntt(m_priv_key->s1().clone())),
m_s2(ntt(m_priv_key->s2().clone())),
m_t0(ntt(m_priv_key->t0().clone())),
m_A(Dilithium_Algos::expand_A(m_priv_key->rho(), m_priv_key->mode())) {}
m_A(Dilithium_Algos::expand_A(m_priv_key->rho(), m_priv_key->mode())) {
options.context().not_implemented("will come in Botan 3.7.0");
options.prehash().not_implemented("will come in Botan 3.7.0");
}

void update(std::span<const uint8_t> input) override { m_h.update(input); }

Expand Down
3 changes: 2 additions & 1 deletion src/lib/pubkey/eckcdsa/eckcdsa.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,12 @@ namespace {

std::unique_ptr<HashFunction> eckcdsa_signature_hash(PK_Signature_Options& options) {
// TODO: We could support prehashing, but it's not standard
options.prehash().not_implemented("non-standard prehashing is not supported");

// intentionally not supporting Raw for ECKCDSA, since we need to know
// the length in advance which complicates the logic for Raw

return HashFunction::create_or_throw(options.hash_function());
return HashFunction::create_or_throw(options.hash_function().required());
}

std::unique_ptr<HashFunction> eckcdsa_signature_hash(const AlgorithmIdentifier& alg_id) {
Expand Down
8 changes: 4 additions & 4 deletions src/lib/pubkey/ed25519/ed25519_key.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -276,9 +276,9 @@ class Ed25519_Hashed_Sign_Operation final : public PK_Ops::Signature {
std::unique_ptr<PK_Ops::Verification> Ed25519_PublicKey::_create_verification_op(PK_Signature_Options& options) const {
options.exclude_provider_for_algorithm(algo_name());

if(auto [uses_prehash, prehash_fn] = options.prehash(); uses_prehash) {
if(auto prehash = options.prehash().optional()) {
return std::make_unique<Ed25519_Hashed_Verify_Operation>(
*this, prehash_fn.value_or("SHA-512"), !prehash_fn.has_value());
*this, prehash->value_or("SHA-512"), !prehash->has_value());
} else {
return std::make_unique<Ed25519_Pure_Verify_Operation>(*this);
}
Expand All @@ -301,9 +301,9 @@ std::unique_ptr<PK_Ops::Signature> Ed25519_PrivateKey::_create_signature_op(Rand
BOTAN_UNUSED(rng);
options.exclude_provider_for_algorithm(algo_name());

if(auto [uses_prehash, prehash_fn] = options.prehash(); uses_prehash) {
if(auto prehash = options.prehash().optional()) {
return std::make_unique<Ed25519_Hashed_Sign_Operation>(
*this, prehash_fn.value_or("SHA-512"), !prehash_fn.has_value());
*this, prehash->value_or("SHA-512"), !prehash->has_value());
} else {
return std::make_unique<Ed25519_Pure_Sign_Operation>(*this);
}
Expand Down
9 changes: 4 additions & 5 deletions src/lib/pubkey/pk_ops.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -85,16 +85,15 @@ secure_vector<uint8_t> PK_Ops::Key_Agreement_with_KDF::agree(size_t key_len,
namespace {

std::unique_ptr<HashFunction> validate_options_returning_hash(PK_Signature_Options& options) {
const auto hash = options.hash_function();
const auto hash = options.hash_function().required();

/*
* In a sense ECDSA/DSA are *always* in prehashing mode, so we accept the case
* where prehashing is requested as long as the prehash hash matches the signature hash.
*/
if(auto [uses_prehash, prehash_fn] = options.prehash(); uses_prehash) {
if(prehash_fn.has_value() && prehash_fn.value() != hash) {
throw Invalid_Argument("This algorithm does not support prehashing with a different hash");
}
if(auto prehash = options.prehash().optional();
prehash.has_value() && prehash->has_value() && prehash->value() != hash) {
throw Invalid_Argument("This algorithm does not support prehashing with a different hash");
}

#if defined(BOTAN_HAS_RAW_HASH_FN)
Expand Down
2 changes: 1 addition & 1 deletion src/lib/pubkey/pk_options.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ PK_Signature_Options::PK_Signature_Options(std::string_view algo, std::string_vi

void PK_Signature_Options::validate_for_hash_based_signature_algorithm(
std::string_view algo_name, std::optional<std::string_view> acceptable_hash) {
if(auto hash = take(m_hash_fn)) {
if(auto hash = hash_function().optional()) {
if(!acceptable_hash.has_value()) {
throw Invalid_Argument(fmt("This {} key does not support explicit hash function choice", algo_name));
}
Expand Down
30 changes: 11 additions & 19 deletions src/lib/pubkey/pk_options.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@
#ifndef BOTAN_PK_OPTIONS_H_
#define BOTAN_PK_OPTIONS_H_

#include <botan/base_builder.h>
#include <botan/mem_ops.h>
#include <botan/options_builder.h>
#include <botan/pk_keys.h>
#include <optional>
#include <span>
Expand Down Expand Up @@ -286,46 +286,38 @@ class BOTAN_PUBLIC_API(3, 6) PK_Signature_Options : public Builder<PK_Signature_

// Getters; these are mostly for internal use

[[nodiscard]] std::string hash_function() { return require(m_hash_fn); }

[[nodiscard]] std::optional<std::string> maybe_hash_function() { return take(m_hash_fn); }
[[nodiscard]] auto hash_function() { return take(m_hash_fn); }

/// It may be acceptable to provide a hash function, for hash-based
/// signatures (like SLH-DSA or LMS), but it is not required.
/// @throws Invalid_Argument if the provided hash is not acceptable
void validate_for_hash_based_signature_algorithm(std::string_view algo_name,
std::optional<std::string_view> acceptable_hash = std::nullopt);

[[nodiscard]] std::pair<bool, std::optional<std::string>> prehash() {
if(auto prehash = take(m_prehash)) {
return {true, std::move(prehash.value())};
} else {
return {false, std::nullopt};
}
}
[[nodiscard]] auto prehash() { return take(m_prehash); }

[[nodiscard]] std::optional<std::string> padding() { return take(m_padding); }
[[nodiscard]] auto padding() { return take(m_padding); }

[[nodiscard]] std::optional<std::vector<uint8_t>> context() { return take(m_context); }
[[nodiscard]] auto context() { return take(m_context); }

[[nodiscard]] std::optional<std::string> provider() { return take(m_provider); }
[[nodiscard]] auto provider() { return take(m_provider); }

/// This is a convenience helper for algorithms that do not support
/// specifying a provider.
/// @throws Provider_Not_Found if a provider is set
void exclude_provider_for_algorithm(std::string_view algo_name) {
if(auto p = provider()) {
if(auto p = provider().optional()) {
throw Provider_Not_Found(algo_name, p.value());
};
}

[[nodiscard]] std::optional<size_t> salt_size() { return take(m_salt_size); }
[[nodiscard]] auto salt_size() { return take(m_salt_size); }

[[nodiscard]] bool using_der_encoded_signature() { return take(m_use_der).value_or(false); }
[[nodiscard]] bool using_der_encoded_signature() { return take(m_use_der).or_default(false); }

[[nodiscard]] bool using_deterministic_signature() { return take(m_deterministic_sig).value_or(false); }
[[nodiscard]] bool using_deterministic_signature() { return take(m_deterministic_sig).or_default(false); }

[[nodiscard]] bool using_explicit_trailer_field() { return take(m_explicit_trailer_field).value_or(false); }
[[nodiscard]] bool using_explicit_trailer_field() { return take(m_explicit_trailer_field).or_default(false); }

private:
friend class Builder<PK_Signature_Options>;
Expand Down
8 changes: 4 additions & 4 deletions src/lib/pubkey/sm2/sm2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -104,11 +104,11 @@ class SM2_Signature_Operation final : public PK_Ops::Signature {
public:
SM2_Signature_Operation(const SM2_PrivateKey& sm2, PK_Signature_Options& options) :
m_group(sm2.domain()), m_x(sm2._private_key()), m_da_inv(sm2._get_da_inv()) {
const auto hash = options.hash_function();
const auto hash = options.hash_function().required();
if(hash == "Raw") {
// m_hash is null, m_za is empty
} else {
auto context = options.context().value_or(sm2_default_userid);
auto context = options.context().or_default(sm2_default_userid);

m_hash = HashFunction::create_or_throw(hash);
// ZA=H256(ENTLA || IDA || a || b || xG || yG || xA || yA)
Expand Down Expand Up @@ -171,11 +171,11 @@ class SM2_Verification_Operation final : public PK_Ops::Verification {
public:
SM2_Verification_Operation(const SM2_PublicKey& sm2, PK_Signature_Options& options) :
m_group(sm2.domain()), m_gy_mul(sm2._public_key()) {
const auto hash = options.hash_function();
const auto hash = options.hash_function().required();
if(hash == "Raw") {
// m_hash is null, m_za is empty
} else {
auto context = options.context().value_or(sm2_default_userid);
auto context = options.context().or_default(sm2_default_userid);

m_hash = HashFunction::create_or_throw(hash);
// ZA=H256(ENTLA || IDA || a || b || xG || yG || xA || yA)
Expand Down
2 changes: 2 additions & 0 deletions src/lib/pubkey/sphincsplus/sphincsplus_common/sphincsplus.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,8 @@ std::unique_ptr<PK_Ops::Signature> SphincsPlus_PrivateKey::_create_signature_op(
PK_Signature_Options& options) const {
BOTAN_UNUSED(rng);
options.exclude_provider_for_algorithm(algo_name());
options.context().not_implemented("will come in Botan 3.7.0");
options.prehash().not_implemented("will come in Botan 3.7.0");
options.validate_for_hash_based_signature_algorithm(algo_name(), m_public->parameters().hash_name());
return std::make_unique<SphincsPlus_Signature_Operation>(
m_private, m_public, options.using_deterministic_signature());
Expand Down
2 changes: 1 addition & 1 deletion src/lib/utils/info.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,14 @@ load_on always
<header:public>
assert.h
allocator.h
base_builder.h
compiler.h
concepts.h
data_src.h
database.h
exceptn.h
mem_ops.h
mutex.h
options_builder.h
template_utils.h
types.h
strong_type.h
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
* Botan is released under the Simplified BSD License (see license.txt)
*/

#include <botan/base_builder.h>
#include <botan/options_builder.h>

#if defined(BOTAN_HAS_HASH)
#include <botan/hash.h>
Expand Down
Loading

0 comments on commit 1be9081

Please sign in to comment.