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