Port to binderized keymaster HAL

This patch ports keystore to the HIDL based binderized keymaster HAL.
Keystore has no more dependencies on legacy keymaster headers, and
therefore data structures, constant declarations, or enums. All
keymaster related data structures and enums used by keystore are the
once defined by the HIDL based keymaster HAL definition.  In the process
of porting, keystore underwent some changes:

* Keystore got a new implementation of AuthorizationSet that is fully
  based on the new HIDL data structures. Key parameters are now either
  organised as AuthorizationSets or hidl_vec<KeyParameter>.  (Formerly,
  this was a mixture of keymaster's AuthorizationSet,
  std::vec<keymaster_key_param_t>, and keymaster_key_param_set_t.)  The
  former is used for memory management and provides algorithms for
  assembling, joining, and subtracting sets of parameters.  The latter
  is used as wire format for the HAL IPC; it can wrap the memory owned
  by an AuthorizationSet for this purpose.  The AuthorizationSet is
  accompanied by a new implementation of type safe functions for
  creating and accessing tagged key parameters,
  Authorizations (keystore/keymaster_tags.h).
* A new type (KSSReturnCode) was introduced that wraps keystore service
  response codes. Keystore has two sets of error codes.  ErrorCode
  errors are less than 0 and use 0 as success value.  ResponseCode
  errors are greater than zero and use 1 as success value.  This patch
  changes ResponseCode to be an enum class so that is no longer
  assignable to int without a cast. The new return type can only be
  initialized by ResponseCode or ErrorCode and when accessed as int32_t,
  which happens on serialization when the response is send to a client,
  the success values are coalesced onto 1 as expected by the
  clients. KSSreturnCode is also comparable to ResponseCode and
  ErrorCode, and the predicate isOk() returns true if it was initialized
  with either ErrorCode::OK (0) or ReponseCode::NO_ERROR (1).
* A bug was fixed, that caused the keystore verify function to return
  success, regardless of the input, internal errors, or lack of
  permissions.
* The marshalling code in IKeystoreService.cpp was rewritten.  For data
  structures that are known to keymaster, the client facing side of
  keystore uses HIDL based data structures as (target) source
  for (un)marshaling to avoid further conversion.  hidl_vecs are used to
  wrap parcel memory without copying and taking ownership where
  possible.
* Explicit use of malloc is reduced (malloc was required by the C nature
  of the old HAL).  The new implementations avoid explicit use of
  malloc/new and waive the use of pointers for return values. Instead,
  functions return by value objects that take ownership of secondary
  memory allocations where required.

Test: runtest --path=cts/tests/tests/keystore/src/android/keystore/cts

Bug: 32020919
Change-Id: I59d3a0f4a6bdf6bb3bbf791ad8827c463effa286
diff --git a/keystore/IKeystoreService.cpp b/keystore/IKeystoreService.cpp
index acd6968..4c26b60 100644
--- a/keystore/IKeystoreService.cpp
+++ b/keystore/IKeystoreService.cpp
@@ -19,28 +19,31 @@
 #include <sys/limits.h>
 #include <sys/types.h>
 
+#include <algorithm>
+#include <limits>
+
 #define LOG_TAG "KeystoreService"
 #include <utils/Log.h>
 
-#include <binder/Parcel.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;
-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* data, size_t len) : mData(data), mSize(len) {}
 
-KeystoreArg::~KeystoreArg() {
-}
+KeystoreArg::~KeystoreArg() {}
 
-const void *KeystoreArg::data() const {
+const void* KeystoreArg::data() const {
     return mData;
 }
 
@@ -48,36 +51,18 @@
     return mSize;
 }
 
-OperationResult::OperationResult() : resultCode(0), token(), handle(0), inputConsumed(0),
-    data(NULL), dataLength(0) {
-}
+OperationResult::OperationResult() : resultCode(), token(), handle(0), inputConsumed(0), data() {}
 
