1fb7ef469SJerome Forissier // SPDX-License-Identifier: BSD-2-Clause 2064663e8SJens Wiklander /* 3064663e8SJens Wiklander * Copyright (c) 2015-2017, Linaro Limited 4064663e8SJens Wiklander */ 5064663e8SJens Wiklander 6064663e8SJens Wiklander #include <crypto/crypto.h> 7064663e8SJens Wiklander #include <signed_hdr.h> 8064663e8SJens Wiklander #include <stdlib.h> 9064663e8SJens Wiklander #include <string.h> 10064663e8SJens Wiklander #include <ta_pub_key.h> 11064663e8SJens Wiklander #include <tee_api_types.h> 12064663e8SJens Wiklander #include <tee/tee_cryp_utl.h> 13064663e8SJens Wiklander #include <utee_defines.h> 14062765e4SJerome Forissier #include <util.h> 15064663e8SJens Wiklander 16*ec1aa4faSJens Wiklander struct shdr *shdr_alloc_and_copy(size_t offs, const void *img, size_t img_size) 17064663e8SJens Wiklander { 18064663e8SJens Wiklander size_t shdr_size; 19064663e8SJens Wiklander struct shdr *shdr; 20062765e4SJerome Forissier vaddr_t img_va = (vaddr_t)img; 21062765e4SJerome Forissier vaddr_t tmp = 0; 22*ec1aa4faSJens Wiklander size_t end = 0; 23064663e8SJens Wiklander 24*ec1aa4faSJens Wiklander if (ADD_OVERFLOW(offs, sizeof(struct shdr), &end) || end > img_size) 254ca9e426SJoakim Bech return NULL; 264ca9e426SJoakim Bech 27*ec1aa4faSJens Wiklander shdr_size = SHDR_GET_SIZE((const struct shdr *)(img_va + offs)); 28*ec1aa4faSJens Wiklander if (ADD_OVERFLOW(offs, shdr_size, &end) || end > img_size) 294ca9e426SJoakim Bech return NULL; 30064663e8SJens Wiklander 31062765e4SJerome Forissier if (ADD_OVERFLOW(img_va, shdr_size, &tmp)) 32062765e4SJerome Forissier return NULL; 33062765e4SJerome Forissier 34064663e8SJens Wiklander shdr = malloc(shdr_size); 35064663e8SJens Wiklander if (!shdr) 36064663e8SJens Wiklander return NULL; 37*ec1aa4faSJens Wiklander memcpy(shdr, (const uint8_t *)img + offs, shdr_size); 38064663e8SJens Wiklander 39064663e8SJens Wiklander /* Check that the data wasn't modified before the copy was completed */ 40064663e8SJens Wiklander if (shdr_size != SHDR_GET_SIZE(shdr)) { 41064663e8SJens Wiklander free(shdr); 42064663e8SJens Wiklander return NULL; 43064663e8SJens Wiklander } 44064663e8SJens Wiklander 45064663e8SJens Wiklander return shdr; 46064663e8SJens Wiklander } 47064663e8SJens Wiklander 48064663e8SJens Wiklander TEE_Result shdr_verify_signature(const struct shdr *shdr) 49064663e8SJens Wiklander { 50064663e8SJens Wiklander struct rsa_public_key key; 51064663e8SJens Wiklander TEE_Result res; 52064663e8SJens Wiklander uint32_t e = TEE_U32_TO_BIG_ENDIAN(ta_pub_key_exponent); 53064663e8SJens Wiklander size_t hash_size; 54064663e8SJens Wiklander 55064663e8SJens Wiklander if (shdr->magic != SHDR_MAGIC) 56064663e8SJens Wiklander return TEE_ERROR_SECURITY; 57064663e8SJens Wiklander 58064663e8SJens Wiklander if (TEE_ALG_GET_MAIN_ALG(shdr->algo) != TEE_MAIN_ALGO_RSA) 59064663e8SJens Wiklander return TEE_ERROR_SECURITY; 60064663e8SJens Wiklander 617c767434SAlbert Schwarzkopf res = tee_alg_get_digest_size(TEE_DIGEST_HASH_TO_ALGO(shdr->algo), 62064663e8SJens Wiklander &hash_size); 63064663e8SJens Wiklander if (res) 64064663e8SJens Wiklander return TEE_ERROR_SECURITY; 65064663e8SJens Wiklander if (hash_size != shdr->hash_size) 66064663e8SJens Wiklander return TEE_ERROR_SECURITY; 67064663e8SJens Wiklander 6844c8e3cbSCedric Neveux res = crypto_acipher_alloc_rsa_public_key(&key, 6944c8e3cbSCedric Neveux ta_pub_key_modulus_size * 8); 70064663e8SJens Wiklander if (res) 71064663e8SJens Wiklander return TEE_ERROR_SECURITY; 72064663e8SJens Wiklander 73064663e8SJens Wiklander res = crypto_bignum_bin2bn((uint8_t *)&e, sizeof(e), key.e); 74064663e8SJens Wiklander if (res) 75064663e8SJens Wiklander goto out; 76064663e8SJens Wiklander res = crypto_bignum_bin2bn(ta_pub_key_modulus, ta_pub_key_modulus_size, 77064663e8SJens Wiklander key.n); 78064663e8SJens Wiklander if (res) 79064663e8SJens Wiklander goto out; 80064663e8SJens Wiklander 812139aa8cSJens Wiklander res = crypto_acipher_rsassa_verify(shdr->algo, &key, shdr->hash_size, 82064663e8SJens Wiklander SHDR_GET_HASH(shdr), shdr->hash_size, 83064663e8SJens Wiklander SHDR_GET_SIG(shdr), shdr->sig_size); 84064663e8SJens Wiklander out: 85064663e8SJens Wiklander crypto_acipher_free_rsa_public_key(&key); 86064663e8SJens Wiklander if (res) 87064663e8SJens Wiklander return TEE_ERROR_SECURITY; 88064663e8SJens Wiklander return TEE_SUCCESS; 89064663e8SJens Wiklander } 90