/* * 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 #include #include #include #include #include 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 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 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 all Keymaster instances that early boot has ended and early boot-only keys can no longer // be created or used. static void earlyBootEnded(); private: std::unique_ptr 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