1 /*
2 * Copyright 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 "hwbcc-srv"
18
19 #include <assert.h>
20 #include <interface/hwbcc/hwbcc.h>
21 #include <lib/hwbcc/srv/srv.h>
22 #include <lib/tipc/tipc.h>
23 #include <lib/tipc/tipc_srv.h>
24 #include <string.h>
25 #include <trusty_ipc.h>
26 #include <trusty_log.h>
27 #include <uapi/err.h>
28
29 struct hwbcc_req {
30 struct hwbcc_req_hdr hdr;
31 struct hwbcc_req_sign_data args;
32 uint8_t data_and_aad[HWBCC_MAX_DATA_TO_SIGN_SIZE + HWBCC_MAX_AAD_SIZE];
33 };
34 STATIC_ASSERT(sizeof(struct hwbcc_req) ==
35 sizeof(struct hwbcc_req_hdr) +
36 sizeof(struct hwbcc_req_sign_data) +
37 HWBCC_MAX_DATA_TO_SIGN_SIZE + HWBCC_MAX_AAD_SIZE);
38
39 struct hwbcc_resp {
40 struct hwbcc_resp_hdr hdr;
41 uint8_t payload[HWBCC_MAX_RESP_PAYLOAD_SIZE];
42 };
43 STATIC_ASSERT(sizeof(struct hwbcc_resp) ==
44 sizeof(struct hwbcc_resp_hdr) + HWBCC_MAX_RESP_PAYLOAD_SIZE);
45
46 /* UUID: {5f902ace-5e5c-4cd8-ae54-87b88c22ddaf} */
47 static const struct uuid km_uuid = {
48 0x5f902ace,
49 0x5e5c,
50 0x4cd8,
51 {0xae, 0x54, 0x87, 0xb8, 0x8c, 0x22, 0xdd, 0xaf},
52 };
53
54 /* UUID: {0e109d31-8bbe-47d6-bb47-e1dd08910e16} */
55 static const struct uuid hwbcc_test_uuid = {
56 0x0e109d31,
57 0x8bbe,
58 0x47d6,
59 {0xbb, 0x47, 0xe1, 0xdd, 0x08, 0x91, 0x0e, 0x16},
60 };
61
62 /* UUID: {67925337-2c03-49ed-9240-d51b6fea3e30} */
63 static const struct uuid hwbcc_rust_test_uuid = {
64 0x67925337,
65 0x2c03,
66 0x49ed,
67 {0x92, 0x40, 0xd5, 0x1b, 0x6f, 0xea, 0x3e, 0x30},
68 };
69
70 /* UUID: {08d3ed40-bde2-448c-a91d75f1989c57ef} */
71 static const struct uuid widevine_uuid = {
72 0x08d3ed40,
73 0xbde2,
74 0x448c,
75 {0xa9, 0x1d, 0x75, 0xf1, 0x98, 0x9c, 0x57, 0xef},
76 };
77
78 /* ZERO UUID to allow connections from non-secure world */
79 static const struct uuid zero_uuid = UUID_INITIAL_VALUE(zero_uuid);
80
81 static const struct uuid* allowed_uuids[] = {
82 &km_uuid, &hwbcc_test_uuid, &hwbcc_rust_test_uuid,
83 &widevine_uuid, &zero_uuid,
84 };
85
86 static struct tipc_port_acl acl = {
87 .flags = IPC_PORT_ALLOW_TA_CONNECT | IPC_PORT_ALLOW_NS_CONNECT,
88 .uuids = allowed_uuids,
89 .uuid_num = countof(allowed_uuids),
90 };
91
92 static struct tipc_port port = {
93 .name = HWBCC_PORT,
94 .msg_max_size =
95 MAX(sizeof(struct hwbcc_req), sizeof(struct hwbcc_resp)),
96 .msg_queue_len = 1,
97 .acl = &acl,
98 };
99
100 static const struct hwbcc_ops* hwbcc_ops;
101
hwbcc_check_ops(const struct hwbcc_ops * ops)102 static int hwbcc_check_ops(const struct hwbcc_ops* ops) {
103 if (!ops->init || !ops->close || !ops->sign_key || !ops->get_bcc ||
104 !ops->get_dice_artifacts || !ops->ns_deprivilege) {
105 TLOGE("NULL ops pointers\n");
106 return ERR_INVALID_ARGS;
107 }
108 return NO_ERROR;
109 }
110
on_connect(const struct tipc_port * port,handle_t chan,const struct uuid * peer,void ** ctx_p)111 static int on_connect(const struct tipc_port* port,
112 handle_t chan,
113 const struct uuid* peer,
114 void** ctx_p) {
115 assert(hwbcc_ops);
116
117 hwbcc_session_t s;
118 int rc = hwbcc_ops->init(&s, peer);
119 if (rc != NO_ERROR) {
120 TLOGE("Failed to init HWBCC session: %d\n", rc);
121 return rc;
122 }
123
124 *ctx_p = s;
125 return NO_ERROR;
126 }
127
on_channel_cleanup(void * ctx)128 static void on_channel_cleanup(void* ctx) {
129 assert(hwbcc_ops);
130
131 hwbcc_session_t s = ctx;
132 hwbcc_ops->close(s);
133 }
134
handle_sign_data(hwbcc_session_t s,handle_t chan,uint32_t test_mode,struct hwbcc_req_sign_data * args,const uint8_t * data_and_aad)135 static int handle_sign_data(hwbcc_session_t s,
136 handle_t chan,
137 uint32_t test_mode,
138 struct hwbcc_req_sign_data* args,
139 const uint8_t* data_and_aad) {
140 int rc;
141 struct hwbcc_resp resp = {0};
142 size_t payload_size = 0;
143
144 assert(hwbcc_ops);
145
146 rc = hwbcc_ops->sign_key(s, test_mode, args->algorithm, data_and_aad,
147 args->data_size, data_and_aad + args->data_size,
148 args->aad_size, resp.payload, sizeof(resp.payload),
149 &payload_size);
150 if (rc != NO_ERROR) {
151 TLOGE("HWBCC_CMD_SIGN_DATA failure: %d\n", rc);
152 }
153
154 resp.hdr.cmd = HWBCC_CMD_SIGN_DATA | HWBCC_CMD_RESP_BIT;
155 resp.hdr.status = rc;
156 resp.hdr.payload_size = payload_size;
157 rc = tipc_send1(chan, &resp, sizeof(resp.hdr) + payload_size);
158 if (rc < 0) {
159 return rc;
160 }
161
162 if ((size_t)rc != sizeof(resp.hdr) + payload_size) {
163 return ERR_BAD_LEN;
164 }
165
166 return NO_ERROR;
167 }
168
handle_get_bcc(hwbcc_session_t s,handle_t chan,uint32_t test_mode)169 static int handle_get_bcc(hwbcc_session_t s,
170 handle_t chan,
171 uint32_t test_mode) {
172 int rc;
173 struct hwbcc_resp resp = {0};
174 size_t payload_size = 0;
175
176 assert(hwbcc_ops);
177
178 rc = hwbcc_ops->get_bcc(s, test_mode, resp.payload, sizeof(resp.payload),
179 &payload_size);
180 if (rc != NO_ERROR) {
181 TLOGE("HWBCC_CMD_GET_BCC failure: %d\n", rc);
182 }
183
184 resp.hdr.cmd = HWBCC_CMD_GET_BCC | HWBCC_CMD_RESP_BIT;
185 resp.hdr.status = rc;
186 resp.hdr.payload_size = payload_size;
187 rc = tipc_send1(chan, &resp, sizeof(resp.hdr) + payload_size);
188 if (rc < 0) {
189 return rc;
190 }
191
192 if ((size_t)rc != sizeof(resp.hdr) + payload_size) {
193 return ERR_BAD_LEN;
194 }
195
196 return NO_ERROR;
197 }
198
handle_get_dice_artifacts(hwbcc_session_t s,handle_t chan,uint64_t context)199 static int handle_get_dice_artifacts(hwbcc_session_t s,
200 handle_t chan,
201 uint64_t context) {
202 int rc;
203 struct hwbcc_resp resp = {0};
204 size_t payload_size = 0;
205
206 assert(hwbcc_ops);
207
208 rc = hwbcc_ops->get_dice_artifacts(s, context, resp.payload,
209 sizeof(resp.payload), &payload_size);
210
211 if (rc != NO_ERROR) {
212 TLOGE("HWBCC_CMD_GET_DICE_ARTIFACTS failure: %d\n", rc);
213 }
214
215 resp.hdr.cmd = HWBCC_CMD_GET_DICE_ARTIFACTS | HWBCC_CMD_RESP_BIT;
216 resp.hdr.status = rc;
217 resp.hdr.payload_size = payload_size;
218
219 rc = tipc_send1(chan, &resp, sizeof(resp.hdr) + payload_size);
220 if (rc < 0) {
221 return rc;
222 }
223
224 if ((size_t)rc != sizeof(resp.hdr) + payload_size) {
225 return ERR_BAD_LEN;
226 }
227
228 return NO_ERROR;
229 }
230
handle_ns_deprivilege(hwbcc_session_t s,handle_t chan)231 static int handle_ns_deprivilege(hwbcc_session_t s, handle_t chan) {
232 int rc;
233 struct hwbcc_resp resp = {0};
234
235 assert(hwbcc_ops);
236
237 rc = hwbcc_ops->ns_deprivilege(s);
238
239 if (rc != NO_ERROR) {
240 TLOGE("HWBCC_CMD_NS_DEPRIVILEGE failure: %d\n", rc);
241 }
242
243 resp.hdr.cmd = HWBCC_CMD_NS_DEPRIVILEGE | HWBCC_CMD_RESP_BIT;
244 resp.hdr.status = rc;
245
246 rc = tipc_send1(chan, &resp, sizeof(resp.hdr));
247 if (rc < 0) {
248 return rc;
249 }
250
251 if ((size_t)rc != sizeof(resp.hdr)) {
252 return ERR_BAD_LEN;
253 }
254
255 return NO_ERROR;
256 }
257
on_message(const struct tipc_port * port,handle_t chan,void * ctx)258 static int on_message(const struct tipc_port* port, handle_t chan, void* ctx) {
259 int rc;
260 struct hwbcc_req req;
261 hwbcc_session_t s = ctx;
262
263 rc = tipc_recv1(chan, sizeof(req.hdr), &req, sizeof(req));
264 if (rc < 0) {
265 TLOGE("Failed to read command %d\n", rc);
266 return rc;
267 }
268
269 switch (req.hdr.cmd) {
270 case HWBCC_CMD_SIGN_DATA: {
271 if ((size_t)rc < sizeof(req.hdr) + sizeof(req.args)) {
272 return ERR_BAD_LEN;
273 }
274
275 if (req.args.aad_size > HWBCC_MAX_AAD_SIZE) {
276 return ERR_BAD_LEN;
277 }
278
279 if (req.args.data_size > HWBCC_MAX_DATA_TO_SIGN_SIZE) {
280 return ERR_BAD_LEN;
281 }
282
283 if (rc - sizeof(req.hdr) - sizeof(req.args) !=
284 req.args.data_size + req.args.aad_size) {
285 return ERR_BAD_LEN;
286 }
287
288 return handle_sign_data(s, chan, req.hdr.test_mode, &req.args,
289 req.data_and_aad);
290 }
291
292 case HWBCC_CMD_GET_BCC:
293 if (rc != sizeof(req.hdr)) {
294 return ERR_BAD_LEN;
295 }
296
297 return handle_get_bcc(s, chan, req.hdr.test_mode);
298
299 case HWBCC_CMD_GET_DICE_ARTIFACTS:
300 if (rc != sizeof(req.hdr)) {
301 return ERR_BAD_LEN;
302 }
303
304 return handle_get_dice_artifacts(s, chan, req.hdr.context);
305
306 case HWBCC_CMD_NS_DEPRIVILEGE:
307 if (rc != sizeof(req.hdr)) {
308 return ERR_BAD_LEN;
309 }
310
311 return handle_ns_deprivilege(s, chan);
312
313 default:
314 TLOGE("Received unknown command %x\n", req.hdr.cmd);
315 return ERR_CMD_UNKNOWN;
316 }
317
318 return NO_ERROR;
319 }
320
321 static struct tipc_srv_ops tipc_ops = {
322 .on_connect = on_connect,
323 .on_message = on_message,
324 .on_channel_cleanup = on_channel_cleanup,
325 };
326
327 /*
328 * TODO: Currently we only support one instance of HWBCC service, i.e. this
329 * function can only be called once.
330 */
add_hwbcc_service(struct tipc_hset * hset,const struct hwbcc_ops * ops)331 int add_hwbcc_service(struct tipc_hset* hset, const struct hwbcc_ops* ops) {
332 int rc = hwbcc_check_ops(ops);
333 if (rc != NO_ERROR) {
334 return rc;
335 }
336 hwbcc_ops = ops;
337
338 return tipc_add_service(hset, &port, 1, 1, &tipc_ops);
339 }
340