參考鏈接
- Linux加密框架的算法管理(四)_家有一希的博客-CSDN博客
函數(shù)介紹
- 如前所述,無論是靜態(tài)算法還是動(dòng)態(tài)算法,算法注冊(cè)的最后一步都是進(jìn)行算法正確性檢驗(yàn),一般流程是先調(diào)用__crypto_register_alg函數(shù)進(jìn)行通用的算法注冊(cè)(即將待注冊(cè)的算法添加到算法管理鏈表中),同時(shí)創(chuàng)建對(duì)應(yīng)的檢測(cè)用算法幼蟲,然后調(diào)用crypto_wait_for_test函數(shù)啟動(dòng)算法正確性檢驗(yàn),并等待檢驗(yàn)結(jié)束。
- 簡單地說,算法正確性檢驗(yàn)就是利用樣本數(shù)據(jù)sampledata對(duì)算法接口進(jìn)行計(jì)算正確性的驗(yàn)證。算法通過正確性檢驗(yàn)的標(biāo)志是算法標(biāo)志cra_flags中置算法已檢測(cè)標(biāo)志CRYPTO_ALG_TESTED。算法通過正確性檢驗(yàn)說明能夠提供正常的服務(wù),如加密/解密服務(wù)、計(jì)算消息摘要服務(wù)等。
- crypto_wait_for_test函數(shù)用于啟動(dòng)算法正確性檢驗(yàn),并等待檢驗(yàn)結(jié)束,輸入?yún)?shù)為檢測(cè)用算法幼蟲larval
- 函數(shù)處理流程如下所示。
static void crypto_wait_for_test(struct crypto_larval *larval)
{int err;err = crypto_probing_notify(CRYPTO_MSG_ALG_REGISTER, larval->adult);if (err != NOTIFY_STOP) {if (WARN_ON(err != NOTIFY_DONE))goto out;crypto_alg_tested(larval->alg.cra_driver_name, 0);}err = wait_for_completion_killable(&larval->completion);WARN_ON(err);if (!err)crypto_notify(CRYPTO_MSG_ALG_LOADED, larval);out:crypto_larval_kill(&larval->alg);
}
- 1)在crypto_wait_for_test函數(shù)中,調(diào)用crypto_probing_notify函數(shù)在加密通知鏈上發(fā)布算法正確性檢驗(yàn)(CRYPTO_MSG_ALG_REGISTER)的通知,攜帶的參數(shù)為檢測(cè)用算法幼蟲對(duì)應(yīng)的算法成蟲,即待檢驗(yàn)的算法。
- 2)靜態(tài)算法(如AES算法)注冊(cè)發(fā)布算法檢驗(yàn)通知時(shí),算法管理鏈表如下所示,其中aes_larval_t表示檢測(cè)用算法幼蟲,關(guān)聯(lián)到對(duì)應(yīng)的算法成蟲(aes_larval_t->adult=aes_alg)。?
- 3)動(dòng)態(tài)算法(如"cbc(aes)"算法)注冊(cè)發(fā)布算法檢驗(yàn)通知時(shí),算法管理鏈表如下所示,其中cbc_aes_larval_r表示注冊(cè)用算法幼蟲,cbc_aes_larval_t表示檢測(cè)用算法幼蟲,注冊(cè)用算法幼蟲還未關(guān)聯(lián)到算法成蟲,檢測(cè)用算法幼蟲關(guān)聯(lián)到算法成蟲(cbc_aes_larval_t->adult=cbc_aes_alg)。?
算法檢測(cè)啟動(dòng)
- 發(fā)布算法檢測(cè)通知后,加密通知鏈回調(diào)函數(shù)cryptomgr_notify(CRYPTO_MSG_ALG_REGISTER)將調(diào)用cryptomgr_schedule_test函數(shù)啟動(dòng)算法檢測(cè)。
- algboss.c - crypto/algboss.c - Linux source code (v5.15.12) - Bootlin
static int cryptomgr_notify(struct notifier_block *this, unsigned long msg,void *data)
{switch (msg) {case CRYPTO_MSG_ALG_REQUEST:return cryptomgr_schedule_probe(data);case CRYPTO_MSG_ALG_REGISTER:return cryptomgr_schedule_test(data);case CRYPTO_MSG_ALG_LOADED:break;}return NOTIFY_DONE;
}
- algboss.c - crypto/algboss.c - Linux source code (v5.15.12) - Bootlin
static int cryptomgr_schedule_test(struct crypto_alg *alg)
{struct task_struct *thread;struct crypto_test_param *param;u32 type;if (!try_module_get(THIS_MODULE))goto err;param = kzalloc(sizeof(*param), GFP_KERNEL);if (!param)goto err_put_module;memcpy(param->driver, alg->cra_driver_name, sizeof(param->driver));memcpy(param->alg, alg->cra_name, sizeof(param->alg));type = alg->cra_flags;/* Do not test internal algorithms. */if (type & CRYPTO_ALG_INTERNAL)type |= CRYPTO_ALG_TESTED;param->type = type;thread = kthread_run(cryptomgr_test, param, "cryptomgr_test");if (IS_ERR(thread))goto err_free_param;return NOTIFY_STOP;err_free_param:kfree(param);
err_put_module:module_put(THIS_MODULE);
err:return NOTIFY_OK;
}
- cryptomgr_schedule_test函數(shù)輸入?yún)?shù)為待檢測(cè)的算法alg,通過創(chuàng)建專門的算法檢測(cè)線程處理算法正確性檢驗(yàn)
- 處理流程如下所示
- ?1)算法正確性檢驗(yàn)的參數(shù)數(shù)據(jù)結(jié)構(gòu)為struct crypto_test_param,定義如下所示。
- algboss.c - crypto/algboss.c - Linux source code (v5.15.12) - Bootlin
struct crypto_test_param {char driver[CRYPTO_MAX_ALG_NAME];char alg[CRYPTO_MAX_ALG_NAME];u32 type;
};
參數(shù)介紹
- 如上所示,算法正確性檢驗(yàn)的參數(shù)包括算法驅(qū)動(dòng)名driver、算法名alg和算法類型type。
- 2)cryptomgr_schedule_test函數(shù)將創(chuàng)建名為"cryptomgr_test"的內(nèi)核線程(即算法檢驗(yàn)線程)處理算法正確性檢驗(yàn),處理接口為cryptomgr_test。
thread = kthread_run(cryptomgr_test, param, "cryptomgr_test");if (IS_ERR(thread))goto err_free_param;return NOTIFY_STOP;
- 3)在cryptomgr_test函數(shù)中,調(diào)用alg_test函數(shù)根據(jù)算法驅(qū)動(dòng)名driver、算法名alg和算法類型type實(shí)現(xiàn)算法正確性檢驗(yàn)。
- err = alg_test(param->driver, param->alg, type, CRYPTO_ALG_TESTED);
static int cryptomgr_test(void *data)
{struct crypto_test_param *param = data;u32 type = param->type;int err = 0;#ifdef CONFIG_CRYPTO_MANAGER_DISABLE_TESTSgoto skiptest;
#endifif (type & CRYPTO_ALG_TESTED)goto skiptest;err = alg_test(param->driver, param->alg, type, CRYPTO_ALG_TESTED);skiptest:crypto_alg_tested(param->driver, err);kfree(param);module_put_and_exit(0);
}static int cryptomgr_schedule_test(struct crypto_alg *alg)
{struct task_struct *thread;struct crypto_test_param *param;u32 type;if (!try_module_get(THIS_MODULE))goto err;param = kzalloc(sizeof(*param), GFP_KERNEL);if (!param)goto err_put_module;memcpy(param->driver, alg->cra_driver_name, sizeof(param->driver));memcpy(param->alg, alg->cra_name, sizeof(param->alg));type = alg->cra_flags;/* Do not test internal algorithms. */if (type & CRYPTO_ALG_INTERNAL)type |= CRYPTO_ALG_TESTED;param->type = type;thread = kthread_run(cryptomgr_test, param, "cryptomgr_test");if (IS_ERR(thread))goto err_free_param;return NOTIFY_STOP;err_free_param:kfree(param);
err_put_module:module_put(THIS_MODULE);
err:return NOTIFY_OK;
}
算法檢測(cè)結(jié)束
- 在cryptomgr_test函數(shù)中,算法正確性檢驗(yàn)結(jié)束后將調(diào)用crypto_alg_tested函數(shù)完成收尾工作。
- algapi.c - crypto/algapi.c - Linux source code (v5.15.12) - Bootlin
void crypto_alg_tested(const char *name, int err)
{struct crypto_larval *test;struct crypto_alg *alg;struct crypto_alg *q;LIST_HEAD(list);bool best;down_write(&crypto_alg_sem);list_for_each_entry(q, &crypto_alg_list, cra_list) {if (crypto_is_moribund(q) || !crypto_is_larval(q))continue;test = (struct crypto_larval *)q;if (!strcmp(q->cra_driver_name, name))goto found;}pr_err("alg: Unexpected test result for %s: %d\n", name, err);goto unlock;found:q->cra_flags |= CRYPTO_ALG_DEAD;alg = test->adult;if (err || list_empty(&alg->cra_list))goto complete;alg->cra_flags |= CRYPTO_ALG_TESTED;/* Only satisfy larval waiters if we are the best. */best = true;list_for_each_entry(q, &crypto_alg_list, cra_list) {if (crypto_is_moribund(q) || !crypto_is_larval(q))continue;if (strcmp(alg->cra_name, q->cra_name))continue;if (q->cra_priority > alg->cra_priority) {best = false;break;}}list_for_each_entry(q, &crypto_alg_list, cra_list) {if (q == alg)continue;if (crypto_is_moribund(q))continue;if (crypto_is_larval(q)) {struct crypto_larval *larval = (void *)q;/** Check to see if either our generic name or* specific name can satisfy the name requested* by the larval entry q.*/if (strcmp(alg->cra_name, q->cra_name) &&strcmp(alg->cra_driver_name, q->cra_name))continue;if (larval->adult)continue;if ((q->cra_flags ^ alg->cra_flags) & larval->mask)continue;if (best && crypto_mod_get(alg))larval->adult = alg;elselarval->adult = ERR_PTR(-EAGAIN);continue;}if (strcmp(alg->cra_name, q->cra_name))continue;if (strcmp(alg->cra_driver_name, q->cra_driver_name) &&q->cra_priority > alg->cra_priority)continue;crypto_remove_spawns(q, &list, alg);}complete:complete_all(&test->completion);unlock:up_write(&crypto_alg_sem);crypto_remove_final(&list);
}
EXPORT_SYMBOL_GPL(crypto_alg_tested);
- crypto_alg_tested函數(shù)輸入?yún)?shù)包括算法驅(qū)動(dòng)名name和檢驗(yàn)結(jié)果err(為0表示檢驗(yàn)正確,非0表示檢驗(yàn)失敗),處理流程如下所示。
- 1)檢測(cè)結(jié)束收尾時(shí),需要通過算法幼蟲的完成量喚醒等待注冊(cè)、檢驗(yàn)結(jié)束的線程。
- 在crypto_alg_tested函數(shù)中,首先根據(jù)輸入的算法驅(qū)動(dòng)名name查找對(duì)應(yīng)的檢測(cè)用算法幼蟲test,如下所示。
test = (struct crypto_larval *)q;if (!strcmp(q->cra_driver_name, name))goto found;
- 然后根據(jù)檢測(cè)用算法幼蟲test關(guān)聯(lián)到算法成蟲alg,如果算法檢測(cè)通過(err=0)則設(shè)置算法成功alg的已檢驗(yàn)標(biāo)志 CRYPTO_ALG_TESTED,同時(shí)將檢測(cè)用算法幼蟲設(shè)置為已死亡,表示檢測(cè)用算法幼蟲的使命終結(jié),如下所示。
found:q->cra_flags |= CRYPTO_ALG_DEAD;alg = test->adult;if (err || list_empty(&alg->cra_list))goto complete;alg->cra_flags |= CRYPTO_ALG_TESTED;
- 2)算法檢驗(yàn)結(jié)束收尾時(shí),算法管理鏈表如下所示。
- 注意:算法檢驗(yàn)收尾時(shí),只是通過注冊(cè)用和檢驗(yàn)用算法幼蟲喚醒等待算法注冊(cè)完成的線程,并不清理注冊(cè)過程中的中間變量(即注冊(cè)用和檢驗(yàn)用算法幼蟲)?
?
總結(jié)
以上是生活随笔為你收集整理的linux加密框架 crypto 算法管理 - 算法检测的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。