10 #include <botan/hash.h>
11 #include <botan/hash_id.h>
12 #include <botan/der_enc.h>
13 #include <botan/workfactor.h>
14 #include <botan/pk_ops.h>
17 #include <tss/platform.h>
19 #include <trousers/trousers.h>
27 void tss_error(TSS_RESULT res,
const char* expr,
const char* file,
int line)
29 std::ostringstream err;
30 err <<
"TPM error " << Trspi_Error_String(res)
31 <<
" layer " << Trspi_Error_Layer(res)
32 <<
" in " << expr <<
" at " << file <<
":" << line;
34 throw TPM_Error(err.str());
37 TSS_FLAG bit_flag(
size_t bits)
43 return TSS_KEY_SIZE_1024;
45 return TSS_KEY_SIZE_2048;
49 return TSS_KEY_SIZE_4096;
51 return TSS_KEY_SIZE_8192;
53 return TSS_KEY_SIZE_16384;
55 throw Invalid_Argument(
"Unsupported TPM key size " +
std::to_string(bits));
60 bool is_srk_uuid(
const UUID& uuid)
62 static const uint8_t srk[16] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 };
63 const std::vector<uint8_t>& b = uuid.binary_value();
64 return (b.size() == 16 &&
same_mem(b.data(), srk, 16));
68 #define TSPI_CHECK_SUCCESS(expr) do { \
69 TSS_RESULT res = expr; \
70 if(res != TSS_SUCCESS) \
71 tss_error(res, #expr, __FILE__, __LINE__); \
74 std::vector<uint8_t> get_obj_attr(TSS_HCONTEXT ctx,
83 std::vector<uint8_t> r(data, data + data_len);
90 void set_policy_secret(TSS_HPOLICY policy,
const char* secret)
94 BYTE* as_b =
const_cast<BYTE*
>(
reinterpret_cast<const BYTE*
>(secret));
96 TSS_SECRET_MODE_PLAIN,
102 static const uint8_t nullpass[20] = { 0 };
105 TSS_SECRET_MODE_SHA1,
107 const_cast<BYTE*>(nullpass)));
111 TSS_UUID to_tss_uuid(
const UUID& uuid)
113 static_assert(
sizeof(TSS_UUID) == 16,
"Expected size of packed UUID");
116 std::memcpy(&tss_uuid, uuid.binary_value().data(), 16);
120 UUID from_tss_uuid(
const TSS_UUID& tss_uuid)
122 static_assert(
sizeof(TSS_UUID) == 16,
"Expected size of packed UUID");
124 std::vector<uint8_t> mem(16);
125 std::memcpy(mem.data(), &tss_uuid, 16);
126 UUID uuid(std::move(mem));
132 if(flag == TSS_PS_TYPE_USER)
134 else if(flag == TSS_PS_TYPE_SYSTEM)
143 return "tpmkey:uuid=" + uuid.to_string() +
";storage=" + storage_str;
146 std::string format_url(
const TSS_UUID& tss_uuid, TSS_FLAG store_type)
148 UUID uuid = from_tss_uuid(tss_uuid);
150 return format_url(from_tss_uuid(tss_uuid),
151 storage_type_from_tss_flag(store_type));
163 const TSS_UUID SRK_UUID = TSS_UUID_SRK;
165 TSPI_CHECK_SUCCESS(::Tspi_Context_LoadKeyByUUID(m_ctx, TSS_PS_TYPE_SYSTEM, SRK_UUID, &m_srk));
167 TSS_HPOLICY srk_policy;
169 set_policy_secret(srk_policy, srk_password);
194 std::memcpy(out, mem, out_len);
204 const char* key_password) : m_ctx(ctx)
209 TSS_FLAG key_flags = bit_flag(bits) | TSS_KEY_VOLATILE | TSS_KEY_TYPE_SIGNING;
215 TSS_TSPATTRIB_KEYINFO_SIGSCHEME,
216 TSS_SS_RSASSAPKCS1V15_DER));
220 set_policy_secret(policy, key_password);
232 m_storage(storage_type)
234 const TSS_FLAG key_ps_type =
244 const std::vector<uint8_t>& blob) : m_ctx(ctx)
247 const_cast<uint8_t*
>(blob.data()),
259 m_storage = storage_type;
261 const TSS_UUID key_uuid = to_tss_uuid(m_uuid);
262 const TSS_FLAG key_ps_type =
265 const TSS_UUID srk_uuid = TSS_UUID_SRK;
278 if(storage_type != m_storage)
281 " already registered with different storage type");
284 return format_url(m_uuid, m_storage);
289 TSS_KM_KEYINFO2* key_info;
290 UINT32 key_info_size;
299 std::vector<std::string> r(key_info_size);
301 for(
size_t i = 0; i != key_info_size; ++i)
303 r[i] = format_url(key_info[i].keyUUID, key_info[i].persistentStorageType);
312 BigInt TPM_PrivateKey::get_n()
const
317 TSS_TSPATTRIB_RSAKEY_INFO,
318 TSS_TSPATTRIB_KEYINFO_RSA_MODULUS));
324 BigInt TPM_PrivateKey::get_e()
const
329 TSS_TSPATTRIB_RSAKEY_INFO,
330 TSS_TSPATTRIB_KEYINFO_RSA_EXPONENT));
343 return get_n().
bits();
364 throw TPM_Error(
"Private key export not supported for TPM keys");
369 return get_obj_attr(m_ctx.
handle(), m_key,
370 TSS_TSPATTRIB_KEY_BLOB,
371 TSS_TSPATTRIB_KEYBLOB_BLOB);
376 return std::unique_ptr<Public_Key>(
new RSA_PublicKey(get_n(), get_e()));
390 const std::string& hash_name) :
397 void update(
const uint8_t msg[],
size_t msg_len)
override
399 m_hash->update(msg, msg_len);
402 secure_vector<uint8_t> sign(RandomNumberGenerator&)
override
411 secure_vector<uint8_t> msg_hash =
m_hash->final();
413 std::vector<uint8_t> id_and_msg;
414 id_and_msg.reserve(
m_hash_id.size() + msg_hash.size());
416 id_and_msg.insert(id_and_msg.end(), msg_hash.begin(), msg_hash.end());
418 TSS_HCONTEXT ctx =
m_key.ctx().handle();
420 TSPI_CHECK_SUCCESS(::Tspi_Context_CreateObject(ctx, TSS_OBJECT_TYPE_HASH, TSS_HASH_OTHER, &tpm_hash));
421 TSPI_CHECK_SUCCESS(::Tspi_Hash_SetHashValue(tpm_hash, id_and_msg.size(), id_and_msg.data()));
423 BYTE* sig_bytes =
nullptr;
426 secure_vector<uint8_t> sig(sig_bytes, sig_bytes + sig_len);
445 std::unique_ptr<PK_Ops::Signature>
447 const std::string& params,
448 const std::string& )
const
450 return std::unique_ptr<PK_Ops::Signature>(
new TPM_Signing_Operation(*
this, params));
bool same_mem(const T *p1, const T *p2, size_t n)
std::vector< uint8_t > get_contents_unlocked()
size_t key_length() const override
TSS_HCONTEXT handle() const
std::unique_ptr< Public_Key > public_key() const
std::vector< uint8_t > public_key_bits() const override
#define TSPI_CHECK_SUCCESS(expr)
std::string to_string(const BER_Object &obj)
std::string to_string() const
std::vector< uint8_t > m_hash_id
virtual OID get_oid() const
void stir_random(const uint8_t in[], size_t in_len)
DER_Encoder & encode(bool b)
secure_vector< uint8_t > private_key_bits() const override
TPM_Context(pin_cb cb, const char *srk_password)
uint32_t current_counter()
std::vector< T, secure_allocator< T >> secure_vector
size_t if_work_factor(size_t bits)
std::function< std::string(std::string)> pin_cb
TPM_PrivateKey(TPM_Context &ctx, size_t bits, const char *key_password)
std::unique_ptr< PK_Ops::Signature > create_signature_op(RandomNumberGenerator &rng, const std::string ¶ms, const std::string &provider) const override
std::vector< uint8_t > export_blob() const
AlgorithmIdentifier algorithm_identifier() const override
std::vector< uint8_t > pkcs_hash_id(const std::string &name)
size_t estimated_strength() const override
static std::vector< std::string > registered_keys(TPM_Context &ctx)
bool check_key(RandomNumberGenerator &rng, bool) const override
DER_Encoder & start_cons(ASN1_Tag type_tag, ASN1_Tag class_tag=UNIVERSAL)
std::string register_key(TPM_Storage_Type storage_type)
std::unique_ptr< HashFunction > m_hash
const TPM_PrivateKey & m_key
void gen_random(uint8_t out[], size_t out_len)
static BigInt decode(const uint8_t buf[], size_t length, Base base=Binary)
TPM_Context & ctx() const