Make vold use keystore2 instead of keymaster
Make vold use keystore2 for all its operations instead of directly using
keymaster. This way, we won't have any clients that bypass keystore2,
and we'll no longer need to reserve a keymaster operation for vold.
Note that we now hardcode "SecurityLevel::TRUSTED_ENVIRONMENT" (TEE)
when talking to Keystore2 since Keystore2 only allows TEE and STRONGBOX.
Keystore2 presents any SOFTWARE implementation as a TEE to callers when
no "real" TEE is present. As far as storage encryption is concerned,
there's no advantage to using a STRONGBOX when a "real" TEE is present,
and a STRONGBOX can't be present if a "real" TEE isn't, so asking
Keystore2 for a TEE is the best we can do in any situation.
The difference in behaviour only really affects the full disk encryption
code in cryptfs.cpp, which used to explicitly check that the keymaster
device is a "real" TEE (as opposed to a SOFTWARE implementation) before
using it (it can no longer do so since Keystore2 doesn't provide a way
to do this).
A little code history digging (7c49ab0a0b in particular) shows that
cryptfs.cpp cared about two things when using a keymaster.
- 1) that the keys generated by the keymaster were "standalone" keys -
i.e. that the keymaster could operate on those keys without
requiring /data or any other service to be available.
- 2) that the keymaster was a non-SOFTWARE implementation so that things
would still work in case a "real" TEE keymaster was ever somehow
added to the device after first boot.
Today, all "real" TEE keymasters always generate "standalone" keys, and
a TEE has been required in Android devices since at least Android N. The
only two exceptions are Goldfish and ARC++, which have SOFTWARE
keymasters, but both those keymasters also generate "standalone" keys.
We're also no longer worried about possibly adding a "real" TEE KM to
either of those devices after first boot. So there's no longer a reason
cryptfs.cpp can't use the SOFTWARE keymaster on those devices.
There's also already an upgrade path in place (see
test_mount_encrypted_fs() in cryptfs.cpp) to upgrade the kdf that's
being used once a TEE keymaster is added to the device. So it's safe for
cryptfs.cpp to ask for a TEE keymaster from Keystore2 and use it
blindly, without checking whether or not it's a "real" TEE, which is why
Keymaster::isSecure() just returns true now. A future patch will remove
that function and simplify its callers.
Bug: 181910578
Test: cuttlefish and bramble boot. Adding, switching between, stopping
and removing users work.
Change-Id: Iaebfef082eca0da8a305043fafb6d85e5de14cf8
diff --git a/Keymaster.h b/Keymaster.h
index ccf018e..84b473e 100644
--- a/Keymaster.h
+++ b/Keymaster.h
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
+// TODO: Maybe "Keymaster" should be replaced with Keystore2 everywhere?
#ifndef ANDROID_VOLD_KEYMASTER_H
#define ANDROID_VOLD_KEYMASTER_H
@@ -24,33 +24,25 @@
#include <utility>
#include <android-base/macros.h>
-#include <keymasterV4_1/Keymaster.h>
-#include <keymasterV4_1/authorization_set.h>
+#include <keymint_support/authorization_set.h>
+#include <keymint_support/keymint_tags.h>
+
+#include <aidl/android/hardware/security/keymint/ErrorCode.h>
+#include <aidl/android/system/keystore2/IKeystoreService.h>
+#include <android/binder_manager.h>
namespace android {
namespace vold {
-namespace km {
+namespace ks2 = ::aidl::android::system::keystore2;
+namespace km = ::aidl::android::hardware::security::keymint;
-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.
+// C++ wrappers to the Keystore2 AIDL 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
+// Wrapper for a Keystore2 operation handle representing an
+// ongoing Keystore2 operation. Aborts the operation
// in the destructor if it is unfinished. Methods log failures
// to LOG(ERROR).
class KeymasterOperation {
@@ -58,8 +50,9 @@
~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; }
+ explicit operator bool() const { return (bool)ks2Operation; }
+ km::ErrorCode getErrorCode() const { return errorCode; }
+ std::optional<std::string> getUpgradedBlob() const { return upgradedBlob; }
// Call "update" repeatedly until all of the input is consumed, and
// concatenate the output. Return true on success.
template <class TI, class TO>
@@ -75,102 +68,74 @@
// 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} {}
+ KeymasterOperation() { errorCode = km::ErrorCode::UNKNOWN_ERROR; }
// Move Assignment
KeymasterOperation& operator=(KeymasterOperation&& rhs) {
- mDevice = rhs.mDevice;
- rhs.mDevice = nullptr;
+ ks2Operation = rhs.ks2Operation;
+ rhs.ks2Operation = nullptr;
- mOpHandle = rhs.mOpHandle;
- rhs.mOpHandle = 0;
+ upgradedBlob = rhs.upgradedBlob;
+ rhs.upgradedBlob = std::nullopt;
- mError = rhs.mError;
- rhs.mError = km::ErrorCode::UNKNOWN_ERROR;
+ errorCode = rhs.errorCode;
+ rhs.errorCode = 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} {}
+ KeymasterOperation(std::shared_ptr<ks2::IKeystoreOperation> ks2Op,
+ std::optional<std::vector<uint8_t>> blob)
+ : ks2Operation{ks2Op}, errorCode{km::ErrorCode::OK} {
+ if (blob)
+ upgradedBlob = std::optional(std::string(blob->begin(), blob->end()));
+ else
+ upgradedBlob = std::nullopt;
+ }
+
+ KeymasterOperation(km::ErrorCode errCode) : errorCode{errCode} {}
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;
+ std::shared_ptr<ks2::IKeystoreOperation> ks2Operation;
+ std::optional<std::string> upgradedBlob;
+ km::ErrorCode errorCode;
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.
+// Wrapper for keystore2 methods that vold uses.
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.
+ // false if we failed to get a keystore2 security level.
+ explicit operator bool() { return (bool)securityLevel; }
+ // Generate a key using keystore2 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
+ // Exports a keystore2 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.
+ // If supported, permanently delete a key from the keymint device it belongs to.
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,
+ // If the key was upgraded as a result of a call to this method, the returned KeymasterOperation
+ // also stores the upgraded key blob.
+ KeymasterOperation begin(const std::string& key, const km::AuthorizationSet& inParams,
km::AuthorizationSet* outParams);
bool isSecure();
- // Tell all Keymaster instances that early boot has ended and early boot-only keys can no longer
+ // Tell all Keymint devices that early boot has ended and early boot-only keys can no longer
// be created or used.
static void earlyBootEnded();
private:
- sp<KmDevice> mDevice;
+ std::shared_ptr<ks2::IKeystoreSecurityLevel> securityLevel;
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