Chinaunix首页 | 论坛 | 博客
  • 博客访问: 91092
  • 博文数量: 99
  • 博客积分: 55
  • 博客等级: 民兵
  • 技术积分: 510
  • 用 户 组: 普通用户
  • 注册时间: 2012-03-20 21:29
文章分类

全部博文(99)

文章存档

2013年(5)

2012年(94)

我的朋友

分类: 网络与安全

2013-05-15 23:06:34

原文地址:Linux中的加解密实现 作者:wuyaalan

每种操作系统的发展,都缺少不了安全的相伴。linux安全主要包括了系统安全、数据/资源安全、通信安全和应用安全。
linux里面常用到的安全技术包括PAM(Pluggable Authentication Modules)机制、Linux能力机制、入侵检测机制、加密文件机制、安全审计、基于ACL的自主访问控制、强制访问控制、防火墙、杀毒软件、网络安全、DRM(Digital Rigths Management,数字版权管理)
这里主要分析内核里面提供的加解密接口。内核版本3.5.4
linux里面具体算法的实现在crypt文件下,其中有个tcrypt.c文件,该文件是一个测试文件。可以看下如何使用内核接口进行加解密。
在include/linux/crypto.h里面 给出了内核加密应用程序的接口,主要有结构体、操作集以及函数的定义。
目录include/crypto给出了各个算法的具体头文件定义。

内核中一个算法模板结构体crypto_template,该结构体主要用来对内核中的算法进行管理操作。在内核中构造某个算法时会触发算法模板分配算法实例。


该结构给出了算法模板的组织形式以及触发后对应的算法实例的组织模式。其中钩子函数alloc就在在构造函数时算法模板返回一个crypto_instance实例。free用来释放对象以及create用来创建算法模板。

上面提到了crypto_instance,该结构体就属于算法实例。

结构体crypto_instance中字段alg,该字段是算法库中提供的统一的一个算法接口,不同算法库模块化之后,算法操作函数指针都通过填充crypto_alg,存入到crypto_alg_list全局链表中。在查找某个算法实例时,内核就通过遍历crypto_alg_list全局链表查看是否存在某个crypto_alg算法实例。比如函数__crypto_alg_lookup的实现就是通过list_for_each_entry(q, &crypto_alg_list, cra_list)来进行查找算法。

有了算法实例之后是否就可以使用某个算法进行加解密了?no。算法实例仅仅能说明内核中全局链表存在这样的算法,具体算法的使用还要进行算法注册,算法对象的分配等等工作。
接下来介绍算法对象crypto_tfm.在使用具体算法库中的具体算法时,内核通过通用结构crypto_tfm进行描述。

结构crypto_tfm里面给出了一些具体的算法。有异步分组算法、认证加密算法、分组加密算法、hash算法、压缩算法以及随机数产生算法等。这里具体算法实现后引用__crt_alg实现和crypto_alg的关联。
内核为了很好的实现不同算法的区分,针对不同算法使用和crypto_tfm相同的结构进行区分不同的算法。比如上面的aead认证加密算法就使用了struct crypto_aead {
          struct crypto_tfm base;
 };
来区分。


要实现一个算法,就要实现如何对数据进行加解密等操作,和这些相关联的是一些算法的操作集。
什么是算法操作集,算法操作集里面定了了实现一个具体算法的钩子函数定义,只要用户实现这些钩子函数然后进行填充操作集就实现了数据加解密操作。
比如struct blkcipher_tfm {
 362         void *iv;
 363         int (*setkey)(struct crypto_tfm *tfm, const u8 *key,
 364                       unsigned int keylen);
 365         int (*encrypt)(struct blkcipher_desc *desc, struct scatterlist *dst     ,
 366                        struct scatterlist *src, unsigned int nbytes);
 367         int (*decrypt)(struct blkcipher_desc *desc, struct scatterlist *dst     ,
 368                        struct scatterlist *src, unsigned int nbytes);
 369 };
 370
里面就给出了实现分组加解密的一些钩子定义,有密钥设置、加密操作和解密操作。
struct blkcipher_alg {
 232         int (*setkey)(struct crypto_tfm *tfm, const u8 *key,
 233                       unsigned int keylen);
 234         int (*encrypt)(struct blkcipher_desc *desc,
 235                        struct scatterlist *dst, struct scatterlist *src,
 236                        unsigned int nbytes);
 237         int (*decrypt)(struct blkcipher_desc *desc,
 238                        struct scatterlist *dst, struct scatterlist *src,
 239                        unsigned int nbytes);
 240
 241         const char *geniv;
 242
 243         unsigned int min_keysize;
 244         unsigned int max_keysize;
 245         unsigned int ivsize;
 246 };
我们可以看出blkcipher_tfm和blkcipher_alg功能基本一样,都给出了分组算法的操作集。通常具体算法xxx_tfm来自于xxx_alg。

到底怎么填充具体算法实现,这里以des算法和分组算法为例进行解释。
static struct crypto_alg des_alg = {
    .cra_name        =    "des",
    .cra_flags        =    CRYPTO_ALG_TYPE_CIPHER,
    .cra_blocksize        =    DES_BLOCK_SIZE,
    .cra_ctxsize        =    sizeof(struct des_ctx),
    .cra_module        =    THIS_MODULE,
    .cra_alignmask        =    3,
    .cra_list        =    LIST_HEAD_INIT(des_alg.cra_list),
    .cra_u            =    { .cipher = {
    .cia_min_keysize    =    DES_KEY_SIZE,
    .cia_max_keysize    =    DES_KEY_SIZE,
    .cia_setkey        =    des_setkey,
    .cia_encrypt        =    des_encrypt,
    .cia_decrypt        =    des_decrypt } }
};
很明了的对统一算法接口结构crypto_alg进行赋值,在联合体cra_u中实现对分组算法的钩子填充。


异步分组算法的实现是通过填充结构crypto_type来实现。具体原型如下:

该结构主要对说明了算法的类型、算法上下文大小、算法的初始化、算法显示等等。其中算法的初始化里面包含了算法的加解密操作;算法的显示show里面说明了算法的类型、算法是同步还是异步、块大小、最大最小密钥等算法信息。
const struct crypto_type crypto_ablkcipher_type = {
    .ctxsize = crypto_ablkcipher_ctxsize,
    .init = crypto_init_ablkcipher_ops,
#ifdef CONFIG_PROC_FS
    .show = crypto_ablkcipher_show,
#endif
    .report = crypto_ablkcipher_report,
};

给出了以上相关结构,内核中一个算法的基本架构就出来了。那么好像还没有讲到如何调用、实现一个算法的接口。
分配算法对象的接口为cryoto_alloc_xxx(),
比如要实现一个对象分配struct crypto_cipher *tfm;
tfm = crypto_alloc_cipher("算法名",类型,掩码),一般设置类型和掩码为0.

注册具体算法的接口为crypto_register_xxx(),注销为crypto_unregister_xxx()。算法查找接口为crypto_alg_lookup()。其中XXX为具体算法名称。




参考文献:
linux安全体系分析与编程, 倪继利,电子工业出版社,
,linux加密涉及与实现。
简单调用实现例子。%E5%86%85%E6%A0%B8%E5%86%85%E4%BD%BF%E7%94%A8md5%E5%8A%A0%E5%AF%86%E5%87%BD%E6%95%B0.html




阅读(573) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~