内核加密机制及应用

本文介绍了Linux内核3.3.8中的加密机制,包括总体框架、数据结构和算法流程。内核加密机制涉及两个全局链表:crypto_template_list和crypto_alg_list,分别用于保存加密方式和加密算法。加密算法的注册过程涉及到crypto_alg和crypto_template结构体,以及crypto_spawn结构。以Ecryptfs为例,展示了加密算法的使用,包括确定算法、模块注册和相关结构体的细节。

内核加密机制

  • linux 3.3.8

总体框架

仅显示关键结构

这里写图片描述

内核加密机制在内核中保存两个全局链表crypto_template_listcrypto_alg_list

  • crypto_template_list 保存所有的加密方式

    • e.g cbc ecb
  • crypto_alg_list 保存所有的加密算法

    • e.g md5 sha128 aes

crypto_template_list由各个算法通过crypto_register_template函数添加到链表中

crypto_alg_list由各个算法通过crypto_register_alg函数添加到链表中

数据结构说明

crypto_alg结构可以理解为真正保存加密接口的一个通用结构

  • struct list_head cra_users;

    指向crypto_spawn结构所在的链表

  • union cra_u;

    union {
    struct ablkcipher_alg ablkcipher;
      struct aead_alg aead;
    struct blkcipher_alg blkcipher;
    struct cipher_alg cipher;
    struct compress_alg compress;
    struct rng_alg rng;
    } cra_u;

    xxxxxx_alg结构体说明

    保存实际算法实现的函数接口和算法相关信息

    • blkcipher_alg
    struct blkcipher_alg {
      int (* setkey) (struct crypto_tfm *tfm, const u8 *key,unsigned int keylen);
      int (* encrypt) (struct blkcipher_desc *desc,struct scatterlist *dst, struct scatterlist *src,unsigned int nbytes);
      int (* decrypt) (struct blkcipher_desc *desc,struct scatterlist *dst, struct scatterlist *src,unsigned int nbytes);
      const char * geniv;
      unsigned int min_keysize;
      unsigned int max_keysize;
      unsigned int ivsize;
    };
    • int (* setkey)

      将产生的密钥及其相关信息保存在crypto_tfm结构的__crt_ctx[]部分。

      同它也负责检查密钥长度的合法性,以防在cra_init函数调用时,使用密钥长度与实际设置长度不符。

    • int (* encrypt)

      加密存放在scatterlist里面的数据,需要对齐scatterlist并且确保每一个加密块大小已经设置好

      这个函数不应该去修改__crt_ctx[]部分数据

    • int (* decrypt)

      环境与encrypt一致 过程与encrypt相反

  • union中结构初始化流程

    • cipher

    首先由算法本身实现xxxxx_alg结构体的初始化,通过xxx_mod_init函数调用crypto_register_xxxxx函数将xxxxx_alg传递到crypto_alg结构体中

    通过__crypto_register_alg函数将当前crypto_alg结构体添加到crypto_alg_list链表当中

    至此加密算法在内核中已成功注册

    • ablkcipher/rng/aead/blkcipher/compress

    首先由算法本身实现crypto_alg结构体的初始化,使用crypto_register_alg函数调用__crypto_register_alg函数

    将当前crypto_alg结构体添加到crypto_alg_list链表当中,至此xxxxx_alg算法在内核中已成功注册

crypto_template结构是通用组合算法的模板

  • struct hlist_head instances;

    该字段保存temp下所有的实例

  • struct crypto_instance *(*alloc)(struct rtattr **tb);

    每个算法在该函数中保存自己的模板

crypto_instance结构就是加密方式的一个实例对象 通过函数XXXX_alloc_instance

  • struct crypto_alg alg;

    该算法实现的函数接口

  • struct crypto_template *tmpl;

    算法实例对应的模板

  • void *__ctx[];

    保存crypto_spawn结构

crypto_spawn结构保存加密算法和加密方式的所有信息,以便之后通过crypto_spawn_tfm生成crypto_tfm的对象

  • struct crypto_alg *alg;

    保存的加密算法的接口

  • struct crypto_instance *inst;

    保存的加密方式的接口

Ps.以上结构体在内存中一直存在

crypto_tfm结构是内核中真正组合算法的实例化对象,真正的操作对象

  • union crt_u;

    union {
    struct ablkcipher_tfm ablkcipher;
    struct aead_tfm aead;
    struct blkcipher_tfm blkcipher;
    struct cipher_tfm cipher;
    struct hash_tfm hash;
    struct compress_tfm compress;
    struct rng_tfm rng;
    } crt_u;

    保存算法能够正常使用的最基本参数和函数接口

  • void *__crt_ctx[];

    保存加密算法注册的结构体的相关内容

    常用来保存加密算法密钥的相关信息

算法组合流程

仅涉及密钥加解密过程时,不需要算法的组合

