Skip to content

Commit

Permalink
Merge remote-tracking branch 'remotes/berrange/tags/pull-qcrypto-2016…
Browse files Browse the repository at this point in the history
…-12-21-2' into staging

Merge qcrypto 2016/12/21 v2

# gpg: Signature made Thu 22 Dec 2016 10:46:17 GMT
# gpg:                using RSA key 0xBE86EBB415104FDF
# gpg: Good signature from "Daniel P. Berrange <dan@berrange.com>"
# gpg:                 aka "Daniel P. Berrange <berrange@redhat.com>"
# Primary key fingerprint: DAF3 A6FD B26B 6291 2D0E  8E3F BE86 EBB4 1510 4FDF

* remotes/berrange/tags/pull-qcrypto-2016-12-21-2:
  crypto: add HMAC algorithms testcases
  crypto: support HMAC algorithms based on nettle
  crypto: support HMAC algorithms based on glib
  crypto: support HMAC algorithms based on libgcrypt
  crypto: add HMAC algorithms framework
  configure: add CONFIG_GCRYPT_HMAC item
  crypto: add 3des-ede support when using libgcrypt/nettle
  cipher: fix leak on initialization error

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
  • Loading branch information
pm215 committed Dec 22, 2016
2 parents 225adf1 + 4fd460b commit c76904e
Show file tree
Hide file tree
Showing 14 changed files with 1,191 additions and 6 deletions.
17 changes: 17 additions & 0 deletions configure
Expand Up @@ -313,6 +313,7 @@ gnutls_rnd=""
nettle=""
nettle_kdf="no"
gcrypt=""
gcrypt_hmac="no"
gcrypt_kdf="no"
vte=""
virglrenderer=""
Expand Down Expand Up @@ -2417,6 +2418,19 @@ EOF
if compile_prog "$gcrypt_cflags" "$gcrypt_libs" ; then
gcrypt_kdf=yes
fi

