---
title: 国密支持
description: "在参考2.1.2-3 编译TA应用时，修改config_cloud.ini配置文件中的secEncryptContentAlg为1，表明对TA机密时采用国密SM4-CBC。"
url: https://www.hikunpeng.com/document/detail/zh/kunpengboostkithistory/240RC2/confidt/kunpengtrustzone_20_0065.html
sourcePath: /source/zh/kunpengboostkithistory/240RC2/confidt/kunpengtrustzone_20_0065.html
indexId: cfac08cff6ce4607e000eba9cc154bc58526177933ca69b4e9c75644c68e34ad78
---
# 国密支持

#### TA应用加密支持国密

在参考2.1.2-3 编译TA应用时，修改config_cloud.ini配置文件中的secEncryptContentAlg为1，表明对TA机密时采用国密SM4-CBC。


重新执行make，则在TA签名打包过程中，对TA的加密将自动采用SM4-CBC国密算法。运行CA加载TA时，TEEOS会根据配置信息采用国密算法解密。


#### 安全存储支持国密

只需要在调用如下安全存储接口生成持久化对象时，在入参flags或上TEE_DATA_FLAG_GM，后续对该持久化对象操作时，使用的加密和摘要算法将自动切换为国密。

```
// 创建一个新的持久化对象
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写入数据。
```
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算法时，可配置硬件加速，实现性能大幅度提升。使用硬件加速需新调用如下接口函数。

```
// 为Operation设置硬件引擎SEC_CRYPTO flag。
TEE_Result TEE_SetCryptoFlag(TEE_OperationHandle operation, uint32_t crypto);
```

参数：

- operation：加解密Operation。
- crypto：加解密引擎，配置为SEC_CRYPTO表示使用SEC驱动硬件加速。

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

参数：

- operation：加解密Operation。必须设置过SEC_CRYPTO的硬件引擎flag，且加解密的算法必须为支持加速的算法。
- length：输入输出数据最大大小，后续加解密的输入输出数据大小不能超过该值。
- memrefs：用于存放申请的dma内存数组。
- memref_num：作为入参表示数组的大小，作为出参表示成功申请的内存个数。


可参考如下简单示例：其使用硬件加速SM4-CBC加密数据。

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

```
#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);
tloge("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内存使能项。

```
gpd.ta.dma_allocable:    true
```


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


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