帶相關資料認證加密 (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 資訊。 此函式設定關聯資料的長度。