1 /*
2  * Copyright (c) 2022-2023, Arm Limited. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 #include <assert.h>
7 #include <stdint.h>
8 #include <string.h>
9 
10 #include <common/debug.h>
11 #include <drivers/auth/crypto_mod.h>
12 #include <drivers/measured_boot/rss/rss_measured_boot.h>
13 #include <lib/psa/measured_boot.h>
14 #include <psa/crypto_types.h>
15 #include <psa/crypto_values.h>
16 #include <psa/error.h>
17 
18 #define MBOOT_ALG_SHA512 0
19 #define MBOOT_ALG_SHA384 1
20 #define MBOOT_ALG_SHA256 2
21 
22 #if MBOOT_ALG_ID == MBOOT_ALG_SHA512
23 #define	CRYPTO_MD_ID		CRYPTO_MD_SHA512
24 #define PSA_CRYPTO_MD_ID	PSA_ALG_SHA_512
25 #elif MBOOT_ALG_ID == MBOOT_ALG_SHA384
26 #define	CRYPTO_MD_ID		CRYPTO_MD_SHA384
27 #define PSA_CRYPTO_MD_ID	PSA_ALG_SHA_384
28 #elif MBOOT_ALG_ID == MBOOT_ALG_SHA256
29 #define	CRYPTO_MD_ID		CRYPTO_MD_SHA256
30 #define PSA_CRYPTO_MD_ID	PSA_ALG_SHA_256
31 #else
32 #  error Invalid Measured Boot algorithm.
33 #endif /* MBOOT_ALG_ID */
34 
35 #if ENABLE_ASSERTIONS
null_arr(const uint8_t * signer_id,size_t signer_id_size)36 static bool null_arr(const uint8_t *signer_id, size_t signer_id_size)
37 {
38 	for (size_t i = 0U; i < signer_id_size; i++) {
39 		if (signer_id[i] != 0U) {
40 			return false;
41 		}
42 	}
43 
44 	return true;
45 }
46 #endif /* ENABLE_ASSERTIONS */
47 
48 /* Functions' declarations */
rss_measured_boot_init(struct rss_mboot_metadata * metadata_ptr)49 void rss_measured_boot_init(struct rss_mboot_metadata *metadata_ptr)
50 {
51 	assert(metadata_ptr != NULL);
52 
53 	/* Init the non-const members of the metadata structure */
54 	while (metadata_ptr->id != RSS_MBOOT_INVALID_ID) {
55 		assert(null_arr(metadata_ptr->signer_id, MBOOT_DIGEST_SIZE));
56 		metadata_ptr->sw_type_size =
57 			strlen((const char *)&metadata_ptr->sw_type) + 1;
58 		metadata_ptr++;
59 	}
60 }
61 
rss_mboot_measure_and_record(struct rss_mboot_metadata * metadata_ptr,uintptr_t data_base,uint32_t data_size,uint32_t data_id)62 int rss_mboot_measure_and_record(struct rss_mboot_metadata *metadata_ptr,
63 				 uintptr_t data_base, uint32_t data_size,
64 				 uint32_t data_id)
65 {
66 	unsigned char hash_data[CRYPTO_MD_MAX_SIZE];
67 	int rc;
68 	psa_status_t ret;
69 
70 	assert(metadata_ptr != NULL);
71 
72 	/* Get the metadata associated with this image. */
73 	while ((metadata_ptr->id != RSS_MBOOT_INVALID_ID) &&
74 		(metadata_ptr->id != data_id)) {
75 		metadata_ptr++;
76 	}
77 
78 	/* If image is not present in metadata array then skip */
79 	if (metadata_ptr->id == RSS_MBOOT_INVALID_ID) {
80 		return 0;
81 	}
82 
83 	/* Calculate hash */
84 	rc = crypto_mod_calc_hash(CRYPTO_MD_ID,
85 				  (void *)data_base, data_size, hash_data);
86 	if (rc != 0) {
87 		return rc;
88 	}
89 
90 	ret = rss_measured_boot_extend_measurement(
91 						metadata_ptr->slot,
92 						metadata_ptr->signer_id,
93 						metadata_ptr->signer_id_size,
94 						metadata_ptr->version,
95 						metadata_ptr->version_size,
96 						PSA_CRYPTO_MD_ID,
97 						metadata_ptr->sw_type,
98 						metadata_ptr->sw_type_size,
99 						hash_data,
100 						MBOOT_DIGEST_SIZE,
101 						metadata_ptr->lock_measurement);
102 	if (ret != PSA_SUCCESS) {
103 		return ret;
104 	}
105 
106 	return 0;
107 }
108 
rss_mboot_set_signer_id(struct rss_mboot_metadata * metadata_ptr,const void * pk_oid,const void * pk_ptr,size_t pk_len)109 int rss_mboot_set_signer_id(struct rss_mboot_metadata *metadata_ptr,
110 			    const void *pk_oid,
111 			    const void *pk_ptr,
112 			    size_t pk_len)
113 {
114 	unsigned char hash_data[CRYPTO_MD_MAX_SIZE];
115 	int rc;
116 	bool hash_calc_done = false;
117 
118 	assert(metadata_ptr != NULL);
119 
120 	/*
121 	 * Do an exhaustive search over the platform metadata to find
122 	 * all images whose key OID matches the one passed in argument.
123 	 *
124 	 * Note that it is not an error if do not get any matches.
125 	 * The platform may decide not to measure all of the images
126 	 * in the system.
127 	 */
128 	while (metadata_ptr->id != RSS_MBOOT_INVALID_ID) {
129 		/* Get the metadata associated with this key-oid */
130 		if (metadata_ptr->pk_oid == pk_oid) {
131 			if (!hash_calc_done) {
132 				/* Calculate public key hash */
133 				rc = crypto_mod_calc_hash(CRYPTO_MD_ID,
134 							  (void *)pk_ptr,
135 							  pk_len, hash_data);
136 				if (rc != 0) {
137 					return rc;
138 				}
139 
140 				hash_calc_done = true;
141 			}
142 
143 			/*
144 			 * Fill the signer-ID field with the newly/already
145 			 * computed hash of the public key and update its
146 			 * signer ID size field with compile-time decided
147 			 * digest size.
148 			 */
149 			(void)memcpy(metadata_ptr->signer_id,
150 				     hash_data,
151 				     MBOOT_DIGEST_SIZE);
152 			metadata_ptr->signer_id_size = MBOOT_DIGEST_SIZE;
153 		}
154 
155 		metadata_ptr++;
156 	}
157 
158 	return 0;
159 }
160