You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
478 lines
16 KiB
478 lines
16 KiB
/* |
|
** |
|
** 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(); |
|
} |
|
|
|
/* 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; |
|
} |
|
|
|
/* 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); |
|
} |
|
|
|
}
|
|
|