logo资料库

Linux加密框架设计与实现.pdf

第1页 / 共131页
第2页 / 共131页
第3页 / 共131页
第4页 / 共131页
第5页 / 共131页
第6页 / 共131页
第7页 / 共131页
第8页 / 共131页
资料共131页,剩余部分请下载后查看
Linux 加密框架设计与实现 目录 Linux 加密框架设计与实现 .................................................................................................. 1 一、 前言 ....................................................................................................................... 3 二、 算法模版 ................................................................................................................ 3 1. 模版的基本概念 ........................................................................................................ 3 2. 算法模版的查找 ........................................................................................................ 5 3. 模版的算法实例分配时机 ......................................................................................... 6 三、 HMAC ................................................................................................................... 10 1. 算法模版的注册与注销 ....................................................................................... 10 2. 算法实例的分配 .................................................................................................. 11 3. 待孵化的卵 .......................................................................................................... 14 4. 算法的初始化 ...................................................................................................... 15 5. MD5 的 tfm 分配 .................................................................................................. 27 6. 密钥设置 .............................................................................................................. 37 7. 数据验证 .............................................................................................................. 40 8. MD5 的实现 ......................................................................................................... 52 9. 小结 ..................................................................................................................... 59 四、 authenc ................................................................................................................ 59 1. 注册算法模版 ...................................................................................................... 59 2. 算法实列的分配 .................................................................................................. 60 3. cbc 算法模版 ....................................................................................................... 63 4. authenc 的 spawn................................................................................................. 65 5. crypto_lookup_skcipher........................................................................................ 66 6. 分配 tfm ............................................................................................................... 75 7. 8. spawn 的孵化 ...................................................................................................... 83 crypto_aead_setauthsize ...................................................................................... 93
9. 密钥设置 crypto_aead_setkey ............................................................................ 94 10. 解密 ................................................................................................................ 100 11. 加密 ................................................................................................................ 114 五、 硬件加密支持 .................................................................................................... 121 1. 设备及算法初始化 ............................................................................................ 121 2. tfm 初始化 ......................................................................................................... 124 3. 设置密钥 ............................................................................................................ 126 4. 加密 ................................................................................................................... 127 5. 解密 ................................................................................................................... 130 后记 .................................................................................................................................. 131
作者:独孤九贱 版权所有,转载请注明作者及出处 一、 前言 Linux 加密框架是内核安全子系统的重要组成部份,同时,它又一个的独立子系统形式 出现,从它出现在内核根目录下的 crypto/就可以看出其地位了。 Crypto 实现较为复杂,其主要体现在其 OOP 的设计思路和高度的对像抽像与封装模型, 作者展现了其出色的架构设计水准和面向对像的抽像能力。本文力图从 xfrm 的两个重要协 议 AH 和 ESP 对加密框架的使用,展现其设计与实现。 内核版本:2.6.31.13 二、 算法模版 1. 模版的基本概念 算法模版是加密框架的第一个重要概念。内核中有很多算法是动态生成的,例如 cbc(des) 算法。内核并不存在这样的算法,它事实上是 cbc 和 des 的组合,但是内核加密框架从统一 抽像管理的角度。将 cbc(des)看做一个算法,在实际使用时动态分配并向内核注册该算法。 这样,可以将 cbc 抽像为一个模版,它可以同任意的加密算法进行组合。算法模版使用结构 crypto_template 来描述,其结构原型: //模版链表成员,用于注册 //算法实例链表首部 //模块指针 struct crypto_instance *(*alloc)(struct rtattr **tb); void (*free)(struct crypto_instance *inst); struct crypto_template { struct list_head list; struct hlist_head instances; struct module *module; }; 例如,一个名为 cbc 的算法模版,可以用它来动态分配 cbc(des),cbc(twofish)……诸如此 类。 crypto/algapi.c 下包含了模版的一些常用操作。最为常见的就是模版的注册与注销,其实质 char name[CRYPTO_MAX_ALG_NAME]; //模版名称 //算法实例分配 //算法实例释放
down_write(&crypto_alg_sem); if (q == tmpl) goto out; struct crypto_template *q; int err = -EEXIST; //遍历 crypto_template_list,看当前模板是否被注册 list_for_each_entry(q, &crypto_template_list, list) { } 是对以 crypto_template_list 为首的链表的操作过程: static LIST_HEAD(crypto_template_list); int crypto_register_template(struct crypto_template *tmpl) { out: } EXPORT_SYMBOL_GPL(crypto_register_template); //注册之 list_add(&tmpl->list, &crypto_template_list); //事件通告 crypto_notify(CRYPTO_MSG_TMPL_REGISTER, tmpl); err = 0; up_write(&crypto_alg_sem); return err; 注销算法模版,除了模版本身,还有一个重要的内容是处理算法模版产生的算法实例, struct crypto_instance *inst; struct hlist_node *p, *n; struct hlist_head *list; LIST_HEAD(users); 关于算法实例,后文详述。 void crypto_unregister_template(struct crypto_template *tmpl) { BUG_ON(list_empty(&tmpl->list)); //注销算法模版,并重新初始化模版的 list 成员 list_del_init(&tmpl->list); //首先移除模版上的所有算法实例 down_write(&crypto_alg_sem);
crypto_notify(CRYPTO_MSG_TMPL_UNREGISTER, tmpl); int err = crypto_remove_alg(&inst->alg, &users); BUG_ON(err); list = &tmpl->instances; hlist_for_each_entry(inst, p, list, list) { } } EXPORT_SYMBOL_GPL(crypto_unregister_template); up_write(&crypto_alg_sem); //释放模版的所有算法实例分配的内存 hlist_for_each_entry_safe(inst, p, n, list, list) { } crypto_remove_final(&users); BUG_ON(atomic_read(&inst->alg.cra_refcnt) != 1); tmpl->free(inst); 2. 算法模版的查找 return try_then_request_module(__crypto_lookup_template(name), name); crypto_lookup_template 函数根据名称,查找相应的模版: struct crypto_template *crypto_lookup_template(const char *name) { } __crypto_lookup_template 完成实质的模版模找工作,而 try_then_request_module 则尝试动 态插入相应的内核模块,如果需要的话: static struct crypto_template *__crypto_lookup_template(const char *name) { 后返回查找到的模版 down_read(&crypto_alg_sem); //遍历 crypto_template_list 链,匹备模版名称 list_for_each_entry(q, &crypto_template_list, list) { if (strcmp(q->name, name)) //查找命中,需要对其增加引用,以防止其正在使用时,模块被卸载。完成该操作 struct crypto_template *q, *tmpl = NULL; if (unlikely(!crypto_tmpl_get(q))) continue;
continue; tmpl = q; break; } up_read(&crypto_alg_sem); return tmpl; } 3. 模版的算法实例分配时机 模版可以看做一个静态的概念,其只有被动态创建后才具有生命力,本文将模版通过 alloc 分配创建的算法(对像)称为“实例(instance)”。 …… ok = crypto_probing_notify(CRYPTO_MSG_ALG_REQUEST, larval); …… 算法模版的核心作用是,上层调用者构造一个完整合法的算法名称,如 hmac(md5),触 发模版的 alloc 动作,为该名称分配一个算法实例,类似于为类实例化一个对像,最终的目 的还是使用算法本身。对于 xfrm 来说,一个典型的算法模版的实例分配触发流程如下所述: xfrm 包裹了一层加密框架支持,参后文“ xfrm 加密框架”一节,其算法查找函数为 xfrm_find_algo,它调用 crypto_has_alg 函数进行算法的查找,以验证自己支持的算法是否被 内核支持,如 xfrm 支持 cbc(des),但此时并不知道内核是否有这个算法(如果该算法首次被 使用,则还没有分配算法实例)。crypto_has_alg 会调用 crypto_alg_mod_lookup 完成查找工 作,crypto_alg_mod_lookup 函数查找不命中,会调用 crypto_probing_notify 函数进行请求探 测: struct crypto_alg *crypto_alg_mod_lookup(const char *name, u32 type, u32 mask) { } 请求是通过通知链表来通告的: int crypto_probing_notify(unsigned long val, void *v) { ok = blocking_notifier_call_chain(&crypto_chain, val, v); if (ok == NOTIFY_DONE) { } int ok; return ok; request_module("cryptomgr"); ok = blocking_notifier_call_chain(&crypto_chain, val, v);
.notifier_call = cryptomgr_notify, return crypto_register_notifier(&cryptomgr_notifier); } 在 algboss.c 中注册了一个名为 cryptomgr_notifier 的通告块结 构,其通告处理函数为 cryptomgr_notify: static struct notifier_block cryptomgr_notifier = { }; static int __init cryptomgr_init(void) { } static void __exit cryptomgr_exit(void) { } 这样,当有算法被使用的时候,会调用通告块的处理函数 cryptomgr_notify,因为此时的消 息是 CRYPTO_MSG_ALG_REQUEST,所以 cryptomgr_schedule_probe 进行算法的探测: static int cryptomgr_notify(struct notifier_block *this, unsigned long msg, { int err = crypto_unregister_notifier(&cryptomgr_notifier); BUG_ON(err); switch (msg) { case CRYPTO_MSG_ALG_REQUEST: …… void *data) return cryptomgr_schedule_probe(data); return NOTIFY_DONE; } cryptomgr_schedule_probe 启动一个名为 cryptomgr_probe 的内核线程来进行算法模版的探 测: static int cryptomgr_schedule_probe(struct crypto_larval *larval) { } …… //构造 param,以供后面使用 …… thread = kthread_run(cryptomgr_probe, param, "cryptomgr_probe"); ……
goto err; inst = tmpl->alloc(param->tb); if (IS_ERR(inst)) else if ((err = crypto_register_instance(tmpl, inst))) err = PTR_ERR(inst); tmpl->free(inst); struct cryptomgr_param *param = data; struct crypto_template *tmpl; struct crypto_instance *inst; int err; //查找算法模版 tmpl = crypto_lookup_template(param->template); if (!tmpl) //循环调用模版的 alloc 函数分配算法实列,并将模版注册之 //这里值得注意的是循环的条件,当返回码为-EAGAIN 时,会循环再次尝试 //这样使用的一个场景后面会分析到 do { } while (err == -EAGAIN && !signal_pending(current)); cryptomgr_probe 完成具体的算法探测过程: static int cryptomgr_probe(void *data) { out: err: } 理解了算法的注册与查找后,再来理解这个函数就非常容易了,其核心在 do{}while 循环中, 包含了算法实例的分配和注册动作。针对每一种算法模版,其 alloc 动作不尽一致。后文会 对 xfrm 使用的算法模版一一阐述。 crypto_larval_error(param->larval, param->otype, param->omask); goto out; //查找中会增加引用,这里已经用完了释放之 crypto_tmpl_put(tmpl); if (err) goto err; kfree(param); module_put_and_exit(0); 为什么不把“算法实例”直接称之为“算法”,这是因为实例包含了更多的内容,其由
分享到:
收藏