参考链接
- Linux加密框架中的主要数据结构(四)_家有一希的博客-CSDN博客
- algapi.h - include/crypto/algapi.h - Linux source code (v5.15.11) - Bootlin
struct crypto_instance {struct crypto_alg alg;struct crypto_template *tmpl;union {/* Node in list of instances after registration. */struct hlist_node list;/* List of attached spawns before registration. */struct crypto_spawn *spawns;};void *__ctx[] CRYPTO_MINALIGN_ATTR;
};
算法模板实例数据结构 crypto_instance各成员变量含义如下所示:
- 1)alg:算法模板实例对应的算法说明
- Linux加密框架crypto crypto_alg|cipher_alg数据结构|AES例子_CHYabc123456hh的博客-CSDN博客
- 2)tmpl:算法模板实例使用的算法模板
- algapi.h - include/crypto/algapi.h - Linux source code (v5.15.11) - Bootlin
- 3)list:算法模板实例在算法模板的实例哈希链表中对应的节点。
- 注册后实例列表中的节点。
- spawns:注册前的附加生成列表。
- algapi.h - include/crypto/algapi.h - Linux source code (v5.15.11) - Bootlin
- 4)__ctx:算法模板实例的上下文。
例子
- 由算法模板实例数据结构定义,算法模板实例也是一种算法,如分组算法根据算法模板(如CBC模式)创建的块加密算法。
- CBC算法模板的创建实例接口为crypto_cbc_alloc,输入参数为创建CBC算法模板实例的参数tb,返回值为新创建的算法模板实例。
- crypto_cbc_alloc函数创建CBC算法模板流程如下所示
- 上面参考链接的内容,如下,但是在目前较为新的版本中 v5.15.11已经不再使用了
- 根据上述流程进行推导
- 无论是通过alloc接口还是create接口创建算法模板实例,输入参数tb为创建算法模板实例的相关参数,至少包括算法类型及屏蔽位(tb[0])和基础算法的算法名(tb[1])。每个参数都是TLV格式,类型T有CRYPTOA_TYPE(算法类型)、CRYPTOA_ALG(基础算法名)、CRYPTOA_U32等多种类型,而每种类型的参数值不同,因此接口输入参数tb的数据类型struct rtattr只包括rta_len和rta_type两个成员变量,分别对应着TLV结构的L和T,参数值数据结构根据参数类型定义。
- 参数类型为CRYPTOA_TYPE时,算法类型TLV结构(即tb[0])如下所示,通过函数crypto_get_attr_type可以获取算法类型和屏蔽位。
/* Generic structure for encapsulation of optional route information.It is reminiscent of sockaddr, but with sa_family replacedwith attribute type.*/struct rtattr {unsigned short rta_len;unsigned short rta_type;
};
- Linux加密框架 crypto 算法模板_CHYabc123456hh的博客-CSDN博客
- 首先调用 crypto_attr_type
- 其中 crypto_attr_type 显示如下,包含type和mask
- crypto_attr_type返回的类型是 RTA_DATA(rta),
- 其中RTA_DATA 定义如下,返回的是void*指向一块内存区域,这个内存区域使用的时候可以转型为crypto_attr_type的结构
- #define RTA_DATA(rta) ((void*)(((char*)(rta)) + RTA_LENGTH(0)))
- #define RTA_LENGTH(len) (RTA_ALIGN(sizeof(struct rtattr)) + (len))
struct crypto_attr_type {u32 type;u32 mask;
};
- Linux加密框架 crypto 算法模板_CHYabc123456hh的博客-CSDN博客
- 参数类型为CRYPTOA_ALG时,基础算法名TLV结构(即tb[1])如下所示,通过函数crypto_attr_alg_name获取基础算法名
- crypto_template结构体内部的 create函数,需要输入 crypto_template模板名字和rtattr类型(rta_len 和 rta_type )进行创建
- crypto_spawn
- list: 在基础算法的用户链表users中的链表节点
- alg: 关联的基础算法
- frontend: 关联的算法实例前端,即算法类型常量
- mask: 算法的类型屏蔽位
- crypto_type
- 例子
- Linux加密框架 crypto 算法模板 CBC模板举例_CHYabc123456hh的博客-CSDN博客
/*** skcipher_alloc_instance_simple - allocate instance of simple block cipher mode** Allocate an skcipher_instance for a simple block cipher mode of operation,* e.g. cbc or ecb. The instance context will have just a single crypto_spawn,* that for the underlying cipher. The {min,max}_keysize, ivsize, blocksize,* alignmask, and priority are set from the underlying cipher but can be* overridden if needed. The tfm context defaults to skcipher_ctx_simple, and* default ->setkey(), ->init(), and ->exit() methods are installed.** @tmpl: the template being instantiated* @tb: the template parameters** Return: a pointer to the new instance, or an ERR_PTR(). The caller still* needs to register the instance.*/struct skcipher_instance *skcipher_alloc_instance_simple(struct crypto_template *tmpl, struct rtattr **tb)
{u32 mask;struct skcipher_instance *inst;struct crypto_cipher_spawn *spawn;struct crypto_alg *cipher_alg;int err;err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_SKCIPHER, &mask);if (err)return ERR_PTR(err);inst = kzalloc(sizeof(*inst) + sizeof(*spawn), GFP_KERNEL);if (!inst)return ERR_PTR(-ENOMEM);spawn = skcipher_instance_ctx(inst);err = crypto_grab_cipher(spawn, skcipher_crypto_instance(inst),crypto_attr_alg_name(tb[1]), 0, mask);if (err)goto err_free_inst;cipher_alg = crypto_spawn_cipher_alg(spawn);err = crypto_inst_setname(skcipher_crypto_instance(inst), tmpl->name,cipher_alg);if (err)goto err_free_inst;inst->free = skcipher_free_instance_simple;/* Default algorithm properties, can be overridden */inst->alg.base.cra_blocksize = cipher_alg->cra_blocksize;inst->alg.base.cra_alignmask = cipher_alg->cra_alignmask;inst->alg.base.cra_priority = cipher_alg->cra_priority;inst->alg.min_keysize = cipher_alg->cra_cipher.cia_min_keysize;inst->alg.max_keysize = cipher_alg->cra_cipher.cia_max_keysize;inst->alg.ivsize = cipher_alg->cra_blocksize;/* Use skcipher_ctx_simple by default, can be overridden */inst->alg.base.cra_ctxsize = sizeof(struct skcipher_ctx_simple);inst->alg.setkey = skcipher_setkey_simple;inst->alg.init = skcipher_init_tfm_simple;inst->alg.exit = skcipher_exit_tfm_simple;return inst;err_free_inst:skcipher_free_instance_simple(inst);return ERR_PTR(err);
}
inst = kzalloc(sizeof(*inst) + sizeof(*spawn), GFP_KERNEL);
- 其中,*spawn的类型是crypto_cipher_spawn,参见代码:crypto_cipher_spawn是在crypto_spawn的基础上是进一步封装
struct crypto_cipher_spawn {struct crypto_spawn base;
};
- 回到参考链接中
- Linux加密框架中的主要数据结构(四)_家有一希的博客-CSDN博客
- head为0,表示算法模板实例前不预留空间
- spawn = skcipher_instance_ctx(inst)
- skcipher.h - include/crypto/internal/skcipher.h - Linux source code (v5.15.11) - Bootlin
- algapi.h - include/crypto/algapi.h - Linux source code (v5.15.11) - Bootlin
- 通过上述两个函数,实现了spawn和inst->_ctx 指向同一片区域,如图所示
- cipher_alg = crypto_spawn_cipher_alg(spawn);
- cipher.h - include/crypto/internal/cipher.h - Linux source code (v5.15.11) - Bootlin
- 也就是 spawn起到了一个衔接器的作用,衔接算法模板实例inst 和 基础算法cipher_alg
- 设置个性化算法属性,继承基础算法的算法属性 和 设置算法通用属性
- 参考链接里面中的 crypto_cbc_alloc函数接口好像不再使用了,目前与其相近是函数流程如下
整体流程