Botan 3.6.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 return 64;
51 default:
52 throw Invalid_State("TPM 2.0 hash object with unexpected hash type");
53 }
54}
55
57 m_handle._reset();
58}
59
60std::unique_ptr<Botan::HashFunction> HashFunction::copy_state() const {
61 throw Not_Implemented("TPM 2.0 hash functions do not support copy_state");
62}
63
64std::unique_ptr<Botan::HashFunction> HashFunction::new_object() const {
65 return std::make_unique<HashFunction>(m_handle.context(), name(), m_hierarchy, m_sessions);
66}
67
68void HashFunction::lazy_setup() {
69 if(m_handle.has_transient_handle()) {
70 return;
71 }
72
73 const auto auth = init_empty<TPM2B_AUTH>();
74 const auto rc = check_rc_expecting<TPM2_RC_HASH>("Esys_HashSequenceStart",
75 Esys_HashSequenceStart(*m_handle.context(),
76 m_sessions[0],
77 m_sessions[1],
78 m_sessions[2],
79 &auth,
80 m_hash_type,
81 out_transient_handle(m_handle)));
82
83 if(rc == TPM2_RC_HASH) {
84 throw Lookup_Error(fmt("TPM 2.0 Hash {} is not supported", name()));
85 }
86}
87
88void HashFunction::add_data(std::span<const uint8_t> input) {
89 lazy_setup();
90
91 BufferSlicer slicer(input);
92 while(slicer.remaining() > 0) {
93 const size_t chunk = std::min(slicer.remaining(), size_t(TPM2_MAX_DIGEST_BUFFER));
94 const auto data = copy_into<TPM2B_MAX_BUFFER>(slicer.take(chunk));
96 "Esys_SequenceUpdate",
97 Esys_SequenceUpdate(
98 *m_handle.context(), m_handle.transient_handle(), m_sessions[0], m_sessions[1], m_sessions[2], &data));
99 }
100 BOTAN_ASSERT_NOMSG(slicer.empty());
101}
102
103std::pair<unique_esys_ptr<TPM2B_DIGEST>, unique_esys_ptr<TPMT_TK_HASHCHECK>> HashFunction::final_with_ticket() {
105
106 std::pair<unique_esys_ptr<TPM2B_DIGEST>, unique_esys_ptr<TPMT_TK_HASHCHECK>> result;
107
108 const auto nodata = init_empty<TPM2B_MAX_BUFFER>();
109 check_rc("Esys_SequenceComplete",
110 Esys_SequenceComplete(*m_handle.context(),
111 m_handle.transient_handle(),
112 m_sessions[0],
113 m_sessions[1],
114 m_sessions[2],
115 &nodata,
116 m_hierarchy,
117 out_ptr(result.first),
118 out_ptr(result.second)));
119 BOTAN_ASSERT_NONNULL(result.first);
120
121 // Esys_SequenceComplete() destroys the underlying transient object
122 // so we need to disengage it's RAII wrapper.
123 m_handle._disengage();
124
125 return result;
126}
127
128void HashFunction::final_result(std::span<uint8_t> output) {
129 const auto digest_and_ticket = final_with_ticket();
130 BOTAN_ASSERT_NONNULL(digest_and_ticket.first);
131 BOTAN_ASSERT_NOMSG(digest_and_ticket.first->size <= output.size());
132 BOTAN_DEBUG_ASSERT(digest_and_ticket.first->size == output_length());
133
134 copy_mem(output.first(output.size()), as_span(*digest_and_ticket.first));
135}
136
137} // 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:56
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:64
std::unique_ptr< Botan::HashFunction > copy_state() const override
Definition tpm2_hash.cpp:60
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:142
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:154
TPMI_ALG_HASH get_tpm2_hash_type(std::string_view hash_name)
constexpr auto out_transient_handle(Object &object)
Definition tpm2_util.h:209
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:146