// don't have to explicitly care about underlying buffer layout yourself
// in case of encryption...
EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
EVP_EncryptInit(ctx, cipher, NULL, NULL);
EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, IVLEN, NULL);
EVP_EncryptInit(ctx, NULL, gcm_key, gcm_iv);
// add associated data
EVP_EncryptUpdate(ctx, NULL, &outlen, ad, adlen);
// encrypt payload
EVP_EncryptUpdate(ctx, outbuf, &outlen, enc_msg, enc_len);
EVP_EncryptFinal(ctx, outbuf, &outlen);
// get auth tag
EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, TAGLEN, gcm_tag);
// and descryption...
EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
EVP_DecryptInit(ctx, cipher, NULL, NULL);
EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, IVLEN, NULL);
EVP_DecryptInit(ctx, NULL, gcm_key, gcm_iv);
// add associated data
EVP_DecryptUpdate(ctx, NULL, &outlen, ad, adlen);
// decrypt payload
EVP_DecryptUpdate(ctx, outbuf, &outlen, inbuf_bin, bin_outlen);
// set auth tag
EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, TAGLEN, gcm_tag);
EVP_DecryptFinal(ctx, outbuf, &outlen);
// https://elixir.bootlin.com/linux/v6.14/source/include/crypto/aead.h#L488
/**
* 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 || ciphertext || 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).
*/
# https://datatracker.ietf.org/doc/html/rfc4106
for aes256:
- associated data:
8bytes in case of IPSEC without ESN
but doesn't matter as long as
we correctly align underlying buffer layout
- key:
32bytes with 4bytes as salt at the end
- nonce:
8 bytes
u8 assoc_msg[GCM_ASSOCLEN] = {
0x11, 0x22, 0x33, 0x44,
0x11, 0x22, 0x33, 0x44,
0x11, 0x22, 0x33, 0x44,
0x11, 0x22, 0x33, 0x44,
};
u8 nonce[GCM_NONCELEN] = {
0x99, 0x99, 0x99, 0x99,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
u8 key[GCM_KEYLEN] = {
0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
0xaa, 0xbb,
0x00, 0x00, 0x00, 0x00,
};
[Dec 3 23:59] init kcrypt
[ +0.000319] original data: this is test data for kcrypt
[ +0.000013] kcrypt: encryption completed
[ +0.000001] - assoc: ."3D."3D."3D."3D
[ +0.000001] - cryptogram: NT..\xb9r\xb3\xeaj:.e3.\xa6X..\xbe-x.Z.G\xd2..
[ +0.000000] - auth tag: \xfc\xddk.\xe6.x.@\xa7z\xc4S..\xce
[ +0.000002] kcrypt: decryption completed
[ +0.000001] authenticated plaintext: this is test data for kcrypt
[ +37.572556] exit kcrypt
// after encryption...
EVP_EncryptFinal(ctx, outbuf + outlen, &outlen);
// ...rather than getting tag
HMAC(EVP_sha256(), cbc_auth, KEYLEN, outbuf, outlen, result, &resultlen);
// after decryption...
EVP_DecryptFinal(ctx, outbuf + outlen, &outlen);
// rather than setting tag
HMAC(EVP_sha256(), cbc_auth, KEYLEN, inbuf_bin, bin_outlen, result, &resultlen);
// https://elixir.bootlin.com/linux/v6.14/source/include/crypto/skcipher.h#L905
/**
* skcipher_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_skcipher_ivsize
*
* This function allows setting of the source data and destination data
* scatter / gather lists.
*
* 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.
*/
u8 nonce[CBC_IVLEN] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
u8 key[CBC_KEYLEN] = {
0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
0xaa, 0xbb,
};
u8 auth_key[CBC_AUTHKEYLEN] = {
0x11, 0x22, 0x33, 0x44, 0x55, 0x66,
0x11, 0x22, 0x33, 0x44, 0x55, 0x66,
0x11, 0x22, 0x33, 0x44, 0x55, 0x66,
0x11, 0x22, 0x33, 0x44, 0x55, 0x66,
0x11, 0x22, 0x33, 0x44, 0x55, 0x66,
0x11, 0x22,
};
// can truncate for auth
u8 auth_val[CBC_AUTHLEN] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
[Dec 4 00:24] init kcrypt
[ +0.000004] kcrypt: datalen: 28
[ +0.000001] kcrypt: padded datalen: 32
[ +0.000036] kcrypt: auth val calculated for nonce + padded data
[ +0.000001] - auth val: .T,Z?\xfb\xba.[V8\xda.u.`._7.w^\xd9]k\xb6..G\xc2W#
[ +0.000001] original data: this is test data for kcrypt
[ +0.000002] kcrypt: encryption completed
[ +0.000000] - cryptogram: .G\xf9.\xb0\xcf.?\xc8.\xf9hc4uu1I\xdb)\xa1'.1.\xc0Y.%.D.
[ +0.000002] kcrypt: decryption completed
[ +0.000004] kcrypt: auth val calculated for nonce + padded data after decryption
[ +0.000001] - auth val: .T,Z?\xfb\xba.[V8\xda.u.`._7.w^\xd9]k\xb6..G\xc2W#
[ +0.000001] kcrypt: auth value matched
[ +0.000001] authenticated plaintext: this is test data for kcrypt
[ +11.913847] exit kcrypt