blob: 75cd2252489d6fbffaf91797d64740609bc233a8 [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
41namespace android {
42
43static const String16 KEYGUARD_PERMISSION("android.permission.ACCESS_KEYGUARD_SECURE_STORAGE");
44static const String16 DUMP_PERMISSION("android.permission.DUMP");
45
46class GateKeeperProxy : public BnGateKeeperService {
47public:
48 GateKeeperProxy() {
49 int ret = hw_get_module_by_class(GATEKEEPER_HARDWARE_MODULE_ID, NULL, &module);
50 if (ret < 0)
51 LOG_ALWAYS_FATAL_IF(ret < 0, "Unable to find GateKeeper HAL");
52 ret = gatekeeper_open(module, &device);
53 if (ret < 0)
54 LOG_ALWAYS_FATAL_IF(ret < 0, "Unable to open GateKeeper HAL");
55 }
56
57 virtual ~GateKeeperProxy() {
58 gatekeeper_close(device);
59 }
60
Andres Morales6a49c2f2015-04-16 13:16:24 -070061 void store_sid(uint32_t uid, uint64_t sid) {
62 char filename[21];
63 sprintf(filename, "%u", uid);
64 int fd = open(filename, O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR | S_IWUSR);
65 if (fd < 0) {
Andres Moralesdcb3fbd2015-04-17 09:00:28 -070066 ALOGE("could not open file: %s: %s", filename, strerror(errno));
Andres Morales6a49c2f2015-04-16 13:16:24 -070067 return;
68 }
69 write(fd, &sid, sizeof(sid));
70 close(fd);
71 }
72
73 void maybe_store_sid(uint32_t uid, uint64_t sid) {
74 char filename[21];
75 sprintf(filename, "%u", uid);
76 if (access(filename, F_OK) == -1) {
77 store_sid(uid, sid);
78 }
79 }
80
81 uint64_t read_sid(uint32_t uid) {
82 char filename[21];
83 uint64_t sid;
84 sprintf(filename, "%u", uid);
85 int fd = open(filename, O_RDONLY);
86 if (fd < 0) return 0;
87 read(fd, &sid, sizeof(sid));
88 return sid;
89 }
90
Andres Moralesdcb3fbd2015-04-17 09:00:28 -070091 void clear_sid(uint32_t uid) {
92 char filename[21];
93 sprintf(filename, "%u", uid);
94 if (remove(filename) < 0) {
95 ALOGE("%s: could not remove file [%s], attempting 0 write", __func__, strerror(errno));
96 store_sid(uid, 0);
97 }
98 }
99
Andres Morales2d08dce2015-04-03 16:40:15 -0700100 virtual status_t enroll(uint32_t uid,
101 const uint8_t *current_password_handle, uint32_t current_password_handle_length,
102 const uint8_t *current_password, uint32_t current_password_length,
103 const uint8_t *desired_password, uint32_t desired_password_length,
104 uint8_t **enrolled_password_handle, uint32_t *enrolled_password_handle_length) {
105 IPCThreadState* ipc = IPCThreadState::self();
106 const int calling_pid = ipc->getCallingPid();
107 const int calling_uid = ipc->getCallingUid();
108 if (!PermissionCache::checkPermission(KEYGUARD_PERMISSION, calling_pid, calling_uid)) {
109 return PERMISSION_DENIED;
110 }
111
112 // need a desired password to enroll
113 if (desired_password_length == 0) return -EINVAL;
114 int ret = device->enroll(device, uid,
115 current_password_handle, current_password_handle_length,
116 current_password, current_password_length,
117 desired_password, desired_password_length,
118 enrolled_password_handle, enrolled_password_handle_length);
Andres Morales6a49c2f2015-04-16 13:16:24 -0700119 if (ret >= 0) {
120 gatekeeper::password_handle_t *handle =
121 reinterpret_cast<gatekeeper::password_handle_t *>(*enrolled_password_handle);
122 store_sid(uid, handle->user_id);
123 return NO_ERROR;
124 }
125 return UNKNOWN_ERROR;
Andres Morales2d08dce2015-04-03 16:40:15 -0700126 }
127
Andres Moralesc828ae82015-04-10 21:03:07 -0700128 virtual status_t verify(uint32_t uid,
Andres Morales2d08dce2015-04-03 16:40:15 -0700129 const uint8_t *enrolled_password_handle, uint32_t enrolled_password_handle_length,
130 const uint8_t *provided_password, uint32_t provided_password_length) {
Andres Moralesc828ae82015-04-10 21:03:07 -0700131 uint8_t *auth_token;
132 uint32_t auth_token_length;
133 return verifyChallenge(uid, 0, enrolled_password_handle, enrolled_password_handle_length,
134 provided_password, provided_password_length,
135 &auth_token, &auth_token_length);
136 }
137
138 virtual status_t verifyChallenge(uint32_t uid, uint64_t challenge,
139 const uint8_t *enrolled_password_handle, uint32_t enrolled_password_handle_length,
140 const uint8_t *provided_password, uint32_t provided_password_length,
141 uint8_t **auth_token, uint32_t *auth_token_length) {
Andres Morales2d08dce2015-04-03 16:40:15 -0700142 IPCThreadState* ipc = IPCThreadState::self();
143 const int calling_pid = ipc->getCallingPid();
144 const int calling_uid = ipc->getCallingUid();
145 if (!PermissionCache::checkPermission(KEYGUARD_PERMISSION, calling_pid, calling_uid)) {
146 return PERMISSION_DENIED;
147 }
148
149 // can't verify if we're missing either param
150 if ((enrolled_password_handle_length | provided_password_length) == 0)
151 return -EINVAL;
152
Andres Morales851b57c2015-04-09 19:23:48 -0700153 int ret = device->verify(device, uid, challenge,
Andres Morales2d08dce2015-04-03 16:40:15 -0700154 enrolled_password_handle, enrolled_password_handle_length,
Andres Moralesc828ae82015-04-10 21:03:07 -0700155 provided_password, provided_password_length, auth_token, auth_token_length);
Andres Morales2d08dce2015-04-03 16:40:15 -0700156
Andres Moralesc828ae82015-04-10 21:03:07 -0700157 if (ret >= 0 && *auth_token != NULL && *auth_token_length > 0) {
Andres Morales2d08dce2015-04-03 16:40:15 -0700158 // TODO: cache service?
159 sp<IServiceManager> sm = defaultServiceManager();
160 sp<IBinder> binder = sm->getService(String16("android.security.keystore"));
161 sp<IKeystoreService> service = interface_cast<IKeystoreService>(binder);
162 if (service != NULL) {
Andres Morales2ae8b4c2015-04-13 09:20:09 -0700163 status_t ret = service->addAuthToken(*auth_token, *auth_token_length);
164 if (ret != ResponseCode::NO_ERROR) {
165 ALOGE("Falure sending auth token to KeyStore: %d", ret);
Andres Morales2d08dce2015-04-03 16:40:15 -0700166 }
167 } else {
168 ALOGE("Unable to communicate with KeyStore");
169 }
170 }
171
Andres Morales6a49c2f2015-04-16 13:16:24 -0700172 if (ret >= 0) {
173 maybe_store_sid(uid, reinterpret_cast<const gatekeeper::password_handle_t *>(
174 enrolled_password_handle)->user_id);
175 return NO_ERROR;
176 }
177
178 return UNKNOWN_ERROR;
179 }
180
181 virtual uint64_t getSecureUserId(uint32_t uid) {
182 return read_sid(uid);
Andres Morales2d08dce2015-04-03 16:40:15 -0700183 }
184
Andres Morales7c9c3bc2015-04-16 15:57:17 -0700185 virtual void clearSecureUserId(uint32_t uid) {
186 IPCThreadState* ipc = IPCThreadState::self();
187 const int calling_pid = ipc->getCallingPid();
188 const int calling_uid = ipc->getCallingUid();
189 if (!PermissionCache::checkPermission(KEYGUARD_PERMISSION, calling_pid, calling_uid)) {
190 ALOGE("%s: permission denied for [%d:%d]", __func__, calling_pid, calling_uid);
191 return;
192 }
Andres Moralesdcb3fbd2015-04-17 09:00:28 -0700193 clear_sid(uid);
Andres Morales7c9c3bc2015-04-16 15:57:17 -0700194 }
195
Andres Morales2d08dce2015-04-03 16:40:15 -0700196 virtual status_t dump(int fd, const Vector<String16> &) {
197 IPCThreadState* ipc = IPCThreadState::self();
198 const int pid = ipc->getCallingPid();
199 const int uid = ipc->getCallingUid();
200 if (!PermissionCache::checkPermission(DUMP_PERMISSION, pid, uid)) {
201 return PERMISSION_DENIED;
202 }
203
204 if (device == NULL) {
205 const char *result = "Device not available";
206 write(fd, result, strlen(result) + 1);
207 } else {
208 const char *result = "OK";
209 write(fd, result, strlen(result) + 1);
210 }
211
212 return NO_ERROR;
213 }
214
215private:
216 gatekeeper_device_t *device;
217 const hw_module_t *module;
218};
219}// namespace android
220
Andres Morales6a49c2f2015-04-16 13:16:24 -0700221int main(int argc, char* argv[]) {
Andres Morales2d08dce2015-04-03 16:40:15 -0700222 ALOGI("Starting gatekeeperd...");
Andres Morales6a49c2f2015-04-16 13:16:24 -0700223 if (argc < 2) {
224 ALOGE("A directory must be specified!");
225 return 1;
226 }
227 if (chdir(argv[1]) == -1) {
228 ALOGE("chdir: %s: %s", argv[1], strerror(errno));
229 return 1;
230 }
231
Andres Morales2d08dce2015-04-03 16:40:15 -0700232 android::sp<android::IServiceManager> sm = android::defaultServiceManager();
233 android::sp<android::GateKeeperProxy> proxy = new android::GateKeeperProxy();
234 android::status_t ret = sm->addService(
235 android::String16("android.service.gatekeeper.IGateKeeperService"), proxy);
236 if (ret != android::OK) {
237 ALOGE("Couldn't register binder service!");
238 return -1;
239 }
240
241 /*
242 * We're the only thread in existence, so we're just going to process
243 * Binder transaction as a single-threaded program.
244 */
245 android::IPCThreadState::self()->joinThreadPool();
246 return 0;
247}