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