impalabs space base graphics
Huawei TrustZone TA_SignTool OOB Read
This advisory contains information about the following vulnerabilities:

The SignTool TA conforms to the GlobalPlatform TEE Internal Core API. As such, it receives commands from a client application located in the normal world. These commands are handled by the TA_InvokeCommandEntryPoint function. This TA implements 16 commands, including CmdInitObjectWithKeys which contains a vulnerability.

OOB Access in CmdInitObjectWithKeys

CmdInitObjectWithKeys is used to allocate a transient object populated with a user-provided set of attributes. For example, the object could be a RSA keypair, and its attributes the modulus, public exponent and private exponent. retrieveUint32FromBuffer simply dereferences its argument, byte-swaps it and returns it.

int CmdInitObjectWithKeys(void *session, unsigned int paramTypes, TEE_Param *params) {
    // [...]
    attrInfo = (uint32_t *)params[1].memref.buffer;
    attrData = (uint8_t  *)params[2].memref.buffer;
    // [...]
    i = 0;
    do {
        attributeID = retrieveUint32FromBuffer(attrInfo);
        offset = retrieveUint32FromBuffer(attrInfo + 1);
        length = retrieveUint32FromBuffer(attrInfo + 2);
        attrInfo += 3;
        TEE_InitRefAttribute(&attrs[3 * i++], attributeID, attrData + offset, length);
    }
    while (i < attrCount);
    // [...]
    object = *(TEE_ObjectHandle *)session;
    TEE_PopulateTransientObject(object, attrs, attrCount);
    // [...]
}

For each attribute, the user needs to provide 3 dwords in the first buffer attrInfo:

  • the attributeID;
  • the offset of the attribute data in the second buffer attrData;
  • the length of the attribute data.

The issue is that the offset is unbounded, so attrData + offset can be made to point to an arbitrary location. During the later call to TEE_PopulateTransientObject, the attribute data will be copied into an object handle that is saved in the session.

Exploitation

Our Device Setup

The device we have developed an exploit for is a P40 Pro running the firmware update ELS-LGRP4-OVS_11.0.0.196. The trustlet binary MD5 checksum is as follows:

HWELS:/ # md5sum /vendor/bin/9b17660b-8968-4eed-917e-dd32379bd548.sec
f47939bd8d271f0cc8bedbd02042bb28  /vendor/bin/9b17660b-8968-4eed-917e-dd32379bd548.sec

Huawei's TEE OS iTrustee implements a whitelist mechanism that only allows specific client applications (native binaries or APKs) to talk to a trusted application.

In our case, the HuaweiNfcActiveCard TA can only be called by 4 native binaries and 2 APKs:

  • /vendor/bin/atcmdserver (uid 0);
  • system_server (uid 1000);
  • com.huawei.systemserver APK;
  • com.huawei.cryptosms.service APK;
  • /vendor/bin/hw/vendor.huawei.hardware.huaweisigntool@1.0-service (uid 1000);
  • /vendor/bin/hw/vendor.huawei.hardware.hwsecurity-service (uid 1000).

The authentication mechanism is implemented in 3 parts:
- the teecd daemon, that implements the TEE Client API, checks which native binary/APK is talking to it and sends that information to the kernel driver;
- the kernel driver ensures that it is talking to teecd, and forwards the information it received to the TEE OS;
- the TEE OS verifies that the client application is in the TA's whitelist.

Since we did not want to bother with injecting code in one of these binaries, we chose to circumvent the authentication by patching the kernel driver to add the ability to impersonate any native binary/APK.

Arbitrary Read

To achieve an arbitrary read, we first send a CmdInitObjectWithKeys command to initialize an RSA keypair object with 3 attributes: a modulus, public exponent and private exponent. By specifying an offset of addr - attrData for the modulus, it will be initialized with the data located at addr. We obtained the address of the second input buffer attrData empirically and using knowledge from past exploits, and verified that this address always stays the same.

Next we send a CmdGetPublicKey command that returns the modulus and public exponent from the object we just created. The modulus attribute data will be the data that was read from addr.

In the exploit, we demonstrate our read primitive by dumping the trustlet memory:

adb wait-for-device shell su root sh -c 0 "/data/local/tmp/ta_signtool"
ta_base_addr = 380d000
0x0380d000: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 .ELF............
0x0380d010: 03 00 28 00 01 00 00 00 cc 10 00 00 34 00 00 00 ..(.........4...
0x0380d020: 88 69 00 00 00 02 00 05 34 00 20 00 05 00 28 00 .i......4. ...(.
0x0380d030: 11 00 10 00 01 00 00 00 00 00 00 00 00 00 00 00 ................

Affected Devices

We have verified that the vulnerability impacted the following device(s):

  • Kirin 990: P40 Pro (ELS)

Please note that other models might have been affected.

Patch

Name Severity CVE Patch
OOB Access in CmdInitObjectWithKeys Critical CVE-2021-40020 January 2022

Timeline

  • Oct. 08, 2021 - A vulnerability report is sent to Huawei PSIRT.
  • Nov. 16, 2021 - Huawei PSIRT acknowledges the vulnerability report.
  • Jan. 01, 2022 - Huawei PSIRT states that these issues were fixed in the January 2022 update.
  • From Nov. 30, 2022 to Jul, 19 2023 - We exchange regularly about the release of our advisories.