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