Port cryptfs to HILD keymaster HAL
Cryptfs uses keymaster for key derivation. Vold has a C++ abstraction
for Keymaster. However, cryptfs, being a pure C implementation, uses
its own abstraction of the keymaster HAL.
This patch expresses cryptfs' keymaster abstraction in terms of
vold's C++ Keymaster abstraction, consolidating the code base to a
single point where the actual keymaster HAL is beeing used.
Test: successfully upgrade bullhead/angler while using FDE and
having a PIN set
run vold_cryptfs_scrypt_hidlization_equivalence_test
Bug: 35028230
Bug: 32020919
Change-Id: Ic3b765720be0cf7899dda5005fa89347ffb59b9f
diff --git a/cryptfs.c b/cryptfs.c
index e2606ec..2797409 100644
--- a/cryptfs.c
+++ b/cryptfs.c
@@ -61,12 +61,9 @@
#include "f2fs_sparseblock.h"
#include "CheckBattery.h"
#include "Process.h"
+#include "Keymaster.h"
#include <bootloader_message/bootloader_message.h>
-#include <hardware/keymaster0.h>
-#include <hardware/keymaster1.h>
-
-#define UNUSED __attribute__((unused))
#define UNUSED __attribute__((unused))
@@ -108,181 +105,32 @@
static int master_key_saved = 0;
static struct crypt_persist_data *persist_data = NULL;
-static int keymaster_init(keymaster0_device_t **keymaster0_dev,
- keymaster1_device_t **keymaster1_dev)
-{
- int rc;
-
- const hw_module_t* mod;
- rc = hw_get_module_by_class(KEYSTORE_HARDWARE_MODULE_ID, NULL, &mod);
- if (rc) {
- ALOGE("could not find any keystore module");
- goto err;
- }
-
- SLOGI("keymaster module name is %s", mod->name);
- SLOGI("keymaster version is %d", mod->module_api_version);
-
- *keymaster0_dev = NULL;
- *keymaster1_dev = NULL;
- if (mod->module_api_version == KEYMASTER_MODULE_API_VERSION_1_0) {
- SLOGI("Found keymaster1 module, using keymaster1 API.");
- rc = keymaster1_open(mod, keymaster1_dev);
- } else {
- SLOGI("Found keymaster0 module, using keymaster0 API.");
- rc = keymaster0_open(mod, keymaster0_dev);
- }
-
- if (rc) {
- ALOGE("could not open keymaster device in %s (%s)",
- KEYSTORE_HARDWARE_MODULE_ID, strerror(-rc));
- goto err;
- }
-
- return 0;
-
-err:
- *keymaster0_dev = NULL;
- *keymaster1_dev = NULL;
- return rc;
-}
-
/* Should we use keymaster? */
static int keymaster_check_compatibility()
{
- keymaster0_device_t *keymaster0_dev = 0;
- keymaster1_device_t *keymaster1_dev = 0;
- int rc = 0;
-
- if (keymaster_init(&keymaster0_dev, &keymaster1_dev)) {
- SLOGE("Failed to init keymaster");
- rc = -1;
- goto out;
- }
-
- if (keymaster1_dev) {
- rc = 1;
- goto out;
- }
-
- if (!keymaster0_dev || !keymaster0_dev->common.module) {
- rc = -1;
- goto out;
- }
-
- // TODO(swillden): Check to see if there's any reason to require v0.3. I think v0.1 and v0.2
- // should work.
- if (keymaster0_dev->common.module->module_api_version
- < KEYMASTER_MODULE_API_VERSION_0_3) {
- rc = 0;
- goto out;
- }
-
- if (!(keymaster0_dev->flags & KEYMASTER_SOFTWARE_ONLY) &&
- (keymaster0_dev->flags & KEYMASTER_BLOBS_ARE_STANDALONE)) {
- rc = 1;
- }
-
-out:
- if (keymaster1_dev) {
- keymaster1_close(keymaster1_dev);
- }
- if (keymaster0_dev) {
- keymaster0_close(keymaster0_dev);
- }
- return rc;
+ return keymaster_compatibility_cryptfs_scrypt();
}
/* Create a new keymaster key and store it in this footer */
static int keymaster_create_key(struct crypt_mnt_ftr *ftr)
{
- uint8_t* key = 0;
- keymaster0_device_t *keymaster0_dev = 0;
- keymaster1_device_t *keymaster1_dev = 0;
-
if (ftr->keymaster_blob_size) {
SLOGI("Already have key");
return 0;
}
- if (keymaster_init(&keymaster0_dev, &keymaster1_dev)) {
- SLOGE("Failed to init keymaster");
+ int rc = keymaster_create_key_for_cryptfs_scrypt(RSA_KEY_SIZE, RSA_EXPONENT,
+ KEYMASTER_CRYPTFS_RATE_LIMIT, ftr->keymaster_blob, KEYMASTER_BLOB_SIZE,
+ &ftr->keymaster_blob_size);
+ if (rc) {
+ if (ftr->keymaster_blob_size > KEYMASTER_BLOB_SIZE) {
+ SLOGE("Keymaster key blob to large)");
+ ftr->keymaster_blob_size = 0;
+ }
+ SLOGE("Failed to generate keypair");
return -1;
}
-
- int rc = 0;
- size_t key_size = 0;
- if (keymaster1_dev) {
- keymaster_key_param_t params[] = {
- /* Algorithm & size specifications. Stick with RSA for now. Switch to AES later. */
- keymaster_param_enum(KM_TAG_ALGORITHM, KM_ALGORITHM_RSA),
- keymaster_param_int(KM_TAG_KEY_SIZE, RSA_KEY_SIZE),
- keymaster_param_long(KM_TAG_RSA_PUBLIC_EXPONENT, RSA_EXPONENT),
-
- /* The only allowed purpose for this key is signing. */
- keymaster_param_enum(KM_TAG_PURPOSE, KM_PURPOSE_SIGN),
-
- /* Padding & digest specifications. */
- keymaster_param_enum(KM_TAG_PADDING, KM_PAD_NONE),
- keymaster_param_enum(KM_TAG_DIGEST, KM_DIGEST_NONE),
-
- /* Require that the key be usable in standalone mode. File system isn't available. */
- keymaster_param_enum(KM_TAG_BLOB_USAGE_REQUIREMENTS, KM_BLOB_STANDALONE),
-
- /* No auth requirements, because cryptfs is not yet integrated with gatekeeper. */
- keymaster_param_bool(KM_TAG_NO_AUTH_REQUIRED),
-
- /* Rate-limit key usage attempts, to rate-limit brute force */
- keymaster_param_int(KM_TAG_MIN_SECONDS_BETWEEN_OPS, KEYMASTER_CRYPTFS_RATE_LIMIT),
- };
- keymaster_key_param_set_t param_set = { params, sizeof(params)/sizeof(*params) };
- keymaster_key_blob_t key_blob;
- keymaster_error_t error = keymaster1_dev->generate_key(keymaster1_dev, ¶m_set,
- &key_blob,
- NULL /* characteristics */);
- if (error != KM_ERROR_OK) {
- SLOGE("Failed to generate keymaster1 key, error %d", error);
- rc = -1;
- goto out;
- }
-
- key = (uint8_t*)key_blob.key_material;
- key_size = key_blob.key_material_size;
- }
- else if (keymaster0_dev) {
- keymaster_rsa_keygen_params_t params;
- memset(¶ms, '\0', sizeof(params));
- params.public_exponent = RSA_EXPONENT;
- params.modulus_size = RSA_KEY_SIZE;
-
- if (keymaster0_dev->generate_keypair(keymaster0_dev, TYPE_RSA, ¶ms,
- &key, &key_size)) {
- SLOGE("Failed to generate keypair");
- rc = -1;
- goto out;
- }
- } else {
- SLOGE("Cryptfs bug: keymaster_init succeeded but didn't initialize a device");
- rc = -1;
- goto out;
- }
-
- if (key_size > KEYMASTER_BLOB_SIZE) {
- SLOGE("Keymaster key too large for crypto footer");
- rc = -1;
- goto out;
- }
-
- memcpy(ftr->keymaster_blob, key, key_size);
- ftr->keymaster_blob_size = key_size;
-
-out:
- if (keymaster0_dev)
- keymaster0_close(keymaster0_dev);
- if (keymaster1_dev)
- keymaster1_close(keymaster1_dev);
- free(key);
- return rc;
+ return 0;
}
/* This signs the given object using the keymaster key. */
@@ -292,15 +140,6 @@
unsigned char **signature,
size_t *signature_size)
{
- int rc = 0;
- keymaster0_device_t *keymaster0_dev = 0;
- keymaster1_device_t *keymaster1_dev = 0;
- if (keymaster_init(&keymaster0_dev, &keymaster1_dev)) {
- SLOGE("Failed to init keymaster");
- rc = -1;
- goto out;
- }
-
unsigned char to_sign[RSA_KEY_SIZE_BYTES];
size_t to_sign_size = sizeof(to_sign);
memset(to_sign, 0, RSA_KEY_SIZE_BYTES);
@@ -332,91 +171,10 @@
break;
default:
SLOGE("Unknown KDF type %d", ftr->kdf_type);
- rc = -1;
- goto out;
+ return -1;
}
-
- if (keymaster0_dev) {
- keymaster_rsa_sign_params_t params;
- params.digest_type = DIGEST_NONE;
- params.padding_type = PADDING_NONE;
-
- rc = keymaster0_dev->sign_data(keymaster0_dev,
- ¶ms,
- ftr->keymaster_blob,
- ftr->keymaster_blob_size,
- to_sign,
- to_sign_size,
- signature,
- signature_size);
- goto out;
- } else if (keymaster1_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_error_t error = keymaster1_dev->begin(keymaster1_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 = keymaster1_dev->begin(keymaster1_dev, KM_PURPOSE_SIGN, &key,
- ¶m_set, NULL /* out_params */,
- &op_handle);
- }
- if (error != KM_ERROR_OK) {
- SLOGE("Error starting keymaster signature transaction: %d", error);
- rc = -1;
- goto out;
- }
-
- keymaster_blob_t input = { to_sign, to_sign_size };
- size_t input_consumed;
- error = keymaster1_dev->update(keymaster1_dev, op_handle, NULL /* in_params */,
- &input, &input_consumed, NULL /* out_params */,
- NULL /* output */);
- if (error != KM_ERROR_OK) {
- SLOGE("Error sending data to keymaster signature transaction: %d", 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.
- SLOGE("Keymaster update() did not consume all data.");
- keymaster1_dev->abort(keymaster1_dev, op_handle);
- rc = -1;
- goto out;
- }
-
- keymaster_blob_t tmp_sig;
- error = keymaster1_dev->finish(keymaster1_dev, op_handle, NULL /* in_params */,
- NULL /* verify signature */, NULL /* out_params */,
- &tmp_sig);
- if (error != KM_ERROR_OK) {
- SLOGE("Error finishing keymaster signature transaction: %d", error);
- rc = -1;
- goto out;
- }
-
- *signature = (uint8_t*)tmp_sig.data;
- *signature_size = tmp_sig.data_length;
- } else {
- SLOGE("Cryptfs bug: keymaster_init succeded but didn't initialize a device.");
- rc = -1;
- goto out;
- }
-
- out:
- if (keymaster1_dev)
- keymaster1_close(keymaster1_dev);
- if (keymaster0_dev)
- keymaster0_close(keymaster0_dev);
-
- return rc;
+ return keymaster_sign_object_for_cryptfs_scrypt(ftr->keymaster_blob, ftr->keymaster_blob_size,
+ KEYMASTER_CRYPTFS_RATE_LIMIT, to_sign, to_sign_size, signature, signature_size);
}
/* Store password when userdata is successfully decrypted and mounted.