9#ifndef BOTAN_TPM2_UTIL_H_
10#define BOTAN_TPM2_UTIL_H_
12#include <botan/bigint.h>
13#include <botan/concepts.h>
14#include <botan/mem_ops.h>
15#include <botan/tpm2_context.h>
16#include <botan/tpm2_error.h>
17#include <botan/tpm2_object.h>
19#include <botan/internal/fmt.h>
25#include <tss2/tss2_esys.h>
26#include <tss2/tss2_rc.h>
35#if defined(TSS2_BASE_RC_CALLBACK_NULL)
37 #define BOTAN_TSS2_SUPPORTS_CRYPTO_CALLBACKS
40 #define BOTAN_TSS2_SUPPORTS_ERROR_DECODING
43#if defined(TPM2_RC_FW_LIMITED)
45 #define BOTAN_TSS2_SUPPORTS_SM4_IN_CRYPTO_CALLBACKS
56 if(rc != TSS2_RC_SUCCESS) {
57 throw Error(location, rc);
71template <
TSS2_RC... expected_errors>
72 requires(
sizeof...(expected_errors) > 0)
75 if(rc == TSS2_RC_SUCCESS) {
83 const bool is_expected_by_caller = ((decoded_rc == expected_errors) || ...);
84 if(is_expected_by_caller) {
98 { t.buffer } -> std::convertible_to<const uint8_t*>;
99 { t.size } -> std::convertible_to<size_t>;
104 return std::span{data.buffer, data.size};
111 data.size =
static_cast<decltype(data.size)
>(length);
117template <tpm2_buffer T>
118constexpr void copy_into(T& dest, std::span<const uint8_t> data) {
124template <tpm2_buffer T>
133template <concepts::resizable_
byte_buffer OutT>
136 result.resize(data.size);
142template <tpm2_buffer T>
146 result.size =
static_cast<decltype(result.size)
>(length);
152template <tpm2_buffer T>
186 m_object(object), m_persistent(persistent), m_handle(persistent ? 0 : ESYS_TR_NONE) {}
194 m_object.handles().persistent = m_handle;
196 m_object.handles().transient = m_handle;
205 [[nodiscard]]
constexpr operator uint32_t*() &&
noexcept {
return &m_handle; }
208 constexpr bool was_written()
const {
return m_handle != (m_persistent ? 0 : ESYS_TR_NONE); }
230template <
typename FieldPo
interT, std::
unsigned_
integral MaskT>
231 requires std::is_member_object_pointer_v<FieldPointerT>
237 [[nodiscard]]
constexpr bool&
operator()(
auto&
object)
const noexcept {
return object.*
field; }
240 [[nodiscard]]
constexpr bool operator()(
const auto&
object)
const noexcept {
return object.*
field; }
244template <
typename MaskT,
typename FieldPo
interT>
255template <std::unsigned_integral UnderlyingT,
256 typename AttributeWrapperT,
260 template <std::invocable<const PropMap<
bool AttributeWrapperT::*, UnderlyingT>&> FnT>
261 static constexpr void for_all(FnT&& fn) {
265 static consteval bool all_single_bit_bitmasks() {
267 for_all([&](
auto&& prop) { result = result && (std::popcount(prop.mask) == 1); });
271 static_assert(all_single_bit_bitmasks(),
"props... must contain single-bit flags only");
274 static constexpr UnderlyingT
render(AttributeWrapperT attributes) {
275 UnderlyingT result = 0;
276 for_all([&](
auto&& prop) {
277 if(prop(attributes)) {
284 static constexpr AttributeWrapperT
read(UnderlyingT attributes) {
285 AttributeWrapperT result;
286 for_all([&](
auto&& prop) { prop(result) = (attributes & prop.mask) != 0; });
291#if defined(BOTAN_HAS_RSA)
300inline std::pair<BigInt, BigInt> rsa_pubkey_components_from_tss2_public(
const TPM2B_PUBLIC* public_blob) {
302 const auto& pub = public_blob->publicArea;
303 BOTAN_ARG_CHECK(pub.type == TPM2_ALG_RSA,
"Public key is not an RSA key");
306 const auto exponent = (pub.parameters.rsaDetail.exponent == 0) ? 65537 : pub.parameters.rsaDetail.exponent;
#define BOTAN_ASSERT_NOMSG(expr)
#define BOTAN_ASSERT_NONNULL(ptr)
#define BOTAN_ARG_CHECK(expr, msg)
static constexpr AttributeWrapperT read(UnderlyingT attributes)
static constexpr UnderlyingT render(AttributeWrapperT attributes)
ObjectSetter(const ObjectSetter &)=delete
constexpr ObjectSetter(Object &object, bool persistent=false)
ObjectSetter & operator=(ObjectSetter &&)=delete
ObjectSetter(ObjectSetter &&)=delete
constexpr ~ObjectSetter() noexcept
ObjectSetter & operator=(const ObjectSetter &)=delete
PropMap(MaskT, FieldPointerT) -> PropMap< MaskT, FieldPointerT >
Deduction guide to simplify the creation of PropMap instances.
constexpr T init_empty()
Create an empty TPM2 buffer of the given type.
constexpr void check_rc(std::string_view location, TSS2_RC rc)
constexpr auto out_persistent_handle(Object &object)
std::unique_ptr< T, esys_liberator > unique_esys_ptr
A unique pointer type for ESYS handles that automatically frees the handle.
TSS2_RC get_raw_rc(TSS2_RC rc)
constexpr T init_with_size(size_t length)
Create a TPM2 buffer of a given type and length.
constexpr auto out_transient_handle(Object &object)
constexpr void copy_into(T &dest, std::span< const uint8_t > data)
constexpr auto as_span(tpm2_buffer auto &data)
Construct a std::span as a view into a TPM2 buffer.
constexpr TSS2_RC check_rc_expecting(std::string_view location, TSS2_RC rc)
constexpr void clear_bytes(void *ptr, size_t bytes)
constexpr void copy_mem(T *out, const T *in, size_t n)
std::optional< TPM2_HANDLE > persistent
constexpr bool operator()(const auto &object) const noexcept
Read-only access the boolean member 'field' from the given object.
constexpr bool & operator()(auto &object) const noexcept
Access the boolean member 'field' from the given object.
unique_esys_ptr< TPM2B_PUBLIC > pub
unique_esys_ptr< TPM2B_NAME > qualified_name
unique_esys_ptr< TPM2B_NAME > name
void operator()(void *handle)
uint32_t ESYS_TR
Forward declaration of TSS2 type for convenience.
uint32_t TSS2_RC
Forward declaration of TSS2 type for convenience.