You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
qemu/crypto/cipher-nettle.c.inc

716 lines
28 KiB
C++

/*
* QEMU Crypto cipher nettle 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 <http://www.gnu.org/licenses/>.
*
*/
#ifdef CONFIG_QEMU_PRIVATE_XTS
#include "crypto/xts.h"
#endif
#include <nettle/nettle-types.h>
#include <nettle/aes.h>
#include <nettle/des.h>
#include <nettle/cbc.h>
#include <nettle/cast128.h>
#include <nettle/serpent.h>
#include <nettle/twofish.h>
#include <nettle/ctr.h>
#ifndef CONFIG_QEMU_PRIVATE_XTS
#include <nettle/xts.h>
#endif
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_ctx_free(QCryptoCipher *ctx)
{
g_free(ctx);
}
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;
}
#define DEFINE_SETIV(NAME, TYPE, BLEN) \
static int NAME##_setiv(QCryptoCipher *cipher, const uint8_t *iv, \
size_t niv, Error **errp) \
{ \
TYPE *ctx = container_of(cipher, TYPE, base); \
if (niv != BLEN) { \
error_setg(errp, "Expected IV size %d not %zu", BLEN, niv); \
return -1; \
} \
memcpy(ctx->iv, iv, niv); \
return 0; \
}
#define DEFINE_ECB(NAME, TYPE, BLEN, ENCRYPT, DECRYPT) \
static int NAME##_encrypt_ecb(QCryptoCipher *cipher, const void *in, \
void *out, size_t len, Error **errp) \
{ \
TYPE *ctx = container_of(cipher, TYPE, base); \
if (!qcrypto_length_check(len, BLEN, errp)) { \
return -1; \
} \
ENCRYPT(&ctx->key, len, out, in); \
return 0; \
} \
static int NAME##_decrypt_ecb(QCryptoCipher *cipher, const void *in, \
void *out, size_t len, Error **errp) \
{ \
TYPE *ctx = container_of(cipher, TYPE, base); \
if (!qcrypto_length_check(len, BLEN, errp)) { \
return -1; \
} \
DECRYPT(&ctx->key, len, out, in); \
return 0; \
} \
static const struct QCryptoCipherDriver NAME##_driver_ecb = { \
.cipher_encrypt = NAME##_encrypt_ecb, \
.cipher_decrypt = NAME##_decrypt_ecb, \
.cipher_setiv = qcrypto_cipher_no_setiv, \
.cipher_free = qcrypto_cipher_ctx_free, \
};
#define DEFINE_CBC(NAME, TYPE, BLEN, ENCRYPT, DECRYPT) \
static int NAME##_encrypt_cbc(QCryptoCipher *cipher, const void *in, \
void *out, size_t len, Error **errp) \
{ \
TYPE *ctx = container_of(cipher, TYPE, base); \
if (!qcrypto_length_check(len, BLEN, errp)) { \
return -1; \
} \
cbc_encrypt(&ctx->key, ENCRYPT, BLEN, ctx->iv, len, out, in); \
return 0; \
} \
static int NAME##_decrypt_cbc(QCryptoCipher *cipher, const void *in, \
void *out, size_t len, Error **errp) \
{ \
TYPE *ctx = container_of(cipher, TYPE, base); \
if (!qcrypto_length_check(len, BLEN, errp)) { \
return -1; \
} \
cbc_decrypt(&ctx->key, DECRYPT, BLEN, ctx->iv, len, out, in); \
return 0; \
} \
static const struct QCryptoCipherDriver NAME##_driver_cbc = { \
.cipher_encrypt = NAME##_encrypt_cbc, \
.cipher_decrypt = NAME##_decrypt_cbc, \
.cipher_setiv = NAME##_setiv, \
.cipher_free = qcrypto_cipher_ctx_free, \
};
#define DEFINE_CTR(NAME, TYPE, BLEN, ENCRYPT) \
static int NAME##_encrypt_ctr(QCryptoCipher *cipher, const void *in, \
void *out, size_t len, Error **errp) \
{ \
TYPE *ctx = container_of(cipher, TYPE, base); \
if (!qcrypto_length_check(len, BLEN, errp)) { \
return -1; \
} \
ctr_crypt(&ctx->key, ENCRYPT, BLEN, ctx->iv, len, out, in); \
return 0; \
} \
static const struct QCryptoCipherDriver NAME##_driver_ctr = { \
.cipher_encrypt = NAME##_encrypt_ctr, \
.cipher_decrypt = NAME##_encrypt_ctr, \
.cipher_setiv = NAME##_setiv, \
.cipher_free = qcrypto_cipher_ctx_free, \
};
#ifdef CONFIG_QEMU_PRIVATE_XTS
#define DEFINE__XTS(NAME, TYPE, BLEN, ENCRYPT, DECRYPT) \
static void NAME##_xts_wrape(const void *ctx, size_t length, \
uint8_t *dst, const uint8_t *src) \
{ \
ENCRYPT((const void *)ctx, length, dst, src); \
} \
static void NAME##_xts_wrapd(const void *ctx, size_t length, \
uint8_t *dst, const uint8_t *src) \
{ \
DECRYPT((const void *)ctx, length, dst, src); \
} \
static int NAME##_encrypt_xts(QCryptoCipher *cipher, const void *in, \
void *out, size_t len, Error **errp) \
{ \
TYPE *ctx = container_of(cipher, TYPE, base); \
if (!qcrypto_length_check(len, BLEN, errp)) { \
return -1; \
} \
xts_encrypt(&ctx->key, &ctx->key_xts, \
NAME##_xts_wrape, NAME##_xts_wrapd, \
ctx->iv, len, out, in); \
return 0; \
} \
static int NAME##_decrypt_xts(QCryptoCipher *cipher, const void *in, \
void *out, size_t len, Error **errp) \
{ \
TYPE *ctx = container_of(cipher, TYPE, base); \
if (!qcrypto_length_check(len, BLEN, errp)) { \
return -1; \
} \
xts_decrypt(&ctx->key, &ctx->key_xts, \
NAME##_xts_wrape, NAME##_xts_wrapd, \
ctx->iv, len, out, in); \
return 0; \
}
#else
#define DEFINE__XTS(NAME, TYPE, BLEN, ENCRYPT, DECRYPT) \
static int NAME##_encrypt_xts(QCryptoCipher *cipher, const void *in, \
void *out, size_t len, Error **errp) \
{ \
TYPE *ctx = container_of(cipher, TYPE, base); \
if (!qcrypto_length_check(len, BLEN, errp)) { \
return -1; \
} \
xts_encrypt_message(&ctx->key, &ctx->key_xts, ENCRYPT, \
ctx->iv, len, out, in); \
return 0; \
} \
static int NAME##_decrypt_xts(QCryptoCipher *cipher, const void *in, \
void *out, size_t len, Error **errp) \
{ \
TYPE *ctx = container_of(cipher, TYPE, base); \
if (!qcrypto_length_check(len, BLEN, errp)) { \
return -1; \
} \
xts_decrypt_message(&ctx->key, &ctx->key_xts, DECRYPT, ENCRYPT, \
ctx->iv, len, out, in); \
return 0; \
}
#endif
#define DEFINE_XTS(NAME, TYPE, BLEN, ENCRYPT, DECRYPT) \
QEMU_BUILD_BUG_ON(BLEN != XTS_BLOCK_SIZE); \
DEFINE__XTS(NAME, TYPE, BLEN, ENCRYPT, DECRYPT) \
static const struct QCryptoCipherDriver NAME##_driver_xts = { \
.cipher_encrypt = NAME##_encrypt_xts, \
.cipher_decrypt = NAME##_decrypt_xts, \
.cipher_setiv = NAME##_setiv, \
.cipher_free = qcrypto_cipher_ctx_free, \
};
#define DEFINE_ECB_CBC_CTR(NAME, TYPE, BLEN, ENCRYPT, DECRYPT) \
DEFINE_SETIV(NAME, TYPE, BLEN) \
DEFINE_ECB(NAME, TYPE, BLEN, ENCRYPT, DECRYPT) \
DEFINE_CBC(NAME, TYPE, BLEN, ENCRYPT, DECRYPT) \
DEFINE_CTR(NAME, TYPE, BLEN, ENCRYPT)
#define DEFINE_ECB_CBC_CTR_XTS(NAME, TYPE, BLEN, ENCRYPT, DECRYPT) \
DEFINE_ECB_CBC_CTR(NAME, TYPE, BLEN, ENCRYPT, DECRYPT) \
DEFINE_XTS(NAME, TYPE, BLEN, ENCRYPT, DECRYPT)
typedef struct QCryptoNettleDES {
QCryptoCipher base;
struct des_ctx key;
uint8_t iv[DES_BLOCK_SIZE];
} QCryptoNettleDES;
static void des_encrypt_native(const void *ctx, size_t length,
uint8_t *dst, const uint8_t *src)
{
des_encrypt(ctx, length, dst, src);
}
static void des_decrypt_native(const void *ctx, size_t length,
uint8_t *dst, const uint8_t *src)
{
des_decrypt(ctx, length, dst, src);
}
DEFINE_ECB_CBC_CTR(qcrypto_nettle_des, QCryptoNettleDES,
DES_BLOCK_SIZE, des_encrypt_native, des_decrypt_native)
typedef struct QCryptoNettleDES3 {
QCryptoCipher base;
struct des3_ctx key;
uint8_t iv[DES3_BLOCK_SIZE];
} QCryptoNettleDES3;
static void des3_encrypt_native(const void *ctx, size_t length,
uint8_t *dst, const uint8_t *src)
{
des3_encrypt(ctx, length, dst, src);
}
static void des3_decrypt_native(const void *ctx, size_t length,
uint8_t *dst, const uint8_t *src)
{
des3_decrypt(ctx, length, dst, src);
}
DEFINE_ECB_CBC_CTR(qcrypto_nettle_des3, QCryptoNettleDES3, DES3_BLOCK_SIZE,
des3_encrypt_native, des3_decrypt_native)
typedef struct QCryptoNettleAES128 {
QCryptoCipher base;
uint8_t iv[AES_BLOCK_SIZE];
/* First key from pair is encode, second key is decode. */
struct aes128_ctx key[2], key_xts[2];
} QCryptoNettleAES128;
static void aes128_encrypt_native(const void *ctx, size_t length,
uint8_t *dst, const uint8_t *src)
{
const struct aes128_ctx *keys = ctx;
aes128_encrypt(&keys[0], length, dst, src);
}
static void aes128_decrypt_native(const void *ctx, size_t length,
uint8_t *dst, const uint8_t *src)
{
const struct aes128_ctx *keys = ctx;
aes128_decrypt(&keys[1], length, dst, src);
}
DEFINE_ECB_CBC_CTR_XTS(qcrypto_nettle_aes128,
QCryptoNettleAES128, AES_BLOCK_SIZE,
aes128_encrypt_native, aes128_decrypt_native)
typedef struct QCryptoNettleAES192 {
QCryptoCipher base;
uint8_t iv[AES_BLOCK_SIZE];
/* First key from pair is encode, second key is decode. */
struct aes192_ctx key[2], key_xts[2];
} QCryptoNettleAES192;
static void aes192_encrypt_native(const void *ctx, size_t length,
uint8_t *dst, const uint8_t *src)
{
const struct aes192_ctx *keys = ctx;
aes192_encrypt(&keys[0], length, dst, src);
}
static void aes192_decrypt_native(const void *ctx, size_t length,
uint8_t *dst, const uint8_t *src)
{
const struct aes192_ctx *keys = ctx;
aes192_decrypt(&keys[1], length, dst, src);
}
DEFINE_ECB_CBC_CTR_XTS(qcrypto_nettle_aes192,
QCryptoNettleAES192, AES_BLOCK_SIZE,
aes192_encrypt_native, aes192_decrypt_native)
typedef struct QCryptoNettleAES256 {
QCryptoCipher base;
uint8_t iv[AES_BLOCK_SIZE];
/* First key from pair is encode, second key is decode. */
struct aes256_ctx key[2], key_xts[2];
} QCryptoNettleAES256;
static void aes256_encrypt_native(const void *ctx, size_t length,
uint8_t *dst, const uint8_t *src)
{
const struct aes256_ctx *keys = ctx;
aes256_encrypt(&keys[0], length, dst, src);
}
static void aes256_decrypt_native(const void *ctx, size_t length,
uint8_t *dst, const uint8_t *src)
{
const struct aes256_ctx *keys = ctx;
aes256_decrypt(&keys[1], length, dst, src);
}
DEFINE_ECB_CBC_CTR_XTS(qcrypto_nettle_aes256,
QCryptoNettleAES256, AES_BLOCK_SIZE,
aes256_encrypt_native, aes256_decrypt_native)
typedef struct QCryptoNettleCAST128 {
QCryptoCipher base;
uint8_t iv[CAST128_BLOCK_SIZE];
struct cast128_ctx key, key_xts;
} QCryptoNettleCAST128;
static void cast128_encrypt_native(const void *ctx, size_t length,
uint8_t *dst, const uint8_t *src)
{
cast128_encrypt(ctx, length, dst, src);
}
static void cast128_decrypt_native(const void *ctx, size_t length,
uint8_t *dst, const uint8_t *src)
{
cast128_decrypt(ctx, length, dst, src);
}
DEFINE_ECB_CBC_CTR(qcrypto_nettle_cast128,
QCryptoNettleCAST128, CAST128_BLOCK_SIZE,
cast128_encrypt_native, cast128_decrypt_native)
typedef struct QCryptoNettleSerpent {
QCryptoCipher base;
uint8_t iv[SERPENT_BLOCK_SIZE];
struct serpent_ctx key, key_xts;
} QCryptoNettleSerpent;
static void serpent_encrypt_native(const void *ctx, size_t length,
uint8_t *dst, const uint8_t *src)
{
serpent_encrypt(ctx, length, dst, src);
}
static void serpent_decrypt_native(const void *ctx, size_t length,
uint8_t *dst, const uint8_t *src)
{
serpent_decrypt(ctx, length, dst, src);
}
DEFINE_ECB_CBC_CTR_XTS(qcrypto_nettle_serpent,
QCryptoNettleSerpent, SERPENT_BLOCK_SIZE,
serpent_encrypt_native, serpent_decrypt_native)
typedef struct QCryptoNettleTwofish {
QCryptoCipher base;
uint8_t iv[TWOFISH_BLOCK_SIZE];
struct twofish_ctx key, key_xts;
} QCryptoNettleTwofish;
static void twofish_encrypt_native(const void *ctx, size_t length,
uint8_t *dst, const uint8_t *src)
{
twofish_encrypt(ctx, length, dst, src);
}
static void twofish_decrypt_native(const void *ctx, size_t length,
uint8_t *dst, const uint8_t *src)
{
twofish_decrypt(ctx, length, dst, src);
}
DEFINE_ECB_CBC_CTR_XTS(qcrypto_nettle_twofish,
QCryptoNettleTwofish, TWOFISH_BLOCK_SIZE,
twofish_encrypt_native, twofish_decrypt_native)
bool qcrypto_cipher_supports(QCryptoCipherAlgorithm alg,
QCryptoCipherMode mode)
{
switch (alg) {
case QCRYPTO_CIPHER_ALG_DES:
case QCRYPTO_CIPHER_ALG_3DES:
case QCRYPTO_CIPHER_ALG_AES_128:
case QCRYPTO_CIPHER_ALG_AES_192:
case QCRYPTO_CIPHER_ALG_AES_256:
case QCRYPTO_CIPHER_ALG_CAST5_128:
case QCRYPTO_CIPHER_ALG_SERPENT_128:
case QCRYPTO_CIPHER_ALG_SERPENT_192:
case QCRYPTO_CIPHER_ALG_SERPENT_256:
case QCRYPTO_CIPHER_ALG_TWOFISH_128:
case QCRYPTO_CIPHER_ALG_TWOFISH_192:
case QCRYPTO_CIPHER_ALG_TWOFISH_256:
break;
default:
return false;
}
switch (mode) {
case QCRYPTO_CIPHER_MODE_ECB:
case QCRYPTO_CIPHER_MODE_CBC:
case QCRYPTO_CIPHER_MODE_XTS:
case QCRYPTO_CIPHER_MODE_CTR:
return true;
default:
return false;
}
}
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:
case QCRYPTO_CIPHER_MODE_CTR:
break;
default:
goto bad_cipher_mode;
}
if (!qcrypto_cipher_validate_key_length(alg, mode, nkey, errp)) {
return NULL;
}
switch (alg) {
case QCRYPTO_CIPHER_ALG_DES:
{
QCryptoNettleDES *ctx;
const QCryptoCipherDriver *drv;
switch (mode) {
case QCRYPTO_CIPHER_MODE_ECB:
drv = &qcrypto_nettle_des_driver_ecb;
break;
case QCRYPTO_CIPHER_MODE_CBC:
drv = &qcrypto_nettle_des_driver_cbc;
break;
case QCRYPTO_CIPHER_MODE_CTR:
drv = &qcrypto_nettle_des_driver_ctr;
break;
default:
goto bad_cipher_mode;
}
ctx = g_new0(QCryptoNettleDES, 1);
ctx->base.driver = drv;
des_set_key(&ctx->key, key);
return &ctx->base;
}
case QCRYPTO_CIPHER_ALG_3DES:
{
QCryptoNettleDES3 *ctx;
const QCryptoCipherDriver *drv;
switch (mode) {
case QCRYPTO_CIPHER_MODE_ECB:
drv = &qcrypto_nettle_des3_driver_ecb;
break;
case QCRYPTO_CIPHER_MODE_CBC:
drv = &qcrypto_nettle_des3_driver_cbc;
break;
case QCRYPTO_CIPHER_MODE_CTR:
drv = &qcrypto_nettle_des3_driver_ctr;
break;
default:
goto bad_cipher_mode;
}
ctx = g_new0(QCryptoNettleDES3, 1);
ctx->base.driver = drv;
des3_set_key(&ctx->key, key);
return &ctx->base;
}
case QCRYPTO_CIPHER_ALG_AES_128:
{
QCryptoNettleAES128 *ctx = g_new0(QCryptoNettleAES128, 1);
switch (mode) {
case QCRYPTO_CIPHER_MODE_ECB:
ctx->base.driver = &qcrypto_nettle_aes128_driver_ecb;
break;
case QCRYPTO_CIPHER_MODE_CBC:
ctx->base.driver = &qcrypto_nettle_aes128_driver_cbc;
break;
case QCRYPTO_CIPHER_MODE_CTR:
ctx->base.driver = &qcrypto_nettle_aes128_driver_ctr;
break;
case QCRYPTO_CIPHER_MODE_XTS:
ctx->base.driver = &qcrypto_nettle_aes128_driver_xts;
nkey /= 2;
aes128_set_encrypt_key(&ctx->key_xts[0], key + nkey);
aes128_set_decrypt_key(&ctx->key_xts[1], key + nkey);
break;
default:
g_assert_not_reached();
}
aes128_set_encrypt_key(&ctx->key[0], key);
aes128_set_decrypt_key(&ctx->key[1], key);
return &ctx->base;
}
case QCRYPTO_CIPHER_ALG_AES_192:
{
QCryptoNettleAES192 *ctx = g_new0(QCryptoNettleAES192, 1);
switch (mode) {
case QCRYPTO_CIPHER_MODE_ECB:
ctx->base.driver = &qcrypto_nettle_aes192_driver_ecb;
break;
case QCRYPTO_CIPHER_MODE_CBC:
ctx->base.driver = &qcrypto_nettle_aes192_driver_cbc;
break;
case QCRYPTO_CIPHER_MODE_CTR:
ctx->base.driver = &qcrypto_nettle_aes192_driver_ctr;
break;
case QCRYPTO_CIPHER_MODE_XTS:
ctx->base.driver = &qcrypto_nettle_aes192_driver_xts;
nkey /= 2;
aes192_set_encrypt_key(&ctx->key_xts[0], key + nkey);
aes192_set_decrypt_key(&ctx->key_xts[1], key + nkey);
break;
default:
g_assert_not_reached();
}
aes192_set_encrypt_key(&ctx->key[0], key);
aes192_set_decrypt_key(&ctx->key[1], key);
return &ctx->base;
}
case QCRYPTO_CIPHER_ALG_AES_256:
{
QCryptoNettleAES256 *ctx = g_new0(QCryptoNettleAES256, 1);
switch (mode) {
case QCRYPTO_CIPHER_MODE_ECB:
ctx->base.driver = &qcrypto_nettle_aes256_driver_ecb;
break;
case QCRYPTO_CIPHER_MODE_CBC:
ctx->base.driver = &qcrypto_nettle_aes256_driver_cbc;
break;
case QCRYPTO_CIPHER_MODE_CTR:
ctx->base.driver = &qcrypto_nettle_aes256_driver_ctr;
break;
case QCRYPTO_CIPHER_MODE_XTS:
ctx->base.driver = &qcrypto_nettle_aes256_driver_xts;
nkey /= 2;
aes256_set_encrypt_key(&ctx->key_xts[0], key + nkey);
aes256_set_decrypt_key(&ctx->key_xts[1], key + nkey);
break;
default:
g_assert_not_reached();
}
aes256_set_encrypt_key(&ctx->key[0], key);
aes256_set_decrypt_key(&ctx->key[1], key);
return &ctx->base;
}
case QCRYPTO_CIPHER_ALG_CAST5_128:
{
QCryptoNettleCAST128 *ctx;
const QCryptoCipherDriver *drv;
switch (mode) {
case QCRYPTO_CIPHER_MODE_ECB:
drv = &qcrypto_nettle_cast128_driver_ecb;
break;
case QCRYPTO_CIPHER_MODE_CBC:
drv = &qcrypto_nettle_cast128_driver_cbc;
break;
case QCRYPTO_CIPHER_MODE_CTR:
drv = &qcrypto_nettle_cast128_driver_ctr;
break;
default:
goto bad_cipher_mode;
}
ctx = g_new0(QCryptoNettleCAST128, 1);
ctx->base.driver = drv;
cast5_set_key(&ctx->key, nkey, key);
return &ctx->base;
}
case QCRYPTO_CIPHER_ALG_SERPENT_128:
case QCRYPTO_CIPHER_ALG_SERPENT_192:
case QCRYPTO_CIPHER_ALG_SERPENT_256:
{
QCryptoNettleSerpent *ctx = g_new0(QCryptoNettleSerpent, 1);
switch (mode) {
case QCRYPTO_CIPHER_MODE_ECB:
ctx->base.driver = &qcrypto_nettle_serpent_driver_ecb;
break;
case QCRYPTO_CIPHER_MODE_CBC:
ctx->base.driver = &qcrypto_nettle_serpent_driver_cbc;
break;
case QCRYPTO_CIPHER_MODE_CTR:
ctx->base.driver = &qcrypto_nettle_serpent_driver_ctr;
break;
case QCRYPTO_CIPHER_MODE_XTS:
ctx->base.driver = &qcrypto_nettle_serpent_driver_xts;
nkey /= 2;
serpent_set_key(&ctx->key_xts, nkey, key + nkey);
break;
default:
g_assert_not_reached();
}
serpent_set_key(&ctx->key, nkey, key);
return &ctx->base;
}
case QCRYPTO_CIPHER_ALG_TWOFISH_128:
case QCRYPTO_CIPHER_ALG_TWOFISH_192:
case QCRYPTO_CIPHER_ALG_TWOFISH_256:
{
QCryptoNettleTwofish *ctx = g_new0(QCryptoNettleTwofish, 1);
switch (mode) {
case QCRYPTO_CIPHER_MODE_ECB:
ctx->base.driver = &qcrypto_nettle_twofish_driver_ecb;
break;
case QCRYPTO_CIPHER_MODE_CBC:
ctx->base.driver = &qcrypto_nettle_twofish_driver_cbc;
break;
case QCRYPTO_CIPHER_MODE_CTR:
ctx->base.driver = &qcrypto_nettle_twofish_driver_ctr;
break;
case QCRYPTO_CIPHER_MODE_XTS:
ctx->base.driver = &qcrypto_nettle_twofish_driver_xts;
nkey /= 2;
twofish_set_key(&ctx->key_xts, nkey, key + nkey);
break;
default:
g_assert_not_reached();
}
twofish_set_key(&ctx->key, nkey, key);
return &ctx->base;
}
default:
error_setg(errp, "Unsupported cipher algorithm %s",
QCryptoCipherAlgorithm_str(alg));
return NULL;
}
bad_cipher_mode:
error_setg(errp, "Unsupported cipher mode %s",
QCryptoCipherMode_str(mode));
return NULL;
}