Kerberos V 加密 API¶
概述¶
此 API 提供 Kerberos 5 风格的加密功能,用于密钥派生、加密和校验,可用于网络文件系统,也可用于实现 GSSAPI 所需的低级加密。
支持以下加密类型
KRB5_ENCTYPE_AES128_CTS_HMAC_SHA1_96
KRB5_ENCTYPE_AES256_CTS_HMAC_SHA1_96
KRB5_ENCTYPE_AES128_CTS_HMAC_SHA256_128
KRB5_ENCTYPE_AES256_CTS_HMAC_SHA384_192
KRB5_ENCTYPE_CAMELLIA128_CTS_CMAC
KRB5_ENCTYPE_CAMELLIA256_CTS_CMAC
KRB5_CKSUMTYPE_HMAC_SHA1_96_AES128
KRB5_CKSUMTYPE_HMAC_SHA1_96_AES256
KRB5_CKSUMTYPE_CMAC_CAMELLIA128
KRB5_CKSUMTYPE_CMAC_CAMELLIA256
KRB5_CKSUMTYPE_HMAC_SHA256_128_AES128
KRB5_CKSUMTYPE_HMAC_SHA384_192_AES256
API 可通过以下方式包含
#include <crypto/krb5.h>
小型缓冲区¶
为了传递小块数据(如密钥),定义了一个缓冲区结构,提供数据指针和数据大小。
struct krb5_buffer {
unsigned int len;
void *data;
};
编码类型¶
编码类型由以下结构定义
struct krb5_enctype {
int etype;
int ctype;
const char *name;
u16 key_bytes;
u16 key_len;
u16 Kc_len;
u16 Ke_len;
u16 Ki_len;
u16 prf_len;
u16 block_len;
u16 conf_len;
u16 cksum_len;
...
};
对 API 用户感兴趣的字段如下
etype
和ctype
分别表示此编码类型用于加密和校验的协议号。它们包含KRB5_ENCTYPE_*
和KRB5_CKSUMTYPE_*
常量。
name
是编码的正式名称。
key_len
和key_bytes
是输入密钥长度和派生密钥长度。(我认为它们只对 DES 不同,这里不支持 DES)。
Kc_len
、Ke_len
和Ki_len
是派生 Kc、Ke 和 Ki 密钥的大小。Kc 用于校验模式;Ke 和 Ki 用于加密模式。
prf_len
是 PRF+ 函数计算结果的大小。
block_len
、conf_len
和cksum_len
分别是加密块长度、混淆器长度和校验和长度。这三者都用于加密模式,但只有校验和长度用于校验模式。
编码类型通过以下函数按编号查找
const struct krb5_enctype *crypto_krb5_find_enctype(u32 enctype);
密钥派生¶
一旦应用程序选择了加密类型,用于实际加密的密钥就可以从传输密钥派生出来。
PRF+ 计算¶
为帮助密钥派生,提供了一个计算 Kerberos GSSAPI 机制的 PRF+ 函数
int crypto_krb5_calc_PRFplus(const struct krb5_enctype *krb5,
const struct krb5_buffer *K,
unsigned int L,
const struct krb5_buffer *S,
struct krb5_buffer *result,
gfp_t gfp);
这可用于从源密钥加上额外数据来派生传输密钥,以限制其使用。
加密函数¶
一旦密钥派生完成,就可以对数据执行加密操作。调用者在准备要传输的消息时,必须在缓冲区中为混淆器(如果需要)和校验和的存储留出间隙。为此提供了一个枚举和一对函数
enum krb5_crypto_mode {
KRB5_CHECKSUM_MODE,
KRB5_ENCRYPT_MODE,
};
size_t crypto_krb5_how_much_buffer(const struct krb5_enctype *krb5,
enum krb5_crypto_mode mode,
size_t data_size, size_t *_offset);
size_t crypto_krb5_how_much_data(const struct krb5_enctype *krb5,
enum krb5_crypto_mode mode,
size_t *_buffer_size, size_t *_offset);
所有这些函数都接受编码类型和加密模式指示(仅校验和或完全加密)。
第一个函数返回容纳给定数据量所需的缓冲区大小;第二个函数返回特定大小的缓冲区可容纳多少数据,并相应地调整所需缓冲区的大小。在这两种情况下,数据在缓冲区内的偏移量也会返回。
当收到消息时,可以通过调用以下函数确定消息中数据的位置和大小
void crypto_krb5_where_is_the_data(const struct krb5_enctype *krb5,
enum krb5_crypto_mode mode,
size_t *_offset, size_t *_len);
调用者向函数提供消息的偏移量和长度,然后函数会更改这些值以指示包含数据的区域(加上任何填充)。由调用者确定有多少填充。
准备函数¶
提供了两个函数来分配和准备加密对象,以便供动作函数使用
struct crypto_aead *
crypto_krb5_prepare_encryption(const struct krb5_enctype *krb5,
const struct krb5_buffer *TK,
u32 usage, gfp_t gfp);
struct crypto_shash *
crypto_krb5_prepare_checksum(const struct krb5_enctype *krb5,
const struct krb5_buffer *TK,
u32 usage, gfp_t gfp);
这两个函数都接受编码类型、传输密钥以及用于派生适当子密钥的使用值。它们创建一个适当的加密对象,一个用于加密的 AEAD 模板和一个用于校验和的同步哈希,并在其上设置密钥并进行配置。调用者应将这些句柄传递给下面的动作函数。
加密模式¶
提供一对函数来加密和解密消息
ssize_t crypto_krb5_encrypt(const struct krb5_enctype *krb5,
struct crypto_aead *aead,
struct scatterlist *sg, unsigned int nr_sg,
size_t sg_len,
size_t data_offset, size_t data_len,
bool preconfounded);
int crypto_krb5_decrypt(const struct krb5_enctype *krb5,
struct crypto_aead *aead,
struct scatterlist *sg, unsigned int nr_sg,
size_t *_offset, size_t *_len);
在这两种情况下,输入和输出缓冲区都由相同的散列列表指示。
对于加密函数,输出缓冲区可能大于所需(返回生成的输出量),并且指示了数据的位置和大小(必须与编码匹配)。如果未设置混淆器,函数将插入一个。
对于解密函数,提供消息在缓冲区中的偏移量和长度,并将其缩小以适应数据。解密函数将验证消息中的任何校验和,如果不匹配则返回错误。
校验和模式¶
提供一对函数来生成消息的校验和并验证该校验和
ssize_t crypto_krb5_get_mic(const struct krb5_enctype *krb5,
struct crypto_shash *shash,
const struct krb5_buffer *metadata,
struct scatterlist *sg, unsigned int nr_sg,
size_t sg_len,
size_t data_offset, size_t data_len);
int crypto_krb5_verify_mic(const struct krb5_enctype *krb5,
struct crypto_shash *shash,
const struct krb5_buffer *metadata,
struct scatterlist *sg, unsigned int nr_sg,
size_t *_offset, size_t *_len);
在这两种情况下,输入和输出缓冲区都由相同的散列列表指示。可以传入额外的元数据,这些元数据将在数据之前添加到哈希中。
对于 get_mic 函数,输出缓冲区可能大于所需(返回生成的输出量),并且指示了数据的位置和大小(必须与编码匹配)。
对于验证函数,提供消息在缓冲区中的偏移量和长度,并将其缩小以适应数据。如果校验和不匹配,将返回错误。
krb5enc AEAD 算法¶
提供了一个名为“krb5enc”的模板 AEAD 加密算法,它在加密明文之前对其进行哈希处理(与 authenc 相反)。crypto_krb5_prepare_encryption()
返回的句柄可能是其中之一,但此 API 的用户没有直接与其交互的要求。
作为参考,其密钥格式以格式号的 BE32 开始。只提供了格式 1,其后是 Ke 密钥长度的 BE32,然后是 Ki 密钥长度的 BE32,接着是 Ke 密钥的字节,然后是 Ki 密钥。
使用特定顺序的单词意味着静态测试数据不需要字节序转换。