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

描述

作者简介:

baron (csdn:代码改变世界ctw),九年手机安全/SOC底层安全开发经验。擅长trustzone/tee安全产品的设计和开发。

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

目录

1、RSA 开关

2、RSA 实现

3、其它非对称密码

4、非对称密码算法的使用示例

5、总结

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个功能:

rsasetpriv_key

rsasetpub_key

rsa_enc

rsa_dec

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

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

3、其它非对称密码

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

ecdsanistp192

ecdsanistp256

ecdsanistp384

以为ecdsanistp192 为例:

 

(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 : 公钥验签

ecdsasetpub_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 : 公钥验签

sm2setpub_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 : 公钥验签

ecrdsasetpub_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()
", __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
", __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的:”导入公钥、公钥验签” 功能

 

原文标题:Linux Kernel中非对称密码算法的实现

文章出处:【微信公众号:Linux阅码场】欢迎添加关注!文章转载请注明出处。  

      审核编辑:彭静
打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分