static TEE_Result ree_fs_ta_get_tag(const struct user_ta_store_handle *h, uint8_t *tag, unsigned int *tag_len) { struct ree_fs_ta_handle *handle = (struct ree_fs_ta_handle *)h; if (!tag || *tag_len < handle->shdr->hash_size) { *tag_len = handle->shdr->hash_size; return TEE_ERROR_SHORT_BUFFER; } *tag_len = handle->shdr->hash_size; memcpy(tag, SHDR_GET_HASH(handle->shdr), handle->shdr->hash_size); return TEE_SUCCESS; }
static TEE_Result check_shdr(struct shdr *shdr) { struct rsa_public_key key; TEE_Result res; uint32_t e = TEE_U32_TO_BIG_ENDIAN(ta_pub_key_exponent); size_t hash_size; if (shdr->magic != SHDR_MAGIC || shdr->img_type != SHDR_TA) return TEE_ERROR_SECURITY; if (TEE_ALG_GET_MAIN_ALG(shdr->algo) != TEE_MAIN_ALGO_RSA) return TEE_ERROR_SECURITY; res = tee_hash_get_digest_size(TEE_DIGEST_HASH_TO_ALGO(shdr->algo), &hash_size); if (res != TEE_SUCCESS) return res; if (hash_size != shdr->hash_size) return TEE_ERROR_SECURITY; if (!crypto_ops.acipher.alloc_rsa_public_key || !crypto_ops.acipher.free_rsa_public_key || !crypto_ops.acipher.rsassa_verify || !crypto_ops.bignum.bin2bn) return TEE_ERROR_NOT_SUPPORTED; res = crypto_ops.acipher.alloc_rsa_public_key(&key, shdr->sig_size); if (res != TEE_SUCCESS) return res; res = crypto_ops.bignum.bin2bn((uint8_t *)&e, sizeof(e), key.e); if (res != TEE_SUCCESS) goto out; res = crypto_ops.bignum.bin2bn(ta_pub_key_modulus, ta_pub_key_modulus_size, key.n); if (res != TEE_SUCCESS) goto out; res = crypto_ops.acipher.rsassa_verify(shdr->algo, &key, -1, SHDR_GET_HASH(shdr), shdr->hash_size, SHDR_GET_SIG(shdr), shdr->sig_size); out: crypto_ops.acipher.free_rsa_public_key(&key); if (res != TEE_SUCCESS) return TEE_ERROR_SECURITY; return TEE_SUCCESS; }
static TEE_Result check_digest(struct ree_fs_ta_handle *h) { void *digest = NULL; TEE_Result res; digest = malloc(h->shdr->hash_size); if (!digest) return TEE_ERROR_OUT_OF_MEMORY; res = crypto_hash_final(h->hash_ctx, h->hash_algo, digest, h->shdr->hash_size); if (res != TEE_SUCCESS) { res = TEE_ERROR_SECURITY; goto out; } if (memcmp(digest, SHDR_GET_HASH(h->shdr), h->shdr->hash_size)) res = TEE_ERROR_SECURITY; out: free(digest); return res; }
static TEE_Result install_ta(struct shdr *shdr, const uint8_t *nw, size_t nw_size) { TEE_Result res; struct tee_tadb_ta_write *ta; uint32_t hash_algo = 0; void *hash_ctx = NULL; size_t offs; const size_t buf_size = 2 * 4096; void *buf; struct tee_tadb_property property; struct shdr_bootstrap_ta bs_ta; if (shdr->img_type != SHDR_BOOTSTRAP_TA) return TEE_ERROR_SECURITY; if (nw_size < (sizeof(struct shdr_bootstrap_ta) + SHDR_GET_SIZE(shdr))) return TEE_ERROR_SECURITY; if (shdr->hash_size > buf_size) return TEE_ERROR_SECURITY; buf = malloc(buf_size); if (!buf) return TEE_ERROR_OUT_OF_MEMORY; /* * Initialize a hash context and run the algorithm over the signed * header (less the final file hash and its signature of course) */ hash_algo = TEE_DIGEST_HASH_TO_ALGO(shdr->algo); res = crypto_hash_alloc_ctx(&hash_ctx, hash_algo); if (res) goto err; res = crypto_hash_init(hash_ctx, hash_algo); if (res) goto err_free_hash_ctx; res = crypto_hash_update(hash_ctx, hash_algo, (uint8_t *)shdr, sizeof(*shdr)); if (res) goto err_free_hash_ctx; offs = SHDR_GET_SIZE(shdr); memcpy(&bs_ta, nw + offs, sizeof(bs_ta)); /* Check that we're not downgrading a TA */ res = check_install_conflict(&bs_ta); if (res) goto err_free_hash_ctx; res = crypto_hash_update(hash_ctx, hash_algo, (uint8_t *)&bs_ta, sizeof(bs_ta)); if (res) goto err_free_hash_ctx; offs += sizeof(bs_ta); memset(&property, 0, sizeof(property)); COMPILE_TIME_ASSERT(sizeof(property.uuid) == sizeof(bs_ta.uuid)); tee_uuid_from_octets(&property.uuid, bs_ta.uuid); property.version = bs_ta.version; property.custom_size = 0; property.bin_size = nw_size - offs; DMSG("Installing %pUl", (void *)&property.uuid); res = tee_tadb_ta_create(&property, &ta); if (res) goto err_free_hash_ctx; while (offs < nw_size) { size_t l = MIN(buf_size, nw_size - offs); memcpy(buf, nw + offs, l); res = crypto_hash_update(hash_ctx, hash_algo, buf, l); if (res) goto err_ta_finalize; res = tee_tadb_ta_write(ta, buf, l); if (res) goto err_ta_finalize; offs += l; } res = crypto_hash_final(hash_ctx, hash_algo, buf, shdr->hash_size); if (res) goto err_ta_finalize; if (consttime_memcmp(buf, SHDR_GET_HASH(shdr), shdr->hash_size)) { res = TEE_ERROR_SECURITY; goto err_ta_finalize; } crypto_hash_free_ctx(hash_ctx, hash_algo); free(buf); return tee_tadb_ta_close_and_commit(ta); err_ta_finalize: tee_tadb_ta_close_and_delete(ta); err_free_hash_ctx: crypto_hash_free_ctx(hash_ctx, hash_algo); err: free(buf); return res; }