Study

OPTEE system call 실습

부산대보금자리 2021. 7. 24. 15:34

optee 내에서 client가 api를 호출하는 경우 TEEC operation을 사용한다.

이는 optee_client에 있다.

호출이 되는 순서는 다음을 따른다. 

이는 user 영역에서 kernel -> smc를 거쳐 -> tee의 함수를 실행시킨다.

  1. User application: TEEC_InvokeCommand()
    https://github.com/OP-TEE/optee_client/blob/master/libteec/src/tee_client_api.c#L555
    Here ioctl() invocation occurs (it's right in TEEC_InvokeCommand implementation)
    https://github.com/OP-TEE/optee_client/blob/master/libteec/src/tee_client_api.c#L600
  2. Linux Kernel/tee kmod: ioctl is handled by tee_ioctl handler in tee kernel module, https://github.com/linaro-swg/linux/blob/optee/drivers/tee/tee_core.c#L674
  3. Linux Kernel/tee kmod: Then we call optee_infoke_func of optee kernel module https://github.com/linaro-swg/linux/blob/optee/drivers/tee/tee_core.c#L674 (tee part),
    https://github.com/linaro-swg/linux/blob/optee/drivers/tee/optee/call.c#L323 (opteeoptee_infoke_func implementation)
  4. Linux Kernel/optee kmod: Then optee kmod: optee_infoke_func()->optee_do_call_with_arg()-> __arm_smccc_smc() (implementation of __arm_smcc_smc() you can find here https://github.com/linaro-swg/linux/blob/optee/arch/arm/kernel/smccc-call.S, which is a wrapper over SMCinstruction)
  5. Secure Monitor: handling of this SMC exception begins here https://github.com/OP-TEE/optee_os/blob/master/core/arch/arm/sm/sm_a32.S#L115
    Here we save CPU context, perform some checks, if this SMC exception came from NormalWorld etc.
  6. OP-TEE OS Core: and finally we get to tee_entry_std() https://github.com/OP-TEE/optee_os/blob/master/core/arch/arm/tee/entry_std.c#L517, which then calls entry_invoke_command()

ta부분을 보면 TEEC operation을 쓰는 경우는 안보인다. 

즉 secure world에서는 normal world에서 요청한 사항에 대해서 필요할 경우 system call을 써서 해결하고 결과를 return 해준다.

 

build 될때 결과물들은 out-br/examples~ 에 담긴다. 

excution file에는 ta쪽은 포함되지 않는다. 

ta쪽 실행파일은 ta/out에 .ta파일로 나온다. 

이 파일은 disassemble되어 나오지 않는다. 포함된 스크립트 파일로 기계어로 바꾸어 볼수만 있다.

 

- System call 만들기 

분기의 변경이 있을때 마다 system call 을 요청하여 해당 handler를 처리하고(레지스터값 해쉬연산하여 저장) 돌아갈때는 변경되는 분기로 돌아감으로써 원격 증명을 하고자 한다.

 

optee_os syscall 등록 방법, ex를 기반하여 새로 작성하였으니 참조바람

1) /optee_os/core/arch/arm/tee arch_svc.c tee_svc_syscall_table SYSCALL_ENTRY(<함수 이름>)으로 추가

ex) SYSCALL_ENTRY(syscall_mycall); (72번째라고 가정)

여기서 mycall이 아니라 mysyscall이다. 

2) /optee_os/lib/libutee/include tee_syscall_numbers.h TEE_SCN_<이름>으로 번호 등록

ex) #define TEE_SCN_MYSYSCALL 72

3) /optee_os/core/include/tee/tee_svc.h에 함수 정의

ex) TEE_Result syscall_mysyscall(int a, int b, int *sum);

4) /optee_os/core/tee/tee_svc.c에 함수 구현

ex)

TEE_Result syscall_mysyscall(int a, int b, int *sum) { // a + b

TEE_Result res;

*sum = a + b;

return res;

}

5) /optee_os/lib/libutee/include/utee_syscalls.h userland syscall 정의 (위 정의된 함수와 signature가 동일해야 함)

