OP-TEE / optee_os

Trusted side of the TEE
Other
1.55k stars 1.05k forks source link

Fuzzing TA framework #6546

Closed NewDwarf closed 7 months ago

NewDwarf commented 8 months ago

...it is interesting whether developers think about writing reference implementation of the internal API specification to cut the syscall* abstraction so that to invoke TEE* API directly from the fuzzer. I created such partly implementation to run coverage guided fuzzing of TA's. And it works pretty well. I believe it would be nice to have a such framework for TA developers, but, probably, there are some obstacles, difficulties for that. Just for example

TEE_Result TEE_ReadObjectData(TEE_ObjectHandle object, void *buffer,
        uint32_t size, uint32_t *count)
{
    if (object == TEE_HANDLE_NULL)   
        return TEE_ERROR_BAD_PARAMETERS;

    if (buffer == NULL)
        return TEE_ERROR_BAD_PARAMETERS;

    *count = read((int)(uintptr_t) object, buffer, size);

    return TEE_SUCCESS;
}
jbech-linaro commented 8 months ago

Hi, some work related to this was done by https://twitter.com/jmartijnb from Riscure a couple of years ago (see this for details). I remember he also had challenges and had to to rather invasive changes here and there. It's interesting, yes, but if we should be able to use something like this it has to be done without too many modifications.

We do run a monthly call for OP-TEE people, if you'd like to show what you've done and would like to discuss in person, then that meeting could be a good slot to get more feedback (next meeting Jan 23rd).

NewDwarf commented 8 months ago

@jbech-linaro Hi. Thanks for the feedback. Riscure's work is more about fuzzing the OP-TEE OS itself. I would like to focus more on the trusted applications. ...and I am not sure whether this repo is the right place for this topic. The main problem to implement reliable fuzzing TA framework is a complicated workflow of specific internal API. For example, the API for working with the trusted storage has S-EL0 -> S-EL1 transition via a system call, internal work with complex structures, and, finally, RPC calls to REE's tee-supplicant. The original idea was to combine the whole logic and implement it as a set of regular functions (which would implements specification os the GP's internal API) to be able to link it with the target fuzz TA and then run it as a userspace application for fuzzing. To achieve this, I guess, there should be created a separated repo (but I am not sure).

The second idea I have for TA fuzzing is to write kind of TA proxy which would translate part of valid context to the client application. The main benefit of this approach - we can run it on the real OEM HW and under real OP-TEE control. For example, let's take a target TA for fuzzing which generates random. To build a fuzzer for the target "generate random" TA, we

  1. implement fuzzing logic
  2. take original TA source file
  3. Implement all required internal API. Internally, it is just adapters to forward necessary call into the TEE.

    
    void TEE_GenerateRandom(void *randomBuffer, uint32_t randomBufferLen)
    {
    uint32_t err_origin;
    TEEC_Operation op = { 0 };
    memset(&op, 0, sizeof(op));
    
    op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_OUTPUT,
                     TEEC_NONE, TEEC_NONE, TEEC_NONE);
    
    op.params[0].tmpref.buffer = randomBuffer;
    op.params[0].tmpref.size = randomBufferLen;
    
    res = TEEC_InvokeCommand(&sess, TA_RANDOM_CMD_GENERATE_PROXY,
                 &op, &err_origin);
    if (res != TEEC_SUCCESS)
        errx(1, ">>> TEE PROXY (TEE_GenerateRandom) failed with code 0x%x origin 0x%x",
            res, err_origin);
    }

4. Implement the handler for the TA_RANDOM_CMD_GENERATE_PROXY command. The main goals for the handlers are 
a. Invoke the appropriate real internal API
b. return valid output (pointers, integers) as is to outside so that don't break execution context.

I am new in this area and when I wondered how I would test TA's, I didn't find any reliable and simple solution, so I decided to think about it by myself and ask a community.
jenswi-linaro commented 8 months ago

The GP API is implemented in libutee which as the name suggests is a library, so functions are easily overridden if you add another library earlier on the command line. It could very well make sense to add this to the optee_test git.

github-actions[bot] commented 7 months ago

This issue has been marked as a stale issue because it has been open (more than) 30 days with no activity. Remove the stale label or add a comment, otherwise this issue will automatically be closed in 5 days. Note, that you can always re-open a closed issue at any time.