-OperationResult::~OperationResult() {
-}
+OperationResult::~OperationResult() {}
 
 status_t OperationResult::readFromParcel(const Parcel* inn) {
     const Parcel& in = *inn;
-    resultCode = in.readInt32();
+    resultCode = ErrorCode(in.readInt32());
     token = in.readStrongBinder();
-    handle = static_cast<keymaster_operation_handle_t>(in.readInt64());
+    handle = static_cast<uint64_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);
+    data = readKeymasterBlob(in);
+    outParams = readParamSetFromParcel(in);
     return OK;
 }
 
@@ -86,322 +71,28 @@
     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);
+    writeKeymasterBlob(data, out);
+    writeParamSetToParcel(outParams, out);
     return OK;
 }
 
-ExportResult::ExportResult() : resultCode(0), exportData(NULL), dataLength(0) {
-}
+ExportResult::ExportResult() : resultCode() {}
 
-ExportResult::~ExportResult() {
-}
+ExportResult::~ExportResult() {}
 
 status_t ExportResult::readFromParcel(const Parcel* inn) {
     const Parcel& in = *inn;
-    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");
-        }
-    }
+    resultCode = ErrorCode(in.readInt32());
+    exportData = readKeymasterBlob(in);
     return OK;
 }
 
 status_t 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.");
-        }
-    }
+    writeKeymasterBlob(exportData, out);
     return OK;
 }
 
-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, &param)) {
-            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);
-}
-
-status_t KeyCharacteristics::readFromParcel(const Parcel* inn) {
-    const Parcel& in = *inn;
-    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;
-    return OK;
-}
-
-status_t 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);
-    }
-    return OK;
-}
-
-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 = static_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
  */
@@ -420,77 +111,31 @@
     }
 }
 
-// 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:
-    explicit BpKeystoreService(const sp<IBinder>& impl)
-        : BpInterface<IKeystoreService>(impl)
-    {
-    }
+class BpKeystoreService : public BpInterface<IKeystoreService> {
+  public:
+    explicit BpKeystoreService(const sp<IBinder>& impl) : BpInterface<IKeystoreService>(impl) {}
 
     // test ping
-    virtual int32_t getState(int32_t userId)
-    {
+    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 -1;
+            return ResponseCode::SYSTEM_ERROR;
         }
         int32_t err = reply.readExceptionCode();
-        int32_t ret = reply.readInt32();
+        ResponseCode ret = ResponseCode(reply.readInt32());
         if (err < 0) {
             ALOGD("getState() caught exception %d\n", err);
-            return -1;
+            return ResponseCode::SYSTEM_ERROR;
         }
         return ret;
     }
 
-    virtual int32_t get(const String16& name, int32_t uid, uint8_t** item, size_t* itemLength)
-    {
+    KeyStoreServiceReturnCode get(const String16& name, int32_t uid,
+                                  hidl_vec<uint8_t>* item) override {
         Parcel data, reply;
         data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
         data.writeString16(name);
@@ -498,58 +143,40 @@
         status_t status = remote()->transact(BnKeystoreService::GET, data, &reply);
         if (status != NO_ERROR) {
             ALOGD("get() could not contact remote: %d\n", status);
-            return -1;
+            return ResponseCode::SYSTEM_ERROR;
         }
         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 ResponseCode::SYSTEM_ERROR;
         }
-        return 0;
+        auto resultItem = readBlobAsByteArray(reply);
+        if (item) *item = resultItem.value();
+        return ResponseCode(reply.readInt32());
     }
 
-    virtual int32_t insert(const String16& name, const uint8_t* item, size_t itemLength, int uid,
-            int32_t flags)
-    {
+    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);
-        data.writeInt32(itemLength);
-        void* buf = data.writeInplace(itemLength);
-        memcpy(buf, item, itemLength);
+        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 -1;
+            return ResponseCode::SYSTEM_ERROR;
         }
         int32_t err = reply.readExceptionCode();
-        int32_t ret = reply.readInt32();
         if (err < 0) {
             ALOGD("import() caught exception %d\n", err);
-            return -1;
+            return ResponseCode::SYSTEM_ERROR;
         }
-        return ret;
+        return ResponseCode(reply.readInt32());
     }
 
