/* * Copyright (C) 2020 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #pragma once #include #include #include #include #include #include #include #include #include #include "certificate_utils.h" using ::aidl::android::hardware::security::keymint::AttestationKey; using ::aidl::android::hardware::security::keymint::BeginResult; using ::aidl::android::hardware::security::keymint::Certificate; using ::aidl::android::hardware::security::keymint::HardwareAuthToken; using ::aidl::android::hardware::security::keymint::KeyCharacteristics; using ::aidl::android::hardware::security::keymint::KeyCreationResult; using ::aidl::android::hardware::security::keymint::KeyFormat; using ::aidl::android::hardware::security::keymint::KeyMintHardwareInfo; using ::aidl::android::hardware::security::keymint::KeyParameter; using ::aidl::android::hardware::security::keymint::KeyPurpose; using KeyMintSecurityLevel = ::aidl::android::hardware::security::keymint::SecurityLevel; using V4_0_ErrorCode = ::android::hardware::keymaster::V4_0::ErrorCode; using ::aidl::android::hardware::security::keymint::IKeyMintDevice; using KMV1_ErrorCode = ::aidl::android::hardware::security::keymint::ErrorCode; using ::aidl::android::hardware::security::secureclock::ISecureClock; using ::aidl::android::hardware::security::secureclock::TimeStampToken; using ::aidl::android::hardware::security::sharedsecret::ISharedSecret; using ::aidl::android::hardware::security::sharedsecret::SharedSecretParameters; using ::aidl::android::security::compat::BnKeystoreCompatService; using ::android::hardware::keymaster::V4_1::support::Keymaster; using ::ndk::ScopedAStatus; class OperationSlot; class OperationSlotManager; // An abstraction for a single operation slot. // This contains logic to ensure that we do not free the slot multiple times, // e.g., if we call abort twice on the same operation. class OperationSlot { friend OperationSlotManager; private: std::shared_ptr mOperationSlots; std::optional> mReservedGuard; protected: OperationSlot(std::shared_ptr, std::optional> reservedGuard); OperationSlot(const OperationSlot&) = delete; OperationSlot& operator=(const OperationSlot&) = delete; public: OperationSlot() : mOperationSlots(nullptr), mReservedGuard(std::nullopt) {} OperationSlot(OperationSlot&&) = default; OperationSlot& operator=(OperationSlot&&) = default; ~OperationSlot(); }; class OperationSlotManager { private: uint8_t mNumFreeSlots; std::mutex mNumFreeSlotsMutex; std::mutex mReservedSlotMutex; public: void setNumFreeSlots(uint8_t numFreeSlots); static std::optional claimSlot(std::shared_ptr operationSlots); static OperationSlot claimReservedSlot(std::shared_ptr operationSlots); void freeSlot(); }; class KeyMintDevice : public aidl::android::hardware::security::keymint::BnKeyMintDevice { private: ::android::sp mDevice; std::shared_ptr mOperationSlots; public: explicit KeyMintDevice(::android::sp, KeyMintSecurityLevel); static std::shared_ptr createKeyMintDevice(KeyMintSecurityLevel securityLevel); static std::shared_ptr getWrappedKeymasterDevice(KeyMintSecurityLevel securityLevel); ScopedAStatus getHardwareInfo(KeyMintHardwareInfo* _aidl_return) override; ScopedAStatus addRngEntropy(const std::vector& in_data) override; ScopedAStatus generateKey(const std::vector& in_keyParams, const std::optional& in_attestationKey, KeyCreationResult* out_creationResult) override; ScopedAStatus importKey(const std::vector& in_inKeyParams, KeyFormat in_inKeyFormat, const std::vector& in_inKeyData, const std::optional& in_attestationKey, KeyCreationResult* out_creationResult) override; ScopedAStatus importWrappedKey(const std::vector& in_inWrappedKeyData, const std::vector& in_inWrappingKeyBlob, const std::vector& in_inMaskingKey, const std::vector& in_inUnwrappingParams, int64_t in_inPasswordSid, int64_t in_inBiometricSid, KeyCreationResult* out_creationResult) override; ScopedAStatus upgradeKey(const std::vector& in_inKeyBlobToUpgrade, const std::vector& in_inUpgradeParams, std::vector* _aidl_return) override; ScopedAStatus deleteKey(const std::vector& in_inKeyBlob) override; ScopedAStatus deleteAllKeys() override; ScopedAStatus destroyAttestationIds() override; ScopedAStatus begin(KeyPurpose in_inPurpose, const std::vector& in_inKeyBlob, const std::vector& in_inParams, const std::optional& in_inAuthToken, BeginResult* _aidl_return) override; ScopedAStatus beginInternal(KeyPurpose in_inPurpose, const std::vector& in_inKeyBlob, const std::vector& in_inParams, const std::optional& in_inAuthToken, bool useReservedSlot, BeginResult* _aidl_return); ScopedAStatus deviceLocked(bool passwordOnly, const std::optional& timestampToken) override; ScopedAStatus earlyBootEnded() override; ScopedAStatus convertStorageKeyToEphemeral(const std::vector& storageKeyBlob, std::vector* ephemeralKeyBlob) override; ScopedAStatus getKeyCharacteristics(const std::vector& storageKeyBlob, const std::vector& appId, const std::vector& appData, std::vector* keyCharacteristics) override; ScopedAStatus getRootOfTrustChallenge(std::array* challenge); ScopedAStatus getRootOfTrust(const std::array& challenge, std::vector* rootOfTrust); ScopedAStatus sendRootOfTrust(const std::vector& rootOfTrust); ScopedAStatus setAdditionalAttestationInfo(const std::vector& additionalAttestationInfo); // These are public to allow testing code to use them directly. // This class should not be used publicly anyway. std::variant, KMV1_ErrorCode> getCertificate(const std::vector& keyParams, const std::vector& keyBlob, bool isWrappedKey = false); void setNumFreeSlots(uint8_t numFreeSlots); private: std::optional signCertificate(const std::vector& keyParams, const std::vector& keyBlob, X509* cert); KeyMintSecurityLevel securityLevel_; // Software-based KeyMint device used to implement ECDH. std::shared_ptr softKeyMintDevice_; }; class KeyMintOperation : public aidl::android::hardware::security::keymint::BnKeyMintOperation { public: KeyMintOperation(::android::sp device, uint64_t operationHandle, OperationSlot slot) : mDevice(device), mOperationHandle(operationHandle), mOperationSlot(std::move(slot)) {} ~KeyMintOperation(); ScopedAStatus updateAad(const std::vector& input, const std::optional& authToken, const std::optional& timestampToken) override; ScopedAStatus update(const std::vector& input, const std::optional& authToken, const std::optional& timestampToken, std::vector* output) override; ScopedAStatus finish(const std::optional>& input, const std::optional>& signature, const std::optional& authToken, const std::optional& timeStampToken, const std::optional>& confirmationToken, std::vector* output) override; ScopedAStatus abort(); private: /** * Sets mUpdateBuffer to the given value. * @param data */ void setUpdateBuffer(std::vector data); /** * If mUpdateBuffer is not empty, suffix is appended to mUpdateBuffer, and a reference to * mUpdateBuffer is returned. Otherwise a reference to suffix is returned. * @param suffix * @return */ const std::vector& getExtendedUpdateBuffer(const std::vector& suffix); std::vector mUpdateBuffer; ::android::sp mDevice; uint64_t mOperationHandle; std::optional mOperationSlot; }; class SharedSecret : public aidl::android::hardware::security::sharedsecret::BnSharedSecret { private: ::android::sp mDevice; public: SharedSecret(::android::sp device) : mDevice(device) {} static std::shared_ptr createSharedSecret(KeyMintSecurityLevel securityLevel); virtual ScopedAStatus getSharedSecretParameters(SharedSecretParameters* _aidl_return) override; virtual ScopedAStatus computeSharedSecret(const std::vector& in_params, std::vector* _aidl_return) override; }; class SecureClock : public aidl::android::hardware::security::secureclock::BnSecureClock { private: ::android::sp mDevice; public: SecureClock(::android::sp device) : mDevice(device) {} static std::shared_ptr createSecureClock(KeyMintSecurityLevel securityLevel); ScopedAStatus generateTimeStamp(int64_t in_challenge, TimeStampToken* _aidl_return) override; }; class KeystoreCompatService : public BnKeystoreCompatService { private: std::unordered_map> mDeviceCache; std::unordered_map> mSharedSecretCache; std::shared_ptr mSecureClock; public: KeystoreCompatService() {} ScopedAStatus getKeyMintDevice(KeyMintSecurityLevel in_securityLevel, std::shared_ptr* _aidl_return) override; ScopedAStatus getSharedSecret(KeyMintSecurityLevel in_securityLevel, std::shared_ptr* _aidl_return) override; ScopedAStatus getSecureClock(std::shared_ptr* _aidl_return) override; };