mirror of
https://gitlab.com/qemu-project/qemu.git
synced 2026-10-28 14:04:39 +08:00
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:
1 parent
4ed7ae88ec
commit
a99cc7d959
3 files changed
+216
No files matched your search
@@ -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);
|
||||
}
|
||||
@@ -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',
|
||||
|
||||
@@ -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
|
||||
Reference in new issue
Block a user