OP-TEE / optee_os

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

transfering string to secure world and return another string from secure world to rich world #6877

Open misagham opened 3 weeks ago

misagham commented 3 weeks ago

hi i just new on optee i build it on jetson xavier nx and implement hello_world example and its work completely fine . i just need to transfer a string from rich world to secure world and because of op.params[0].value.a is integer i cant do it i have take a look to this issue https://github.com/OP-TEE/optee_os/issues/1248 and modified the code base on what it is in the issue asked but i cant understand what to do in the last part when it says "In the TA I copied the character string to the passed buffer and updated the length before return " can you help me to complete this ??

this is part of client code : memset(&op, 0, sizeof(op)); char arg[20]; memset(arg, 0, sizeof(arg)); strcpy(arg,"Helarld");

char ret[20];
op.params[0].tmpref.buffer = (void *)arg;
op.params[0].tmpref.size = 20;

/*
 * Prepare the argument. Pass a value in the first parameter,
 * the remaining three parameters are unused.
 */
op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INPUT,
                                     TEEC_MEMREF_TEMP_OUTPUT,
                                     TEEC_NONE,
                                     TEEC_NONE);

res = TEEC_InvokeCommand(&sess, TA_AB_TEST_CMD_INC_VALUE, &op, &err_origin);
if (res != TEEC_SUCCESS)
    errx(1, "TEEC_InvokeCommand failed with code 0x%x origin 0x%x",res, err_origin);
else{
    printf("Return Success \n");
            printf("Returned string : %s \n", (char *) op.params[1].tmpref.buffer); // this comes to null
            printf("Returned size : %d \n\n", op.params[1].tmpref.size); // this prints 8
    }

and this is part of TA: static TEE_Result inc_value(uint32_t param_types, TEE_Param params[4]) {

uint32_t exp_param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT,
                                               TEE_PARAM_TYPE_MEMREF_OUTPUT,
                                               TEE_PARAM_TYPE_NONE,
                                               TEE_PARAM_TYPE_NONE);

    char ret_arg[] = "Bye Bye";
params[1].memref.buffer = (void *) ret_arg;
params[1].memref.size = 8;

DMSG("has been called");

if (param_types != exp_param_types)
    return TEE_ERROR_BAD_PARAMETERS;

return TEE_SUCCESS;

}

when i run the Trusted app it give me back this : Return Success Returned string : ������ Returned size : 8

ivila commented 3 weeks ago

@misagham When input, you must set buffer to a valid pointer:

    char ret[20];
    op.params[0].tmpref.buffer = (void *)arg;
    op.params[0].tmpref.size = 20;
    // you must set the pointer reference so that TEE world can move share data into it.
    op.params[1].tmpref.buffer = ret;
    op.params[1].tmpref.size = sizeof(ret);

    op.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INPUT,
                                     TEEC_MEMREF_TEMP_OUTPUT,
                                     TEEC_NONE,
                                     TEEC_NONE);

    res = TEEC_InvokeCommand(&sess, TA_AB_TEST_CMD_INC_VALUE, &op, &err_origin);
    if (res != TEEC_SUCCESS)
    errx(1, "TEEC_InvokeCommand failed with code 0x%x origin 0x%x",res, err_origin);
    else{
    printf("Return Success \n");
        printf("Returned string : %s \n", ret); // just print ret directly
        //printf("Returned string : %s \n", (char *) op.params[1].tmpref.buffer); // this comes to null
        printf("Returned size : %d \n\n", op.params[1].tmpref.size); // this prints 8
    }

Also, you may need to check the buffer size of params[1] in TEE world in case of there are short of memory, and use TEE_MemMove to copy your output data

static TEE_Result inc_value(uint32_t param_types, TEE_Param params[4]) {
    uint32_t exp_param_types = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT,
                                               TEE_PARAM_TYPE_MEMREF_OUTPUT,
                                               TEE_PARAM_TYPE_NONE,
                                               TEE_PARAM_TYPE_NONE);

    if (param_types != exp_param_types)
    return TEE_ERROR_BAD_PARAMETERS;
    // check output size first
    if (params[1].memref.size < sizeof(ret_arg)) {
        EMSG("short output buffer");
        return TEE_ERROR_SHORT_BUFFER;
    }
    // then set output
    char ret_arg[] = "Bye Bye";
    // Don't set value directly, Use TEE_MemMove instead
    // params[1].memref.buffer = (void *) ret_arg;
    TEE_MemMove(params[1].memref.buffer, ret_arg, sizeof(ret_arg));
    params[1].memref.size = sizeof(ret_arg);

    DMSG("has been called");

    return TEE_SUCCESS;
}
ivila commented 3 weeks ago

You make two mistakes: 1)in REE: you must provide a valid pointer when using TEEC_MEMREF_TEMP_OUTPUT 2)in TEE: setting pointer value of TEE_Param.memref.buffer do not take effect, and even it take effect, REE world cannot visit the memory in TEE world. You must use TEE_MemMove to copy memory from TEE world to REE world when using TEEC_MEMREF_TEMP_OUTPUT

misagham commented 2 weeks ago

