/* * 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 OperationSlots { private: uint8_t mNumFreeSlots; std::mutex mNumFreeSlotsMutex; public: void setNumFreeSlots(uint8_t numFreeSlots); bool claimSlot(); void freeSlot(); }; // 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 { private: OperationSlots* mOperationSlots; bool mIsActive; public: OperationSlot(OperationSlots* slots, bool isActive) : mOperationSlots(slots), mIsActive(isActive) {} void freeSlot(); bool hasSlot() { return mIsActive; } }; class KeyMintDevice : public aidl::android::hardware::security::keymint::BnKeyMintDevice { private: ::android::sp mDevice; OperationSlots mOperationSlots; public: explicit KeyMintDevice(::android::sp, KeyMintSecurityLevel); static std::shared_ptr createKeyMintDevice(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 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; // 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); 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, OperationSlots* slots, bool isActive) : mDevice(device), mOperationHandle(operationHandle), mOperationSlot(slots, isActive) {} ~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; OperationSlot 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; };