前言

上一期我们对ISEE-M的整体设计架构,核心模块以及系统优势进行了介绍,尤其系统的安全能力,是为物联设备终端提供提供强大的安全保障的关键。而今天我们要介绍ISEE-M的开发工具环境以及开发示例。上一期还没看过的同学,欢迎进入点击链接了解详情~

提到SDK,相信大家最关心的就是部署是否简单快速?是否便于开发?文档是否通俗易懂?嗯,当然Yes~

ISEE-M SDK基于MCUXpresso SDK设计开发,支持GP TEE Client API,可扩展支持第三方RTOS。ISEE-M内部支持GP TEE Internal API,非常方便用户开发。部署简单,可一键合入MCUXpresso SDK。同时提供开发指南,帮助开发者快速着手开发。

ISEE-M SDK使用说明

  • 开发环境
  1. 基于MCUXpresso SDK开发环境即可,无需额外环境准备
  2. 支持MCUXpresso SDK 2.6.2及以上
  3. 支持工具链/IDE: KEIL 5.28
  • 目录结构

ISEE-M SDK基于MCUXpresso SDK设计开发,与MCUXpresso SDK低耦合,目录结构参考下图所示:

 

 

 

 

 

 

 

 

 

 

SDK工程结构分为示例工程和ISEE-M组件库两部分:

  1. 示例工程分为两个子工程,demo_project_ns是非安全工程(REE侧),对应开发业务中安全不敏感的逻辑,demo_project_s是安全工程(TEE侧),对应开发业务中安全敏感的操作(敏感数据或关键算法)。
  2. ISEE-M组件库的路径为middleware/iseem/sdk,doc存放ISEE-M相关文档,在include和library中,分别有teec和tee目录,teec由非安全工程使用,tee由安全工程使用。
  • 支持API & Module概述
  1. GP TEE 客户端 API v1.0及以上
  2. GP TEE 内部 API v1.0及以上
  3. 支持PUF/HashCrypt/Casper/RNG等关键硬件模块

GP TEE Client API (部分API例举)

TEEC_InitializeContext
TEEC_FinalizeContext
TEEC_RegisterSharedMemory
TEEC_AllocateSharedMemory
TEEC_ReleaseSharedMemory
TEEC_OpenSession
TEEC_CloseSession
TEEC_InvokeCommand

GP TEE Internal API (部分API例举)

加密操作 API

TEE_CipherInit
TEE_CipherUpdate
TEE_CipherDoFinal
TEE_AsymmetricEncrypt
TEE_AsymmetricDecrypt
TEE_AsymmetricSignDigest
TEE_AsymmetricVerifyDigest
TEE_GenerateRandom
TEE_MACInit
TEE_MACUpdate

TEE_MACComputeFinal
TEE_MACCompareFinal TEE_DigestUpdate
TEE_DigestDoFinal

Trusted Storage API

TEE_OpenPersistentObject
TEE_CreatePersistentObject
TEE_CloseAndDeletePersistentObject
TEE_RenamePersistentObject

注:GlobalPlatform(GP)是跨行业的国际标准组织,致力于开发、制定并发布安全芯片的技术标准,以促进多应用产业环境的管理及其安全、可互操作的业务部署。

GlobalPlatform组织发布的GP相关规范可以在官方网站上获取:https://globalplatform.org/specs-library/?filter-committee=tee

《TEE Client API Specification v1.0_GPD_SPE_00》

《TEE_Internal_Core_API_Specification_v1.2.1》

  • 开发CA/TA

CA(Client Application)泛指非安全侧(REE侧)的工程,可参考SDK目录中demo_project_ns。

TA(Trusted Application)泛指安全侧(TEE侧)的工程,可参考SDK目录中demo_project_s。

开发者可以基于提供的示例代码和开发指南,开发实现相应功能。

