【LPC55 系列】LPC55S69 开发之 TrustZone Demo 介绍说明

關鍵字 :NXPTrustZone

TrustZone Demo 使用说明文档

  • TrustZone 简介

TrustZone是ARM公司针对消费电子设备设计的一种硬件架构,其目的是为消费电子产品构建一个安全框架来抵御各种可能的攻击。

在处理器架构上,每个物理的处理器核提供两个虚拟核,一个是非安全核(Non-secure, NS),另一个是安全核(Secure),在这二者之间切换的机制叫做monitor模式。NS核只能访问NS的系统资源,而安全核能访问所有资源。普通世界的软件可以使用SMC指令或者通过硬件异常机制的一个子集来进入到monitor模式。

 

  • LPC55S69 TrustZone 使用说明
  • 在 Security 工程中借助开发工具 MCUXpresso IDE 配置工具设置 TEE (Trusted Execution Environment)用户内存区域的设置
    • 设置 Secure Code Area (安全代码区域) 和 Size ,设置安全级别为 S-Priv
    • 设置 Secure Stack and Data Area 和 Size ,设置安全级别为 S-Priv
    • 设置 Veneer Table Area 和Size ,设置安全级别外 NSC-Priv
    • 设置 Non-secure Code Area 和 Size ,设置安全级别为 NS-User
    • 设置 Non-secure Stack and Data Area 和 Size ,设置安全级别为 NS-User

 

  • 内存安全访问配置(主要设置安全属性单元 SAU 和 内存保护单元 MPC)
    • 配置安全属性单元SAU ,一般SAU 与 IDAU (实施定义属性单元)共同决定内存的类别:安全 、 非安全 、 非安全可调用

IDAU 一般规定好了内存的类型,用户无须配置它,它的规则是 :

  • Address 0x0000_0000 to 0x1FFF_FFFF
    – Non-secure (always)
  • Address 0x2000_0000 to 0xFFFF_FFFF
    – Non-secure if HADDR[28]=0
    – Secure if HADDR[28]=1

所以用户更改内存的属性类型只要通过改变 SAU 的安全级别,然后综合两者的级别等级就可以实现配置用户所需要的内存属性类型

配置 SAU :按照用户内存区域划分好的类型进行配置,使得内存的属性类型符合用户区域的属性(安全 、 非安全 、 安全可调用,也就是实现用户安全代码 、 堆栈和数据内存为安全类型,非安全代码 、 堆栈和数据内存为非安全类型,Veneer Table 为非安全可调用类型 ),选择安全级别为 NS 或 NSC

  • 配置 MPC

          内存保护单元 MPC 的配置主要是决定内存的访问许可,通过与内存区域的安全级别进行对比决定是否能够访问该内存地址

          MPC 可以设置四个安全级别类型 :S-User 、 S-Priv  、 NS-User 、 NS-Priv

          根据 SAU & IDAU 所确定的内存安全类型级别,配置 MPC 的安全级别类型,使其一致

  • 其他选项的配置,一般选择默认,由此点击更新代码就可以生成 h 和 tzm_config.c 文件供用户 secure 工程主程序调用
  • Secure Code Project 属性配置

2.1 安全世界代码工程的属性配置Build MCU settings

2.1.1 安全代码所在 flash 首地址和代码空间大小 Size

2.1.2 非安全可调用函数代码所在 flash 首地址和空间大小 Size

2.1.3 安全代码的堆栈和数据所在的 RAM 的首地址和空间大小 Size

 

2.2 安全世界代码工程的属性配置Build Settings

2.2.1 MCU C compiler 的架构(Architecture)选择:选择 Cortex-M33

2.2.2 MCU C compiler 的 TrustZone 工程类型:Secure

2.2.3 MCU Link 的架构(Architecture)选择 Cortex-M33

2.2.4 MCU Link 的TrustZone : TruseZone 工程类型为 Secure

      安全网关导入库选择 SG-Veneer_table memory region

 

2.3 MCU Debugger TrustZone 勾选使能非安全的预编程镜像

    选择非安全世界代码的工程问文件

  • Non Secure Code Project 属性配置

3.1 非安全世界代码工程的属性配置Build MCU settings

3.1.1 非安全代码所在 flash 首地址和代码空间大小 Size

3.1.2 非安全代码的堆栈和数据所在的 RAM 的首地址和空间大小 Size

 

3.2 非安全世界代码工程的属性配置Build Settings

3.2.1 MCU C compiler 的架构(Architecture)选择:选择 Cortex-M33

3.2.2 MCU C compiler 的 TrustZone 工程类型:Non-Secure

3.2.3 MCU Link 的架构(Architecture)选择 Cortex-M33

