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 "TrustyKeymaster"
18
19 // TODO: make this generic in libtrusty
20
21 #include <errno.h>
22 #include <poll.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <sys/uio.h>
26 #include <unistd.h>
27
28 #include <algorithm>
29 #include <variant>
30 #include <vector>
31
32 #include <log/log.h>
33 #include <trusty/tipc.h>
34
35 #include <trusty_keymaster/ipc/keymaster_ipc.h>
36 #include <trusty_keymaster/ipc/trusty_keymaster_ipc.h>
37 #include <utils/Timers.h>
38
39 static const char* trusty_device_name = "/dev/trusty-ipc-dev0";
40
41 static int handle_ = -1;
42
43 static const int timeout_ms = 10 * 1000;
44 static const int max_timeout_ms = 60 * 1000;
45
trusty_keymaster_set_dev_name(const char * device_name)46 void trusty_keymaster_set_dev_name(const char* device_name) {
47 trusty_device_name = device_name;
48 }
trusty_keymaster_connect()49 int trusty_keymaster_connect() {
50 int rc = tipc_connect(trusty_device_name, KEYMASTER_PORT);
51 if (rc < 0) {
52 return rc;
53 }
54
55 handle_ = rc;
56 return 0;
57 }
58
59 class VectorEraser {
60 public:
VectorEraser(std::vector<uint8_t> * v)61 VectorEraser(std::vector<uint8_t>* v) : _v(v) {}
~VectorEraser()62 ~VectorEraser() {
63 if (_v) {
64 std::fill(const_cast<volatile uint8_t*>(_v->data()),
65 const_cast<volatile uint8_t*>(_v->data() + _v->size()), 0);
66 }
67 }
disarm()68 void disarm() { _v = nullptr; }
69 VectorEraser(const VectorEraser&) = delete;
70 VectorEraser& operator=(const VectorEraser&) = delete;
71 VectorEraser(VectorEraser&& other) = delete;
72 VectorEraser& operator=(VectorEraser&&) = delete;
73
74 private:
75 std::vector<uint8_t>* _v;
76 };
77
trusty_keymaster_call_2(uint32_t cmd,void * in,uint32_t in_size)78 std::variant<int, std::vector<uint8_t>> trusty_keymaster_call_2(uint32_t cmd, void* in,
79 uint32_t in_size) {
80 if (handle_ < 0) {
81 ALOGE("not connected\n");
82 return -EINVAL;
83 }
84
85 size_t msg_size = in_size + sizeof(struct keymaster_message);
86 struct keymaster_message* msg = reinterpret_cast<struct keymaster_message*>(malloc(msg_size));
87 if (!msg) {
88 ALOGE("failed to allocate msg buffer\n");
89 return -EINVAL;
90 }
91
92 msg->cmd = cmd;
93 memcpy(msg->payload, in, in_size);
94
95 nsecs_t start_time_ns = systemTime(SYSTEM_TIME_MONOTONIC);
96 bool timed_out = false;
97 int poll_timeout_ms = timeout_ms;
98 while (true) {
99 struct pollfd pfd;
100 pfd.fd = handle_;
101 pfd.events = POLLOUT;
102 pfd.revents = 0;
103
104 int p = poll(&pfd, 1, poll_timeout_ms);
105 if (p == 0) {
106 ALOGW("write for cmd %d is taking more than %lld nsecs", cmd,
107 (long long)(systemTime(SYSTEM_TIME_MONOTONIC) - start_time_ns));
108 timed_out = true;
109 poll_timeout_ms *= 2;
110 if (poll_timeout_ms > max_timeout_ms) {
111 poll_timeout_ms = max_timeout_ms;
112 }
113 continue;
114 } else if (p < 0) {
115 ALOGE("write poll error: %d", errno);
116 } else if (pfd.revents != POLLOUT) {
117 ALOGW("unexpected poll() result: %d", pfd.revents);
118 }
119 break;
120 }
121
122 ssize_t rc = write(handle_, msg, msg_size);
123 if (timed_out) {
124 ALOGW("write for cmd %d finished after %lld nsecs", cmd,
125 (long long)(systemTime(SYSTEM_TIME_MONOTONIC) - start_time_ns));
126 }
127 free(msg);
128
129 if (rc < 0) {
130 ALOGE("failed to send cmd (%d) to %s: %s\n", cmd, KEYMASTER_PORT, strerror(errno));
131 return -errno;
132 }
133
134 std::vector<uint8_t> out(TRUSTY_KEYMASTER_RECV_BUF_SIZE);
135 VectorEraser out_eraser(&out);
136 uint8_t* write_pos = out.data();
137 uint8_t* out_end = out.data() + out.size();
138
139 struct iovec iov[2];
140 struct keymaster_message header;
141 iov[0] = {.iov_base = &header, .iov_len = sizeof(struct keymaster_message)};
142 while (true) {
143 if (out_end - write_pos < KEYMASTER_MAX_BUFFER_LENGTH) {
144 // In stead of using std::vector.resize(), allocate a new one to have chance
145 // at zeroing the old buffer.
146 std::vector<uint8_t> new_out(out.size() + KEYMASTER_MAX_BUFFER_LENGTH);
147 // After the swap below this erases the old out buffer.
148 VectorEraser new_out_eraser(&new_out);
149 std::copy(out.data(), write_pos, new_out.begin());
150
151 auto write_offset = write_pos - out.data();
152
153 std::swap(new_out, out);
154
155 write_pos = out.data() + write_offset;
156 out_end = out.data() + out.size();
157 }
158 size_t buffer_size = 0;
159 if (__builtin_sub_overflow(reinterpret_cast<uintptr_t>(out_end),
160 reinterpret_cast<uintptr_t>(write_pos), &buffer_size)) {
161 return -EOVERFLOW;
162 }
163 iov[1] = {.iov_base = write_pos, .iov_len = buffer_size};
164 start_time_ns = systemTime(SYSTEM_TIME_MONOTONIC);
165 timed_out = false;
166 poll_timeout_ms = timeout_ms;
167 while (true) {
168 struct pollfd pfd;
169 pfd.fd = handle_;
170 pfd.events = POLLIN;
171 pfd.revents = 0;
172
173 int p = poll(&pfd, 1, poll_timeout_ms);
174 if (p == 0) {
175 ALOGW("readv for cmd %d is taking more than %lld nsecs", cmd,
176 (long long)(systemTime(SYSTEM_TIME_MONOTONIC) - start_time_ns));
177 timed_out = true;
178 poll_timeout_ms *= 2;
179 if (poll_timeout_ms > max_timeout_ms) {
180 poll_timeout_ms = max_timeout_ms;
181 }
182 continue;
183 } else if (p < 0) {
184 ALOGE("read poll error: %d", errno);
185 } else if (pfd.revents != POLLIN) {
186 ALOGW("unexpected poll() result: %d", pfd.revents);
187 }
188 break;
189 }
190 rc = readv(handle_, iov, 2);
191 if (timed_out) {
192 ALOGW("readv for cmd %d finished after %lld nsecs", cmd,
193 (long long)(systemTime(SYSTEM_TIME_MONOTONIC) - start_time_ns));
194 }
195 if (rc < 0) {
196 ALOGE("failed to retrieve response for cmd (%d) to %s: %s\n", cmd, KEYMASTER_PORT,
197 strerror(errno));
198 return -errno;
199 }
200
201 if ((size_t)rc < sizeof(struct keymaster_message)) {
202 ALOGE("invalid response size (%d)\n", (int)rc);
203 return -EINVAL;
204 }
205
206 if ((cmd | KEYMASTER_RESP_BIT) != (header.cmd & ~(KEYMASTER_STOP_BIT))) {
207 ALOGE("invalid command (%d)", header.cmd);
208 return -EINVAL;
209 }
210 write_pos += ((size_t)rc - sizeof(struct keymaster_message));
211 if (header.cmd & KEYMASTER_STOP_BIT) {
212 break;
213 }
214 }
215
216 out.resize(write_pos - out.data());
217 out_eraser.disarm();
218 return out;
219 }
220
trusty_keymaster_call(uint32_t cmd,void * in,uint32_t in_size,uint8_t * out,uint32_t * out_size)221 int trusty_keymaster_call(uint32_t cmd, void* in, uint32_t in_size, uint8_t* out,
222 uint32_t* out_size) {
223 auto result = trusty_keymaster_call_2(cmd, in, in_size);
224 if (auto out_buffer = std::get_if<std::vector<uint8_t>>(&result)) {
225 if (out_buffer->size() <= *out_size) {
226 std::copy(out_buffer->begin(), out_buffer->end(), out);
227 std::fill(const_cast<volatile uint8_t*>(&*out_buffer->begin()),
228 const_cast<volatile uint8_t*>(&*out_buffer->end()), 0);
229
230 *out_size = out_buffer->size();
231 return 0;
232 } else {
233 ALOGE("Message was to large (%zu) for the provided buffer (%u)", out_buffer->size(),
234 *out_size);
235 return -EMSGSIZE;
236 }
237 } else {
238 return std::get<int>(result);
239 }
240 }
241
trusty_keymaster_disconnect()242 void trusty_keymaster_disconnect() {
243 if (handle_ >= 0) {
244 tipc_close(handle_);
245 }
246 handle_ = -1;
247 }
248
translate_error(int err)249 keymaster_error_t translate_error(int err) {
250 switch (err) {
251 case 0:
252 return KM_ERROR_OK;
253 case -EPERM:
254 case -EACCES:
255 return KM_ERROR_SECURE_HW_ACCESS_DENIED;
256
257 case -ECANCELED:
258 return KM_ERROR_OPERATION_CANCELLED;
259
260 case -ENODEV:
261 return KM_ERROR_UNIMPLEMENTED;
262
263 case -ENOMEM:
264 return KM_ERROR_MEMORY_ALLOCATION_FAILED;
265
266 case -EBUSY:
267 return KM_ERROR_SECURE_HW_BUSY;
268
269 case -EIO:
270 return KM_ERROR_SECURE_HW_COMMUNICATION_FAILED;
271
272 case -EOVERFLOW:
273 return KM_ERROR_INVALID_INPUT_LENGTH;
274
275 default:
276 return KM_ERROR_UNKNOWN_ERROR;
277 }
278 }
279
trusty_keymaster_send(uint32_t command,const keymaster::Serializable & req,keymaster::KeymasterResponse * rsp)280 keymaster_error_t trusty_keymaster_send(uint32_t command, const keymaster::Serializable& req,
281 keymaster::KeymasterResponse* rsp) {
282 uint32_t req_size = req.SerializedSize();
283 if (req_size > TRUSTY_KEYMASTER_SEND_BUF_SIZE) {
284 ALOGE("Request too big: %u Max size: %u", req_size, TRUSTY_KEYMASTER_SEND_BUF_SIZE);
285 return KM_ERROR_INVALID_INPUT_LENGTH;
286 }
287
288 uint8_t send_buf[TRUSTY_KEYMASTER_SEND_BUF_SIZE];
289 keymaster::Eraser send_buf_eraser(send_buf, TRUSTY_KEYMASTER_SEND_BUF_SIZE);
290 req.Serialize(send_buf, send_buf + req_size);
291
292 // Send it
293 auto response = trusty_keymaster_call_2(command, send_buf, req_size);
294 if (auto response_buffer = std::get_if<std::vector<uint8_t>>(&response)) {
295 keymaster::Eraser response_buffer_erasor(response_buffer->data(), response_buffer->size());
296 ALOGV("Received %zu byte response\n", response_buffer->size());
297
298 const uint8_t* p = response_buffer->data();
299 if (!rsp->Deserialize(&p, p + response_buffer->size())) {
300 ALOGE("Error deserializing response of size %zu\n", response_buffer->size());
301 return KM_ERROR_UNKNOWN_ERROR;
302 } else if (rsp->error != KM_ERROR_OK) {
303 ALOGE("Response of size %zu contained error code %d\n", response_buffer->size(),
304 (int)rsp->error);
305 }
306 return rsp->error;
307 } else {
308 auto rc = std::get<int>(response);
309 // Reset the connection on tipc error
310 trusty_keymaster_disconnect();
311 trusty_keymaster_connect();
312 ALOGE("tipc error: %d\n", rc);
313 // TODO(swillden): Distinguish permanent from transient errors and set error_ appropriately.
314 return translate_error(rc);
315 }
316 }
317