在本示例中,CA将敏感数据存储到TA的安全存储中,并在CA需要时从TA安全存储中读出敏感数据。CA和TA通过GP TEE Client API通信,TA将CA请求的敏感数据加密后存储到非易失存储中,加密及存储通过TEE Internal API实现。密钥存储在TEE侧,REE侧程序无法获得,从而保证了敏感数据的安全。

  • CA代码片段如下:
  1. intcmd_type = CMD_ENCRYPT_AND_STORAGE_WRITE;
  2. constTEEC_UUID demo_ta_uuid = DEMO_TA_UUID;
  3. TEEC_Context context;
  4. TEEC_Session session;
  5. TEEC_InitializeContext(NULL,&context);
  6. TEEC_OpenSession(&context,&session,&demo_ta_uuid,0,NULL,NULL,NULL);
  7. TEEC_Operation operation;
  8. cmd_type = getchar();
  9. cmd_type -= 0x30;
  10. if(cmd_type == CMD_ENCRYPT_AND_STORAGE_WRITE)
  11. {
  12. paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INPUT,TEEC_NONE,
  13. TEEC_NONE,TEEC_NONE);
  14. params[0].tmpref.buffer = send_data;
  15. params[0].tmpref.size = sizeof(send_data);
  16. printf(“CA: send write command\n”,cmd_type);
  17. TEEC_InvokeCommand(&session,CMD_ENCRYPT_AND_STORAGE_WRITE,&operation,NULL);
  18. }
  19. elseif(cmd_type == CMD_STORAGE_READ_AND_DECRYPT)
  20. {
  21. hexdump8(“CA: prepare data buffer:”,receive_data,128);
  22. paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_OUTPUT,TEEC_NONE,
  23. TEEC_NONE,TEEC_NONE);
  24. params[0].tmpref.buffer = receive_data;
  25. params[0].tmpref.size = sizeof(receive_data);
  26. printf(“CA: send read command\n”,cmd_type);
  27. TEEC_InvokeCommand(&session,CMD_STORAGE_READ_AND_DECRYPT,&operation,NULL);
  28. hexdump8(“CA: receive data:”,receive_data,128);
  29. } else{
  30. printf(“cmd type %d not support\n”,cmd_type);
  31. }
  32. TEEC_CloseSession(&session);
  33. TEEC_FinalizeContext(&context);
  • TA代码片段如下:
  1. TEE_OperationHandle operation = NULL;
  2. TEE_ObjectHandle keyObj = NULL;
  3. TEE_ObjectHandle dataObj = NULL;
  4. TEE_Attribute attr[1] = {0};
  5. TEE_Result res = TEE_ERROR_GENERIC;
  6. size_t output_len = 0;
  7. uint8_t *tmp_data_buf = NULL;
  8. if((data == NULL) || (len != 128))
  9. {
  10. returnTEE_ERROR_BAD_PARAMETERS;
  11. }
  12. output_len = len;
  13. tmp_data_buf = TEE_Malloc(len, 0);
  14. if(!tmp_data_buf)
  15. {
  16. LOG_ERR(“TEE Malloc buffer failed”);
  17. returnTEE_ERROR_OUT_OF_MEMORY;
  18. }
  19. LOG_INFO(“read data from persistent object.”);
  20. res = TEE_OpenPersistentObject(TEE_STORAGE_PRIVATE, (void*)obj_name,
  21. sizeof(obj_name), flags | TEE_DATA_FLAG_SHARE_READ |
  22. TEE_DATA_FLAG_ACCESS_WRITE_META, &dataObj);
  23. if(res != TEE_SUCCESS)
  24. {
  25. LOG_ERR(“TEE_OpenPersistentObject failed”);
  26. gotoout;
  27. }
  28. res = TEE_ReadObjectData(dataObj, tmp_data_buf, len, &output_len);
  29. if(res != TEE_SUCCESS)
  30. {
  31. LOG_ERR(“read object failed”);
  32. gotoout;
  33. }
  34. hexdump8(“TA: data from storage with encrpyt”,tmp_data_buf,output_len);
  35. LOG_INFO(“read data success.”);
  36. LOG_INFO(“decrypt data to ree buffer.”);
  37. res = TEE_AllocateOperation(&operation, TEE_ALG_AES_CBC_NOPAD,
  38. TEE_MODE_DECRYPT, 256);
  39. if(res != TEE_SUCCESS)
  40. {
  41. LOG_ERR(“allocate operation failed, res %x”, res);
  42. gotoout;
  43. }
  44. res = TEE_AllocateTransientObject(TEE_TYPE_AES, 256, &keyObj);
  45. if(res != TEE_SUCCESS)
  46. {
  47. LOG_ERR(“allocate key failed, res %x”, res);
  48. gotoout;
  49. }
  50. TEE_InitRefAttribute(attr, TEE_ATTR_SECRET_VALUE, key, sizeof(key));
  51. res = TEE_PopulateTransientObject(keyObj, attr, 1);
  52. if(res != TEE_SUCCESS)
  53. {
  54. LOG_ERR(“populate key failed, res %x”, res);
  55. gotoout;
  56. }
  57. res =  TEE_SetOperationKey(operation, keyObj);
  58. if(res != TEE_SUCCESS)
  59. {
  60. LOG_ERR(“set key failed, res %x”, res);
  61. gotoout;
  62. }
  63. TEE_CipherInit(operation, iv, sizeof(iv));
  64. res = TEE_CipherUpdate(operation, tmp_data_buf, output_len, data,
  65. (size_t*)&len);
  66. if(res != TEE_SUCCESS)
  67. {
  68. LOG_ERR(“cipher update failed, res %x”, res);
  69. gotoout;
  70. }
  71. res = TEE_CipherDoFinal(operation, NULL, 0, data, (size_t*)&len);
  72. if(res != TEE_SUCCESS)
  73. {
  74. LOG_ERR(“cipher dofinal failed, res %x”, res);
  75. gotoout;
  76. }
  77. LOG_INFO(“decrypt data success.”);
  • 工程编译

工程编译操作超简单,打开工程->编译->烧写 三步走即可。

演示工程环境说明:

  1. 芯片型号:LPC55S69-EVK
  2. MCUXpresso SDK版本:2.6.2

编译步骤:

  1. Keil打开示例程序工程/boards/lpcxpresso55s69/iseem_examples/demo/cm33_core0/demo_project_s/mdk/demo_project.uvmpw ,该操作会打开demo_project_s,demo_project_ns两个子工程。
  2. 依次编译demo_project_s和demo_project_ns工程。
  3. 设置demo_project_s为活动工程,连接device,烧写。
  • 主要功能

在本示例中,CA将敏感信息存储到TA的安全存储中,并在CA需要时从TA安全存储中读出敏感信息。

CA和TA通过GP TEE Client API通信,TA将CA请求的敏感信息加密后存储到非易失存储中,加密及存储通过TEE Internal API实现。密钥存储在TEE侧,REE侧程序无法获得,保证了密钥的安全。

程序可根据终端传入的参数来执行对应的功能。输入参数1,将信息存储到安全存储中;输入参数2,将信息从安全存储中读出。

  • API使用代码示例&编译

这部分已经在前面介绍,这里不再赘述。

  • 运行演示

运行前,先准备串口环境,用于查看运行结果。串口工具有很多,例如putty。在串口工具中,设置好芯片设备的COM号以及波特率115200运行即可。

示例程序在串口中运行结果演示如下:

 

 

 

 

 

 

 

 

 

 

 

我们还将继续推出此系列的后续文章,敬请持续关注豆荚科技公众号。