diff options
Diffstat (limited to 'qemu/crypto/cipher-builtin.c')
-rw-r--r-- | qemu/crypto/cipher-builtin.c | 513 |
1 files changed, 0 insertions, 513 deletions
diff --git a/qemu/crypto/cipher-builtin.c b/qemu/crypto/cipher-builtin.c deleted file mode 100644 index 88963f65c..000000000 --- a/qemu/crypto/cipher-builtin.c +++ /dev/null @@ -1,513 +0,0 @@ -/* - * 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 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/aes.h" -#include "crypto/desrfb.h" -#include "crypto/xts.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(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(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((AES_KEY *)&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((AES_KEY *)&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 int qcrypto_cipher_init_aes(QCryptoCipher *cipher, - const uint8_t *key, size_t nkey, - Error **errp) -{ - QCryptoCipherBuiltin *ctxt; - - if (cipher->mode != QCRYPTO_CIPHER_MODE_CBC && - cipher->mode != QCRYPTO_CIPHER_MODE_ECB && - cipher->mode != QCRYPTO_CIPHER_MODE_XTS) { - error_setg(errp, "Unsupported cipher mode %d", cipher->mode); - return -1; - } - - ctxt = g_new0(QCryptoCipherBuiltin, 1); - - if (cipher->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; - - cipher->opaque = ctxt; - - return 0; - - error: - g_free(ctxt); - return -1; -} - - -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 int qcrypto_cipher_init_des_rfb(QCryptoCipher *cipher, - const uint8_t *key, size_t nkey, - Error **errp) -{ - QCryptoCipherBuiltin *ctxt; - - if (cipher->mode != QCRYPTO_CIPHER_MODE_ECB) { - error_setg(errp, "Unsupported cipher mode %d", cipher->mode); - return -1; - } - - 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; - - cipher->opaque = ctxt; - - return 0; -} - - -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: - return true; - default: - return false; - } -} - - -QCryptoCipher *qcrypto_cipher_new(QCryptoCipherAlgorithm alg, - QCryptoCipherMode mode, - const uint8_t *key, size_t nkey, - Error **errp) -{ - QCryptoCipher *cipher; - - cipher = g_new0(QCryptoCipher, 1); - cipher->alg = alg; - cipher->mode = mode; - - if (!qcrypto_cipher_validate_key_length(alg, mode, nkey, errp)) { - goto error; - } - - switch (cipher->alg) { - case QCRYPTO_CIPHER_ALG_DES_RFB: - if (qcrypto_cipher_init_des_rfb(cipher, key, nkey, errp) < 0) { - goto error; - } - break; - case QCRYPTO_CIPHER_ALG_AES_128: - case QCRYPTO_CIPHER_ALG_AES_192: - case QCRYPTO_CIPHER_ALG_AES_256: - if (qcrypto_cipher_init_aes(cipher, key, nkey, errp) < 0) { - goto error; - } - break; - default: - error_setg(errp, - "Unsupported cipher algorithm %d", cipher->alg); - goto error; - } - - return cipher; - - error: - g_free(cipher); - return NULL; -} - -void qcrypto_cipher_free(QCryptoCipher *cipher) -{ - QCryptoCipherBuiltin *ctxt; - - if (!cipher) { - return; - } - - ctxt = cipher->opaque; - ctxt->free(cipher); - g_free(cipher); -} - - -int qcrypto_cipher_encrypt(QCryptoCipher *cipher, - const void *in, - void *out, - size_t len, - Error **errp) -{ - QCryptoCipherBuiltin *ctxt = cipher->opaque; - - if (len % ctxt->blocksize) { - 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); -} - - -int qcrypto_cipher_decrypt(QCryptoCipher *cipher, - const void *in, - void *out, - size_t len, - Error **errp) -{ - QCryptoCipherBuiltin *ctxt = cipher->opaque; - - if (len % ctxt->blocksize) { - 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); -} - - -int qcrypto_cipher_setiv(QCryptoCipher *cipher, - const uint8_t *iv, size_t niv, - Error **errp) -{ - QCryptoCipherBuiltin *ctxt = cipher->opaque; - - return ctxt->setiv(cipher, iv, niv, errp); -} |