From 6d92bdf44375f9819539927b7f234ba89ce9365e Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 28 Aug 2020 10:05:09 -0700 Subject: crypto: Rename cipher include files to .c.inc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit QEMU standard procedure for included c files is to use *.c.inc. E.g. there are a different set of checks that are applied. Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Richard Henderson Signed-off-by: Daniel P. Berrangé --- crypto/cipher-builtin.c.inc | 532 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 532 insertions(+) create mode 100644 crypto/cipher-builtin.c.inc (limited to 'crypto/cipher-builtin.c.inc') diff --git a/crypto/cipher-builtin.c.inc b/crypto/cipher-builtin.c.inc new file mode 100644 index 0000000000..6eafd39da0 --- /dev/null +++ b/crypto/cipher-builtin.c.inc @@ -0,0 +1,532 @@ +/* + * QEMU Crypto cipher built-in algorithms + * + * Copyright (c) 2015 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 . + * + */ + +#include "qemu/osdep.h" +#include "crypto/aes.h" +#include "crypto/desrfb.h" +#include "crypto/xts.h" +#include "cipherpriv.h" + +typedef struct QCryptoCipherBuiltinAESContext QCryptoCipherBuiltinAESContext; +struct QCryptoCipherBuiltinAESContext { + AES_KEY enc; + AES_KEY dec; +}; +typedef struct QCryptoCipherBuiltinAES QCryptoCipherBuiltinAES; +struct QCryptoCipherBuiltinAES { + QCryptoCipherBuiltinAESContext key; + QCryptoCipherBuiltinAESContext key_tweak; + uint8_t iv[AES_BLOCK_SIZE]; +}; +typedef struct QCryptoCipherBuiltinDESRFB QCryptoCipherBuiltinDESRFB; +struct QCryptoCipherBuiltinDESRFB { + uint8_t *key; + size_t nkey; +}; + +typedef struct QCryptoCipherBuiltin QCryptoCipherBuiltin; +struct QCryptoCipherBuiltin { + union { + QCryptoCipherBuiltinAES aes; + QCryptoCipherBuiltinDESRFB desrfb; + } state; + size_t blocksize; + void (*free)(QCryptoCipher *cipher); + int (*setiv)(QCryptoCipher *cipher, + const uint8_t *iv, size_t niv, + Error **errp); + int (*encrypt)(QCryptoCipher *cipher, + const void *in, + void *out, + size_t len, + Error **errp); + int (*decrypt)(QCryptoCipher *cipher, + const void *in, + void *out, + size_t len, + Error **errp); +}; + + +static void qcrypto_cipher_free_aes(QCryptoCipher *cipher) +{ + QCryptoCipherBuiltin *ctxt = cipher->opaque; + + g_free(ctxt); + cipher->opaque = NULL; +} + + +static void qcrypto_cipher_aes_ecb_encrypt(const AES_KEY *key, + const void *in, + void *out, + size_t len) +{ + const uint8_t *inptr = in; + uint8_t *outptr = out; + while (len) { + if (len > AES_BLOCK_SIZE) { + AES_encrypt(inptr, outptr, key); + inptr += AES_BLOCK_SIZE; + outptr += AES_BLOCK_SIZE; + len -= AES_BLOCK_SIZE; + } else { + uint8_t tmp1[AES_BLOCK_SIZE], tmp2[AES_BLOCK_SIZE]; + memcpy(tmp1, inptr, len); + /* Fill with 0 to avoid valgrind uninitialized reads */ + memset(tmp1 + len, 0, sizeof(tmp1) - len); + AES_encrypt(tmp1, tmp2, key); + memcpy(outptr, tmp2, len); + len = 0; + } + } +} + + +static void qcrypto_cipher_aes_ecb_decrypt(const AES_KEY *key, + const void *in, + void *out, + size_t len) +{ + const uint8_t *inptr = in; + uint8_t *outptr = out; + while (len) { + if (len > AES_BLOCK_SIZE) { + AES_decrypt(inptr, outptr, key); + inptr += AES_BLOCK_SIZE; + outptr += AES_BLOCK_SIZE; + len -= AES_BLOCK_SIZE; + } else { + uint8_t tmp1[AES_BLOCK_SIZE], tmp2[AES_BLOCK_SIZE]; + memcpy(tmp1, inptr, len); + /* Fill with 0 to avoid valgrind uninitialized reads */ + memset(tmp1 + len, 0, sizeof(tmp1) - len); + AES_decrypt(tmp1, tmp2, key); + memcpy(outptr, tmp2, len); + len = 0; + } + } +} + + +static void qcrypto_cipher_aes_xts_encrypt(const void *ctx, + size_t length, + uint8_t *dst, + const uint8_t *src) +{ + const QCryptoCipherBuiltinAESContext *aesctx = ctx; + + qcrypto_cipher_aes_ecb_encrypt(&aesctx->enc, src, dst, length); +} + + +static void qcrypto_cipher_aes_xts_decrypt(const void *ctx, + size_t length, + uint8_t *dst, + const uint8_t *src) +{ + const QCryptoCipherBuiltinAESContext *aesctx = ctx; + + qcrypto_cipher_aes_ecb_decrypt(&aesctx->dec, src, dst, length); +} + + +static int qcrypto_cipher_encrypt_aes(QCryptoCipher *cipher, + const void *in, + void *out, + size_t len, + Error **errp) +{ + QCryptoCipherBuiltin *ctxt = cipher->opaque; + + switch (cipher->mode) { + case QCRYPTO_CIPHER_MODE_ECB: + qcrypto_cipher_aes_ecb_encrypt(&ctxt->state.aes.key.enc, + in, out, len); + break; + case QCRYPTO_CIPHER_MODE_CBC: + AES_cbc_encrypt(in, out, len, + &ctxt->state.aes.key.enc, + ctxt->state.aes.iv, 1); + break; + case QCRYPTO_CIPHER_MODE_XTS: + xts_encrypt(&ctxt->state.aes.key, + &ctxt->state.aes.key_tweak, + qcrypto_cipher_aes_xts_encrypt, + qcrypto_cipher_aes_xts_decrypt, + ctxt->state.aes.iv, + len, out, in); + break; + default: + g_assert_not_reached(); + } + + return 0; +} + + +static int qcrypto_cipher_decrypt_aes(QCryptoCipher *cipher, + const void *in, + void *out, + size_t len, + Error **errp) +{ + QCryptoCipherBuiltin *ctxt = cipher->opaque; + + switch (cipher->mode) { + case QCRYPTO_CIPHER_MODE_ECB: + qcrypto_cipher_aes_ecb_decrypt(&ctxt->state.aes.key.dec, + in, out, len); + break; + case QCRYPTO_CIPHER_MODE_CBC: + AES_cbc_encrypt(in, out, len, + &ctxt->state.aes.key.dec, + ctxt->state.aes.iv, 0); + break; + case QCRYPTO_CIPHER_MODE_XTS: + xts_decrypt(&ctxt->state.aes.key, + &ctxt->state.aes.key_tweak, + qcrypto_cipher_aes_xts_encrypt, + qcrypto_cipher_aes_xts_decrypt, + ctxt->state.aes.iv, + len, out, in); + break; + default: + g_assert_not_reached(); + } + + return 0; +} + +static int qcrypto_cipher_setiv_aes(QCryptoCipher *cipher, + const uint8_t *iv, size_t niv, + Error **errp) +{ + QCryptoCipherBuiltin *ctxt = cipher->opaque; + if (niv != AES_BLOCK_SIZE) { + error_setg(errp, "IV must be %d bytes not %zu", + AES_BLOCK_SIZE, niv); + return -1; + } + + memcpy(ctxt->state.aes.iv, iv, AES_BLOCK_SIZE); + + return 0; +} + + + + +static QCryptoCipherBuiltin * +qcrypto_cipher_init_aes(QCryptoCipherMode mode, + const uint8_t *key, size_t nkey, + Error **errp) +{ + QCryptoCipherBuiltin *ctxt; + + if (mode != QCRYPTO_CIPHER_MODE_CBC && + mode != QCRYPTO_CIPHER_MODE_ECB && + mode != QCRYPTO_CIPHER_MODE_XTS) { + error_setg(errp, "Unsupported cipher mode %s", + QCryptoCipherMode_str(mode)); + return NULL; + } + + ctxt = g_new0(QCryptoCipherBuiltin, 1); + + if (mode == QCRYPTO_CIPHER_MODE_XTS) { + if (AES_set_encrypt_key(key, nkey * 4, &ctxt->state.aes.key.enc) != 0) { + error_setg(errp, "Failed to set encryption key"); + goto error; + } + + if (AES_set_decrypt_key(key, nkey * 4, &ctxt->state.aes.key.dec) != 0) { + error_setg(errp, "Failed to set decryption key"); + goto error; + } + + if (AES_set_encrypt_key(key + (nkey / 2), nkey * 4, + &ctxt->state.aes.key_tweak.enc) != 0) { + error_setg(errp, "Failed to set encryption key"); + goto error; + } + + if (AES_set_decrypt_key(key + (nkey / 2), nkey * 4, + &ctxt->state.aes.key_tweak.dec) != 0) { + error_setg(errp, "Failed to set decryption key"); + goto error; + } + } else { + if (AES_set_encrypt_key(key, nkey * 8, &ctxt->state.aes.key.enc) != 0) { + error_setg(errp, "Failed to set encryption key"); + goto error; + } + + if (AES_set_decrypt_key(key, nkey * 8, &ctxt->state.aes.key.dec) != 0) { + error_setg(errp, "Failed to set decryption key"); + goto error; + } + } + + ctxt->blocksize = AES_BLOCK_SIZE; + ctxt->free = qcrypto_cipher_free_aes; + ctxt->setiv = qcrypto_cipher_setiv_aes; + ctxt->encrypt = qcrypto_cipher_encrypt_aes; + ctxt->decrypt = qcrypto_cipher_decrypt_aes; + + return ctxt; + + error: + g_free(ctxt); + return NULL; +} + + +static void qcrypto_cipher_free_des_rfb(QCryptoCipher *cipher) +{ + QCryptoCipherBuiltin *ctxt = cipher->opaque; + + g_free(ctxt->state.desrfb.key); + g_free(ctxt); + cipher->opaque = NULL; +} + + +static int qcrypto_cipher_encrypt_des_rfb(QCryptoCipher *cipher, + const void *in, + void *out, + size_t len, + Error **errp) +{ + QCryptoCipherBuiltin *ctxt = cipher->opaque; + size_t i; + + if (len % 8) { + error_setg(errp, "Buffer size must be multiple of 8 not %zu", + len); + return -1; + } + + deskey(ctxt->state.desrfb.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) +{ + QCryptoCipherBuiltin *ctxt = cipher->opaque; + size_t i; + + if (len % 8) { + error_setg(errp, "Buffer size must be multiple of 8 not %zu", + len); + return -1; + } + + deskey(ctxt->state.desrfb.key, DE1); + + for (i = 0; i < len; i += 8) { + des((void *)in + i, out + i); + } + + return 0; +} + + +static int qcrypto_cipher_setiv_des_rfb(QCryptoCipher *cipher, + const uint8_t *iv, size_t niv, + Error **errp) +{ + error_setg(errp, "Setting IV is not supported"); + return -1; +} + + +static QCryptoCipherBuiltin * +qcrypto_cipher_init_des_rfb(QCryptoCipherMode mode, + const uint8_t *key, size_t nkey, + Error **errp) +{ + QCryptoCipherBuiltin *ctxt; + + if (mode != QCRYPTO_CIPHER_MODE_ECB) { + error_setg(errp, "Unsupported cipher mode %s", + QCryptoCipherMode_str(mode)); + return NULL; + } + + ctxt = g_new0(QCryptoCipherBuiltin, 1); + + ctxt->state.desrfb.key = g_new0(uint8_t, nkey); + memcpy(ctxt->state.desrfb.key, key, nkey); + ctxt->state.desrfb.nkey = nkey; + + ctxt->blocksize = 8; + ctxt->free = qcrypto_cipher_free_des_rfb; + ctxt->setiv = qcrypto_cipher_setiv_des_rfb; + ctxt->encrypt = qcrypto_cipher_encrypt_des_rfb; + ctxt->decrypt = qcrypto_cipher_decrypt_des_rfb; + + return ctxt; +} + + +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; + } +} + + +static QCryptoCipherBuiltin *qcrypto_cipher_ctx_new(QCryptoCipherAlgorithm alg, + QCryptoCipherMode mode, + const uint8_t *key, + size_t nkey, + Error **errp) +{ + QCryptoCipherBuiltin *ctxt; + + 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_str(mode)); + return NULL; + } + + if (!qcrypto_cipher_validate_key_length(alg, mode, nkey, errp)) { + return NULL; + } + + switch (alg) { + case QCRYPTO_CIPHER_ALG_DES_RFB: + ctxt = qcrypto_cipher_init_des_rfb(mode, key, nkey, errp); + break; + case QCRYPTO_CIPHER_ALG_AES_128: + case QCRYPTO_CIPHER_ALG_AES_192: + case QCRYPTO_CIPHER_ALG_AES_256: + ctxt = qcrypto_cipher_init_aes(mode, key, nkey, errp); + break; + default: + error_setg(errp, + "Unsupported cipher algorithm %s", + QCryptoCipherAlgorithm_str(alg)); + return NULL; + } + + return ctxt; +} + +static void +qcrypto_builtin_cipher_ctx_free(QCryptoCipher *cipher) +{ + QCryptoCipherBuiltin *ctxt; + + ctxt = cipher->opaque; + ctxt->free(cipher); +} + + +static int +qcrypto_builtin_cipher_encrypt(QCryptoCipher *cipher, + const void *in, + void *out, + size_t len, + Error **errp) +{ + QCryptoCipherBuiltin *ctxt = cipher->opaque; + + if (len & (ctxt->blocksize - 1)) { + error_setg(errp, "Length %zu must be a multiple of block size %zu", + len, ctxt->blocksize); + return -1; + } + + return ctxt->encrypt(cipher, in, out, len, errp); +} + + +static int +qcrypto_builtin_cipher_decrypt(QCryptoCipher *cipher, + const void *in, + void *out, + size_t len, + Error **errp) +{ + QCryptoCipherBuiltin *ctxt = cipher->opaque; + + if (len & (ctxt->blocksize - 1)) { + error_setg(errp, "Length %zu must be a multiple of block size %zu", + len, ctxt->blocksize); + return -1; + } + + return ctxt->decrypt(cipher, in, out, len, errp); +} + + +static int +qcrypto_builtin_cipher_setiv(QCryptoCipher *cipher, + const uint8_t *iv, size_t niv, + Error **errp) +{ + QCryptoCipherBuiltin *ctxt = cipher->opaque; + + return ctxt->setiv(cipher, iv, niv, errp); +} + + +static struct QCryptoCipherDriver qcrypto_cipher_lib_driver = { + .cipher_encrypt = qcrypto_builtin_cipher_encrypt, + .cipher_decrypt = qcrypto_builtin_cipher_decrypt, + .cipher_setiv = qcrypto_builtin_cipher_setiv, + .cipher_free = qcrypto_builtin_cipher_ctx_free, +}; -- cgit 1.4.1 From 7d823bf4e9241aa960de50d2b09ac8f9560bcdd8 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 28 Aug 2020 10:05:10 -0700 Subject: crypto: Remove redundant includes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Both qemu/osdep.h and cipherpriv.h have already been included by the parent cipher.c. Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Richard Henderson Signed-off-by: Daniel P. Berrangé --- crypto/cipher-builtin.c.inc | 2 -- crypto/cipher-gcrypt.c.inc | 2 -- crypto/cipher-nettle.c.inc | 2 -- 3 files changed, 6 deletions(-) (limited to 'crypto/cipher-builtin.c.inc') diff --git a/crypto/cipher-builtin.c.inc b/crypto/cipher-builtin.c.inc index 6eafd39da0..56d45b0227 100644 --- a/crypto/cipher-builtin.c.inc +++ b/crypto/cipher-builtin.c.inc @@ -18,11 +18,9 @@ * */ -#include "qemu/osdep.h" #include "crypto/aes.h" #include "crypto/desrfb.h" #include "crypto/xts.h" -#include "cipherpriv.h" typedef struct QCryptoCipherBuiltinAESContext QCryptoCipherBuiltinAESContext; struct QCryptoCipherBuiltinAESContext { diff --git a/crypto/cipher-gcrypt.c.inc b/crypto/cipher-gcrypt.c.inc index 81e4745bff..a62839914b 100644 --- a/crypto/cipher-gcrypt.c.inc +++ b/crypto/cipher-gcrypt.c.inc @@ -18,11 +18,9 @@ * */ -#include "qemu/osdep.h" #ifdef CONFIG_QEMU_PRIVATE_XTS #include "crypto/xts.h" #endif -#include "cipherpriv.h" #include diff --git a/crypto/cipher-nettle.c.inc b/crypto/cipher-nettle.c.inc index 0677fdfd33..256931a823 100644 --- a/crypto/cipher-nettle.c.inc +++ b/crypto/cipher-nettle.c.inc @@ -18,11 +18,9 @@ * */ -#include "qemu/osdep.h" #ifdef CONFIG_QEMU_PRIVATE_XTS #include "crypto/xts.h" #endif -#include "cipherpriv.h" #include #include -- cgit 1.4.1 From 7b5dbfb777ff4894ebcd71f5014d26abeef916c6 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 28 Aug 2020 10:05:13 -0700 Subject: crypto: Use the correct const type for driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This allows the in memory structures to be read-only. Signed-off-by: Richard Henderson Signed-off-by: Daniel P. Berrangé --- crypto/cipher-afalg.c | 2 +- crypto/cipher-builtin.c.inc | 2 +- crypto/cipher-gcrypt.c.inc | 2 +- crypto/cipher-nettle.c.inc | 2 +- crypto/cipher.c | 12 ++++++------ crypto/cipherpriv.h | 2 +- include/crypto/cipher.h | 2 +- 7 files changed, 12 insertions(+), 12 deletions(-) (limited to 'crypto/cipher-builtin.c.inc') diff --git a/crypto/cipher-afalg.c b/crypto/cipher-afalg.c index cd72284690..5c7c44761b 100644 --- a/crypto/cipher-afalg.c +++ b/crypto/cipher-afalg.c @@ -218,7 +218,7 @@ static void qcrypto_afalg_comm_ctx_free(QCryptoCipher *cipher) qcrypto_afalg_comm_free(cipher->opaque); } -struct QCryptoCipherDriver qcrypto_cipher_afalg_driver = { +const struct QCryptoCipherDriver qcrypto_cipher_afalg_driver = { .cipher_encrypt = qcrypto_afalg_cipher_encrypt, .cipher_decrypt = qcrypto_afalg_cipher_decrypt, .cipher_setiv = qcrypto_afalg_cipher_setiv, diff --git a/crypto/cipher-builtin.c.inc b/crypto/cipher-builtin.c.inc index 56d45b0227..156f32f1c7 100644 --- a/crypto/cipher-builtin.c.inc +++ b/crypto/cipher-builtin.c.inc @@ -522,7 +522,7 @@ qcrypto_builtin_cipher_setiv(QCryptoCipher *cipher, } -static struct QCryptoCipherDriver qcrypto_cipher_lib_driver = { +static const struct QCryptoCipherDriver qcrypto_cipher_lib_driver = { .cipher_encrypt = qcrypto_builtin_cipher_encrypt, .cipher_decrypt = qcrypto_builtin_cipher_decrypt, .cipher_setiv = qcrypto_builtin_cipher_setiv, diff --git a/crypto/cipher-gcrypt.c.inc b/crypto/cipher-gcrypt.c.inc index a62839914b..18850fadb9 100644 --- a/crypto/cipher-gcrypt.c.inc +++ b/crypto/cipher-gcrypt.c.inc @@ -413,7 +413,7 @@ qcrypto_gcrypt_cipher_setiv(QCryptoCipher *cipher, } -static struct QCryptoCipherDriver qcrypto_cipher_lib_driver = { +static const struct QCryptoCipherDriver qcrypto_cipher_lib_driver = { .cipher_encrypt = qcrypto_gcrypt_cipher_encrypt, .cipher_decrypt = qcrypto_gcrypt_cipher_decrypt, .cipher_setiv = qcrypto_gcrypt_cipher_setiv, diff --git a/crypto/cipher-nettle.c.inc b/crypto/cipher-nettle.c.inc index 0404cfc6da..6ecce5e8ea 100644 --- a/crypto/cipher-nettle.c.inc +++ b/crypto/cipher-nettle.c.inc @@ -724,7 +724,7 @@ qcrypto_nettle_cipher_setiv(QCryptoCipher *cipher, } -static struct QCryptoCipherDriver qcrypto_cipher_lib_driver = { +static const struct QCryptoCipherDriver qcrypto_cipher_lib_driver = { .cipher_encrypt = qcrypto_nettle_cipher_encrypt, .cipher_decrypt = qcrypto_nettle_cipher_decrypt, .cipher_setiv = qcrypto_nettle_cipher_setiv, diff --git a/crypto/cipher.c b/crypto/cipher.c index 005b5da4de..3ca4a7e662 100644 --- a/crypto/cipher.c +++ b/crypto/cipher.c @@ -165,7 +165,7 @@ QCryptoCipher *qcrypto_cipher_new(QCryptoCipherAlgorithm alg, { QCryptoCipher *cipher; void *ctx = NULL; - QCryptoCipherDriver *drv = NULL; + const QCryptoCipherDriver *drv = NULL; #ifdef CONFIG_AF_ALG ctx = qcrypto_afalg_cipher_ctx_new(alg, mode, key, nkey, NULL); @@ -187,7 +187,7 @@ QCryptoCipher *qcrypto_cipher_new(QCryptoCipherAlgorithm alg, cipher->alg = alg; cipher->mode = mode; cipher->opaque = ctx; - cipher->driver = (void *)drv; + cipher->driver = drv; return cipher; } @@ -199,7 +199,7 @@ int qcrypto_cipher_encrypt(QCryptoCipher *cipher, size_t len, Error **errp) { - QCryptoCipherDriver *drv = cipher->driver; + const QCryptoCipherDriver *drv = cipher->driver; return drv->cipher_encrypt(cipher, in, out, len, errp); } @@ -210,7 +210,7 @@ int qcrypto_cipher_decrypt(QCryptoCipher *cipher, size_t len, Error **errp) { - QCryptoCipherDriver *drv = cipher->driver; + const QCryptoCipherDriver *drv = cipher->driver; return drv->cipher_decrypt(cipher, in, out, len, errp); } @@ -219,14 +219,14 @@ int qcrypto_cipher_setiv(QCryptoCipher *cipher, const uint8_t *iv, size_t niv, Error **errp) { - QCryptoCipherDriver *drv = cipher->driver; + const QCryptoCipherDriver *drv = cipher->driver; return drv->cipher_setiv(cipher, iv, niv, errp); } void qcrypto_cipher_free(QCryptoCipher *cipher) { - QCryptoCipherDriver *drv; + const QCryptoCipherDriver *drv; if (cipher) { drv = cipher->driver; drv->cipher_free(cipher); diff --git a/crypto/cipherpriv.h b/crypto/cipherpriv.h index 9228c9fc3a..b73be33bd2 100644 --- a/crypto/cipherpriv.h +++ b/crypto/cipherpriv.h @@ -47,7 +47,7 @@ qcrypto_afalg_cipher_ctx_new(QCryptoCipherAlgorithm alg, const uint8_t *key, size_t nkey, Error **errp); -extern struct QCryptoCipherDriver qcrypto_cipher_afalg_driver; +extern const struct QCryptoCipherDriver qcrypto_cipher_afalg_driver; #endif diff --git a/include/crypto/cipher.h b/include/crypto/cipher.h index 8a42a683a4..cc57179a4d 100644 --- a/include/crypto/cipher.h +++ b/include/crypto/cipher.h @@ -81,7 +81,7 @@ struct QCryptoCipher { QCryptoCipherAlgorithm alg; QCryptoCipherMode mode; void *opaque; - void *driver; + const QCryptoCipherDriver *driver; }; /** -- cgit 1.4.1 From 3eedf5cc9d45f94e2fd229f0a7aaca556a4ac734 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 28 Aug 2020 10:05:14 -0700 Subject: crypto: Allocate QCryptoCipher with the subclass MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Merge the allocation of "opaque" into the allocation of "cipher". This is step one in reducing the indirection in these classes. Signed-off-by: Richard Henderson Signed-off-by: Daniel P. Berrangé --- crypto/afalgpriv.h | 3 ++ crypto/cipher-afalg.c | 20 +++++++------ crypto/cipher-builtin.c.inc | 68 +++++++++++++++++++++++---------------------- crypto/cipher-gcrypt.c.inc | 23 ++++++++------- crypto/cipher-nettle.c.inc | 24 ++++++++-------- crypto/cipher.c | 20 +++++-------- crypto/cipherpriv.h | 2 +- include/crypto/cipher.h | 1 - 8 files changed, 84 insertions(+), 77 deletions(-) (limited to 'crypto/cipher-builtin.c.inc') diff --git a/crypto/afalgpriv.h b/crypto/afalgpriv.h index f6550b5c51..5a2393f1b7 100644 --- a/crypto/afalgpriv.h +++ b/crypto/afalgpriv.h @@ -15,6 +15,7 @@ #define QCRYPTO_AFALGPRIV_H #include +#include "crypto/cipher.h" #define SALG_TYPE_LEN_MAX 14 #define SALG_NAME_LEN_MAX 64 @@ -32,6 +33,8 @@ typedef struct QCryptoAFAlg QCryptoAFAlg; struct QCryptoAFAlg { + QCryptoCipher base; + int tfmfd; int opfd; struct msghdr *msg; diff --git a/crypto/cipher-afalg.c b/crypto/cipher-afalg.c index 5c7c44761b..86e5249bd6 100644 --- a/crypto/cipher-afalg.c +++ b/crypto/cipher-afalg.c @@ -58,7 +58,7 @@ qcrypto_afalg_cipher_format_name(QCryptoCipherAlgorithm alg, return name; } -QCryptoAFAlg * +QCryptoCipher * qcrypto_afalg_cipher_ctx_new(QCryptoCipherAlgorithm alg, QCryptoCipherMode mode, const uint8_t *key, @@ -109,7 +109,7 @@ qcrypto_afalg_cipher_ctx_new(QCryptoCipherAlgorithm alg, } afalg->cmsg = CMSG_FIRSTHDR(afalg->msg); - return afalg; + return &afalg->base; } static int @@ -117,9 +117,9 @@ qcrypto_afalg_cipher_setiv(QCryptoCipher *cipher, const uint8_t *iv, size_t niv, Error **errp) { + QCryptoAFAlg *afalg = container_of(cipher, QCryptoAFAlg, base); struct af_alg_iv *alg_iv; size_t expect_niv; - QCryptoAFAlg *afalg = cipher->opaque; expect_niv = qcrypto_cipher_get_iv_len(cipher->alg, cipher->mode); if (niv != expect_niv) { @@ -200,8 +200,9 @@ qcrypto_afalg_cipher_encrypt(QCryptoCipher *cipher, const void *in, void *out, size_t len, Error **errp) { - return qcrypto_afalg_cipher_op(cipher->opaque, in, out, - len, true, errp); + QCryptoAFAlg *afalg = container_of(cipher, QCryptoAFAlg, base); + + return qcrypto_afalg_cipher_op(afalg, in, out, len, true, errp); } static int @@ -209,13 +210,16 @@ qcrypto_afalg_cipher_decrypt(QCryptoCipher *cipher, const void *in, void *out, size_t len, Error **errp) { - return qcrypto_afalg_cipher_op(cipher->opaque, in, out, - len, false, errp); + QCryptoAFAlg *afalg = container_of(cipher, QCryptoAFAlg, base); + + return qcrypto_afalg_cipher_op(afalg, in, out, len, false, errp); } static void qcrypto_afalg_comm_ctx_free(QCryptoCipher *cipher) { - qcrypto_afalg_comm_free(cipher->opaque); + QCryptoAFAlg *afalg = container_of(cipher, QCryptoAFAlg, base); + + qcrypto_afalg_comm_free(afalg); } const struct QCryptoCipherDriver qcrypto_cipher_afalg_driver = { diff --git a/crypto/cipher-builtin.c.inc b/crypto/cipher-builtin.c.inc index 156f32f1c7..6a03e23040 100644 --- a/crypto/cipher-builtin.c.inc +++ b/crypto/cipher-builtin.c.inc @@ -41,6 +41,8 @@ struct QCryptoCipherBuiltinDESRFB { typedef struct QCryptoCipherBuiltin QCryptoCipherBuiltin; struct QCryptoCipherBuiltin { + QCryptoCipher base; + union { QCryptoCipherBuiltinAES aes; QCryptoCipherBuiltinDESRFB desrfb; @@ -65,10 +67,7 @@ struct QCryptoCipherBuiltin { static void qcrypto_cipher_free_aes(QCryptoCipher *cipher) { - QCryptoCipherBuiltin *ctxt = cipher->opaque; - - g_free(ctxt); - cipher->opaque = NULL; + g_free(cipher); } @@ -152,7 +151,8 @@ static int qcrypto_cipher_encrypt_aes(QCryptoCipher *cipher, size_t len, Error **errp) { - QCryptoCipherBuiltin *ctxt = cipher->opaque; + QCryptoCipherBuiltin *ctxt + = container_of(cipher, QCryptoCipherBuiltin, base); switch (cipher->mode) { case QCRYPTO_CIPHER_MODE_ECB: @@ -186,7 +186,8 @@ static int qcrypto_cipher_decrypt_aes(QCryptoCipher *cipher, size_t len, Error **errp) { - QCryptoCipherBuiltin *ctxt = cipher->opaque; + QCryptoCipherBuiltin *ctxt + = container_of(cipher, QCryptoCipherBuiltin, base); switch (cipher->mode) { case QCRYPTO_CIPHER_MODE_ECB: @@ -217,7 +218,9 @@ static int qcrypto_cipher_setiv_aes(QCryptoCipher *cipher, const uint8_t *iv, size_t niv, Error **errp) { - QCryptoCipherBuiltin *ctxt = cipher->opaque; + QCryptoCipherBuiltin *ctxt + = container_of(cipher, QCryptoCipherBuiltin, base); + if (niv != AES_BLOCK_SIZE) { error_setg(errp, "IV must be %d bytes not %zu", AES_BLOCK_SIZE, niv); @@ -232,7 +235,7 @@ static int qcrypto_cipher_setiv_aes(QCryptoCipher *cipher, -static QCryptoCipherBuiltin * +static QCryptoCipher * qcrypto_cipher_init_aes(QCryptoCipherMode mode, const uint8_t *key, size_t nkey, Error **errp) @@ -289,7 +292,7 @@ qcrypto_cipher_init_aes(QCryptoCipherMode mode, ctxt->encrypt = qcrypto_cipher_encrypt_aes; ctxt->decrypt = qcrypto_cipher_decrypt_aes; - return ctxt; + return &ctxt->base; error: g_free(ctxt); @@ -299,11 +302,11 @@ qcrypto_cipher_init_aes(QCryptoCipherMode mode, static void qcrypto_cipher_free_des_rfb(QCryptoCipher *cipher) { - QCryptoCipherBuiltin *ctxt = cipher->opaque; + QCryptoCipherBuiltin *ctxt + = container_of(cipher, QCryptoCipherBuiltin, base); g_free(ctxt->state.desrfb.key); g_free(ctxt); - cipher->opaque = NULL; } @@ -313,7 +316,8 @@ static int qcrypto_cipher_encrypt_des_rfb(QCryptoCipher *cipher, size_t len, Error **errp) { - QCryptoCipherBuiltin *ctxt = cipher->opaque; + QCryptoCipherBuiltin *ctxt + = container_of(cipher, QCryptoCipherBuiltin, base); size_t i; if (len % 8) { @@ -338,7 +342,8 @@ static int qcrypto_cipher_decrypt_des_rfb(QCryptoCipher *cipher, size_t len, Error **errp) { - QCryptoCipherBuiltin *ctxt = cipher->opaque; + QCryptoCipherBuiltin *ctxt + = container_of(cipher, QCryptoCipherBuiltin, base); size_t i; if (len % 8) { @@ -366,7 +371,7 @@ static int qcrypto_cipher_setiv_des_rfb(QCryptoCipher *cipher, } -static QCryptoCipherBuiltin * +static QCryptoCipher * qcrypto_cipher_init_des_rfb(QCryptoCipherMode mode, const uint8_t *key, size_t nkey, Error **errp) @@ -391,7 +396,7 @@ qcrypto_cipher_init_des_rfb(QCryptoCipherMode mode, ctxt->encrypt = qcrypto_cipher_encrypt_des_rfb; ctxt->decrypt = qcrypto_cipher_decrypt_des_rfb; - return ctxt; + return &ctxt->base; } @@ -421,14 +426,12 @@ bool qcrypto_cipher_supports(QCryptoCipherAlgorithm alg, } -static QCryptoCipherBuiltin *qcrypto_cipher_ctx_new(QCryptoCipherAlgorithm alg, - QCryptoCipherMode mode, - const uint8_t *key, - size_t nkey, - Error **errp) +static QCryptoCipher *qcrypto_cipher_ctx_new(QCryptoCipherAlgorithm alg, + QCryptoCipherMode mode, + const uint8_t *key, + size_t nkey, + Error **errp) { - QCryptoCipherBuiltin *ctxt; - switch (mode) { case QCRYPTO_CIPHER_MODE_ECB: case QCRYPTO_CIPHER_MODE_CBC: @@ -446,29 +449,25 @@ static QCryptoCipherBuiltin *qcrypto_cipher_ctx_new(QCryptoCipherAlgorithm alg, switch (alg) { case QCRYPTO_CIPHER_ALG_DES_RFB: - ctxt = qcrypto_cipher_init_des_rfb(mode, key, nkey, errp); - break; + return qcrypto_cipher_init_des_rfb(mode, key, nkey, errp); case QCRYPTO_CIPHER_ALG_AES_128: case QCRYPTO_CIPHER_ALG_AES_192: case QCRYPTO_CIPHER_ALG_AES_256: - ctxt = qcrypto_cipher_init_aes(mode, key, nkey, errp); - break; + return qcrypto_cipher_init_aes(mode, key, nkey, errp); default: error_setg(errp, "Unsupported cipher algorithm %s", QCryptoCipherAlgorithm_str(alg)); return NULL; } - - return ctxt; } static void qcrypto_builtin_cipher_ctx_free(QCryptoCipher *cipher) { - QCryptoCipherBuiltin *ctxt; + QCryptoCipherBuiltin *ctxt + = container_of(cipher, QCryptoCipherBuiltin, base); - ctxt = cipher->opaque; ctxt->free(cipher); } @@ -480,7 +479,8 @@ qcrypto_builtin_cipher_encrypt(QCryptoCipher *cipher, size_t len, Error **errp) { - QCryptoCipherBuiltin *ctxt = cipher->opaque; + QCryptoCipherBuiltin *ctxt + = container_of(cipher, QCryptoCipherBuiltin, base); if (len & (ctxt->blocksize - 1)) { error_setg(errp, "Length %zu must be a multiple of block size %zu", @@ -499,7 +499,8 @@ qcrypto_builtin_cipher_decrypt(QCryptoCipher *cipher, size_t len, Error **errp) { - QCryptoCipherBuiltin *ctxt = cipher->opaque; + QCryptoCipherBuiltin *ctxt + = container_of(cipher, QCryptoCipherBuiltin, base); if (len & (ctxt->blocksize - 1)) { error_setg(errp, "Length %zu must be a multiple of block size %zu", @@ -516,7 +517,8 @@ qcrypto_builtin_cipher_setiv(QCryptoCipher *cipher, const uint8_t *iv, size_t niv, Error **errp) { - QCryptoCipherBuiltin *ctxt = cipher->opaque; + QCryptoCipherBuiltin *ctxt + = container_of(cipher, QCryptoCipherBuiltin, base); return ctxt->setiv(cipher, iv, niv, errp); } diff --git a/crypto/cipher-gcrypt.c.inc b/crypto/cipher-gcrypt.c.inc index 18850fadb9..3b3c85e265 100644 --- a/crypto/cipher-gcrypt.c.inc +++ b/crypto/cipher-gcrypt.c.inc @@ -58,6 +58,7 @@ bool qcrypto_cipher_supports(QCryptoCipherAlgorithm alg, typedef struct QCryptoCipherGcrypt QCryptoCipherGcrypt; struct QCryptoCipherGcrypt { + QCryptoCipher base; gcry_cipher_hd_t handle; size_t blocksize; #ifdef CONFIG_QEMU_PRIVATE_XTS @@ -86,11 +87,11 @@ qcrypto_gcrypt_cipher_free_ctx(QCryptoCipherGcrypt *ctx, } -static QCryptoCipherGcrypt *qcrypto_cipher_ctx_new(QCryptoCipherAlgorithm alg, - QCryptoCipherMode mode, - const uint8_t *key, - size_t nkey, - Error **errp) +static QCryptoCipher *qcrypto_cipher_ctx_new(QCryptoCipherAlgorithm alg, + QCryptoCipherMode mode, + const uint8_t *key, + size_t nkey, + Error **errp) { QCryptoCipherGcrypt *ctx; gcry_error_t err; @@ -257,7 +258,7 @@ static QCryptoCipherGcrypt *qcrypto_cipher_ctx_new(QCryptoCipherAlgorithm alg, } #endif - return ctx; + return &ctx->base; error: qcrypto_gcrypt_cipher_free_ctx(ctx, mode); @@ -268,7 +269,9 @@ static QCryptoCipherGcrypt *qcrypto_cipher_ctx_new(QCryptoCipherAlgorithm alg, static void qcrypto_gcrypt_cipher_ctx_free(QCryptoCipher *cipher) { - qcrypto_gcrypt_cipher_free_ctx(cipher->opaque, cipher->mode); + QCryptoCipherGcrypt *ctx = container_of(cipher, QCryptoCipherGcrypt, base); + + qcrypto_gcrypt_cipher_free_ctx(ctx, cipher->mode); } @@ -301,7 +304,7 @@ qcrypto_gcrypt_cipher_encrypt(QCryptoCipher *cipher, size_t len, Error **errp) { - QCryptoCipherGcrypt *ctx = cipher->opaque; + QCryptoCipherGcrypt *ctx = container_of(cipher, QCryptoCipherGcrypt, base); gcry_error_t err; if (len & (ctx->blocksize - 1)) { @@ -340,7 +343,7 @@ qcrypto_gcrypt_cipher_decrypt(QCryptoCipher *cipher, size_t len, Error **errp) { - QCryptoCipherGcrypt *ctx = cipher->opaque; + QCryptoCipherGcrypt *ctx = container_of(cipher, QCryptoCipherGcrypt, base); gcry_error_t err; if (len & (ctx->blocksize - 1)) { @@ -376,7 +379,7 @@ qcrypto_gcrypt_cipher_setiv(QCryptoCipher *cipher, const uint8_t *iv, size_t niv, Error **errp) { - QCryptoCipherGcrypt *ctx = cipher->opaque; + QCryptoCipherGcrypt *ctx = container_of(cipher, QCryptoCipherGcrypt, base); gcry_error_t err; if (niv != ctx->blocksize) { diff --git a/crypto/cipher-nettle.c.inc b/crypto/cipher-nettle.c.inc index 6ecce5e8ea..d8371d1f37 100644 --- a/crypto/cipher-nettle.c.inc +++ b/crypto/cipher-nettle.c.inc @@ -294,6 +294,8 @@ static void twofish_decrypt_wrapper(const void *ctx, size_t length, typedef struct QCryptoCipherNettle QCryptoCipherNettle; struct QCryptoCipherNettle { + QCryptoCipher base; + /* Primary cipher context for all modes */ void *ctx; /* Second cipher context for XTS mode only */ @@ -355,11 +357,11 @@ qcrypto_nettle_cipher_free_ctx(QCryptoCipherNettle *ctx) } -static QCryptoCipherNettle *qcrypto_cipher_ctx_new(QCryptoCipherAlgorithm alg, - QCryptoCipherMode mode, - const uint8_t *key, - size_t nkey, - Error **errp) +static QCryptoCipher *qcrypto_cipher_ctx_new(QCryptoCipherAlgorithm alg, + QCryptoCipherMode mode, + const uint8_t *key, + size_t nkey, + Error **errp) { QCryptoCipherNettle *ctx; uint8_t *rfbkey; @@ -585,7 +587,7 @@ static QCryptoCipherNettle *qcrypto_cipher_ctx_new(QCryptoCipherAlgorithm alg, ctx->iv = g_new0(uint8_t, ctx->blocksize); - return ctx; + return &ctx->base; error: qcrypto_nettle_cipher_free_ctx(ctx); @@ -596,9 +598,8 @@ static QCryptoCipherNettle *qcrypto_cipher_ctx_new(QCryptoCipherAlgorithm alg, static void qcrypto_nettle_cipher_ctx_free(QCryptoCipher *cipher) { - QCryptoCipherNettle *ctx; + QCryptoCipherNettle *ctx = container_of(cipher, QCryptoCipherNettle, base); - ctx = cipher->opaque; qcrypto_nettle_cipher_free_ctx(ctx); } @@ -610,7 +611,7 @@ qcrypto_nettle_cipher_encrypt(QCryptoCipher *cipher, size_t len, Error **errp) { - QCryptoCipherNettle *ctx = cipher->opaque; + QCryptoCipherNettle *ctx = container_of(cipher, QCryptoCipherNettle, base); if (len & (ctx->blocksize - 1)) { error_setg(errp, "Length %zu must be a multiple of block size %zu", @@ -663,7 +664,7 @@ qcrypto_nettle_cipher_decrypt(QCryptoCipher *cipher, size_t len, Error **errp) { - QCryptoCipherNettle *ctx = cipher->opaque; + QCryptoCipherNettle *ctx = container_of(cipher, QCryptoCipherNettle, base); if (len & (ctx->blocksize - 1)) { error_setg(errp, "Length %zu must be a multiple of block size %zu", @@ -713,7 +714,8 @@ qcrypto_nettle_cipher_setiv(QCryptoCipher *cipher, const uint8_t *iv, size_t niv, Error **errp) { - QCryptoCipherNettle *ctx = cipher->opaque; + QCryptoCipherNettle *ctx = container_of(cipher, QCryptoCipherNettle, base); + if (niv != ctx->blocksize) { error_setg(errp, "Expected IV size %zu not %zu", ctx->blocksize, niv); diff --git a/crypto/cipher.c b/crypto/cipher.c index 3ca4a7e662..737fc0735d 100644 --- a/crypto/cipher.c +++ b/crypto/cipher.c @@ -163,30 +163,27 @@ QCryptoCipher *qcrypto_cipher_new(QCryptoCipherAlgorithm alg, const uint8_t *key, size_t nkey, Error **errp) { - QCryptoCipher *cipher; - void *ctx = NULL; + QCryptoCipher *cipher = NULL; const QCryptoCipherDriver *drv = NULL; #ifdef CONFIG_AF_ALG - ctx = qcrypto_afalg_cipher_ctx_new(alg, mode, key, nkey, NULL); - if (ctx) { + cipher = qcrypto_afalg_cipher_ctx_new(alg, mode, key, nkey, NULL); + if (cipher) { drv = &qcrypto_cipher_afalg_driver; } #endif - if (!ctx) { - ctx = qcrypto_cipher_ctx_new(alg, mode, key, nkey, errp); - if (!ctx) { + if (!cipher) { + cipher = qcrypto_cipher_ctx_new(alg, mode, key, nkey, errp); + if (!cipher) { return NULL; } drv = &qcrypto_cipher_lib_driver; } - cipher = g_new0(QCryptoCipher, 1); cipher->alg = alg; cipher->mode = mode; - cipher->opaque = ctx; cipher->driver = drv; return cipher; @@ -226,10 +223,7 @@ int qcrypto_cipher_setiv(QCryptoCipher *cipher, void qcrypto_cipher_free(QCryptoCipher *cipher) { - const QCryptoCipherDriver *drv; if (cipher) { - drv = cipher->driver; - drv->cipher_free(cipher); - g_free(cipher); + cipher->driver->cipher_free(cipher); } } diff --git a/crypto/cipherpriv.h b/crypto/cipherpriv.h index b73be33bd2..437b109b5e 100644 --- a/crypto/cipherpriv.h +++ b/crypto/cipherpriv.h @@ -41,7 +41,7 @@ struct QCryptoCipherDriver { #include "afalgpriv.h" -extern QCryptoAFAlg * +extern QCryptoCipher * qcrypto_afalg_cipher_ctx_new(QCryptoCipherAlgorithm alg, QCryptoCipherMode mode, const uint8_t *key, diff --git a/include/crypto/cipher.h b/include/crypto/cipher.h index cc57179a4d..083e12a7d9 100644 --- a/include/crypto/cipher.h +++ b/include/crypto/cipher.h @@ -80,7 +80,6 @@ typedef struct QCryptoCipherDriver QCryptoCipherDriver; struct QCryptoCipher { QCryptoCipherAlgorithm alg; QCryptoCipherMode mode; - void *opaque; const QCryptoCipherDriver *driver; }; -- cgit 1.4.1 From da30cd77e1dab21560286627eea9609e8a460ce9 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 28 Aug 2020 10:05:15 -0700 Subject: crypto: Move cipher->driver init to qcrypto_*_cipher_ctx_new MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The class vtable should be set by the class initializer. This will also allow additional subclassing, reducing the amount of indirection in the hierarchy. Signed-off-by: Richard Henderson Signed-off-by: Daniel P. Berrangé --- crypto/cipher-afalg.c | 5 ++++- crypto/cipher-builtin.c.inc | 4 ++++ crypto/cipher-gcrypt.c.inc | 2 ++ crypto/cipher-nettle.c.inc | 3 +++ crypto/cipher.c | 7 ------- crypto/cipherpriv.h | 2 -- 6 files changed, 13 insertions(+), 10 deletions(-) (limited to 'crypto/cipher-builtin.c.inc') diff --git a/crypto/cipher-afalg.c b/crypto/cipher-afalg.c index 86e5249bd6..052355a8a9 100644 --- a/crypto/cipher-afalg.c +++ b/crypto/cipher-afalg.c @@ -58,6 +58,8 @@ qcrypto_afalg_cipher_format_name(QCryptoCipherAlgorithm alg, return name; } +static const struct QCryptoCipherDriver qcrypto_cipher_afalg_driver; + QCryptoCipher * qcrypto_afalg_cipher_ctx_new(QCryptoCipherAlgorithm alg, QCryptoCipherMode mode, @@ -109,6 +111,7 @@ qcrypto_afalg_cipher_ctx_new(QCryptoCipherAlgorithm alg, } afalg->cmsg = CMSG_FIRSTHDR(afalg->msg); + afalg->base.driver = &qcrypto_cipher_afalg_driver; return &afalg->base; } @@ -222,7 +225,7 @@ static void qcrypto_afalg_comm_ctx_free(QCryptoCipher *cipher) qcrypto_afalg_comm_free(afalg); } -const struct QCryptoCipherDriver qcrypto_cipher_afalg_driver = { +static const struct QCryptoCipherDriver qcrypto_cipher_afalg_driver = { .cipher_encrypt = qcrypto_afalg_cipher_encrypt, .cipher_decrypt = qcrypto_afalg_cipher_decrypt, .cipher_setiv = qcrypto_afalg_cipher_setiv, diff --git a/crypto/cipher-builtin.c.inc b/crypto/cipher-builtin.c.inc index 6a03e23040..1444139f36 100644 --- a/crypto/cipher-builtin.c.inc +++ b/crypto/cipher-builtin.c.inc @@ -22,6 +22,8 @@ #include "crypto/desrfb.h" #include "crypto/xts.h" +static const struct QCryptoCipherDriver qcrypto_cipher_lib_driver; + typedef struct QCryptoCipherBuiltinAESContext QCryptoCipherBuiltinAESContext; struct QCryptoCipherBuiltinAESContext { AES_KEY enc; @@ -292,6 +294,7 @@ qcrypto_cipher_init_aes(QCryptoCipherMode mode, ctxt->encrypt = qcrypto_cipher_encrypt_aes; ctxt->decrypt = qcrypto_cipher_decrypt_aes; + ctxt->base.driver = &qcrypto_cipher_lib_driver; return &ctxt->base; error: @@ -396,6 +399,7 @@ qcrypto_cipher_init_des_rfb(QCryptoCipherMode mode, ctxt->encrypt = qcrypto_cipher_encrypt_des_rfb; ctxt->decrypt = qcrypto_cipher_decrypt_des_rfb; + ctxt->base.driver = &qcrypto_cipher_lib_driver; return &ctxt->base; } diff --git a/crypto/cipher-gcrypt.c.inc b/crypto/cipher-gcrypt.c.inc index 3b3c85e265..7a1fbc9745 100644 --- a/crypto/cipher-gcrypt.c.inc +++ b/crypto/cipher-gcrypt.c.inc @@ -24,6 +24,7 @@ #include +static const struct QCryptoCipherDriver qcrypto_cipher_lib_driver; bool qcrypto_cipher_supports(QCryptoCipherAlgorithm alg, QCryptoCipherMode mode) @@ -258,6 +259,7 @@ static QCryptoCipher *qcrypto_cipher_ctx_new(QCryptoCipherAlgorithm alg, } #endif + ctx->base.driver = &qcrypto_cipher_lib_driver; return &ctx->base; error: diff --git a/crypto/cipher-nettle.c.inc b/crypto/cipher-nettle.c.inc index d8371d1f37..36d57ef430 100644 --- a/crypto/cipher-nettle.c.inc +++ b/crypto/cipher-nettle.c.inc @@ -34,6 +34,8 @@ #include #endif +static const struct QCryptoCipherDriver qcrypto_cipher_lib_driver; + typedef void (*QCryptoCipherNettleFuncWrapper)(const void *ctx, size_t length, uint8_t *dst, @@ -587,6 +589,7 @@ static QCryptoCipher *qcrypto_cipher_ctx_new(QCryptoCipherAlgorithm alg, ctx->iv = g_new0(uint8_t, ctx->blocksize); + ctx->base.driver = &qcrypto_cipher_lib_driver; return &ctx->base; error: diff --git a/crypto/cipher.c b/crypto/cipher.c index 737fc0735d..3711b552fa 100644 --- a/crypto/cipher.c +++ b/crypto/cipher.c @@ -164,13 +164,9 @@ QCryptoCipher *qcrypto_cipher_new(QCryptoCipherAlgorithm alg, Error **errp) { QCryptoCipher *cipher = NULL; - const QCryptoCipherDriver *drv = NULL; #ifdef CONFIG_AF_ALG cipher = qcrypto_afalg_cipher_ctx_new(alg, mode, key, nkey, NULL); - if (cipher) { - drv = &qcrypto_cipher_afalg_driver; - } #endif if (!cipher) { @@ -178,13 +174,10 @@ QCryptoCipher *qcrypto_cipher_new(QCryptoCipherAlgorithm alg, if (!cipher) { return NULL; } - - drv = &qcrypto_cipher_lib_driver; } cipher->alg = alg; cipher->mode = mode; - cipher->driver = drv; return cipher; } diff --git a/crypto/cipherpriv.h b/crypto/cipherpriv.h index 437b109b5e..396527857d 100644 --- a/crypto/cipherpriv.h +++ b/crypto/cipherpriv.h @@ -47,8 +47,6 @@ qcrypto_afalg_cipher_ctx_new(QCryptoCipherAlgorithm alg, const uint8_t *key, size_t nkey, Error **errp); -extern const struct QCryptoCipherDriver qcrypto_cipher_afalg_driver; - #endif #endif -- cgit 1.4.1 From 838e4631cb26618df8b2e3ed3d3b6801c4cd1424 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 28 Aug 2020 10:05:17 -0700 Subject: crypto/builtin: Remove odd-sized AES block handling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We verified that the data block is properly sized modulo AES_BLOCK_SIZE within qcrypto_builtin_cipher_{en,de}crypt. Therefore we will never have to handle odd sized blocks. Signed-off-by: Richard Henderson Signed-off-by: Daniel P. Berrangé --- crypto/cipher-builtin.c.inc | 40 ++++++++++++---------------------------- 1 file changed, 12 insertions(+), 28 deletions(-) (limited to 'crypto/cipher-builtin.c.inc') diff --git a/crypto/cipher-builtin.c.inc b/crypto/cipher-builtin.c.inc index 1444139f36..e2ae5d090c 100644 --- a/crypto/cipher-builtin.c.inc +++ b/crypto/cipher-builtin.c.inc @@ -80,21 +80,13 @@ static void qcrypto_cipher_aes_ecb_encrypt(const AES_KEY *key, { const uint8_t *inptr = in; uint8_t *outptr = out; + + /* We have already verified that len % AES_BLOCK_SIZE == 0. */ while (len) { - if (len > AES_BLOCK_SIZE) { - AES_encrypt(inptr, outptr, key); - inptr += AES_BLOCK_SIZE; - outptr += AES_BLOCK_SIZE; - len -= AES_BLOCK_SIZE; - } else { - uint8_t tmp1[AES_BLOCK_SIZE], tmp2[AES_BLOCK_SIZE]; - memcpy(tmp1, inptr, len); - /* Fill with 0 to avoid valgrind uninitialized reads */ - memset(tmp1 + len, 0, sizeof(tmp1) - len); - AES_encrypt(tmp1, tmp2, key); - memcpy(outptr, tmp2, len); - len = 0; - } + AES_encrypt(inptr, outptr, key); + inptr += AES_BLOCK_SIZE; + outptr += AES_BLOCK_SIZE; + len -= AES_BLOCK_SIZE; } } @@ -106,21 +98,13 @@ static void qcrypto_cipher_aes_ecb_decrypt(const AES_KEY *key, { const uint8_t *inptr = in; uint8_t *outptr = out; + + /* We have already verified that len % AES_BLOCK_SIZE == 0. */ while (len) { - if (len > AES_BLOCK_SIZE) { - AES_decrypt(inptr, outptr, key); - inptr += AES_BLOCK_SIZE; - outptr += AES_BLOCK_SIZE; - len -= AES_BLOCK_SIZE; - } else { - uint8_t tmp1[AES_BLOCK_SIZE], tmp2[AES_BLOCK_SIZE]; - memcpy(tmp1, inptr, len); - /* Fill with 0 to avoid valgrind uninitialized reads */ - memset(tmp1 + len, 0, sizeof(tmp1) - len); - AES_decrypt(tmp1, tmp2, key); - memcpy(outptr, tmp2, len); - len = 0; - } + AES_decrypt(inptr, outptr, key); + inptr += AES_BLOCK_SIZE; + outptr += AES_BLOCK_SIZE; + len -= AES_BLOCK_SIZE; } } -- cgit 1.4.1 From 8ee47cddbe758ae521792f4b52ed3d86af993da6 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 28 Aug 2020 10:05:18 -0700 Subject: crypto/builtin: Merge qcrypto_cipher_aes_{ecb,xts}_{en,de}crypt MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There's no real reason we need two separate helper functions here. Standardize on the function signature required for xts_encrypt. Rename to do_aes_{en,de}crypt_ecb, since the helper does not itself do anything with respect to xts. Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Richard Henderson Signed-off-by: Daniel P. Berrangé --- crypto/cipher-builtin.c.inc | 73 ++++++++++++++------------------------------- 1 file changed, 22 insertions(+), 51 deletions(-) (limited to 'crypto/cipher-builtin.c.inc') diff --git a/crypto/cipher-builtin.c.inc b/crypto/cipher-builtin.c.inc index e2ae5d090c..8e21f2673f 100644 --- a/crypto/cipher-builtin.c.inc +++ b/crypto/cipher-builtin.c.inc @@ -72,65 +72,38 @@ static void qcrypto_cipher_free_aes(QCryptoCipher *cipher) g_free(cipher); } - -static void qcrypto_cipher_aes_ecb_encrypt(const AES_KEY *key, - const void *in, - void *out, - size_t len) +static void do_aes_encrypt_ecb(const void *vctx, + size_t len, + uint8_t *out, + const uint8_t *in) { - const uint8_t *inptr = in; - uint8_t *outptr = out; + const QCryptoCipherBuiltinAESContext *ctx = vctx; /* We have already verified that len % AES_BLOCK_SIZE == 0. */ while (len) { - AES_encrypt(inptr, outptr, key); - inptr += AES_BLOCK_SIZE; - outptr += AES_BLOCK_SIZE; + AES_encrypt(in, out, &ctx->enc); + in += AES_BLOCK_SIZE; + out += AES_BLOCK_SIZE; len -= AES_BLOCK_SIZE; } } - -static void qcrypto_cipher_aes_ecb_decrypt(const AES_KEY *key, - const void *in, - void *out, - size_t len) +static void do_aes_decrypt_ecb(const void *vctx, + size_t len, + uint8_t *out, + const uint8_t *in) { - const uint8_t *inptr = in; - uint8_t *outptr = out; + const QCryptoCipherBuiltinAESContext *ctx = vctx; /* We have already verified that len % AES_BLOCK_SIZE == 0. */ while (len) { - AES_decrypt(inptr, outptr, key); - inptr += AES_BLOCK_SIZE; - outptr += AES_BLOCK_SIZE; + AES_decrypt(in, out, &ctx->dec); + in += AES_BLOCK_SIZE; + out += AES_BLOCK_SIZE; len -= AES_BLOCK_SIZE; } } - -static void qcrypto_cipher_aes_xts_encrypt(const void *ctx, - size_t length, - uint8_t *dst, - const uint8_t *src) -{ - const QCryptoCipherBuiltinAESContext *aesctx = ctx; - - qcrypto_cipher_aes_ecb_encrypt(&aesctx->enc, src, dst, length); -} - - -static void qcrypto_cipher_aes_xts_decrypt(const void *ctx, - size_t length, - uint8_t *dst, - const uint8_t *src) -{ - const QCryptoCipherBuiltinAESContext *aesctx = ctx; - - qcrypto_cipher_aes_ecb_decrypt(&aesctx->dec, src, dst, length); -} - - static int qcrypto_cipher_encrypt_aes(QCryptoCipher *cipher, const void *in, void *out, @@ -142,8 +115,7 @@ static int qcrypto_cipher_encrypt_aes(QCryptoCipher *cipher, switch (cipher->mode) { case QCRYPTO_CIPHER_MODE_ECB: - qcrypto_cipher_aes_ecb_encrypt(&ctxt->state.aes.key.enc, - in, out, len); + do_aes_encrypt_ecb(&ctxt->state.aes.key, len, out, in); break; case QCRYPTO_CIPHER_MODE_CBC: AES_cbc_encrypt(in, out, len, @@ -153,8 +125,8 @@ static int qcrypto_cipher_encrypt_aes(QCryptoCipher *cipher, case QCRYPTO_CIPHER_MODE_XTS: xts_encrypt(&ctxt->state.aes.key, &ctxt->state.aes.key_tweak, - qcrypto_cipher_aes_xts_encrypt, - qcrypto_cipher_aes_xts_decrypt, + do_aes_encrypt_ecb, + do_aes_decrypt_ecb, ctxt->state.aes.iv, len, out, in); break; @@ -177,8 +149,7 @@ static int qcrypto_cipher_decrypt_aes(QCryptoCipher *cipher, switch (cipher->mode) { case QCRYPTO_CIPHER_MODE_ECB: - qcrypto_cipher_aes_ecb_decrypt(&ctxt->state.aes.key.dec, - in, out, len); + do_aes_decrypt_ecb(&ctxt->state.aes.key, len, out, in); break; case QCRYPTO_CIPHER_MODE_CBC: AES_cbc_encrypt(in, out, len, @@ -188,8 +159,8 @@ static int qcrypto_cipher_decrypt_aes(QCryptoCipher *cipher, case QCRYPTO_CIPHER_MODE_XTS: xts_decrypt(&ctxt->state.aes.key, &ctxt->state.aes.key_tweak, - qcrypto_cipher_aes_xts_encrypt, - qcrypto_cipher_aes_xts_decrypt, + do_aes_encrypt_ecb, + do_aes_decrypt_ecb, ctxt->state.aes.iv, len, out, in); break; -- cgit 1.4.1 From a2d76b6b2e324972641749f9fffd9eab27c89509 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 28 Aug 2020 10:05:19 -0700 Subject: crypto/builtin: Move AES_cbc_encrypt into cipher-builtin.inc.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit By making the function private, we will be able to make further simplifications. Re-indent the migrated code and fix the missing braces for CODING_STYLE. Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Richard Henderson Signed-off-by: Daniel P. Berrangé --- crypto/aes.c | 51 ----------------------------------------- crypto/cipher-builtin.c.inc | 56 +++++++++++++++++++++++++++++++++++++++++++++ include/crypto/aes.h | 4 ---- 3 files changed, 56 insertions(+), 55 deletions(-) (limited to 'crypto/cipher-builtin.c.inc') diff --git a/crypto/aes.c b/crypto/aes.c index 0f6a195af8..159800df65 100644 --- a/crypto/aes.c +++ b/crypto/aes.c @@ -1599,54 +1599,3 @@ void AES_decrypt(const unsigned char *in, unsigned char *out, } #endif /* AES_ASM */ - -void AES_cbc_encrypt(const unsigned char *in, unsigned char *out, - const unsigned long length, const AES_KEY *key, - unsigned char *ivec, const int enc) -{ - - unsigned long n; - unsigned long len = length; - unsigned char tmp[AES_BLOCK_SIZE]; - - assert(in && out && key && ivec); - - if (enc) { - while (len >= AES_BLOCK_SIZE) { - for(n=0; n < AES_BLOCK_SIZE; ++n) - tmp[n] = in[n] ^ ivec[n]; - AES_encrypt(tmp, out, key); - memcpy(ivec, out, AES_BLOCK_SIZE); - len -= AES_BLOCK_SIZE; - in += AES_BLOCK_SIZE; - out += AES_BLOCK_SIZE; - } - if (len) { - for(n=0; n < len; ++n) - tmp[n] = in[n] ^ ivec[n]; - for(n=len; n < AES_BLOCK_SIZE; ++n) - tmp[n] = ivec[n]; - AES_encrypt(tmp, tmp, key); - memcpy(out, tmp, AES_BLOCK_SIZE); - memcpy(ivec, tmp, AES_BLOCK_SIZE); - } - } else { - while (len >= AES_BLOCK_SIZE) { - memcpy(tmp, in, AES_BLOCK_SIZE); - AES_decrypt(in, out, key); - for(n=0; n < AES_BLOCK_SIZE; ++n) - out[n] ^= ivec[n]; - memcpy(ivec, tmp, AES_BLOCK_SIZE); - len -= AES_BLOCK_SIZE; - in += AES_BLOCK_SIZE; - out += AES_BLOCK_SIZE; - } - if (len) { - memcpy(tmp, in, AES_BLOCK_SIZE); - AES_decrypt(tmp, tmp, key); - for(n=0; n < len; ++n) - out[n] = tmp[n] ^ ivec[n]; - memcpy(ivec, tmp, AES_BLOCK_SIZE); - } - } -} diff --git a/crypto/cipher-builtin.c.inc b/crypto/cipher-builtin.c.inc index 8e21f2673f..61baad265a 100644 --- a/crypto/cipher-builtin.c.inc +++ b/crypto/cipher-builtin.c.inc @@ -104,6 +104,62 @@ static void do_aes_decrypt_ecb(const void *vctx, } } +static void AES_cbc_encrypt(const unsigned char *in, unsigned char *out, + const unsigned long length, const AES_KEY *key, + unsigned char *ivec, const int enc) +{ + unsigned long n; + unsigned long len = length; + unsigned char tmp[AES_BLOCK_SIZE]; + + assert(in && out && key && ivec); + + if (enc) { + while (len >= AES_BLOCK_SIZE) { + for (n = 0; n < AES_BLOCK_SIZE; ++n) { + tmp[n] = in[n] ^ ivec[n]; + } + AES_encrypt(tmp, out, key); + memcpy(ivec, out, AES_BLOCK_SIZE); + len -= AES_BLOCK_SIZE; + in += AES_BLOCK_SIZE; + out += AES_BLOCK_SIZE; + } + if (len) { + for (n = 0; n < len; ++n) { + tmp[n] = in[n] ^ ivec[n]; + } + for (n = len; n < AES_BLOCK_SIZE; ++n) { + tmp[n] = ivec[n]; + } + AES_encrypt(tmp, tmp, key); + memcpy(out, tmp, AES_BLOCK_SIZE); + memcpy(ivec, tmp, AES_BLOCK_SIZE); + } + } else { + while (len >= AES_BLOCK_SIZE) { + memcpy(tmp, in, AES_BLOCK_SIZE); + AES_decrypt(in, out, key); + for (n = 0; n < AES_BLOCK_SIZE; ++n) { + out[n] ^= ivec[n]; + } + memcpy(ivec, tmp, AES_BLOCK_SIZE); + len -= AES_BLOCK_SIZE; + in += AES_BLOCK_SIZE; + out += AES_BLOCK_SIZE; + } + if (len) { + memcpy(tmp, in, AES_BLOCK_SIZE); + AES_decrypt(tmp, tmp, key); + for (n = 0; n < len; ++n) { + out[n] = tmp[n] ^ ivec[n]; + } + memcpy(ivec, tmp, AES_BLOCK_SIZE); + } + } +} + + static int qcrypto_cipher_encrypt_aes(QCryptoCipher *cipher, const void *in, void *out, diff --git a/include/crypto/aes.h b/include/crypto/aes.h index 12fb321b89..ba297d6a73 100644 --- a/include/crypto/aes.h +++ b/include/crypto/aes.h @@ -16,7 +16,6 @@ typedef struct aes_key_st AES_KEY; #define AES_set_decrypt_key QEMU_AES_set_decrypt_key #define AES_encrypt QEMU_AES_encrypt #define AES_decrypt QEMU_AES_decrypt -#define AES_cbc_encrypt QEMU_AES_cbc_encrypt int AES_set_encrypt_key(const unsigned char *userKey, const int bits, AES_KEY *key); @@ -27,9 +26,6 @@ void AES_encrypt(const unsigned char *in, unsigned char *out, const AES_KEY *key); void AES_decrypt(const unsigned char *in, unsigned char *out, const AES_KEY *key); -void AES_cbc_encrypt(const unsigned char *in, unsigned char *out, - const unsigned long length, const AES_KEY *key, - unsigned char *ivec, const int enc); extern const uint8_t AES_sbox[256]; extern const uint8_t AES_isbox[256]; -- cgit 1.4.1 From ef186f4bc24ea7159a57776e8add1e9478b9702e Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 28 Aug 2020 10:05:20 -0700 Subject: crypto/builtin: Split and simplify AES_encrypt_cbc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Split into encrypt/decrypt functions, dropping the "enc" argument. Now that the function is private to this file, we know that "len" is a multiple of AES_BLOCK_SIZE. So drop the odd block size code. Name the functions do_aes_*crypt_cbc to match the *_ecb functions. Reorder and re-type the arguments to match as well. Signed-off-by: Richard Henderson Signed-off-by: Daniel P. Berrangé --- crypto/cipher-builtin.c.inc | 99 ++++++++++++++++++++------------------------- 1 file changed, 43 insertions(+), 56 deletions(-) (limited to 'crypto/cipher-builtin.c.inc') diff --git a/crypto/cipher-builtin.c.inc b/crypto/cipher-builtin.c.inc index 61baad265a..b1fe3b08c3 100644 --- a/crypto/cipher-builtin.c.inc +++ b/crypto/cipher-builtin.c.inc @@ -104,61 +104,50 @@ static void do_aes_decrypt_ecb(const void *vctx, } } -static void AES_cbc_encrypt(const unsigned char *in, unsigned char *out, - const unsigned long length, const AES_KEY *key, - unsigned char *ivec, const int enc) +static void do_aes_encrypt_cbc(const AES_KEY *key, + size_t len, + uint8_t *out, + const uint8_t *in, + uint8_t *ivec) { - unsigned long n; - unsigned long len = length; - unsigned char tmp[AES_BLOCK_SIZE]; - - assert(in && out && key && ivec); - - if (enc) { - while (len >= AES_BLOCK_SIZE) { - for (n = 0; n < AES_BLOCK_SIZE; ++n) { - tmp[n] = in[n] ^ ivec[n]; - } - AES_encrypt(tmp, out, key); - memcpy(ivec, out, AES_BLOCK_SIZE); - len -= AES_BLOCK_SIZE; - in += AES_BLOCK_SIZE; - out += AES_BLOCK_SIZE; - } - if (len) { - for (n = 0; n < len; ++n) { - tmp[n] = in[n] ^ ivec[n]; - } - for (n = len; n < AES_BLOCK_SIZE; ++n) { - tmp[n] = ivec[n]; - } - AES_encrypt(tmp, tmp, key); - memcpy(out, tmp, AES_BLOCK_SIZE); - memcpy(ivec, tmp, AES_BLOCK_SIZE); - } - } else { - while (len >= AES_BLOCK_SIZE) { - memcpy(tmp, in, AES_BLOCK_SIZE); - AES_decrypt(in, out, key); - for (n = 0; n < AES_BLOCK_SIZE; ++n) { - out[n] ^= ivec[n]; - } - memcpy(ivec, tmp, AES_BLOCK_SIZE); - len -= AES_BLOCK_SIZE; - in += AES_BLOCK_SIZE; - out += AES_BLOCK_SIZE; - } - if (len) { - memcpy(tmp, in, AES_BLOCK_SIZE); - AES_decrypt(tmp, tmp, key); - for (n = 0; n < len; ++n) { - out[n] = tmp[n] ^ ivec[n]; - } - memcpy(ivec, tmp, AES_BLOCK_SIZE); + uint8_t tmp[AES_BLOCK_SIZE]; + size_t n; + + /* We have already verified that len % AES_BLOCK_SIZE == 0. */ + while (len) { + for (n = 0; n < AES_BLOCK_SIZE; ++n) { + tmp[n] = in[n] ^ ivec[n]; } + AES_encrypt(tmp, out, key); + memcpy(ivec, out, AES_BLOCK_SIZE); + len -= AES_BLOCK_SIZE; + in += AES_BLOCK_SIZE; + out += AES_BLOCK_SIZE; } } +static void do_aes_decrypt_cbc(const AES_KEY *key, + size_t len, + uint8_t *out, + const uint8_t *in, + uint8_t *ivec) +{ + uint8_t tmp[AES_BLOCK_SIZE]; + size_t n; + + /* We have already verified that len % AES_BLOCK_SIZE == 0. */ + while (len) { + memcpy(tmp, in, AES_BLOCK_SIZE); + AES_decrypt(in, out, key); + for (n = 0; n < AES_BLOCK_SIZE; ++n) { + out[n] ^= ivec[n]; + } + memcpy(ivec, tmp, AES_BLOCK_SIZE); + len -= AES_BLOCK_SIZE; + in += AES_BLOCK_SIZE; + out += AES_BLOCK_SIZE; + } +} static int qcrypto_cipher_encrypt_aes(QCryptoCipher *cipher, const void *in, @@ -174,9 +163,8 @@ static int qcrypto_cipher_encrypt_aes(QCryptoCipher *cipher, do_aes_encrypt_ecb(&ctxt->state.aes.key, len, out, in); break; case QCRYPTO_CIPHER_MODE_CBC: - AES_cbc_encrypt(in, out, len, - &ctxt->state.aes.key.enc, - ctxt->state.aes.iv, 1); + do_aes_encrypt_cbc(&ctxt->state.aes.key.enc, len, out, in, + ctxt->state.aes.iv); break; case QCRYPTO_CIPHER_MODE_XTS: xts_encrypt(&ctxt->state.aes.key, @@ -208,9 +196,8 @@ static int qcrypto_cipher_decrypt_aes(QCryptoCipher *cipher, do_aes_decrypt_ecb(&ctxt->state.aes.key, len, out, in); break; case QCRYPTO_CIPHER_MODE_CBC: - AES_cbc_encrypt(in, out, len, - &ctxt->state.aes.key.dec, - ctxt->state.aes.iv, 0); + do_aes_decrypt_cbc(&ctxt->state.aes.key.dec, len, out, in, + ctxt->state.aes.iv); break; case QCRYPTO_CIPHER_MODE_XTS: xts_decrypt(&ctxt->state.aes.key, -- cgit 1.4.1 From a3db31b83ef56ec044dbd7b89f3560855d5f8d5e Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 28 Aug 2020 10:05:21 -0700 Subject: crypto/builtin: Split QCryptoCipherBuiltin into subclasses MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We had a second set of function pointers in QCryptoCipherBuiltin, which are redundant with QCryptoCipherDriver. Split the AES and DES implementations to avoid one level of indirection. Signed-off-by: Richard Henderson Signed-off-by: Daniel P. Berrangé --- crypto/cipher-builtin.c.inc | 519 ++++++++++++++++++-------------------------- 1 file changed, 210 insertions(+), 309 deletions(-) (limited to 'crypto/cipher-builtin.c.inc') diff --git a/crypto/cipher-builtin.c.inc b/crypto/cipher-builtin.c.inc index b1fe3b08c3..7597cf4a10 100644 --- a/crypto/cipher-builtin.c.inc +++ b/crypto/cipher-builtin.c.inc @@ -22,56 +22,45 @@ #include "crypto/desrfb.h" #include "crypto/xts.h" -static const struct QCryptoCipherDriver qcrypto_cipher_lib_driver; - typedef struct QCryptoCipherBuiltinAESContext QCryptoCipherBuiltinAESContext; struct QCryptoCipherBuiltinAESContext { AES_KEY enc; AES_KEY dec; }; + typedef struct QCryptoCipherBuiltinAES QCryptoCipherBuiltinAES; struct QCryptoCipherBuiltinAES { + QCryptoCipher base; QCryptoCipherBuiltinAESContext key; QCryptoCipherBuiltinAESContext key_tweak; uint8_t iv[AES_BLOCK_SIZE]; }; -typedef struct QCryptoCipherBuiltinDESRFB QCryptoCipherBuiltinDESRFB; -struct QCryptoCipherBuiltinDESRFB { - uint8_t *key; - size_t nkey; -}; -typedef struct QCryptoCipherBuiltin QCryptoCipherBuiltin; -struct QCryptoCipherBuiltin { - QCryptoCipher base; - - union { - QCryptoCipherBuiltinAES aes; - QCryptoCipherBuiltinDESRFB desrfb; - } state; - size_t blocksize; - void (*free)(QCryptoCipher *cipher); - int (*setiv)(QCryptoCipher *cipher, - const uint8_t *iv, size_t niv, - Error **errp); - int (*encrypt)(QCryptoCipher *cipher, - const void *in, - void *out, - size_t len, - Error **errp); - int (*decrypt)(QCryptoCipher *cipher, - const void *in, - void *out, - size_t len, - Error **errp); -}; +static inline bool qcrypto_length_check(size_t len, size_t blocksize, + Error **errp) +{ + if (unlikely(len & (blocksize - 1))) { + error_setg(errp, "Length %zu must be a multiple of block size %zu", + len, blocksize); + return false; + } + return true; +} -static void qcrypto_cipher_free_aes(QCryptoCipher *cipher) +static void qcrypto_cipher_ctx_free(QCryptoCipher *cipher) { g_free(cipher); } +static int qcrypto_cipher_no_setiv(QCryptoCipher *cipher, + const uint8_t *iv, size_t niv, + Error **errp) +{ + error_setg(errp, "Setting IV is not supported"); + return -1; +} + static void do_aes_encrypt_ecb(const void *vctx, size_t len, uint8_t *out, @@ -149,185 +138,154 @@ static void do_aes_decrypt_cbc(const AES_KEY *key, } } -static int qcrypto_cipher_encrypt_aes(QCryptoCipher *cipher, - const void *in, - void *out, - size_t len, - Error **errp) +static int qcrypto_cipher_aes_encrypt_ecb(QCryptoCipher *cipher, + const void *in, void *out, + size_t len, Error **errp) { - QCryptoCipherBuiltin *ctxt - = container_of(cipher, QCryptoCipherBuiltin, base); + QCryptoCipherBuiltinAES *ctx + = container_of(cipher, QCryptoCipherBuiltinAES, base); - switch (cipher->mode) { - case QCRYPTO_CIPHER_MODE_ECB: - do_aes_encrypt_ecb(&ctxt->state.aes.key, len, out, in); - break; - case QCRYPTO_CIPHER_MODE_CBC: - do_aes_encrypt_cbc(&ctxt->state.aes.key.enc, len, out, in, - ctxt->state.aes.iv); - break; - case QCRYPTO_CIPHER_MODE_XTS: - xts_encrypt(&ctxt->state.aes.key, - &ctxt->state.aes.key_tweak, - do_aes_encrypt_ecb, - do_aes_decrypt_ecb, - ctxt->state.aes.iv, - len, out, in); - break; - default: - g_assert_not_reached(); + if (!qcrypto_length_check(len, AES_BLOCK_SIZE, errp)) { + return -1; } - + do_aes_encrypt_ecb(&ctx->key, len, out, in); return 0; } - -static int qcrypto_cipher_decrypt_aes(QCryptoCipher *cipher, - const void *in, - void *out, - size_t len, - Error **errp) +static int qcrypto_cipher_aes_decrypt_ecb(QCryptoCipher *cipher, + const void *in, void *out, + size_t len, Error **errp) { - QCryptoCipherBuiltin *ctxt - = container_of(cipher, QCryptoCipherBuiltin, base); + QCryptoCipherBuiltinAES *ctx + = container_of(cipher, QCryptoCipherBuiltinAES, base); - switch (cipher->mode) { - case QCRYPTO_CIPHER_MODE_ECB: - do_aes_decrypt_ecb(&ctxt->state.aes.key, len, out, in); - break; - case QCRYPTO_CIPHER_MODE_CBC: - do_aes_decrypt_cbc(&ctxt->state.aes.key.dec, len, out, in, - ctxt->state.aes.iv); - break; - case QCRYPTO_CIPHER_MODE_XTS: - xts_decrypt(&ctxt->state.aes.key, - &ctxt->state.aes.key_tweak, - do_aes_encrypt_ecb, - do_aes_decrypt_ecb, - ctxt->state.aes.iv, - len, out, in); - break; - default: - g_assert_not_reached(); + if (!qcrypto_length_check(len, AES_BLOCK_SIZE, errp)) { + return -1; } - + do_aes_decrypt_ecb(&ctx->key, len, out, in); return 0; } -static int qcrypto_cipher_setiv_aes(QCryptoCipher *cipher, - const uint8_t *iv, size_t niv, - Error **errp) +static int qcrypto_cipher_aes_encrypt_cbc(QCryptoCipher *cipher, + const void *in, void *out, + size_t len, Error **errp) { - QCryptoCipherBuiltin *ctxt - = container_of(cipher, QCryptoCipherBuiltin, base); + QCryptoCipherBuiltinAES *ctx + = container_of(cipher, QCryptoCipherBuiltinAES, base); - if (niv != AES_BLOCK_SIZE) { - error_setg(errp, "IV must be %d bytes not %zu", - AES_BLOCK_SIZE, niv); + if (!qcrypto_length_check(len, AES_BLOCK_SIZE, errp)) { return -1; } - - memcpy(ctxt->state.aes.iv, iv, AES_BLOCK_SIZE); - + do_aes_encrypt_cbc(&ctx->key.enc, len, out, in, ctx->iv); return 0; } +static int qcrypto_cipher_aes_decrypt_cbc(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; + } + do_aes_decrypt_cbc(&ctx->key.dec, len, out, in, ctx->iv); + return 0; +} - -static QCryptoCipher * -qcrypto_cipher_init_aes(QCryptoCipherMode mode, - const uint8_t *key, size_t nkey, - Error **errp) +static int qcrypto_cipher_aes_encrypt_xts(QCryptoCipher *cipher, + const void *in, void *out, + size_t len, Error **errp) { - QCryptoCipherBuiltin *ctxt; + QCryptoCipherBuiltinAES *ctx + = container_of(cipher, QCryptoCipherBuiltinAES, base); - if (mode != QCRYPTO_CIPHER_MODE_CBC && - mode != QCRYPTO_CIPHER_MODE_ECB && - mode != QCRYPTO_CIPHER_MODE_XTS) { - error_setg(errp, "Unsupported cipher mode %s", - QCryptoCipherMode_str(mode)); - return NULL; + 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; +} - ctxt = g_new0(QCryptoCipherBuiltin, 1); +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 (mode == QCRYPTO_CIPHER_MODE_XTS) { - if (AES_set_encrypt_key(key, nkey * 4, &ctxt->state.aes.key.enc) != 0) { - error_setg(errp, "Failed to set encryption key"); - goto error; - } + 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; +} - if (AES_set_decrypt_key(key, nkey * 4, &ctxt->state.aes.key.dec) != 0) { - error_setg(errp, "Failed to set decryption key"); - goto error; - } - if (AES_set_encrypt_key(key + (nkey / 2), nkey * 4, - &ctxt->state.aes.key_tweak.enc) != 0) { - error_setg(errp, "Failed to set encryption key"); - goto error; - } - - if (AES_set_decrypt_key(key + (nkey / 2), nkey * 4, - &ctxt->state.aes.key_tweak.dec) != 0) { - error_setg(errp, "Failed to set decryption key"); - goto error; - } - } else { - if (AES_set_encrypt_key(key, nkey * 8, &ctxt->state.aes.key.enc) != 0) { - error_setg(errp, "Failed to set encryption key"); - goto error; - } +static int qcrypto_cipher_aes_setiv(QCryptoCipher *cipher, const uint8_t *iv, + size_t niv, Error **errp) +{ + QCryptoCipherBuiltinAES *ctx + = container_of(cipher, QCryptoCipherBuiltinAES, base); - if (AES_set_decrypt_key(key, nkey * 8, &ctxt->state.aes.key.dec) != 0) { - error_setg(errp, "Failed to set decryption key"); - goto error; - } + if (niv != AES_BLOCK_SIZE) { + error_setg(errp, "IV must be %d bytes not %zu", + AES_BLOCK_SIZE, niv); + return -1; } - ctxt->blocksize = AES_BLOCK_SIZE; - ctxt->free = qcrypto_cipher_free_aes; - ctxt->setiv = qcrypto_cipher_setiv_aes; - ctxt->encrypt = qcrypto_cipher_encrypt_aes; - ctxt->decrypt = qcrypto_cipher_decrypt_aes; + memcpy(ctx->iv, iv, AES_BLOCK_SIZE); + return 0; +} - ctxt->base.driver = &qcrypto_cipher_lib_driver; - return &ctxt->base; +static const struct QCryptoCipherDriver qcrypto_cipher_aes_driver_ecb = { + .cipher_encrypt = qcrypto_cipher_aes_encrypt_ecb, + .cipher_decrypt = qcrypto_cipher_aes_decrypt_ecb, + .cipher_setiv = qcrypto_cipher_no_setiv, + .cipher_free = qcrypto_cipher_ctx_free, +}; - error: - g_free(ctxt); - return NULL; -} +static const struct QCryptoCipherDriver qcrypto_cipher_aes_driver_cbc = { + .cipher_encrypt = qcrypto_cipher_aes_encrypt_cbc, + .cipher_decrypt = qcrypto_cipher_aes_decrypt_cbc, + .cipher_setiv = qcrypto_cipher_aes_setiv, + .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, +}; -static void qcrypto_cipher_free_des_rfb(QCryptoCipher *cipher) -{ - QCryptoCipherBuiltin *ctxt - = container_of(cipher, QCryptoCipherBuiltin, base); - g_free(ctxt->state.desrfb.key); - g_free(ctxt); -} +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) + const void *in, void *out, + size_t len, Error **errp) { - QCryptoCipherBuiltin *ctxt - = container_of(cipher, QCryptoCipherBuiltin, base); + QCryptoCipherBuiltinDESRFB *ctx + = container_of(cipher, QCryptoCipherBuiltinDESRFB, base); size_t i; - if (len % 8) { - error_setg(errp, "Buffer size must be multiple of 8 not %zu", - len); + if (!qcrypto_length_check(len, 8, errp)) { return -1; } - deskey(ctxt->state.desrfb.key, EN0); + deskey(ctx->key, EN0); for (i = 0; i < len; i += 8) { des((void *)in + i, out + i); @@ -336,24 +294,19 @@ static int qcrypto_cipher_encrypt_des_rfb(QCryptoCipher *cipher, return 0; } - static int qcrypto_cipher_decrypt_des_rfb(QCryptoCipher *cipher, - const void *in, - void *out, - size_t len, - Error **errp) + const void *in, void *out, + size_t len, Error **errp) { - QCryptoCipherBuiltin *ctxt - = container_of(cipher, QCryptoCipherBuiltin, base); + QCryptoCipherBuiltinDESRFB *ctx + = container_of(cipher, QCryptoCipherBuiltinDESRFB, base); size_t i; - if (len % 8) { - error_setg(errp, "Buffer size must be multiple of 8 not %zu", - len); + if (!qcrypto_length_check(len, 8, errp)) { return -1; } - deskey(ctxt->state.desrfb.key, DE1); + deskey(ctx->key, DE1); for (i = 0; i < len; i += 8) { des((void *)in + i, out + i); @@ -362,173 +315,121 @@ static int qcrypto_cipher_decrypt_des_rfb(QCryptoCipher *cipher, return 0; } - -static int qcrypto_cipher_setiv_des_rfb(QCryptoCipher *cipher, - const uint8_t *iv, size_t niv, - Error **errp) -{ - error_setg(errp, "Setting IV is not supported"); - return -1; -} - - -static QCryptoCipher * -qcrypto_cipher_init_des_rfb(QCryptoCipherMode mode, - const uint8_t *key, size_t nkey, - Error **errp) -{ - QCryptoCipherBuiltin *ctxt; - - if (mode != QCRYPTO_CIPHER_MODE_ECB) { - error_setg(errp, "Unsupported cipher mode %s", - QCryptoCipherMode_str(mode)); - return NULL; - } - - ctxt = g_new0(QCryptoCipherBuiltin, 1); - - ctxt->state.desrfb.key = g_new0(uint8_t, nkey); - memcpy(ctxt->state.desrfb.key, key, nkey); - ctxt->state.desrfb.nkey = nkey; - - ctxt->blocksize = 8; - ctxt->free = qcrypto_cipher_free_des_rfb; - ctxt->setiv = qcrypto_cipher_setiv_des_rfb; - ctxt->encrypt = qcrypto_cipher_encrypt_des_rfb; - ctxt->decrypt = qcrypto_cipher_decrypt_des_rfb; - - ctxt->base.driver = &qcrypto_cipher_lib_driver; - return &ctxt->base; -} - +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; + } 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; - } } - static QCryptoCipher *qcrypto_cipher_ctx_new(QCryptoCipherAlgorithm alg, QCryptoCipherMode mode, const uint8_t *key, size_t nkey, Error **errp) { - 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_str(mode)); - return NULL; - } - if (!qcrypto_cipher_validate_key_length(alg, mode, nkey, errp)) { return NULL; } switch (alg) { case QCRYPTO_CIPHER_ALG_DES_RFB: - return qcrypto_cipher_init_des_rfb(mode, key, nkey, errp); + 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: - return qcrypto_cipher_init_aes(mode, key, nkey, errp); + { + QCryptoCipherBuiltinAES *ctx; + const QCryptoCipherDriver *drv; + + switch (mode) { + case QCRYPTO_CIPHER_MODE_ECB: + drv = &qcrypto_cipher_aes_driver_ecb; + break; + 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; + } + if (AES_set_decrypt_key(key, nkey * 8, &ctx->key.dec)) { + error_setg(errp, "Failed to set decryption key"); + goto error; + } + + return &ctx->base; + + error: + g_free(ctx); + return NULL; + } + default: error_setg(errp, "Unsupported cipher algorithm %s", QCryptoCipherAlgorithm_str(alg)); return NULL; } -} - -static void -qcrypto_builtin_cipher_ctx_free(QCryptoCipher *cipher) -{ - QCryptoCipherBuiltin *ctxt - = container_of(cipher, QCryptoCipherBuiltin, base); - - ctxt->free(cipher); -} - -static int -qcrypto_builtin_cipher_encrypt(QCryptoCipher *cipher, - const void *in, - void *out, - size_t len, - Error **errp) -{ - QCryptoCipherBuiltin *ctxt - = container_of(cipher, QCryptoCipherBuiltin, base); - - if (len & (ctxt->blocksize - 1)) { - error_setg(errp, "Length %zu must be a multiple of block size %zu", - len, ctxt->blocksize); - return -1; - } - - return ctxt->encrypt(cipher, in, out, len, errp); -} - - -static int -qcrypto_builtin_cipher_decrypt(QCryptoCipher *cipher, - const void *in, - void *out, - size_t len, - Error **errp) -{ - QCryptoCipherBuiltin *ctxt - = container_of(cipher, QCryptoCipherBuiltin, base); - - if (len & (ctxt->blocksize - 1)) { - error_setg(errp, "Length %zu must be a multiple of block size %zu", - len, ctxt->blocksize); - return -1; - } - - return ctxt->decrypt(cipher, in, out, len, errp); -} - - -static int -qcrypto_builtin_cipher_setiv(QCryptoCipher *cipher, - const uint8_t *iv, size_t niv, - Error **errp) -{ - QCryptoCipherBuiltin *ctxt - = container_of(cipher, QCryptoCipherBuiltin, base); - - return ctxt->setiv(cipher, iv, niv, errp); + bad_mode: + error_setg(errp, "Unsupported cipher mode %s", + QCryptoCipherMode_str(mode)); + return NULL; } - - -static const struct QCryptoCipherDriver qcrypto_cipher_lib_driver = { - .cipher_encrypt = qcrypto_builtin_cipher_encrypt, - .cipher_decrypt = qcrypto_builtin_cipher_decrypt, - .cipher_setiv = qcrypto_builtin_cipher_setiv, - .cipher_free = qcrypto_builtin_cipher_ctx_free, -}; -- cgit 1.4.1