带相关数据认证加密 (AEAD) 算法定义

AEAD 密码 API 与 CRYPTO_ALG_TYPE_AEAD 类型的密码一起使用(在 /proc/crypto 中列为 “aead” 类型)

此类型加密最突出的示例是 GCM 和 CCM。但是,内核支持其他类型的 AEAD 密码,这些密码通过以下密码字符串定义

authenc(keyed message digest, block cipher)

例如:authenc(hmac(sha256), cbc(aes))

为对称密钥密码操作提供的示例代码也适用于此处。 当然,所有 _skcipher_ 符号都必须与以下讨论的 _aead_ 对等符号交换。 此外,对于 AEAD 操作,必须使用 aead_request_set_ad 函数在执行加密或解密操作之前设置指向关联数据内存位置的指针。 与异步分组密码操作的另一个偏差是,调用者应显式检查 crypto_aead_decrypt 的 -EBADMSG。 该错误指示身份验证错误,即消息完整性受到破坏。 本质上,-EBADMSG 错误代码是 AEAD 密码优于“标准”分组链接模式的关键优势。

内存结构

源散列表必须包含关联数据 || 明文或密文的串联。

目标散列表具有相同的布局,不同之处在于,明文(或密文)在加密(或解密)期间将按身份验证标签大小增长(或缩小)。 身份验证标签在加密操作期间生成并附加到密文。 在解密期间,身份验证标签与密文一起使用,以验证明文和关联数据的完整性。

通过对源和目标使用相同的散列表指针来启用就地加密/解密。

即使在异地情况下,也必须在目标中为关联数据保留空间,即使它不会被写入。 这使得就地和异地情况更加一致。“目标”关联数据可以别名“源”关联数据。

与其他散列表加密 API 一样,散列表的已用部分不允许出现零长度散列表元素。 因此,如果没有关联数据,则第一个元素必须指向明文/密文。

为了满足 IPsec 的需求,一个特殊的怪癖适用于 rfc4106、rfc4309、rfc4543 和 rfc7539esp 密码。 对于这些密码,关联数据缓冲区的最后 “ivsize” 个字节必须包含 IV 的第二个副本。 这是对传递给 aead_request_set_crypt() 的副本的补充。 这两个 IV 副本不得不同;相同算法的不同实现可能会在这种情况下表现不同。 请注意,该算法实际上可能不会将 IV 视为关联数据;尽管如此,传递给 aead_request_set_ad() 的长度必须包含它。

struct aead_request

AEAD 请求

定义:

struct aead_request {
    struct crypto_async_request base;
    unsigned int assoclen;
    unsigned int cryptlen;
    u8 *iv;
    struct scatterlist *src;
    struct scatterlist *dst;
    void *__ctx[] ;
};

成员

base

异步加密请求的通用属性

assoclen

用于身份验证的关联数据长度(以字节为单位)

cryptlen

要加密或解密的数据的长度

iv

初始化向量

src

源数据

dst

目标数据

__ctx

私有上下文数据的开始

struct aead_alg

AEAD 密码定义

定义:

struct aead_alg {
    int (*setkey)(struct crypto_aead *tfm, const u8 *key, unsigned int keylen);
    int (*setauthsize)(struct crypto_aead *tfm, unsigned int authsize);
    int (*encrypt)(struct aead_request *req);
    int (*decrypt)(struct aead_request *req);
    int (*init)(struct crypto_aead *tfm);
    void (*exit)(struct crypto_aead *tfm);
    unsigned int ivsize;
    unsigned int maxauthsize;
    unsigned int chunksize;
    struct crypto_alg base;
};

成员

setkey

请参阅 struct skcipher_alg

setauthsize

设置 AEAD 转换的身份验证大小。 此函数用于指定使用者请求的身份验证标签大小,该标签要么由加密期间的转换生成,要么是要在解密操作期间提供的身份验证标签的大小。 此函数还负责检查身份验证标签大小的有效性。

encrypt

请参阅 struct skcipher_alg

decrypt

请参阅 struct skcipher_alg

init

初始化加密转换对象。 此函数用于初始化加密转换对象。 此函数仅在实例化时调用一次,就在转换上下文分配之后。 如果加密硬件有一些特殊要求需要由软件处理,则此函数应检查转换的精确要求,并放置任何软件回退。

exit

取消初始化加密转换对象。 这是 init 的对应项,用于删除 init 中设置的各种更改。

ivsize

请参阅 struct skcipher_alg

maxauthsize

设置转换支持的最大身份验证标签大小。 转换可能支持较小的标签大小。 由于身份验证标签是消息摘要,用于确保加密数据的完整性,因此使用者通常需要此变量定义的最大身份验证标签。

