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 struct keybox_chan_ctx {
36 struct tipc_event_handler evt_handler;
37 handle_t chan;
38 };
39
40 static void keybox_port_handler(const uevent_t* ev, void* priv);
41 static void keybox_chan_handler(const uevent_t* ev, void* priv);
42
43 static handle_t keybox_port = INVALID_IPC_HANDLE;
44
45 static struct tipc_event_handler keybox_port_evt_handler = {
46 .proc = keybox_port_handler,
47 };
48
keybox_shutdown(struct keybox_chan_ctx * ctx)49 static void keybox_shutdown(struct keybox_chan_ctx* ctx) {
50 close(ctx->chan);
51 free(ctx);
52 }
53
54 struct full_keybox_unwrap_req {
55 struct keybox_unwrap_req unwrap_header;
56 uint8_t wrapped_keybox[KEYBOX_MAX_SIZE];
57 };
58
59 struct full_keybox_unwrap_resp {
60 struct keybox_resp header;
61 struct keybox_unwrap_resp unwrap_header;
62 };
63
keybox_handle_unwrap(handle_t chan,struct full_keybox_unwrap_req * req,size_t req_size)64 static int keybox_handle_unwrap(handle_t chan,
65 struct full_keybox_unwrap_req* req,
66 size_t req_size) {
67 struct full_keybox_unwrap_resp rsp = {
68 .header.cmd = KEYBOX_CMD_UNWRAP | KEYBOX_CMD_RSP_BIT,
69 };
70
71 uint8_t output[KEYBOX_MAX_SIZE];
72 if (req_size < sizeof(req->unwrap_header)) {
73 rsp.header.status = KEYBOX_STATUS_INVALID_REQUEST;
74 goto out;
75 }
76
77 uint64_t computed_size;
78 if (__builtin_add_overflow(req->unwrap_header.wrapped_keybox_len,
79 sizeof(req->unwrap_header), &computed_size)) {
80 rsp.header.status = KEYBOX_STATUS_INVALID_REQUEST;
81 goto out;
82 }
83 if (computed_size != req_size) {
84 rsp.header.status = KEYBOX_STATUS_INVALID_REQUEST;
85 goto out;
86 }
87
88 rsp.header.status = keybox_unwrap(
89 req->wrapped_keybox, req->unwrap_header.wrapped_keybox_len, output,
90 sizeof(output), (size_t*)&rsp.unwrap_header.unwrapped_keybox_len);
91 if (rsp.header.status != KEYBOX_STATUS_SUCCESS) {
92 goto out;
93 }
94
95 return tipc_send2(chan, &rsp, sizeof(rsp), output,
96 rsp.unwrap_header.unwrapped_keybox_len);
97
98 out:
99 return tipc_send1(chan, &rsp, sizeof(rsp.header));
100 }
101
102 struct full_keybox_req {
103 struct keybox_req header;
104 union {
105 struct full_keybox_unwrap_req unwrap;
106 } cmd_header;
107 };
108
keybox_handle_msg(struct keybox_chan_ctx * ctx)109 static int keybox_handle_msg(struct keybox_chan_ctx* ctx) {
110 int rc;
111 struct full_keybox_req req;
112 enum keybox_status status = KEYBOX_STATUS_SUCCESS;
113 rc = tipc_recv1(ctx->chan, sizeof(req.header), &req, sizeof(req));
114 if (rc < 0) {
115 TLOGE("Failed (%d) to receive Keybox message\n", rc);
116 return KEYBOX_STATUS_INTERNAL_ERROR;
117 }
118
119 size_t cmd_specific_size = (size_t)rc - sizeof(req.header);
120 switch (req.header.cmd) {
121 case KEYBOX_CMD_UNWRAP:
122 rc = keybox_handle_unwrap(ctx->chan, &req.cmd_header.unwrap,
123 cmd_specific_size);
124 break;
125 default:
126 TLOGE("Invalid Keybox command: %d\n", req.header.cmd);
127 struct keybox_resp rsp;
128 rsp.cmd = req.header.cmd | KEYBOX_CMD_RSP_BIT;
129 rsp.status = KEYBOX_STATUS_INVALID_REQUEST;
130 rc = tipc_send1(ctx->chan, &rsp, sizeof(rsp));
131 }
132
133 if (rc < 0) {
134 status = KEYBOX_STATUS_INTERNAL_ERROR;
135 }
136
137 return status;
138 }
139
keybox_chan_handler(const uevent_t * ev,void * priv)140 static void keybox_chan_handler(const uevent_t* ev, void* priv) {
141 struct keybox_chan_ctx* ctx = (struct keybox_chan_ctx*)priv;
142 assert(ctx);
143 assert(ev->handle == ctx->chan);
144
145 tipc_handle_chan_errors(ev);
146 int rc = 0;
147 if (ev->event & IPC_HANDLE_POLL_MSG) {
148 rc = keybox_handle_msg(ctx);
149 }
150 if (ev->event & IPC_HANDLE_POLL_HUP) {
151 keybox_shutdown(ctx);
152 }
153 if (rc) {
154 keybox_shutdown(ctx);
155 }
156 }
157
keybox_port_handler(const uevent_t * ev,void * priv)158 static void keybox_port_handler(const uevent_t* ev, void* priv) {
159 uuid_t peer_uuid;
160
161 tipc_handle_port_errors(ev);
162
163 if (ev->event & IPC_HANDLE_POLL_READY) {
164 handle_t chan;
165
166 /* incoming connection: accept it */
167 int rc = accept(ev->handle, &peer_uuid);
168 if (rc < 0) {
169 TLOGE("failed (%d) to accept on port %d\n", rc, ev->handle);
170 return;
171 }
172 chan = (handle_t)rc;
173
174 struct keybox_chan_ctx* ctx = calloc(1, sizeof(struct keybox_chan_ctx));
175
176 if (!ctx) {
177 TLOGE("failed to alloc state for chan %d\n", chan);
178 close(chan);
179 return;
180 }
181
182 /* init channel state */
183 ctx->evt_handler.priv = ctx;
184 ctx->evt_handler.proc = keybox_chan_handler;
185 ctx->chan = chan;
186
187 /* attach channel handler */
188 rc = set_cookie(chan, &ctx->evt_handler);
189 if (rc) {
190 TLOGE("failed (%d) to set_cookie on chan %d\n", rc, chan);
191 free(ctx);
192 close(chan);
193 return;
194 }
195 }
196 }
197
198 /*
199 * Initialize Keybox service
200 */
keybox_start_service(void)201 int keybox_start_service(void) {
202 int rc;
203
204 TLOGD("Start Keybox service\n");
205
206 /* create Keybox port */
207 rc = port_create(KEYBOX_PORT, 1, sizeof(struct full_keybox_req),
208 IPC_PORT_ALLOW_TA_CONNECT);
209 if (rc < 0) {
210 TLOGE("Failed (%d) to create port '%s'\n", rc, KEYBOX_PORT);
211 goto cleanup;
212 }
213
214 keybox_port = (handle_t)rc;
215 set_cookie(keybox_port, &keybox_port_evt_handler);
216
217 return NO_ERROR;
218
219 cleanup:
220 close(keybox_port);
221 return rc;
222 }
223