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 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 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 uint32_t hash_algo = 0; 46 void *hash_ctx = NULL; 47 size_t offs; 48 const size_t buf_size = 2 * 4096; 49 void *buf; 50 struct tee_tadb_property property; 51 struct shdr_bootstrap_ta bs_ta; 52 53 if (shdr->img_type != SHDR_BOOTSTRAP_TA) 54 return TEE_ERROR_SECURITY; 55 56 if (nw_size < (sizeof(struct shdr_bootstrap_ta) + SHDR_GET_SIZE(shdr))) 57 return TEE_ERROR_SECURITY; 58 59 if (shdr->hash_size > buf_size) 60 return TEE_ERROR_SECURITY; 61 62 buf = malloc(buf_size); 63 if (!buf) 64 return TEE_ERROR_OUT_OF_MEMORY; 65 66 /* 67 * Initialize a hash context and run the algorithm over the signed 68 * header (less the final file hash and its signature of course) 69 */ 70 hash_algo = TEE_DIGEST_HASH_TO_ALGO(shdr->algo); 71 res = crypto_hash_alloc_ctx(&hash_ctx, hash_algo); 72 if (res) 73 goto err; 74 res = crypto_hash_init(hash_ctx, hash_algo); 75 if (res) 76 goto err_free_hash_ctx; 77 res = crypto_hash_update(hash_ctx, hash_algo, (uint8_t *)shdr, 78 sizeof(*shdr)); 79 if (res) 80 goto err_free_hash_ctx; 81 82 offs = SHDR_GET_SIZE(shdr); 83 memcpy(&bs_ta, nw + offs, sizeof(bs_ta)); 84 85 /* Check that we're not downgrading a TA */ 86 res = check_install_conflict(&bs_ta); 87 if (res) 88 goto err_free_hash_ctx; 89 90 res = crypto_hash_update(hash_ctx, hash_algo, (uint8_t *)&bs_ta, 91 sizeof(bs_ta)); 92 if (res) 93 goto err_free_hash_ctx; 94 offs += sizeof(bs_ta); 95 96 memset(&property, 0, sizeof(property)); 97 COMPILE_TIME_ASSERT(sizeof(property.uuid) == sizeof(bs_ta.uuid)); 98 tee_uuid_from_octets(&property.uuid, bs_ta.uuid); 99 property.version = bs_ta.ta_version; 100 property.custom_size = 0; 101 property.bin_size = nw_size - offs; 102 DMSG("Installing %pUl", (void *)&property.uuid); 103 104 res = tee_tadb_ta_create(&property, &ta); 105 if (res) 106 goto err_free_hash_ctx; 107 108 while (offs < nw_size) { 109 size_t l = MIN(buf_size, nw_size - offs); 110 111 memcpy(buf, nw + offs, l); 112 res = crypto_hash_update(hash_ctx, hash_algo, buf, l); 113 if (res) 114 goto err_ta_finalize; 115 res = tee_tadb_ta_write(ta, buf, l); 116 if (res) 117 goto err_ta_finalize; 118 offs += l; 119 } 120 121 res = crypto_hash_final(hash_ctx, hash_algo, buf, shdr->hash_size); 122 if (res) 123 goto err_ta_finalize; 124 if (consttime_memcmp(buf, SHDR_GET_HASH(shdr), shdr->hash_size)) { 125 res = TEE_ERROR_SECURITY; 126 goto err_ta_finalize; 127 } 128 129 crypto_hash_free_ctx(hash_ctx, hash_algo); 130 free(buf); 131 return tee_tadb_ta_close_and_commit(ta); 132 133 err_ta_finalize: 134 tee_tadb_ta_close_and_delete(ta); 135 err_free_hash_ctx: 136 crypto_hash_free_ctx(hash_ctx, hash_algo); 137 err: 138 free(buf); 139 return res; 140 } 141 142 static TEE_Result bootstrap(uint32_t param_types, 143 TEE_Param params[TEE_NUM_PARAMS]) 144 { 145 TEE_Result res; 146 struct shdr *shdr; 147 const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT, 148 TEE_PARAM_TYPE_NONE, 149 TEE_PARAM_TYPE_NONE, 150 TEE_PARAM_TYPE_NONE); 151 152 if (param_types != exp_pt) 153 return TEE_ERROR_BAD_PARAMETERS; 154 155 shdr = shdr_alloc_and_copy(params->memref.buffer, params->memref.size); 156 if (!shdr) 157 return TEE_ERROR_SECURITY; 158 159 res = shdr_verify_signature(shdr); 160 if (res) 161 goto out; 162 163 res = install_ta(shdr, params->memref.buffer, params->memref.size); 164 out: 165 shdr_free(shdr); 166 return res; 167 } 168 169 static TEE_Result invoke_command(void *sess_ctx __unused, uint32_t cmd_id, 170 uint32_t param_types, 171 TEE_Param params[TEE_NUM_PARAMS]) 172 { 173 switch (cmd_id) { 174 case PTA_SECSTOR_TA_MGMT_BOOTSTRAP: 175 return bootstrap(param_types, params); 176 default: 177 break; 178 } 179 return TEE_ERROR_NOT_IMPLEMENTED; 180 } 181 182 pseudo_ta_register(.uuid = PTA_SECSTOR_TA_MGMT_UUID, .name = "secstor_ta_mgmt", 183 /* 184 * TA_FLAG_SINGLE_INSTANCE and TA_FLAG_MULTI_SESSION are 185 * current part of PTA_DEFAULT_FLAGS, but as this TA 186 * depends on those two flags we add them explicitly 187 * too. 188 */ 189 .flags = PTA_DEFAULT_FLAGS | TA_FLAG_SINGLE_INSTANCE | 190 TA_FLAG_MULTI_SESSION, 191 .invoke_command_entry_point = invoke_command); 192