引流关键词: 中断、同步异常、异步异常、irq、fiq、BL1,BL2,BL3,BL31,BL32,BL33,AP_BL1,AP_BL2,AP_BL3,AP_BL31,AP_BL32,AP_BL33,SCP_BL1,SCP_BL2,BL0,BL30, optee、ATF、TF-A、Trustzone、optee3.14、MMU、VMSA、cache、TLB、arm、armv8、armv9、TEE、安全、内存管理、页表…
快速链接:
.
👉👉👉 个人博客笔记导读目录(全部) 👈👈👈
[专栏目录]-ATF/FF-A/specification学习
2.身份验证框架和信任链
本文档的目的是描述在可信固件-A (TF-A) 中实现的身份验证框架。该框架满足以下要求:
(1) 平台端口应该可以根据证书层次结构和用于验证特定图像/证书的机制来指定信任链。
(2) 该框架应区分:
-
用于编码和传输信息的机制,例如 DER 编码的 X.509v3 证书以传送主题公钥、散列和非易失性计数器。
-
用于验证传输信息的机制,即密码库。
该框架是按照下图所示的模块化方法设计的:
+---------------+---------------+------------+
| Trusted | Trusted | Trusted |
| Firmware | Firmware | Firmware |
| Generic | IO Framework | Platform |
| Code i.e. | (IO) | Port |
| BL1/BL2 (GEN) | | (PP) |
+---------------+---------------+------------+
^ ^ ^
| | |
v v v
+-----------+ +-----------+ +-----------+
| | | | | Image |
| Crypto | | Auth | | Parser |
| Module |<->| Module |<->| Module |
| (CM) | | (AM) | | (IPM) |
| | | | | |
+-----------+ +-----------+ +-----------+
^ ^
| |
v v
+----------------+ +-----------------+
| Cryptographic | | Image Parser |
| Libraries (CL) | | Libraries (IPL) |
+----------------+ +-----------------+
| |
| |
| |
v v
+-----------------+
| Misc. Libs e.g. |
| ASN.1 decoder |
| |
+-----------------+
DIAGRAM 1.
本文档描述了身份验证框架的内部细节以及可用于指定信任链的抽象机制。
2.1。框架设计
本节描述了框架设计的某些方面及其背后的基本原理。这些方面是验证信任链的关键。
2.1.1。信任链
CoT 基本上是一系列身份验证图像,通常以信任根开始,最终形成单个数据图像。下图说明了它如何映射到 TBBR-Client 规范中描述的 BL31 映像的 CoT 。
+------------------+ +-------------------+
| ROTPK/ROTPK Hash |------>| Trusted Key |
+------------------+ | Certificate |
| (Auth Image) |
/+-------------------+
/ |
/ |
/ |
/ |
L v
+------------------+ +-------------------+
| Trusted World |------>| BL31 Key |
| Public Key | | Certificate |
+------------------+ | (Auth Image) |
+-------------------+
/ |
/ |
/ |
/ |
/ v
+------------------+ L +-------------------+
| BL31 Content |------>| BL31 Content |
| Certificate PK | | Certificate |
+------------------+ | (Auth Image) |
+-------------------+
/ |
/ |
/ |
/ |
/ v
+------------------+ L +-------------------+
| BL31 Hash |------>| BL31 Image |
| | | (Data Image) |
+------------------+ | |
+-------------------+
DIAGRAM 2.
信任根通常是已经在平台中烧毁且无法修改的公钥(ROTPK)。
2.1.2. 镜像类型
CoT 中的图像分为认证图像和数据图像。认证图像包含用于认证数据图像或另一个认证图像的信息。数据映像通常是引导加载程序二进制文件,但也可以是任何其他需要身份验证的数据。
2.1.3。组件职责
对于信任链中的每个图像,执行以下高级操作来验证它:
-
(1)静态或在运行时为图像分配内存。
-
(2)识别图像并将其加载到分配的内存中。
-
(3)根据图像类型检查图像的完整性。
-
(4)根据使用的加密算法对图像进行身份验证。
-
(5)如果图像是验证图像,则提取将用于验证 CoT 中的下一个图像的信息。
在图 1 中,每个组件负责一个或多个这些操作。下面简要介绍一下职责。
2.1.3.1。TF-A 通用代码和 IO 框架(GEN/IO)
这些组件负责为 BL1 或 BL2 中的特定图像启动身份验证过程。对于每个需要身份验证的 BL 图像,通用代码会递归地询问身份验证模块父图像是什么,直到达到经过身份验证的图像或 ROT。然后Generic代码调用IO框架加载镜像并调用Authentication模块对其进行认证,跟随CoT从ROT到Image。
2.1.3.2。TF-A 平台端口 (PP)
该平台负责:
-
(1)为需要验证的每个图像指定 CoT。稍后将解释平台如何指定 CoT 的详细信息。该平台还指定了用于每个图像的身份验证方法和解析方法。
-
(2)为每个图像中的每个参数静态分配内存,用于验证 CoT,例如用于公钥、哈希等的内存。
-
(3)提供 ROTPK 或它的散列。
-
(4)向 IPM 提供附加信息以使其能够识别和提取图像中包含的身份验证参数,例如,如果参数存储为 X509v3 扩展,则必须提供相应的 OID。
-
(5)满足 IPM 和 CM 的任何其他内存要求(本文档中当前未描述)。
-
(6)导出函数来验证使用 CM 无法解释的身份验证方法的图像,例如,如果必须使用 NV 计数器验证图像,则要与之比较的计数器的值只能由平台提供。
-
(7)如果正在使用专有图像格式(稍后描述),则导出自定义 IPM。
2.1.3.3。认证模块 (AM)
它负责:
-
(1)提供必要的抽象机制来描述 CoT。其中,身份验证和图像解析方法必须由 CoT 中的 PP 指定。
-
(2)利用 PP、IPM 和 CM 导出的功能验证 GEN 通过的 CoT。
-
(3)跟踪哪些图像已经过验证。如果一个图像是多个 CoT 的一部分,那么它应该只验证一次,例如 TBBR-Client 规范中的可信世界密钥证书。包含验证 SCP_BL2、BL31、BL32 的信息,每个都有单独的 CoT。(这个责任没有在本文档中描述,但应该很容易实现)。
-
(4)重用用于数据图像的内存来验证认证图像,例如在图 2 中描述的 CoT 中,每个证书都可以在平台为 BL31 图像保留的内存中加载和验证。到加载 BL31(数据图像)时,所有验证它的信息都将从父图像(即 BL31 内容证书)中提取出来。假设认证图像的大小永远不会超过数据图像的大小。应该可以在构建时使用断言来验证这一点。
2.1.3.4。密码模块 (CM)
CM 负责提供 API 以:
-
(1)验证数字签名。
-
(2)验证哈希。
CM 不包含任何与加密相关的代码,但它依赖于外部库来执行加密操作。必须实现链接 CM 和外部库的加密库 (CL)。CL必须提供以下功能:
void (*init)(void);
int (*verify_signature)(void *data_ptr, unsigned int data_len,
void *sig_ptr, unsigned int sig_len,
void *sig_alg, unsigned int sig_alg_len,
void *pk_ptr, unsigned int pk_len);
int (*verify_hash)(void *data_ptr, unsigned int data_len,
void *digest_info_ptr, unsigned int digest_info_len);
这些函数使用宏在 CM 中注册:
REGISTER_CRYPTO_LIB(_name, _init, _verify_signature, _verify_hash);
_name必须是包含 CL 名称的字符串。此名称用于调试目的。
2.1.3.5。图像解析器模块 (IPM)
IPM 负责:
-
(1)检查 IO 框架加载的每个图像的完整性。
-
(2)根据平台在 CoT 描述符中提供的描述提取用于验证图像的参数。
图像可能有不同的格式(例如,身份验证图像可以是 x509v3 证书、签名的 ELF 文件或任何其他特定于平台的格式)。IPM 允许为 CoT 中使用的每种图像格式注册一个图像解析器库 (IPL)。这个库必须实现特定的方法来解析图像。IPM 从 CoT 获取图像格式并调用正确的 IPL 来检查图像完整性并提取认证参数。
有关 IPM 提供的用于定义和注册 IPL 的机制的更多详细信息,请参阅“描述图像解析方法”部分。
2.1.4。身份验证方法
AM 支持以下认证方式:
-
(1)哈希
-
(2)电子签名
平台可以在 CoT 中指定这些方法,以防它决定定义自定义 CoT 而不是重用预定义的 CoT。
如果一个数据图像使用多种方法,那么所有方法必须是同一个 CoT 的一部分。参数的数量和类型是特定于方法的。这些参数应使用 IPM 从父图像中获取。
- (1)哈希
参数:
-
指向要散列的数据的指针
-
数据长度
-
指向哈希的指针
-
哈希的长度
哈希将由以下 ASN.1 类型的 DER 编码表示:
DigestInfo ::= SEQUENCE {
digestAlgorithm DigestAlgorithmIdentifier,
digest Digest
}
这种 ASN.1 结构可以消除任何关于散列算法类型的假设,因为此信息伴随散列。这应该允许密码库 (CL) 支持多种散列算法实现。
- (2)电子签名
参数:
-
指向要签名的数据的指针
-
数据长度
-
公钥算法
-
公钥值
-
数字签名算法
-
数字签名值
公钥参数将由以下 ASN.1 类型的 DER 编码表示:
SubjectPublicKeyInfo ::= SEQUENCE {
algorithm AlgorithmIdentifier{PUBLIC-KEY,{PublicKeyAlgorithms}},
subjectPublicKey BIT STRING }
数字签名算法将由以下 ASN.1 类型的 DER 编码表示。
AlgorithmIdentifier {ALGORITHM:IOSet } ::= SEQUENCE {
algorithm ALGORITHM.&id({IOSet}),
parameters ALGORITHM.&Type({IOSet}{@algorithm}) OPTIONAL
}
数字签名将由以下形式表示:
signature ::= BIT STRING
身份验证框架将使用图像描述符来提取与身份验证相关的所有信息。
2.2. 指定信任链
CoT 可以描述为以特定顺序链接在一起的一组图像描述符。顺序决定了它们必须被验证的顺序。每个图像都有一组属性,允许 AM 对其进行验证。这些属性如下所述。
PP 负责为数据图像定义单个或多个 CoT。除非另有说明,以下部分中描述的数据结构由 PP 静态填充。
2.2.1。描述图像解析方法
解析方法是指特定图像的格式。例如,代表证书的身份验证图像可以是 X.509v3 格式。表示引导加载程序阶段的数据映像可以是原始二进制或 ELF 格式。IPM 支持三种解析方法。图像必须使用下面描述的三种方法之一。IPL 负责解释单个解析方法。平台使用的每种方法都必须有一个 IPL。
-
(1)原始格式:此格式实际上是 nop,因为使用此方法的图像被视为原始二进制格式,例如 TF-A 使用的引导加载程序图像。此方法应仅用于数据图像。
-
(2)X509V3 方法:此方法使用 X.509 等行业标准来表示 PKI 证书(身份验证图像)。预计将提供可用于解析此方法表示的图像的开源库。此类库可用于编写相应的 IPL,例如 mbed TLS 中的 X.509 解析库代码。
-
(3)平台定义方法:此方法满足平台特定的专有标准来表示身份验证或数据图像。例如,数据图像的签名可以附加到数据图像原始二进制文件中。可以将标头附加到组合的 blob 以指定每个组件的范围。平台必须实现相应的 IPL 来解释这种格式。
以下枚举可用于定义这三种方法。
typedef enum img_type_enum {
IMG_RAW, /* Binary image */
IMG_PLAT, /* Platform specific format */
IMG_CERT, /* X509v3 certificate */
IMG_MAX_TYPES,
} img_type_t;
IPL 必须提供具有以下原型的函数:
void init(void);
int check_integrity(void *img, unsigned int img_len);
int get_auth_param(const auth_param_type_desc_t *type_desc,
void *img, unsigned int img_len,
void **param, unsigned int *param_len);
必须使用以下宏注册每种类型的 IPL:
REGISTER_IMG_PARSER_LIB(_type, _name, _init, _check_int, _get_param)
-
_type: 上述类型之一。
-
_name:包含用于调试目的的 IPL 名称的字符串。
-
_init:初始化函数指针。
-
_check_int:检查图像完整性函数指针。
-
_get_param: 提取认证参数函数指针。
该init()函数将用于初始化 IPL。
该check_integrity()函数传递一个指针,该指针指向 IO 框架已加载图像的内存和图像长度。应该保证图片是解析方式对应的格式,没有被篡改过。例如,RFC-2459 描述了 X.509 证书的验证序列。
该get_auth_param()函数被传递一个参数描述符,其中包含有关参数 (type_desc和cookie) 的信息,以从图像中识别和提取与该参数对应的数据。此数据将用于验证 CoT 序列中的当前或下一个图像。
CoT 中的每个图像都将指定它使用的解析方法。IPM 将使用此信息来查找图像的正确解析器描述符。
2.2.2。描述身份验证方法
作为 CoT 的一部分,每个图像都必须指定一种或多种身份验证方法,用于对其进行验证。如“身份验证方法”部分所述,AM 支持三种方法。
typedef enum {
AUTH_METHOD_NONE,
AUTH_METHOD_HASH,
AUTH_METHOD_SIG,
AUTH_METHOD_NUM
} auth_method_type_t;
AM 定义了身份验证方法使用的每个参数的类型。它使用这些信息来:
指定get_auth_param()IPM 导出的函数,应从图像中提取哪个参数。
调用CM和PP导出的校验函数时,正确编组参数。
从父图像中提取身份验证参数以验证子图像,例如为了验证证书图像,必须从父图像中获取公钥。
typedef enum {
AUTH_PARAM_NONE,
AUTH_PARAM_RAW_DATA, /* Raw image data */
AUTH_PARAM_SIG, /* The image signature */
AUTH_PARAM_SIG_ALG, /* The image signature algorithm */
AUTH_PARAM_HASH, /* A hash (including the algorithm) */
AUTH_PARAM_PUB_KEY, /* A public key */
} auth_param_type_t;
AM 定义了以下结构来识别验证图像所需的身份验证参数。
typedef struct auth_param_type_desc_s {
auth_param_type_t type;
void *cookie;
} auth_param_type_desc_t;
cookie平台使用它来为 IPM 指定附加信息,使其能够唯一标识应从图像中提取的参数。例如,BL3x 图像在其相应内容证书中的哈希存储在 X509v3 自定义扩展字段中。扩展字段只能使用 OID 来标识。在这种情况下,cookie可以包含指向平台为散列扩展字段定义的 OID 的指针,而该type字段可以设置为AUTH_PARAM_HASH。该字段的值为 0cookie表示未使用该字段。
对于每种方法,AM 都定义了一个结构,其中包含验证图像所需的参数。
/*
* Parameters for authentication by hash matching
*/
typedef struct auth_method_param_hash_s {
auth_param_type_desc_t *data; /* Data to hash */
auth_param_type_desc_t *hash; /* Hash to match with */
} auth_method_param_hash_t;
/*
* Parameters for authentication by signature
*/
typedef struct auth_method_param_sig_s {
auth_param_type_desc_t *pk; /* Public key */
auth_param_type_desc_t *sig; /* Signature to check */
auth_param_type_desc_t *alg; /* Signature algorithm */
auth_param_type_desc_t *tbs; /* Data signed */
} auth_method_param_sig_t;
AM 定义了以下结构来描述验证图像的身份验证方法
/*
* Authentication method descriptor
*/
typedef struct auth_method_desc_s {
auth_method_type_t type;
union {
auth_method_param_hash_t hash;
auth_method_param_sig_t sig;
} param;
} auth_method_desc_t;
使用type字段中指定的方法类型,AM 找出param联合内需要访问的字段。
2.2.3。存储认证参数
用于验证图像的参数auth_param_type_desc_t可以从图像本身或其父图像中获得。为加载父图像分配的内存将被重新用于加载子图像。因此,从父级获得的用于验证子图像的参数需要为它们单独分配内存,以便存储它们。此内存必须由平台端口静态分配。
AM 定义了以下结构来存储与认证参数对应的数据。
typedef struct auth_param_data_desc_s {
void *auth_param_ptr;
unsigned int auth_param_len;
} auth_param_data_desc_t;
该auth_param_ptr字段由平台初始化。该auth_param_len 字段用于指定内存中数据的长度。
对于可以从子图像本身获取的参数,IPM 负责在执行函数时填充auth_param_ptr和字段。auth_param_lenimg_get_auth_param()
AM 定义了以下结构,以使图像能够描述应从中提取并用于验证 CoT 中的下一个图像(子图像)的参数。
typedef struct auth_param_desc_s {
auth_param_type_desc_t type_desc;
auth_param_data_desc_t data;
} auth_param_desc_t;
2.2.4。在 CoT 中描述图像
CoT 中的图像是上述 CoT 的以下方面的合并。
-
(1)平台指定的唯一标识符,允许 IO 框架在 FIP 中定位图像并将其加载到为 CoT 中的数据图像保留的内存中。
-
(2)AM 使用的一种解析方法来查找适当的 IPM。
-
(3)上一节中描述的身份验证方法及其参数。这些用于验证当前图像。
-
(4)用于验证当前 CoT 中的下一个图像的参数。这些参数仅由身份验证图像指定,一旦经过验证,就可以从当前图像中提取。
以下数据结构描述了 CoT 中的图像。
typedef struct auth_img_desc_s {
unsigned int img_id;
const struct auth_img_desc_s *parent;
img_type_t img_type;
const auth_method_desc_t *const img_auth_methods;
const auth_param_desc_t *const authenticated_data;
} auth_img_desc_t;
CoT 定义为指向由字段auth_image_desc_t链接在一起的结构的指针数组。parent那些没有父节点的节点必须使用存储在平台中的 ROTPK 进行身份验证。
2.3. 实现示例
本节是详细指南,解释使用身份验证框架的可信引导实现。此示例对应于 TBBR-Client 文档中指定的应用功能模式 (AFM)。建议与源代码一起阅读本指南。
2.3.1。TBBR CoT
BL1 和 BL2 特有的 CoT 可以分别在drivers/auth/tbbr/tbbr_cot_bl1.c 和中找到drivers/auth/tbbr/tbbr_cot_bl2.c。在 BL1 和 BL2 中使用的通用 CoT 可以在drivers/auth/tbbr/tbbr_cot_common.c. 这个 CoT 由一组指向图像描述符的指针组成,并使用宏在框架中注册REGISTER_COT(cot_desc),其中 cot_desc必须是数组的名称(传递指针或任何其他类型的间接将导致注册过程失败)。
参与引导过程的映像数量取决于 CoT。然而,在 TF-A 中有一组最少的图像是强制性的,因此所有 CoT 都必须呈现:
-
BL2
-
SCP_BL2(特定于平台)
-
BL31
-
BL32(可选的)
-
BL33
TBBR 指定了必须伴随这些图像以进行正确身份验证的附加证书。有关 TBBR CoT 的详细信息可在 Trusted Board Boot文档中找到。
遵循移植指南,平台必须为将在引导过程中加载的所有映像和证书提供唯一标识符。如果平台使用 TBBR 作为可信引导的参考,则这些标识符可以从include/common/tbbr/tbbr_img_def.h. Arm 平台将此文件包含在include/plat/arm/common/arm_def.h. 其他平台也可能包含此文件或提供自己的标识符。
重要提示:身份验证模块使用这些标识符来索引 CoT 数组,因此数组中的描述符位置必须与标识符匹配。
每个图像描述符必须指定:
-
img_id:平台定义的对应图片唯一标识。
-
img_type:图像解析器模块使用图像类型调用正确的解析库来检查图像完整性并提取所需的认证参数。目前支持三种类型的图像:
– IMG_RAW:图像是原始二进制文件。除了读取整个图像之外,没有可用的解析功能。
– IMG_PLAT:图像格式是特定于平台的。平台可以将此类型用于身份验证框架不直接支持的自定义图像。
– IMG_CERT:图像是 x509v3 证书。 -
parent: 指向父图像描述符的指针。父级将包含验证当前图像所需的信息。如果 parent 为 NULL,则从平台获取认证参数(即 BL2 和 Trusted Key 证书使用 ROT 私钥签名,其公共部分存储在平台中)。
-
img_auth_methods:这指向一个数组,该数组定义了必须检查的身份验证方法以认为图像已通过身份验证。每个方法都包含一个类型和一个参数描述符列表。参数描述符由类型和cookie 组成,cookie 将指向从图像中提取该参数所需的特定信息(即,如果参数存储在x509v3 扩展中,cookie 将指向扩展OID)。根据方法类型,必须指定不同数量的参数。该指针不应为 NULL。支持的方法有:
– AUTH_METHOD_HASH:图像的哈希必须与从父图像中提取的哈希匹配。必须指定以下参数描述符:
----- data:要散列的数据(从当前图像中获取)
----- hash:参考哈希(从父图像获得)
– AUTH_METHOD_SIG: 图像(通常是证书)必须使用其公共部分从父图像(如果父图像为 NULL 则为平台)提取的私钥签名。必须指定以下参数描述符:
----- pk: 公钥(从父镜像中获取)
----- sig:数字签名(从当前图像中获得)
----- alg:使用的签名算法(从当前图像中获得)
----- data:要签名的数据(从当前图像中获取) -
authenticated_data:此数组指针指示一旦图像经过身份验证,必须从图像中提取哪些身份验证参数。每个参数由一个参数描述符和用于存储参数的缓冲区地址/大小组成。CoT 负责分配所需的内存来存储参数。该指针可能为 NULL。
在该tbbr_cot*.c文件中,分配了一组缓冲区来存储从证书中提取的参数。在 TBBR CoT 的情况下,这些参数是散列和公钥。在 DER 格式中,一个 RSA-4096 公钥需要 550 个字节,而散列需要 51 个字节。根据 CoT 和身份验证过程,一些缓冲区可能会在引导期间的不同阶段重复使用。
接下来在该文件中,定义参数描述符。这些描述符将用于从相应的图像中提取参数数据。
2.3.1.1。示例:BL31 信任链
四个图像描述符构成了 BL31 信任链:
static const auth_img_desc_t trusted_key_cert = {
.img_id = TRUSTED_KEY_CERT_ID,
.img_type = IMG_CERT,
.parent = NULL,
.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
[0] = {
.type = AUTH_METHOD_SIG,
.param.sig = {
.pk = &subject_pk,
.sig = &sig,
.alg = &sig_alg,
.data = &raw_data
}
},
[1] = {
.type = AUTH_METHOD_NV_CTR,
.param.nv_ctr = {
.cert_nv_ctr = &trusted_nv_ctr,
.plat_nv_ctr = &trusted_nv_ctr
}
}
},
.authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
[0] = {
.type_desc = &trusted_world_pk,
.data = {
.ptr = (void *)trusted_world_pk_buf,
.len = (unsigned int)PK_DER_LEN
}
},
[1] = {
.type_desc = &non_trusted_world_pk,
.data = {
.ptr = (void *)non_trusted_world_pk_buf,
.len = (unsigned int)PK_DER_LEN
}
}
}
};
static const auth_img_desc_t soc_fw_key_cert = {
.img_id = SOC_FW_KEY_CERT_ID,
.img_type = IMG_CERT,
.parent = &trusted_key_cert,
.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
[0] = {
.type = AUTH_METHOD_SIG,
.param.sig = {
.pk = &trusted_world_pk,
.sig = &sig,
.alg = &sig_alg,
.data = &raw_data
}
},
[1] = {
.type = AUTH_METHOD_NV_CTR,
.param.nv_ctr = {
.cert_nv_ctr = &trusted_nv_ctr,
.plat_nv_ctr = &trusted_nv_ctr
}
}
},
.authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
[0] = {
.type_desc = &soc_fw_content_pk,
.data = {
.ptr = (void *)content_pk_buf,
.len = (unsigned int)PK_DER_LEN
}
}
}
};
static const auth_img_desc_t soc_fw_content_cert = {
.img_id = SOC_FW_CONTENT_CERT_ID,
.img_type = IMG_CERT,
.parent = &soc_fw_key_cert,
.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
[0] = {
.type = AUTH_METHOD_SIG,
.param.sig = {
.pk = &soc_fw_content_pk,
.sig = &sig,
.alg = &sig_alg,
.data = &raw_data
}
},
[1] = {
.type = AUTH_METHOD_NV_CTR,
.param.nv_ctr = {
.cert_nv_ctr = &trusted_nv_ctr,
.plat_nv_ctr = &trusted_nv_ctr
}
}
},
.authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
[0] = {
.type_desc = &soc_fw_hash,
.data = {
.ptr = (void *)soc_fw_hash_buf,
.len = (unsigned int)HASH_DER_LEN
}
},
[1] = {
.type_desc = &soc_fw_config_hash,
.data = {
.ptr = (void *)soc_fw_config_hash_buf,
.len = (unsigned int)HASH_DER_LEN
}
}
}
};
static const auth_img_desc_t bl31_image = {
.img_id = BL31_IMAGE_ID,
.img_type = IMG_RAW,
.parent = &soc_fw_content_cert,
.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
[0] = {
.type = AUTH_METHOD_HASH,
.param.hash = {
.data = &raw_data,
.hash = &soc_fw_hash
}
}
}
};
Trusted Key 证书使用ROT 私钥签名,并包含 Trusted World 公钥和 Non-Trusted World 公钥作为 x509v3 扩展。这必须分别使用 img_auth_methods和authenticated_data数组在图像描述符中指定。
可信密钥证书通过使用 ROTPK 检查其数字签名来进行身份验证。检查签名需要四个参数:公钥、算法、签名和已签名的数据。因此,认证方法必须指定四个参数描述符:
-
subject_pk: 类型的参数描述符AUTH_PARAM_PUB_KEY。此类型用于从父图像中提取公钥。如果 cookie 是 OID,则从相应的 x509v3 扩展中提取密钥。如果 cookie 为 NULL,则检索主题公钥。在这种情况下,由于父图像为 NULL,因此从平台获取公钥(此密钥将是 ROTPK)。
-
sig: 类型的参数描述符AUTH_PARAM_SIG。它用于从证书中提取签名。
-
sig_alg: 类型的参数描述符AUTH_PARAM_SIG。它用于从证书中提取签名算法。
-
raw_data: 类型的参数描述符AUTH_PARAM_RAW_DATA。它用于从证书中提取要签名的数据。
一旦检查了签名并验证了证书,就需要从证书中提取 Trusted World 公钥。authenticated_data为此,在数组中创建了一个新条目。在该条目中,必须指定相应的参数描述符以及缓冲区地址以存储参数值。在这种情况下,trusted_world_pk 描述符用于从具有 OID 的 x509v3 扩展中提取公钥 TRUSTED_WORLD_PK_OID。BL31 密钥证书将使用该描述符作为签名认证方法中的参数。密钥存储在 trusted_world_pk_buf缓冲区中。
BL31 Key 证书是通过使用之前从 Trusted Key 证书中获得的 Trusted World 公钥检查其数字签名来验证的。在图像描述符中,我们通过签名指定单一的身份验证方法,其公钥为trusted_world_pk. 一旦这个证书被认证,我们必须提取 BL31 公钥,存储在soc_fw_content_pk. 该密钥将被复制到 content_pk_buf缓冲区。
BL31 证书是通过使用先前从 BL31 Key 证书中获得的BL31 公钥检查其数字签名来验证的。soc_fw_content_pk我们使用公钥指定身份验证方法。身份验证后,我们需要提取 BL31 哈希值,存储在指定的扩展名中soc_fw_hash。此哈希将被复制到 soc_fw_hash_buf缓冲区。
BL31图像通过计算其哈希值并将其与从 BL31 证书获得的哈希值进行匹配来进行身份验证。图像描述符包含通过哈希的单一身份验证方法。散列方法的参数是参考散列、soc_fw_hash和要散列的数据。在这种情况下,它是整个图像,所以我们指定raw_data.
2.3.2. 图像解析器库
图像解析器模块依赖库来检查图像完整性并提取身份验证参数。解析器库的数量和类型取决于 CoT 中使用的图像。原始图像不需要库,因此 TBBR CoT 只需要 x509v3 库。
Arm 平台将使用基于 mbed TLS 的 x509v3 库。这个库可以在drivers/auth/mbedtls/mbedtls_x509_parser.c. 它导出三个函数:
void init(void);
int check_integrity(void *img, unsigned int img_len);
int get_auth_param(const auth_param_type_desc_t *type_desc,
void *img, unsigned int img_len,
void **param, unsigned int *param_len);
该库使用宏在框架中注册 REGISTER_IMG_PARSER_LIB()。图像解析模块每次需要访问类型为 的图像时IMG_CERT,都会调用该文件中导出的相应函数。
必须更新构建系统以包含相应的库和 mbed TLS 源。Arm 平台使用该arm_common.mk文件来拉取源。
2.3.3。密码库
密码模块依赖于库来执行所需的操作,即验证散列或数字签名。Arm 平台将使用基于 mbed TLS 的库,该库位于 drivers/auth/mbedtls/mbedtls_crypto.c. 该库使用宏在身份验证框架中注册,REGISTER_CRYPTO_LIB()并导出四个函数:
void init(void);
int verify_signature(void *data_ptr, unsigned int data_len,
void *sig_ptr, unsigned int sig_len,
void *sig_alg, unsigned int sig_alg_len,
void *pk_ptr, unsigned int pk_len);
int verify_hash(void *data_ptr, unsigned int data_len,
void *digest_info_ptr, unsigned int digest_info_len);
int auth_decrypt(enum crypto_dec_algo dec_algo, void *data_ptr,
size_t len, const void *key, unsigned int key_len,
unsigned int key_flags, const void *iv,
unsigned int iv_len, const void *tag,
unsigned int tag_len)
mbedTLS 库算法支持由 TF_MBEDTLS_KEY_ALG和TF_MBEDTLS_KEY_SIZE变量配置。
-
TF_MBEDTLS_KEY_ALG可以接受 3 个值:rsa、ecdsa或rsa+ecdsa。此变量允许 Makefile 在构建中包含各种算法的相应源。将变量设置为rsa+ecdsa 可以支持 mbedTLS 库中的 rsa 和 ecdsa 算法。
-
TF_MBEDTLS_KEY_SIZE设置 TFA 支持的 RSA 密钥大小。有效值包括 1024、2048、3072 和 4096。
-
TF_MBEDTLS_USE_AES_GCM启用基于 AES-GCM 算法的认证解密支持。有效值为 0 和 1。
注意:如果代码大小是一个问题,MBEDTLS_SHA256_SMALLER可以在平台 Makefile 中定义构建选项。它将使 mbed TLS 使用 SHA-256 的实现,内存占用更小(约 1.5 KB 少)但速度更慢(约 30%)。