am ad4661a0: Merge "Add Keymaster 1.0 binder methods"
* commit 'ad4661a0be6b627735116d26a32033c959852c40':
Add Keymaster 1.0 binder methods
diff --git a/keystore/IKeystoreService.cpp b/keystore/IKeystoreService.cpp
index 53788bd..e3f7602 100644
--- a/keystore/IKeystoreService.cpp
+++ b/keystore/IKeystoreService.cpp
@@ -16,6 +16,7 @@
*/
#include <stdint.h>
+#include <sys/limits.h>
#include <sys/types.h>
#define LOG_TAG "KeystoreService"
@@ -29,6 +30,8 @@
namespace android {
+static keymaster_key_param_t* readParamList(const Parcel& in, size_t* length);
+
KeystoreArg::KeystoreArg(const void* data, size_t len)
: mData(data), mSize(len) {
}
@@ -44,6 +47,317 @@
return mSize;
}
+OperationResult::OperationResult() : resultCode(0), token(), inputConsumed(0),
+ data(NULL), dataLength(0) {
+}
+
+OperationResult::~OperationResult() {
+}
+
+void OperationResult::readFromParcel(const Parcel& in) {
+ resultCode = in.readInt32();
+ token = in.readStrongBinder();
+ inputConsumed = in.readInt32();
+ ssize_t length = in.readInt32();
+ dataLength = 0;
+ if (length > 0) {
+ const void* buf = in.readInplace(length);
+ if (buf) {
+ data.reset(reinterpret_cast<uint8_t*>(malloc(length)));
+ if (data.get()) {
+ memcpy(data.get(), buf, length);
+ dataLength = (size_t) length;
+ } else {
+ ALOGE("Failed to allocate OperationResult buffer");
+ }
+ } else {
+ ALOGE("Failed to readInplace OperationResult data");
+ }
+ }
+}
+
+void OperationResult::writeToParcel(Parcel* out) const {
+ out->writeInt32(resultCode);
+ out->writeStrongBinder(token);
+ out->writeInt32(inputConsumed);
+ out->writeInt32(dataLength);
+ if (dataLength && data) {
+ void* buf = out->writeInplace(dataLength);
+ if (buf) {
+ memcpy(buf, data.get(), dataLength);
+ } else {
+ ALOGE("Failed to writeInplace OperationResult data.");
+ }
+ }
+}
+
+ExportResult::ExportResult() : resultCode(0), exportData(NULL), dataLength(0) {
+}
+
+ExportResult::~ExportResult() {
+}
+
+void ExportResult::readFromParcel(const Parcel& in) {
+ resultCode = in.readInt32();
+ ssize_t length = in.readInt32();
+ dataLength = 0;
+ if (length > 0) {
+ const void* buf = in.readInplace(length);
+ if (buf) {
+ exportData.reset(reinterpret_cast<uint8_t*>(malloc(length)));
+ if (exportData.get()) {
+ memcpy(exportData.get(), buf, length);
+ dataLength = (size_t) length;
+ } else {
+ ALOGE("Failed to allocate ExportData buffer");
+ }
+ } else {
+ ALOGE("Failed to readInplace ExportData data");
+ }
+ }
+}
+
+void ExportResult::writeToParcel(Parcel* out) const {
+ out->writeInt32(resultCode);
+ out->writeInt32(dataLength);
+ if (exportData && dataLength) {
+ void* buf = out->writeInplace(dataLength);
+ if (buf) {
+ memcpy(buf, exportData.get(), dataLength);
+ } else {
+ ALOGE("Failed to writeInplace ExportResult data.");
+ }
+ }
+}
+
+KeymasterArguments::KeymasterArguments() {
+}
+
+KeymasterArguments::~KeymasterArguments() {
+ keymaster_free_param_values(params.data(), params.size());
+}
+
+void KeymasterArguments::readFromParcel(const Parcel& in) {
+ ssize_t length = in.readInt32();
+ size_t ulength = (size_t) length;
+ if (length < 0) {
+ ulength = 0;
+ }
+ keymaster_free_param_values(params.data(), params.size());
+ params.clear();
+ for(size_t i = 0; i < ulength; i++) {
+ keymaster_key_param_t param;
+ if (!readKeymasterArgumentFromParcel(in, ¶m)) {
+ ALOGE("Error reading keymaster argument from parcel");
+ break;
+ }
+ params.push_back(param);
+ }
+}
+
+void KeymasterArguments::writeToParcel(Parcel* out) const {
+ out->writeInt32(params.size());
+ for (auto param : params) {
+ out->writeInt32(1);
+ writeKeymasterArgumentToParcel(param, out);
+ }
+}
+
+KeyCharacteristics::KeyCharacteristics() {
+ memset((void*) &characteristics, 0, sizeof(characteristics));
+}
+
+KeyCharacteristics::~KeyCharacteristics() {
+ keymaster_free_characteristics(&characteristics);
+}
+
+void KeyCharacteristics::readFromParcel(const Parcel& in) {
+ size_t length = 0;
+ keymaster_key_param_t* params = readParamList(in, &length);
+ characteristics.sw_enforced.params = params;
+ characteristics.sw_enforced.length = length;
+
+ params = readParamList(in, &length);
+ characteristics.hw_enforced.params = params;
+ characteristics.hw_enforced.length = length;
+}
+
+void KeyCharacteristics::writeToParcel(Parcel* out) const {
+ if (characteristics.sw_enforced.params) {
+ out->writeInt32(characteristics.sw_enforced.length);
+ for (size_t i = 0; i < characteristics.sw_enforced.length; i++) {
+ out->writeInt32(1);
+ writeKeymasterArgumentToParcel(characteristics.sw_enforced.params[i], out);
+ }
+ } else {
+ out->writeInt32(0);
+ }
+ if (characteristics.hw_enforced.params) {
+ out->writeInt32(characteristics.hw_enforced.length);
+ for (size_t i = 0; i < characteristics.hw_enforced.length; i++) {
+ out->writeInt32(1);
+ writeKeymasterArgumentToParcel(characteristics.hw_enforced.params[i], out);
+ }
+ } else {
+ out->writeInt32(0);
+ }
+}
+
+void writeKeymasterArgumentToParcel(const keymaster_key_param_t& param, Parcel* out) {
+ switch (keymaster_tag_get_type(param.tag)) {
+ case KM_ENUM:
+ case KM_ENUM_REP: {
+ out->writeInt32(param.tag);
+ out->writeInt32(param.enumerated);
+ break;
+ }
+ case KM_INT:
+ case KM_INT_REP: {
+ out->writeInt32(param.tag);
+ out->writeInt32(param.integer);
+ break;
+ }
+ case KM_LONG: {
+ out->writeInt32(param.tag);
+ out->writeInt64(param.long_integer);
+ break;
+ }
+ case KM_DATE: {
+ out->writeInt32(param.tag);
+ out->writeInt64(param.date_time);
+ break;
+ }
+ case KM_BOOL: {
+ out->writeInt32(param.tag);
+ break;
+ }
+ case KM_BIGNUM:
+ case KM_BYTES: {
+ out->writeInt32(param.tag);
+ out->writeInt32(param.blob.data_length);
+ void* buf = out->writeInplace(param.blob.data_length);
+ if (buf) {
+ memcpy(buf, param.blob.data, param.blob.data_length);
+ } else {
+ ALOGE("Failed to writeInplace keymaster blob param");
+ }
+ break;
+ }
+ default: {
+ ALOGE("Failed to write argument: Unsupported keymaster_tag_t %d", param.tag);
+ }
+ }
+}
+
+
+bool readKeymasterArgumentFromParcel(const Parcel& in, keymaster_key_param_t* out) {
+ if (in.readInt32() == 0) {
+ return false;
+ }
+ keymaster_tag_t tag = static_cast<keymaster_tag_t>(in.readInt32());
+ switch (keymaster_tag_get_type(tag)) {
+ case KM_ENUM:
+ case KM_ENUM_REP: {
+ uint32_t value = in.readInt32();
+ *out = keymaster_param_enum(tag, value);
+ break;
+ }
+ case KM_INT:
+ case KM_INT_REP: {
+ uint32_t value = in.readInt32();
+ *out = keymaster_param_int(tag, value);
+ break;
+ }
+ case KM_LONG: {
+ uint64_t value = in.readInt64();
+ *out = keymaster_param_long(tag, value);
+ break;
+ }
+ case KM_DATE: {
+ uint64_t value = in.readInt64();
+ *out = keymaster_param_date(tag, value);
+ break;
+ }
+ case KM_BOOL: {
+ *out = keymaster_param_bool(tag);
+ break;
+ }
+ case KM_BIGNUM:
+ case KM_BYTES: {
+ ssize_t length = in.readInt32();
+ uint8_t* data = NULL;
+ size_t ulength = 0;
+ if (length >= 0) {
+ ulength = (size_t) length;
+ // use malloc here so we can use keymaster_free_param_values
+ // consistently.
+ data = reinterpret_cast<uint8_t*>(malloc(ulength));
+ const void* buf = in.readInplace(ulength);
+ if (!buf || !data) {
+ ALOGE("Failed to allocate buffer for keymaster blob param");
+ return false;
+ }
+ memcpy(data, buf, ulength);
+ }
+ *out = keymaster_param_blob(tag, data, ulength);
+ break;
+ }
+ default: {
+ ALOGE("Unsupported keymaster_tag_t %d", tag);
+ return false;
+ }
+ }
+ return true;
+}
+
+// Read a keymaster_key_param_t* from a Parcel for use in a
+// keymaster_key_characteristics_t. This will be free'd by calling
+// keymaster_free_key_characteristics.
+static keymaster_key_param_t* readParamList(const Parcel& in, size_t* length) {
+ ssize_t slength = in.readInt32();
+ *length = 0;
+ if (slength < 0) {
+ return NULL;
+ }
+ *length = (size_t) slength;
+ if (*length >= UINT_MAX / sizeof(keymaster_key_param_t)) {
+ return NULL;
+ }
+ keymaster_key_param_t* list =
+ reinterpret_cast<keymaster_key_param_t*>(malloc(*length *
+ sizeof(keymaster_key_param_t)));
+ if (!list) {
+ ALOGD("Failed to allocate buffer for generateKey outCharacteristics");
+ goto err;
+ }
+ for (size_t i = 0; i < *length ; i++) {
+ if (!readKeymasterArgumentFromParcel(in, &list[i])) {
+ ALOGE("Failed to read keymaster argument");
+ keymaster_free_param_values(list, i);
+ goto err;
+ }
+ }
+ return list;
+err:
+ free(list);
+ return NULL;
+}
+
+static void readKeymasterBlob(const Parcel& in, keymaster_blob_t* blob) {
+ ssize_t length = in.readInt32();
+ if (length > 0) {
+ blob->data = (uint8_t*) in.readInplace(length);
+ if (blob->data) {
+ blob->data_length = (size_t) length;
+ } else {
+ blob->data_length = 0;
+ }
+ } else {
+ blob->data = NULL;
+ blob->data_length = 0;
+ }
+}
+
class BpKeystoreService: public BpInterface<IKeystoreService>
{
public:
@@ -639,6 +953,253 @@
}
return ret;
}
+ virtual int32_t addRngEntropy(const uint8_t* buf, size_t bufLength)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
+ data.writeInt32(bufLength);
+ data.writeByteArray(bufLength, buf);
+ status_t status = remote()->transact(BnKeystoreService::ADD_RNG_ENTROPY, data, &reply);
+ if (status != NO_ERROR) {
+ ALOGD("addRngEntropy() could not contact remote: %d\n", status);
+ return -1;
+ }
+ int32_t err = reply.readExceptionCode();
+ int32_t ret = reply.readInt32();
+ if (err < 0) {
+ ALOGD("addRngEntropy() caught exception %d\n", err);
+ return -1;
+ }
+ return ret;
+ };
+
+ virtual int32_t generateKey(const String16& name, const KeymasterArguments& params,
+ int uid, int flags, KeyCharacteristics* outCharacteristics)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
+ data.writeString16(name);
+ data.writeInt32(1);
+ params.writeToParcel(&data);
+ data.writeInt32(uid);
+ data.writeInt32(flags);
+ status_t status = remote()->transact(BnKeystoreService::GENERATE_KEY, data, &reply);
+ if (status != NO_ERROR) {
+ ALOGD("generateKey() could not contact remote: %d\n", status);
+ return KM_ERROR_UNKNOWN_ERROR;
+ }
+ int32_t err = reply.readExceptionCode();
+ int32_t ret = reply.readInt32();
+ if (err < 0) {
+ ALOGD("generateKey() caught exception %d\n", err);
+ return KM_ERROR_UNKNOWN_ERROR;
+ }
+ if (reply.readInt32() != 0 && outCharacteristics) {
+ outCharacteristics->readFromParcel(reply);
+ }
+ return ret;
+ }
+ virtual int32_t getKeyCharacteristics(const String16& name,
+ const keymaster_blob_t& clientId,
+ const keymaster_blob_t& appData,
+ KeyCharacteristics* outCharacteristics)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
+ data.writeString16(name);
+ data.writeByteArray(clientId.data_length, clientId.data);
+ data.writeByteArray(appData.data_length, appData.data);
+ status_t status = remote()->transact(BnKeystoreService::GET_KEY_CHARACTERISTICS,
+ data, &reply);
+ if (status != NO_ERROR) {
+ ALOGD("getKeyCharacteristics() could not contact remote: %d\n", status);
+ return KM_ERROR_UNKNOWN_ERROR;
+ }
+ int32_t err = reply.readExceptionCode();
+ int32_t ret = reply.readInt32();
+ if (err < 0) {
+ ALOGD("getKeyCharacteristics() caught exception %d\n", err);
+ return KM_ERROR_UNKNOWN_ERROR;
+ }
+ if (reply.readInt32() != 0 && outCharacteristics) {
+ outCharacteristics->readFromParcel(reply);
+ }
+ return ret;
+ }
+ 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,
+ KeyCharacteristics* outCharacteristics)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
+ data.writeString16(name);
+ data.writeInt32(1);
+ params.writeToParcel(&data);
+ data.writeInt32(format);
+ data.writeByteArray(keyLength, keyData);
+ data.writeInt32(uid);
+ data.writeInt32(flags);
+ status_t status = remote()->transact(BnKeystoreService::IMPORT_KEY, data, &reply);
+ if (status != NO_ERROR) {
+ ALOGD("importKey() could not contact remote: %d\n", status);
+ return KM_ERROR_UNKNOWN_ERROR;
+ }
+ int32_t err = reply.readExceptionCode();
+ int32_t ret = reply.readInt32();
+ if (err < 0) {
+ ALOGD("importKey() caught exception %d\n", err);
+ return KM_ERROR_UNKNOWN_ERROR;
+ }
+ if (reply.readInt32() != 0 && outCharacteristics) {
+ outCharacteristics->readFromParcel(reply);
+ }
+ return ret;
+ }
+
+ virtual void exportKey(const String16& name, keymaster_key_format_t format,
+ const keymaster_blob_t& clientId,
+ const keymaster_blob_t& appData, ExportResult* result)
+ {
+ if (!result) {
+ return;
+ }
+
+ Parcel data, reply;
+ data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
+ data.writeString16(name);
+ data.writeInt32(format);
+ data.writeByteArray(clientId.data_length, clientId.data);
+ data.writeByteArray(appData.data_length, appData.data);
+ status_t status = remote()->transact(BnKeystoreService::EXPORT_KEY, data, &reply);
+ if (status != NO_ERROR) {
+ ALOGD("exportKey() could not contact remote: %d\n", status);
+ result->resultCode = KM_ERROR_UNKNOWN_ERROR;
+ return;
+ }
+ int32_t err = reply.readExceptionCode();
+ if (err < 0) {
+ ALOGD("exportKey() caught exception %d\n", err);
+ result->resultCode = KM_ERROR_UNKNOWN_ERROR;
+ return;
+ }
+ if (reply.readInt32() != 0) {
+ result->readFromParcel(reply);
+ }
+ }
+
+ virtual void begin(const sp<IBinder>& appToken, const String16& name,
+ keymaster_purpose_t purpose, bool pruneable,
+ const KeymasterArguments& params, KeymasterArguments* outParams,
+ OperationResult* result)
+ {
+ if (!result || !outParams) {
+ return;
+ }
+ Parcel data, reply;
+ data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
+ data.writeStrongBinder(appToken);
+ data.writeString16(name);
+ data.writeInt32(purpose);
+ data.writeInt32(pruneable ? 1 : 0);
+ data.writeInt32(1);
+ params.writeToParcel(&data);
+ status_t status = remote()->transact(BnKeystoreService::BEGIN, data, &reply);
+ if (status != NO_ERROR) {
+ ALOGD("begin() could not contact remote: %d\n", status);
+ result->resultCode = KM_ERROR_UNKNOWN_ERROR;
+ return;
+ }
+ int32_t err = reply.readExceptionCode();
+ if (err < 0) {
+ ALOGD("begin() caught exception %d\n", err);
+ result->resultCode = KM_ERROR_UNKNOWN_ERROR;
+ return;
+ }
+ if (reply.readInt32() != 0) {
+ result->readFromParcel(reply);
+ }
+ if (reply.readInt32() != 0) {
+ outParams->readFromParcel(reply);
+ }
+ }
+
+ virtual void update(const sp<IBinder>& token, const KeymasterArguments& params,
+ uint8_t* opData, size_t dataLength, OperationResult* result)
+ {
+ if (!result) {
+ return;
+ }
+ Parcel data, reply;
+ data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
+ data.writeStrongBinder(token);
+ data.writeInt32(1);
+ params.writeToParcel(&data);
+ data.writeByteArray(dataLength, opData);
+ status_t status = remote()->transact(BnKeystoreService::UPDATE, data, &reply);
+ if (status != NO_ERROR) {
+ ALOGD("update() could not contact remote: %d\n", status);
+ result->resultCode = KM_ERROR_UNKNOWN_ERROR;
+ return;
+ }
+ int32_t err = reply.readExceptionCode();
+ if (err < 0) {
+ ALOGD("update() caught exception %d\n", err);
+ result->resultCode = KM_ERROR_UNKNOWN_ERROR;
+ return;
+ }
+ if (reply.readInt32() != 0) {
+ result->readFromParcel(reply);
+ }
+ }
+
+ virtual void finish(const sp<IBinder>& token, const KeymasterArguments& params,
+ uint8_t* signature, size_t signatureLength, OperationResult* result)
+ {
+ if (!result) {
+ return;
+ }
+ Parcel data, reply;
+ data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
+ data.writeStrongBinder(token);
+ data.writeInt32(1);
+ params.writeToParcel(&data);
+ data.writeByteArray(signatureLength, signature);
+ status_t status = remote()->transact(BnKeystoreService::FINISH, data, &reply);
+ if (status != NO_ERROR) {
+ ALOGD("finish() could not contact remote: %d\n", status);
+ result->resultCode = KM_ERROR_UNKNOWN_ERROR;
+ return;
+ }
+ int32_t err = reply.readExceptionCode();
+ if (err < 0) {
+ ALOGD("finish() caught exception %d\n", err);
+ result->resultCode = KM_ERROR_UNKNOWN_ERROR;
+ return;
+ }
+ if (reply.readInt32() != 0) {
+ result->readFromParcel(reply);
+ }
+ }
+
+ virtual int32_t abort(const sp<IBinder>& token)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
+ data.writeStrongBinder(token);
+ status_t status = remote()->transact(BnKeystoreService::FINISH, data, &reply);
+ if (status != NO_ERROR) {
+ ALOGD("abort() could not contact remote: %d\n", status);
+ return KM_ERROR_UNKNOWN_ERROR;
+ }
+ int32_t err = reply.readExceptionCode();
+ int32_t ret = reply.readInt32();
+ if (err < 0) {
+ ALOGD("abort() caught exception %d\n", err);
+ return KM_ERROR_UNKNOWN_ERROR;
+ }
+ return ret;
+ }
};
IMPLEMENT_META_INTERFACE(KeystoreService, "android.security.IKeystoreService");
@@ -965,6 +1526,170 @@
reply->writeInt32(ret);
return NO_ERROR;
}
+ case ADD_RNG_ENTROPY: {
+ CHECK_INTERFACE(IKeystoreService, data, reply);
+ size_t size = data.readInt32();
+ uint8_t* bytes;
+ if (size > 0) {
+ bytes = (uint8_t*) data.readInplace(size);
+ } else {
+ bytes = NULL;
+ }
+ int32_t ret = addRngEntropy(bytes, size);
+ reply->writeNoException();
+ reply->writeInt32(ret);
+ return NO_ERROR;
+ }
+ case GENERATE_KEY: {
+ CHECK_INTERFACE(IKeystoreService, data, reply);
+ String16 name = data.readString16();
+ KeymasterArguments args;
+ if (data.readInt32() != 0) {
+ args.readFromParcel(data);
+ }
+ int32_t uid = data.readInt32();
+ int32_t flags = data.readInt32();
+ KeyCharacteristics outCharacteristics;
+ int32_t ret = generateKey(name, args, uid, flags, &outCharacteristics);
+ reply->writeNoException();
+ reply->writeInt32(ret);
+ reply->writeInt32(1);
+ outCharacteristics.writeToParcel(reply);
+ return NO_ERROR;
+ }
+ case GET_KEY_CHARACTERISTICS: {
+ CHECK_INTERFACE(IKeystoreService, data, reply);
+ String16 name = data.readString16();
+ keymaster_blob_t clientId, appData;
+ readKeymasterBlob(data, &clientId);
+ readKeymasterBlob(data, &appData);
+ KeyCharacteristics outCharacteristics;
+ int ret = getKeyCharacteristics(name, clientId, appData, &outCharacteristics);
+ reply->writeNoException();
+ reply->writeInt32(ret);
+ reply->writeInt32(1);
+ outCharacteristics.writeToParcel(reply);
+ return NO_ERROR;
+ }
+ case IMPORT_KEY: {
+ CHECK_INTERFACE(IKeystoreService, data, reply);
+ String16 name = data.readString16();
+ KeymasterArguments args;
+ if (data.readInt32() != 0) {
+ args.readFromParcel(data);
+ }
+ keymaster_key_format_t format = static_cast<keymaster_key_format_t>(data.readInt32());
+ uint8_t* keyData = NULL;
+ ssize_t keyLength = data.readInt32();
+ size_t ukeyLength = (size_t) keyLength;
+ if (keyLength >= 0) {
+ keyData = (uint8_t*) data.readInplace(keyLength);
+ } else {
+ ukeyLength = 0;
+ }
+ int32_t uid = data.readInt32();
+ int32_t flags = data.readInt32();
+ KeyCharacteristics outCharacteristics;
+ int32_t ret = importKey(name, args, format, keyData, ukeyLength, uid, flags,
+ &outCharacteristics);
+ reply->writeNoException();
+ reply->writeInt32(ret);
+ reply->writeInt32(1);
+ outCharacteristics.writeToParcel(reply);
+
+ return NO_ERROR;
+ }
+ case EXPORT_KEY: {
+ CHECK_INTERFACE(IKeystoreService, data, reply);
+ String16 name = data.readString16();
+ keymaster_key_format_t format = static_cast<keymaster_key_format_t>(data.readInt32());
+ keymaster_blob_t clientId, appData;
+ readKeymasterBlob(data, &clientId);
+ readKeymasterBlob(data, &appData);
+ ExportResult result;
+ exportKey(name, format, clientId, appData, &result);
+ reply->writeNoException();
+ reply->writeInt32(1);
+ result.writeToParcel(reply);
+
+ return NO_ERROR;
+ }
+ case BEGIN: {
+ CHECK_INTERFACE(IKeystoreService, data, reply);
+ sp<IBinder> token = data.readStrongBinder();
+ String16 name = data.readString16();
+ keymaster_purpose_t purpose = static_cast<keymaster_purpose_t>(data.readInt32());
+ bool pruneable = data.readInt32() != 0;
+ KeymasterArguments args;
+ if (data.readInt32() != 0) {
+ args.readFromParcel(data);
+ }
+ KeymasterArguments outArgs;
+ OperationResult result;
+ begin(token, name, purpose, pruneable, args, &outArgs, &result);
+ reply->writeNoException();
+ reply->writeInt32(1);
+ result.writeToParcel(reply);
+ reply->writeInt32(1);
+ outArgs.writeToParcel(reply);
+
+ return NO_ERROR;
+ }
+ case UPDATE: {
+ CHECK_INTERFACE(IKeystoreService, data, reply);
+ sp<IBinder> token = data.readStrongBinder();
+ KeymasterArguments args;
+ if (data.readInt32() != 0) {
+ args.readFromParcel(data);
+ }
+ uint8_t* buf = NULL;
+ ssize_t bufLength = data.readInt32();
+ size_t ubufLength = (size_t) bufLength;
+ if (bufLength > 0) {
+ buf = (uint8_t*) data.readInplace(ubufLength);
+ } else {
+ ubufLength = 0;
+ }
+ OperationResult result;
+ update(token, args, buf, ubufLength, &result);
+ reply->writeNoException();
+ reply->writeInt32(1);
+ result.writeToParcel(reply);
+
+ return NO_ERROR;
+ }
+ case FINISH: {
+ CHECK_INTERFACE(IKeystoreService, data, reply);
+ sp<IBinder> token = data.readStrongBinder();
+ KeymasterArguments args;
+ if (data.readInt32() != 0) {
+ args.readFromParcel(data);
+ }
+ uint8_t* buf = NULL;
+ ssize_t bufLength = data.readInt32();
+ size_t ubufLength = (size_t) bufLength;
+ if (bufLength > 0) {
+ buf = (uint8_t*) data.readInplace(ubufLength);
+ } else {
+ ubufLength = 0;
+ }
+ OperationResult result;
+ finish(token, args, buf, ubufLength, &result);
+ reply->writeNoException();
+ reply->writeInt32(1);
+ result.writeToParcel(reply);
+
+ return NO_ERROR;
+ }
+ case ABORT: {
+ CHECK_INTERFACE(IKeystoreService, data, reply);
+ sp<IBinder> token = data.readStrongBinder();
+ int32_t result = abort(token);
+ reply->writeNoException();
+ reply->writeInt32(result);
+
+ return NO_ERROR;
+ }
default:
return BBinder::onTransact(code, data, reply, flags);
}
diff --git a/keystore/include/keystore/IKeystoreService.h b/keystore/include/keystore/IKeystoreService.h
index afdff8d..f69b76e 100644
--- a/keystore/include/keystore/IKeystoreService.h
+++ b/keystore/include/keystore/IKeystoreService.h
@@ -17,9 +17,11 @@
#ifndef KEYSTORE_IKEYSTORESERVICE_H
#define KEYSTORE_IKEYSTORESERVICE_H
+#include <hardware/keymaster_defs.h>
#include <utils/RefBase.h>
#include <binder/IInterface.h>
#include <binder/Parcel.h>
+#include <vector>
namespace android {
@@ -36,6 +38,59 @@
size_t mSize;
};
+struct MallocDeleter {
+ void operator()(uint8_t* p) { free(p); }
+};
+
+// struct for serializing the results of begin/update/finish
+struct OperationResult {
+ OperationResult();
+ ~OperationResult();
+ void readFromParcel(const Parcel& in);
+ void writeToParcel(Parcel* out) const;
+
+ int resultCode;
+ sp<IBinder> token;
+ int inputConsumed;
+ std::unique_ptr<uint8_t[], MallocDeleter> data;
+ size_t dataLength;
+};
+
+// struct for serializing the results of export
+struct ExportResult {
+ ExportResult();
+ ~ExportResult();
+ void readFromParcel(const Parcel& in);
+ void writeToParcel(Parcel* out) const;
+
+ int resultCode;
+ std::unique_ptr<uint8_t[], MallocDeleter> exportData;
+ size_t dataLength;
+};
+
+// struct for serializing/deserializing a list of keymaster_key_param_t's
+struct KeymasterArguments {
+ KeymasterArguments();
+ ~KeymasterArguments();
+ void readFromParcel(const Parcel& in);
+ void writeToParcel(Parcel* out) const;
+
+ std::vector<keymaster_key_param_t> params;
+};
+
+// struct for serializing keymaster_key_characteristics_t's
+struct KeyCharacteristics {
+ KeyCharacteristics();
+ ~KeyCharacteristics();
+ void readFromParcel(const Parcel& in);
+ void writeToParcel(Parcel* out) const;
+
+ keymaster_key_characteristics_t characteristics;
+};
+
+bool readKeymasterArgumentFromParcel(const Parcel& in, keymaster_key_param_t* out);
+void writeKeymasterArgumentToParcel(const keymaster_key_param_t& param, Parcel* out);
+
/*
* This must be kept manually in sync with frameworks/base's IKeystoreService.java
*/
@@ -68,6 +123,15 @@
RESET_UID = IBinder::FIRST_CALL_TRANSACTION + 23,
SYNC_UID = IBinder::FIRST_CALL_TRANSACTION + 24,
PASSWORD_UID = IBinder::FIRST_CALL_TRANSACTION + 25,
+ ADD_RNG_ENTROPY = IBinder::FIRST_CALL_TRANSACTION + 26,
+ GENERATE_KEY = IBinder::FIRST_CALL_TRANSACTION + 27,
+ GET_KEY_CHARACTERISTICS = IBinder::FIRST_CALL_TRANSACTION + 28,
+ IMPORT_KEY = IBinder::FIRST_CALL_TRANSACTION + 29,
+ EXPORT_KEY = IBinder::FIRST_CALL_TRANSACTION + 30,
+ BEGIN = IBinder::FIRST_CALL_TRANSACTION + 31,
+ UPDATE = IBinder::FIRST_CALL_TRANSACTION + 32,
+ FINISH = IBinder::FIRST_CALL_TRANSACTION + 33,
+ ABORT = IBinder::FIRST_CALL_TRANSACTION + 34,
};
DECLARE_META_INTERFACE(KeystoreService);
@@ -129,6 +193,37 @@
virtual int32_t sync_uid(int32_t sourceUid, int32_t targetUid) = 0;
virtual int32_t password_uid(const String16& password, int32_t uid) = 0;
+
+ 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;
+ 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,
+ KeyCharacteristics* outCharacteristics) = 0;
+
+ virtual void exportKey(const String16& name, keymaster_key_format_t format,
+ const keymaster_blob_t& clientId,
+ const keymaster_blob_t& appData, ExportResult* result) = 0;
+
+ virtual void begin(const sp<IBinder>& apptoken, const String16& name,
+ keymaster_purpose_t purpose, bool pruneable,
+ const KeymasterArguments& params, KeymasterArguments* outParams,
+ OperationResult* result) = 0;
+
+ virtual void update(const sp<IBinder>& token, const KeymasterArguments& params,
+ uint8_t* data, size_t dataLength, OperationResult* result) = 0;
+
+ virtual void finish(const sp<IBinder>& token, const KeymasterArguments& params,
+ uint8_t* signature, size_t signatureLength, OperationResult* result) = 0;
+
+ virtual int32_t abort(const sp<IBinder>& handle) = 0;
+
};
// ----------------------------------------------------------------------------
diff --git a/keystore/keystore.cpp b/keystore/keystore.cpp
index 194b87c..cf799f1 100644
--- a/keystore/keystore.cpp
+++ b/keystore/keystore.cpp
@@ -2433,6 +2433,56 @@
return ::SYSTEM_ERROR;
}
+ int32_t addRngEntropy(const uint8_t* /*data*/, size_t /*dataLength*/) {
+ return KM_ERROR_UNIMPLEMENTED;
+ }
+
+ int32_t generateKey(const String16& /*name*/, const KeymasterArguments& /*params*/,
+ int /*uid*/, int /*flags*/, KeyCharacteristics* /*outCharacteristics*/) {
+ return KM_ERROR_UNIMPLEMENTED;
+ }
+
+ int32_t getKeyCharacteristics(const String16& /*name*/,
+ const keymaster_blob_t& /*clientId*/,
+ const keymaster_blob_t& /*appData*/,
+ KeyCharacteristics* /*outCharacteristics*/) {
+ return KM_ERROR_UNIMPLEMENTED;
+ }
+
+ 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*/,
+ KeyCharacteristics* /*outCharacteristics*/) {
+ return KM_ERROR_UNIMPLEMENTED;
+ }
+
+ void exportKey(const String16& /*name*/, keymaster_key_format_t /*format*/,
+ const keymaster_blob_t& /*clientId*/,
+ const keymaster_blob_t& /*appData*/, ExportResult* result) {
+ result->resultCode = KM_ERROR_UNIMPLEMENTED;
+ }
+
+ void begin(const sp<IBinder>& /*appToken*/, const String16& /*name*/,
+ keymaster_purpose_t /*purpose*/, bool /*pruneable*/,
+ const KeymasterArguments& /*params*/, KeymasterArguments* /*outParams*/,
+ OperationResult* result) {
+ result->resultCode = KM_ERROR_UNIMPLEMENTED;
+ }
+
+ void update(const sp<IBinder>& /*token*/, const KeymasterArguments& /*params*/,
+ uint8_t* /*data*/, size_t /*dataLength*/, OperationResult* result) {
+ result->resultCode = KM_ERROR_UNIMPLEMENTED;
+ }
+
+ void finish(const sp<IBinder>& /*token*/, const KeymasterArguments& /*args*/,
+ uint8_t* /*signature*/, size_t /*signatureLength*/, OperationResult* result) {
+ result->resultCode = KM_ERROR_UNIMPLEMENTED;
+ }
+
+ int32_t abort(const sp<IBinder>& /*token*/) {
+ return KM_ERROR_UNIMPLEMENTED;
+ }
+
private:
inline bool isKeystoreUnlocked(State state) {
switch (state) {