| /* |
| * Copyright (C) 2016 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. |
| */ |
| |
| #ifndef ANDROID_VOLD_KEYMASTER_H |
| #define ANDROID_VOLD_KEYMASTER_H |
| |
| #include "KeyBuffer.h" |
| |
| #include <memory> |
| #include <string> |
| #include <utility> |
| |
| #include <android-base/macros.h> |
| #include <keymasterV4_1/Keymaster.h> |
| #include <keymasterV4_1/authorization_set.h> |
| |
| namespace android { |
| namespace vold { |
| |
| namespace km { |
| |
| using namespace ::android::hardware::keymaster::V4_1; |
| |
| // Surprisingly -- to me, at least -- this is totally fine. You can re-define symbols that were |
| // brought in via a using directive (the "using namespace") above. In general this seems like a |
| // dangerous thing to rely on, but in this case its implications are simple and straightforward: |
| // km::ErrorCode refers to the 4.0 ErrorCode, though we pull everything else from 4.1. |
| using ErrorCode = ::android::hardware::keymaster::V4_0::ErrorCode; |
| using V4_1_ErrorCode = ::android::hardware::keymaster::V4_1::ErrorCode; |
| |
| } // namespace km |
| |
| using KmDevice = km::support::Keymaster; |
| |
| // C++ wrappers to the Keymaster hidl interface. |
| // This is tailored to the needs of KeyStorage, but could be extended to be |
| // a more general interface. |
| |
| // Wrapper for a Keymaster operation handle representing an |
| // ongoing Keymaster operation. Aborts the operation |
| // in the destructor if it is unfinished. Methods log failures |
| // to LOG(ERROR). |
| class KeymasterOperation { |
| public: |
| ~KeymasterOperation(); |
| // Is this instance valid? This is false if creation fails, and becomes |
| // false on finish or if an update fails. |
| explicit operator bool() const { return mError == km::ErrorCode::OK; } |
| km::ErrorCode errorCode() const { return mError; } |
| // Call "update" repeatedly until all of the input is consumed, and |
| // concatenate the output. Return true on success. |
| template <class TI, class TO> |
| bool updateCompletely(TI& input, TO* output) { |
| if (output) output->clear(); |
| return updateCompletely(input.data(), input.size(), [&](const char* b, size_t n) { |
| if (output) std::copy(b, b + n, std::back_inserter(*output)); |
| }); |
| } |
| |
| // Finish and write the output to this string, unless pointer is null. |
| bool finish(std::string* output); |
| // Move constructor |
| KeymasterOperation(KeymasterOperation&& rhs) { *this = std::move(rhs); } |
| // Construct an object in an error state for error returns |
| KeymasterOperation() : mDevice{nullptr}, mOpHandle{0}, mError{km::ErrorCode::UNKNOWN_ERROR} {} |
| // Move Assignment |
| KeymasterOperation& operator=(KeymasterOperation&& rhs) { |
| mDevice = rhs.mDevice; |
| rhs.mDevice = nullptr; |
| |
| mOpHandle = rhs.mOpHandle; |
| rhs.mOpHandle = 0; |
| |
| mError = rhs.mError; |
| rhs.mError = km::ErrorCode::UNKNOWN_ERROR; |
| |
| return *this; |
| } |
| |
| private: |
| KeymasterOperation(KmDevice* d, uint64_t h) |
| : mDevice{d}, mOpHandle{h}, mError{km::ErrorCode::OK} {} |
| KeymasterOperation(km::ErrorCode error) : mDevice{nullptr}, mOpHandle{0}, mError{error} {} |
| |
| bool updateCompletely(const char* input, size_t inputLen, |
| const std::function<void(const char*, size_t)> consumer); |
| |
| KmDevice* mDevice; |
| uint64_t mOpHandle; |
| km::ErrorCode mError; |
| DISALLOW_COPY_AND_ASSIGN(KeymasterOperation); |
| friend class Keymaster; |
| }; |
| |
| // Wrapper for a Keymaster device for methods that start a KeymasterOperation or are not |
| // part of one. |
| class Keymaster { |
| public: |
| Keymaster(); |
| // false if we failed to open the keymaster device. |
| explicit operator bool() { return mDevice.get() != nullptr; } |
| // Generate a key in the keymaster from the given params. |
| bool generateKey(const km::AuthorizationSet& inParams, std::string* key); |
| // Exports a keymaster key with STORAGE_KEY tag wrapped with a per-boot ephemeral key |
| bool exportKey(const KeyBuffer& kmKey, std::string* key); |
| // If the keymaster supports it, permanently delete a key. |
| bool deleteKey(const std::string& key); |
| // Replace stored key blob in response to KM_ERROR_KEY_REQUIRES_UPGRADE. |
| bool upgradeKey(const std::string& oldKey, const km::AuthorizationSet& inParams, |
| std::string* newKey); |
| // Begin a new cryptographic operation, collecting output parameters if pointer is non-null |
| KeymasterOperation begin(km::KeyPurpose purpose, const std::string& key, |
| const km::AuthorizationSet& inParams, |
| const km::HardwareAuthToken& authToken, |
| km::AuthorizationSet* outParams); |
| bool isSecure(); |
| |
| // Tell Keymaster that early boot has ended and early boot-only keys can no longer be created or |
| // used. |
| void earlyBootEnded(); |
| |
| private: |
| std::unique_ptr<KmDevice> mDevice; |
| DISALLOW_COPY_AND_ASSIGN(Keymaster); |
| static bool hmacKeyGenerated; |
| }; |
| |
| } // namespace vold |
| } // namespace android |
| |
| // FIXME no longer needed now cryptfs is in C++. |
| |
| /* |
| * The following functions provide C bindings to keymaster services |
| * needed by cryptfs scrypt. The compatibility check checks whether |
| * the keymaster implementation is considered secure, i.e., TEE backed. |
| * The create_key function generates an RSA key for signing. |
| * The sign_object function signes an object with the given keymaster |
| * key. |
| */ |
| |
| /* Return values for keymaster_sign_object_for_cryptfs_scrypt */ |
| |
| enum class KeymasterSignResult { |
| ok = 0, |
| error = -1, |
| upgrade = -2, |
| }; |
| |
| int keymaster_compatibility_cryptfs_scrypt(); |
| int keymaster_create_key_for_cryptfs_scrypt(uint32_t rsa_key_size, uint64_t rsa_exponent, |
| uint32_t ratelimit, uint8_t* key_buffer, |
| uint32_t key_buffer_size, uint32_t* key_out_size); |
| |
| int keymaster_upgrade_key_for_cryptfs_scrypt(uint32_t rsa_key_size, uint64_t rsa_exponent, |
| uint32_t ratelimit, const uint8_t* key_blob, |
| size_t key_blob_size, uint8_t* key_buffer, |
| uint32_t key_buffer_size, uint32_t* key_out_size); |
| |
| KeymasterSignResult keymaster_sign_object_for_cryptfs_scrypt( |
| const uint8_t* key_blob, size_t key_blob_size, uint32_t ratelimit, const uint8_t* object, |
| const size_t object_size, uint8_t** signature_buffer, size_t* signature_buffer_size); |
| |
| #endif |