Skip to content

Commit

Permalink
TPM2 wrapper uses PK_Options
Browse files Browse the repository at this point in the history
  • Loading branch information
reneme committed Jan 16, 2025
1 parent 2b206c3 commit de6d3aa
Show file tree
Hide file tree
Showing 7 changed files with 86 additions and 76 deletions.
8 changes: 5 additions & 3 deletions src/lib/prov/tpm2/tpm2_algo_mappings.h
Original file line number Diff line number Diff line change
Expand Up @@ -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{
Expand Down
32 changes: 16 additions & 16 deletions src/lib/prov/tpm2/tpm2_ecc/tpm2_ecc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -159,15 +159,16 @@ std::unique_ptr<TPM2::PrivateKey> 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
};
}

Expand All @@ -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()); }

Expand All @@ -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<const uint8_t> sig_data) const override {
Expand All @@ -239,17 +240,16 @@ class EC_Verification_Operation final : public Verification_Operation {

} // namespace

std::unique_ptr<PK_Ops::Verification> EC_PublicKey::create_verification_op(std::string_view params,
std::string_view provider) const {
BOTAN_UNUSED(provider);
return std::make_unique<EC_Verification_Operation>(handles(), sessions(), params);
std::unique_ptr<PK_Ops::Verification> EC_PublicKey::_create_verification_op(PK_Signature_Options& options) const {
options.exclude_provider();
return std::make_unique<EC_Verification_Operation>(handles(), sessions(), options);
}

std::unique_ptr<PK_Ops::Signature> 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<EC_Signature_Operation>(handles(), sessions(), params);
std::unique_ptr<PK_Ops::Signature> EC_PrivateKey::_create_signature_op(Botan::RandomNumberGenerator& rng,
PK_Signature_Options& options) const {
BOTAN_UNUSED(rng);
options.exclude_provider();
return std::make_unique<EC_Signature_Operation>(handles(), sessions(), options);
}

} // namespace Botan::TPM2
8 changes: 3 additions & 5 deletions src/lib/prov/tpm2/tpm2_ecc/tpm2_ecc.h
Original file line number Diff line number Diff line change
Expand Up @@ -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<PK_Ops::Verification> create_verification_op(std::string_view params,
std::string_view provider) const override;
std::unique_ptr<PK_Ops::Verification> _create_verification_op(PK_Signature_Options& options) const override;

protected:
friend class TPM2::PublicKey;
Expand Down Expand Up @@ -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<PK_Ops::Signature> create_signature_op(Botan::RandomNumberGenerator& rng,
std::string_view params,
std::string_view provider) const override;
std::unique_ptr<PK_Ops::Signature> _create_signature_op(Botan::RandomNumberGenerator& rng,
PK_Signature_Options& options) const override;

protected:
friend class TPM2::PrivateKey;
Expand Down
20 changes: 15 additions & 5 deletions src/lib/prov/tpm2/tpm2_pkops.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

#include <botan/internal/tpm2_pkops.h>

#include <botan/internal/emsa.h>
#include <botan/internal/stl_util.h>
#include <botan/internal/tpm2_algo_mappings.h>
#include <botan/internal/tpm2_hash.h>
Expand Down Expand Up @@ -44,9 +45,14 @@ std::unique_ptr<Botan::HashFunction> 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<PK_Ops::Signature>(
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<uint8_t> Signature_Operation::sign(Botan::RandomNumberGenerator& rng) {
BOTAN_UNUSED(rng);
Expand Down Expand Up @@ -96,9 +102,13 @@ std::vector<uint8_t> Signature_Operation::sign(Botan::RandomNumberGenerator& rng

Verification_Operation::Verification_Operation(const Object& object,
const SessionBundle& sessions,
const SignatureAlgorithmSelection& algorithms) :
Signature_Operation_Base<PK_Ops::Verification>(
object, sessions, algorithms, Botan::HashFunction::create_or_throw(algorithms.hash_name)) {}
SignatureAlgorithmSelection algorithms) :
Signature_Operation_Base<PK_Ops::Verification>(object,
sessions,
{
Botan::HashFunction::create_or_throw(algorithms.hash_name),
std::move(algorithms),
}) {}

bool Verification_Operation::is_valid_signature(std::span<const uint8_t> sig_data) {
TPM2B_DIGEST digest;
Expand Down
37 changes: 22 additions & 15 deletions src/lib/prov/tpm2/tpm2_pkops.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,28 +12,29 @@
#include <botan/pk_ops.h>

#include <botan/hash.h>
#include <botan/internal/emsa.h>
#include <botan/internal/tpm2_util.h>

namespace Botan::TPM2 {

struct SignatureAlgorithmSelection {
TPMT_SIG_SCHEME signature_scheme;
std::string hash_name;
std::optional<std::string> padding;
std::unique_ptr<EMSA> emsa;
};

template <typename PKOpT>
class Signature_Operation_Base : public PKOpT {
public:
Signature_Operation_Base(const Object& object,
const SessionBundle& sessions,
const SignatureAlgorithmSelection& algorithms,
std::unique_ptr<Botan::HashFunction> hash) :
Signature_Operation_Base(
const Object& object,
const SessionBundle& sessions,
std::pair<std::unique_ptr<Botan::HashFunction>, 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);
}

Expand All @@ -51,14 +52,22 @@ class Signature_Operation_Base : public PKOpT {

const TPMT_SIG_SCHEME& scheme() const { return m_scheme; }

std::optional<std::string> 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<Botan::HashFunction> m_hash;
std::optional<std::string> 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<EMSA> m_emsa;
};

/**
Expand All @@ -73,9 +82,7 @@ class Signature_Operation_Base : public PKOpT {
*/
class Signature_Operation : public Signature_Operation_Base<PK_Ops::Signature> {
public:
Signature_Operation(const Object& object,
const SessionBundle& sessions,
const SignatureAlgorithmSelection& algorithms);
Signature_Operation(const Object& object, const SessionBundle& sessions, SignatureAlgorithmSelection algorithms);

std::vector<uint8_t> sign(Botan::RandomNumberGenerator& rng) override;

Expand All @@ -91,7 +98,7 @@ class Verification_Operation : public Signature_Operation_Base<PK_Ops::Verificat
public:
Verification_Operation(const Object& object,
const SessionBundle& sessions,
const SignatureAlgorithmSelection& algorithms);
SignatureAlgorithmSelection algorithms);

bool is_valid_signature(std::span<const uint8_t> sig_data) override;

Expand Down
49 changes: 22 additions & 27 deletions src/lib/prov/tpm2/tpm2_rsa/tpm2_rsa.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -125,21 +125,24 @@ std::unique_ptr<TPM2::PrivateKey> 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),
};
}

Expand All @@ -149,23 +152,16 @@ 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()); }

