Does QEMU/KVM use Intel AES instructions for encrypted qcow2 images if the host CPU has them

cpudisk-encryptionencryptionkvm

The qcow2 image file format for KVM can use AES encryption. The encryption is applied at the cluster level:

Each sector within each cluster is independently encrypted using AES Cipher Block Chaining mode, using the sector's offset (relative to the start of the device) in little-endian format as the first 64 bits of the 128 bit initialisation vector.

The cluster size can be set from 512 bytes to 2M (64K appears to be the default).

One of the main issues with using qcow2 encryption is the performance hit for the CPU – every disk write or non-cached read needs to encrypt or unencrypt.

What I'd like to know is does QEMU/KVM use the Intel AES instructions to mitigate the performance hit if the host CPU has them? If so, does usage or performance depend significantly on cluster size?

Intel® AES instructions are a new set of instructions available beginning with the all new 2010 Intel® Core™ processor family based on the 32nm Intel® microarchitecture codename Westmere. These instructions enable fast and secure data encryption and decryption, using the Advanced Encryption Standard (AES) which is defined by FIPS Publication number 197. Since AES is currently the dominant block cipher, and it is used in various protocols, the new instructions are valuable for a wide range of applications.

Best Answer

At least with the Fedora 20 package qemu-img (1.6.2, 10.fc20) does not use AES-NI for AES crypto.

Confirming

One can verify it like this:

  1. Does the CPU have AES-NI?

    $ grep aes /proc/cpuinfo  -i
    

    For example my Intel Core 7 has this extension.

  2. Install the necessary debug packages:

    # debuginfo-install qemu-img
    
  3. Run qemu-img in a debugger:

    $ gdb --args qemu-img convert -o encryption -O qcow2 disk1.img enc1.qcow2
    
  4. Set a break-point in a well known qemu encryption function that is not optimized for AES-NI:

    (gdb) b AES_encrypt
    Breakpoint 1 at 0x794b0: file util/aes.c, line 881.
    
  5. Run the program:

    (gdb) r
    Starting program: /usr/bin/qemu-img convert -o encryption -O qcow2 disk1.img enc1.qcow2
    

Results

In my testing it does stop there:

Breakpoint 1, AES_encrypt (in=0x7ffff7fabd60 "...", key=0x555555c1b510) at util/aes.c:881
881          const AES_KEY *key) {
(gdb) n
889     assert(in && out && key);
(gdb) n
881          const AES_KEY *key) {
(gdb) n
889     assert(in && out && key);
(gdb) n
896     s0 = GETU32(in     ) ^ rk[0];
(gdb) n
897     s1 = GETU32(in +  4) ^ rk[1];

Meaning that, indeed, Intel AES instructions are not used.

My first thought was that qemu-img perhaps just uses libcrypto such that AES-NI is automatically used, when available. qemu-img even links against libcrypto (cf ldd $(which qemu-img)) - but it does not seem to use it for AES crypto. Hmm.

I derived the breakpoint location via grepping the QEMU source code. On Fedora you can get it like this:

$ fedpkg clone -a qemu
$ cd qemu
$ fedpkg source
$ tar xfv qemu-2.2.0-rc1.tar.bz2
$ cd qemu-2.2.0-rc1

NOTE: gdb can be exited via the quit command.

Related Question