快速链接:
.
👉👉👉 个人博客笔记导读目录(全部) 👈👈👈
- 付费专栏-付费课程 【购买须知】
- 我的联系方式-自建交流群-学习群 【必看/必看!!】
- ATF架构开发精讲-专题目录👈👈👈
- ARMv8/ARMv9架构入门到精通-[目录] 👈👈👈
5.2. 身份验证框架和信任链
本文档旨在描述身份验证框架 在受信任固件 A (TF-A) 中实现。该框架满足了 以下要求:
- 平台端口应该可以指定信任链 证书层次结构的术语和用于验证 特定图像/证书。
- 该框架应区分:
- 用于编码和传输信息的机制,例如 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.
本文档介绍身份验证框架的内部详细信息,以及 可用于指定信任链的抽象机制。
5.2.1. 框架设计
本节介绍框架设计的某些方面和基本原理 在他们身后。这些方面是验证信任链的关键。
5.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.
信任根通常是已在 平台,且无法修改。
5.2.1.2. 图像类型
CoT 中的图像分为身份验证图像和数据图像。一 身份验证图像包含用于验证数据图像的信息,或者 另一个身份验证图像。数据镜像通常是引导加载程序二进制文件,但 它可以是需要身份验证的任何其他数据。
5.2.1.3. 组件职责
对于信任链中的每个图像,以下高级操作是 执行以验证它:
- 以静态方式或在运行时为图像分配内存。
- 识别图像并将其加载到分配的内存中。
- 根据图像的类型检查图像的完整性。
- 根据所使用的加密算法对图像进行身份验证。
- 如果图像是身份验证图像,请提取将要 用于验证 CoT 中的下一个图像。
在图 1 中,每个组件负责其中的一个或多个操作。 下面简要介绍这些职责。
5.2.1.3.1. TF-A通用代码和IO框架(GEN/IO)
这些组件负责启动 BL1 或 BL2 中的特定图像。对于每个需要身份验证的 BL 图像, 泛型代码递归地询问身份验证模块什么是父模块 图像,直到达到经过身份验证的图像或 ROT。然后 泛型代码调用 IO 框架来加载图像,并调用 身份验证模块对其进行身份验证,遵循 CoT 从 ROT 到 Image。
5.2.1.3.2. TF-A平台端口(PP)
该平台负责:
- 为每个需要进行身份验证的映像指定 CoT。的详细信息 平台将如何指定 CoT 将在后面解释。平台 此外,还指定了用于 每张图片。
- 静态为每张图像中的每个参数分配内存,即 用于验证 CoT,例如公钥、哈希等的内存。
- 提供 ROTPK 或其哈希。
- 向 IPM 提供额外信息,使其能够识别和 提取图像中包含的身份验证参数,例如,如果 参数存储为 X509v3 扩展名,对应的 OID 必须为 提供。
- 满足 IPM 和 CM 的任何其他内存要求(目前未满足 在本文档中进行了描述)。
- 导出函数以验证使用以下身份验证方法的图像 CM 无法解释,例如,如果必须使用 NV计数器,则要比较的计数器的值只能是 由平台提供。
- 如果正在使用专有图像格式,请导出自定义 IPM(所述 稍后)。
5.2.1.3.3. 认证模块(AM)
它负责:
- 提供必要的抽象机制来描述 CoT。其中 除此之外,必须指定身份验证和图像解析方法 由 CoT 中的 PP 提供。
- 通过使用 GEN 导出的功能来验证 GEN 传递的 CoT PP、IPM 和 CM。
- 跟踪哪些图像已经过验证。如果图像是 多个 CoT,则应仅验证一次,例如受信任的世界 TBBR-Client 规范中的密钥证书包含需要验证的信息 SCP_BL2、BL31、BL32 每个都有单独的 CoT。(这 本文档中未描述责任,但应说明责任 实施起来微不足道)。
- 重复使用用于数据图像的内存来验证身份验证图像,例如 在图 2 中描述的 CoT 中,每个证书都可以加载和 在平台为 BL31 图像预留的内存中进行了验证。作者: 加载BL31(数据图像)时,所有信息都要对其进行认证 将从父图像中提取,即 BL31 内容 证书。假设身份验证图像的大小将 永远不要超过数据图像的大小。应该可以验证这一点 在构建时使用断言。
5.2.1.3.4. 加密模块(CM)
CM 负责提供 API,以便:
- 验证数字签名。
- 验证哈希。
CM 不包含任何与加密相关的代码,但它依赖于 用于执行加密操作的外部库。加密库 (CL) 必须实现链接 CM 和外部库。以下 函数必须由 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 (*calc_hash)(enum crypto_md_algo alg, void *data_ptr,
unsigned int data_len,
unsigned char output[CRYPTO_MD_MAX_SIZE])
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);
这些函数使用宏在 CM 中注册:
REGISTER_CRYPTO_LIB(_name,
_init,
_verify_signature,
_verify_hash,
_calc_hash,
_auth_decrypt,
_convert_pk);
_name
必须是包含 CL 名称的字符串。此名称用于 调试目的。
Crypto 模块提供了一个计算和 使用提供的哈希算法返回给定数据的哈希值。 该函数主要用于 and features 中,用于计算各种图像/数据的哈希值。_calc_hash``MEASURED_BOOT``DRTM_SUPPORT
可选地,可以提供平台功能来转换公钥 (_convert_pk)。仅当平台保存 ROTPK 的哈希值时,才使用它。 大多数平台保存 ROTPK 的哈希值,但有些平台保存的可能略有不同 信息 - 例如 ROTPK 的哈希值以及一些相关信息。 定义此函数可以转换用于验证的 ROTPK 缓冲区的签名(特定于平台的公钥),其中 哈希保存在 OTP 中。
int (*convert_pk)(void *full_pk_ptr, unsigned int full_pk_len,
void **hashed_pk_ptr, unsigned int *hashed_pk_len);
full_pk_ptr
:指向可分辨编码规则 (DER) ROTPK 的指针。full_pk_len
:DER ROTPK 大小。hashed_pk_ptr
:返回指向缓冲区的指针,哪个哈希应该是保存在 OTP 中的哈希。hashed_pk_len
:前一个缓冲区大小
5.2.1.3.5. 图像解析器模块(IPM)
IPM 负责:
- 检查 IO 框架加载的每个图像的完整性。
- 根据 平台在 CoT 描述符中提供的描述。
图像可能具有不同的格式(例如,身份验证图像可能是 x509v3 证书、签名的 ELF 文件或任何其他特定于平台的格式)。 IPM 允许为每种图像格式注册图像解析器库 (IPL) 用于 CoT。该库必须实现特定的方法来解析 图像。IPM 从 CoT 获取图像格式,并调用正确的 IPL 来 检查镜像完整性并解压认证参数。
有关 IPM 提供用于定义和注册 IPL 的机制。
5.2.1.4. 认证方法
AM支持以下认证方法:
- 散 列
- 数字签名
如果平台决定定义,则可以在 CoT 中指定这些方法 自定义 CoT,而不是重用预定义的 CoT。
如果数据图像使用多个方法,则所有方法都必须是 相同的 CoT。参数的数量和类型是特定于方法的。这些 应使用 IPM 从父映像中获取参数。
-
散 列
参数:
- 指向要哈希的数据的指针
- 数据的长度
- 指向哈希的指针
- 哈希的长度
哈希将由以下 ASN 的 DER 编码表示。 类型:
DigestInfo ::= SEQUENCE { digestAlgorithm DigestAlgorithmIdentifier, digest Digest }
这种 ASN.1 结构使得可以删除有关 用作此信息伴随哈希的哈希算法的类型。这 应允许加密库 (CL) 支持多个哈希 算法实现。
-
数字签名
参数:
- 指向要签名的数据的指针
- 数据的长度
- 公钥算法
- 公钥值
- 数字签名算法
- 数字签名值
公钥参数将由 的 DER 编码表示 以下 ASN.1 类型:
SubjectPublicKeyInfo ::= SEQUENCE { algorithm AlgorithmIdentifier{PUBLIC-KEY,{PublicKeyAlgorithms}}, subjectPublicKey BIT STRING }
数字签名算法将由 DER 编码表示 以下 ASN.1 类型。
AlgorithmIdentifier {ALGORITHM:IOSet } ::= SEQUENCE { algorithm ALGORITHM.&id({IOSet}), parameters ALGORITHM.&Type({IOSet}{@algorithm}) OPTIONAL }
数字签名将由以下方面表示:
signature ::= BIT STRING
身份验证框架将使用图像描述符来提取所有 与身份验证相关的信息。
5.2.2. 指定信任链
CoT 可以描述为一组链接在一起的图像描述符,它们以 特定顺序。顺序决定了它们必须处于的顺序 验证。每个图像都有一组属性,允许AM对其进行验证。 下面将介绍这些属性。
PP 负责为数据图像定义单个或多个 CoT。 除非另有说明,否则数据结构如下所述 部分由 PP 静态填充。
5.2.2.1. 描述图像解析方法
解析方法是指特定图像的格式。例如, 表示证书的身份验证图像可能位于 X.509v3 中 格式。表示引导加载程序阶段的数据映像可以是原始二进制文件 或 ELF 格式。IPM 支持三种分析方法。图像必须使用一个 下面描述的三种方法。IPL 负责解释 单一解析方法。对于使用的每种方法,都必须有一个 IPL 平台。
- 原始格式:使用此方法,此格式实际上作为图像是nop 被视为原始二进制格式,例如,引导加载程序图像由 TF-A型。此方法只能由数据图像使用。
- X509V3 方法:此方法使用 X.509 等行业标准来表示 PKI 证书(身份验证图像)。期望开源 将提供可用于解析所表示的图像的库 通过这种方法。此类库可用于编写相应的 IPL 例如,在 mbed TLS 中解析 X.509 库代码。
- 平台定义方法:此方法适用于特定于平台的方法 用于表示身份验证或数据图像的专有标准。为 例如,可以将数据图像的签名附加到数据图像中 原始二进制文件。可以在组合的 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
:提取认证参数函数指针。
该函数将用于初始化 IPL。init()
该函数被传递一个指向内存的指针,其中 image 已被 IO 框架加载,并且 image 长度。它应确保 图像采用与解析方法对应的格式,并且没有 被篡改。例如,RFC-2459 描述了 X.509 证书。check_integrity()
该函数传递一个参数描述符,其中包含 有关要标识的参数 ( 和 ) 的信息,以及 从图像中提取与该参数对应的数据。这些数据将 用于验证 CoT 序列中的当前图像或下一个图像。get_auth_param()``type_desc``cookie
CoT 中的每个图像都将指定它使用的分析方法。此信息 IPM 将使用它来查找图像的正确解析器描述符。
5.2.2.2. 描述认证方法
作为 CoT 的一部分,每个图像都必须指定一种或多种身份验证方法 这将用于验证它。如“身份验证”部分所述 方法“,AM支持三种方法。
typedef enum {
AUTH_METHOD_NONE,
AUTH_METHOD_HASH,
AUTH_METHOD_SIG,
AUTH_METHOD_NUM
} auth_method_type_t;
AM 定义身份验证方法使用的每个参数的类型。它 使用此信息来:
- 指定 IPM 导出的函数,其中 参数应从图像中提取。
get_auth_param()
- 在调用验证函数时正确编组参数 由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_NV_CTR, /* A non-volatile counter */
} 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 进行识别。在这种情况下,可以 包含指向由哈希扩展的平台定义的 OID 的指针 字段,而该字段可以设置为 。值为 0 表示 该字段表示未使用该字段。`cookie``type``AUTH_PARAM_HASH``cookie
对于每种方法,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;
使用字段中指定的方法类型,AM 会找出哪个字段 需要在联盟内部访问。type``param
5.2.2.3. 存储认证参数
用于验证图像的参数可能是 从图像本身或其父图像获取。分配的内存 为了加载父图像,将重新用于加载子图像。因此 从父级获取的参数,用于验证子级图像的需求 为它们单独分配内存,以便存储它们。这 内存必须由平台端口静态分配。auth_param_type_desc_t
AM定义了以下结构来存储对应于一个 authentication 参数。
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 为 负责填充 AND 字段 执行函数时。auth_param_ptr``auth_param_len``img_get_auth_param()
AM 定义了以下结构,使图像能够描述 应从中提取并用于验证下一张图像的参数 (孩子)在婴儿床上。
typedef struct auth_param_desc_s {
auth_param_type_desc_t type_desc;
auth_param_data_desc_t data;
} auth_param_desc_t;
5.2.2.4. 在CoT中描述图像
CoT 中的图像是所描述的 CoT 的以下方面的整合 以上。
- 由平台指定的唯一标识符,允许 IO 框架 在 FIP 中找到图像,并将其加载到为数据保留的内存中 CoT 中的图像。
- AM 用来查找合适的 IPM 的一种解析方法。
- 身份验证方法及其参数,如上所述 部分。这些用于验证当前图像。
- 用于验证当前 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 被定义为指向结构的指针数组 通过字段链接在一起。那些没有父节点的节点必须是 使用存储在平台中的 ROTPK 进行身份验证。auth_image_desc_t``parent
5.2.3. 实现示例
本部分是一份详细的指南,解释了使用 身份验证框架。此示例对应于 Applicative TBBR-Client 文档中指定的功能模式 (AFM)。是的 建议阅读本指南和源代码。
5.2.3.1. TBBR CoT
特定于 BL1 和 BL2 的 CoT 可以分别在 和 中找到。跨 BL1 和 BL2 可以在 中找到。 此 CoT 由指向图像描述符的指针数组组成,它是 使用宏在框架中注册,其中必须是数组的名称(传递指针或任何其他 间接类型将导致注册过程失败)。drivers/auth/tbbr/tbbr_cot_bl1.c``drivers/auth/tbbr/tbbr_cot_bl2.c``drivers/auth/tbbr/tbbr_cot_common.c``REGISTER_COT(cot_desc)``cot_desc
参与启动过程的映像数量取决于 CoT。 但是,在 TF-A 中,有一组最小的图像是必需的,因此 所有 CoT 必须出示:
BL2
SCP_BL2
(特定于平台)BL31
BL32
(可选)BL33
TBBR 指定了这些映像必须附带的其他证书 用于正确的身份验证。有关 TBBR CoT 的详细信息,请参阅受信任板启动文档。
按照移植指南,平台必须提供独特的 将在 启动过程。如果平台使用 TBBR 作为受信任启动的参考, 这些标识符可以从 中获取。 Arm 平台将此文件包含在 中。其他 平台也可能包含此文件或提供自己的标识符。include/common/tbbr/tbbr_img_def.h``include/plat/arm/common/arm_def.h
重要提示:身份验证模块使用这些标识符来索引 CoT 数组,因此数组中的描述符位置必须与标识符匹配。
每个图像描述符必须指定:
img_id
:平台定义的对应图像唯一标识符。img_type
:图像解析器模块使用图像类型来调用正确的 解析库以检查图像完整性并提取所需的 身份验证参数。目前支持三种类型的图像:IMG_RAW
:图像是原始二进制文件。没有可用的解析函数, 除了阅读整个图像。IMG_PLAT
:图像格式特定于平台。平台可能会使用此 认证不直接支持的自定义镜像的类型 框架。IMG_CERT
:映像是 x509v3 证书。
parent
:指向父图像描述符的指针。父级将包含 验证当前图像所需的信息。如果父母 为 NULL,则认证参数将从平台获取 (即 BL2 和受信任密钥证书使用 ROT 私有证书进行签名 密钥,其公共部分存储在平台中)。img_auth_methods
:这指向一个数组,该数组定义了 必须检查才能考虑图像的身份验证方法 认证。每种方法都由一个类型和一个参数列表组成 描述 符。参数描述符由类型和 cookie 组成,该 cookie 将指向从中提取该参数所需的特定信息 图像(即,如果参数存储在 x509v3 扩展中,则 cookie 将指向扩展名 OID)。根据方法类型,一个 必须指定不同数量的参数。此指针不应是 零。 支持的方法包括:AUTH_METHOD_HASH
:图像的哈希值必须与提取的哈希值匹配 从父映像。以下参数描述符必须是 指定:data
:要哈希的数据(从当前图像获取)hash
:引用哈希(从父图像获取)
AUTH_METHOD_SIG
:必须对图像(通常是证书)进行签名 从父映像中提取公共部分的私钥(或 如果父级为 NULL,则为平台)。以下参数描述符 必须指定:pk
:公钥(从父图像获取)sig
:数字签名(从当前图像获得)alg
:使用的签名算法(从当前图像中获得)data
:要签名的数据(从当前图像中获取)
authenticated_data
:此数组指针指示什么身份验证 一旦图像经过身份验证,就必须从图像中提取参数。 每个参数都由参数描述符和缓冲区组成 address/size 来存储参数。CoT 负责分配 存储参数所需的内存。此指针可能为 NULL。
在该文件中,分配了一组缓冲区来存储参数 从证书中提取。在 TBBR CoT 的情况下,这些参数 是哈希和公钥。在 DER 格式中,RSA-4096 公钥需要 550 字节,哈希需要 51 个字节。取决于 CoT 和身份验证 过程中,某些缓冲区可能会在启动过程中的不同阶段重复使用。tbbr_cot*.c
接下来,在该文件中,定义参数描述符。这些描述符将 用于从对应图像中提取参数数据。
5.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
}
}
}
};
受信任密钥证书使用 ROT 私钥签名,并包含 受信任世界公钥和不受信任世界公钥,如 x509v3 扩展。这必须分别使用 和 数组在图像描述符中指定。img_auth_methods``authenticated_data
受信任密钥证书通过检查其数字签名进行身份验证 使用 ROTPK.检查签名需要四个参数:公众 密钥、算法、签名和已签名的数据。因此 必须使用身份验证方法指定四个参数描述符:
subject_pk
:类型的参数描述符。此类型 用于从父镜像中提取公钥。如果 cookie 是 OID,则密钥是从相应的 x509v3 扩展中提取的。如果 cookie 为 NULL,则检索主题公钥。在这种情况下,因为 父镜像为NULL,公钥从平台获取 (此密钥将是 ROTPK)。AUTH_PARAM_PUB_KEY
sig
:类型的参数描述符。它用于提取 证书中的签名。AUTH_PARAM_SIG
sig_alg
:类型的参数描述符。它用于 从证书中提取签名算法。AUTH_PARAM_SIG
raw_data
:类型的参数描述符。它被用于 从证书中提取要签名的数据。AUTH_PARAM_RAW_DATA
一旦检查了签名并验证了证书,那么 需要从证书中提取 Trusted World 公钥。新条目 为此目的在数组中创建。在该条目中, 必须将相应的参数描述符与缓冲区一起指定 address 来存储参数值。在这种情况下,描述符用于从具有 OID 的 x509v3 扩展中提取公钥。BL31 密钥证书将使用此描述符作为 参数。密钥存储在缓冲区中。authenticated_data``trusted_world_pk``TRUSTED_WORLD_PK_OID``trusted_world_pk_buf
BL31 密钥证书通过检查其数字签名进行身份验证 使用之前从受信任密钥获取的受信任世界公钥 证书。在图像描述符中,我们指定了单一的身份验证方法 通过签名,其公钥是 .一旦这个证书 已经过认证,我们得解压BL31公钥,存储在 由 指定的扩展名。此键将被复制到缓冲区。trusted_world_pk``soc_fw_content_pk``content_pk_buf
BL31 证书通过检查其数字签名进行身份验证 使用之前从 BL31 密钥证书获取的 BL31 公钥。 我们指定使用公钥的身份验证方法。 身份验证后,我们需要提取存储在扩展中的 BL31 哈希值 由 指定。此哈希将被复制到缓冲区。soc_fw_content_pk``soc_fw_hash``soc_fw_hash_buf
BL31 图像通过计算其哈希值并匹配它来进行身份验证 使用从 BL31 证书获得的哈希值。图像描述符包含 通过哈希的单一身份验证方法。哈希方法的参数是 引用哈希 和要进行哈希处理的数据。在本例中, 它是整个图像,因此我们指定 .soc_fw_hash``raw_data
5.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
5.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 crypto_mod_calc_hash(enum crypto_md_algo alg, void *data_ptr,
unsigned int data_len,
unsigned char output[CRYPTO_MD_MAX_SIZE])
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。
注意
如果代码大小是一个问题,则构建选项可以 在平台 Makefile 中定义。它将使 mbed TLS 使用 SHA-256 的实现,内存占用量更小(~1.5 KB 少),但 较慢 (~30%)。MBEDTLS_SHA256_SMALLER