From f844836ddccf3dbcba142128da5dd8ee618f3e91 Mon Sep 17 00:00:00 2001 From: Gonglei Date: Mon, 26 Sep 2016 17:23:21 +0800 Subject: [PATCH 1/6] crypto: extend mode as a parameter in qcrypto_cipher_supports() It can't guarantee all cipher modes are supported if one cipher algorithm is supported by a backend. Let's extend qcrypto_cipher_supports() to take both the algorithm and mode as parameters. Signed-off-by: Gonglei Signed-off-by: Daniel P. Berrange --- block/qcow.c | 3 ++- block/qcow2.c | 3 ++- crypto/cipher-builtin.c | 14 +++++++++++++- crypto/cipher-gcrypt.c | 13 ++++++++++++- crypto/cipher-nettle.c | 13 ++++++++++++- include/crypto/cipher.h | 6 ++++-- tests/test-crypto-cipher.c | 2 +- ui/vnc.c | 2 +- 8 files changed, 47 insertions(+), 9 deletions(-) diff --git a/block/qcow.c b/block/qcow.c index 94f01b3d0c..7540f43f46 100644 --- a/block/qcow.c +++ b/block/qcow.c @@ -153,7 +153,8 @@ static int qcow_open(BlockDriverState *bs, QDict *options, int flags, ret = -EINVAL; goto fail; } - if (!qcrypto_cipher_supports(QCRYPTO_CIPHER_ALG_AES_128)) { + if (!qcrypto_cipher_supports(QCRYPTO_CIPHER_ALG_AES_128, + QCRYPTO_CIPHER_MODE_CBC)) { error_setg(errp, "AES cipher not available"); ret = -EINVAL; goto fail; diff --git a/block/qcow2.c b/block/qcow2.c index 0e53a4d666..e11c7c9d16 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -959,7 +959,8 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags, ret = -EINVAL; goto fail; } - if (!qcrypto_cipher_supports(QCRYPTO_CIPHER_ALG_AES_128)) { + if (!qcrypto_cipher_supports(QCRYPTO_CIPHER_ALG_AES_128, + QCRYPTO_CIPHER_MODE_CBC)) { error_setg(errp, "AES cipher not available"); ret = -EINVAL; goto fail; diff --git a/crypto/cipher-builtin.c b/crypto/cipher-builtin.c index 9d258428b0..fd59a9e461 100644 --- a/crypto/cipher-builtin.c +++ b/crypto/cipher-builtin.c @@ -400,14 +400,26 @@ static int qcrypto_cipher_init_des_rfb(QCryptoCipher *cipher, } -bool qcrypto_cipher_supports(QCryptoCipherAlgorithm alg) +bool qcrypto_cipher_supports(QCryptoCipherAlgorithm alg, + QCryptoCipherMode mode) { switch (alg) { case QCRYPTO_CIPHER_ALG_DES_RFB: case QCRYPTO_CIPHER_ALG_AES_128: case QCRYPTO_CIPHER_ALG_AES_192: case QCRYPTO_CIPHER_ALG_AES_256: + break; + default: + return false; + } + + switch (mode) { + case QCRYPTO_CIPHER_MODE_ECB: + case QCRYPTO_CIPHER_MODE_CBC: + case QCRYPTO_CIPHER_MODE_XTS: return true; + case QCRYPTO_CIPHER_MODE_CTR: + return false; default: return false; } diff --git a/crypto/cipher-gcrypt.c b/crypto/cipher-gcrypt.c index da3f4c74db..05026c0a0e 100644 --- a/crypto/cipher-gcrypt.c +++ b/crypto/cipher-gcrypt.c @@ -24,7 +24,8 @@ #include -bool qcrypto_cipher_supports(QCryptoCipherAlgorithm alg) +bool qcrypto_cipher_supports(QCryptoCipherAlgorithm alg, + QCryptoCipherMode mode) { switch (alg) { case QCRYPTO_CIPHER_ALG_DES_RFB: @@ -37,6 +38,16 @@ bool qcrypto_cipher_supports(QCryptoCipherAlgorithm alg) case QCRYPTO_CIPHER_ALG_SERPENT_256: case QCRYPTO_CIPHER_ALG_TWOFISH_128: case QCRYPTO_CIPHER_ALG_TWOFISH_256: + break; + default: + return false; + } + + switch (mode) { + case QCRYPTO_CIPHER_MODE_ECB: + case QCRYPTO_CIPHER_MODE_CBC: + case QCRYPTO_CIPHER_MODE_XTS: + case QCRYPTO_CIPHER_MODE_CTR: return true; default: return false; diff --git a/crypto/cipher-nettle.c b/crypto/cipher-nettle.c index 879d831694..72d106922d 100644 --- a/crypto/cipher-nettle.c +++ b/crypto/cipher-nettle.c @@ -191,7 +191,8 @@ struct QCryptoCipherNettle { size_t blocksize; }; -bool qcrypto_cipher_supports(QCryptoCipherAlgorithm alg) +bool qcrypto_cipher_supports(QCryptoCipherAlgorithm alg, + QCryptoCipherMode mode) { switch (alg) { case QCRYPTO_CIPHER_ALG_DES_RFB: @@ -205,6 +206,16 @@ bool qcrypto_cipher_supports(QCryptoCipherAlgorithm alg) case QCRYPTO_CIPHER_ALG_TWOFISH_128: case QCRYPTO_CIPHER_ALG_TWOFISH_192: case QCRYPTO_CIPHER_ALG_TWOFISH_256: + break; + default: + return false; + } + + switch (mode) { + case QCRYPTO_CIPHER_MODE_ECB: + case QCRYPTO_CIPHER_MODE_CBC: + case QCRYPTO_CIPHER_MODE_XTS: + case QCRYPTO_CIPHER_MODE_CTR: return true; default: return false; diff --git a/include/crypto/cipher.h b/include/crypto/cipher.h index 376654dcdd..97638e7bbf 100644 --- a/include/crypto/cipher.h +++ b/include/crypto/cipher.h @@ -85,13 +85,15 @@ struct QCryptoCipher { /** * qcrypto_cipher_supports: * @alg: the cipher algorithm + * @mode: the cipher mode * - * Determine if @alg cipher algorithm is supported by the + * Determine if @alg cipher algorithm in @mode is supported by the * current configured build * * Returns: true if the algorithm is supported, false otherwise */ -bool qcrypto_cipher_supports(QCryptoCipherAlgorithm alg); +bool qcrypto_cipher_supports(QCryptoCipherAlgorithm alg, + QCryptoCipherMode mode); /** * qcrypto_cipher_get_block_len: diff --git a/tests/test-crypto-cipher.c b/tests/test-crypto-cipher.c index b89dfa2b65..84929789d9 100644 --- a/tests/test-crypto-cipher.c +++ b/tests/test-crypto-cipher.c @@ -616,7 +616,7 @@ int main(int argc, char **argv) g_assert(qcrypto_init(NULL) == 0); for (i = 0; i < G_N_ELEMENTS(test_data); i++) { - if (qcrypto_cipher_supports(test_data[i].alg)) { + if (qcrypto_cipher_supports(test_data[i].alg, test_data[i].mode)) { g_test_add_data_func(test_data[i].path, &test_data[i], test_cipher); } } diff --git a/ui/vnc.c b/ui/vnc.c index c1e98fb6bf..1bedc95b57 100644 --- a/ui/vnc.c +++ b/ui/vnc.c @@ -3606,7 +3606,7 @@ void vnc_display_open(const char *id, Error **errp) goto fail; } if (!qcrypto_cipher_supports( - QCRYPTO_CIPHER_ALG_DES_RFB)) { + QCRYPTO_CIPHER_ALG_DES_RFB, QCRYPTO_CIPHER_MODE_ECB)) { error_setg(errp, "Cipher backend does not support DES RFB algorithm"); goto fail; From 3c28292f390f642bbb3dba0949ecf36aaf7be0d6 Mon Sep 17 00:00:00 2001 From: Gonglei Date: Mon, 26 Sep 2016 17:23:22 +0800 Subject: [PATCH 2/6] crypto: add CTR mode support Introduce CTR mode support for the cipher APIs. CTR mode uses a counter rather than a traditional IV. The counter has additional properties, including a nonce and initial counter block. We reuse the ctx->iv as the counter for conveniences. Both libgcrypt and nettle are support CTR mode, the cipher-builtin doesn't support yet. Signed-off-by: Gonglei Signed-off-by: Daniel P. Berrange --- crypto/cipher-gcrypt.c | 25 ++++++++++++----- crypto/cipher-nettle.c | 15 ++++++++++- crypto/cipher.c | 1 + include/crypto/cipher.h | 6 ++--- qapi/crypto.json | 3 ++- tests/test-crypto-cipher.c | 55 ++++++++++++++++++++++++++++++++++++++ 6 files changed, 94 insertions(+), 11 deletions(-) diff --git a/crypto/cipher-gcrypt.c b/crypto/cipher-gcrypt.c index 05026c0a0e..c550db9008 100644 --- a/crypto/cipher-gcrypt.c +++ b/crypto/cipher-gcrypt.c @@ -59,6 +59,7 @@ struct QCryptoCipherGcrypt { gcry_cipher_hd_t handle; gcry_cipher_hd_t tweakhandle; size_t blocksize; + /* Initialization vector or Counter */ uint8_t *iv; }; @@ -80,6 +81,9 @@ QCryptoCipher *qcrypto_cipher_new(QCryptoCipherAlgorithm alg, case QCRYPTO_CIPHER_MODE_CBC: gcrymode = GCRY_CIPHER_MODE_CBC; break; + case QCRYPTO_CIPHER_MODE_CTR: + gcrymode = GCRY_CIPHER_MODE_CTR; + break; default: error_setg(errp, "Unsupported cipher mode %s", QCryptoCipherMode_lookup[mode]); @@ -350,12 +354,21 @@ int qcrypto_cipher_setiv(QCryptoCipher *cipher, if (ctx->iv) { memcpy(ctx->iv, iv, niv); } else { - 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)); - return -1; + if (cipher->mode == QCRYPTO_CIPHER_MODE_CTR) { + err = gcry_cipher_setctr(ctx->handle, iv, niv); + if (err != 0) { + error_setg(errp, "Cannot set Counter: %s", + gcry_strerror(err)); + return -1; + } + } else { + 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)); + return -1; + } } } diff --git a/crypto/cipher-nettle.c b/crypto/cipher-nettle.c index 72d106922d..cd094cd6a5 100644 --- a/crypto/cipher-nettle.c +++ b/crypto/cipher-nettle.c @@ -28,6 +28,7 @@ #include #include #include +#include typedef void (*QCryptoCipherNettleFuncWrapper)(const void *ctx, size_t length, @@ -186,7 +187,7 @@ struct QCryptoCipherNettle { QCryptoCipherNettleFuncNative alg_decrypt_native; QCryptoCipherNettleFuncWrapper alg_encrypt_wrapper; QCryptoCipherNettleFuncWrapper alg_decrypt_wrapper; - + /* Initialization vector or Counter */ uint8_t *iv; size_t blocksize; }; @@ -236,6 +237,7 @@ QCryptoCipher *qcrypto_cipher_new(QCryptoCipherAlgorithm alg, case QCRYPTO_CIPHER_MODE_ECB: case QCRYPTO_CIPHER_MODE_CBC: case QCRYPTO_CIPHER_MODE_XTS: + case QCRYPTO_CIPHER_MODE_CTR: break; default: error_setg(errp, "Unsupported cipher mode %s", @@ -441,6 +443,12 @@ int qcrypto_cipher_encrypt(QCryptoCipher *cipher, ctx->iv, len, out, in); break; + case QCRYPTO_CIPHER_MODE_CTR: + ctr_crypt(ctx->ctx, ctx->alg_encrypt_native, + ctx->blocksize, ctx->iv, + len, out, in); + break; + default: error_setg(errp, "Unsupported cipher mode %s", QCryptoCipherMode_lookup[cipher->mode]); @@ -480,6 +488,11 @@ int qcrypto_cipher_decrypt(QCryptoCipher *cipher, ctx->alg_encrypt_wrapper, ctx->alg_decrypt_wrapper, ctx->iv, len, out, in); break; + case QCRYPTO_CIPHER_MODE_CTR: + ctr_crypt(ctx->ctx, ctx->alg_encrypt_native, + ctx->blocksize, ctx->iv, + len, out, in); + break; default: error_setg(errp, "Unsupported cipher mode %s", diff --git a/crypto/cipher.c b/crypto/cipher.c index cafb454363..a9bca41302 100644 --- a/crypto/cipher.c +++ b/crypto/cipher.c @@ -55,6 +55,7 @@ static bool mode_need_iv[QCRYPTO_CIPHER_MODE__MAX] = { [QCRYPTO_CIPHER_MODE_ECB] = false, [QCRYPTO_CIPHER_MODE_CBC] = true, [QCRYPTO_CIPHER_MODE_XTS] = true, + [QCRYPTO_CIPHER_MODE_CTR] = true, }; diff --git a/include/crypto/cipher.h b/include/crypto/cipher.h index 97638e7bbf..bec9f412b0 100644 --- a/include/crypto/cipher.h +++ b/include/crypto/cipher.h @@ -215,16 +215,16 @@ int qcrypto_cipher_decrypt(QCryptoCipher *cipher, /** * qcrypto_cipher_setiv: * @cipher: the cipher object - * @iv: the initialization vector bytes + * @iv: the initialization vector or counter (CTR mode) bytes * @niv: the length of @iv * @errpr: pointer to a NULL-initialized error object * * If the @cipher object is setup to use a mode that requires - * initialization vectors, this sets the initialization vector + * initialization vectors or counter, this sets the @niv * bytes. The @iv data should have the same length as the * cipher key used when originally constructing the cipher * object. It is an error to set an initialization vector - * if the cipher mode does not require one. + * or counter if the cipher mode does not require one. * * Returns: 0 on success, -1 on error */ diff --git a/qapi/crypto.json b/qapi/crypto.json index 6933b13bd0..5c9d7d4a36 100644 --- a/qapi/crypto.json +++ b/qapi/crypto.json @@ -89,11 +89,12 @@ # @ecb: Electronic Code Book # @cbc: Cipher Block Chaining # @xts: XEX with tweaked code book and ciphertext stealing +# @ctr: Counter (Since 2.8) # Since: 2.6 ## { 'enum': 'QCryptoCipherMode', 'prefix': 'QCRYPTO_CIPHER_MODE', - 'data': ['ecb', 'cbc', 'xts']} + 'data': ['ecb', 'cbc', 'xts', 'ctr']} ## diff --git a/tests/test-crypto-cipher.c b/tests/test-crypto-cipher.c index 84929789d9..5d9e535e2e 100644 --- a/tests/test-crypto-cipher.c +++ b/tests/test-crypto-cipher.c @@ -380,6 +380,61 @@ static QCryptoCipherTestData test_data[] = { .key = "27182818284590452353602874713526" "31415926535897932384626433832795", + }, + { + /* NIST F.5.1 CTR-AES128.Encrypt */ + .path = "/crypto/cipher/aes-ctr-128", + .alg = QCRYPTO_CIPHER_ALG_AES_128, + .mode = QCRYPTO_CIPHER_MODE_CTR, + .key = "2b7e151628aed2a6abf7158809cf4f3c", + .iv = "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff", + .plaintext = + "6bc1bee22e409f96e93d7e117393172a" + "ae2d8a571e03ac9c9eb76fac45af8e51" + "30c81c46a35ce411e5fbc1191a0a52ef" + "f69f2445df4f9b17ad2b417be66c3710", + .ciphertext = + "874d6191b620e3261bef6864990db6ce" + "9806f66b7970fdff8617187bb9fffdff" + "5ae4df3edbd5d35e5b4f09020db03eab" + "1e031dda2fbe03d1792170a0f3009cee", + }, + { + /* NIST F.5.3 CTR-AES192.Encrypt */ + .path = "/crypto/cipher/aes-ctr-192", + .alg = QCRYPTO_CIPHER_ALG_AES_192, + .mode = QCRYPTO_CIPHER_MODE_CTR, + .key = "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b", + .iv = "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff", + .plaintext = + "6bc1bee22e409f96e93d7e117393172a" + "ae2d8a571e03ac9c9eb76fac45af8e51" + "30c81c46a35ce411e5fbc1191a0a52ef" + "f69f2445df4f9b17ad2b417be66c3710", + .ciphertext = + "1abc932417521ca24f2b0459fe7e6e0b" + "090339ec0aa6faefd5ccc2c6f4ce8e94" + "1e36b26bd1ebc670d1bd1d665620abf7" + "4f78a7f6d29809585a97daec58c6b050", + }, + { + /* NIST F.5.5 CTR-AES256.Encrypt */ + .path = "/crypto/cipher/aes-ctr-256", + .alg = QCRYPTO_CIPHER_ALG_AES_256, + .mode = QCRYPTO_CIPHER_MODE_CTR, + .key = "603deb1015ca71be2b73aef0857d7781" + "1f352c073b6108d72d9810a30914dff4", + .iv = "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff", + .plaintext = + "6bc1bee22e409f96e93d7e117393172a" + "ae2d8a571e03ac9c9eb76fac45af8e51" + "30c81c46a35ce411e5fbc1191a0a52ef" + "f69f2445df4f9b17ad2b417be66c3710", + .ciphertext = + "601ec313775789a5b7a7f504bbf3d228" + "f443e3ca4d62b59aca84e990cacaf5c5" + "2b0930daa23de94ce87017ba2d84988d" + "dfc9c58db67aada613c2dd08457941a6", } }; From 77cf26cd89c6e6947fe856a079061cebaecd5435 Mon Sep 17 00:00:00 2001 From: Gonglei Date: Mon, 26 Sep 2016 17:23:23 +0800 Subject: [PATCH 3/6] crypto: add mode check in qcrypto_cipher_new() for cipher-builtin Signed-off-by: Gonglei Signed-off-by: Daniel P. Berrange --- crypto/cipher-builtin.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/crypto/cipher-builtin.c b/crypto/cipher-builtin.c index fd59a9e461..b4bc2b9ca6 100644 --- a/crypto/cipher-builtin.c +++ b/crypto/cipher-builtin.c @@ -433,6 +433,17 @@ QCryptoCipher *qcrypto_cipher_new(QCryptoCipherAlgorithm alg, { QCryptoCipher *cipher; + switch (mode) { + case QCRYPTO_CIPHER_MODE_ECB: + case QCRYPTO_CIPHER_MODE_CBC: + case QCRYPTO_CIPHER_MODE_XTS: + break; + default: + error_setg(errp, "Unsupported cipher mode %s", + QCryptoCipherMode_lookup[mode]); + return NULL; + } + cipher = g_new0(QCryptoCipher, 1); cipher->alg = alg; cipher->mode = mode; From 48b95ea4f0933c13d778c0478cb82bbfdd515981 Mon Sep 17 00:00:00 2001 From: Gonglei Date: Sat, 24 Sep 2016 08:36:19 +0800 Subject: [PATCH 4/6] qtest: fix make check complaint in crypto module MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CC tests/test-crypto-tlscredsx509.o CC tests/crypto-tls-x509-helpers.o CC tests/pkix_asn1_tab.o tests/pkix_asn1_tab.c:7:22: warning: libtasn1.h: No such file or directory tests/pkix_asn1_tab.c:9: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘pkix_asn1_tab’ make: *** [tests/pkix_asn1_tab.o] Error 1 Signed-off-by: Gonglei Signed-off-by: Daniel P. Berrange --- tests/pkix_asn1_tab.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/pkix_asn1_tab.c b/tests/pkix_asn1_tab.c index 903bc02518..f15fc515cb 100644 --- a/tests/pkix_asn1_tab.c +++ b/tests/pkix_asn1_tab.c @@ -4,7 +4,9 @@ */ #include "qemu/osdep.h" -#include +#include "tests/crypto-tls-x509-helpers.h" + +#ifdef QCRYPTO_HAVE_TLS_TEST_SUPPORT const ASN1_ARRAY_TYPE pkix_asn1_tab[] = { {"PKIX1", 536875024, 0}, @@ -1103,3 +1105,4 @@ const ASN1_ARRAY_TYPE pkix_asn1_tab[] = { {0, 1048586, "2"}, {0, 0, 0} }; +#endif /* QCRYPTO_HAVE_TLS_TEST_SUPPORT */ From d26d6b5d34f825c452f9bf3c9d5126181b10f25b Mon Sep 17 00:00:00 2001 From: "Daniel P. Berrange" Date: Thu, 29 Sep 2016 12:43:35 +0100 Subject: [PATCH 5/6] crypto: fix initialization of crypto in tests The test-io-channel-tls test was missing a call to qcrypto_init and test-crypto-hash was initializing it multiple times, Reviewed-by: Eric Blake Signed-off-by: Daniel P. Berrange --- tests/test-crypto-hash.c | 12 ++---------- tests/test-io-channel-tls.c | 3 +++ 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/tests/test-crypto-hash.c b/tests/test-crypto-hash.c index 42fc77a107..214a9f72c3 100644 --- a/tests/test-crypto-hash.c +++ b/tests/test-crypto-hash.c @@ -89,8 +89,6 @@ static void test_hash_alloc(void) { size_t i; - g_assert(qcrypto_init(NULL) == 0); - for (i = 0; i < G_N_ELEMENTS(expected_outputs) ; i++) { uint8_t *result = NULL; size_t resultlen = 0; @@ -123,8 +121,6 @@ static void test_hash_prealloc(void) { size_t i; - g_assert(qcrypto_init(NULL) == 0); - for (i = 0; i < G_N_ELEMENTS(expected_outputs) ; i++) { uint8_t *result; size_t resultlen; @@ -161,8 +157,6 @@ static void test_hash_iov(void) { size_t i; - g_assert(qcrypto_init(NULL) == 0); - for (i = 0; i < G_N_ELEMENTS(expected_outputs) ; i++) { struct iovec iov[3] = { { .iov_base = (char *)INPUT_TEXT1, .iov_len = strlen(INPUT_TEXT1) }, @@ -199,8 +193,6 @@ static void test_hash_digest(void) { size_t i; - g_assert(qcrypto_init(NULL) == 0); - for (i = 0; i < G_N_ELEMENTS(expected_outputs) ; i++) { int ret; char *digest; @@ -230,8 +222,6 @@ static void test_hash_base64(void) { size_t i; - g_assert(qcrypto_init(NULL) == 0); - for (i = 0; i < G_N_ELEMENTS(expected_outputs) ; i++) { int ret; char *digest; @@ -253,6 +243,8 @@ static void test_hash_base64(void) int main(int argc, char **argv) { + g_assert(qcrypto_init(NULL) == 0); + g_test_init(&argc, &argv, NULL); g_test_add_func("/crypto/hash/iov", test_hash_iov); g_test_add_func("/crypto/hash/alloc", test_hash_alloc); diff --git a/tests/test-io-channel-tls.c b/tests/test-io-channel-tls.c index 3c361a7bef..bd3ae2bf7a 100644 --- a/tests/test-io-channel-tls.c +++ b/tests/test-io-channel-tls.c @@ -27,6 +27,7 @@ #include "io/channel-tls.h" #include "io/channel-socket.h" #include "io-channel-helpers.h" +#include "crypto/init.h" #include "crypto/tlscredsx509.h" #include "qemu/acl.h" #include "qom/object_interfaces.h" @@ -265,6 +266,8 @@ int main(int argc, char **argv) { int ret; + g_assert(qcrypto_init(NULL) == 0); + module_call_init(MODULE_INIT_QOM); g_test_init(&argc, &argv, NULL); setenv("GNUTLS_FORCE_FIPS_MODE", "2", 1); From 373166636b9f07c60d7c32610bd346acf7d143e9 Mon Sep 17 00:00:00 2001 From: "Daniel P. Berrange" Date: Mon, 10 Oct 2016 12:17:50 +0100 Subject: [PATCH 6/6] crypto: fix initialization of gcrypt threading The gcrypt threads implementation must be set before calling any other gcrypt APIs, especially gcry_check_version(), since that triggers initialization of the random pool. After that is initialized, changes to the threads impl won't be honoured by the random pool code. This means that gcrypt will think thread locking is needed and so try to acquire the random pool mutex, but this is NULL as no threads impl was set originally. This results in a crash in the random pool code. For the same reasons, we must set the gcrypt threads impl before calling gnutls_init, since that will also trigger gcry_check_version Reviewed-by: Eric Blake Signed-off-by: Daniel P. Berrange --- crypto/init.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/crypto/init.c b/crypto/init.c index 16e099b489..f65207e57d 100644 --- a/crypto/init.c +++ b/crypto/init.c @@ -119,6 +119,10 @@ static struct gcry_thread_cbs qcrypto_gcrypt_thread_impl = { int qcrypto_init(Error **errp) { +#ifdef QCRYPTO_INIT_GCRYPT_THREADS + gcry_control(GCRYCTL_SET_THREAD_CBS, &qcrypto_gcrypt_thread_impl); +#endif /* QCRYPTO_INIT_GCRYPT_THREADS */ + #ifdef CONFIG_GNUTLS int ret; ret = gnutls_global_init(); @@ -139,9 +143,6 @@ int qcrypto_init(Error **errp) error_setg(errp, "Unable to initialize gcrypt"); return -1; } -#ifdef QCRYPTO_INIT_GCRYPT_THREADS - gcry_control(GCRYCTL_SET_THREAD_CBS, &qcrypto_gcrypt_thread_impl); -#endif /* QCRYPTO_INIT_GCRYPT_THREADS */ gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0); #endif