1 /*
2 * Copyright (C) 2021 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 TLOG_TAG "lib_hwaes_server"
18
19 #include <assert.h>
20 #include <lib/hwaes_server/hwaes_server.h>
21 #include <lib/tipc/tipc_srv.h>
22 #include <stdlib.h>
23 #include <sys/auxv.h>
24 #include <sys/mman.h>
25 #include <trusty/sys/mman.h>
26
27 #include <trusty_log.h>
28 #include <uapi/err.h>
29
30 #include <inttypes.h>
31
32 #define AUX_PAGE_SIZE() getauxval(AT_PAGESZ)
33
34 struct shm {
35 void* base;
36 size_t size;
37 int mmap_prot;
38 };
39
40 /**
41 * tipc_err_to_hwaes_err() - translates tipc/lk err to hwaes err value
42 * @tipc_err: tipc err value
43 *
44 * Returns: enum hwaes_err value
45 */
tipc_err_to_hwaes_err(int tipc_err)46 static enum hwaes_err tipc_err_to_hwaes_err(int tipc_err) {
47 switch (tipc_err) {
48 case NO_ERROR:
49 return HWAES_NO_ERROR;
50 case ERR_INVALID_ARGS:
51 return HWAES_ERR_INVALID_ARGS;
52 case ERR_IO:
53 return HWAES_ERR_IO;
54 case ERR_BAD_HANDLE:
55 return HWAES_ERR_BAD_HANDLE;
56 case ERR_NOT_IMPLEMENTED:
57 return HWAES_ERR_NOT_IMPLEMENTED;
58 default:
59 return HWAES_ERR_GENERIC;
60 }
61 }
62
63 /**
64 * int hwaes_send_resp() - send response to the client
65 * @chan: the channel handle.
66 * @buf: the pointer to the buffer to store the response.
67 * @buf_sz: the size of the buffer pointed by @buf parameter.
68 *
69 * Returns: NO_ERROR on success, negative error code on failure
70 */
hwaes_send_resp(handle_t chan,void * buf,size_t buf_sz)71 static int hwaes_send_resp(handle_t chan, void* buf, size_t buf_sz) {
72 struct hwaes_resp* resp_header = (struct hwaes_resp*)buf;
73 resp_header->cmd |= HWAES_RESP_BIT;
74
75 int rc = tipc_send1(chan, buf, buf_sz);
76 if ((size_t)rc != buf_sz) {
77 TLOGE("failed (%d) to send message. Expected to send %zu bytes.\n", rc,
78 buf_sz);
79 if (rc >= 0) {
80 rc = ERR_BAD_LEN;
81 }
82 return rc;
83 }
84 return NO_ERROR;
85 }
86
87 /**
88 * int hwaes_map_shm() - map the shared memories.
89 * @num: the number of shared memories.
90 * @handles: the array of shared memory handles.
91 * @shm_descs: the array of shared memory descriptors.
92 * @shms: the array of shared memories.
93 *
94 * Returns: NO_ERROR on success, negative error code on failure
95 */
hwaes_map_shm(size_t num,handle_t * handles,struct hwaes_shm_desc * shm_descs,struct shm * shms)96 static int hwaes_map_shm(size_t num,
97 handle_t* handles,
98 struct hwaes_shm_desc* shm_descs,
99 struct shm* shms) {
100 for (size_t i = 0; i < num; i++) {
101 if (shm_descs[i].reserved) {
102 TLOGE("bad shared memory descriptor, reserved not 0, (%d)\n",
103 shm_descs[i].reserved);
104 return ERR_IO;
105 }
106
107 if (~1U & shm_descs[i].write) {
108 TLOGE("the write flag (%u) of shared memory is invalid.\n",
109 shm_descs[i].write);
110 return ERR_IO;
111 }
112 int mmap_prot = PROT_READ;
113 if (shm_descs[i].write) {
114 mmap_prot |= PROT_WRITE;
115 }
116
117 uint64_t size64 = shm_descs[i].size;
118 if (size64 > SIZE_MAX) {
119 TLOGE("share memory size is larger than SIZE_MAX\n");
120 return ERR_INVALID_ARGS;
121 }
122
123 size_t size = size64;
124 if (size == 0 || size % AUX_PAGE_SIZE()) {
125 TLOGE("size (%zu) of shared memory is invalid.\n", size);
126 return ERR_INVALID_ARGS;
127 }
128
129 shms[i].base = mmap(0, shm_descs[i].size, mmap_prot, 0, handles[i], 0);
130 if (shms[i].base == MAP_FAILED) {
131 TLOGE("failed to mmap() shared memory for handle (%zu).\n", i);
132 return ERR_BAD_HANDLE;
133 }
134 shms[i].size = shm_descs[i].size;
135 shms[i].mmap_prot = mmap_prot;
136 }
137 return NO_ERROR;
138 }
139
140 /**
141 * void hwaes_unmap_shm() - unmap the shared memories.
142 * @num: the number of shared memories.
143 * @shms: the array of shared memories.
144 *
145 */
hwaes_unmap_shm(size_t num,struct shm * shms)146 static void hwaes_unmap_shm(size_t num, struct shm* shms) {
147 for (size_t i = 0; i < num; i++) {
148 if (shms[i].size) {
149 int rc = munmap(shms[i].base, shms[i].size);
150 if (rc != NO_ERROR) {
151 TLOGW("munmap() failed: %d\n", rc);
152 }
153 }
154 }
155 }
156
157 /**
158 * int hwaes_set_arg_out() - set the output argument
159 * @data_desc_ptr: pointer to a data_desc.
160 * @mmap_prot: shared memory mmap flag required for the argument.
161 * @shms: the array of shared memories.
162 * @num_shms: the number of shared memories.
163 * @buf_start: the start of the buffer.
164 * @max_buf_sz: the maximum size of the buffer.
165 * @offset_ptr: pointer to the offset to the start of the buffer.
166 * @arg_ptr: pointer to the output argument.
167 *
168 * Returns: NO_ERROR on success, negative error code on failure
169 */
hwaes_set_arg_out(struct hwaes_data_desc * data_desc_ptr,int mmap_prot,struct shm * shms,size_t num_shms,uint8_t * buf_start,size_t max_buf_sz,size_t * offset_ptr,struct hwaes_arg_out * arg_ptr)170 static int hwaes_set_arg_out(struct hwaes_data_desc* data_desc_ptr,
171 int mmap_prot,
172 struct shm* shms,
173 size_t num_shms,
174 uint8_t* buf_start,
175 size_t max_buf_sz,
176 size_t* offset_ptr,
177 struct hwaes_arg_out* arg_ptr) {
178 if (data_desc_ptr->reserved) {
179 TLOGE("bad data descriptor, reserved not 0, (%d)\n",
180 data_desc_ptr->reserved);
181 return ERR_IO;
182 }
183
184 size_t offset = *offset_ptr;
185 if (data_desc_ptr->len) {
186 if (data_desc_ptr->len > SIZE_MAX) {
187 TLOGE("data length is larger than SIZE_MAX\n");
188 return ERR_INVALID_ARGS;
189 }
190 arg_ptr->len = data_desc_ptr->len;
191 if (HWAES_INVALID_INDEX != data_desc_ptr->shm_idx) {
192 if (data_desc_ptr->shm_idx >= num_shms) {
193 TLOGE("invalid shared memory index\n");
194 return ERR_IO;
195 }
196 int shm_mmap_prot = shms[data_desc_ptr->shm_idx].mmap_prot;
197 if (~shm_mmap_prot & mmap_prot) {
198 TLOGE("invalid shared memory protect flag\n");
199 return ERR_IO;
200 }
201 size_t end_offset;
202 if (__builtin_add_overflow(data_desc_ptr->offset,
203 data_desc_ptr->len, &end_offset)) {
204 TLOGE("the calculation of end_offset overflows \n");
205 return ERR_INVALID_ARGS;
206 }
207 if (shms[data_desc_ptr->shm_idx].size < end_offset) {
208 TLOGE("data exceeds shared memory boundaries\n");
209 return ERR_INVALID_ARGS;
210 }
211 arg_ptr->data_ptr =
212 shms[data_desc_ptr->shm_idx].base + data_desc_ptr->offset;
213 } else {
214 if (offset != data_desc_ptr->offset) {
215 /* Some buffers may have buffer alignment requirements.
216 * For inlined buffers, the offsets should be adjusted
217 * on the client side to achieve the required alignment.
218 * If this has been done, the offset needs updating here
219 * also, read it from the descriptor (it should be
220 * not less than end of the previous entry, though).
221 */
222 if (data_desc_ptr->offset < offset) {
223 TLOGE("invalid descriptor offset (%" PRIu64 " < %zu)\n",
224 data_desc_ptr->offset, offset);
225 return ERR_INVALID_ARGS;
226 }
227 offset = data_desc_ptr->offset;
228 }
229
230 if (__builtin_add_overflow(offset, data_desc_ptr->len, &offset)) {
231 TLOGE("the calculation of offset overflows\n");
232 return ERR_INVALID_ARGS;
233 }
234 if (offset > max_buf_sz) {
235 TLOGE("offset (%zu) exceeds the maximum message size\n",
236 offset);
237 return ERR_INVALID_ARGS;
238 }
239 arg_ptr->data_ptr = buf_start + data_desc_ptr->offset;
240 *offset_ptr = offset;
241 }
242 }
243 return NO_ERROR;
244 }
245
hwaes_set_arg_in(struct hwaes_data_desc * data_desc_ptr,int mmap_prot,struct shm * shms,size_t num_shms,uint8_t * buf_start,size_t max_buf_sz,size_t * offset_ptr,struct hwaes_arg_in * arg)246 static int hwaes_set_arg_in(struct hwaes_data_desc* data_desc_ptr,
247 int mmap_prot,
248 struct shm* shms,
249 size_t num_shms,
250 uint8_t* buf_start,
251 size_t max_buf_sz,
252 size_t* offset_ptr,
253 struct hwaes_arg_in* arg) {
254 int rc;
255 struct hwaes_arg_out out_arg = {0};
256 rc = hwaes_set_arg_out(data_desc_ptr, mmap_prot, shms, num_shms, buf_start,
257 max_buf_sz, offset_ptr, &out_arg);
258 if (rc != NO_ERROR) {
259 return rc;
260 }
261 arg->data_ptr = out_arg.data_ptr;
262 arg->len = out_arg.len;
263 return NO_ERROR;
264 }
265
266 /**
267 * int hwaes_handle_aes_cmd() - handle request with HWAES_AES command
268 * @chan: the channel handle.
269 * @req_msg_buf: the request message buffer.
270 * @req_msg_size: the size of request message.
271 * @resp_msg_buf: the response message buffer.
272 * @shm_handles: the array of shared memory handles.
273 * @num_handles: the number of shared memory handles.
274 *
275 * Returns: NO_ERROR on success, negative error code on failure
276 */
hwaes_handle_aes_cmd(handle_t chan,uint8_t * req_msg_buf,size_t req_msg_size,uint8_t * resp_msg_buf,handle_t * shm_handles,size_t num_handles)277 static int hwaes_handle_aes_cmd(handle_t chan,
278 uint8_t* req_msg_buf,
279 size_t req_msg_size,
280 uint8_t* resp_msg_buf,
281 handle_t* shm_handles,
282 size_t num_handles) {
283 int rc;
284 struct shm shms[HWAES_MAX_NUM_HANDLES] = {0};
285
286 struct hwaes_req* req_header = (struct hwaes_req*)req_msg_buf;
287
288 struct hwaes_resp* resp_header = (struct hwaes_resp*)resp_msg_buf;
289 size_t resp_msg_size = sizeof(*resp_header);
290
291 struct hwaes_aes_req* cmd_header =
292 (struct hwaes_aes_req*)(req_msg_buf + sizeof(*req_header));
293
294 if (cmd_header->reserved) {
295 TLOGE("bad cmd header, reserved not 0, (%d)\n", cmd_header->reserved);
296 return ERR_NOT_VALID;
297 }
298
299 size_t header_num_handles = cmd_header->num_handles;
300
301 if (header_num_handles != num_handles) {
302 TLOGE("header specified num_handles(%zu) is not equal to the num_handles(%zu)\n",
303 header_num_handles, num_handles);
304 return ERR_NOT_VALID;
305 }
306
307 size_t req_header_size = sizeof(*req_header) + sizeof(*cmd_header) +
308 num_handles * sizeof(struct hwaes_shm_desc);
309
310 if (req_header_size > HWAES_MAX_MSG_SIZE) {
311 TLOGE("request header size (%zu) exceeds the maximum message size\n",
312 req_header_size);
313 return ERR_NOT_VALID;
314 }
315
316 struct hwaes_shm_desc* shm_descs =
317 (struct hwaes_shm_desc*)(req_msg_buf + sizeof(*req_header) +
318 sizeof(*cmd_header));
319
320 rc = hwaes_map_shm(num_handles, shm_handles, shm_descs, shms);
321 if (rc != NO_ERROR) {
322 TLOGE("failed to hwaes_map_shm()\n");
323 resp_header->result = tipc_err_to_hwaes_err(rc);
324 goto out;
325 }
326
327 struct hwaes_aes_op_args args = {
328 .key_type = cmd_header->key_type,
329 .padding = cmd_header->padding,
330 .mode = cmd_header->mode,
331 .encrypt = !!cmd_header->encrypt,
332 };
333
334 size_t req_offset = req_header_size;
335 size_t resp_offset = resp_msg_size;
336
337 rc = hwaes_set_arg_in(&cmd_header->key, PROT_READ, shms, num_handles,
338 req_msg_buf, req_msg_size, &req_offset, &args.key);
339 if (rc != NO_ERROR) {
340 TLOGE("failed to set key\n");
341 resp_header->result = tipc_err_to_hwaes_err(rc);
342 goto out;
343 }
344
345 rc = hwaes_set_arg_in(&cmd_header->iv, PROT_READ, shms, num_handles,
346 req_msg_buf, req_msg_size, &req_offset, &args.iv);
347 if (rc != NO_ERROR) {
348 TLOGE("failed to set iv\n");
349 resp_header->result = tipc_err_to_hwaes_err(rc);
350 goto out;
351 }
352
353 rc = hwaes_set_arg_in(&cmd_header->aad, PROT_READ, shms, num_handles,
354 req_msg_buf, req_msg_size, &req_offset, &args.aad);
355 if (rc != NO_ERROR) {
356 TLOGE("failed to set aad\n");
357 resp_header->result = tipc_err_to_hwaes_err(rc);
358 goto out;
359 }
360
361 rc = hwaes_set_arg_in(&cmd_header->text_in, PROT_READ, shms, num_handles,
362 req_msg_buf, req_msg_size, &req_offset,
363 &args.text_in);
364 if (rc != NO_ERROR) {
365 TLOGE("failed to set text_in\n");
366 resp_header->result = tipc_err_to_hwaes_err(rc);
367 goto out;
368 }
369
370 rc = hwaes_set_arg_in(&cmd_header->tag_in, PROT_READ, shms, num_handles,
371 req_msg_buf, req_msg_size, &req_offset, &args.tag_in);
372 if (rc != NO_ERROR) {
373 TLOGE("failed to set tag_in\n");
374 resp_header->result = tipc_err_to_hwaes_err(rc);
375 goto out;
376 }
377
378 rc = hwaes_set_arg_out(&cmd_header->text_out, PROT_READ | PROT_WRITE, shms,
379 num_handles, resp_msg_buf, HWAES_MAX_MSG_SIZE,
380 &resp_offset, &args.text_out);
381 if (rc != NO_ERROR) {
382 TLOGE("failed to set text_out\n");
383 resp_header->result = tipc_err_to_hwaes_err(rc);
384 goto out;
385 }
386
387 rc = hwaes_set_arg_out(&cmd_header->tag_out, PROT_READ | PROT_WRITE, shms,
388 num_handles, resp_msg_buf, HWAES_MAX_MSG_SIZE,
389 &resp_offset, &args.tag_out);
390 if (rc != NO_ERROR) {
391 TLOGE("failed to set tag_out\n");
392 resp_header->result = tipc_err_to_hwaes_err(rc);
393 goto out;
394 }
395
396 resp_header->result = hwaes_aes_op(&args);
397 if (resp_header->result == HWAES_NO_ERROR) {
398 resp_msg_size = resp_offset;
399 }
400
401 out:
402 rc = hwaes_send_resp(chan, resp_msg_buf, resp_msg_size);
403 hwaes_unmap_shm(cmd_header->num_handles, shms);
404 return rc;
405 }
406
407 /**
408 * int hwaes_read_req() - read the request from the client
409 * @chan: the channel handle.
410 * @buf: the pointer to the buffer to store the request.
411 * @shm_handles: the array of shared memory handles.
412 * @num_handles_ptr: pointer to the number of shared memory handles.
413 * @req_msg_size_ptr: pointer to the size of request message.
414 *
415 * Returns: NO_ERROR on success, negative error code on failure
416 */
hwaes_read_req(handle_t chan,void * buf,handle_t * shm_handles,size_t * num_handles_ptr,size_t * req_msg_size_ptr)417 static int hwaes_read_req(handle_t chan,
418 void* buf,
419 handle_t* shm_handles,
420 size_t* num_handles_ptr,
421 size_t* req_msg_size_ptr) {
422 int rc;
423 struct ipc_msg_info msg_inf;
424
425 rc = get_msg(chan, &msg_inf);
426 if (rc != NO_ERROR) {
427 TLOGE("failed (%d) to get_msg()\n", rc);
428 return rc;
429 }
430
431 if (msg_inf.len < sizeof(struct hwaes_req) ||
432 msg_inf.len > HWAES_MAX_MSG_SIZE) {
433 TLOGE("unexpected msg size: buffer too small or too big\n");
434 rc = ERR_BAD_LEN;
435 goto free_msg;
436 }
437
438 if (msg_inf.num_handles > HWAES_MAX_NUM_HANDLES) {
439 TLOGE("too many shared memory handles\n");
440 rc = ERR_BAD_LEN;
441 goto free_msg;
442 }
443
444 struct iovec iov = {
445 .iov_base = buf,
446 .iov_len = HWAES_MAX_MSG_SIZE,
447 };
448 struct ipc_msg ipc_msg = {
449 .iov = &iov,
450 .num_iov = 1,
451 .handles = shm_handles,
452 .num_handles = msg_inf.num_handles,
453 };
454
455 rc = read_msg(chan, msg_inf.id, 0, &ipc_msg);
456 if (rc < 0) {
457 TLOGE("failed (%d) to read_msg()\n", rc);
458 goto free_msg;
459 }
460 assert(rc == (int)msg_inf.len);
461
462 *req_msg_size_ptr = rc;
463 *num_handles_ptr = msg_inf.num_handles;
464 rc = NO_ERROR;
465
466 free_msg:
467 put_msg(chan, msg_inf.id);
468 return rc;
469 }
470
hwaes_on_message(const struct tipc_port * port,handle_t chan,void * ctx)471 static int hwaes_on_message(const struct tipc_port* port,
472 handle_t chan,
473 void* ctx) {
474 int rc;
475
476 handle_t shm_handles[HWAES_MAX_NUM_HANDLES];
477 size_t num_handles = 0;
478 size_t req_msg_size;
479
480 uint8_t* req_msg_buf = memalign(AUX_PAGE_SIZE(), HWAES_MAX_MSG_SIZE);
481 uint8_t* resp_msg_buf = memalign(AUX_PAGE_SIZE(), HWAES_MAX_MSG_SIZE);
482
483 if (req_msg_buf == 0 || resp_msg_buf == 0) {
484 TLOGE("failed to allocate memory for req/resp msg.\n");
485 rc = ERR_NO_MEMORY;
486 goto free_handles;
487 }
488
489 rc = hwaes_read_req(chan, req_msg_buf, shm_handles, &num_handles,
490 &req_msg_size);
491 if (rc != NO_ERROR) {
492 TLOGE("failed (%d) to hwaes_read_req()\n", rc);
493 num_handles = 0;
494 goto free_handles;
495 };
496
497 struct hwaes_req* req_header = (struct hwaes_req*)req_msg_buf;
498 if (req_header->reserved) {
499 TLOGE("bad general header, reserved not 0, (%d)\n",
500 req_header->reserved);
501 rc = ERR_NOT_VALID;
502 goto free_handles;
503 }
504
505 struct hwaes_resp* resp_header = (struct hwaes_resp*)resp_msg_buf;
506
507 resp_header->cmd = req_header->cmd;
508
509 /* handle it */
510 switch (req_header->cmd) {
511 case HWAES_AES:
512 rc = hwaes_handle_aes_cmd(chan, req_msg_buf, req_msg_size, resp_msg_buf,
513 shm_handles, num_handles);
514 break;
515
516 default:
517 TLOGE("unsupported request: %d\n", (int)req_header->cmd);
518 resp_header->result = HWAES_ERR_NOT_IMPLEMENTED;
519 rc = hwaes_send_resp(chan, resp_header, sizeof(*resp_header));
520 }
521
522 free_handles:
523 for (size_t i = 0; i < num_handles; i++) {
524 close(shm_handles[i]);
525 }
526
527 free(req_msg_buf);
528 free(resp_msg_buf);
529
530 return rc;
531 }
532
add_hwaes_service(struct tipc_hset * hset,const uuid_t ** allowed_clients,size_t allowed_clients_len)533 int add_hwaes_service(struct tipc_hset* hset,
534 const uuid_t** allowed_clients,
535 size_t allowed_clients_len) {
536 static struct tipc_port_acl acl = {
537 .flags = IPC_PORT_ALLOW_TA_CONNECT,
538 };
539 acl.uuid_num = allowed_clients_len;
540 acl.uuids = allowed_clients;
541
542 static struct tipc_port port = {
543 .name = HWAES_PORT,
544 .msg_max_size = HWAES_MAX_MSG_SIZE,
545 .msg_queue_len = 1,
546 .acl = &acl,
547 };
548 static struct tipc_srv_ops ops = {
549 .on_message = hwaes_on_message,
550 };
551 return tipc_add_service(hset, &port, 1, 2, &ops);
552 }
553