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 使用者感興趣的欄位如下

  • etypectype 分別表示此編碼型別用於加密和校驗的協議號。它們包含 KRB5_ENCTYPE_*KRB5_CKSUMTYPE_* 常量。

  • name 是編碼的正式名稱。

  • key_lenkey_bytes 是輸入金鑰長度和派生金鑰長度。(我認為它們只對 DES 不同,這裡不支援 DES)。

  • Kc_lenKe_lenKi_len 是派生 Kc、Ke 和 Ki 金鑰的大小。Kc 用於校驗模式;Ke 和 Ki 用於加密模式。

  • prf_len 是 PRF+ 函式計算結果的大小。

  • block_lenconf_lencksum_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 金鑰。

使用特定順序的單詞意味著靜態測試資料不需要位元組序轉換。