查看: 1571|回复: 2

[分享] 物联网安全之cortex m33 MCU LPC55XX trustzone实操

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

    [LV.8]以坛为家I

    3298

    主题

    6545

    帖子

    0

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    32004
    最后登录
    2024-4-9
    发表于 2020-10-20 16:19:37 | 显示全部楼层 |阅读模式
    物联网安全之cortex m33 MCU LPC55XX trustzone实操


    本文针对ARMv8m架构M33 MCU安全特性使用进行介绍,以LPC55xx系列为例,为大家阐述如何使用Trustzone技术提高物联网设备安全性,适合有一定平台安全基础的物联网设备开发人员、安全方案开发人员。


    背景
    为了提升平台安全性,ARM推出了ARMv8m架构,该架构引入了Trustzone安全扩展,该技术主要利用隔离技术将地址空间划分安全和非安全区域,实现了空间隔离,这里我们称之为安全世界和非安全世界,两个世界的切换/交互通过指令集增加的几条指令实现(SG/BXNX/BLXNX)。该架构主要包括两个系列产品,以m23为代表的baseline产品以及以m33以为代表的mainline产品,前者可以认为是m0的安全版本,后者是m3/m4的安全版本。因为本文主要目的是实操,所以Trustzone具体技术知识不展开讲述。


    现状
    市面上已经有多家芯片厂商推出了m23/m33内核的MCU产品,这气势不亚于当年的cortex m0/m3/m4,因为大家知道安全是制约物联网规模的重要原因之一,而armv8m中的trustzone能够解决设备中大部分安全问题。


    安全目标

    利用这些芯片我们可以实现哪些安全目标?
    11.png
    实操LPC55xx

    设置安全属性单元SAU
    1. /* SAU region boundaries */
    2. #define REGION_0_BASE 0
    3. #define REGION_0_END 0x0FFFFFFFU
    4. #define REGION_1_BASE 0x20000000U
    5. #define REGION_1_END 0xFFFFFFFFU
    6. #define REGION_2_BASE 0x1000FE00U
    7. #define REGION_2_END 0x1000FFFFU
    8.     /* Set SAU Control register: Disable SAU and All Secure */
    9.     SAU->CTRL = 0;

    10.     /* Set SAU region number */
    11.     SAU->RNR = 0;
    12.     /* Region base address */
    13.     SAU->RBAR = REGION_0_BASE & SAU_RBAR_BADDR_Msk;
    14.     /* Region end address */
    15.     SAU->RLAR = ((REGION_0_END & SAU_RLAR_LADDR_Msk) | ((0U << SAU_RLAR_NSC_Pos) & SAU_RLAR_NSC_Msk)) |
    16.                 ((1U << SAU_RLAR_ENABLE_Pos) & SAU_RLAR_ENABLE_Msk);

    17.     /* Set SAU region number */
    18.     SAU->RNR = 0x00000001U;
    19.     /* Region base address */
    20.     SAU->RBAR = REGION_1_BASE & SAU_RBAR_BADDR_Msk;
    21.     /* Region end address */
    22.     SAU->RLAR = ((REGION_1_END & SAU_RLAR_LADDR_Msk) | ((0U << SAU_RLAR_NSC_Pos) & SAU_RLAR_NSC_Msk)) |
    23.                 ((1U << SAU_RLAR_ENABLE_Pos) & SAU_RLAR_ENABLE_Msk);

    24.     /* Set SAU region number */
    25.     SAU->RNR = 0x00000002U;
    26.     /* Region base address */
    27.     SAU->RBAR = REGION_2_BASE & SAU_RBAR_BADDR_Msk;
    28.     /* Region end address */
    29.     SAU->RLAR = ((REGION_2_END & SAU_RLAR_LADDR_Msk) | ((1U << SAU_RLAR_NSC_Pos) & SAU_RLAR_NSC_Msk)) |
    30.                 ((1U << SAU_RLAR_ENABLE_Pos) & SAU_RLAR_ENABLE_Msk);

    31.     /* Force memory writes before continuing */
    32.     __DSB();
    33.     /* Flush and refill pipeline with updated permissions */
    34.     __ISB();
    35.     /* Set SAU Control register: Enable SAU and All Secure (applied only if disabled) */
    36.     SAU->CTRL = 0x00000001U;
    复制代码
    12.png
    根据代码设置和SAU/IDAU规则可以看出,我们将4G空间按照256M大小以此划分为非安全/安全交替的地址,相邻的256M空间映射到同一个物理器件,这种技术成为alias技术,安全世界可以使用安全地址访问硬件,而非安全世界可以使用对应的安全地址访问硬件,驱动程序无需修改。硬件是否允许访问,取决于MPC/PPC等设置。另外0x1000FE00U处预留了512字节的非安全可调用区域,用来存放跳板函数(veneer entry)。


    设置存储器保护控制器MPC
    LPC55xx通过AHB Secure Controller来设置ROM/FLASH/SRAM安全属性
    1. /*设置前64KB flash为安全属性*/
    2.     AHB_SECURE_CTRL->SEC_CTRL_FLASH_ROM[0].SEC_CTRL_FLASH_MEM_RULE[0] = 0x00000033U;
    3.     AHB_SECURE_CTRL->SEC_CTRL_FLASH_ROM[0].SEC_CTRL_FLASH_MEM_RULE[1] = 0;
    4.     AHB_SECURE_CTRL->SEC_CTRL_FLASH_ROM[0].SEC_CTRL_FLASH_MEM_RULE[2] = 0;
    5.    
    6.     /*设置ROM为非安全属性*/
    7.     AHB_SECURE_CTRL->SEC_CTRL_FLASH_ROM[0].SEC_CTRL_ROM_MEM_RULE[0]   = 0;
    8.     AHB_SECURE_CTRL->SEC_CTRL_FLASH_ROM[0].SEC_CTRL_ROM_MEM_RULE[1]   = 0;
    9.     AHB_SECURE_CTRL->SEC_CTRL_FLASH_ROM[0].SEC_CTRL_ROM_MEM_RULE[2]   = 0;
    10.     AHB_SECURE_CTRL->SEC_CTRL_FLASH_ROM[0].SEC_CTRL_ROM_MEM_RULE[3]   = 0;

    11.         /*设置前128KB SRAM为安全属性*/
    12.     AHB_SECURE_CTRL->SEC_CTRL_RAMX[0].MEM_RULE[0]                     = 0;
    13.     AHB_SECURE_CTRL->SEC_CTRL_RAM0[0].MEM_RULE[0]                     = 0x33333333U;
    14.     AHB_SECURE_CTRL->SEC_CTRL_RAM0[0].MEM_RULE[1]                     = 0;
    15.     AHB_SECURE_CTRL->SEC_CTRL_RAM1[0].MEM_RULE[0]                     = 0;
    16.     AHB_SECURE_CTRL->SEC_CTRL_RAM1[0].MEM_RULE[1]                     = 0;
    17.     AHB_SECURE_CTRL->SEC_CTRL_RAM2[0].MEM_RULE[0]                     = 0;
    18.     AHB_SECURE_CTRL->SEC_CTRL_RAM2[0].MEM_RULE[1]                     = 0;
    19.     AHB_SECURE_CTRL->SEC_CTRL_RAM3[0].MEM_RULE[0]                     = 0;
    20.     AHB_SECURE_CTRL->SEC_CTRL_RAM3[0].MEM_RULE[1]                     = 0;
    21.     AHB_SECURE_CTRL->SEC_CTRL_RAM4[0].MEM_RULE[0]                     = 0;
    22.     AHB_SECURE_CTRL->SEC_CTRL_USB_HS[0].MEM_RULE[0]                   = 0;
    复制代码
    这样设置后,我们可以将安全代码链接到0x1000 0000处,大小限制64KB,数据链接到0x3000 0000处,大小限制128KB;非安全代码链接到0x0001 0000处,大小限制567KB.


    设置外设保护控制器PPC
    1.   //--- Security level configuration of peripherals --------------------
    2.     AHB_SECURE_CTRL->SEC_CTRL_APB_BRIDGE[0].SEC_CTRL_APB_BRIDGE0_MEM_CTRL0 = 0x00000033U;
    3.     AHB_SECURE_CTRL->SEC_CTRL_APB_BRIDGE[0].SEC_CTRL_APB_BRIDGE0_MEM_CTRL1 = 0;
    4.     AHB_SECURE_CTRL->SEC_CTRL_APB_BRIDGE[0].SEC_CTRL_APB_BRIDGE0_MEM_CTRL2 = 0;
    5.     AHB_SECURE_CTRL->SEC_CTRL_APB_BRIDGE[0].SEC_CTRL_APB_BRIDGE1_MEM_CTRL0 = 0;
    6.     AHB_SECURE_CTRL->SEC_CTRL_APB_BRIDGE[0].SEC_CTRL_APB_BRIDGE1_MEM_CTRL1 = 0;
    7.     AHB_SECURE_CTRL->SEC_CTRL_APB_BRIDGE[0].SEC_CTRL_APB_BRIDGE1_MEM_CTRL2 = 0;
    8.     AHB_SECURE_CTRL->SEC_CTRL_APB_BRIDGE[0].SEC_CTRL_APB_BRIDGE1_MEM_CTRL3 = 0;
    9.     AHB_SECURE_CTRL->SEC_CTRL_AHB0_0_SLAVE_RULE                            = 0x03000000U;
    10.     AHB_SECURE_CTRL->SEC_CTRL_AHB0_1_SLAVE_RULE                            = 0;
    11.     AHB_SECURE_CTRL->SEC_CTRL_AHB1_0_SLAVE_RULE                            = 0;
    12.     AHB_SECURE_CTRL->SEC_CTRL_AHB1_1_SLAVE_RULE                            = 0;
    13.     AHB_SECURE_CTRL->SEC_CTRL_AHB2[0].SEC_CTRL_AHB2_0_SLAVE_RULE           = 0;
    14.     AHB_SECURE_CTRL->SEC_CTRL_AHB2[0].SEC_CTRL_AHB2_1_SLAVE_RULE           = 0;
    15.     AHB_SECURE_CTRL->SEC_GPIO_MASK0 = 0xFFFFFFFFU;
    16.     AHB_SECURE_CTRL->SEC_GPIO_MASK1 = 0xFFFFFFFFU;
    复制代码
    设置flexcomm、iocon、syscon外设为安全属性,其他为非安全属性,flexcomm用来安全世界串口打印,iocon用来设置端口、syscon用来设置模块上下电。


    设置中断安全属性TZIC
    1. NVIC->ITNS[0] = 0;
    2.     NVIC->ITNS[1] = 0;
    复制代码
    设置所有IRQ中断属性为非安全属性。


    非安全世界访问安全世界函数
    1. /* Non-secure callable (entry) function, calling a non-secure callback function */
    2. __attribute__((cmse_nonsecure_entry)) uint32_t StringCompare_NSE(volatile callbackptr callback, char const *s1, char const *s2)
    3. {
    4.     callbackptr_NS callback_NS;
    5.     size_t  string_length;
    6.     int result;

    7.     /* Input parameters check */
    8.     /* Check whether function pointer is located in non-secure memory */
    9.     callback_NS = (callbackptr_NS)cmse_nsfptr_create(callback);
    10.     if (cmse_check_pointed_object((int *)callback_NS, CMSE_NONSECURE) == NULL)
    11.     {
    12.         PRINTF("The callback is not located in normal world!\r\n");
    13.         abort();
    14.     }
    15.     /* Check whether string is properly terminated */
    16.     string_length = strnlen(s1, MAX_STRING_LENGTH);
    17.     if ((string_length == MAX_STRING_LENGTH) && (s1[string_length] != '\0'))
    18.     {
    19.         PRINTF("First string too long or invalid string termination!\r\n");
    20.          abort();
    21.     }
    22.     /* Check whether string is properly terminated */
    23.     string_length = strnlen(s2, MAX_STRING_LENGTH);
    24.     if ((string_length == MAX_STRING_LENGTH) && (s2[string_length] != '\0'))
    25.     {
    26.         PRINTF("Second string too long or invalid string termination!\r\n");
    27.          abort();
    28.     }
    29.     PRINTF("Comparing two string as a callback to normal world\r\n");
    30.     PRINTF("String 1: ");
    31.     PRINTF(s1);
    32.     PRINTF("String 2: ");
    33.     PRINTF(s2);
    34.     result = callback_NS(s1, s2);
    35.     return result;
    36. }
    复制代码
    这是一个在安全世界实现的字符串比较代码,通过cmse_nonsecure_entry attribute属性来提示编译器在非安全可调用区域(上面SAU配置过)生成跳板,跳板也很简单,每个跳板有两条32位指令组成:
    1. sg
    2. bx StringCompare_NSE
    复制代码
    上面预留了512个字节,能够存放64个跳板函数,跳板相关的链接脚本如下:
    1. #define  m_veneer_table_start          0x1000FE00U
    2. #define  m_veneer_table_size           0x200
    3. LR_m_veneer_table m_veneer_table_start m_veneer_table_size {
    4.   ER_m_veneer_table m_veneer_table_start m_veneer_table_size {; veneer table
    5.     *(Veneer$CMSE)
    6.   }
    7. }
    复制代码

    所以非安全世界要想访问安全世界函数很简单,只需要将函数设置为cmse_nonsecure_entry 属性即可。值得注意的是,由于跳板函数只能通过R0~R3传递数据(两个世界的栈是独立的),所以跳板函数参数不要超过4个。非安全世界只能通过跳板函数访问安全世界提供的服务。

    安全世界访问非安全世界函数
    安全世界可以访问安全世界的资源(数据和代码),但是不能直接执行非安全世界代码,需要通过一下方式调用非安全世界函数:

    1. typedef int (*callbackptr_NS)(char const * s1, char const * s2)
    2. __attribute__((cmse_nonsecure_call));

    3.   callbackptr_NS callback_NS;
    4.   callback_NS = (callbackptr_NS)cmse_nsfptr_create(callback);
    5.   callback_NS(s1, s2);
    复制代码

    callback是非安全世界函数地址,通过cmse_nsfptr_create函数将其转换为cmse_nonsecure_call属性的函数,这样编译器会将调用指令有blx替换成blxnx,触发安全世界的切换。

    值得注意的问题

    A0版本芯片不要开secure boot,不要写prince key

    A0版本PFR驱动和ROM不一致

    Hashcrypt设置为安全后需要lock才能生效

    使用flash驱动时需要将ROM对应区域划分为安全

    使用最新的sdk(目前为2.7.1,对应keil DFP 12.1.1)

    以上是LPC55xx平台安全属性配置以及两个世界的交互介绍,这些只是我们开发过程中比较简单的一部分,更深层次的使用问题可以在留言区留言






    签到签到
    回复

    使用道具 举报

  • TA的每日心情

    2024-2-5 12:06
  • 签到天数: 627 天

    [LV.9]以坛为家II

    94

    主题

    1628

    帖子

    2

    版主

    Rank: 7Rank: 7Rank: 7

    积分
    4429

    热心会员

    最后登录
    2024-2-5
    发表于 2020-10-21 08:58:10 | 显示全部楼层
    厉害,谢谢楼主分享~
    哎...今天够累的,签到来了~
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    开心
    2024-4-10 22:38
  • 签到天数: 1335 天

    [LV.10]以坛为家III

    88

    主题

    4292

    帖子

    12

    版主

    Rank: 7Rank: 7Rank: 7

    积分
    9049
    最后登录
    2024-4-13
    发表于 2020-10-22 11:09:37 | 显示全部楼层
    这个LPC55S69的可玩性还是非常大的啊
    该会员没有填写今日想说内容.
    回复 支持 反对

    使用道具 举报

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

    本版积分规则

    关闭

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

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

    GMT+8, 2024-4-20 15:47 , Processed in 0.126553 second(s), 24 queries , MemCache On.

    Powered by Discuz! X3.4

    Copyright © 2001-2021, Tencent Cloud.

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