# Equipment Certification TEE Specification

# 1. background

Device identity is the basis for the normal operation of VOIP services, developers access VOIP services, will be through the following two processes to determine the identity:

  1. Device registration. Calibrate the device with two dimensions SN + modelId.
  2. Grab a note. Before making VOIP calls, you need to get the corresponding ticket for this device.

For machines without TEE, we require the device system to be able to manipulate the RPMB region stored in EMMC, and we need to assign the RPMMB to the VOIP service, which writes the unique key corresponding to the device to the KEY region stored when the device is registered for authentication purposes.

For a machine with a TEE, we rely on the results of the TEE, but we need to complete the development of the TA in the TEE according to the specification.

# 2. TA Development

Whether optee, trusty, qsee, etc., the TEE process is usually as follows:

Open TEE Environment > Open a Session > Send Commands > Get Information > End Session > Close TEE Environment

Here we need to define the following criteria:

  1. The session name.
  2. The function of the command.
  3. The interactive data definition of the command.
  4. Operational logic in TA

Device developers need to develop according to the specifications as follows:

  1. TA development requires developers or tee providers to develop TA in accordance with the specifications.
  2. HAL development, HAL is used to interact with TA, WeChat system services based on this HAL.
  3. Service integration, running rpmbd_tee published by WeChat as a system service.

The TA divides the storage into two regions on logic .It is important to note that this data should ultimately reside in the rpmb partition of EMMC or UFS, or other secure device areas that are not accessible by REE.

  1. Key area: 32 bytes. The TA code logic needs to implement this area to be written only once, similar to the OTP (One Time Programmable) area on hardware.
  2. Data area: the unit is Blocks, each Block has 256 bytes, with a minimum requirement of 32 bytes. The developer can determine the size depending on the actual situation and return the corresponding error code if the limit is exceeded.Block addresses start with 0 .

# 2.1 Session Name

The name of TA is unified as ta_devauth

# 2.2 Command Definition

Define three commands, reading data, writing data, and writing keys.

#define TA_DEVAUTH_CMD_READ   0x10
#define TA_DEVAUTH_CMD_WRITE  0x11
#define TA_DEVAUTH_CMD_PROKEY 0x12

Detailed instructions:

command TA_DEVAUTH_CMD_READ 0x10
function Read 1 block of data
parameter 输入:Block 地址

输入/输出:Block 数据 BUFFER,284字节,见 2.3 数据定义。

输出:签名 BUFFER,=32字节
return 0:成功读取,并返回 284 字节数据和 32 字节签名

-1:参数错误。

-2:地址越界。

-3:密钥区还没被写。

-5:其它错误。
Special Notes If the keyfield has not been written (for example, the bare data is all 0x00, or there is no TEE document file in the system? ), which is considered to be a brand new unactivated device that needs to read an error returning -3.
command TA_DEVAUTH_CMD_WRITE 0x11
function Write 1 block of data
parameter 输入:Block 地址

输入:Block 数据 BUFFER,=284字节,见 2.3 数据定义。

输入:对应的签名 BUFFER,=32字节
return 0:写入成功。

-1:参数错误。

-2:地址越界。

-3:密钥区还没被写。

-4:签名错误。

-5:其它错误。
Special Notes If the keyfield has not been written (for example, the bare data is all 0x00, or there is no TEE document file in the system? ), which is considered to be a brand new unactivated device that needs to return -3.

Before writing the data, this function needs to calculate the corresponding signature of the data, and compare it with the signature passed in by the parameter. If the comparison is unsuccessful, it returns -4
command TA_DEVAUTH_CMD_PROKEY 0x12
function Write the key
parameter Key BUFFER, = 32 bytes
return 0:写入成功。

-1:参数错误。

-3:密钥区已有数据。

-5:其它错误。
Special Notes If there is already data in the keyarea (for example, the naked data is not 0x00, or there is a file? ), then needs to return -3.

# 2.3 Data Definition

The size of the incoming and outgoing buffer when interacting with a TA is 284 bytes , which is defined as follows:

struct ta_data {
    uint8_t  data[256];    // 此 256 字节是 TA 写入到1个Block的内容
    uint8_t  nonce[16];    // 一般为随机字节,传入与传出的一定要一致。
    uint32_t reserve1;
    uint16_t reserve2;
    uint16_t reserve3;
    uint16_t reserve4;
    uint16_t reserve5;
};

