| // 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_ |