-    virtual int32_t del(const String16& name, int uid)
-    {
+    KeyStoreServiceReturnCode del(const String16& name, int uid) override {
         Parcel data, reply;
         data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
         data.writeString16(name);
@@ -557,19 +184,17 @@
         status_t status = remote()->transact(BnKeystoreService::DEL, data, &reply);
         if (status != NO_ERROR) {
             ALOGD("del() could not contact remote: %d\n", status);
-            return -1;
+            return ResponseCode::SYSTEM_ERROR;
         }
         int32_t err = reply.readExceptionCode();
-        int32_t ret = reply.readInt32();
         if (err < 0) {
             ALOGD("del() caught exception %d\n", err);
-            return -1;
+            return ResponseCode::SYSTEM_ERROR;
         }
-        return ret;
+        return ResponseCode(reply.readInt32());
     }
 
-    virtual int32_t exist(const String16& name, int uid)
-    {
+    KeyStoreServiceReturnCode exist(const String16& name, int uid) override {
         Parcel data, reply;
         data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
         data.writeString16(name);
@@ -577,19 +202,18 @@
         status_t status = remote()->transact(BnKeystoreService::EXIST, data, &reply);
         if (status != NO_ERROR) {
             ALOGD("exist() could not contact remote: %d\n", status);
-            return -1;
+            return ResponseCode::SYSTEM_ERROR;
         }
         int32_t err = reply.readExceptionCode();
-        int32_t ret = reply.readInt32();
         if (err < 0) {
             ALOGD("exist() caught exception %d\n", err);
-            return -1;
+            return ResponseCode::SYSTEM_ERROR;
         }
-        return ret;
+        return ResponseCode(reply.readInt32());
     }
 
-    virtual int32_t list(const String16& prefix, int uid, Vector<String16>* matches)
-    {
+    KeyStoreServiceReturnCode list(const String16& prefix, int uid,
+                                   Vector<String16>* matches) override {
         Parcel data, reply;
         data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
         data.writeString16(prefix);
@@ -597,81 +221,74 @@
         status_t status = remote()->transact(BnKeystoreService::LIST, data, &reply);
         if (status != NO_ERROR) {
             ALOGD("list() could not contact remote: %d\n", status);
-            return -1;
+            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());
         }
-        int32_t ret = reply.readInt32();
         if (err < 0) {
             ALOGD("list() caught exception %d\n", err);
-            return -1;
+            return ResponseCode::SYSTEM_ERROR;
         }
-        return ret;
+        return ResponseCode(reply.readInt32());
     }
 
-    virtual int32_t reset()
-    {
+    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 -1;
+            return ResponseCode::SYSTEM_ERROR;
         }
         int32_t err = reply.readExceptionCode();
-        int32_t ret = reply.readInt32();
         if (err < 0) {
             ALOGD("reset() caught exception %d\n", err);
-            return -1;
+            return ResponseCode::SYSTEM_ERROR;
         }
-        return ret;
+        return ResponseCode(reply.readInt32());
     }
 
-    virtual int32_t onUserPasswordChanged(int32_t userId, const String16& password)
-    {
+    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);
+        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;
+            return ResponseCode::SYSTEM_ERROR;
         }
         int32_t err = reply.readExceptionCode();
-        int32_t ret = reply.readInt32();
         if (err < 0) {
             ALOGD("onUserPasswordChanged() caught exception %d\n", err);
-            return -1;
+            return ResponseCode::SYSTEM_ERROR;
         }
-        return ret;
+        return ResponseCode(reply.readInt32());
     }
 
-    virtual int32_t lock(int32_t userId)
-    {
+    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 -1;
+            return ResponseCode::SYSTEM_ERROR;
         }
         int32_t err = reply.readExceptionCode();
-        int32_t ret = reply.readInt32();
         if (err < 0) {
             ALOGD("lock() caught exception %d\n", err);
-            return -1;
+            return ResponseCode::SYSTEM_ERROR;
         }
-        return ret;
+        return ResponseCode(reply.readInt32());
     }
 
