crypto_alloc_ahash函数
- 加密框架中的哈希算法可以是同步方式实现的也可以是异步方式实现的,但是算法应用不关注哈希算法的实现方式,关注的是哈希算法提供的算法接口。为实现统一管理,加密框架默认哈希算法的实现方式为异步方式,将哈希算法的外部接口统一定义为异步哈希算法接口。
- 算法实例是算法应用和加密框架之间的桥梁,算法应用通过算法实例实现算法调用。以哈希算法实例为例,在IPSEC框架的AH协议模块中,协议状态初始化(ah_init_state函数)时,将根据配置的认证算法名(x->aalg->alg_name)创建对应的异步哈希算法实例ahash,如下所示。
- ah4.c - net/ipv4/ah4.c - Linux source code (v5.15.12) - Bootlin
static int ah_init_state(struct xfrm_state *x)
{struct ah_data *ahp = NULL;struct xfrm_algo_desc *aalg_desc;struct crypto_ahash *ahash;if (!x->aalg)goto error;if (x->encap)goto error;ahp = kzalloc(sizeof(*ahp), GFP_KERNEL);if (!ahp)return -ENOMEM;ahash = crypto_alloc_ahash(x->aalg->alg_name, 0, 0);if (IS_ERR(ahash))goto error;ahp->ahash = ahash;if (crypto_ahash_setkey(ahash, x->aalg->alg_key,(x->aalg->alg_key_len + 7) / 8))goto error;/** Lookup the algorithm description maintained by xfrm_algo,* verify crypto transform properties, and store information* we need for AH processing. This lookup cannot fail here* after a successful crypto_alloc_ahash().*/aalg_desc = xfrm_aalg_get_byname(x->aalg->alg_name, 0);BUG_ON(!aalg_desc);if (aalg_desc->uinfo.auth.icv_fullbits/8 !=crypto_ahash_digestsize(ahash)) {pr_info("%s: %s digestsize %u != %hu\n",__func__, x->aalg->alg_name,crypto_ahash_digestsize(ahash),aalg_desc->uinfo.auth.icv_fullbits / 8);goto error;}ahp->icv_full_len = aalg_desc->uinfo.auth.icv_fullbits/8;ahp->icv_trunc_len = x->aalg->alg_trunc_len/8;if (x->props.flags & XFRM_STATE_ALIGN4)x->props.header_len = XFRM_ALIGN4(sizeof(struct ip_auth_hdr) +ahp->icv_trunc_len);elsex->props.header_len = XFRM_ALIGN8(sizeof(struct ip_auth_hdr) +ahp->icv_trunc_len);if (x->props.mode == XFRM_MODE_TUNNEL)x->props.header_len += sizeof(struct iphdr);x->data = ahp;return 0;error:if (ahp) {crypto_free_ahash(ahp->ahash);kfree(ahp);}return -EINVAL;
}
- crypto_alloc_ahash函数的输入参数包括算法名alg_name、算法类型type和算法类型屏蔽字mask,返回值为新创建的异步哈希算法实例,函数处理流程非常简单,调用crypto_alloc_tfm函数创建算法alg_name对应的异步哈希算法实例。
struct crypto_ahash *crypto_alloc_ahash(const char *alg_name, u32 type,u32 mask)
{return crypto_alloc_tfm(alg_name, &crypto_ahash_type, type, mask);
}
EXPORT_SYMBOL_GPL(crypto_alloc_ahash);
crypto_alloc_tfm函数
static inline void *crypto_alloc_tfm(const char *alg_name,const struct crypto_type *frontend, u32 type, u32 mask)
{return crypto_alloc_tfm_node(alg_name, frontend, type, mask, NUMA_NO_NODE);
}
- crypto_alloc_tfm函数的输入参数包括算法名alg_name、算法前端fronted(即算法类型常量)、算法类型type和算法类型屏蔽字mask
- 处理流程如下图所示。
- 1)crypto_alloc_tfm函数内部嵌套了一个函数crypto_alloc_tfm_node
- crypto_alloc_tfm_node函数 处理流程包括两步,第一步调用crypto_find_alg函数查找符合条件的算法alg,第二步调用crypto_create_tfm_node函数根据算法alg创建对应的算法实例tfm。
- 2)crypto_alloc_tfm_node函数返回一个void*类型的通用指针(即内存地址),由直接或间接的调用者负责解释通用指针的具体含义(即具体表示何种数据结构的指针)(使用的时候,将void*转化为 具体使用的结构体指针),如crypto_alloc_ahash函数作为直接调用者将crypto_alloc_tfm函数返回的通用指针解释为异步哈希算法实例的指针。
- 即 将void* 转化为 crypto_ahash* 类型的指针
- api.c - crypto/api.c - Linux source code (v5.15.12) - Bootlin
- 3)crypto_alloc_ahash函数调用crypto_alloc_tfm函数时,输入的算法前端为crypto_ahash_type,定义如下所示。
- ahash.c - crypto/ahash.c - Linux source code (v5.15.12) - Bootlin
static const struct crypto_type crypto_ahash_type = {.extsize = crypto_ahash_extsize,.init_tfm = crypto_ahash_init_tfm,.free = crypto_ahash_free_instance,
#ifdef CONFIG_PROC_FS.show = crypto_ahash_show,
#endif.report = crypto_ahash_report,.maskclear = ~CRYPTO_ALG_TYPE_MASK,.maskset = CRYPTO_ALG_TYPE_AHASH_MASK,.type = CRYPTO_ALG_TYPE_AHASH,.tfmsize = offsetof(struct crypto_ahash, base),
};
crypto_create_tfm_node函数的
- crypto_create_tfm_node函数的输入参数包括通用算法说明alg和算法前端frontend
- 处理流程如下所示
- 1)在申请内存前,需要计算算法实例所需的内存空间total,包括个性化算法实例占用的内存空间tfmsize、通用算法实例占用的内存空间以及算法实例占用的额外内存空间extsize,如下图所示。
- 个性化算法实例内存空间由算法前端的成员变量tfmsize确定,算法实例占用的额外内存空间由具体算法确定,通过算法前端的extsize接口获取。创建异步哈希算法实例时,算法前端为crypto_ahash_type,tfmzise为offsetof(struct crypto_ahash, base),extsize接口为crypto_ahash_extsize函数
crypto_ahash_extsize函数
- ahash.c - crypto/ahash.c - Linux source code (v5.15.12) - Bootlin
static unsigned int crypto_ahash_extsize(struct crypto_alg *alg)
{if (alg->cra_type != &crypto_ahash_type)return sizeof(struct crypto_shash *);return crypto_alg_extsize(alg);
}
- 如上所示,算法实例占用的额外内存空间与哈希算法实现方式有关
- 实现方式为异步方式时,额外内存空间为异步哈希算法上下文空间;
- 实现方式为同步方式时,额外内存空间用于保存同步哈希算法实现指针。
- 2)申请完内存空间mem后,需要初始化通用算法实例tfm,包括:
- a)通用算法实例tfm关联到通用算法说明alg, tfm->__crt_alg = alg;
- b) 调用算法前端frontend的init_tfm接口初始化tfm。创建异步哈希算法实例时,算法前端crypto_ahash_type定义的initial_tfm接口为crypto_ahash_init_tfm函数。
crypto_ahash_init_tfm函数的主要功能是利用异步哈希算法说明alg的算法接口初始化异步哈希算法实例hash的算法接口,但是如果算法的实现方式不是异步方式,将调用crypto_init_shash_ops_async函数使用同步哈希算法的异步实现接口(形如shash_async_xxx)初始化异步哈希算法实例的算法接口。 - c)如果通用算法说明alg定义了cra_init接口则调用其进一步初始化tfm。在加密框架中,一般情况下动态算法的算法说明都会定义cra_init接口,而静态算法的算法说明都不定义cra_init接口,如HMAC模板创建的动态算法的算法说明的cra_init接口为hmac_init_tfm,而MD5算法的算法说明未定义cra_init接口