Skip to content

Commit

Permalink
Merge remote-tracking branch 'remotes/berrange-gitlab/tags/crypto-and…
Browse files Browse the repository at this point in the history
…-more-pull-request' into staging

Merge crypto updates and misc fixes

 * Introduce a GNUTLS backend for crypto algorithms
 * Change crypto library preference gnutls > gcrypt > nettle > built-in
 * Remove built-in DES impl
 * Remove XTS mode from built-in AES impl
 * Fix seccomp rules to allow resource info getters
 * Fix migration performance test
 * Use GDateTime in io/ and net/rocker/ code
 * Improve docs for -smp

# gpg: Signature made Wed 14 Jul 2021 15:08:00 BST
# gpg:                using RSA key DAF3A6FDB26B62912D0E8E3FBE86EBB415104FDF
# gpg: Good signature from "Daniel P. Berrange <[email protected]>" [full]
# gpg:                 aka "Daniel P. Berrange <[email protected]>" [full]
# Primary key fingerprint: DAF3 A6FD B26B 6291 2D0E  8E3F BE86 EBB4 1510 4FDF

* remotes/berrange-gitlab/tags/crypto-and-more-pull-request: (26 commits)
  qemu-options: rewrite help for -smp options
  qemu-options: tweak to show that CPU count is optional
  qemu-options: re-arrange CPU topology options
  docs: fix typo s/Intel/AMD/ in CPU model notes
  tests/migration: fix unix socket migration
  seccomp: don't block getters for resource control syscalls
  io: use GDateTime for formatting timestamp for websock headers
  net/rocker: use GDateTime for formatting timestamp in debug messages
  crypto: prefer gnutls as the crypto backend if new enough
  crypto: add gnutls pbkdf provider
  crypto: add gnutls hmac provider
  crypto: add gnutls hash provider
  crypto: add gnutls cipher provider
  crypto: introduce build system for gnutls crypto backend
  crypto: flip priority of backends to prefer gcrypt
  crypto: replace 'des-rfb' cipher with 'des'
  crypto: delete built-in XTS cipher mode support
  crypto: delete built-in DES implementation
  crypto: add crypto tests for single block DES-ECB and DES-CBC
  crypto: drop custom XTS support in gcrypt driver
  ...

Signed-off-by: Peter Maydell <[email protected]>
  • Loading branch information
pm215 committed Jul 15, 2021
2 parents 438951e + 80d7835 commit d412734
Show file tree
Hide file tree
Showing 25 changed files with 865 additions and 913 deletions.
132 changes: 0 additions & 132 deletions crypto/cipher-builtin.c.inc
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,6 @@
*/

#include "crypto/aes.h"
#include "crypto/desrfb.h"
#include "crypto/xts.h"

typedef struct QCryptoCipherBuiltinAESContext QCryptoCipherBuiltinAESContext;
struct QCryptoCipherBuiltinAESContext {
Expand All @@ -32,7 +30,6 @@ typedef struct QCryptoCipherBuiltinAES QCryptoCipherBuiltinAES;
struct QCryptoCipherBuiltinAES {
QCryptoCipher base;
QCryptoCipherBuiltinAESContext key;
QCryptoCipherBuiltinAESContext key_tweak;
uint8_t iv[AES_BLOCK_SIZE];
};

Expand Down Expand Up @@ -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)
{
Expand Down Expand Up @@ -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;
Expand All @@ -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:
Expand All @@ -382,29 +266,13 @@ 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;
}

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;
Expand Down
143 changes: 3 additions & 140 deletions crypto/cipher-gcrypt.c.inc
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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;


Expand Down Expand Up @@ -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,
Expand All @@ -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:
Expand Down Expand Up @@ -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;
Expand All @@ -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;
Expand All @@ -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;
Expand Down
Loading

0 comments on commit d412734

Please sign in to comment.