Botan 3.7.1
Crypto and TLS for C&
tpm2_hash.cpp
Go to the documentation of this file.
1/*
2* TPM 2.0 Hash Function Wrappers
3* (C) 2024 Jack Lloyd
4* (C) 2024 René Meusel, Amos Treiber - Rohde & Schwarz Cybersecurity GmbH, financed by LANCOM Systems GmbH
5*
6* Botan is released under the Simplified BSD License (see license.txt)
7*/
8
9#include <botan/internal/tpm2_hash.h>
10
11#include <botan/internal/fmt.h>
12#include <botan/internal/stl_util.h>
13#include <botan/internal/tpm2_algo_mappings.h>
14
15#include <tss2/tss2_esys.h>
16
17namespace Botan::TPM2 {
18
19HashFunction::HashFunction(std::shared_ptr<Context> ctx,
20 std::string_view algorithm,
21 TPMI_RH_HIERARCHY hierarchy,
22 SessionBundle sessions) :
23 m_hash_type(get_tpm2_hash_type(algorithm)),
24 m_hierarchy(hierarchy),
25 m_handle(std::move(ctx)),
26 m_sessions(std::move(sessions)) {
27 // When creating a new hash object we assume that the call will use it to
28 // hash data and therefore setup the hash object immediately.
29 lazy_setup();
30}
31
32std::string HashFunction::name() const {
33 return get_botan_hash_name(m_hash_type);
34}
35
37 switch(m_hash_type) {
38 case TPM2_ALG_SHA1:
39 return 20;
40 case TPM2_ALG_SHA256:
41 case TPM2_ALG_SHA3_256:
42 case TPM2_ALG_SM3_256:
43 return 32;
44 case TPM2_ALG_SHA384:
45 case TPM2_ALG_SHA3_384:
46 return 48;
47 case TPM2_ALG_SHA512:
48 case TPM2_ALG_SHA3_512:
49 return 64;
50 default:
51 throw Invalid_State("TPM 2.0 hash object with unexpected hash type");
52 }
53}
54
56 m_handle._reset();
57}
58
59std::unique_ptr<Botan::HashFunction> HashFunction::copy_state() const {
60 throw Not_Implemented("TPM 2.0 hash functions do not support copy_state");
61}
62
63std::unique_ptr<Botan::HashFunction> HashFunction::new_object() const {
64 return std::make_unique<HashFunction>(m_handle.context(), name(), m_hierarchy, m_sessions);
65}
66
67void HashFunction::lazy_setup() {
68 if(m_handle.has_transient_handle()) {
69 return;
70 }
71
72 const auto auth = init_empty<TPM2B_AUTH>();
73 const auto rc = check_rc_expecting<TPM2_RC_HASH>("Esys_HashSequenceStart",
74 Esys_HashSequenceStart(*m_handle.context(),
75 m_sessions[0],
76 m_sessions[1],
77 m_sessions[2],
78 &auth,
79 m_hash_type,
80 out_transient_handle(m_handle)));
81
82 if(rc == TPM2_RC_HASH) {
83 throw Lookup_Error(fmt("TPM 2.0 Hash {} is not supported", name()));
84 }
85}
86
87void HashFunction::add_data(std::span<const uint8_t> input) {
88 lazy_setup();
89
90 BufferSlicer slicer(input);
91 while(slicer.remaining() > 0) {
92 const size_t chunk = std::min(slicer.remaining(), size_t(TPM2_MAX_DIGEST_BUFFER));
93 const auto data = copy_into<TPM2B_MAX_BUFFER>(slicer.take(chunk));
95 "Esys_SequenceUpdate",
96 Esys_SequenceUpdate(
97 *m_handle.context(), m_handle.transient_handle(), m_sessions[0], m_sessions[1], m_sessions[2], &data));
98 }
99 BOTAN_ASSERT_NOMSG(slicer.empty());
100}
101
102std::pair<unique_esys_ptr<TPM2B_DIGEST>, unique_esys_ptr<TPMT_TK_HASHCHECK>> HashFunction::final_with_ticket() {
104
105 std::pair<unique_esys_ptr<TPM2B_DIGEST>, unique_esys_ptr<TPMT_TK_HASHCHECK>> result;
106
107 const auto nodata = init_empty<TPM2B_MAX_BUFFER>();
108 check_rc("Esys_SequenceComplete",
109 Esys_SequenceComplete(*m_handle.context(),
110 m_handle.transient_handle(),
111 m_sessions[0],
112 m_sessions[1],
113 m_sessions[2],
114 &nodata,
115 m_hierarchy,
116 out_ptr(result.first),
117 out_ptr(result.second)));
118 BOTAN_ASSERT_NONNULL(result.first);
119
120 // Esys_SequenceComplete() destroys the underlying transient object
121 // so we need to disengage it's RAII wrapper.
122 m_handle._disengage();
123
124 return result;
125}
126
127void HashFunction::final_result(std::span<uint8_t> output) {
128 const auto digest_and_ticket = final_with_ticket();
129 BOTAN_ASSERT_NONNULL(digest_and_ticket.first);
130 BOTAN_ASSERT_NOMSG(digest_and_ticket.first->size <= output.size());
131 BOTAN_DEBUG_ASSERT(digest_and_ticket.first->size == output_length());
132
133 copy_mem(output.first(output.size()), as_span(*digest_and_ticket.first));
134}
135
136} // namespace Botan::TPM2
#define BOTAN_ASSERT_NOMSG(expr)
Definition assert.h:59
#define BOTAN_DEBUG_ASSERT(expr)
Definition assert.h:98
#define BOTAN_STATE_CHECK(expr)
Definition assert.h:41
#define BOTAN_ASSERT_NONNULL(ptr)
Definition assert.h:86
void clear() override
Definition tpm2_hash.cpp:55
size_t output_length() const override
Definition tpm2_hash.cpp:36
std::string name() const override
Definition tpm2_hash.cpp:32
HashFunction(std::shared_ptr< Context > ctx, std::string_view algorithm, TPMI_RH_HIERARCHY hierarchy=ESYS_TR_RH_NULL, SessionBundle sessions={})
Definition tpm2_hash.cpp:19
std::unique_ptr< Botan::HashFunction > new_object() const override
Definition tpm2_hash.cpp:63
std::unique_ptr< Botan::HashFunction > copy_state() const override
Definition tpm2_hash.cpp:59
std::pair< unique_esys_ptr< TPM2B_DIGEST >, unique_esys_ptr< TPMT_TK_HASHCHECK > > final_with_ticket()
bool has_transient_handle() const
void _reset() noexcept
Flush the object's TPM handles and reset its internal state.
const std::shared_ptr< Context > & context() const
ESYS_TR transient_handle() const noexcept
void _disengage() noexcept
Reset the object's internal state without flushing its TPM handles.
constexpr T init_empty()
Create an empty TPM2 buffer of the given type.
Definition tpm2_util.h:152
constexpr void check_rc(std::string_view location, TSS2_RC rc)
Definition tpm2_util.h:54
std::unique_ptr< T, esys_liberator > unique_esys_ptr
A unique pointer type for ESYS handles that automatically frees the handle.
Definition tpm2_util.h:162
TPMI_ALG_HASH get_tpm2_hash_type(std::string_view hash_name)
constexpr auto out_transient_handle(Object &object)
Definition tpm2_util.h:217
constexpr void copy_into(T &dest, std::span< const uint8_t > data)
Definition tpm2_util.h:117
constexpr auto as_span(tpm2_buffer auto &data)
Construct a std::span as a view into a TPM2 buffer.
Definition tpm2_util.h:102
std::string get_botan_hash_name(TPM2_ALG_ID hash_id)
constexpr TSS2_RC check_rc_expecting(std::string_view location, TSS2_RC rc)
Definition tpm2_util.h:72
constexpr auto out_ptr(T &outptr) noexcept
Definition stl_util.h:420
std::string fmt(std::string_view format, const T &... args)
Definition fmt.h:53
constexpr void copy_mem(T *out, const T *in, size_t n)
Definition mem_ops.h:147