1fb7ef469SJerome Forissier // SPDX-License-Identifier: BSD-2-Clause 2064663e8SJens Wiklander /* 3c34d0d91SJens Wiklander * Copyright (c) 2015-2022, Linaro Limited 4064663e8SJens Wiklander */ 5064663e8SJens Wiklander 6064663e8SJens Wiklander #include <crypto/crypto.h> 78a697013SJens Wiklander #include <fault_mitigation.h> 8c34d0d91SJens Wiklander #include <kernel/panic.h> 9c34d0d91SJens Wiklander #include <mempool.h> 10064663e8SJens Wiklander #include <signed_hdr.h> 11064663e8SJens Wiklander #include <stdlib.h> 12064663e8SJens Wiklander #include <string.h> 13064663e8SJens Wiklander #include <ta_pub_key.h> 14064663e8SJens Wiklander #include <tee_api_types.h> 15064663e8SJens Wiklander #include <tee/tee_cryp_utl.h> 16c34d0d91SJens Wiklander #include <tee/uuid.h> 17064663e8SJens Wiklander #include <utee_defines.h> 18062765e4SJerome Forissier #include <util.h> 19064663e8SJens Wiklander 20ec1aa4faSJens Wiklander struct shdr *shdr_alloc_and_copy(size_t offs, const void *img, size_t img_size) 21064663e8SJens Wiklander { 22064663e8SJens Wiklander size_t shdr_size; 23064663e8SJens Wiklander struct shdr *shdr; 24062765e4SJerome Forissier vaddr_t img_va = (vaddr_t)img; 25062765e4SJerome Forissier vaddr_t tmp = 0; 26ec1aa4faSJens Wiklander size_t end = 0; 27064663e8SJens Wiklander 28ec1aa4faSJens Wiklander if (ADD_OVERFLOW(offs, sizeof(struct shdr), &end) || end > img_size) 294ca9e426SJoakim Bech return NULL; 304ca9e426SJoakim Bech 31ec1aa4faSJens Wiklander shdr_size = SHDR_GET_SIZE((const struct shdr *)(img_va + offs)); 326b5d1120SJens Wiklander if (!shdr_size || ADD_OVERFLOW(offs, shdr_size, &end) || end > img_size) 334ca9e426SJoakim Bech return NULL; 34064663e8SJens Wiklander 35062765e4SJerome Forissier if (ADD_OVERFLOW(img_va, shdr_size, &tmp)) 36062765e4SJerome Forissier return NULL; 37062765e4SJerome Forissier 38064663e8SJens Wiklander shdr = malloc(shdr_size); 39064663e8SJens Wiklander if (!shdr) 40064663e8SJens Wiklander return NULL; 41ec1aa4faSJens Wiklander memcpy(shdr, (const uint8_t *)img + offs, shdr_size); 42064663e8SJens Wiklander 43064663e8SJens Wiklander /* Check that the data wasn't modified before the copy was completed */ 44064663e8SJens Wiklander if (shdr_size != SHDR_GET_SIZE(shdr)) { 45064663e8SJens Wiklander free(shdr); 46064663e8SJens Wiklander return NULL; 47064663e8SJens Wiklander } 48064663e8SJens Wiklander 49064663e8SJens Wiklander return shdr; 50064663e8SJens Wiklander } 51064663e8SJens Wiklander 52bef7d11dSJens Wiklander static bool is_weak_hash_algo(uint32_t algo) 53bef7d11dSJens Wiklander { 54bef7d11dSJens Wiklander return algo == TEE_ALG_MD5 || algo == TEE_ALG_SHA1 || 55*c5a0587fSJoakim Bech algo == TEE_ALG_MD5SHA1 || algo == TEE_ALG_SHA224; 56bef7d11dSJens Wiklander } 57bef7d11dSJens Wiklander 58064663e8SJens Wiklander TEE_Result shdr_verify_signature(const struct shdr *shdr) 59064663e8SJens Wiklander { 60bef7d11dSJens Wiklander struct rsa_public_key key = { }; 61bef7d11dSJens Wiklander TEE_Result res = TEE_SUCCESS; 62064663e8SJens Wiklander uint32_t e = TEE_U32_TO_BIG_ENDIAN(ta_pub_key_exponent); 638a697013SJens Wiklander struct ftmn ftmn = { }; 648a697013SJens Wiklander unsigned int err_incr = 2; 65bef7d11dSJens Wiklander size_t hash_size = 0; 66bef7d11dSJens Wiklander size_t hash_algo = 0; 67064663e8SJens Wiklander 68064663e8SJens Wiklander if (shdr->magic != SHDR_MAGIC) 698a697013SJens Wiklander goto err; 70064663e8SJens Wiklander 71064663e8SJens Wiklander if (TEE_ALG_GET_MAIN_ALG(shdr->algo) != TEE_MAIN_ALGO_RSA) 728a697013SJens Wiklander goto err; 73064663e8SJens Wiklander 74bef7d11dSJens Wiklander hash_algo = TEE_DIGEST_HASH_TO_ALGO(shdr->algo); 75bef7d11dSJens Wiklander if (is_weak_hash_algo(hash_algo)) 768a697013SJens Wiklander goto err; 77bef7d11dSJens Wiklander 78bef7d11dSJens Wiklander res = tee_alg_get_digest_size(hash_algo, &hash_size); 79064663e8SJens Wiklander if (res) 808a697013SJens Wiklander goto err; 81064663e8SJens Wiklander if (hash_size != shdr->hash_size) 828a697013SJens Wiklander goto err; 83064663e8SJens Wiklander 8444c8e3cbSCedric Neveux res = crypto_acipher_alloc_rsa_public_key(&key, 8544c8e3cbSCedric Neveux ta_pub_key_modulus_size * 8); 86064663e8SJens Wiklander if (res) 878a697013SJens Wiklander goto err; 88064663e8SJens Wiklander 89064663e8SJens Wiklander res = crypto_bignum_bin2bn((uint8_t *)&e, sizeof(e), key.e); 90064663e8SJens Wiklander if (res) 918a697013SJens Wiklander goto err; 92064663e8SJens Wiklander res = crypto_bignum_bin2bn(ta_pub_key_modulus, ta_pub_key_modulus_size, 93064663e8SJens Wiklander key.n); 94064663e8SJens Wiklander if (res) 958a697013SJens Wiklander goto err; 96064663e8SJens Wiklander 978a697013SJens Wiklander FTMN_CALL_FUNC(res, &ftmn, FTMN_INCR0, 988a697013SJens Wiklander crypto_acipher_rsassa_verify, shdr->algo, &key, 998a697013SJens Wiklander shdr->hash_size, SHDR_GET_HASH(shdr), shdr->hash_size, 100064663e8SJens Wiklander SHDR_GET_SIG(shdr), shdr->sig_size); 1018a697013SJens Wiklander if (!res) { 1028a697013SJens Wiklander ftmn_checkpoint(&ftmn, FTMN_INCR0); 1038a697013SJens Wiklander goto out; 1048a697013SJens Wiklander } 1058a697013SJens Wiklander err_incr = 1; 1068a697013SJens Wiklander err: 1078a697013SJens Wiklander res = TEE_ERROR_SECURITY; 1088a697013SJens Wiklander FTMN_SET_CHECK_RES_NOT_ZERO(&ftmn, err_incr * FTMN_INCR0, res); 109064663e8SJens Wiklander out: 1108a697013SJens Wiklander FTMN_CALLEE_DONE_CHECK(&ftmn, FTMN_INCR0, FTMN_STEP_COUNT(2), res); 111064663e8SJens Wiklander crypto_acipher_free_rsa_public_key(&key); 1128a697013SJens Wiklander return res; 113064663e8SJens Wiklander } 114c34d0d91SJens Wiklander 115c34d0d91SJens Wiklander static const struct shdr_subkey_attr * 116c34d0d91SJens Wiklander find_attr(const struct shdr_subkey *subkey, uint32_t id) 117c34d0d91SJens Wiklander { 118c34d0d91SJens Wiklander size_t n = 0; 119c34d0d91SJens Wiklander 120c34d0d91SJens Wiklander for (n = 0; n < subkey->attr_count; n++) 121c34d0d91SJens Wiklander if (subkey->attrs[n].id == id) 122c34d0d91SJens Wiklander return subkey->attrs + n; 123c34d0d91SJens Wiklander 124c34d0d91SJens Wiklander return NULL; 125c34d0d91SJens Wiklander } 126c34d0d91SJens Wiklander 127c34d0d91SJens Wiklander static TEE_Result load_rsa_key(const struct shdr_subkey *subkey, 128c34d0d91SJens Wiklander struct rsa_public_key **key_pp) 129c34d0d91SJens Wiklander { 130c34d0d91SJens Wiklander const uint8_t *base = (const uint8_t *)subkey; 131c34d0d91SJens Wiklander const struct shdr_subkey_attr *pub_exp = NULL; 132c34d0d91SJens Wiklander const struct shdr_subkey_attr *modulus = NULL; 133c34d0d91SJens Wiklander struct rsa_public_key *key = NULL; 134c34d0d91SJens Wiklander TEE_Result res = TEE_SUCCESS; 135c34d0d91SJens Wiklander 136c34d0d91SJens Wiklander pub_exp = find_attr(subkey, TEE_ATTR_RSA_PUBLIC_EXPONENT); 137c34d0d91SJens Wiklander if (!pub_exp) 138c34d0d91SJens Wiklander return TEE_ERROR_SECURITY; 139c34d0d91SJens Wiklander modulus = find_attr(subkey, TEE_ATTR_RSA_MODULUS); 140c34d0d91SJens Wiklander if (!modulus) 141c34d0d91SJens Wiklander return TEE_ERROR_SECURITY; 142c34d0d91SJens Wiklander 143c34d0d91SJens Wiklander key = calloc(1, sizeof(*key)); 144c34d0d91SJens Wiklander if (!key) 145c34d0d91SJens Wiklander return TEE_ERROR_OUT_OF_MEMORY; 146c34d0d91SJens Wiklander res = crypto_acipher_alloc_rsa_public_key(key, modulus->size * 8); 147c34d0d91SJens Wiklander if (res) 148c34d0d91SJens Wiklander goto err_key; 149c34d0d91SJens Wiklander 150c34d0d91SJens Wiklander res = crypto_bignum_bin2bn(base + pub_exp->offs, pub_exp->size, key->e); 151c34d0d91SJens Wiklander if (res) 152c34d0d91SJens Wiklander goto err; 153c34d0d91SJens Wiklander res = crypto_bignum_bin2bn(base + modulus->offs, modulus->size, key->n); 154c34d0d91SJens Wiklander if (res) 155c34d0d91SJens Wiklander goto err; 156c34d0d91SJens Wiklander 157c34d0d91SJens Wiklander *key_pp = key; 158c34d0d91SJens Wiklander return TEE_SUCCESS; 159c34d0d91SJens Wiklander err: 160c34d0d91SJens Wiklander crypto_acipher_free_rsa_public_key(key); 161c34d0d91SJens Wiklander err_key: 162c34d0d91SJens Wiklander free(key); 163c34d0d91SJens Wiklander return TEE_ERROR_SECURITY; 164c34d0d91SJens Wiklander } 165c34d0d91SJens Wiklander 166c34d0d91SJens Wiklander static TEE_Result check_attrs(const struct shdr_subkey *subkey, size_t img_size) 167c34d0d91SJens Wiklander { 168c34d0d91SJens Wiklander const struct shdr_subkey_attr *attrs = subkey->attrs; 169c34d0d91SJens Wiklander size_t end = 0; 170c34d0d91SJens Wiklander size_t n = 0; 171c34d0d91SJens Wiklander 172c34d0d91SJens Wiklander if (MUL_OVERFLOW(subkey->attr_count, sizeof(*attrs), &end) || 173c34d0d91SJens Wiklander ADD_OVERFLOW(end, sizeof(*subkey), &end) || 174c34d0d91SJens Wiklander end > img_size) 175c34d0d91SJens Wiklander return TEE_ERROR_SECURITY; 176c34d0d91SJens Wiklander 177c34d0d91SJens Wiklander for (n = 0; n < subkey->attr_count; n++) 178c34d0d91SJens Wiklander if (ADD_OVERFLOW(attrs[n].offs, attrs[n].size, &end) || 179c34d0d91SJens Wiklander end > img_size) 180c34d0d91SJens Wiklander return TEE_ERROR_SECURITY; 181c34d0d91SJens Wiklander 182c34d0d91SJens Wiklander return TEE_SUCCESS; 183c34d0d91SJens Wiklander } 184c34d0d91SJens Wiklander 185c34d0d91SJens Wiklander static TEE_Result calc_next_uuid(uint8_t uuid[sizeof(TEE_UUID)], 186c34d0d91SJens Wiklander const uint8_t my_uuid[sizeof(TEE_UUID)], 187c34d0d91SJens Wiklander const void *ns_name, size_t name_size) 188c34d0d91SJens Wiklander { 189c34d0d91SJens Wiklander TEE_Result res = TEE_ERROR_SECURITY; 190c34d0d91SJens Wiklander void *ctx = NULL; 191c34d0d91SJens Wiklander struct { 192c34d0d91SJens Wiklander uint8_t digest[TEE_SHA1_HASH_SIZE]; 193c34d0d91SJens Wiklander TEE_UUID uuid; 194c34d0d91SJens Wiklander char name_str[]; 195c34d0d91SJens Wiklander } *tmp = NULL; 196c34d0d91SJens Wiklander 197c34d0d91SJens Wiklander if (!name_size) { 198c34d0d91SJens Wiklander memcpy(uuid, my_uuid, sizeof(TEE_UUID)); 199c34d0d91SJens Wiklander return TEE_SUCCESS; 200c34d0d91SJens Wiklander } 201c34d0d91SJens Wiklander 202c34d0d91SJens Wiklander /* 203c34d0d91SJens Wiklander * RFC 4122 requires a SHA-1 digest for UUID v5. Use SHA-512 204c34d0d91SJens Wiklander * instead for better collision resistance. 205c34d0d91SJens Wiklander */ 206c34d0d91SJens Wiklander if (crypto_hash_alloc_ctx(&ctx, TEE_ALG_SHA512)) 207c34d0d91SJens Wiklander return TEE_ERROR_SECURITY; 208c34d0d91SJens Wiklander 209c34d0d91SJens Wiklander tmp = mempool_alloc(mempool_default, sizeof(*tmp) + name_size); 210c34d0d91SJens Wiklander if (!tmp) 211c34d0d91SJens Wiklander goto out_ctx; 212c34d0d91SJens Wiklander memcpy(tmp->name_str, ns_name, name_size); 213c34d0d91SJens Wiklander 214c34d0d91SJens Wiklander if (crypto_hash_init(ctx) || 215c34d0d91SJens Wiklander crypto_hash_update(ctx, my_uuid, sizeof(TEE_UUID)) || 216c34d0d91SJens Wiklander crypto_hash_update(ctx, (const void *)tmp->name_str, 217c34d0d91SJens Wiklander strnlen(tmp->name_str, name_size)) || 218c34d0d91SJens Wiklander crypto_hash_final(ctx, tmp->digest, sizeof(tmp->digest))) 219c34d0d91SJens Wiklander goto out_mempool; 220c34d0d91SJens Wiklander 221c34d0d91SJens Wiklander tee_uuid_from_octets(&tmp->uuid, tmp->digest); 222c34d0d91SJens Wiklander /* 223c34d0d91SJens Wiklander * Set the four most significant bits (bits 12 through 15) of the 224c34d0d91SJens Wiklander * time_hi_and_version field to 5. 225c34d0d91SJens Wiklander */ 226c34d0d91SJens Wiklander tmp->uuid.timeHiAndVersion &= ~SHIFT_U32(0xf, 12); 227c34d0d91SJens Wiklander tmp->uuid.timeHiAndVersion |= SHIFT_U32(5, 12); 228c34d0d91SJens Wiklander /* 229c34d0d91SJens Wiklander * Set the two most significant bits (bits 6 and 7) of the 230c34d0d91SJens Wiklander * clock_seq_hi_and_reserved to zero and one, respectively. 231c34d0d91SJens Wiklander */ 232c34d0d91SJens Wiklander tmp->uuid.clockSeqAndNode[0] &= ~BIT(6); 233c34d0d91SJens Wiklander tmp->uuid.clockSeqAndNode[0] |= BIT(7); 234c34d0d91SJens Wiklander 235c34d0d91SJens Wiklander tee_uuid_to_octets(uuid, &tmp->uuid); 236c34d0d91SJens Wiklander res = TEE_SUCCESS; 237c34d0d91SJens Wiklander 238c34d0d91SJens Wiklander out_mempool: 239c34d0d91SJens Wiklander mempool_free(mempool_default, tmp); 240c34d0d91SJens Wiklander out_ctx: 241c34d0d91SJens Wiklander crypto_hash_free_ctx(ctx); 242c34d0d91SJens Wiklander 243c34d0d91SJens Wiklander return res; 244c34d0d91SJens Wiklander } 245c34d0d91SJens Wiklander 246c34d0d91SJens Wiklander TEE_Result shdr_load_pub_key(const struct shdr *shdr, size_t offs, 247c34d0d91SJens Wiklander const uint8_t *ns_img, size_t ns_img_size, 248c34d0d91SJens Wiklander const uint8_t next_uuid[sizeof(TEE_UUID)], 249c34d0d91SJens Wiklander uint32_t max_depth, struct shdr_pub_key *key) 250c34d0d91SJens Wiklander { 251c34d0d91SJens Wiklander struct shdr_subkey *subkey = NULL; 252c34d0d91SJens Wiklander TEE_Result res = TEE_SUCCESS; 253c34d0d91SJens Wiklander void *digest = NULL; 254c34d0d91SJens Wiklander uint8_t *img = NULL; 255c34d0d91SJens Wiklander void *ctx = NULL; 256c34d0d91SJens Wiklander size_t end = 0; 257c34d0d91SJens Wiklander 258c34d0d91SJens Wiklander if (shdr->img_type != SHDR_SUBKEY) 259c34d0d91SJens Wiklander return TEE_ERROR_SECURITY; 260c34d0d91SJens Wiklander 261c34d0d91SJens Wiklander if (shdr->img_size < sizeof(*subkey)) 262c34d0d91SJens Wiklander return TEE_ERROR_SECURITY; 263c34d0d91SJens Wiklander 264c34d0d91SJens Wiklander if (ADD_OVERFLOW(shdr->img_size, offs, &end) || end > ns_img_size) 265c34d0d91SJens Wiklander return TEE_ERROR_SECURITY; 266c34d0d91SJens Wiklander 267c34d0d91SJens Wiklander img = mempool_alloc(mempool_default, shdr->img_size + shdr->hash_size); 268c34d0d91SJens Wiklander if (!img) 269c34d0d91SJens Wiklander return TEE_ERROR_OUT_OF_MEMORY; 270c34d0d91SJens Wiklander memcpy(img + shdr->hash_size, ns_img + offs, shdr->img_size); 271c34d0d91SJens Wiklander subkey = (void *)(img + shdr->hash_size); 272c34d0d91SJens Wiklander digest = img; 273c34d0d91SJens Wiklander 274c34d0d91SJens Wiklander if (crypto_hash_alloc_ctx(&ctx, TEE_DIGEST_HASH_TO_ALGO(shdr->algo))) { 275c34d0d91SJens Wiklander res = TEE_ERROR_SECURITY; 276c34d0d91SJens Wiklander goto out_mempool; 277c34d0d91SJens Wiklander } 278c34d0d91SJens Wiklander 279c34d0d91SJens Wiklander if (crypto_hash_init(ctx) || 280c34d0d91SJens Wiklander crypto_hash_update(ctx, (const void *)shdr, sizeof(*shdr)) || 281c34d0d91SJens Wiklander crypto_hash_update(ctx, (const void *)subkey, shdr->img_size) || 282c34d0d91SJens Wiklander crypto_hash_final(ctx, digest, shdr->hash_size) || 283c34d0d91SJens Wiklander memcmp(digest, SHDR_GET_HASH(shdr), shdr->hash_size)) { 284c34d0d91SJens Wiklander res = TEE_ERROR_SECURITY; 285c34d0d91SJens Wiklander goto out_ctx; 286c34d0d91SJens Wiklander } 287c34d0d91SJens Wiklander 288c34d0d91SJens Wiklander res = check_attrs(subkey, shdr->img_size); 289c34d0d91SJens Wiklander if (res) 290c34d0d91SJens Wiklander goto out_ctx; 291c34d0d91SJens Wiklander 292c34d0d91SJens Wiklander if (subkey->max_depth >= max_depth) { 293c34d0d91SJens Wiklander res = TEE_ERROR_SECURITY; 294c34d0d91SJens Wiklander goto out_ctx; 295c34d0d91SJens Wiklander } 296c34d0d91SJens Wiklander if (next_uuid && memcmp(next_uuid, subkey->uuid, sizeof(TEE_UUID))) { 297c34d0d91SJens Wiklander res = TEE_ERROR_SECURITY; 298c34d0d91SJens Wiklander goto out_ctx; 299c34d0d91SJens Wiklander } 300c34d0d91SJens Wiklander 301c34d0d91SJens Wiklander key->max_depth = subkey->max_depth; 302c34d0d91SJens Wiklander key->name_size = subkey->name_size; 303c34d0d91SJens Wiklander memcpy(key->uuid, subkey->uuid, sizeof(TEE_UUID)); 304c34d0d91SJens Wiklander if (ADD_OVERFLOW(key->name_size, offs + shdr->img_size, &end) || 305c34d0d91SJens Wiklander end > ns_img_size) { 306c34d0d91SJens Wiklander res = TEE_ERROR_SECURITY; 307c34d0d91SJens Wiklander goto out_ctx; 308c34d0d91SJens Wiklander } 309c34d0d91SJens Wiklander res = calc_next_uuid(key->next_uuid, key->uuid, 310c34d0d91SJens Wiklander ns_img + offs + shdr->img_size, key->name_size); 311c34d0d91SJens Wiklander if (res) 312c34d0d91SJens Wiklander goto out_ctx; 313c34d0d91SJens Wiklander 314c34d0d91SJens Wiklander key->main_algo = TEE_ALG_GET_MAIN_ALG(subkey->algo); 315c34d0d91SJens Wiklander switch (key->main_algo) { 316c34d0d91SJens Wiklander case TEE_MAIN_ALGO_RSA: 317c34d0d91SJens Wiklander res = load_rsa_key(subkey, &key->pub_key.rsa); 318c34d0d91SJens Wiklander break; 319c34d0d91SJens Wiklander default: 320c34d0d91SJens Wiklander res = TEE_ERROR_SECURITY; 321c34d0d91SJens Wiklander break; 322c34d0d91SJens Wiklander } 323c34d0d91SJens Wiklander 324c34d0d91SJens Wiklander out_ctx: 325c34d0d91SJens Wiklander crypto_hash_free_ctx(ctx); 326c34d0d91SJens Wiklander out_mempool: 327c34d0d91SJens Wiklander mempool_free(mempool_default, img); 328c34d0d91SJens Wiklander return res; 329c34d0d91SJens Wiklander } 330c34d0d91SJens Wiklander 331c34d0d91SJens Wiklander void shdr_free_pub_key(struct shdr_pub_key *key) 332c34d0d91SJens Wiklander { 333c34d0d91SJens Wiklander if (key) { 334c34d0d91SJens Wiklander switch (key->main_algo) { 335c34d0d91SJens Wiklander case TEE_MAIN_ALGO_RSA: 336c34d0d91SJens Wiklander crypto_acipher_free_rsa_public_key(key->pub_key.rsa); 337c34d0d91SJens Wiklander free(key->pub_key.rsa); 338c34d0d91SJens Wiklander break; 339c34d0d91SJens Wiklander default: 340c34d0d91SJens Wiklander panic(); 341c34d0d91SJens Wiklander } 342c34d0d91SJens Wiklander } 343c34d0d91SJens Wiklander } 344c34d0d91SJens Wiklander 345c34d0d91SJens Wiklander TEE_Result shdr_verify_signature2(struct shdr_pub_key *key, 346c34d0d91SJens Wiklander const struct shdr *shdr) 347c34d0d91SJens Wiklander { 3488a697013SJens Wiklander TEE_Result res = TEE_SUCCESS; 3498a697013SJens Wiklander unsigned int err_incr = 2; 3508a697013SJens Wiklander struct ftmn ftmn = { }; 351c34d0d91SJens Wiklander size_t hash_size = 0; 352bef7d11dSJens Wiklander size_t hash_algo = 0; 353c34d0d91SJens Wiklander 354c34d0d91SJens Wiklander if (shdr->magic != SHDR_MAGIC) 3558a697013SJens Wiklander goto err; 356c34d0d91SJens Wiklander 357c34d0d91SJens Wiklander if (TEE_ALG_GET_MAIN_ALG(shdr->algo) != key->main_algo) 3588a697013SJens Wiklander goto err; 359c34d0d91SJens Wiklander 360bef7d11dSJens Wiklander hash_algo = TEE_DIGEST_HASH_TO_ALGO(shdr->algo); 361bef7d11dSJens Wiklander if (is_weak_hash_algo(hash_algo)) 3628a697013SJens Wiklander goto err; 363bef7d11dSJens Wiklander 364bef7d11dSJens Wiklander if (tee_alg_get_digest_size(hash_algo, &hash_size) || 365c34d0d91SJens Wiklander hash_size != shdr->hash_size) 3668a697013SJens Wiklander goto err; 367c34d0d91SJens Wiklander 368c34d0d91SJens Wiklander switch (key->main_algo) { 369c34d0d91SJens Wiklander case TEE_MAIN_ALGO_RSA: 3708a697013SJens Wiklander FTMN_CALL_FUNC(res, &ftmn, FTMN_INCR0, 3718a697013SJens Wiklander crypto_acipher_rsassa_verify, shdr->algo, 3728a697013SJens Wiklander key->pub_key.rsa, shdr->hash_size, 3738a697013SJens Wiklander SHDR_GET_HASH(shdr), shdr->hash_size, 3748a697013SJens Wiklander SHDR_GET_SIG(shdr), shdr->sig_size); 375c34d0d91SJens Wiklander break; 376c34d0d91SJens Wiklander default: 377c34d0d91SJens Wiklander panic(); 378c34d0d91SJens Wiklander } 379c34d0d91SJens Wiklander 3808a697013SJens Wiklander if (!res) { 3818a697013SJens Wiklander ftmn_checkpoint(&ftmn, FTMN_INCR0); 3828a697013SJens Wiklander goto out; 3838a697013SJens Wiklander } 3848a697013SJens Wiklander err_incr = 1; 3858a697013SJens Wiklander err: 3868a697013SJens Wiklander res = TEE_ERROR_SECURITY; 3878a697013SJens Wiklander FTMN_SET_CHECK_RES_NOT_ZERO(&ftmn, err_incr * FTMN_INCR0, res); 3888a697013SJens Wiklander out: 3898a697013SJens Wiklander FTMN_CALLEE_DONE_CHECK(&ftmn, FTMN_INCR0, FTMN_STEP_COUNT(2), res); 3908a697013SJens Wiklander return res; 391c34d0d91SJens Wiklander } 392