blob: 9b4590e9b826f4146a4f3bd6e25e528bdd9b3289 [file] [log] [blame]
/*
**
** 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/types.h>
#define LOG_TAG "KeystoreService"
#include <utils/Log.h>
#include <binder/Parcel.h>
#include <binder/IPCThreadState.h>
#include <binder/IServiceManager.h>
#include <keystore/IKeystoreService.h>
namespace android {
class BpKeystoreService: public BpInterface<IKeystoreService>
{
public:
BpKeystoreService(const sp<IBinder>& impl)
: BpInterface<IKeystoreService>(impl)
{
}
// test ping
virtual int32_t test()
{
Parcel data, reply;
data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
status_t status = remote()->transact(BnKeystoreService::TEST, data, &reply);
if (status != NO_ERROR) {
ALOGD("test() could not contact remote: %d\n", status);
return -1;
}
int32_t err = reply.readExceptionCode();
int32_t ret = reply.readInt32();
if (err < 0) {
ALOGD("test() caught exception %d\n", err);
return -1;
}
return ret;
}
virtual int32_t get(const String16& name, uint8_t** item, size_t* itemLength)
{
Parcel data, reply;
data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
data.writeString16(name);
status_t status = remote()->transact(BnKeystoreService::GET, data, &reply);
if (status != NO_ERROR) {
ALOGD("get() could not contact remote: %d\n", status);
return -1;
}
int32_t err = reply.readExceptionCode();
ssize_t len = reply.readInt32();
if (len >= 0 && (size_t) len <= reply.dataAvail()) {
size_t ulen = (size_t) len;
const void* buf = reply.readInplace(ulen);
*item = (uint8_t*) malloc(ulen);
if (*item != NULL) {
memcpy(*item, buf, ulen);
*itemLength = ulen;
} else {
ALOGE("out of memory allocating output array in get");
*itemLength = 0;
}
} else {
*itemLength = 0;
}
if (err < 0) {
ALOGD("get() caught exception %d\n", err);
return -1;
}
return 0;
}
virtual int32_t insert(const String16& name, const uint8_t* item, size_t itemLength)
{
Parcel data, reply;
data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
data.writeString16(name);
data.writeInt32(itemLength);
void* buf = data.writeInplace(itemLength);
memcpy(buf, item, itemLength);
status_t status = remote()->transact(BnKeystoreService::INSERT, data, &reply);
if (status != NO_ERROR) {
ALOGD("import() could not contact remote: %d\n", status);
return -1;
}
int32_t err = reply.readExceptionCode();
int32_t ret = reply.readInt32();
if (err < 0) {
ALOGD("import() caught exception %d\n", err);
return -1;
}
return ret;
}
virtual int32_t del(const String16& name)
{
Parcel data, reply;
data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
data.writeString16(name);
status_t status = remote()->transact(BnKeystoreService::DEL, data, &reply);
if (status != NO_ERROR) {
ALOGD("del() could not contact remote: %d\n", status);
return -1;
}
int32_t err = reply.readExceptionCode();
int32_t ret = reply.readInt32();
if (err < 0) {
ALOGD("del() caught exception %d\n", err);
return -1;
}
return ret;
}
virtual int32_t exist(const String16& name)
{
Parcel data, reply;
data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
data.writeString16(name);
status_t status = remote()->transact(BnKeystoreService::EXIST, data, &reply);
if (status != NO_ERROR) {
ALOGD("exist() could not contact remote: %d\n", status);
return -1;
}
int32_t err = reply.readExceptionCode();
int32_t ret = reply.readInt32();
if (err < 0) {
ALOGD("exist() caught exception %d\n", err);
return -1;
}
return ret;
}
virtual int32_t saw(const String16& name, Vector<String16>* matches)
{
Parcel data, reply;
data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
data.writeString16(name);
status_t status = remote()->transact(BnKeystoreService::SAW, data, &reply);
if (status != NO_ERROR) {
ALOGD("saw() could not contact remote: %d\n", status);
return -1;
}
int32_t err = reply.readExceptionCode();
int32_t numMatches = reply.readInt32();
for (int32_t i = 0; i < numMatches; i++) {
matches->push(reply.readString16());
}
int32_t ret = reply.readInt32();
if (err < 0) {
ALOGD("saw() caught exception %d\n", err);
return -1;
}
return ret;
}
virtual int32_t reset()
{
Parcel data, reply;
data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
status_t status = remote()->transact(BnKeystoreService::RESET, data, &reply);
if (status != NO_ERROR) {
ALOGD("reset() could not contact remote: %d\n", status);
return -1;
}
int32_t err = reply.readExceptionCode();
int32_t ret = reply.readInt32();
if (err < 0) {
ALOGD("reset() caught exception %d\n", err);
return -1;
}
return ret;
}
virtual int32_t password(const String16& password)
{
Parcel data, reply;
data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
data.writeString16(password);
status_t status = remote()->transact(BnKeystoreService::PASSWORD, data, &reply);
if (status != NO_ERROR) {
ALOGD("password() could not contact remote: %d\n", status);
return -1;
}
int32_t err = reply.readExceptionCode();
int32_t ret = reply.readInt32();
if (err < 0) {
ALOGD("password() caught exception %d\n", err);
return -1;
}
return ret;
}
virtual int32_t lock()
{
Parcel data, reply;
data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
status_t status = remote()->transact(BnKeystoreService::LOCK, data, &reply);
if (status != NO_ERROR) {
ALOGD("lock() could not contact remote: %d\n", status);
return -1;
}
int32_t err = reply.readExceptionCode();
int32_t ret = reply.readInt32();
if (err < 0) {
ALOGD("lock() caught exception %d\n", err);
return -1;
}
return ret;
}
virtual int32_t unlock(const String16& password)
{
Parcel data, reply;
data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
data.writeString16(password);
status_t status = remote()->transact(BnKeystoreService::UNLOCK, data, &reply);
if (status != NO_ERROR) {
ALOGD("unlock() could not contact remote: %d\n", status);
return -1;
}
int32_t err = reply.readExceptionCode();
int32_t ret = reply.readInt32();
if (err < 0) {
ALOGD("unlock() caught exception %d\n", err);
return -1;
}
return ret;
}
virtual int32_t zero()
{
Parcel data, reply;
data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
status_t status = remote()->transact(BnKeystoreService::ZERO, data, &reply);
if (status != NO_ERROR) {
ALOGD("zero() could not contact remote: %d\n", status);
return -1;
}
int32_t err = reply.readExceptionCode();
int32_t ret = reply.readInt32();
if (err < 0) {
ALOGD("zero() caught exception %d\n", err);
return -1;
}
return ret;
}
virtual int32_t generate(const String16& name)
{
Parcel data, reply;
data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
data.writeString16(name);
status_t status = remote()->transact(BnKeystoreService::GENERATE, data, &reply);
if (status != NO_ERROR) {
ALOGD("generate() could not contact remote: %d\n", status);
return -1;
}
int32_t err = reply.readExceptionCode();
int32_t ret = reply.readInt32();
if (err < 0) {
ALOGD("generate() caught exception %d\n", err);
return -1;
}
return ret;
}
virtual int32_t import(const String16& name, const uint8_t* key, size_t keyLength)
{
Parcel data, reply;
data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
data.writeString16(name);
data.writeInt32(keyLength);
void* buf = data.writeInplace(keyLength);
memcpy(buf, key, keyLength);
status_t status = remote()->transact(BnKeystoreService::IMPORT, data, &reply);
if (status != NO_ERROR) {
ALOGD("import() could not contact remote: %d\n", status);
return -1;
}
int32_t err = reply.readExceptionCode();
int32_t ret = reply.readInt32();
if (err < 0) {
ALOGD("import() caught exception %d\n", err);
return -1;
}
return ret;
}
virtual int32_t sign(const String16& name, const uint8_t* in, size_t inLength, uint8_t** out,
size_t* outLength)
{
Parcel data, reply;
data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
data.writeString16(name);
data.writeInt32(inLength);
void* buf = data.writeInplace(inLength);
memcpy(buf, in, inLength);
status_t status = remote()->transact(BnKeystoreService::SIGN, data, &reply);
if (status != NO_ERROR) {
ALOGD("import() could not contact remote: %d\n", status);
return -1;
}
int32_t err = reply.readExceptionCode();
ssize_t len = reply.readInt32();
if (len >= 0 && (size_t) len <= reply.dataAvail()) {
size_t ulen = (size_t) len;
const void* outBuf = reply.readInplace(ulen);
*out = (uint8_t*) malloc(ulen);
if (*out != NULL) {
memcpy((void*) *out, outBuf, ulen);
*outLength = ulen;
} else {
ALOGE("out of memory allocating output array in sign");
*outLength = 0;
}
} else {
*outLength = 0;
}
if (err < 0) {
ALOGD("import() caught exception %d\n", err);
return -1;
}
return 0;
}
virtual int32_t verify(const String16& name, const uint8_t* in, size_t inLength,
const uint8_t* signature, size_t signatureLength)
{
Parcel data, reply;
void* buf;
data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
data.writeString16(name);
data.writeInt32(inLength);
buf = data.writeInplace(inLength);
memcpy(buf, in, inLength);
data.writeInt32(signatureLength);
buf = data.writeInplace(signatureLength);
memcpy(buf, signature, signatureLength);
status_t status = remote()->transact(BnKeystoreService::VERIFY, data, &reply);
if (status != NO_ERROR) {
ALOGD("verify() could not contact remote: %d\n", status);
return -1;
}
int32_t err = reply.readExceptionCode();
int32_t ret = reply.readInt32();
if (err < 0) {
ALOGD("verify() caught exception %d\n", err);
return -1;
}
return ret;
}
virtual int32_t get_pubkey(const String16& name, uint8_t** pubkey, size_t* pubkeyLength)
{
Parcel data, reply;
data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
data.writeString16(name);
status_t status = remote()->transact(BnKeystoreService::GET_PUBKEY, data, &reply);
if (status != NO_ERROR) {
ALOGD("get_pubkey() could not contact remote: %d\n", status);
return -1;
}
int32_t err = reply.readExceptionCode();
ssize_t len = reply.readInt32();
if (len >= 0 && (size_t) len <= reply.dataAvail()) {
size_t ulen = (size_t) len;
const void* buf = reply.readInplace(ulen);
*pubkey = (uint8_t*) malloc(ulen);
if (*pubkey != NULL) {
memcpy(*pubkey, buf, ulen);
*pubkeyLength = ulen;
} else {
ALOGE("out of memory allocating output array in get_pubkey");
*pubkeyLength = 0;
}
} else {
*pubkeyLength = 0;
}
if (err < 0) {
ALOGD("get_pubkey() caught exception %d\n", err);
return -1;
}
return 0;
}
virtual int32_t del_key(const String16& name)
{
Parcel data, reply;
data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
data.writeString16(name);
status_t status = remote()->transact(BnKeystoreService::DEL_KEY, data, &reply);
if (status != NO_ERROR) {
ALOGD("del_key() could not contact remote: %d\n", status);
return -1;
}
int32_t err = reply.readExceptionCode();
int32_t ret = reply.readInt32();
if (err < 0) {
ALOGD("del_key() caught exception %d\n", err);
return -1;
}
return ret;
}
virtual int32_t grant(const String16& name, int32_t granteeUid)
{
Parcel data, reply;
data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
data.writeString16(name);
data.writeInt32(granteeUid);
status_t status = remote()->transact(BnKeystoreService::GRANT, data, &reply);
if (status != NO_ERROR) {
ALOGD("grant() could not contact remote: %d\n", status);
return -1;
}
int32_t err = reply.readExceptionCode();
int32_t ret = reply.readInt32();
if (err < 0) {
ALOGD("grant() caught exception %d\n", err);
return -1;
}
return ret;
}
virtual int32_t ungrant(const String16& name, int32_t granteeUid)
{
Parcel data, reply;
data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
data.writeString16(name);
data.writeInt32(granteeUid);
status_t status = remote()->transact(BnKeystoreService::UNGRANT, data, &reply);
if (status != NO_ERROR) {
ALOGD("ungrant() could not contact remote: %d\n", status);
return -1;
}
int32_t err = reply.readExceptionCode();
int32_t ret = reply.readInt32();
if (err < 0) {
ALOGD("ungrant() caught exception %d\n", err);
return -1;
}
return ret;
}
int64_t getmtime(const String16& name)
{
Parcel data, reply;
data.writeInterfaceToken(IKeystoreService::getInterfaceDescriptor());
data.writeString16(name);
status_t status = remote()->transact(BnKeystoreService::GETMTIME, data, &reply);
if (status != NO_ERROR) {
ALOGD("getmtime() could not contact remote: %d\n", status);
return -1;
}
int32_t err = reply.readExceptionCode();
int64_t ret = reply.readInt64();
if (err < 0) {
ALOGD("getmtime() caught exception %d\n", err);
return -1;
}
return ret;
}
};
IMPLEMENT_META_INTERFACE(KeystoreService, "android.security.keystore");
// ----------------------------------------------------------------------
status_t BnKeystoreService::onTransact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
switch(code) {
case TEST: {
CHECK_INTERFACE(IKeystoreService, data, reply);
int32_t ret = test();
reply->writeNoException();
reply->writeInt32(ret);
return NO_ERROR;
} break;
case GET: {
CHECK_INTERFACE(IKeystoreService, data, reply);
String16 name = data.readString16();
void* out = NULL;
size_t outSize = 0;
int32_t ret = get(name, (uint8_t**) &out, &outSize);
reply->writeNoException();
if (ret == 1) {
reply->writeInt32(outSize);
void* buf = reply->writeInplace(outSize);
memcpy(buf, out, outSize);
free(out);
} else {
reply->writeInt32(-1);
}
return NO_ERROR;
} break;
case INSERT: {
CHECK_INTERFACE(IKeystoreService, data, reply);
String16 name = data.readString16();
ssize_t inSize = data.readInt32();
const void* in;
if (inSize >= 0 && (size_t) inSize <= data.dataAvail()) {
in = data.readInplace(inSize);
} else {
in = NULL;
inSize = 0;
}
int32_t ret = insert(name, (const uint8_t*) in, (size_t) inSize);
reply->writeNoException();
reply->writeInt32(ret);
return NO_ERROR;
} break;
case DEL: {
CHECK_INTERFACE(IKeystoreService, data, reply);
String16 name = data.readString16();
int32_t ret = del(name);
reply->writeNoException();
reply->writeInt32(ret);
return NO_ERROR;
} break;
case EXIST: {
CHECK_INTERFACE(IKeystoreService, data, reply);
String16 name = data.readString16();
int32_t ret = exist(name);
reply->writeNoException();
reply->writeInt32(ret);
return NO_ERROR;
} break;
case SAW: {
CHECK_INTERFACE(IKeystoreService, data, reply);
String16 name = data.readString16();
Vector<String16> matches;
int32_t ret = saw(name, &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 PASSWORD: {
CHECK_INTERFACE(IKeystoreService, data, reply);
String16 pass = data.readString16();
int32_t ret = password(pass);
reply->writeNoException();
reply->writeInt32(ret);
return NO_ERROR;
} break;
case LOCK: {
CHECK_INTERFACE(IKeystoreService, data, reply);
int32_t ret = lock();
reply->writeNoException();
reply->writeInt32(ret);
return NO_ERROR;
} break;
case UNLOCK: {
CHECK_INTERFACE(IKeystoreService, data, reply);
String16 pass = data.readString16();
int32_t ret = unlock(pass);
reply->writeNoException();
reply->writeInt32(ret);
return NO_ERROR;
} break;
case ZERO: {
CHECK_INTERFACE(IKeystoreService, data, reply);
int32_t ret = zero();
reply->writeNoException();
reply->writeInt32(ret);
return NO_ERROR;
} break;
case GENERATE: {
CHECK_INTERFACE(IKeystoreService, data, reply);
String16 name = data.readString16();
int32_t ret = generate(name);
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;
}
int32_t ret = import(name, (const uint8_t*) in, (size_t) inSize);
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();
reply->writeInt32(outSize);
void* buf = reply->writeInplace(outSize);
memcpy(buf, out, outSize);
free(out);
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();
reply->writeInt32(outSize);
void* buf = reply->writeInplace(outSize);
memcpy(buf, out, outSize);
free(out);
reply->writeInt32(ret);
return NO_ERROR;
}
case DEL_KEY: {
CHECK_INTERFACE(IKeystoreService, data, reply);
String16 name = data.readString16();
int32_t ret = del_key(name);
reply->writeNoException();
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();
int64_t ret = getmtime(name);
reply->writeNoException();
reply->writeInt64(ret);
return NO_ERROR;
} break;
default:
return BBinder::onTransact(code, data, reply, flags);
}
}
// ----------------------------------------------------------------------------
}; // namespace android