cat > $TMPC << EOF
#include <gcrypt.h>
int main(void) {
gcry_mac_hd_t handle;
gcry_mac_open(&handle, GCRY_MAC_HMAC_MD5,
GCRY_MAC_FLAG_SECURE, NULL);
return 0;
}
EOF
if compile_prog "$gcrypt_cflags" "$gcrypt_libs" ; then
gcrypt_hmac=yes
fi
else
if test "$gcrypt" = "yes"; then
feature_not_found "gcrypt" "Install gcrypt devel"
Expand Down Expand Up @@ -5387,6 +5401,9 @@ if test "$gnutls_rnd" = "yes" ; then
fi
if test "$gcrypt" = "yes" ; then
echo "CONFIG_GCRYPT=y" >> $config_host_mak
if test "$gcrypt_hmac" = "yes" ; then
echo "CONFIG_GCRYPT_HMAC=y" >> $config_host_mak
fi
if test "$gcrypt_kdf" = "yes" ; then
echo "CONFIG_GCRYPT_KDF=y" >> $config_host_mak
fi
Expand Down
4 changes: 4 additions & 0 deletions crypto/Makefile.objs
Expand Up @@ -3,6 +3,10 @@ crypto-obj-y += hash.o
crypto-obj-$(CONFIG_NETTLE) += hash-nettle.o
crypto-obj-$(if $(CONFIG_NETTLE),n,$(CONFIG_GCRYPT)) += hash-gcrypt.o
crypto-obj-$(if $(CONFIG_NETTLE),n,$(if $(CONFIG_GCRYPT),n,y)) += hash-glib.o
crypto-obj-y += hmac.o
crypto-obj-$(CONFIG_NETTLE) += hmac-nettle.o
crypto-obj-$(CONFIG_GCRYPT_HMAC) += hmac-gcrypt.o
crypto-obj-$(if $(CONFIG_NETTLE),n,$(if $(CONFIG_GCRYPT_HMAC),n,y)) += hmac-glib.o
crypto-obj-y += aes.o
crypto-obj-y += desrfb.o
crypto-obj-y += cipher.o
Expand Down
6 changes: 6 additions & 0 deletions crypto/cipher-gcrypt.c
Expand Up @@ -29,6 +29,7 @@ bool qcrypto_cipher_supports(QCryptoCipherAlgorithm alg,
{
switch (alg) {
case QCRYPTO_CIPHER_ALG_DES_RFB:
case QCRYPTO_CIPHER_ALG_3DES:
case QCRYPTO_CIPHER_ALG_AES_128:
case QCRYPTO_CIPHER_ALG_AES_192:
case QCRYPTO_CIPHER_ALG_AES_256:
Expand Down Expand Up @@ -99,6 +100,10 @@ QCryptoCipher *qcrypto_cipher_new(QCryptoCipherAlgorithm alg,
gcryalg = GCRY_CIPHER_DES;
break;

case QCRYPTO_CIPHER_ALG_3DES:
gcryalg = GCRY_CIPHER_3DES;
break;

case QCRYPTO_CIPHER_ALG_AES_128:
gcryalg = GCRY_CIPHER_AES128;
break;
Expand Down Expand Up @@ -200,6 +205,7 @@ QCryptoCipher *qcrypto_cipher_new(QCryptoCipherAlgorithm alg,
case QCRYPTO_CIPHER_ALG_TWOFISH_256:
ctx->blocksize = 16;
break;
case QCRYPTO_CIPHER_ALG_3DES:
case QCRYPTO_CIPHER_ALG_CAST5_128:
ctx->blocksize = 8;
break;
Expand Down
42 changes: 39 additions & 3 deletions crypto/cipher-nettle.c
Expand Up @@ -78,6 +78,18 @@ static void des_decrypt_native(cipher_ctx_t ctx, cipher_length_t length,
des_decrypt(ctx, length, dst, src);
}

static void des3_encrypt_native(cipher_ctx_t ctx, cipher_length_t length,
uint8_t *dst, const uint8_t *src)
{
des3_encrypt(ctx, length, dst, src);
}

static void des3_decrypt_native(cipher_ctx_t ctx, cipher_length_t length,
uint8_t *dst, const uint8_t *src)
{
des3_decrypt(ctx, length, dst, src);
}

static void cast128_encrypt_native(cipher_ctx_t ctx, cipher_length_t length,
uint8_t *dst, const uint8_t *src)
{
Expand Down Expand Up @@ -140,6 +152,18 @@ static void des_decrypt_wrapper(const void *ctx, size_t length,
des_decrypt(ctx, length, dst, src);
}

static void des3_encrypt_wrapper(const void *ctx, size_t length,
uint8_t *dst, const uint8_t *src)
{
des3_encrypt(ctx, length, dst, src);
}

static void des3_decrypt_wrapper(const void *ctx, size_t length,
uint8_t *dst, const uint8_t *src)
{
des3_decrypt(ctx, length, dst, src);
}

static void cast128_encrypt_wrapper(const void *ctx, size_t length,
uint8_t *dst, const uint8_t *src)
{
Expand Down Expand Up @@ -197,6 +221,7 @@ bool qcrypto_cipher_supports(QCryptoCipherAlgorithm alg,
{
switch (alg) {
case QCRYPTO_CIPHER_ALG_DES_RFB:
case QCRYPTO_CIPHER_ALG_3DES:
case QCRYPTO_CIPHER_ALG_AES_128:
case QCRYPTO_CIPHER_ALG_AES_192:
case QCRYPTO_CIPHER_ALG_AES_256:
Expand Down Expand Up @@ -254,6 +279,7 @@ QCryptoCipher *qcrypto_cipher_new(QCryptoCipherAlgorithm alg,
cipher->mode = mode;

ctx = g_new0(QCryptoCipherNettle, 1);
cipher->opaque = ctx;

switch (alg) {
case QCRYPTO_CIPHER_ALG_DES_RFB:
Expand All @@ -270,6 +296,18 @@ QCryptoCipher *qcrypto_cipher_new(QCryptoCipherAlgorithm alg,
ctx->blocksize = DES_BLOCK_SIZE;
break;

case QCRYPTO_CIPHER_ALG_3DES:
ctx->ctx = g_new0(struct des3_ctx, 1);
des3_set_key(ctx->ctx, key);

ctx->alg_encrypt_native = des3_encrypt_native;
ctx->alg_decrypt_native = des3_decrypt_native;
ctx->alg_encrypt_wrapper = des3_encrypt_wrapper;
ctx->alg_decrypt_wrapper = des3_decrypt_wrapper;

ctx->blocksize = DES3_BLOCK_SIZE;
break;

case QCRYPTO_CIPHER_ALG_AES_128:
case QCRYPTO_CIPHER_ALG_AES_192:
case QCRYPTO_CIPHER_ALG_AES_256:
Expand Down Expand Up @@ -384,13 +422,11 @@ QCryptoCipher *qcrypto_cipher_new(QCryptoCipherAlgorithm alg,
}

ctx->iv = g_new0(uint8_t, ctx->blocksize);
cipher->opaque = ctx;

return cipher;

error:
g_free(cipher);
g_free(ctx);
qcrypto_cipher_free(cipher);
return NULL;
}

Expand Down
7 changes: 5 additions & 2 deletions crypto/cipher.c
Expand Up @@ -28,6 +28,7 @@ static size_t alg_key_len[QCRYPTO_CIPHER_ALG__MAX] = {
[QCRYPTO_CIPHER_ALG_AES_192] = 24,
[QCRYPTO_CIPHER_ALG_AES_256] = 32,
[QCRYPTO_CIPHER_ALG_DES_RFB] = 8,
[QCRYPTO_CIPHER_ALG_3DES] = 24,
[QCRYPTO_CIPHER_ALG_CAST5_128] = 16,
[QCRYPTO_CIPHER_ALG_SERPENT_128] = 16,
[QCRYPTO_CIPHER_ALG_SERPENT_192] = 24,
Expand All @@ -42,6 +43,7 @@ static size_t alg_block_len[QCRYPTO_CIPHER_ALG__MAX] = {
[QCRYPTO_CIPHER_ALG_AES_192] = 16,
[QCRYPTO_CIPHER_ALG_AES_256] = 16,
[QCRYPTO_CIPHER_ALG_DES_RFB] = 8,
[QCRYPTO_CIPHER_ALG_3DES] = 8,
[QCRYPTO_CIPHER_ALG_CAST5_128] = 8,
[QCRYPTO_CIPHER_ALG_SERPENT_128] = 16,
[QCRYPTO_CIPHER_ALG_SERPENT_192] = 16,
Expand Down Expand Up @@ -107,8 +109,9 @@ qcrypto_cipher_validate_key_length(QCryptoCipherAlgorithm alg,
}

if (mode == QCRYPTO_CIPHER_MODE_XTS) {
if (alg == QCRYPTO_CIPHER_ALG_DES_RFB) {
error_setg(errp, "XTS mode not compatible with DES-RFB");
if (alg == QCRYPTO_CIPHER_ALG_DES_RFB
|| alg == QCRYPTO_CIPHER_ALG_3DES) {
error_setg(errp, "XTS mode not compatible with DES-RFB/3DES");
return false;
}
if (nkey % 2) {
Expand Down
152 changes: 152 additions & 0 deletions crypto/hmac-gcrypt.c
@@ -0,0 +1,152 @@
/*
* QEMU Crypto hmac algorithms (based on libgcrypt)
*
* Copyright (c) 2016 HUAWEI TECHNOLOGIES CO., LTD.
*
* Authors:
* Longpeng(Mike) <longpeng2@huawei.com>
*
* This work is licensed under the terms of the GNU GPL, version 2 or
* (at your option) any later version. See the COPYING file in the
* top-level directory.
*
*/

#include "qemu/osdep.h"
#include "qapi/error.h"
#include "crypto/hmac.h"
#include <gcrypt.h>

static int qcrypto_hmac_alg_map[QCRYPTO_HASH_ALG__MAX] = {
[QCRYPTO_HASH_ALG_MD5] = GCRY_MAC_HMAC_MD5,
[QCRYPTO_HASH_ALG_SHA1] = GCRY_MAC_HMAC_SHA1,
[QCRYPTO_HASH_ALG_SHA224] = GCRY_MAC_HMAC_SHA224,
[QCRYPTO_HASH_ALG_SHA256] = GCRY_MAC_HMAC_SHA256,
[QCRYPTO_HASH_ALG_SHA384] = GCRY_MAC_HMAC_SHA384,
[QCRYPTO_HASH_ALG_SHA512] = GCRY_MAC_HMAC_SHA512,
[QCRYPTO_HASH_ALG_RIPEMD160] = GCRY_MAC_HMAC_RMD160,
};

typedef struct QCryptoHmacGcrypt QCryptoHmacGcrypt;
struct QCryptoHmacGcrypt {
gcry_mac_hd_t handle;
};

bool qcrypto_hmac_supports(QCryptoHashAlgorithm alg)
{
if (alg < G_N_ELEMENTS(qcrypto_hmac_alg_map) &&
qcrypto_hmac_alg_map[alg] != GCRY_MAC_NONE) {
return true;
}

return false;
}

QCryptoHmac *qcrypto_hmac_new(QCryptoHashAlgorithm alg,
const uint8_t *key, size_t nkey,
Error **errp)
{
QCryptoHmac *hmac;
QCryptoHmacGcrypt *ctx;
gcry_error_t err;

if (!qcrypto_hmac_supports(alg)) {
error_setg(errp, "Unsupported hmac algorithm %s",
QCryptoHashAlgorithm_lookup[alg]);
return NULL;
}

hmac = g_new0(QCryptoHmac, 1);
hmac->alg = alg;

ctx = g_new0(QCryptoHmacGcrypt, 1);

err = gcry_mac_open(&ctx->handle, qcrypto_hmac_alg_map[alg],
GCRY_MAC_FLAG_SECURE, NULL);
if (err != 0) {
error_setg(errp, "Cannot initialize hmac: %s",
gcry_strerror(err));
goto error;
}

err = gcry_mac_setkey(ctx->handle, (const void *)key, nkey);
if (err != 0) {
error_setg(errp, "Cannot set key: %s",
gcry_strerror(err));
goto error;
}

hmac->opaque = ctx;
return hmac;

error:
g_free(ctx);
g_free(hmac);
return NULL;
}

void qcrypto_hmac_free(QCryptoHmac *hmac)
{
QCryptoHmacGcrypt *ctx;

if (!hmac) {
return;
}

ctx = hmac->opaque;
gcry_mac_close(ctx->handle);

g_free(ctx);
g_free(hmac);
}

int qcrypto_hmac_bytesv(QCryptoHmac *hmac,
const struct iovec *iov,
size_t niov,
uint8_t **result,
size_t *resultlen,
Error **errp)
{
QCryptoHmacGcrypt *ctx;
gcry_error_t err;
uint32_t ret;
int i;

ctx = hmac->opaque;

for (i = 0; i < niov; i++) {
gcry_mac_write(ctx->handle, iov[i].iov_base, iov[i].iov_len);
}

ret = gcry_mac_get_algo_maclen(qcrypto_hmac_alg_map[hmac->alg]);
if (ret <= 0) {
error_setg(errp, "Unable to get hmac length: %s",
gcry_strerror(ret));
return -1;
}

if (*resultlen == 0) {
*resultlen = ret;
*result = g_new0(uint8_t, *resultlen);
} else if (*resultlen != ret) {
error_setg(errp, "Result buffer size %zu is smaller than hmac %d",
*resultlen, ret);
return -1;
}

err = gcry_mac_read(ctx->handle, *result, resultlen);
if (err != 0) {
error_setg(errp, "Cannot get result: %s",
gcry_strerror(err));
return -1;
}

err = gcry_mac_reset(ctx->handle);
if (err != 0) {
error_setg(errp, "Cannot reset hmac context: %s",
gcry_strerror(err));
return -1;
}

return 0;
}

0 comments on commit c76904e

Please sign in to comment.