// sizeof(struct ta_data) = 284

The signature buffer size is 32 bytes .



CA and TA interaction message definition:

struct ta_message {
    uint32_t        cmd;        // 命令号
    uint32_t        block;      // 读写地址
    struct ta_data  data;       // 284 字节数据
    uint8_t         key[32];    // 32 字节 Key
    uint8_t         hmac[32];   // 32 字节 hmac
    int             ret;        // 返回值
};

CA side reference pseudocode:

static int tee_send_cmd_req(struct ta_message* ta_msg) {
    int rc = 0;
    
    if (ca_handle == 0) {
        printf("not connected\n");
        return -EINVAL;
    }
    
    if (tee_send_msg(ca_handle, ta_msg) < 0) {
        return -1;
    }
    
    if (tee_resp_msg(ca_handle, ta_msg) < 0) {
        return -1;
    }
    
    return 0;
}

# 2.4 Logic of operations

The algorithm for data signature is HMAC_SHA256.

When reading the data, TA's process:

  1. If there is no data in the key area, return -3.
  2. The read address parameter corresponds to 256 bytes of data for a Block.
  3. The 256 bytes read and the 16 bytes noce and other reserve in the input parameter make a total of 284 bytes.
  4. Take advantage of the 32-byte key in the key area, sign 284 bytes, and return 284 bytes as well as the signature.

When writing data, TA's flow:

  1. If there is no data in the key area, return -3.
  2. Get 284 bytes in the input parameter, and get signature 1 in the input argument.
  3. Take advantage of the 32-byte key in the key area, sign 284 bytes, and get a signature2.
  4. Compare signature 1 with signature 2 and write 256 of 284 bytes to the corresponding block if equal, and return error -4 if unequal.

When writing the key, TA's process:

  1. If the key area already has data, return -3.
  2. Write a 32-byte key to the key area.

An example of signed data from which developers can validate their hmac_sha256:

char *key = "AAAABBBBCCCCDDDDEEEEFFFFGGGGHHHH";
uint8_t buffer[284] = {0};

int main(int argc, char **argv) {
    uint8_t hmac[32] = {0};
    memset(buffer, 0x55, 284);

    hmac_sha256(key, 32,
      buffer, 284,
      hmac, sizeof(hmac)
    );

    for (int i=0; i < 32; i++) {
        printf("%02x ", hmac[i]);
    }
    return 0;
}
// The above code outputs:
// 61 16 67 22 a0 93 66 74 bb 75 f8 87 0e 5e d4 59 2c d6 99 c0 14 a6 93 70 bd ff ea 3e 8e 84 52 4e 

