diff --git a/src/lib/prov/tpm2/tpm2_algo_mappings.h b/src/lib/prov/tpm2/tpm2_algo_mappings.h index fcf1b40dcea..324141bede5 100644 --- a/src/lib/prov/tpm2/tpm2_algo_mappings.h +++ b/src/lib/prov/tpm2/tpm2_algo_mappings.h @@ -346,9 +346,11 @@ namespace Botan::TPM2 { return std::nullopt; } - if(scheme.value() == TPM2_ALG_RSAPSS && req.arg_count() != 1) { - // RSA signing using PSS with MGF1 - return std::nullopt; + if(scheme.value() == TPM2_ALG_RSAPSS) { + // RSA signing using PSS with MGF1 and salt size of 32 + if(req.arg(1, "MGF1") != "MGF1" || req.arg_as_integer(2, 32) != 32) { + return std::nullopt; + } } return TPMT_SIG_SCHEME{ diff --git a/src/lib/prov/tpm2/tpm2_ecc/tpm2_ecc.cpp b/src/lib/prov/tpm2/tpm2_ecc/tpm2_ecc.cpp index 04552a65257..44a49e689da 100644 --- a/src/lib/prov/tpm2/tpm2_ecc/tpm2_ecc.cpp +++ b/src/lib/prov/tpm2/tpm2_ecc/tpm2_ecc.cpp @@ -159,15 +159,16 @@ std::unique_ptr EC_PrivateKey::create_unrestricted_transient(c namespace { -SignatureAlgorithmSelection make_signature_scheme(std::string_view hash_name) { +SignatureAlgorithmSelection make_signature_scheme(PK_Signature_Options& options) { + auto hash_name = options.hash_function().required(); return { .signature_scheme = TPMT_SIG_SCHEME{ .scheme = TPM2_ALG_ECDSA, // Only support ECDSA .details = {.any = {.hashAlg = get_tpm2_hash_type(hash_name)}}, }, - .hash_name = std::string(hash_name), - .padding = std::nullopt, + .hash_name = std::move(hash_name), + .emsa = nullptr, // ECC does not use an EMSA }; } @@ -183,8 +184,8 @@ size_t signature_length_for_key_handle(const SessionBundle& sessions, const Obje class EC_Signature_Operation final : public Signature_Operation { public: - EC_Signature_Operation(const Object& object, const SessionBundle& sessions, std::string_view hash) : - Signature_Operation(object, sessions, make_signature_scheme(hash)) {} + EC_Signature_Operation(const Object& object, const SessionBundle& sessions, PK_Signature_Options& options) : + Signature_Operation(object, sessions, make_signature_scheme(options)) {} size_t signature_length() const override { return signature_length_for_key_handle(sessions(), key_handle()); } @@ -211,8 +212,8 @@ class EC_Signature_Operation final : public Signature_Operation { class EC_Verification_Operation final : public Verification_Operation { public: - EC_Verification_Operation(const Object& object, const SessionBundle& sessions, std::string_view hash) : - Verification_Operation(object, sessions, make_signature_scheme(hash)) {} + EC_Verification_Operation(const Object& object, const SessionBundle& sessions, PK_Signature_Options& options) : + Verification_Operation(object, sessions, make_signature_scheme(options)) {} private: TPMT_SIGNATURE unmarshal_signature(std::span sig_data) const override { @@ -239,17 +240,16 @@ class EC_Verification_Operation final : public Verification_Operation { } // namespace -std::unique_ptr EC_PublicKey::create_verification_op(std::string_view params, - std::string_view provider) const { - BOTAN_UNUSED(provider); - return std::make_unique(handles(), sessions(), params); +std::unique_ptr EC_PublicKey::_create_verification_op(PK_Signature_Options& options) const { + options.exclude_provider(); + return std::make_unique(handles(), sessions(), options); } -std::unique_ptr EC_PrivateKey::create_signature_op(Botan::RandomNumberGenerator& rng, - std::string_view params, - std::string_view provider) const { - BOTAN_UNUSED(rng, provider); - return std::make_unique(handles(), sessions(), params); +std::unique_ptr EC_PrivateKey::_create_signature_op(Botan::RandomNumberGenerator& rng, + PK_Signature_Options& options) const { + BOTAN_UNUSED(rng); + options.exclude_provider(); + return std::make_unique(handles(), sessions(), options); } } // namespace Botan::TPM2 diff --git a/src/lib/prov/tpm2/tpm2_ecc/tpm2_ecc.h b/src/lib/prov/tpm2/tpm2_ecc/tpm2_ecc.h index 6f9d166e080..03faf801741 100644 --- a/src/lib/prov/tpm2/tpm2_ecc/tpm2_ecc.h +++ b/src/lib/prov/tpm2/tpm2_ecc/tpm2_ecc.h @@ -37,8 +37,7 @@ class BOTAN_PUBLIC_API(3, 6) EC_PublicKey final : public virtual Botan::TPM2::Pu return op == PublicKeyOperation::Signature; } - std::unique_ptr create_verification_op(std::string_view params, - std::string_view provider) const override; + std::unique_ptr _create_verification_op(PK_Signature_Options& options) const override; protected: friend class TPM2::PublicKey; @@ -96,9 +95,8 @@ class BOTAN_PUBLIC_API(3, 6) EC_PrivateKey final : public virtual Botan::TPM2::P bool supports_operation(PublicKeyOperation op) const override { return op == PublicKeyOperation::Signature; } - std::unique_ptr create_signature_op(Botan::RandomNumberGenerator& rng, - std::string_view params, - std::string_view provider) const override; + std::unique_ptr _create_signature_op(Botan::RandomNumberGenerator& rng, + PK_Signature_Options& options) const override; protected: friend class TPM2::PrivateKey; diff --git a/src/lib/prov/tpm2/tpm2_pkops.cpp b/src/lib/prov/tpm2/tpm2_pkops.cpp index bf1b9c48f5c..ff76d1b3b48 100644 --- a/src/lib/prov/tpm2/tpm2_pkops.cpp +++ b/src/lib/prov/tpm2/tpm2_pkops.cpp @@ -8,6 +8,7 @@ #include +#include #include #include #include @@ -44,9 +45,14 @@ std::unique_ptr create_hash_function(const Object& key_hand Signature_Operation::Signature_Operation(const Object& object, const SessionBundle& sessions, - const SignatureAlgorithmSelection& algorithms) : + SignatureAlgorithmSelection algorithms) : Botan::TPM2::Signature_Operation_Base( - object, sessions, algorithms, create_hash_function(object, sessions, algorithms.hash_name)) {} + object, + sessions, + { + create_hash_function(object, sessions, algorithms.hash_name), + std::move(algorithms), + }) {} std::vector Signature_Operation::sign(Botan::RandomNumberGenerator& rng) { BOTAN_UNUSED(rng); @@ -96,9 +102,13 @@ std::vector Signature_Operation::sign(Botan::RandomNumberGenerator& rng Verification_Operation::Verification_Operation(const Object& object, const SessionBundle& sessions, - const SignatureAlgorithmSelection& algorithms) : - Signature_Operation_Base( - object, sessions, algorithms, Botan::HashFunction::create_or_throw(algorithms.hash_name)) {} + SignatureAlgorithmSelection algorithms) : + Signature_Operation_Base(object, + sessions, + { + Botan::HashFunction::create_or_throw(algorithms.hash_name), + std::move(algorithms), + }) {} bool Verification_Operation::is_valid_signature(std::span sig_data) { TPM2B_DIGEST digest; diff --git a/src/lib/prov/tpm2/tpm2_pkops.h b/src/lib/prov/tpm2/tpm2_pkops.h index 52ca9bb3619..8785732bbff 100644 --- a/src/lib/prov/tpm2/tpm2_pkops.h +++ b/src/lib/prov/tpm2/tpm2_pkops.h @@ -12,6 +12,7 @@ #include #include +#include #include namespace Botan::TPM2 { @@ -19,21 +20,21 @@ namespace Botan::TPM2 { struct SignatureAlgorithmSelection { TPMT_SIG_SCHEME signature_scheme; std::string hash_name; - std::optional padding; + std::unique_ptr emsa; }; template class Signature_Operation_Base : public PKOpT { public: - Signature_Operation_Base(const Object& object, - const SessionBundle& sessions, - const SignatureAlgorithmSelection& algorithms, - std::unique_ptr hash) : + Signature_Operation_Base( + const Object& object, + const SessionBundle& sessions, + std::pair, SignatureAlgorithmSelection> algorithms) : m_key_handle(object), m_sessions(sessions), - m_scheme(algorithms.signature_scheme), - m_hash(std::move(hash)), - m_padding(algorithms.padding) { + m_hash(std::move(algorithms.first)), + m_scheme(algorithms.second.signature_scheme), + m_emsa(std::move(algorithms.second.emsa)) { BOTAN_ASSERT_NONNULL(m_hash); } @@ -51,14 +52,22 @@ class Signature_Operation_Base : public PKOpT { const TPMT_SIG_SCHEME& scheme() const { return m_scheme; } - std::optional padding() const { return m_padding; } + EMSA* emsa() const { + BOTAN_STATE_CHECK(m_emsa); + return m_emsa.get(); + } private: const Object& m_key_handle; const SessionBundle& m_sessions; - TPMT_SIG_SCHEME m_scheme; std::unique_ptr m_hash; - std::optional m_padding; + TPMT_SIG_SCHEME m_scheme; + + // This EMSA object actually isn't required, we just need it to + // conveniently parse the EMSA the user selected. + // + // TODO: This is a hack, and we should clean this up. + std::unique_ptr m_emsa; }; /** @@ -73,9 +82,7 @@ class Signature_Operation_Base : public PKOpT { */ class Signature_Operation : public Signature_Operation_Base { public: - Signature_Operation(const Object& object, - const SessionBundle& sessions, - const SignatureAlgorithmSelection& algorithms); + Signature_Operation(const Object& object, const SessionBundle& sessions, SignatureAlgorithmSelection algorithms); std::vector sign(Botan::RandomNumberGenerator& rng) override; @@ -91,7 +98,7 @@ class Verification_Operation : public Signature_Operation_Base sig_data) override; diff --git a/src/lib/prov/tpm2/tpm2_rsa/tpm2_rsa.cpp b/src/lib/prov/tpm2/tpm2_rsa/tpm2_rsa.cpp index 3f8a406f39b..4887f0a2b80 100644 --- a/src/lib/prov/tpm2/tpm2_rsa/tpm2_rsa.cpp +++ b/src/lib/prov/tpm2/tpm2_rsa/tpm2_rsa.cpp @@ -125,21 +125,24 @@ std::unique_ptr RSA_PrivateKey::create_unrestricted_transient( namespace { -SignatureAlgorithmSelection select_signature_algorithms(std::string_view padding) { - const SCAN_Name req(padding); +SignatureAlgorithmSelection select_signature_algorithms(PK_Signature_Options& options) { + auto emsa = EMSA::create_or_throw(options); + const auto emsa_name = emsa->name(); + + const SCAN_Name req(emsa_name); if(req.arg_count() == 0) { throw Invalid_Argument("RSA signing padding scheme must at least specify a hash function"); } - auto sig_scheme = rsa_signature_scheme_botan_to_tss2(padding); + auto sig_scheme = rsa_signature_scheme_botan_to_tss2(emsa_name); if(!sig_scheme) { - throw Not_Implemented(Botan::fmt("RSA signing with padding scheme {}", padding)); + throw Not_Implemented(Botan::fmt("RSA signing with padding scheme {}", emsa_name)); } return { .signature_scheme = sig_scheme.value(), - .hash_name = req.arg(0), - .padding = std::string(padding), + .hash_name = emsa->hash_function(), + .emsa = std::move(emsa), }; } @@ -149,8 +152,8 @@ size_t signature_length_for_key_handle(const SessionBundle& sessions, const Obje class RSA_Signature_Operation final : public Signature_Operation { public: - RSA_Signature_Operation(const Object& object, const SessionBundle& sessions, std::string_view padding) : - Signature_Operation(object, sessions, select_signature_algorithms(padding)) {} + RSA_Signature_Operation(const Object& object, const SessionBundle& sessions, PK_Signature_Options& options) : + Signature_Operation(object, sessions, select_signature_algorithms(options)) {} size_t signature_length() const override { return signature_length_for_key_handle(sessions(), key_handle()); } @@ -158,14 +161,7 @@ class RSA_Signature_Operation final : public Signature_Operation { // TODO: This is essentially a copy of the ::algorithm_identifier() // in `rsa.h`. We should probably refactor this into a common // function. - - // This EMSA object actually isn't required, we just need it to - // conveniently figure out the algorithm identifier. - // - // TODO: This is a hack, and we should clean this up. - BOTAN_STATE_CHECK(padding().has_value()); - const auto emsa = EMSA::create_or_throw(padding().value()); - const std::string emsa_name = emsa->name(); + const std::string emsa_name = emsa()->name(); try { const std::string full_name = "RSA/" + emsa_name; @@ -199,8 +195,8 @@ class RSA_Signature_Operation final : public Signature_Operation { class RSA_Verification_Operation final : public Verification_Operation { public: - RSA_Verification_Operation(const Object& object, const SessionBundle& sessions, std::string_view padding) : - Verification_Operation(object, sessions, select_signature_algorithms(padding)) {} + RSA_Verification_Operation(const Object& object, const SessionBundle& sessions, PK_Signature_Options& options) : + Verification_Operation(object, sessions, select_signature_algorithms(options)) {} private: TPMT_SIGNATURE unmarshal_signature(std::span signature) const override { @@ -373,17 +369,16 @@ class RSA_Decryption_Operation final : public PK_Ops::Decryption { } // namespace -std::unique_ptr RSA_PublicKey::create_verification_op(std::string_view params, - std::string_view provider) const { - BOTAN_UNUSED(provider); - return std::make_unique(handles(), sessions(), params); +std::unique_ptr RSA_PublicKey::_create_verification_op(PK_Signature_Options& options) const { + options.exclude_provider(); + return std::make_unique(handles(), sessions(), options); } -std::unique_ptr RSA_PrivateKey::create_signature_op(Botan::RandomNumberGenerator& rng, - std::string_view params, - std::string_view provider) const { - BOTAN_UNUSED(rng, provider); - return std::make_unique(handles(), sessions(), params); +std::unique_ptr RSA_PrivateKey::_create_signature_op(Botan::RandomNumberGenerator& rng, + PK_Signature_Options& options) const { + BOTAN_UNUSED(rng); + options.exclude_provider(); + return std::make_unique(handles(), sessions(), options); } std::unique_ptr RSA_PublicKey::create_encryption_op(Botan::RandomNumberGenerator& rng, diff --git a/src/lib/prov/tpm2/tpm2_rsa/tpm2_rsa.h b/src/lib/prov/tpm2/tpm2_rsa/tpm2_rsa.h index 32e33fbf7ce..a4e4c9749c1 100644 --- a/src/lib/prov/tpm2/tpm2_rsa/tpm2_rsa.h +++ b/src/lib/prov/tpm2/tpm2_rsa/tpm2_rsa.h @@ -30,8 +30,7 @@ class BOTAN_PUBLIC_API(3, 6) RSA_PublicKey final : public virtual Botan::TPM2::P return op == PublicKeyOperation::Encryption || op == PublicKeyOperation::Signature; } - std::unique_ptr create_verification_op(std::string_view params, - std::string_view provider) const override; + std::unique_ptr _create_verification_op(PK_Signature_Options& options) const override; std::unique_ptr create_encryption_op(Botan::RandomNumberGenerator& rng, std::string_view params, @@ -86,9 +85,8 @@ class BOTAN_PUBLIC_API(3, 6) RSA_PrivateKey final : public virtual Botan::TPM2:: return op == PublicKeyOperation::Encryption || op == PublicKeyOperation::Signature; } - std::unique_ptr create_signature_op(Botan::RandomNumberGenerator& rng, - std::string_view params, - std::string_view provider) const override; + std::unique_ptr _create_signature_op(Botan::RandomNumberGenerator& rng, + PK_Signature_Options& options) const override; std::unique_ptr create_decryption_op(Botan::RandomNumberGenerator& rng, std::string_view params,