-    virtual int32_t unlock(int32_t userId, const String16& password)
-    {
+    KeyStoreServiceReturnCode unlock(int32_t userId, const String16& password) override {
         Parcel data, reply;
         data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
         data.writeInt32(userId);
@@ -679,19 +296,17 @@
         status_t status = remote()->transact(BnKeystoreService::UNLOCK, data, &reply);
         if (status != NO_ERROR) {
             ALOGD("unlock() could not contact remote: %d\n", status);
-            return -1;
+            return ResponseCode::SYSTEM_ERROR;
         }
         int32_t err = reply.readExceptionCode();
-        int32_t ret = reply.readInt32();
         if (err < 0) {
             ALOGD("unlock() caught exception %d\n", err);
-            return -1;
+            return ResponseCode::SYSTEM_ERROR;
         }
-        return ret;
+        return ResponseCode(reply.readInt32());
     }
 
-    virtual bool isEmpty(int32_t userId)
-    {
+    bool isEmpty(int32_t userId) override {
         Parcel data, reply;
         data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
         data.writeInt32(userId);
@@ -701,17 +316,16 @@
             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;
+        return reply.readInt32() != 0;
     }
 
-    virtual int32_t generate(const String16& name, int32_t uid, int32_t keyType, int32_t keySize,
-            int32_t flags, Vector<sp<KeystoreArg> >* args)
-    {
+    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);
@@ -721,7 +335,7 @@
         data.writeInt32(flags);
         data.writeInt32(1);
         data.writeInt32(args->size());
-        for (Vector<sp<KeystoreArg> >::iterator it = args->begin(); it != args->end(); ++it) {
+        for (Vector<sp<KeystoreArg>>::iterator it = args->begin(); it != args->end(); ++it) {
             sp<KeystoreArg> item = *it;
             size_t keyLength = item->size();
             data.writeInt32(keyLength);
@@ -731,142 +345,104 @@
         status_t status = remote()->transact(BnKeystoreService::GENERATE, data, &reply);
         if (status != NO_ERROR) {
             ALOGD("generate() could not contact remote: %d\n", status);
-            return -1;
+            return ResponseCode::SYSTEM_ERROR;
         }
         int32_t err = reply.readExceptionCode();
-        int32_t ret = reply.readInt32();
         if (err < 0) {
             ALOGD("generate() caught exception %d\n", err);
-            return -1;
+            return ResponseCode::SYSTEM_ERROR;
         }
-        return ret;
+        return ResponseCode(reply.readInt32());
     }
 
-    virtual int32_t import(const String16& name, const uint8_t* key, size_t keyLength, int uid,
-            int flags)
-    {
+    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);
-        data.writeInt32(keyLength);
-        void* buf = data.writeInplace(keyLength);
-        memcpy(buf, key, keyLength);
+        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 -1;
+            return ResponseCode::SYSTEM_ERROR;
         }
         int32_t err = reply.readExceptionCode();
-        int32_t ret = reply.readInt32();
         if (err < 0) {
             ALOGD("import() caught exception %d\n", err);
-            return -1;
+            return ResponseCode::SYSTEM_ERROR;
         }
-        return ret;
+        return ResponseCode(reply.readInt32());
     }
 
-    virtual int32_t sign(const String16& name, const uint8_t* in, size_t inLength, uint8_t** out,
-            size_t* outLength)
-    {
+    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);
-        data.writeInt32(inLength);
-        void* buf = data.writeInplace(inLength);
-        memcpy(buf, in, inLength);
+        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 -1;
+            return ResponseCode::SYSTEM_ERROR;
         }
         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 ResponseCode::SYSTEM_ERROR;
         }
-        return 0;
+        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());
     }
 
-    virtual int32_t verify(const String16& name, const uint8_t* in, size_t inLength,
-            const uint8_t* signature, size_t signatureLength)
-    {
+    KeyStoreServiceReturnCode verify(const String16& name, const hidl_vec<uint8_t>& in,
+                                     const hidl_vec<uint8_t>& signature) override {
         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);
+        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 -1;
+            return ResponseCode::SYSTEM_ERROR;
         }
         int32_t err = reply.readExceptionCode();
