国密支持

TA应用加密支持国密

2.1.2-3 编译TA应用节,使用itrustee-sdk脚本对TA镜像签名打包时,默认使用国际算法AES进行加密。若需使用国密算法,可修改config_cloud.ini配置文件中的secEncryptContentAlg为1,表明对加密时采用国密SM4-CBC。

然后重新执行make即可,则在TA签名打包过程中,对TA的加密将自动采用SM4-CBC国密算法。对应的,在TEEOS加载TA镜像时,会根据配置信息采用SM4-CBC进行解密。

安全存储支持国密

TA调用安全存储接口保存持久化数据时,默认使用国际算法进行加密,若需使用国密算法,可在调用安全存储接口生成持久化对象时,将入参flags与TEE_DATA_FLAG_GM进行或操作,则后续操作此持久化对象时,将使用国密算法进行加密和摘要计算。

1
2
3
4
5
// 创建一个新的持久化对象
TEE_Result TEE_CreatePersistentObject(uint32_t storageID, const void *objectID, size_t objectIDLen, uint32_t flags, TEE_ObjectHandle attributes, const void *initialData, size_t initialDataLen, TEE_ObjectHandle *object);

// 打开一个新的持久化对象
TEE_Result TEE_OpenPersistentObject(uint32_t storageID, const void *objectID, size_t objectIDLen, uint32_t flags,TEE_ObjectHandle *object);
可参考如下简单示例:其先调用TEE_CreatePersistentObject创建一个持久化对象,再调用TEE_WriteObjectData写入数据。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
TEE_Result WritePersistentData(const void *buffer, size_t len)
{
    TEE_Result ret;
    uint32_t storageID = TEE_OBJECT_STORAGE_PRIVATE;
    TEE_ObjectHandle persistentObj = NULL;
    void *objectID = "sec_storage_data/store_key_sample.txt";
    void *aes_key = NULL;
    // 创建持久化对象时添加国密标志TEE_DATA_FLAG_GM
    ret = TEE_CreatePersistentObject(storageID, objectID, strlen(objectID), \
        TEE_DATA_FLAG_ACCESS_WRITE | TEE_DATA_FLAG_GM, NULL, NULL, 0, &persistentObj);
    if (ret != TEE_SUCCESS) {
        tloge("Failed to create object:ret = 0x%x\n", ret);
        return ret;
    }
    // 写入数据时自动使用国密算法
    ret = TEE_WriteObjectData(persistentObj, buffer, len);
    if (ret != TEE_SUCCESS) {
        tloge("Failed to write data:ret = 0x%x\n", ret);
        goto close;
    }
    tloge("write persistent data success\n");
close:
    TEE_CloseObject(persistentObj);
    return ret;
}

国密算法支持硬件加速

当客户在TEE内调用国密SM4-CBC/ECB算法时,可配置硬件加速,实现性能大幅度提升。使用硬件加速需新调用如下接口函数。

1
2
// 为operation句柄设置硬件加速引擎SEC_CRYPTO标志。
TEE_Result TEE_SetCryptoFlag(TEE_OperationHandle operation, uint32_t crypto);

参数:

1
2
// 使能硬件加速,申请dma内存,用于减少内存拷贝。
int32_t tee_enable_crypto_accelerator(TEE_OperationHandle operation, size_t length, struct accel_memref_t *memrefs,  int *memref_num);

参数:

可参考如下简单示例:其使用硬件加速进行SM4-CBC计算。

  1. 参考示例编写TA代码,(客户可参考helloworld添加CA TA通信必要接口)

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    #define SM4_KEY_SIZE 128
    #define DMA_ACCEL_MEM_NUM 2
    #define SM4_IV_LEN 16
    
    TEE_Result SEC_AccelerateSM4_CBC(void *inBuf, size_t inLen, void *outBuf, size_t *outLen)
    {
        TEE_Result ret;
        TEE_ObjectHandle key = NULL;
        TEE_OperationHandle operation = NULL;
        struct accel_memref_t accel_memrefs[DMA_ACCEL_MEM_NUM];
        int memref_num = DMA_ACCEL_MEM_NUM;
        uint8_t iv[SM4_IV_LEN] = {0};
        
        ret = TEE_AllocateTransientObject(TEE_TYPE_SM4, SM4_KEY_SIZE, &key);
        if (ret != TEE_SUCCESS) {
            tloge("alloc key object failed. ret=0x%x\n", ret);
            return ret;
        }
        ret = TEE_GenerateKey(key, SM4_KEY_SIZE, NULL, 0);
        if (ret != TEE_SUCCESS) {
            tloge("generate random key failed. ret=0x%x\n", ret);
            goto free_key;
        }
        ret = TEE_AllocateOperation(&operation, TEE_ALG_SM4_CBC_NOPAD, TEE_MODE_ENCRYPT, SM4_KEY_SIZE);
        if (ret != TEE_SUCCESS) {
            tloge("alloc operation failed, ret=0x%x\n", ret);
            goto free_key;
        }
        // 设置flag必须在TEE_SetOperationKey和tee_enable_crypto_accelerator之前
        ret = TEE_SetCryptoFlag(operation, SEC_CRYPTO);
        if (ret != TEE_SUCCESS) {
            tloge("set crypto flag failed. ret=0x%x\n", ret);
            goto free_opt;
        }
        ret = TEE_SetOperationKey(operation, key);
        if (ret != TEE_SUCCESS) {
            tloge("operation set key failed. ret=0x%x\n", ret);
            goto free_opt;
        }
        // 申请2个dma内存,分别存放输入数据和输出数据
        if (tee_enable_crypto_accelerator(operation, inLen, accel_memrefs, &memref_num) != 0 || memref_num != DMA_ACCEL_MEM_NUM) {
            tloge("tee_enable_crypto_accelerator failed\n");
            goto free_opt;
        }
        (void)memcpy_s((void *)(accel_memrefs[0].buffer), inLen, inBuf, inLen);
        (void)memset_s((void *)(accel_memrefs[1].buffer), inLen, 0, inLen);
        TEE_CipherInit(operation, iv, SM4_IV_LEN);
        ret = TEE_CipherDoFinal(operation, NULL, inLen, NULL, outLen);
        if (ret != TEE_SUCCESS) {
            tloge("cipher do final failed. ret=0x%x\n", ret);
            goto free_opt;
        }
        (void)memcpy_s(outBuf, *outLen, (void *)(accel_memrefs[1].buffer), *outLen);
        tlogi("sm4-cbc cipher success. outLen=%d\n", *outLen);
    free_opt:
        TEE_FreeOperation(operation);
    free_key:
        TEE_FreeTransientObject(key);
        return ret;
    }
    

  2. 配置config.mk中的GP API_LEVEL为3。

  3. 配置manifest.txt,添加dma内存使能项。

    1
    gpd.ta.dma_allocable:    true
    

    至此即完成了硬件加速的代码编写和配置。

  • TEE_SetCryptoFlag需在TEE_SetOperationKey调用之前调用。
  • 若调用TEE_CipherInit出现“All 64 queues of QM are busy”,表明此时TEE内的硬件加速队列资源被占满,后续调用Update或doFinal无法使用硬件加速功能,此时软算功能仍是支持的。