Merge "Allow entropy to be provided to some operations"
diff --git a/keystore/IKeystoreService.cpp b/keystore/IKeystoreService.cpp
index 3a23059..7be3a97 100644
--- a/keystore/IKeystoreService.cpp
+++ b/keystore/IKeystoreService.cpp
@@ -999,13 +999,15 @@
};
virtual int32_t generateKey(const String16& name, const KeymasterArguments& params,
- int uid, int flags, KeyCharacteristics* outCharacteristics)
+ const uint8_t* entropy, size_t entropyLength, int uid, int flags,
+ KeyCharacteristics* outCharacteristics)
{
Parcel data, reply;
data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
data.writeString16(name);
data.writeInt32(1);
params.writeToParcel(&data);
+ data.writeByteArray(entropyLength, entropy);
data.writeInt32(uid);
data.writeInt32(flags);
status_t status = remote()->transact(BnKeystoreService::GENERATE_KEY, data, &reply);
@@ -1131,7 +1133,8 @@
virtual void begin(const sp<IBinder>& appToken, const String16& name,
keymaster_purpose_t purpose, bool pruneable,
- const KeymasterArguments& params, KeymasterArguments* outParams,
+ const KeymasterArguments& params, const uint8_t* entropy,
+ size_t entropyLength, KeymasterArguments* outParams,
OperationResult* result)
{
if (!result || !outParams) {
@@ -1145,6 +1148,7 @@
data.writeInt32(pruneable ? 1 : 0);
data.writeInt32(1);
params.writeToParcel(&data);
+ data.writeByteArray(entropyLength, entropy);
status_t status = remote()->transact(BnKeystoreService::BEGIN, data, &reply);
if (status != NO_ERROR) {
ALOGD("begin() could not contact remote: %d\n", status);
@@ -1584,10 +1588,14 @@
if (data.readInt32() != 0) {
args.readFromParcel(data);
}
+ const uint8_t* entropy = NULL;
+ size_t entropyLength = 0;
+ readByteArray(data, &entropy, &entropyLength);
int32_t uid = data.readInt32();
int32_t flags = data.readInt32();
KeyCharacteristics outCharacteristics;
- int32_t ret = generateKey(name, args, uid, flags, &outCharacteristics);
+ int32_t ret = generateKey(name, args, entropy, entropyLength, uid, flags,
+ &outCharacteristics);
reply->writeNoException();
reply->writeInt32(ret);
reply->writeInt32(1);
@@ -1655,9 +1663,13 @@
if (data.readInt32() != 0) {
args.readFromParcel(data);
}
+ const uint8_t* entropy = NULL;
+ size_t entropyLength = 0;
+ readByteArray(data, &entropy, &entropyLength);
KeymasterArguments outArgs;
OperationResult result;
- begin(token, name, purpose, pruneable, args, &outArgs, &result);
+ begin(token, name, purpose, pruneable, args, entropy, entropyLength, &outArgs,
+ &result);
reply->writeNoException();
reply->writeInt32(1);
result.writeToParcel(reply);
diff --git a/keystore/include/keystore/IKeystoreService.h b/keystore/include/keystore/IKeystoreService.h
index f7f1295..6cae3cb 100644
--- a/keystore/include/keystore/IKeystoreService.h
+++ b/keystore/include/keystore/IKeystoreService.h
@@ -197,11 +197,14 @@
virtual int32_t addRngEntropy(const uint8_t* data, size_t dataLength) = 0;
virtual int32_t generateKey(const String16& name, const KeymasterArguments& params,
- int uid, int flags, KeyCharacteristics* outCharacteristics) = 0;
+ const uint8_t* entropy, size_t entropyLength, int uid, int flags,
+ KeyCharacteristics* outCharacteristics) = 0;
+
virtual int32_t getKeyCharacteristics(const String16& name,
const keymaster_blob_t* clientId,
const keymaster_blob_t* appData,
KeyCharacteristics* outCharacteristics) = 0;
+
virtual int32_t importKey(const String16& name, const KeymasterArguments& params,
keymaster_key_format_t format, const uint8_t *keyData,
size_t keyLength, int uid, int flags,
@@ -213,7 +216,8 @@
virtual void begin(const sp<IBinder>& apptoken, const String16& name,
keymaster_purpose_t purpose, bool pruneable,
- const KeymasterArguments& params, KeymasterArguments* outParams,
+ const KeymasterArguments& params, const uint8_t* entropy,
+ size_t entropyLength, KeymasterArguments* outParams,
OperationResult* result) = 0;
virtual void update(const sp<IBinder>& token, const KeymasterArguments& params,
diff --git a/keystore/keystore.cpp b/keystore/keystore.cpp
index a949ffb..8523db6 100644
--- a/keystore/keystore.cpp
+++ b/keystore/keystore.cpp
@@ -2469,7 +2469,8 @@
}
int32_t generateKey(const String16& name, const KeymasterArguments& params,
- int uid, int flags, KeyCharacteristics* outCharacteristics) {
+ const uint8_t* entropy, size_t entropyLength, int uid, int flags,
+ KeyCharacteristics* outCharacteristics) {
uid_t callingUid = IPCThreadState::self()->getCallingUid();
pid_t callingPid = IPCThreadState::self()->getCallingPid();
if (!has_permission(callingUid, P_INSERT, callingPid)) {
@@ -2499,19 +2500,37 @@
if (device == NULL) {
return ::SYSTEM_ERROR;
}
- // TODO: Seed from Linux RNG either before this or periodically
+ // TODO: Seed from Linux RNG before this.
if (device->common.module->module_api_version >= KEYMASTER_MODULE_API_VERSION_1_0 &&
device->generate_key != NULL) {
- rc = device->generate_key(device, params.params.data(), params.params.size(), &blob,
- &out);
+ if (!entropy) {
+ rc = KM_ERROR_OK;
+ } else if (device->add_rng_entropy) {
+ rc = device->add_rng_entropy(device, entropy, entropyLength);
+ } else {
+ rc = KM_ERROR_UNIMPLEMENTED;
+ }
+ if (rc == KM_ERROR_OK) {
+ rc = device->generate_key(device, params.params.data(), params.params.size(),
+ &blob, &out);
+ }
}
// If the HW device didn't support generate_key or generate_key failed
// fall back to the software implementation.
if (rc && fallback->generate_key != NULL) {
isFallback = true;
- rc = fallback->generate_key(fallback, params.params.data(), params.params.size(),
- &blob,
- &out);
+ if (!entropy) {
+ rc = KM_ERROR_OK;
+ } else if (fallback->add_rng_entropy) {
+ rc = fallback->add_rng_entropy(fallback, entropy, entropyLength);
+ } else {
+ rc = KM_ERROR_UNIMPLEMENTED;
+ }
+ if (rc == KM_ERROR_OK) {
+ rc = fallback->generate_key(fallback, params.params.data(), params.params.size(),
+ &blob,
+ &out);
+ }
}
if (out) {
@@ -2676,8 +2695,8 @@
}
void begin(const sp<IBinder>& appToken, const String16& name, keymaster_purpose_t purpose,
- bool pruneable, const KeymasterArguments& params,
- KeymasterArguments* outParams, OperationResult* result) {
+ bool pruneable, const KeymasterArguments& params, const uint8_t* entropy,
+ size_t entropyLength, KeymasterArguments* outParams, OperationResult* result) {
if (!result || !outParams) {
ALOGE("Unexpected null arguments to begin()");
return;
@@ -2703,10 +2722,22 @@
size_t outSize;
keymaster_operation_handle_t handle;
keymaster1_device_t* dev = mKeyStore->getDeviceForBlob(keyBlob);
+ keymaster_error_t err = KM_ERROR_UNIMPLEMENTED;
+ // Add entropy to the device first.
+ if (entropy) {
+ if (dev->add_rng_entropy) {
+ err = dev->add_rng_entropy(dev, entropy, entropyLength);
+ } else {
+ err = KM_ERROR_UNIMPLEMENTED;
+ }
+ if (err) {
+ result->resultCode = err;
+ return;
+ }
+ }
// TODO: Check authorization.
- keymaster_error_t err = dev->begin(dev, purpose, &key, params.params.data(),
- params.params.size(), &out, &outSize,
- &handle);
+ err = dev->begin(dev, purpose, &key, params.params.data(), params.params.size(), &out,
+ &outSize, &handle);
// If there are too many operations abort the oldest operation that was
// started as pruneable and try again.