AlgorithmIdentifier algorithm_identifier() const override {
// 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;
Expand Down Expand Up @@ -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<const uint8_t> signature) const override {
Expand Down Expand Up @@ -373,17 +369,16 @@ class RSA_Decryption_Operation final : public PK_Ops::Decryption {

} // namespace

std::unique_ptr<PK_Ops::Verification> RSA_PublicKey::create_verification_op(std::string_view params,
std::string_view provider) const {
BOTAN_UNUSED(provider);
return std::make_unique<RSA_Verification_Operation>(handles(), sessions(), params);
std::unique_ptr<PK_Ops::Verification> RSA_PublicKey::_create_verification_op(PK_Signature_Options& options) const {
options.exclude_provider();
return std::make_unique<RSA_Verification_Operation>(handles(), sessions(), options);
}

std::unique_ptr<PK_Ops::Signature> 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<RSA_Signature_Operation>(handles(), sessions(), params);
std::unique_ptr<PK_Ops::Signature> RSA_PrivateKey::_create_signature_op(Botan::RandomNumberGenerator& rng,
PK_Signature_Options& options) const {
BOTAN_UNUSED(rng);
options.exclude_provider();
return std::make_unique<RSA_Signature_Operation>(handles(), sessions(), options);
}

std::unique_ptr<PK_Ops::Encryption> RSA_PublicKey::create_encryption_op(Botan::RandomNumberGenerator& rng,
Expand Down
8 changes: 3 additions & 5 deletions src/lib/prov/tpm2/tpm2_rsa/tpm2_rsa.h
Original file line number Diff line number Diff line change
Expand Up @@ -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<PK_Ops::Verification> create_verification_op(std::string_view params,
std::string_view provider) const override;
std::unique_ptr<PK_Ops::Verification> _create_verification_op(PK_Signature_Options& options) const override;

std::unique_ptr<PK_Ops::Encryption> create_encryption_op(Botan::RandomNumberGenerator& rng,
std::string_view params,
Expand Down Expand Up @@ -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<PK_Ops::Signature> create_signature_op(Botan::RandomNumberGenerator& rng,
std::string_view params,
std::string_view provider) const override;
std::unique_ptr<PK_Ops::Signature> _create_signature_op(Botan::RandomNumberGenerator& rng,
PK_Signature_Options& options) const override;

std::unique_ptr<PK_Ops::Decryption> create_decryption_op(Botan::RandomNumberGenerator& rng,
std::string_view params,
Expand Down

0 comments on commit de6d3aa

Please sign in to comment.