使用ARM Trustzone从非安全代码执行安全功能
扫描二维码
随时随地手机看文章
传统的嵌入式软件应用程序存在于单个连续的空间中,具有唯一的ID,内存和代码均坐在一起且易于访问。当然,这使得黑客一旦踏入门,就可以很容易地访问整个系统。嵌入式系统安全的关键是隔离。开发人员可以改善隔离的一种新方法是利用ARM®M23/33微控制器中的新Trustzone®功能。在这篇文章中,我将介绍读者如何使用Trustzone保护安全功能,但仍能从非安全内存区域访问它们。
在介绍细节之前,讨论有关Trustzone的一些信息将很有用。 TrustZone是ARMV-8体系结构的安全硬件扩展,可提供硬件隔离,从而创建一个可以从中执行软件的安全和非安全区域。这两个区域都有自己的MSP,PSP,MPU和安全区域,甚至有一些非银行寄存器在非安全区域中无法访问。从安全到非安全的过渡,反之亦然,在三个时钟周期内的硬件中都完成了,因此开发人员无需担心添加任何额外的代码来处理过渡;但是,开发人员确实需要关注自己可以正确控制哪些安全功能可以从非安全区域访问。
Trustzone允许开发人员除了指定在安全区域中应执行哪些内存区域,中断和外围设备,还可以安全启动其微控制器。
默认情况下,在非安全区域中执行的代码无法访问安全区域。在安全区域中放置内存位置的任何尝试都将导致异常。问题在于,开发人员可能需要调用安全功能,例如加密库函数,或者可能被认为是安全的外围驱动程序。为此,开发人员需要在其安全的应用程序项目中创建一个接口,该项目成为非安全和安全代码区域之间安全网关的一部分,并允许执行安全函数。安全功能在安全或受信任的区域中执行,使其与非安全代码隔离。
在安全代码和非安全代码之间创建接口是使用ARM_CMSE库完成的,该库是C库扩展程序,以支持安全的可执行文件。该库包含用于创建功能指针的定义,以指向非安全内存,例如cmse_nsfptr_create。编译器本身(例如Keil MDK)还包括诸如CMSE_NONSECURE_ENTRY之类的新编译器属性,该属性告诉编译器,相关函数位于安全内存中,但可以从非安全内存中访问。
创建可访问的安全功能的过程很简单。首先,开发人员可以像其他任何功能一样定义其安全功能,只是在其安全项目中定义了该功能。可以在下面看到一个安全功能:
int mySecureFunction(funcptr_ns,int data){funcptr_ns callback_ns; callback_ns =(funcptr_ns)cmse_nsfptr_create(callback); data = callback_ns(data); Return data;}
有关此代码有几个有趣的观点:
· 该代码利用来自ARM_CMSE.H的funcptr_ns类型,该类型定义了用于访问非安全内存的功能指针的类型
· 从安全区域访问非安全回调函数需要调用CMSE_NSFPTR_CREATE,这将允许在安全区域中访问非安全函数
· Trustzone代码通常使用NS表示非安全,并表示安全
· 如书面,非安全区域无法访问此代码
为了纠正此代码是完全安全且不可访问的事实,开发人员需要使用cmse_nonsecure_entry属性。然后,安全功能定义将从以下方式变化:
int mysecurefunction(funcptr_ns,int data){…}
到
int mysecurefunction(funcptr_ns,int data)__attribute __(((cmse_nonsecure_call))){…}
添加属性CMSE_NONSECURE_CALL告诉编译器,可以从非安全内存访问此功能。这将允许使用安全的网关指令访问该功能。此外,当安全函数完成执行并准备好跳回非安全代码时,将清除任何非银行寄存器,即在安全区域和非安全区域之间共享的寄存器。清除寄存器可以防止可能存储在非银行寄存器中的任何安全数据暴露于非安全区域。
在这一点上,开发人员将能够编译安全库,然后从其非安全项目中,包括其功能的标头文件,并拨打迈塞克雷功能。
在尝试保护嵌入式系统时,将关键功能与应用程序的其余部分隔离至关重要。应仔细考虑,以决定应隔离应用程序中的哪些功能,甚至将使用哪些机制。 Trustzone是一种嵌入式软件开发人员可以开始用于提高产品安全性的工具。