TEE_Result utee_mysyscall(int a, int b, int *sum);

6) /optee_os/lib/libutee/arch/arm/utee_syscalls_asm.S UTEE_SYSCALL <함수명>, <syscall 번호>, <파라미터 개수>로 등록

ex) UTEE_SYSCALL utee_mysyscall, TEE_SCN_MYSYSCALL, 3

7) /optee_os/lib/libutee/include/tee_api.h user TA에서 사용할 wrapper 함수 정의

ex) TEE_Result TEE_GetMysyscall(int result); // 당연히 내부 구현에 따라 파라미터가 위 함수와 다를 수 있음

8) /optee_os/lib/libutee/tee_api.c에 정의한 함수에 대한 wrapper 구현 (userland에서 사용할 함수)

ex)

TEE_Result TEE_GetMysyscall(int *result)

{

TEE_Result res = utee_mysyscall(1, 2, result);

return res;

}

 

9) user TA 에서 위 함수 호출하여 사용

<user TA 내에서>

int result;

TEE_GetMysyscall(&result);

//  result 3을 결과값으로 가짐.

 

- 에러

arch_svc.c는 처음에 SYSCALL_ENTRY를 넣어줬던 소스파일

이 안에 COMPILE_TIME_ASSERT라는 매크로에서 문제가 발생한다

맨 첫줄에 error의 의미는 case 1 : ~

case 1: ~ 이런식으로 중복된 case 가 있을때 생기는 에러라고 한다. 

그렇다면 내 생각에는 COMPILE_TIME_ASSERT안에서 == 연산이 0이되서 매크로안의 x에 0이들어가고

그로 인해 case((0)) 이 추가 되면서 중복된 case가 생긴 것 같다. 즉 1이되야함

그렇다면 내가 syscall을 추가함에 있어서 TEE_SCN_MAX를 수정안해줘서 생긴것 같다. 

TEE_SCN_MAX가 define된곳을 찾아야될것 같다. 

찾았다. 두번째 수정 헤더파일에 있어서 이것을 71로 고쳤다.

첫 에러는 사라지고 두번째 에러가 나왔다.

핸들러 부분인데 이걸 왜적었는지 모르겠다. 

이렇게 고친다. 

세번째 에러다.

보니까 .c 파일에는 void로 해놓고 .h에는 int로 해뒀다. 

.c로 가서 고친다. 

4번째 에러다.

이건 utee_syscalls.h에서 return type을 void로 해놓아서 _utee 가 void 가 리턴되서 생기는 오류다

이와 같이 고친다

이제 정상 동작을 한다. 

첫번째 에러 뺴고는 다 내가 실수한것이다.. 집중력이 떨어졌을때 해서 실수가 많았던것 같다. 

 

 

tee_svc.c

syscall_get_time(unsigned long cat, TEE_Time *mytime);

→ tee_time_get_sys_time()이 호출됨

 위는 optee_os/core/arch/arm/kernel/tee_time_arm_cntpct.c에서 정의된 struct time_source arm_cntpct_time_source에 의해 초기화된 arm_cnt_get_sys_time이 호출되며

 위는 다시 arch/arm/incluce/kernel time_source.h에서 REGISTER_TIME_SOURCE 가 정의되어 있는데, 이는 time_source_init()이라는 함수를 자동 생성하는 매크로.

 위 함수 내에서 time_source arm_cntpct로 만들어짐. 이 함수는 init_teecore() 함수에 의해 호출된다.

→ init_teecore() init_primary_helper에 의해 호출되고 이는 다시 generic_boot_init_primary에 의해 호출된다.

'Study' 카테고리의 다른 글

OPTEE pc레지스터 & secure storage(수정중)  (0) 2021.07.26
OPTEE Systemcall Hash연산  (0) 2021.07.25
ELF파일  (0) 2021.07.25
ARM TrustZone 메커니즘  (2) 2021.07.22
ARMv8  (0) 2021.07.22