cryptfs: add support for keymaster 2
Change-Id: I1c4f06551897c8964ac2d40c9e785d527cc83847
diff --git a/crypto/fde/cryptfs.cpp b/crypto/fde/cryptfs.cpp
index 7c30eef..2d1595f 100644
--- a/crypto/fde/cryptfs.cpp
+++ b/crypto/fde/cryptfs.cpp
@@ -74,6 +74,7 @@
#include <openssl/sha.h>
#include <hardware/keymaster0.h>
#include <hardware/keymaster1.h>
+#include <hardware/keymaster2.h>
#endif
//#include "android-base/properties.h"
//#include <bootloader_message/bootloader_message.h>
@@ -176,7 +177,8 @@
}
#else //TW_KEYMASTER_MAX_API == 0
static int keymaster_init(keymaster0_device_t **keymaster0_dev,
- keymaster1_device_t **keymaster1_dev)
+ keymaster1_device_t **keymaster1_dev,
+ keymaster2_device_t **keymaster2_dev)
{
int rc;
@@ -192,7 +194,11 @@
*keymaster0_dev = NULL;
*keymaster1_dev = NULL;
- if (mod->module_api_version == KEYMASTER_MODULE_API_VERSION_1_0) {
+ *keymaster2_dev = NULL;
+ if (mod->module_api_version == KEYMASTER_MODULE_API_VERSION_2_0) {
+ printf("Found keymaster2 module, using keymaster2 API.\n");
+ rc = keymaster2_open(mod, keymaster2_dev);
+ } else if (mod->module_api_version == KEYMASTER_MODULE_API_VERSION_1_0) {
printf("Found keymaster1 module, using keymaster1 API.\n");
rc = keymaster1_open(mod, keymaster1_dev);
} else {
@@ -211,6 +217,7 @@
err:
*keymaster0_dev = NULL;
*keymaster1_dev = NULL;
+ *keymaster2_dev = NULL;
return rc;
}
#endif //TW_KEYMASTER_MAX_API == 0
@@ -424,7 +431,8 @@
#if TW_KEYMASTER_MAX_API >= 1
keymaster0_device_t *keymaster0_dev = 0;
keymaster1_device_t *keymaster1_dev = 0;
- if (keymaster_init(&keymaster0_dev, &keymaster1_dev)) {
+ keymaster2_device_t *keymaster2_dev = 0;
+ if (keymaster_init(&keymaster0_dev, &keymaster1_dev, &keymaster2_dev)) {
#else
keymaster_device_t *keymaster0_dev = 0;
if (keymaster_init(&keymaster0_dev)) {
@@ -504,6 +512,82 @@
*signature_size = tmp_sig.data_length;
rc = 0;
}
+ else if (keymaster2_dev) {
+ keymaster_key_blob_t key = { ftr->keymaster_blob, ftr->keymaster_blob_size };
+ keymaster_key_param_t params[] = {
+ keymaster_param_enum(KM_TAG_PADDING, KM_PAD_NONE),
+ keymaster_param_enum(KM_TAG_DIGEST, KM_DIGEST_NONE),
+ };
+ keymaster_key_param_set_t param_set = { params, sizeof(params)/sizeof(*params) };
+ keymaster_operation_handle_t op_handle;
+ keymaster_key_param_t config_params[] = {
+ // Set these to crazy values so we don't need to synchronize
+ // the recovery with system updates.
+ // key upgrades will be required; it will be upgraded in-memory
+ keymaster_param_int(KM_TAG_OS_VERSION, 999999),
+ keymaster_param_int(KM_TAG_OS_PATCHLEVEL, 209912),
+ };
+ keymaster_key_param_set_t config_param_set = { config_params, sizeof(config_params)/sizeof(*config_params) };
+ keymaster2_dev->configure(keymaster2_dev, &config_param_set);
+ keymaster_error_t error = keymaster2_dev->begin(keymaster2_dev, KM_PURPOSE_SIGN, &key,
+ ¶m_set, NULL /* out_params */,
+ &op_handle);
+ if (error == KM_ERROR_KEY_RATE_LIMIT_EXCEEDED) {
+ // Key usage has been rate-limited. Wait a bit and try again.
+ sleep(KEYMASTER_CRYPTFS_RATE_LIMIT);
+ error = keymaster2_dev->begin(keymaster2_dev, KM_PURPOSE_SIGN, &key,
+ ¶m_set, NULL /* out_params */,
+ &op_handle);
+ }
+
+ if (error == KM_ERROR_KEY_REQUIRES_UPGRADE) {
+ // Upgrade key in-memory if required
+ // Do not actually write it back; just keep it in memory
+ const keymaster_key_blob_t key_to_upd = key;
+ keymaster2_dev->upgrade_key(keymaster2_dev, &key_to_upd, &config_param_set, &key);
+ error = keymaster2_dev->begin(keymaster2_dev, KM_PURPOSE_SIGN, &key,
+ ¶m_set, NULL /* out_params */,
+ &op_handle);
+ }
+
+ if (error != KM_ERROR_OK) {
+ printf("Error starting keymaster signature transaction: %d\n", error);
+ rc = -1;
+ goto out;
+ }
+
+ keymaster_blob_t input = { to_sign, to_sign_size };
+ size_t input_consumed;
+ error = keymaster2_dev->update(keymaster2_dev, op_handle, NULL /* in_params */,
+ &input, &input_consumed, NULL /* out_params */,
+ NULL /* output */);
+ if (error != KM_ERROR_OK) {
+ printf("Error sending data to keymaster signature transaction: %d\n", error);
+ rc = -1;
+ goto out;
+ }
+ if (input_consumed != to_sign_size) {
+ // This should never happen. If it does, it's a bug in the keymaster implementation.
+ printf("Keymaster update() did not consume all data.\n");
+ keymaster2_dev->abort(keymaster2_dev, op_handle);
+ rc = -1;
+ goto out;
+ }
+
+ keymaster_blob_t tmp_sig;
+ error = keymaster2_dev->finish(keymaster2_dev, op_handle, NULL /* in_params */,
+ NULL, NULL /* verify signature */, NULL /* out_params */,
+ &tmp_sig);
+ if (error != KM_ERROR_OK) {
+ printf("Error finishing keymaster signature transaction: %d\n", error);
+ rc = -1;
+ goto out;
+ }
+
+ *signature = (uint8_t*)tmp_sig.data;
+ *signature_size = tmp_sig.data_length;
+ rc = 0;
+ }
#endif // TW_KEYMASTER_API >= 1
out:
@@ -949,7 +1033,9 @@
tgt->next = crypt_params - buffer;
for (i = 0; i < TABLE_LOAD_RETRIES; i++) {
- if (! ioctl(fd, DM_TABLE_LOAD, io)) {
+ int ret = ioctl(fd, DM_TABLE_LOAD, io);
+ if (!ret) {
+ SLOGI("ioctl err: %d", ret);
break;
}
usleep(500000);