Rate This Document
Findability
Accuracy
Completeness
Readability

SM Algorithms

SM Algorithms for TA Encryption

In 2.1.2-3, the AES algorithm is adopted for encryption by default when the itrustee-sdk script is used to sign and package TA images. To use an SM algorithm instead, set secEncryptContentAlg in the config_cloud.ini file to 1, which indicates that SM4-CBC is used for encryption.

Run the make command again. When the TA is being signed and packaged, the SM4-CBC algorithm is used to encrypt the TA. Correspondingly, when loading a TA image, the TEE OS uses SM4-CBC for decryption based on the configuration information.

SM Algorithms for Secure Storage

When a TA invokes the secure storage API to save persistent data, a non-SM algorithm is used for encryption by default. If you want to use an SM algorithm instead, you can perform the OR operation on the flags input parameter and TEE_DATA_FLAG_GM when calling the secure storage API to generate a persistent object. After that, when the persistent object is operated, an SM algorithm is used for encryption and digest calculation.

1
2
3
4
5
// Create a persistent object.
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);

// Open a persistent object.
TEE_Result TEE_OpenPersistentObject(uint32_t storageID, const void *objectID, size_t objectIDLen, uint32_t flags,TEE_ObjectHandle *object);
Refer to the following example: Call the TEE_CreatePersistentObject API to create a persistent object and then TEE_WriteObjectData to write data.
 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;
    // Add the SM algorithm flag TEE_DATA_FLAG_GM when creating a persistent object.
    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;
    }
    // The SM algorithm is automatically used when writing data.
    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;
}

SM Algorithms for Hardware-based Acceleration

If you use SM4-CBC or SM4-ECB algorithm in the TEE, hardware-based acceleration can be enabled to greatly improve performance. Hardware-based acceleration requires calling the following API function:

1
2
// Set the SEC_CRYPTO flag of the hardware-based acceleration engine for the operation handle.
TEE_Result TEE_SetCryptoFlag(TEE_OperationHandle operation, uint32_t crypto);

Parameter description:

  • operation: operation handle.
  • crypto: encryption and decryption engine. The value SEC_CRYPTO indicates that the SEC driver is used for hardware-based acceleration.
1
2
// Enable hardware-based acceleration and apply for DMA memory to reduce memory copy operations.
int32_t tee_enable_crypto_accelerator(TEE_OperationHandle operation, size_t length, struct accel_memref_t *memrefs,  int *memref_num);

Parameter description:

  • operation: operation handle. To call this API, the underlying engine must be set to SEC_CRYPTO, and the algorithm ID in the handle must be supported by the underlying engine. Currently, only SM4-CBC and ECB are supported.
  • length: maximum size of the input and output data. The size of the input and output data for subsequent encryption or decryption cannot exceed this value.
  • memrefs: stores the allocated DMA memory arrays.
  • memref_num: indicates the array size when being used as an input parameter, and indicates the number of allocated DMA memory blocks when being used as an output parameter.

Refer to the following example: Use the hardware-based acceleration for SM4-CBC computing.

  1. Compile the TA code based on the sample code. (You can refer to helloworld to add necessary APIs for communication between CAs and TAs.)
     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;
        }
        // The flag must be set before TEE_SetOperationKey and 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;
        }
        // Apply for two DMA buffers, one to store the input data and the other to store the output data.
        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. Set GP API_LEVEL to 3 in the config.mk file.

  3. Add the DMA memory option to the manifest.txt file.
    1
    gpd.ta.dma_allocable:    true
    

    Till now you have compiled and configured the hardware-based acceleration code.

  • TEE_SetCryptoFlag must be called before TEE_SetOperationKey.
  • If All 64 queues of QM are busy is displayed when calling TEE_CipherInit, the hardware-based acceleration queues in the TEE are all occupied. The hardware-based acceleration function cannot be used when Update or doFinal is called later. Even in this case, the software computing function is still supported.