ATF密钥生成和验签

ATF密钥生成和验签

根密钥生成

  1. 密钥的生成依赖openssl库,需要提前安装:

    sudo apt-get install openssl
    
  2. 生成.pem格式的RSA4096私钥

    openssl genrsa -out pri_key.pem 4096
    
  3. 生成对应的DER格式公钥

     openssl rsa -in pri_key.pem -pubout -out pub_key.der -outform DER
    
  4. 计算公钥hash

    openssl dgst -sha256 -binary pub_key.der > pub_key_sha256.bin
    

这里生成的私钥即可用于image的签名,公钥可用于验签,rotpk(根公钥)的hash通常存储在efuse或者otp中。根据ATF中定义的CoT实例,rotpk用于对trusted_boot_fw_cert和trusted_key_cert进行验签。

为什么不直接在efuse和otp中直接存储公钥?

原因之一为公钥通常比较大,直接放在efuse中会占用较大空间,不划算。而使用sha256算法进行hash计算得到的摘要仅256bit,存储在efuse中不会占太大空间。

验签

由于efuse中存储的值是rotpk的hash,这样就导致一个问题,在信任链建立的初始阶段,无法从efuse中直接得到公钥对image进行验签, 该如何解决?

因为trusted_boot_fw_cert和trusted_key_cert是使用根密钥进行签名的,对应的公钥会被存储在x509证书内部。

x509证书结构

重要的组成部分为与签名该证书的私钥对应的公钥,尾部的证书自身的签名

image

那么在验签的时候就需要:

  1. 从证书中取出公钥对证书本身进行验签。这样保证了证书内容没被修改,但是不能保证公钥是否被修改。验签详细步骤为:

    • 从证书中提取数字签名。
    • 使用相同的哈希函数对证书内容(除了数字签名)进行哈希计算,得到一个新的哈希值。
    • 使用公钥对数字签名进行解密,解密后应该得到与新哈希值相同的原始哈希值。
    • 如果解密后的哈希值与新计算的哈希值相同,那么数字签名验证成功,这表明证书未被篡改。
  2. 然后需要对从证书中取出的公钥计算hash,并与efuse中存储的hash值做比较。如果相同则验签通过,否则验签失败。

    对应的code位于drivers/auth/auth_mod.c​:

/*
 * Authenticate by digital signature
 *
 * This function implements 'AUTH_METHOD_SIG'. To authenticate an image using
 * this method, the image must contain:
 *
 *   - Data to be signed
 *   - Signature
 *   - Signature algorithm
 *
 * We rely on the image parser module to extract this data from the image.
 * The parent image must contain:
 *
 *   - Public key (or a hash of it)
 *
 * If the parent image contains only a hash of the key, we will try to obtain
 * the public key from the image itself (i.e. self-signed certificates). In that
 * case, the signature verification is considered just an integrity check and
 * the authentication is established by calculating the hash of the key and
 * comparing it with the hash obtained from the parent.
 *
 * If the image has no parent (NULL), it means it has to be authenticated using
 * the ROTPK stored in the platform. Again, this ROTPK could be the key itself
 * or a hash of it.
 *
 * Return: 0 = success, Otherwise = error
 */
static int auth_signature(const auth_method_param_sig_t *param,
			  const auth_img_desc_t *img_desc,
			  void *img, unsigned int img_len)
{
	void *data_ptr, *pk_ptr, *pk_hash_ptr, *sig_ptr, *sig_alg_ptr;
	unsigned int data_len, pk_len, pk_hash_len, sig_len, sig_alg_len;
	unsigned int flags = 0;
	int rc = 0;

	/* Get the data to be signed from current image */
	rc = img_parser_get_auth_param(img_desc->img_type, param->data,
			img, img_len, &data_ptr, &data_len);
	return_if_error(rc);

	/* Get the signature from current image */
	rc = img_parser_get_auth_param(img_desc->img_type, param->sig,
			img, img_len, &sig_ptr, &sig_len);
	return_if_error(rc);

	/* Get the signature algorithm from current image */
	rc = img_parser_get_auth_param(img_desc->img_type, param->alg,
			img, img_len, &sig_alg_ptr, &sig_alg_len);
	return_if_error(rc);

	/* Get the public key from the parent. If there is no parent (NULL),
	 * the certificate has been signed with the ROTPK, so we have to get
	 * the PK from the platform */
	if (img_desc->parent) {
		rc = auth_get_param(param->pk, img_desc->parent,
				&pk_ptr, &pk_len);
	} else {
		rc = plat_get_rotpk_info(param->pk->cookie, &pk_ptr, &pk_len,
				&flags);
	}
	return_if_error(rc);

	//如果ROTPK是hash,就需要从证书中获取公钥,使用这个公钥验签
	if (flags & (ROTPK_IS_HASH | ROTPK_NOT_DEPLOYED)) {
		/* If the PK is a hash of the key or if the ROTPK is not
		   deployed on the platform, retrieve the key from the image */
		pk_hash_ptr = pk_ptr;
		pk_hash_len = pk_len;
		rc = img_parser_get_auth_param(img_desc->img_type,
					param->pk, img, img_len,
					&pk_ptr, &pk_len);
		return_if_error(rc);

		/* Ask the crypto module to verify the signature */
		rc = crypto_mod_verify_signature(data_ptr, data_len,
						 sig_ptr, sig_len,
						 sig_alg_ptr, sig_alg_len,
						 pk_ptr, pk_len);
		return_if_error(rc);

		if (flags & ROTPK_NOT_DEPLOYED) {
			NOTICE("ROTPK is not deployed on platform. "
				"Skipping ROTPK verification.\n");
		} else {
#if PLAT_VERIFY_ROTPK
		//还需要验证证书中公钥是否合法,这是平台定义的,一般是计算公钥hash并与OTP中的hash对比。
			rc = plat_verify_rotpk(pk_ptr, pk_len,
					pk_hash_ptr, pk_hash_len);
#else
			/* platform may store the hash of a prefixed, suffixed or modified pk */
			rc = plat_convert_pk(pk_ptr, pk_len, &pk_ptr, &pk_len);
			return_if_error(rc);

			/* Ask the crypto-module to verify the key hash */
			rc = crypto_mod_verify_hash(pk_ptr, pk_len,
				    pk_hash_ptr, pk_hash_len);
#endif
		}
	} else {
		/* Ask the crypto module to verify the signature */
		rc = crypto_mod_verify_signature(data_ptr, data_len,
						 sig_ptr, sig_len,
						 sig_alg_ptr, sig_alg_len,
						 pk_ptr, pk_len);
	}

	return rc;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Liangtao`

请作者喝杯咖啡吧~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值