• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 "TrustyGateKeeper"
18 
19 #include <assert.h>
20 #include <errno.h>
21 #include <stdio.h>
22 
23 #include <type_traits>
24 
25 #include <log/log.h>
26 
27 #include "trusty_gatekeeper.h"
28 #include "trusty_gatekeeper_ipc.h"
29 #include "gatekeeper_ipc.h"
30 
31 namespace gatekeeper {
32 
33 const uint32_t SEND_BUF_SIZE = 8192;
34 const uint32_t RECV_BUF_SIZE = 8192;
35 
TrustyGateKeeperDevice(const hw_module_t * module)36 TrustyGateKeeperDevice::TrustyGateKeeperDevice(const hw_module_t *module) {
37 #if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__)
38     static_assert(std::is_standard_layout<TrustyGateKeeperDevice>::value,
39                   "TrustyGateKeeperDevice must be standard layout");
40     static_assert(offsetof(TrustyGateKeeperDevice, device_) == 0,
41                   "device_ must be the first member of TrustyGateKeeperDevice");
42     static_assert(offsetof(TrustyGateKeeperDevice, device_.common) == 0,
43                   "common must be the first member of gatekeeper_device");
44 #else
45     assert(reinterpret_cast<gatekeeper_device_t *>(this) == &device_);
46     assert(reinterpret_cast<hw_device_t *>(this) == &(device_.common));
47 #endif
48 
49     memset(&device_, 0, sizeof(device_));
50     device_.common.tag = HARDWARE_DEVICE_TAG;
51     device_.common.version = 1;
52     device_.common.module = const_cast<hw_module_t *>(module);
53     device_.common.close = close_device;
54 
55     device_.enroll = enroll;
56     device_.verify = verify;
57     device_.delete_user = nullptr;
58     device_.delete_all_users = nullptr;
59 
60     int rc = trusty_gatekeeper_connect();
61     if (rc < 0) {
62         ALOGE("Error initializing trusty session: %d", rc);
63     }
64 
65     error_ = rc;
66 
67 }
68 
hw_device()69 hw_device_t* TrustyGateKeeperDevice::hw_device() {
70     return &device_.common;
71 }
72 
close_device(hw_device_t * dev)73 int TrustyGateKeeperDevice::close_device(hw_device_t* dev) {
74     delete reinterpret_cast<TrustyGateKeeperDevice *>(dev);
75     return 0;
76 }
77 
~TrustyGateKeeperDevice()78 TrustyGateKeeperDevice::~TrustyGateKeeperDevice() {
79     trusty_gatekeeper_disconnect();
80 }
81 
Enroll(uint32_t uid,const uint8_t * current_password_handle,uint32_t current_password_handle_length,const uint8_t * current_password,uint32_t current_password_length,const uint8_t * desired_password,uint32_t desired_password_length,uint8_t ** enrolled_password_handle,uint32_t * enrolled_password_handle_length)82 int TrustyGateKeeperDevice::Enroll(uint32_t uid, const uint8_t *current_password_handle,
83         uint32_t current_password_handle_length, const uint8_t *current_password,
84         uint32_t current_password_length, const uint8_t *desired_password,
85         uint32_t desired_password_length, uint8_t **enrolled_password_handle,
86         uint32_t *enrolled_password_handle_length) {
87 
88     if (error_ != 0) {
89         return error_;
90     }
91 
92     SizedBuffer desired_password_buffer(desired_password_length);
93     memcpy(desired_password_buffer.buffer.get(), desired_password, desired_password_length);
94 
95     SizedBuffer current_password_handle_buffer(current_password_handle_length);
96     if (current_password_handle) {
97         memcpy(current_password_handle_buffer.buffer.get(), current_password_handle,
98                 current_password_handle_length);
99     }
100 
101     SizedBuffer current_password_buffer(current_password_length);
102     if (current_password) {
103         memcpy(current_password_buffer.buffer.get(), current_password, current_password_length);
104     }
105 
106     EnrollRequest request(uid, &current_password_handle_buffer, &desired_password_buffer,
107             &current_password_buffer);
108     EnrollResponse response;
109 
110     gatekeeper_error_t error = Send(request, &response);
111 
112     if (error == ERROR_RETRY) {
113         return response.retry_timeout;
114     } else if (error != ERROR_NONE) {
115         return -EINVAL;
116     }
117 
118     *enrolled_password_handle = response.enrolled_password_handle.buffer.release();
119     *enrolled_password_handle_length = response.enrolled_password_handle.length;
120 
121 
122     return 0;
123 }
124 
Verify(uint32_t uid,uint64_t challenge,const uint8_t * enrolled_password_handle,uint32_t enrolled_password_handle_length,const uint8_t * provided_password,uint32_t provided_password_length,uint8_t ** auth_token,uint32_t * auth_token_length,bool * request_reenroll)125 int TrustyGateKeeperDevice::Verify(uint32_t uid, uint64_t challenge,
126         const uint8_t *enrolled_password_handle, uint32_t enrolled_password_handle_length,
127         const uint8_t *provided_password, uint32_t provided_password_length,
128         uint8_t **auth_token, uint32_t *auth_token_length, bool *request_reenroll) {
129     if (error_ != 0) {
130         return error_;
131     }
132 
133     SizedBuffer password_handle_buffer(enrolled_password_handle_length);
134     memcpy(password_handle_buffer.buffer.get(), enrolled_password_handle,
135             enrolled_password_handle_length);
136     SizedBuffer provided_password_buffer(provided_password_length);
137     memcpy(provided_password_buffer.buffer.get(), provided_password, provided_password_length);
138 
139     VerifyRequest request(uid, challenge, &password_handle_buffer, &provided_password_buffer);
140     VerifyResponse response;
141 
142     gatekeeper_error_t error = Send(request, &response);
143 
144     if (error == ERROR_RETRY) {
145         return response.retry_timeout;
146     } else if (error != ERROR_NONE) {
147         return -EINVAL;
148     }
149 
150     if (auth_token != NULL && auth_token_length != NULL) {
151        *auth_token = response.auth_token.buffer.release();
152        *auth_token_length = response.auth_token.length;
153     }
154 
155     if (request_reenroll != NULL) {
156         *request_reenroll = response.request_reenroll;
157     }
158 
159     return 0;
160 }
161 
Send(uint32_t command,const GateKeeperMessage & request,GateKeeperMessage * response)162 gatekeeper_error_t TrustyGateKeeperDevice::Send(uint32_t command, const GateKeeperMessage& request,
163         GateKeeperMessage *response) {
164     uint32_t request_size = request.GetSerializedSize();
165     if (request_size > SEND_BUF_SIZE)
166         return ERROR_INVALID;
167     uint8_t send_buf[SEND_BUF_SIZE];
168     request.Serialize(send_buf, send_buf + request_size);
169 
170     // Send it
171     uint8_t recv_buf[RECV_BUF_SIZE];
172     uint32_t response_size = RECV_BUF_SIZE;
173     int rc = trusty_gatekeeper_call(command, send_buf, request_size, recv_buf, &response_size);
174     if (rc < 0) {
175         ALOGE("error (%d) calling gatekeeper TA", rc);
176         return ERROR_INVALID;
177     }
178 
179     const gatekeeper_message *msg = reinterpret_cast<gatekeeper_message *>(recv_buf);
180     const uint8_t *payload = msg->payload;
181 
182     return response->Deserialize(payload, payload + response_size);
183 }
184 
convert_device(const gatekeeper_device * dev)185 static inline TrustyGateKeeperDevice *convert_device(const gatekeeper_device *dev) {
186     return reinterpret_cast<TrustyGateKeeperDevice *>(const_cast<gatekeeper_device *>(dev));
187 }
188 
189 /* static */
enroll(const struct gatekeeper_device * dev,uint32_t uid,const uint8_t * current_password_handle,uint32_t current_password_handle_length,const uint8_t * current_password,uint32_t current_password_length,const uint8_t * desired_password,uint32_t desired_password_length,uint8_t ** enrolled_password_handle,uint32_t * enrolled_password_handle_length)190 int TrustyGateKeeperDevice::enroll(const struct gatekeeper_device *dev, uint32_t uid,
191             const uint8_t *current_password_handle, uint32_t current_password_handle_length,
192             const uint8_t *current_password, uint32_t current_password_length,
193             const uint8_t *desired_password, uint32_t desired_password_length,
194             uint8_t **enrolled_password_handle, uint32_t *enrolled_password_handle_length) {
195 
196     if (dev == NULL ||
197             enrolled_password_handle == NULL || enrolled_password_handle_length == NULL ||
198             desired_password == NULL || desired_password_length == 0)
199         return -EINVAL;
200 
201     // Current password and current password handle go together
202     if (current_password_handle == NULL || current_password_handle_length == 0 ||
203             current_password == NULL || current_password_length == 0) {
204         current_password_handle = NULL;
205         current_password_handle_length = 0;
206         current_password = NULL;
207         current_password_length = 0;
208     }
209 
210     return convert_device(dev)->Enroll(uid, current_password_handle, current_password_handle_length,
211             current_password, current_password_length, desired_password, desired_password_length,
212             enrolled_password_handle, enrolled_password_handle_length);
213 
214 }
215 
216 /* static */
verify(const struct gatekeeper_device * dev,uint32_t uid,uint64_t challenge,const uint8_t * enrolled_password_handle,uint32_t enrolled_password_handle_length,const uint8_t * provided_password,uint32_t provided_password_length,uint8_t ** auth_token,uint32_t * auth_token_length,bool * request_reenroll)217 int TrustyGateKeeperDevice::verify(const struct gatekeeper_device *dev, uint32_t uid,
218         uint64_t challenge, const uint8_t *enrolled_password_handle,
219         uint32_t enrolled_password_handle_length, const uint8_t *provided_password,
220         uint32_t provided_password_length, uint8_t **auth_token, uint32_t *auth_token_length,
221         bool *request_reenroll) {
222 
223     if (dev == NULL || enrolled_password_handle == NULL ||
224             provided_password == NULL) {
225         return -EINVAL;
226     }
227 
228     return convert_device(dev)->Verify(uid, challenge, enrolled_password_handle,
229             enrolled_password_handle_length, provided_password, provided_password_length,
230             auth_token, auth_token_length, request_reenroll);
231 }
232 };
233