-        int32_t ret = reply.readInt32();
         if (err < 0) {
             ALOGD("verify() caught exception %d\n", err);
-            return -1;
+            return ResponseCode::SYSTEM_ERROR;
         }
-        return ret;
+        return ResponseCode(reply.readInt32());
     }
 
-    virtual int32_t get_pubkey(const String16& name, uint8_t** pubkey, size_t* pubkeyLength)
-    {
+    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 -1;
+            return ResponseCode::SYSTEM_ERROR;
         }
         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 ResponseCode::SYSTEM_ERROR;
         }
-        return 0;
-     }
+        auto resultKey = readBlobAsByteArray(reply);
+        if (pubkey) *pubkey = resultKey.value();
+        return ResponseCode(reply.readInt32());
+    }
 
-    virtual int32_t grant(const String16& name, int32_t granteeUid)
-    {
+    KeyStoreServiceReturnCode grant(const String16& name, int32_t granteeUid) override {
         Parcel data, reply;
         data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
         data.writeString16(name);
@@ -874,19 +450,17 @@
         status_t status = remote()->transact(BnKeystoreService::GRANT, data, &reply);
         if (status != NO_ERROR) {
             ALOGD("grant() could not contact remote: %d\n", status);
-            return -1;
+            return ResponseCode::SYSTEM_ERROR;
         }
         int32_t err = reply.readExceptionCode();
-        int32_t ret = reply.readInt32();
         if (err < 0) {
             ALOGD("grant() caught exception %d\n", err);
-            return -1;
+            return ResponseCode::SYSTEM_ERROR;
         }
-        return ret;
+        return ResponseCode(reply.readInt32());
     }
 
-    virtual int32_t ungrant(const String16& name, int32_t granteeUid)
-    {
+    KeyStoreServiceReturnCode ungrant(const String16& name, int32_t granteeUid) override {
         Parcel data, reply;
         data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
         data.writeString16(name);
@@ -894,19 +468,17 @@
         status_t status = remote()->transact(BnKeystoreService::UNGRANT, data, &reply);
         if (status != NO_ERROR) {
             ALOGD("ungrant() could not contact remote: %d\n", status);
-            return -1;
+            return ResponseCode::SYSTEM_ERROR;
         }
         int32_t err = reply.readExceptionCode();
-        int32_t ret = reply.readInt32();
         if (err < 0) {
             ALOGD("ungrant() caught exception %d\n", err);
-            return -1;
+            return ResponseCode::SYSTEM_ERROR;
         }
-        return ret;
+        return ResponseCode(reply.readInt32());
     }
 
-    int64_t getmtime(const String16& name, int32_t uid)
-    {
+    int64_t getmtime(const String16& name, int32_t uid) override {
         Parcel data, reply;
         data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
         data.writeString16(name);
@@ -917,17 +489,15 @@
             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;
+        return reply.readInt64();
     }
 
-    virtual int32_t duplicate(const String16& srcKey, int32_t srcUid, const String16& destKey,
-            int32_t destUid)
-    {
+    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);
@@ -937,19 +507,17 @@
         status_t status = remote()->transact(BnKeystoreService::DUPLICATE, data, &reply);
         if (status != NO_ERROR) {
             ALOGD("duplicate() could not contact remote: %d\n", status);
-            return -1;
+            return ResponseCode::SYSTEM_ERROR;
         }
         int32_t err = reply.readExceptionCode();
-        int32_t ret = reply.readInt32();
         if (err < 0) {
             ALOGD("duplicate() caught exception %d\n", err);
-            return -1;
+            return ResponseCode::SYSTEM_ERROR;
         }
-        return ret;
+        return ResponseCode(reply.readInt32());
     }
 
-    virtual int32_t is_hardware_backed(const String16& keyType)
-    {
+    int32_t is_hardware_backed(const String16& keyType) override {
         Parcel data, reply;
         data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
         data.writeString16(keyType);
@@ -959,151 +527,132 @@
             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;
+        return reply.readInt32();
     }
 
-    virtual int32_t clear_uid(int64_t uid)
-    {
+    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 -1;
+            return ResponseCode::SYSTEM_ERROR;
         }
         int32_t err = reply.readExceptionCode();
-        int32_t ret = reply.readInt32();
         if (err < 0) {
             ALOGD("clear_uid() caught exception %d\n", err);
-            return -1;
+            return ResponseCode::SYSTEM_ERROR;
         }
-        return ret;
+        return ResponseCode(reply.readInt32());
     }
 
-    virtual int32_t addRngEntropy(const uint8_t* buf, size_t bufLength)
-    {
+    KeyStoreServiceReturnCode addRngEntropy(const hidl_vec<uint8_t>& entropy) override {
         Parcel data, reply;
         data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
-        data.writeByteArray(bufLength, buf);
+        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 -1;
+            return ResponseCode::SYSTEM_ERROR;
         }
         int32_t err = reply.readExceptionCode();
-        int32_t ret = reply.readInt32();
         if (err < 0) {
             ALOGD("addRngEntropy() caught exception %d\n", err);
-            return -1;
+            return ResponseCode::SYSTEM_ERROR;
         }
-        return ret;
+        return ResponseCode(reply.readInt32());
     };
 
-    virtual int32_t generateKey(const String16& name, const KeymasterArguments& params,
-                                const uint8_t* entropy, size_t entropyLength, int uid, int flags,
-                                KeyCharacteristics* outCharacteristics)
-    {
+    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);
-        data.writeInt32(1);
-        params.writeToParcel(&data);
-        data.writeByteArray(entropyLength, entropy);
+        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 KM_ERROR_UNKNOWN_ERROR;
+            return ResponseCode::SYSTEM_ERROR;
         }
         int32_t err = reply.readExceptionCode();
-        int32_t ret = reply.readInt32();
+        ResponseCode ret = ResponseCode(reply.readInt32());
         if (err < 0) {
             ALOGD("generateKey() caught exception %d\n", err);
-            return KM_ERROR_UNKNOWN_ERROR;
+            return ResponseCode::SYSTEM_ERROR;
         }
         if (outCharacteristics) {
-            reply.readParcelable(outCharacteristics);
+            *outCharacteristics = nullable(readKeyCharacteristicsFromParcel, reply).value();
         }
         return ret;
     }