3.2.4 MCU Link 的TrustZone : TrustZone 工程类型类型为 Non-Secure

      安全网关导入库选择 :工作区间的安全代码工程的镜像文件内

  • TrustZone 安全代码文件c

4.1 安全世界代码需要在执行main 函数前进入 TrustZone 的内存配置操作,所以调用弱函数 SystemInitHook() ,把TrustZone 初始化函数放在里面执行,在调试时,执行启动文件的时候就会调用该系统初始化的函数,所以无需将其放在 main() 函数中去执行,其他如一般工程文件一样,正常配置外设即可

 

4.2 跳转非安全世界代码的条件入口 :

4.2.1 首先将之前配置的非安全代码所在 Flash 的首地址定义保留,方便调用

 

 

#define DEMO_CODE_START_NS         0x00010000


#define NON_SECURE_START DEMO_CODE_START_NS

      重定义非安全回调函数的功能,这是ARM 定义的修饰的语句,编译会转化为汇编语言跳转到非安全世界去执行代码,用户从安全世界切换到非安全世界的入口地址变量需要利用这一语句去定义:

typedef void (*funcptr_ns) (void) __attribute__((cmse_nonsecure_call));

funcptr_ns ResetHandler_ns;

4.2.2 在执行完安全世界代码后,在 main() 函数里添加调转入口:

      利用上述定义的变量进行以下操作:

      main() 函数中安全的代码函数执行完毕后,设置跳转入口 :

/* Set non-secure main stack (MSP_NS) */

__TZ_set_MSP_NS(*((uint32_t *)(NON_SECURE_START)));



/* Set non-secure vector table */

SCB_NS->VTOR = NON_SECURE_START;



/* Get non-secure reset handler */

ResetHandler_ns = (funcptr_ns)(*((uint32_t *)((NON_SECURE_START) + 4U)));



/* Jump to normal world */

ResetHandler_ns();

配置好上述的语句,代码执行到这里会切换到非安全世界的 main() 中去执行语句。

 

  • TrustZone 安全代码文件 c

这个文件下的函数主要是供非安全世界代码语句进行调用的,并且该文件的函数主要的执行代码语句是在安全世界内的,由于非安全世界不能直接调用,所以需要设置这一个跳转板供非安全世界去调用,所以该文件的函数需要直接被调用的都需要重新定义修饰一下,在函数的前面增加 __attribute__ ((cmse_nonsecure_entry))

 

  • TrustZone 非安全代码文件c

6.1 TrustZone 非安全世界的工程中,不需要去设置 TrustZone 内存区域的代码

    但是在进入 main() 函数之前,需要定义一个系统的初始化函数

void SystemInit(void)

{

}

配置这一语句就可以了,如果缺失该语句,从安全世界无法调转到非安全世界来执行代码,会出现 HardFault

 

6.2 在main() 函数中无需进行初始化,直接调用 Veneer_table.c 中的打印和比较语句

  之前尝试在 main() 函数中初始化 GPIO 、USART 、PININT 都出现 HardFault,而且尝试在 SystemInit() 中去初始化它们,结果一样出现 HardFault

6.3 在main.c 文件中,需要包含头文件 veneer_table.h 以及其他在本工程中的头文件

 

  • TrustZone 两个工程的编译和执行

7.1 TrustZone 工程文件中,一般先编译 非安全世界的工程代码,

然后再编译安全世界的工程代码

7.2 TrustZone 工程先执行安全世界的代码语句,执行完成后,调转到非安全世界去执行非安全代码语句,当非安全世界代码语句调用到安全世界的函数,会用到安全网关向量表进入到 veneer_table.c 去调用打印函数,执行完就停留在非安全世界的 while(1); 死循环中。

  • 在 demo 例程中,安全世界使用一个滴答定时中断,使得函数可以中断返回安全世界中执行相应的代码语句,执行完毕会重新切换到非安全世界
  • TrustZone 中,还有一个 Secure GPIO 的作用,目的就是让在安全世界中所配置的 IO 引脚收发的信息不被非安全世界的代码读取,只要将 GPIO 的对应引脚配置为掩码,然后当按下该 IO 口按键,非安全世界无法读取该 IO 引脚的状态,从而保护了信息通信的外泄。

在安全世界代码中,也可以配置安全 GPIO 来区别普通的 GPIO ,使得 GPIO 的状态可以通过 Secure GPIO 来读取。

8. 参考


END TrustZone

★博文內容均由個人提供,與平台無關,如有違法或侵權,請與網站管理員聯繫。

★文明上網,請理性發言。內容一周內被舉報5次,發文人進小黑屋喔~

評論