1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
|
/*
* TPM 1.2 interface
* (C) 2015 Jack Lloyd
*
* Botan is released under the Simplified BSD License (see license.txt)
*/
#ifndef BOTAN_TPM_H_
#define BOTAN_TPM_H_
#include <botan/exceptn.h>
#include <botan/pk_keys.h>
#include <botan/bigint.h>
#include <botan/rng.h>
#include <botan/uuid.h>
#include <functional>
//TODO remove this
#include <tss/tspi.h>
namespace Botan {
class BOTAN_PUBLIC_API(2,0) TPM_Error final : public Exception
{
public:
TPM_Error(const std::string& err) : Exception(err) {}
ErrorType error_type() const noexcept override { return ErrorType::TPMError; }
};
/**
* Creates a connection to the TPM. All other TPM types take and hold
* a TPM_Context reference, so all other objects must be deallocated
* before ~TPM_Context runs.
*
* Use nullptr for the srk_password to indicate the well known secret
* (ie, an unencrypted SRK). This is usually what you want.
*
* TODO: handling owner password?
*/
class BOTAN_PUBLIC_API(2,0) TPM_Context final
{
public:
/**
* User callback for getting the PIN. Will be passed the best available
* description of what we are attempting to load.
*/
typedef std::function<std::string (std::string)> pin_cb;
TPM_Context(pin_cb cb, const char* srk_password);
~TPM_Context();
// Get data from the TPM's RNG, whatever that is
void gen_random(uint8_t out[], size_t out_len);
// Uses Tspi_TPM_StirRandom to add data to TPM's internal pool
void stir_random(const uint8_t in[], size_t in_len);
std::string get_user_pin(const std::string& who)
{
return m_pin_cb(who);
}
uint32_t current_counter();
TSS_HCONTEXT handle() const { return m_ctx; }
TSS_HKEY srk() const { return m_srk; }
private:
std::function<std::string (std::string)> m_pin_cb;
TSS_HCONTEXT m_ctx;
TSS_HKEY m_srk;
TSS_HTPM m_tpm;
};
class BOTAN_PUBLIC_API(2,0) TPM_RNG final : public Hardware_RNG
{
public:
TPM_RNG(TPM_Context& ctx) : m_ctx(ctx) {}
bool accepts_input() const override { return true; }
void add_entropy(const uint8_t in[], size_t in_len) override
{
m_ctx.stir_random(in, in_len);
}
void randomize(uint8_t out[], size_t out_len) override
{
m_ctx.gen_random(out, out_len);
}
std::string name() const override { return "TPM_RNG"; }
bool is_seeded() const override { return true; }
private:
TPM_Context& m_ctx;
};
enum class TPM_Storage_Type { User, System };
/*
* Also implements the public interface, but does not have usable
* TODO: derive from RSA_PublicKey???
*/
class BOTAN_PUBLIC_API(2,0) TPM_PrivateKey final : public Private_Key
{
public:
// TODO: key import?
/*
* Create a new key on the TPM parented to the SRK
* @param bits must be 1024 or 2048
*/
TPM_PrivateKey(TPM_Context& ctx, size_t bits, const char* key_password);
// reference an existing TPM key using URL syntax from GnuTLS
// "tpmkey:uuid=79f07ca9-73ac-478a-9093-11ca6702e774;storage=user"
//TPM_PrivateKey(TPM_Context& ctx, const std::string& tpm_url);
TPM_PrivateKey(TPM_Context& ctx,
const std::string& uuid,
TPM_Storage_Type storage_type);
TPM_PrivateKey(TPM_Context& ctx,
const std::vector<uint8_t>& blob);
/**
* If the key is not currently registered under a known UUID,
* generates a new random UUID and registers the key.
* Returns the access URL.
*/
std::string register_key(TPM_Storage_Type storage_type);
/**
* Returns a copy of the public key
*/
std::unique_ptr<Public_Key> public_key() const;
std::vector<uint8_t> export_blob() const;
TPM_Context& ctx() const { return m_ctx; }
TSS_HKEY handle() const { return m_key; }
/*
* Returns the list of all keys (in URL format) registered with the system
*/
static std::vector<std::string> registered_keys(TPM_Context& ctx);
size_t estimated_strength() const override;
size_t key_length() const override;
AlgorithmIdentifier algorithm_identifier() const override;
std::vector<uint8_t> public_key_bits() const override;
secure_vector<uint8_t> private_key_bits() const override;
bool check_key(RandomNumberGenerator& rng, bool) const override;
BigInt get_n() const;
BigInt get_e() const;
std::string algo_name() const override { return "RSA"; } // ???
std::unique_ptr<PK_Ops::Signature>
create_signature_op(RandomNumberGenerator& rng,
const std::string& params,
const std::string& provider) const override;
private:
TPM_Context& m_ctx;
TSS_HKEY m_key;
// Only set for registered keys
UUID m_uuid;
TPM_Storage_Type m_storage;
// Lazily computed in get_n, get_e
mutable BigInt m_n, m_e;
};
// TODO: NVRAM interface
// TODO: PCR measurement, writing, key locking
}
#endif
|