Linux Kernel中非对称密码算法的实现

本文详细介绍了Linux Kernel中RSA、ECDSA、SM2和ECRDSA四种非对称加密算法的实现,包括关键函数、接口及其实现的功能。如RSA的公钥私钥设置和加解密,ECDSA的公钥验签等。同时提供了一个使用示例,展示了如何在Linux Kernel中调用这些非对称加密算法。
摘要由CSDN通过智能技术生成

引流关键词: AES, ECB,CBC,XTS,CTR,OFB,CFB,RSA,RSA1024,RSA2048,RSA3072,ECC,ECDSA,加密,解密,加解密,国密,SM2,SM3,SM4,openssl,mbedtls

快速链接:
.
👉👉👉 个人博客笔记导读目录(全部) 👈👈👈


说明:
在默认情况下,本文讲述的都是ARMV8-aarch64架构,linux kernel 5.14

1、RSA 开关

RSA的实现由CONFIG_CRYPTO_RSA 宏控制,该宏依赖于:

  • CONFIG_CRYPTO_AKCIPHER
  • CONFIG_CRYPTO_MANAGER
  • CONFIG_MPILIB
  • CONFIG_ASN1
(linux/crypto/Kconfig)

config CRYPTO_RSA
	tristate "RSA algorithm"
	select CRYPTO_AKCIPHER
	select CRYPTO_MANAGER
	select MPILIB
	select ASN1
	help
	  Generic implementation of the RSA public key algorithm.
2、RSA 实现
(linux/crypto/rsa.c)

static struct akcipher_alg rsa = {
	.encrypt = rsa_enc,
	.decrypt = rsa_dec,
	.set_priv_key = rsa_set_priv_key,
	.set_pub_key = rsa_set_pub_key,
	.max_size = rsa_max_size,
	.exit = rsa_exit_tfm,
	.base = {
		.cra_name = "rsa",
		.cra_driver_name = "rsa-generic",
		.cra_priority = 100,
		.cra_module = THIS_MODULE,
		.cra_ctxsize = sizeof(struct rsa_mpi_key),
	},
};

主要实现了4个功能:

  • rsa_set_priv_key
  • rsa_set_pub_key
  • rsa_enc
  • rsa_dec

其中rsa_set_priv_keyrsa_set_pub_key的实现,主要就是接受raw格式的密钥(DER格密钥),将其转换成nddpq等因子填充到密码学结构体中。
rsa_encrsa_dec ,主要就是公钥加密、私钥解密的这种用法。

此类密码学具体算法的实现,都是由linux/lib/mpi 第三方libary实现的,是一种C语言的实现方式。

3、其它非对称密码

(1)、实现了3个ecdsa的密码算法

  • ecdsa_nist_p192
  • ecdsa_nist_p256
  • ecdsa_nist_p384

以为ecdsa_nist_p192 为例:

(linux/crypto/ecdsa.c)

static struct akcipher_alg ecdsa_nist_p192 = {
	.verify = ecdsa_verify,
	.set_pub_key = ecdsa_set_pub_key,
	.max_size = ecdsa_max_size,
	.init = ecdsa_nist_p192_init_tfm,
	.exit = ecdsa_exit_tfm,
	.base = {
		.cra_name = "ecdsa-nist-p192",
		.cra_driver_name = "ecdsa-nist-p192-generic",
		.cra_priority = 100,
		.cra_module = THIS_MODULE,
		.cra_ctxsize = sizeof(struct ecc_ctx),
	},
};

仅仅实现了两个接口函数:

  • ecdsa_verify : 公钥验签
  • ecdsa_set_pub_key :导入公钥

(2)、实现了1个sm2的密码算法

(linux/crypto/sm2.c)

static struct akcipher_alg sm2 = {
	.verify = sm2_verify,
	.set_pub_key = sm2_set_pub_key,
	.max_size = sm2_max_size,
	.init = sm2_init_tfm,
	.exit = sm2_exit_tfm,
	.base = {
		.cra_name = "sm2",
		.cra_driver_name = "sm2-generic",
		.cra_priority = 100,
		.cra_module = THIS_MODULE,
		.cra_ctxsize = sizeof(struct mpi_ec_ctx),
	},
};

仅仅实现了两个接口函数:

  • sm2_verify : 公钥验签
  • sm2_set_pub_key :导入公钥

(3)、实现了1个ecr的密码算法

(linux/crypto/ecrdsa.c)

