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