-    virtual int32_t getKeyCharacteristics(const String16& name,
-                                          const keymaster_blob_t* clientId,
-                                          const keymaster_blob_t* appData,
-                                          int32_t uid, KeyCharacteristics* outCharacteristics)
-    {
+    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);
-        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);
-        }
+        writeBlobAsByteArray(clientId, &data);
+        writeBlobAsByteArray(appData, &data);
         data.writeInt32(uid);
-        status_t status = remote()->transact(BnKeystoreService::GET_KEY_CHARACTERISTICS,
-                                             data, &reply);
+        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;
+            return ResponseCode::SYSTEM_ERROR;
         }
         int32_t err = reply.readExceptionCode();
-        int32_t ret = reply.readInt32();
+        ResponseCode ret = ResponseCode(reply.readInt32());
         if (err < 0) {
             ALOGD("getKeyCharacteristics() caught exception %d\n", err);
-            return KM_ERROR_UNKNOWN_ERROR;
+            return ResponseCode::SYSTEM_ERROR;
         }
         if (outCharacteristics) {
-            reply.readParcelable(outCharacteristics);
+            *outCharacteristics = nullable(readKeyCharacteristicsFromParcel, reply).value();
         }
         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)
-    {
+    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);
-        data.writeInt32(1);
-        params.writeToParcel(&data);
-        data.writeInt32(format);
-        data.writeByteArray(keyLength, keyData);
+        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 KM_ERROR_UNKNOWN_ERROR;
+            return ResponseCode::SYSTEM_ERROR;
         }
         int32_t err = reply.readExceptionCode();
-        int32_t ret = reply.readInt32();
+        ResponseCode ret = ResponseCode(reply.readInt32());
         if (err < 0) {
             ALOGD("importKey() caught exception %d\n", err);
-            return KM_ERROR_UNKNOWN_ERROR;
+            return ResponseCode::SYSTEM_ERROR;
         }
         if (outCharacteristics) {
-            reply.readParcelable(outCharacteristics);
+            *outCharacteristics = nullable(readKeyCharacteristicsFromParcel, reply).value();
         }
         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)