static struct akcipher_alg ecrdsa_alg = {
	.verify		= ecrdsa_verify,
	.set_pub_key	= ecrdsa_set_pub_key,
	.max_size	= ecrdsa_max_size,
	.exit		= ecrdsa_exit_tfm,
	.base = {
		.cra_name	 = "ecrdsa",
		.cra_driver_name = "ecrdsa-generic",
		.cra_priority	 = 100,
		.cra_module	 = THIS_MODULE,
		.cra_ctxsize	 = sizeof(struct ecrdsa_ctx),
	},
};

仅仅实现了两个接口函数:

  • ecrdsa_verify : 公钥验签
  • ecrdsa_set_pub_key :导入公钥
4、非对称密码算法的使用示例

如下所示,实现了public_key_verify_signature(key,signature), 这个函数的实现,也被export出来,相当于又封装了一层。
另外其它模块如果有对非对称密码学算法的需求,也可以直接调用非对称密码学算法的API,例如直接调用如下这样的函数:

  • crypto_akcipher_verify()
  • crypto_akcipher_set_pub_key()

如下是public_key_verify_signature(key,signature)的实现,也可以当作非对称密码学算法的使用示例:

(linux/crypto/asymmetric_keys/public_key.c)



/*
 * Verify a signature using a public key.
 */
int public_key_verify_signature(const struct public_key *pkey,
				const struct public_key_signature *sig)
{
	struct crypto_wait cwait;
	struct crypto_akcipher *tfm;
	struct akcipher_request *req;
	struct scatterlist src_sg[2];
	char alg_name[CRYPTO_MAX_ALG_NAME];
	char *key, *ptr;
	int ret;

	pr_devel("==>%s()\n", __func__);

	BUG_ON(!pkey);
	BUG_ON(!sig);
	BUG_ON(!sig->s);

	ret = software_key_determine_akcipher(sig->encoding,
					      sig->hash_algo,
					      pkey, alg_name);
	if (ret < 0)
		return ret;

	tfm = crypto_alloc_akcipher(alg_name, 0, 0);
	if (IS_ERR(tfm))
		return PTR_ERR(tfm);

	ret = -ENOMEM;
	req = akcipher_request_alloc(tfm, GFP_KERNEL);
	if (!req)
		goto error_free_tfm;

	key = kmalloc(pkey->keylen + sizeof(u32) * 2 + pkey->paramlen,
		      GFP_KERNEL);
	if (!key)
		goto error_free_req;

	memcpy(key, pkey->key, pkey->keylen);
	ptr = key + pkey->keylen;
	ptr = pkey_pack_u32(ptr, pkey->algo);
	ptr = pkey_pack_u32(ptr, pkey->paramlen);
	memcpy(ptr, pkey->params, pkey->paramlen);

	if (pkey->key_is_private)
		ret = crypto_akcipher_set_priv_key(tfm, key, pkey->keylen);
	else
		ret = crypto_akcipher_set_pub_key(tfm, key, pkey->keylen);
	if (ret)
		goto error_free_key;

	if (sig->pkey_algo && strcmp(sig->pkey_algo, "sm2") == 0 &&
	    sig->data_size) {
		ret = cert_sig_digest_update(sig, tfm);
		if (ret)
			goto error_free_key;
	}

	sg_init_table(src_sg, 2);
	sg_set_buf(&src_sg[0], sig->s, sig->s_size);
	sg_set_buf(&src_sg[1], sig->digest, sig->digest_size);
	akcipher_request_set_crypt(req, src_sg, NULL, sig->s_size,
				   sig->digest_size);
	crypto_init_wait(&cwait);
	akcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG |
				      CRYPTO_TFM_REQ_MAY_SLEEP,
				      crypto_req_done, &cwait);
	ret = crypto_wait_req(crypto_akcipher_verify(req), &cwait);

error_free_key:
	kfree(key);
error_free_req:
	akcipher_request_free(req);
error_free_tfm:
	crypto_free_akcipher(tfm);
	pr_devel("<==%s() = %d\n", __func__, ret);
	if (WARN_ON_ONCE(ret > 0))
		ret = -EINVAL;
	return ret;
}
EXPORT_SYMBOL_GPL(public_key_verify_signature);
5、总结

Linux Kernel非对称密码算法的实现总结如下:

  • 实现了RSA的:“导入公钥、导入私钥、公钥加密私钥解密” 功能
  • 实现了ecdsa的:”导入公钥、公钥验签” 功能
  • 实现了sm2的:”导入公钥、公钥验签” 功能
  • 实现了ecr的:”导入公钥、公钥验签” 功能
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

代码改变世界ctw

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值