Skip to content

Commit

Permalink
Introduce a base builder as discussed here: #4318 (comment)
Browse files Browse the repository at this point in the history
  • Loading branch information
reneme committed Sep 11, 2024
1 parent bbaa196 commit c43bb8c
Show file tree
Hide file tree
Showing 55 changed files with 1,017 additions and 798 deletions.
13 changes: 6 additions & 7 deletions src/cli/pubkey.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -187,10 +187,10 @@ class PK_Sign final : public Command {
throw CLI_Error_Unsupported("hashing", hash_fn);
}

const auto options =
sig_options(key->algo_name(), get_arg("padding"), hash_fn, flag_set("der-format"), get_arg("provider"));

Botan::PK_Signer signer(*key, rng(), options);
Botan::PK_Signer signer(
*key,
rng(),
sig_options(key->algo_name(), get_arg("padding"), hash_fn, flag_set("der-format"), get_arg("provider")));

auto onData = [&signer](const uint8_t b[], size_t l) { signer.update(b, l); };
Command::read_file(get_arg("file"), onData);
Expand Down Expand Up @@ -234,9 +234,8 @@ class PK_Verify final : public Command {
throw CLI_Error_Unsupported("hashing", hash_fn);
}

const auto options = sig_options(key->algo_name(), get_arg("padding"), hash_fn, flag_set("der-format"), "");

Botan::PK_Verifier verifier(*key, options);
Botan::PK_Verifier verifier(
*key, sig_options(key->algo_name(), get_arg("padding"), hash_fn, flag_set("der-format"), ""));
auto onData = [&verifier](const uint8_t b[], size_t l) { verifier.update(b, l); };
Command::read_file(get_arg("file"), onData);

Expand Down
1 change: 1 addition & 0 deletions src/lib/math/pcurves/pcurves_impl/pcurves_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#define BOTAN_PCURVES_IMPL_H_

#include <botan/rng.h>
#include <botan/template_utils.h>
#include <botan/internal/ct_utils.h>
#include <botan/internal/loadstor.h>
#include <botan/internal/pcurves_util.h>
Expand Down
49 changes: 25 additions & 24 deletions src/lib/pk_pad/emsa.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,75 +32,76 @@

