Insights on TEE, using keymaster and libhybris
-
Hi everyone,
I've made a post a couple of months ago regarding ARM TrustZone support (can be found here.
In short: I wanted to research working with ARM TrustZone on non-Android devices, and as there seemed to be almost no documentation available I asked here.Now, after a quite some time of back-and-forth I've got some insights on the architecture and links between the different components (ARM TrustZone/Trusted Execution Engine -> Kernel -> Secure/Rich OS).
The goal of this post is two-fold:
- Share the stuff I've learned so it hopefully helps others treading the same or a similar path.
- Verify my assumptions and possibly help me answer one or two questions, which are solely regarding building a binary using the UT built libraries that Android also has (most notably the keymaster stuff).
Regarding the first point:
An Android install utilizing a Trusted Execution Environment (which is every phone nowadays) looks like the following from an OS perspective:
Quick Explanation:- The Rich OS is the userspace, here all apps reside and run.
- The Trusted Execution Environment is strictly separated from the Rich OS, only exposing API functions as provided in a TEE Client API
- The Kernel is able to communicate with both the Rich OS and TEE.
Now, my assumption regarding an Ubuntu Touch installation looked something like this:
As you can see, in this image, all components (Rich OS, Kernel and TEE) have been replaced with Ubuntu Touch variants. This led me to believe that Ubuntu Touch would have a documented TEE Client API (which was not the case).
After some more research, I realised that Ubuntu Touch is not reimplementing all the stuff Android provides in their libraries (i.e. hidl definitions, keymaster etc). Instead, it only compiles them against the Ubuntu Touch libc++.
This can easily be verified: Take any Android shared object file, locate the same file on Ubuntu Touch and from a terminal use nm:nm -D -C <.so-file>
This results in the outputting of all symbols in their respective files.
For Android, the namespace they're compiled into is std::__ndk1, which is the namespace used for bionic.
For Ubuntu Touch, the namespace is std::__1, which is the libc++ namespace.As a conclusion, after installing Ubuntu Touch the system (to my knowledge) looks like this:
.
This means that theoretically, all the Android shared objects are still there and should work as expected (given some restrictions).
At this point, I've tried cross-compiling a simple C++ binary for Ubuntu Touch. Not a problem whatsoever, as long as I don't use any of the more exotic libraries (keymaster from android/hardware/keymaster/3.0/ in my case).
This is where it all starts to get a little hairy: No matter what I do, I am unable to build a binary utilizing an android library for Ubuntu Touch.
I tried- cross-compiling
- compiling natively on the phone inside of a libertine container
- Compiling against the Android NDK and changing the namespace to match the symbols present in Ubuntu Touch libraries
None have worked so far, with only two options left:
- I have overlooked something essential, as the Ubuntu Touch platform has to have a way to compile for their own platform (or we would be using std::__ndk1 stuff still).
- Have some sort of compatibility layer (I know about Halium). In regards to this: I've found some stuff about libhybris which might be helpful, but documentation is sparse.
This is also where my questions come in: Can any of you offer insight on if libhybris could possibly solve my problem?
Any insight is very welcome, sorry for the long and detailed postThank you all in advance!
TL;DR: Trusted Execution Environment is a great thing, documentation is sparse. How do I build a native binary using .so files that Android also has, but are newly compiled for Ubuntu Touch/How do I use libhybris?