blob: c0f22792968b5f27b49c64420f5d1da4f49c45b3 [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 Morales531e3e82015-06-01 17:23:04 -0700139 bool rr;
140
141 // immediately verify this password so we don't ask the user to enter it again
142 // if they just created it.
143 verify(uid, *enrolled_password_handle, sizeof(password_handle_t), desired_password,
144 desired_password_length, &rr);
Andres Morales6a49c2f2015-04-16 13:16:24 -0700145 }
Andres Moralesae242922015-05-18 09:26:19 -0700146
147 return ret;
Andres Morales2d08dce2015-04-03 16:40:15 -0700148 }
149
Andres Moralesae242922015-05-18 09:26:19 -0700150 virtual int verify(uint32_t uid,
Andres Morales2d08dce2015-04-03 16:40:15 -0700151 const uint8_t *enrolled_password_handle, uint32_t enrolled_password_handle_length,
Andres Moralesae242922015-05-18 09:26:19 -0700152 const uint8_t *provided_password, uint32_t provided_password_length, bool *request_reenroll) {
Andres Moralesc828ae82015-04-10 21:03:07 -0700153 uint8_t *auth_token;
154 uint32_t auth_token_length;
155 return verifyChallenge(uid, 0, enrolled_password_handle, enrolled_password_handle_length,
156 provided_password, provided_password_length,
Andres Moralesae242922015-05-18 09:26:19 -0700157 &auth_token, &auth_token_length, request_reenroll);
Andres Moralesc828ae82015-04-10 21:03:07 -0700158 }
159
Andres Moralesae242922015-05-18 09:26:19 -0700160 virtual int verifyChallenge(uint32_t uid, uint64_t challenge,
Andres Moralesc828ae82015-04-10 21:03:07 -0700161 const uint8_t *enrolled_password_handle, uint32_t enrolled_password_handle_length,
162 const uint8_t *provided_password, uint32_t provided_password_length,
Andres Moralesae242922015-05-18 09:26:19 -0700163 uint8_t **auth_token, uint32_t *auth_token_length, bool *request_reenroll) {
Andres Morales2d08dce2015-04-03 16:40:15 -0700164 IPCThreadState* ipc = IPCThreadState::self();
165 const int calling_pid = ipc->getCallingPid();
166 const int calling_uid = ipc->getCallingUid();
167 if (!PermissionCache::checkPermission(KEYGUARD_PERMISSION, calling_pid, calling_uid)) {
168 return PERMISSION_DENIED;
169 }
170
171 // can't verify if we're missing either param
172 if ((enrolled_password_handle_length | provided_password_length) == 0)
173 return -EINVAL;
174
Andres Morales33dfdc72015-05-12 15:37:20 -0700175 int ret;
176 if (device) {
177 ret = device->verify(device, uid, challenge,
Andres Morales2d08dce2015-04-03 16:40:15 -0700178 enrolled_password_handle, enrolled_password_handle_length,
Andres Moralesae242922015-05-18 09:26:19 -0700179 provided_password, provided_password_length, auth_token, auth_token_length,
180 request_reenroll);
Andres Morales33dfdc72015-05-12 15:37:20 -0700181 } else {
182 ret = soft_device->verify(uid, challenge,
183 enrolled_password_handle, enrolled_password_handle_length,
Andres Moralesae242922015-05-18 09:26:19 -0700184 provided_password, provided_password_length, auth_token, auth_token_length,
185 request_reenroll);
Andres Morales33dfdc72015-05-12 15:37:20 -0700186 }
Andres Morales2d08dce2015-04-03 16:40:15 -0700187
Andres Moralesae242922015-05-18 09:26:19 -0700188 if (ret == 0 && *auth_token != NULL && *auth_token_length > 0) {
Andres Morales2d08dce2015-04-03 16:40:15 -0700189 // TODO: cache service?
190 sp<IServiceManager> sm = defaultServiceManager();
191 sp<IBinder> binder = sm->getService(String16("android.security.keystore"));
192 sp<IKeystoreService> service = interface_cast<IKeystoreService>(binder);
193 if (service != NULL) {
Andres Morales2ae8b4c2015-04-13 09:20:09 -0700194 status_t ret = service->addAuthToken(*auth_token, *auth_token_length);
195 if (ret != ResponseCode::NO_ERROR) {
196 ALOGE("Falure sending auth token to KeyStore: %d", ret);
Andres Morales2d08dce2015-04-03 16:40:15 -0700197 }
198 } else {
199 ALOGE("Unable to communicate with KeyStore");
200 }
201 }
202
Andres Moralesae242922015-05-18 09:26:19 -0700203 if (ret == 0) {
Andres Morales6a49c2f2015-04-16 13:16:24 -0700204 maybe_store_sid(uid, reinterpret_cast<const gatekeeper::password_handle_t *>(
205 enrolled_password_handle)->user_id);
Andres Morales6a49c2f2015-04-16 13:16:24 -0700206 }
207
Andres Moralesae242922015-05-18 09:26:19 -0700208 return ret;
Andres Morales6a49c2f2015-04-16 13:16:24 -0700209 }
210
211 virtual uint64_t getSecureUserId(uint32_t uid) {
212 return read_sid(uid);
Andres Morales2d08dce2015-04-03 16:40:15 -0700213 }
214
Andres Morales7c9c3bc2015-04-16 15:57:17 -0700215 virtual void clearSecureUserId(uint32_t uid) {
216 IPCThreadState* ipc = IPCThreadState::self();
217 const int calling_pid = ipc->getCallingPid();
218 const int calling_uid = ipc->getCallingUid();
219 if (!PermissionCache::checkPermission(KEYGUARD_PERMISSION, calling_pid, calling_uid)) {
220 ALOGE("%s: permission denied for [%d:%d]", __func__, calling_pid, calling_uid);
221 return;
222 }
Andres Moralesdcb3fbd2015-04-17 09:00:28 -0700223 clear_sid(uid);
Andres Morales7c9c3bc2015-04-16 15:57:17 -0700224 }
225
Andres Morales2d08dce2015-04-03 16:40:15 -0700226 virtual status_t dump(int fd, const Vector<String16> &) {
227 IPCThreadState* ipc = IPCThreadState::self();
228 const int pid = ipc->getCallingPid();
229 const int uid = ipc->getCallingUid();
230 if (!PermissionCache::checkPermission(DUMP_PERMISSION, pid, uid)) {
231 return PERMISSION_DENIED;
232 }
233
234 if (device == NULL) {
235 const char *result = "Device not available";
236 write(fd, result, strlen(result) + 1);
237 } else {
238 const char *result = "OK";
239 write(fd, result, strlen(result) + 1);
240 }
241
242 return NO_ERROR;
243 }
244
245private:
246 gatekeeper_device_t *device;
Andres Morales33dfdc72015-05-12 15:37:20 -0700247 UniquePtr<SoftGateKeeperDevice> soft_device;
Andres Morales2d08dce2015-04-03 16:40:15 -0700248 const hw_module_t *module;
249};
250}// namespace android
251
Andres Morales6a49c2f2015-04-16 13:16:24 -0700252int main(int argc, char* argv[]) {
Andres Morales2d08dce2015-04-03 16:40:15 -0700253 ALOGI("Starting gatekeeperd...");
Andres Morales6a49c2f2015-04-16 13:16:24 -0700254 if (argc < 2) {
255 ALOGE("A directory must be specified!");
256 return 1;
257 }
258 if (chdir(argv[1]) == -1) {
259 ALOGE("chdir: %s: %s", argv[1], strerror(errno));
260 return 1;
261 }
262
Andres Morales2d08dce2015-04-03 16:40:15 -0700263 android::sp<android::IServiceManager> sm = android::defaultServiceManager();
264 android::sp<android::GateKeeperProxy> proxy = new android::GateKeeperProxy();
265 android::status_t ret = sm->addService(
266 android::String16("android.service.gatekeeper.IGateKeeperService"), proxy);
267 if (ret != android::OK) {
268 ALOGE("Couldn't register binder service!");
269 return -1;
270 }
271
272 /*
273 * We're the only thread in existence, so we're just going to process
274 * Binder transaction as a single-threaded program.
275 */
276 android::IPCThreadState::self()->joinThreadPool();
277 return 0;
278}