Hmac_sha256 for the standard algorithm, the general tee has such an algorithm, if not, can refer to the open source implementation of](https://github.com/ogay/hmac/blob/master/hmac_sha2.c) .

# 2.5 Note

  1. The key and data areas in TEE are guaranteed to have a "permanent storage" feature and should not be directly accessed by REE in any way and not be lost with the user's refresh, upgrade or other routine behavior.
  2. The key area needs to be implemented as an OTP feature, i.e. written only once.
  3. When there is no data in the key area, the error code needs to be returned as a specification.
  4. Manufacturers need to CA test routines and code to WeChat, WeChat acceptance test.

# 3. HALDevelopment

According to the HAL specification to complete the development of HAL, HAL uses CA code to interact with TA, complete the use of TEE.

HAL path:android / hardware / interface / devauth

# 3.1 HAL specification

types.hal

package android.hardware.devauth@1.0;

enum TA_CMD : uint32_t {
    TA_DEVAUTH_CMD_READ = 0x10,
    TA_DEVAUTH_CMD_WRITE = 0x11,
    TA_DEVAUTH_CMD_PROKEY = 0x12,
};

struct ta_data {
    uint8_t[256] data; // 此 256 字节是 TA 写入到1个Block的内容
    uint8_t[16]  nonce; // 一般为随机字节,传入与传出的一定要一致。
    uint32_t reserve1;
    uint16_t reserve2;
    uint16_t reserve3;
    uint16_t reserve4;
    uint16_t reserve5;
};

struct ta_message {
    uint32_t        cmd;        // 命令号
    uint32_t        block;      // 读写地址
    ta_data         data;       // 284 字节数据
    uint8_t[32]     key;        // 32 字节 Key
    HMacBuffer      hmac;       // 32 字节 hmac
    int8_t          ret;        // 返回值
};

typedef uint8_t[32] HMacBuffer;
typedef uint8_t[32] ProKeyBuffer;

typedef ta_data ta_data_t;
typedef ta_message ta_message_t;

IDevauth.hal

package android.hardware.devauth@1.0;

interface IDevauth {

    /**
     * 读 Block 数据
     *
     * @param addr:     Block 地址
     * @param data:     输入的 struct ta_data
     * @return retval:  返回值,返回值说明请见规范
     * @return data:    返回的 struct ta_data,284 字节。
     * @return hmac:    返回的签名, 32 字节。
     *
     */
    read_block(uint16_t addr, ta_data data) generates (int8_t retval, vec<uint8_t> data, vec<uint8_t> hmac); 

    /**
     * 写 Block 数据
     *
     * @param addr:     Block 地址
     * @param data:     输入输出数据,对应规范里的 struct ta_data,284 字节。
     * @param hmac:     HAL 写数据时用的签名, 32 字节
     *
     * @return retval:  返回值说明请见规范
     */
    write_block(uint16_t addr, ta_data data, HMacBuffer hmac) generates (int8_t retval); 

    /**
     * 写 Key
     *
     * @param key:      32 字节key
     *
     * @return retval:  返回值说明请见规范
     */
    program_key(ProKeyBuffer key) generates(int8_t retval);
};

# 3.2 Development Reference

Hardware / interfaces / devauth / 1.0 /`` IDevauth.haltypes.hal, as stated above.

Then use the following method to generate the code:

LOC=hardware/interfaces/devauth/1.0/default
PACKAGE=android.hardware.devauth@1.0
hidl-gen -o $LOC -Lc++-impl -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport ${PACKAGE}
hidl-gen -o $LOC -Landroidbp-impl -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport ${PACKAGE}
./hardware/interfaces/update-makefiles.sh

The hal directory should be as follows:

root~/android> tree hardware/interfaces/devauth/
hardware/interfaces/devauth/
└── 1.0
    ├── Android.bp
    ├── default
    │   ├── Android.bp
    │   ├── Devauth.cpp
    │   └── Devauth.h
    ├── IDevauth.hal
    └── types.hal

2 directories, 6 files

Then according to the HAL interface definition, in the corresponding interface function to complete the development of CA code.

# 4. acceptance

# 4.1 Submit information

  • ✓Chip platform, storage type. Examples: MTK81xx, EMMC64GB
  • ✓REE operating system details. Example: Android 7 64 bit
  • ✓TEE system details. Example: Based on optee, the provider is xxx
  • ✓Data storage location in the tee. Example: RPMB partition in EMMC
  • ✓The TA code on the TEE side. Example: ta_devauth module code
  • ✓The CA code on the REE side. Example: Test case code package and corresponding TEE function so.
  • ✓The HAL code on the REE side. Example: Code under hardware / interface / devauth.
  • ✓Can adbroot prototype.

# 4.2 Test cases

After the developer completes the TA development of the TEE, they should develop test cases to verify the function and logic of the TA. Presupposition: ta_deauth has no data in the area managed . Then run the following test items in order.

  1. Read data test, expected return -3
  2. Write the data test, expecting a return of -3
  3. Write key test, expecting 0 return
  4. Write key test, expected to return -3
  5. Read the data test, expect to return 0, and the data is all 0x00 and signed.
  6. Write data test with correct HMAC, expect to return 0
  7. Write data test with wrong HMAC, expected to return -4
  8. Read the data test, expecting to return 0, and return the correct data and signature.

You can add your own CA implementation to the official test case code to quickly validate the TA.

After the developer completes the HAL development, the test case can be tested with ,

You can also download the compiled tee_hal_test for testing, as follows

  1. Tee_hal_testafor a brand new test that requires a ta_devauth managed area without any data.
  2. Tee_hal_testtakes no parameters and can be run after 1.

# 4.3 integrated

4.2 After passing the test cases in rpmbd_tee, download rpmbd_tee and integrate it into the system to run as a service, refer to:

service rpmbd_tee /system/bin/rpmbd_tee
  class main
  user root
  group root system