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_BUFFER_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_BUFFER_SIZE];
91     uint8_t priv_key[DICE_PRIVATE_KEY_BUFFER_SIZE];
92 
93     uint8_t test_key_seed[DICE_PRIVATE_KEY_SEED_SIZE];
94     uint8_t test_pub_key[DICE_PUBLIC_KEY_BUFFER_SIZE];
95     uint8_t test_priv_key[DICE_PRIVATE_KEY_BUFFER_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_BUFFER_SIZE];
195     result = DiceKeypairFromSeed(
196             NULL, kDicePrincipalAuthority, private_key_seed,
197             srv_state.dice_root.UDS_pub_key, 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, kDicePrincipalSubject,
261                                  session->key_seed, session->pub_key,
262                                  session->priv_key);
263     rc = dice_result_to_err(result);
264     if (rc != NO_ERROR) {
265         TLOGE("Failed to generate keypair: %d\n", rc);
266         return rc;
267     }
268 
269     /* Init test keys */
270     rc = trusty_rng_secure_rand(session->test_key_seed,
271                                 sizeof(session->test_key_seed));
272     if (rc != NO_ERROR) {
273         goto err;
274     }
275 
276     result = DiceKeypairFromSeed(srv_state.dice_ctx, kDicePrincipalSubject,
277                                  session->test_key_seed, session->test_pub_key,
278                                  session->test_priv_key);
279     rc = dice_result_to_err(result);
280     if (rc != NO_ERROR) {
281         TLOGE("Failed to generate test keypair: %d\n", rc);
282         return rc;
283     }
284 
285     *s = (swbcc_session_t)session;
286     return NO_ERROR;
287 
288 err:
289     free(session);
290     return rc;
291 }
292 
swbcc_get_client(swbcc_session_t s,struct uuid * client)293 void swbcc_get_client(swbcc_session_t s, struct uuid* client) {
294     struct swbcc_session* session = (struct swbcc_session*)s;
295     memcpy(client, &session->client_uuid, sizeof(struct uuid));
296 }
297 
swbcc_ns_deprivilege(swbcc_session_t s)298 int swbcc_ns_deprivilege(swbcc_session_t s) {
299     srv_state.ns_deprivileged = true;
300     return NO_ERROR;
301 }
302 
swbcc_close(swbcc_session_t s)303 void swbcc_close(swbcc_session_t s) {
304     free(s);
305 }
306 
307 /*
308  * Format and (size) of a COSE_Sign1 Msg in this case is:
309  * Array header (1) | Protected Params (4) | Unprotected Params (1) |
310  * MAC Key Hdr (2) | MAC Key (32) | Sig Hdr (2) | Sig (64)
311  */
312 #define MAC_SIGN1_SIZE (106)
313 
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)314 int swbcc_sign_key(swbcc_session_t s,
315                    uint32_t test_mode,
316                    int32_t cose_algorithm,
317                    const uint8_t* key,
318                    uint32_t key_size,
319                    const uint8_t* aad,
320                    size_t aad_size,
321                    uint8_t* cose_sign1,
322                    size_t cose_sign1_buf_size,
323                    size_t* cose_sign1_size) {
324     int rc;
325     DiceResult result;
326     const uint8_t* signing_key;
327     struct swbcc_session* session = s;
328 
329     assert(s);
330     assert(key);
331     assert(aad);
332     assert(cose_sign1);
333     assert(cose_sign1_size);
334     assert(cose_sign1_buf_size >= MAC_SIGN1_SIZE);
335 
336     if (cose_algorithm != HWBCC_ALGORITHM_ED25519) {
337         TLOGE("Signing algorithm is not supported: %d\n", cose_algorithm);
338         return ERR_NOT_SUPPORTED;
339     }
340 
341     signing_key = test_mode ? session->test_priv_key : session->priv_key;
342 
343     result = DiceCoseSignAndEncodeSign1(
344             srv_state.dice_ctx, key, key_size, aad, aad_size, signing_key,
345             cose_sign1_buf_size, cose_sign1, cose_sign1_size);
346     rc = dice_result_to_err(result);
347     if (rc != NO_ERROR) {
348         TLOGE("Failed to generate COSE_Sign1: %d\n", rc);
349         return rc;
350     }
351 
352     return NO_ERROR;
353 }
354 
355 #define CONFIG_DESCRIPTOR_TOTAL_SIZE 48
356 
357 /*
358  * Format and (size) of a COSE_Sign1 Msg in this case is:
359  * Array header (1) | Protected Params (4) | Unprotected Params (1) |
360  * CWT Hdr (2) | CWT (76) | Sig Hdr (2) | Sig (64)
361  */
362 #define BCC_SIGN1_SIZE (150)
363 
364 /*
365  * Format and (size) of BCC in this case is:
366  * Array header (1) | Encoded pub key (44) | COSE_Sign1 certificate
367  */
368 #define BCC_TOTAL_SIZE (45 + BCC_SIGN1_SIZE)
369 
encode_degenerate_cert(void * dice_ctx,const uint8_t * seed,uint8_t * cert,size_t cert_buf_size,size_t * cert_size)370 static int encode_degenerate_cert(void* dice_ctx,
371                                   const uint8_t* seed,
372                                   uint8_t* cert,
373                                   size_t cert_buf_size,
374                                   size_t* cert_size) {
375     int rc;
376     DiceResult result;
377     DiceInputValues input_values = {};
378 
379     /*
380      * No need to provide DICE inputs for this self-signed certificate other
381      * than the configuration descriptor which should conform to the
382      * specification from the RKP HAL.
383      */
384     DiceAndroidConfigValues config_values = {};
385     uint8_t config_descriptor_encoded[CONFIG_DESCRIPTOR_TOTAL_SIZE];
386     size_t config_descriptor_encoded_size = 0;
387 
388     result = DiceAndroidFormatConfigDescriptor(
389             &config_values, sizeof(config_descriptor_encoded),
390             config_descriptor_encoded, &config_descriptor_encoded_size);
391 
392     rc = dice_result_to_err(result);
393     if (rc != NO_ERROR) {
394         TLOGE("Failed to format config descriptor : %d\n", rc);
395         return rc;
396     }
397 
398     input_values.config_type = kDiceConfigTypeDescriptor;
399     input_values.config_descriptor = config_descriptor_encoded;
400     input_values.config_descriptor_size = config_descriptor_encoded_size;
401 
402     result = DiceGenerateCertificate(dice_ctx, seed, seed, &input_values,
403                                      cert_buf_size, cert, cert_size);
404     rc = dice_result_to_err(result);
405     if (rc != NO_ERROR) {
406         TLOGE("Failed to generate certificate: %d\n", rc);
407         return rc;
408     }
409 
410     return NO_ERROR;
411 }
412 
swbcc_get_bcc(swbcc_session_t s,uint32_t test_mode,uint8_t * bcc,size_t bcc_buf_size,size_t * bcc_size)413 int swbcc_get_bcc(swbcc_session_t s,
414                   uint32_t test_mode,
415                   uint8_t* bcc,
416                   size_t bcc_buf_size,
417                   size_t* bcc_size) {
418     int rc;
419     DiceResult result;
420     struct CborOut out;
421     const uint8_t* seed;
422     const uint8_t* pub_key;
423     size_t bcc_used;
424     struct swbcc_session* session = s;
425 
426     assert(s);
427     assert(bcc);
428     assert(bcc_size);
429     assert(bcc_buf_size >= BCC_TOTAL_SIZE);
430 
431     if (test_mode) {
432         seed = session->test_key_seed;
433         pub_key = session->test_pub_key;
434     } else {
435         seed = session->key_seed;
436         pub_key = session->pub_key;
437     }
438 
439     /* Encode BCC */
440     CborOutInit(bcc, bcc_buf_size, &out);
441     CborWriteArray(2, &out);
442     assert(!CborOutOverflowed(&out));
443 
444     bcc_used = CborOutSize(&out);
445     bcc += bcc_used;
446     bcc_buf_size -= bcc_used;
447     *bcc_size = bcc_used;
448 
449     /* Encode first entry in the array which is a COSE_Key */
450     result =
451             DiceCoseEncodePublicKey(srv_state.dice_ctx, kDicePrincipalAuthority,
452                                     pub_key, bcc_buf_size, bcc, &bcc_used);
453     rc = dice_result_to_err(result);
454     if (rc != NO_ERROR) {
455         TLOGE("Failed to encode public key: %d\n", rc);
456         return rc;
457     }
458 
459     bcc += bcc_used;
460     bcc_buf_size -= bcc_used;
461     *bcc_size += bcc_used;
462 
463     /* Encode second entry in the array which is a COSE_Sign1 */
464     rc = encode_degenerate_cert(srv_state.dice_ctx, seed, bcc, bcc_buf_size,
465                                 &bcc_used);
466     if (rc != NO_ERROR) {
467         TLOGE("Failed to generate certificate: %d\n", rc);
468         return rc;
469     }
470 
471     *bcc_size += bcc_used;
472     return NO_ERROR;
473 }
474 
475 /*
476  * Size of a DICE artifacts handed over from root (without Bcc) is:
477  * CBOR tags + Two CDIs = 71
478  */
479 #define DICE_ARTIFACTS_WO_BCC_TOTAL_SIZE 71
480 
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)481 int swbcc_get_dice_artifacts(swbcc_session_t s,
482                              uint64_t context,
483                              uint8_t* dice_artifacts,
484                              size_t dice_artifacts_buf_size,
485                              size_t* dice_artifacts_size) {
486     assert(s);
487     int rc;
488     DiceResult result;
489     assert(dice_artifacts);
490     assert(dice_artifacts_size);
491     assert(dice_artifacts_buf_size >= DICE_ARTIFACTS_WO_BCC_TOTAL_SIZE);
492 
493     struct DICEArtifacts dice_artifacts_for_target = {};
494 
495     /**
496      * TODO: Currently, we assume that the only caller of this method is ABL
497      * (i.e. non-secure world). Therefore, we return DICE artifacts (i.e.
498      * BccHandover) without a Bcc, for privacy reasons. However, when this
499      * method serves TAs, certain refactoring will be required, such as:
500      * differentiating the caller from the caller's UUID,
501      * having multiple child nodes in DICE root corresponding to the TAs, which
502      * contain their DICE information, and including the Bcc in the DICE
503      * chain returned to the TAs.
504      */
505 
506     /* Initialize the DICE input values. */
507     DiceInputValues input_values = {};
508     memcpy(input_values.code_hash,
509            srv_state.dice_root.child_node_info.code_hash,
510            sizeof(srv_state.dice_root.child_node_info.code_hash));
511 
512     input_values.config_type = kDiceConfigTypeDescriptor;
513 
514     uint8_t config_descriptor_encoded[CONFIG_DESCRIPTOR_TOTAL_SIZE];
515     size_t config_descriptor_encoded_size = 0;
516 
517     result = DiceAndroidFormatConfigDescriptor(
518             &(srv_state.dice_root.child_node_info.config_descriptor),
519             sizeof(config_descriptor_encoded), config_descriptor_encoded,
520             &config_descriptor_encoded_size);
521 
522     rc = dice_result_to_err(result);
523 
524     if (rc != NO_ERROR) {
525         TLOGE("Failed to format config descriptor : %d\n", rc);
526         return rc;
527     }
528 
529     input_values.config_descriptor = config_descriptor_encoded;
530     input_values.config_descriptor_size = config_descriptor_encoded_size;
531 
532     memcpy(input_values.authority_hash,
533            srv_state.dice_root.child_node_info.authority_hash,
534            sizeof(srv_state.dice_root.child_node_info.authority_hash));
535 
536     /* Set the mode */
537     if (system_state_app_loading_unlocked()) {
538         input_values.mode = kDiceModeDebug;
539     } else {
540         input_values.mode = kDiceModeNormal;
541     }
542 
543     /*
544      * DICE artifacts to be handed over from root to the child nodes takes the
545      * following format.
546      * BccHandover = {
547      *   1 : bstr .size 32,	// CDI_Attest
548      *   2 : bstr .size 32,	// CDI_Seal
549      *   ? 3 : Bcc,        	// Cert_Chain
550      * }
551      * where Bcc = [
552      *         PubKeyEd25519 / PubKeyECDSA256, // Root pub key
553      *         BccEntry,                       // Root -> leaf
554      *       ]
555      * In the BccHandover returned to non-secure world, we do not include
556      * anything pre-FRS. Therefore, only the two CDIs are included in the
557      * BccHandover.
558      */
559 
560     // Factory reset secret is mixed in only for the non-secure world.
561     memcpy(input_values.hidden, srv_state.dice_root.FRS,
562            sizeof(srv_state.dice_root.FRS));
563 
564     result = DiceMainFlow(NULL, srv_state.dice_root.UDS,
565                           srv_state.dice_root.UDS, &input_values, 0, NULL, NULL,
566                           dice_artifacts_for_target.next_cdi_attest,
567                           dice_artifacts_for_target.next_cdi_seal);
568     rc = dice_result_to_err(result);
569 
570     if (rc != NO_ERROR) {
571         TLOGE("Failed to derive DICE CDIs : %d\n", rc);
572         return rc;
573     }
574 
575     struct CborOut out;
576     CborOutInit(dice_artifacts, dice_artifacts_buf_size, &out);
577     CborWriteMap(2, &out);
578     CborWriteInt(1, &out);
579     CborWriteBstr(DICE_CDI_SIZE, dice_artifacts_for_target.next_cdi_attest,
580                   &out);
581     CborWriteInt(2, &out);
582     CborWriteBstr(DICE_CDI_SIZE, dice_artifacts_for_target.next_cdi_seal, &out);
583     assert(!CborOutOverflowed(&out));
584 
585     *dice_artifacts_size = CborOutSize(&out);
586 
587     return NO_ERROR;
588 }
589