Home | History | Annotate | Download | only in gatekeeper
      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, &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 
    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