Merge qcrypto 2017/07/18 v2

-----BEGIN PGP SIGNATURE-----
 
 iQIcBAABCAAGBQJZbyI5AAoJEL6G67QVEE/fyPUP/AlDNC/k0vr7jqaGciqsBelm
 k8Bi9aTEC+/A/tW4q2+insjbfmTZemGubMzmi4wk2vMn8flQRva7fYgnOCzwY4o5
 gsGPPDRK0QhOeyXfneTrfHTyLtcDRnWITCtdSIJk520NmL4a1ClWHtDbUW26+3z7
 MfWUnNZHamNtg+8AXxQf20xWsklMIchjKCtFLhB8KQxZcUEG9GayAoY9s/6Rv5pD
 QrmrJeRhDzW7pXMeQZoVPdiyXmzfd9yK3y/CT0Rk3l2P5miBn0kFn3nNCgh2EsF5
 JSh8F9SGK2dMhuJXUpsl9P2LzafPcsHVgNRo3s7qGpzQT3NhqvaZb7/tMsGizVvK
 cMgecDnWN0JreTVnLu4+4FPhs6XAcj8P3+rbrUdgJgH/2qrOISM+VXWHwPhQ8jUA
 R+yEmdzMWAgF2926Gm5X1iMWyBlzIYwXSoQDY5b40hO76FtPWHKgYY5g5aaLq6qO
 cTvw6dPHoHc6LDyuJ0m6htLSKjSSr86fv2FySBYr7Tbma2ZKK66vWQJ5xA8jA5QF
 vFd3esNT0AF+JsmpNsxoadzlBTBEl8sL58d4J4goJULY75VlTN/Fi+zWmNOU9nX2
 OWakEApSESHAeBeDd5+doLG9JqQEbeG9jBCS7vVJspEmivLd/PI3F/142zFnPItp
 iNpQXVpx2aMFZWs5ueot
 =iobN
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'remotes/berrange/tags/pull-qcrypto-2017-07-18-2' into staging

Merge qcrypto 2017/07/18 v2

# gpg: Signature made Wed 19 Jul 2017 10:11:21 BST
# gpg:                using RSA key 0xBE86EBB415104FDF
# gpg: Good signature from "Daniel P. Berrange <dan@berrange.com>"
# gpg:                 aka "Daniel P. Berrange <berrange@redhat.com>"
# gpg: WARNING: This key is not certified with a trusted signature!
# gpg:          There is no indication that the signature belongs to the owner.
# Primary key fingerprint: DAF3 A6FD B26B 6291 2D0E  8E3F BE86 EBB4 1510 4FDF

* remotes/berrange/tags/pull-qcrypto-2017-07-18-2:
  tests: crypto: add hmac speed benchmark support
  tests: crypto: add hash speed benchmark support
  tests: crypto: add cipher speed benchmark support
  crypto: hmac: add af_alg-backend hmac support
  crypto: hash: add afalg-backend hash support
  crypto: cipher: add afalg-backend cipher support
  crypto: introduce some common functions for af_alg backend
  crypto: hmac: add hmac driver framework
  crypto: hmac: introduce qcrypto_hmac_ctx_new for glib-backend
  crypto: hmac: introduce qcrypto_hmac_ctx_new for nettle-backend
  crypto: hmac: introduce qcrypto_hmac_ctx_new for gcrypt-backend
  crypto: hmac: move crypto/hmac.h into include/crypto/
  crypto: hash: add hash driver framework
  crypto: cipher: add cipher driver framework
  crypto: cipher: introduce qcrypto_cipher_ctx_new for builtin-backend
  crypto: cipher: introduce qcrypto_cipher_ctx_new for nettle-backend
  crypto: cipher: introduce qcrypto_cipher_ctx_new for gcrypt-backend
  crypto: cipher: introduce context free function

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2017-07-19 20:45:37 +01:00
commit d4e59218ab
28 changed files with 1499 additions and 245 deletions

37
configure vendored
View File

@ -375,6 +375,7 @@ libnfs=""
coroutine=""
coroutine_pool=""
debug_stack_usage="no"
crypto_afalg="no"
seccomp=""
glusterfs=""
glusterfs_xlator_opt="no"
@ -1124,6 +1125,10 @@ for opt do
;;
--enable-debug-stack-usage) debug_stack_usage="yes"
;;
--enable-crypto-afalg) crypto_afalg="yes"
;;
--disable-crypto-afalg) crypto_afalg="no"
;;
--disable-docs) docs="no"
;;
--enable-docs) docs="yes"
@ -1518,6 +1523,7 @@ disabled with --disable-FEATURE, default is enabled if available:
qom-cast-debug cast debugging support
tools build qemu-io, qemu-nbd and qemu-image tools
vxhs Veritas HyperScale vDisk backend support
crypto-afalg Linux AF_ALG crypto backend driver
NOTE: The object files are built at the place where configure is launched
EOF
@ -4852,6 +4858,32 @@ if compile_prog "" "" ; then
have_af_vsock=yes
fi
##########################################
# check for usable AF_ALG environment
hava_afalg=no
cat > $TMPC << EOF
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <linux/if_alg.h>
int main(void) {
int sock;
sock = socket(AF_ALG, SOCK_SEQPACKET, 0);
return sock;
}
EOF
if compile_prog "" "" ; then
have_afalg=yes
fi
if test "$crypto_afalg" = "yes"
then
if test "$have_afalg" != "yes"
then
error_exit "AF_ALG requested but could not be detected"
fi
fi
#################################################
# Sparc implicitly links with --relax, which is
# incompatible with -r, so --no-relax should be
@ -5333,6 +5365,7 @@ echo "seccomp support $seccomp"
echo "coroutine backend $coroutine"
echo "coroutine pool $coroutine_pool"
echo "debug stack usage $debug_stack_usage"
echo "crypto afalg $crypto_afalg"
echo "GlusterFS support $glusterfs"
echo "gcov $gcov_tool"
echo "gcov enabled $gcov"
@ -5844,6 +5877,10 @@ if test "$debug_stack_usage" = "yes" ; then
echo "CONFIG_DEBUG_STACK_USAGE=y" >> $config_host_mak
fi
if test "$crypto_afalg" = "yes" ; then
echo "CONFIG_AF_ALG=y" >> $config_host_mak
fi
if test "$open_by_handle_at" = "yes" ; then
echo "CONFIG_OPEN_BY_HANDLE=y" >> $config_host_mak
fi

View File

@ -10,6 +10,9 @@ crypto-obj-$(if $(CONFIG_NETTLE),n,$(if $(CONFIG_GCRYPT_HMAC),n,y)) += hmac-glib
crypto-obj-y += aes.o
crypto-obj-y += desrfb.o
crypto-obj-y += cipher.o
crypto-obj-$(CONFIG_AF_ALG) += afalg.o
crypto-obj-$(CONFIG_AF_ALG) += cipher-afalg.o
crypto-obj-$(CONFIG_AF_ALG) += hash-afalg.o
crypto-obj-y += tlscreds.o
crypto-obj-y += tlscredsanon.o
crypto-obj-y += tlscredsx509.o

116
crypto/afalg.c Normal file
View File

@ -0,0 +1,116 @@
/*
* QEMU Crypto af_alg support
*
* Copyright (c) 2017 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 "qemu/cutils.h"
#include "qemu/sockets.h"
#include "qapi/error.h"
#include "afalgpriv.h"
static bool
qcrypto_afalg_build_saddr(const char *type, const char *name,
struct sockaddr_alg *salg, Error **errp)
{
salg->salg_family = AF_ALG;
if (strnlen(type, SALG_TYPE_LEN_MAX) >= SALG_TYPE_LEN_MAX) {
error_setg(errp, "Afalg type(%s) is larger than %d bytes",
type, SALG_TYPE_LEN_MAX);
return false;
}
if (strnlen(name, SALG_NAME_LEN_MAX) >= SALG_NAME_LEN_MAX) {
error_setg(errp, "Afalg name(%s) is larger than %d bytes",
name, SALG_NAME_LEN_MAX);
return false;
}
pstrcpy((char *)salg->salg_type, SALG_TYPE_LEN_MAX, type);
pstrcpy((char *)salg->salg_name, SALG_NAME_LEN_MAX, name);
return true;
}
static int
qcrypto_afalg_socket_bind(const char *type, const char *name,
Error **errp)
{
int sbind;
struct sockaddr_alg salg = {0};
if (!qcrypto_afalg_build_saddr(type, name, &salg, errp)) {
return -1;
}
sbind = qemu_socket(AF_ALG, SOCK_SEQPACKET, 0);
if (sbind < 0) {
error_setg_errno(errp, errno, "Failed to create socket");
return -1;
}
if (bind(sbind, (const struct sockaddr *)&salg, sizeof(salg)) != 0) {
error_setg_errno(errp, errno, "Failed to bind socket");
closesocket(sbind);
return -1;
}
return sbind;
}
QCryptoAFAlg *
qcrypto_afalg_comm_alloc(const char *type, const char *name,
Error **errp)
{
QCryptoAFAlg *afalg;
afalg = g_new0(QCryptoAFAlg, 1);
/* initilize crypto API socket */
afalg->opfd = -1;
afalg->tfmfd = qcrypto_afalg_socket_bind(type, name, errp);
if (afalg->tfmfd == -1) {
goto error;
}
afalg->opfd = qemu_accept(afalg->tfmfd, NULL, 0);
if (afalg->opfd == -1) {
error_setg_errno(errp, errno, "Failed to accept socket");
goto error;
}
return afalg;
error:
qcrypto_afalg_comm_free(afalg);
return NULL;
}
void qcrypto_afalg_comm_free(QCryptoAFAlg *afalg)
{
if (!afalg) {
return;
}
if (afalg->msg) {
g_free(afalg->msg->msg_control);
g_free(afalg->msg);
}
if (afalg->tfmfd != -1) {
closesocket(afalg->tfmfd);
}
if (afalg->opfd != -1) {
closesocket(afalg->opfd);
}
g_free(afalg);
}

