托管与非托管C:提高嵌入式应用程序的安全性和可靠性
安全性和可靠性都是任何值得信赖的系统的关键组成部分。构建既安全又可靠的嵌入式应用程序是很困难的,因为它很可能是用C或c++语言编写的。即使过了这么多年,C和c++仍然是嵌入式软件开发的首选语言。C或c++程序的执行称为“非托管”,这意味着执行不受任何运行时的管理。
通常,在“托管”世界中,通常称为“运行时”的环境负责将代码编译成机器代码,然后执行它。此外,运行时还提供了一些重要的服务,如自动内存管理、安全边界、类型安全等。但是这种保护只适用于高级编程语言,比如。net框架及其运行时CLR。
相反,非托管代码由操作系统执行,并直接在底层硬件上运行。其他的一切,从内存管理到安全考虑,都是程序员的负担。
如何提高嵌入式应用程序的安全性?
安全风险来自那些积极尝试利用系统漏洞的攻击者。在进行安全性设计时,必须假设对手可能会在任何时候试图使事情出错。以下是需要考虑的关键因素:
- 设计简洁
保持系统设计尽可能简单是提高系统安全性的最佳方法之一。更简单的设计减少了攻击面,减少了意外系统交互的可能性。
- 安全启动
安全启动是一种功能,系统仅使用设备制造商信任的软件来验证设备启动。它利用设备信任锚提供的签名,这是用于为设备代码签名的公钥基础设施(PKI)根的公共部分。当嵌入式系统启动时,将使用此公钥和相应的信任链验证引导映像,以确保启动时软件未被篡改。
- HSM的使用
硬件安全模块(HSM)处理加密和解密任务,并嵌入操作系统和应用程序管理。这些模块通常以系统单片或直接连接到嵌入式系统的插件卡的形式出现。在制造过程中,可以在芯片上生成私钥,也可以将私钥注入每个芯片中,作为信任的根。当私钥通过公钥基础设施或PKI认证时,安全设备标识符可以成为可信设备连接的基础组件。
如何提高嵌入式应用的可靠性?
主要的可靠性风险本质上不是恶意的——例如,物理设备故障。在为可靠性进行设计时,必须假设在某个时间点可能会出错。程序员可以采用许多技术来使嵌入式应用程序可靠:
- 故障安全的实现
在嵌入式编码中,程序员几乎负责所有的事情。因此,为所有可能的系统故障实现适当的故障安全机制以避免错误发生时的非理性行为是很重要的。
- 检查数据完整性
对于扩展的运行时,检查关键变量和数据结构的完整性非常重要。这可以通过在内存中保存CRC或校验和并定期验证状态来实现。
- 避免动态内存分配
典型的嵌入式系统没有足够的带宽来提供碎片内存。在这种资源受限的嵌入式系统中,内存的动态分配可能导致内存泄漏,因此应该避免。
- 使用内存保护单元
内存保护单元,通常称为MPU,是许多基于arm的微控制器中存在的可选组件。MPU通过设置本地权限和属性来分隔内存中的部分。这种机制在实际场景中有几种用途,例如当CPU在用户模式下运行时防止访问内存,或者防止从RAM中的可写位置获取执行代码。当MPU被启用时,它通过在违反规则时触发内存异常中断来强制执行这些规则。
- 看门狗的使用
大多数现代微处理器都支持看门狗定时器,以提供从某些类型的系统挂起中恢复的能力。它可以在几毫秒内识别软件冻结并适当地重置系统,防止进一步的系统故障。
安全性和可靠性有很多共同之处——这两者都是所有信息系统的固有属性,一开始牺牲它们是很诱人的,但后来修复起来代价高昂。尽管开发者充满希望和乐观,嵌入式系统还是会动摇他们对微控制器的信心。每一个比特和字节都需要维护和细致的奉献,以确保随着时间的推移,软件与相关硬件一起正确安全地运行。这几种方法可能不足以设计安全性和可靠性;基于安全性和可靠性的重要性,必须选择其他合适的方法。
作者简介
汽车软件专家,在软件定义汽车、智能汽车照明、数字仪表盘、车载信息娱乐和导航系统的应用和中间件开发方面拥有12年的经验。
让我们知道你对这篇文章的看法。
请在下面发表评论。