• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 /* UUID: {19c7289c-5004-4a30-b85a-2a22a76e6327} */
79 static const struct uuid widevine_vm_uuid = {
80         0x19c7289c,
81         0x5004,
82         0x4a30,
83         {0xb8, 0x5a, 0x2a, 0x22, 0xa7, 0x6e, 0x63, 0x27},
84 };
85 
86 /* ZERO UUID to allow connections from non-secure world */
87 static const struct uuid zero_uuid = UUID_INITIAL_VALUE(zero_uuid);
88 
89 static const struct uuid* allowed_uuids[] = {
90         &km_uuid,       &hwbcc_test_uuid,  &hwbcc_rust_test_uuid,
91         &widevine_uuid, &widevine_vm_uuid, &zero_uuid,
92 };
93 
94 static struct tipc_port_acl acl = {
95         .flags = IPC_PORT_ALLOW_TA_CONNECT | IPC_PORT_ALLOW_NS_CONNECT,
96         .uuids = allowed_uuids,
97         .uuid_num = countof(allowed_uuids),
98 };
99 
100 static struct tipc_port port = {
101         .name = HWBCC_PORT,
102         .msg_max_size =
103                 MAX(sizeof(struct hwbcc_req), sizeof(struct hwbcc_resp)),
104         .msg_queue_len = 1,
105         .acl = &acl,
106 };
107 
108 static const struct hwbcc_ops* hwbcc_ops;
109 
hwbcc_check_ops(const struct hwbcc_ops * ops)110 static int hwbcc_check_ops(const struct hwbcc_ops* ops) {
111     if (!ops->init || !ops->close || !ops->sign_key || !ops->get_bcc ||
112         !ops->get_dice_artifacts || !ops->ns_deprivilege) {
113         TLOGE("NULL ops pointers\n");
114         return ERR_INVALID_ARGS;
115     }
116     return NO_ERROR;
117 }
118 
on_connect(const struct tipc_port * port,handle_t chan,const struct uuid * peer,void ** ctx_p)119 static int on_connect(const struct tipc_port* port,
120                       handle_t chan,
121                       const struct uuid* peer,
122                       void** ctx_p) {
123     assert(hwbcc_ops);
124 
125     hwbcc_session_t s;
126     int rc = hwbcc_ops->init(&s, peer);
127     if (rc != NO_ERROR) {
128         TLOGE("Failed to init HWBCC session: %d\n", rc);
129         return rc;
130     }
131 
132     *ctx_p = s;
133     return NO_ERROR;
134 }
135 
on_channel_cleanup(void * ctx)136 static void on_channel_cleanup(void* ctx) {
137     assert(hwbcc_ops);
138 
139     hwbcc_session_t s = ctx;
140     hwbcc_ops->close(s);
141 }
142 
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)143 static int handle_sign_data(hwbcc_session_t s,
144                             handle_t chan,
145                             uint32_t test_mode,
146                             struct hwbcc_req_sign_data* args,
147                             const uint8_t* data_and_aad) {
148     int rc;
149     struct hwbcc_resp resp = {0};
150     size_t payload_size = 0;
151 
152     assert(hwbcc_ops);
153 
154     rc = hwbcc_ops->sign_key(s, test_mode, args->algorithm, data_and_aad,
155                              args->data_size, data_and_aad + args->data_size,
156                              args->aad_size, resp.payload, sizeof(resp.payload),
157                              &payload_size);
158     if (rc != NO_ERROR) {
159         TLOGE("HWBCC_CMD_SIGN_DATA failure: %d\n", rc);
160     }
161 
162     resp.hdr.cmd = HWBCC_CMD_SIGN_DATA | HWBCC_CMD_RESP_BIT;
163     resp.hdr.status = rc;
164     resp.hdr.payload_size = payload_size;
165     rc = tipc_send1(chan, &resp, sizeof(resp.hdr) + payload_size);
166     if (rc < 0) {
167         return rc;
168     }
169 
170     if ((size_t)rc != sizeof(resp.hdr) + payload_size) {
171         return ERR_BAD_LEN;
172     }
173 
174     return NO_ERROR;
175 }
176 
handle_get_bcc(hwbcc_session_t s,handle_t chan,uint32_t test_mode)177 static int handle_get_bcc(hwbcc_session_t s,
178                           handle_t chan,
179                           uint32_t test_mode) {
180     int rc;
181     struct hwbcc_resp resp = {0};
182     size_t payload_size = 0;
183 
184     assert(hwbcc_ops);
185 
186     rc = hwbcc_ops->get_bcc(s, test_mode, resp.payload, sizeof(resp.payload),
187                             &payload_size);
188     if (rc != NO_ERROR) {
189         TLOGE("HWBCC_CMD_GET_BCC failure: %d\n", rc);
190     }
191 
192     resp.hdr.cmd = HWBCC_CMD_GET_BCC | HWBCC_CMD_RESP_BIT;
193     resp.hdr.status = rc;
194     resp.hdr.payload_size = payload_size;
195     rc = tipc_send1(chan, &resp, sizeof(resp.hdr) + payload_size);
196     if (rc < 0) {
197         return rc;
198     }
199 
200     if ((size_t)rc != sizeof(resp.hdr) + payload_size) {
201         return ERR_BAD_LEN;
202     }
203 
204     return NO_ERROR;
205 }
206 
handle_get_dice_artifacts(hwbcc_session_t s,handle_t chan,uint64_t context)207 static int handle_get_dice_artifacts(hwbcc_session_t s,
208                                      handle_t chan,
209                                      uint64_t context) {
210     int rc;
211     struct hwbcc_resp resp = {0};
212     size_t payload_size = 0;
213 
214     assert(hwbcc_ops);
215 
216     rc = hwbcc_ops->get_dice_artifacts(s, context, resp.payload,
217                                        sizeof(resp.payload), &payload_size);
218 
219     if (rc != NO_ERROR) {
220         TLOGE("HWBCC_CMD_GET_DICE_ARTIFACTS failure: %d\n", rc);
221     }
222 
223     resp.hdr.cmd = HWBCC_CMD_GET_DICE_ARTIFACTS | HWBCC_CMD_RESP_BIT;
224     resp.hdr.status = rc;
225     resp.hdr.payload_size = payload_size;
226 
227     rc = tipc_send1(chan, &resp, sizeof(resp.hdr) + payload_size);
228     if (rc < 0) {
229         return rc;
230     }
231 
232     if ((size_t)rc != sizeof(resp.hdr) + payload_size) {
233         return ERR_BAD_LEN;
234     }
235 
236     return NO_ERROR;
237 }
238 
handle_ns_deprivilege(hwbcc_session_t s,handle_t chan)239 static int handle_ns_deprivilege(hwbcc_session_t s, handle_t chan) {
240     int rc;
241     struct hwbcc_resp resp = {0};
242 
243     assert(hwbcc_ops);
244 
245     rc = hwbcc_ops->ns_deprivilege(s);
246 
247     if (rc != NO_ERROR) {
248         TLOGE("HWBCC_CMD_NS_DEPRIVILEGE failure: %d\n", rc);
249     }
250 
251     resp.hdr.cmd = HWBCC_CMD_NS_DEPRIVILEGE | HWBCC_CMD_RESP_BIT;
252     resp.hdr.status = rc;
253 
254     rc = tipc_send1(chan, &resp, sizeof(resp.hdr));
255     if (rc < 0) {
256         return rc;
257     }
258 
259     if ((size_t)rc != sizeof(resp.hdr)) {
260         return ERR_BAD_LEN;
261     }
262 
263     return NO_ERROR;
264 }
265 
on_message(const struct tipc_port * port,handle_t chan,void * ctx)266 static int on_message(const struct tipc_port* port, handle_t chan, void* ctx) {
267     int rc;
268     struct hwbcc_req req;
269     hwbcc_session_t s = ctx;
270 
271     rc = tipc_recv1(chan, sizeof(req.hdr), &req, sizeof(req));
272     if (rc < 0) {
273         TLOGE("Failed to read command %d\n", rc);
274         return rc;
275     }
276 
277     switch (req.hdr.cmd) {
278     case HWBCC_CMD_SIGN_DATA: {
279         if ((size_t)rc < sizeof(req.hdr) + sizeof(req.args)) {
280             return ERR_BAD_LEN;
281         }
282 
283         if (req.args.aad_size > HWBCC_MAX_AAD_SIZE) {
284             return ERR_BAD_LEN;
285         }
286 
287         if (req.args.data_size > HWBCC_MAX_DATA_TO_SIGN_SIZE) {
288             return ERR_BAD_LEN;
289         }
290 
291         if (rc - sizeof(req.hdr) - sizeof(req.args) !=
292             req.args.data_size + req.args.aad_size) {
293             return ERR_BAD_LEN;
294         }
295 
296         return handle_sign_data(s, chan, req.hdr.test_mode, &req.args,
297                                 req.data_and_aad);
298     }
299 
300     case HWBCC_CMD_GET_BCC:
301         if (rc != sizeof(req.hdr)) {
302             return ERR_BAD_LEN;
303         }
304 
305         return handle_get_bcc(s, chan, req.hdr.test_mode);
306 
307     case HWBCC_CMD_GET_DICE_ARTIFACTS:
308         if (rc != sizeof(req.hdr)) {
309             return ERR_BAD_LEN;
310         }
311 
312         return handle_get_dice_artifacts(s, chan, req.hdr.context);
313 
314     case HWBCC_CMD_NS_DEPRIVILEGE:
315         if (rc != sizeof(req.hdr)) {
316             return ERR_BAD_LEN;
317         }
318 
319         return handle_ns_deprivilege(s, chan);
320 
321     default:
322         TLOGE("Received unknown command %x\n", req.hdr.cmd);
323         return ERR_CMD_UNKNOWN;
324     }
325 
326     return NO_ERROR;
327 }
328 
329 static struct tipc_srv_ops tipc_ops = {
330         .on_connect = on_connect,
331         .on_message = on_message,
332         .on_channel_cleanup = on_channel_cleanup,
333 };
334 
335 /*
336  * TODO: Currently we only support one instance of HWBCC service, i.e. this
337  * function can only be called once.
338  */
add_hwbcc_service(struct tipc_hset * hset,const struct hwbcc_ops * ops)339 int add_hwbcc_service(struct tipc_hset* hset, const struct hwbcc_ops* ops) {
340     int rc = hwbcc_check_ops(ops);
341     if (rc != NO_ERROR) {
342         return rc;
343     }
344     hwbcc_ops = ops;
345 
346     return tipc_add_service(hset, &port, 1, 1, &tipc_ops);
347 }
348