1 /*
2 *
3 * Copyright (C) 2017 GlobalLogic
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18 #include <string>
19 #include <utils/Log.h>
20
21 #include <gatekeeper_ipc.h>
22 #include "optee_gatekeeper_device.h"
23
24 #undef LOG_TAG
25 #define LOG_TAG "OpteeGateKeeper"
26
27 namespace android {
28 namespace hardware {
29 namespace gatekeeper {
30 namespace V1_0 {
31 namespace optee {
32
OpteeGateKeeperDevice()33 OpteeGateKeeperDevice::OpteeGateKeeperDevice()
34 : connected_(false)
35 {
36 initialize();
37 connect();
38 }
39
~OpteeGateKeeperDevice()40 OpteeGateKeeperDevice::~OpteeGateKeeperDevice()
41 {
42 disconnect();
43 finalize();
44 }
45
getConnected()46 bool OpteeGateKeeperDevice::getConnected() {
47 ALOGD("%s %d connected_ = %d", __func__, __LINE__, connected_);
48 return connected_;
49 }
50
enroll(uint32_t uid,const hidl_vec<uint8_t> & currentPasswordHandle,const hidl_vec<uint8_t> & currentPassword,const hidl_vec<uint8_t> & desiredPassword,enroll_cb cb)51 Return<void> OpteeGateKeeperDevice::enroll(uint32_t uid,
52 const hidl_vec<uint8_t>& currentPasswordHandle,
53 const hidl_vec<uint8_t>& currentPassword,
54 const hidl_vec<uint8_t>& desiredPassword,
55 enroll_cb cb)
56 {
57 ALOGV("Start enroll");
58 GatekeeperResponse rsp;
59
60 if (!connected_) {
61 ALOGE("Device is not connected");
62 rsp.code = GatekeeperStatusCode::ERROR_GENERAL_FAILURE;
63 cb(rsp);
64 return Void();
65 }
66
67 if (desiredPassword.size() == 0) {
68 ALOGE("Can't enroll new password with zero length");
69 rsp.code = GatekeeperStatusCode::ERROR_GENERAL_FAILURE;
70 cb(rsp);
71 return Void();
72 }
73
74 /*
75 * Enroll request layout
76 * +--------------------------------+---------------------------------+
77 * | Name | Number of bytes |
78 * +--------------------------------+---------------------------------+
79 * | uid | 4 |
80 * | desired_password_length | 4 |
81 * | desired_password | #desired_password_length |
82 * | current_password_length | 4 |
83 * | current_password | #current_password_length |
84 * | current_password_handle_length | 4 |
85 * | current_password_handle | #current_password_handle_length |
86 * +--------------------------------+---------------------------------+
87 */
88 const uint32_t request_size = sizeof(uid) +
89 sizeof(desiredPassword.size()) +
90 desiredPassword.size() +
91 sizeof(currentPassword.size()) +
92 currentPassword.size() +
93 sizeof(currentPasswordHandle.size()) +
94 currentPasswordHandle.size();
95 uint8_t request[request_size];
96
97 uint8_t *i_req = request;
98 serialize_int(&i_req, uid);
99 serialize_blob(&i_req, desiredPassword.data(), desiredPassword.size());
100 serialize_blob(&i_req, currentPassword.data(), currentPassword.size());
101 serialize_blob(&i_req, currentPasswordHandle.data(),
102 currentPasswordHandle.size());
103
104 uint32_t response_size = RECV_BUF_SIZE;
105 uint8_t response[response_size];
106
107 if(!Send(GK_ENROLL, request, request_size, response, response_size)) {
108 ALOGE("Enroll failed without respond");
109 rsp.code = GatekeeperStatusCode::ERROR_GENERAL_FAILURE;
110 cb(rsp);
111 return Void();
112 }
113
114 const uint8_t *i_resp = response;
115 uint32_t error;
116
117 /*
118 * Enroll response layout
119 * +--------------------------------+---------------------------------+
120 * | Name | Number of bytes |
121 * +--------------------------------+---------------------------------+
122 * | error | 4 |
123 * +--------------------------------+---------------------------------+
124 * | retry_timeout | 4 |
125 * +------------------------------ OR --------------------------------+
126 * | response_handle_length | 4 |
127 * | response_handle | #response_handle_length |
128 * +--------------------------------+---------------------------------+
129 */
130 deserialize_int(&i_resp, &error);
131 if (error == ERROR_RETRY) {
132 uint32_t retry_timeout;
133 deserialize_int(&i_resp, &retry_timeout);
134 ALOGV("Enroll returns retry timeout %u", retry_timeout);
135 rsp.timeout = retry_timeout;
136 rsp.code = GatekeeperStatusCode::ERROR_RETRY_TIMEOUT;
137 cb(rsp);
138 return Void();
139 }
140
141 if (error != ERROR_NONE) {
142 ALOGE("Enroll failed");
143 rsp.code = GatekeeperStatusCode::ERROR_GENERAL_FAILURE;
144 cb(rsp);
145 return Void();
146 }
147
148 const uint8_t *response_handle = nullptr;
149 uint32_t response_handle_length = 0;
150
151 deserialize_blob(&i_resp, &response_handle, &response_handle_length);
152
153 std::unique_ptr<uint8_t []> response_handle_ret(
154 new (std::nothrow) uint8_t[response_handle_length]);
155 if (!response_handle_ret) {
156 ALOGE("Cannot create enrolled password handle, not enough memory");
157 rsp.code = GatekeeperStatusCode::ERROR_GENERAL_FAILURE;
158 cb(rsp);
159 return Void();
160 }
161
162 memcpy(response_handle_ret.get(), response_handle, response_handle_length);
163
164 rsp.data.setToExternal(response_handle_ret.release(),
165 response_handle_length,
166 true);
167 rsp.code = GatekeeperStatusCode::STATUS_OK;
168
169 ALOGV("Enroll returns success");
170
171 cb(rsp);
172 return Void();
173 }
174
verify(uint32_t uid,uint64_t challenge,const hidl_vec<uint8_t> & enrolledPasswordHandle,const hidl_vec<uint8_t> & providedPassword,verify_cb cb)175 Return<void> OpteeGateKeeperDevice::verify(uint32_t uid,
176 uint64_t challenge,
177 const hidl_vec<uint8_t>& enrolledPasswordHandle,
178 const hidl_vec<uint8_t>& providedPassword,
179 verify_cb cb)
180 {
181 ALOGV("Start verify");
182 GatekeeperResponse rsp;
183
184 if (!connected_) {
185 ALOGE("Device is not connected");
186 rsp.code = GatekeeperStatusCode::ERROR_GENERAL_FAILURE;
187 cb(rsp);
188 return Void();
189 }
190
191 /*
192 * Verify request layout
193 * +---------------------------------+----------------------------------+
194 * | Name | Number of bytes |
195 * +---------------------------------+----------------------------------+
196 * | uid | 4 |
197 * | challenge | 8 |
198 * | enrolled_password_handle_length | 4 |
199 * | enrolled_password_handle | #enrolled_password_handle_length |
200 * | provided_password_length | 4 |
201 * | provided_password | #provided_password_length |
202 * +---------------------------------+----------------------------------+
203 */
204 const uint32_t request_size = sizeof(uid) +
205 sizeof(challenge) +
206 sizeof(enrolledPasswordHandle.size()) +
207 enrolledPasswordHandle.size() +
208 sizeof(providedPassword.size()) +
209 providedPassword.size();
210 uint8_t request[request_size];
211
212 uint8_t *i_req = request;
213 serialize_int(&i_req, uid);
214 serialize_int64(&i_req, challenge);
215 serialize_blob(&i_req, enrolledPasswordHandle.data(),
216 enrolledPasswordHandle.size());
217 serialize_blob(&i_req, providedPassword.data(), providedPassword.size());
218
219 uint32_t response_size = RECV_BUF_SIZE;
220 uint8_t response[response_size];
221
222 if(!Send(GK_VERIFY, request, request_size, response, response_size)) {
223 ALOGE("Verify failed without respond");
224 rsp.code = GatekeeperStatusCode::ERROR_GENERAL_FAILURE;
225 cb(rsp);
226 return Void();
227 }
228
229 const uint8_t *i_resp = response;
230 uint32_t error;
231
232 /*
233 * Verify response layout
234 * +--------------------------------+---------------------------------+
235 * | Name | Number of bytes |
236 * +--------------------------------+---------------------------------+
237 * | error | 4 |
238 * +--------------------------------+---------------------------------+
239 * | retry_timeout | 4 |
240 * +------------------------------ OR --------------------------------+
241 * | response_auth_token_length | 4 |
242 * | response_auth_token | #response_handle_length |
243 * | response_request_reenroll | 4 |
244 * +--------------------------------+---------------------------------+
245 */
246 deserialize_int(&i_resp, &error);
247 if (error == ERROR_RETRY) {
248 uint32_t retry_timeout;
249 deserialize_int(&i_resp, &retry_timeout);
250 ALOGV("Verify returns retry timeout %u", retry_timeout);
251 rsp.timeout = retry_timeout;
252 rsp.code = GatekeeperStatusCode::ERROR_RETRY_TIMEOUT;
253 cb(rsp);
254 return Void();
255 } else if (error != ERROR_NONE) {
256 ALOGE("Verify failed");
257 rsp.code = GatekeeperStatusCode::ERROR_GENERAL_FAILURE;
258 cb(rsp);
259 return Void();
260 }
261
262 const uint8_t *response_auth_token = nullptr;
263 uint32_t response_auth_token_length = 0;
264
265 deserialize_blob(&i_resp, &response_auth_token,
266 &response_auth_token_length);
267
268 std::unique_ptr<uint8_t []> auth_token_ret(
269 new (std::nothrow) uint8_t[response_auth_token_length]);
270 if (!auth_token_ret) {
271 ALOGE("Cannot create auth token, not enough memory");
272 rsp.code = GatekeeperStatusCode::ERROR_GENERAL_FAILURE;
273 cb(rsp);
274 return Void();
275 }
276
277 memcpy(auth_token_ret.get(), response_auth_token,
278 response_auth_token_length);
279 rsp.data.setToExternal(auth_token_ret.release(),
280 response_auth_token_length,
281 true);
282
283 uint32_t response_request_reenroll;
284 deserialize_int(&i_resp, &response_request_reenroll);
285
286 if (response_request_reenroll != 0) {
287 rsp.code = GatekeeperStatusCode::STATUS_REENROLL;
288 } else {
289 rsp.code = GatekeeperStatusCode::STATUS_OK;
290 }
291
292 ALOGV("Verify returns success");
293
294 cb(rsp);
295 return Void();
296 }
297
deleteUser(uint32_t uid,deleteUser_cb cb)298 Return<void> OpteeGateKeeperDevice::deleteUser(uint32_t uid, deleteUser_cb cb)
299 {
300 GatekeeperResponse rsp;
301 (void)uid;
302 rsp.code = GatekeeperStatusCode::ERROR_NOT_IMPLEMENTED;
303 cb(rsp);
304 return Void();
305 }
306
deleteAllUsers(deleteAllUsers_cb cb)307 Return<void> OpteeGateKeeperDevice::deleteAllUsers(deleteAllUsers_cb cb)
308 {
309 GatekeeperResponse rsp;
310 rsp.code = GatekeeperStatusCode::ERROR_NOT_IMPLEMENTED;
311 cb(rsp);
312 return Void();
313 }
314
initialize()315 bool OpteeGateKeeperDevice::initialize()
316 {
317 if (!gatekeeperIPC_.initialize()) {
318 ALOGE("Fail to connect to TEE");
319 return false;
320 }
321
322 return true;
323 }
324
connect()325 bool OpteeGateKeeperDevice::connect()
326 {
327 if (connected_) {
328 ALOGE("Device is already connected");
329 return false;
330 }
331
332 if (!gatekeeperIPC_.connect(TA_GATEKEEPER_UUID)) {
333 ALOGE("Fail to load Gatekeeper TA");
334 return false;
335 }
336 connected_ = true;
337
338 ALOGV("Connected");
339
340 return true;
341 }
342
disconnect()343 void OpteeGateKeeperDevice::disconnect()
344 {
345 if (connected_) {
346 gatekeeperIPC_.disconnect();
347 connected_ = false;
348 }
349
350 ALOGV("Disconnected");
351 }
352
finalize()353 void OpteeGateKeeperDevice::finalize()
354 {
355 gatekeeperIPC_.finalize();
356 }
357
Send(uint32_t command,const uint8_t * request,uint32_t request_size,uint8_t * response,uint32_t & response_size)358 bool OpteeGateKeeperDevice::Send(uint32_t command,
359 const uint8_t *request, uint32_t request_size,
360 uint8_t *response, uint32_t& response_size)
361 {
362 return gatekeeperIPC_.call(command, request, request_size,
363 response, response_size);
364 }
365
366 } // namespace optee
367 } // namespace V1_0
368 } // namespace gatekeeper
369 } // namespace hardware
370 } // namespace android