1 /*
2  * Copyright (c) 2024, Arm Limited. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #include <assert.h>
8 #include <stdint.h>
9 #include <string.h>
10 
11 #include <psa/crypto_types.h>
12 #include <psa/crypto_values.h>
13 
14 #include <common/debug.h>
15 #include <drivers/auth/crypto_mod.h>
16 #include <drivers/measured_boot/rse/dice_prot_env.h>
17 #include <lib/cassert.h>
18 #include <lib/psa/dice_protection_environment.h>
19 
20 #include <platform_def.h>
21 
22 #define DPE_ALG_SHA512 0
23 #define DPE_ALG_SHA384 1
24 #define DPE_ALG_SHA256 2
25 
26 #if DPE_ALG_ID == DPE_ALG_SHA512
27 #define	CRYPTO_MD_ID		CRYPTO_MD_SHA512
28 #define PSA_CRYPTO_MD_ID	PSA_ALG_SHA_512
29 #elif DPE_ALG_ID == DPE_ALG_SHA384
30 #define	CRYPTO_MD_ID		CRYPTO_MD_SHA384
31 #define PSA_CRYPTO_MD_ID	PSA_ALG_SHA_384
32 #elif DPE_ALG_ID == DPE_ALG_SHA256
33 #define	CRYPTO_MD_ID		CRYPTO_MD_SHA256
34 #define PSA_CRYPTO_MD_ID	PSA_ALG_SHA_256
35 #else
36 #  error Invalid DPE hash algorithm.
37 #endif /* DPE_ALG_ID */
38 
39 /* Ensure that computed hash values fits into the DiceInputValues structure */
40 CASSERT(DICE_HASH_SIZE >= DPE_DIGEST_SIZE,
41 	assert_digest_size_bigger_than_allocated_buffer);
42 
43 static int initial_context_handle;
44 
map_metadata_to_dice_inputs(struct dpe_metadata * metadata,DiceInputValues * dice_inputs)45 static void map_metadata_to_dice_inputs(struct dpe_metadata *metadata,
46 					DiceInputValues  *dice_inputs)
47 {
48 	/* Hash of the content certificate signing key (public part) */
49 	memcpy(dice_inputs->authority_hash, metadata->signer_id,
50 	       DPE_DIGEST_SIZE);
51 
52 	/* SW type string identifier */
53 	assert(metadata->sw_type_size < DICE_CODE_DESCRIPTOR_MAX_SIZE);
54 	dice_inputs->code_descriptor = metadata->sw_type;
55 	dice_inputs->code_descriptor_size = metadata->sw_type_size;
56 }
57 
dpe_init(struct dpe_metadata * metadata)58 void dpe_init(struct dpe_metadata *metadata)
59 {
60 	assert(metadata != NULL);
61 
62 	/* Init the non-const members of the metadata structure */
63 	while (metadata->id != DPE_INVALID_ID) {
64 		/* Terminating 0 character is not needed due to CBOR encoding */
65 		metadata->sw_type_size =
66 			strlen((const char *)&metadata->sw_type);
67 		metadata++;
68 	}
69 
70 	plat_dpe_get_context_handle(&initial_context_handle);
71 }
72 
dpe_measure_and_record(struct dpe_metadata * metadata,uintptr_t data_base,uint32_t data_size,uint32_t data_id)73 int dpe_measure_and_record(struct dpe_metadata *metadata,
74 			   uintptr_t data_base, uint32_t data_size,
75 			   uint32_t data_id)
76 {
77 	static int current_context_handle;
78 	DiceInputValues dice_inputs = { 0 };
79 	int new_parent_context_handle;
80 	int new_context_handle;
81 	dpe_error_t ret;
82 	int rc;
83 
84 	assert(metadata != NULL);
85 
86 	/* Get the metadata associated with this image. */
87 	while ((metadata->id != DPE_INVALID_ID) && (metadata->id != data_id)) {
88 		metadata++;
89 	}
90 
91 	/* If image is not present in metadata array then skip */
92 	if (metadata->id == DPE_INVALID_ID) {
93 		return 0;
94 	}
95 
96 	/* Calculate hash */
97 	rc = crypto_mod_calc_hash(CRYPTO_MD_ID,
98 				  (void *)data_base, data_size,
99 				   dice_inputs.code_hash);
100 	if (rc != 0) {
101 		return rc;
102 	}
103 
104 	map_metadata_to_dice_inputs(metadata, &dice_inputs);
105 
106 	/* Only at the first call */
107 	if (current_context_handle == 0) {
108 		current_context_handle = initial_context_handle;
109 	}
110 
111 	VERBOSE("Calling dpe_derive_context, image_id: %d\n", metadata->id);
112 	ret = dpe_derive_context(current_context_handle,
113 				 metadata->cert_id,
114 				 metadata->retain_parent_context,
115 				 metadata->allow_new_context_to_derive,
116 				 metadata->create_certificate,
117 				 &dice_inputs,
118 				 0, /* target_locality */
119 				 false, /* return_certificate */
120 				 true, /* allow_new_context_to_export */
121 				 false, /* export_cdi */
122 				 &new_context_handle,
123 				 &new_parent_context_handle,
124 				 NULL, 0, NULL,  /* new_certificate_* */
125 				 NULL, 0, NULL); /* exported_cdi_* */
126 	if (ret == DPE_NO_ERROR) {
127 		current_context_handle = new_parent_context_handle;
128 		if (metadata->allow_new_context_to_derive == true) {
129 			/* Share new_context_handle with child component:
130 			 * e.g: BL2, BL33.
131 			 */
132 			VERBOSE("Share new_context_handle with child: 0x%x\n",
133 				new_context_handle);
134 			plat_dpe_share_context_handle(&new_context_handle);
135 		}
136 	} else {
137 		ERROR("dpe_derive_context failed: %d\n", ret);
138 	}
139 
140 	return (ret == DPE_NO_ERROR) ? 0 : -1;
141 }
142 
dpe_set_signer_id(struct dpe_metadata * metadata,const void * pk_oid,const void * pk_ptr,size_t pk_len)143 int dpe_set_signer_id(struct dpe_metadata *metadata,
144 		      const void *pk_oid,
145 		      const void *pk_ptr,
146 		      size_t pk_len)
147 {
148 	unsigned char hash_data[CRYPTO_MD_MAX_SIZE];
149 	int rc;
150 	bool hash_calc_done = false;
151 
152 	assert(metadata != NULL);
153 
154 	/*
155 	 * Do an exhaustive search over the platform metadata to find
156 	 * all images whose key OID matches the one passed in argument.
157 	 *
158 	 * Note that it is not an error if do not get any matches.
159 	 * The platform may decide not to measure all of the images
160 	 * in the system.
161 	 */
162 	while (metadata->id != DPE_INVALID_ID) {
163 		/* Get the metadata associated with this key-oid */
164 		if (metadata->pk_oid == pk_oid) {
165 			if (hash_calc_done == false) {
166 				/* Calculate public key hash */
167 				rc = crypto_mod_calc_hash(CRYPTO_MD_ID,
168 							  (void *)pk_ptr,
169 							  pk_len, hash_data);
170 				if (rc != 0) {
171 					return rc;
172 				}
173 
174 				hash_calc_done = true;
175 			}
176 
177 			/*
178 			 * Fill the signer-ID field with the newly/already
179 			 * computed hash of the public key and update its
180 			 * signer ID size field with compile-time decided
181 			 * digest size.
182 			 */
183 			(void)memcpy(metadata->signer_id,
184 				     hash_data,
185 				     DPE_DIGEST_SIZE);
186 			metadata->signer_id_size = DPE_DIGEST_SIZE;
187 		}
188 
189 		metadata++;
190 	}
191 
192 	return 0;
193 }
194