From da6e899f4e1429add2ef023e0cc6b0fcca42c945 Mon Sep 17 00:00:00 2001 From: Shawn Willden Date: Wed, 3 Jun 2015 09:40:45 -0600 Subject: [PATCH] Add keymaster1 support to vold. Bug: 21607106 Change-Id: I498141b90888d4f0652912413b04519f61886935 --- cryptfs.c | 245 ++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 193 insertions(+), 52 deletions(-) diff --git a/cryptfs.c b/cryptfs.c index ecfc3a6..23bf2e1 100644 --- a/cryptfs.c +++ b/cryptfs.c @@ -61,6 +61,7 @@ #include "Process.h" #include +#include #define UNUSED __attribute__((unused)) @@ -88,6 +89,8 @@ #define RSA_KEY_SIZE 2048 #define RSA_KEY_SIZE_BYTES (RSA_KEY_SIZE / 8) #define RSA_EXPONENT 0x10001 +#define KEYMASTER_CRYPTFS_RATE_LIMIT 1 // Maximum one try per second +#define KEYMASTER_CRYPTFS_APP_ID "vold cryptfs" #define RETRY_MOUNT_ATTEMPTS 10 #define RETRY_MOUNT_DELAY_SECONDS 1 @@ -99,7 +102,8 @@ static char *saved_mount_point; static int master_key_saved = 0; static struct crypt_persist_data *persist_data = NULL; -static int keymaster_init(keymaster0_device_t **keymaster_dev) +static int keymaster_init(keymaster0_device_t **keymaster0_dev, + keymaster1_device_t **keymaster1_dev) { int rc; @@ -107,50 +111,74 @@ static int keymaster_init(keymaster0_device_t **keymaster_dev) rc = hw_get_module_by_class(KEYSTORE_HARDWARE_MODULE_ID, NULL, &mod); if (rc) { ALOGE("could not find any keystore module"); - goto out; + 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); } - rc = keymaster0_open(mod, keymaster_dev); if (rc) { ALOGE("could not open keymaster device in %s (%s)", - KEYSTORE_HARDWARE_MODULE_ID, strerror(-rc)); - goto out; + KEYSTORE_HARDWARE_MODULE_ID, strerror(-rc)); + goto err; } return 0; -out: - *keymaster_dev = NULL; +err: + *keymaster0_dev = NULL; + *keymaster1_dev = NULL; return rc; } /* Should we use keymaster? */ static int keymaster_check_compatibility() { - keymaster0_device_t *keymaster_dev = 0; + keymaster0_device_t *keymaster0_dev = 0; + keymaster1_device_t *keymaster1_dev = 0; int rc = 0; - if (keymaster_init(&keymaster_dev)) { + if (keymaster_init(&keymaster0_dev, &keymaster1_dev)) { SLOGE("Failed to init keymaster"); rc = -1; goto out; } - SLOGI("keymaster version is %d", keymaster_dev->common.module->module_api_version); + if (keymaster1_dev) { + rc = 1; + goto out; + } - if (keymaster_dev->common.module->module_api_version + // 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 (!(keymaster_dev->flags & KEYMASTER_SOFTWARE_ONLY) && - (keymaster_dev->flags & KEYMASTER_BLOBS_ARE_STANDALONE)) { + if (!(keymaster0_dev->flags & KEYMASTER_SOFTWARE_ONLY) && + (keymaster0_dev->flags & KEYMASTER_BLOBS_ARE_STANDALONE)) { rc = 1; } out: - keymaster0_close(keymaster_dev); + if (keymaster1_dev) { + keymaster1_close(keymaster1_dev); + } + if (keymaster0_dev) { + keymaster0_close(keymaster0_dev); + } return rc; } @@ -158,24 +186,72 @@ out: static int keymaster_create_key(struct crypt_mnt_ftr *ftr) { uint8_t* key = 0; - keymaster0_device_t *keymaster_dev = 0; + keymaster0_device_t *keymaster0_dev = 0; + keymaster1_device_t *keymaster1_dev = 0; - if (keymaster_init(&keymaster_dev)) { + if (keymaster_init(&keymaster0_dev, &keymaster1_dev)) { SLOGE("Failed to init keymaster"); 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), - keymaster_rsa_keygen_params_t params; - memset(¶ms, '\0', sizeof(params)); - params.public_exponent = RSA_EXPONENT; - params.modulus_size = RSA_KEY_SIZE; + /* Padding & digest specifications. We'll use none/none, but add better options + * just in case we want to use them later. Actual selection is done at operation + * time, but restricted to options specified at keygen. */ + keymaster_param_enum(KM_TAG_PADDING, KM_PAD_NONE), + keymaster_param_enum(KM_TAG_PADDING, KM_PAD_RSA_PKCS1_1_5_SIGN), + keymaster_param_enum(KM_TAG_DIGEST, KM_DIGEST_NONE), + keymaster_param_enum(KM_TAG_DIGEST, KM_DIGEST_SHA_2_256), - size_t key_size; - if (keymaster_dev->generate_keypair(keymaster_dev, TYPE_RSA, ¶ms, - &key, &key_size)) { - SLOGE("Failed to generate keypair"); + /* 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), + + /* Set app ID to a value keystore will never use */ + keymaster_param_blob(KM_TAG_APPLICATION_ID, (uint8_t*)KEYMASTER_CRYPTFS_APP_ID, + sizeof(KEYMASTER_CRYPTFS_APP_ID)), + + /* 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; } @@ -190,7 +266,10 @@ static int keymaster_create_key(struct crypt_mnt_ftr *ftr) ftr->keymaster_blob_size = key_size; out: - keymaster0_close(keymaster_dev); + if (keymaster0_dev) + keymaster0_close(keymaster0_dev); + if (keymaster1_dev) + keymaster1_close(keymaster1_dev); free(key); return rc; } @@ -203,20 +282,14 @@ static int keymaster_sign_object(struct crypt_mnt_ftr *ftr, size_t *signature_size) { int rc = 0; - keymaster0_device_t *keymaster_dev = 0; - if (keymaster_init(&keymaster_dev)) { + keymaster0_device_t *keymaster0_dev = 0; + keymaster1_device_t *keymaster1_dev = 0; + if (keymaster_init(&keymaster0_dev, &keymaster1_dev)) { SLOGE("Failed to init keymaster"); - return -1; + rc = -1; + goto out; } - /* We currently set the digest type to DIGEST_NONE because it's the - * only supported value for keymaster. A similar issue exists with - * PADDING_NONE. Long term both of these should likely change. - */ - keymaster_rsa_sign_params_t params; - params.digest_type = DIGEST_NONE; - params.padding_type = PADDING_NONE; - unsigned char to_sign[RSA_KEY_SIZE_BYTES]; size_t to_sign_size = sizeof(to_sign); memset(to_sign, 0, RSA_KEY_SIZE_BYTES); @@ -241,30 +314,98 @@ static int keymaster_sign_object(struct crypt_mnt_ftr *ftr, // is zero. We could have zero-padded to the left instead, but // this approach is slightly more robust against changes in // object size. However, it's still broken (but not unusably - // so) because we really should be using a proper RSA padding - // function, such as OAEP. - // - // TODO(paullawrence): When keymaster 0.4 is available, change - // this to use the padding options it provides. + // so) because we really should be using a proper deterministic + // RSA padding function, such as PKCS1. memcpy(to_sign + 1, object, min(RSA_KEY_SIZE_BYTES - 1, object_size)); SLOGI("Signing safely-padded object"); break; default: SLOGE("Unknown KDF type %d", ftr->kdf_type); - return -1; + rc = -1; + goto out; } - rc = keymaster_dev->sign_data(keymaster_dev, - ¶ms, - ftr->keymaster_blob, - ftr->keymaster_blob_size, - to_sign, - to_sign_size, - signature, - signature_size); + if (keymaster0_dev) { + keymaster_rsa_sign_params_t params; + params.digest_type = DIGEST_NONE; + params.padding_type = PADDING_NONE; - keymaster0_close(keymaster_dev); - return rc; + 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_VERIFICATION_FAILED) { + // 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; } /* Store password when userdata is successfully decrypted and mounted.