Skip to content

Commit

Permalink
Enhance Side Channel resistance of TPM2 RSA Decryption Wrapper
Browse files Browse the repository at this point in the history
Unfortunately, the ESAPI call already introduces some
side channel leaks by allocating the result buffer only
if the decryption succeeds.

Co-Authored-By: René Meusel <[email protected]>
  • Loading branch information
atreiber94 and reneme committed Nov 7, 2024
1 parent 679ca89 commit 1d082c7
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 10 deletions.
26 changes: 19 additions & 7 deletions src/lib/prov/tpm2/tpm2_rsa/tpm2_rsa.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -340,13 +340,25 @@ class RSA_Decryption_Operation final : public PK_Ops::Decryption {
&label,
out_ptr(plaintext)));

valid_mask = CT::Mask<uint8_t>::is_equal(rc, TPM2_RC_SUCCESS).value();
if(rc == TPM2_RC_SUCCESS) {
BOTAN_ASSERT_NONNULL(plaintext);
return copy_into<secure_vector<uint8_t>>(*plaintext);
} else {
return {};
}
const auto success = CT::Mask<decltype(rc)>::is_equal(rc, TPM2_RC_SUCCESS).as_choice();
valid_mask = CT::Mask<uint8_t>::from_choice(success).value();

// A "typical" payload size for RSA encryption, assuming that we usually
// encrypt some symmetric key of a hybrid encryption scheme.
constexpr size_t default_plaintext_length = 32;

// When Esys_RSA_Decrypt fails to decrypt the ciphertext (e.g. because
// of a PKCS#1.5 padding failure), the `plaintext` pointer will be nullptr.
// This behaviour in itself is likely exposing a timing side channel already.
// Nevertheless, we do our best to mitigate any oracles by always copying a
// dummy plaintext value in this case.
auto dummy_plaintext = init_with_size<TPM2B_PUBLIC_KEY_RSA>(default_plaintext_length);
auto* out = &dummy_plaintext;
auto* maybe_plaintext = plaintext.get();
CT::conditional_swap_ptr(success.as_bool(), out, maybe_plaintext);

BOTAN_ASSERT_NONNULL(out);
return copy_into<secure_vector<uint8_t>>(*out);
}

size_t plaintext_length(size_t /* ciphertext_length */) const override {
Expand Down
14 changes: 11 additions & 3 deletions src/lib/prov/tpm2/tpm2_util.h
Original file line number Diff line number Diff line change
Expand Up @@ -137,14 +137,22 @@ constexpr OutT copy_into(const tpm2_buffer auto& data) {
return result;
}

/// Create an empty TPM2 buffer of the given type.
/// Create a TPM2 buffer of a given type and @p length.
template <tpm2_buffer T>
constexpr T init_empty() {
constexpr T init_with_size(size_t length) {
T result;
result.size = 0;
BOTAN_ASSERT_NOMSG(length <= sizeof(result.buffer));
result.size = length;
clear_bytes(result.buffer, length);
return result;
}

/// Create an empty TPM2 buffer of the given type.
template <tpm2_buffer T>
constexpr T init_empty() {
return init_with_size<T>(0);
}

struct esys_liberator {
void operator()(void* handle) { Esys_Free(handle); }
};
Expand Down

0 comments on commit 1d082c7

Please sign in to comment.