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 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 69 hw_device_t* TrustyGateKeeperDevice::hw_device() { 70 return &device_.common; 71 } 72 73 int TrustyGateKeeperDevice::close_device(hw_device_t* dev) { 74 delete reinterpret_cast<TrustyGateKeeperDevice *>(dev); 75 return 0; 76 } 77 78 TrustyGateKeeperDevice::~TrustyGateKeeperDevice() { 79 trusty_gatekeeper_disconnect(); 80 } 81 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, ¤t_password_handle_buffer, &desired_password_buffer, 107 ¤t_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 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 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 185 static inline TrustyGateKeeperDevice *convert_device(const gatekeeper_device *dev) { 186 return reinterpret_cast<TrustyGateKeeperDevice *>(const_cast<gatekeeper_device *>(dev)); 187 } 188 189 /* static */ 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 */ 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