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 "keybox"
18
19 #include <assert.h>
20 #include <inttypes.h>
21 #include <lk/list.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <uapi/err.h>
26
27 #include <interface/keybox/keybox.h>
28
29 #include <lib/tipc/tipc.h>
30 #include <trusty_log.h>
31
32 #include "keybox.h"
33 #include "srv.h"
34
35 /* 0 means unlimited number of connections */
36 #define KEYBOX_MAX_NUM_CHANNELS 0
37
38 struct keybox_chan_ctx {
39 struct tipc_event_handler evt_handler;
40 handle_t chan;
41 };
42
43 struct full_keybox_unwrap_req {
44 struct keybox_unwrap_req unwrap_header;
45 uint8_t wrapped_keybox[KEYBOX_MAX_SIZE];
46 };
47
48 struct full_keybox_unwrap_resp {
49 struct keybox_resp header;
50 struct keybox_unwrap_resp unwrap_header;
51 };
52
keybox_handle_unwrap(handle_t chan,struct full_keybox_unwrap_req * req,size_t req_size)53 static int keybox_handle_unwrap(handle_t chan,
54 struct full_keybox_unwrap_req* req,
55 size_t req_size) {
56 struct full_keybox_unwrap_resp rsp = {
57 .header.cmd = KEYBOX_CMD_UNWRAP | KEYBOX_CMD_RSP_BIT,
58 };
59
60 uint8_t output[KEYBOX_MAX_SIZE];
61 if (req_size < sizeof(req->unwrap_header)) {
62 rsp.header.status = KEYBOX_STATUS_INVALID_REQUEST;
63 goto out;
64 }
65
66 uint64_t computed_size;
67 if (__builtin_add_overflow(req->unwrap_header.wrapped_keybox_len,
68 sizeof(req->unwrap_header), &computed_size)) {
69 rsp.header.status = KEYBOX_STATUS_INVALID_REQUEST;
70 goto out;
71 }
72 if (computed_size != req_size) {
73 rsp.header.status = KEYBOX_STATUS_INVALID_REQUEST;
74 goto out;
75 }
76
77 rsp.header.status = keybox_unwrap(
78 req->wrapped_keybox, req->unwrap_header.wrapped_keybox_len, output,
79 sizeof(output), (size_t*)&rsp.unwrap_header.unwrapped_keybox_len);
80 if (rsp.header.status != KEYBOX_STATUS_SUCCESS) {
81 goto out;
82 }
83
84 return tipc_send2(chan, &rsp, sizeof(rsp), output,
85 rsp.unwrap_header.unwrapped_keybox_len);
86
87 out:
88 return tipc_send1(chan, &rsp, sizeof(rsp.header));
89 }
90
91 struct full_keybox_req {
92 struct keybox_req header;
93 union {
94 struct full_keybox_unwrap_req unwrap;
95 } cmd_header;
96 };
97
keybox_chan_handle_msg(const struct tipc_port * port,handle_t chan,void * ctx)98 static int keybox_chan_handle_msg(const struct tipc_port* port,
99 handle_t chan,
100 void* ctx) {
101 int rc;
102 struct full_keybox_req req;
103 enum keybox_status status = KEYBOX_STATUS_SUCCESS;
104 rc = tipc_recv1(chan, sizeof(req.header), &req, sizeof(req));
105 if (rc < 0) {
106 TLOGE("Failed (%d) to receive Keybox message\n", rc);
107 return KEYBOX_STATUS_INTERNAL_ERROR;
108 }
109
110 size_t cmd_specific_size = (size_t)rc - sizeof(req.header);
111 switch (req.header.cmd) {
112 case KEYBOX_CMD_UNWRAP:
113 rc = keybox_handle_unwrap(chan, &req.cmd_header.unwrap,
114 cmd_specific_size);
115 break;
116 default:
117 TLOGE("Invalid Keybox command: %d\n", req.header.cmd);
118 struct keybox_resp rsp;
119 rsp.cmd = req.header.cmd | KEYBOX_CMD_RSP_BIT;
120 rsp.status = KEYBOX_STATUS_INVALID_REQUEST;
121 rc = tipc_send1(chan, &rsp, sizeof(rsp));
122 }
123
124 if (rc < 0) {
125 status = KEYBOX_STATUS_INTERNAL_ERROR;
126 }
127
128 return status;
129 }
130
131 /*
132 * Initialize Keybox service
133 */
keybox_start_service(struct tipc_hset * hset)134 int keybox_start_service(struct tipc_hset* hset) {
135 TLOGD("Start Keybox service\n");
136
137 // TODO: check why we are not restricting connections by uuid
138 static struct tipc_port_acl acl = {
139 .flags = IPC_PORT_ALLOW_TA_CONNECT,
140 .uuid_num = 0,
141 .uuids = NULL,
142 };
143
144 static struct tipc_port port = {
145 .name = KEYBOX_PORT,
146 .msg_max_size = sizeof(struct full_keybox_req),
147 .msg_queue_len = 1,
148 .acl = &acl,
149 };
150 static struct tipc_srv_ops ops = {
151 .on_message = keybox_chan_handle_msg,
152 };
153 return tipc_add_service(hset, &port, 1, KEYBOX_MAX_NUM_CHANNELS, &ops);
154 }
155