You make two mistakes: 1)in REE: you must provide a valid pointer when using TEEC_MEMREF_TEMP_OUTPUT 2)in TEE: setting pointer value of TEE_Param.memref.buffer do not take effect, and even it take effect, REE world cannot visit the memory in TEE world. You must use TEE_MemMove to copy memory from TEE world to REE world when using TEEC_MEMREF_TEMP_OUTPUT

hi ivilia thank you so much for your guidance its work for me . i have another issue what if i want to do something to the application binary build with the os ?? i made a service to run the optee application with startup but its possible to remove it from startup by third-party user and prevent the program to run . i actually want to do something nobody have access to the binary of the optee program to remove it and somehow if optee program not worked the OS boot stuck middle of process somewhere and don't continue the boot process. have you any idea that how can i do it??

ivila commented 2 weeks ago

You make two mistakes: 1)in REE: you must provide a valid pointer when using TEEC_MEMREF_TEMP_OUTPUT 2)in TEE: setting pointer value of TEE_Param.memref.buffer do not take effect, and even it take effect, REE world cannot visit the memory in TEE world. You must use TEE_MemMove to copy memory from TEE world to REE world when using TEEC_MEMREF_TEMP_OUTPUT

hi ivilia thank you so much for your guidance its work for me . i have another issue what if i want to do something to the application binary build with the os ?? i made a service to run the optee application with startup but its possible to remove it from startup by third-party user and prevent the program to run . i actually want to do something nobody have access to the binary of the optee program to remove it and somehow if optee program not worked the OS boot stuck middle of process somewhere and don't continue the boot process. have you any idea that how can i do it??

May I ask for more detail? First, what service do you mean? Do you mean a service in REE(linux) side? Second, what optee application do you mean? The TA part or the CA part?

I just assume you are saying that you wrote a Linux service, and it calls a CA program to run a TA, and somehow some third-party users can remove the CA and the TA, resulting your Linux Service failed to run, and you want to prevent this kind of thing to happen.

Actually I know little about this kind of thing, what I can tell is:

Method 1

protect your CA and TA using linux's permission control, set the owner of your binary to root, and grant only read and execute permissions to others, also, you need to forbid others to grant root permission.

Method 2

check and download the CA and TA in your service, making sure that the CA and TA are recoverable.

Method 3

compile them as firmware, for example, make your TA as PTA.

misagham commented 2 weeks ago

You make two mistakes: 1)in REE: you must provide a valid pointer when using TEEC_MEMREF_TEMP_OUTPUT 2)in TEE: setting pointer value of TEE_Param.memref.buffer do not take effect, and even it take effect, REE world cannot visit the memory in TEE world. You must use TEE_MemMove to copy memory from TEE world to REE world when using TEEC_MEMREF_TEMP_OUTPUT

hi ivilia thank you so much for your guidance its work for me . i have another issue what if i want to do something to the application binary build with the os ?? i made a service to run the optee application with startup but its possible to remove it from startup by third-party user and prevent the program to run . i actually want to do something nobody have access to the binary of the optee program to remove it and somehow if optee program not worked the OS boot stuck middle of process somewhere and don't continue the boot process. have you any idea that how can i do it??

May I ask for more detail? First, what service do you mean? Do you mean a service in REE(linux) side? Second, what optee application do you mean? The TA part or the CA part?

I just assume you are saying that you wrote a Linux service, and it calls a CA program to run a TA, and somehow some third-party users can remove the CA and the TA, resulting your Linux Service failed to run, and you want to prevent this kind of thing to happen.

Actually I know little about this kind of thing, what I can tell is:

Method 1

protect your CA and TA using linux's permission control, set the owner of your binary to root, and grant only read and execute permissions to others, also, you need to forbid others to grant root permission.

Method 2

check and download the CA and TA in your service, making sure that the CA and TA are recoverable.

Method 3

compile them as firmware, for example, make your TA as PTA.

hi ivilia yes you assumption is completely right . i have make a CA that when i run it take a parameter from system and then make a TA run on secure side and will transfer those parameter to TA to check that with stored parameter . i assume the third party user have no access to TA and that parameter and then CA make a problem and i have to protect the CA somehow to run completely reliable and nobody able to prevent processing it and if there was a problem in running of the program the whole system get down .

thanks for your advise but i gonna say i tested method 1 and 2 before but its not the solution, because in each one of them there is simple solution to remove CA app from running but about method 3 how can i compile them with firmware ?? how can i make my TA as PTA ?? do you have any documents or tutorial for that??

ivila commented 2 weeks ago

For compile TA as PTA, you may check the pta folder in optee_os.git. You can take the hwrng.c and sub.mk for example, check this commit to see how they add a pta. You can add your own PTAs and recompile the optee_os.

And out of curiosity, why method1 and method2 won't work, and you said that they can remove CA app from running, do those third-party users can easily grant root permission? If so, then none of the apps(both CA and TA) in your system can be safe, as if they have root permission, they can easily override everything on the drive, even just clear your optee-os and just reboot, and they can easily destroy everything in REE either(program, driver, module, kernel, everything if they are root).