64
crypto/afalgpriv.h Normal file
View File

@ -0,0 +1,64 @@
/*
* QEMU Crypto af_alg support
*
* Copyright (c) 2017 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.
*/
#ifndef QCRYPTO_AFALGPRIV_H
#define QCRYPTO_AFALGPRIV_H
#include <linux/if_alg.h>
#define SALG_TYPE_LEN_MAX 14
#define SALG_NAME_LEN_MAX 64
#ifndef SOL_ALG
#define SOL_ALG 279
#endif
#define AFALG_TYPE_CIPHER "skcipher"
#define AFALG_TYPE_HASH "hash"
#define ALG_OPTYPE_LEN 4
#define ALG_MSGIV_LEN(len) (sizeof(struct af_alg_iv) + (len))
typedef struct QCryptoAFAlg QCryptoAFAlg;
struct QCryptoAFAlg {
int tfmfd;
int opfd;
struct msghdr *msg;
struct cmsghdr *cmsg;
};
/**
* qcrypto_afalg_comm_alloc:
* @type: the type of crypto operation
* @name: the name of crypto operation
*
* Allocate a QCryptoAFAlg object and bind itself to
* a AF_ALG socket.
*
* Returns:
* a new QCryptoAFAlg object, or NULL in error.
*/
QCryptoAFAlg *
qcrypto_afalg_comm_alloc(const char *type, const char *name,
Error **errp);
/**
* afalg_comm_free:
* @afalg: the QCryptoAFAlg object
*
* Free the @afalg.
*/
void qcrypto_afalg_comm_free(QCryptoAFAlg *afalg);
#endif

226
crypto/cipher-afalg.c Normal file
View File

@ -0,0 +1,226 @@
/*
* QEMU Crypto af_alg-backend cipher support
*
* Copyright (c) 2017 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 "qemu/sockets.h"
#include "qemu-common.h"
#include "qapi/error.h"
#include "crypto/cipher.h"
#include "cipherpriv.h"
static char *
qcrypto_afalg_cipher_format_name(QCryptoCipherAlgorithm alg,
QCryptoCipherMode mode,
Error **errp)
{
char *name;
const char *alg_name;
const char *mode_name;
switch (alg) {
case QCRYPTO_CIPHER_ALG_AES_128:
case QCRYPTO_CIPHER_ALG_AES_192:
case QCRYPTO_CIPHER_ALG_AES_256:
alg_name = "aes";
break;
case QCRYPTO_CIPHER_ALG_CAST5_128:
alg_name = "cast5";
break;
case QCRYPTO_CIPHER_ALG_SERPENT_128:
case QCRYPTO_CIPHER_ALG_SERPENT_192:
case QCRYPTO_CIPHER_ALG_SERPENT_256:
alg_name = "serpent";
break;
case QCRYPTO_CIPHER_ALG_TWOFISH_128:
case QCRYPTO_CIPHER_ALG_TWOFISH_192:
case QCRYPTO_CIPHER_ALG_TWOFISH_256:
alg_name = "twofish";
break;
default:
error_setg(errp, "Unsupported cipher algorithm %d", alg);
return NULL;
}
mode_name = QCryptoCipherMode_lookup[mode];
name = g_strdup_printf("%s(%s)", mode_name, alg_name);
return name;
}
QCryptoAFAlg *
qcrypto_afalg_cipher_ctx_new(QCryptoCipherAlgorithm alg,
QCryptoCipherMode mode,
const uint8_t *key,
size_t nkey, Error **errp)
{
QCryptoAFAlg *afalg;
size_t expect_niv;
char *name;
name = qcrypto_afalg_cipher_format_name(alg, mode, errp);
if (!name) {
return NULL;
}
afalg = qcrypto_afalg_comm_alloc(AFALG_TYPE_CIPHER, name, errp);
if (!afalg) {
g_free(name);
return NULL;
}
g_free(name);
/* setkey */
if (qemu_setsockopt(afalg->tfmfd, SOL_ALG, ALG_SET_KEY, key,
nkey) != 0) {
error_setg_errno(errp, errno, "Set key failed");
qcrypto_afalg_comm_free(afalg);
return NULL;
}
/* prepare msg header */
afalg->msg = g_new0(struct msghdr, 1);
afalg->msg->msg_controllen += CMSG_SPACE(ALG_OPTYPE_LEN);
expect_niv = qcrypto_cipher_get_iv_len(alg, mode);
if (expect_niv) {
afalg->msg->msg_controllen += CMSG_SPACE(ALG_MSGIV_LEN(expect_niv));
}
afalg->msg->msg_control = g_new0(uint8_t, afalg->msg->msg_controllen);
/* We use 1st msghdr for crypto-info and 2nd msghdr for IV-info */
afalg->cmsg = CMSG_FIRSTHDR(afalg->msg);
afalg->cmsg->cmsg_type = ALG_SET_OP;
afalg->cmsg->cmsg_len = CMSG_SPACE(ALG_OPTYPE_LEN);
if (expect_niv) {
afalg->cmsg = CMSG_NXTHDR(afalg->msg, afalg->cmsg);
afalg->cmsg->cmsg_type = ALG_SET_IV;
afalg->cmsg->cmsg_len = CMSG_SPACE(ALG_MSGIV_LEN(expect_niv));
}
afalg->cmsg = CMSG_FIRSTHDR(afalg->msg);
return afalg;
}
static int
qcrypto_afalg_cipher_setiv(QCryptoCipher *cipher,
const uint8_t *iv,
size_t niv, Error **errp)
{
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) {
error_setg(errp, "Set IV len(%zu) not match expected(%zu)",
niv, expect_niv);
return -1;
}
/* move ->cmsg to next msghdr, for IV-info */
afalg->cmsg = CMSG_NXTHDR(afalg->msg, afalg->cmsg);
/* build setiv msg */
afalg->cmsg->cmsg_level = SOL_ALG;
alg_iv = (struct af_alg_iv *)CMSG_DATA(afalg->cmsg);
alg_iv->ivlen = niv;
memcpy(alg_iv->iv, iv, niv);
return 0;
}
static int
qcrypto_afalg_cipher_op(QCryptoAFAlg *afalg,
const void *in, void *out,
size_t len, bool do_encrypt,
Error **errp)
{
uint32_t *type = NULL;
struct iovec iov;
size_t ret, rlen, done = 0;
uint32_t origin_controllen;
origin_controllen = afalg->msg->msg_controllen;
/* movev ->cmsg to first header, for crypto-info */
afalg->cmsg = CMSG_FIRSTHDR(afalg->msg);
/* build encrypt msg */
afalg->cmsg->cmsg_level = SOL_ALG;
afalg->msg->msg_iov = &iov;
afalg->msg->msg_iovlen = 1;
type = (uint32_t *)CMSG_DATA(afalg->cmsg);
if (do_encrypt) {
*type = ALG_OP_ENCRYPT;
} else {
*type = ALG_OP_DECRYPT;
}
do {
iov.iov_base = (void *)in + done;
iov.iov_len = len - done;
/* send info to AF_ALG core */
ret = sendmsg(afalg->opfd, afalg->msg, 0);
if (ret == -1) {
error_setg_errno(errp, errno, "Send data to AF_ALG core failed");
return -1;
}
/* encrypto && get result */
rlen = read(afalg->opfd, out, ret);
if (rlen == -1) {
error_setg_errno(errp, errno, "Get result from AF_ALG core failed");
return -1;
}
assert(rlen == ret);
/* do not update IV for following chunks */
afalg->msg->msg_controllen = 0;
done += ret;
} while (done < len);
afalg->msg->msg_controllen = origin_controllen;
return 0;
}
static int
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);
}
static int
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);
}
static void qcrypto_afalg_comm_ctx_free(QCryptoCipher *cipher)
{
qcrypto_afalg_comm_free(cipher->opaque);
}
struct QCryptoCipherDriver qcrypto_cipher_afalg_driver = {
.cipher_encrypt = qcrypto_afalg_cipher_encrypt,
.cipher_decrypt = qcrypto_afalg_cipher_decrypt,
.cipher_setiv = qcrypto_afalg_cipher_setiv,
.cipher_free = qcrypto_afalg_comm_ctx_free,
};

