假设某个SA配置使用的认证算法为"hmac(md5)"(即x->aalg->alg_name为"hmac(md5)"),在调用ah_init_state函数初始化SA状态时,将创建认证算法对应的异步哈希算法实例ahash,并设置HMAC密钥(密钥数据保存在SA中,即x->aalg->alg_key)。 由于默认算法以异步方式实现,因此在ah_init_state函数中将调用crypto_alloc_ahash函数创建与认证算法"hmac(md5)"对应的异步哈希算法实例,记为hmac_md5_ahash。 由于MD5算法是以同步方式实现的,由其衍生的"hmac(md5)"算法也是以同步方式实现的,因此也会同步创建"hmac(md5)"算法的同步哈希算法实例,记为hmac_md5_shash。 由于"hmac(md5)"算法是在MD5算法基础上构造的,具体的算法运算由MD5算法实现,因此还会同步创建MD5算法的同步哈希算法实例,记为md5_shash。 综上所述,调用crypto_alloc_ahash函数实际上创建了三个算法实例,其中hmac_md5_ahash是面向具体算法应用(如IPSEC模块)的,md5_shash是面向具体算法实现(如MD5算法)的,hmac_md5_shash负责将hmac_md5_ahash和md5_shash两个算法实例串联在一起,三个算法实例的关系如下所示。 2. 创建哈希算法实例hmac_md5_ahash(一)
下面将按照函数调用关系逐步说明如何创建哈希算法实例hmac_md5_ahash。 1)ah_init_state函数 ah_init_state函数调用crypto_alloc_ahash函数异步哈希算法实例hmac_md5_ahash时,输入参数包括算法alg_name(=“hmac(md5)”)、算法类型type(=0)和算法类型屏蔽字mask(=0)。 从函数的输入参数可知,ah_init_state函数不关心认证算法的实现方式,只关心是否有可提供服务的认证算法。 2)crypto_alloc_ahash函数 实际上crypto_alloc_ahash函数是一个包裹函数(wrapper),具体工作由crypto_alloc_tfm函数实现。crypto_alloc_tfm函数继承了调用者所有的输入参数。 由于crypto_alloc_tfm函数并不是创建特定的算法实例(即特定数据结构指针),而是返回一个通用指针(即void *),由调用者具体解释通用指针的含义(即将通用指针转换为特定算法实例数据结构指针)。不同类型算法实例占用的内存空间不同、初始化流程存在差异,这些不同和差异由crypto_alloc_tfm函数的输入参数frontend说明,在这里参数frontend按照字面理解为算法前端,按照数据结构实际上就是算法类型常量指针。 由于crypto_alloc_ahash函数用于创建异步哈希算法实例,因此在调用crypto_alloc_tfm函数时传递的frontend参数为异步哈希算法类型常量crypto_shash_type,调用结束后将crypto_alloc_tfm函数返回地通用指针隐式地强制转换为异步哈希算法实例指针。 3)crypto_alloc_tfm函数 crypto_alloc_tfm函数的基本逻辑是先调用crypto_find_alg函数查找符合条件(包括算法名alg_name、算法类型type和算法类型屏蔽字)的算法alg,然后再调用crypto_create_tfm函数创建与算法alg关联的算法实例tfm。 假设第一次使用"hmac(md5)“算法,算法查找不命中,因此加密框架将根据算法模板(HMAC模板)和基础算法(MD5算法)动态创建新的算法(通用算法说明记为hmac_md5_alg)并注册。 截至到目前为止,函数接口调用关系如下图所示。 3. 创建动态算法"hmac(md5)”(一) 1)crypto_find_alg函数 crypto_find_alg函数的主要功能是确认算法查找的预期算法类型(包括算法类型type以及算法类型屏蔽字mask)和算法查找接口lookup,如下所示。
if (frontend) { type &= frontend->maskclear; mask &= frontend->maskclear; type |= frontend->type; mask |= frontend->maskset; if (frontend->lookup) lookup = frontend->lookup; }按照调用关系,此时传递给crypto_find_alg函数的算法前端frontend为异步哈希算法类型常量crypto_ahash_type,算法类型type和算法类型屏蔽字均为0,其中算法前端frontend与算法查找相关的成员变量如下所示。
const struct crypto_type crypto_ahash_type = { ...... .maskclear = ~CRYPTO_ALG_TYPE_MASK, .maskset = CRYPTO_ALG_TYPE_AHASH_MASK, .type = CRYPTO_ALG_TYPE_AHASH, ...... };在调用算法查找接口lookup(默认接口crypto_alg_mod_lookup)时,算法类型type为CRYPTO_ALG_TYPE_AHASH,算法类型屏蔽字mask为CRYPTO_ALG_TYPE_AHASH_MASK。 在遍历算法管理链表查找算法前(crypto_larval_lookup函数),还会再次更新算法类型为type=type&mask=0x08(在算法类型定义中为CRYPTO_ALG_TYPE_HASH)。 在遍历管理算法链表时,如果((cra_flags ^ type) & mask)=0表示当前算法满足查找条件中的算法类型要求,否则不满足算法类型要求,也就是说只要是哈希算法,无论是同步方式实现还是异步方式实现,都满足算法类型要求。 2)crypto_alg_mod_lookup函数 在crypto_alg_mod_lookup函数中,调用crypto_larval_lookup函数查找符合条件的算法。假设第一次使用"hmac(md5)"算法,算法查找不命中,在调用crypto_larval_lookup函数时将返回一个与查找算法同名的注册用算法幼虫,记为hmac_md5_larval_r。 算法查找不命中时,加密框架尝试动态创建符合条件的算法,调用cryptomgr_schedule_probe函数在加密通知链发布一个算法注册(CRYPTO_MSG_ALG_REQUEST)通知,动态创建"hmac(md5)“算法,传递的参数由注册用算法幼虫hmac_md5_larval_r指定。 发布算法注册通知时,通过解析注册用算法幼虫hmac_md5_larval_r的算法名(即"hmac(md5)”)可获取算法模板名hmac和基础算法名md5,加上预期的算法类型共同组成传递给算法探测线程cryptomgr_probe的参数param。 算法探测线程运行时,根据算法模板名hmac查找到对应的算法模板hmac_tmpl。由于算法模板hmac_tmpl定义了create接口(即hmac_create函数),将调用之根据参数列表param->tb创建并注册动态算法。
