| /* | 
 | ** | 
 | ** 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> | 
 |  | 
 | #include <algorithm> | 
 | #include <limits> | 
 |  | 
 | #define LOG_TAG "KeystoreService" | 
 | #include <utils/Log.h> | 
 |  | 
 | #include <binder/IPCThreadState.h> | 
 | #include <binder/IServiceManager.h> | 
 | #include <binder/Parcel.h> | 
 |  | 
 | #include <keystore/IKeystoreService.h> | 
 | #include <keystore/keystore_hidl_support.h> | 
 |  | 
 | #include "keystore_aidl_hidl_marshalling_utils.h" | 
 |  | 
 | namespace android { | 
 | using namespace ::keystore; | 
 |  | 
 | const ssize_t MAX_GENERATE_ARGS = 3; | 
 |  | 
 | 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(), token(), handle(0), inputConsumed(0), data() {} | 
 |  | 
 | OperationResult::~OperationResult() {} | 
 |  | 
 | status_t OperationResult::readFromParcel(const Parcel* inn) { | 
 |     const Parcel& in = *inn; | 
 |     resultCode = ErrorCode(in.readInt32()); | 
 |     token = in.readStrongBinder(); | 
 |     handle = static_cast<uint64_t>(in.readInt64()); | 
 |     inputConsumed = in.readInt32(); | 
 |     data = readKeymasterBlob(in); | 
 |     outParams = readParamSetFromParcel(in); | 
 |     return OK; | 
 | } | 
 |  | 
 | status_t OperationResult::writeToParcel(Parcel* out) const { | 
 |     out->writeInt32(resultCode); | 
 |     out->writeStrongBinder(token); | 
 |     out->writeInt64(handle); | 
 |     out->writeInt32(inputConsumed); | 
 |     writeKeymasterBlob(data, out); | 
 |     writeParamSetToParcel(outParams, out); | 
 |     return OK; | 
 | } | 
 |  | 
 | ExportResult::ExportResult() : resultCode() {} | 
 |  | 
 | ExportResult::~ExportResult() {} | 
 |  | 
 | status_t ExportResult::readFromParcel(const Parcel* inn) { | 
 |     const Parcel& in = *inn; | 
 |     resultCode = ErrorCode(in.readInt32()); | 
 |     exportData = readKeymasterBlob(in); | 
 |     return OK; | 
 | } | 
 |  | 
 | status_t ExportResult::writeToParcel(Parcel* out) const { | 
 |     out->writeInt32(resultCode); | 
 |     writeKeymasterBlob(exportData, out); | 
 |     return OK; | 
 | } | 
 |  | 
 | /** | 
 |  * 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; | 
 |     } | 
 | } | 
 |  | 
 | class BpKeystoreService : public BpInterface<IKeystoreService> { | 
 |   public: | 
 |     explicit BpKeystoreService(const sp<IBinder>& impl) : BpInterface<IKeystoreService>(impl) {} | 
 |  | 
 |     // test ping | 
 |     KeyStoreServiceReturnCode getState(int32_t userId) override { | 
 |         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 ResponseCode::SYSTEM_ERROR; | 
 |         } | 
 |         int32_t err = reply.readExceptionCode(); | 
 |         ResponseCode ret = ResponseCode(reply.readInt32()); | 
 |         if (err < 0) { | 
 |             ALOGD("getState() caught exception %d\n", err); | 
 |             return ResponseCode::SYSTEM_ERROR; | 
 |         } | 
 |         return ret; | 
 |     } | 
 |  | 
 |     KeyStoreServiceReturnCode get(const String16& name, int32_t uid, | 
 |                                   hidl_vec<uint8_t>* item) override { | 
 |         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 ResponseCode::SYSTEM_ERROR; | 
 |         } | 
 |         int32_t err = reply.readExceptionCode(); | 
 |         if (err < 0) { | 
 |             ALOGD("get() caught exception %d\n", err); | 
 |             return ResponseCode::SYSTEM_ERROR; | 
 |         } | 
 |         auto resultItem = readBlobAsByteArray(reply); | 
 |         if (item) *item = resultItem.value(); | 
 |         return ResponseCode(reply.readInt32()); | 
 |     } | 
 |  | 
 |     KeyStoreServiceReturnCode insert(const String16& name, const hidl_vec<uint8_t>& item, int uid, | 
 |                                      int32_t flags) override { | 
 |         Parcel data, reply; | 
 |         data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor()); | 
 |         data.writeString16(name); | 
 |         writeBlobAsByteArray(item, &data); | 
 |         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 ResponseCode::SYSTEM_ERROR; | 
 |         } | 
 |         int32_t err = reply.readExceptionCode(); | 
 |         if (err < 0) { | 
 |             ALOGD("import() caught exception %d\n", err); | 
 |             return ResponseCode::SYSTEM_ERROR; | 
 |         } | 
 |         return ResponseCode(reply.readInt32()); | 
 |     } | 
 |  | 
 |     KeyStoreServiceReturnCode del(const String16& name, int uid) override { | 
 |         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 ResponseCode::SYSTEM_ERROR; | 
 |         } | 
 |         int32_t err = reply.readExceptionCode(); | 
 |         if (err < 0) { | 
 |             ALOGD("del() caught exception %d\n", err); | 
 |             return ResponseCode::SYSTEM_ERROR; | 
 |         } | 
 |         return ResponseCode(reply.readInt32()); | 
 |     } | 
 |  | 
 |     KeyStoreServiceReturnCode exist(const String16& name, int uid) override { | 
 |         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 ResponseCode::SYSTEM_ERROR; | 
 |         } | 
 |         int32_t err = reply.readExceptionCode(); | 
 |         if (err < 0) { | 
 |             ALOGD("exist() caught exception %d\n", err); | 
 |             return ResponseCode::SYSTEM_ERROR; | 
 |         } | 
 |         return ResponseCode(reply.readInt32()); | 
 |     } | 
 |  | 
 |     KeyStoreServiceReturnCode list(const String16& prefix, int uid, | 
 |                                    Vector<String16>* matches) override { | 
 |         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 ResponseCode::SYSTEM_ERROR; | 
 |         } | 
 |         int32_t err = reply.readExceptionCode(); | 
 |         int32_t numMatches = reply.readInt32(); | 
 |         for (int32_t i = 0; i < numMatches; i++) { | 
 |             matches->push(reply.readString16()); | 
 |         } | 
 |         if (err < 0) { | 
 |             ALOGD("list() caught exception %d\n", err); | 
 |             return ResponseCode::SYSTEM_ERROR; | 
 |         } | 
 |         return ResponseCode(reply.readInt32()); | 
 |     } | 
 |  | 
 |     KeyStoreServiceReturnCode reset() override { | 
 |         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 ResponseCode::SYSTEM_ERROR; | 
 |         } | 
 |         int32_t err = reply.readExceptionCode(); | 
 |         if (err < 0) { | 
 |             ALOGD("reset() caught exception %d\n", err); | 
 |             return ResponseCode::SYSTEM_ERROR; | 
 |         } | 
 |         return ResponseCode(reply.readInt32()); | 
 |     } | 
 |  | 
 |     KeyStoreServiceReturnCode onUserPasswordChanged(int32_t userId, | 
 |                                                     const String16& password) override { | 
 |         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 ResponseCode::SYSTEM_ERROR; | 
 |         } | 
 |         int32_t err = reply.readExceptionCode(); | 
 |         if (err < 0) { | 
 |             ALOGD("onUserPasswordChanged() caught exception %d\n", err); | 
 |             return ResponseCode::SYSTEM_ERROR; | 
 |         } | 
 |         return ResponseCode(reply.readInt32()); | 
 |     } | 
 |  | 
 |     KeyStoreServiceReturnCode lock(int32_t userId) override { | 
 |         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 ResponseCode::SYSTEM_ERROR; | 
 |         } | 
 |         int32_t err = reply.readExceptionCode(); | 
 |         if (err < 0) { | 
 |             ALOGD("lock() caught exception %d\n", err); | 
 |             return ResponseCode::SYSTEM_ERROR; | 
 |         } | 
 |         return ResponseCode(reply.readInt32()); | 
 |     } | 
 |  | 
 |     KeyStoreServiceReturnCode unlock(int32_t userId, const String16& password) override { | 
 |         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 ResponseCode::SYSTEM_ERROR; | 
 |         } | 
 |         int32_t err = reply.readExceptionCode(); | 
 |         if (err < 0) { | 
 |             ALOGD("unlock() caught exception %d\n", err); | 
 |             return ResponseCode::SYSTEM_ERROR; | 
 |         } | 
 |         return ResponseCode(reply.readInt32()); | 
 |     } | 
 |  | 
 |     bool isEmpty(int32_t userId) override { | 
 |         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(); | 
 |         if (err < 0) { | 
 |             ALOGD("isEmpty() caught exception %d\n", err); | 
 |             return false; | 
 |         } | 
 |         return reply.readInt32() != 0; | 
 |     } | 
 |  | 
 |     KeyStoreServiceReturnCode generate(const String16& name, int32_t uid, int32_t keyType, | 
 |                                        int32_t keySize, int32_t flags, | 
 |                                        Vector<sp<KeystoreArg>>* args) override { | 
 |         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 ResponseCode::SYSTEM_ERROR; | 
 |         } | 
 |         int32_t err = reply.readExceptionCode(); | 
 |         if (err < 0) { | 
 |             ALOGD("generate() caught exception %d\n", err); | 
 |             return ResponseCode::SYSTEM_ERROR; | 
 |         } | 
 |         return ResponseCode(reply.readInt32()); | 
 |     } | 
 |  | 
 |     KeyStoreServiceReturnCode import(const String16& name, const hidl_vec<uint8_t>& key, int uid, | 
 |                                      int flags) override { | 
 |         Parcel data, reply; | 
 |         data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor()); | 
 |         data.writeString16(name); | 
 |         writeBlobAsByteArray(key, &data); | 
 |         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 ResponseCode::SYSTEM_ERROR; | 
 |         } | 
 |         int32_t err = reply.readExceptionCode(); | 
 |         if (err < 0) { | 
 |             ALOGD("import() caught exception %d\n", err); | 
 |             return ResponseCode::SYSTEM_ERROR; | 
 |         } | 
 |         return ResponseCode(reply.readInt32()); | 
 |     } | 
 |  | 
 |     KeyStoreServiceReturnCode sign(const String16& name, const hidl_vec<uint8_t>& in, | 
 |                                    hidl_vec<uint8_t>* out) override { | 
 |         Parcel data, reply; | 
 |         data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor()); | 
 |         data.writeString16(name); | 
 |         writeBlobAsByteArray(in, &data); | 
 |         status_t status = remote()->transact(BnKeystoreService::SIGN, data, &reply); | 
 |         if (status != NO_ERROR) { | 
 |             ALOGD("import() could not contact remote: %d\n", status); | 
 |             return ResponseCode::SYSTEM_ERROR; | 
 |         } | 
 |         int32_t err = reply.readExceptionCode(); | 
 |         if (err < 0) { | 
 |             ALOGD("import() caught exception %d\n", err); | 
 |             return ResponseCode::SYSTEM_ERROR; | 
 |         } | 
 |         auto outBlob = readBlobAsByteArray(reply); | 
 |         if (out) { | 
 |             // don't need to check outBlob.isOk() | 
 |             // if !outBlob.isOk() the wrapped value is default constructed and therefore empty, | 
 |             // as expected. | 
 |             *out = outBlob.value(); | 
 |         } | 
 |         return ResponseCode(reply.readInt32()); | 
 |     } | 
 |  | 
 |     KeyStoreServiceReturnCode verify(const String16& name, const hidl_vec<uint8_t>& in, | 
 |                                      const hidl_vec<uint8_t>& signature) override { | 
 |         Parcel data, reply; | 
 |  | 
 |         data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor()); | 
 |         data.writeString16(name); | 
 |         writeBlobAsByteArray(in, &data); | 
 |         writeBlobAsByteArray(signature, &data); | 
 |         status_t status = remote()->transact(BnKeystoreService::VERIFY, data, &reply); | 
 |         if (status != NO_ERROR) { | 
 |             ALOGD("verify() could not contact remote: %d\n", status); | 
 |             return ResponseCode::SYSTEM_ERROR; | 
 |         } | 
 |         int32_t err = reply.readExceptionCode(); | 
 |         if (err < 0) { | 
 |             ALOGD("verify() caught exception %d\n", err); | 
 |             return ResponseCode::SYSTEM_ERROR; | 
 |         } | 
 |         return ResponseCode(reply.readInt32()); | 
 |     } | 
 |  | 
 |     KeyStoreServiceReturnCode get_pubkey(const String16& name, hidl_vec<uint8_t>* pubkey) override { | 
 |         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 ResponseCode::SYSTEM_ERROR; | 
 |         } | 
 |         int32_t err = reply.readExceptionCode(); | 
 |         if (err < 0) { | 
 |             ALOGD("get_pubkey() caught exception %d\n", err); | 
 |             return ResponseCode::SYSTEM_ERROR; | 
 |         } | 
 |         auto resultKey = readBlobAsByteArray(reply); | 
 |         if (pubkey) *pubkey = resultKey.value(); | 
 |         return ResponseCode(reply.readInt32()); | 
 |     } | 
 |  | 
 |     KeyStoreServiceReturnCode grant(const String16& name, int32_t granteeUid) override { | 
 |         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 ResponseCode::SYSTEM_ERROR; | 
 |         } | 
 |         int32_t err = reply.readExceptionCode(); | 
 |         if (err < 0) { | 
 |             ALOGD("grant() caught exception %d\n", err); | 
 |             return ResponseCode::SYSTEM_ERROR; | 
 |         } | 
 |         return ResponseCode(reply.readInt32()); | 
 |     } | 
 |  | 
 |     KeyStoreServiceReturnCode ungrant(const String16& name, int32_t granteeUid) override { | 
 |         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 ResponseCode::SYSTEM_ERROR; | 
 |         } | 
 |         int32_t err = reply.readExceptionCode(); | 
 |         if (err < 0) { | 
 |             ALOGD("ungrant() caught exception %d\n", err); | 
 |             return ResponseCode::SYSTEM_ERROR; | 
 |         } | 
 |         return ResponseCode(reply.readInt32()); | 
 |     } | 
 |  | 
 |     int64_t getmtime(const String16& name, int32_t uid) override { | 
 |         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(); | 
 |         if (err < 0) { | 
 |             ALOGD("getmtime() caught exception %d\n", err); | 
 |             return -1; | 
 |         } | 
 |         return reply.readInt64(); | 
 |     } | 
 |  | 
 |     KeyStoreServiceReturnCode duplicate(const String16& srcKey, int32_t srcUid, | 
 |                                         const String16& destKey, int32_t destUid) override { | 
 |         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 ResponseCode::SYSTEM_ERROR; | 
 |         } | 
 |         int32_t err = reply.readExceptionCode(); | 
 |         if (err < 0) { | 
 |             ALOGD("duplicate() caught exception %d\n", err); | 
 |             return ResponseCode::SYSTEM_ERROR; | 
 |         } | 
 |         return ResponseCode(reply.readInt32()); | 
 |     } | 
 |  | 
 |     int32_t is_hardware_backed(const String16& keyType) override { | 
 |         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(); | 
 |         if (err < 0) { | 
 |             ALOGD("is_hardware_backed() caught exception %d\n", err); | 
 |             return -1; | 
 |         } | 
 |         return reply.readInt32(); | 
 |     } | 
 |  | 
 |     KeyStoreServiceReturnCode clear_uid(int64_t uid) override { | 
 |         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 ResponseCode::SYSTEM_ERROR; | 
 |         } | 
 |         int32_t err = reply.readExceptionCode(); | 
 |         if (err < 0) { | 
 |             ALOGD("clear_uid() caught exception %d\n", err); | 
 |             return ResponseCode::SYSTEM_ERROR; | 
 |         } | 
 |         return ResponseCode(reply.readInt32()); | 
 |     } | 
 |  | 
 |     KeyStoreServiceReturnCode addRngEntropy(const hidl_vec<uint8_t>& entropy) override { | 
 |         Parcel data, reply; | 
 |         data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor()); | 
 |         writeBlobAsByteArray(entropy, &data); | 
 |         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 ResponseCode::SYSTEM_ERROR; | 
 |         } | 
 |         int32_t err = reply.readExceptionCode(); | 
 |         if (err < 0) { | 
 |             ALOGD("addRngEntropy() caught exception %d\n", err); | 
 |             return ResponseCode::SYSTEM_ERROR; | 
 |         } | 
 |         return ResponseCode(reply.readInt32()); | 
 |     }; | 
 |  | 
 |     KeyStoreServiceReturnCode generateKey(const String16& name, | 
 |                                           const hidl_vec<KeyParameter>& params, | 
 |                                           const hidl_vec<uint8_t>& entropy, int uid, int flags, | 
 |                                           KeyCharacteristics* outCharacteristics) override { | 
 |         Parcel data, reply; | 
 |         data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor()); | 
 |         data.writeString16(name); | 
 |         nullable(writeParamSetToParcel, params, &data); | 
 |         writeBlobAsByteArray(entropy, &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 ResponseCode::SYSTEM_ERROR; | 
 |         } | 
 |         int32_t err = reply.readExceptionCode(); | 
 |         ResponseCode ret = ResponseCode(reply.readInt32()); | 
 |         if (err < 0) { | 
 |             ALOGD("generateKey() caught exception %d\n", err); | 
 |             return ResponseCode::SYSTEM_ERROR; | 
 |         } | 
 |         if (outCharacteristics) { | 
 |             *outCharacteristics = nullable(readKeyCharacteristicsFromParcel, reply).value(); | 
 |         } | 
 |         return ret; | 
 |     } | 
 |     KeyStoreServiceReturnCode | 
 |     getKeyCharacteristics(const String16& name, const hidl_vec<uint8_t>& clientId, | 
 |                           const hidl_vec<uint8_t>& appData, int32_t uid, | 
 |                           KeyCharacteristics* outCharacteristics) override { | 
 |         Parcel data, reply; | 
 |         data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor()); | 
 |         data.writeString16(name); | 
 |         writeBlobAsByteArray(clientId, &data); | 
 |         writeBlobAsByteArray(appData, &data); | 
 |         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 ResponseCode::SYSTEM_ERROR; | 
 |         } | 
 |         int32_t err = reply.readExceptionCode(); | 
 |         ResponseCode ret = ResponseCode(reply.readInt32()); | 
 |         if (err < 0) { | 
 |             ALOGD("getKeyCharacteristics() caught exception %d\n", err); | 
 |             return ResponseCode::SYSTEM_ERROR; | 
 |         } | 
 |         if (outCharacteristics) { | 
 |             *outCharacteristics = nullable(readKeyCharacteristicsFromParcel, reply).value(); | 
 |         } | 
 |         return ret; | 
 |     } | 
 |     KeyStoreServiceReturnCode importKey(const String16& name, const hidl_vec<KeyParameter>& params, | 
 |                                         KeyFormat format, const hidl_vec<uint8_t>& keyData, int uid, | 
 |                                         int flags, | 
 |                                         KeyCharacteristics* outCharacteristics) override { | 
 |         Parcel data, reply; | 
 |         data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor()); | 
 |         data.writeString16(name); | 
 |         nullable(writeParamSetToParcel, params, &data); | 
 |         data.writeInt32(uint32_t(format)); | 
 |         writeBlobAsByteArray(keyData, &data); | 
 |         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 ResponseCode::SYSTEM_ERROR; | 
 |         } | 
 |         int32_t err = reply.readExceptionCode(); | 
 |         ResponseCode ret = ResponseCode(reply.readInt32()); | 
 |         if (err < 0) { | 
 |             ALOGD("importKey() caught exception %d\n", err); | 
 |             return ResponseCode::SYSTEM_ERROR; | 
 |         } | 
 |         if (outCharacteristics) { | 
 |             *outCharacteristics = nullable(readKeyCharacteristicsFromParcel, reply).value(); | 
 |         } | 
 |         return ret; | 
 |     } | 
 |  | 
 |     void exportKey(const String16& name, KeyFormat format, const hidl_vec<uint8_t>& clientId, | 
 |                    const hidl_vec<uint8_t>& appData, int32_t uid, ExportResult* result) override { | 
 |         if (!result) { | 
 |             return; | 
 |         } | 
 |  | 
 |         Parcel data, reply; | 
 |         data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor()); | 
 |         data.writeString16(name); | 
 |         data.writeInt32(int32_t(format)); | 
 |         writeBlobAsByteArray(clientId, &data); | 
 |         writeBlobAsByteArray(appData, &data); | 
 |         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 = ResponseCode::SYSTEM_ERROR; | 
 |             return; | 
 |         } | 
 |         int32_t err = reply.readExceptionCode(); | 
 |         if (err < 0) { | 
 |             ALOGD("exportKey() caught exception %d\n", err); | 
 |             result->resultCode = ResponseCode::SYSTEM_ERROR; | 
 |             return; | 
 |         } | 
 |  | 
 |         reply.readParcelable(result); | 
 |     } | 
 |  | 
 |     void begin(const sp<IBinder>& appToken, const String16& name, KeyPurpose purpose, | 
 |                bool pruneable, const hidl_vec<KeyParameter>& params, | 
 |                const hidl_vec<uint8_t>& entropy, int32_t uid, OperationResult* result) override { | 
 |         if (!result) { | 
 |             return; | 
 |         } | 
 |         Parcel data, reply; | 
 |         data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor()); | 
 |         data.writeStrongBinder(appToken); | 
 |         data.writeString16(name); | 
 |         data.writeInt32(int32_t(purpose)); | 
 |         data.writeInt32(pruneable ? 1 : 0); | 
 |         nullable(writeParamSetToParcel, params, &data); | 
 |         writeBlobAsByteArray(entropy, &data); | 
 |         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 = ResponseCode::SYSTEM_ERROR; | 
 |             return; | 
 |         } | 
 |         int32_t err = reply.readExceptionCode(); | 
 |         if (err < 0) { | 
 |             ALOGD("begin() caught exception %d\n", err); | 
 |             result->resultCode = ResponseCode::SYSTEM_ERROR; | 
 |             return; | 
 |         } | 
 |  | 
 |         reply.readParcelable(result); | 
 |     } | 
 |  | 
 |     void update(const sp<IBinder>& token, const hidl_vec<KeyParameter>& params, | 
 |                 const hidl_vec<uint8_t>& opData, OperationResult* result) override { | 
 |         if (!result) { | 
 |             return; | 
 |         } | 
 |         Parcel data, reply; | 
 |         data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor()); | 
 |         data.writeStrongBinder(token); | 
 |         nullable(writeParamSetToParcel, params, &data); | 
 |         writeBlobAsByteArray(opData, &data); | 
 |         status_t status = remote()->transact(BnKeystoreService::UPDATE, data, &reply); | 
 |         if (status != NO_ERROR) { | 
 |             ALOGD("update() could not contact remote: %d\n", status); | 
 |             result->resultCode = ResponseCode::SYSTEM_ERROR; | 
 |             return; | 
 |         } | 
 |         int32_t err = reply.readExceptionCode(); | 
 |         if (err < 0) { | 
 |             ALOGD("update() caught exception %d\n", err); | 
 |             result->resultCode = ResponseCode::SYSTEM_ERROR; | 
 |             return; | 
 |         } | 
 |  | 
 |         reply.readParcelable(result); | 
 |     } | 
 |  | 
 |     void finish(const sp<IBinder>& token, const hidl_vec<KeyParameter>& params, | 
 |                 const hidl_vec<uint8_t>& signature, const hidl_vec<uint8_t>& entropy, | 
 |                 OperationResult* result) override { | 
 |         if (!result) { | 
 |             return; | 
 |         } | 
 |         Parcel data, reply; | 
 |         data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor()); | 
 |         data.writeStrongBinder(token); | 
 |         nullable(writeParamSetToParcel, params, &data); | 
 |         writeBlobAsByteArray(signature, &data); | 
 |         writeBlobAsByteArray(entropy, &data); | 
 |         status_t status = remote()->transact(BnKeystoreService::FINISH, data, &reply); | 
 |         if (status != NO_ERROR) { | 
 |             ALOGD("finish() could not contact remote: %d\n", status); | 
 |             result->resultCode = ResponseCode::SYSTEM_ERROR; | 
 |             return; | 
 |         } | 
 |         int32_t err = reply.readExceptionCode(); | 
 |         if (err < 0) { | 
 |             ALOGD("finish() caught exception %d\n", err); | 
 |             result->resultCode = ResponseCode::SYSTEM_ERROR; | 
 |             return; | 
 |         } | 
 |  | 
 |         reply.readParcelable(result); | 
 |     } | 
 |  | 
 |     KeyStoreServiceReturnCode abort(const sp<IBinder>& token) override { | 
 |         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 ResponseCode::SYSTEM_ERROR; | 
 |         } | 
 |         int32_t err = reply.readExceptionCode(); | 
 |         if (err < 0) { | 
 |             ALOGD("abort() caught exception %d\n", err); | 
 |             return ResponseCode::SYSTEM_ERROR; | 
 |         } | 
 |         return ResponseCode(reply.readInt32()); | 
 |     } | 
 |  | 
 |     bool isOperationAuthorized(const sp<IBinder>& token) override { | 
 |         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(); | 
 |         if (err < 0) { | 
 |             ALOGD("isOperationAuthorized() caught exception %d\n", err); | 
 |             return false; | 
 |         } | 
 |         return reply.readInt32() == 1; | 
 |     } | 
 |  | 
 |     KeyStoreServiceReturnCode addAuthToken(const uint8_t* token, size_t length) override { | 
 |         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 ResponseCode::SYSTEM_ERROR; | 
 |         } | 
 |         int32_t err = reply.readExceptionCode(); | 
 |         if (err < 0) { | 
 |             ALOGD("addAuthToken() caught exception %d\n", err); | 
 |             return ResponseCode::SYSTEM_ERROR; | 
 |         } | 
 |         return ResponseCode(reply.readInt32()); | 
 |     }; | 
 |  | 
 |     KeyStoreServiceReturnCode onUserAdded(int32_t userId, int32_t parentId) override { | 
 |         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 ResponseCode::SYSTEM_ERROR; | 
 |         } | 
 |         int32_t err = reply.readExceptionCode(); | 
 |         if (err < 0) { | 
 |             ALOGD("onUserAdded() caught exception %d\n", err); | 
 |             return ResponseCode::SYSTEM_ERROR; | 
 |         } | 
 |         return ResponseCode(reply.readInt32()); | 
 |     } | 
 |  | 
 |     KeyStoreServiceReturnCode onUserRemoved(int32_t userId) override { | 
 |         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 ResponseCode::SYSTEM_ERROR; | 
 |         } | 
 |         int32_t err = reply.readExceptionCode(); | 
 |         if (err < 0) { | 
 |             ALOGD("onUserRemoved() caught exception %d\n", err); | 
 |             return ResponseCode::SYSTEM_ERROR; | 
 |         } | 
 |         return ResponseCode(reply.readInt32()); | 
 |     } | 
 |  | 
 |     KeyStoreServiceReturnCode attestKey(const String16& name, const hidl_vec<KeyParameter>& params, | 
 |                                         hidl_vec<hidl_vec<uint8_t>>* outChain) override { | 
 |         if (!outChain) return ErrorCode::OUTPUT_PARAMETER_NULL; | 
 |  | 
 |         Parcel data, reply; | 
 |         data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor()); | 
 |         data.writeString16(name); | 
 |         nullable(writeParamSetToParcel, params, &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 ResponseCode::SYSTEM_ERROR; | 
 |         } | 
 |         int32_t err = reply.readExceptionCode(); | 
 |         ResponseCode ret = ResponseCode(reply.readInt32()); | 
 |         if (err < 0) { | 
 |             ALOGD("attestKey() caught exception %d\n", err); | 
 |             return ResponseCode::SYSTEM_ERROR; | 
 |         } | 
 |         if (reply.readInt32() != 0) { | 
 |             *outChain = readCertificateChainFromParcel(reply); | 
 |         } | 
 |         return ret; | 
 |     } | 
 |  | 
 |     KeyStoreServiceReturnCode onDeviceOffBody() override { | 
 |         Parcel data, reply; | 
 |         data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor()); | 
 |         status_t status = remote()->transact(BnKeystoreService::ON_DEVICE_OFF_BODY, data, &reply); | 
 |         if (status != NO_ERROR) { | 
 |             ALOGD("onDeviceOffBody() could not contact remote: %d\n", status); | 
 |             return ResponseCode::SYSTEM_ERROR; | 
 |         } | 
 |         int32_t err = reply.readExceptionCode(); | 
 |         if (err < 0) { | 
 |             ALOGD("onDeviceOffBody() caught exception %d\n", err); | 
 |             return ResponseCode::SYSTEM_ERROR; | 
 |         } | 
 |         return ResponseCode(reply.readInt32()); | 
 |     } | 
 | }; | 
 |  | 
 | 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(); | 
 |         hidl_vec<uint8_t> out; | 
 |         auto ret = get(name, uid, &out); | 
 |         reply->writeNoException(); | 
 |         if (ret.isOk()) { | 
 |             writeBlobAsByteArray(out, reply); | 
 |         } else { | 
 |             reply->writeInt32(-1); | 
 |         } | 
 |         reply->writeInt32(ret); | 
 |         return NO_ERROR; | 
 |     } break; | 
 |     case INSERT: { | 
 |         CHECK_INTERFACE(IKeystoreService, data, reply); | 
 |         String16 name = data.readString16(); | 
 |         auto in = readBlobAsByteArray(data); | 
 |         int uid = data.readInt32(); | 
 |         int32_t flags = data.readInt32(); | 
 |         int32_t ret = insert(name, in.value(), 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(); | 
 |         auto in = readBlobAsByteArray(data); | 
 |         int uid = data.readInt32(); | 
 |         int32_t flags = data.readInt32(); | 
 |         auto ret = import(name, in.value(), uid, flags); | 
 |         reply->writeNoException(); | 
 |         reply->writeInt32(ret); | 
 |         return NO_ERROR; | 
 |     } break; | 
 |     case SIGN: { | 
 |         CHECK_INTERFACE(IKeystoreService, data, reply); | 
 |         String16 name = data.readString16(); | 
 |         auto in = readBlobAsByteArray(data); | 
 |         hidl_vec<uint8_t> out; | 
 |         auto ret = sign(name, in.value(), &out); | 
 |         reply->writeNoException(); | 
 |         writeBlobAsByteArray(out, reply); | 
 |         reply->writeInt32(ret); | 
 |         return NO_ERROR; | 
 |     } break; | 
 |     case VERIFY: { | 
 |         CHECK_INTERFACE(IKeystoreService, data, reply); | 
 |         String16 name = data.readString16(); | 
 |         auto in = readBlobAsByteArray(data); | 
 |         auto signature = readBlobAsByteArray(data); | 
 |         auto ret = verify(name, in.value(), signature.value()); | 
 |         reply->writeNoException(); | 
 |         reply->writeInt32(ret); | 
 |         return NO_ERROR; | 
 |     } break; | 
 |     case GET_PUBKEY: { | 
 |         CHECK_INTERFACE(IKeystoreService, data, reply); | 
 |         String16 name = data.readString16(); | 
 |         hidl_vec<uint8_t> out; | 
 |         auto ret = get_pubkey(name, &out); | 
 |         reply->writeNoException(); | 
 |         writeBlobAsByteArray(out, reply); | 
 |         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); | 
 |         auto entropy = readBlobAsByteArray(data); | 
 |         auto ret = addRngEntropy(entropy.value()); | 
 |         reply->writeNoException(); | 
 |         reply->writeInt32(ret); | 
 |         return NO_ERROR; | 
 |     } | 
 |     case GENERATE_KEY: { | 
 |         CHECK_INTERFACE(IKeystoreService, data, reply); | 
 |         String16 name = data.readString16(); | 
 |         auto params = nullable(readParamSetFromParcel, data); | 
 |         auto entropy = readBlobAsByteArray(data); | 
 |         int32_t uid = data.readInt32(); | 
 |         int32_t flags = data.readInt32(); | 
 |         KeyCharacteristics outCharacteristics; | 
 |         int32_t ret = | 
 |             generateKey(name, params.value(), entropy.value(), uid, flags, &outCharacteristics); | 
 |         reply->writeNoException(); | 
 |         reply->writeInt32(ret); | 
 |         nullable(writeKeyCharacteristicsToParcel, outCharacteristics, reply); | 
 |         return NO_ERROR; | 
 |     } | 
 |     case GET_KEY_CHARACTERISTICS: { | 
 |         CHECK_INTERFACE(IKeystoreService, data, reply); | 
 |         String16 name = data.readString16(); | 
 |         auto clientId = nullable(readKeymasterBlob, data, true); | 
 |         auto appData = nullable(readKeymasterBlob, data, true); | 
 |         int32_t uid = data.readInt32(); | 
 |         KeyCharacteristics outCharacteristics; | 
 |         int ret = getKeyCharacteristics(name, clientId.value(), appData.value(), uid, | 
 |                                         &outCharacteristics); | 
 |         reply->writeNoException(); | 
 |         reply->writeInt32(ret); | 
 |         nullable(writeKeyCharacteristicsToParcel, outCharacteristics, reply); | 
 |         return NO_ERROR; | 
 |     } | 
 |     case IMPORT_KEY: { | 
 |         CHECK_INTERFACE(IKeystoreService, data, reply); | 
 |         String16 name = data.readString16(); | 
 |         auto args = nullable(readParamSetFromParcel, data); | 
 |         KeyFormat format = static_cast<KeyFormat>(data.readInt32()); | 
 |         auto keyData = readBlobAsByteArray(data); | 
 |         int32_t uid = data.readInt32(); | 
 |         int32_t flags = data.readInt32(); | 
 |         KeyCharacteristics outCharacteristics; | 
 |         int32_t ret = | 
 |             importKey(name, args.value(), format, keyData.value(), uid, flags, &outCharacteristics); | 
 |         reply->writeNoException(); | 
 |         reply->writeInt32(ret); | 
 |         nullable(writeKeyCharacteristicsToParcel, outCharacteristics, reply); | 
 |         return NO_ERROR; | 
 |     } | 
 |     case EXPORT_KEY: { | 
 |         CHECK_INTERFACE(IKeystoreService, data, reply); | 
 |         String16 name = data.readString16(); | 
 |         KeyFormat format = static_cast<KeyFormat>(data.readInt32()); | 
 |         auto clientId = nullable(readKeymasterBlob, data, true); | 
 |         auto appData = nullable(readKeymasterBlob, data, true); | 
 |         int32_t uid = data.readInt32(); | 
 |         ExportResult result; | 
 |         exportKey(name, format, clientId.value(), appData.value(), uid, &result); | 
 |         reply->writeNoException(); | 
 |         reply->writeParcelable(result); | 
 |  | 
 |         return NO_ERROR; | 
 |     } | 
 |     case BEGIN: { | 
 |         CHECK_INTERFACE(IKeystoreService, data, reply); | 
 |         sp<IBinder> token = data.readStrongBinder(); | 
 |         String16 name = data.readString16(); | 
 |         KeyPurpose purpose = static_cast<KeyPurpose>(data.readInt32()); | 
 |         bool pruneable = data.readInt32() != 0; | 
 |         auto args = nullable(readParamSetFromParcel, data); | 
 |         auto entropy = readBlobAsByteArray(data); | 
 |         int32_t uid = data.readInt32(); | 
 |         OperationResult result; | 
 |         begin(token, name, purpose, pruneable, args.value(), entropy.value(), uid, &result); | 
 |         reply->writeNoException(); | 
 |         reply->writeParcelable(result); | 
 |  | 
 |         return NO_ERROR; | 
 |     } | 
 |     case UPDATE: { | 
 |         CHECK_INTERFACE(IKeystoreService, data, reply); | 
 |         sp<IBinder> token = data.readStrongBinder(); | 
 |         auto args = nullable(readParamSetFromParcel, data); | 
 |         auto buf = readBlobAsByteArray(data); | 
 |         OperationResult result; | 
 |         update(token, args.value(), buf.value(), &result); | 
 |         reply->writeNoException(); | 
 |         reply->writeParcelable(result); | 
 |  | 
 |         return NO_ERROR; | 
 |     } | 
 |     case FINISH: { | 
 |         CHECK_INTERFACE(IKeystoreService, data, reply); | 
 |         sp<IBinder> token = data.readStrongBinder(); | 
 |         auto args = nullable(readParamSetFromParcel, data); | 
 |         auto signature = readBlobAsByteArray(data); | 
 |         auto entropy = readBlobAsByteArray(data); | 
 |         OperationResult result; | 
 |         finish(token, args.value(), signature.value(), entropy.value(), &result); | 
 |         reply->writeNoException(); | 
 |         reply->writeParcelable(result); | 
 |  | 
 |         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(); | 
 |         auto params = nullable(readParamSetFromParcel, data); | 
 |         hidl_vec<hidl_vec<uint8_t>> chain; | 
 |         int ret = attestKey(name, params.value(), &chain); | 
 |         reply->writeNoException(); | 
 |         reply->writeInt32(ret); | 
 |         nullable(writeCertificateChainToParcel, chain, reply); | 
 |  | 
 |         return NO_ERROR; | 
 |     } | 
 |     case ON_DEVICE_OFF_BODY: { | 
 |         CHECK_INTERFACE(IKeystoreService, data, reply); | 
 |         int32_t ret = onDeviceOffBody(); | 
 |         reply->writeNoException(); | 
 |         reply->writeInt32(ret); | 
 |  | 
 |         return NO_ERROR; | 
 |     } | 
 |     default: | 
 |         return BBinder::onTransact(code, data, reply, flags); | 
 |     } | 
 | } | 
 |  | 
 | // ---------------------------------------------------------------------------- | 
 |  | 
 | };  // namespace android |