chunksize

请参阅 struct skcipher_alg

base

通用加密密码算法的定义。

描述

ivsize 之外的所有字段都是强制性的,必须填写。

带相关数据认证加密 (AEAD) 密码 API

struct crypto_aead *crypto_alloc_aead(const char *alg_name, u32 type, u32 mask)

分配 AEAD 密码句柄

参数

const char *alg_name

是 AEAD 密码的 cra_name / name 或 cra_driver_name / driver name

u32 type

指定密码的类型

u32 mask

指定密码的掩码

描述

为 AEAD 分配密码句柄。 返回的 struct crypto_aead 是密码句柄,是该 AEAD 的任何后续 API 调用所必需的。

返回

在成功的情况下,分配的密码句柄;如果发生错误,则 IS_ERR() 为 true,PTR_ERR() 返回错误代码。

如果发生错误,PTR_ERR() 将返回错误代码。

void crypto_free_aead(struct crypto_aead *tfm)

零化并释放 aead 句柄

参数

struct crypto_aead *tfm

要释放的密码句柄

描述

如果 tfm 是 NULL 或错误指针,则此函数不执行任何操作。

unsigned int crypto_aead_ivsize(struct crypto_aead *tfm)

获取 IV 大小

参数

struct crypto_aead *tfm

密码句柄

描述

返回密码句柄引用的 aead 的 IV 大小。 如果密码不需要 IV,则此 IV 大小可能为零。

返回

IV 大小(以字节为单位)

unsigned int crypto_aead_authsize(struct crypto_aead *tfm)

获取最大身份验证数据大小

参数

struct crypto_aead *tfm

密码句柄

描述

返回 AEAD 密码句柄引用的 AEAD 密码的最大身份验证数据大小。 如果密码实现硬编码最大值,则身份验证数据大小可能为零。

身份验证数据也称为“标签值”。

返回

身份验证数据大小/标签大小(以字节为单位)

unsigned int crypto_aead_blocksize(struct crypto_aead *tfm)

获取密码的块大小

参数

struct crypto_aead *tfm

密码句柄

描述

返回使用密码句柄引用的 AEAD 的块大小。 调用者可以使用该信息来为加密或解密操作返回的数据分配适当的内存

返回

密码的块大小

int crypto_aead_setkey(struct crypto_aead *tfm, const u8 *key, unsigned int keylen)

设置密码的密钥

参数

struct crypto_aead *tfm

密码句柄

const u8 *key

保存密钥的缓冲区

unsigned int keylen

密钥的长度(以字节为单位)

描述

为密码句柄引用的 AEAD 设置调用者提供的密钥。

请注意,密钥长度决定密码类型。 许多块密码根据密钥大小实现不同的密码模式,例如 AES-128 与 AES-192 与 AES-256。 当为 AES 密码句柄提供 16 字节密钥时,将执行 AES-128。

返回

如果密钥设置成功,则为 0;如果发生错误,则 < 0

int crypto_aead_setauthsize(struct crypto_aead *tfm, unsigned int authsize)

设置身份验证数据大小

参数

struct crypto_aead *tfm

密码句柄

unsigned int authsize

身份验证数据的大小/标签大小(以字节为单位)

描述

设置身份验证数据大小/标签大小。 除了关联数据之外,AEAD 还要求身份验证标签(或 MAC)。

返回

如果密钥设置成功,则为 0;如果发生错误,则 < 0

int crypto_aead_encrypt(struct aead_request *req)

加密明文

参数

struct aead_request *req

引用 aead_request 句柄,该句柄保存执行密码操作所需的所有信息

描述

使用 aead_request 句柄加密明文数据。 该数据结构以及如何使用数据填充它将在 aead_request_* 函数中讨论。

重要提示 加密操作创建身份验证数据/

标签。 该数据与创建的密文连接。 因此,密文内存大小是给定的块密码块数 + crypto_aead_setauthsize 调用定义的大小。 调用者必须确保有足够的内存可用于密文和身份验证标签。

返回

如果密码操作成功,则为 0;如果发生错误,则 < 0

int crypto_aead_decrypt(struct aead_request *req)

解密密文

参数

struct aead_request *req

引用 aead_request 句柄,该句柄保存执行密码操作所需的所有信息

描述

使用 aead_request 句柄解密密文数据。 该数据结构以及如何使用数据填充它将在 aead_request_* 函数中讨论。

重要提示 调用者必须连接密文,后跟

身份验证数据/标签。 该身份验证数据/标签必须具有 crypto_aead_setauthsize 调用定义的大小。

