diff --git a/crypto/fde/cryptfs.cpp b/crypto/fde/cryptfs.cpp index 7c30eef8..2d1595f3 100644 --- a/crypto/fde/cryptfs.cpp +++ b/crypto/fde/cryptfs.cpp @@ -74,6 +74,7 @@ #include #include #include +#include #endif //#include "android-base/properties.h" //#include @@ -176,7 +177,8 @@ out: } #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 @@ static int keymaster_init(keymaster0_device_t **keymaster0_dev, *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 @@ static int keymaster_init(keymaster0_device_t **keymaster0_dev, err: *keymaster0_dev = NULL; *keymaster1_dev = NULL; + *keymaster2_dev = NULL; return rc; } #endif //TW_KEYMASTER_MAX_API == 0 @@ -424,7 +431,8 @@ static int keymaster_sign_object(struct crypt_mnt_ftr *ftr, #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)) { @@ -500,6 +508,82 @@ static int keymaster_sign_object(struct crypt_mnt_ftr *ftr, goto out; } + *signature = (uint8_t*)tmp_sig.data; + *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; @@ -949,7 +1033,9 @@ static int load_crypto_mapping_table(struct crypt_mnt_ftr *crypt_ftr, 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);