/*
**
** Copyright 2008, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
#include <stdint.h>
#include <sys/limits.h>
#include <sys/types.h>
#include <algorithm>
#include <limits>
#define LOG_TAG "KeystoreService"
#include <utils/Log.h>
#include <binder/IPCThreadState.h>
#include <binder/IServiceManager.h>
#include <binder/Parcel.h>
#include <keystore/IKeystoreService.h>
#include <keystore/keystore_hidl_support.h>
#include "keystore_aidl_hidl_marshalling_utils.h"
namespace android {
using namespace ::keystore;
const ssize_t MAX_GENERATE_ARGS = 3;
KeystoreArg::KeystoreArg(const void* data, size_t len) : mData(data), mSize(len) {}
KeystoreArg::~KeystoreArg() {}
const void* KeystoreArg::data() const {
return mData;
}
size_t KeystoreArg::size() const {
return mSize;
}
OperationResult::OperationResult() : resultCode(), token(), handle(0), inputConsumed(0), data() {}
OperationResult::~OperationResult() {}
status_t OperationResult::readFromParcel(const Parcel* inn) {
const Parcel& in = *inn;
resultCode = ErrorCode(in.readInt32());
token = in.readStrongBinder();
handle = static_cast<uint64_t>(in.readInt64());
inputConsumed = in.readInt32();
data = readKeymasterBlob(in);
outParams = readParamSetFromParcel(in);
return OK;
}
status_t OperationResult::writeToParcel(Parcel* out) const {
out->writeInt32(resultCode);
out->writeStrongBinder(token);
out->writeInt64(handle);
out->writeInt32(inputConsumed);
writeKeymasterBlob(data, out);
writeParamSetToParcel(outParams, out);
return OK;
}
ExportResult::ExportResult() : resultCode() {}
ExportResult::~ExportResult() {}
status_t ExportResult::readFromParcel(const Parcel* inn) {
const Parcel& in = *inn;
resultCode = ErrorCode(in.readInt32());
exportData = readKeymasterBlob(in);
return OK;
}
status_t ExportResult::writeToParcel(Parcel* out) const {
out->writeInt32(resultCode);
writeKeymasterBlob(exportData, out);
return OK;
}
/**
* Read a byte array from in. The data at *data is still owned by the parcel
*/
static void readByteArray(const Parcel& in, const uint8_t** data, size_t* length) {
ssize_t slength = in.readInt32();
if (slength > 0) {
*data = reinterpret_cast<const uint8_t*>(in.readInplace(slength));
if (*data) {
*length = static_cast<size_t>(slength);
} else {
*length = 0;
}
} else {
*data = NULL;
*length = 0;
}
}
class BpKeystoreService : public BpInterface<IKeystoreService> {
public:
explicit BpKeystoreService(const sp<IBinder>& impl) : BpInterface<IKeystoreService>(impl) {}
// test ping
KeyStoreServiceReturnCode getState(int32_t userId) override {
Parcel data, reply;
data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
data.writeInt32(userId);
status_t status = remote()->transact(BnKeystoreService::GET_STATE, data, &reply);
if (status != NO_ERROR) {
ALOGD("getState() could not contact remote: %d\n", status);
return ResponseCode::SYSTEM_ERROR;
}
int32_t err = reply.readExceptionCode();
ResponseCode ret = ResponseCode(reply.readInt32());
if (err < 0) {
ALOGD("getState() caught exception %d\n", err);
return ResponseCode::SYSTEM_ERROR;
}
return ret;
}
KeyStoreServiceReturnCode get(const String16& name, int32_t uid,
hidl_vec<uint8_t>* item) override {
Parcel data, reply;
data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
data.writeString16(name);
data.writeInt32(uid);
status_t status = remote()->transact(BnKeystoreService::GET, data, &reply);
if (status != NO_ERROR) {
ALOGD("get() could not contact remote: %d\n", status);
return ResponseCode::SYSTEM_ERROR;
}
int32_t err = reply.readExceptionCode();
if (err < 0) {
ALOGD("get() caught exception %d\n", err);
return ResponseCode::SYSTEM_ERROR;
}
auto resultItem = readBlobAsByteArray(reply);
if (item) *item = resultItem.value();
return ResponseCode(reply.readInt32());
}
KeyStoreServiceReturnCode insert(const String16& name, const hidl_vec<uint8_t>& item, int uid,
int32_t flags) override {
Parcel data, reply;
data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
data.writeString16(name);
writeBlobAsByteArray(item, &data);
data.writeInt32(uid);
data.writeInt32(flags);
status_t status = remote()->transact(BnKeystoreService::INSERT, data, &reply);
if (status != NO_ERROR) {
ALOGD("import() could not contact remote: %d\n", status);
return ResponseCode::SYSTEM_ERROR;
}
int32_t err = reply.readExceptionCode();
if (err < 0) {
ALOGD("import() caught exception %d\n", err);
return ResponseCode::SYSTEM_ERROR;
}
return ResponseCode(reply.readInt32());
}
KeyStoreServiceReturnCode del(const String16& name, int uid) override {
Parcel data, reply;
data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
data.writeString16(name);
data.writeInt32(uid);
status_t status = remote()->transact(BnKeystoreService::DEL, data, &reply);
if (status != NO_ERROR) {
ALOGD("del() could not contact remote: %d\n", status);
return ResponseCode::SYSTEM_ERROR;
}
int32_t err = reply.readExceptionCode();
if (err < 0) {
ALOGD("del() caught exception %d\n", err);
return ResponseCode::SYSTEM_ERROR;
}
return ResponseCode(reply.readInt32());
}
KeyStoreServiceReturnCode exist(const String16& name, int uid) override {
Parcel data, reply;
data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
data.writeString16(name);
data.writeInt32(uid);
status_t status = remote()->transact(BnKeystoreService::EXIST, data, &reply);
if (status != NO_ERROR) {
ALOGD("exist() could not contact remote: %d\n", status);
return ResponseCode::SYSTEM_ERROR;
}
int32_t err = reply.readExceptionCode();
if (err < 0) {
ALOGD("exist() caught exception %d\n", err);
return ResponseCode::SYSTEM_ERROR;
}
return ResponseCode(reply.readInt32());
}
KeyStoreServiceReturnCode list(const String16& prefix, int uid,
Vector<String16>* matches) override {
Parcel data, reply;
data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
data.writeString16(prefix);
data.writeInt32(uid);
status_t status = remote()->transact(BnKeystoreService::LIST, data, &reply);
if (status != NO_ERROR) {
ALOGD("list() could not contact remote: %d\n", status);
return ResponseCode::SYSTEM_ERROR;
}
int32_t err = reply.readExceptionCode();
int32_t numMatches = reply.readInt32();
for (int32_t i = 0; i < numMatches; i++) {
matches->push(reply.readString16());
}
if (err < 0) {
ALOGD("list() caught exception %d\n", err);
return ResponseCode::SYSTEM_ERROR;
}
return ResponseCode(reply.readInt32());
}
KeyStoreServiceReturnCode reset() override {
Parcel data, reply;
data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
status_t status = remote()->transact(BnKeystoreService::RESET, data, &reply);
if (status != NO_ERROR) {
ALOGD("reset() could not contact remote: %d\n", status);
return ResponseCode::SYSTEM_ERROR;
}
int32_t err = reply.readExceptionCode();
if (err < 0) {
ALOGD("reset() caught exception %d\n", err);
return ResponseCode::SYSTEM_ERROR;
}
return ResponseCode(reply.readInt32());
}
KeyStoreServiceReturnCode onUserPasswordChanged(int32_t userId,
const String16& password) override {
Parcel data, reply;
data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
data.writeInt32(userId);
data.writeString16(password);
status_t status =
remote()->transact(BnKeystoreService::ON_USER_PASSWORD_CHANGED, data, &reply);
if (status != NO_ERROR) {
ALOGD("onUserPasswordChanged() could not contact remote: %d\n", status);
return ResponseCode::SYSTEM_ERROR;
}
int32_t err = reply.readExceptionCode();
if (err < 0) {
ALOGD("onUserPasswordChanged() caught exception %d\n", err);
return ResponseCode::SYSTEM_ERROR;
}
return ResponseCode(reply.readInt32());
}
KeyStoreServiceReturnCode lock(int32_t userId) override {
Parcel data, reply;
data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
data.writeInt32(userId);
status_t status = remote()->transact(BnKeystoreService::LOCK, data, &reply);
if (status != NO_ERROR) {
ALOGD("lock() could not contact remote: %d\n", status);
return ResponseCode::SYSTEM_ERROR;
}
int32_t err = reply.readExceptionCode();
if (err < 0) {
ALOGD("lock() caught exception %d\n", err);
return ResponseCode::SYSTEM_ERROR;
}
return ResponseCode(reply.readInt32());
}
KeyStoreServiceReturnCode unlock(int32_t userId, const String16& password) override {
Parcel data, reply;
data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
data.writeInt32(userId);
data.writeString16(password);
status_t status = remote()->transact(BnKeystoreService::UNLOCK, data, &reply);
if (status != NO_ERROR) {
ALOGD("unlock() could not contact remote: %d\n", status);
return ResponseCode::SYSTEM_ERROR;
}
int32_t err = reply.readExceptionCode();
if (err < 0) {
ALOGD("unlock() caught exception %d\n", err);
return ResponseCode::SYSTEM_ERROR;
}
return ResponseCode(reply.readInt32());
}
bool isEmpty(int32_t userId) override {
Parcel data, reply;
data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
data.writeInt32(userId);
status_t status = remote()->transact(BnKeystoreService::IS_EMPTY, data, &reply);
if (status != NO_ERROR) {
ALOGD("isEmpty() could not contact remote: %d\n", status);
return false;
}
int32_t err = reply.readExceptionCode();
if (err < 0) {
ALOGD("isEmpty() caught exception %d\n", err);
return false;
}
return reply.readInt32() != 0;
}
KeyStoreServiceReturnCode generate(const String16& name, int32_t uid, int32_t keyType,
int32_t keySize, int32_t flags,
Vector<sp<KeystoreArg>>* args) override {
Parcel data, reply;
data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
data.writeString16(name);
data.writeInt32(uid);
data.writeInt32(keyType);
data.writeInt32(keySize);
data.writeInt32(flags);
data.writeInt32(1);
data.writeInt32(args->size());
for (Vector<sp<KeystoreArg>>::iterator it = args->begin(); it != args->end(); ++it) {
sp<KeystoreArg> item = *it;
size_t keyLength = item->size();
data.writeInt32(keyLength);
void* buf = data.writeInplace(keyLength);
memcpy(buf, item->data(), keyLength);
}
status_t status = remote()->transact(BnKeystoreService::GENERATE, data, &reply);
if (status != NO_ERROR) {
ALOGD("generate() could not contact remote: %d\n", status);
return ResponseCode::SYSTEM_ERROR;
}
int32_t err = reply.readExceptionCode();
if (err < 0) {
ALOGD("generate() caught exception %d\n", err);
return ResponseCode::SYSTEM_ERROR;
}
return ResponseCode(reply.readInt32());
}
KeyStoreServiceReturnCode import(const String16& name, const hidl_vec<uint8_t>& key, int uid,
int flags) override {
Parcel data, reply;
data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
data.writeString16(name);
writeBlobAsByteArray(key, &data);
data.writeInt32(uid);
data.writeInt32(flags);
status_t status = remote()->transact(BnKeystoreService::IMPORT, data, &reply);
if (status != NO_ERROR) {
ALOGD("import() could not contact remote: %d\n", status);
return ResponseCode::SYSTEM_ERROR;
}
int32_t err = reply.readExceptionCode();
if (err < 0) {
ALOGD("import() caught exception %d\n", err);
return ResponseCode::SYSTEM_ERROR;
}
return ResponseCode(reply.readInt32());
}
KeyStoreServiceReturnCode sign(const String16& name, const hidl_vec<uint8_t>& in,
hidl_vec<uint8_t>* out) override {
Parcel data, reply;
data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
data.writeString16(name);
writeBlobAsByteArray(in, &data);
status_t status = remote()->transact(BnKeystoreService::SIGN, data, &reply);
if (status != NO_ERROR) {
ALOGD("import() could not contact remote: %d\n", status);
return ResponseCode::SYSTEM_ERROR;
}
int32_t err = reply.readExceptionCode();
if (err < 0) {
ALOGD("import() caught exception %d\n", err);
return ResponseCode::SYSTEM_ERROR;
}
auto outBlob = readBlobAsByteArray(reply);
if (out) {
// don't need to check outBlob.isOk()
// if !outBlob.isOk() the wrapped value is default constructed and therefore empty,
// as expected.
*out = outBlob.value();
}
return ResponseCode(reply.readInt32());
}
KeyStoreServiceReturnCode verify(const String16& name, const hidl_vec<uint8_t>& in,
const hidl_vec<uint8_t>& signature) override {
Parcel data, reply;
data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
data.writeString16(name);
writeBlobAsByteArray(in, &data);
writeBlobAsByteArray(signature, &data);
status_t status = remote()->transact(BnKeystoreService::VERIFY, data, &reply);
if (status != NO_ERROR) {
ALOGD("verify() could not contact remote: %d\n", status);
return ResponseCode::SYSTEM_ERROR;
}
int32_t err = reply.readExceptionCode();
if (err < 0) {
ALOGD("verify() caught exception %d\n", err);
return ResponseCode::SYSTEM_ERROR;
}
return ResponseCode(reply.readInt32());
}
KeyStoreServiceReturnCode get_pubkey(const String16& name, hidl_vec<uint8_t>* pubkey) override {
Parcel data, reply;
data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
data.writeString16(name);
status_t status = remote()->transact(BnKeystoreService::GET_PUBKEY, data, &reply);
if (status != NO_ERROR) {
ALOGD("get_pubkey() could not contact remote: %d\n", status);
return ResponseCode::SYSTEM_ERROR;
}
int32_t err = reply.readExceptionCode();
if (err < 0) {
ALOGD("get_pubkey() caught exception %d\n", err);
return ResponseCode::SYSTEM_ERROR;
}
auto resultKey = readBlobAsByteArray(reply);
if (pubkey) *pubkey = resultKey.value();
return ResponseCode(reply.readInt32());
}
KeyStoreServiceReturnCode grant(const String16& name, int32_t granteeUid) override {
Parcel data, reply;
data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
data.writeString16(name);
data.writeInt32(granteeUid);
status_t status = remote()->transact(BnKeystoreService::GRANT, data, &reply);
if (status != NO_ERROR) {
ALOGD("grant() could not contact remote: %d\n", status);
return ResponseCode::SYSTEM_ERROR;
}
int32_t err = reply.readExceptionCode();
if (err < 0) {
ALOGD("grant() caught exception %d\n", err);
return ResponseCode::SYSTEM_ERROR;
}
return ResponseCode(reply.readInt32());
}
KeyStoreServiceReturnCode ungrant(const String16& name, int32_t granteeUid) override {
Parcel data, reply;
data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
data.writeString16(name);
data.writeInt32(granteeUid);
status_t status = remote()->transact(BnKeystoreService::UNGRANT, data, &reply);
if (status != NO_ERROR) {
ALOGD("ungrant() could not contact remote: %d\n", status);
return ResponseCode::SYSTEM_ERROR;
}
int32_t err = reply.readExceptionCode();
if (err < 0) {
ALOGD("ungrant() caught exception %d\n", err);
return ResponseCode::SYSTEM_ERROR;
}
return ResponseCode(reply.readInt32());
}
int64_t getmtime(const String16& name, int32_t uid) override {
Parcel data, reply;
data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
data.writeString16(name);
data.writeInt32(uid);
status_t status = remote()->transact(BnKeystoreService::GETMTIME, data, &reply);
if (status != NO_ERROR) {
ALOGD("getmtime() could not contact remote: %d\n", status);
return -1;
}
int32_t err = reply.readExceptionCode();
if (err < 0) {
ALOGD("getmtime() caught exception %d\n", err);
return -1;
}
return reply.readInt64();
}
KeyStoreServiceReturnCode duplicate(const String16& srcKey, int32_t srcUid,
const String16& destKey, int32_t destUid) override {
Parcel data, reply;
data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
data.writeString16(srcKey);
data.writeInt32(srcUid);
data.writeString16(destKey);
data.writeInt32(destUid);
status_t status = remote()->transact(BnKeystoreService::DUPLICATE, data, &reply);
if (status != NO_ERROR) {
ALOGD("duplicate() could not contact remote: %d\n", status);
return ResponseCode::SYSTEM_ERROR;
}
int32_t err = reply.readExceptionCode();
if (err < 0) {
ALOGD("duplicate() caught exception %d\n", err);
return ResponseCode::SYSTEM_ERROR;
}
return ResponseCode(reply.readInt32());
}
int32_t is_hardware_backed(const String16& keyType) override {
Parcel data, reply;
data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
data.writeString16(keyType);
status_t status = remote()->transact(BnKeystoreService::IS_HARDWARE_BACKED, data, &reply);
if (status != NO_ERROR) {
ALOGD("is_hardware_backed() could not contact remote: %d\n", status);
return -1;
}
int32_t err = reply.readExceptionCode();
if (err < 0) {
ALOGD("is_hardware_backed() caught exception %d\n", err);
return -1;
}
return reply.readInt32();
}
KeyStoreServiceReturnCode clear_uid(int64_t uid) override {
Parcel data, reply;
data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
data.writeInt64(uid);
status_t status = remote()->transact(BnKeystoreService::CLEAR_UID, data, &reply);
if (status != NO_ERROR) {
ALOGD("clear_uid() could not contact remote: %d\n", status);
return ResponseCode::SYSTEM_ERROR;
}
int32_t err = reply.readExceptionCode();
if (err < 0) {
ALOGD("clear_uid() caught exception %d\n", err);
return ResponseCode::SYSTEM_ERROR;
}
return ResponseCode(reply.readInt32());
}
KeyStoreServiceReturnCode addRngEntropy(const hidl_vec<uint8_t>& entropy) override {
Parcel data, reply;
data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
writeBlobAsByteArray(entropy, &data);
status_t status = remote()->transact(BnKeystoreService::ADD_RNG_ENTROPY, data, &reply);
if (status != NO_ERROR) {
ALOGD("addRngEntropy() could not contact remote: %d\n", status);
return ResponseCode::SYSTEM_ERROR;
}
int32_t err = reply.readExceptionCode();
if (err < 0) {
ALOGD("addRngEntropy() caught exception %d\n", err);
return ResponseCode::SYSTEM_ERROR;
}
return ResponseCode(reply.readInt32());
};
KeyStoreServiceReturnCode generateKey(const String16& name,
const hidl_vec<KeyParameter>& params,
const hidl_vec<uint8_t>& entropy, int uid, int flags,
KeyCharacteristics* outCharacteristics) override {
Parcel data, reply;
data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
data.writeString16(name);
nullable(writeParamSetToParcel, params, &data);
writeBlobAsByteArray(entropy, &data);
data.writeInt32(uid);
data.writeInt32(flags);
status_t status = remote()->transact(BnKeystoreService::GENERATE_KEY, data, &reply);
if (status != NO_ERROR) {
ALOGD("generateKey() could not contact remote: %d\n", status);
return ResponseCode::SYSTEM_ERROR;
}
int32_t err = reply.readExceptionCode();
ResponseCode ret = ResponseCode(reply.readInt32());
if (err < 0) {
ALOGD("generateKey() caught exception %d\n", err);
return ResponseCode::SYSTEM_ERROR;
}
if (outCharacteristics) {
*outCharacteristics = nullable(readKeyCharacteristicsFromParcel, reply).value();
}
return ret;
}
KeyStoreServiceReturnCode
getKeyCharacteristics(const String16& name, const hidl_vec<uint8_t>& clientId,
const hidl_vec<uint8_t>& appData, int32_t uid,
KeyCharacteristics* outCharacteristics) override {
Parcel data, reply;
data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
data.writeString16(name);
writeBlobAsByteArray(clientId, &data);
writeBlobAsByteArray(appData, &data);
data.writeInt32(uid);
status_t status =
remote()->transact(BnKeystoreService::GET_KEY_CHARACTERISTICS, data, &reply);
if (status != NO_ERROR) {
ALOGD("getKeyCharacteristics() could not contact remote: %d\n", status);
return ResponseCode::SYSTEM_ERROR;
}
int32_t err = reply.readExceptionCode();
ResponseCode ret = ResponseCode(reply.readInt32());
if (err < 0) {
ALOGD("getKeyCharacteristics() caught exception %d\n", err);
return ResponseCode::SYSTEM_ERROR;
}
if (outCharacteristics) {
*outCharacteristics = nullable(readKeyCharacteristicsFromParcel, reply).value();
}
return ret;
}
KeyStoreServiceReturnCode importKey(const String16& name, const hidl_vec<KeyParameter>& params,
KeyFormat format, const hidl_vec<uint8_t>& keyData, int uid,
int flags,
KeyCharacteristics* outCharacteristics) override {
Parcel data, reply;
data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
data.writeString16(name);
nullable(writeParamSetToParcel, params, &data);
data.writeInt32(uint32_t(format));
writeBlobAsByteArray(keyData, &data);
data.writeInt32(uid);
data.writeInt32(flags);
status_t status = remote()->transact(BnKeystoreService::IMPORT_KEY, data, &reply);
if (status != NO_ERROR) {
ALOGD("importKey() could not contact remote: %d\n", status);
return ResponseCode::SYSTEM_ERROR;
}
int32_t err = reply.readExceptionCode();
ResponseCode ret = ResponseCode(reply.readInt32());
if (err < 0) {
ALOGD("importKey() caught exception %d\n", err);
return ResponseCode::SYSTEM_ERROR;
}
if (outCharacteristics) {
*outCharacteristics = nullable(readKeyCharacteristicsFromParcel, reply).value();
}
return ret;
}
void exportKey(const String16& name, KeyFormat format, const hidl_vec<uint8_t>& clientId,
const hidl_vec<uint8_t>& appData, int32_t uid, ExportResult* result) override {
if (!result) {
return;
}
Parcel data, reply;
data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
data.writeString16(name);
data.writeInt32(int32_t(format));
writeBlobAsByteArray(clientId, &data);
writeBlobAsByteArray(appData, &data);
data.writeInt32(uid);
status_t status = remote()->transact(BnKeystoreService::EXPORT_KEY, data, &reply);
if (status != NO_ERROR) {
ALOGD("exportKey() could not contact remote: %d\n", status);
result->resultCode = ResponseCode::SYSTEM_ERROR;
return;
}
int32_t err = reply.readExceptionCode();
if (err < 0) {
ALOGD("exportKey() caught exception %d\n", err);
result->resultCode = ResponseCode::SYSTEM_ERROR;
return;
}
reply.readParcelable(result);
}
void begin(const sp<IBinder>& appToken, const String16& name, KeyPurpose purpose,
bool pruneable, const hidl_vec<KeyParameter>& params,
const hidl_vec<uint8_t>& entropy, int32_t uid, OperationResult* result) override {
if (!result) {
return;
}
Parcel data, reply;
data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
data.writeStrongBinder(appToken);
data.writeString16(name);
data.writeInt32(int32_t(purpose));
data.writeInt32(pruneable ? 1 : 0);
nullable(writeParamSetToParcel, params, &data);
writeBlobAsByteArray(entropy, &data);
data.writeInt32(uid);
status_t status = remote()->transact(BnKeystoreService::BEGIN, data, &reply);
if (status != NO_ERROR) {
ALOGD("begin() could not contact remote: %d\n", status);
result->resultCode = ResponseCode::SYSTEM_ERROR;
return;
}
int32_t err = reply.readExceptionCode();
if (err < 0) {
ALOGD("begin() caught exception %d\n", err);
result->resultCode = ResponseCode::SYSTEM_ERROR;
return;
}
reply.readParcelable(result);
}
void update(const sp<IBinder>& token, const hidl_vec<KeyParameter>& params,
const hidl_vec<uint8_t>& opData, OperationResult* result) override {
if (!result) {
return;
}
Parcel data, reply;
data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
data.writeStrongBinder(token);
nullable(writeParamSetToParcel, params, &data);
writeBlobAsByteArray(opData, &data);
status_t status = remote()->transact(BnKeystoreService::UPDATE, data, &reply);
if (status != NO_ERROR) {
ALOGD("update() could not contact remote: %d\n", status);
result->resultCode = ResponseCode::SYSTEM_ERROR;
return;
}
int32_t err = reply.readExceptionCode();
if (err < 0) {
ALOGD("update() caught exception %d\n", err);
result->resultCode = ResponseCode::SYSTEM_ERROR;
return;
}
reply.readParcelable(result);
}
void finish(const sp<IBinder>& token, const hidl_vec<KeyParameter>& params,
const hidl_vec<uint8_t>& signature, const hidl_vec<uint8_t>& entropy,
OperationResult* result) override {
if (!result) {
return;
}
Parcel data, reply;
data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
data.writeStrongBinder(token);
nullable(writeParamSetToParcel, params, &data);
writeBlobAsByteArray(signature, &data);
writeBlobAsByteArray(entropy, &data);
status_t status = remote()->transact(BnKeystoreService::FINISH, data, &reply);
if (status != NO_ERROR) {
ALOGD("finish() could not contact remote: %d\n", status);
result->resultCode = ResponseCode::SYSTEM_ERROR;
return;
}
int32_t err = reply.readExceptionCode();
if (err < 0) {
ALOGD("finish() caught exception %d\n", err);
result->resultCode = ResponseCode::SYSTEM_ERROR;
return;
}
reply.readParcelable(result);
}
KeyStoreServiceReturnCode abort(const sp<IBinder>& token) override {
Parcel data, reply;
data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
data.writeStrongBinder(token);
status_t status = remote()->transact(BnKeystoreService::ABORT, data, &reply);
if (status != NO_ERROR) {
ALOGD("abort() could not contact remote: %d\n", status);
return ResponseCode::SYSTEM_ERROR;
}
int32_t err = reply.readExceptionCode();
if (err < 0) {
ALOGD("abort() caught exception %d\n", err);
return ResponseCode::SYSTEM_ERROR;
}
return ResponseCode(reply.readInt32());
}
bool isOperationAuthorized(const sp<IBinder>& token) override {
Parcel data, reply;
data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
data.writeStrongBinder(token);
status_t status =
remote()->transact(BnKeystoreService::IS_OPERATION_AUTHORIZED, data, &reply);
if (status != NO_ERROR) {
ALOGD("isOperationAuthorized() could not contact remote: %d\n", status);
return false;
}
int32_t err = reply.readExceptionCode();
if (err < 0) {
ALOGD("isOperationAuthorized() caught exception %d\n", err);
return false;
}
return reply.readInt32() == 1;
}
KeyStoreServiceReturnCode addAuthToken(const uint8_t* token, size_t length) override {
Parcel data, reply;
data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
data.writeByteArray(length, token);
status_t status = remote()->transact(BnKeystoreService::ADD_AUTH_TOKEN, data, &reply);
if (status != NO_ERROR) {
ALOGD("addAuthToken() could not contact remote: %d\n", status);
return ResponseCode::SYSTEM_ERROR;
}
int32_t err = reply.readExceptionCode();
if (err < 0) {
ALOGD("addAuthToken() caught exception %d\n", err);
return ResponseCode::SYSTEM_ERROR;
}
return ResponseCode(reply.readInt32());
};
KeyStoreServiceReturnCode onUserAdded(int32_t userId, int32_t parentId) override {
Parcel data, reply;
data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
data.writeInt32(userId);
data.writeInt32(parentId);
status_t status = remote()->transact(BnKeystoreService::ON_USER_ADDED, data, &reply);
if (status != NO_ERROR) {
ALOGD("onUserAdded() could not contact remote: %d\n", status);
return ResponseCode::SYSTEM_ERROR;
}
int32_t err = reply.readExceptionCode();
if (err < 0) {
ALOGD("onUserAdded() caught exception %d\n", err);
return ResponseCode::SYSTEM_ERROR;
}
return ResponseCode(reply.readInt32());
}
KeyStoreServiceReturnCode onUserRemoved(int32_t userId) override {
Parcel data, reply;
data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
data.writeInt32(userId);
status_t status = remote()->transact(BnKeystoreService::ON_USER_REMOVED, data, &reply);
if (status != NO_ERROR) {
ALOGD("onUserRemoved() could not contact remote: %d\n", status);
return ResponseCode::SYSTEM_ERROR;
}
int32_t err = reply.readExceptionCode();
if (err < 0) {
ALOGD("onUserRemoved() caught exception %d\n", err);
return ResponseCode::SYSTEM_ERROR;
}
return ResponseCode(reply.readInt32());
}
KeyStoreServiceReturnCode attestKey(const String16& name, const hidl_vec<KeyParameter>& params,
hidl_vec<hidl_vec<uint8_t>>* outChain) override {
if (!outChain) return ErrorCode::OUTPUT_PARAMETER_NULL;
Parcel data, reply;
data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
data.writeString16(name);
nullable(writeParamSetToParcel, params, &data);
status_t status = remote()->transact(BnKeystoreService::ATTEST_KEY, data, &reply);
if (status != NO_ERROR) {
ALOGD("attestkey() count not contact remote: %d\n", status);
return ResponseCode::SYSTEM_ERROR;
}
int32_t err = reply.readExceptionCode();
ResponseCode ret = ResponseCode(reply.readInt32());
if (err < 0) {
ALOGD("attestKey() caught exception %d\n", err);
return ResponseCode::SYSTEM_ERROR;
}
if (reply.readInt32() != 0) {
*outChain = readCertificateChainFromParcel(reply);
}
return ret;
}
KeyStoreServiceReturnCode attestDeviceIds(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());
nullable(writeParamSetToParcel, params, &data);
status_t status = remote()->transact(BnKeystoreService::ATTEST_DEVICE_IDS, data, &reply);
if (status != NO_ERROR) {
ALOGD("attestDeviceIds() count not contact remote: %d\n", status);
return ResponseCode::SYSTEM_ERROR;
}
int32_t err = reply.readExceptionCode();
ResponseCode ret = ResponseCode(reply.readInt32());
if (err < 0) {
ALOGD("attestDeviceIds() caught exception %d\n", err);
return ResponseCode::SYSTEM_ERROR;
}
if (reply.readInt32() != 0) {
*outChain = readCertificateChainFromParcel(reply);
}
return ret;
}
KeyStoreServiceReturnCode onDeviceOffBody() override {
Parcel data, reply;
data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
status_t status = remote()->transact(BnKeystoreService::ON_DEVICE_OFF_BODY, data, &reply);
if (status != NO_ERROR) {
ALOGD("onDeviceOffBody() could not contact remote: %d\n", status);
return ResponseCode::SYSTEM_ERROR;
}
int32_t err = reply.readExceptionCode();
if (err < 0) {
ALOGD("onDeviceOffBody() caught exception %d\n", err);
return ResponseCode::SYSTEM_ERROR;
}
return ResponseCode(reply.readInt32());
}
};
IMPLEMENT_META_INTERFACE(KeystoreService, "android.security.IKeystoreService");
// ----------------------------------------------------------------------
status_t BnKeystoreService::onTransact(uint32_t code, const Parcel& data, Parcel* reply,
uint32_t flags) {
switch (code) {
case GET_STATE: {
CHECK_INTERFACE(IKeystoreService, data, reply);
int32_t userId = data.readInt32();
int32_t ret = getState(userId);
reply->writeNoException();
reply->writeInt32(ret);
return NO_ERROR;
} break;
case GET: {
CHECK_INTERFACE(IKeystoreService, data, reply);
String16 name = data.readString16();
int32_t uid = data.readInt32();
hidl_vec<uint8_t> out;
auto ret = get(name, uid, &out);
reply->writeNoException();
if (ret.isOk()) {
writeBlobAsByteArray(out, reply);
} else {
reply->writeInt32(-1);
}
reply->writeInt32(ret);
return NO_ERROR;
} break;
case INSERT: {
CHECK_INTERFACE(IKeystoreService, data, reply);
String16 name = data.readString16();
auto in = readBlobAsByteArray(data);
int uid = data.readInt32();
int32_t flags = data.readInt32();
int32_t ret = insert(name, in.value(), uid, flags);
reply->writeNoException();
reply->writeInt32(ret);
return NO_ERROR;
} break;
case DEL: {
CHECK_INTERFACE(IKeystoreService, data, reply);
String16 name = data.readString16();
int uid = data.readInt32();
int32_t ret = del(name, uid);
reply->writeNoException();
reply->writeInt32(ret);
return NO_ERROR;
} break;
case EXIST: {
CHECK_INTERFACE(IKeystoreService, data, reply);
String16 name = data.readString16();
int uid = data.readInt32();
int32_t ret = exist(name, uid);
reply->writeNoException();
reply->writeInt32(ret);
return NO_ERROR;
} break;
case LIST: {
CHECK_INTERFACE(IKeystoreService, data, reply);
String16 prefix = data.readString16();
int uid = data.readInt32();
Vector<String16> matches;
int32_t ret = list(prefix, uid, &matches);
reply->writeNoException();
reply->writeInt32(matches.size());
Vector<String16>::const_iterator it = matches.begin();
for (; it != matches.end(); ++it) {
reply->writeString16(*it);
}
reply->writeInt32(ret);
return NO_ERROR;
} break;
case RESET: {
CHECK_INTERFACE(IKeystoreService, data, reply);
int32_t ret = reset();
reply->writeNoException();
reply->writeInt32(ret);
return NO_ERROR;
} break;
case ON_USER_PASSWORD_CHANGED: {
CHECK_INTERFACE(IKeystoreService, data, reply);
int32_t userId = data.readInt32();
String16 pass = data.readString16();
int32_t ret = onUserPasswordChanged(userId, pass);
reply->writeNoException();
reply->writeInt32(ret);
return NO_ERROR;
} break;
case LOCK: {
CHECK_INTERFACE(IKeystoreService, data, reply);
int32_t userId = data.readInt32();
int32_t ret = lock(userId);
reply->writeNoException();
reply->writeInt32(ret);
return NO_ERROR;
} break;
case UNLOCK: {
CHECK_INTERFACE(IKeystoreService, data, reply);
int32_t userId = data.readInt32();
String16 pass = data.readString16();
int32_t ret = unlock(userId, pass);
reply->writeNoException();
reply->writeInt32(ret);
return NO_ERROR;
} break;
case IS_EMPTY: {
CHECK_INTERFACE(IKeystoreService, data, reply);
int32_t userId = data.readInt32();
bool ret = isEmpty(userId);
reply->writeNoException();
reply->writeInt32(ret ? 1 : 0);
return NO_ERROR;
} break;
case GENERATE: {
CHECK_INTERFACE(IKeystoreService, data, reply);
String16 name = data.readString16();
int32_t uid = data.readInt32();
int32_t keyType = data.readInt32();
int32_t keySize = data.readInt32();
int32_t flags = data.readInt32();
Vector<sp<KeystoreArg>> args;
int32_t argsPresent = data.readInt32();
if (argsPresent == 1) {
ssize_t numArgs = data.readInt32();
if (numArgs > MAX_GENERATE_ARGS) {
return BAD_VALUE;
}
if (numArgs > 0) {
for (size_t i = 0; i < (size_t)numArgs; i++) {
ssize_t inSize = data.readInt32();
if (inSize >= 0 && (size_t)inSize <= data.dataAvail()) {
sp<KeystoreArg> arg = new KeystoreArg(data.readInplace(inSize), inSize);
args.push_back(arg);
} else {
args.push_back(NULL);
}
}
}
}
int32_t ret = generate(name, uid, keyType, keySize, flags, &args);
reply->writeNoException();
reply->writeInt32(ret);
return NO_ERROR;
} break;
case IMPORT: {
CHECK_INTERFACE(IKeystoreService, data, reply);
String16 name = data.readString16();
auto in = readBlobAsByteArray(data);
int uid = data.readInt32();
int32_t flags = data.readInt32();
auto ret = import(name, in.value(), uid, flags);
reply->writeNoException();
reply->writeInt32(ret);
return NO_ERROR;
} break;
case SIGN: {
CHECK_INTERFACE(IKeystoreService, data, reply);
String16 name = data.readString16();
auto in = readBlobAsByteArray(data);
hidl_vec<uint8_t> out;
auto ret = sign(name, in.value(), &out);
reply->writeNoException();
writeBlobAsByteArray(out, reply);
reply->writeInt32(ret);
return NO_ERROR;
} break;
case VERIFY: {
CHECK_INTERFACE(IKeystoreService, data, reply);
String16 name = data.readString16();
auto in = readBlobAsByteArray(data);
auto signature = readBlobAsByteArray(data);
auto ret = verify(name, in.value(), signature.value());
reply->writeNoException();
reply->writeInt32(ret);
return NO_ERROR;
} break;
case GET_PUBKEY: {
CHECK_INTERFACE(IKeystoreService, data, reply);
String16 name = data.readString16();
hidl_vec<uint8_t> out;
auto ret = get_pubkey(name, &out);
reply->writeNoException();
writeBlobAsByteArray(out, reply);
reply->writeInt32(ret);
return NO_ERROR;
} break;
case GRANT: {
CHECK_INTERFACE(IKeystoreService, data, reply);
String16 name = data.readString16();
int32_t granteeUid = data.readInt32();
int32_t ret = grant(name, granteeUid);
reply->writeNoException();
reply->writeInt32(ret);
return NO_ERROR;
} break;
case UNGRANT: {
CHECK_INTERFACE(IKeystoreService, data, reply);
String16 name = data.readString16();
int32_t granteeUid = data.readInt32();
int32_t ret = ungrant(name, granteeUid);
reply->writeNoException();
reply->writeInt32(ret);
return NO_ERROR;
} break;
case GETMTIME: {
CHECK_INTERFACE(IKeystoreService, data, reply);
String16 name = data.readString16();
int32_t uid = data.readInt32();
int64_t ret = getmtime(name, uid);
reply->writeNoException();
reply->writeInt64(ret);
return NO_ERROR;
} break;
case DUPLICATE: {
CHECK_INTERFACE(IKeystoreService, data, reply);
String16 srcKey = data.readString16();
int32_t srcUid = data.readInt32();
String16 destKey = data.readString16();
int32_t destUid = data.readInt32();
int32_t ret = duplicate(srcKey, srcUid, destKey, destUid);
reply->writeNoException();
reply->writeInt32(ret);
return NO_ERROR;
} break;
case IS_HARDWARE_BACKED: {
CHECK_INTERFACE(IKeystoreService, data, reply);
String16 keyType = data.readString16();
int32_t ret = is_hardware_backed(keyType);
reply->writeNoException();
reply->writeInt32(ret);
return NO_ERROR;
}
case CLEAR_UID: {
CHECK_INTERFACE(IKeystoreService, data, reply);
int64_t uid = data.readInt64();
int32_t ret = clear_uid(uid);
reply->writeNoException();
reply->writeInt32(ret);
return NO_ERROR;
}
case ADD_RNG_ENTROPY: {
CHECK_INTERFACE(IKeystoreService, data, reply);
auto entropy = readBlobAsByteArray(data);
auto ret = addRngEntropy(entropy.value());
reply->writeNoException();
reply->writeInt32(ret);
return NO_ERROR;
}
case GENERATE_KEY: {
CHECK_INTERFACE(IKeystoreService, data, reply);
String16 name = data.readString16();
auto params = nullable(readParamSetFromParcel, data);
auto entropy = readBlobAsByteArray(data);
int32_t uid = data.readInt32();
int32_t flags = data.readInt32();
KeyCharacteristics outCharacteristics;
int32_t ret =
generateKey(name, params.value(), entropy.value(), uid, flags, &outCharacteristics);
reply->writeNoException();
reply->writeInt32(ret);
nullable(writeKeyCharacteristicsToParcel, outCharacteristics, reply);
return NO_ERROR;
}
case GET_KEY_CHARACTERISTICS: {
CHECK_INTERFACE(IKeystoreService, data, reply);
String16 name = data.readString16();
auto clientId = nullable(readKeymasterBlob, data, true);
auto appData = nullable(readKeymasterBlob, data, true);
int32_t uid = data.readInt32();
KeyCharacteristics outCharacteristics;
int ret = getKeyCharacteristics(name, clientId.value(), appData.value(), uid,
&outCharacteristics);
reply->writeNoException();
reply->writeInt32(ret);
nullable(writeKeyCharacteristicsToParcel, outCharacteristics, reply);
return NO_ERROR;
}
case IMPORT_KEY: {
CHECK_INTERFACE(IKeystoreService, data, reply);
String16 name = data.readString16();
auto args = nullable(readParamSetFromParcel, data);
KeyFormat format = static_cast<KeyFormat>(data.readInt32());
auto keyData = readBlobAsByteArray(data);
int32_t uid = data.readInt32();
int32_t flags = data.readInt32();
KeyCharacteristics outCharacteristics;
int32_t ret =
importKey(name, args.value(), format, keyData.value(), uid, flags, &outCharacteristics);
reply->writeNoException();
reply->writeInt32(ret);
nullable(writeKeyCharacteristicsToParcel, outCharacteristics, reply);
return NO_ERROR;
}
case EXPORT_KEY: {
CHECK_INTERFACE(IKeystoreService, data, reply);
String16 name = data.readString16();
KeyFormat format = static_cast<KeyFormat>(data.readInt32());
auto clientId = nullable(readKeymasterBlob, data, true);
auto appData = nullable(readKeymasterBlob, data, true);
int32_t uid = data.readInt32();
ExportResult result;
exportKey(name, format, clientId.value(), appData.value(), uid, &result);
reply->writeNoException();
reply->writeParcelable(result);
return NO_ERROR;
}
case BEGIN: {
CHECK_INTERFACE(IKeystoreService, data, reply);
sp<IBinder> token = data.readStrongBinder();
String16 name = data.readString16();
KeyPurpose purpose = static_cast<KeyPurpose>(data.readInt32());
bool pruneable = data.readInt32() != 0;
auto args = nullable(readParamSetFromParcel, data);
auto entropy = readBlobAsByteArray(data);
int32_t uid = data.readInt32();
OperationResult result;
begin(token, name, purpose, pruneable, args.value(), entropy.value(), uid, &result);
reply->writeNoException();
reply->writeParcelable(result);
return NO_ERROR;
}
case UPDATE: {
CHECK_INTERFACE(IKeystoreService, data, reply);
sp<IBinder> token = data.readStrongBinder();
auto args = nullable(readParamSetFromParcel, data);
auto buf = readBlobAsByteArray(data);
OperationResult result;
update(token, args.value(), buf.value(), &result);
reply->writeNoException();
reply->writeParcelable(result);
return NO_ERROR;
}
case FINISH: {
CHECK_INTERFACE(IKeystoreService, data, reply);
sp<IBinder> token = data.readStrongBinder();
auto args = nullable(readParamSetFromParcel, data);
auto signature = readBlobAsByteArray(data);
auto entropy = readBlobAsByteArray(data);
OperationResult result;
finish(token, args.value(), signature.value(), entropy.value(), &result);
reply->writeNoException();
reply->writeParcelable(result);
return NO_ERROR;
}
case ABORT: {
CHECK_INTERFACE(IKeystoreService, data, reply);
sp<IBinder> token = data.readStrongBinder();
int32_t result = abort(token);
reply->writeNoException();
reply->writeInt32(result);
return NO_ERROR;
}
case IS_OPERATION_AUTHORIZED: {
CHECK_INTERFACE(IKeystoreService, data, reply);
sp<IBinder> token = data.readStrongBinder();
bool result = isOperationAuthorized(token);
reply->writeNoException();
reply->writeInt32(result ? 1 : 0);
return NO_ERROR;
}
case ADD_AUTH_TOKEN: {
CHECK_INTERFACE(IKeystoreService, data, reply);
const uint8_t* token_bytes = NULL;
size_t size = 0;
readByteArray(data, &token_bytes, &size);
int32_t result = addAuthToken(token_bytes, size);
reply->writeNoException();
reply->writeInt32(result);
return NO_ERROR;
}
case ON_USER_ADDED: {
CHECK_INTERFACE(IKeystoreService, data, reply);
int32_t userId = data.readInt32();
int32_t parentId = data.readInt32();
int32_t result = onUserAdded(userId, parentId);
reply->writeNoException();
reply->writeInt32(result);
return NO_ERROR;
}
case ON_USER_REMOVED: {
CHECK_INTERFACE(IKeystoreService, data, reply);
int32_t userId = data.readInt32();
int32_t result = onUserRemoved(userId);
reply->writeNoException();
reply->writeInt32(result);
return NO_ERROR;
}
case ATTEST_KEY: {
CHECK_INTERFACE(IKeystoreService, data, reply);
String16 name = data.readString16();
auto params = nullable(readParamSetFromParcel, data);
hidl_vec<hidl_vec<uint8_t>> chain;
int ret = attestKey(name, params.value(), &chain);
reply->writeNoException();
reply->writeInt32(ret);
nullable(writeCertificateChainToParcel, chain, reply);
return NO_ERROR;
}
case ATTEST_DEVICE_IDS: {
CHECK_INTERFACE(IKeystoreService, data, reply);
auto params = nullable(readParamSetFromParcel, data);
hidl_vec<hidl_vec<uint8_t>> chain;
int ret = attestDeviceIds(params.value(), &chain);
reply->writeNoException();
reply->writeInt32(ret);
nullable(writeCertificateChainToParcel, chain, reply);
return NO_ERROR;
}
case ON_DEVICE_OFF_BODY: {
CHECK_INTERFACE(IKeystoreService, data, reply);
int32_t ret = onDeviceOffBody();
reply->writeNoException();
reply->writeInt32(ret);
return NO_ERROR;
}
default:
return BBinder::onTransact(code, data, reply, flags);
}
}
// ----------------------------------------------------------------------------
}; // namespace android