-    {
+    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;
         }
@@ -1111,39 +660,29 @@
         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(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 = KM_ERROR_UNKNOWN_ERROR;
+            result->resultCode = ResponseCode::SYSTEM_ERROR;
             return;
         }
         int32_t err = reply.readExceptionCode();
         if (err < 0) {
             ALOGD("exportKey() caught exception %d\n", err);
-            result->resultCode = KM_ERROR_UNKNOWN_ERROR;
+            result->resultCode = ResponseCode::SYSTEM_ERROR;
             return;
         }
 
         reply.readParcelable(result);
     }
 
-    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)
-    {
+    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;
         }
@@ -1151,147 +690,134 @@
         data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
         data.writeStrongBinder(appToken);
         data.writeString16(name);
-        data.writeInt32(purpose);
+        data.writeInt32(int32_t(purpose));
         data.writeInt32(pruneable ? 1 : 0);
-        data.writeInt32(1);
-        params.writeToParcel(&data);
-        data.writeByteArray(entropyLength, entropy);
+        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 = KM_ERROR_UNKNOWN_ERROR;
+            result->resultCode = ResponseCode::SYSTEM_ERROR;
             return;
         }
         int32_t err = reply.readExceptionCode();
         if (err < 0) {
             ALOGD("begin() caught exception %d\n", err);
-            result->resultCode = KM_ERROR_UNKNOWN_ERROR;
+            result->resultCode = ResponseCode::SYSTEM_ERROR;
             return;
         }
 
         reply.readParcelable(result);
     }
 
-    virtual void update(const sp<IBinder>& token, const KeymasterArguments& params,
-                        const uint8_t* opData, size_t dataLength, OperationResult* 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);
-        data.writeInt32(1);
-        params.writeToParcel(&data);
-        data.writeByteArray(dataLength, opData);
+        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 = KM_ERROR_UNKNOWN_ERROR;
+            result->resultCode = ResponseCode::SYSTEM_ERROR;
             return;
         }
         int32_t err = reply.readExceptionCode();
         if (err < 0) {
             ALOGD("update() caught exception %d\n", err);
-            result->resultCode = KM_ERROR_UNKNOWN_ERROR;
+            result->resultCode = ResponseCode::SYSTEM_ERROR;
             return;
         }
 
         reply.readParcelable(result);
     }
 
-    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)
-    {
+    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);
-        data.writeInt32(1);
-        params.writeToParcel(&data);
-        data.writeByteArray(signatureLength, signature);
-        data.writeByteArray(entropyLength, entropy);
+        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 = KM_ERROR_UNKNOWN_ERROR;
+            result->resultCode = ResponseCode::SYSTEM_ERROR;
             return;
         }
         int32_t err = reply.readExceptionCode();
         if (err < 0) {
             ALOGD("finish() caught exception %d\n", err);
-            result->resultCode = KM_ERROR_UNKNOWN_ERROR;
+            result->resultCode = ResponseCode::SYSTEM_ERROR;
             return;
         }
 
         reply.readParcelable(result);
     }
 
-    virtual int32_t abort(const sp<IBinder>& token)
-    {
+    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 KM_ERROR_UNKNOWN_ERROR;
+            return ResponseCode::SYSTEM_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 ResponseCode::SYSTEM_ERROR;
         }
-        return ret;
+        return ResponseCode(reply.readInt32());
     }
 
-    virtual bool isOperationAuthorized(const sp<IBinder>& token)
-    {
+    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);
+        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;
+        return reply.readInt32() == 1;
     }
 
-    virtual int32_t addAuthToken(const uint8_t* token, size_t length)
-    {
+    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 -1;
+            return ResponseCode::SYSTEM_ERROR;
         }
         int32_t err = reply.readExceptionCode();
-        int32_t ret = reply.readInt32();
         if (err < 0) {
             ALOGD("addAuthToken() caught exception %d\n", err);
-            return -1;
+            return ResponseCode::SYSTEM_ERROR;
         }
