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