This is the second part of a blog series covering my security research into Samsung’s TrustZone.
This post is a companion to my talk from Ekoparty 2017, namely the reverse engineering process of T-base. The slides and video of the talk are both available online.
In fact, since both of those are available, for this part of the series I didn’t quite write a “storytelling” blog post. Instead, this post only does what the slide/video format does not accomplish: a more accessible enumeration of the most important results (code snippets, declarations of reversed functions/structures). So it’s more like a wiki then a blog post.
To extract all the T-base firmware parts that are embedded in the Sboot image (microkernel, Run Time Manager, tlLibrary, Crypto Driver, etc), find the extract table by the string marker “t-base”:
ROM:00147000 tbase_extract_table DCB "t-base ",0 ; descriptor struct:
ROM:00147000 ; char name[8]
ROM:00147000 ; int offset
ROM:00147000 ; int size
ROM:00147000 ; char padding[0x10]
ROM:00147000 ;
ROM:00147000 ; real start offset: 0x132000
ROM:00147000 ;
ROM:00147000 ; Mtk: 0->0x147000 -> the Microkernel image itself -> go back 0x15000 from "t-base"
ROM:00147000 ; Image_h: 0x147000 -> 0x148000 -> so that's this
ROM:00147000 ; Rtm: 0x148000 -> RTM is the Run-Time Manager (aka S0CB)
ROM:00147000 ;
ROM:00147000 ; drcrypt: 0x167000 -> MCLF file (Crypto Driver)
ROM:00147000 ; tlproxy: 0x17A000 -> MCLF file (SFS Trustlet)
ROM:00147000 ; sth2: 0x17B000 -> MCLF file (SFS Driver)
ROM:00147000 ; mclib: 0x183000 -> tlLib (runtime library for Trustlets and Drivers)
ROM:00147008 DCD 0
ROM:0014700C DCD 0x5D000
ROM:00147010 ALIGN 0x20
ROM:00147020 aMtk DCB "mtk ",0
ROM:00147028 DCD 0
ROM:0014702C DCD 0x15000
ROM:00147030 ALIGN 0x20
ROM:00147040 aImage_h DCB "image_h",0
ROM:00147048 DCD 0x15000
ROM:0014704C DCD unk_1000
ROM:00147050 ALIGN 0x20
ROM:00147060 aRtm DCB "rtm ",0
ROM:00147068 DCD 0x16000
ROM:0014706C DCD 0x1F000
ROM:00147070 ALIGN 0x20
ROM:00147080 aDrcrypt DCB "drcrypt",0
ROM:00147088 DCD 0x35000
ROM:0014708C DCD 0x13000
ROM:00147090 ALIGN 0x20
ROM:001470A0 aTlproxy DCB "tlproxy",0
ROM:001470A8 DCD 0x48000
ROM:001470AC DCD 0x1000
ROM:001470B0 DCD 0
ROM:001470B4 DCD 0
ROM:001470B8 DCD 0
ROM:001470BC DCD 0
ROM:001470C0 aSth2 DCB "sth2 ",0
ROM:001470C8 DCD 0x49000
ROM:001470CC DCD unk_8000
ROM:001470D0 ALIGN 0x20
ROM:001470E0 aMclib DCB "mclib ",0
ROM:001470E8 DCD 0x51000
ROM:001470EC DCD unk_C000
ROM:001470F0 ALIGN 0x1000
ROM:00148000 S0CB_HDR DCB "S0CB",0 ; Rtm offset points here
ROM:00148005 DCB 0x10, 0, 0
ROM:00148008 DCD unk_C000
ROM:0014800C DCD dword_D000
ROM:00148010 DCD 0
ROM:00148014 DCD 0x11960
ROM:00148018 DCD 0xB295
ROM:0014801C DCD 0x3F
ROM:00148020 DCD 0x6A
ROM:00148024 aMccb DCB "MCCB",0
ROM:00148029 DCD 0
ROM:0014802D DCD 0
I have identified the following T-base → ATF invocable SMCs:
ROM:00133054 tbase_smc_send_VBAR ; CODE XREF: config_tbase_and_tell_aft_the_vbar+E↑p
ROM:00133054 LDR R0, =0xB2000002
ROM:00133058 MOV R1, #1
ROM:0013305C LDR R2, =0x7F00000 ; normal VBAR address
ROM:00133060 SMC #0
ROM:00133064 BX LR
ROM:00133064 ; End of function tbase_smc_send_VBAR
ROM:00133064
ROM:00133068
ROM:00133068 ; =============== S U B R O U T I N E =======================================
ROM:00133068
ROM:00133068 ; Attributes: noreturn
ROM:00133068
ROM:00133068 tbase_smc_fastcall_status_then_ret_to_nonSW
ROM:00133068 ; CODE XREF: sub_1343AA:loc_1354C8↓p
ROM:00133068 ; translate_MSMBase_to_VA+46↓p
ROM:00133068 LDR R0, =0xB2000004
ROM:0013306C MOV R1, #1
ROM:00133070 MOV R2, #1
ROM:00133074 SMC #0
ROM:00133078 LDR R0, =0x2000001
ROM:0013307C SMC #0
ROM:00133080
ROM:00133080 loc_133080 ; CODE XREF: tbase_smc_fastcall_status_then_ret_to_nonSW:loc_133080↓j
ROM:00133080 B loc_133080
ROM:00133080 ; End of function tbase_smc_fastcall_status_then_ret_to_nonSW
ROM:00133080
ROM:00133084
ROM:00133084 ; =============== S U B R O U T I N E =======================================
ROM:00133084
ROM:00133084
ROM:00133084 tbase_smc_fastcall_status ; CODE XREF: sub_1343AA+31C6↓p
ROM:00133084 LDR R0, =0xB2000004
ROM:00133088 MOV R1, #1
ROM:0013308C MOV R2, #3
ROM:00133090 SMC #0
ROM:00133094 BX LR
ROM:00133094 ; End of function tbase_smc_fastcall_status
ROM:00133094
ROM:00133098
ROM:00133098 ; =============== S U B R O U T I N E =======================================
ROM:00133098
ROM:00133098
ROM:00133098 tbase_smc_fastcall_print
ROM:00133098 MOV R2, R0
ROM:0013309C LDR R0, =0xB2000003
ROM:001330A0 MOV R1, #1
ROM:001330A4 SMC #0
ROM:001330A8 BX LR
ROM:001330A8 ; End of function tbase_smc_fastcall_print
.tbase_mem_data:07F0D86C ; ===========================================================================
.tbase_mem_data:07F0D86C
.tbase_mem_data:07F0D86C ; Segment type: Pure data
.tbase_mem_data:07F0D86C AREA .tbase_mem_data, DATA, ALIGN=0
.tbase_mem_data:07F0D86C ; ORG 0x7F0D86C
.tbase_mem_data:07F0D86C syscall_table DCD svc_0_nop+1 ; DATA XREF: invoke_syscall_from_table+40↑o
.tbase_mem_data:07F0D86C ; invoke_syscall_from_table:syscall_table_ptr↑o
.tbase_mem_data:07F0D870 DCD svc_1_init_process+1
.tbase_mem_data:07F0D874 DCD svc_2_nop+1
.tbase_mem_data:07F0D878 DCD svc_3_nop+1
.tbase_mem_data:07F0D87C DCD svc_4+1 ; Did not find this invoked anywhere in {RTM,tlLib}
.tbase_mem_data:07F0D880 DCD svc_5_start_process+1
.tbase_mem_data:07F0D884 DCD svc_exit+1
.tbase_mem_data:07F0D888 DCD svc_mmap+1
.tbase_mem_data:07F0D88C DCD svc_8_munmap+1
.tbase_mem_data:07F0D890 DCD svc_9_start_thread+1
.tbase_mem_data:07F0D894 DCD svc_A_stop_thread+1
.tbase_mem_data:07F0D898 DCD svc_B_return_0xD+1
.tbase_mem_data:07F0D89C DCD svc_C_modify_thread_registers+1
.tbase_mem_data:07F0D8A0 DCD svc_D_mprotect+1
.tbase_mem_data:07F0D8A4 DCD svc_E_resume_thread+1
.tbase_mem_data:07F0D8A8 DCD svc_F+1
.tbase_mem_data:07F0D8AC DCD svc_10_set_thread_prio+1
.tbase_mem_data:07F0D8B0 DCD svc_11_ipc+1
.tbase_mem_data:07F0D8B4 DCD svc_12_int_attach+1
.tbase_mem_data:07F0D8B8 DCD svc_13_int_detach+1
.tbase_mem_data:07F0D8BC DCD svc_14_sigwait+1
.tbase_mem_data:07F0D8C0 DCD svc_15_signal+1
.tbase_mem_data:07F0D8C4 DCD svc_16+1 ; Did not find this invoked anywhere in {RTM,tlLib}
.tbase_mem_data:07F0D8C8 DCD svc_tbase_smc_fastcall_input+1
.tbase_mem_data:07F0D8CC DCD svc_18_log_char+1
.tbase_mem_data:07F0D8D0 DCD svc_19_get_secure_timestamp+1
.tbase_mem_data:07F0D8D4 DCD svc_1A_control+1 ; includes a lot, such as:
.tbase_mem_data:07F0D8D4 ; - driver shmem map/unmap
.tbase_mem_data:07F0D8D4 ; - get/set exception info
.tbase_mem_data:07F0D8D4 ; - get MCP queue info
.tbase_mem_data:07F0D8D4 ; - get IPCH phys address values
.tbase_mem_data:07F0D8D4 ; - cache control
.tbase_mem_data:07F0D8D4 ; - virt2phys, phys2virt translation
.tbase_mem_data:07F0D8D4 ; - set custom fastcall, call custom fastcall
.tbase_mem_data:07F0D8D4 ;
.tbase_mem_data:07F0D8D4 ; Known sub-handlers:
.tbase_mem_data:07F0D8D4 ;
.tbase_mem_data:07F0D8D4 ; -0x8F: getting/setting fastcall configuration values
.tbase_mem_data:07F0D8D4 ; - 0xC: get S0CB PA
.tbase_mem_data:07F0D8D4 ; - 0xA: notify (nSW - trigger interrupt)
.tbase_mem_data:07F0D8D4 ; - 0xB: notify driver (drTriggerIntr)
.tbase_mem_data:07F0D8D4 ; - 0xD: get fc_init perm flags
.tbase_mem_data:07F0D8D4 ; - 0x1: set exception info
.tbase_mem_data:07F0D8D4 ; - 0x2: get fault info
.tbase_mem_data:07F0D8D4 ; - 0x4,0x5,0x6,0x7: get MCP queue info
.tbase_mem_data:07F0D8D4 ; (mci_buffer_addr, nq_length, mcp_queue_addr, mcp_queue_len)
.tbase_mem_data:07F0D8D4 ; - 0x9: map mcp cmd queue (in kernel)
.tbase_mem_data:07F0D8D4 ; -0x90 -> more control
.tbase_mem_data:07F0D8D4 ; - 5: read info for exception
.tbase_mem_data:07F0D8D4 ; - 7: translate VA to PA
.tbase_mem_data:07F0D8D4 ; -0x91 virt-to-phys and also virt-to-phys64
.tbase_mem_data:07F0D8D4 ; -0x92 -> I-cache clean/invalidate, D-cache clean/invalidate
.tbase_mem_data:07F0D8D4 ; -0x81:map, 0x83: unmap, 0x85:map.
.tbase_mem_data:07F0D8D4 ; - Difference in 81/85: map into TA/driver or map into RTM
.tbase_mem_data:07F0D8D4 ; -0x94 -> set custom fastcall handler
.tbase_mem_data:07F0D8D4 ; -0x95 -> SMC fastcall 5 (unk)
.tbase_mem_data:07F0D8D4 ; -0x96 -> getPhysMemType
.tbase_mem_data:07F0D8D4 ; -0x98 -> exec f
Note: The talk calls RTM “S0CB”, based on the magic value of its fileformat. Using the hint from the Sboot firmware, the probably more accurate name I now use for it instead is RTM (“Run Time Manager”).
This is a uniquely powerful user-space process in T-base, always started first, and tasked with starting and managing all other processes (trustlets). So similar to init on Linux. It servers three functions:
The MCP commands were known from public sources. For IPC, the first 12 IPC command definitions can be found in source code here! I used the naming convention seen here for the rest that I was able to associate functionality with:
/** Possible message types/event types of the system. */
typedef enum {
MSG_NULL = 0, // Used for initializing state machines
/***************/
MSG_RQ = 1, /**< Request; client -> server; */
MSG_RS = 2, /**< Response; server -> client */
MSG_RD = 3, /**< Ready; server -> IPCH */
MSG_NOT = 4, /**< Notification; client -> IPCH; */
MSG_CLOSE_TRUSTLET = 5, /**< Close Trustlet; MSH -> IPCH; IPCH -> all servers */
MSG_CLOSE_TRUSTLET_ACK = 6, /**< Close Trustlet Ack; servers -> IPCH */
MSG_MAP = 7, /**< Map; driver <-> IPCH; */
MSG_ERR_NOT = 8, /**< Error Notification; EXCH/SIQH -> IPCH; */
MSG_CLOSE_DRIVER = 9, /**< Close driver; MSH -> IPCH; IPCH -> driver */
MSG_CLOSE_DRIVER_ACK = 10, /**< Close driver Ack; driver -> IPCH; IPCH -> MSH */
MSG_GET_DRIVER_VERSION = 11, /**< GetDriverVersion; client <--> IPCH */
MSG_GET_DRAPI_VERSION = 12, /**< GetDrApiVersion; driver <--> IPCH */
MSG_SET_NOTIFICATION_HANDLER = 13, // Driver <-> IPCH
MSG_DRV_NOT = 15, // Driver -> Trustlet
MSG_SET_FASTCALL_HANDLER = 16, // Driver <-> IPCH
MSG_GET_CLIENT_ROOT_AND_SP_ID = 17, // Driver <-> IPCH
MSG_CALL_FASTCALL = 25, // DRIVER -> IPCH -> Kernel
MSG_GET_CLI_UUID = 26, // Driver <-> IPCH
MSG_RQ_2 = 27, // Client -> Server
MSG_MAP_VA_DIRECT = 31, // DRIVER <-> IPCH
MSG_MAP_PY_DIRECT = 32, // DRIVER <-> IPCH
MSG_UNMAP_PY_DIRECT = 33, // DRIVER <-> IPCH
MSG_GET_MEM_TYPE = 34, // DRIVER <-> IPCH
MSG_UNMAP_VA_DIRECT = 35 // DRIVER <-> IPCH
} message_t;
ROM:07D0BE38 tlApi_syscall_table DCD tlApiNOP+1 ; 0
ROM:07D0BE38 DCD tlApiGetVersion+1 ; 1
ROM:07D0BE38 DCD tlApiGetMobicoreVersion+1; 2
ROM:07D0BE38 DCD tlApiGetPlatformInfo+1; 3
ROM:07D0BE38 DCD tlApiExit+1 ; 4
ROM:07D0BE38 DCD tlApiLogvPrintf+1 ; 5
ROM:07D0BE38 DCD tlApiWaitNotification+1; 6
ROM:07D0BE38 DCD tlApiNotify+1 ; 7
ROM:07D0BE38 DCD tlApi_callDriver+1 ; 8
ROM:07D0BE38 DCD tlApiWrapObjectExt+1; 9
ROM:07D0BE38 DCD tlApiUnwrapObjectExt+1; 10
ROM:07D0BE38 DCD tlApiGetSuid+1 ; 11
ROM:07D0BE38 DCD tlApiSecSPICmd+1 ; 12
ROM:07D0BE38 DCD tlApiCrAbort+1 ; 13
ROM:07D0BE38 DCD tlApiRandomGenerateData+1; 14
ROM:07D0BE38 DCD tlApiGenerateKeyPair+1; 15
ROM:07D0BE38 DCD tlApiCipherInitWithData+1; 16
ROM:07D0BE38 DCD tlApiCipherUpdate+1 ; 17
ROM:07D0BE38 DCD tlApiCipherDoFinal+1; 18
ROM:07D0BE38 DCD tlApiSignatureInitWithData+1; 19
ROM:07D0BE38 DCD tlApiSignatureUpdate+1; 20
ROM:07D0BE38 DCD tlApiSignatureSign+1; 21
ROM:07D0BE38 DCD tlApiSignatureVerify+1; 22
ROM:07D0BE38 DCD tpiApiMessageDigestInitWithData+1; 23
ROM:07D0BE38 DCD tlApiMessageDigestUpdate+1; 24
ROM:07D0BE38 DCD tlApiMessageDigestDoFinal+1; 25
ROM:07D0BE38 DCD tlApiGetVirtMemType+1; 26
ROM:07D0BE38 DCD tlApiDeriveKey+1 ; 27
ROM:07D0BE38 DCD tlApiMalloc+1 ; 28
ROM:07D0BE38 DCD tlApiRealloc+1 ; 29
ROM:07D0BE38 DCD tlApiFree+1 ; 30
(...)
ROM:07D0BE38 DCD tlApiGetIDs+1 ; 43
(...)
ROM:07D0BE38 DCD tlApiRandomGenerateData_wrap+1; 83
ROM:07D0BE38 DCD tlApiCrash+1 ; 84
ROM:07D0BE38 DCD tlApiEndorse+1 ; 85
ROM:07D0BE38 DCD tlApiTuiGetScreenInfo+1; 86
ROM:07D0BE38 DCD tlApiTuiOpenSession+1; 87
ROM:07D0BE38 DCD tlApiTuiCloseSession+1; 88
ROM:07D0BE38 DCD tlApiTuiSetImage+1 ; 89
ROM:07D0BE38 DCD tlApiTuiGetTouchEvent+1; 90
ROM:07D0BE38 DCD tlApiTuiGetTouchEventsLoop+1; 91
ROM:07D0BE38 DCD tlApiDrmProcessContent+1; 92
ROM:07D0BE38 DCD tlApiDrmOpenSession+1; 93
ROM:07D0BE38 DCD tlApiDrmCloseSession+1; 94
ROM:07D0BE38 DCD tlApiDrmCheckLink+1 ; 95
ROM:07D0BE38 DCD tlApiDeriveKey_wrapper+1; 96
ROM:07D0BE38 DCD tlApiUnwrapObjectExt_wrapper+1; 97
ROM:07D0BE38 DCD tlApiGetSecureTimestamp+1; 98
ROM:07D0C114 ; int drApi_syscall_table[62]
ROM:07D0C114 drApi_syscall_table DCD drApiGetVersion+1 ; 0
ROM:07D0C114 ; DATA XREF: get_syscall_fn+30↑o
ROM:07D0C114 ; ROM:off_7D0A9F8↑o
ROM:07D0C114 DCD drApiExit+1 ; 1
ROM:07D0C114 DCD drApiMapPhys+1 ; 2
ROM:07D0C114 DCD drApiUnmap+1 ; 3
ROM:07D0C114 DCD drApiMapPhysPage4KBWithHardware+1; 4
ROM:07D0C114 DCD drApiMapClient+1 ; 5
ROM:07D0C114 DCD drApiMapClientAndParams+1; 6
ROM:07D0C114 DCD drApiAddrTranslateAndCheck+1; 7
ROM:07D0C114 DCD drApiGetTaskid+1 ; 8
ROM:07D0C114 DCD drApiTaskidGetThreadid+1; 9
ROM:07D0C114 DCD drApiGetLocalThreadId+1; 10
ROM:07D0C114 DCD drApiStartThread+1 ; 11
ROM:07D0C114 DCD drApiStopThread+1 ; 12
ROM:07D0C114 DCD drApiResumeThread+1 ; 13
ROM:07D0C114 DCD drApiThreadSleep+1 ; 14
ROM:07D0C114 DCD drApiSetThreadPriority+1; 15
ROM:07D0C114 DCD drApiIntrAttach+1 ; 16
ROM:07D0C114 DCD drApiIntrDetach+1 ; 17
ROM:07D0C114 DCD drApiWaitForIntr+1 ; 18
ROM:07D0C114 DCD drApiTriggerIntr+1 ; 19
ROM:07D0C114 DCD drApiIpcWaitForMessage+1; 20
ROM:07D0C114 DCD drApiIpcCallToIPCH+1; 21
ROM:07D0C114 DCD drApiIpcSignal+1 ; 22
ROM:07D0C114 DCD drApiIpcSigWait+1 ; 23
ROM:07D0C114 DCD drApiNotify+1 ; 24
ROM:07D0C114 DCD drApiSystemCtrl+1 ; 25
ROM:07D0C114 DCD sub_7D0A2CE+1 ; 26
ROM:07D0C114 DCD drApiVirt2Phys+1 ; 27
ROM:07D0C114 DCD drApiCacheDataClean+1; 28
ROM:07D0C114 DCD drApiCacheDataCleanAndInvalidate+1; 29
ROM:07D0C114 DCD drApiNotifyClient+1 ; 30
ROM:07D0C114 DCD drApiThreadExRegs+1 ; 31
ROM:07D0C114 DCD drApiInstallFc+1 ; 32
ROM:07D0C114 DCD drApiIpcUnknownMessage+1; 33
ROM:07D0C114 DCD drApiIpcUnknownException+1; 34
ROM:07D0C114 DCD drApiGetPhysMemType+1; 35
ROM:07D0C114 DCD drApiGetClientRootAndSpId+1; 36
ROM:07D0C114 DCD drApiCacheDataCleanRange+1; 37
ROM:07D0C114 DCD drApiCacheDataCleanAndInvalidateRange+1; 38
ROM:07D0C114 DCD drApiMapPhys64+1 ; 39
ROM:07D0C114 DCD drApiMapPhys64_2+1 ; 40
ROM:07D0C114 DCD drApiVirt2Phys64+1 ; 41
ROM:07D0C114 DCD drApiGetPhysMemType64+1; 42
ROM:07D0C114 DCD drApiUpdateNotificationThread+1; 43
ROM:07D0C114 DCD drApiRestartThread+1; 44
ROM:07D0C114 DCD drApiGetSecureTimestamp+1; 45
ROM:07D0C114 DCD drApiFastCall+1 ; 46
ROM:07D0C114 DCD drApiGetClientUuid+1; 47
ROM:07D0C114 DCD sub_7D0A2AC+1 ; 48
ROM:07D0C114 DCD drApiMapVirtBuf+1 ; 49
ROM:07D0C114 DCD drApiUnmapPhys2+1 ; 50
ROM:07D0C114 DCD drApiMapPhys2+1 ; 51
ROM:07D0C114 DCD drApiUnmapVirtBuf2+1; 52
ROM:07D0C114 DCD sub_7D07D76+1 ; 53
ROM:07D0C114 DCD sub_7D0A558+1 ; 54
ROM:07D0C114 DCD sub_7D0A574+1 ; 55
ROM:07D0C114 DCD sub_7D0A5D6+1 ; 56
ROM:07D0C114 DCD sub_7D0A738+1 ; 57
ROM:07D0C114 DCD sub_7D0A1BA+1 ; 58
ROM:07D0C114 DCD sub_7D0A1C8+1 ; 59
ROM:07D0C114 DCD sub_7D0A5F4+1 ; 60
ROM:07D0C114 DCD sub_7D0A60C+1 ; 61
Sandboxing Mechanisms