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