aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crypto/cipher-builtin.c.inc132
-rw-r--r--crypto/cipher-gcrypt.c.inc143
-rw-r--r--crypto/cipher-gnutls.c.inc335
-rw-r--r--crypto/cipher-nettle.c.inc26
-rw-r--r--crypto/cipher.c30
-rw-r--r--crypto/desrfb.c416
-rw-r--r--crypto/hash-gnutls.c104
-rw-r--r--crypto/hmac-gnutls.c139
-rw-r--r--crypto/init.c62
-rw-r--r--crypto/meson.build12
-rw-r--r--crypto/pbkdf-gnutls.c90
-rw-r--r--docs/system/cpu-models-x86.rst.inc2
-rw-r--r--hw/net/rocker/rocker.h11
-rw-r--r--io/channel-websock.c10
-rw-r--r--meson.build102
-rw-r--r--qapi/crypto.json4
-rw-r--r--qemu-options.hx41
-rw-r--r--softmmu/qemu-seccomp.c6
-rw-r--r--tests/migration/guestperf/engine.py2
-rw-r--r--tests/unit/test-crypto-cipher.c31
-rw-r--r--tests/unit/test-crypto-hash.c13
-rw-r--r--tests/unit/test-crypto-hmac.c28
-rw-r--r--tests/unit/test-crypto-ivgen.c14
-rw-r--r--tests/unit/test-crypto-pbkdf.c5
-rw-r--r--ui/vnc.c20
25 files changed, 865 insertions, 913 deletions
diff --git a/crypto/cipher-builtin.c.inc b/crypto/cipher-builtin.c.inc
index 7597cf4..b409089 100644
--- a/crypto/cipher-builtin.c.inc
+++ b/crypto/cipher-builtin.c.inc
@@ -19,8 +19,6 @@
*/
#include "crypto/aes.h"
-#include "crypto/desrfb.h"
-#include "crypto/xts.h"
typedef struct QCryptoCipherBuiltinAESContext QCryptoCipherBuiltinAESContext;
struct QCryptoCipherBuiltinAESContext {
@@ -32,7 +30,6 @@ typedef struct QCryptoCipherBuiltinAES QCryptoCipherBuiltinAES;
struct QCryptoCipherBuiltinAES {
QCryptoCipher base;
QCryptoCipherBuiltinAESContext key;
- QCryptoCipherBuiltinAESContext key_tweak;
uint8_t iv[AES_BLOCK_SIZE];
};
@@ -194,39 +191,6 @@ static int qcrypto_cipher_aes_decrypt_cbc(QCryptoCipher *cipher,
return 0;
}
-static int qcrypto_cipher_aes_encrypt_xts(QCryptoCipher *cipher,
- const void *in, void *out,
- size_t len, Error **errp)
-{
- QCryptoCipherBuiltinAES *ctx
- = container_of(cipher, QCryptoCipherBuiltinAES, base);
-
- if (!qcrypto_length_check(len, AES_BLOCK_SIZE, errp)) {
- return -1;
- }
- xts_encrypt(&ctx->key, &ctx->key_tweak,
- do_aes_encrypt_ecb, do_aes_decrypt_ecb,
- ctx->iv, len, out, in);
- return 0;
-}
-
-static int qcrypto_cipher_aes_decrypt_xts(QCryptoCipher *cipher,
- const void *in, void *out,
- size_t len, Error **errp)
-{
- QCryptoCipherBuiltinAES *ctx
- = container_of(cipher, QCryptoCipherBuiltinAES, base);
-
- if (!qcrypto_length_check(len, AES_BLOCK_SIZE, errp)) {
- return -1;
- }
- xts_decrypt(&ctx->key, &ctx->key_tweak,
- do_aes_encrypt_ecb, do_aes_decrypt_ecb,
- ctx->iv, len, out, in);
- return 0;
-}
-
-
static int qcrypto_cipher_aes_setiv(QCryptoCipher *cipher, const uint8_t *iv,
size_t niv, Error **errp)
{
@@ -257,84 +221,16 @@ static const struct QCryptoCipherDriver qcrypto_cipher_aes_driver_cbc = {
.cipher_free = qcrypto_cipher_ctx_free,
};
-static const struct QCryptoCipherDriver qcrypto_cipher_aes_driver_xts = {
- .cipher_encrypt = qcrypto_cipher_aes_encrypt_xts,
- .cipher_decrypt = qcrypto_cipher_aes_decrypt_xts,
- .cipher_setiv = qcrypto_cipher_aes_setiv,
- .cipher_free = qcrypto_cipher_ctx_free,
-};
-
-
-typedef struct QCryptoCipherBuiltinDESRFB QCryptoCipherBuiltinDESRFB;
-struct QCryptoCipherBuiltinDESRFB {
- QCryptoCipher base;
-
- /* C.f. alg_key_len[QCRYPTO_CIPHER_ALG_DES_RFB] */
- uint8_t key[8];
-};
-
-static int qcrypto_cipher_encrypt_des_rfb(QCryptoCipher *cipher,
- const void *in, void *out,
- size_t len, Error **errp)
-{
- QCryptoCipherBuiltinDESRFB *ctx
- = container_of(cipher, QCryptoCipherBuiltinDESRFB, base);
- size_t i;
-
- if (!qcrypto_length_check(len, 8, errp)) {
- return -1;
- }
-
- deskey(ctx->key, EN0);
-
- for (i = 0; i < len; i += 8) {
- des((void *)in + i, out + i);
- }
-
- return 0;
-}
-
-static int qcrypto_cipher_decrypt_des_rfb(QCryptoCipher *cipher,
- const void *in, void *out,
- size_t len, Error **errp)
-{
- QCryptoCipherBuiltinDESRFB *ctx
- = container_of(cipher, QCryptoCipherBuiltinDESRFB, base);
- size_t i;
-
- if (!qcrypto_length_check(len, 8, errp)) {
- return -1;
- }
-
- deskey(ctx->key, DE1);
-
- for (i = 0; i < len; i += 8) {
- des((void *)in + i, out + i);
- }
-
- return 0;
-}
-
-static const struct QCryptoCipherDriver qcrypto_cipher_des_rfb_driver = {
- .cipher_encrypt = qcrypto_cipher_encrypt_des_rfb,
- .cipher_decrypt = qcrypto_cipher_decrypt_des_rfb,
- .cipher_setiv = qcrypto_cipher_no_setiv,
- .cipher_free = qcrypto_cipher_ctx_free,
-};
-
bool qcrypto_cipher_supports(QCryptoCipherAlgorithm alg,
QCryptoCipherMode mode)
{
switch (alg) {
- case QCRYPTO_CIPHER_ALG_DES_RFB:
- return mode == QCRYPTO_CIPHER_MODE_ECB;
case QCRYPTO_CIPHER_ALG_AES_128:
case QCRYPTO_CIPHER_ALG_AES_192:
case QCRYPTO_CIPHER_ALG_AES_256:
switch (mode) {
case QCRYPTO_CIPHER_MODE_ECB:
case QCRYPTO_CIPHER_MODE_CBC:
- case QCRYPTO_CIPHER_MODE_XTS:
return true;
default:
return false;
@@ -356,18 +252,6 @@ static QCryptoCipher *qcrypto_cipher_ctx_new(QCryptoCipherAlgorithm alg,
}
switch (alg) {
- case QCRYPTO_CIPHER_ALG_DES_RFB:
- if (mode == QCRYPTO_CIPHER_MODE_ECB) {
- QCryptoCipherBuiltinDESRFB *ctx;
-
- ctx = g_new0(QCryptoCipherBuiltinDESRFB, 1);
- ctx->base.driver = &qcrypto_cipher_des_rfb_driver;
- memcpy(ctx->key, key, sizeof(ctx->key));
-
- return &ctx->base;
- }
- goto bad_mode;
-
case QCRYPTO_CIPHER_ALG_AES_128:
case QCRYPTO_CIPHER_ALG_AES_192:
case QCRYPTO_CIPHER_ALG_AES_256:
@@ -382,9 +266,6 @@ static QCryptoCipher *qcrypto_cipher_ctx_new(QCryptoCipherAlgorithm alg,
case QCRYPTO_CIPHER_MODE_CBC:
drv = &qcrypto_cipher_aes_driver_cbc;
break;
- case QCRYPTO_CIPHER_MODE_XTS:
- drv = &qcrypto_cipher_aes_driver_xts;
- break;
default:
goto bad_mode;
}
@@ -392,19 +273,6 @@ static QCryptoCipher *qcrypto_cipher_ctx_new(QCryptoCipherAlgorithm alg,
ctx = g_new0(QCryptoCipherBuiltinAES, 1);
ctx->base.driver = drv;
- if (mode == QCRYPTO_CIPHER_MODE_XTS) {
- nkey /= 2;
- if (AES_set_encrypt_key(key + nkey, nkey * 8,
- &ctx->key_tweak.enc)) {
- error_setg(errp, "Failed to set encryption key");
- goto error;
- }
- if (AES_set_decrypt_key(key + nkey, nkey * 8,
- &ctx->key_tweak.dec)) {
- error_setg(errp, "Failed to set decryption key");
- goto error;
- }
- }
if (AES_set_encrypt_key(key, nkey * 8, &ctx->key.enc)) {
error_setg(errp, "Failed to set encryption key");
goto error;
diff --git a/crypto/cipher-gcrypt.c.inc b/crypto/cipher-gcrypt.c.inc
index 42d4137..a6a0117 100644
--- a/crypto/cipher-gcrypt.c.inc
+++ b/crypto/cipher-gcrypt.c.inc
@@ -18,17 +18,13 @@
*
*/
-#ifdef CONFIG_QEMU_PRIVATE_XTS
-#include "crypto/xts.h"
-#endif
-
#include <gcrypt.h>
bool qcrypto_cipher_supports(QCryptoCipherAlgorithm alg,
QCryptoCipherMode mode)
{
switch (alg) {
- case QCRYPTO_CIPHER_ALG_DES_RFB:
+ case QCRYPTO_CIPHER_ALG_DES:
case QCRYPTO_CIPHER_ALG_3DES:
case QCRYPTO_CIPHER_ALG_AES_128:
case QCRYPTO_CIPHER_ALG_AES_192:
@@ -59,10 +55,6 @@ typedef struct QCryptoCipherGcrypt {
QCryptoCipher base;
gcry_cipher_hd_t handle;
size_t blocksize;
-#ifdef CONFIG_QEMU_PRIVATE_XTS
- gcry_cipher_hd_t tweakhandle;
- uint8_t iv[XTS_BLOCK_SIZE];
-#endif
} QCryptoCipherGcrypt;
@@ -178,90 +170,6 @@ static const struct QCryptoCipherDriver qcrypto_gcrypt_ctr_driver = {
.cipher_free = qcrypto_gcrypt_ctx_free,
};
-#ifdef CONFIG_QEMU_PRIVATE_XTS
-static void qcrypto_gcrypt_xts_ctx_free(QCryptoCipher *cipher)
-{
- QCryptoCipherGcrypt *ctx = container_of(cipher, QCryptoCipherGcrypt, base);
-
- gcry_cipher_close(ctx->tweakhandle);
- qcrypto_gcrypt_ctx_free(cipher);
-}
-
-static void qcrypto_gcrypt_xts_wrape(const void *ctx, size_t length,
- uint8_t *dst, const uint8_t *src)
-{
- gcry_error_t err;
- err = gcry_cipher_encrypt((gcry_cipher_hd_t)ctx, dst, length, src, length);
- g_assert(err == 0);
-}
-
-static void qcrypto_gcrypt_xts_wrapd(const void *ctx, size_t length,
- uint8_t *dst, const uint8_t *src)
-{
- gcry_error_t err;
- err = gcry_cipher_decrypt((gcry_cipher_hd_t)ctx, dst, length, src, length);
- g_assert(err == 0);
-}
-
-static int qcrypto_gcrypt_xts_encrypt(QCryptoCipher *cipher, const void *in,
- void *out, size_t len, Error **errp)
-{
- QCryptoCipherGcrypt *ctx = container_of(cipher, QCryptoCipherGcrypt, base);
-
- if (len & (ctx->blocksize - 1)) {
- error_setg(errp, "Length %zu must be a multiple of block size %zu",
- len, ctx->blocksize);
- return -1;
- }
-
- xts_encrypt(ctx->handle, ctx->tweakhandle,
- qcrypto_gcrypt_xts_wrape, qcrypto_gcrypt_xts_wrapd,
- ctx->iv, len, out, in);
- return 0;
-}
-
-static int qcrypto_gcrypt_xts_decrypt(QCryptoCipher *cipher, const void *in,
- void *out, size_t len, Error **errp)
-{
- QCryptoCipherGcrypt *ctx = container_of(cipher, QCryptoCipherGcrypt, base);
-
- if (len & (ctx->blocksize - 1)) {
- error_setg(errp, "Length %zu must be a multiple of block size %zu",
- len, ctx->blocksize);
- return -1;
- }
-
- xts_decrypt(ctx->handle, ctx->tweakhandle,
- qcrypto_gcrypt_xts_wrape, qcrypto_gcrypt_xts_wrapd,
- ctx->iv, len, out, in);
- return 0;
-}
-
-static int qcrypto_gcrypt_xts_setiv(QCryptoCipher *cipher,
- const uint8_t *iv, size_t niv,
- Error **errp)
-{
- QCryptoCipherGcrypt *ctx = container_of(cipher, QCryptoCipherGcrypt, base);
-
- if (niv != ctx->blocksize) {
- error_setg(errp, "Expected IV size %zu not %zu",
- ctx->blocksize, niv);
- return -1;
- }
-
- memcpy(ctx->iv, iv, niv);
- return 0;
-}
-
-static const struct QCryptoCipherDriver qcrypto_gcrypt_xts_driver = {
- .cipher_encrypt = qcrypto_gcrypt_xts_encrypt,
- .cipher_decrypt = qcrypto_gcrypt_xts_decrypt,
- .cipher_setiv = qcrypto_gcrypt_xts_setiv,
- .cipher_free = qcrypto_gcrypt_xts_ctx_free,
-};
-#endif /* CONFIG_QEMU_PRIVATE_XTS */
-
-
static QCryptoCipher *qcrypto_cipher_ctx_new(QCryptoCipherAlgorithm alg,
QCryptoCipherMode mode,
const uint8_t *key,
@@ -278,7 +186,7 @@ static QCryptoCipher *qcrypto_cipher_ctx_new(QCryptoCipherAlgorithm alg,
}
switch (alg) {
- case QCRYPTO_CIPHER_ALG_DES_RFB:
+ case QCRYPTO_CIPHER_ALG_DES:
gcryalg = GCRY_CIPHER_DES;
break;
case QCRYPTO_CIPHER_ALG_3DES:
@@ -323,12 +231,7 @@ static QCryptoCipher *qcrypto_cipher_ctx_new(QCryptoCipherAlgorithm alg,
gcrymode = GCRY_CIPHER_MODE_ECB;
break;
case QCRYPTO_CIPHER_MODE_XTS:
-#ifdef CONFIG_QEMU_PRIVATE_XTS
- drv = &qcrypto_gcrypt_xts_driver;
- gcrymode = GCRY_CIPHER_MODE_ECB;
-#else
gcrymode = GCRY_CIPHER_MODE_XTS;
-#endif
break;
case QCRYPTO_CIPHER_MODE_CBC:
gcrymode = GCRY_CIPHER_MODE_CBC;
@@ -354,44 +257,7 @@ static QCryptoCipher *qcrypto_cipher_ctx_new(QCryptoCipherAlgorithm alg,
}
ctx->blocksize = gcry_cipher_get_algo_blklen(gcryalg);
-#ifdef CONFIG_QEMU_PRIVATE_XTS
- if (mode == QCRYPTO_CIPHER_MODE_XTS) {
- if (ctx->blocksize != XTS_BLOCK_SIZE) {
- error_setg(errp,
- "Cipher block size %zu must equal XTS block size %d",
- ctx->blocksize, XTS_BLOCK_SIZE);
- goto error;
- }
- err = gcry_cipher_open(&ctx->tweakhandle, gcryalg, gcrymode, 0);
- if (err != 0) {
- error_setg(errp, "Cannot initialize cipher: %s",
- gcry_strerror(err));
- goto error;
- }
- }
-#endif
-
- if (alg == QCRYPTO_CIPHER_ALG_DES_RFB) {
- /* We're using standard DES cipher from gcrypt, so we need
- * to munge the key so that the results are the same as the
- * bizarre RFB variant of DES :-)
- */
- uint8_t *rfbkey = qcrypto_cipher_munge_des_rfb_key(key, nkey);
- err = gcry_cipher_setkey(ctx->handle, rfbkey, nkey);
- g_free(rfbkey);
- } else {
-#ifdef CONFIG_QEMU_PRIVATE_XTS
- if (mode == QCRYPTO_CIPHER_MODE_XTS) {
- nkey /= 2;
- err = gcry_cipher_setkey(ctx->tweakhandle, key + nkey, nkey);
- if (err != 0) {
- error_setg(errp, "Cannot set key: %s", gcry_strerror(err));
- goto error;
- }
- }
-#endif
- err = gcry_cipher_setkey(ctx->handle, key, nkey);
- }
+ err = gcry_cipher_setkey(ctx->handle, key, nkey);
if (err != 0) {
error_setg(errp, "Cannot set key: %s", gcry_strerror(err));
goto error;
@@ -400,9 +266,6 @@ static QCryptoCipher *qcrypto_cipher_ctx_new(QCryptoCipherAlgorithm alg,
return &ctx->base;
error:
-#ifdef CONFIG_QEMU_PRIVATE_XTS
- gcry_cipher_close(ctx->tweakhandle);
-#endif
gcry_cipher_close(ctx->handle);
g_free(ctx);
return NULL;
diff --git a/crypto/cipher-gnutls.c.inc b/crypto/cipher-gnutls.c.inc
new file mode 100644
index 0000000..501e4e0
--- /dev/null
+++ b/crypto/cipher-gnutls.c.inc
@@ -0,0 +1,335 @@
+/*
+ * QEMU Crypto cipher gnutls algorithms
+ *
+ * Copyright (c) 2021 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "cipherpriv.h"
+
+#include <gnutls/crypto.h>
+
+#if GNUTLS_VERSION_NUMBER >= 0x030608
+#define QEMU_GNUTLS_XTS
+#endif
+
+bool qcrypto_cipher_supports(QCryptoCipherAlgorithm alg,
+ QCryptoCipherMode mode)
+{
+
+ switch (mode) {
+ case QCRYPTO_CIPHER_MODE_ECB:
+ case QCRYPTO_CIPHER_MODE_CBC:
+ switch (alg) {
+ case QCRYPTO_CIPHER_ALG_AES_128:
+ case QCRYPTO_CIPHER_ALG_AES_192:
+ case QCRYPTO_CIPHER_ALG_AES_256:
+ case QCRYPTO_CIPHER_ALG_DES:
+ case QCRYPTO_CIPHER_ALG_3DES:
+ return true;
+ default:
+ return false;
+ }
+#ifdef QEMU_GNUTLS_XTS
+ case QCRYPTO_CIPHER_MODE_XTS:
+ switch (alg) {
+ case QCRYPTO_CIPHER_ALG_AES_128:
+ case QCRYPTO_CIPHER_ALG_AES_256:
+ return true;
+ default:
+ return false;
+ }
+#endif
+ default:
+ return false;
+ }
+}
+
+typedef struct QCryptoCipherGnutls QCryptoCipherGnutls;
+struct QCryptoCipherGnutls {
+ QCryptoCipher base;
+ gnutls_cipher_hd_t handle; /* XTS & CBC mode */
+ gnutls_cipher_algorithm_t galg; /* ECB mode */
+ guint8 *key; /* ECB mode */
+ size_t nkey; /* ECB mode */
+ size_t blocksize;
+};
+
+
+static void
+qcrypto_gnutls_cipher_free(QCryptoCipher *cipher)
+{
+ QCryptoCipherGnutls *ctx = container_of(cipher, QCryptoCipherGnutls, base);
+
+ g_free(ctx->key);
+ if (ctx->handle) {
+ gnutls_cipher_deinit(ctx->handle);
+ }
+ g_free(ctx);
+}
+
+
+static int
+qcrypto_gnutls_cipher_encrypt(QCryptoCipher *cipher,
+ const void *in,
+ void *out,
+ size_t len,
+ Error **errp)
+{
+ QCryptoCipherGnutls *ctx = container_of(cipher, QCryptoCipherGnutls, base);
+ int err;
+
+ if (len % ctx->blocksize) {
+ error_setg(errp, "Length %zu must be a multiple of block size %zu",
+ len, ctx->blocksize);
+ return -1;
+ }
+
+ if (ctx->handle) { /* CBC / XTS mode */
+ err = gnutls_cipher_encrypt2(ctx->handle,
+ in, len,
+ out, len);
+ if (err != 0) {
+ error_setg(errp, "Cannot encrypt data: %s",
+ gnutls_strerror(err));
+ return -1;
+ }
+ } else { /* ECB mode very inefficiently faked with CBC */
+ g_autofree unsigned char *iv = g_new0(unsigned char, ctx->blocksize);
+ while (len) {
+ gnutls_cipher_hd_t handle;
+ gnutls_datum_t gkey = { (unsigned char *)ctx->key, ctx->nkey };
+ int err = gnutls_cipher_init(&handle, ctx->galg, &gkey, NULL);
+ if (err != 0) {
+ error_setg(errp, "Cannot initialize cipher: %s",
+ gnutls_strerror(err));
+ return -1;
+ }
+
+ gnutls_cipher_set_iv(handle, iv, ctx->blocksize);
+
+ err = gnutls_cipher_encrypt2(handle,
+ in, ctx->blocksize,
+ out, ctx->blocksize);
+ if (err != 0) {
+ gnutls_cipher_deinit(handle);
+ error_setg(errp, "Cannot encrypt data: %s",
+ gnutls_strerror(err));
+ return -1;
+ }
+ gnutls_cipher_deinit(handle);
+
+ len -= ctx->blocksize;
+ in += ctx->blocksize;
+ out += ctx->blocksize;
+ }
+ }
+
+ return 0;
+}
+
+
+static int
+qcrypto_gnutls_cipher_decrypt(QCryptoCipher *cipher,
+ const void *in,
+ void *out,
+ size_t len,
+ Error **errp)
+{
+ QCryptoCipherGnutls *ctx = container_of(cipher, QCryptoCipherGnutls, base);
+ int err;
+
+ if (len % ctx->blocksize) {
+ error_setg(errp, "Length %zu must be a multiple of block size %zu",
+ len, ctx->blocksize);
+ return -1;
+ }
+
+ if (ctx->handle) { /* CBC / XTS mode */
+ err = gnutls_cipher_decrypt2(ctx->handle,
+ in, len,
+ out, len);
+
+ if (err != 0) {
+ error_setg(errp, "Cannot decrypt data: %s",
+ gnutls_strerror(err));
+ return -1;
+ }
+ } else { /* ECB mode very inefficiently faked with CBC */
+ g_autofree unsigned char *iv = g_new0(unsigned char, ctx->blocksize);
+ while (len) {
+ gnutls_cipher_hd_t handle;
+ gnutls_datum_t gkey = { (unsigned char *)ctx->key, ctx->nkey };
+ int err = gnutls_cipher_init(&handle, ctx->galg, &gkey, NULL);
+ if (err != 0) {
+ error_setg(errp, "Cannot initialize cipher: %s",
+ gnutls_strerror(err));
+ return -1;
+ }
+
+ gnutls_cipher_set_iv(handle, iv, ctx->blocksize);
+
+ err = gnutls_cipher_decrypt2(handle,
+ in, ctx->blocksize,
+ out, ctx->blocksize);
+ if (err != 0) {
+ gnutls_cipher_deinit(handle);
+ error_setg(errp, "Cannot encrypt data: %s",
+ gnutls_strerror(err));
+ return -1;
+ }
+ gnutls_cipher_deinit(handle);
+
+ len -= ctx->blocksize;
+ in += ctx->blocksize;
+ out += ctx->blocksize;
+ }
+ }
+
+ return 0;
+}
+
+static int
+qcrypto_gnutls_cipher_setiv(QCryptoCipher *cipher,
+ const uint8_t *iv, size_t niv,
+ Error **errp)
+{
+ QCryptoCipherGnutls *ctx = container_of(cipher, QCryptoCipherGnutls, base);
+
+ if (niv != ctx->blocksize) {
+ error_setg(errp, "Expected IV size %zu not %zu",
+ ctx->blocksize, niv);
+ return -1;
+ }
+
+ gnutls_cipher_set_iv(ctx->handle, (unsigned char *)iv, niv);
+
+ return 0;
+}
+
+
+static struct QCryptoCipherDriver gnutls_driver = {
+ .cipher_encrypt = qcrypto_gnutls_cipher_encrypt,
+ .cipher_decrypt = qcrypto_gnutls_cipher_decrypt,
+ .cipher_setiv = qcrypto_gnutls_cipher_setiv,
+ .cipher_free = qcrypto_gnutls_cipher_free,
+};
+
+static QCryptoCipher *qcrypto_cipher_ctx_new(QCryptoCipherAlgorithm alg,
+ QCryptoCipherMode mode,
+ const uint8_t *key,
+ size_t nkey,
+ Error **errp)
+{
+ QCryptoCipherGnutls *ctx;
+ gnutls_datum_t gkey = { (unsigned char *)key, nkey };
+ gnutls_cipher_algorithm_t galg = GNUTLS_CIPHER_UNKNOWN;
+ int err;
+
+ switch (mode) {
+#ifdef QEMU_GNUTLS_XTS
+ case QCRYPTO_CIPHER_MODE_XTS:
+ switch (alg) {
+ case QCRYPTO_CIPHER_ALG_AES_128:
+ galg = GNUTLS_CIPHER_AES_128_XTS;
+ break;
+ case QCRYPTO_CIPHER_ALG_AES_256:
+ galg = GNUTLS_CIPHER_AES_256_XTS;
+ break;
+ default:
+ break;
+ }
+ break;
+#endif
+
+ case QCRYPTO_CIPHER_MODE_ECB:
+ case QCRYPTO_CIPHER_MODE_CBC:
+ switch (alg) {
+ case QCRYPTO_CIPHER_ALG_AES_128:
+ galg = GNUTLS_CIPHER_AES_128_CBC;
+ break;
+ case QCRYPTO_CIPHER_ALG_AES_192:
+ galg = GNUTLS_CIPHER_AES_192_CBC;
+ break;
+ case QCRYPTO_CIPHER_ALG_AES_256:
+ galg = GNUTLS_CIPHER_AES_256_CBC;
+ break;
+ case QCRYPTO_CIPHER_ALG_DES:
+ galg = GNUTLS_CIPHER_DES_CBC;
+ break;
+ case QCRYPTO_CIPHER_ALG_3DES:
+ galg = GNUTLS_CIPHER_3DES_CBC;
+ break;
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+
+ if (galg == GNUTLS_CIPHER_UNKNOWN) {
+ error_setg(errp, "Unsupported cipher algorithm %s with %s mode",
+ QCryptoCipherAlgorithm_str(alg),
+ QCryptoCipherMode_str(mode));
+ return NULL;
+ }
+
+ if (!qcrypto_cipher_validate_key_length(alg, mode, nkey, errp)) {
+ return NULL;
+ }
+
+ ctx = g_new0(QCryptoCipherGnutls, 1);
+ ctx->base.driver = &gnutls_driver;
+
+ if (mode == QCRYPTO_CIPHER_MODE_ECB) {
+ ctx->key = g_new0(guint8, nkey);
+ memcpy(ctx->key, key, nkey);
+ ctx->nkey = nkey;
+ ctx->galg = galg;
+ } else {
+ err = gnutls_cipher_init(&ctx->handle, galg, &gkey, NULL);
+ if (err != 0) {
+ error_setg(errp, "Cannot initialize cipher: %s",
+ gnutls_strerror(err));
+ goto error;
+ }
+ }
+
+ if (alg == QCRYPTO_CIPHER_ALG_DES ||
+ alg == QCRYPTO_CIPHER_ALG_3DES)
+ ctx->blocksize = 8;
+ else
+ ctx->blocksize = 16;
+
+ /*
+ * Our API contract for requires iv to be optional
+ * but nettle gets unhappy when called by gnutls
+ * in this case, so we just force set a default
+ * all-zeros IV, to match behaviour of other backends.
+ */
+ if (mode != QCRYPTO_CIPHER_MODE_ECB) {
+ g_autofree unsigned char *iv = g_new0(unsigned char, ctx->blocksize);
+ gnutls_cipher_set_iv(ctx->handle, iv, ctx->blocksize);
+ }
+
+ return &ctx->base;
+
+ error:
+ qcrypto_gnutls_cipher_free(&ctx->base);
+ return NULL;
+}
diff --git a/crypto/cipher-nettle.c.inc b/crypto/cipher-nettle.c.inc
index fc6f40c..24cc61f 100644
--- a/crypto/cipher-nettle.c.inc
+++ b/crypto/cipher-nettle.c.inc
@@ -235,11 +235,11 @@ static const struct QCryptoCipherDriver NAME##_driver_xts = { \
DEFINE_XTS(NAME, TYPE, BLEN, ENCRYPT, DECRYPT)
-typedef struct QCryptoNettleDESRFB {
+typedef struct QCryptoNettleDES {
QCryptoCipher base;
struct des_ctx key;
uint8_t iv[DES_BLOCK_SIZE];
-} QCryptoNettleDESRFB;
+} QCryptoNettleDES;
static void des_encrypt_native(const void *ctx, size_t length,
uint8_t *dst, const uint8_t *src)
@@ -253,7 +253,7 @@ static void des_decrypt_native(const void *ctx, size_t length,
des_decrypt(ctx, length, dst, src);
}
-DEFINE_ECB_CBC_CTR(qcrypto_nettle_des_rfb, QCryptoNettleDESRFB,
+DEFINE_ECB_CBC_CTR(qcrypto_nettle_des, QCryptoNettleDES,
DES_BLOCK_SIZE, des_encrypt_native, des_decrypt_native)
@@ -431,7 +431,7 @@ bool qcrypto_cipher_supports(QCryptoCipherAlgorithm alg,
QCryptoCipherMode mode)
{
switch (alg) {
- case QCRYPTO_CIPHER_ALG_DES_RFB:
+ case QCRYPTO_CIPHER_ALG_DES:
case QCRYPTO_CIPHER_ALG_3DES:
case QCRYPTO_CIPHER_ALG_AES_128:
case QCRYPTO_CIPHER_ALG_AES_192:
@@ -480,32 +480,28 @@ static QCryptoCipher *qcrypto_cipher_ctx_new(QCryptoCipherAlgorithm alg,
}
switch (alg) {
- case QCRYPTO_CIPHER_ALG_DES_RFB:
+ case QCRYPTO_CIPHER_ALG_DES:
{
- QCryptoNettleDESRFB *ctx;
+ QCryptoNettleDES *ctx;
const QCryptoCipherDriver *drv;
- uint8_t *rfbkey;
switch (mode) {
case QCRYPTO_CIPHER_MODE_ECB:
- drv = &qcrypto_nettle_des_rfb_driver_ecb;
+ drv = &qcrypto_nettle_des_driver_ecb;
break;
case QCRYPTO_CIPHER_MODE_CBC:
- drv = &qcrypto_nettle_des_rfb_driver_cbc;
+ drv = &qcrypto_nettle_des_driver_cbc;
break;
case QCRYPTO_CIPHER_MODE_CTR:
- drv = &qcrypto_nettle_des_rfb_driver_ctr;
+ drv = &qcrypto_nettle_des_driver_ctr;
break;
default:
goto bad_cipher_mode;
}
- ctx = g_new0(QCryptoNettleDESRFB, 1);
+ ctx = g_new0(QCryptoNettleDES, 1);
ctx->base.driver = drv;
-
- rfbkey = qcrypto_cipher_munge_des_rfb_key(key, nkey);
- des_set_key(&ctx->key, rfbkey);
- g_free(rfbkey);
+ des_set_key(&ctx->key, key);
return &ctx->base;
}
diff --git a/crypto/cipher.c b/crypto/cipher.c
index 068b2fb..74b09a5 100644
--- a/crypto/cipher.c
+++ b/crypto/cipher.c
@@ -29,7 +29,7 @@ static const size_t alg_key_len[QCRYPTO_CIPHER_ALG__MAX] = {
[QCRYPTO_CIPHER_ALG_AES_128] = 16,
[QCRYPTO_CIPHER_ALG_AES_192] = 24,
[QCRYPTO_CIPHER_ALG_AES_256] = 32,
- [QCRYPTO_CIPHER_ALG_DES_RFB] = 8,
+ [QCRYPTO_CIPHER_ALG_DES] = 8,
[QCRYPTO_CIPHER_ALG_3DES] = 24,
[QCRYPTO_CIPHER_ALG_CAST5_128] = 16,
[QCRYPTO_CIPHER_ALG_SERPENT_128] = 16,
@@ -44,7 +44,7 @@ static const size_t alg_block_len[QCRYPTO_CIPHER_ALG__MAX] = {
[QCRYPTO_CIPHER_ALG_AES_128] = 16,
[QCRYPTO_CIPHER_ALG_AES_192] = 16,
[QCRYPTO_CIPHER_ALG_AES_256] = 16,
- [QCRYPTO_CIPHER_ALG_DES_RFB] = 8,
+ [QCRYPTO_CIPHER_ALG_DES] = 8,
[QCRYPTO_CIPHER_ALG_3DES] = 8,
[QCRYPTO_CIPHER_ALG_CAST5_128] = 8,
[QCRYPTO_CIPHER_ALG_SERPENT_128] = 16,
@@ -107,9 +107,9 @@ qcrypto_cipher_validate_key_length(QCryptoCipherAlgorithm alg,
}
if (mode == QCRYPTO_CIPHER_MODE_XTS) {
- if (alg == QCRYPTO_CIPHER_ALG_DES_RFB
- || alg == QCRYPTO_CIPHER_ALG_3DES) {
- error_setg(errp, "XTS mode not compatible with DES-RFB/3DES");
+ if (alg == QCRYPTO_CIPHER_ALG_DES ||
+ alg == QCRYPTO_CIPHER_ALG_3DES) {
+ error_setg(errp, "XTS mode not compatible with DES/3DES");
return false;
}
if (nkey % 2) {
@@ -132,28 +132,12 @@ qcrypto_cipher_validate_key_length(QCryptoCipherAlgorithm alg,
return true;
}
-#if defined(CONFIG_GCRYPT) || defined(CONFIG_NETTLE)
-static uint8_t *
-qcrypto_cipher_munge_des_rfb_key(const uint8_t *key,
- size_t nkey)
-{
- uint8_t *ret = g_new0(uint8_t, nkey);
- size_t i;
- for (i = 0; i < nkey; i++) {
- uint8_t r = key[i];
- r = (r & 0xf0) >> 4 | (r & 0x0f) << 4;
- r = (r & 0xcc) >> 2 | (r & 0x33) << 2;
- r = (r & 0xaa) >> 1 | (r & 0x55) << 1;
- ret[i] = r;
- }
- return ret;
-}
-#endif /* CONFIG_GCRYPT || CONFIG_NETTLE */
-
#ifdef CONFIG_GCRYPT
#include "cipher-gcrypt.c.inc"
#elif defined CONFIG_NETTLE
#include "cipher-nettle.c.inc"
+#elif defined CONFIG_GNUTLS_CRYPTO
+#include "cipher-gnutls.c.inc"
#else
#include "cipher-builtin.c.inc"
#endif
diff --git a/crypto/desrfb.c b/crypto/desrfb.c
deleted file mode 100644
index b2a105e..0000000
--- a/crypto/desrfb.c
+++ /dev/null
@@ -1,416 +0,0 @@
-/*
- * This is D3DES (V5.09) by Richard Outerbridge with the double and
- * triple-length support removed for use in VNC. Also the bytebit[] array
- * has been reversed so that the most significant bit in each byte of the
- * key is ignored, not the least significant.
- *
- * These changes are:
- * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- */
-
-/* D3DES (V5.09) -
- *
- * A portable, public domain, version of the Data Encryption Standard.
- *
- * Written with Symantec's THINK (Lightspeed) C by Richard Outerbridge.
- * Thanks to: Dan Hoey for his excellent Initial and Inverse permutation
- * code; Jim Gillogly & Phil Karn for the DES key schedule code; Dennis
- * Ferguson, Eric Young and Dana How for comparing notes; and Ray Lau,
- * for humouring me on.
- *
- * Copyright (c) 1988,1989,1990,1991,1992 by Richard Outerbridge.
- * (GEnie : OUTER; CIS : [71755,204]) Graven Imagery, 1992.
- */
-
-#include "qemu/osdep.h"
-#include "crypto/desrfb.h"
-
-static void scrunch(unsigned char *, unsigned long *);
-static void unscrun(unsigned long *, unsigned char *);
-static void desfunc(unsigned long *, unsigned long *);
-static void cookey(unsigned long *);
-
-static unsigned long KnL[32] = { 0L };
-
-static const unsigned short bytebit[8] = {
- 01, 02, 04, 010, 020, 040, 0100, 0200 };
-
-static const unsigned long bigbyte[24] = {
- 0x800000L, 0x400000L, 0x200000L, 0x100000L,
- 0x80000L, 0x40000L, 0x20000L, 0x10000L,
- 0x8000L, 0x4000L, 0x2000L, 0x1000L,
- 0x800L, 0x400L, 0x200L, 0x100L,
- 0x80L, 0x40L, 0x20L, 0x10L,
- 0x8L, 0x4L, 0x2L, 0x1L };
-
-/* Use the key schedule specified in the Standard (ANSI X3.92-1981). */
-
-static const unsigned char pc1[56] = {
- 56, 48, 40, 32, 24, 16, 8, 0, 57, 49, 41, 33, 25, 17,
- 9, 1, 58, 50, 42, 34, 26, 18, 10, 2, 59, 51, 43, 35,
- 62, 54, 46, 38, 30, 22, 14, 6, 61, 53, 45, 37, 29, 21,
- 13, 5, 60, 52, 44, 36, 28, 20, 12, 4, 27, 19, 11, 3 };
-
-static const unsigned char totrot[16] = {
- 1, 2, 4, 6, 8, 10, 12, 14, 15, 17, 19, 21, 23, 25, 27, 28 };
-
-static const unsigned char pc2[48] = {
- 13, 16, 10, 23, 0, 4, 2, 27, 14, 5, 20, 9,
- 22, 18, 11, 3, 25, 7, 15, 6, 26, 19, 12, 1,
- 40, 51, 30, 36, 46, 54, 29, 39, 50, 44, 32, 47,
- 43, 48, 38, 55, 33, 52, 45, 41, 49, 35, 28, 31 };
-
-/* Thanks to James Gillogly & Phil Karn! */
-void deskey(unsigned char *key, int edf)
-{
- register int i, j, l, m, n;
- unsigned char pc1m[56], pcr[56];
- unsigned long kn[32];
-
- for ( j = 0; j < 56; j++ ) {
- l = pc1[j];
- m = l & 07;
- pc1m[j] = (key[l >> 3] & bytebit[m]) ? 1 : 0;
- }
- for( i = 0; i < 16; i++ ) {
- if( edf == DE1 ) m = (15 - i) << 1;
- else m = i << 1;
- n = m + 1;
- kn[m] = kn[n] = 0L;
- for( j = 0; j < 28; j++ ) {
- l = j + totrot[i];
- if( l < 28 ) pcr[j] = pc1m[l];
- else pcr[j] = pc1m[l - 28];
- }
- for( j = 28; j < 56; j++ ) {
- l = j + totrot[i];
- if( l < 56 ) pcr[j] = pc1m[l];
- else pcr[j] = pc1m[l - 28];
- }
- for( j = 0; j < 24; j++ ) {
- if( pcr[pc2[j]] ) kn[m] |= bigbyte[j];
- if( pcr[pc2[j + 24]] ) kn[n] |= bigbyte[j];
- }
- }
- cookey(kn);
- return;
- }
-
-static void cookey(register unsigned long *raw1)
-{
- register unsigned long *cook, *raw0;
- unsigned long dough[32];
- register int i;
-
- cook = dough;
- for( i = 0; i < 16; i++, raw1++ ) {
- raw0 = raw1++;
- *cook = (*raw0 & 0x00fc0000L) << 6;
- *cook |= (*raw0 & 0x00000fc0L) << 10;
- *cook |= (*raw1 & 0x00fc0000L) >> 10;
- *cook++ |= (*raw1 & 0x00000fc0L) >> 6;
- *cook = (*raw0 & 0x0003f000L) << 12;
- *cook |= (*raw0 & 0x0000003fL) << 16;
- *cook |= (*raw1 & 0x0003f000L) >> 4;
- *cook++ |= (*raw1 & 0x0000003fL);
- }
- usekey(dough);
- return;
- }
-
-void usekey(register unsigned long *from)
-{
- register unsigned long *to, *endp;
-
- to = KnL, endp = &KnL[32];
- while( to < endp ) *to++ = *from++;
- return;
- }
-
-void des(unsigned char *inblock, unsigned char *outblock)
-{
- unsigned long work[2];
-
- scrunch(inblock, work);
- desfunc(work, KnL);
- unscrun(work, outblock);
- return;
- }
-
-static void scrunch(register unsigned char *outof, register unsigned long *into)
-{
- *into = (*outof++ & 0xffL) << 24;
- *into |= (*outof++ & 0xffL) << 16;
- *into |= (*outof++ & 0xffL) << 8;
- *into++ |= (*outof++ & 0xffL);
- *into = (*outof++ & 0xffL) << 24;
- *into |= (*outof++ & 0xffL) << 16;
- *into |= (*outof++ & 0xffL) << 8;
- *into |= (*outof & 0xffL);
- return;
- }
-
-static void unscrun(register unsigned long *outof, register unsigned char *into)
-{
- *into++ = (unsigned char)((*outof >> 24) & 0xffL);
- *into++ = (unsigned char)((*outof >> 16) & 0xffL);
- *into++ = (unsigned char)((*outof >> 8) & 0xffL);
- *into++ = (unsigned char)(*outof++ & 0xffL);
- *into++ = (unsigned char)((*outof >> 24) & 0xffL);
- *into++ = (unsigned char)((*outof >> 16) & 0xffL);
- *into++ = (unsigned char)((*outof >> 8) & 0xffL);
- *into = (unsigned char)(*outof & 0xffL);
- return;
- }
-
-static const unsigned long SP1[64] = {
- 0x01010400L, 0x00000000L, 0x00010000L, 0x01010404L,
- 0x01010004L, 0x00010404L, 0x00000004L, 0x00010000L,
- 0x00000400L, 0x01010400L, 0x01010404L, 0x00000400L,
- 0x01000404L, 0x01010004L, 0x01000000L, 0x00000004L,
- 0x00000404L, 0x01000400L, 0x01000400L, 0x00010400L,
- 0x00010400L, 0x01010000L, 0x01010000L, 0x01000404L,
- 0x00010004L, 0x01000004L, 0x01000004L, 0x00010004L,
- 0x00000000L, 0x00000404L, 0x00010404L, 0x01000000L,
- 0x00010000L, 0x01010404L, 0x00000004L, 0x01010000L,
- 0x01010400L, 0x01000000L, 0x01000000L, 0x00000400L,
- 0x01010004L, 0x00010000L, 0x00010400L, 0x01000004L,
- 0x00000400L, 0x00000004L, 0x01000404L, 0x00010404L,
- 0x01010404L, 0x00010004L, 0x01010000L, 0x01000404L,
- 0x01000004L, 0x00000404L, 0x00010404L, 0x01010400L,
- 0x00000404L, 0x01000400L, 0x01000400L, 0x00000000L,
- 0x00010004L, 0x00010400L, 0x00000000L, 0x01010004L };
-
-static const unsigned long SP2[64] = {
- 0x80108020L, 0x80008000L, 0x00008000L, 0x00108020L,
- 0x00100000L, 0x00000020L, 0x80100020L, 0x80008020L,
- 0x80000020L, 0x80108020L, 0x80108000L, 0x80000000L,
- 0x80008000L, 0x00100000L, 0x00000020L, 0x80100020L,
- 0x00108000L, 0x00100020L, 0x80008020L, 0x00000000L,
- 0x80000000L, 0x00008000L, 0x00108020L, 0x80100000L,
- 0x00100020L, 0x80000020L, 0x00000000L, 0x00108000L,
- 0x00008020L, 0x80108000L, 0x80100000L, 0x00008020L,
- 0x00000000L, 0x00108020L, 0x80100020L, 0x00100000L,
- 0x80008020L, 0x80100000L, 0x80108000L, 0x00008000L,
- 0x80100000L, 0x80008000L, 0x00000020L, 0x80108020L,
- 0x00108020L, 0x00000020L, 0x00008000L, 0x80000000L,
- 0x00008020L, 0x80108000L, 0x00100000L, 0x80000020L,
- 0x00100020L, 0x80008020L, 0x80000020L, 0x00100020L,
- 0x00108000L, 0x00000000L, 0x80008000L, 0x00008020L,
- 0x80000000L, 0x80100020L, 0x80108020L, 0x00108000L };
-
-static const unsigned long SP3[64] = {
- 0x00000208L, 0x08020200L, 0x00000000L, 0x08020008L,
- 0x08000200L, 0x00000000L, 0x00020208L, 0x08000200L,
- 0x00020008L, 0x08000008L, 0x08000008L, 0x00020000L,
- 0x08020208L, 0x00020008L, 0x08020000L, 0x00000208L,
- 0x08000000L, 0x00000008L, 0x08020200L, 0x00000200L,
- 0x00020200L, 0x08020000L, 0x08020008L, 0x00020208L,
- 0x08000208L, 0x00020200L, 0x00020000L, 0x08000208L,
- 0x00000008L, 0x08020208L, 0x00000200L, 0x08000000L,
- 0x08020200L, 0x08000000L, 0x00020008L, 0x00000208L,
- 0x00020000L, 0x08020200L, 0x08000200L, 0x00000000L,
- 0x00000200L, 0x00020008L, 0x08020208L, 0x08000200L,
- 0x08000008L, 0x00000200L, 0x00000000L, 0x08020008L,
- 0x08000208L, 0x00020000L, 0x08000000L, 0x08020208L,
- 0x00000008L, 0x00020208L, 0x00020200L, 0x08000008L,
- 0x08020000L, 0x08000208L, 0x00000208L, 0x08020000L,
- 0x00020208L, 0x00000008L, 0x08020008L, 0x00020200L };
-
-static const unsigned long SP4[64] = {
- 0x00802001L, 0x00002081L, 0x00002081L, 0x00000080L,
- 0x00802080L, 0x00800081L, 0x00800001L, 0x00002001L,
- 0x00000000L, 0x00802000L, 0x00802000L, 0x00802081L,
- 0x00000081L, 0x00000000L, 0x00800080L, 0x00800001L,
- 0x00000001L, 0x00002000L, 0x00800000L, 0x00802001L,
- 0x00000080L, 0x00800000L, 0x00002001L, 0x00002080L,
- 0x00800081L, 0x00000001L, 0x00002080L, 0x00800080L,
- 0x00002000L, 0x00802080L, 0x00802081L, 0x00000081L,
- 0x00800080L, 0x00800001L, 0x00802000L, 0x00802081L,
- 0x00000081L, 0x00000000L, 0x00000000L, 0x00802000L,
- 0x00002080L, 0x00800080L, 0x00800081L, 0x00000001L,
- 0x00802001L, 0x00002081L, 0x00002081L, 0x00000080L,
- 0x00802081L, 0x00000081L, 0x00000001L, 0x00002000L,
- 0x00800001L, 0x00002001L, 0x00802080L, 0x00800081L,
- 0x00002001L, 0x00002080L, 0x00800000L, 0x00802001L,
- 0x00000080L, 0x00800000L, 0x00002000L, 0x00802080L };
-
-static const unsigned long SP5[64] = {
- 0x00000100L, 0x02080100L, 0x02080000L, 0x42000100L,
- 0x00080000L, 0x00000100L, 0x40000000L, 0x02080000L,
- 0x40080100L, 0x00080000L, 0x02000100L, 0x40080100L,
- 0x42000100L, 0x42080000L, 0x00080100L, 0x40000000L,
- 0x02000000L, 0x40080000L, 0x40080000L, 0x00000000L,
- 0x40000100L, 0x42080100L, 0x42080100L, 0x02000100L,
- 0x42080000L, 0x40000100L, 0x00000000L, 0x42000000L,
- 0x02080100L, 0x02000000L, 0x42000000L, 0x00080100L,
- 0x00080000L, 0x42000100L, 0x00000100L, 0x02000000L,
- 0x40000000L, 0x02080000L, 0x42000100L, 0x40080100L,
- 0x02000100L, 0x40000000L, 0x42080000L, 0x02080100L,
- 0x40080100L, 0x00000100L, 0x02000000L, 0x42080000L,
- 0x42080100L, 0x00080100L, 0x42000000L, 0x42080100L,
- 0x02080000L, 0x00000000L, 0x40080000L, 0x42000000L,
- 0x00080100L, 0x02000100L, 0x40000100L, 0x00080000L,
- 0x00000000L, 0x40080000L, 0x02080100L, 0x40000100L };
-
-static const unsigned long SP6[64] = {
- 0x20000010L, 0x20400000L, 0x00004000L, 0x20404010L,
- 0x20400000L, 0x00000010L, 0x20404010L, 0x00400000L,
- 0x20004000L, 0x00404010L, 0x00400000L, 0x20000010L,
- 0x00400010L, 0x20004000L, 0x20000000L, 0x00004010L,
- 0x00000000L, 0x00400010L, 0x20004010L, 0x00004000L,
- 0x00404000L, 0x20004010L, 0x00000010L, 0x20400010L,
- 0x20400010L, 0x00000000L, 0x00404010L, 0x20404000L,
- 0x00004010L, 0x00404000L, 0x20404000L, 0x20000000L,
- 0x20004000L, 0x00000010L, 0x20400010L, 0x00404000L,
- 0x20404010L, 0x00400000L, 0x00004010L, 0x20000010L,
- 0x00400000L, 0x20004000L, 0x20000000L, 0x00004010L,
- 0x20000010L, 0x20404010L, 0x00404000L, 0x20400000L,
- 0x00404010L, 0x20404000L, 0x00000000L, 0x20400010L,
- 0x00000010L, 0x00004000L, 0x20400000L, 0x00404010L,
- 0x00004000L, 0x00400010L, 0x20004010L, 0x00000000L,
- 0x20404000L, 0x20000000L, 0x00400010L, 0x20004010L };
-
-static const unsigned long SP7[64] = {
- 0x00200000L, 0x04200002L, 0x04000802L, 0x00000000L,
- 0x00000800L, 0x04000802L, 0x00200802L, 0x04200800L,
- 0x04200802L, 0x00200000L, 0x00000000L, 0x04000002L,
- 0x00000002L, 0x04000000L, 0x04200002L, 0x00000802L,
- 0x04000800L, 0x00200802L, 0x00200002L, 0x04000800L,
- 0x04000002L, 0x04200000L, 0x04200800L, 0x00200002L,
- 0x04200000L, 0x00000800L, 0x00000802L, 0x04200802L,
- 0x00200800L, 0x00000002L, 0x04000000L, 0x00200800L,
- 0x04000000L, 0x00200800L, 0x00200000L, 0x04000802L,
- 0x04000802L, 0x04200002L, 0x04200002L, 0x00000002L,
- 0x00200002L, 0x04000000L, 0x04000800L, 0x00200000L,
- 0x04200800L, 0x00000802L, 0x00200802L, 0x04200800L,
- 0x00000802L, 0x04000002L, 0x04200802L, 0x04200000L,
- 0x00200800L, 0x00000000L, 0x00000002L, 0x04200802L,
- 0x00000000L, 0x00200802L, 0x04200000L, 0x00000800L,
- 0x04000002L, 0x04000800L, 0x00000800L, 0x00200002L };
-
-static const unsigned long SP8[64] = {
- 0x10001040L, 0x00001000L, 0x00040000L, 0x10041040L,
- 0x10000000L, 0x10001040L, 0x00000040L, 0x10000000L,
- 0x00040040L, 0x10040000L, 0x10041040L, 0x00041000L,
- 0x10041000L, 0x00041040L, 0x00001000L, 0x00000040L,
- 0x10040000L, 0x10000040L, 0x10001000L, 0x00001040L,
- 0x00041000L, 0x00040040L, 0x10040040L, 0x10041000L,
- 0x00001040L, 0x00000000L, 0x00000000L, 0x10040040L,
- 0x10000040L, 0x10001000L, 0x00041040L, 0x00040000L,
- 0x00041040L, 0x00040000L, 0x10041000L, 0x00001000L,
- 0x00000040L, 0x10040040L, 0x00001000L, 0x00041040L,
- 0x10001000L, 0x00000040L, 0x10000040L, 0x10040000L,
- 0x10040040L, 0x10000000L, 0x00040000L, 0x10001040L,
- 0x00000000L, 0x10041040L, 0x00040040L, 0x10000040L,
- 0x10040000L, 0x10001000L, 0x10001040L, 0x00000000L,
- 0x10041040L, 0x00041000L, 0x00041000L, 0x00001040L,
- 0x00001040L, 0x00040040L, 0x10000000L, 0x10041000L };
-
-static void desfunc(register unsigned long *block, register unsigned long *keys)
-{
- register unsigned long fval, work, right, leftt;
- register int round;
-
- leftt = block[0];
- right = block[1];
- work = ((leftt >> 4) ^ right) & 0x0f0f0f0fL;
- right ^= work;
- leftt ^= (work << 4);
- work = ((leftt >> 16) ^ right) & 0x0000ffffL;
- right ^= work;
- leftt ^= (work << 16);
- work = ((right >> 2) ^ leftt) & 0x33333333L;
- leftt ^= work;
- right ^= (work << 2);
- work = ((right >> 8) ^ leftt) & 0x00ff00ffL;
- leftt ^= work;
- right ^= (work << 8);
- right = ((right << 1) | ((right >> 31) & 1L)) & 0xffffffffL;
- work = (leftt ^ right) & 0xaaaaaaaaL;
- leftt ^= work;
- right ^= work;
- leftt = ((leftt << 1) | ((leftt >> 31) & 1L)) & 0xffffffffL;
-
- for( round = 0; round < 8; round++ ) {
- work = (right << 28) | (right >> 4);
- work ^= *keys++;
- fval = SP7[ work & 0x3fL];
- fval |= SP5[(work >> 8) & 0x3fL];
- fval |= SP3[(work >> 16) & 0x3fL];
- fval |= SP1[(work >> 24) & 0x3fL];
- work = right ^ *keys++;
- fval |= SP8[ work & 0x3fL];
- fval |= SP6[(work >> 8) & 0x3fL];
- fval |= SP4[(work >> 16) & 0x3fL];
- fval |= SP2[(work >> 24) & 0x3fL];
- leftt ^= fval;
- work = (leftt << 28) | (leftt >> 4);
- work ^= *keys++;
- fval = SP7[ work & 0x3fL];
- fval |= SP5[(work >> 8) & 0x3fL];
- fval |= SP3[(work >> 16) & 0x3fL];
- fval |= SP1[(work >> 24) & 0x3fL];
- work = leftt ^ *keys++;
- fval |= SP8[ work & 0x3fL];
- fval |= SP6[(work >> 8) & 0x3fL];
- fval |= SP4[(work >> 16) & 0x3fL];
- fval |= SP2[(work >> 24) & 0x3fL];
- right ^= fval;
- }
-
- right = (right << 31) | (right >> 1);
- work = (leftt ^ right) & 0xaaaaaaaaL;
- leftt ^= work;
- right ^= work;
- leftt = (leftt << 31) | (leftt >> 1);
- work = ((leftt >> 8) ^ right) & 0x00ff00ffL;
- right ^= work;
- leftt ^= (work << 8);
- work = ((leftt >> 2) ^ right) & 0x33333333L;
- right ^= work;
- leftt ^= (work << 2);
- work = ((right >> 16) ^ leftt) & 0x0000ffffL;
- leftt ^= work;
- right ^= (work << 16);
- work = ((right >> 4) ^ leftt) & 0x0f0f0f0fL;
- leftt ^= work;
- right ^= (work << 4);
- *block++ = right;
- *block = leftt;
- return;
- }
-
-/* Validation sets:
- *
- * Single-length key, single-length plaintext -
- * Key : 0123 4567 89ab cdef
- * Plain : 0123 4567 89ab cde7
- * Cipher : c957 4425 6a5e d31d
- *
- * Double-length key, single-length plaintext -
- * Key : 0123 4567 89ab cdef fedc ba98 7654 3210
- * Plain : 0123 4567 89ab cde7
- * Cipher : 7f1d 0a77 826b 8aff
- *
- * Double-length key, double-length plaintext -
- * Key : 0123 4567 89ab cdef fedc ba98 7654 3210
- * Plain : 0123 4567 89ab cdef 0123 4567 89ab cdff
- * Cipher : 27a0 8440 406a df60 278f 47cf 42d6 15d7
- *
- * Triple-length key, single-length plaintext -
- * Key : 0123 4567 89ab cdef fedc ba98 7654 3210 89ab cdef 0123 4567
- * Plain : 0123 4567 89ab cde7
- * Cipher : de0b 7c06 ae5e 0ed5
- *
- * Triple-length key, double-length plaintext -
- * Key : 0123 4567 89ab cdef fedc ba98 7654 3210 89ab cdef 0123 4567
- * Plain : 0123 4567 89ab cdef 0123 4567 89ab cdff
- * Cipher : ad0d 1b30 ac17 cf07 0ed1 1c63 81e4 4de5
- *
- * d3des V5.0a rwo 9208.07 18:44 Graven Imagery
- **********************************************************************/
diff --git a/crypto/hash-gnutls.c b/crypto/hash-gnutls.c
new file mode 100644
index 0000000..17911ac
--- /dev/null
+++ b/crypto/hash-gnutls.c
@@ -0,0 +1,104 @@
+/*
+ * QEMU Crypto hash algorithms
+ *
+ * Copyright (c) 2021 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "qemu/osdep.h"
+#include <gnutls/crypto.h>
+#include "qapi/error.h"
+#include "crypto/hash.h"
+#include "hashpriv.h"
+
+
+static int qcrypto_hash_alg_map[QCRYPTO_HASH_ALG__MAX] = {
+ [QCRYPTO_HASH_ALG_MD5] = GNUTLS_DIG_MD5,
+ [QCRYPTO_HASH_ALG_SHA1] = GNUTLS_DIG_SHA1,
+ [QCRYPTO_HASH_ALG_SHA224] = GNUTLS_DIG_SHA224,
+ [QCRYPTO_HASH_ALG_SHA256] = GNUTLS_DIG_SHA256,
+ [QCRYPTO_HASH_ALG_SHA384] = GNUTLS_DIG_SHA384,
+ [QCRYPTO_HASH_ALG_SHA512] = GNUTLS_DIG_SHA512,
+ [QCRYPTO_HASH_ALG_RIPEMD160] = GNUTLS_DIG_RMD160,
+};
+
+gboolean qcrypto_hash_supports(QCryptoHashAlgorithm alg)
+{
+ size_t i;
+ const gnutls_digest_algorithm_t *algs;
+ if (alg >= G_N_ELEMENTS(qcrypto_hash_alg_map) ||
+ qcrypto_hash_alg_map[alg] == GNUTLS_DIG_UNKNOWN) {
+ return false;
+ }
+ algs = gnutls_digest_list();
+ for (i = 0; algs[i] != GNUTLS_DIG_UNKNOWN; i++) {
+ if (algs[i] == qcrypto_hash_alg_map[alg]) {
+ return true;
+ }
+ }
+ return false;
+}
+
+
+static int
+qcrypto_gnutls_hash_bytesv(QCryptoHashAlgorithm alg,
+ const struct iovec *iov,
+ size_t niov,
+ uint8_t **result,
+ size_t *resultlen,
+ Error **errp)
+{
+ int i, ret;
+ gnutls_hash_hd_t hash;
+
+ if (!qcrypto_hash_supports(alg)) {
+ error_setg(errp,
+ "Unknown hash algorithm %d",
+ alg);
+ return -1;
+ }
+
+ ret = gnutls_hash_get_len(qcrypto_hash_alg_map[alg]);
+ if (*resultlen == 0) {
+ *resultlen = ret;
+ *result = g_new0(uint8_t, *resultlen);
+ } else if (*resultlen != ret) {
+ error_setg(errp,
+ "Result buffer size %zu is smaller than hash %d",
+ *resultlen, ret);
+ return -1;
+ }
+
+ ret = gnutls_hash_init(&hash, qcrypto_hash_alg_map[alg]);
+ if (ret < 0) {
+ error_setg(errp,
+ "Unable to initialize hash algorithm: %s",
+ gnutls_strerror(ret));
+ return -1;
+ }
+
+ for (i = 0; i < niov; i++) {
+ gnutls_hash(hash, iov[i].iov_base, iov[i].iov_len);
+ }
+
+ gnutls_hash_deinit(hash, *result);
+ return 0;
+}
+
+
+QCryptoHashDriver qcrypto_hash_lib_driver = {
+ .hash_bytesv = qcrypto_gnutls_hash_bytesv,
+};
diff --git a/crypto/hmac-gnutls.c b/crypto/hmac-gnutls.c
new file mode 100644
index 0000000..24db383
--- /dev/null
+++ b/crypto/hmac-gnutls.c
@@ -0,0 +1,139 @@
+/*
+ * QEMU Crypto hmac algorithms
+ *
+ * Copyright (c) 2021 Red Hat, Inc.
+ *
+ * Derived from hmac-gcrypt.c:
+ *
+ * Copyright (c) 2016 HUAWEI TECHNOLOGIES CO., LTD.
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or
+ * (at your option) any later version. See the COPYING file in the
+ * top-level directory.
+ *
+ */
+
+#include "qemu/osdep.h"
+#include <gnutls/crypto.h>
+
+#include "qapi/error.h"
+#include "crypto/hmac.h"
+#include "hmacpriv.h"
+
+static int qcrypto_hmac_alg_map[QCRYPTO_HASH_ALG__MAX] = {
+ [QCRYPTO_HASH_ALG_MD5] = GNUTLS_MAC_MD5,
+ [QCRYPTO_HASH_ALG_SHA1] = GNUTLS_MAC_SHA1,
+ [QCRYPTO_HASH_ALG_SHA224] = GNUTLS_MAC_SHA224,
+ [QCRYPTO_HASH_ALG_SHA256] = GNUTLS_MAC_SHA256,
+ [QCRYPTO_HASH_ALG_SHA384] = GNUTLS_MAC_SHA384,
+ [QCRYPTO_HASH_ALG_SHA512] = GNUTLS_MAC_SHA512,
+ [QCRYPTO_HASH_ALG_RIPEMD160] = GNUTLS_MAC_RMD160,
+};
+
+typedef struct QCryptoHmacGnutls QCryptoHmacGnutls;
+struct QCryptoHmacGnutls {
+ gnutls_hmac_hd_t handle;
+};
+
+bool qcrypto_hmac_supports(QCryptoHashAlgorithm alg)
+{
+ size_t i;
+ const gnutls_digest_algorithm_t *algs;
+ if (alg >= G_N_ELEMENTS(qcrypto_hmac_alg_map) ||
+ qcrypto_hmac_alg_map[alg] == GNUTLS_DIG_UNKNOWN) {
+ return false;
+ }
+ algs = gnutls_digest_list();
+ for (i = 0; algs[i] != GNUTLS_DIG_UNKNOWN; i++) {
+ if (algs[i] == qcrypto_hmac_alg_map[alg]) {
+ return true;
+ }
+ }
+ return false;
+}
+
+void *qcrypto_hmac_ctx_new(QCryptoHashAlgorithm alg,
+ const uint8_t *key, size_t nkey,
+ Error **errp)
+{
+ QCryptoHmacGnutls *ctx;
+ int err;
+
+ if (!qcrypto_hmac_supports(alg)) {
+ error_setg(errp, "Unsupported hmac algorithm %s",
+ QCryptoHashAlgorithm_str(alg));
+ return NULL;
+ }
+
+ ctx = g_new0(QCryptoHmacGnutls, 1);
+
+ err = gnutls_hmac_init(&ctx->handle,
+ qcrypto_hmac_alg_map[alg],
+ (const void *)key, nkey);
+ if (err != 0) {
+ error_setg(errp, "Cannot initialize hmac: %s",
+ gnutls_strerror(err));
+ goto error;
+ }
+
+ return ctx;
+
+error:
+ g_free(ctx);
+ return NULL;
+}
+
+static void
+qcrypto_gnutls_hmac_ctx_free(QCryptoHmac *hmac)
+{
+ QCryptoHmacGnutls *ctx;
+
+ ctx = hmac->opaque;
+ gnutls_hmac_deinit(ctx->handle, NULL);
+
+ g_free(ctx);
+}
+
+static int
+qcrypto_gnutls_hmac_bytesv(QCryptoHmac *hmac,
+ const struct iovec *iov,
+ size_t niov,
+ uint8_t **result,
+ size_t *resultlen,
+ Error **errp)
+{
+ QCryptoHmacGnutls *ctx;
+ uint32_t ret;
+ int i;
+
+ ctx = hmac->opaque;
+
+ for (i = 0; i < niov; i++) {
+ gnutls_hmac(ctx->handle, iov[i].iov_base, iov[i].iov_len);
+ }
+
+ ret = gnutls_hmac_get_len(qcrypto_hmac_alg_map[hmac->alg]);
+ if (ret <= 0) {
+ error_setg(errp, "Unable to get hmac length: %s",
+ gnutls_strerror(ret));
+ return -1;
+ }
+
+ if (*resultlen == 0) {
+ *resultlen = ret;
+ *result = g_new0(uint8_t, *resultlen);
+ } else if (*resultlen != ret) {
+ error_setg(errp, "Result buffer size %zu is smaller than hmac %d",
+ *resultlen, ret);
+ return -1;
+ }
+
+ gnutls_hmac_output(ctx->handle, *result);
+
+ return 0;
+}
+
+QCryptoHmacDriver qcrypto_hmac_lib_driver = {
+ .hmac_bytesv = qcrypto_gnutls_hmac_bytesv,
+ .hmac_free = qcrypto_gnutls_hmac_ctx_free,
+};
diff --git a/crypto/init.c b/crypto/init.c
index ea233b9..fb7f1bf 100644
--- a/crypto/init.c
+++ b/crypto/init.c
@@ -35,21 +35,6 @@
#include "crypto/random.h"
/* #define DEBUG_GNUTLS */
-
-/*
- * We need to init gcrypt threading if
- *
- * - gcrypt < 1.6.0
- *
- */
-
-#if (defined(CONFIG_GCRYPT) && \
- (GCRYPT_VERSION_NUMBER < 0x010600))
-#define QCRYPTO_INIT_GCRYPT_THREADS
-#else
-#undef QCRYPTO_INIT_GCRYPT_THREADS
-#endif
-
#ifdef DEBUG_GNUTLS
static void qcrypto_gnutls_log(int level, const char *str)
{
@@ -57,55 +42,8 @@ static void qcrypto_gnutls_log(int level, const char *str)
}
#endif
-#ifdef QCRYPTO_INIT_GCRYPT_THREADS
-static int qcrypto_gcrypt_mutex_init(void **priv)
-{ \
- QemuMutex *lock = NULL;
- lock = g_new0(QemuMutex, 1);
- qemu_mutex_init(lock);
- *priv = lock;
- return 0;
-}
-
-static int qcrypto_gcrypt_mutex_destroy(void **priv)
-{
- QemuMutex *lock = *priv;
- qemu_mutex_destroy(lock);
- g_free(lock);
- return 0;
-}
-
-static int qcrypto_gcrypt_mutex_lock(void **priv)
-{
- QemuMutex *lock = *priv;
- qemu_mutex_lock(lock);
- return 0;
-}
-
-static int qcrypto_gcrypt_mutex_unlock(void **priv)
-{
- QemuMutex *lock = *priv;
- qemu_mutex_unlock(lock);
- return 0;
-}
-
-static struct gcry_thread_cbs qcrypto_gcrypt_thread_impl = {
- (GCRY_THREAD_OPTION_PTHREAD | (GCRY_THREAD_OPTION_VERSION << 8)),
- NULL,
- qcrypto_gcrypt_mutex_init,
- qcrypto_gcrypt_mutex_destroy,
- qcrypto_gcrypt_mutex_lock,
- qcrypto_gcrypt_mutex_unlock,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
-};
-#endif /* QCRYPTO_INIT_GCRYPT */
-
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();
diff --git a/crypto/meson.build b/crypto/meson.build
index 7cbf1a6..95a6a83 100644
--- a/crypto/meson.build
+++ b/crypto/meson.build
@@ -5,7 +5,6 @@ crypto_ss.add(files(
'block-qcow.c',
'block.c',
'cipher.c',
- 'desrfb.c',
'hash.c',
'hmac.c',
'ivgen-essiv.c',
@@ -24,14 +23,16 @@ crypto_ss.add(files(
if nettle.found()
crypto_ss.add(nettle, files('hash-nettle.c', 'hmac-nettle.c', 'pbkdf-nettle.c'))
+ if xts == 'private'
+ crypto_ss.add(files('xts.c'))
+ endif
elif gcrypt.found()
crypto_ss.add(gcrypt, files('hash-gcrypt.c', 'hmac-gcrypt.c', 'pbkdf-gcrypt.c'))
+elif gnutls_crypto.found()
+ crypto_ss.add(gnutls, files('hash-gnutls.c', 'hmac-gnutls.c', 'pbkdf-gnutls.c'))
else
crypto_ss.add(files('hash-glib.c', 'hmac-glib.c', 'pbkdf-stub.c'))
endif
-if xts == 'private'
- crypto_ss.add(files('xts.c'))
-endif
crypto_ss.add(when: 'CONFIG_SECRET_KEYRING', if_true: files('secret_keyring.c'))
crypto_ss.add(when: 'CONFIG_AF_ALG', if_true: files('afalg.c', 'cipher-afalg.c', 'hash-afalg.c'))
@@ -39,6 +40,9 @@ crypto_ss.add(when: gnutls, if_true: files('tls-cipher-suites.c'))
util_ss.add(files('aes.c'))
util_ss.add(files('init.c'))
+if gnutls.found()
+ util_ss.add(gnutls)
+endif
if gcrypt.found()
util_ss.add(gcrypt, files('random-gcrypt.c'))
diff --git a/crypto/pbkdf-gnutls.c b/crypto/pbkdf-gnutls.c
new file mode 100644
index 0000000..2dfbbd3
--- /dev/null
+++ b/crypto/pbkdf-gnutls.c
@@ -0,0 +1,90 @@
+/*
+ * QEMU Crypto PBKDF support (Password-Based Key Derivation Function)
+ *
+ * Copyright (c) 2021 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "qemu/osdep.h"
+#include <gnutls/crypto.h>
+#include "qapi/error.h"
+#include "crypto/pbkdf.h"
+
+bool qcrypto_pbkdf2_supports(QCryptoHashAlgorithm hash)
+{
+ switch (hash) {
+ case QCRYPTO_HASH_ALG_MD5:
+ case QCRYPTO_HASH_ALG_SHA1:
+ case QCRYPTO_HASH_ALG_SHA224:
+ case QCRYPTO_HASH_ALG_SHA256:
+ case QCRYPTO_HASH_ALG_SHA384:
+ case QCRYPTO_HASH_ALG_SHA512:
+ case QCRYPTO_HASH_ALG_RIPEMD160:
+ return true;
+ default:
+ return false;
+ }
+}
+
+int qcrypto_pbkdf2(QCryptoHashAlgorithm hash,
+ const uint8_t *key, size_t nkey,
+ const uint8_t *salt, size_t nsalt,
+ uint64_t iterations,
+ uint8_t *out, size_t nout,
+ Error **errp)
+{
+ static const int hash_map[QCRYPTO_HASH_ALG__MAX] = {
+ [QCRYPTO_HASH_ALG_MD5] = GNUTLS_DIG_MD5,
+ [QCRYPTO_HASH_ALG_SHA1] = GNUTLS_DIG_SHA1,
+ [QCRYPTO_HASH_ALG_SHA224] = GNUTLS_DIG_SHA224,
+ [QCRYPTO_HASH_ALG_SHA256] = GNUTLS_DIG_SHA256,
+ [QCRYPTO_HASH_ALG_SHA384] = GNUTLS_DIG_SHA384,
+ [QCRYPTO_HASH_ALG_SHA512] = GNUTLS_DIG_SHA512,
+ [QCRYPTO_HASH_ALG_RIPEMD160] = GNUTLS_DIG_RMD160,
+ };
+ int ret;
+ const gnutls_datum_t gkey = { (unsigned char *)key, nkey };
+ const gnutls_datum_t gsalt = { (unsigned char *)salt, nsalt };
+
+ if (iterations > ULONG_MAX) {
+ error_setg_errno(errp, ERANGE,
+ "PBKDF iterations %llu must be less than %lu",
+ (long long unsigned)iterations, ULONG_MAX);
+ return -1;
+ }
+
+ if (hash >= G_N_ELEMENTS(hash_map) ||
+ hash_map[hash] == GNUTLS_DIG_UNKNOWN) {
+ error_setg_errno(errp, ENOSYS,
+ "PBKDF does not support hash algorithm %s",
+ QCryptoHashAlgorithm_str(hash));
+ return -1;
+ }
+
+ ret = gnutls_pbkdf2(hash_map[hash],
+ &gkey,
+ &gsalt,
+ iterations,
+ out,
+ nout);
+ if (ret != 0) {
+ error_setg(errp, "Cannot derive password: %s",
+ gnutls_strerror(ret));
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/docs/system/cpu-models-x86.rst.inc b/docs/system/cpu-models-x86.rst.inc
index f40ee03..9119f5d 100644
--- a/docs/system/cpu-models-x86.rst.inc
+++ b/docs/system/cpu-models-x86.rst.inc
@@ -227,7 +227,7 @@ features are included if using "Host passthrough" or "Host model".
Preferred CPU models for AMD x86 hosts
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-The following CPU models are preferred for use on Intel hosts.
+The following CPU models are preferred for use on AMD hosts.
Administrators / applications are recommended to use the CPU model that
matches the generation of the host CPUs in use. In a deployment with a
mixture of host CPU models between machines, if live migration
diff --git a/hw/net/rocker/rocker.h b/hw/net/rocker/rocker.h
index 941c932..412fa44 100644
--- a/hw/net/rocker/rocker.h
+++ b/hw/net/rocker/rocker.h
@@ -25,14 +25,9 @@
#if defined(DEBUG_ROCKER)
# define DPRINTF(fmt, ...) \
do { \
- struct timeval tv; \
- char timestr[64]; \
- time_t now; \
- gettimeofday(&tv, NULL); \
- now = tv.tv_sec; \
- strftime(timestr, sizeof(timestr), "%T", localtime(&now)); \
- fprintf(stderr, "%s.%06ld ", timestr, tv.tv_usec); \
- fprintf(stderr, "ROCKER: " fmt, ## __VA_ARGS__); \
+ g_autoptr(GDateTime) now = g_date_time_new_now_local(); \
+ g_autofree char *nowstr = g_date_time_format(now, "%T.%f");\
+ fprintf(stderr, "%s ROCKER: " fmt, nowstr, ## __VA_ARGS__);\
} while (0)
#else
static inline GCC_FMT_ATTR(1, 2) int DPRINTF(const char *fmt, ...)
diff --git a/io/channel-websock.c b/io/channel-websock.c
index 03c1f7c..70889bb 100644
--- a/io/channel-websock.c
+++ b/io/channel-websock.c
@@ -177,15 +177,9 @@ qio_channel_websock_handshake_send_res(QIOChannelWebsock *ioc,
static gchar *qio_channel_websock_date_str(void)
{
- struct tm tm;
- time_t now = time(NULL);
- char datebuf[128];
+ g_autoptr(GDateTime) now = g_date_time_new_now_utc();
- gmtime_r(&now, &tm);
-
- strftime(datebuf, sizeof(datebuf), "%a, %d %b %Y %H:%M:%S GMT", &tm);
-
- return g_strdup(datebuf);
+ return g_date_time_format(now, "%a, %d %b %Y %H:%M:%S GMT");
}
static void qio_channel_websock_handshake_send_res_err(QIOChannelWebsock *ioc,
diff --git a/meson.build b/meson.build
index e5de144..6e4d2d8 100644
--- a/meson.build
+++ b/meson.build
@@ -823,50 +823,77 @@ if 'CONFIG_OPENGL' in config_host
endif
gnutls = not_found
+gnutls_crypto = not_found
if not get_option('gnutls').auto() or have_system
- gnutls = dependency('gnutls', version: '>=3.5.18',
- method: 'pkg-config',
- required: get_option('gnutls'),
- kwargs: static_kwargs)
+ # For general TLS support our min gnutls matches
+ # that implied by our platform support matrix
+ #
+ # For the crypto backends, we look for a newer
+ # gnutls:
+ #
+ # Version 3.6.8 is needed to get XTS
+ # Version 3.6.13 is needed to get PBKDF
+ # Version 3.6.14 is needed to get HW accelerated XTS
+ #
+ # If newer enough gnutls isn't available, we can
+ # still use a different crypto backend to satisfy
+ # the platform support requirements
+ gnutls_crypto = dependency('gnutls', version: '>=3.6.14',
+ method: 'pkg-config',
+ required: false,
+ kwargs: static_kwargs)
+ if gnutls_crypto.found()
+ gnutls = gnutls_crypto
+ else
+ # Our min version if all we need is TLS
+ gnutls = dependency('gnutls', version: '>=3.5.18',
+ method: 'pkg-config',
+ required: get_option('gnutls'),
+ kwargs: static_kwargs)
+ endif
endif
-# Nettle has priority over gcrypt
+# We prefer use of gnutls for crypto, unless the options
+# explicitly asked for nettle or gcrypt.
+#
+# If gnutls isn't available for crypto, then we'll prefer
+# gcrypt over nettle for performance reasons.
gcrypt = not_found
nettle = not_found
-xts = 'private'
+xts = 'none'
+
if get_option('nettle').enabled() and get_option('gcrypt').enabled()
error('Only one of gcrypt & nettle can be enabled')
-elif (not get_option('nettle').auto() or have_system) and not get_option('gcrypt').enabled()
- nettle = dependency('nettle', version: '>=3.4',
- method: 'pkg-config',
- required: get_option('nettle'),
- kwargs: static_kwargs)
- if nettle.found() and cc.has_header('nettle/xts.h', dependencies: nettle)
- xts = 'nettle'
- endif
endif
-if (not get_option('gcrypt').auto() or have_system) and not nettle.found()
- gcrypt = dependency('libgcrypt', version: '>=1.5',
- method: 'config-tool',
- required: get_option('gcrypt'),
- kwargs: static_kwargs)
- if gcrypt.found() and cc.compiles('''
- #include <gcrypt.h>
- int main(void) {
- gcry_cipher_hd_t handle;
- gcry_cipher_open(&handle, GCRY_CIPHER_AES, GCRY_CIPHER_MODE_XTS, 0);
- return 0;
- }
- ''', dependencies: gcrypt)
- xts = 'gcrypt'
+
+# Explicit nettle/gcrypt request, so ignore gnutls for crypto
+if get_option('nettle').enabled() or get_option('gcrypt').enabled()
+ gnutls_crypto = not_found
+endif
+
+if not gnutls_crypto.found()
+ if (not get_option('gcrypt').auto() or have_system) and not get_option('nettle').enabled()
+ gcrypt = dependency('libgcrypt', version: '>=1.8',
+ method: 'config-tool',
+ required: get_option('gcrypt'),
+ kwargs: static_kwargs)
+ # Debian has removed -lgpg-error from libgcrypt-config
+ # as it "spreads unnecessary dependencies" which in
+ # turn breaks static builds...
+ if gcrypt.found() and enable_static
+ gcrypt = declare_dependency(dependencies: [
+ gcrypt,
+ cc.find_library('gpg-error', required: true, kwargs: static_kwargs)])
+ endif
endif
- # Debian has removed -lgpg-error from libgcrypt-config
- # as it "spreads unnecessary dependencies" which in
- # turn breaks static builds...
- if gcrypt.found() and enable_static
- gcrypt = declare_dependency(dependencies: [
- gcrypt,
- cc.find_library('gpg-error', required: true, kwargs: static_kwargs)])
+ if (not get_option('nettle').auto() or have_system) and not gcrypt.found()
+ nettle = dependency('nettle', version: '>=3.4',
+ method: 'pkg-config',
+ required: get_option('nettle'),
+ kwargs: static_kwargs)
+ if nettle.found() and not cc.has_header('nettle/xts.h', dependencies: nettle)
+ xts = 'private'
+ endif
endif
endif
@@ -1253,6 +1280,7 @@ config_host_data.set('CONFIG_XKBCOMMON', xkbcommon.found())
config_host_data.set('CONFIG_KEYUTILS', keyutils.found())
config_host_data.set('CONFIG_GETTID', has_gettid)
config_host_data.set('CONFIG_GNUTLS', gnutls.found())
+config_host_data.set('CONFIG_GNUTLS_CRYPTO', gnutls_crypto.found())
config_host_data.set('CONFIG_GCRYPT', gcrypt.found())
config_host_data.set('CONFIG_NETTLE', nettle.found())
config_host_data.set('CONFIG_QEMU_PRIVATE_XTS', xts == 'private')
@@ -2988,11 +3016,9 @@ summary(summary_info, bool_yn: true, section: 'Block layer support')
summary_info = {}
summary_info += {'TLS priority': config_host['CONFIG_TLS_PRIORITY']}
summary_info += {'GNUTLS support': gnutls.found()}
+summary_info += {'GNUTLS crypto': gnutls_crypto.found()}
# TODO: add back version
summary_info += {'libgcrypt': gcrypt.found()}
-if gcrypt.found()
- summary_info += {' XTS': xts != 'private'}
-endif
# TODO: add back version
summary_info += {'nettle': nettle.found()}
if nettle.found()
diff --git a/qapi/crypto.json b/qapi/crypto.json
index 7116ae9..1ec54c1 100644
--- a/qapi/crypto.json
+++ b/qapi/crypto.json
@@ -66,7 +66,7 @@
# @aes-128: AES with 128 bit / 16 byte keys
# @aes-192: AES with 192 bit / 24 byte keys
# @aes-256: AES with 256 bit / 32 byte keys
-# @des-rfb: RFB specific variant of single DES. Do not use except in VNC.
+# @des: DES with 56 bit / 8 byte keys. Do not use except in VNC. (since 6.1)
# @3des: 3DES(EDE) with 192 bit / 24 byte keys (since 2.9)
# @cast5-128: Cast5 with 128 bit / 16 byte keys
# @serpent-128: Serpent with 128 bit / 16 byte keys
@@ -80,7 +80,7 @@
{ 'enum': 'QCryptoCipherAlgorithm',
'prefix': 'QCRYPTO_CIPHER_ALG',
'data': ['aes-128', 'aes-192', 'aes-256',
- 'des-rfb', '3des',
+ 'des', '3des',
'cast5-128',
'serpent-128', 'serpent-192', 'serpent-256',
'twofish-128', 'twofish-192', 'twofish-256']}
diff --git a/qemu-options.hx b/qemu-options.hx
index 8965dab..214c477 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -196,25 +196,38 @@ SRST
ERST
DEF("smp", HAS_ARG, QEMU_OPTION_smp,
- "-smp [cpus=]n[,maxcpus=cpus][,cores=cores][,threads=threads][,dies=dies][,sockets=sockets]\n"
+ "-smp [[cpus=]n][,maxcpus=cpus][,sockets=sockets][,dies=dies][,cores=cores][,threads=threads]\n"
" set the number of CPUs to 'n' [default=1]\n"
- " maxcpus= maximum number of total cpus, including\n"
+ " maxcpus= maximum number of total CPUs, including\n"
" offline CPUs for hotplug, etc\n"
- " cores= number of CPU cores on one socket (for PC, it's on one die)\n"
- " threads= number of threads on one CPU core\n"
+ " sockets= number of discrete sockets in the system\n"
" dies= number of CPU dies on one socket (for PC only)\n"
- " sockets= number of discrete sockets in the system\n",
+ " cores= number of CPU cores on one socket (for PC, it's on one die)\n"
+ " threads= number of threads on one CPU core\n",
QEMU_ARCH_ALL)
SRST
-``-smp [cpus=]n[,cores=cores][,threads=threads][,dies=dies][,sockets=sockets][,maxcpus=maxcpus]``
- Simulate an SMP system with n CPUs. On the PC target, up to 255 CPUs
- are supported. On Sparc32 target, Linux limits the number of usable
- CPUs to 4. For the PC target, the number of cores per die, the
- number of threads per cores, the number of dies per packages and the
- total number of sockets can be specified. Missing values will be
- computed. If any on the three values is given, the total number of
- CPUs n can be omitted. maxcpus specifies the maximum number of
- hotpluggable CPUs.
+``-smp [[cpus=]n][,maxcpus=maxcpus][,sockets=sockets][,dies=dies][,cores=cores][,threads=threads]``
+ Simulate a SMP system with '\ ``n``\ ' CPUs initially present on
+ the machine type board. On boards supporting CPU hotplug, the optional
+ '\ ``maxcpus``\ ' parameter can be set to enable further CPUs to be
+ added at runtime. If omitted the maximum number of CPUs will be
+ set to match the initial CPU count. Both parameters are subject to
+ an upper limit that is determined by the specific machine type chosen.
+
+ To control reporting of CPU topology information, the number of sockets,
+ dies per socket, cores per die, and threads per core can be specified.
+ The sum `` sockets * cores * dies * threads `` must be equal to the
+ maximum CPU count. CPU targets may only support a subset of the topology
+ parameters. Where a CPU target does not support use of a particular
+ topology parameter, its value should be assumed to be 1 for the purpose
+ of computing the CPU maximum count.
+
+ Either the initial CPU count, or at least one of the topology parameters
+ must be specified. Values for any omitted parameters will be computed
+ from those which are given. Historically preference was given to the
+ coarsest topology parameters when computing missing values (ie sockets
+ preferred over cores, which were preferred over threads), however, this
+ behaviour is considered liable to change.
ERST
DEF("numa", HAS_ARG, QEMU_OPTION_numa,
diff --git a/softmmu/qemu-seccomp.c b/softmmu/qemu-seccomp.c
index 9c29d9c..f500267 100644
--- a/softmmu/qemu-seccomp.c
+++ b/softmmu/qemu-seccomp.c
@@ -97,17 +97,11 @@ static const struct QemuSeccompSyscall denylist[] = {
{ SCMP_SYS(vfork), QEMU_SECCOMP_SET_SPAWN },
{ SCMP_SYS(execve), QEMU_SECCOMP_SET_SPAWN },
/* resource control */
- { SCMP_SYS(getpriority), QEMU_SECCOMP_SET_RESOURCECTL },
{ SCMP_SYS(setpriority), QEMU_SECCOMP_SET_RESOURCECTL },
{ SCMP_SYS(sched_setparam), QEMU_SECCOMP_SET_RESOURCECTL },
- { SCMP_SYS(sched_getparam), QEMU_SECCOMP_SET_RESOURCECTL },
{ SCMP_SYS(sched_setscheduler), QEMU_SECCOMP_SET_RESOURCECTL,
ARRAY_SIZE(sched_setscheduler_arg), sched_setscheduler_arg },
- { SCMP_SYS(sched_getscheduler), QEMU_SECCOMP_SET_RESOURCECTL },
{ SCMP_SYS(sched_setaffinity), QEMU_SECCOMP_SET_RESOURCECTL },
- { SCMP_SYS(sched_getaffinity), QEMU_SECCOMP_SET_RESOURCECTL },
- { SCMP_SYS(sched_get_priority_max), QEMU_SECCOMP_SET_RESOURCECTL },
- { SCMP_SYS(sched_get_priority_min), QEMU_SECCOMP_SET_RESOURCECTL },
};
static inline __attribute__((unused)) int
diff --git a/tests/migration/guestperf/engine.py b/tests/migration/guestperf/engine.py
index 7c991c4..87a6ab2 100644
--- a/tests/migration/guestperf/engine.py
+++ b/tests/migration/guestperf/engine.py
@@ -423,7 +423,7 @@ class Engine(object):
progress_history = ret[0]
qemu_timings = ret[1]
vcpu_timings = ret[2]
- if uri[0:5] == "unix:":
+ if uri[0:5] == "unix:" and os.path.exists(uri[5:]):
os.remove(uri[5:])
if os.path.exists(srcmonaddr):
diff --git a/tests/unit/test-crypto-cipher.c b/tests/unit/test-crypto-cipher.c
index 280319a..d9d9d07 100644
--- a/tests/unit/test-crypto-cipher.c
+++ b/tests/unit/test-crypto-cipher.c
@@ -150,10 +150,33 @@ static QCryptoCipherTestData test_data[] = {
"b2eb05e2c39be9fcda6c19078c6a9d1b",
},
{
- .path = "/crypto/cipher/des-rfb-ecb-56",
- .alg = QCRYPTO_CIPHER_ALG_DES_RFB,
+ /*
+ * Testing 'password' as plaintext fits
+ * in single AES block, and gives identical
+ * ciphertext in ECB and CBC modes
+ */
+ .path = "/crypto/cipher/des-ecb-56-one-block",
+ .alg = QCRYPTO_CIPHER_ALG_DES,
+ .mode = QCRYPTO_CIPHER_MODE_ECB,
+ .key = "80c4a2e691d5b3f7",
+ .plaintext = "70617373776f7264",
+ .ciphertext = "73fa80b66134e403",
+ },
+ {
+ /* See previous comment */
+ .path = "/crypto/cipher/des-cbc-56-one-block",
+ .alg = QCRYPTO_CIPHER_ALG_DES,
+ .mode = QCRYPTO_CIPHER_MODE_CBC,
+ .key = "80c4a2e691d5b3f7",
+ .iv = "0000000000000000",
+ .plaintext = "70617373776f7264",
+ .ciphertext = "73fa80b66134e403",
+ },
+ {
+ .path = "/crypto/cipher/des-ecb-56",
+ .alg = QCRYPTO_CIPHER_ALG_DES,
.mode = QCRYPTO_CIPHER_MODE_ECB,
- .key = "0123456789abcdef",
+ .key = "80c4a2e691d5b3f7",
.plaintext =
"6bc1bee22e409f96e93d7e117393172a"
"ae2d8a571e03ac9c9eb76fac45af8e51"
@@ -165,7 +188,6 @@ static QCryptoCipherTestData test_data[] = {
"ffd29f1bb5596ad94ea2d8e6196b7f09"
"30d8ed0bf2773af36dd82a6280c20926",
},
-#if defined(CONFIG_NETTLE) || defined(CONFIG_GCRYPT)
{
/* Borrowed from linux-kernel crypto/testmgr.h */
.path = "/crypto/cipher/3des-cbc",
@@ -283,7 +305,6 @@ static QCryptoCipherTestData test_data[] = {
"407772c2ea0e3a7846b991b6e73d5142"
"fd51b0c62c6313785ceefccfc4700034",
},
-#endif
{
/* RFC 2144, Appendix B.1 */
.path = "/crypto/cipher/cast5-128",
diff --git a/tests/unit/test-crypto-hash.c b/tests/unit/test-crypto-hash.c
index ce7d0ab..1f4abb8 100644
--- a/tests/unit/test-crypto-hash.c
+++ b/tests/unit/test-crypto-hash.c
@@ -104,7 +104,7 @@ static void test_hash_alloc(void)
strlen(INPUT_TEXT),
&result,
&resultlen,
- NULL);
+ &error_fatal);
g_assert(ret == 0);
g_assert(resultlen == expected_lens[i]);
@@ -139,7 +139,7 @@ static void test_hash_prealloc(void)
strlen(INPUT_TEXT),
&result,
&resultlen,
- NULL);
+ &error_fatal);
g_assert(ret == 0);
g_assert(resultlen == expected_lens[i]);
@@ -176,7 +176,7 @@ static void test_hash_iov(void)
iov, 3,
&result,
&resultlen,
- NULL);
+ &error_fatal);
g_assert(ret == 0);
g_assert(resultlen == expected_lens[i]);
for (j = 0; j < resultlen; j++) {
@@ -210,7 +210,7 @@ static void test_hash_digest(void)
INPUT_TEXT,
strlen(INPUT_TEXT),
&digest,
- NULL);
+ &error_fatal);
g_assert(ret == 0);
g_assert_cmpstr(digest, ==, expected_outputs[i]);
g_free(digest);
@@ -234,7 +234,7 @@ static void test_hash_base64(void)
INPUT_TEXT,
strlen(INPUT_TEXT),
&digest,
- NULL);
+ &error_fatal);
g_assert(ret == 0);
g_assert_cmpstr(digest, ==, expected_outputs_b64[i]);
g_free(digest);
@@ -243,7 +243,8 @@ static void test_hash_base64(void)
int main(int argc, char **argv)
{
- g_assert(qcrypto_init(NULL) == 0);
+ int ret = qcrypto_init(&error_fatal);
+ g_assert(ret == 0);
g_test_init(&argc, &argv, NULL);
g_test_add_func("/crypto/hash/iov", test_hash_iov);
diff --git a/tests/unit/test-crypto-hmac.c b/tests/unit/test-crypto-hmac.c
index ee55382..23eb724 100644
--- a/tests/unit/test-crypto-hmac.c
+++ b/tests/unit/test-crypto-hmac.c
@@ -89,7 +89,6 @@ static void test_hmac_alloc(void)
QCryptoHmac *hmac = NULL;
uint8_t *result = NULL;
size_t resultlen = 0;
- Error *err = NULL;
const char *exp_output = NULL;
int ret;
size_t j;
@@ -101,14 +100,12 @@ static void test_hmac_alloc(void)
exp_output = data->hex_digest;
hmac = qcrypto_hmac_new(data->alg, (const uint8_t *)KEY,
- strlen(KEY), &err);
- g_assert(err == NULL);
+ strlen(KEY), &error_fatal);
g_assert(hmac != NULL);
ret = qcrypto_hmac_bytes(hmac, (const char *)INPUT_TEXT,
strlen(INPUT_TEXT), &result,
- &resultlen, &err);
- g_assert(err == NULL);
+ &resultlen, &error_fatal);
g_assert(ret == 0);
for (j = 0; j < resultlen; j++) {
@@ -131,7 +128,6 @@ static void test_hmac_prealloc(void)
QCryptoHmac *hmac = NULL;
uint8_t *result = NULL;
size_t resultlen = 0;
- Error *err = NULL;
const char *exp_output = NULL;
int ret;
size_t j;
@@ -146,14 +142,12 @@ static void test_hmac_prealloc(void)
result = g_new0(uint8_t, resultlen);
hmac = qcrypto_hmac_new(data->alg, (const uint8_t *)KEY,
- strlen(KEY), &err);
- g_assert(err == NULL);
+ strlen(KEY), &error_fatal);
g_assert(hmac != NULL);
ret = qcrypto_hmac_bytes(hmac, (const char *)INPUT_TEXT,
strlen(INPUT_TEXT), &result,
- &resultlen, &err);
- g_assert(err == NULL);
+ &resultlen, &error_fatal);
g_assert(ret == 0);
exp_output = data->hex_digest;
@@ -177,7 +171,6 @@ static void test_hmac_iov(void)
QCryptoHmac *hmac = NULL;
uint8_t *result = NULL;
size_t resultlen = 0;
- Error *err = NULL;
const char *exp_output = NULL;
int ret;
size_t j;
@@ -194,13 +187,11 @@ static void test_hmac_iov(void)
exp_output = data->hex_digest;
hmac = qcrypto_hmac_new(data->alg, (const uint8_t *)KEY,
- strlen(KEY), &err);
- g_assert(err == NULL);
+ strlen(KEY), &error_fatal);
g_assert(hmac != NULL);
ret = qcrypto_hmac_bytesv(hmac, iov, 3, &result,
- &resultlen, &err);
- g_assert(err == NULL);
+ &resultlen, &error_fatal);
g_assert(ret == 0);
for (j = 0; j < resultlen; j++) {
@@ -222,7 +213,6 @@ static void test_hmac_digest(void)
QCryptoHmacTestData *data = &test_data[i];
QCryptoHmac *hmac = NULL;
uint8_t *result = NULL;
- Error *err = NULL;
const char *exp_output = NULL;
int ret;
@@ -233,14 +223,12 @@ static void test_hmac_digest(void)
exp_output = data->hex_digest;
hmac = qcrypto_hmac_new(data->alg, (const uint8_t *)KEY,
- strlen(KEY), &err);
- g_assert(err == NULL);
+ strlen(KEY), &error_fatal);
g_assert(hmac != NULL);
ret = qcrypto_hmac_digest(hmac, (const char *)INPUT_TEXT,
strlen(INPUT_TEXT), (char **)&result,
- &err);
- g_assert(err == NULL);
+ &error_fatal);
g_assert(ret == 0);
g_assert_cmpstr((const char *)result, ==, exp_output);
diff --git a/tests/unit/test-crypto-ivgen.c b/tests/unit/test-crypto-ivgen.c
index f581e6a..29630ed 100644
--- a/tests/unit/test-crypto-ivgen.c
+++ b/tests/unit/test-crypto-ivgen.c
@@ -136,8 +136,15 @@ struct QCryptoIVGenTestData {
static void test_ivgen(const void *opaque)
{
const struct QCryptoIVGenTestData *data = opaque;
- uint8_t *iv = g_new0(uint8_t, data->niv);
- QCryptoIVGen *ivgen = qcrypto_ivgen_new(
+ g_autofree uint8_t *iv = g_new0(uint8_t, data->niv);
+ g_autoptr(QCryptoIVGen) ivgen = NULL;
+
+ if (!qcrypto_cipher_supports(data->cipheralg,
+ QCRYPTO_CIPHER_MODE_ECB)) {
+ return;
+ }
+
+ ivgen = qcrypto_ivgen_new(
data->ivalg,
data->cipheralg,
data->hashalg,
@@ -152,9 +159,6 @@ static void test_ivgen(const void *opaque)
&error_abort);
g_assert(memcmp(iv, data->iv, data->niv) == 0);
-
- qcrypto_ivgen_free(ivgen);
- g_free(iv);
}
int main(int argc, char **argv)
diff --git a/tests/unit/test-crypto-pbkdf.c b/tests/unit/test-crypto-pbkdf.c
index c50fd63..43c417f 100644
--- a/tests/unit/test-crypto-pbkdf.c
+++ b/tests/unit/test-crypto-pbkdf.c
@@ -229,10 +229,8 @@ static QCryptoPbkdfTestData test_data[] = {
},
/* non-RFC misc test data */
-#ifdef CONFIG_NETTLE
{
- /* empty password test.
- * Broken with libgcrypt <= 1.5.0, hence CONFIG_NETTLE */
+ /* empty password test. */
.path = "/crypto/pbkdf/nonrfc/sha1/iter2",
.hash = QCRYPTO_HASH_ALG_SHA1,
.iterations = 2,
@@ -244,7 +242,6 @@ static QCryptoPbkdfTestData test_data[] = {
"\xbf\x03\xe1\x1c\x71\xca\x79\x4e\x07\x97",
.nout = 20
},
-#endif
{
/* Password exceeds block size test */
.path = "/crypto/pbkdf/nonrfc/sha256/iter1200",
diff --git a/ui/vnc.c b/ui/vnc.c
index 0e5fcb2..af02522 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -2733,6 +2733,19 @@ static void authentication_failed(VncState *vs)
vnc_client_error(vs);
}
+static void
+vnc_munge_des_rfb_key(unsigned char *key, size_t nkey)
+{
+ size_t i;
+ for (i = 0; i < nkey; i++) {
+ uint8_t r = key[i];
+ r = (r & 0xf0) >> 4 | (r & 0x0f) << 4;
+ r = (r & 0xcc) >> 2 | (r & 0x33) << 2;
+ r = (r & 0xaa) >> 1 | (r & 0x55) << 1;
+ key[i] = r;
+ }
+}
+
static int protocol_client_auth_vnc(VncState *vs, uint8_t *data, size_t len)
{
unsigned char response[VNC_AUTH_CHALLENGE_SIZE];
@@ -2757,9 +2770,10 @@ static int protocol_client_auth_vnc(VncState *vs, uint8_t *data, size_t len)
pwlen = strlen(vs->vd->password);
for (i=0; i<sizeof(key); i++)
key[i] = i<pwlen ? vs->vd->password[i] : 0;
+ vnc_munge_des_rfb_key(key, sizeof(key));
cipher = qcrypto_cipher_new(
- QCRYPTO_CIPHER_ALG_DES_RFB,
+ QCRYPTO_CIPHER_ALG_DES,
QCRYPTO_CIPHER_MODE_ECB,
key, G_N_ELEMENTS(key),
&err);
@@ -4045,9 +4059,9 @@ void vnc_display_open(const char *id, Error **errp)
goto fail;
}
if (!qcrypto_cipher_supports(
- QCRYPTO_CIPHER_ALG_DES_RFB, QCRYPTO_CIPHER_MODE_ECB)) {
+ QCRYPTO_CIPHER_ALG_DES, QCRYPTO_CIPHER_MODE_ECB)) {
error_setg(errp,
- "Cipher backend does not support DES RFB algorithm");
+ "Cipher backend does not support DES algorithm");
goto fail;
}
}