Add Keymaster 1.0 binder methods
Add all the serialization required for the new keystore binder API to
support keymaster 1.0. The keystore methods themselves are left as
stubs, will be filled in in later commits.
Change-Id: Ibb5855dba879ae35c375c087c54d1bcdca53163f
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) {