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 void *hash_ctx = NULL; 46 size_t offs; 47 const size_t buf_size = 1024; 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 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(0, params->memref.buffer, 153 params->memref.size); 154 if (!shdr) 155 return TEE_ERROR_SECURITY; 156 157 res = shdr_verify_signature(shdr); 158 if (res) 159 goto out; 160 161 res = install_ta(shdr, params->memref.buffer, params->memref.size); 162 out: 163 shdr_free(shdr); 164 return res; 165 } 166 167 static TEE_Result invoke_command(void *sess_ctx __unused, uint32_t cmd_id, 168 uint32_t param_types, 169 TEE_Param params[TEE_NUM_PARAMS]) 170 { 171 switch (cmd_id) { 172 case PTA_SECSTOR_TA_MGMT_BOOTSTRAP: 173 return bootstrap(param_types, params); 174 default: 175 break; 176 } 177 return TEE_ERROR_NOT_IMPLEMENTED; 178 } 179 180 pseudo_ta_register(.uuid = PTA_SECSTOR_TA_MGMT_UUID, .name = "secstor_ta_mgmt", 181 /* 182 * TA_FLAG_SINGLE_INSTANCE and TA_FLAG_MULTI_SESSION are 183 * current part of PTA_DEFAULT_FLAGS, but as this TA 184 * depends on those two flags we add them explicitly 185 * too. 186 */ 187 .flags = PTA_DEFAULT_FLAGS | TA_FLAG_SINGLE_INSTANCE | 188 TA_FLAG_MULTI_SESSION, 189 .invoke_command_entry_point = invoke_command); 190