OP-TEE / optee_os

Trusted side of the TEE
Other
1.51k stars 1.03k forks source link

System halted by FTMN_CALL_FUNC #6909

Open qazsdcx opened 6 days ago

qazsdcx commented 6 days ago

Hi, experts

I am trying to replace the software encryption engine with a hardware encryption engine. I try to use core/drivers/crypto/crypto_api. I use drvcrypt_register_rsa to register rsa_init.

static TEE_Result rsa_init(void)
{
    return drvcrypt_register_rsa(&driver_rsa);
}

driver_init_late(rsa_init);

Then I plan to replace some RSA algorithms with hardware engines and implement the rest with software algorithms(libtomcrypto).

RSA verify function will be implemented by sw_crypto_acipher_rsassa_verify:

static TEE_Result do_ssa_verify(struct drvcrypt_rsa_ssa *ssa_data)
{
    return sw_crypto_acipher_rsassa_verify(ssa_data->algo, ssa_data->key.key, ssa_data->salt_len,
                                         ssa_data->message.data, ssa_data->message.length,
                         ssa_data->signature.data, (ssa_data->signature.length));
}

static const struct drvcrypt_rsa driver_rsa = {
    .alloc_keypair = do_alloc_keypair,
    .alloc_publickey = do_alloc_publickey,
    .free_publickey = do_free_publickey,
    .free_keypair = do_free_keypair,
    .gen_keypair = do_gen_keypair,
    .encrypt = do_encrypt,
    .decrypt = do_decrypt,
    .optional.ssa_sign = do_ssa_sign,
    .optional.ssa_verify = do_ssa_verify,
};

When I run CA to call TA. The sysytem halted. The log is as follows:

/TC:? 0 tee_ta_init_pseudo_ta_session:297 Lookup pseudo TA 4cfe32gh-3042-265a-664d-0740f58bae21 D/TC:? 0 ldelf_load_ldelf:110 ldelf load address 0x80007000 D/LD: ldelf:142 Loading TS 4cfe32gh-3042-265a-664d-0740f58bae21 D/TC:? 0 ldelf_syscall_open_bin:163 Lookup user TA ELF 4cfe32gh-3042-265a-664d-0740f58bae21 (early TA) D/TC:? 0 ldelf_syscall_open_bin:167 res=0xffff0008 D/TC:? 0 ldelf_syscall_open_bin:163 Lookup user TA ELF 4cfe32gh-3042-265a-664d-0740f58bae21 (Secure Storage TA) I/TC: WARNING (insecure configuration): Failed to get monotonic counter for REE FS, using 0 I/TC: WARNING (insecure configuration): Failed to commit dirh counter 2 D/TC:? 0 ldelf_syscall_open_bin:167 res=0xffff0008 D/TC:? 0 ldelf_syscall_open_bin:163 Lookup user TA ELF 4cfe32gh-3042-265a-664d-0740f58bae21 (REE) E/TC:? 0 assertion 'f->arg.hash == (f->my_hash ^ f->called_hash)' failed at lib/libutils/ext/include/fault_mitigation.h:301 <__ftmn_copy_linked_call_res> E/TC:0 0 Panic at core/kernel/assert.c:28 <_assert_break> E/TC:0 0 TEE load address @ 0x3bff0000 E/TC:0 0 Call stack: E/TC:0 0 0x3bff8264 E/TC:0 0 0x3c008314 E/TC:0 0 0x3c003f18 E/TC:0 0 0x3bffc7a8 E/TC:0 0 0x3bffca74 E/TC:0 0 0x3c00de20 E/TC:0 0 0x3c007574 E/TC:0 0 0x3bff59c4 E/TC:0 0 0x3bff5690 E/TC:0 0 0x3bff4340 I/TC: Halting CPU 1

I founthe code shdr_verify_signature() in in signed_hdr.c

TEE_Result shdr_verify_signature(const struct shdr *shdr)
{
    ...

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

    res = crypto_bignum_bin2bn((uint8_t *)&e, sizeof(e), key.e);
    if (res)
        goto err;
    res = crypto_bignum_bin2bn(ta_pub_key_modulus, ta_pub_key_modulus_size,
                   key.n);
    if (res)
        goto err;
    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);
    return res;
}

The return value of sw_crypto_cipher_rsasa_verify is 0, but there is an exception in FTMN_CALL_FUNC.

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)

So how can I solve this problem?

BTW: My OP-TEE os version is 4.1.0

Thanks!

jenswi-linaro commented 4 days ago

I'm not sure if the fault mitigation flow has been tested with a DRVCRYPT and software fallback. Looking at the code it seems that the FTMN_CALLEE_DONE(ret); at the end of crypto_acipher_rsassa_verify() in core/drivers/crypto/crypto_api/acipher/rsa.c might interface with what's done in sw_crypto_cipher_rsasa_verify(). Can you try with that line commented out?

It would be nice with a dummy DRVCRYPT implementation falling back to sw_crypto_cipher_rsasa_verify() in QEMU to improve CI coverage.

qazsdcx commented 2 days ago

I commented out FTMN_CALLEE_DONE(ret) in crypto_acipher_rsassa_verify() (core/drivers/crypto/crypto_api/acipher/rsa.c). It can run pass. Is this a work aound solution?

jenswi-linaro commented 2 days ago

Thanks for confirming. No, it's not a good workaround. I'll try to come up with something.