4 Lifecycle stage
Device生命周期是TRAVEO™ T2G MCU安全的一个关键方面。生命周期阶段遵循严格的不可逆过程,由熔断eFuse(将保险丝的值从“0”更改为“1”)决定。该系统用于按照客户要求的级别保护内部设备数据和代码。图1显示了TRAVEO™ T2G MC通常支持的生命周期阶段。
4.1 NORMAL_PROVISIONED
这是Device在工厂完成调整和测试后的生命周期阶段。所有配置和微调信息都已完成。SFlash中已编程设定了有效的Flash boot代码。为了允许OEM检查工厂中trims、flash boot和其他对象的数据完整性,这些对象的hash(SHA-256截断为128位)存储在eFuse中。该hash被称为FACTORY_hash。客户在此阶段接收零件。
4.2 SECURE
此阶段是安全设备的生命周期阶段。在转换到此阶段之前,eFuse中的SECURE_HASH必须已熔断,并且Code Flash中必须已编程了有效的APP代码。在此阶段,将保护状态设置为SECURE,并部署SECURE访问限制。安全设备只有在其Flash boot和app代码的身份验证成功时才会启动。
当从NORMAL_PROVISIONED生命周期阶段转换到SECURE或SECURE_W_DEBUG生命周期阶段时,由SROM固件计算SECURE_HASH并将其写入eFuse。
请参阅附录H-向安全生命周期阶段转换的示例程序和脚本。
注意:生命周期阶段是不可逆转的。因此,建议在转换到安全生命周期阶段之前对编程过程进行评估,并对应用程序进行身份验证
4.3 SECURE_W_DEBUG
这个阶段与安全生命周期阶段相同,只是设备允许调试。在转换到此阶段之前,电子保险丝中的SECURE_HAH必须已熔断,并且代码闪存中必须已编程了有效的应用程序代码。在此阶段,保护状态设置为SECURE,但会部署NORMAL访问限制以启用调试。当ROM引导或闪存引导过程中出现身份验证失败时,保护状态设置为“安全”,但会部署NORMAL访问限制,启用SWD/JTAG引脚,并且不会转换为“DEAD”状态。
不允许从SECURE_W_DEBUG转换到SECURE。
SECURE_W_DEBUG部件仅由开发人员和软件测试人员使用。
设备不应在此生命周期阶段发货。
请参阅附录H-向SECURE_W_DEBUG生命周期阶段过渡的示例程序和脚本。
4.4 RAM
此阶段允许执行故障分析(FA)。当客户希望对零件进行故障分析时,客户会将零件转换到RMA生命周期阶段。客户在调用TransitiontoRMA API(API功能将device转换为RMA的系统调用)之前擦除所有敏感数据。
当调用系统调用以过渡到RMA时,客户必须创建一个证书,授权将具有特定唯一ID的零件过渡到RMA生命周期阶段。客户将使用与用户app image签名时使用的私钥相同的私钥对证书进行签名。数字签名的验证使用与flash boot在验证用户应用程序时使用的算法相同的算法。存储在SFlash中的相同公钥(由OEM注入)用于验证。
当零件在RMA生命周期阶段reset时,boot将设置访问限制,使DAP只能访问系统AP、用于进行系统调用的IPC MMIO寄存器和用于通信的足够RAM。然后,它将等待来自DAP的系统调用(OpenRMA API)以及授权证书。boot过程在成功执行OpenRMA API之前不会启动任何固件。命令成功后,存储在eFuse中的生命周期阶段不能从RMA更改。每次reset部件时,必须先成功执行OpenRMA API,然后才能使用部件。要执行OpenRMA API,客户必须创建使用其私钥签名的证书。
注意:处于DEAD保护状态或CORRUPTED生命周期阶段的设备无法转换至RMA生命周期阶段。只能从SECURE或SECURE_W_DEBUG生命周期阶段过渡到RMA。因此如果是NORMAL_PROVISIONED生命周期阶段,设备需要先转换到SECURE或SECURE_W_DEBUG,然后再转换到RMA。
注意:运行TransitiontoRMA API需要RSA密钥对(私钥和公钥)。私钥用于创建证书,公钥用于对证书进行身份验证。公钥必须提前写入设备。
注意:运行OpenRMA API可能需要RSA密钥对(私钥和公钥)。私钥用于创建证书,公钥用于对证书进行身份验证。公钥必须提前写入设备。然而,如果设备从SECURE_WITH_DEBUG生命周期阶段转换到RMA生命周期阶段,则跳过OpenRMA,并且设备不等待OpenRMA执行。因此,对设备的完全访问将在没有证书的情况下解锁,并且将执行用户应用程序。
注意:在执行TransitiontoRMA和OpenRMA API的过程中可能会出现ECC错误。因此,在TransitiontoRMA API执行期间和OpenRMA API执行之后,用户软件应小心处理故障。
如果设备由于意外的身份验证失败(如硬件故障或敏感数据擦除)而转换到DEAD保护状态,并且无法转换到RMA生命周期阶段,您可以通过准备第二个应用程序软件来解决此问题,只允许转换到RMA生命周期阶段。起始地址在TOC2中定义。如果第一应用程序软件出现故障或擦除了所有第一应用程序,则Flash Boot可以运行第二应用程序。然而,如果第二应用软件的认证也被破坏,则设备不能转换到生命周期阶段。第二应用软件可以专门用于RMA管理。建议第二应用程序软件位于与第一应用程序软件不同的扇区中,从而只有第一应用程序可以被擦除。TOC2详细信息见TOC2,第二应用软件实现见附录I——第二应用程序软件实现。然而,如果设备满足引导加载程序启用条件,则当所有第一应用程序都已被擦除时,第二应用程序无法被激活。有关引导加载程序启用条件,请参阅TOC2。
如果第一个应用程序全部被擦除,它可以转换到DEAD状态。有两种选择:
•未实施第二个应用程序的情况
−擦除后,准备并重新编程已签名的伪代码和数字签名替换第一个应用程序软件。此伪代码可以专门用于RMA管理。
•实施第二个应用程序的案例
−擦除后,准备并重新编程伪应用程序头替换第一个应用程序软件。
有关应用程序头的实现,请参见附录J-伪应用程序头实现。
−禁用引导加载程序。(TOC2_FLAGS.FB_BOOTLOADER_CTL=0x2)仅在NORMAL_PROVISIONED生命周期阶段可用
4.4.1 Requirements for transition to RMA lifecycle stage
本节描述了用于过渡到RMA生命周期阶段的TransitiontoRMA和OpenRMA API执行的条件。
4.4.1.1 TransitiontoRMA API
在TransitiontoRMA API执行期间可能会发生ECC错误。因此,在触发TransitiontoRMA API之前,用户软件不应为Crypto和SRAM0 ECC错误配置故障结构。软件将忽略TransitiontoRMA API执行期间报告的ECC错误。以下故障需要屏蔽:
• CYT2B 系列故障号:
- CPUSS_RAMC0_C_ECC (Fault number = 58)
- CPUSS_RAMC0_NC_ECC (Fault number = 59)
- CPUSS_CRYPTO_C_ECC (Fault number = 64)
- CPUSS_CRYPTO_NC_ECC (Fault number = 65)
有关故障编号,请参阅设备特定数据表[1];有关屏蔽故障的示例,请参阅运行API。此外,处于RMA生命周期阶段的设备在每次reset时都需要OpenRMA API。设备特定故障,如硬件故障,故障报告触发reset。执行OpenRMA后,设备无法打开RMA。触发TransitiontoRMA API之前有两个选项:
•提前屏蔽触发重置的设备特定故障。此外,还要屏蔽在OpenRMA之后运行的应用程序软件。
•重新编程仅执行RMA管理的伪代码。
证书和数字签名必须写入SRAM才能运行TransitiontoRMA API。使用TransitiontoRMA API将设备移动到RMA生命周期阶段时,必须从[System RAM0 start address+4KB]放置证书和数字签名等参数。
有关证书和数字签名,请参阅附录E-向RMA生命周期阶段过渡。
4.4.1.2 OpenRMA API
在OpenRMA API执行期间也可能发生ECC错误。因此,在OpenRMA API之后运行的软件不应为加密和SRAM0 ECC错误配置错误结构。软件将忽略报告的ECC故障。有关需要屏蔽的故障,请参阅TransitiontoRMA API,有关屏蔽故障的示例,请参阅运行API。
RMA生命周期阶段的保护状态指示为VIRGIN。因此,软件可以通过CPUS_PROTECTION寄存器知道设备是否处于RMA生命周期阶段。有关更多详细信息,请参阅寄存器TRM[2]。
证书和数字签名必须写入SRAM才能运行OpenRMA API。在设备过渡到RMA生命周期阶段后,系统DAP只能通过系统DAP MPU访问IPC MMIO和1/16的系统RAM0。使用OpenRMA API时,证书和数字签名等参数必须放置如下:
•SRAM 0大小大于64 KB的设备:参数必须放置在从[System RAM0 start address+4KB]到[System RAM 0 start address+1/16 of System RAM0 size]。
•SRMA0小于等于64 KB的设备:参数必须放置在[System RAM0 start address+2KB]的600字节以内。证书和签名地址为24字节,数字签名为512字节。(RSA-4K)
有关证书和数字签名,请参阅附录E-向RMA生命周期阶段过渡。
有关故障编号和系统RAM0大小,请参阅设备特定数据表[1]。
4.5 CORRUPTED
如果在读取决定生命周期阶段的eFuse位时检测到读取错误,则设备处于该生命周期阶段。设备将进入DEAD保护状态,并且只能通过SYS-AP读取IPC MMIO。不允许其他访问。
5 Boot sequence and chain of trust
CoT本质上是boot序列的一部分。它从信任的root开始,是存储在ROM中的初始boot代码,不能更改。
5.1引导顺序
在大多数情况下,引导序列和验证序列是相同的。图2显示了CM0+是如何从reset开始运行的。复位后,CM0+从ROM引导开始执行。ROM boot验证SFlash。SFlash验证完成后,执行跳转到flash boot,并根据保护状态的需要配置DAP。请注意,颜色编码描述了数据和代码所在的内存类型。
flash boot接下来会验证TOC2中列出的第一个APP,并在验证后跳转到其入口点。在本应用程序说明中定义的安全系统中,第一个用户应用程序是安全映像。安全映像配置硬件以保护系统安全后,如果需要,它将验证主用户应用程序。
如果发现SFlash或安全映像无效或损坏,设备将进入DEAD保护状态,并保持在DEAD保护态,直到设备重置。
注意:如果设备进入DEAD保护状态,则无法过渡到RMA生命周期阶段,也无法执行故障分析。
5.2 Chain of Trust (CoT)
信任链的基础依赖于无法更改的内存,如ROM。信任链的其余部分依赖于这一事实。
ROM代码不能更改,用于验证下一个执行块;在这种情况下,它是flash boot。
flash boot代码、微调常数和TOC1处于无法重新编程的SFlash中。其中大部分是在工厂预编程的,该部分的计算哈希值存储在eFuse中,称为factory_hash值。这样可以确保在提供MCU后,闪存启动代码、微调值和TOC1不会被篡改。
在生命周期阶段从正常过渡到安全之后,SFlash块将使用另一个称为“Secure_hash”的哈希值进行验证。该值也存储在eFuse中,编程后无法更改。SFlash中的这些项目包括TOC2和公钥。
用于在正常生命周期阶段验证SFlash的FACTORY_HASH值存储在eFuse中,不能更改。
不同的位置用于验证SFlash与编程的额外项目和SECURE_HASH。该位置被写入eFuse的单独部分。
每次设备在安全生命周期阶段从reset中唤醒时,都会使用SECURE_HAH验证整个SFlash块。如果在验证SFlash时发现错误,则设备将不再完成boot序列,并进入DEAD状态。
当验证成功时,整个SFlash现在是可信的,因为它的验证是基于内存(eFuse)的,在ROM中的SFlash验证过程中,如果没有检测就无法修改内存。
锁定在SFlash中的公钥是安全的,并且在不被检测到的情况下无法更改。它被flash boot用来验证boot过程中的下一步。flash boot会验证Secure Image block中的代码,其中包括代码block末尾的数字签名。flash boot使用SHA-256 hash函数(使用公钥)来计算Secure Image block的数字签名。附加到Secure Image block的数字签名使用与SFlash中的公钥关联的私钥进行加密,该私钥使用高达RSA 4096位的加密。然后检查SHA-256 hash函数计算出的数字签名和block末尾存储的数字加密签名,看它们是否匹配。如果它们匹配,则Secure Image block已经过验证。Secure Image 可以使用相同的过程来验证用户Application Block。
有关安全映像代码的签名和验证流程,请参见图4和图5。
图3从数据和代码验证的角度展示了CoT。
6 Code signing and validation
本节介绍对代码块进行签名的过程,以便在启动时对其进行验证。所使用的加密方法是使用私钥和公钥的公钥加密编码法(PKC)。必须小心将私钥保存在安全的位置,这样它就永远不会进入公共域。如果私钥暴露,将危及系统的安全。公司必须创建一种方法,允许对私钥进行非常有限的访问。另一方面,任何人都可以查看公钥。唯一的要求是必须验证或锁定公钥,使其不能更改,或者检测到对公钥的任何修改。TRAVEO中™ T2G MCU,公钥存储在SFlash中,并使用上面CoT部分中定义的SECURE_HASH进行验证。
附录A-创建公钥和私钥的示例中讨论了生成和使用私钥和私钥的更多细节。
6.1 Code signing
在boot时验证代码(例如用户app程序),必须在build时创建数字签名并将其与代码捆绑在一起。代码本身不是以加密格式存储在闪存中,而是对数字签名进行加密。使用SHA-256 hash函数(使用公钥)生成数字签名(a),然后使用具有高达RSA-4096位加密的私钥进行加密(b)。数字签名被加密的原因是,第三方在无法访问私钥的情况下无法创建有效的代码/签名包。见图4。
注意:对于RSA 2048、3072和4096支持,请参阅特定于设备的datash[1](在“零件号/订购代码术语”一节下,硬件选项)。
6.2 Code validation
安全系统必须能够检测不是由原始制造商或可信来源创建的代码。如果检测到不受信任的代码,则执行必须通过已知路径到达安全状态。这也验证了固件不是故意或意外损坏的。验证需要三部分:数据、签名和加密密钥。数据和签名是成对的;密钥存储在一个无法更改的位置。
•数据:这包括组成嵌入式系统中固件的可执行代码和常量。这些数据通常存在于闪存中,通常可以在某个时间进行修改。根据系统的不同,您可以对其进行修改或更新。因此,您必须能够确定此数据是否来自已知来源,并且没有因意外或恶意事件而损坏。
•数字签名:数字签名是数据块的hash。在这种情况下使用的哈希算法是SHA-256。数字签名可以单独用于验证数据是否完好无损。通过使用加密密钥加密数字签名,您可以确定数据是否来自可信来源,以及是否完好无损。
•加密密钥:可以是公钥,也可以是私钥。当前application note描述的系统中,公钥存储在设备上,私钥由开发者保护。公钥必须通过以下两种方式之一进行保护:
1.一种验证密钥来源的方法。这可以通过与已知源或服务器进行某种类型的通信来实现。这对于那些在需要时无法容易实现与已知服务器通信的设备来说是不实用的。
2.使用存储在无法修改的内存中的密钥来验证密钥数据本身。对于嵌入式系统来说,这是最有可能的选择。TRAVEO中™ T2G MCU,根据包含公钥、flash boot代码和微调值的区域计算哈希。然后将该Hash存储在一次性可编程eFuse中,并称为“SECURE_HAH”。
用户app程序binary code block(应用程序包)包括加密数字签名在build时创建。Secure Image应用程序也使用此格式。
1、为了验证代码块,使用HASH函数(SHA-256)校验计算二进制代码image,从而创建计算的数字签名或数字摘要。
2、接下来,使用存储的公钥对加密的数字签名进行解密,以揭示解密的数字签名。然后检查计算的数字摘要和解密的数字摘要(签名)是否完全匹配。如果它们完全匹配,则代码验证通过。见图5。
注意:由于加密内存缓冲区初始化不正确,在使用app程序身份验证boot后可能会设置加密ECC错误。因此,用户软件应该清除或忽略Crypto-ECC错误,这些错误是在使用应用程序身份验证引导时生成的。
7 Resource protection
资源保护意味着在运行时,只有本应访问内存空间或寄存器空间的总线主机或任务才能访问它。这可以是读取、写入或执行的组合。TRAVEO公司™ T2G MCU具有称为“protection units
”的块来添加此功能。这些保护单元可以配置为创建多个保护区,包括闪存、SRAM、外围设备和I/O。然后,这些区域可以受到CPU、任务或两者的限制。有四种主要类型的保护单元:MPU、SMPU、PPU和SWPU。
•每个CPU都有自己的MPU。MPU与其他保护单元的保护结构不同。MPU保护结构仅适用于与单个主设备相关的保护属性。MPU保护结构没有与它们相关联的保护上下文参数。MPU的保护属性是user/privilege, read/write/execute。MPU是特定于每个总线主控器的,并提供针对其各种线程或任务的资源保护。
•SMPU保护多个主机使用的内存区域。这些SMPU具有MPU的所有属性、保护上下文和非安全属性。Secure Image使用SMPU来限制非安全应用程序对内存安全部分的访问。用于flash写入操作的寄存器受到限制,因此只有SROM代码可以访问这些操作。这消除了对flash的任何意外写入或擦除。此外,用于加密操作的SRAM和寄存器也受到保护,以确保操作的安全。
•PPU是专门为保护外围寄存器而设计的。PPU类似于SMPU。PPU是固定功能的,因为它们是硬线的,用于保护特定的外围区域。因此,这种类型的PPU不能在保护结构中配置地址和大小参数,但可以设置保护属性。
•SWPU用于实现对闪存(编程/擦除)和eFuse(读取/写入)的访问限制。SWPU分为两部分,并存储在SFlash中。第一部分是由boot过程配置的,不能更改。第二部分可以由应用程序用于特定于该应用程序的附加访问限制。它可以在NORMAL_PROVISIONED生命周期阶段通过写入SFlash中的特定row进行更新。此外,还可以使用SROM API进行更新。ROM/flash boot从SFlash读取并配置SWPU的两个部分。SWPU由FWPU、ERPU和EWPU组成。
7.1 Boot protection
某些保护单元是在boot过程中配置的,无法重新配置。这些保护单元对于提供安全系统和提供对系统调用功能的可靠访问至关重要。有关引导保护的详细信息,请参阅体系结构TRM[2]中的BootROM章节。
7.2 Application protection
您可以在boot过程中使用SWPU配置对闪存和eFuse的访问保护。这被称为应用程序保护单元。在设备处于NORMAL_PROVISIONED生命周期状态的情况下,可以在SFlash中配置应用程序保护单元。应用程序保护SWPU最多有16个FWPU条目,最多有4个ERPU和EWPU条目。
有关SWPU的详细信息,请参阅体系结构TRM[2]中的“保护单元”一章。
7.3 Security enhance PPU configuration
当magic number设置为安全标记(TOC2_security_UPDATES_marker)时,boot过程会配置以下PPU以增强安全性。此功能在TRAVEO™ T2G Body Controller Entry/High devices中有效,此功能适用于TRAVEO™ T2G群集设备,而不设置安全标记。表2显示了由安全标记配置的PPU。
可编程PPU11和13通过与PERI_MS_PPU_FX_CPUS_CM0组合帮助分离HSM软件和应用软件。例如,允许可编程PPU 11和13访问应用软件,并且允许PERI_MS_PPU_FX_CPUSS_CM0访问HSM软件。因此,CPUS_AP_CTL寄存器完全由HSM软件控制,而CPUS_CM0_CLOCK_CTL和RAM0_PWR_CTL、RAM1_PWR_CTL可以由应用软件控制。
可编程PPU 12用于保护CPUS_ECC_CTL寄存器。此寄存器提供ECC错误插入功能。ECC错误注入是测试存储器ECC逻辑的一种有价值的工具。TRAVEO中™ 与由多个CPU共享存储器的任何其他微控制器一样,T2G MCU的ECC错误注入能力可能被一个CPU或调试器滥用,以操纵其他CPU使用的存储器区域中的数据,并可能危及其安全性。为了减轻这种风险,建议禁用ECC错误注入功能或限制其使用,至少对于HSM使用的存储器是这样。假设ECC逻辑将仅在设备启动期间进行测试,并且一旦启动完成,在常规设备操作期间不需要ECC错误注入功能。为了降低安全风险,建议在ECC测试完成后,通过使用适当的PPU配置阻止对ECC错误注入控制寄存器的访问,禁用ECC错误注入逻辑。更确切地说,用户应该确保ECC错误注入控制寄存器不能被写入。如果启动后需要对ECC错误注入控制寄存器进行写入访问,则用户应确保只有受信任的SW才能对这些寄存器进行写入。
图6显示了可编程PPU 11、12、13、PERI_MS_PPU_FX_CPUSS_CM0的使用示例。可编程PPU比固定PPU具有更高的优先级。对于相同的PPU组,较低的数字具有较高的优先级。
对于安全系统,建议通过HSM软件配置这些PPU。
意外写入PERI_GR2_SL_CTL寄存器可能会停止向核心MCU功能块发送时钟信号。
PERI_MS_PPU_FX_PERI_GR2_GROUP保护PERI_GR2_SL_CTL免受意外写入访问。
当TRAVEO™ T2G Body Controller Entry/High devices中未设置安全标记时,可编程PPU 11、12和13未配置,PERI_MS_PPU_FX_PERI_GR2_GROUP为默认值。
安全标志位置见TOC2。有关此配置示例,请参阅安全增强PPU配置。
7.4 Debug and test access port restriction
TRAVEO™ T2G MCU可以根据生命周期阶段和保护状态,在boot过程中为测试访问端口配置调试访问端口和MPU。表3显示了每个访问限制的存储位置以及部署它的条件。
可以更新Normal and Normal Dead 访问限制,但不能更新Secure and Secure Dead 访问限制。
表4列出了访问限制配置。配置参数对于所有访问限制都是通用的。
注意:可以更新Normal和Normal Dead访问限制,但不能将其设置为限制较少。
例如,禁用DAP设置不能更改为启用DAP设置。
7.4.1 Minimum requirements for a system call initiated by a debugger
需要考虑几个项目,以启用执行向RMA API过渡的系统调用所需的访问。考虑到一个安全的系统,建议暂时禁用所有DAP,作为初始访问限制配置的一部分。同样重要的是要记住,启用的CM4_DAP允许调试器为CM4 CPU通电,并从任意内存地址开始执行代码。当ROM/Flash引导配置SWD/JTAG引脚时,这是可能的。在最坏的情况下,甚至在CM0+应用程序启动之前就可能发生这种情况。
如果CM0+应用程序(例如HSM软件)具有特定的资产,这些资产必须受到主应用程序的保护(例如存储在闪存的HSM部分中的密钥),建议不要通过访问限制启用CPU访问端口。否则,在CM0+启用保护之前,可以使用CM4 CPU访问HSM内存。要启用Sys_DAP,请在用户应用程序中执行以下步骤。要执行这些步骤,所有DAP应设置为“禁用”(暂时禁用),SYS_AP_MPU_ENABLE应设置成“0”(禁用)。
1.配置所有必要的DAP引脚。
2.配置Sys_DAP MPU结构,以便访问所需的资源(例如IPC MMIO、SRAM等)。
3.配置Sys_DAP MPU结构,使其不授予对SRAM区域的任何访问权限,该区域由TransitiontoRMA API额外使用。这是从(SRAM0+2 KB)开始的2 KB的SRAM。
4.配置PPU以保护Sys_DAP MPU。
5.确保PPU/SMPU设置允许所需的IPC MMIO和SRAM访问
6.用户软件中的中断初始化:启用IRQ0和IRQ1以允许处理系统调用中断。为两个中断定义中断向量。
7.启用所有必要的DAP
注意:如果上述任何配置项失败,则无法应用系统调用。
注意:在启用DAP之前执行步骤1至5。
注意:您必须根据您的安全需求决定将这些步骤分配给各个CPU。
有关更多详细信息,请参阅调试访问端口身份验证。
8 Configure a secure system
本节将带您了解安全系统的每一部分,并描述如何生成它们。使用CoT配置一个完全安全的系统比生成一个简单的应用程序更复杂。除了用户代码,它还需要包含其他几个在简单(非安全)系统中通常不需要的部分。以下是创建安全系统时需要编程的内存部分:
build一个block可能依赖于build另一个block。例如,TOC2包含secure image block
和user application block的起始地址。存储在eFuse中的SECURE_HAH取决于SFlash中的所有内容。请注意,其中一些项目是通过适当的SROM固件隐式编程的。
8.1 TOC2
SFlash中有两个表格部分:TOC1和TOC2。TOC1用于内部目的,不可由用户编辑。
TOC2用于指向每个应用程序的位置。在TOC2中,Secure Image被指示为“User application”,Main User application显示为“CM4 or CM7 core x User application”(x显示CPU编号)。
您可能需要更改两个参数,以获得更快的启动顺序,偏移量为0x1F8(见表6):启动时钟频率参数“clock_CONFIG”和调试参数“LISTEN_WINDOW”。您可以将TOC2中的这些值更改为表中定义的值。表6列出了TOC2的要素。
当满足以下条件时,bootloader 程序将启用。
•flash开始处的两个word必须为“0xFFFFFFFF”。
•TOC2有效,内部引导加载程序由TOC2_FLAGS.FB_bootloader_CTL位启用(默认),或者TOC2为空
•保护状态不是SECURE,也不是SECURE_DEAD。
•在一秒钟的等待窗口内,没有发生调试器连接。
在满足bootloader 程序的启用条件的情况下,当擦除第一个应用程序时,将启动引导加载程序,而不会激活第二个应用程序。
因此,如果不必要,建议禁用引导加载程序(TOC2_FLAGS.FB_BOOTLOADER_CTL=0x2)。
8.1.1 Configuration
要为TOC2生成正确的值,请在项目中包含以下代码的实例。
/** Flashboot parameters */
#define CY_SI_FLASHBOOT_FLAGS ((CY_SI_FLASHBOOT_CLK_100MHZ << CY_SI_TOC_FLAGS_CLOCKS_POS) \
| (CY_SI_FLASHBOOT_WAIT_20MS << CY_SI_TOC_FLAGS_DELAY_POS) \
| (CY_SI_FLASHBOOT_SWJ_ENABLE << CY_SI_TOC_FLAGS_SWJEN_POS) \
| (CY_SI_FLASHBOOT_VALIDATE_ENABLE << CY_SI_TOC_FLAGS_APP_VERIFY_POS) \
| (CY_SI_FLASHBOOT_FBLOADER_DISABLE << CY_SI_TOC_FLAGS_FBLOADER_ENABLE_POS))
/** TOC2 in SFlash */
CY_SECTION(".cy_toc_part2") __USED static const cy_stc_si_toc_t cy_toc2 =
{
.objSize = CY_SI_TOC2_OBJECTSIZE, /* Offset+0x00: Object Size (Bytes) excluding CRC */
.magicNum = CY_SI_TOC2_MAGICNUMBER, /* Offset+0x04: TOC2 ID (magic number) */
.smifCfgAddr = 0UL, /* Offset+0x08: SMIF config list pointer */
.cm0pappAddr1 = CY_SI_SECURE_FLASH_BEGIN, /* Offset+0x0C: App1 (CM0+ First User App Object) addr */
.cm0pappFormat1 = CY_SI_APP_FORMAT_CYPRESS, /* Offset+0x10: App1 Format */
.cm0pappAddr2 = CY_SI_USERAPP_FLASH_BEGIN, /* Offset+0x14: App2 (CM0+ Second User App Object) addr */
.cm0pappFormat2 = CY_SI_APP_FORMAT_BASIC, /* Offset+0x18: App2 Format */
.cm4_71appAddr1 = CY_SI_CM471_1stAPP_FLASH_BEGIN, /* Offset+0x1C: App3 (CM4/CM7_1 1st User App Object) addr */
.cm4_71appAddr2 = CY_SI_CM471_2ndAPP_FLASH_BEGIN, /* Offset+0x20: App4 (CM4/CM7_1 2nd User App Object) addr */
.cm72appAddr1 = CY_SI_CM72_1stAPP_FLASH_BEGIN, /* Offset+0x24: App5 (CM7_2 1st User App Object) addr */
.cm72appAddr2 = CY_SI_CM72_2ndAPP_FLASH_BEGIN, /* Offset+0x28: App6 (CM7_2 1st User App Object) addr */
.reserved1 = 0UL, /* Offset+0x2C-0xFB: Reserved area 212Bytes */
.securityMarker = CY_SECURITY_NOT_ENHANCED, /* Offset+0xFC Security Enhance Marker */
.shashObj = 3UL, /* Offset+0x100: Number of verified additional objects */
.sigKeyAddr = CY_SI_PUBLIC_KEY, /* Offset+0x104: Addr of signature verification key */
.swpuAddr = CY_SI_SWPU_BEGIN, /* Offset+0x108: Addr of SWPU Objects */
.toc2Addr = 0UL, /* Offset+0x10C: TOC2_OBJECT_ADDR_UNUSED */
.addObj = 0UL, /* Offset+0x110-0x1F4: Reserved area 232Bytes */
.tocFlags = CY_SI_FLASHBOOT_FLAGS, /* Flashboot flags stored in TOC2 */
.crc = 0UL, /* Offset+0x1FC: Reserved area 1Byte */
};
8.2 User application block
安全应用程序必须使用公共加密密钥进行验证。为此,应用程序必须包含使用Cypress安全应用程序格式(CySAF)的数字签名。用户应用程序格式在TOC2中指定为“第一/第二用户应用程序对象的格式(偏移量=0x10/0x18)”。
这允许flash boot在启动过程中执行验证,然后再执行应用程序。应用程序格式封装了应用程序二进制文件、应用程序元数据和加密的数字签名。尽管这种格式的CM0+和CM4 image都有位置,但Secure Image只需要CM0+ image。用户应用程序包括这两个image,请参见图8。
注意:CySAF需要将生命周期阶段转换为SECURE或SECURE_W_DEBUG。因此,在将生命周期阶段从NORMAL_PROVISIONED转换为RMA时,也需要CySAF。
将生命周期阶段从NORMAL_PROVISIONED过渡到RMA,请参见附录E-过渡到RMA生命周期阶段。
表7列出了CySAF中header section的详细信息。它定义了总大小、core数量、应用程序类型以及每个core应用程序向量表的偏移量。
要为应用程序header生成正确的值,请在项目中包含以下代码的实例。
/** Secure Application header */
CY_SECTION(".cy_app_header") __USED static const cy_stc_si_appheader_t cy_si_appHeader =
{
.objSize = CY_M0PLUS_SI_SIZE,
.appId = (CY_SI_APP_VERSION | CY_SI_APP_ID_SECUREIMG),
.appAttributes = 0UL, /* Reserved */
.numCores = 1UL, /* Only CM0+ */
.core0Vt = CY_SI_VT_OFFSET, /* CM0+ VT offset */
.core0Id = CY_SI_CPUID | CY_SI_CORE_IDX, /* CM0+ core ID */
};
/** Secure Image Digital signature (Populated by cymcuelftool) */
CY_SECTION(".cy_app_signature") __USED CY_ALIGN(4)
static const uint8_t cy_si_appSignature[CY_SI_SECURE_DIGSIG_SIZE] = {0u};
8.3 Secure boot RSA public key format
加密算法是SHA-256+RSASSA PKCS v1.5算法作为签名验证方案。RSA密钥的位置由用户定义。用户应提供一个指向TOC2中key的指针。当放入SFlash时,通过ROM boot HASH计算来检查公钥内容是否有任何更改。
SFlash区域以二进制格式存储公钥。预先计算了模数、指数和三个系数,以加快验证速度。图9显示了格式。
密钥存储在三个结构中。
第一个结构“Key”作为一个对象存储,可以很容易地包含在SECURE_HASH计算中。“Signature Scheme”定义了密钥的结构。“Object Size”包含公钥对象的完整大小(包含整个三个结构)。
第二个结构包含公钥的各个部分:系数(K1、K2、K3)、指数(E)和模数(N)。这些值必须存储在字节的小端序列(将一个多位数的低位放在较小的地址处,高位放在较大的地址处,则称小端序)表中。
第三种结构是指向每条公钥的指针列表,公钥是调用SROM固件所需的格式。
要为公钥格式生成正确的值,请在项目中包含以下代码的实例。
附录A-创建公钥和私钥的示例中讨论了生成和使用私钥和私钥的更多细节。
/** Public key in SFlash */
CY_SECTION(".cy_SFlash_public_key") __USED const cy_si_stc_public_key_t cy_publicKey =
{
.objSize = sizeof(cy_si_stc_public_key_t),
.signatureScheme = 0UL,
.publicKeyStruct =
{
.moduloAddr = CY_SI_PUBLIC_KEY + offsetof(cy_si_stc_public_key_t, moduloData),
.moduloSize = CY_SI_PUBLIC_KEY_SIZEOF_BYTE * CY_SI_PUBLIC_KEY_MODULOLENGTH,
.expAddr = CY_SI_PUBLIC_KEY + offsetof(cy_si_stc_public_key_t, expData),
.expSize = CY_SI_PUBLIC_KEY_SIZEOF_BYTE * CY_SI_PUBLIC_KEY_EXPLENGTH,
.barrettAddr = CY_SI_PUBLIC_KEY + offsetof(cy_si_stc_public_key_t, barrettData),
.inverseModuloAddr = CY_SI_PUBLIC_KEY + offsetof(cy_si_stc_public_key_t,
inverseModuloData),
.rBarAddr = CY_SI_PUBLIC_KEY + offsetof(cy_si_stc_public_key_t, rBarData),
},
.moduloData =
{ // N(Modulus)
},
.expData =
{ // E(Exponent)
},
.barrettData =
{ // K1
},
.inverseModuloData =
{ // K2
},
.rBarData =
{ // K3
},
};