Botan 3.11.0
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/buffer_slicer.h>
12#include <botan/internal/fmt.h>
13#include <botan/internal/stl_util.h>
14#include <botan/internal/tpm2_algo_mappings.h>
15
16#include <tss2/tss2_esys.h>
17
18namespace Botan::TPM2 {
19
20HashFunction::HashFunction(std::shared_ptr<Context> ctx,
21 std::string_view algorithm,
22 TPMI_RH_HIERARCHY hierarchy,
23 SessionBundle sessions) :
24 m_hash_type(get_tpm2_hash_type(algorithm)),
25 m_hierarchy(hierarchy),
26 m_handle(std::move(ctx)),
27 m_sessions(std::move(sessions)) {
28 // When creating a new hash object we assume that the call will use it to
29 // hash data and therefore setup the hash object immediately.
30 lazy_setup();
31}
32
33std::string HashFunction::name() const {
34 return get_botan_hash_name(m_hash_type);
35}
36
38 switch(m_hash_type) {
39 case TPM2_ALG_SHA1:
40 return 20;
41 case TPM2_ALG_SHA256:
42 case TPM2_ALG_SHA3_256:
43 case TPM2_ALG_SM3_256:
44 return 32;
45 case TPM2_ALG_SHA384:
46 case TPM2_ALG_SHA3_384:
47 return 48;
48 case TPM2_ALG_SHA512:
49 case TPM2_ALG_SHA3_512:
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()->esys_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));
95 check_rc("Esys_SequenceUpdate",
96 Esys_SequenceUpdate(m_handle.context()->esys_context(),
97 m_handle.transient_handle(),
98 m_sessions[0],
99 m_sessions[1],
100 m_sessions[2],
101 &data));
102 }
103 BOTAN_ASSERT_NOMSG(slicer.empty());
104}
105
106std::pair<unique_esys_ptr<TPM2B_DIGEST>, unique_esys_ptr<TPMT_TK_HASHCHECK>> HashFunction::final_with_ticket() {
107 BOTAN_STATE_CHECK(m_handle.has_transient_handle());
108
109 std::pair<unique_esys_ptr<TPM2B_DIGEST>, unique_esys_ptr<TPMT_TK_HASHCHECK>> result;
110
111 const auto nodata = init_empty<TPM2B_MAX_BUFFER>();
112 check_rc("Esys_SequenceComplete",
113 Esys_SequenceComplete(m_handle.context()->esys_context(),
114 m_handle.transient_handle(),
115 m_sessions[0],
116 m_sessions[1],
117 m_sessions[2],
118 &nodata,
119 m_hierarchy,
120 out_ptr(result.first),
121 out_ptr(result.second)));
122 BOTAN_ASSERT_NONNULL(result.first);
123
124 // Esys_SequenceComplete() destroys the underlying transient object
125 // so we need to disengage it's RAII wrapper.
126 m_handle._disengage();
127
128 return result;
129}
130
131void HashFunction::final_result(std::span<uint8_t> output) {
132 const auto digest_and_ticket = final_with_ticket();
133 BOTAN_ASSERT_NONNULL(digest_and_ticket.first);
134 BOTAN_ASSERT_NOMSG(digest_and_ticket.first->size <= output.size());
135 BOTAN_DEBUG_ASSERT(digest_and_ticket.first->size == output_length());
136
137 copy_mem(output.first(output.size()), as_span(*digest_and_ticket.first));
138}
139
140} // namespace Botan::TPM2
#define BOTAN_ASSERT_NOMSG(expr)
Definition assert.h:75
#define BOTAN_DEBUG_ASSERT(expr)
Definition assert.h:129
#define BOTAN_STATE_CHECK(expr)
Definition assert.h:49
#define BOTAN_ASSERT_NONNULL(ptr)
Definition assert.h:114
void clear() override
Definition tpm2_hash.cpp:56
size_t output_length() const override
Definition tpm2_hash.cpp:37
std::string name() const override
Definition tpm2_hash.cpp:33
HashFunction(std::shared_ptr< Context > ctx, std::string_view algorithm, TPMI_RH_HIERARCHY hierarchy=ESYS_TR_RH_NULL, SessionBundle sessions={})
Definition tpm2_hash.cpp:20
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
const std::shared_ptr< Context > & context() const
constexpr T init_empty()
Create an empty TPM2 buffer of the given type.
Definition tpm2_util.h:153
constexpr void check_rc(std::string_view location, TSS2_RC rc)
Definition tpm2_util.h:55
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:163
TPMI_ALG_HASH get_tpm2_hash_type(std::string_view hash_name)
constexpr auto out_transient_handle(Object &object)
Definition tpm2_util.h:219
constexpr void copy_into(T &dest, std::span< const uint8_t > data)
Definition tpm2_util.h:118
constexpr auto as_span(tpm2_buffer auto &data)
Construct a std::span as a view into a TPM2 buffer.
Definition tpm2_util.h:103
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:73
constexpr void copy_mem(T *out, const T *in, size_t n)
Definition mem_ops.h:144
constexpr auto out_ptr(T &outptr) noexcept
Definition stl_util.h:127
std::string fmt(std::string_view format, const T &... args)
Definition fmt.h:53