impalabs space base graphics
Huawei TrustZone TA_uDFingerPrint Vulnerabilities
This advisory contains information about the following vulnerabilities:

Param Buffer Overflow in TA_fp_tee_get_indices

There is a buffer overflow on a TEE_Param buffer in the command TA_fp_tee_get_indices (ID #0x11).

TA_fp_tee_get_indices calls fpc_ta_get_indices, which expects a buffer and its size. However, in this case, the size comes from a user-controlled value stored in the first TEE_Param parameter.

uint64_t TA_fp_tee_get_indices(uint32_t paramTypes, TEE_Param params[4]) {
    // [...]
    ret = fpc_ta_get_indices(params[1].memref.buffer, &params[0].value.a);
    // [...]
}

This address and the size are then propagated from fpc_ta_get_indices to fpc_db_get_primary_and_privacy_fingerprint_indices.

uint64_t fpc_ta_get_indices(void *obuf1_addr, unsigned int *ioval0_a_p) {
    // [...]
    indices = fpc_db_get_indices(
        g_user_template_db,
        fp_active_fingerprint_set_key,
        obuf1_addr,
        *ioval0_a_p,
        ioval0_a_p);
    // [...]
}
uint64_t fpc_db_get_indices(user_db_t *user_db, uint32_t key,
    uint32_t *outbuf, uint32_t oufbuf_len, uint32_t *outbuf_count_p)
{
    // [...]
    fpc_db_get_primary_and_privacy_fingerprint_indices(
        user_db, outbuf, oufbuf_len_, outbuf_count_p);
    // [...]
}

And in fpc_db_get_primary_and_privacy_fingerprint_indices, the length, which is user-controlled, is used to compute the end of the buffer to set all of its bytes to 0. If we specify a size that exceeds the actual length of the buffer an overflow occurs.

uint64_t fpc_db_get_primary_and_privacy_fingerprint_indices(user_db_t *user_db,
    uint32_t *outbuf, uint32_t oufbuf_len, uint32_t *outbuf_count_p)
{
    // [...]
    curr_obuf_p = outbuf;
    obuf_end = outbuf + oufbuf_len;
    do
        *curr_obuf_p++ = 0;
    while ( v8 != v9 );
    // [...]
}

This bug can be triggered using a proof of concept code results in the following output:

[HM] [ERROR][2171]vmem_as_ondemand_prepare failed
[HM] [ERROR][2496]process 1e00000028 (tid: 40) data abort: 
[HM] [ERROR][2498]Bad memory access on address: 0x70005000, fault_code: 0x92000047
[HM] 
[HM] Dump task states for tcb
[HM] ----------
[HM]     name=[TA_uDFingerPrin] tid=40 is-idle=0 is-curr=0
[HM]     state=BLOCKED@MEMFAULT sched.pol=0 prio=46 queued=1
[HM]     aff[0]=ff
[HM]     flags=0 smc-switch=0 ca=8053 prefer-ca=8053
[HM] Registers dump:
[HM] ----------
[HM] 64 bits userspace stack dump:
[HM] ----------
[HM] <fpc_db_get_primary_and_privacy_fingerprint_indices+0x40/0x164>
[HM] <fpc_db_get_indices>+0xf0/0x188
[HM] <fpc_db_get_indices>+0xf0/0x188
[HM] <fpc_ta_get_indices>+0x38/0xcc
[HM] <TA_fp_tee_get_indices>+0x98/0x140
[HM] <tee_task_entry>+0x7f0/0x868
[HM] <thread_func_wrapper>+0x34/0x58
[HM] Dump task states END
[HM] 

Code Pointer Leak in lib_sync_sensor_info

There are multiple code pointer leaks in lib_sync_sensor_info. This function is used to resolve the addresses of library functions that can be called by the TA. After a function is resolved, its address is printed using SLog, and thus accessible from the normal world using logcat.

uint64_t lib_sync_sensor_info(...) {
    // ...
    lib_init_calibrate_dl = dlsym(g_palgorithm, "lib_init_calibrate_dl");
    SLog("%s: lib:%s, func_name:%s, func:0x%x\n",
        "sl_init_so_func", "g_palgorithm", "lib_init_calibrate_dl",
        lib_init_calibrate_dl);
    // ...
}

This bug can be triggered using a proof of concept code that results in the following output:

[TA_uDFingerPrint-1] [debug] 2685:TA_fp_init_so_lib:TA_fp_init_so_lib
[TA_uDFingerPrint-1] fpc_init_so_lib: sensor_type:0x1211
[TA_uDFingerPrint-1] fpc_init_so_lib: alg_lib_name:libalgorithm1211.so
[TA_uDFingerPrint-1] fpc_init_so_lib: algorithm dlopen start
[TA_uDFingerPrint-1] fpc_init_so_lib: p_lib_name:g_palgorithm, lib_name:libalgorithm1211.so, p_lib:0x3d116c0
[TA_uDFingerPrint-1] fpc_init_so_lib: algorithm lib dlopen success
[TA_uDFingerPrint-1] fpc_init_so_lib: p_algorithm:16843968
[TA_uDFingerPrint-1] fp_algorithm_func_dlsym: IN
[TA_uDFingerPrint-1] fp_algorithm_func_dlsym: lib:g_palgorithm, func_name:fp_init_alg_and_pp_lib, func:0x3d8e258
[TA_uDFingerPrint-1] fp_algorithm_func_dlsym: lib:g_palgorithm, func_name:fp_init_check_template_version, func:0x3d8e260
[TA_uDFingerPrint-1] fp_algorithm_func_dlsym: lib:g_palgorithm, func_name:fp_get_current_template_version, func:0x3d8e2e0

Lack of Locking when Accessing Global Variables

As visible in the logs when the trustlet is loaded, it is multi sessions. As a result, proper care must be taken when accessing or modifying global variables. Unfortunately, this trustlet is not doing any kind of locking, so many race conditions issues arise.

[GTask] TA name: TA_uDFingerPrint, UUID: a423e43d, ELF: 1461440, stack: 191072, heap: 29884416, multi session: True, keepalive: False, singleInstance: True

It should be possible to trigger double-frees, use-after-frees and various crashes by writing a multi-threaded CA that calls multiple commands concurrently. Race conditions could be triggered on the database, fingerprint set, and template objects (that are all heap-allocated and stored in global variables).

Proof of concept code that triggers race conditions using concurrent TA_fp_tee_init results in the following crashes:

[HM] [ERROR][2171]vmem_as_ondemand_prepare failed
[HM] [ERROR][2496]process 220000003c (tid: 60) data abort: 
[HM] [ERROR][2498]Bad memory access on address: 0x0, fault_code: 0x92000046
[HM] 
[HM] Dump task states for tcb
[HM] ----------
[HM]     name=[TA_uDFingerPrin] tid=60 is-idle=0 is-curr=0
[HM]     state=BLOCKED@MEMFAULT sched.pol=0 prio=46 queued=1
[HM]     aff[0]=ff
[HM]     flags=0 smc-switch=0 ca=9177 prefer-ca=9177
[HM] Registers dump:
[HM] ----------
[HM] 64 bits userspace stack dump:
[HM] ----------
[HM] <memset+0xc/0xc8>
[HM] <gf_lib_secspi_write_flash>+0x264/0x2e8
[HM] <flash_deep_sleep>+0x70/0xb0
[HM] <lib_sync_sensor_info>+0x128/0xb64
[HM] <func_init_sensor>+0x850/0x8c4
[HM] <fp_init_sensor>+0x170/0x5c0
[HM] <fpc_ta_init>+0xac/0x2c8
[HM] <TA_fp_tee_init>+0x78/0xc8
[HM] <tee_task_entry>+0x7f0/0x868
[HM] <thread_func_wrapper>+0x34/0x58
[HM] Dump task states END
[HM] 
[HM] [ERROR][2171]vmem_as_ondemand_prepare failed
[HM] [ERROR][2496]process 2200000036 (tid: 54) data abort: 
[HM] [ERROR][2498]Bad memory access on address: 0x1, fault_code: 0x92000006
[HM] 
[HM] Dump task states for tcb
[HM] ----------
[HM]     name=[TA_uDFingerPrin] tid=54 is-idle=0 is-curr=0
[HM]     state=BLOCKED@MEMFAULT sched.pol=0 prio=46 queued=1
[HM]     aff[0]=ff
[HM]     flags=0 smc-switch=0 ca=9179 prefer-ca=9179
[HM] Registers dump:
[HM] ----------
[HM] 64 bits userspace stack dump:
[HM] ----------
[HM] <memcpy+0x30/0x344>
[HM] <gf_lib_secspi_read_flash>+0x240/0x2e8
[HM] <flash_load_info>+0x68/0x17c
[HM] <flash_check_flash_version>+0x88/0x348
[HM] <lib_sync_sensor_info>+0x24c/0xb64
[HM] <func_init_sensor>+0x850/0x8c4
[HM] <fp_init_sensor>+0x170/0x5c0
[HM] <fpc_ta_init>+0xac/0x2c8
[HM] <TA_fp_tee_init>+0x78/0xc8
[HM] <tee_task_entry>+0x7f0/0x868
[HM] <thread_func_wrapper>+0x34/0x58
[HM] Dump task states END
[HM]

Affected Devices

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

  • Kirin 990: P40 Pro (ELS)

Please note that other models might have been affected.

Patch

Name Severity CVE Patch
Param Buffer Overflow in TA_fp_tee_get_indices High CVE-2022-46316 December 2022
Code Pointer Leak in lib_sync_sensor_info Low N/A Fixed
Lack of Locking when Accessing Global Variables Low N/A Fixed

Timeline

  • Feb. 02, 2022 - A vulnerability report is sent to Huawei PSIRT.
  • May 07, 2022 - Huawei PSIRT acknowledges the vulnerability report.
  • Dec. 01, 2022 - Huawei PSIRT states that these issues were fixed in the December 2022 update.
  • From Nov. 30, 2022 to Jul, 19 2023 - We exchange regularly about the release of our advisories.
  • Jul. 03, 2023 - Huawei PSIRT informs us that some of the vulnerabilities are not patched and will be fixed in the August 2023 update.