TEE_Result tee_mac_get_digest_size(uint32_t algo, size_t *size) { switch (algo) { case TEE_ALG_HMAC_MD5: case TEE_ALG_HMAC_SHA224: case TEE_ALG_HMAC_SHA1: case TEE_ALG_HMAC_SHA256: case TEE_ALG_HMAC_SHA384: case TEE_ALG_HMAC_SHA512: return tee_hash_get_digest_size(algo, size); case TEE_ALG_AES_CBC_MAC_NOPAD: case TEE_ALG_AES_CBC_MAC_PKCS5: case TEE_ALG_AES_CMAC: *size = TEE_AES_BLOCK_SIZE; return TEE_SUCCESS; case TEE_ALG_DES_CBC_MAC_NOPAD: case TEE_ALG_DES_CBC_MAC_PKCS5: case TEE_ALG_DES3_CBC_MAC_NOPAD: case TEE_ALG_DES3_CBC_MAC_PKCS5: *size = TEE_DES_BLOCK_SIZE; return TEE_SUCCESS; default: return TEE_ERROR_NOT_SUPPORTED; } }
TEE_Result tee_cryp_concat_kdf(uint32_t hash_id, const uint8_t *shared_secret, size_t shared_secret_len, const uint8_t *other_info, size_t other_info_len, uint8_t *derived_key, size_t derived_key_len) { TEE_Result res; size_t hash_len, i, n, sz; void *ctx = NULL; uint8_t tmp[TEE_MAX_HASH_SIZE]; uint32_t be_count; uint8_t *out = derived_key; uint32_t hash_algo = TEE_ALG_HASH_ALGO(hash_id); res = crypto_hash_alloc_ctx(&ctx, hash_algo); if (res != TEE_SUCCESS) return res; res = tee_hash_get_digest_size(hash_algo, &hash_len); if (res != TEE_SUCCESS) goto out; n = derived_key_len / hash_len; sz = hash_len; for (i = 1; i <= n + 1; i++) { be_count = TEE_U32_TO_BIG_ENDIAN(i); res = crypto_hash_init(ctx, hash_algo); if (res != TEE_SUCCESS) goto out; res = crypto_hash_update(ctx, hash_algo, (uint8_t *)&be_count, sizeof(be_count)); if (res != TEE_SUCCESS) goto out; res = crypto_hash_update(ctx, hash_algo, shared_secret, shared_secret_len); if (res != TEE_SUCCESS) goto out; if (other_info && other_info_len) { res = crypto_hash_update(ctx, hash_algo, other_info, other_info_len); if (res != TEE_SUCCESS) goto out; } res = crypto_hash_final(ctx, hash_algo, tmp, sizeof(tmp)); if (res != TEE_SUCCESS) goto out; if (i == n + 1) sz = derived_key_len % hash_len; memcpy(out, tmp, sz); out += sz; } res = TEE_SUCCESS; out: crypto_hash_free_ctx(ctx, hash_algo); return res; }
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; }