-        return ret;
+        return ResponseCode(reply.readInt32());
     };
 
-    virtual int32_t onUserAdded(int32_t userId, int32_t parentId)
-    {
+    KeyStoreServiceReturnCode onUserAdded(int32_t userId, int32_t parentId) override {
         Parcel data, reply;
         data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
         data.writeInt32(userId);
@@ -1299,609 +825,499 @@
         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;
+            return ResponseCode::SYSTEM_ERROR;
         }
         int32_t err = reply.readExceptionCode();
-        int32_t ret = reply.readInt32();
         if (err < 0) {
             ALOGD("onUserAdded() caught exception %d\n", err);
-            return -1;
+            return ResponseCode::SYSTEM_ERROR;
         }
-        return ret;
+        return ResponseCode(reply.readInt32());
     }
 
-    virtual int32_t onUserRemoved(int32_t userId)
-    {
+    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 -1;
+            return ResponseCode::SYSTEM_ERROR;
         }
         int32_t err = reply.readExceptionCode();
-        int32_t ret = reply.readInt32();
         if (err < 0) {
             ALOGD("onUserRemoved() caught exception %d\n", err);
-            return -1;
+            return ResponseCode::SYSTEM_ERROR;
         }
-        return ret;
+        return ResponseCode(reply.readInt32());
     }
 
-    virtual int32_t attestKey(const String16& name, const KeymasterArguments& params,
-                              KeymasterCertificateChain* outChain) {
-        if (!outChain)
-            return KM_ERROR_OUTPUT_PARAMETER_NULL;
+    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);
-        data.writeInt32(1);  // params is not NULL.
-        params.writeToParcel(&data);
+        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 KM_ERROR_UNKNOWN_ERROR;
+            return ResponseCode::SYSTEM_ERROR;
         }
         int32_t err = reply.readExceptionCode();
-        int32_t ret = reply.readInt32();
+        ResponseCode ret = ResponseCode(reply.readInt32());
         if (err < 0) {
             ALOGD("attestKey() caught exception %d\n", err);
-            return KM_ERROR_UNKNOWN_ERROR;
+            return ResponseCode::SYSTEM_ERROR;
         }
         if (reply.readInt32() != 0) {
-            outChain->readFromParcel(reply);
+            *outChain = readCertificateChainFromParcel(reply);
         }
         return ret;
     }
 
-    virtual int32_t onDeviceOffBody()
-    {
+    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 -1;
+            return ResponseCode::SYSTEM_ERROR;
         }
         int32_t err = reply.readExceptionCode();
-        int32_t ret = reply.readInt32();
         if (err < 0) {
             ALOGD("onDeviceOffBody() caught exception %d\n", err);
-            return -1;
+            return ResponseCode::SYSTEM_ERROR;
         }
-        return ret;
+        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();
-            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);
+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;
             }
-            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);
-                        }
+            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->writeParcelable(outCharacteristics);
-            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);
-            if (clientId.get() && clientId->data) {
-                free(const_cast<void*>(static_cast<const void*>(clientId->data)));
-            }
-            if (appData.get() && appData->data) {
-                free(const_cast<void*>(static_cast<const void*>(appData->data)));
-            }
-            reply->writeNoException();
-            reply->writeInt32(ret);
-            reply->writeParcelable(outCharacteristics);
-            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->writeParcelable(outCharacteristics);
-            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);
-            if (clientId.get() && clientId->data) {
-                free(const_cast<void*>(static_cast<const void*>(clientId->data)));
-            }
-            if (appData.get() && appData->data) {
-                free(const_cast<void*>(static_cast<const void*>(appData->data)));
-            }
-            reply->writeNoException();
-            reply->writeParcelable(result);
+        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();
-            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->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();
-            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->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();
-            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->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 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 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 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_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 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;
+    }
+    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;
+    }
+    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);
+        return NO_ERROR;
+    }
+    default:
+        return BBinder::onTransact(code, data, reply, flags);
     }
 }
 
 // ----------------------------------------------------------------------------
 
-}; // namespace android
+};  // namespace android