Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 18 additions & 43 deletions src/cli/pubkey.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,12 @@
#include <botan/hex.h>
#include <botan/pk_algs.h>
#include <botan/pk_keys.h>
#include <botan/pk_options.h>
#include <botan/pkcs8.h>
#include <botan/pubkey.h>
#include <botan/x509_key.h>
#include <botan/internal/workfactor.h>
#include <fstream>
#include <sstream>

#if defined(BOTAN_HAS_DL_GROUP)
#include <botan/dl_group.h>
Expand Down Expand Up @@ -96,26 +96,17 @@ BOTAN_REGISTER_COMMAND("keygen", PK_Keygen);

namespace {

std::string choose_sig_padding(const std::string& key, const std::string& padding, const std::string& hash) {
if(key == "RSA") {
std::ostringstream oss;
if(padding.empty()) {
oss << "PSS";
} else {
oss << padding;
}

oss << "(" << hash << ")";
return oss.str();
} else if(padding.empty()) {
return hash;
} else if(hash.empty()) {
return padding;
} else {
std::ostringstream oss;
oss << padding << "(" << hash << ")";
return oss.str();
Botan::PK_Signature_Options sig_options(
std::string_view key, std::string_view padding, std::string_view hash, bool use_der, std::string_view provider) {

@falko-strenzke falko-strenzke Mar 27, 2026

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using string arguments is not a good approach in my view. But maybe for now it is the simplest option. However, in the future, we can add a type framework for the parameters and start to define further constructors for the PK_Signature_Options.

if(key == "RSA" && padding.empty()) {
return sig_options(key, "PSS", hash, use_der, provider);
}

return Botan::PK_Signature_Options()
.with_hash(hash)
.with_padding(padding)
.with_der_encoded_signature(use_der)
.with_provider(provider);
}

} // namespace
Expand Down Expand Up @@ -198,21 +189,14 @@ class PK_Sign final : public Command {
throw CLI_Error_Unsupported("hashing", hash_fn);
}

const std::string sig_padding = choose_sig_padding(key->algo_name(), get_arg("padding"), hash_fn);

auto format = Botan::Signature_Format::Standard;

if(flag_set("der-format")) {
if(!key->_signature_element_size_for_DER_encoding()) {
throw CLI_Usage_Error("Key type " + key->algo_name() +
" does not support DER formatting for signatures");
}
format = Botan::Signature_Format::DerSequence;
if(flag_set("der-format") && !key->_signature_element_size_for_DER_encoding()) {
throw CLI_Usage_Error("Key type " + key->algo_name() + " does not support DER formatting for signatures");
}

const std::string provider = get_arg("provider");
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(), sig_padding, format, provider);
Botan::PK_Signer signer(*key, rng(), options);

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 @@ -256,18 +240,9 @@ class PK_Verify final : public Command {
throw CLI_Error_Unsupported("hashing", hash_fn);
}

const std::string sig_padding = choose_sig_padding(key->algo_name(), get_arg("padding"), hash_fn);

auto format = Botan::Signature_Format::Standard;
if(flag_set("der-format")) {
if(key->message_parts() == 1) {
throw CLI_Usage_Error("Key type " + key->algo_name() +
" does not support DER formatting for signatures");
}
format = Botan::Signature_Format::DerSequence;
}
const auto options = sig_options(key->algo_name(), get_arg("padding"), hash_fn, flag_set("der-format"), "");

Botan::PK_Verifier verifier(*key, sig_padding, format);
Botan::PK_Verifier verifier(*key, options);
auto onData = [&verifier](const uint8_t b[], size_t l) { verifier.update(b, l); };
Command::read_file(get_arg("file"), onData);

Expand Down
4 changes: 2 additions & 2 deletions src/examples/ecdsa.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,13 @@ int main() {
const std::string message("This is a tasty burger!");

// sign data
Botan::PK_Signer signer(key, rng, "SHA-256");
Botan::PK_Signer signer(key, rng, Botan::PK_Signature_Options().with_hash("SHA-256"));
signer.update(message);
std::vector<uint8_t> signature = signer.signature(rng);
std::cout << "Signature:\n" << Botan::hex_encode(signature);

// now verify the signature
Botan::PK_Verifier verifier(key, "SHA-256");
Botan::PK_Verifier verifier(key, Botan::PK_Signature_Options().with_hash("SHA-256"));
verifier.update(message);
std::cout << "\nis " << (verifier.check_signature(signature) ? "valid" : "invalid");
return 0;
Expand Down
2 changes: 1 addition & 1 deletion src/examples/pkcs11_ecdsa.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ int main() {

std::vector<uint8_t> plaintext(20, 0x01);

Botan::PK_Signer signer(key_pair.second, rng, "Raw", Botan::Signature_Format::Standard, "pkcs11");
Botan::PK_Signer signer(key_pair.second, rng, Botan::PK_Signature_Options().with_hash("Raw"));
auto signature = signer.sign_message(plaintext, rng);

Botan::PK_Verifier token_verifier(key_pair.first, "Raw", Botan::Signature_Format::Standard, "pkcs11");
Expand Down
4 changes: 2 additions & 2 deletions src/examples/xmss.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,14 @@ int main() {
const Botan::XMSS_PublicKey& public_key(private_key);

// create Public Key Signer using the private key.
Botan::PK_Signer signer(private_key, rng, "");
Botan::PK_Signer signer(private_key, rng);

// create and sign a message using the Public Key Signer.
Botan::secure_vector<uint8_t> msg{0x01, 0x02, 0x03, 0x04};
auto sig = signer.sign_message(msg, rng);

// create Public Key Verifier using the public key
Botan::PK_Verifier verifier(public_key, "");
Botan::PK_Verifier verifier(public_key);

// verify the signature for the previously generated message.
if(verifier.verify_message(msg, sig)) {
Expand Down
30 changes: 20 additions & 10 deletions src/lib/pk_pad/sig_padding/emsa_pkcs1/pkcs1_sig_padding.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,11 @@

#include <botan/internal/pkcs1_sig_padding.h>

#include <botan/assert.h>
#include <botan/exceptn.h>
#include <botan/hash.h>
#include <botan/mem_ops.h>
#include <botan/pk_options.h>
#include <botan/internal/buffer_stuffer.h>
#include <botan/internal/fmt.h>
#include <botan/internal/hash_id.h>
Expand Down Expand Up @@ -75,8 +77,12 @@ bool PKCS1v15_SignaturePaddingScheme::verify(std::span<const uint8_t> coded,
}
}

PKCS1v15_SignaturePaddingScheme::PKCS1v15_SignaturePaddingScheme(std::unique_ptr<HashFunction> hash) :
m_hash(std::move(hash)) {
PKCS1v15_SignaturePaddingScheme::PKCS1v15_SignaturePaddingScheme(const PK_Signature_Options& options) :
m_hash(HashFunction::create_or_throw(options.hash_function_name())) {
BOTAN_ARG_CHECK(!options.using_salt_size(), "PKCS1v15 does not support a salt");
BOTAN_ARG_CHECK(!options.using_explicit_trailer_field(), "PKCS1v15 does not support a padding trailer field");
BOTAN_ARG_CHECK(!options.using_prehash(), "PKCS1v15 does not support prehashing");

m_hash_id = pkcs_hash_id(m_hash->name());
}

Expand All @@ -96,15 +102,19 @@ std::string PKCS1v15_Raw_SignaturePaddingScheme::name() const {
}
}

PKCS1v15_Raw_SignaturePaddingScheme::PKCS1v15_Raw_SignaturePaddingScheme() : m_hash_output_len(0) {
// m_hash_id, m_hash_name left empty
}
PKCS1v15_Raw_SignaturePaddingScheme::PKCS1v15_Raw_SignaturePaddingScheme(const PK_Signature_Options& options) {
BOTAN_ARG_CHECK(!options.using_salt_size(), "PKCS1v15 does not support a salt");
BOTAN_ARG_CHECK(!options.using_explicit_trailer_field(), "PKCS1v15 does not support a padding trailer field");

PKCS1v15_Raw_SignaturePaddingScheme::PKCS1v15_Raw_SignaturePaddingScheme(std::string_view hash_algo) {
std::unique_ptr<HashFunction> hash(HashFunction::create_or_throw(hash_algo));
m_hash_id = pkcs_hash_id(hash_algo);
m_hash_name = hash->name();
m_hash_output_len = hash->output_length();
if(const auto& hash_algo = options.prehash_function()) {
std::unique_ptr<HashFunction> hash(HashFunction::create_or_throw(hash_algo.value()));
m_hash_id = pkcs_hash_id(hash->name());
m_hash_name = hash->name();
m_hash_output_len = hash->output_length();
} else {
m_hash_output_len = 0;
// m_hash_id, m_hash_name left empty
}
}

void PKCS1v15_Raw_SignaturePaddingScheme::update(const uint8_t input[], size_t length) {
Expand Down
17 changes: 4 additions & 13 deletions src/lib/pk_pad/sig_padding/emsa_pkcs1/pkcs1_sig_padding.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@

#include <memory>
#include <string>
#include <string_view>
#include <vector>

namespace Botan {

class HashFunction;
class PK_Signature_Options;

/**
* PKCS #1 v1.5 signature padding
Expand All @@ -26,10 +26,7 @@ class HashFunction;
*/
class PKCS1v15_SignaturePaddingScheme final : public SignaturePaddingScheme {
public:
/**
* @param hash the hash function to use
*/
explicit PKCS1v15_SignaturePaddingScheme(std::unique_ptr<HashFunction> hash);
explicit PKCS1v15_SignaturePaddingScheme(const PK_Signature_Options& options);

void update(const uint8_t input[], size_t length) override;

Expand Down Expand Up @@ -57,6 +54,8 @@ class PKCS1v15_SignaturePaddingScheme final : public SignaturePaddingScheme {
*/
class PKCS1v15_Raw_SignaturePaddingScheme final : public SignaturePaddingScheme {
public:
explicit PKCS1v15_Raw_SignaturePaddingScheme(const PK_Signature_Options& options);

void update(const uint8_t input[], size_t length) override;

std::vector<uint8_t> raw_data() override;
Expand All @@ -67,14 +66,6 @@ class PKCS1v15_Raw_SignaturePaddingScheme final : public SignaturePaddingScheme

bool verify(std::span<const uint8_t> coded, std::span<const uint8_t> raw, size_t key_bits) override;

PKCS1v15_Raw_SignaturePaddingScheme();

/**
* @param hash_algo the digest id for that hash is included in
* the signature.
*/
explicit PKCS1v15_Raw_SignaturePaddingScheme(std::string_view hash_algo);

std::string hash_function() const override { return m_hash_name; }

std::string name() const override;
Expand Down
30 changes: 22 additions & 8 deletions src/lib/pk_pad/sig_padding/emsa_pssr/pssr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@

#include <botan/internal/pssr.h>

#include <botan/assert.h>
#include <botan/exceptn.h>
#include <botan/hash.h>
#include <botan/pk_options.h>
#include <botan/rng.h>
#include <botan/internal/buffer_stuffer.h>
#include <botan/internal/ct_utils.h>
Expand Down Expand Up @@ -146,11 +148,17 @@ bool pss_verify(HashFunction& hash,

} // namespace

PSSR::PSSR(std::unique_ptr<HashFunction> hash) :
m_hash(std::move(hash)), m_salt_size(m_hash->output_length()), m_required_salt_len(false) {}
PSSR::PSSR(const PK_Signature_Options& options) :
m_hash(HashFunction::create_or_throw(options.hash_function_name())),
m_salt_size(options.salt_size().value_or(m_hash->output_length())),
m_required_salt_len(options.using_salt_size()) {
BOTAN_ARG_CHECK(!options.using_prehash(), "PSS does not support prehashing");
BOTAN_ARG_CHECK(!options.using_explicit_trailer_field(), "PSS does not support a padding trailer field");

PSSR::PSSR(std::unique_ptr<HashFunction> hash, size_t salt_size) :
m_hash(std::move(hash)), m_salt_size(salt_size), m_required_salt_len(true) {}
if(options.using_deterministic_signature() && m_salt_size > 0) {
throw Invalid_Argument("PSS with a non-zero salt cannot produce deterministic signatures");
}
}

/*
* PSSR Update Operation
Expand Down Expand Up @@ -193,11 +201,17 @@ std::string PSSR::name() const {
return fmt("PSS({},MGF1,{})", m_hash->name(), m_salt_size);
}

PSS_Raw::PSS_Raw(std::unique_ptr<HashFunction> hash) :
m_hash(std::move(hash)), m_salt_size(m_hash->output_length()), m_required_salt_len(false) {}
PSS_Raw::PSS_Raw(const PK_Signature_Options& options) :
m_hash(HashFunction::create_or_throw(options.hash_function_name())),
m_salt_size(options.salt_size().value_or(m_hash->output_length())),
m_required_salt_len(options.using_salt_size()) {
BOTAN_ARG_CHECK(!options.using_prehash(), "PSS_Raw does not support prehashing");
BOTAN_ARG_CHECK(!options.using_explicit_trailer_field(), "PSS does not support a padding trailer field");

PSS_Raw::PSS_Raw(std::unique_ptr<HashFunction> hash, size_t salt_size) :
m_hash(std::move(hash)), m_salt_size(salt_size), m_required_salt_len(true) {}
if(options.using_deterministic_signature() && m_salt_size > 0) {
throw Invalid_Argument("PSS with a non-zero salt cannot produce deterministic signatures");
}
}

/*
* PSS_Raw Update Operation
Expand Down
23 changes: 3 additions & 20 deletions src/lib/pk_pad/sig_padding/emsa_pssr/pssr.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,22 +17,14 @@ namespace Botan {

class RandomNumberGenerator;
class HashFunction;
class PK_Signature_Options;

/**
* PSSR (called EMSA4 in IEEE 1363 and in old versions of the library)
*/
class PSSR final : public SignaturePaddingScheme {
public:
/**
* @param hash the hash function to use
*/
explicit PSSR(std::unique_ptr<HashFunction> hash);

/**
* @param hash the hash function to use
* @param salt_size the size of the salt to use in bytes
*/
PSSR(std::unique_ptr<HashFunction> hash, size_t salt_size);
explicit PSSR(const PK_Signature_Options& options);

std::string name() const override;

Expand Down Expand Up @@ -60,16 +52,7 @@ class PSSR final : public SignaturePaddingScheme {
*/
class PSS_Raw final : public SignaturePaddingScheme {
public:
/**
* @param hash the hash function to use
*/
explicit PSS_Raw(std::unique_ptr<HashFunction> hash);

/**
* @param hash the hash function to use
* @param salt_size the size of the salt to use in bytes
*/
PSS_Raw(std::unique_ptr<HashFunction> hash, size_t salt_size);
explicit PSS_Raw(const PK_Signature_Options& options);

std::string hash_function() const override;

Expand Down
17 changes: 17 additions & 0 deletions src/lib/pk_pad/sig_padding/emsa_raw/raw_sig_padding.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,30 @@

#include <botan/internal/raw_sig_padding.h>

#include <botan/assert.h>
#include <botan/exceptn.h>
#include <botan/hash.h>
#include <botan/mem_ops.h>
#include <botan/pk_options.h>
#include <botan/internal/ct_utils.h>
#include <botan/internal/fmt.h>

namespace Botan {

SignRawBytes::SignRawBytes(const PK_Signature_Options& options) :
m_expected_size([&]() -> size_t {
BOTAN_ARG_CHECK(!options.using_salt_size(), "Raw signing does not support a salt");
BOTAN_ARG_CHECK(!options.using_explicit_trailer_field(),
"Raw signing does not support a padding trailer field");

if(options.using_prehash()) {
if(auto hash = HashFunction::create(options.prehash_function().value())) {
return hash->output_length();
}
}
return 0;
}()) {}

std::string SignRawBytes::name() const {
if(m_expected_size > 0) {
return fmt("Raw({})", m_expected_size);
Expand Down
3 changes: 2 additions & 1 deletion src/lib/pk_pad/sig_padding/emsa_raw/raw_sig_padding.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

namespace Botan {

class PK_Signature_Options;
class RandomNumberGenerator;

/**
Expand All @@ -22,7 +23,7 @@ class RandomNumberGenerator;
*/
class SignRawBytes final : public SignaturePaddingScheme {
public:
explicit SignRawBytes(size_t expected_hash_size = 0) : m_expected_size(expected_hash_size) {}
explicit SignRawBytes(const PK_Signature_Options& options);

std::string hash_function() const override { return "Raw"; }

Expand Down
Loading
Loading