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