Secure Element Access

Stars
LSPosed
GitHub
release
build
license
issues

A module to explicitly give trusted apps access to the secure element (eSE) by using a safer application ID based implementation, regardless of the ARF configuration on the eUICC. Additionally, it provides a way to toggle between eSIM and UIM modes for devices with non-removable eUICC.

Compatibility

Usage

Feature Scope
Allow privileged applications com.android.se
Grant Qualcomm RIL permissions system_server
Switch Qualcomm RIL eSIM/UIM modes com.android.phone + system_server

Switching between eSIM/UIM

On Qualcomm devices with a non-removable eUICC, an OEM hook tunnel can power cycle the eSIM slot and flip its persistent enable flag in the modem at /nv/item_files/modem/uim/uimdrv/esim_enable. This application provides a generic editor for that protocol: pick an action and a slot, adjust the payload if needed, then Send.

Action Message ID Arguments
eSIM on 86 power=1, slot, ignore_hotswap=0, esim_enable=1
eSIM off 86 power=0, slot, ignore_hotswap=0, esim_enable=0
UIM on 85 power=1, slot, ignore_hotswap=0
UIM off 85 power=0, slot, ignore_hotswap=-1

Implementation

On Android, eUICC APIs are by default restricted to whitelisted apps. This makes sense because most eUICC chips are integrated into the device. If someone wants to access the chip, say for instance to provision a profile, they generally need to do so through a Local Profile Assistant (LPA) app, which can either be

In the case of a removable eSIM (such as those from sysmocom, estk.me or esim.me), the options are limited as they do not have control over device firmware. Users also have to rely heavily on carrier support for their apps as the ARF is baked into the eUICC itself.

However, there is a caveat. Likely to facilitate Android vendor testing, full access to the eUICC can also be granted if the ROM firmware is built with a debuggable flag, i.e. ro.debuggable=1, while configured to accept all channel access requests, persist.service.seek=fullaccess. Effectively, this translates to setting mUseAra and mUseArf fields to false while granting mFullAccess in com.android.se.security.AccessControlEnforcer according to the sources.

A previous version of this module enabled eSE access for third-party apps by patching these 3 flags directly in AccessControlEnforcer. However, that approach is more of a one-size-fits-all solution that does not distinguish potentially malicious apps from legitimate ones, posing a significant risk when enabled.

Tracing the source code to see how access can be more granularly provided, I found that app eligibility eventually comes down to the isPrivilegedApplication check in com.android.se.Terminal. There is no need to touch AccessControlEnforcer at all, as that check already operates on one of the default steps intended for carrier applications.

Therefore, this module instead modifies the response from that check without any drastic changes to how AccessControlEnforcer behaves. It is also possible to be even more specific with the patching, down to the exact application signature rather than using the application ID, but that would be more cumbersome to support and maintain.

For users who are still not entirely convinced of how secure this is, you are welcome to trim the list even further and include only your own application ID in your build. Since Android by default does not allow app signatures to be overwritten during updates, you should be protected as long as your custom LPA app is signed properly 👍

Releases