New issue
Advanced search Search tips
Starred by 2 users
Status: WontFix
Owner:
Closed: Jul 20
Cc:



Sign in to add a comment
Samsung: Trustonic <t-base TEE does not perform revocation of trustlets
Project Member Reported by laginimaineb@google.com, Apr 21 2017 Back to list
Trustonic's Trusted Execution Environment (TEE) OS is able to load Trusted Applications (TAs) into the <t-base TEE. The TAs are signed, and their signature is verified during the loading process. The public key (modulus and public exponent) is appended to the end of the TA, and the hash of the public key is verified against a hash embedded in the TEE OS's binary.

 --------------------------------------------------------------------------------------------------------------------
 | MCLF Header | Data | Text | Modulus Length | Modulus | Public Exponent Length | Public Exponent | Signature Blob |
 --------------------------------------------------------------------------------------------------------------------
 |                           |                                                                     |                
 |                           ^---------------SHA256 checked against TEE-embedded hash--------------^                
 |                                                                                                 |                 
 |                                                                                                 |                 
 ^---------------------------------------------Signed----------------------------------------------^
 
However, since vulnerabilities may be found in the TAs themselves (https://bugs.chromium.org/p/project-zero/issues/detail?id=938, https://bugs.chromium.org/p/project-zero/issues/detail?id=939), the TEE OS must also revoke old TAs in order to prevent attackers in the Non-Secure World from intentionally loading an old vulnerable trustlet and exploiting it to gain code-execution within the TEE.

<t-base as used on Samsung devices, including the Galaxy S7 Edge (SM-G935F), seems to allow old trustlets to be loaded freely.

In order to load a TA into the TEE from the Non-Secure World, an attacker can use any of the following techniques:

1. Use the MobiCore Driver directly
-----------------------------------

The communication with the TEE OS (including the trustlet load request) is performed by the MobiCore driver. The driver can be communicated with using the "/dev/mobicore-user" device, which has an SELinux context of "mobicore-user_device". On the SM-G935F XXS1APG3, the SELinux policy allows the following contexts to access the device:

   allow trustonic_tee_proxy mobicore-user_device : chr_file { ioctl read write getattr lock append open } ; 
   allow platformappdomain mobicore-user_device : chr_file { ioctl read write getattr lock append open } ; 
   allow secure_storage mobicore-user_device : chr_file { ioctl read write getattr lock append open } ; 
   allow tlc_server mobicore-user_device : chr_file { ioctl read write getattr lock append open } ; 
   allow fingerprintd mobicore-user_device : chr_file { ioctl read write getattr lock append open } ; 
   allow system_app mobicore-user_device : chr_file { ioctl read write getattr lock append open } ; 
   allow ipm mobicore-user_device : chr_file { ioctl read write getattr lock append open } ; 
   allow vcsFPService mobicore-user_device : chr_file { ioctl read write getattr lock append open } ; 
   allow trustonicpartner_app mobicore-user_device : chr_file { ioctl read write getattr lock append open } ; 
   allow cs mobicore-user_device : chr_file { ioctl read write getattr lock append open } ; 
   allow actlmand mobicore-user_device : chr_file { ioctl read write getattr lock append open } ; 
   allow radio mobicore-user_device : chr_file { ioctl read write getattr lock append open } ; 
   allow irisd mobicore-user_device : chr_file { ioctl read write getattr lock append open } ; 
   allow daemon_app_process mobicore-user_device : chr_file write ; 
   allow otp_server mobicore-user_device : chr_file { ioctl read write getattr lock append open } ; 
   allow surfaceflinger mobicore-user_device : chr_file { ioctl read write getattr lock append open } ; 
   allow secprov_nexti mobicore-user_device : chr_file { ioctl read write getattr lock append open } ; 
   allow at_distributor mobicore-user_device : chr_file { ioctl read write getattr lock append open } ; 
   allow vold mobicore-user_device : chr_file { ioctl read write getattr lock append open } ; 
   allow drmserver mobicore-user_device : chr_file { ioctl read write getattr lock append open } ; 
   allow tsdaemon mobicore-user_device : chr_file { ioctl read write getattr lock append open } ; 
   allow good_app mobicore-user_device : chr_file { ioctl read write getattr lock append open } ; 
   allow sem mobicore-user_device : chr_file { ioctl read write open } ; 
   allow keystore mobicore-user_device : chr_file { ioctl read write getattr lock append open } ; 
   allow system_server mobicore-user_device : chr_file { ioctl read write getattr lock append open } ; 
   allow mobicoredaemon mobicore-user_device : chr_file { ioctl read write getattr lock append open } ; 
   allow sdp_cryptod mobicore-user_device : chr_file { ioctl read write getattr lock append open } ; 
   allow gatekeeperd mobicore-user_device : chr_file { ioctl read write getattr lock append open } ; 
   allow mediaserver mobicore-user_device : chr_file { ioctl read write getattr lock append open } ; 
   allow dtvserver mobicore-user_device : chr_file { ioctl read write getattr lock append open } ; 
   allow bauthserver mobicore-user_device : chr_file { ioctl read write getattr lock append open } ; 
   allow cbd mobicore-user_device : chr_file { ioctl read write getattr lock append open } ; 

2. Use the MobiCore Driver Daemon
---------------------------------

The "mcDriverDaemon" process is a daemon that allows clients to issue requests to the TEE (which are then routed to the driver), including loading new trustlets. The daemon may load trustlets either from the system partition ("/system/app/mcRegistry"), or from the data partition ("/data/app/mcRegistry"). Therefore, attackers are able to load trustlets into the TEE by placing a trustlet binary in the data partition (under the directory above) and sending a load request to the daemon.

While the load request itself specifies the UUID of the trustlet to be loaded, the daemon only uses the UUID to locate the binary, and doesn't ensure that it matches the UUID encoded in the trustlet's header. Therefore, it is possible to load any trustlet (regardless of UUID) by placing a binary with an arbitrary UUID (e.g., 07050501000000000000000000000020.tlbin) in the data partition's registry directory, and subsequently sending a load request with the same UUID to mcDriverDaemon.

The communication with the daemon is done via a UNIX domain socket. The daemon has an SELinux context of "mobicoredaemon". On the SM-G935F XXS1APG3, the SELinux policy allows the following contexts to access the daemon:

   allow gatekeeperd mobicoredaemon : unix_stream_socket connectto ; 
   allow drmserver mobicoredaemon : unix_stream_socket connectto ; 
   allow mobicoredaemon init : unix_stream_socket connectto ; 
   allow otp_server mobicoredaemon : unix_stream_socket connectto ; 
   allow tlc_server mobicoredaemon : unix_stream_socket connectto ; 
   allow trustonic_tee_proxy mobicoredaemon : unix_stream_socket connectto ; 
   allow bauthserver mobicoredaemon : unix_stream_socket connectto ; 
   allow secprov_nexti mobicoredaemon : unix_stream_socket connectto ; 
   allow vold mobicoredaemon : unix_stream_socket connectto ; 
   allow system_server mobicoredaemon : unix_stream_socket connectto ; 
   allow cs mobicoredaemon : unix_stream_socket connectto ; 
   allow secure_storage mobicoredaemon : unix_stream_socket connectto ; 
   allow fingerprintd mobicoredaemon : unix_stream_socket connectto ; 
   allow ipm mobicoredaemon : unix_stream_socket connectto ; 
   allow platformappdomain mobicoredaemon : unix_stream_socket connectto ; 
   allow good_app mobicoredaemon : unix_stream_socket connectto ; 
   allow system_app mobicoredaemon : unix_stream_socket connectto ; 
   allow sem mobicoredaemon : unix_stream_socket connectto ; 
   allow keystore mobicoredaemon : unix_stream_socket connectto ; 
   allow surfaceflinger mobicoredaemon : unix_stream_socket connectto ; 
   allow at_distributor mobicoredaemon : unix_stream_socket connectto ; 
   allow vcsFPService mobicoredaemon : unix_stream_socket connectto ; 
   allow tsdaemon mobicoredaemon : unix_stream_socket connectto ; 
   allow cbd mobicoredaemon : unix_stream_socket connectto ; 
   allow mobicoredaemon mobicoredaemon : unix_stream_socket { ioctl read write create getattr setattr lock relabelfrom relabelto append bind connect listen accept getopt setopt shutdown recvfrom sendto recv_msg send_msg name_bind connectto newconn acceptfrom } ; 
   allow sdp_cryptod mobicoredaemon : unix_stream_socket connectto ; 
   allow radio mobicoredaemon : unix_stream_socket connectto ; 
   allow dtvserver mobicoredaemon : unix_stream_socket connectto ; 
   allow mediaserver mobicoredaemon : unix_stream_socket connectto ; 
   allow trustonicpartner_app mobicoredaemon : unix_stream_socket connectto ; 

----

It's not clear whether or not the TEE OS can utilise an RPMB block to revoke trustlets. Looking at the trustlets' header format, there appears to be a single "serviceVersion" field (https://android.googlesource.com/platform/hardware/samsung_slsi/exynos5/+/jb-mr1-dev/mobicore/common/MobiCore/inc/mcLoadFormat.h#137). I've written a python script (get_service_versions.py) which extracts and lists the version field for each TA under a given directory tree. Running it on my own repository of firmware images (multiple devices and firmware versions) shows that all TAs across different devices and versions have the same version field. I've included the output of this script under "service_versions.txt".

I've written another script to extract the modulus from each trustlet binary, and group together different firmware versions/devices that share the same signing key (extract_mclf_pubkeys.py). After running this script it appears that both the Galaxy S7 Edge (G935F) and the Galaxy S7 (G930F) use the same signing key. While this is not necessarily an issue in and of itself, it means that attackers can load TAs from either device into the other (therefore expanding the list of possible vulnerable TAs that can be leveraged to attack the TEE).

----

I'm attaching a PoC which demonstrates this issue.

The PoC takes an old trustlet from a previous version (XXU1APC8) of the G935F and writes it to "/data/app/mcRegistry/07050501000000000000000000000020.tlbin". Then, it connects to mcDriverDaemon and sends a load request for the same crafted UUID. This causes the daemon to load our TA from the data registry into the TEE.

I've included three TA binaries under the "binaries" directory:
  -ffffffff00000000000000000000002e.tlbin_CURRENT_VERSION - The current version of the TA
  -ffffffff00000000000000000000002e.tlbin_FROM_G930F      - The same TA taken from the G930F
  -ffffffff00000000000000000000002e.tlbin_OLD_VERSION     - An old version of the TA, taken from version XXU1APC8

All three TAs can be loaded successfully on the SM-G935F, version XXS1APG3.

The PoC can be built by following these steps:
  1. Embed the old TA binary into a header file by running:
         python binary_to_header.py binaries/ffffffff00000000000000000000002e.tlbin_OLD_VERSION ta.h TA_DATA
  2. Compile the PoC into a shellcode by running "./build.sh"

Note that the resulting shellcode binary needs to run under system_server (e.g., by using https://bugs.chromium.org/p/project-zero/issues/detail?id=928).

After running the PoC, the logcat output should include the following lines:

BitUnmap: open() called
BitUnmap: Opening MobiCore device
BitUnmap: Allocating WSM for TCI
BitUnmap: Opening the session
BitUnmap: tlc_open() succeeded
BitUnmap: tlc_open: 0

After the TA is loaded, the following line will be written to dmesg:
 "Trustonic TEE: d01|Trustlet FingerPrint::Starting"

This bug is subject to a 90 day disclosure deadline. If 90 days elapse
without a broadly available patch, then the bug report will automatically
become visible to the public.
 
 
service_versions.txt
31.8 KB View Download
get_service_versions.py
1.1 KB View Download
extract_mclf_pubkeys.py
1.6 KB View Download
MobiCoreRevocation.tar.gz
408 KB Download
Project Member Comment 1 by laginimaineb@google.com, Jul 12
Samsung has provided the following update: "Latest Trustonic kinibi 400 family now supports rollback prevention feature for trustlets and this is fully supported since Galaxy S8/S8+ devices".
Project Member Comment 2 by laginimaineb@google.com, Jul 14
Attaching exploit for OTP trustlet, allowing TEE code-execution.
KinibiOTP.tar.gz
6.8 KB Download
Project Member Comment 3 by laginimaineb@google.com, Jul 20
Labels: -Restrict-View-Commit Deadline-Exceeded
Status: WontFix
Deadline exceeded -- automatically derestricting.
Do you know if the TAs can be loaded in Samsung Knox devices? Is there any proteccion or prevention that can be taken? Many thanks.
Sign in to add a comment