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 "swbcc"
18
19 #include <assert.h>
20 #include <dice/android.h>
21 #include <dice/cbor_writer.h>
22 #include <dice/dice.h>
23 #include <dice/ops.h>
24 #include <dice/ops/trait/cose.h>
25 #include <dice/utils.h>
26 #include <interface/hwbcc/hwbcc.h>
27 #include <lib/hwbcc/common/swbcc.h>
28 #include <lib/hwkey/hwkey.h>
29 #include <lib/rng/trusty_rng.h>
30 #include <lib/system_state/system_state.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include <trusty_log.h>
34 #include <uapi/err.h>
35
36 static const uint8_t kdf_ctx[] = "RkpDerivCtx";
37 static const uint8_t uds_ctx[] = "UdsDeriveCtx";
38
39 /* ZERO UUID represents non-secure world */
40 static const struct uuid zero_uuid = UUID_INITIAL_VALUE(zero_uuid);
41
42 /* Set of information required to derive DICE artifacts for the child node. */
43 struct ChildNodeInfo {
44 uint8_t code_hash[DICE_HASH_SIZE];
45 uint8_t authority_hash[DICE_HASH_SIZE];
46 DiceAndroidConfigValues config_descriptor;
47 };
48
49 struct dice_root_state {
50 /* Unique Device Secret - A hardware backed secret */
51 uint8_t UDS[DICE_CDI_SIZE];
52 /* Public key of the key pair derived from a seed derived from UDS. */
53 uint8_t UDS_pub_key[DICE_PUBLIC_KEY_SIZE];
54 /* Secret (of size: DICE_HIDDEN_SIZE) with factory reset life time. */
55 uint8_t FRS[DICE_HIDDEN_SIZE];
56 /**
57 * Information about the child node of Trusty in the DICE chain in
58 * non-secure world (e.g. ABL).
59 */
60 struct ChildNodeInfo child_node_info;
61 };
62
63 struct swbcc_srv_state {
64 void* dice_ctx;
65 struct dice_root_state dice_root;
66 /**
67 * This is set to 1 when a deprivileged call is received from non-secure
68 * world. Assumption: there are no concurrent calls to this app.
69 */
70 bool ns_deprivileged;
71 };
72
73 static struct swbcc_srv_state srv_state;
74
dice_result_to_err(DiceResult result)75 static int dice_result_to_err(DiceResult result) {
76 switch (result) {
77 case kDiceResultOk:
78 return NO_ERROR;
79 case kDiceResultInvalidInput:
80 return ERR_INVALID_ARGS;
81 case kDiceResultBufferTooSmall:
82 return ERR_NOT_ENOUGH_BUFFER;
83 case kDiceResultPlatformError:
84 return (int)result;
85 }
86 }
87
88 struct swbcc_session {
89 uint8_t key_seed[DICE_PRIVATE_KEY_SEED_SIZE];
90 uint8_t pub_key[DICE_PUBLIC_KEY_SIZE];
91 uint8_t priv_key[DICE_PRIVATE_KEY_SIZE];
92
93 uint8_t test_key_seed[DICE_PRIVATE_KEY_SEED_SIZE];
94 uint8_t test_pub_key[DICE_PUBLIC_KEY_SIZE];
95 uint8_t test_priv_key[DICE_PRIVATE_KEY_SIZE];
96
97 struct uuid client_uuid;
98 };
99
100 /* Max size of COSE_Sign1 including payload. */
101 #define MAX_CERTIFICATE_SIZE 512
102
103 /* Set of DICE artifacts passed on from one stage to the next */
104 struct DICEArtifacts {
105 uint8_t next_cdi_attest[DICE_CDI_SIZE];
106 uint8_t next_cdi_seal[DICE_CDI_SIZE];
107 uint8_t next_certificate[MAX_CERTIFICATE_SIZE];
108 size_t next_certificate_size;
109 };
110
111 /* Checks if the call to the TA is from non-secure world. */
is_zero_uuid(const struct uuid peer)112 static bool is_zero_uuid(const struct uuid peer) {
113 if (memcmp(&peer, &zero_uuid, sizeof(zero_uuid))) {
114 return false;
115 } else {
116 return true;
117 }
118 }
119
derive_seed(uint8_t * ctx,uint8_t * seed)120 static int derive_seed(uint8_t* ctx, uint8_t* seed) {
121 long rc = hwkey_open();
122 if (rc < 0) {
123 TLOGE("Failed hwkey_open(): %ld\n", rc);
124 return rc;
125 }
126 hwkey_session_t session = (hwkey_session_t)rc;
127
128 uint32_t kdf_version = HWKEY_KDF_VERSION_1;
129 rc = hwkey_derive(session, &kdf_version, ctx, seed,
130 DICE_PRIVATE_KEY_SEED_SIZE);
131 if (rc != NO_ERROR) {
132 TLOGE("Failed hwkey_derive(): %ld\n", rc);
133 goto out;
134 }
135
136 rc = NO_ERROR;
137
138 out:
139 hwkey_close(session);
140 return (int)rc;
141 }
142
swbcc_glob_init(const uint8_t FRS[DICE_HIDDEN_SIZE],const uint8_t code_hash[DICE_HASH_SIZE],const uint8_t authority_hash[DICE_HASH_SIZE],const DiceAndroidConfigValues * config_descriptor)143 int swbcc_glob_init(const uint8_t FRS[DICE_HIDDEN_SIZE],
144 const uint8_t code_hash[DICE_HASH_SIZE],
145 const uint8_t authority_hash[DICE_HASH_SIZE],
146 const DiceAndroidConfigValues* config_descriptor) {
147 assert(FRS);
148
149 srv_state.ns_deprivileged = false;
150
151 memcpy(srv_state.dice_root.FRS, FRS, DICE_HIDDEN_SIZE);
152
153 memcpy(srv_state.dice_root.child_node_info.code_hash, code_hash,
154 DICE_HIDDEN_SIZE);
155 memcpy(srv_state.dice_root.child_node_info.authority_hash, authority_hash,
156 DICE_HIDDEN_SIZE);
157 srv_state.dice_root.child_node_info.config_descriptor.configs =
158 config_descriptor->configs;
159 /* Component name is not copied, assuming it points to string literals which
160 * are static. */
161 srv_state.dice_root.child_node_info.config_descriptor.component_name =
162 config_descriptor->component_name;
163 srv_state.dice_root.child_node_info.config_descriptor.component_version =
164 config_descriptor->component_version;
165
166 int rc;
167 DiceResult result;
168 uint8_t ctx[DICE_PRIVATE_KEY_SEED_SIZE];
169
170 memset(ctx, 0, sizeof(ctx));
171 memcpy(ctx, uds_ctx, sizeof(uds_ctx));
172
173 /* Init UDS */
174 rc = derive_seed(ctx, srv_state.dice_root.UDS);
175 if (rc != NO_ERROR) {
176 TLOGE("Failed to derive a hardware backed key for UDS.\n");
177 return rc;
178 }
179
180 /* Derive private key seed */
181 uint8_t private_key_seed[DICE_PRIVATE_KEY_SEED_SIZE];
182 result = DiceDeriveCdiPrivateKeySeed(NULL, srv_state.dice_root.UDS,
183 private_key_seed);
184 rc = dice_result_to_err(result);
185 if (rc != NO_ERROR) {
186 TLOGE("Failed to derive a seed for UDS key pair.\n");
187 return rc;
188 }
189 /**
190 * Derive UDS key pair. UDS public key is kept in dice_root to construct
191 * the certificate chain for the child nodes. UDS private key is derived in
192 * every DICE operation which uses it.
193 */
194 uint8_t UDS_private_key[DICE_PRIVATE_KEY_SIZE];
195 result = DiceKeypairFromSeed(NULL, private_key_seed,
196 srv_state.dice_root.UDS_pub_key,
197 UDS_private_key);
198
199 rc = dice_result_to_err(result);
200 if (rc != NO_ERROR) {
201 TLOGE("Failed to derive UDS key pair.\n");
202 return rc;
203 }
204
205 return rc;
206 }
207
swbcc_init(swbcc_session_t * s,const struct uuid * client)208 int swbcc_init(swbcc_session_t* s, const struct uuid* client) {
209 int rc;
210 DiceResult result;
211 uint8_t ctx[DICE_PRIVATE_KEY_SEED_SIZE];
212
213 struct swbcc_session* session =
214 (struct swbcc_session*)calloc(1, sizeof(*session));
215 if (!session) {
216 return ERR_NO_MEMORY;
217 }
218
219 session->client_uuid = *client;
220
221 /**
222 * If the call to hwbcc is to obtain the DICE artifacts, we do not need to
223 * initialize anything other than the UUID in the session, because the
224 * common UDS is initialized during the initialization of the service. We
225 * only need to track the client UUID in that case in order to retrieve the
226 * client's CDI inputs (e.g. code hash). But at this point we do not know
227 * which API method the client is going to call. However, we know that if
228 * the call is from non-secure world, the goal is to retrieve the DICE
229 * artifacts. Therefore, we filter based on the zero UUID for now. But in
230 * the future, we can filter the legacy case of creating a KM specific BCC
231 * via the KM UUID, because the main purpose of hwbcc service is to provide
232 * the DICE artifacts to the clients.
233 */
234 if (is_zero_uuid(session->client_uuid)) {
235 *s = (swbcc_session_t)session;
236
237 /**
238 * Stop serving calls from non-secure world after receiving
239 * `ns_deprivilege` call.
240 */
241 if (srv_state.ns_deprivileged) {
242 return ERR_NOT_ALLOWED;
243 }
244
245 return NO_ERROR;
246 }
247
248 STATIC_ASSERT(sizeof(ctx) >= sizeof(*client) + sizeof(kdf_ctx));
249
250 memset(ctx, 0, sizeof(ctx));
251 memcpy(ctx, client, sizeof(*client));
252 memcpy(ctx + sizeof(*client), kdf_ctx, sizeof(kdf_ctx));
253
254 /* Init BCC keys */
255 rc = derive_seed(ctx, session->key_seed);
256 if (rc != NO_ERROR) {
257 goto err;
258 }
259
260 result = DiceKeypairFromSeed(srv_state.dice_ctx, session->key_seed,
261 session->pub_key, session->priv_key);
262 rc = dice_result_to_err(result);
263 if (rc != NO_ERROR) {
264 TLOGE("Failed to generate keypair: %d\n", rc);
265 return rc;
266 }
267
268 /* Init test keys */
269 rc = trusty_rng_secure_rand(session->test_key_seed,
270 sizeof(session->test_key_seed));
271 if (rc != NO_ERROR) {
272 goto err;
273 }
274
275 result = DiceKeypairFromSeed(srv_state.dice_ctx, session->test_key_seed,
276 session->test_pub_key, session->test_priv_key);
277 rc = dice_result_to_err(result);
278 if (rc != NO_ERROR) {
279 TLOGE("Failed to generate test keypair: %d\n", rc);
280 return rc;
281 }
282
283 *s = (swbcc_session_t)session;
284 return NO_ERROR;
285
286 err:
287 free(session);
288 return rc;
289 }
290
swbcc_ns_deprivilege(swbcc_session_t s)291 int swbcc_ns_deprivilege(swbcc_session_t s) {
292 srv_state.ns_deprivileged = true;
293 return NO_ERROR;
294 }
295
swbcc_close(swbcc_session_t s)296 void swbcc_close(swbcc_session_t s) {
297 free(s);
298 }
299
300 /*
301 * Format and (size) of a COSE_Sign1 Msg in this case is:
302 * Array header (1) | Protected Params (4) | Unprotected Params (1) |
303 * MAC Key Hdr (2) | MAC Key (32) | Sig Hdr (2) | Sig (64)
304 */
305 #define MAC_SIGN1_SIZE (106)
306
swbcc_sign_key(swbcc_session_t s,uint32_t test_mode,int32_t cose_algorithm,const uint8_t * key,uint32_t key_size,const uint8_t * aad,size_t aad_size,uint8_t * cose_sign1,size_t cose_sign1_buf_size,size_t * cose_sign1_size)307 int swbcc_sign_key(swbcc_session_t s,
308 uint32_t test_mode,
309 int32_t cose_algorithm,
310 const uint8_t* key,
311 uint32_t key_size,
312 const uint8_t* aad,
313 size_t aad_size,
314 uint8_t* cose_sign1,
315 size_t cose_sign1_buf_size,
316 size_t* cose_sign1_size) {
317 int rc;
318 DiceResult result;
319 const uint8_t* signing_key;
320 struct swbcc_session* session = s;
321
322 assert(s);
323 assert(key);
324 assert(aad);
325 assert(cose_sign1);
326 assert(cose_sign1_size);
327 assert(cose_sign1_buf_size >= MAC_SIGN1_SIZE);
328
329 if (cose_algorithm != HWBCC_ALGORITHM_ED25519) {
330 TLOGE("Signing algorithm is not supported: %d\n", cose_algorithm);
331 return ERR_NOT_SUPPORTED;
332 }
333
334 signing_key = test_mode ? session->test_priv_key : session->priv_key;
335
336 result = DiceCoseSignAndEncodeSign1(
337 srv_state.dice_ctx, key, key_size, aad, aad_size, signing_key,
338 cose_sign1_buf_size, cose_sign1, cose_sign1_size);
339 rc = dice_result_to_err(result);
340 if (rc != NO_ERROR) {
341 TLOGE("Failed to generate COSE_Sign1: %d\n", rc);
342 return rc;
343 }
344
345 return NO_ERROR;
346 }
347
348 #define CONFIG_DESCRIPTOR_TOTAL_SIZE 48
349
350 /*
351 * Format and (size) of a COSE_Sign1 Msg in this case is:
352 * Array header (1) | Protected Params (4) | Unprotected Params (1) |
353 * CWT Hdr (2) | CWT (76) | Sig Hdr (2) | Sig (64)
354 */
355 #define BCC_SIGN1_SIZE (150)
356
357 /*
358 * Format and (size) of BCC in this case is:
359 * Array header (1) | Encoded pub key (44) | COSE_Sign1 certificate
360 */
361 #define BCC_TOTAL_SIZE (45 + BCC_SIGN1_SIZE)
362
encode_degenerate_cert(void * dice_ctx,const uint8_t * seed,uint8_t * cert,size_t cert_buf_size,size_t * cert_size)363 static int encode_degenerate_cert(void* dice_ctx,
364 const uint8_t* seed,
365 uint8_t* cert,
366 size_t cert_buf_size,
367 size_t* cert_size) {
368 int rc;
369 DiceResult result;
370 DiceInputValues input_values = {};
371
372 /*
373 * No need to provide DICE inputs for this self-signed certificate other
374 * than the configuration descriptor which should conform to the
375 * specification from the RKP HAL.
376 */
377 DiceAndroidConfigValues config_values = {};
378 uint8_t config_descriptor_encoded[CONFIG_DESCRIPTOR_TOTAL_SIZE];
379 size_t config_descriptor_encoded_size = 0;
380
381 result = DiceAndroidFormatConfigDescriptor(
382 &config_values, sizeof(config_descriptor_encoded),
383 config_descriptor_encoded, &config_descriptor_encoded_size);
384
385 rc = dice_result_to_err(result);
386 if (rc != NO_ERROR) {
387 TLOGE("Failed to format config descriptor : %d\n", rc);
388 return rc;
389 }
390
391 input_values.config_type = kDiceConfigTypeDescriptor;
392 input_values.config_descriptor = config_descriptor_encoded;
393 input_values.config_descriptor_size = config_descriptor_encoded_size;
394
395 result = DiceGenerateCertificate(dice_ctx, seed, seed, &input_values,
396 cert_buf_size, cert, cert_size);
397 rc = dice_result_to_err(result);
398 if (rc != NO_ERROR) {
399 TLOGE("Failed to generate certificate: %d\n", rc);
400 return rc;
401 }
402
403 return NO_ERROR;
404 }
405
swbcc_get_bcc(swbcc_session_t s,uint32_t test_mode,uint8_t * bcc,size_t bcc_buf_size,size_t * bcc_size)406 int swbcc_get_bcc(swbcc_session_t s,
407 uint32_t test_mode,
408 uint8_t* bcc,
409 size_t bcc_buf_size,
410 size_t* bcc_size) {
411 int rc;
412 DiceResult result;
413 struct CborOut out;
414 const uint8_t* seed;
415 const uint8_t* pub_key;
416 size_t bcc_used;
417 struct swbcc_session* session = s;
418
419 assert(s);
420 assert(bcc);
421 assert(bcc_size);
422 assert(bcc_buf_size >= BCC_TOTAL_SIZE);
423
424 if (test_mode) {
425 seed = session->test_key_seed;
426 pub_key = session->test_pub_key;
427 } else {
428 seed = session->key_seed;
429 pub_key = session->pub_key;
430 }
431
432 /* Encode BCC */
433 CborOutInit(bcc, bcc_buf_size, &out);
434 CborWriteArray(2, &out);
435 assert(!CborOutOverflowed(&out));
436
437 bcc_used = CborOutSize(&out);
438 bcc += bcc_used;
439 bcc_buf_size -= bcc_used;
440 *bcc_size = bcc_used;
441
442 /* Encode first entry in the array which is a COSE_Key */
443 result = DiceCoseEncodePublicKey(srv_state.dice_ctx, pub_key, bcc_buf_size,
444 bcc, &bcc_used);
445 rc = dice_result_to_err(result);
446 if (rc != NO_ERROR) {
447 TLOGE("Failed to encode public key: %d\n", rc);
448 return rc;
449 }
450
451 bcc += bcc_used;
452 bcc_buf_size -= bcc_used;
453 *bcc_size += bcc_used;
454
455 /* Encode second entry in the array which is a COSE_Sign1 */
456 rc = encode_degenerate_cert(srv_state.dice_ctx, seed, bcc, bcc_buf_size,
457 &bcc_used);
458 if (rc != NO_ERROR) {
459 TLOGE("Failed to generate certificate: %d\n", rc);
460 return rc;
461 }
462
463 *bcc_size += bcc_used;
464 return NO_ERROR;
465 }
466
467 /*
468 * Size of a DICE artifacts handed over from root (without Bcc) is:
469 * CBOR tags + Two CDIs = 71
470 */
471 #define DICE_ARTIFACTS_WO_BCC_TOTAL_SIZE 71
472
swbcc_get_dice_artifacts(swbcc_session_t s,uint64_t context,uint8_t * dice_artifacts,size_t dice_artifacts_buf_size,size_t * dice_artifacts_size)473 int swbcc_get_dice_artifacts(swbcc_session_t s,
474 uint64_t context,
475 uint8_t* dice_artifacts,
476 size_t dice_artifacts_buf_size,
477 size_t* dice_artifacts_size) {
478 assert(s);
479 int rc;
480 DiceResult result;
481 assert(dice_artifacts);
482 assert(dice_artifacts_size);
483 assert(dice_artifacts_buf_size >= DICE_ARTIFACTS_WO_BCC_TOTAL_SIZE);
484
485 struct DICEArtifacts dice_artifacts_for_target = {};
486
487 /**
488 * TODO: Currently, we assume that the only caller of this method is ABL
489 * (i.e. non-secure world). Therefore, we return DICE artifacts (i.e.
490 * BccHandover) without a Bcc, for privacy reasons. However, when this
491 * method serves TAs, certain refactoring will be required, such as:
492 * differentiating the caller from the caller's UUID,
493 * having multiple child nodes in DICE root corresponding to the TAs, which
494 * contain their DICE information, and including the Bcc in the DICE
495 * chain returned to the TAs.
496 */
497
498 /* Initialize the DICE input values. */
499 DiceInputValues input_values = {};
500 memcpy(input_values.code_hash,
501 srv_state.dice_root.child_node_info.code_hash,
502 sizeof(srv_state.dice_root.child_node_info.code_hash));
503
504 input_values.config_type = kDiceConfigTypeDescriptor;
505
506 uint8_t config_descriptor_encoded[CONFIG_DESCRIPTOR_TOTAL_SIZE];
507 size_t config_descriptor_encoded_size = 0;
508
509 result = DiceAndroidFormatConfigDescriptor(
510 &(srv_state.dice_root.child_node_info.config_descriptor),
511 sizeof(config_descriptor_encoded), config_descriptor_encoded,
512 &config_descriptor_encoded_size);
513
514 rc = dice_result_to_err(result);
515
516 if (rc != NO_ERROR) {
517 TLOGE("Failed to format config descriptor : %d\n", rc);
518 return rc;
519 }
520
521 input_values.config_descriptor = config_descriptor_encoded;
522 input_values.config_descriptor_size = config_descriptor_encoded_size;
523
524 memcpy(input_values.authority_hash,
525 srv_state.dice_root.child_node_info.authority_hash,
526 sizeof(srv_state.dice_root.child_node_info.authority_hash));
527
528 /* Set the mode */
529 if (system_state_app_loading_unlocked()) {
530 input_values.mode = kDiceModeDebug;
531 } else {
532 input_values.mode = kDiceModeNormal;
533 }
534
535 /*
536 * DICE artifacts to be handed over from root to the child nodes takes the
537 * following format.
538 * BccHandover = {
539 * 1 : bstr .size 32, // CDI_Attest
540 * 2 : bstr .size 32, // CDI_Seal
541 * ? 3 : Bcc, // Cert_Chain
542 * }
543 * where Bcc = [
544 * PubKeyEd25519 / PubKeyECDSA256, // Root pub key
545 * BccEntry, // Root -> leaf
546 * ]
547 * In the BccHandover returned to non-secure world, we do not include
548 * anything pre-FRS. Therefore, only the two CDIs are included in the
549 * BccHandover.
550 */
551
552 // Factory reset secret is mixed in only for the non-secure world.
553 memcpy(input_values.hidden, srv_state.dice_root.FRS,
554 sizeof(srv_state.dice_root.FRS));
555
556 result = DiceMainFlow(NULL, srv_state.dice_root.UDS,
557 srv_state.dice_root.UDS, &input_values, 0, NULL, NULL,
558 dice_artifacts_for_target.next_cdi_attest,
559 dice_artifacts_for_target.next_cdi_seal);
560 rc = dice_result_to_err(result);
561
562 if (rc != NO_ERROR) {
563 TLOGE("Failed to derive DICE CDIs : %d\n", rc);
564 return rc;
565 }
566
567 struct CborOut out;
568 CborOutInit(dice_artifacts, dice_artifacts_buf_size, &out);
569 CborWriteMap(2, &out);
570 CborWriteInt(1, &out);
571 CborWriteBstr(DICE_CDI_SIZE, dice_artifacts_for_target.next_cdi_attest,
572 &out);
573 CborWriteInt(2, &out);
574 CborWriteBstr(DICE_CDI_SIZE, dice_artifacts_for_target.next_cdi_seal, &out);
575 assert(!CborOutOverflowed(&out));
576
577 *dice_artifacts_size = CborOutSize(&out);
578
579 return NO_ERROR;
580 }
581