在我的工作中,我想使用aes-gcm算法来加密linux内核模块中的数据,所以我选择了aead api。在aes gcm中,aad数据可以设置为0-264位,但在代码中如果我使用aead_request_set_ad()函数设置,则scatterlist struct的数据为null,这将是错误。 AES-GCM algorithm
接下来是我在linux内核4.10中的代码:
int aes_gcm_decrypt(struct crypto_aead *tfm, u8 *j_0, u8 *aad,
u8 *data, size_t data_len, u8 *mic)
{
struct scatterlist sg[3];
struct aead_request *aead_req;
int reqsize = sizeof(*aead_req) + crypto_aead_reqsize(tfm);
int err;
if (data_len == 0)
return -EINVAL;
aead_req = kzalloc(reqsize + GCM_AAD_LEN, GFP_ATOMIC);
if (!aead_req)
return -ENOMEM;
sg_init_table(sg, 3);
sg_set_buf(&sg[0], aad,0);
sg_set_buf(&sg[1], data, data_len);
sg_set_buf(&sg[2], mic, 16);
aead_request_set_tfm(aead_req, tfm);
aead_request_set_crypt(aead_req, sg, sg,
data_len + 16, j_0);
aead_request_set_ad(aead_req, sg[0].length);
err = crypto_aead_decrypt(aead_req);
kzfree(aead_req);
return err;
}
如果我使用sg_set_page(& sg [0],ZERO_PAGE(0),0,0)设置sg [0],那也是错误的。
如果我删除sg [0]也是错误的......
在aead_request_set_crypt函数中,注释如下:
/**
* aead_request_set_crypt - set data buffers
* @req: request handle
* @src: source scatter / gather list
* @dst: destination scatter / gather list
* @cryptlen: number of bytes to process from @src
* @iv: IV for the cipher operation which must comply with the IV size defined
* by crypto_aead_ivsize()
*
* Setting the source data and destination data scatter / gather lists which
* hold the associated data concatenated with the plaintext or ciphertext. See
* below for the authentication tag.
*
* For encryption, the source is treated as the plaintext and the
* destination is the ciphertext. For a decryption operation, the use is
* reversed - the source is the ciphertext and the destination is the plaintext.
*
* The memory structure for cipher operation has the following structure:
*
* - AEAD encryption input: assoc data || plaintext
* - AEAD encryption output: assoc data || cipherntext || auth tag
* - AEAD decryption input: assoc data || ciphertext || auth tag
* - AEAD decryption output: assoc data || plaintext
*
* Albeit the kernel requires the presence of the AAD buffer, however,
* the kernel does not fill the AAD buffer in the output case. If the
* caller wants to have that data buffer filled, the caller must either
* use an in-place cipher operation (i.e. same memory location for
* input/output memory location).
*/
关联数据必须存在,所以如何设置它的长度为零?
答案 0 :(得分:0)
我自己已经解决了这个问题。就像这样:
struct scatterlist sg[2];
...
sg_set_buf(&sg[0], data, data_len);
sg_set_buf(&sg[1], mic, 16);
...
aead_request_set_ad(aead_req, 0);
只需定义两个scatterlist结构并设置广告零。