1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3 * Copyright (c) 2015-2022, Linaro Limited
4 */
5
6 #include <crypto/crypto.h>
7 #include <fault_mitigation.h>
8 #include <kernel/panic.h>
9 #include <mempool.h>
10 #include <signed_hdr.h>
11 #include <stdlib.h>
12 #include <string.h>
13 #include <ta_pub_key.h>
14 #include <tee_api_types.h>
15 #include <tee/tee_cryp_utl.h>
16 #include <tee/uuid.h>
17 #include <utee_defines.h>
18 #include <util.h>
19
shdr_alloc_and_copy(size_t offs,const void * img,size_t img_size)20 struct shdr *shdr_alloc_and_copy(size_t offs, const void *img, size_t img_size)
21 {
22 size_t shdr_size;
23 struct shdr *shdr;
24 vaddr_t img_va = (vaddr_t)img;
25 vaddr_t tmp = 0;
26 size_t end = 0;
27
28 if (ADD_OVERFLOW(offs, sizeof(struct shdr), &end) || end > img_size)
29 return NULL;
30
31 shdr_size = SHDR_GET_SIZE((const struct shdr *)(img_va + offs));
32 if (ADD_OVERFLOW(offs, shdr_size, &end) || end > img_size)
33 return NULL;
34
35 if (ADD_OVERFLOW(img_va, shdr_size, &tmp))
36 return NULL;
37
38 shdr = malloc(shdr_size);
39 if (!shdr)
40 return NULL;
41 memcpy(shdr, (const uint8_t *)img + offs, shdr_size);
42
43 /* Check that the data wasn't modified before the copy was completed */
44 if (shdr_size != SHDR_GET_SIZE(shdr)) {
45 free(shdr);
46 return NULL;
47 }
48
49 return shdr;
50 }
51
is_weak_hash_algo(uint32_t algo)52 static bool is_weak_hash_algo(uint32_t algo)
53 {
54 return algo == TEE_ALG_MD5 || algo == TEE_ALG_SHA1 ||
55 algo == TEE_ALG_MD5SHA1;
56 }
57
shdr_verify_signature(const struct shdr * shdr)58 TEE_Result shdr_verify_signature(const struct shdr *shdr)
59 {
60 struct rsa_public_key key = { };
61 TEE_Result res = TEE_SUCCESS;
62 uint32_t e = TEE_U32_TO_BIG_ENDIAN(ta_pub_key_exponent);
63 struct ftmn ftmn = { };
64 unsigned int err_incr = 2;
65 size_t hash_size = 0;
66 size_t hash_algo = 0;
67
68 if (shdr->magic != SHDR_MAGIC)
69 goto err;
70
71 if (TEE_ALG_GET_MAIN_ALG(shdr->algo) != TEE_MAIN_ALGO_RSA)
72 goto err;
73
74 hash_algo = TEE_DIGEST_HASH_TO_ALGO(shdr->algo);
75 if (is_weak_hash_algo(hash_algo))
76 goto err;
77
78 res = tee_alg_get_digest_size(hash_algo, &hash_size);
79 if (res)
80 goto err;
81 if (hash_size != shdr->hash_size)
82 goto err;
83
84 res = crypto_acipher_alloc_rsa_public_key(&key,
85 ta_pub_key_modulus_size * 8);
86 if (res)
87 goto err;
88
89 res = crypto_bignum_bin2bn((uint8_t *)&e, sizeof(e), key.e);
90 if (res)
91 goto err;
92 res = crypto_bignum_bin2bn(ta_pub_key_modulus, ta_pub_key_modulus_size,
93 key.n);
94 if (res)
95 goto err;
96
97 FTMN_CALL_FUNC(res, &ftmn, FTMN_INCR0,
98 crypto_acipher_rsassa_verify, shdr->algo, &key,
99 shdr->hash_size, SHDR_GET_HASH(shdr), shdr->hash_size,
100 SHDR_GET_SIG(shdr), shdr->sig_size);
101 if (!res) {
102 ftmn_checkpoint(&ftmn, FTMN_INCR0);
103 goto out;
104 }
105 err_incr = 1;
106 err:
107 res = TEE_ERROR_SECURITY;
108 FTMN_SET_CHECK_RES_NOT_ZERO(&ftmn, err_incr * FTMN_INCR0, res);
109 out:
110 FTMN_CALLEE_DONE_CHECK(&ftmn, FTMN_INCR0, FTMN_STEP_COUNT(2), res);
111 crypto_acipher_free_rsa_public_key(&key);
112 return res;
113 }
114
115 static const struct shdr_subkey_attr *
find_attr(const struct shdr_subkey * subkey,uint32_t id)116 find_attr(const struct shdr_subkey *subkey, uint32_t id)
117 {
118 size_t n = 0;
119
120 for (n = 0; n < subkey->attr_count; n++)
121 if (subkey->attrs[n].id == id)
122 return subkey->attrs + n;
123
124 return NULL;
125 }
126
load_rsa_key(const struct shdr_subkey * subkey,struct rsa_public_key ** key_pp)127 static TEE_Result load_rsa_key(const struct shdr_subkey *subkey,
128 struct rsa_public_key **key_pp)
129 {
130 const uint8_t *base = (const uint8_t *)subkey;
131 const struct shdr_subkey_attr *pub_exp = NULL;
132 const struct shdr_subkey_attr *modulus = NULL;
133 struct rsa_public_key *key = NULL;
134 TEE_Result res = TEE_SUCCESS;
135
136 pub_exp = find_attr(subkey, TEE_ATTR_RSA_PUBLIC_EXPONENT);
137 if (!pub_exp)
138 return TEE_ERROR_SECURITY;
139 modulus = find_attr(subkey, TEE_ATTR_RSA_MODULUS);
140 if (!modulus)
141 return TEE_ERROR_SECURITY;
142
143 key = calloc(1, sizeof(*key));
144 if (!key)
145 return TEE_ERROR_OUT_OF_MEMORY;
146 res = crypto_acipher_alloc_rsa_public_key(key, modulus->size * 8);
147 if (res)
148 goto err_key;
149
150 res = crypto_bignum_bin2bn(base + pub_exp->offs, pub_exp->size, key->e);
151 if (res)
152 goto err;
153 res = crypto_bignum_bin2bn(base + modulus->offs, modulus->size, key->n);
154 if (res)
155 goto err;
156
157 *key_pp = key;
158 return TEE_SUCCESS;
159 err:
160 crypto_acipher_free_rsa_public_key(key);
161 err_key:
162 free(key);
163 return TEE_ERROR_SECURITY;
164 }
165
check_attrs(const struct shdr_subkey * subkey,size_t img_size)166 static TEE_Result check_attrs(const struct shdr_subkey *subkey, size_t img_size)
167 {
168 const struct shdr_subkey_attr *attrs = subkey->attrs;
169 size_t end = 0;
170 size_t n = 0;
171
172 if (MUL_OVERFLOW(subkey->attr_count, sizeof(*attrs), &end) ||
173 ADD_OVERFLOW(end, sizeof(*subkey), &end) ||
174 end > img_size)
175 return TEE_ERROR_SECURITY;
176
177 for (n = 0; n < subkey->attr_count; n++)
178 if (ADD_OVERFLOW(attrs[n].offs, attrs[n].size, &end) ||
179 end > img_size)
180 return TEE_ERROR_SECURITY;
181
182 return TEE_SUCCESS;
183 }
184
calc_next_uuid(uint8_t uuid[sizeof (TEE_UUID)],const uint8_t my_uuid[sizeof (TEE_UUID)],const void * ns_name,size_t name_size)185 static TEE_Result calc_next_uuid(uint8_t uuid[sizeof(TEE_UUID)],
186 const uint8_t my_uuid[sizeof(TEE_UUID)],
187 const void *ns_name, size_t name_size)
188 {
189 TEE_Result res = TEE_ERROR_SECURITY;
190 void *ctx = NULL;
191 struct {
192 uint8_t digest[TEE_SHA1_HASH_SIZE];
193 TEE_UUID uuid;
194 char name_str[];
195 } *tmp = NULL;
196
197 if (!name_size) {
198 memcpy(uuid, my_uuid, sizeof(TEE_UUID));
199 return TEE_SUCCESS;
200 }
201
202 /*
203 * RFC 4122 requires a SHA-1 digest for UUID v5. Use SHA-512
204 * instead for better collision resistance.
205 */
206 if (crypto_hash_alloc_ctx(&ctx, TEE_ALG_SHA512))
207 return TEE_ERROR_SECURITY;
208
209 tmp = mempool_alloc(mempool_default, sizeof(*tmp) + name_size);
210 if (!tmp)
211 goto out_ctx;
212 memcpy(tmp->name_str, ns_name, name_size);
213
214 if (crypto_hash_init(ctx) ||
215 crypto_hash_update(ctx, my_uuid, sizeof(TEE_UUID)) ||
216 crypto_hash_update(ctx, (const void *)tmp->name_str,
217 strnlen(tmp->name_str, name_size)) ||
218 crypto_hash_final(ctx, tmp->digest, sizeof(tmp->digest)))
219 goto out_mempool;
220
221 tee_uuid_from_octets(&tmp->uuid, tmp->digest);
222 /*
223 * Set the four most significant bits (bits 12 through 15) of the
224 * time_hi_and_version field to 5.
225 */
226 tmp->uuid.timeHiAndVersion &= ~SHIFT_U32(0xf, 12);
227 tmp->uuid.timeHiAndVersion |= SHIFT_U32(5, 12);
228 /*
229 * Set the two most significant bits (bits 6 and 7) of the
230 * clock_seq_hi_and_reserved to zero and one, respectively.
231 */
232 tmp->uuid.clockSeqAndNode[0] &= ~BIT(6);
233 tmp->uuid.clockSeqAndNode[0] |= BIT(7);
234
235 tee_uuid_to_octets(uuid, &tmp->uuid);
236 res = TEE_SUCCESS;
237
238 out_mempool:
239 mempool_free(mempool_default, tmp);
240 out_ctx:
241 crypto_hash_free_ctx(ctx);
242
243 return res;
244 }
245
shdr_load_pub_key(const struct shdr * shdr,size_t offs,const uint8_t * ns_img,size_t ns_img_size,const uint8_t next_uuid[sizeof (TEE_UUID)],uint32_t max_depth,struct shdr_pub_key * key)246 TEE_Result shdr_load_pub_key(const struct shdr *shdr, size_t offs,
247 const uint8_t *ns_img, size_t ns_img_size,
248 const uint8_t next_uuid[sizeof(TEE_UUID)],
249 uint32_t max_depth, struct shdr_pub_key *key)
250 {
251 struct shdr_subkey *subkey = NULL;
252 TEE_Result res = TEE_SUCCESS;
253 void *digest = NULL;
254 uint8_t *img = NULL;
255 void *ctx = NULL;
256 size_t end = 0;
257
258 if (shdr->img_type != SHDR_SUBKEY)
259 return TEE_ERROR_SECURITY;
260
261 if (shdr->img_size < sizeof(*subkey))
262 return TEE_ERROR_SECURITY;
263
264 if (ADD_OVERFLOW(shdr->img_size, offs, &end) || end > ns_img_size)
265 return TEE_ERROR_SECURITY;
266
267 img = mempool_alloc(mempool_default, shdr->img_size + shdr->hash_size);
268 if (!img)
269 return TEE_ERROR_OUT_OF_MEMORY;
270 memcpy(img + shdr->hash_size, ns_img + offs, shdr->img_size);
271 subkey = (void *)(img + shdr->hash_size);
272 digest = img;
273
274 if (crypto_hash_alloc_ctx(&ctx, TEE_DIGEST_HASH_TO_ALGO(shdr->algo))) {
275 res = TEE_ERROR_SECURITY;
276 goto out_mempool;
277 }
278
279 if (crypto_hash_init(ctx) ||
280 crypto_hash_update(ctx, (const void *)shdr, sizeof(*shdr)) ||
281 crypto_hash_update(ctx, (const void *)subkey, shdr->img_size) ||
282 crypto_hash_final(ctx, digest, shdr->hash_size) ||
283 memcmp(digest, SHDR_GET_HASH(shdr), shdr->hash_size)) {
284 res = TEE_ERROR_SECURITY;
285 goto out_ctx;
286 }
287
288 res = check_attrs(subkey, shdr->img_size);
289 if (res)
290 goto out_ctx;
291
292 if (subkey->max_depth >= max_depth) {
293 res = TEE_ERROR_SECURITY;
294 goto out_ctx;
295 }
296 if (next_uuid && memcmp(next_uuid, subkey->uuid, sizeof(TEE_UUID))) {
297 res = TEE_ERROR_SECURITY;
298 goto out_ctx;
299 }
300
301 key->max_depth = subkey->max_depth;
302 key->name_size = subkey->name_size;
303 memcpy(key->uuid, subkey->uuid, sizeof(TEE_UUID));
304 if (ADD_OVERFLOW(key->name_size, offs + shdr->img_size, &end) ||
305 end > ns_img_size) {
306 res = TEE_ERROR_SECURITY;
307 goto out_ctx;
308 }
309 res = calc_next_uuid(key->next_uuid, key->uuid,
310 ns_img + offs + shdr->img_size, key->name_size);
311 if (res)
312 goto out_ctx;
313
314 key->main_algo = TEE_ALG_GET_MAIN_ALG(subkey->algo);
315 switch (key->main_algo) {
316 case TEE_MAIN_ALGO_RSA:
317 res = load_rsa_key(subkey, &key->pub_key.rsa);
318 break;
319 default:
320 res = TEE_ERROR_SECURITY;
321 break;
322 }
323
324 out_ctx:
325 crypto_hash_free_ctx(ctx);
326 out_mempool:
327 mempool_free(mempool_default, img);
328 return res;
329 }
330
shdr_free_pub_key(struct shdr_pub_key * key)331 void shdr_free_pub_key(struct shdr_pub_key *key)
332 {
333 if (key) {
334 switch (key->main_algo) {
335 case TEE_MAIN_ALGO_RSA:
336 crypto_acipher_free_rsa_public_key(key->pub_key.rsa);
337 free(key->pub_key.rsa);
338 break;
339 default:
340 panic();
341 }
342 }
343 }
344
shdr_verify_signature2(struct shdr_pub_key * key,const struct shdr * shdr)345 TEE_Result shdr_verify_signature2(struct shdr_pub_key *key,
346 const struct shdr *shdr)
347 {
348 TEE_Result res = TEE_SUCCESS;
349 unsigned int err_incr = 2;
350 struct ftmn ftmn = { };
351 size_t hash_size = 0;
352 size_t hash_algo = 0;
353
354 if (shdr->magic != SHDR_MAGIC)
355 goto err;
356
357 if (TEE_ALG_GET_MAIN_ALG(shdr->algo) != key->main_algo)
358 goto err;
359
360 hash_algo = TEE_DIGEST_HASH_TO_ALGO(shdr->algo);
361 if (is_weak_hash_algo(hash_algo))
362 goto err;
363
364 if (tee_alg_get_digest_size(hash_algo, &hash_size) ||
365 hash_size != shdr->hash_size)
366 goto err;
367
368 switch (key->main_algo) {
369 case TEE_MAIN_ALGO_RSA:
370 FTMN_CALL_FUNC(res, &ftmn, FTMN_INCR0,
371 crypto_acipher_rsassa_verify, shdr->algo,
372 key->pub_key.rsa, shdr->hash_size,
373 SHDR_GET_HASH(shdr), shdr->hash_size,
374 SHDR_GET_SIG(shdr), shdr->sig_size);
375 break;
376 default:
377 panic();
378 }
379
380 if (!res) {
381 ftmn_checkpoint(&ftmn, FTMN_INCR0);
382 goto out;
383 }
384 err_incr = 1;
385 err:
386 res = TEE_ERROR_SECURITY;
387 FTMN_SET_CHECK_RES_NOT_ZERO(&ftmn, err_incr * FTMN_INCR0, res);
388 out:
389 FTMN_CALLEE_DONE_CHECK(&ftmn, FTMN_INCR0, FTMN_STEP_COUNT(2), res);
390 return res;
391 }
392