Skip to content

Commit

Permalink
core: add fault mitigations to shdr_verify_signature*()
Browse files Browse the repository at this point in the history
Adds fault mitigations to shdr_verify_signature() and
shdr_verify_signature2(). shdr_verify_signature() and
shdr_verify_signature2() are called using the wrapper FTMN_CALL_FUNC()
which verifies that the correct function was called and that the return
value hasn't been tampered with.

Acked-by: Jerome Forissier <jerome.forissier@linaro.org>
Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
  • Loading branch information
jenswi-linaro authored and jforissier committed Nov 25, 2022
1 parent b303be9 commit 8a69701
Showing 1 changed file with 48 additions and 26 deletions.
74 changes: 48 additions & 26 deletions core/crypto/signed_hdr.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
*/

#include <crypto/crypto.h>
#include <fault_mitigation.h>
#include <kernel/panic.h>
#include <mempool.h>
#include <signed_hdr.h>
Expand Down Expand Up @@ -59,46 +60,56 @@ TEE_Result shdr_verify_signature(const struct shdr *shdr)
struct rsa_public_key key = { };
TEE_Result res = TEE_SUCCESS;
uint32_t e = TEE_U32_TO_BIG_ENDIAN(ta_pub_key_exponent);
struct ftmn ftmn = { };
unsigned int err_incr = 2;
size_t hash_size = 0;
size_t hash_algo = 0;

if (shdr->magic != SHDR_MAGIC)
return TEE_ERROR_SECURITY;
goto err;

if (TEE_ALG_GET_MAIN_ALG(shdr->algo) != TEE_MAIN_ALGO_RSA)
return TEE_ERROR_SECURITY;
goto err;

hash_algo = TEE_DIGEST_HASH_TO_ALGO(shdr->algo);
if (is_weak_hash_algo(hash_algo))
return TEE_ERROR_SECURITY;
goto err;

res = tee_alg_get_digest_size(hash_algo, &hash_size);
if (res)
return TEE_ERROR_SECURITY;
goto err;
if (hash_size != shdr->hash_size)
return TEE_ERROR_SECURITY;
goto err;

res = crypto_acipher_alloc_rsa_public_key(&key,
ta_pub_key_modulus_size * 8);
if (res)
return TEE_ERROR_SECURITY;
goto err;

res = crypto_bignum_bin2bn((uint8_t *)&e, sizeof(e), key.e);
if (res)
goto out;
goto err;
res = crypto_bignum_bin2bn(ta_pub_key_modulus, ta_pub_key_modulus_size,
key.n);
if (res)
goto out;
goto err;

res = crypto_acipher_rsassa_verify(shdr->algo, &key, shdr->hash_size,
SHDR_GET_HASH(shdr), shdr->hash_size,
SHDR_GET_SIG(shdr), shdr->sig_size);
FTMN_CALL_FUNC(res, &ftmn, FTMN_INCR0,
crypto_acipher_rsassa_verify, shdr->algo, &key,
shdr->hash_size, SHDR_GET_HASH(shdr), shdr->hash_size,
SHDR_GET_SIG(shdr), shdr->sig_size);
if (!res) {
ftmn_checkpoint(&ftmn, FTMN_INCR0);
goto out;
}
err_incr = 1;
err:
res = TEE_ERROR_SECURITY;
FTMN_SET_CHECK_RES_NOT_ZERO(&ftmn, err_incr * FTMN_INCR0, res);
out:
FTMN_CALLEE_DONE_CHECK(&ftmn, FTMN_INCR0, FTMN_STEP_COUNT(2), res);
crypto_acipher_free_rsa_public_key(&key);
if (res)
return TEE_ERROR_SECURITY;
return TEE_SUCCESS;
return res;
}

static const struct shdr_subkey_attr *
Expand Down Expand Up @@ -334,36 +345,47 @@ void shdr_free_pub_key(struct shdr_pub_key *key)
TEE_Result shdr_verify_signature2(struct shdr_pub_key *key,
const struct shdr *shdr)
{
TEE_Result res = TEE_SUCCESS;
unsigned int err_incr = 2;
struct ftmn ftmn = { };
size_t hash_size = 0;
size_t hash_algo = 0;

if (shdr->magic != SHDR_MAGIC)
return TEE_ERROR_SECURITY;
goto err;

if (TEE_ALG_GET_MAIN_ALG(shdr->algo) != key->main_algo)
return TEE_ERROR_SECURITY;
goto err;

hash_algo = TEE_DIGEST_HASH_TO_ALGO(shdr->algo);
if (is_weak_hash_algo(hash_algo))
return TEE_ERROR_SECURITY;
goto err;

if (tee_alg_get_digest_size(hash_algo, &hash_size) ||
hash_size != shdr->hash_size)
return TEE_ERROR_SECURITY;
goto err;

switch (key->main_algo) {
case TEE_MAIN_ALGO_RSA:
if (crypto_acipher_rsassa_verify(shdr->algo, key->pub_key.rsa,
shdr->hash_size,
SHDR_GET_HASH(shdr),
shdr->hash_size,
SHDR_GET_SIG(shdr),
shdr->sig_size))
return TEE_ERROR_SECURITY;
FTMN_CALL_FUNC(res, &ftmn, FTMN_INCR0,
crypto_acipher_rsassa_verify, shdr->algo,
key->pub_key.rsa, shdr->hash_size,
SHDR_GET_HASH(shdr), shdr->hash_size,
SHDR_GET_SIG(shdr), shdr->sig_size);
break;
default:
panic();
}

return TEE_SUCCESS;
if (!res) {
ftmn_checkpoint(&ftmn, FTMN_INCR0);
goto out;
}
err_incr = 1;
err:
res = TEE_ERROR_SECURITY;
FTMN_SET_CHECK_RES_NOT_ZERO(&ftmn, err_incr * FTMN_INCR0, res);
out:
FTMN_CALLEE_DONE_CHECK(&ftmn, FTMN_INCR0, FTMN_STEP_COUNT(2), res);
return res;
}

0 comments on commit 8a69701

Please sign in to comment.