crypto_xxxx_alloc
|                          run kthread(cryptomgr_probe)
+---->crypto_get_attr_alg-------------------------------> cryptomgr_probe[get crypto_alg]
|
+---->crypto_alloc_instance----> crypto_init_spawn[combine crypto_instance and crypto_alg]
函数中数据结构的传递
e.g  xxxx = shash
xxxxxx_desc
     |
     +--->crypto_xxxxx
              |
              +---->crypto_tfm
                        |
                        +---> xxxx_tfm
                        |
                        +---> crypto_alg
                                  |
                                  +----> xxxx_alg

Ecryptfs中的使用

加密算法
确定算法

使用crypto_alloc_hash函数设置使用的算法

crypto_alloc_hash(ECRYPTFS_DEFAULT_HASH, 0, CRYPTO_ALG_ASYNC);
/* ECRYPTFS_DEFAULT_HASH 该字段设置算法 */
模块注册

init update final详细流程

以MD5为例介绍内核加密模块在内核中的注册过程

/* crypto/md5.c */
static struct shash_alg alg = {
    .digestsize =   MD5_DIGEST_SIZE,
    .init       =   md5_init,
    .update     =   md5_update,
    .final      =   md5_final,
    .export     =   md5_export,
    .import     =   md5_import,
    .descsize   =   sizeof(struct md5_state),
    .statesize  =   sizeof(struct md5_state),
    .base       =   {
        .cra_name   =   "md5",
        .cra_flags  =   CRYPTO_ALG_TYPE_SHASH,
        .cra_blocksize  =   MD5_HMAC_BLOCK_SIZE,
        .cra_module =   THIS_MODULE,
    }
};

首先由算法本身实现shash_alg结构体的初始化,通过md5_mod_init函数调用crypto_register_shash函数将shash_alg传递到crypto_alg结构体中

通过__crypto_register_alg函数将当前crypto_alg结构体添加到crypto_alg_list链表当中

至此加密算法在内核中已成功注册

相关结构体
  • 函数调用关系

crypto_alloc_hash函数将crypto_algshash_alg连接起来
这里写图片描述

static struct crypto_alg *__crypto_alg_lookup(const char *name, u32 type,
                          u32 mask)
{
    struct crypto_alg *q, *alg = NULL;
    int best = -2;
    /* 遍历crypto_alg_list链表 查找符合条件的q并返回 */
    list_for_each_entry(q, &crypto_alg_list, cra_list) {
        int exact, fuzzy;

        if (crypto_is_moribund(q))
            continue;

        if ((q->cra_flags ^ type) & mask)
            continue;

        if (crypto_is_larval(q) &&
            !crypto_is_test_larval((struct crypto_larval *)q) &&
            ((struct crypto_larval *)q)->mask != mask)
            continue;

        exact = !strcmp(q->cra_driver_name, name);
        fuzzy = !strcmp(q->cra_name, name);
        if (!exact && !(fuzzy && q->cra_priority > best))
            continue;

        if (unlikely(!crypto_mod_get(q)))
            continue;

        best = q->cra_priority;
        if (alg)
            crypto_mod_put(alg);
        alg = q;

        if (exact)
            break;
    }

    return alg;
}
static int crypto_init_ops(struct crypto_tfm *tfm, u32 type, u32 mask)
{
    const struct crypto_type *type_obj = tfm->__crt_alg->cra_type;

    if (type_obj)
        return type_obj->init(tfm, type, mask);/* 此步骤调用shash_compat_init函数 */

    switch (crypto_tfm_alg_type(tfm)) {
    case CRYPTO_ALG_TYPE_CIPHER:
        return crypto_init_cipher_ops(tfm);

    case CRYPTO_ALG_TYPE_COMPRESS:
        return crypto_init_compress_ops(tfm);

    default:
        break;
    }

    BUG();
    return -EINVAL;
}
  • 结构体传递
    这里写图片描述

至此找到MD5所对应的shash_alg结构体

加密方式
确定算法

通过ecryptfs_crypto_api_algify_cipher_name函数设置加密方式

ecryptfs_crypto_api_algify_cipher_name(&full_alg_name, crypt_stat->cipher, "cbc");
/* crypt_stat->cipher为加密算法 cbc为加密模式 */
模块注册

以cbc(aes)为例介绍在内核模块中的注册流程

static struct crypto_template crypto_cbc_tmpl = {
    .name = "cbc",
    .alloc = crypto_cbc_alloc,
    .free = crypto_cbc_free,
    .module = THIS_MODULE,
};

首先在结构体中初始化相关字段保存在crypto_template结构体中,通过crypto_cbc_module_init函数调用crypto_register_template函数将crypto_template结构体插入crypto_template_list链表中以完成注册

相关结构体
  • 函数调用关系
    这里写图片描述

crypto_algblkcipher_alg对应起来

  • ecb

    ecryptfs_process_key_cipher函数中初始化为ecb模式

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值