View File

@ -22,6 +22,7 @@
#include "crypto/aes.h"
#include "crypto/desrfb.h"
#include "crypto/xts.h"
#include "cipherpriv.h"
typedef struct QCryptoCipherBuiltinAESContext QCryptoCipherBuiltinAESContext;
struct QCryptoCipherBuiltinAESContext {
@ -235,23 +236,24 @@ static int qcrypto_cipher_setiv_aes(QCryptoCipher *cipher,
static int qcrypto_cipher_init_aes(QCryptoCipher *cipher,
const uint8_t *key, size_t nkey,
Error **errp)
static QCryptoCipherBuiltin *
qcrypto_cipher_init_aes(QCryptoCipherMode mode,
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) {
if (mode != QCRYPTO_CIPHER_MODE_CBC &&
mode != QCRYPTO_CIPHER_MODE_ECB &&
mode != QCRYPTO_CIPHER_MODE_XTS) {
error_setg(errp, "Unsupported cipher mode %s",
QCryptoCipherMode_lookup[cipher->mode]);
return -1;
QCryptoCipherMode_lookup[mode]);
return NULL;
}
ctxt = g_new0(QCryptoCipherBuiltin, 1);
if (cipher->mode == QCRYPTO_CIPHER_MODE_XTS) {
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;
@ -291,13 +293,11 @@ static int qcrypto_cipher_init_aes(QCryptoCipher *cipher,
ctxt->encrypt = qcrypto_cipher_encrypt_aes;
ctxt->decrypt = qcrypto_cipher_decrypt_aes;
cipher->opaque = ctxt;
return 0;
return ctxt;
error:
g_free(ctxt);
return -1;
return NULL;
}
@ -370,16 +370,17 @@ static int qcrypto_cipher_setiv_des_rfb(QCryptoCipher *cipher,
}
static int qcrypto_cipher_init_des_rfb(QCryptoCipher *cipher,
const uint8_t *key, size_t nkey,
Error **errp)
static QCryptoCipherBuiltin *
qcrypto_cipher_init_des_rfb(QCryptoCipherMode mode,
const uint8_t *key, size_t nkey,
Error **errp)
{
QCryptoCipherBuiltin *ctxt;
if (cipher->mode != QCRYPTO_CIPHER_MODE_ECB) {
if (mode != QCRYPTO_CIPHER_MODE_ECB) {
error_setg(errp, "Unsupported cipher mode %s",
QCryptoCipherMode_lookup[cipher->mode]);
return -1;
QCryptoCipherMode_lookup[mode]);
return NULL;
}
ctxt = g_new0(QCryptoCipherBuiltin, 1);
@ -394,9 +395,7 @@ static int qcrypto_cipher_init_des_rfb(QCryptoCipher *cipher,
ctxt->encrypt = qcrypto_cipher_encrypt_des_rfb;
ctxt->decrypt = qcrypto_cipher_decrypt_des_rfb;
cipher->opaque = ctxt;
return 0;
return ctxt;
}
@ -426,12 +425,13 @@ bool qcrypto_cipher_supports(QCryptoCipherAlgorithm alg,
}
QCryptoCipher *qcrypto_cipher_new(QCryptoCipherAlgorithm alg,
QCryptoCipherMode mode,
const uint8_t *key, size_t nkey,
Error **errp)
static QCryptoCipherBuiltin *qcrypto_cipher_ctx_new(QCryptoCipherAlgorithm alg,
QCryptoCipherMode mode,
const uint8_t *key,
size_t nkey,
Error **errp)
{
QCryptoCipher *cipher;
QCryptoCipherBuiltin *ctxt;
switch (mode) {
case QCRYPTO_CIPHER_MODE_ECB:
@ -444,60 +444,45 @@ QCryptoCipher *qcrypto_cipher_new(QCryptoCipherAlgorithm alg,
return NULL;
}
cipher = g_new0(QCryptoCipher, 1);
cipher->alg = alg;
cipher->mode = mode;
if (!qcrypto_cipher_validate_key_length(alg, mode, nkey, errp)) {
goto error;
return NULL;
}
switch (cipher->alg) {
switch (alg) {
case QCRYPTO_CIPHER_ALG_DES_RFB:
if (qcrypto_cipher_init_des_rfb(cipher, key, nkey, errp) < 0) {
goto error;
}
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:
if (qcrypto_cipher_init_aes(cipher, key, nkey, errp) < 0) {
goto error;
}
ctxt = qcrypto_cipher_init_aes(mode, key, nkey, errp);
break;
default:
error_setg(errp,
"Unsupported cipher algorithm %s",
QCryptoCipherAlgorithm_lookup[cipher->alg]);
goto error;
QCryptoCipherAlgorithm_lookup[alg]);
return NULL;
}
return cipher;
error:
g_free(cipher);
return NULL;
return ctxt;
}
void qcrypto_cipher_free(QCryptoCipher *cipher)
static void
qcrypto_builtin_cipher_ctx_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)
static int
qcrypto_builtin_cipher_encrypt(QCryptoCipher *cipher,
const void *in,
void *out,
size_t len,
Error **errp)
{
QCryptoCipherBuiltin *ctxt = cipher->opaque;
@ -511,11 +496,12 @@ int qcrypto_cipher_encrypt(QCryptoCipher *cipher,
}
int qcrypto_cipher_decrypt(QCryptoCipher *cipher,
const void *in,
void *out,
size_t len,
Error **errp)
static int
qcrypto_builtin_cipher_decrypt(QCryptoCipher *cipher,
const void *in,
void *out,
size_t len,
Error **errp)
{
QCryptoCipherBuiltin *ctxt = cipher->opaque;
@ -529,11 +515,20 @@ int qcrypto_cipher_decrypt(QCryptoCipher *cipher,
}
int qcrypto_cipher_setiv(QCryptoCipher *cipher,
const uint8_t *iv, size_t niv,
Error **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,
};

View File

@ -20,6 +20,7 @@
#include "qemu/osdep.h"
#include "crypto/xts.h"
#include "cipherpriv.h"
#include <gcrypt.h>
@ -64,12 +65,29 @@ struct QCryptoCipherGcrypt {
uint8_t *iv;
};
QCryptoCipher *qcrypto_cipher_new(QCryptoCipherAlgorithm alg,
QCryptoCipherMode mode,
const uint8_t *key, size_t nkey,
Error **errp)
static void
qcrypto_gcrypt_cipher_free_ctx(QCryptoCipherGcrypt *ctx,
QCryptoCipherMode mode)
{
if (!ctx) {
return;
}
gcry_cipher_close(ctx->handle);
if (mode == QCRYPTO_CIPHER_MODE_XTS) {
gcry_cipher_close(ctx->tweakhandle);
}
g_free(ctx->iv);
g_free(ctx);
}
static QCryptoCipherGcrypt *qcrypto_cipher_ctx_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;
@ -146,10 +164,6 @@ QCryptoCipher *qcrypto_cipher_new(QCryptoCipherAlgorithm 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);
@ -158,7 +172,7 @@ QCryptoCipher *qcrypto_cipher_new(QCryptoCipherAlgorithm alg,
gcry_strerror(err));
goto error;
}
if (cipher->mode == QCRYPTO_CIPHER_MODE_XTS) {
if (mode == QCRYPTO_CIPHER_MODE_XTS) {
err = gcry_cipher_open(&ctx->tweakhandle, gcryalg, gcrymode, 0);
if (err != 0) {
error_setg(errp, "Cannot initialize cipher: %s",
@ -167,7 +181,7 @@ QCryptoCipher *qcrypto_cipher_new(QCryptoCipherAlgorithm alg,
}
}
if (cipher->alg == QCRYPTO_CIPHER_ALG_DES_RFB) {
if (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 :-)
@ -177,7 +191,7 @@ QCryptoCipher *qcrypto_cipher_new(QCryptoCipherAlgorithm alg,
g_free(rfbkey);
ctx->blocksize = 8;
} else {
if (cipher->mode == QCRYPTO_CIPHER_MODE_XTS) {
if (mode == QCRYPTO_CIPHER_MODE_XTS) {
nkey /= 2;
err = gcry_cipher_setkey(ctx->handle, key, nkey);
if (err != 0) {
@ -194,7 +208,7 @@ QCryptoCipher *qcrypto_cipher_new(QCryptoCipherAlgorithm alg,
gcry_strerror(err));
goto error;
}
switch (cipher->alg) {
switch (alg) {
case QCRYPTO_CIPHER_ALG_AES_128:
case QCRYPTO_CIPHER_ALG_AES_192:
case QCRYPTO_CIPHER_ALG_AES_256:
@ -214,7 +228,7 @@ QCryptoCipher *qcrypto_cipher_new(QCryptoCipherAlgorithm alg,
}
}
if (cipher->mode == QCRYPTO_CIPHER_MODE_XTS) {
if (mode == QCRYPTO_CIPHER_MODE_XTS) {
if (ctx->blocksize != XTS_BLOCK_SIZE) {
error_setg(errp,
"Cipher block size %zu must equal XTS block size %d",
@ -224,34 +238,18 @@ QCryptoCipher *qcrypto_cipher_new(QCryptoCipherAlgorithm alg,
ctx->iv = g_new0(uint8_t, ctx->blocksize);
}
cipher->opaque = ctx;
return cipher;
return ctx;
error:
gcry_cipher_close(ctx->handle);
if (cipher->mode == QCRYPTO_CIPHER_MODE_XTS) {
gcry_cipher_close(ctx->tweakhandle);
}
g_free(ctx);
g_free(cipher);
qcrypto_gcrypt_cipher_free_ctx(ctx, mode);
return NULL;
}
void qcrypto_cipher_free(QCryptoCipher *cipher)
static void
qcrypto_gcrypt_cipher_ctx_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);
qcrypto_gcrypt_cipher_free_ctx(cipher->opaque, cipher->mode);
}
@ -275,11 +273,12 @@ static void qcrypto_gcrypt_xts_decrypt(const void *ctx,
g_assert(err == 0);
}
int qcrypto_cipher_encrypt(QCryptoCipher *cipher,
const void *in,
void *out,
size_t len,
Error **errp)
static int
qcrypto_gcrypt_cipher_encrypt(QCryptoCipher *cipher,
const void *in,
void *out,
size_t len,
Error **errp)
{
QCryptoCipherGcrypt *ctx = cipher->opaque;
gcry_error_t err;
@ -310,11 +309,12 @@ int qcrypto_cipher_encrypt(QCryptoCipher *cipher,
}
int qcrypto_cipher_decrypt(QCryptoCipher *cipher,
const void *in,
void *out,
size_t len,
Error **errp)
static int
qcrypto_gcrypt_cipher_decrypt(QCryptoCipher *cipher,
const void *in,
void *out,
size_t len,
Error **errp)
{
QCryptoCipherGcrypt *ctx = cipher->opaque;
gcry_error_t err;
@ -344,9 +344,10 @@ int qcrypto_cipher_decrypt(QCryptoCipher *cipher,
return 0;
}
int qcrypto_cipher_setiv(QCryptoCipher *cipher,
const uint8_t *iv, size_t niv,
Error **errp)
static int
qcrypto_gcrypt_cipher_setiv(QCryptoCipher *cipher,
const uint8_t *iv, size_t niv,
Error **errp)
{
QCryptoCipherGcrypt *ctx = cipher->opaque;
gcry_error_t err;
@ -380,3 +381,11 @@ int qcrypto_cipher_setiv(QCryptoCipher *cipher,
return 0;
}
static struct QCryptoCipherDriver qcrypto_cipher_lib_driver = {
.cipher_encrypt = qcrypto_gcrypt_cipher_encrypt,
.cipher_decrypt = qcrypto_gcrypt_cipher_decrypt,
.cipher_setiv = qcrypto_gcrypt_cipher_setiv,
.cipher_free = qcrypto_gcrypt_cipher_ctx_free,
};

View File

@ -20,6 +20,7 @@
#include "qemu/osdep.h"
#include "crypto/xts.h"
#include "cipherpriv.h"
#include <nettle/nettle-types.h>
#include <nettle/aes.h>
@ -249,12 +250,26 @@ bool qcrypto_cipher_supports(QCryptoCipherAlgorithm alg,
}
QCryptoCipher *qcrypto_cipher_new(QCryptoCipherAlgorithm alg,
QCryptoCipherMode mode,
const uint8_t *key, size_t nkey,
Error **errp)
static void
qcrypto_nettle_cipher_free_ctx(QCryptoCipherNettle *ctx)
{
if (!ctx) {
return;
}
g_free(ctx->iv);
g_free(ctx->ctx);
g_free(ctx->ctx_tweak);
g_free(ctx);
}
static QCryptoCipherNettle *qcrypto_cipher_ctx_new(QCryptoCipherAlgorithm alg,
QCryptoCipherMode mode,
const uint8_t *key,
size_t nkey,
Error **errp)
{
QCryptoCipher *cipher;
QCryptoCipherNettle *ctx;
uint8_t *rfbkey;
@ -274,12 +289,7 @@ QCryptoCipher *qcrypto_cipher_new(QCryptoCipherAlgorithm alg,
return NULL;
}
cipher = g_new0(QCryptoCipher, 1);
cipher->alg = alg;
cipher->mode = mode;
ctx = g_new0(QCryptoCipherNettle, 1);
cipher->opaque = ctx;
switch (alg) {
case QCRYPTO_CIPHER_ALG_DES_RFB:
@ -423,36 +433,30 @@ QCryptoCipher *qcrypto_cipher_new(QCryptoCipherAlgorithm alg,
ctx->iv = g_new0(uint8_t, ctx->blocksize);
return cipher;
return ctx;
error:
qcrypto_cipher_free(cipher);
qcrypto_nettle_cipher_free_ctx(ctx);
return NULL;
}
void qcrypto_cipher_free(QCryptoCipher *cipher)
static void
qcrypto_nettle_cipher_ctx_free(QCryptoCipher *cipher)
{
QCryptoCipherNettle *ctx;
if (!cipher) {
return;
}
ctx = cipher->opaque;
g_free(ctx->iv);
g_free(ctx->ctx);
g_free(ctx->ctx_tweak);
g_free(ctx);
g_free(cipher);
qcrypto_nettle_cipher_free_ctx(ctx);
}
int qcrypto_cipher_encrypt(QCryptoCipher *cipher,
const void *in,
void *out,
size_t len,
Error **errp)
static int
qcrypto_nettle_cipher_encrypt(QCryptoCipher *cipher,
const void *in,
void *out,
size_t len,
Error **errp)
{
QCryptoCipherNettle *ctx = cipher->opaque;
@ -494,11 +498,12 @@ int qcrypto_cipher_encrypt(QCryptoCipher *cipher,
}
int qcrypto_cipher_decrypt(QCryptoCipher *cipher,
const void *in,
void *out,
size_t len,
Error **errp)
static int
qcrypto_nettle_cipher_decrypt(QCryptoCipher *cipher,
const void *in,
void *out,
size_t len,
Error **errp)
{
QCryptoCipherNettle *ctx = cipher->opaque;
@ -538,9 +543,10 @@ int qcrypto_cipher_decrypt(QCryptoCipher *cipher,
return 0;
}
int qcrypto_cipher_setiv(QCryptoCipher *cipher,
const uint8_t *iv, size_t niv,
Error **errp)
static int
qcrypto_nettle_cipher_setiv(QCryptoCipher *cipher,
const uint8_t *iv, size_t niv,
Error **errp)
{
QCryptoCipherNettle *ctx = cipher->opaque;
if (niv != ctx->blocksize) {
@ -551,3 +557,11 @@ int qcrypto_cipher_setiv(QCryptoCipher *cipher,
memcpy(ctx->iv, iv, niv);
return 0;
}
static struct QCryptoCipherDriver qcrypto_cipher_lib_driver = {
.cipher_encrypt = qcrypto_nettle_cipher_encrypt,
.cipher_decrypt = qcrypto_nettle_cipher_decrypt,
.cipher_setiv = qcrypto_nettle_cipher_setiv,
.cipher_free = qcrypto_nettle_cipher_ctx_free,
};

View File

@ -21,6 +21,7 @@
#include "qemu/osdep.h"
#include "qapi/error.h"
#include "crypto/cipher.h"
#include "cipherpriv.h"
static size_t alg_key_len[QCRYPTO_CIPHER_ALG__MAX] = {
@ -155,3 +156,82 @@ qcrypto_cipher_munge_des_rfb_key(const uint8_t *key,
#else
#include "crypto/cipher-builtin.c"
#endif
QCryptoCipher *qcrypto_cipher_new(QCryptoCipherAlgorithm alg,
QCryptoCipherMode mode,
const uint8_t *key, size_t nkey,
Error **errp)
{
QCryptoCipher *cipher;
void *ctx = NULL;
Error *err2 = NULL;
QCryptoCipherDriver *drv = NULL;
#ifdef CONFIG_AF_ALG
ctx = qcrypto_afalg_cipher_ctx_new(alg, mode, key, nkey, &err2);
if (ctx) {
drv = &qcrypto_cipher_afalg_driver;
}
#endif
if (!ctx) {
ctx = qcrypto_cipher_ctx_new(alg, mode, key, nkey, errp);
if (!ctx) {
error_free(err2);
return NULL;
}
drv = &qcrypto_cipher_lib_driver;
error_free(err2);
}
cipher = g_new0(QCryptoCipher, 1);
cipher->alg = alg;
cipher->mode = mode;
cipher->opaque = ctx;
cipher->driver = (void *)drv;
return cipher;
}
int qcrypto_cipher_encrypt(QCryptoCipher *cipher,
const void *in,
void *out,
size_t len,
Error **errp)
{
QCryptoCipherDriver *drv = cipher->driver;
return drv->cipher_encrypt(cipher, in, out, len, errp);
}
int qcrypto_cipher_decrypt(QCryptoCipher *cipher,
const void *in,
void *out,
size_t len,
Error **errp)
{
QCryptoCipherDriver *drv = cipher->driver;
return drv->cipher_decrypt(cipher, in, out, len, errp);
}
int qcrypto_cipher_setiv(QCryptoCipher *cipher,
const uint8_t *iv, size_t niv,
Error **errp)
{
QCryptoCipherDriver *drv = cipher->driver;
return drv->cipher_setiv(cipher, iv, niv, errp);
}
void qcrypto_cipher_free(QCryptoCipher *cipher)
{
QCryptoCipherDriver *drv;
if (cipher) {
drv = cipher->driver;
drv->cipher_free(cipher);
g_free(cipher);
}
}

56
crypto/cipherpriv.h Normal file
View File

@ -0,0 +1,56 @@
/*
* QEMU Crypto cipher driver supports
*
* Copyright (c) 2017 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.
*
*/
#ifndef QCRYPTO_CIPHERPRIV_H
#define QCRYPTO_CIPHERPRIV_H
#include "qapi-types.h"
typedef struct QCryptoCipherDriver QCryptoCipherDriver;
struct QCryptoCipherDriver {
int (*cipher_encrypt)(QCryptoCipher *cipher,
const void *in,
void *out,
size_t len,
Error **errp);
int (*cipher_decrypt)(QCryptoCipher *cipher,
const void *in,
void *out,
size_t len,
Error **errp);
int (*cipher_setiv)(QCryptoCipher *cipher,
const uint8_t *iv, size_t niv,
Error **errp);
void (*cipher_free)(QCryptoCipher *cipher);
};
#ifdef CONFIG_AF_ALG
#include "afalgpriv.h"
extern QCryptoAFAlg *
qcrypto_afalg_cipher_ctx_new(QCryptoCipherAlgorithm alg,
QCryptoCipherMode mode,
const uint8_t *key,
size_t nkey, Error **errp);
extern struct QCryptoCipherDriver qcrypto_cipher_afalg_driver;
#endif
#endif

214
crypto/hash-afalg.c Normal file
View File

@ -0,0 +1,214 @@
/*
* QEMU Crypto af_alg-backend hash/hmac support
*
* Copyright (c) 2017 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 "qemu/iov.h"
#include "qemu/sockets.h"
#include "qemu-common.h"
#include "qapi/error.h"
#include "crypto/hash.h"
#include "crypto/hmac.h"
#include "hashpriv.h"
#include "hmacpriv.h"
static char *
qcrypto_afalg_hash_format_name(QCryptoHashAlgorithm alg,
bool is_hmac,
Error **errp)
{
char *name;
const char *alg_name;
switch (alg) {
case QCRYPTO_HASH_ALG_MD5:
alg_name = "md5";
break;
case QCRYPTO_HASH_ALG_SHA1:
alg_name = "sha1";
break;
case QCRYPTO_HASH_ALG_SHA224:
alg_name = "sha224";
break;
case QCRYPTO_HASH_ALG_SHA256:
alg_name = "sha256";
break;
case QCRYPTO_HASH_ALG_SHA384:
alg_name = "sha384";
break;
case QCRYPTO_HASH_ALG_SHA512:
alg_name = "sha512";
break;
case QCRYPTO_HASH_ALG_RIPEMD160:
alg_name = "rmd160";
break;
default:
error_setg(errp, "Unsupported hash algorithm %d", alg);
return NULL;
}
if (is_hmac) {
name = g_strdup_printf("hmac(%s)", alg_name);
} else {
name = g_strdup_printf("%s", alg_name);
}
return name;
}
static QCryptoAFAlg *
qcrypto_afalg_hash_hmac_ctx_new(QCryptoHashAlgorithm alg,
const uint8_t *key, size_t nkey,
bool is_hmac, Error **errp)
{
QCryptoAFAlg *afalg;
char *name;
name = qcrypto_afalg_hash_format_name(alg, is_hmac, errp);
if (!name) {
return NULL;
}
afalg = qcrypto_afalg_comm_alloc(AFALG_TYPE_HASH, name, errp);
if (!afalg) {
g_free(name);
return NULL;
}
g_free(name);
/* HMAC needs setkey */
if (is_hmac) {
if (qemu_setsockopt(afalg->tfmfd, SOL_ALG, ALG_SET_KEY,
key, nkey) != 0) {
error_setg_errno(errp, errno, "Set hmac key failed");
qcrypto_afalg_comm_free(afalg);
return NULL;
}
}
return afalg;
}
static QCryptoAFAlg *
qcrypto_afalg_hash_ctx_new(QCryptoHashAlgorithm alg,
Error **errp)
{
return qcrypto_afalg_hash_hmac_ctx_new(alg, NULL, 0, false, errp);
}
QCryptoAFAlg *
qcrypto_afalg_hmac_ctx_new(QCryptoHashAlgorithm alg,
const uint8_t *key, size_t nkey,
Error **errp)
{
return qcrypto_afalg_hash_hmac_ctx_new(alg, key, nkey, true, errp);
}
static int
qcrypto_afalg_hash_hmac_bytesv(QCryptoAFAlg *hmac,
QCryptoHashAlgorithm alg,
const struct iovec *iov,
size_t niov, uint8_t **result,
size_t *resultlen,
Error **errp)
{
QCryptoAFAlg *afalg;
struct iovec outv;
int ret = 0;
bool is_hmac = (hmac != NULL) ? true : false;
const int expect_len = qcrypto_hash_digest_len(alg);
if (*resultlen == 0) {
*resultlen = expect_len;
*result = g_new0(uint8_t, *resultlen);
} else if (*resultlen != expect_len) {
error_setg(errp,
"Result buffer size %zu is not match hash %d",
*resultlen, expect_len);
return -1;
}
if (is_hmac) {
afalg = hmac;
} else {
afalg = qcrypto_afalg_hash_ctx_new(alg, errp);
if (!afalg) {
return -1;
}
}
/* send data to kernel's crypto core */
ret = iov_send_recv(afalg->opfd, iov, niov,
0, iov_size(iov, niov), true);
if (ret < 0) {
error_setg_errno(errp, errno, "Send data to afalg-core failed");
goto out;
}
/* hash && get result */
outv.iov_base = *result;
outv.iov_len = *resultlen;
ret = iov_send_recv(afalg->opfd, &outv, 1,
0, iov_size(&outv, 1), false);
if (ret < 0) {
error_setg_errno(errp, errno, "Recv result from afalg-core failed");
} else {
ret = 0;
}
out:
if (!is_hmac) {
qcrypto_afalg_comm_free(afalg);
}
return ret;
}
static int
qcrypto_afalg_hash_bytesv(QCryptoHashAlgorithm alg,
const struct iovec *iov,
size_t niov, uint8_t **result,
size_t *resultlen,
Error **errp)
{
return qcrypto_afalg_hash_hmac_bytesv(NULL, alg, iov, niov, result,
resultlen, errp);
}
static int
qcrypto_afalg_hmac_bytesv(QCryptoHmac *hmac,
const struct iovec *iov,
size_t niov, uint8_t **result,
size_t *resultlen,
Error **errp)
{
return qcrypto_afalg_hash_hmac_bytesv(hmac->opaque, hmac->alg,
iov, niov, result, resultlen,
errp);
}
static void qcrypto_afalg_hmac_ctx_free(QCryptoHmac *hmac)
{
QCryptoAFAlg *afalg;
afalg = hmac->opaque;
qcrypto_afalg_comm_free(afalg);
}
QCryptoHashDriver qcrypto_hash_afalg_driver = {
.hash_bytesv = qcrypto_afalg_hash_bytesv,
};
QCryptoHmacDriver qcrypto_hmac_afalg_driver = {
.hmac_bytesv = qcrypto_afalg_hmac_bytesv,
.hmac_free = qcrypto_afalg_hmac_ctx_free,
};

View File

@ -22,6 +22,7 @@
#include <gcrypt.h>
#include "qapi/error.h"
#include "crypto/hash.h"
#include "hashpriv.h"
static int qcrypto_hash_alg_map[QCRYPTO_HASH_ALG__MAX] = {
@ -44,12 +45,13 @@ gboolean qcrypto_hash_supports(QCryptoHashAlgorithm alg)
}
int qcrypto_hash_bytesv(QCryptoHashAlgorithm alg,
const struct iovec *iov,
size_t niov,
uint8_t **result,
size_t *resultlen,
Error **errp)
static int
qcrypto_gcrypt_hash_bytesv(QCryptoHashAlgorithm alg,
const struct iovec *iov,
size_t niov,
uint8_t **result,
size_t *resultlen,
Error **errp)
{
int i, ret;
gcry_md_hd_t md;
@ -107,3 +109,8 @@ int qcrypto_hash_bytesv(QCryptoHashAlgorithm alg,
gcry_md_close(md);
return -1;
}
QCryptoHashDriver qcrypto_hash_lib_driver = {
.hash_bytesv = qcrypto_gcrypt_hash_bytesv,
};

View File

@ -21,6 +21,7 @@
#include "qemu/osdep.h"
#include "qapi/error.h"
#include "crypto/hash.h"
#include "hashpriv.h"
static int qcrypto_hash_alg_map[QCRYPTO_HASH_ALG__MAX] = {
@ -47,12 +48,13 @@ gboolean qcrypto_hash_supports(QCryptoHashAlgorithm alg)
}
int qcrypto_hash_bytesv(QCryptoHashAlgorithm alg,
const struct iovec *iov,
size_t niov,
uint8_t **result,
size_t *resultlen,
Error **errp)
static int
qcrypto_glib_hash_bytesv(QCryptoHashAlgorithm alg,
const struct iovec *iov,
size_t niov,
uint8_t **result,
size_t *resultlen,
Error **errp)
{
int i, ret;
GChecksum *cs;
@ -95,3 +97,8 @@ int qcrypto_hash_bytesv(QCryptoHashAlgorithm alg,
g_checksum_free(cs);
return -1;
}
QCryptoHashDriver qcrypto_hash_lib_driver = {
.hash_bytesv = qcrypto_glib_hash_bytesv,
};

View File

@ -21,6 +21,7 @@
#include "qemu/osdep.h"
#include "qapi/error.h"
#include "crypto/hash.h"
#include "hashpriv.h"
#include <nettle/md5.h>
#include <nettle/sha.h>
#include <nettle/ripemd160.h>
@ -103,12 +104,13 @@ gboolean qcrypto_hash_supports(QCryptoHashAlgorithm alg)
}
int qcrypto_hash_bytesv(QCryptoHashAlgorithm alg,
const struct iovec *iov,
size_t niov,
uint8_t **result,
size_t *resultlen,
Error **errp)
static int
qcrypto_nettle_hash_bytesv(QCryptoHashAlgorithm alg,
const struct iovec *iov,
size_t niov,
uint8_t **result,
size_t *resultlen,
Error **errp)
{
int i;
union qcrypto_hash_ctx ctx;
@ -152,3 +154,8 @@ int qcrypto_hash_bytesv(QCryptoHashAlgorithm alg,
return 0;
}
QCryptoHashDriver qcrypto_hash_lib_driver = {
.hash_bytesv = qcrypto_nettle_hash_bytesv,
};

View File

@ -21,6 +21,7 @@
#include "qemu/osdep.h"
#include "qapi/error.h"
#include "crypto/hash.h"
#include "hashpriv.h"
static size_t qcrypto_hash_alg_size[QCRYPTO_HASH_ALG__MAX] = {
[QCRYPTO_HASH_ALG_MD5] = 16,
@ -38,6 +39,35 @@ size_t qcrypto_hash_digest_len(QCryptoHashAlgorithm alg)
return qcrypto_hash_alg_size[alg];
}
int qcrypto_hash_bytesv(QCryptoHashAlgorithm alg,
const struct iovec *iov,
size_t niov,
uint8_t **result,
size_t *resultlen,
Error **errp)
{
#ifdef CONFIG_AF_ALG
int ret;
ret = qcrypto_hash_afalg_driver.hash_bytesv(alg, iov, niov,
result, resultlen,
errp);
if (ret == 0) {
return ret;
}
/*
* TODO:
* Maybe we should treat some afalg errors as fatal
*/
error_free(*errp);
#endif
return qcrypto_hash_lib_driver.hash_bytesv(alg, iov, niov,
result, resultlen,
errp);
}
int qcrypto_hash_bytes(QCryptoHashAlgorithm alg,
const char *buf,

39
crypto/hashpriv.h Normal file
View File

@ -0,0 +1,39 @@
/*
* QEMU Crypto hash driver supports
*
* Copyright (c) 2017 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.
*
*/
#ifndef QCRYPTO_HASHPRIV_H
#define QCRYPTO_HASHPRIV_H
typedef struct QCryptoHashDriver QCryptoHashDriver;
struct QCryptoHashDriver {
int (*hash_bytesv)(QCryptoHashAlgorithm alg,
const struct iovec *iov,
size_t niov,
uint8_t **result,
size_t *resultlen,
Error **errp);
};
extern QCryptoHashDriver qcrypto_hash_lib_driver;
#ifdef CONFIG_AF_ALG
#include "afalgpriv.h"
extern QCryptoHashDriver qcrypto_hash_afalg_driver;
#endif
#endif

View File

@ -15,6 +15,7 @@
#include "qemu/osdep.h"
#include "qapi/error.h"
#include "crypto/hmac.h"
#include "hmacpriv.h"
#include <gcrypt.h>
static int qcrypto_hmac_alg_map[QCRYPTO_HASH_ALG__MAX] = {
@ -42,11 +43,10 @@ bool qcrypto_hmac_supports(QCryptoHashAlgorithm alg)
return false;
}
QCryptoHmac *qcrypto_hmac_new(QCryptoHashAlgorithm alg,
const uint8_t *key, size_t nkey,
Error **errp)
void *qcrypto_hmac_ctx_new(QCryptoHashAlgorithm alg,
const uint8_t *key, size_t nkey,
Error **errp)
{
QCryptoHmac *hmac;
QCryptoHmacGcrypt *ctx;
gcry_error_t err;
@ -56,9 +56,6 @@ QCryptoHmac *qcrypto_hmac_new(QCryptoHashAlgorithm 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],
@ -73,39 +70,35 @@ QCryptoHmac *qcrypto_hmac_new(QCryptoHashAlgorithm alg,
if (err != 0) {
error_setg(errp, "Cannot set key: %s",
gcry_strerror(err));
gcry_mac_close(ctx->handle);
goto error;
}
hmac->opaque = ctx;
return hmac;
return ctx;
error:
g_free(ctx);
g_free(hmac);
return NULL;
}
void qcrypto_hmac_free(QCryptoHmac *hmac)
static void
qcrypto_gcrypt_hmac_ctx_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)
static int
qcrypto_gcrypt_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;
@ -150,3 +143,8 @@ int qcrypto_hmac_bytesv(QCryptoHmac *hmac,
return 0;
}
QCryptoHmacDriver qcrypto_hmac_lib_driver = {
.hmac_bytesv = qcrypto_gcrypt_hmac_bytesv,
.hmac_free = qcrypto_gcrypt_hmac_ctx_free,
};

View File

@ -15,6 +15,7 @@
#include "qemu/osdep.h"
#include "qapi/error.h"
#include "crypto/hmac.h"
#include "hmacpriv.h"
/* Support for HMAC Algos has been added in GLib 2.30 */
#if GLIB_CHECK_VERSION(2, 30, 0)
@ -49,11 +50,10 @@ bool qcrypto_hmac_supports(QCryptoHashAlgorithm alg)
return false;
}
QCryptoHmac *qcrypto_hmac_new(QCryptoHashAlgorithm alg,
const uint8_t *key, size_t nkey,
Error **errp)
void *qcrypto_hmac_ctx_new(QCryptoHashAlgorithm alg,
const uint8_t *key, size_t nkey,
Error **errp)
{
QCryptoHmac *hmac;
QCryptoHmacGlib *ctx;
if (!qcrypto_hmac_supports(alg)) {
@ -62,9 +62,6 @@ QCryptoHmac *qcrypto_hmac_new(QCryptoHashAlgorithm alg,
return NULL;
}
hmac = g_new0(QCryptoHmac, 1);
hmac->alg = alg;
ctx = g_new0(QCryptoHmacGlib, 1);
ctx->ghmac = g_hmac_new(qcrypto_hmac_alg_map[alg],
@ -74,36 +71,31 @@ QCryptoHmac *qcrypto_hmac_new(QCryptoHashAlgorithm alg,
goto error;
}
hmac->opaque = ctx;
return hmac;
return ctx;
error:
g_free(ctx);
g_free(hmac);
return NULL;
}
void qcrypto_hmac_free(QCryptoHmac *hmac)
static void
qcrypto_glib_hmac_ctx_free(QCryptoHmac *hmac)
{
QCryptoHmacGlib *ctx;
if (!hmac) {
return;
}
ctx = hmac->opaque;
g_hmac_unref(ctx->ghmac);
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)
static int
qcrypto_glib_hmac_bytesv(QCryptoHmac *hmac,
const struct iovec *iov,
size_t niov,
uint8_t **result,
size_t *resultlen,
Error **errp)
{
QCryptoHmacGlib *ctx;
int i, ret;
@ -141,26 +133,33 @@ bool qcrypto_hmac_supports(QCryptoHashAlgorithm alg)
return false;
}
QCryptoHmac *qcrypto_hmac_new(QCryptoHashAlgorithm alg,
const uint8_t *key, size_t nkey,
Error **errp)
void *qcrypto_hmac_ctx_new(QCryptoHashAlgorithm alg,
const uint8_t *key, size_t nkey,
Error **errp)
{
return NULL;
}
void qcrypto_hmac_free(QCryptoHmac *hmac)
static void
qcrypto_glib_hmac_ctx_free(QCryptoHmac *hmac)
{
return;
}
int qcrypto_hmac_bytesv(QCryptoHmac *hmac,
const struct iovec *iov,
size_t niov,
uint8_t **result,
size_t *resultlen,
Error **errp)
static int
qcrypto_glib_hmac_bytesv(QCryptoHmac *hmac,
const struct iovec *iov,
size_t niov,
uint8_t **result,
size_t *resultlen,
Error **errp)
{
return -1;
}
#endif
QCryptoHmacDriver qcrypto_hmac_lib_driver = {
.hmac_bytesv = qcrypto_glib_hmac_bytesv,
.hmac_free = qcrypto_glib_hmac_ctx_free,
};

View File

@ -15,6 +15,7 @@
#include "qemu/osdep.h"
#include "qapi/error.h"
#include "crypto/hmac.h"
#include "hmacpriv.h"
#include <nettle/hmac.h>
typedef void (*qcrypto_nettle_hmac_setkey)(void *ctx,
@ -97,11 +98,10 @@ bool qcrypto_hmac_supports(QCryptoHashAlgorithm alg)
return false;
}
QCryptoHmac *qcrypto_hmac_new(QCryptoHashAlgorithm alg,
const uint8_t *key, size_t nkey,
Error **errp)
void *qcrypto_hmac_ctx_new(QCryptoHashAlgorithm alg,
const uint8_t *key, size_t nkey,
Error **errp)
{
QCryptoHmac *hmac;
QCryptoHmacNettle *ctx;
if (!qcrypto_hmac_supports(alg)) {
@ -110,38 +110,29 @@ QCryptoHmac *qcrypto_hmac_new(QCryptoHashAlgorithm alg,
return NULL;
}
hmac = g_new0(QCryptoHmac, 1);
hmac->alg = alg;
ctx = g_new0(QCryptoHmacNettle, 1);
qcrypto_hmac_alg_map[alg].setkey(&ctx->u, nkey, key);
hmac->opaque = ctx;
return hmac;
return ctx;
}
void qcrypto_hmac_free(QCryptoHmac *hmac)
static void
qcrypto_nettle_hmac_ctx_free(QCryptoHmac *hmac)
{
QCryptoHmacNettle *ctx;
if (!hmac) {
return;
}
ctx = hmac->opaque;
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)
static int
qcrypto_nettle_hmac_bytesv(QCryptoHmac *hmac,
const struct iovec *iov,
size_t niov,
uint8_t **result,
size_t *resultlen,
Error **errp)
{
QCryptoHmacNettle *ctx;
int i;
@ -173,3 +164,8 @@ int qcrypto_hmac_bytesv(QCryptoHmac *hmac,
return 0;
}
QCryptoHmacDriver qcrypto_hmac_lib_driver = {
.hmac_bytesv = qcrypto_nettle_hmac_bytesv,
.hmac_free = qcrypto_nettle_hmac_ctx_free,
};

View File

@ -12,9 +12,22 @@
#include "qemu/osdep.h"
#include "qapi/error.h"
#include "crypto/hmac.h"
#include "hmacpriv.h"
static const char hex[] = "0123456789abcdef";
int qcrypto_hmac_bytesv(QCryptoHmac *hmac,
const struct iovec *iov,
size_t niov,
uint8_t **result,
size_t *resultlen,
Error **errp)
{
QCryptoHmacDriver *drv = hmac->driver;
return drv->hmac_bytesv(hmac, iov, niov, result, resultlen, errp);
}
int qcrypto_hmac_bytes(QCryptoHmac *hmac,
const char *buf,
size_t len,
@ -70,3 +83,48 @@ int qcrypto_hmac_digest(QCryptoHmac *hmac,
return qcrypto_hmac_digestv(hmac, &iov, 1, digest, errp);
}
QCryptoHmac *qcrypto_hmac_new(QCryptoHashAlgorithm alg,
const uint8_t *key, size_t nkey,
Error **errp)
{
QCryptoHmac *hmac;
void *ctx = NULL;
Error *err2 = NULL;
QCryptoHmacDriver *drv = NULL;
#ifdef CONFIG_AF_ALG
ctx = qcrypto_afalg_hmac_ctx_new(alg, key, nkey, &err2);
if (ctx) {
drv = &qcrypto_hmac_afalg_driver;
}
#endif
if (!ctx) {
ctx = qcrypto_hmac_ctx_new(alg, key, nkey, errp);
if (!ctx) {
return NULL;
}
drv = &qcrypto_hmac_lib_driver;
error_free(err2);
}
hmac = g_new0(QCryptoHmac, 1);
hmac->alg = alg;
hmac->opaque = ctx;
hmac->driver = (void *)drv;
return hmac;
}
void qcrypto_hmac_free(QCryptoHmac *hmac)
{
QCryptoHmacDriver *drv;
if (hmac) {
drv = hmac->driver;
drv->hmac_free(hmac);
g_free(hmac);
}
}

48
crypto/hmacpriv.h Normal file
View File

@ -0,0 +1,48 @@
/*
* QEMU Crypto hmac driver supports
*
* Copyright (c) 2017 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.
*
*/
#ifndef QCRYPTO_HMACPRIV_H
#define QCRYPTO_HMACPRIV_H
typedef struct QCryptoHmacDriver QCryptoHmacDriver;
struct QCryptoHmacDriver {
int (*hmac_bytesv)(QCryptoHmac *hmac,
const struct iovec *iov,
size_t niov,
uint8_t **result,
size_t *resultlen,
Error **errp);
void (*hmac_free)(QCryptoHmac *hmac);
};
extern void *qcrypto_hmac_ctx_new(QCryptoHashAlgorithm alg,
const uint8_t *key, size_t nkey,
Error **errp);
extern QCryptoHmacDriver qcrypto_hmac_lib_driver;
#ifdef CONFIG_AF_ALG
#include "afalgpriv.h"
extern QCryptoAFAlg *
qcrypto_afalg_hmac_ctx_new(QCryptoHashAlgorithm alg,
const uint8_t *key, size_t nkey,
Error **errp);
extern QCryptoHmacDriver qcrypto_hmac_afalg_driver;
#endif
#endif

View File

@ -80,6 +80,7 @@ struct QCryptoCipher {
QCryptoCipherAlgorithm alg;
QCryptoCipherMode mode;
void *opaque;
void *driver;
};
/**

View File

@ -18,6 +18,7 @@ typedef struct QCryptoHmac QCryptoHmac;
struct QCryptoHmac {
QCryptoHashAlgorithm alg;
void *opaque;
void *driver;
};
/**

3
tests/.gitignore vendored
View File

@ -1,4 +1,7 @@
atomic_add-bench
benchmark-crypto-cipher
benchmark-crypto-hash
benchmark-crypto-hmac
check-qdict
check-qnum
check-qjson

View File

@ -97,8 +97,11 @@ gcov-files-test-keyval-y = util/keyval.c
check-unit-y += tests/test-write-threshold$(EXESUF)
gcov-files-test-write-threshold-y = block/write-threshold.c
check-unit-y += tests/test-crypto-hash$(EXESUF)
check-speed-y += tests/benchmark-crypto-hash$(EXESUF)
check-unit-y += tests/test-crypto-hmac$(EXESUF)
check-speed-y += tests/benchmark-crypto-hmac$(EXESUF)
check-unit-y += tests/test-crypto-cipher$(EXESUF)
check-speed-y += tests/benchmark-crypto-cipher$(EXESUF)
check-unit-y += tests/test-crypto-secret$(EXESUF)
check-unit-$(CONFIG_GNUTLS) += tests/test-crypto-tlscredsx509$(EXESUF)
check-unit-$(CONFIG_GNUTLS) += tests/test-crypto-tlssession$(EXESUF)
@ -532,6 +535,7 @@ test-qom-obj-y = $(qom-obj-y) $(test-util-obj-y)
test-qapi-obj-y = tests/test-qapi-visit.o tests/test-qapi-types.o \
tests/test-qapi-event.o tests/test-qmp-introspect.o \
$(test-qom-obj-y)
benchmark-crypto-obj-y = $(crypto-obj-y) $(test-qom-obj-y)
test-crypto-obj-y = $(crypto-obj-y) $(test-qom-obj-y)
test-io-obj-y = $(io-obj-y) $(test-crypto-obj-y)
test-block-obj-y = $(block-obj-y) $(test-io-obj-y) tests/iothread.o
@ -633,8 +637,11 @@ tests/test-mul64$(EXESUF): tests/test-mul64.o $(test-util-obj-y)
tests/test-bitops$(EXESUF): tests/test-bitops.o $(test-util-obj-y)
tests/test-bitcnt$(EXESUF): tests/test-bitcnt.o $(test-util-obj-y)
tests/test-crypto-hash$(EXESUF): tests/test-crypto-hash.o $(test-crypto-obj-y)
tests/benchmark-crypto-hash$(EXESUF): tests/benchmark-crypto-hash.o $(test-crypto-obj-y)
tests/test-crypto-hmac$(EXESUF): tests/test-crypto-hmac.o $(test-crypto-obj-y)
tests/benchmark-crypto-hmac$(EXESUF): tests/benchmark-crypto-hmac.o $(test-crypto-obj-y)
tests/test-crypto-cipher$(EXESUF): tests/test-crypto-cipher.o $(test-crypto-obj-y)
tests/benchmark-crypto-cipher$(EXESUF): tests/benchmark-crypto-cipher.o $(test-crypto-obj-y)
tests/test-crypto-secret$(EXESUF): tests/test-crypto-secret.o $(test-crypto-obj-y)
tests/test-crypto-xts$(EXESUF): tests/test-crypto-xts.o $(test-crypto-obj-y)
@ -803,6 +810,7 @@ check-help:
@echo " make check-qtest-TARGET Run qtest tests for given target"
@echo " make check-qtest Run qtest tests"
@echo " make check-unit Run qobject tests"
@echo " make check-speed Run qobject speed tests"
@echo " make check-qapi-schema Run QAPI schema tests"
@echo " make check-block Run block tests"
@echo " make check-report.html Generates an HTML test report"
@ -833,8 +841,8 @@ $(patsubst %, check-qtest-%, $(QTEST_TARGETS)): check-qtest-%: $(check-qtest-y)
$(GCOV) $(GCOV_OPTIONS) $$f -o `dirname $$f`; \
done,)
.PHONY: $(patsubst %, check-%, $(check-unit-y))
$(patsubst %, check-%, $(check-unit-y)): check-%: %
.PHONY: $(patsubst %, check-%, $(check-unit-y) $(check-speed-y))
$(patsubst %, check-%, $(check-unit-y) $(check-speed-y)): check-%: %
$(if $(CONFIG_GCOV),@rm -f *.gcda */*.gcda */*/*.gcda */*/*/*.gcda,)
$(call quiet-command, \
MALLOC_PERTURB_=$${MALLOC_PERTURB_:-$$((RANDOM % 255 + 1))} \
@ -893,6 +901,7 @@ check-tests/qapi-schema/doc-good.texi: tests/qapi-schema/doc-good.test.texi
check-qapi-schema: $(patsubst %,check-%, $(check-qapi-schema-y)) check-tests/qapi-schema/doc-good.texi
check-qtest: $(patsubst %,check-qtest-%, $(QTEST_TARGETS))
check-unit: $(patsubst %,check-%, $(check-unit-y))
check-speed: $(patsubst %,check-%, $(check-speed-y))
check-block: $(patsubst %,check-%, $(check-block-y))
check: check-qapi-schema check-unit check-qtest
check-clean:

View File

@ -0,0 +1,88 @@
/*
* QEMU Crypto cipher speed benchmark
*
* Copyright (c) 2017 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 "crypto/init.h"
#include "crypto/cipher.h"
static void test_cipher_speed(const void *opaque)
{
QCryptoCipher *cipher;
Error *err = NULL;
double total = 0.0;
size_t chunk_size = (size_t)opaque;
uint8_t *key = NULL, *iv = NULL;
uint8_t *plaintext = NULL, *ciphertext = NULL;
size_t nkey = qcrypto_cipher_get_key_len(QCRYPTO_CIPHER_ALG_AES_128);
size_t niv = qcrypto_cipher_get_iv_len(QCRYPTO_CIPHER_ALG_AES_128,
QCRYPTO_CIPHER_MODE_CBC);
key = g_new0(uint8_t, nkey);
memset(key, g_test_rand_int(), nkey);
iv = g_new0(uint8_t, niv);
memset(iv, g_test_rand_int(), niv);
ciphertext = g_new0(uint8_t, chunk_size);
plaintext = g_new0(uint8_t, chunk_size);
memset(plaintext, g_test_rand_int(), chunk_size);
cipher = qcrypto_cipher_new(QCRYPTO_CIPHER_ALG_AES_128,
QCRYPTO_CIPHER_MODE_CBC,
key, nkey, &err);
g_assert(cipher != NULL);
g_assert(qcrypto_cipher_setiv(cipher,
iv, niv,
&err) == 0);
g_test_timer_start();
do {
g_assert(qcrypto_cipher_encrypt(cipher,
plaintext,
ciphertext,
chunk_size,
&err) == 0);
total += chunk_size;
} while (g_test_timer_elapsed() < 5.0);
total /= 1024 * 1024; /* to MB */
g_print("cbc(aes128): ");
g_print("Testing chunk_size %ld bytes ", chunk_size);
g_print("done: %.2f MB in %.2f secs: ", total, g_test_timer_last());
g_print("%.2f MB/sec\n", total / g_test_timer_last());
qcrypto_cipher_free(cipher);
g_free(plaintext);
g_free(ciphertext);
g_free(iv);
g_free(key);
}
int main(int argc, char **argv)
{
size_t i;
char name[64];
g_test_init(&argc, &argv, NULL);
g_assert(qcrypto_init(NULL) == 0);
for (i = 512; i <= (64 * 1204); i *= 2) {
memset(name, 0 , sizeof(name));
snprintf(name, sizeof(name), "/crypto/cipher/speed-%lu", i);
g_test_add_data_func(name, (void *)i, test_cipher_speed);
}
return g_test_run();
}

View File

@ -0,0 +1,67 @@
/*
* QEMU Crypto hash speed benchmark
*
* Copyright (c) 2017 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 "crypto/init.h"
#include "crypto/hash.h"
static void test_hash_speed(const void *opaque)
{
size_t chunk_size = (size_t)opaque;
uint8_t *in = NULL, *out = NULL;
size_t out_len = 0;
double total = 0.0;
struct iovec iov;
int ret;
in = g_new0(uint8_t, chunk_size);
memset(in, g_test_rand_int(), chunk_size);
iov.iov_base = (char *)in;
iov.iov_len = chunk_size;
g_test_timer_start();
do {
ret = qcrypto_hash_bytesv(QCRYPTO_HASH_ALG_SHA256,
&iov, 1, &out, &out_len,
NULL);
g_assert(ret == 0);
total += chunk_size;
} while (g_test_timer_elapsed() < 5.0);
total /= 1024 * 1024; /* to MB */
g_print("sha256: ");
g_print("Testing chunk_size %ld bytes ", chunk_size);
g_print("done: %.2f MB in %.2f secs: ", total, g_test_timer_last());
g_print("%.2f MB/sec\n", total / g_test_timer_last());
g_free(out);
g_free(in);
}
int main(int argc, char **argv)
{
size_t i;
char name[64];
g_test_init(&argc, &argv, NULL);
g_assert(qcrypto_init(NULL) == 0);
for (i = 512; i <= (64 * 1204); i *= 2) {
memset(name, 0 , sizeof(name));
snprintf(name, sizeof(name), "/crypto/hash/speed-%lu", i);
g_test_add_data_func(name, (void *)i, test_hash_speed);
}
return g_test_run();
}

View File

@ -0,0 +1,82 @@
/*
* QEMU Crypto hmac speed benchmark
*
* Copyright (c) 2017 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 "crypto/init.h"
#include "crypto/hmac.h"
#define KEY "monkey monkey monkey monkey"
static void test_hmac_speed(const void *opaque)
{
size_t chunk_size = (size_t)opaque;
QCryptoHmac *hmac = NULL;
uint8_t *in = NULL, *out = NULL;
size_t out_len = 0;
double total = 0.0;
struct iovec iov;
Error *err = NULL;
int ret;
if (!qcrypto_hmac_supports(QCRYPTO_HASH_ALG_SHA256)) {
return;
}
in = g_new0(uint8_t, chunk_size);
memset(in, g_test_rand_int(), chunk_size);
iov.iov_base = (char *)in;
iov.iov_len = chunk_size;
g_test_timer_start();
do {
hmac = qcrypto_hmac_new(QCRYPTO_HASH_ALG_SHA256,
(const uint8_t *)KEY, strlen(KEY), &err);
g_assert(err == NULL);
g_assert(hmac != NULL);
ret = qcrypto_hmac_bytesv(hmac, &iov, 1, &out, &out_len, &err);
g_assert(ret == 0);
g_assert(err == NULL);
qcrypto_hmac_free(hmac);
total += chunk_size;
} while (g_test_timer_elapsed() < 5.0);
total /= 1024 * 1024; /* to MB */
g_print("hmac(sha256): ");
g_print("Testing chunk_size %ld bytes ", chunk_size);
g_print("done: %.2f MB in %.2f secs: ", total, g_test_timer_last());
g_print("%.2f MB/sec\n", total / g_test_timer_last());
g_free(out);
g_free(in);
}
int main(int argc, char **argv)
{
size_t i;
char name[64];
g_test_init(&argc, &argv, NULL);
g_assert(qcrypto_init(NULL) == 0);
for (i = 512; i <= (64 * 1204); i *= 2) {
memset(name, 0 , sizeof(name));
snprintf(name, sizeof(name), "/crypto/hmac/speed-%lu", i);
g_test_add_data_func(name, (void *)i, test_hmac_speed);
}
return g_test_run();
}