diff options
Diffstat (limited to 'src/lib/prov/tpm/tpm.h')
-rw-r--r-- | src/lib/prov/tpm/tpm.h | 182 |
1 files changed, 182 insertions, 0 deletions
diff --git a/src/lib/prov/tpm/tpm.h b/src/lib/prov/tpm/tpm.h new file mode 100644 index 000000000..ce5eabe1c --- /dev/null +++ b/src/lib/prov/tpm/tpm.h @@ -0,0 +1,182 @@ +/* +* TPM 1.2 interface +* (C) 2015 Jack Lloyd +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#include <botan/exceptn.h> +#include <botan/pk_keys.h> +#include <botan/bigint.h> +#include <botan/rng.h> +#include <botan/uuid.h> + +//TODO remove this +#include <tss/tspi.h> + +namespace Botan { + +class TPM_Error : public Exception + { + public: + TPM_Error(const std::string& err) : Exception(err) {} + }; + +/** +* 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_DLL TPM_Context + { + 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_DLL TPM_RNG : public RandomNumberGenerator + { + public: + TPM_RNG(TPM_Context& ctx) : m_ctx(ctx) {} + + void randomize(byte out[], size_t out_len) override + { + m_ctx.gen_random(out, out_len); + } + + void clear() override {} + + std::string name() const override { return "TPM_RNG"; } + + size_t reseed_with_sources(Entropy_Sources&, + size_t, + std::chrono::milliseconds) override + { + // TODO: poll and stir + return 0; + } + + void add_entropy(const byte in[], size_t in_len) override + { + m_ctx.stir_random(in, in_len); + } + + 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_DLL TPM_PrivateKey : 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 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; + + size_t max_input_bits() const; + + AlgorithmIdentifier algorithm_identifier() const; + + std::vector<byte> x509_subject_public_key() const; + + secure_vector<byte> pkcs8_private_key() const; // not implemented + + std::unique_ptr<Public_Key> public_key() const; + + bool check_key(RandomNumberGenerator& rng, bool) const override; + + std::string algo_name() const { return "RSA"; } // ??? + + std::vector<uint8_t> export_blob() const; + + TPM_Context& ctx() const { return m_ctx; } + + TSS_HKEY handle() const { return m_key; } + private: + BigInt get_n() const; + BigInt get_e() const; + + 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 + +} |