crypto: Add aes-helpers file to support some AES modes

Add a new file crypto/aes-helpers.c with simple functions
to support some AES modes:
- AES cbc: AES_cbc_encrypt() AES_cbc_decrypt()
- AES ctr: AES_ctr_encrypt()
- AES xts: AES_xts_encrypt() AES_xts_decrypt()
and some AES related helpers:
- AES_xor()
- AES_xts_prep_next_tweak()
Add header file include/crypto/aes-helpers.h for these functions

Signed-off-by: Harald Freudenberger <freude@linux.ibm.com>
Reviewed-by: Finn Callies <fcallies@linux.ibm.com>
Reviewed-by: Ilya Leoshkevich <iii@linux.ibm.com>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
Acked-by: Daniel P. Berrangé <berrange@redhat.com>
Link: https://lore.kernel.org/qemu-devel/20260824083204.40877-8-freude@linux.ibm.com
Signed-off-by: Eric Farman <farman@linux.ibm.com>
This commit is contained in:
Harald Freudenberger authored and Eric Farman committed 2026-09-21 05:58:38 -04:00
1 parent 4ed7ae88ec
commit a99cc7d959
3 files changed
+216

No files matched your search

+106
View File
@@ -0,0 +1,106 @@
/*
* SPDX-License-Identifier: GPL-2.0-or-later
*
* AES helper functions and mode implementations
*
* Authors:
* Harald Freudenberger <freude@linux.ibm.com>
*/
#include "qemu/osdep.h"
#include "crypto/aes.h"
#include "crypto/aes-helpers.h"
void AES_xor(const unsigned char *src1, const unsigned char *src2,
unsigned char *dst)
{
int i;
for (i = 0; i < AES_BLOCK_SIZE; i++) {
dst[i] = src1[i] ^ src2[i];
}
}
void AES_cbc_encrypt(const unsigned char *in, unsigned char *out,
unsigned char *iv, const AES_KEY *key)
{
unsigned char buf[AES_BLOCK_SIZE];
/* in xor iv => buf */
AES_xor(in, iv, buf);
/* encrypt buf => out */
AES_encrypt(buf, out, key);
/* prep iv for next round */
memcpy(iv, out, AES_BLOCK_SIZE);
}
void AES_cbc_decrypt(const unsigned char *in, unsigned char *out,
unsigned char *iv, const AES_KEY *key)
{
unsigned char buf[AES_BLOCK_SIZE];
/* decrypt in => buf */
AES_decrypt(in, buf, key);
/* buf xor iv => out */
AES_xor(buf, iv, out);
/* prep iv for next round */
memcpy(iv, in, AES_BLOCK_SIZE);
}
void AES_ctr_encrypt(const unsigned char *in, unsigned char *out,
const unsigned char *ctr, const AES_KEY *key)
{
unsigned char buf[AES_BLOCK_SIZE];
/* encrypt ctr => buf */
AES_encrypt(ctr, buf, key);
/* exor input data with encrypted ctr => out */
AES_xor(in, buf, out);
}
/*
* Tweak calculation for AES XTS.
* Multiply tweak by α (x) in GF(2^128) per IEEE 1619-2007. The tweak
* is a 128-bit little-endian integer (tweak[0]=LSB, tweak[15]=MSB).
* This implementation has been verified on little and big endian.
*/
void AES_xts_prep_next_tweak(unsigned char *tweak)
{
unsigned char carry;
int i;
carry = tweak[AES_BLOCK_SIZE - 1] >> 7;
for (i = AES_BLOCK_SIZE - 1; i > 0; i--) {
tweak[i] = (unsigned char)((tweak[i] << 1) | (tweak[i - 1] >> 7));
}
tweak[i] = (unsigned char)(tweak[i] << 1);
tweak[i] ^= (unsigned char)(0x87 & (unsigned char)(-(unsigned char)carry));
}
void AES_xts_encrypt(const unsigned char *in, unsigned char *out,
const unsigned char *tweak, const AES_KEY *key)
{
unsigned char buf1[AES_BLOCK_SIZE], buf2[AES_BLOCK_SIZE];
/* in xor tweak => buf1 */
AES_xor(in, tweak, buf1);
/* encrypt buf1 => buf2 */
AES_encrypt(buf1, buf2, key);
/* buf2 xor tweak => out */
AES_xor(buf2, tweak, out);
}
void AES_xts_decrypt(const unsigned char *in, unsigned char *out,
const unsigned char *tweak, const AES_KEY *key)
{
unsigned char buf1[AES_BLOCK_SIZE], buf2[AES_BLOCK_SIZE];
/* in xor tweak => buf1 */
AES_xor(in, tweak, buf1);
/* encrypt buf1 => buf2 */
AES_decrypt(buf1, buf2, key);
/* buf2 xor tweak => out */
AES_xor(buf2, tweak, out);
}
+1
View File
@@ -55,6 +55,7 @@ system_ss.add(when: gnutls, if_true: files('tls-cipher-suites.c'))
util_ss.add(files(
'aes.c',
'aes-helpers.c',
'clmul.c',
'init.c',
'sm4.c',
+109
View File
@@ -0,0 +1,109 @@
/*
* SPDX-License-Identifier: GPL-2.0-or-later
*
* AES helper functions and modes
*/
#ifndef QEMU_AES_HELPERS_H
#define QEMU_AES_HELPERS_H
/**
* AES_xor:
* @src1: first source buffer of AES_BLOCK_SIZE bytes
* @src2: second source buffer of AES_BLOCK_SIZE bytes
* @dst: destination buffer of AES_BLOCK_SIZE bytes
*
* Bitwise XOR operation between two AES blocks.
*/
void AES_xor(const unsigned char *src1, const unsigned char *src2,
unsigned char *dst);
/**
* AES_cbc_encrypt:
* @in: input plaintext block of AES_BLOCK_SIZE bytes
* @out: output ciphertext block of AES_BLOCK_SIZE bytes
* @iv: IV, updated after processing for chaining
* @key: AES key
*
* Single block AES encrypt in CBC (Cipher Block Chaining) mode.
* The input block is XORed with the IV, then encrypted with AES.
* IV is updated at the end and is prepared for the next invocation.
*/
void AES_cbc_encrypt(const unsigned char *in, unsigned char *out,
unsigned char *iv, const AES_KEY *key);
/**
* AES_cbc_decrypt:
* @in: input ciphertext block of AES_BLOCK_SIZE bytes
* @out: output plaintext block of AES_BLOCK_SIZE bytes
* @iv: initialization vector, updated to input block for chaining
* @key: AES key
*
* Single block AES decrypt in CBC (Cipher Block Chaining) mode.
* The input block is decrypted, then XORed with the IV.
* IV is updated at the end and is prepared for the next invocation.
*/
void AES_cbc_decrypt(const unsigned char *in, unsigned char *out,
unsigned char *iv, const AES_KEY *key);
/**
* AES_ctr_encrypt:
* @in: input data block of AES_BLOCK_SIZE bytes
* @out: output data block of AES_BLOCK_SIZE bytes
* @ctr: counter value of AES_BLOCK_SIZE bytes
* @key: AES key
*
* Single block AES encrypt/decrypt in CTR (Counter) mode.
* The counter block is encrypted, then XORed with the
* input data block.
* In CTR mode encrypt and decrypt are identical operations.
* Note that the caller is responsible for incrementing the
* counter block.
*/
void AES_ctr_encrypt(const unsigned char *in, unsigned char *out,
const unsigned char *ctr, const AES_KEY *key);
/**
* AES_xts_prep_next_tweak:
* @tweak: pointer to tweak value to be updated (16 bytes buffer
* containing a 128 bit little endian integer)
*
* Tweak calculation for AES XTS.
* Prepares the next tweak value for AES-XTS mode by multiplying
* the current tweak by α (x) in GF(2^128) according to IEEE 1619-2007.
*/
void AES_xts_prep_next_tweak(unsigned char *tweak);
/**
* AES_xts_encrypt:
* @in: input plaintext block of AES_BLOCK_SIZE bytes
* @out: output ciphertext block of AES_BLOCK_SIZE bytes
* @tweak: tweak value (16 bytes)
* @key: AES key
*
* Single block AES encrypt in XTS mode.
* The input is XORed with the tweak, encrypted, then XORed with
* the tweak again to produce the output.
* Note that the caller is responsible for managing the tweak value.
* Use AES_xts_prep_next_tweak() to advance the tweak for the next block.
*/
void AES_xts_encrypt(const unsigned char *in, unsigned char *out,
const unsigned char *tweak, const AES_KEY *key);
/**
* AES_xts_decrypt:
* @in: input ciphertext block of AES_BLOCK_SIZE bytes
* @out: output plaintext block of AES_BLOCK_SIZE bytes
* @tweak: tweak value (16 bytes)
* @key: AES key
*
* Single block AES decrypt in XTS mode.
* The input is XORed with the tweak, decrypted, then XORed with
* the tweak again to produce the output.
* Note that the caller is responsible for managing the tweak value.
* Use AES_xts_prep_next_tweak() to advance the tweak for the next block.
*/
void AES_xts_decrypt(const unsigned char *in, unsigned char *out,
const unsigned char *tweak, const AES_KEY *key);
#endif