| // Copyright 2022 The ChromiumOS Authors | |
| // Use of this source code is governed by a BSD-style license that can be | |
| // found in the LICENSE file. | |
| #ifndef LIBHWSEC_BACKEND_TPM2_KEY_MANAGEMENT_H_ | |
| #define LIBHWSEC_BACKEND_TPM2_KEY_MANAGEMENT_H_ | |
| #include <cstdint> | |
| #include <functional> | |
| #include <memory> | |
| #include <optional> | |
| #include <string> | |
| #include <utility> | |
| #include <absl/container/flat_hash_map.h> | |
| #include <absl/container/flat_hash_set.h> | |
| #include <base/timer/timer.h> | |
| #include <brillo/secure_blob.h> | |
| #include <crypto/scoped_openssl_types.h> | |
| #include <trunks/tpm_generated.h> | |
| #include "libhwsec/backend/key_management.h" | |
| #include "libhwsec/backend/tpm2/config.h" | |
| #include "libhwsec/backend/tpm2/trunks_context.h" | |
| #include "libhwsec/proxy/proxy.h" | |
| #include "libhwsec/status.h" | |
| #include "libhwsec/structures/key.h" | |
| #include "libhwsec/structures/no_default_init.h" | |
| #include "libhwsec/structures/operation_policy.h" | |
| namespace hwsec { | |
| struct KeyReloadDataTpm2 { | |
| brillo::Blob key_blob; | |
| uint32_t client_count; | |
| base::TimeDelta lazy_expiration_time; | |
| std::unique_ptr<base::OneShotTimer> flush_timer; | |
| }; | |
| struct KeyTpm2 { | |
| enum class Type { | |
| kPersistentKey, | |
| kTransientKey, | |
| kReloadableTransientKey, | |
| }; | |
| struct Cache { | |
| OperationPolicy policy; | |
| NoDefault<trunks::TPMT_PUBLIC> public_area; | |
| }; | |
| NoDefault<Type> type; | |
| NoDefault<trunks::TPM_HANDLE> key_handle; | |
| NoDefault<Cache> cache; | |
| std::optional<KeyReloadDataTpm2> reload_data; | |
| }; | |
| class KeyManagementTpm2 : public KeyManagement { | |
| public: | |
| KeyManagementTpm2(TrunksContext& context, | |
| ConfigTpm2& config, | |
| org::chromium::TpmManagerProxyInterface& tpm_manager, | |
| MiddlewareDerivative& middleware_derivative) | |
| : context_(context), | |
| config_(config), | |
| tpm_manager_(tpm_manager), | |
| middleware_derivative_(middleware_derivative) {} | |
| ~KeyManagementTpm2(); | |
| StatusOr<absl::flat_hash_set<KeyAlgoType>> GetSupportedAlgo() override; | |
| Status IsSupported(KeyAlgoType key_algo, | |
| const CreateKeyOptions& options) override; | |
| StatusOr<CreateKeyResult> CreateKey(const OperationPolicySetting& policy, | |
| KeyAlgoType key_algo, | |
| const LoadKeyOptions& load_key_options, | |
| const CreateKeyOptions& options) override; | |
| StatusOr<ScopedKey> LoadKey(const OperationPolicy& policy, | |
| const brillo::Blob& key_blob, | |
| const LoadKeyOptions& load_key_options) override; | |
| StatusOr<ScopedKey> GetPolicyEndorsementKey( | |
| const OperationPolicySetting& policy, KeyAlgoType key_algo) override; | |
| StatusOr<ScopedKey> GetPersistentKey(PersistentKeyType key_type) override; | |
| StatusOr<brillo::Blob> GetPubkeyHash(Key key) override; | |
| Status Flush(Key key) override; | |
| Status ReloadIfPossible(Key key) override; | |
| StatusOr<ScopedKey> SideLoadKey(uint32_t key_handle) override; | |
| StatusOr<uint32_t> GetKeyHandle(Key key) override; | |
| StatusOr<CreateKeyResult> WrapRSAKey( | |
| const OperationPolicySetting& policy, | |
| const brillo::Blob& public_modulus, | |
| const brillo::SecureBlob& private_prime_factor, | |
| const LoadKeyOptions& load_key_options, | |
| const CreateKeyOptions& options) override; | |
| StatusOr<CreateKeyResult> WrapECCKey( | |
| const OperationPolicySetting& policy, | |
| const brillo::Blob& public_point_x, | |
| const brillo::Blob& public_point_y, | |
| const brillo::SecureBlob& private_value, | |
| const LoadKeyOptions& load_key_options, | |
| const CreateKeyOptions& options) override; | |
| StatusOr<RSAPublicInfo> GetRSAPublicInfo(Key key) override; | |
| StatusOr<ECCPublicInfo> GetECCPublicInfo(Key key) override; | |
| StatusOr<brillo::Blob> GetEndorsementPublicKey( | |
| KeyAlgoType key_algo, PublicKeyEncoding encoding) override; | |
| // Below are TPM2.0 specific code. | |
| // Gets the reference of the internal key data. | |
| StatusOr<std::reference_wrapper<KeyTpm2>> GetKeyData(Key key); | |
| // Loads the key from its DER-encoded Subject Public Key Info. Algorithm | |
| // scheme and hashing algorithm are passed via |scheme| and |hash_alg|. | |
| // Currently, only the RSA signing keys are supported. | |
| StatusOr<ScopedKey> LoadPublicKeyFromSpki( | |
| const brillo::Blob& public_key_spki_der, | |
| trunks::TPM_ALG_ID scheme, | |
| trunks::TPM_ALG_ID hash_alg); | |
| // Gets public key in DER format as string from the |key| or |public_data| of | |
| // the key. The format of public key is SubjectPublicKeyInfo for ECC, | |
| // RSAPublicKey for RSA. | |
| // If |use_rsa_subject_key_info| is true, the format would be | |
| // SubjectPublicKeyInfo for RSA, too. | |
| // TODO(b/172213969): We should get rid of |use_rsa_subject_key_info| | |
| // once the bug is resolved. | |
| StatusOr<brillo::Blob> GetPublicKeyDer(Key key, | |
| bool use_rsa_subject_key_info); | |
| StatusOr<brillo::Blob> GetPublicKeyDerFromPublicData( | |
| const trunks::TPMT_PUBLIC& public_data, bool use_rsa_subject_key_info); | |
| StatusOr<ScopedKey> GetEndorsementKey(KeyAlgoType key_algo); | |
| private: | |
| StatusOr<CreateKeyResult> CreateRsaKey( | |
| const OperationPolicySetting& policy, | |
| const CreateKeyOptions& options, | |
| const LoadKeyOptions& load_key_options); | |
| StatusOr<CreateKeyResult> CreateSoftwareGenRsaKey( | |
| const OperationPolicySetting& policy, | |
| const CreateKeyOptions& options, | |
| const LoadKeyOptions& load_key_options); | |
| StatusOr<CreateKeyResult> CreateEccKey( | |
| const OperationPolicySetting& policy, | |
| const CreateKeyOptions& options, | |
| const LoadKeyOptions& load_key_options); | |
| StatusOr<ScopedKey> LoadKeyInternal( | |
| const OperationPolicy& policy, | |
| KeyTpm2::Type key_type, | |
| uint32_t key_handle, | |
| std::optional<KeyReloadDataTpm2> reload_data); | |
| Status FlushTransientKey(Key key, KeyTpm2& key_data); | |
| Status FlushKeyTokenAndHandle(KeyToken token, trunks::TPM_HANDLE handle); | |
| StatusOr<ECCPublicInfo> GetECCPublicInfoFromPublicData( | |
| const trunks::TPMT_PUBLIC& public_data); | |
| StatusOr<crypto::ScopedEC_KEY> GetEccPublicKey( | |
| const trunks::TPMT_PUBLIC& public_data); | |
| StatusOr<crypto::ScopedRSA> GetRsaPublicKey( | |
| const trunks::TPMT_PUBLIC& public_data); | |
| TrunksContext& context_; | |
| ConfigTpm2& config_; | |
| org::chromium::TpmManagerProxyInterface& tpm_manager_; | |
| MiddlewareDerivative& middleware_derivative_; | |
| KeyToken current_token_ = 0; | |
| // We need pointer/reference stability for values, use an extra unique_ptr | |
| // here. | |
| absl::flat_hash_map<KeyToken, std::unique_ptr<KeyTpm2>> key_map_; | |
| absl::flat_hash_map<PersistentKeyType, KeyToken> persistent_key_map_; | |
| bool shall_flush_immediately_ = false; | |
| }; | |
| } // namespace hwsec | |
| #endif // LIBHWSEC_BACKEND_TPM2_KEY_MANAGEMENT_H_ |