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
This commit is contained in:
parent
d8c0a7e426
commit
015ec30b36
3 changed files with 187 additions and 262 deletions
132
Keymaster.cpp
132
Keymaster.cpp
|
@ -31,7 +31,8 @@ KeymasterOperation::~KeymasterOperation() {
|
|||
}
|
||||
|
||||
bool KeymasterOperation::updateCompletely(const std::string& input, std::string* output) {
|
||||
output->clear();
|
||||
if (output)
|
||||
output->clear();
|
||||
auto it = input.begin();
|
||||
uint32_t inputConsumed;
|
||||
|
||||
|
@ -55,7 +56,7 @@ bool KeymasterOperation::updateCompletely(const std::string& input, std::string*
|
|||
return false;
|
||||
}
|
||||
if (km_error != ErrorCode::OK) {
|
||||
LOG(ERROR) << "update failed, code " << uint32_t(km_error);
|
||||
LOG(ERROR) << "update failed, code " << int32_t(km_error);
|
||||
mDevice = nullptr;
|
||||
return false;
|
||||
}
|
||||
|
@ -86,7 +87,7 @@ bool KeymasterOperation::finish(std::string* output) {
|
|||
return false;
|
||||
}
|
||||
if (km_error != ErrorCode::OK) {
|
||||
LOG(ERROR) << "finish failed, code " << uint32_t(km_error);
|
||||
LOG(ERROR) << "finish failed, code " << int32_t(km_error);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
@ -177,11 +178,134 @@ KeymasterOperation Keymaster::begin(KeyPurpose purpose, const std::string& key,
|
|||
return KeymasterOperation(ErrorCode::UNKNOWN_ERROR);
|
||||
}
|
||||
if (km_error != ErrorCode::OK) {
|
||||
LOG(ERROR) << "begin failed, code " << uint32_t(km_error);
|
||||
LOG(ERROR) << "begin failed, code " << int32_t(km_error);
|
||||
return KeymasterOperation(km_error);
|
||||
}
|
||||
return KeymasterOperation(mDevice, mOpHandle);
|
||||
}
|
||||
bool Keymaster::isSecure() {
|
||||
bool _isSecure = false;
|
||||
auto rc = mDevice->getHardwareFeatures(
|
||||
[&] (bool isSecure, bool, bool, bool) { _isSecure = isSecure; });
|
||||
return rc.isOk() && _isSecure;
|
||||
}
|
||||
|
||||
} // namespace vold
|
||||
} // namespace android
|
||||
|
||||
using namespace ::android::vold;
|
||||
|
||||
int keymaster_compatibility_cryptfs_scrypt() {
|
||||
return Keymaster().isSecure();
|
||||
}
|
||||
|
||||
int keymaster_create_key_for_cryptfs_scrypt(uint32_t rsa_key_size,
|
||||
uint64_t rsa_exponent,
|
||||
uint32_t ratelimit,
|
||||
uint8_t* key_buffer,
|
||||
uint32_t key_buffer_size,
|
||||
uint32_t* key_out_size)
|
||||
{
|
||||
Keymaster dev;
|
||||
std::string key;
|
||||
if (!dev) {
|
||||
LOG(ERROR) << "Failed to initiate keymaster session";
|
||||
return -1;
|
||||
}
|
||||
if (!key_buffer || !key_out_size) {
|
||||
LOG(ERROR) << __FILE__ << ":" << __LINE__ << ":Invalid argument";
|
||||
return -1;
|
||||
}
|
||||
if (key_out_size) {
|
||||
*key_out_size = 0;
|
||||
}
|
||||
|
||||
auto paramBuilder = AuthorizationSetBuilder()
|
||||
.Authorization(TAG_ALGORITHM, Algorithm::RSA)
|
||||
.Authorization(TAG_KEY_SIZE, rsa_key_size)
|
||||
.Authorization(TAG_RSA_PUBLIC_EXPONENT, rsa_exponent)
|
||||
.Authorization(TAG_PURPOSE, KeyPurpose::SIGN)
|
||||
.Authorization(TAG_PADDING, PaddingMode::NONE)
|
||||
.Authorization(TAG_DIGEST, Digest::NONE)
|
||||
.Authorization(TAG_BLOB_USAGE_REQUIREMENTS,
|
||||
KeyBlobUsageRequirements::STANDALONE)
|
||||
.Authorization(TAG_NO_AUTH_REQUIRED)
|
||||
.Authorization(TAG_MIN_SECONDS_BETWEEN_OPS, ratelimit);
|
||||
|
||||
if (!dev.generateKey(paramBuilder, &key)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (key_out_size) {
|
||||
*key_out_size = key.size();
|
||||
}
|
||||
|
||||
if (key_buffer_size < key.size()) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
std::copy(key.data(), key.data() + key.size(), key_buffer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int keymaster_sign_object_for_cryptfs_scrypt(const uint8_t* key_blob,
|
||||
size_t key_blob_size,
|
||||
uint32_t ratelimit,
|
||||
const uint8_t* object,
|
||||
const size_t object_size,
|
||||
uint8_t** signature_buffer,
|
||||
size_t* signature_buffer_size)
|
||||
{
|
||||
Keymaster dev;
|
||||
if (!dev) {
|
||||
LOG(ERROR) << "Failed to initiate keymaster session";
|
||||
return -1;
|
||||
}
|
||||
if (!key_blob || !object || !signature_buffer || !signature_buffer_size) {
|
||||
LOG(ERROR) << __FILE__ << ":" << __LINE__ << ":Invalid argument";
|
||||
return -1;
|
||||
}
|
||||
|
||||
AuthorizationSet outParams;
|
||||
std::string key(reinterpret_cast<const char*>(key_blob), key_blob_size);
|
||||
std::string input(reinterpret_cast<const char*>(object), object_size);
|
||||
std::string output;
|
||||
KeymasterOperation op;
|
||||
|
||||
auto paramBuilder = AuthorizationSetBuilder()
|
||||
.Authorization(TAG_PADDING, PaddingMode::NONE)
|
||||
.Authorization(TAG_DIGEST, Digest::NONE);
|
||||
|
||||
while (true) {
|
||||
op = dev.begin(KeyPurpose::SIGN, key, paramBuilder, &outParams);
|
||||
if (op.error() == ErrorCode::KEY_RATE_LIMIT_EXCEEDED) {
|
||||
sleep(ratelimit);
|
||||
continue;
|
||||
} else break;
|
||||
}
|
||||
|
||||
if (op.error() != ErrorCode::OK) {
|
||||
LOG(ERROR) << "Error starting keymaster signature transaction: " << int32_t(op.error());
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!op.updateCompletely(input, &output)) {
|
||||
LOG(ERROR) << "Error sending data to keymaster signature transaction: "
|
||||
<< uint32_t(op.error());
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!op.finish(&output)) {
|
||||
LOG(ERROR) << "Error finalizing keymaster signature transaction: " << int32_t(op.error());
|
||||
return -1;
|
||||
}
|
||||
|
||||
*signature_buffer = reinterpret_cast<uint8_t*>(malloc(output.size()));
|
||||
if (*signature_buffer == nullptr) {
|
||||
LOG(ERROR) << "Error allocation buffer for keymaster signature";
|
||||
return -1;
|
||||
}
|
||||
*signature_buffer_size = output.size();
|
||||
std::copy(output.data(), output.data() + output.size(), *signature_buffer);
|
||||
return 0;
|
||||
}
|
||||
|
|
45
Keymaster.h
45
Keymaster.h
|
@ -17,6 +17,8 @@
|
|||
#ifndef ANDROID_VOLD_KEYMASTER_H
|
||||
#define ANDROID_VOLD_KEYMASTER_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
@ -59,8 +61,17 @@ class KeymasterOperation {
|
|||
}
|
||||
// Construct an object in an error state for error returns
|
||||
KeymasterOperation()
|
||||
: mDevice{nullptr}, mOpHandle{static_cast<uint64_t>(0)},
|
||||
: mDevice{nullptr}, mOpHandle{0},
|
||||
mError {ErrorCode::UNKNOWN_ERROR} {}
|
||||
// Move Assignment
|
||||
KeymasterOperation& operator= (KeymasterOperation&& rhs) {
|
||||
mDevice = std::move(rhs.mDevice);
|
||||
mOpHandle = std::move(rhs.mOpHandle);
|
||||
mError = std::move(rhs.mError);
|
||||
rhs.mError = ErrorCode::UNKNOWN_ERROR;
|
||||
rhs.mOpHandle = 0;
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
KeymasterOperation(const sp<IKeymasterDevice>& d, uint64_t h)
|
||||
|
@ -92,6 +103,7 @@ class Keymaster {
|
|||
// Begin a new cryptographic operation, collecting output parameters if pointer is non-null
|
||||
KeymasterOperation begin(KeyPurpose purpose, const std::string& key,
|
||||
const AuthorizationSet& inParams, AuthorizationSet* outParams);
|
||||
bool isSecure();
|
||||
|
||||
private:
|
||||
sp<hardware::keymaster::V3_0::IKeymasterDevice> mDevice;
|
||||
|
@ -101,4 +113,35 @@ class Keymaster {
|
|||
} // namespace vold
|
||||
} // namespace android
|
||||
|
||||
#endif // __cplusplus
|
||||
|
||||
|
||||
/*
|
||||
* The following functions provide C bindings to keymaster services
|
||||
* needed by cryptfs scrypt. The compatibility check checks whether
|
||||
* the keymaster implementation is considered secure, i.e., TEE backed.
|
||||
* The create_key function generates an RSA key for signing.
|
||||
* The sign_object function signes an object with the given keymaster
|
||||
* key.
|
||||
*/
|
||||
__BEGIN_DECLS
|
||||
|
||||
int keymaster_compatibility_cryptfs_scrypt();
|
||||
int keymaster_create_key_for_cryptfs_scrypt(uint32_t rsa_key_size,
|
||||
uint64_t rsa_exponent,
|
||||
uint32_t ratelimit,
|
||||
uint8_t* key_buffer,
|
||||
uint32_t key_buffer_size,
|
||||
uint32_t* key_out_size);
|
||||
|
||||
int keymaster_sign_object_for_cryptfs_scrypt(const uint8_t* key_blob,
|
||||
size_t key_blob_size,
|
||||
uint32_t ratelimit,
|
||||
const uint8_t* object,
|
||||
const size_t object_size,
|
||||
uint8_t** signature_buffer,
|
||||
size_t* signature_buffer_size);
|
||||
|
||||
__END_DECLS
|
||||
|
||||
#endif
|
||||
|
|
272
cryptfs.c
272
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 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 **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 @@ static int keymaster_sign_object(struct crypt_mnt_ftr *ftr,
|
|||
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 @@ static int keymaster_sign_object(struct crypt_mnt_ftr *ftr,
|
|||
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.
|
||||
|
|
Loading…
Reference in a new issue