Linux内核密码模块

目录

密码算法介绍

Hash摘要算法

Cipher加解密算法

块密码算法

认证算法 MAC和HMAC

AEAD算法

Linux内核密码模块的基本构件

Linux内核密码模块介绍

如何使用Linux密码模块

用户层调用Linux内核密码模块的方法

cryptodev

AF_ALG

如何开发一个密码引擎驱动

开发一个密码引擎驱动的流程

以cbc(aes)算法为例的实际代码示例


密码算法介绍

密码算法主要是为了保护双方或者多方的通信,涉及到保密性、完整性和可认证性

Hash摘要算法

Hash或Digest是属于完整性,根据指定输入得到“唯一”校验值,比如SHA1,MD5,等等。

针对HASH算法的三个标准:

1、尽可能少的碰撞出相同的摘要值

2、不可能根据摘要值重新生成原数据

3、一个小的修改就能生成完成不同的摘要值

Cipher加解密算法

要求使用一组或者几组数据来加密/解密数据

Cipher算法可以分为流密码算法和块密码算法,还可以分为对称密码算法和非对称密码算法。

其中流密码算法是对一串流数据加密,块密码算法需要限定数据大小的数据块;

其中对称密码算法是指加解密都使用相同的密钥,非对称密码算法加密使用公钥,解密使用私钥。有AES,RSA算法等

块密码算法

块密码算法只能对一小块数据进行加解密,我们需要找个方法来处理任意长度的数据,大部分的块密码算法都要求有Initialization Vector(IV)来混淆加密数据。此算法模式有ECB,CBC等。

认证算法 MAC和HMAC

MAC代表消息认证码,用来认证发送者消息的机制,使用一组密钥和转化算法来生成认证码,使用HASH算法就叫HMAC。

AEAD算法

AEAD算法表示对数据进行认证加密,把认证,加密和摘要一步完成。

Linux内核密码模块的基本构件

Linux内核密码模块介绍

Linux密码模块的基本构件主要为两个结构体:struct crypto_alg和struct crypto_tfm。支持所有的算法,比如Cipher(加解密)、Hash(摘要)、AEAD(链式)、HMAC(认证)和Compression(解压缩)。

密码算法可以用一个基本算法构建的模块来表示,比如hmac(sha1)表示用SHA1摘要实现的HMAC算法,cbc(aes)表示使用AES的CBC模式,authenc(hmac(sha1),cbc(aes))表示使用AES-CBC加解密和SHA1做认证的链式算法,即一次完成加密和认证。

如何使用Linux密码模块

使用Linux密码模块的流程如下图所示:

左侧为流程分割,右侧为对应的实现函数。

Linux内核密码模块_第1张图片

用户层调用Linux内核密码模块的方法

用户层调用Linux内核密码模块的方法有两种,一种是cryptodev,另一种是AF_ALG。

cryptodev

  • 据说性能超过AF_ALG
  • 使用内核密码模块内标准接口
  • 将设备暴露在/dev/crypto目录下
  • 使用ioctl函数设置密码运算上下文
  • 在OpenSSL里原生支持

AF_ALG

  • 在Linux 2.6.38版本后支持
  • 主要通过netlink套接字实现

如何开发一个密码引擎驱动

开发一个密码引擎驱动的流程

1、Linux内核密码模块并不区分硬件引擎与软件实现

2、开发一个密码引擎就只是通过向密码模块子系统注册crypto_alg

3、辨别你想新增算法的类型并与相关的crypto_alg接口绑定,比如skcipher_alg,ahash_alg等等

4、实现xxx_alg接口内容并调用crypto_register_xxx()来向密码子系统注册

以cbc(aes)算法为例的实际代码示例

struct skcipher_alg xxx_cbc_aes_alg = {
    ...
    .base = {
        /* Name used by the framework to find who is implementing what. */
        .cra_name = "cbc(aes)",
        /* Driver name. Can be used to request a specific implementation of an algorithm. */
        .cra_driver_name = "xxx-cbc-aes",
        /* Priority is used when implementation auto-selection takes place:
         * if there are several implementers, the one with the highest priority is chosen.
         * By convention: HW engine > ASM/arch-optimized > plain C
         */
        .cra_priority = 300,
        /* CRYPTO_ALG_TYPE_XX: describes the type algorithm implemented here
         * CRYPTO_ALG_ASYNC: the engine is operating in an asynchronous manner
         * CRYPTO_ALG_KERN_DRIVER_ONLY: engine is not directly accessible to userspace
         */
        .cra_flags = CRYPTO_ALG_TYPE_SKCIPHER | CRYPTO_ALG_KERN_DRIVER_ONLY | CRYPTO_ALG_ASYNC,
        /* Size of the data blocks this algo operates on. */
        .cra_blocksize = AES_BLOCK_SIZE,
        /* Size of the context attached to an algorithm instance. */
        .cra_ctxsize = sizeof(struct xxx_aes_ctx),
        /* constructor/destructor methods called every time an alg instance is created/destroyed. */
        .cra_init = xxx_skcipher_cra_init,
        .cra_exit = xxx_skcipher_cra_exit,
    },
};

struct skcipher_alg mv_cesa_cbc_aes_alg = {
    /* Set key implementation. */
    .setkey = xxx_aes_setkey,
    /* Encrypt/decrypt implementation. */
    .encrypt = xxx_cbc_aes_encrypt,
    .decrypt = xxx_cbc_aes_decrypt,
    /* Symmetric key size. */
    .min_keysize = AES_MIN_KEY_SIZE,
    .max_keysize = AES_MAX_KEY_SIZE,
    /* IV size */
    .ivsize = AES_BLOCK_SIZE,
    .base = {
        ....
    },
};

static int xxx_encrypt(struct skcipher_request *req)
{
    struct my_ctx *ctx = crypto_tfm_ctx(req->base.tfm);
    /* Prepare and queue the request here. Return 0 if the request has
     * been executed, -EINPROGRESS if it's been queued, -EBUSY if it's
     * been backlogged or a different error code for other kind of
     * errors.
     */
    return ret;
}

static int xxx_decrypt(struct skcipher_request *req)
{
    struct my_ctx *ctx = crypto_tfm_ctx(req->base.tfm);
    /* Similar to xxx_encrypt() except this time we prepare and queue
     * a decrypt operation.
     */
    return ret;
}

static int xxx_setkey(struct crypto_skcipher *cipher, const u8 *key,
unsigned int len)
{
    struct my_ctx *ctx = crypto_tfm_ctx(req->base.tfm);
    /* Expand key and assing store the result in the ctx. */
    return ret;
}

你可能感兴趣的:(信息安全,密码)