1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3  * Copyright (c) 2017, Linaro Limited
4  */
5 
6 #include <kernel/pseudo_ta.h>
7 #include <tee/tadb.h>
8 #include <pta_secstor_ta_mgmt.h>
9 #include <signed_hdr.h>
10 #include <string_ext.h>
11 #include <string.h>
12 #include <tee_api_types.h>
13 #include <crypto/crypto.h>
14 #include <tee/uuid.h>
15 #include <types_ext.h>
16 #include <utee_defines.h>
17 
check_install_conflict(const struct shdr_bootstrap_ta * bs_ta)18 static TEE_Result check_install_conflict(const struct shdr_bootstrap_ta *bs_ta)
19 {
20 	TEE_Result res;
21 	struct tee_tadb_ta_read *ta;
22 	TEE_UUID uuid;
23 	const struct tee_tadb_property *prop;
24 
25 	tee_uuid_from_octets(&uuid, bs_ta->uuid);
26 	res = tee_tadb_ta_open(&uuid, &ta);
27 	if (res == TEE_ERROR_ITEM_NOT_FOUND)
28 		return TEE_SUCCESS;
29 	if (res)
30 		return res;
31 
32 	prop = tee_tadb_ta_get_property(ta);
33 	if (prop->version > bs_ta->ta_version)
34 		res = TEE_ERROR_ACCESS_CONFLICT;
35 
36 	tee_tadb_ta_close(ta);
37 	return res;
38 }
39 
install_ta(struct shdr * shdr,const uint8_t * nw,size_t nw_size)40 static TEE_Result install_ta(struct shdr *shdr, const uint8_t *nw,
41 			     size_t nw_size)
42 {
43 	TEE_Result res;
44 	struct tee_tadb_ta_write *ta;
45 	void *hash_ctx = NULL;
46 	size_t offs;
47 	const size_t buf_size = 2 * 4096;
48 	void *buf;
49 	struct tee_tadb_property property;
50 	struct shdr_bootstrap_ta bs_ta;
51 
52 	if (shdr->img_type != SHDR_BOOTSTRAP_TA)
53 		return TEE_ERROR_SECURITY;
54 
55 	if (nw_size < (sizeof(struct shdr_bootstrap_ta) + SHDR_GET_SIZE(shdr)))
56 		return TEE_ERROR_SECURITY;
57 
58 	if (shdr->hash_size > buf_size)
59 		return TEE_ERROR_SECURITY;
60 
61 	buf = malloc(buf_size);
62 	if (!buf)
63 		return TEE_ERROR_OUT_OF_MEMORY;
64 
65 	/*
66 	 * Initialize a hash context and run the algorithm over the signed
67 	 * header (less the final file hash and its signature of course)
68 	 */
69 	res = crypto_hash_alloc_ctx(&hash_ctx,
70 				    TEE_DIGEST_HASH_TO_ALGO(shdr->algo));
71 	if (res)
72 		goto err;
73 	res = crypto_hash_init(hash_ctx);
74 	if (res)
75 		goto err_free_hash_ctx;
76 	res = crypto_hash_update(hash_ctx, (uint8_t *)shdr, sizeof(*shdr));
77 	if (res)
78 		goto err_free_hash_ctx;
79 
80 	offs = SHDR_GET_SIZE(shdr);
81 	memcpy(&bs_ta, nw + offs, sizeof(bs_ta));
82 
83 	/* Check that we're not downgrading a TA */
84 	res = check_install_conflict(&bs_ta);
85 	if (res)
86 		goto err_free_hash_ctx;
87 
88 	res = crypto_hash_update(hash_ctx, (uint8_t *)&bs_ta, sizeof(bs_ta));
89 	if (res)
90 		goto err_free_hash_ctx;
91 	offs += sizeof(bs_ta);
92 
93 	memset(&property, 0, sizeof(property));
94 	COMPILE_TIME_ASSERT(sizeof(property.uuid) == sizeof(bs_ta.uuid));
95 	tee_uuid_from_octets(&property.uuid, bs_ta.uuid);
96 	property.version = bs_ta.ta_version;
97 	property.custom_size = 0;
98 	property.bin_size = nw_size - offs;
99 	DMSG("Installing %pUl", (void *)&property.uuid);
100 
101 	res = tee_tadb_ta_create(&property, &ta);
102 	if (res)
103 		goto err_free_hash_ctx;
104 
105 	while (offs < nw_size) {
106 		size_t l = MIN(buf_size, nw_size - offs);
107 
108 		memcpy(buf, nw + offs, l);
109 		res = crypto_hash_update(hash_ctx, buf, l);
110 		if (res)
111 			goto err_ta_finalize;
112 		res = tee_tadb_ta_write(ta, buf, l);
113 		if (res)
114 			goto err_ta_finalize;
115 		offs += l;
116 	}
117 
118 	res = crypto_hash_final(hash_ctx, buf, shdr->hash_size);
119 	if (res)
120 		goto err_ta_finalize;
121 	if (consttime_memcmp(buf, SHDR_GET_HASH(shdr), shdr->hash_size)) {
122 		res = TEE_ERROR_SECURITY;
123 		goto err_ta_finalize;
124 	}
125 
126 	crypto_hash_free_ctx(hash_ctx);
127 	free(buf);
128 	return tee_tadb_ta_close_and_commit(ta);
129 
130 err_ta_finalize:
131 	tee_tadb_ta_close_and_delete(ta);
132 err_free_hash_ctx:
133 	crypto_hash_free_ctx(hash_ctx);
134 err:
135 	free(buf);
136 	return res;
137 }
138 
bootstrap(uint32_t param_types,TEE_Param params[TEE_NUM_PARAMS])139 static TEE_Result bootstrap(uint32_t param_types,
140 			    TEE_Param params[TEE_NUM_PARAMS])
141 {
142 	TEE_Result res;
143 	struct shdr *shdr;
144 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT,
145 						TEE_PARAM_TYPE_NONE,
146 						TEE_PARAM_TYPE_NONE,
147 						TEE_PARAM_TYPE_NONE);
148 
149 	if (param_types != exp_pt)
150 		return TEE_ERROR_BAD_PARAMETERS;
151 
152 	shdr = shdr_alloc_and_copy(params->memref.buffer, params->memref.size);
153 	if (!shdr)
154 		return TEE_ERROR_SECURITY;
155 
156 	res = shdr_verify_signature(shdr);
157 	if (res)
158 		goto out;
159 
160 	res = install_ta(shdr, params->memref.buffer, params->memref.size);
161 out:
162 	shdr_free(shdr);
163 	return res;
164 }
165 
invoke_command(void * sess_ctx __unused,uint32_t cmd_id,uint32_t param_types,TEE_Param params[TEE_NUM_PARAMS])166 static TEE_Result invoke_command(void *sess_ctx __unused, uint32_t cmd_id,
167 				 uint32_t param_types,
168 				 TEE_Param params[TEE_NUM_PARAMS])
169 {
170 	switch (cmd_id) {
171 	case PTA_SECSTOR_TA_MGMT_BOOTSTRAP:
172 		return bootstrap(param_types, params);
173 	default:
174 		break;
175 	}
176 	return TEE_ERROR_NOT_IMPLEMENTED;
177 }
178 
179 pseudo_ta_register(.uuid = PTA_SECSTOR_TA_MGMT_UUID, .name = "secstor_ta_mgmt",
180 		   /*
181 		    * TA_FLAG_SINGLE_INSTANCE and TA_FLAG_MULTI_SESSION are
182 		    * current part of PTA_DEFAULT_FLAGS, but as this TA
183 		    * depends on those two flags we add them explicitly
184 		    * too.
185 		    */
186 		   .flags = PTA_DEFAULT_FLAGS | TA_FLAG_SINGLE_INSTANCE |
187 			    TA_FLAG_MULTI_SESSION,
188 		   .invoke_command_entry_point = invoke_command);
189