查看: 1233|回复: 0

物联网安全可信计算环境系列之二:终端平台开发套件

[复制链接]
  • TA的每日心情
    开心
    2024-3-26 15:16
  • 签到天数: 266 天

    [LV.8]以坛为家I

    3300

    主题

    6547

    帖子

    0

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    32035
    最后登录
    2024-4-26
    发表于 2019-11-5 14:29:14 | 显示全部楼层 |阅读模式
    本系列文章对构建在LPC55SXX芯片上的安全可信计算环境ISEE-M产品所涉及的诸多方面进行介绍,共由以下五部分组成:
    终端平台基础设计》,对ISEE-M的整体设计架构进行介绍(点击查看)
    终端平台开发套件》,对ISEE-M的开发工具环境进行简介以及开发示例演示(本文)
    系统整体方案介绍》,对基于ISEE-M产品上构建的系统整体解决方案进行介绍(待续)
    生产线配套工具》,对基于ISEE-M产品上生产产线安全问题的思考和解决办法进行介绍(待续)
    生命周期管理》,对基于ISEE-M产品上研发的终端产品的维护、升级安全问题的思考和解决办法的介绍(待续)

    上一期我们对ISEE-M的整体设计架构,核心模块以及系统优势进行了介绍,尤其系统的安全能力,是为物联设备终端提供强大的安全保障的关键。而今天我们要介绍ISEE-M的开发工具环境以及开发示例。上一期还没看过的同学,欢迎进入点击链接了解详情~
    提到SDK,相信大家最关心的就是部署是否简单快速?是否便于开发?文档是否通俗易懂?嗯,当然Yes~
    ISEE-M SDK基于MCUXpressoSDK设计开发,支持GP TEE Client API,可扩展支持第三方RTOS。ISEE-M内部支持GPTEE Internal API,非常方便用户开发。部署简单,可一键合入MCUXpresso SDK。同时提供开发指南,帮助开发者快速着手开发。


    ISEE-M SDK使用说明


    █  开发环境

    基于MCUXpresso SDK开发环境即可,无需额外环境准备

    支持MCUXpresso SDK 2.6.2及以上

    支持Toolchain/IDE: KEIL 5.28

    █  目录结构

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

    11.png

    SDK工程结构分为示例工程和ISEE-M组件库两部分:
    示例工程分为两个子工程,demo_project_ns是非安全工程(REE侧),对应开发业务中安全不敏感的逻辑,demo_project_s是安全工程(TEE侧),对应开发业务中安全敏感的操作(敏感数据或关键算法)。
    ISEE-M组件库的路径为middleware/iseem/sdk,doc存放ISEE-M相关文档,在include和library中,分别有teec和tee目录,teec由非安全工程使用,tee由安全工程使用。

    █  支持API & Module概述

    GP TEEClient API v1.0及以上

    GP TEEInternal API v1.0及以上

    支持PUF/HashCrypt/Casper/RNG等关键硬件模块

    GPTEE Client API(部分API例举):
    TEEC_InitializeContext
    TEEC_FinalizeContext
    TEEC_RegisterSharedMemory
    TEEC_AllocateSharedMemory
    TEEC_ReleaseSharedMemory
    TEEC_OpenSession
    TEEC_CloseSession
    TEEC_InvokeCommand
    GPTEE Internal API(部分API例举)

    Cryptographic Operations 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相关规范可以在官方网站上获取:

    http://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(TrustedApplication)泛指安全侧(TEE侧)的工程,可参考SDK目录中demo_project_s。

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

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

    CA代码片段如下:

    1.        int cmd_type = CMD_ENCRYPT_AND_STORAGE_WRITE;
    2.        const TEEC_UUID demo_ta_uuid = DEMO_TA_UUID;
    3.        TEEC_Context context;
    4.        TEEC_Session session;
    5.         
    6.        TEEC_InitializeContext(NULL,&context);
    7.        TEEC_OpenSession(&context,&session,&demo_ta_uuid,0,NULL,NULL,NULL);
    8.        TEEC_Operation operation;
    9.         
    10.        cmd_type = getchar();
    11.        cmd_type -= 0x30;
    12.        if (cmd_type == CMD_ENCRYPT_AND_STORAGE_WRITE)
    13.        {
    14.            operation.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_INPUT,TEEC_NONE,
    15.            TEEC_NONE,TEEC_NONE);
    16.            operation.params[0].tmpref.buffer = send_data;
    17.            operation.params[0].tmpref.size = sizeof(send_data);
    18.            printf("CA: send write command\n",cmd_type);
    19.            TEEC_InvokeCommand(&session,CMD_ENCRYPT_AND_STORAGE_WRITE,&operation,NULL);
    20.        }
    21.        else if (cmd_type == CMD_STORAGE_READ_AND_DECRYPT)
    22.        {
    23.            hexdump8("CA: prepare data buffer:",receive_data,128);
    24.            operation.paramTypes = TEEC_PARAM_TYPES(TEEC_MEMREF_TEMP_OUTPUT,TEEC_NONE,
    25.            TEEC_NONE,TEEC_NONE);
    26.            operation.params[0].tmpref.buffer = receive_data;
    27.            operation.params[0].tmpref.size = sizeof(receive_data);
    28.            printf("CA: send read command\n",cmd_type);
    29.            TEEC_InvokeCommand(&session,CMD_STORAGE_READ_AND_DECRYPT,&operation,NULL);
    30.         
    31.            hexdump8("CA: receive data:",receive_data,128);
    32.        } else {
    33.            printf("cmd type %d not support\n",cmd_type);
    34.        }
    35.         
    36.        TEEC_CloseSession(&session);
    37.        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.         
    7.           size_t output_len = 0;
    8.           uint8_t *tmp_data_buf = NULL;
    9.         
    10.           if ((data == NULL) || (len != 128))
    11.           {
    12.               return TEE_ERROR_BAD_PARAMETERS;
    13.           }
    14.         
    15.           output_len = len;
    16.         
    17.           tmp_data_buf = TEE_Malloc(len, 0);
    18.           if (!tmp_data_buf)
    19.           {
    20.               LOG_ERR("TEE Malloc buffer failed");
    21.               return TEE_ERROR_OUT_OF_MEMORY;
    22.           }
    23.         
    24.           LOG_INFO("read data from persistent object.");
    25.         
    26.           res = TEE_OpenPersistentObject(TEE_STORAGE_PRIVATE, (void*)obj_name,
    27.                 sizeof(obj_name), flags | TEE_DATA_FLAG_SHARE_READ |
    28.                 TEE_DATA_FLAG_ACCESS_WRITE_META, &dataObj);
    29.           if (res != TEE_SUCCESS)
    30.           {
    31.               LOG_ERR("TEE_OpenPersistentObject failed");
    32.               goto out;
    33.           }
    34.         
    35.           res = TEE_ReadObjectData(dataObj, tmp_data_buf, len, &output_len);
    36.           if (res != TEE_SUCCESS)
    37.           {
    38.               LOG_ERR("read object failed");
    39.               goto out;
    40.           }
    41.           hexdump8("TA: data from storage with encrpyt",tmp_data_buf,output_len);
    42.           LOG_INFO("read data success.");
    43.         
    44.           LOG_INFO("decrypt data to ree buffer.");
    45.           res = TEE_AllocateOperation(&operation, TEE_ALG_AES_CBC_NOPAD,
    46.                 TEE_MODE_DECRYPT, 256);
    47.           if (res != TEE_SUCCESS)
    48.           {
    49.               LOG_ERR("allocate operation failed, res %x", res);
    50.               goto out;
    51.           }
    52.         
    53.           res = TEE_AllocateTransientObject(TEE_TYPE_AES, 256, &keyObj);
    54.           if (res != TEE_SUCCESS)
    55.           {
    56.               LOG_ERR("allocate key failed, res %x", res);
    57.               goto out;
    58.           }
    59.         
    60.           TEE_InitRefAttribute(attr, TEE_ATTR_SECRET_VALUE, key, sizeof(key));
    61.           res = TEE_PopulateTransientObject(keyObj, attr, 1);
    62.           if (res != TEE_SUCCESS)
    63.           {
    64.               LOG_ERR("populate key failed, res %x", res);
    65.               goto out;
    66.           }
    67.         
    68.           res =  TEE_SetOperationKey(operation, keyObj);
    69.           if (res != TEE_SUCCESS)
    70.           {
    71.               LOG_ERR("set key failed, res %x", res);
    72.               goto out;
    73.           }
    74.         
    75.           TEE_CipherInit(operation, iv, sizeof(iv));
    76.           res = TEE_CipherUpdate(operation, tmp_data_buf, output_len, data,
    77.                 (size_t *)&len);
    78.           if (res != TEE_SUCCESS)
    79.           {
    80.               LOG_ERR("cipher update failed, res %x", res);
    81.               goto out;
    82.           }
    83.         
    84.           res = TEE_CipherDoFinal(operation, NULL, 0, data, (size_t *)&len);
    85.           if (res != TEE_SUCCESS)
    86.           {
    87.               LOG_ERR("cipher dofinal failed, res %x", res);
    88.               goto out;
    89.           }
    90.           LOG_INFO("decrypt data success.");


    █  工程编译


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


    演示工程环境说明:


    开发板型号:LPC55S69-EVK


    MCUXpresso SDK版本:2.6.2


    编译步骤:


    Keil打开示例程序工程
    /boards/lpcxpresso55s69/iseem_examples/demo/cm33_core0/demo_project_s/mdk/demo_project.uvmpw,
    该操作会打开demo_project_s,demo_project_ns两个子工程。


    依次编译demo_project_s和demo_project_ns工程。


    设置demo_project_s为活动工程,连接device,烧写。


    Demo程序演示


    █ 主要功能

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

    CA和TA通过GP TEE ClientAPI通信,TA将CA请求的敏感信息加密后存储到非易失存储中,加密及存储通过TEE Internal API实现。密钥存储在TEE侧,REE侧程序无法获得,保证了密钥的安全。
    程序可根据终端传入的参数来执行对应的功能。输入参数1,将信息存储到安全存储中;输入参数2,将信息从安全存储中读出。

    █ API使用代码示例&编译

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

    █  运行演示

    运行前,先准备串口环境,用于查看运行结果。串口工具有很多,例如putty。

    在串口工具中,设置好芯片设备的COM号以及波特率115200运行即可。
    示例程序在串口中运行结果演示如下:

    9.png

    关于上述演示代码下载,请联系豆荚科技。




    作者:豆荚科技                    文章出处:恩智浦MCU加油站
    签到签到
    回复

    使用道具 举报

    您需要登录后才可以回帖 注册/登录

    本版积分规则

    关闭

    站长推荐上一条 /4 下一条

    Archiver|手机版|小黑屋|恩智浦技术社区

    GMT+8, 2024-4-28 03:59 , Processed in 0.114614 second(s), 20 queries , MemCache On.

    Powered by Discuz! X3.4

    Copyright © 2001-2024, Tencent Cloud.

    快速回复 返回顶部 返回列表