/* ** ** Copyright 2017, The Android Open Source Project ** ** Licensed under the Apache License, Version 2.0 (the "License"); ** you may not use this file except in compliance with the License. ** You may obtain a copy of the License at ** ** http://www.apache.org/licenses/LICENSE-2.0 ** ** Unless required by applicable law or agreed to in writing, software ** distributed under the License is distributed on an "AS IS" BASIS, ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ** See the License for the specific language governing permissions and ** limitations under the License. */ #define LOG_TAG "scrypt_test" #include <log/log.h> #include <hardware/keymaster0.h> #include <hardware/keymaster1.h> #include <cstring> #include <gtest/gtest.h> #include "../cryptfs.h" #include "../Keymaster.h" #ifdef CONFIG_HW_DISK_ENCRYPTION #include "cryptfs_hw.h" #endif #define min(a, b) ((a) < (b) ? (a) : (b)) /* Maximum allowed keymaster blob size. */ #define KEYMASTER_BLOB_SIZE 2048 /* Key Derivation Function algorithms */ #define KDF_PBKDF2 1 #define KDF_SCRYPT 2 /* Algorithms 3 & 4 deprecated before shipping outside of google, so removed */ #define KDF_SCRYPT_KEYMASTER 5 #define KEY_LEN_BYTES 16 #define DEFAULT_PASSWORD "default_password" #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 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_old() { 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; } /* Create a new keymaster key and store it in this footer */ static int keymaster_create_key_old(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"); 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; } /* This signs the given object using the keymaster key. */ static int keymaster_sign_object_old(struct crypt_mnt_ftr *ftr, const unsigned char *object, const size_t object_size, unsigned char **signature, size_t *signature_size) { int rc = 0; keymaster0_device_t *keymaster0_dev = 0; keymaster1_device_t *keymaster1_dev = 0; unsigned char to_sign[RSA_KEY_SIZE_BYTES]; size_t to_sign_size = sizeof(to_sign); memset(to_sign, 0, RSA_KEY_SIZE_BYTES); if (keymaster_init(&keymaster0_dev, &keymaster1_dev)) { SLOGE("Failed to init keymaster"); rc = -1; goto out; } // To sign a message with RSA, the message must satisfy two // constraints: // // 1. The message, when interpreted as a big-endian numeric value, must // be strictly less than the public modulus of the RSA key. Note // that because the most significant bit of the public modulus is // guaranteed to be 1 (else it's an (n-1)-bit key, not an n-bit // key), an n-bit message with most significant bit 0 always // satisfies this requirement. // // 2. The message must have the same length in bits as the public // modulus of the RSA key. This requirement isn't mathematically // necessary, but is necessary to ensure consistency in // implementations. switch (ftr->kdf_type) { case KDF_SCRYPT_KEYMASTER: // This ensures the most significant byte of the signed message // 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 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); rc = -1; goto out; } 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; } /* Should we use keymaster? */ static int keymaster_check_compatibility_new() { return keymaster_compatibility_cryptfs_scrypt(); } #if 0 /* Create a new keymaster key and store it in this footer */ static int keymaster_create_key_new(struct crypt_mnt_ftr *ftr) { if (ftr->keymaster_blob_size) { SLOGI("Already have key"); return 0; } 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; } return 0; } #endif /* This signs the given object using the keymaster key. */ static int keymaster_sign_object_new(struct crypt_mnt_ftr *ftr, const unsigned char *object, const size_t object_size, unsigned char **signature, size_t *signature_size) { unsigned char to_sign[RSA_KEY_SIZE_BYTES]; size_t to_sign_size = sizeof(to_sign); memset(to_sign, 0, RSA_KEY_SIZE_BYTES); // To sign a message with RSA, the message must satisfy two // constraints: // // 1. The message, when interpreted as a big-endian numeric value, must // be strictly less than the public modulus of the RSA key. Note // that because the most significant bit of the public modulus is // guaranteed to be 1 (else it's an (n-1)-bit key, not an n-bit // key), an n-bit message with most significant bit 0 always // satisfies this requirement. // // 2. The message must have the same length in bits as the public // modulus of the RSA key. This requirement isn't mathematically // necessary, but is necessary to ensure consistency in // implementations. switch (ftr->kdf_type) { case KDF_SCRYPT_KEYMASTER: // This ensures the most significant byte of the signed message // 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 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; } if (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) != KeymasterSignResult::ok) return -1; return 0; } namespace android { class CryptFsTest : public testing::Test { protected: virtual void SetUp() { } virtual void TearDown() { } }; TEST_F(CryptFsTest, ScryptHidlizationEquivalenceTest) { crypt_mnt_ftr ftr; ftr.kdf_type = KDF_SCRYPT_KEYMASTER; ftr.keymaster_blob_size = 0; ASSERT_EQ(0, keymaster_create_key_old(&ftr)); uint8_t *sig1 = nullptr; uint8_t *sig2 = nullptr; size_t sig_size1 = 123456789; size_t sig_size2 = 123456789; uint8_t object[] = "the object"; ASSERT_EQ(1, keymaster_check_compatibility_old()); ASSERT_EQ(1, keymaster_check_compatibility_new()); ASSERT_EQ(0, keymaster_sign_object_old(&ftr, object, 10, &sig1, &sig_size1)); ASSERT_EQ(0, keymaster_sign_object_new(&ftr, object, 10, &sig2, &sig_size2)); ASSERT_EQ(sig_size1, sig_size2); ASSERT_NE(nullptr, sig1); ASSERT_NE(nullptr, sig2); EXPECT_EQ(0, memcmp(sig1, sig2, sig_size1)); free(sig1); free(sig2); } }