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
31namespace gatekeeper {
32
33const uint32_t SEND_BUF_SIZE = 8192;
34const uint32_t RECV_BUF_SIZE = 8192;
35
36TrustyGateKeeperDevice::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
69hw_device_t* TrustyGateKeeperDevice::hw_device() {
70    return &device_.common;
71}
72
73int TrustyGateKeeperDevice::close_device(hw_device_t* dev) {
74    delete reinterpret_cast<TrustyGateKeeperDevice *>(dev);
75    return 0;
76}
77
78TrustyGateKeeperDevice::~TrustyGateKeeperDevice() {
79    trusty_gatekeeper_disconnect();
80}
81
82int 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
125int 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
162gatekeeper_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
185static inline TrustyGateKeeperDevice *convert_device(const gatekeeper_device *dev) {
186    return reinterpret_cast<TrustyGateKeeperDevice *>(const_cast<gatekeeper_device *>(dev));
187}
188
189/* static */
190int 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 */
217int 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