blob: ad16fa5ddcf87d1be3b32703e6f9f253de96661d [file] [log] [blame]
Andres Morales2d08dce2015-04-03 16:40:15 -07001/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "gatekeeperd"
18
19#include "IGateKeeperService.h"
20
Andres Morales6a49c2f2015-04-16 13:16:24 -070021#include <errno.h>
22#include <stdint.h>
23#include <inttypes.h>
24#include <fcntl.h>
25#include <unistd.h>
26
Andres Morales2d08dce2015-04-03 16:40:15 -070027#include <cutils/log.h>
28#include <utils/Log.h>
29
30#include <binder/IPCThreadState.h>
31#include <binder/IServiceManager.h>
32#include <binder/PermissionCache.h>
33#include <utils/String16.h>
34
35#include <keystore/IKeystoreService.h>
Andres Morales2ae8b4c2015-04-13 09:20:09 -070036#include <keystore/keystore.h> // For error code
Andres Morales6a49c2f2015-04-16 13:16:24 -070037#include <gatekeeper/password_handle.h> // for password_handle_t
Andres Morales2d08dce2015-04-03 16:40:15 -070038#include <hardware/gatekeeper.h>
Andres Morales6a49c2f2015-04-16 13:16:24 -070039#include <hardware/hw_auth_token.h>
Andres Morales2d08dce2015-04-03 16:40:15 -070040
Andres Morales33dfdc72015-05-12 15:37:20 -070041#include "SoftGateKeeperDevice.h"
42
Andres Morales2d08dce2015-04-03 16:40:15 -070043namespace android {
44
45static const String16 KEYGUARD_PERMISSION("android.permission.ACCESS_KEYGUARD_SECURE_STORAGE");
46static const String16 DUMP_PERMISSION("android.permission.DUMP");
47
48class GateKeeperProxy : public BnGateKeeperService {
49public:
50 GateKeeperProxy() {
51 int ret = hw_get_module_by_class(GATEKEEPER_HARDWARE_MODULE_ID, NULL, &module);
Andres Morales33dfdc72015-05-12 15:37:20 -070052 if (ret < 0) {
53 ALOGW("falling back to software GateKeeper");
54 soft_device.reset(new SoftGateKeeperDevice());
55 } else {
56 ret = gatekeeper_open(module, &device);
57 if (ret < 0)
58 LOG_ALWAYS_FATAL_IF(ret < 0, "Unable to open GateKeeper HAL");
59 }
Andres Morales2d08dce2015-04-03 16:40:15 -070060 }
61
62 virtual ~GateKeeperProxy() {
Andres Morales33dfdc72015-05-12 15:37:20 -070063 if (device) gatekeeper_close(device);
Andres Morales2d08dce2015-04-03 16:40:15 -070064 }
65
Andres Morales6a49c2f2015-04-16 13:16:24 -070066 void store_sid(uint32_t uid, uint64_t sid) {
67 char filename[21];
68 sprintf(filename, "%u", uid);
69 int fd = open(filename, O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR | S_IWUSR);
70 if (fd < 0) {
Andres Moralesdcb3fbd2015-04-17 09:00:28 -070071 ALOGE("could not open file: %s: %s", filename, strerror(errno));
Andres Morales6a49c2f2015-04-16 13:16:24 -070072 return;
73 }
74 write(fd, &sid, sizeof(sid));
75 close(fd);
76 }
77
78 void maybe_store_sid(uint32_t uid, uint64_t sid) {
79 char filename[21];
80 sprintf(filename, "%u", uid);
81 if (access(filename, F_OK) == -1) {
82 store_sid(uid, sid);
83 }
84 }
85
86 uint64_t read_sid(uint32_t uid) {
87 char filename[21];
88 uint64_t sid;
89 sprintf(filename, "%u", uid);
90 int fd = open(filename, O_RDONLY);
91 if (fd < 0) return 0;
92 read(fd, &sid, sizeof(sid));
93 return sid;
94 }
95
Andres Moralesdcb3fbd2015-04-17 09:00:28 -070096 void clear_sid(uint32_t uid) {
97 char filename[21];
98 sprintf(filename, "%u", uid);
99 if (remove(filename) < 0) {
100 ALOGE("%s: could not remove file [%s], attempting 0 write", __func__, strerror(errno));
101 store_sid(uid, 0);
102 }
103 }
104
Andres Moralesae242922015-05-18 09:26:19 -0700105 virtual int enroll(uint32_t uid,
Andres Morales2d08dce2015-04-03 16:40:15 -0700106 const uint8_t *current_password_handle, uint32_t current_password_handle_length,
107 const uint8_t *current_password, uint32_t current_password_length,
108 const uint8_t *desired_password, uint32_t desired_password_length,
109 uint8_t **enrolled_password_handle, uint32_t *enrolled_password_handle_length) {
110 IPCThreadState* ipc = IPCThreadState::self();
111 const int calling_pid = ipc->getCallingPid();
112 const int calling_uid = ipc->getCallingUid();
113 if (!PermissionCache::checkPermission(KEYGUARD_PERMISSION, calling_pid, calling_uid)) {
114 return PERMISSION_DENIED;
115 }
116
117 // need a desired password to enroll
118 if (desired_password_length == 0) return -EINVAL;
Andres Morales33dfdc72015-05-12 15:37:20 -0700119
120 int ret;
121 if (device) {
122 ret = device->enroll(device, uid,
123 current_password_handle, current_password_handle_length,
124 current_password, current_password_length,
125 desired_password, desired_password_length,
126 enrolled_password_handle, enrolled_password_handle_length);
127 } else {
128 ret = soft_device->enroll(uid,
129 current_password_handle, current_password_handle_length,
130 current_password, current_password_length,
131 desired_password, desired_password_length,
132 enrolled_password_handle, enrolled_password_handle_length);
133 }
134
Andres Moralesae242922015-05-18 09:26:19 -0700135 if (ret == 0) {
Andres Morales6a49c2f2015-04-16 13:16:24 -0700136 gatekeeper::password_handle_t *handle =
137 reinterpret_cast<gatekeeper::password_handle_t *>(*enrolled_password_handle);
138 store_sid(uid, handle->user_id);
Andres Morales6a49c2f2015-04-16 13:16:24 -0700139 }
Andres Moralesae242922015-05-18 09:26:19 -0700140
141 return ret;
Andres Morales2d08dce2015-04-03 16:40:15 -0700142 }
143
Andres Moralesae242922015-05-18 09:26:19 -0700144 virtual int verify(uint32_t uid,
Andres Morales2d08dce2015-04-03 16:40:15 -0700145 const uint8_t *enrolled_password_handle, uint32_t enrolled_password_handle_length,
Andres Moralesae242922015-05-18 09:26:19 -0700146 const uint8_t *provided_password, uint32_t provided_password_length, bool *request_reenroll) {
Andres Moralesc828ae82015-04-10 21:03:07 -0700147 uint8_t *auth_token;
148 uint32_t auth_token_length;
149 return verifyChallenge(uid, 0, enrolled_password_handle, enrolled_password_handle_length,
150 provided_password, provided_password_length,
Andres Moralesae242922015-05-18 09:26:19 -0700151 &auth_token, &auth_token_length, request_reenroll);
Andres Moralesc828ae82015-04-10 21:03:07 -0700152 }
153
Andres Moralesae242922015-05-18 09:26:19 -0700154 virtual int verifyChallenge(uint32_t uid, uint64_t challenge,
Andres Moralesc828ae82015-04-10 21:03:07 -0700155 const uint8_t *enrolled_password_handle, uint32_t enrolled_password_handle_length,
156 const uint8_t *provided_password, uint32_t provided_password_length,
Andres Moralesae242922015-05-18 09:26:19 -0700157 uint8_t **auth_token, uint32_t *auth_token_length, bool *request_reenroll) {
Andres Morales2d08dce2015-04-03 16:40:15 -0700158 IPCThreadState* ipc = IPCThreadState::self();
159 const int calling_pid = ipc->getCallingPid();
160 const int calling_uid = ipc->getCallingUid();
161 if (!PermissionCache::checkPermission(KEYGUARD_PERMISSION, calling_pid, calling_uid)) {
162 return PERMISSION_DENIED;
163 }
164
165 // can't verify if we're missing either param
166 if ((enrolled_password_handle_length | provided_password_length) == 0)
167 return -EINVAL;
168
Andres Morales33dfdc72015-05-12 15:37:20 -0700169 int ret;
170 if (device) {
171 ret = device->verify(device, uid, challenge,
Andres Morales2d08dce2015-04-03 16:40:15 -0700172 enrolled_password_handle, enrolled_password_handle_length,
Andres Moralesae242922015-05-18 09:26:19 -0700173 provided_password, provided_password_length, auth_token, auth_token_length,
174 request_reenroll);
Andres Morales33dfdc72015-05-12 15:37:20 -0700175 } else {
176 ret = soft_device->verify(uid, challenge,
177 enrolled_password_handle, enrolled_password_handle_length,
Andres Moralesae242922015-05-18 09:26:19 -0700178 provided_password, provided_password_length, auth_token, auth_token_length,
179 request_reenroll);
Andres Morales33dfdc72015-05-12 15:37:20 -0700180 }
Andres Morales2d08dce2015-04-03 16:40:15 -0700181
Andres Moralesae242922015-05-18 09:26:19 -0700182 if (ret == 0 && *auth_token != NULL && *auth_token_length > 0) {
Andres Morales2d08dce2015-04-03 16:40:15 -0700183 // TODO: cache service?
184 sp<IServiceManager> sm = defaultServiceManager();
185 sp<IBinder> binder = sm->getService(String16("android.security.keystore"));
186 sp<IKeystoreService> service = interface_cast<IKeystoreService>(binder);
187 if (service != NULL) {
Andres Morales2ae8b4c2015-04-13 09:20:09 -0700188 status_t ret = service->addAuthToken(*auth_token, *auth_token_length);
189 if (ret != ResponseCode::NO_ERROR) {
190 ALOGE("Falure sending auth token to KeyStore: %d", ret);
Andres Morales2d08dce2015-04-03 16:40:15 -0700191 }
192 } else {
193 ALOGE("Unable to communicate with KeyStore");
194 }
195 }
196
Andres Moralesae242922015-05-18 09:26:19 -0700197 if (ret == 0) {
Andres Morales6a49c2f2015-04-16 13:16:24 -0700198 maybe_store_sid(uid, reinterpret_cast<const gatekeeper::password_handle_t *>(
199 enrolled_password_handle)->user_id);
Andres Morales6a49c2f2015-04-16 13:16:24 -0700200 }
201
Andres Moralesae242922015-05-18 09:26:19 -0700202 return ret;
Andres Morales6a49c2f2015-04-16 13:16:24 -0700203 }
204
205 virtual uint64_t getSecureUserId(uint32_t uid) {
206 return read_sid(uid);
Andres Morales2d08dce2015-04-03 16:40:15 -0700207 }
208
Andres Morales7c9c3bc2015-04-16 15:57:17 -0700209 virtual void clearSecureUserId(uint32_t uid) {
210 IPCThreadState* ipc = IPCThreadState::self();
211 const int calling_pid = ipc->getCallingPid();
212 const int calling_uid = ipc->getCallingUid();
213 if (!PermissionCache::checkPermission(KEYGUARD_PERMISSION, calling_pid, calling_uid)) {
214 ALOGE("%s: permission denied for [%d:%d]", __func__, calling_pid, calling_uid);
215 return;
216 }
Andres Moralesdcb3fbd2015-04-17 09:00:28 -0700217 clear_sid(uid);
Andres Morales7c9c3bc2015-04-16 15:57:17 -0700218 }
219
Andres Morales2d08dce2015-04-03 16:40:15 -0700220 virtual status_t dump(int fd, const Vector<String16> &) {
221 IPCThreadState* ipc = IPCThreadState::self();
222 const int pid = ipc->getCallingPid();
223 const int uid = ipc->getCallingUid();
224 if (!PermissionCache::checkPermission(DUMP_PERMISSION, pid, uid)) {
225 return PERMISSION_DENIED;
226 }
227
228 if (device == NULL) {
229 const char *result = "Device not available";
230 write(fd, result, strlen(result) + 1);
231 } else {
232 const char *result = "OK";
233 write(fd, result, strlen(result) + 1);
234 }
235
236 return NO_ERROR;
237 }
238
239private:
240 gatekeeper_device_t *device;
Andres Morales33dfdc72015-05-12 15:37:20 -0700241 UniquePtr<SoftGateKeeperDevice> soft_device;
Andres Morales2d08dce2015-04-03 16:40:15 -0700242 const hw_module_t *module;
243};
244}// namespace android
245
Andres Morales6a49c2f2015-04-16 13:16:24 -0700246int main(int argc, char* argv[]) {
Andres Morales2d08dce2015-04-03 16:40:15 -0700247 ALOGI("Starting gatekeeperd...");
Andres Morales6a49c2f2015-04-16 13:16:24 -0700248 if (argc < 2) {
249 ALOGE("A directory must be specified!");
250 return 1;
251 }
252 if (chdir(argv[1]) == -1) {
253 ALOGE("chdir: %s: %s", argv[1], strerror(errno));
254 return 1;
255 }
256
Andres Morales2d08dce2015-04-03 16:40:15 -0700257 android::sp<android::IServiceManager> sm = android::defaultServiceManager();
258 android::sp<android::GateKeeperProxy> proxy = new android::GateKeeperProxy();
259 android::status_t ret = sm->addService(
260 android::String16("android.service.gatekeeper.IGateKeeperService"), proxy);
261 if (ret != android::OK) {
262 ALOGE("Couldn't register binder service!");
263 return -1;
264 }
265
266 /*
267 * We're the only thread in existence, so we're just going to process
268 * Binder transaction as a single-threaded program.
269 */
270 android::IPCThreadState::self()->joinThreadPool();
271 return 0;
272}