/* ** ** Copyright 2008, 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. */ #include <stdint.h> #include <sys/limits.h> #include <sys/types.h> #define LOG_TAG "KeystoreService" #include <utils/Log.h> #include <binder/Parcel.h> #include <binder/IPCThreadState.h> #include <binder/IServiceManager.h> #include <keystore/IKeystoreService.h> namespace android { const ssize_t MAX_GENERATE_ARGS = 3; static keymaster_key_param_t* readParamList(const Parcel& in, size_t* length); KeystoreArg::KeystoreArg(const void* data, size_t len) : mData(data), mSize(len) { } KeystoreArg::~KeystoreArg() { } const void *KeystoreArg::data() const { return mData; } size_t KeystoreArg::size() const { return mSize; } OperationResult::OperationResult() : resultCode(0), token(), handle(0), inputConsumed(0), data(NULL), dataLength(0) { } OperationResult::~OperationResult() { } void OperationResult::readFromParcel(const Parcel& in) { resultCode = in.readInt32(); token = in.readStrongBinder(); handle = static_cast<keymaster_operation_handle_t>(in.readInt64()); 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"); } } outParams.readFromParcel(in); } void OperationResult::writeToParcel(Parcel* out) const { out->writeInt32(resultCode); out->writeStrongBinder(token); out->writeInt64(handle); 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."); } } outParams.writeToParcel(out); } 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); } } KeymasterCertificateChain::KeymasterCertificateChain() { memset(&chain, 0, sizeof(chain)); } KeymasterCertificateChain::~KeymasterCertificateChain() { keymaster_free_cert_chain(&chain); } static bool readKeymasterBlob(const Parcel& in, keymaster_blob_t* blob) { if (in.readInt32() != 1) { return false; } ssize_t length = in.readInt32(); if (length <= 0) { return false; } blob->data = reinterpret_cast<const uint8_t*>(malloc(length)); if (!blob->data) return false; const void* buf = in.readInplace(length); if (!buf) return false; blob->data_length = static_cast<size_t>(length); memcpy(const_cast<uint8_t*>(blob->data), buf, length); return true; } void KeymasterCertificateChain::readFromParcel(const Parcel& in) { keymaster_free_cert_chain(&chain); ssize_t count = in.readInt32(); size_t ucount = count; if (count <= 0) { return; } chain.entries = reinterpret_cast<keymaster_blob_t*>(malloc(sizeof(keymaster_blob_t) * ucount)); if (!chain.entries) { ALOGE("Error allocating memory for certificate chain"); return; } memset(chain.entries, 0, sizeof(keymaster_blob_t) * ucount); for (size_t i = 0; i < ucount; ++i) { if (!readKeymasterBlob(in, &chain.entries[i])) { ALOGE("Error reading certificate from parcel"); keymaster_free_cert_chain(&chain); return; } } } void KeymasterCertificateChain::writeToParcel(Parcel* out) const { out->writeInt32(chain.entry_count); for (size_t i = 0; i < chain.entry_count; ++i) { if (chain.entries[i].data) { out->writeInt32(chain.entries[i].data_length); void* buf = out->writeInplace(chain.entries[i].data_length); if (buf) { memcpy(buf, chain.entries[i].data, chain.entries[i].data_length); } else { ALOGE("Failed to writeInplace keymaster cert chain entry"); } } else { out->writeInt32(0); // Tell Java side this object is NULL. ALOGE("Found NULL certificate chain entry"); } } } 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_UINT: case KM_UINT_REP: { out->writeInt32(param.tag); out->writeInt32(param.integer); break; } case KM_ULONG: case KM_ULONG_REP: { 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_UINT: case KM_UINT_REP: { uint32_t value = in.readInt32(); *out = keymaster_param_int(tag, value); break; } case KM_ULONG: case KM_ULONG_REP: { 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"); free(data); 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 byte array from in. The data at *data is still owned by the parcel */ static void readByteArray(const Parcel& in, const uint8_t** data, size_t* length) { ssize_t slength = in.readInt32(); if (slength > 0) { *data = reinterpret_cast<const uint8_t*>(in.readInplace(slength)); if (*data) { *length = static_cast<size_t>(slength); } else { *length = 0; } } else { *data = NULL; *length = 0; } } // 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 std::unique_ptr<keymaster_blob_t> readKeymasterBlob(const Parcel& in) { std::unique_ptr<keymaster_blob_t> blob (new keymaster_blob_t); if (!readKeymasterBlob(in, blob.get())) { blob.reset(); } return blob; } class BpKeystoreService: public BpInterface<IKeystoreService> { public: BpKeystoreService(const sp<IBinder>& impl) : BpInterface<IKeystoreService>(impl) { } // test ping virtual int32_t getState(int32_t userId) { Parcel data, reply; data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor()); data.writeInt32(userId); status_t status = remote()->transact(BnKeystoreService::GET_STATE, data, &reply); if (status != NO_ERROR) { ALOGD("getState() could not contact remote: %d\n", status); return -1; } int32_t err = reply.readExceptionCode(); int32_t ret = reply.readInt32(); if (err < 0) { ALOGD("getState() caught exception %d\n", err); return -1; } return ret; } virtual int32_t get(const String16& name, int32_t uid, uint8_t** item, size_t* itemLength) { Parcel data, reply; data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor()); data.writeString16(name); data.writeInt32(uid); status_t status = remote()->transact(BnKeystoreService::GET, data, &reply); if (status != NO_ERROR) { ALOGD("get() could not contact remote: %d\n", status); return -1; } int32_t err = reply.readExceptionCode(); ssize_t len = reply.readInt32(); if (len >= 0 && (size_t) len <= reply.dataAvail()) { size_t ulen = (size_t) len; const void* buf = reply.readInplace(ulen); *item = (uint8_t*) malloc(ulen); if (*item != NULL) { memcpy(*item, buf, ulen); *itemLength = ulen; } else { ALOGE("out of memory allocating output array in get"); *itemLength = 0; } } else { *itemLength = 0; } if (err < 0) { ALOGD("get() caught exception %d\n", err); return -1; } return 0; } virtual int32_t insert(const String16& name, const uint8_t* item, size_t itemLength, int uid, int32_t flags) { Parcel data, reply; data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor()); data.writeString16(name); data.writeInt32(itemLength); void* buf = data.writeInplace(itemLength); memcpy(buf, item, itemLength); data.writeInt32(uid); data.writeInt32(flags); status_t status = remote()->transact(BnKeystoreService::INSERT, data, &reply); if (status != NO_ERROR) { ALOGD("import() could not contact remote: %d\n", status); return -1; } int32_t err = reply.readExceptionCode(); int32_t ret = reply.readInt32(); if (err < 0) { ALOGD("import() caught exception %d\n", err); return -1; } return ret; } virtual int32_t del(const String16& name, int uid) { Parcel data, reply; data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor()); data.writeString16(name); data.writeInt32(uid); status_t status = remote()->transact(BnKeystoreService::DEL, data, &reply); if (status != NO_ERROR) { ALOGD("del() could not contact remote: %d\n", status); return -1; } int32_t err = reply.readExceptionCode(); int32_t ret = reply.readInt32(); if (err < 0) { ALOGD("del() caught exception %d\n", err); return -1; } return ret; } virtual int32_t exist(const String16& name, int uid) { Parcel data, reply; data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor()); data.writeString16(name); data.writeInt32(uid); status_t status = remote()->transact(BnKeystoreService::EXIST, data, &reply); if (status != NO_ERROR) { ALOGD("exist() could not contact remote: %d\n", status); return -1; } int32_t err = reply.readExceptionCode(); int32_t ret = reply.readInt32(); if (err < 0) { ALOGD("exist() caught exception %d\n", err); return -1; } return ret; } virtual int32_t list(const String16& prefix, int uid, Vector<String16>* matches) { Parcel data, reply; data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor()); data.writeString16(prefix); data.writeInt32(uid); status_t status = remote()->transact(BnKeystoreService::LIST, data, &reply); if (status != NO_ERROR) { ALOGD("list() could not contact remote: %d\n", status); return -1; } int32_t err = reply.readExceptionCode(); int32_t numMatches = reply.readInt32(); for (int32_t i = 0; i < numMatches; i++) { matches->push(reply.readString16()); } int32_t ret = reply.readInt32(); if (err < 0) { ALOGD("list() caught exception %d\n", err); return -1; } return ret; } virtual int32_t reset() { Parcel data, reply; data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor()); status_t status = remote()->transact(BnKeystoreService::RESET, data, &reply); if (status != NO_ERROR) { ALOGD("reset() could not contact remote: %d\n", status); return -1; } int32_t err = reply.readExceptionCode(); int32_t ret = reply.readInt32(); if (err < 0) { ALOGD("reset() caught exception %d\n", err); return -1; } return ret; } virtual int32_t onUserPasswordChanged(int32_t userId, const String16& password) { Parcel data, reply; data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor()); data.writeInt32(userId); data.writeString16(password); status_t status = remote()->transact(BnKeystoreService::ON_USER_PASSWORD_CHANGED, data, &reply); if (status != NO_ERROR) { ALOGD("onUserPasswordChanged() could not contact remote: %d\n", status); return -1; } int32_t err = reply.readExceptionCode(); int32_t ret = reply.readInt32(); if (err < 0) { ALOGD("onUserPasswordChanged() caught exception %d\n", err); return -1; } return ret; } virtual int32_t lock(int32_t userId) { Parcel data, reply; data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor()); data.writeInt32(userId); status_t status = remote()->transact(BnKeystoreService::LOCK, data, &reply); if (status != NO_ERROR) { ALOGD("lock() could not contact remote: %d\n", status); return -1; } int32_t err = reply.readExceptionCode(); int32_t ret = reply.readInt32(); if (err < 0) { ALOGD("lock() caught exception %d\n", err); return -1; } return ret; } virtual int32_t unlock(int32_t userId, const String16& password) { Parcel data, reply; data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor()); data.writeInt32(userId); data.writeString16(password); status_t status = remote()->transact(BnKeystoreService::UNLOCK, data, &reply); if (status != NO_ERROR) { ALOGD("unlock() could not contact remote: %d\n", status); return -1; } int32_t err = reply.readExceptionCode(); int32_t ret = reply.readInt32(); if (err < 0) { ALOGD("unlock() caught exception %d\n", err); return -1; } return ret; } virtual bool isEmpty(int32_t userId) { Parcel data, reply; data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor()); data.writeInt32(userId); status_t status = remote()->transact(BnKeystoreService::IS_EMPTY, data, &reply); if (status != NO_ERROR) { ALOGD("isEmpty() could not contact remote: %d\n", status); return false; } int32_t err = reply.readExceptionCode(); int32_t ret = reply.readInt32(); if (err < 0) { ALOGD("isEmpty() caught exception %d\n", err); return false; } return ret != 0; } virtual int32_t generate(const String16& name, int32_t uid, int32_t keyType, int32_t keySize, int32_t flags, Vector<sp<KeystoreArg> >* args) { Parcel data, reply; data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor()); data.writeString16(name); data.writeInt32(uid); data.writeInt32(keyType); data.writeInt32(keySize); data.writeInt32(flags); data.writeInt32(1); data.writeInt32(args->size()); for (Vector<sp<KeystoreArg> >::iterator it = args->begin(); it != args->end(); ++it) { sp<KeystoreArg> item = *it; size_t keyLength = item->size(); data.writeInt32(keyLength); void* buf = data.writeInplace(keyLength); memcpy(buf, item->data(), keyLength); } status_t status = remote()->transact(BnKeystoreService::GENERATE, data, &reply); if (status != NO_ERROR) { ALOGD("generate() could not contact remote: %d\n", status); return -1; } int32_t err = reply.readExceptionCode(); int32_t ret = reply.readInt32(); if (err < 0) { ALOGD("generate() caught exception %d\n", err); return -1; } return ret; } virtual int32_t import(const String16& name, const uint8_t* key, size_t keyLength, int uid, int flags) { Parcel data, reply; data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor()); data.writeString16(name); data.writeInt32(keyLength); void* buf = data.writeInplace(keyLength); memcpy(buf, key, keyLength); data.writeInt32(uid); data.writeInt32(flags); status_t status = remote()->transact(BnKeystoreService::IMPORT, data, &reply); if (status != NO_ERROR) { ALOGD("import() could not contact remote: %d\n", status); return -1; } int32_t err = reply.readExceptionCode(); int32_t ret = reply.readInt32(); if (err < 0) { ALOGD("import() caught exception %d\n", err); return -1; } return ret; } virtual int32_t sign(const String16& name, const uint8_t* in, size_t inLength, uint8_t** out, size_t* outLength) { Parcel data, reply; data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor()); data.writeString16(name); data.writeInt32(inLength); void* buf = data.writeInplace(inLength); memcpy(buf, in, inLength); status_t status = remote()->transact(BnKeystoreService::SIGN, data, &reply); if (status != NO_ERROR) { ALOGD("import() could not contact remote: %d\n", status); return -1; } int32_t err = reply.readExceptionCode(); ssize_t len = reply.readInt32(); if (len >= 0 && (size_t) len <= reply.dataAvail()) { size_t ulen = (size_t) len; const void* outBuf = reply.readInplace(ulen); *out = (uint8_t*) malloc(ulen); if (*out != NULL) { memcpy((void*) *out, outBuf, ulen); *outLength = ulen; } else { ALOGE("out of memory allocating output array in sign"); *outLength = 0; } } else { *outLength = 0; } if (err < 0) { ALOGD("import() caught exception %d\n", err); return -1; } return 0; } virtual int32_t verify(const String16& name, const uint8_t* in, size_t inLength, const uint8_t* signature, size_t signatureLength) { Parcel data, reply; void* buf; data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor()); data.writeString16(name); data.writeInt32(inLength); buf = data.writeInplace(inLength); memcpy(buf, in, inLength); data.writeInt32(signatureLength); buf = data.writeInplace(signatureLength); memcpy(buf, signature, signatureLength); status_t status = remote()->transact(BnKeystoreService::VERIFY, data, &reply); if (status != NO_ERROR) { ALOGD("verify() could not contact remote: %d\n", status); return -1; } int32_t err = reply.readExceptionCode(); int32_t ret = reply.readInt32(); if (err < 0) { ALOGD("verify() caught exception %d\n", err); return -1; } return ret; } virtual int32_t get_pubkey(const String16& name, uint8_t** pubkey, size_t* pubkeyLength) { Parcel data, reply; data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor()); data.writeString16(name); status_t status = remote()->transact(BnKeystoreService::GET_PUBKEY, data, &reply); if (status != NO_ERROR) { ALOGD("get_pubkey() could not contact remote: %d\n", status); return -1; } int32_t err = reply.readExceptionCode(); ssize_t len = reply.readInt32(); if (len >= 0 && (size_t) len <= reply.dataAvail()) { size_t ulen = (size_t) len; const void* buf = reply.readInplace(ulen); *pubkey = (uint8_t*) malloc(ulen); if (*pubkey != NULL) { memcpy(*pubkey, buf, ulen); *pubkeyLength = ulen; } else { ALOGE("out of memory allocating output array in get_pubkey"); *pubkeyLength = 0; } } else { *pubkeyLength = 0; } if (err < 0) { ALOGD("get_pubkey() caught exception %d\n", err); return -1; } return 0; } virtual int32_t grant(const String16& name, int32_t granteeUid) { Parcel data, reply; data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor()); data.writeString16(name); data.writeInt32(granteeUid); status_t status = remote()->transact(BnKeystoreService::GRANT, data, &reply); if (status != NO_ERROR) { ALOGD("grant() could not contact remote: %d\n", status); return -1; } int32_t err = reply.readExceptionCode(); int32_t ret = reply.readInt32(); if (err < 0) { ALOGD("grant() caught exception %d\n", err); return -1; } return ret; } virtual int32_t ungrant(const String16& name, int32_t granteeUid) { Parcel data, reply; data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor()); data.writeString16(name); data.writeInt32(granteeUid); status_t status = remote()->transact(BnKeystoreService::UNGRANT, data, &reply); if (status != NO_ERROR) { ALOGD("ungrant() could not contact remote: %d\n", status); return -1; } int32_t err = reply.readExceptionCode(); int32_t ret = reply.readInt32(); if (err < 0) { ALOGD("ungrant() caught exception %d\n", err); return -1; } return ret; } int64_t getmtime(const String16& name, int32_t uid) { Parcel data, reply; data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor()); data.writeString16(name); data.writeInt32(uid); status_t status = remote()->transact(BnKeystoreService::GETMTIME, data, &reply); if (status != NO_ERROR) { ALOGD("getmtime() could not contact remote: %d\n", status); return -1; } int32_t err = reply.readExceptionCode(); int64_t ret = reply.readInt64(); if (err < 0) { ALOGD("getmtime() caught exception %d\n", err); return -1; } return ret; } virtual int32_t duplicate(const String16& srcKey, int32_t srcUid, const String16& destKey, int32_t destUid) { Parcel data, reply; data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor()); data.writeString16(srcKey); data.writeInt32(srcUid); data.writeString16(destKey); data.writeInt32(destUid); status_t status = remote()->transact(BnKeystoreService::DUPLICATE, data, &reply); if (status != NO_ERROR) { ALOGD("duplicate() could not contact remote: %d\n", status); return -1; } int32_t err = reply.readExceptionCode(); int32_t ret = reply.readInt32(); if (err < 0) { ALOGD("duplicate() caught exception %d\n", err); return -1; } return ret; } virtual int32_t is_hardware_backed(const String16& keyType) { Parcel data, reply; data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor()); data.writeString16(keyType); status_t status = remote()->transact(BnKeystoreService::IS_HARDWARE_BACKED, data, &reply); if (status != NO_ERROR) { ALOGD("is_hardware_backed() could not contact remote: %d\n", status); return -1; } int32_t err = reply.readExceptionCode(); int32_t ret = reply.readInt32(); if (err < 0) { ALOGD("is_hardware_backed() caught exception %d\n", err); return -1; } return ret; } virtual int32_t clear_uid(int64_t uid) { Parcel data, reply; data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor()); data.writeInt64(uid); status_t status = remote()->transact(BnKeystoreService::CLEAR_UID, data, &reply); if (status != NO_ERROR) { ALOGD("clear_uid() could not contact remote: %d\n", status); return -1; } int32_t err = reply.readExceptionCode(); int32_t ret = reply.readInt32(); if (err < 0) { ALOGD("clear_uid() caught exception %d\n", err); return -1; } return ret; } virtual int32_t addRngEntropy(const uint8_t* buf, size_t bufLength) { Parcel data, reply; data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor()); 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, 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); 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, int32_t uid, KeyCharacteristics* outCharacteristics) { Parcel data, reply; data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor()); data.writeString16(name); if (clientId) { data.writeByteArray(clientId->data_length, clientId->data); } else { data.writeInt32(-1); } if (appData) { data.writeByteArray(appData->data_length, appData->data); } else { data.writeInt32(-1); } data.writeInt32(uid); 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, int32_t uid, ExportResult* result) { if (!result) { return; } Parcel data, reply; data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor()); data.writeString16(name); data.writeInt32(format); if (clientId) { data.writeByteArray(clientId->data_length, clientId->data); } else { data.writeInt32(-1); } if (appData) { data.writeByteArray(appData->data_length, appData->data); } else { data.writeInt32(-1); } data.writeInt32(uid); 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, const uint8_t* entropy, size_t entropyLength, int32_t uid, OperationResult* result) { if (!result) { 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); data.writeByteArray(entropyLength, entropy); data.writeInt32(uid); 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); } } virtual void update(const sp<IBinder>& token, const KeymasterArguments& params, const 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, const uint8_t* signature, size_t signatureLength, const uint8_t* entropy, size_t entropyLength, 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); data.writeByteArray(entropyLength, entropy); 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::ABORT, 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; } virtual bool isOperationAuthorized(const sp<IBinder>& token) { Parcel data, reply; data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor()); data.writeStrongBinder(token); status_t status = remote()->transact(BnKeystoreService::IS_OPERATION_AUTHORIZED, data, &reply); if (status != NO_ERROR) { ALOGD("isOperationAuthorized() could not contact remote: %d\n", status); return false; } int32_t err = reply.readExceptionCode(); int32_t ret = reply.readInt32(); if (err < 0) { ALOGD("isOperationAuthorized() caught exception %d\n", err); return false; } return ret == 1; } virtual int32_t addAuthToken(const uint8_t* token, size_t length) { Parcel data, reply; data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor()); data.writeByteArray(length, token); status_t status = remote()->transact(BnKeystoreService::ADD_AUTH_TOKEN, data, &reply); if (status != NO_ERROR) { ALOGD("addAuthToken() could not contact remote: %d\n", status); return -1; } int32_t err = reply.readExceptionCode(); int32_t ret = reply.readInt32(); if (err < 0) { ALOGD("addAuthToken() caught exception %d\n", err); return -1; } return ret; }; virtual int32_t onUserAdded(int32_t userId, int32_t parentId) { Parcel data, reply; data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor()); data.writeInt32(userId); data.writeInt32(parentId); status_t status = remote()->transact(BnKeystoreService::ON_USER_ADDED, data, &reply); if (status != NO_ERROR) { ALOGD("onUserAdded() could not contact remote: %d\n", status); return -1; } int32_t err = reply.readExceptionCode(); int32_t ret = reply.readInt32(); if (err < 0) { ALOGD("onUserAdded() caught exception %d\n", err); return -1; } return ret; } virtual int32_t onUserRemoved(int32_t userId) { Parcel data, reply; data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor()); data.writeInt32(userId); status_t status = remote()->transact(BnKeystoreService::ON_USER_REMOVED, data, &reply); if (status != NO_ERROR) { ALOGD("onUserRemoved() could not contact remote: %d\n", status); return -1; } int32_t err = reply.readExceptionCode(); int32_t ret = reply.readInt32(); if (err < 0) { ALOGD("onUserRemoved() caught exception %d\n", err); return -1; } return ret; } virtual int32_t attestKey(const String16& name, const KeymasterArguments& params, KeymasterCertificateChain* outChain) { if (!outChain) return KM_ERROR_OUTPUT_PARAMETER_NULL; Parcel data, reply; data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor()); data.writeString16(name); data.writeInt32(1); // params is not NULL. params.writeToParcel(&data); status_t status = remote()->transact(BnKeystoreService::ATTEST_KEY, data, &reply); if (status != NO_ERROR) { ALOGD("attestkey() count 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("attestKey() caught exception %d\n", err); return KM_ERROR_UNKNOWN_ERROR; } if (reply.readInt32() != 0) { outChain->readFromParcel(reply); } return ret; } }; IMPLEMENT_META_INTERFACE(KeystoreService, "android.security.IKeystoreService"); // ---------------------------------------------------------------------- status_t BnKeystoreService::onTransact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) { switch(code) { case GET_STATE: { CHECK_INTERFACE(IKeystoreService, data, reply); int32_t userId = data.readInt32(); int32_t ret = getState(userId); reply->writeNoException(); reply->writeInt32(ret); return NO_ERROR; } break; case GET: { CHECK_INTERFACE(IKeystoreService, data, reply); String16 name = data.readString16(); int32_t uid = data.readInt32(); void* out = NULL; size_t outSize = 0; int32_t ret = get(name, uid, (uint8_t**) &out, &outSize); reply->writeNoException(); if (ret == 1) { reply->writeInt32(outSize); void* buf = reply->writeInplace(outSize); memcpy(buf, out, outSize); free(out); } else { reply->writeInt32(-1); } return NO_ERROR; } break; case INSERT: { CHECK_INTERFACE(IKeystoreService, data, reply); String16 name = data.readString16(); ssize_t inSize = data.readInt32(); const void* in; if (inSize >= 0 && (size_t) inSize <= data.dataAvail()) { in = data.readInplace(inSize); } else { in = NULL; inSize = 0; } int uid = data.readInt32(); int32_t flags = data.readInt32(); int32_t ret = insert(name, (const uint8_t*) in, (size_t) inSize, uid, flags); reply->writeNoException(); reply->writeInt32(ret); return NO_ERROR; } break; case DEL: { CHECK_INTERFACE(IKeystoreService, data, reply); String16 name = data.readString16(); int uid = data.readInt32(); int32_t ret = del(name, uid); reply->writeNoException(); reply->writeInt32(ret); return NO_ERROR; } break; case EXIST: { CHECK_INTERFACE(IKeystoreService, data, reply); String16 name = data.readString16(); int uid = data.readInt32(); int32_t ret = exist(name, uid); reply->writeNoException(); reply->writeInt32(ret); return NO_ERROR; } break; case LIST: { CHECK_INTERFACE(IKeystoreService, data, reply); String16 prefix = data.readString16(); int uid = data.readInt32(); Vector<String16> matches; int32_t ret = list(prefix, uid, &matches); reply->writeNoException(); reply->writeInt32(matches.size()); Vector<String16>::const_iterator it = matches.begin(); for (; it != matches.end(); ++it) { reply->writeString16(*it); } reply->writeInt32(ret); return NO_ERROR; } break; case RESET: { CHECK_INTERFACE(IKeystoreService, data, reply); int32_t ret = reset(); reply->writeNoException(); reply->writeInt32(ret); return NO_ERROR; } break; case ON_USER_PASSWORD_CHANGED: { CHECK_INTERFACE(IKeystoreService, data, reply); int32_t userId = data.readInt32(); String16 pass = data.readString16(); int32_t ret = onUserPasswordChanged(userId, pass); reply->writeNoException(); reply->writeInt32(ret); return NO_ERROR; } break; case LOCK: { CHECK_INTERFACE(IKeystoreService, data, reply); int32_t userId = data.readInt32(); int32_t ret = lock(userId); reply->writeNoException(); reply->writeInt32(ret); return NO_ERROR; } break; case UNLOCK: { CHECK_INTERFACE(IKeystoreService, data, reply); int32_t userId = data.readInt32(); String16 pass = data.readString16(); int32_t ret = unlock(userId, pass); reply->writeNoException(); reply->writeInt32(ret); return NO_ERROR; } break; case IS_EMPTY: { CHECK_INTERFACE(IKeystoreService, data, reply); int32_t userId = data.readInt32(); bool ret = isEmpty(userId); reply->writeNoException(); reply->writeInt32(ret ? 1 : 0); return NO_ERROR; } break; case GENERATE: { CHECK_INTERFACE(IKeystoreService, data, reply); String16 name = data.readString16(); int32_t uid = data.readInt32(); int32_t keyType = data.readInt32(); int32_t keySize = data.readInt32(); int32_t flags = data.readInt32(); Vector<sp<KeystoreArg> > args; int32_t argsPresent = data.readInt32(); if (argsPresent == 1) { ssize_t numArgs = data.readInt32(); if (numArgs > MAX_GENERATE_ARGS) { return BAD_VALUE; } if (numArgs > 0) { for (size_t i = 0; i < (size_t) numArgs; i++) { ssize_t inSize = data.readInt32(); if (inSize >= 0 && (size_t) inSize <= data.dataAvail()) { sp<KeystoreArg> arg = new KeystoreArg(data.readInplace(inSize), inSize); args.push_back(arg); } else { args.push_back(NULL); } } } } int32_t ret = generate(name, uid, keyType, keySize, flags, &args); reply->writeNoException(); reply->writeInt32(ret); return NO_ERROR; } break; case IMPORT: { CHECK_INTERFACE(IKeystoreService, data, reply); String16 name = data.readString16(); ssize_t inSize = data.readInt32(); const void* in; if (inSize >= 0 && (size_t) inSize <= data.dataAvail()) { in = data.readInplace(inSize); } else { in = NULL; inSize = 0; } int uid = data.readInt32(); int32_t flags = data.readInt32(); int32_t ret = import(name, (const uint8_t*) in, (size_t) inSize, uid, flags); reply->writeNoException(); reply->writeInt32(ret); return NO_ERROR; } break; case SIGN: { CHECK_INTERFACE(IKeystoreService, data, reply); String16 name = data.readString16(); ssize_t inSize = data.readInt32(); const void* in; if (inSize >= 0 && (size_t) inSize <= data.dataAvail()) { in = data.readInplace(inSize); } else { in = NULL; inSize = 0; } void* out = NULL; size_t outSize = 0; int32_t ret = sign(name, (const uint8_t*) in, (size_t) inSize, (uint8_t**) &out, &outSize); reply->writeNoException(); if (outSize > 0 && out != NULL) { reply->writeInt32(outSize); void* buf = reply->writeInplace(outSize); memcpy(buf, out, outSize); delete[] reinterpret_cast<uint8_t*>(out); } else { reply->writeInt32(-1); } reply->writeInt32(ret); return NO_ERROR; } break; case VERIFY: { CHECK_INTERFACE(IKeystoreService, data, reply); String16 name = data.readString16(); ssize_t inSize = data.readInt32(); const void* in; if (inSize >= 0 && (size_t) inSize <= data.dataAvail()) { in = data.readInplace(inSize); } else { in = NULL; inSize = 0; } ssize_t sigSize = data.readInt32(); const void* sig; if (sigSize >= 0 && (size_t) sigSize <= data.dataAvail()) { sig = data.readInplace(sigSize); } else { sig = NULL; sigSize = 0; } bool ret = verify(name, (const uint8_t*) in, (size_t) inSize, (const uint8_t*) sig, (size_t) sigSize); reply->writeNoException(); reply->writeInt32(ret ? 1 : 0); return NO_ERROR; } break; case GET_PUBKEY: { CHECK_INTERFACE(IKeystoreService, data, reply); String16 name = data.readString16(); void* out = NULL; size_t outSize = 0; int32_t ret = get_pubkey(name, (unsigned char**) &out, &outSize); reply->writeNoException(); if (outSize > 0 && out != NULL) { reply->writeInt32(outSize); void* buf = reply->writeInplace(outSize); memcpy(buf, out, outSize); free(out); } else { reply->writeInt32(-1); } reply->writeInt32(ret); return NO_ERROR; } break; case GRANT: { CHECK_INTERFACE(IKeystoreService, data, reply); String16 name = data.readString16(); int32_t granteeUid = data.readInt32(); int32_t ret = grant(name, granteeUid); reply->writeNoException(); reply->writeInt32(ret); return NO_ERROR; } break; case UNGRANT: { CHECK_INTERFACE(IKeystoreService, data, reply); String16 name = data.readString16(); int32_t granteeUid = data.readInt32(); int32_t ret = ungrant(name, granteeUid); reply->writeNoException(); reply->writeInt32(ret); return NO_ERROR; } break; case GETMTIME: { CHECK_INTERFACE(IKeystoreService, data, reply); String16 name = data.readString16(); int32_t uid = data.readInt32(); int64_t ret = getmtime(name, uid); reply->writeNoException(); reply->writeInt64(ret); return NO_ERROR; } break; case DUPLICATE: { CHECK_INTERFACE(IKeystoreService, data, reply); String16 srcKey = data.readString16(); int32_t srcUid = data.readInt32(); String16 destKey = data.readString16(); int32_t destUid = data.readInt32(); int32_t ret = duplicate(srcKey, srcUid, destKey, destUid); reply->writeNoException(); reply->writeInt32(ret); return NO_ERROR; } break; case IS_HARDWARE_BACKED: { CHECK_INTERFACE(IKeystoreService, data, reply); String16 keyType = data.readString16(); int32_t ret = is_hardware_backed(keyType); reply->writeNoException(); reply->writeInt32(ret); return NO_ERROR; } case CLEAR_UID: { CHECK_INTERFACE(IKeystoreService, data, reply); int64_t uid = data.readInt64(); int32_t ret = clear_uid(uid); reply->writeNoException(); reply->writeInt32(ret); return NO_ERROR; } case ADD_RNG_ENTROPY: { CHECK_INTERFACE(IKeystoreService, data, reply); const uint8_t* bytes = NULL; size_t size = 0; readByteArray(data, &bytes, &size); 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); } 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, entropy, entropyLength, 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(); std::unique_ptr<keymaster_blob_t> clientId = readKeymasterBlob(data); std::unique_ptr<keymaster_blob_t> appData = readKeymasterBlob(data); int32_t uid = data.readInt32(); KeyCharacteristics outCharacteristics; int ret = getKeyCharacteristics(name, clientId.get(), appData.get(), uid, &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()); const uint8_t* keyData = NULL; size_t keyLength = 0; readByteArray(data, &keyData, &keyLength); int32_t uid = data.readInt32(); int32_t flags = data.readInt32(); KeyCharacteristics outCharacteristics; int32_t ret = importKey(name, args, format, keyData, keyLength, 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()); std::unique_ptr<keymaster_blob_t> clientId = readKeymasterBlob(data); std::unique_ptr<keymaster_blob_t> appData = readKeymasterBlob(data); int32_t uid = data.readInt32(); ExportResult result; exportKey(name, format, clientId.get(), appData.get(), uid, &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); } const uint8_t* entropy = NULL; size_t entropyLength = 0; readByteArray(data, &entropy, &entropyLength); int32_t uid = data.readInt32(); OperationResult result; begin(token, name, purpose, pruneable, args, entropy, entropyLength, uid, &result); reply->writeNoException(); reply->writeInt32(1); result.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); } const uint8_t* buf = NULL; size_t bufLength = 0; readByteArray(data, &buf, &bufLength); OperationResult result; update(token, args, buf, bufLength, &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); } const uint8_t* signature = NULL; size_t signatureLength = 0; readByteArray(data, &signature, &signatureLength); const uint8_t* entropy = NULL; size_t entropyLength = 0; readByteArray(data, &entropy, &entropyLength); OperationResult result; finish(token, args, signature, signatureLength, entropy, entropyLength, &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; } case IS_OPERATION_AUTHORIZED: { CHECK_INTERFACE(IKeystoreService, data, reply); sp<IBinder> token = data.readStrongBinder(); bool result = isOperationAuthorized(token); reply->writeNoException(); reply->writeInt32(result ? 1 : 0); return NO_ERROR; } case ADD_AUTH_TOKEN: { CHECK_INTERFACE(IKeystoreService, data, reply); const uint8_t* token_bytes = NULL; size_t size = 0; readByteArray(data, &token_bytes, &size); int32_t result = addAuthToken(token_bytes, size); reply->writeNoException(); reply->writeInt32(result); return NO_ERROR; } case ON_USER_ADDED: { CHECK_INTERFACE(IKeystoreService, data, reply); int32_t userId = data.readInt32(); int32_t parentId = data.readInt32(); int32_t result = onUserAdded(userId, parentId); reply->writeNoException(); reply->writeInt32(result); return NO_ERROR; } case ON_USER_REMOVED: { CHECK_INTERFACE(IKeystoreService, data, reply); int32_t userId = data.readInt32(); int32_t result = onUserRemoved(userId); reply->writeNoException(); reply->writeInt32(result); return NO_ERROR; } case ATTEST_KEY: { CHECK_INTERFACE(IKeystoreService, data, reply); String16 name = data.readString16(); KeymasterArguments params; if (data.readInt32() != 0) { params.readFromParcel(data); } KeymasterCertificateChain chain; int ret = attestKey(name, params, &chain); reply->writeNoException(); reply->writeInt32(ret); reply->writeInt32(1); chain.writeToParcel(reply); return NO_ERROR; } default: return BBinder::onTransact(code, data, reply, flags); } } // ---------------------------------------------------------------------------- }; // namespace android