namespace Botan {

std::unique_ptr<EMSA> EMSA::create_or_throw(const PK_Signature_Options& options) {
const bool is_raw_hash = !options.using_hash() || options.hash_function_name() == "Raw";
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 bool is_raw_hash = !hash.has_value() || hash.value() == "Raw";
const bool is_raw_padding = !padding.has_value() || padding.value() == "Raw";

if(!options.using_padding() || options.padding() == "Raw") {
if(is_raw_padding) {
// Only valid possibility for empty padding is no hash / "Raw" hash

#if defined(BOTAN_HAS_EMSA_RAW)
if(is_raw_hash) {
if(options.using_prehash()) {
if(auto hash = HashFunction::create(options.prehash_fn().value())) {
return std::make_unique<EMSA_Raw>(hash->output_length());
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());
}
} else {
return std::make_unique<EMSA_Raw>();
}
}
#endif
} else {
const std::string padding = options.padding().value();

// null if raw_hash
auto hash = [&]() -> std::unique_ptr<HashFunction> {
auto hash_fn = [&]() -> std::unique_ptr<HashFunction> {
if(is_raw_hash) {
return nullptr;
} else {
return HashFunction::create(options.hash_function_name());
return HashFunction::create(hash.value());
}
}();

#if defined(BOTAN_HAS_EMSA_PKCS1)
if(padding == "PKCS1v15") {
if(is_raw_hash) {
return std::make_unique<EMSA_PKCS1v15_Raw>(options.prehash_fn());
} else if(hash) {
return std::make_unique<EMSA_PKCS1v15>(std::move(hash));
return std::make_unique<EMSA_PKCS1v15_Raw>(options.prehash().second);
} else if(hash_fn) {
return std::make_unique<EMSA_PKCS1v15>(std::move(hash_fn));
}
}
#endif

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

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

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

//ISO-9796-2 DS 3 is deterministic and DS2 without a salt
if(padding == "ISO_9796_DS3" && hash) {
return std::make_unique<ISO_9796_DS3>(std::move(hash), !options.using_explicit_trailer_field());
if(padding == "ISO_9796_DS3" && hash_fn) {
return std::make_unique<ISO_9796_DS3>(std::move(hash_fn), !options.using_explicit_trailer_field());
}
#endif

#if defined(BOTAN_HAS_EMSA_X931)
if(padding == "X9.31" && hash) {
return std::make_unique<EMSA_X931>(std::move(hash));
if(padding == "X9.31" && hash_fn) {
return std::make_unique<EMSA_X931>(std::move(hash_fn));
}
#endif
}

throw Lookup_Error("Invalid or unavailable signature padding scheme " + options.to_string());
throw Lookup_Error("Invalid or unavailable signature padding scheme\n" + options.to_string());
}

} // namespace Botan
2 changes: 1 addition & 1 deletion src/lib/pk_pad/emsa.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ class BOTAN_TEST_API EMSA {
* @param options the algorithm parameters
* @return pointer to newly allocated object of that type, or throws
*/
static std::unique_ptr<EMSA> create_or_throw(const PK_Signature_Options& options);
static std::unique_ptr<EMSA> create_or_throw(PK_Signature_Options& options);

/**
* Add more data to the signature computation
Expand Down
30 changes: 19 additions & 11 deletions src/lib/prov/pkcs11/p11_ecdsa.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,13 +53,17 @@ std::unique_ptr<Public_Key> PKCS11_ECDSA_PrivateKey::public_key() const {
namespace {

class PKCS11_ECDSA_Signature_Operation final : public PK_Ops::Signature {
public:
PKCS11_ECDSA_Signature_Operation(const PKCS11_ECDSA_PrivateKey& key, const PK_Signature_Options& options) :
private:
PKCS11_ECDSA_Signature_Operation(const PKCS11_ECDSA_PrivateKey& key, std::string_view hash) :
PK_Ops::Signature(),
m_key(key),
m_order_bytes(key.domain().get_order_bytes()),
m_mechanism(MechanismWrapper::create_ecdsa_mechanism(options.hash_function_name())),
m_hash(options.hash_function_name()) {}
m_mechanism(MechanismWrapper::create_ecdsa_mechanism(hash)),
m_hash(hash) {}

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

void update(std::span<const uint8_t> input) override {
if(!m_initialized) {
Expand Down Expand Up @@ -115,12 +119,16 @@ AlgorithmIdentifier PKCS11_ECDSA_Signature_Operation::algorithm_identifier() con
}

class PKCS11_ECDSA_Verification_Operation final : public PK_Ops::Verification {
public:
PKCS11_ECDSA_Verification_Operation(const PKCS11_ECDSA_PublicKey& key, const PK_Signature_Options& options) :
private:
PKCS11_ECDSA_Verification_Operation(const PKCS11_ECDSA_PublicKey& key, std::string_view hash) :
PK_Ops::Verification(),
m_key(key),
m_mechanism(MechanismWrapper::create_ecdsa_mechanism(options.hash_function_name())),
m_hash(options.hash_function_name()) {}
m_mechanism(MechanismWrapper::create_ecdsa_mechanism(hash)),
m_hash(hash) {}

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

void update(std::span<const uint8_t> input) override {
if(!m_initialized) {
Expand Down Expand Up @@ -176,12 +184,12 @@ class PKCS11_ECDSA_Verification_Operation final : public PK_Ops::Verification {
} // namespace

std::unique_ptr<PK_Ops::Verification> PKCS11_ECDSA_PublicKey::_create_verification_op(
const PK_Signature_Options& options) const {
PK_Signature_Options& options) const {
return std::make_unique<PKCS11_ECDSA_Verification_Operation>(*this, options);
}

std::unique_ptr<PK_Ops::Signature> PKCS11_ECDSA_PrivateKey::_create_signature_op(
RandomNumberGenerator& rng, const PK_Signature_Options& options) const {
std::unique_ptr<PK_Ops::Signature> PKCS11_ECDSA_PrivateKey::_create_signature_op(RandomNumberGenerator& rng,
PK_Signature_Options& options) const {
BOTAN_UNUSED(rng);
return std::make_unique<PKCS11_ECDSA_Signature_Operation>(*this, options);
}
Expand Down
4 changes: 2 additions & 2 deletions src/lib/prov/pkcs11/p11_ecdsa.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ class BOTAN_PUBLIC_API(2, 0) PKCS11_ECDSA_PublicKey final : public PKCS11_EC_Pub
throw Not_Implemented("Cannot generate a new PKCS#11 ECDSA keypair from this public key");
}

std::unique_ptr<PK_Ops::Verification> _create_verification_op(const PK_Signature_Options& options) const override;
std::unique_ptr<PK_Ops::Verification> _create_verification_op(PK_Signature_Options& options) const override;
};

BOTAN_DIAGNOSTIC_POP
Expand Down Expand Up @@ -118,7 +118,7 @@ class BOTAN_PUBLIC_API(2, 0) PKCS11_ECDSA_PrivateKey final : public PKCS11_EC_Pr
bool check_key(RandomNumberGenerator&, bool) const override;

std::unique_ptr<PK_Ops::Signature> _create_signature_op(RandomNumberGenerator& rng,
const PK_Signature_Options& options) const override;
PK_Signature_Options& options) const override;
};

using PKCS11_ECDSA_KeyPair = std::pair<PKCS11_ECDSA_PublicKey, PKCS11_ECDSA_PrivateKey>;
Expand Down
21 changes: 12 additions & 9 deletions src/lib/prov/pkcs11/p11_mechanism.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -190,24 +190,27 @@ MechanismWrapper MechanismWrapper::create_rsa_crypt_mechanism(std::string_view p
return mech;
}

MechanismWrapper MechanismWrapper::create_rsa_sign_mechanism(const PK_Signature_Options& options) {
const std::string padding = [&]() {
if(options.using_hash() && options.using_padding()) {
return fmt("{}({})", options.padding().value(), options.hash_function_name());
MechanismWrapper MechanismWrapper::create_rsa_sign_mechanism(PK_Signature_Options& options) {
const std::string mechanism_padding = [&]() {
const auto hash = options.maybe_hash_function();
const auto padding = options.padding();

if(hash && padding) {
return fmt("{}({})", padding.value(), hash.value());
}

if(options.using_padding()) {
return options.padding().value();
if(padding) {
return padding.value();
}

if(options.using_hash()) {
return options.hash_function_name();
if(hash) {
return hash.value();
}

throw Invalid_Argument("RSA signature requires a padding scheme");
}();

auto mechanism_info_it = SignMechanisms.find(padding);
auto mechanism_info_it = SignMechanisms.find(mechanism_padding);
if(mechanism_info_it == SignMechanisms.end()) {
// at this point it would be possible to support additional configurations that are not predefined above by parsing `padding`
throw Lookup_Error("PKCS#11 RSA sign/verify does not support padding with " + padding);
Expand Down
2 changes: 1 addition & 1 deletion src/lib/prov/pkcs11/p11_mechanism.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ class MechanismWrapper final {
* @param options supported paddings are Raw (X.509), EMSA3 (PKCS#1 v1.5), EMSA4 (PKCS#1 PSS),
* EMSA2 (ANSI X9.31) and ISO9796 (ISO/IEC 9796)
*/
static MechanismWrapper create_rsa_sign_mechanism(const PK_Signature_Options& options);
static MechanismWrapper create_rsa_sign_mechanism(PK_Signature_Options& options);

/**
* Creates the CK_MECHANISM data for ECDSA signature/verification
Expand Down
10 changes: 5 additions & 5 deletions src/lib/prov/pkcs11/p11_rsa.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@ class PKCS11_RSA_Encryption_Operation final : public PK_Ops::Encryption {

class PKCS11_RSA_Signature_Operation final : public PK_Ops::Signature {
public:
PKCS11_RSA_Signature_Operation(const PKCS11_RSA_PrivateKey& key, const PK_Signature_Options& options) :
PKCS11_RSA_Signature_Operation(const PKCS11_RSA_PrivateKey& key, PK_Signature_Options& options) :
m_key(key), m_mechanism(MechanismWrapper::create_rsa_sign_mechanism(options)) {}

size_t signature_length() const override { return m_key.get_n().bytes(); }
Expand Down Expand Up @@ -328,7 +328,7 @@ AlgorithmIdentifier PKCS11_RSA_Signature_Operation::algorithm_identifier() const

class PKCS11_RSA_Verification_Operation final : public PK_Ops::Verification {
public:
PKCS11_RSA_Verification_Operation(const PKCS11_RSA_PublicKey& key, const PK_Signature_Options& options) :
PKCS11_RSA_Verification_Operation(const PKCS11_RSA_PublicKey& key, PK_Signature_Options& options) :
m_key(key), m_mechanism(MechanismWrapper::create_rsa_sign_mechanism(options)) {}

void update(std::span<const uint8_t> input) override {
Expand Down Expand Up @@ -394,7 +394,7 @@ std::unique_ptr<PK_Ops::Encryption> PKCS11_RSA_PublicKey::create_encryption_op(R
}

std::unique_ptr<PK_Ops::Verification> PKCS11_RSA_PublicKey::_create_verification_op(
const PK_Signature_Options& options) const {
PK_Signature_Options& options) const {
return std::make_unique<PKCS11_RSA_Verification_Operation>(*this, options);
}

Expand All @@ -408,8 +408,8 @@ std::unique_ptr<PK_Ops::Decryption> PKCS11_RSA_PrivateKey::create_decryption_op(
}
}

std::unique_ptr<PK_Ops::Signature> PKCS11_RSA_PrivateKey::_create_signature_op(
RandomNumberGenerator& rng, const PK_Signature_Options& options) const {
std::unique_ptr<PK_Ops::Signature> PKCS11_RSA_PrivateKey::_create_signature_op(RandomNumberGenerator& rng,
PK_Signature_Options& options) const {
BOTAN_UNUSED(rng);
return std::make_unique<PKCS11_RSA_Signature_Operation>(*this, options);
}
Expand Down
4 changes: 2 additions & 2 deletions src/lib/prov/pkcs11/p11_rsa.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ class BOTAN_PUBLIC_API(2, 0) PKCS11_RSA_PublicKey : public Object,
std::string_view params,
std::string_view provider) const override;

std::unique_ptr<PK_Ops::Verification> _create_verification_op(const PK_Signature_Options& options) const override;
std::unique_ptr<PK_Ops::Verification> _create_verification_op(PK_Signature_Options& options) const override;
};

/// Properties for importing a PKCS#11 RSA private key
Expand Down Expand Up @@ -191,7 +191,7 @@ class BOTAN_PUBLIC_API(2, 0) PKCS11_RSA_PrivateKey final : public Object,
std::string_view provider) const override;

std::unique_ptr<PK_Ops::Signature> _create_signature_op(RandomNumberGenerator& rng,
const PK_Signature_Options& options) const override;
PK_Signature_Options& options) const override;

private:
bool m_use_software_padding = false;
Expand Down
6 changes: 3 additions & 3 deletions src/lib/prov/tpm/tpm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -373,12 +373,12 @@ class TPM_Signing_Operation final : public PK_Ops::Signature {
} // namespace

std::unique_ptr<PK_Ops::Signature> TPM_PrivateKey::_create_signature_op(RandomNumberGenerator& rng,
const PK_Signature_Options& options) const {
PK_Signature_Options& options) const {
BOTAN_UNUSED(rng);
if(!options.using_padding() || options.padding().value() != "PKCS1v15") {
if(auto padding = options.padding(); padding && padding.value() != "PKCS1v15") {
throw Invalid_Argument("TPMv1 can only sign using PKCS1v15 padding");
}
return std::make_unique<TPM_Signing_Operation>(*this, options.hash_function_name());
return std::make_unique<TPM_Signing_Operation>(*this, options.hash_function());
}

} // namespace Botan
2 changes: 1 addition & 1 deletion src/lib/prov/tpm/tpm.h
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ class BOTAN_PUBLIC_API(2, 0) TPM_PrivateKey final : public Private_Key {
bool supports_operation(PublicKeyOperation op) const override { return (op == PublicKeyOperation::Signature); }

std::unique_ptr<PK_Ops::Signature> _create_signature_op(RandomNumberGenerator& rng,
const PK_Signature_Options& options) const override;
PK_Signature_Options& options) const override;

private:
TPM_Context& m_ctx;
Expand Down
Loading

0 comments on commit c43bb8c

Please sign in to comment.