diff options
Diffstat (limited to 'qemu/crypto/cipher-gcrypt.c')
-rw-r--r-- | qemu/crypto/cipher-gcrypt.c | 344 |
1 files changed, 0 insertions, 344 deletions
diff --git a/qemu/crypto/cipher-gcrypt.c b/qemu/crypto/cipher-gcrypt.c deleted file mode 100644 index ede2f70df..000000000 --- a/qemu/crypto/cipher-gcrypt.c +++ /dev/null @@ -1,344 +0,0 @@ -/* - * QEMU Crypto cipher libgcrypt 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 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, see <http://www.gnu.org/licenses/>. - * - */ - -#include "qemu/osdep.h" -#include "crypto/xts.h" - -#include <gcrypt.h> - - -bool qcrypto_cipher_supports(QCryptoCipherAlgorithm alg) -{ - 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: - 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_256: - return true; - default: - return false; - } -} - -typedef struct QCryptoCipherGcrypt QCryptoCipherGcrypt; -struct QCryptoCipherGcrypt { - gcry_cipher_hd_t handle; - gcry_cipher_hd_t tweakhandle; - size_t blocksize; - uint8_t *iv; -}; - -QCryptoCipher *qcrypto_cipher_new(QCryptoCipherAlgorithm alg, - QCryptoCipherMode mode, - const uint8_t *key, size_t nkey, - Error **errp) -{ - QCryptoCipher *cipher; - QCryptoCipherGcrypt *ctx; - gcry_error_t err; - int gcryalg, gcrymode; - - switch (mode) { - case QCRYPTO_CIPHER_MODE_ECB: - case QCRYPTO_CIPHER_MODE_XTS: - gcrymode = GCRY_CIPHER_MODE_ECB; - break; - case QCRYPTO_CIPHER_MODE_CBC: - gcrymode = GCRY_CIPHER_MODE_CBC; - break; - default: - error_setg(errp, "Unsupported cipher mode %d", mode); - return NULL; - } - - if (!qcrypto_cipher_validate_key_length(alg, mode, nkey, errp)) { - return NULL; - } - - switch (alg) { - case QCRYPTO_CIPHER_ALG_DES_RFB: - gcryalg = GCRY_CIPHER_DES; - break; - - case QCRYPTO_CIPHER_ALG_AES_128: - gcryalg = GCRY_CIPHER_AES128; - break; - - case QCRYPTO_CIPHER_ALG_AES_192: - gcryalg = GCRY_CIPHER_AES192; - break; - - case QCRYPTO_CIPHER_ALG_AES_256: - gcryalg = GCRY_CIPHER_AES256; - break; - - case QCRYPTO_CIPHER_ALG_CAST5_128: - gcryalg = GCRY_CIPHER_CAST5; - break; - - case QCRYPTO_CIPHER_ALG_SERPENT_128: - gcryalg = GCRY_CIPHER_SERPENT128; - break; - - case QCRYPTO_CIPHER_ALG_SERPENT_192: - gcryalg = GCRY_CIPHER_SERPENT192; - break; - - case QCRYPTO_CIPHER_ALG_SERPENT_256: - gcryalg = GCRY_CIPHER_SERPENT256; - break; - - case QCRYPTO_CIPHER_ALG_TWOFISH_128: - gcryalg = GCRY_CIPHER_TWOFISH128; - break; - - case QCRYPTO_CIPHER_ALG_TWOFISH_256: - gcryalg = GCRY_CIPHER_TWOFISH; - break; - - default: - error_setg(errp, "Unsupported cipher algorithm %d", alg); - return NULL; - } - - cipher = g_new0(QCryptoCipher, 1); - cipher->alg = alg; - cipher->mode = mode; - - ctx = g_new0(QCryptoCipherGcrypt, 1); - - err = gcry_cipher_open(&ctx->handle, gcryalg, gcrymode, 0); - if (err != 0) { - error_setg(errp, "Cannot initialize cipher: %s", - gcry_strerror(err)); - goto error; - } - if (cipher->mode == QCRYPTO_CIPHER_MODE_XTS) { - err = gcry_cipher_open(&ctx->tweakhandle, gcryalg, gcrymode, 0); - if (err != 0) { - error_setg(errp, "Cannot initialize cipher: %s", - gcry_strerror(err)); - goto error; - } - } - - if (cipher->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); - ctx->blocksize = 8; - } else { - if (cipher->mode == QCRYPTO_CIPHER_MODE_XTS) { - nkey /= 2; - err = gcry_cipher_setkey(ctx->handle, key, nkey); - if (err != 0) { - error_setg(errp, "Cannot set key: %s", - gcry_strerror(err)); - goto error; - } - err = gcry_cipher_setkey(ctx->tweakhandle, key + nkey, nkey); - } else { - err = gcry_cipher_setkey(ctx->handle, key, nkey); - } - if (err != 0) { - error_setg(errp, "Cannot set key: %s", - gcry_strerror(err)); - goto error; - } - switch (cipher->alg) { - case QCRYPTO_CIPHER_ALG_AES_128: - case QCRYPTO_CIPHER_ALG_AES_192: - case QCRYPTO_CIPHER_ALG_AES_256: - 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_256: - ctx->blocksize = 16; - break; - case QCRYPTO_CIPHER_ALG_CAST5_128: - ctx->blocksize = 8; - break; - default: - g_assert_not_reached(); - } - } - - if (cipher->mode == QCRYPTO_CIPHER_MODE_XTS) { - ctx->iv = g_new0(uint8_t, ctx->blocksize); - } - - cipher->opaque = ctx; - return cipher; - - error: - gcry_cipher_close(ctx->handle); - if (cipher->mode == QCRYPTO_CIPHER_MODE_XTS) { - gcry_cipher_close(ctx->tweakhandle); - } - g_free(ctx); - g_free(cipher); - return NULL; -} - - -void qcrypto_cipher_free(QCryptoCipher *cipher) -{ - QCryptoCipherGcrypt *ctx; - if (!cipher) { - return; - } - ctx = cipher->opaque; - gcry_cipher_close(ctx->handle); - if (cipher->mode == QCRYPTO_CIPHER_MODE_XTS) { - gcry_cipher_close(ctx->tweakhandle); - } - g_free(ctx->iv); - g_free(ctx); - g_free(cipher); -} - - -static void qcrypto_gcrypt_xts_encrypt(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_decrypt(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); -} - -int qcrypto_cipher_encrypt(QCryptoCipher *cipher, - const void *in, - void *out, - size_t len, - Error **errp) -{ - QCryptoCipherGcrypt *ctx = cipher->opaque; - gcry_error_t err; - - if (len % ctx->blocksize) { - error_setg(errp, "Length %zu must be a multiple of block size %zu", - len, ctx->blocksize); - return -1; - } - - if (cipher->mode == QCRYPTO_CIPHER_MODE_XTS) { - xts_encrypt(ctx->handle, ctx->tweakhandle, - qcrypto_gcrypt_xts_encrypt, - qcrypto_gcrypt_xts_decrypt, - ctx->iv, len, out, in); - } else { - err = gcry_cipher_encrypt(ctx->handle, - out, len, - in, len); - if (err != 0) { - error_setg(errp, "Cannot encrypt data: %s", - gcry_strerror(err)); - return -1; - } - } - - return 0; -} - - -int qcrypto_cipher_decrypt(QCryptoCipher *cipher, - const void *in, - void *out, - size_t len, - Error **errp) -{ - QCryptoCipherGcrypt *ctx = cipher->opaque; - gcry_error_t err; - - if (len % ctx->blocksize) { - error_setg(errp, "Length %zu must be a multiple of block size %zu", - len, ctx->blocksize); - return -1; - } - - if (cipher->mode == QCRYPTO_CIPHER_MODE_XTS) { - xts_decrypt(ctx->handle, ctx->tweakhandle, - qcrypto_gcrypt_xts_encrypt, - qcrypto_gcrypt_xts_decrypt, - ctx->iv, len, out, in); - } else { - err = gcry_cipher_decrypt(ctx->handle, - out, len, - in, len); - if (err != 0) { - error_setg(errp, "Cannot decrypt data: %s", - gcry_strerror(err)); - return -1; - } - } - - return 0; -} - -int qcrypto_cipher_setiv(QCryptoCipher *cipher, - const uint8_t *iv, size_t niv, - Error **errp) -{ - QCryptoCipherGcrypt *ctx = cipher->opaque; - gcry_error_t err; - - if (niv != ctx->blocksize) { - error_setg(errp, "Expected IV size %zu not %zu", - ctx->blocksize, niv); - return -1; - } - - if (ctx->iv) { - memcpy(ctx->iv, iv, niv); - } else { - gcry_cipher_reset(ctx->handle); - err = gcry_cipher_setiv(ctx->handle, iv, niv); - if (err != 0) { - error_setg(errp, "Cannot set IV: %s", - gcry_strerror(err)); - return -1; - } - } - - return 0; -} |