seantywork

compared openssl userspace api

// 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);

aead comment

// 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).
 */

rfc4106 quirk? for data

# 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,
    }; 

gcm result

[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

cbc difference compared to gcm

// 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);

cbc comment

// 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.
 */


cbc data

    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,
    };

cbc result

[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