返回

如果密码操作成功,则为 0;-EBADMSG:AEAD

密码操作在解密操作期间执行数据的身份验证。 因此,如果密文的身份验证不成功(即密文或关联数据的完整性受到破坏),则该函数将返回此错误;如果发生错误,则 < 0。

异步 AEAD 请求句柄

aead_request 数据结构包含 AEAD 密码操作所需的所有数据指针。 这包括密码句柄(可由多个 aead_request 实例使用)、指向明文和密文的指针、异步回调函数等。 它的作用类似于 aead_request_* API 调用的句柄,与 AEAD 句柄到 crypto_aead_* API 调用的方式类似。

unsigned int crypto_aead_reqsize(struct crypto_aead *tfm)

获取请求数据结构的大小

参数

struct crypto_aead *tfm

密码句柄

返回

字节数

void aead_request_set_tfm(struct aead_request *req, struct crypto_aead *tfm)

更新请求中的密码句柄引用

参数

struct aead_request *req

要修改的请求句柄

struct crypto_aead *tfm

应添加到请求句柄的密码句柄

描述

允许调用者将请求数据结构中现有的 aead 句柄替换为不同的句柄。

struct aead_request *aead_request_alloc(struct crypto_aead *tfm, gfp_t gfp)

分配请求数据结构

参数

struct crypto_aead *tfm

要使用请求注册的密码句柄

gfp_t gfp

内存分配标志,由 API 调用传递给 kmalloc。

描述

分配必须与 AEAD 加密和解密 API 调用一起使用的请求数据结构。 在分配期间,提供的 aead 句柄在请求数据结构中注册。

返回

如果成功,则分配的请求句柄,如果内存不足,则为 NULL

void aead_request_free(struct aead_request *req)

零化并释放请求数据结构

参数

struct aead_request *req

要释放的请求数据结构密码句柄

void aead_request_set_callback(struct aead_request *req, u32 flags, crypto_completion_t compl, void *data)

设置异步回调函数

参数

struct aead_request *req

请求句柄

u32 flags

指定零或标志 CRYPTO_TFM_REQ_MAY_BACKLOG 的 ORing 请求队列可能会备份日志并将等待队列增加到超过初始最大大小;CRYPTO_TFM_REQ_MAY_SLEEP 请求处理可能会休眠

crypto_completion_t compl

要使用请求句柄注册的回调函数指针

void *data

数据指针引用内核加密 API 未使用的内存,但提供给回调函数使用。 在这里,调用者可以提供对回调函数可以操作的内存的引用。 由于回调函数是相对于相关功能异步调用的,因此它可能需要访问相关功能的数据结构,可以使用此指针引用这些数据结构。 回调函数可以通过提供给回调函数的 crypto_async_request 数据结构中的“data”字段访问内存。

描述

设置一旦密码操作完成就会触发的回调函数

回调函数已使用 aead_request 句柄注册,必须符合以下模板

void callback_function(struct crypto_async_request *req, int error)
void aead_request_set_crypt(struct aead_request *req, struct scatterlist *src, struct scatterlist *dst, unsigned int cryptlen, u8 *iv)

设置数据缓冲区

参数

struct aead_request *req

请求句柄

struct scatterlist *src

源散布/收集列表

struct scatterlist *dst

目标散布/收集列表

unsigned int cryptlen

要从 src 处理的字节数

u8 *iv

密码操作的 IV,必须符合 crypto_aead_ivsize() 定义的 IV 大小

描述

设置源数据和目标数据散布/收集列表,这些列表保存与明文或密文连接的关联数据。 有关身份验证标签,请参见下文。

对于加密,源被视为明文,目标是密文。 对于解密操作,使用方法相反 - 源是密文,目标是明文。

密码操作的内存结构具有以下结构

  • AEAD 加密输入:关联数据 || 明文

  • AEAD 加密输出:关联数据 || 密文 || 身份验证标签

  • AEAD 解密输入:关联数据 || 密文 || 身份验证标签

  • AEAD 解密输出:关联数据 || 明文

尽管内核要求存在 AAD 缓冲区,但内核不会在输出情况下填充 AAD 缓冲区。 如果调用者想要填充该数据缓冲区,则调用者必须使用就地密码操作(即输入/输出内存位置的相同内存位置)。

void aead_request_set_ad(struct aead_request *req, unsigned int assoclen)

设置关联数据信息

参数

struct aead_request *req

请求句柄

unsigned int assoclen

关联数据中的字节数

描述

设置 AD 信息。 此函数设置关联数据的长度。