GateKeeper proxy service
Until we have SELinux support for gating access to individual TEE services, we will proxy TEE requests to GateKeeper via this daemon. Change-Id: Ifa316b75f75bff79bdae613a112c8c3c2e7189a8
This commit is contained in:
parent
56b8a6a59f
commit
2d08dce0be
5 changed files with 349 additions and 0 deletions
29
gatekeeperd/Android.mk
Normal file
29
gatekeeperd/Android.mk
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
#
|
||||
# Copyright (C) 2015 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.
|
||||
#
|
||||
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_CFLAGS := -Wall -Wextra -Werror -Wunused
|
||||
LOCAL_SRC_FILES := IGateKeeperService.cpp gatekeeperd.cpp
|
||||
LOCAL_MODULE := gatekeeperd
|
||||
LOCAL_SHARED_LIBRARIES := \
|
||||
libbinder \
|
||||
liblog \
|
||||
libhardware \
|
||||
libutils \
|
||||
libkeystore_binder
|
||||
include $(BUILD_EXECUTABLE)
|
||||
93
gatekeeperd/IGateKeeperService.cpp
Normal file
93
gatekeeperd/IGateKeeperService.cpp
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
/*
|
||||
* Copyright 2015, 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.
|
||||
*/
|
||||
|
||||
#define LOG_TAG "GateKeeperService"
|
||||
#include <utils/Log.h>
|
||||
|
||||
#include "IGateKeeperService.h"
|
||||
|
||||
namespace android {
|
||||
|
||||
const android::String16 IGateKeeperService::descriptor("android.service.gatekeeper.IGateKeeperService");
|
||||
const android::String16& IGateKeeperService::getInterfaceDescriptor() const {
|
||||
return IGateKeeperService::descriptor;
|
||||
}
|
||||
|
||||
status_t BnGateKeeperService::onTransact(
|
||||
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) {
|
||||
switch(code) {
|
||||
case ENROLL: {
|
||||
CHECK_INTERFACE(IGateKeeperService, data, reply);
|
||||
uint32_t uid = data.readInt32();
|
||||
|
||||
ssize_t currentPasswordHandleSize = data.readInt32();
|
||||
const uint8_t *currentPasswordHandle =
|
||||
static_cast<const uint8_t *>(data.readInplace(currentPasswordHandleSize));
|
||||
if (!currentPasswordHandle) currentPasswordHandleSize = 0;
|
||||
|
||||
ssize_t currentPasswordSize = data.readInt32();
|
||||
const uint8_t *currentPassword =
|
||||
static_cast<const uint8_t *>(data.readInplace(currentPasswordSize));
|
||||
if (!currentPassword) currentPasswordSize = 0;
|
||||
|
||||
ssize_t desiredPasswordSize = data.readInt32();
|
||||
const uint8_t *desiredPassword =
|
||||
static_cast<const uint8_t *>(data.readInplace(desiredPasswordSize));
|
||||
if (!desiredPassword) desiredPasswordSize = 0;
|
||||
|
||||
uint8_t *out = NULL;
|
||||
uint32_t outSize = 0;
|
||||
status_t ret = enroll(uid, currentPasswordHandle, currentPasswordHandleSize,
|
||||
currentPassword, currentPasswordSize, desiredPassword,
|
||||
desiredPasswordSize, &out, &outSize);
|
||||
|
||||
reply->writeNoException();
|
||||
if (ret == NO_ERROR && outSize > 0 && out != NULL) {
|
||||
reply->writeInt32(outSize);
|
||||
void *buf = reply->writeInplace(outSize);
|
||||
memcpy(buf, out, outSize);
|
||||
free(out);
|
||||
} else {
|
||||
reply->writeInt32(-1);
|
||||
}
|
||||
return NO_ERROR;
|
||||
}
|
||||
case VERIFY: {
|
||||
CHECK_INTERFACE(IGateKeeperService, data, reply);
|
||||
uint32_t uid = data.readInt32();
|
||||
ssize_t currentPasswordHandleSize = data.readInt32();
|
||||
const uint8_t *currentPasswordHandle =
|
||||
static_cast<const uint8_t *>(data.readInplace(currentPasswordHandleSize));
|
||||
if (!currentPasswordHandle) currentPasswordHandleSize = 0;
|
||||
|
||||
ssize_t currentPasswordSize = data.readInt32();
|
||||
const uint8_t *currentPassword =
|
||||
static_cast<const uint8_t *>(data.readInplace(currentPasswordSize));
|
||||
if (!currentPassword) currentPasswordSize = 0;
|
||||
|
||||
status_t ret = verify(uid, (uint8_t *) currentPasswordHandle, currentPasswordHandleSize,
|
||||
(uint8_t *) currentPassword, currentPasswordSize);
|
||||
reply->writeNoException();
|
||||
reply->writeInt32(ret == NO_ERROR ? 1 : 0);
|
||||
return NO_ERROR;
|
||||
}
|
||||
default:
|
||||
return BBinder::onTransact(code, data, reply, flags);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}; // namespace android
|
||||
70
gatekeeperd/IGateKeeperService.h
Normal file
70
gatekeeperd/IGateKeeperService.h
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
* Copyright (C) 2015 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.
|
||||
*/
|
||||
|
||||
#ifndef IGATEKEEPER_SERVICE_H_
|
||||
#define IGATEKEEPER_SERVICE_H_
|
||||
|
||||
#include <binder/IInterface.h>
|
||||
#include <binder/Parcel.h>
|
||||
|
||||
namespace android {
|
||||
|
||||
/*
|
||||
* This must be kept manually in sync with frameworks/base's IGateKeeperService.aidl
|
||||
*/
|
||||
class IGateKeeperService : public IInterface {
|
||||
public:
|
||||
enum {
|
||||
ENROLL = IBinder::FIRST_CALL_TRANSACTION + 0,
|
||||
VERIFY = IBinder::FIRST_CALL_TRANSACTION + 1,
|
||||
};
|
||||
|
||||
// DECLARE_META_INTERFACE - C++ client interface not needed
|
||||
static const android::String16 descriptor;
|
||||
virtual const android::String16& getInterfaceDescriptor() const;
|
||||
IGateKeeperService() {}
|
||||
virtual ~IGateKeeperService() {}
|
||||
|
||||
/**
|
||||
* Enrolls a password with the GateKeeper. Returns 0 on success, negative on failure.
|
||||
*/
|
||||
virtual status_t enroll(uint32_t uid,
|
||||
const uint8_t *current_password_handle, uint32_t current_password_handle_length,
|
||||
const uint8_t *current_password, uint32_t current_password_length,
|
||||
const uint8_t *desired_password, uint32_t desired_password_length,
|
||||
uint8_t **enrolled_password_handle, uint32_t *enrolled_password_handle_length) = 0;
|
||||
|
||||
/**
|
||||
* Verifies a password previously enrolled with the GateKeeper.
|
||||
* Returns 0 on success, negative on failure.
|
||||
*/
|
||||
virtual status_t verify(uint32_t uid,
|
||||
const uint8_t *enrolled_password_handle, uint32_t enrolled_password_handle_length,
|
||||
const uint8_t *provided_password, uint32_t provided_password_length) = 0;
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
class BnGateKeeperService: public BnInterface<IGateKeeperService> {
|
||||
public:
|
||||
virtual status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply,
|
||||
uint32_t flags = 0);
|
||||
};
|
||||
|
||||
} // namespace android
|
||||
|
||||
#endif
|
||||
|
||||
153
gatekeeperd/gatekeeperd.cpp
Normal file
153
gatekeeperd/gatekeeperd.cpp
Normal file
|
|
@ -0,0 +1,153 @@
|
|||
/*
|
||||
* Copyright (C) 2015 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.
|
||||
*/
|
||||
|
||||
#define LOG_TAG "gatekeeperd"
|
||||
|
||||
#include "IGateKeeperService.h"
|
||||
|
||||
#include <cutils/log.h>
|
||||
#include <utils/Log.h>
|
||||
|
||||
#include <binder/IPCThreadState.h>
|
||||
#include <binder/IServiceManager.h>
|
||||
#include <binder/PermissionCache.h>
|
||||
#include <utils/String16.h>
|
||||
|
||||
#include <keystore/IKeystoreService.h>
|
||||
#include <hardware/gatekeeper.h>
|
||||
|
||||
namespace android {
|
||||
|
||||
static const String16 KEYGUARD_PERMISSION("android.permission.ACCESS_KEYGUARD_SECURE_STORAGE");
|
||||
static const String16 DUMP_PERMISSION("android.permission.DUMP");
|
||||
|
||||
class GateKeeperProxy : public BnGateKeeperService {
|
||||
public:
|
||||
GateKeeperProxy() {
|
||||
int ret = hw_get_module_by_class(GATEKEEPER_HARDWARE_MODULE_ID, NULL, &module);
|
||||
if (ret < 0)
|
||||
LOG_ALWAYS_FATAL_IF(ret < 0, "Unable to find GateKeeper HAL");
|
||||
ret = gatekeeper_open(module, &device);
|
||||
if (ret < 0)
|
||||
LOG_ALWAYS_FATAL_IF(ret < 0, "Unable to open GateKeeper HAL");
|
||||
}
|
||||
|
||||
virtual ~GateKeeperProxy() {
|
||||
gatekeeper_close(device);
|
||||
}
|
||||
|
||||
virtual status_t enroll(uint32_t uid,
|
||||
const uint8_t *current_password_handle, uint32_t current_password_handle_length,
|
||||
const uint8_t *current_password, uint32_t current_password_length,
|
||||
const uint8_t *desired_password, uint32_t desired_password_length,
|
||||
uint8_t **enrolled_password_handle, uint32_t *enrolled_password_handle_length) {
|
||||
IPCThreadState* ipc = IPCThreadState::self();
|
||||
const int calling_pid = ipc->getCallingPid();
|
||||
const int calling_uid = ipc->getCallingUid();
|
||||
if (!PermissionCache::checkPermission(KEYGUARD_PERMISSION, calling_pid, calling_uid)) {
|
||||
return PERMISSION_DENIED;
|
||||
}
|
||||
|
||||
// need a desired password to enroll
|
||||
if (desired_password_length == 0) return -EINVAL;
|
||||
int ret = device->enroll(device, uid,
|
||||
current_password_handle, current_password_handle_length,
|
||||
current_password, current_password_length,
|
||||
desired_password, desired_password_length,
|
||||
enrolled_password_handle, enrolled_password_handle_length);
|
||||
return ret >= 0 ? NO_ERROR : UNKNOWN_ERROR;
|
||||
}
|
||||
|
||||
virtual status_t verify(uint32_t uid,
|
||||
const uint8_t *enrolled_password_handle, uint32_t enrolled_password_handle_length,
|
||||
const uint8_t *provided_password, uint32_t provided_password_length) {
|
||||
IPCThreadState* ipc = IPCThreadState::self();
|
||||
const int calling_pid = ipc->getCallingPid();
|
||||
const int calling_uid = ipc->getCallingUid();
|
||||
if (!PermissionCache::checkPermission(KEYGUARD_PERMISSION, calling_pid, calling_uid)) {
|
||||
return PERMISSION_DENIED;
|
||||
}
|
||||
|
||||
// can't verify if we're missing either param
|
||||
if ((enrolled_password_handle_length | provided_password_length) == 0)
|
||||
return -EINVAL;
|
||||
|
||||
uint8_t *auth_token;
|
||||
uint32_t auth_token_length;
|
||||
int ret = device->verify(device, uid,
|
||||
enrolled_password_handle, enrolled_password_handle_length,
|
||||
provided_password, provided_password_length, &auth_token, &auth_token_length);
|
||||
|
||||
if (ret >= 0 && auth_token != NULL && auth_token_length > 0) {
|
||||
// TODO: cache service?
|
||||
sp<IServiceManager> sm = defaultServiceManager();
|
||||
sp<IBinder> binder = sm->getService(String16("android.security.keystore"));
|
||||
sp<IKeystoreService> service = interface_cast<IKeystoreService>(binder);
|
||||
if (service != NULL) {
|
||||
if (service->addAuthToken(auth_token, auth_token_length) != NO_ERROR) {
|
||||
ALOGE("Falure sending auth token to KeyStore");
|
||||
}
|
||||
} else {
|
||||
ALOGE("Unable to communicate with KeyStore");
|
||||
}
|
||||
}
|
||||
|
||||
return ret >= 0 ? NO_ERROR : UNKNOWN_ERROR;
|
||||
}
|
||||
|
||||
virtual status_t dump(int fd, const Vector<String16> &) {
|
||||
IPCThreadState* ipc = IPCThreadState::self();
|
||||
const int pid = ipc->getCallingPid();
|
||||
const int uid = ipc->getCallingUid();
|
||||
if (!PermissionCache::checkPermission(DUMP_PERMISSION, pid, uid)) {
|
||||
return PERMISSION_DENIED;
|
||||
}
|
||||
|
||||
if (device == NULL) {
|
||||
const char *result = "Device not available";
|
||||
write(fd, result, strlen(result) + 1);
|
||||
} else {
|
||||
const char *result = "OK";
|
||||
write(fd, result, strlen(result) + 1);
|
||||
}
|
||||
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
private:
|
||||
gatekeeper_device_t *device;
|
||||
const hw_module_t *module;
|
||||
};
|
||||
}// namespace android
|
||||
|
||||
int main() {
|
||||
ALOGI("Starting gatekeeperd...");
|
||||
android::sp<android::IServiceManager> sm = android::defaultServiceManager();
|
||||
android::sp<android::GateKeeperProxy> proxy = new android::GateKeeperProxy();
|
||||
android::status_t ret = sm->addService(
|
||||
android::String16("android.service.gatekeeper.IGateKeeperService"), proxy);
|
||||
if (ret != android::OK) {
|
||||
ALOGE("Couldn't register binder service!");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* We're the only thread in existence, so we're just going to process
|
||||
* Binder transaction as a single-threaded program.
|
||||
*/
|
||||
android::IPCThreadState::self()->joinThreadPool();
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -605,6 +605,10 @@ service bootanim /system/bin/bootanimation
|
|||
disabled
|
||||
oneshot
|
||||
|
||||
service gatekeeperd /system/bin/gatekeeperd
|
||||
class main
|
||||
user system
|
||||
|
||||
service installd /system/bin/installd
|
||||
class main
|
||||
socket installd stream 600 system system
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue