Commit 431429a5 authored by Peter Maydell's avatar Peter Maydell
Browse files

Merge remote-tracking branch 'remotes/berrange/tags/qcrypto-fixes-pull-20151022-2' into staging



Merge qcrypto-fixes 2015/10/22

# gpg: Signature made Thu 22 Oct 2015 19:03:45 BST using RSA key ID 15104FDF
# gpg: Good signature from "Daniel P. Berrange <dan@berrange.com>"
# gpg:                 aka "Daniel P. Berrange <berrange@redhat.com>"

* remotes/berrange/tags/qcrypto-fixes-pull-20151022-2:
  configure: avoid polluting global CFLAGS with tasn1 flags
  crypto: add sanity checking of plaintext/ciphertext length
  crypto: don't let builtin aes crash if no IV is provided
  crypto: allow use of nettle/gcrypt to be selected explicitly

Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
parents dfbe0642 90246037
Loading
Loading
Loading
Loading
+93 −18
Original line number Diff line number Diff line
@@ -331,6 +331,8 @@ gtkabi=""
gtk_gl="no"
gnutls=""
gnutls_hash=""
nettle=""
gcrypt=""
vte=""
virglrenderer=""
tpm="yes"
@@ -417,9 +419,6 @@ if test "$debug_info" = "yes"; then
    LDFLAGS="-g $LDFLAGS"
fi

test_cflags=""
test_libs=""

# make source path absolute
source_path=`cd "$source_path"; pwd`

@@ -1114,6 +1113,14 @@ for opt do
  ;;
  --enable-gnutls) gnutls="yes"
  ;;
  --disable-nettle) nettle="no"
  ;;
  --enable-nettle) nettle="yes"
  ;;
  --disable-gcrypt) gcrypt="no"
  ;;
  --enable-gcrypt) gcrypt="yes"
  ;;
  --enable-rdma) rdma="yes"
  ;;
  --disable-rdma) rdma="no"
@@ -1324,6 +1331,8 @@ disabled with --disable-FEATURE, default is enabled if available:
  sparse          sparse checker

  gnutls          GNUTLS cryptography support
  nettle          nettle cryptography support
  gcrypt          libgcrypt cryptography support
  sdl             SDL UI
  --with-sdlabi     select preferred SDL ABI 1.2 or 2.0
  gtk             gtk UI
@@ -2254,20 +2263,76 @@ else
    gnutls_hash="no"
fi

if test "$gnutls_gcrypt" != "no"; then
    if has "libgcrypt-config"; then

# If user didn't give a --disable/enable-gcrypt flag,
# then mark as disabled if user requested nettle
# explicitly, or if gnutls links to nettle
if test -z "$gcrypt"
then
    if test "$nettle" = "yes" || test "$gnutls_nettle" = "yes"
    then
        gcrypt="no"
    fi
fi

# If user didn't give a --disable/enable-nettle flag,
# then mark as disabled if user requested gcrypt
# explicitly, or if gnutls links to gcrypt
if test -z "$nettle"
then
    if test "$gcrypt" = "yes" || test "$gnutls_gcrypt" = "yes"
    then
        nettle="no"
    fi
fi

has_libgcrypt_config() {
    if ! has "libgcrypt-config"
    then
	return 1
    fi

    if test -n "$cross_prefix"
    then
	host=`libgcrypt-config --host`
	if test "$host-" != $cross_prefix
	then
	    return 1
	fi
    fi

    return 0
}

if test "$gcrypt" != "no"; then
    if has_libgcrypt_config; then
        gcrypt_cflags=`libgcrypt-config --cflags`
        gcrypt_libs=`libgcrypt-config --libs`
        # Debian has remove -lgpg-error from libgcrypt-config
        # as it "spreads unnecessary dependencies" which in
        # turn breaks static builds...
        if test "$static" = "yes"
        then
            gcrypt_libs="$gcrypt_libs -lgpg-error"
        fi
        libs_softmmu="$gcrypt_libs $libs_softmmu"
        libs_tools="$gcrypt_libs $libs_tools"
        QEMU_CFLAGS="$QEMU_CFLAGS $gcrypt_cflags"
        gcrypt="yes"
        if test -z "$nettle"; then
           nettle="no"
        fi
    else
        if test "$gcrypt" = "yes"; then
            feature_not_found "gcrypt" "Install gcrypt devel"
        else
            gcrypt="no"
        fi
    fi
fi


if test "$gnutls_nettle" != "no"; then
if test "$nettle" != "no"; then
    if $pkg_config --exists "nettle"; then
        nettle_cflags=`$pkg_config --cflags nettle`
        nettle_libs=`$pkg_config --libs nettle`
@@ -2275,20 +2340,30 @@ if test "$gnutls_nettle" != "no"; then
        libs_softmmu="$nettle_libs $libs_softmmu"
        libs_tools="$nettle_libs $libs_tools"
        QEMU_CFLAGS="$QEMU_CFLAGS $nettle_cflags"
        nettle="yes"
    else
        if test "$nettle" = "yes"; then
            feature_not_found "nettle" "Install nettle devel"
        else
            nettle="no"
        fi
    fi
fi

if test "$gcrypt" = "yes" && test "$nettle" = "yes"
then
    error_exit "Only one of gcrypt & nettle can be enabled"
fi

##########################################
# libtasn1 - only for the TLS creds/session test suite

tasn1=yes
tasn1_cflags=""
tasn1_libs=""
if $pkg_config --exists "libtasn1"; then
    tasn1_cflags=`$pkg_config --cflags libtasn1`
    tasn1_libs=`$pkg_config --libs libtasn1`
    test_cflags="$test_cflags $tasn1_cflags"
    test_libs="$test_libs $tasn1_libs"
else
    tasn1=no
fi
@@ -4621,8 +4696,8 @@ echo "GTK support $gtk"
echo "GTK GL support    $gtk_gl"
echo "GNUTLS support    $gnutls"
echo "GNUTLS hash       $gnutls_hash"
echo "GNUTLS gcrypt     $gnutls_gcrypt"
echo "GNUTLS nettle     $gnutls_nettle ${gnutls_nettle+($nettle_version)}"
echo "libgcrypt         $gcrypt"
echo "nettle            $nettle ${nettle+($nettle_version)}"
echo "libtasn1          $tasn1"
echo "VTE support       $vte"
echo "curses support    $curses"
@@ -4991,11 +5066,11 @@ fi
if test "$gnutls_hash" = "yes" ; then
  echo "CONFIG_GNUTLS_HASH=y" >> $config_host_mak
fi
if test "$gnutls_gcrypt" = "yes" ; then
  echo "CONFIG_GNUTLS_GCRYPT=y" >> $config_host_mak
if test "$gcrypt" = "yes" ; then
  echo "CONFIG_GCRYPT=y" >> $config_host_mak
fi
if test "$gnutls_nettle" = "yes" ; then
  echo "CONFIG_GNUTLS_NETTLE=y" >> $config_host_mak
if test "$nettle" = "yes" ; then
  echo "CONFIG_NETTLE=y" >> $config_host_mak
  echo "CONFIG_NETTLE_VERSION_MAJOR=${nettle_version%%.*}" >> $config_host_mak
fi
if test "$tasn1" = "yes" ; then
@@ -5330,8 +5405,8 @@ echo "EXESUF=$EXESUF" >> $config_host_mak
echo "DSOSUF=$DSOSUF" >> $config_host_mak
echo "LDFLAGS_SHARED=$LDFLAGS_SHARED" >> $config_host_mak
echo "LIBS_QGA+=$libs_qga" >> $config_host_mak
echo "TEST_LIBS=$test_libs" >> $config_host_mak
echo "TEST_CFLAGS=$test_cflags" >> $config_host_mak
echo "TASN1_LIBS=$tasn1_libs" >> $config_host_mak
echo "TASN1_CFLAGS=$tasn1_cflags" >> $config_host_mak
echo "POD2MAN=$POD2MAN" >> $config_host_mak
echo "TRANSLATE_OPT_CFLAGS=$TRANSLATE_OPT_CFLAGS" >> $config_host_mak
if test "$gcov" = "yes" ; then
+20 −9
Original line number Diff line number Diff line
@@ -25,8 +25,7 @@ typedef struct QCryptoCipherBuiltinAES QCryptoCipherBuiltinAES;
struct QCryptoCipherBuiltinAES {
    AES_KEY encrypt_key;
    AES_KEY decrypt_key;
    uint8_t *iv;
    size_t niv;
    uint8_t iv[AES_BLOCK_SIZE];
};
typedef struct QCryptoCipherBuiltinDESRFB QCryptoCipherBuiltinDESRFB;
struct QCryptoCipherBuiltinDESRFB {
@@ -40,6 +39,7 @@ struct QCryptoCipherBuiltin {
        QCryptoCipherBuiltinAES aes;
        QCryptoCipherBuiltinDESRFB desrfb;
    } state;
    size_t blocksize;
    void (*free)(QCryptoCipher *cipher);
    int (*setiv)(QCryptoCipher *cipher,
                 const uint8_t *iv, size_t niv,
@@ -61,7 +61,6 @@ static void qcrypto_cipher_free_aes(QCryptoCipher *cipher)
{
    QCryptoCipherBuiltin *ctxt = cipher->opaque;

    g_free(ctxt->state.aes.iv);
    g_free(ctxt);
    cipher->opaque = NULL;
}
@@ -145,15 +144,13 @@ static int qcrypto_cipher_setiv_aes(QCryptoCipher *cipher,
                                     Error **errp)
{
    QCryptoCipherBuiltin *ctxt = cipher->opaque;
    if (niv != 16) {
        error_setg(errp, "IV must be 16 bytes not %zu", niv);
    if (niv != AES_BLOCK_SIZE) {
        error_setg(errp, "IV must be %d bytes not %zu",
                   AES_BLOCK_SIZE, niv);
        return -1;
    }

    g_free(ctxt->state.aes.iv);
    ctxt->state.aes.iv = g_new0(uint8_t, niv);
    memcpy(ctxt->state.aes.iv, iv, niv);
    ctxt->state.aes.niv = niv;
    memcpy(ctxt->state.aes.iv, iv, AES_BLOCK_SIZE);

    return 0;
}
@@ -185,6 +182,7 @@ static int qcrypto_cipher_init_aes(QCryptoCipher *cipher,
        goto error;
    }

    ctxt->blocksize = AES_BLOCK_SIZE;
    ctxt->free = qcrypto_cipher_free_aes;
    ctxt->setiv = qcrypto_cipher_setiv_aes;
    ctxt->encrypt = qcrypto_cipher_encrypt_aes;
@@ -286,6 +284,7 @@ static int qcrypto_cipher_init_des_rfb(QCryptoCipher *cipher,
    memcpy(ctxt->state.desrfb.key, key, nkey);
    ctxt->state.desrfb.nkey = nkey;

    ctxt->blocksize = 8;
    ctxt->free = qcrypto_cipher_free_des_rfb;
    ctxt->setiv = qcrypto_cipher_setiv_des_rfb;
    ctxt->encrypt = qcrypto_cipher_encrypt_des_rfb;
@@ -374,6 +373,12 @@ int qcrypto_cipher_encrypt(QCryptoCipher *cipher,
{
    QCryptoCipherBuiltin *ctxt = cipher->opaque;

    if (len % ctxt->blocksize) {
        error_setg(errp, "Length %zu must be a multiple of block size %zu",
                   len, ctxt->blocksize);
        return -1;
    }

    return ctxt->encrypt(cipher, in, out, len, errp);
}

@@ -386,6 +391,12 @@ int qcrypto_cipher_decrypt(QCryptoCipher *cipher,
{
    QCryptoCipherBuiltin *ctxt = cipher->opaque;

    if (len % ctxt->blocksize) {
        error_setg(errp, "Length %zu must be a multiple of block size %zu",
                   len, ctxt->blocksize);
        return -1;
    }

    return ctxt->decrypt(cipher, in, out, len, errp);
}

+45 −16
Original line number Diff line number Diff line
@@ -34,6 +34,11 @@ bool qcrypto_cipher_supports(QCryptoCipherAlgorithm alg)
    }
}

typedef struct QCryptoCipherGcrypt QCryptoCipherGcrypt;
struct QCryptoCipherGcrypt {
    gcry_cipher_hd_t handle;
    size_t blocksize;
};

QCryptoCipher *qcrypto_cipher_new(QCryptoCipherAlgorithm alg,
                                  QCryptoCipherMode mode,
@@ -41,7 +46,7 @@ QCryptoCipher *qcrypto_cipher_new(QCryptoCipherAlgorithm alg,
                                  Error **errp)
{
    QCryptoCipher *cipher;
    gcry_cipher_hd_t handle;
    QCryptoCipherGcrypt *ctx;
    gcry_error_t err;
    int gcryalg, gcrymode;

@@ -87,7 +92,9 @@ QCryptoCipher *qcrypto_cipher_new(QCryptoCipherAlgorithm alg,
    cipher->alg = alg;
    cipher->mode = mode;

    err = gcry_cipher_open(&handle, gcryalg, gcrymode, 0);
    ctx = g_new0(QCryptoCipherGcrypt, 1);

    err = gcry_cipher_open(&ctx->handle, gcryalg, gcrymode, 0);
    if (err != 0) {
        error_setg(errp, "Cannot initialize cipher: %s",
                   gcry_strerror(err));
@@ -100,10 +107,12 @@ QCryptoCipher *qcrypto_cipher_new(QCryptoCipherAlgorithm alg,
         * bizarre RFB variant of DES :-)
         */
        uint8_t *rfbkey = qcrypto_cipher_munge_des_rfb_key(key, nkey);
        err = gcry_cipher_setkey(handle, rfbkey, nkey);
        err = gcry_cipher_setkey(ctx->handle, rfbkey, nkey);
        g_free(rfbkey);
        ctx->blocksize = 8;
    } else {
        err = gcry_cipher_setkey(handle, key, nkey);
        err = gcry_cipher_setkey(ctx->handle, key, nkey);
        ctx->blocksize = 16;
    }
    if (err != 0) {
        error_setg(errp, "Cannot set key: %s",
@@ -111,11 +120,12 @@ QCryptoCipher *qcrypto_cipher_new(QCryptoCipherAlgorithm alg,
        goto error;
    }

    cipher->opaque = handle;
    cipher->opaque = ctx;
    return cipher;

 error:
    gcry_cipher_close(handle);
    gcry_cipher_close(ctx->handle);
    g_free(ctx);
    g_free(cipher);
    return NULL;
}
@@ -123,12 +133,13 @@ QCryptoCipher *qcrypto_cipher_new(QCryptoCipherAlgorithm alg,

void qcrypto_cipher_free(QCryptoCipher *cipher)
{
    gcry_cipher_hd_t handle;
    QCryptoCipherGcrypt *ctx;
    if (!cipher) {
        return;
    }
    handle = cipher->opaque;
    gcry_cipher_close(handle);
    ctx = cipher->opaque;
    gcry_cipher_close(ctx->handle);
    g_free(ctx);
    g_free(cipher);
}

@@ -139,10 +150,16 @@ int qcrypto_cipher_encrypt(QCryptoCipher *cipher,
                           size_t len,
                           Error **errp)
{
    gcry_cipher_hd_t handle = cipher->opaque;
    QCryptoCipherGcrypt *ctx = cipher->opaque;
    gcry_error_t err;

    err = gcry_cipher_encrypt(handle,
    if (len % ctx->blocksize) {
        error_setg(errp, "Length %zu must be a multiple of block size %zu",
                   len, ctx->blocksize);
        return -1;
    }

    err = gcry_cipher_encrypt(ctx->handle,
                              out, len,
                              in, len);
    if (err != 0) {
@@ -161,10 +178,16 @@ int qcrypto_cipher_decrypt(QCryptoCipher *cipher,
                           size_t len,
                           Error **errp)
{
    gcry_cipher_hd_t handle = cipher->opaque;
    QCryptoCipherGcrypt *ctx = cipher->opaque;
    gcry_error_t err;

    err = gcry_cipher_decrypt(handle,
    if (len % ctx->blocksize) {
        error_setg(errp, "Length %zu must be a multiple of block size %zu",
                   len, ctx->blocksize);
        return -1;
    }

    err = gcry_cipher_decrypt(ctx->handle,
                              out, len,
                              in, len);
    if (err != 0) {
@@ -180,11 +203,17 @@ int qcrypto_cipher_setiv(QCryptoCipher *cipher,
                         const uint8_t *iv, size_t niv,
                         Error **errp)
{
    gcry_cipher_hd_t handle = cipher->opaque;
    QCryptoCipherGcrypt *ctx = cipher->opaque;
    gcry_error_t err;

    gcry_cipher_reset(handle);
    err = gcry_cipher_setiv(handle, iv, niv);
    if (niv != ctx->blocksize) {
        error_setg(errp, "Expected IV size %zu not %zu",
                   ctx->blocksize, niv);
        return -1;
    }

    gcry_cipher_reset(ctx->handle);
    err = gcry_cipher_setiv(ctx->handle, iv, niv);
    if (err != 0) {
        error_setg(errp, "Cannot set IV: %s",
                   gcry_strerror(err));
+20 −8
Original line number Diff line number Diff line
@@ -69,7 +69,7 @@ struct QCryptoCipherNettle {
    nettle_cipher_func *alg_encrypt;
    nettle_cipher_func *alg_decrypt;
    uint8_t *iv;
    size_t niv;
    size_t blocksize;
};

bool qcrypto_cipher_supports(QCryptoCipherAlgorithm alg)
@@ -125,7 +125,7 @@ QCryptoCipher *qcrypto_cipher_new(QCryptoCipherAlgorithm alg,
        ctx->alg_encrypt = des_encrypt_wrapper;
        ctx->alg_decrypt = des_decrypt_wrapper;

        ctx->niv = DES_BLOCK_SIZE;
        ctx->blocksize = DES_BLOCK_SIZE;
        break;

    case QCRYPTO_CIPHER_ALG_AES_128:
@@ -140,14 +140,14 @@ QCryptoCipher *qcrypto_cipher_new(QCryptoCipherAlgorithm alg,
        ctx->alg_encrypt = aes_encrypt_wrapper;
        ctx->alg_decrypt = aes_decrypt_wrapper;

        ctx->niv = AES_BLOCK_SIZE;
        ctx->blocksize = AES_BLOCK_SIZE;
        break;
    default:
        error_setg(errp, "Unsupported cipher algorithm %d", alg);
        goto error;
    }

    ctx->iv = g_new0(uint8_t, ctx->niv);
    ctx->iv = g_new0(uint8_t, ctx->blocksize);
    cipher->opaque = ctx;

    return cipher;
@@ -184,6 +184,12 @@ int qcrypto_cipher_encrypt(QCryptoCipher *cipher,
{
    QCryptoCipherNettle *ctx = cipher->opaque;

    if (len % ctx->blocksize) {
        error_setg(errp, "Length %zu must be a multiple of block size %zu",
                   len, ctx->blocksize);
        return -1;
    }

    switch (cipher->mode) {
    case QCRYPTO_CIPHER_MODE_ECB:
        ctx->alg_encrypt(ctx->ctx_encrypt, len, out, in);
@@ -191,7 +197,7 @@ int qcrypto_cipher_encrypt(QCryptoCipher *cipher,

    case QCRYPTO_CIPHER_MODE_CBC:
        cbc_encrypt(ctx->ctx_encrypt, ctx->alg_encrypt,
                    ctx->niv, ctx->iv,
                    ctx->blocksize, ctx->iv,
                    len, out, in);
        break;
    default:
@@ -211,6 +217,12 @@ int qcrypto_cipher_decrypt(QCryptoCipher *cipher,
{
    QCryptoCipherNettle *ctx = cipher->opaque;

    if (len % ctx->blocksize) {
        error_setg(errp, "Length %zu must be a multiple of block size %zu",
                   len, ctx->blocksize);
        return -1;
    }

    switch (cipher->mode) {
    case QCRYPTO_CIPHER_MODE_ECB:
        ctx->alg_decrypt(ctx->ctx_decrypt ? ctx->ctx_decrypt : ctx->ctx_encrypt,
@@ -219,7 +231,7 @@ int qcrypto_cipher_decrypt(QCryptoCipher *cipher,

    case QCRYPTO_CIPHER_MODE_CBC:
        cbc_decrypt(ctx->ctx_decrypt ? ctx->ctx_decrypt : ctx->ctx_encrypt,
                    ctx->alg_decrypt, ctx->niv, ctx->iv,
                    ctx->alg_decrypt, ctx->blocksize, ctx->iv,
                    len, out, in);
        break;
    default:
@@ -235,9 +247,9 @@ int qcrypto_cipher_setiv(QCryptoCipher *cipher,
                         Error **errp)
{
    QCryptoCipherNettle *ctx = cipher->opaque;
    if (niv != ctx->niv) {
    if (niv != ctx->blocksize) {
        error_setg(errp, "Expected IV size %zu not %zu",
                   ctx->niv, niv);
                   ctx->blocksize, niv);
        return -1;
    }
    memcpy(ctx->iv, iv, niv);
+4 −4
Original line number Diff line number Diff line
@@ -47,7 +47,7 @@ qcrypto_cipher_validate_key_length(QCryptoCipherAlgorithm alg,
    return true;
}

#if defined(CONFIG_GNUTLS_GCRYPT) || defined(CONFIG_GNUTLS_NETTLE)
#if defined(CONFIG_GCRYPT) || defined(CONFIG_NETTLE)
static uint8_t *
qcrypto_cipher_munge_des_rfb_key(const uint8_t *key,
                                 size_t nkey)
@@ -63,11 +63,11 @@ qcrypto_cipher_munge_des_rfb_key(const uint8_t *key,
    }
    return ret;
}
#endif /* CONFIG_GNUTLS_GCRYPT || CONFIG_GNUTLS_NETTLE */
#endif /* CONFIG_GCRYPT || CONFIG_NETTLE */

#ifdef CONFIG_GNUTLS_GCRYPT
#ifdef CONFIG_GCRYPT
#include "crypto/cipher-gcrypt.c"
#elif defined CONFIG_GNUTLS_NETTLE
#elif defined CONFIG_NETTLE
#include "crypto/cipher-nettle.c"
#else
#include "crypto/cipher-builtin.c"
Loading