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