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:
commit
d4e59218ab
|
@ -375,6 +375,7 @@ libnfs=""
|
||||||
coroutine=""
|
coroutine=""
|
||||||
coroutine_pool=""
|
coroutine_pool=""
|
||||||
debug_stack_usage="no"
|
debug_stack_usage="no"
|
||||||
|
crypto_afalg="no"
|
||||||
seccomp=""
|
seccomp=""
|
||||||
glusterfs=""
|
glusterfs=""
|
||||||
glusterfs_xlator_opt="no"
|
glusterfs_xlator_opt="no"
|
||||||
|
@ -1124,6 +1125,10 @@ for opt do
|
||||||
;;
|
;;
|
||||||
--enable-debug-stack-usage) debug_stack_usage="yes"
|
--enable-debug-stack-usage) debug_stack_usage="yes"
|
||||||
;;
|
;;
|
||||||
|
--enable-crypto-afalg) crypto_afalg="yes"
|
||||||
|
;;
|
||||||
|
--disable-crypto-afalg) crypto_afalg="no"
|
||||||
|
;;
|
||||||
--disable-docs) docs="no"
|
--disable-docs) docs="no"
|
||||||
;;
|
;;
|
||||||
--enable-docs) docs="yes"
|
--enable-docs) docs="yes"
|
||||||
|
@ -1518,6 +1523,7 @@ disabled with --disable-FEATURE, default is enabled if available:
|
||||||
qom-cast-debug cast debugging support
|
qom-cast-debug cast debugging support
|
||||||
tools build qemu-io, qemu-nbd and qemu-image tools
|
tools build qemu-io, qemu-nbd and qemu-image tools
|
||||||
vxhs Veritas HyperScale vDisk backend support
|
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
|
NOTE: The object files are built at the place where configure is launched
|
||||||
EOF
|
EOF
|
||||||
|
@ -4852,6 +4858,32 @@ if compile_prog "" "" ; then
|
||||||
have_af_vsock=yes
|
have_af_vsock=yes
|
||||||
fi
|
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
|
# Sparc implicitly links with --relax, which is
|
||||||
# incompatible with -r, so --no-relax should be
|
# incompatible with -r, so --no-relax should be
|
||||||
|
@ -5333,6 +5365,7 @@ echo "seccomp support $seccomp"
|
||||||
echo "coroutine backend $coroutine"
|
echo "coroutine backend $coroutine"
|
||||||
echo "coroutine pool $coroutine_pool"
|
echo "coroutine pool $coroutine_pool"
|
||||||
echo "debug stack usage $debug_stack_usage"
|
echo "debug stack usage $debug_stack_usage"
|
||||||
|
echo "crypto afalg $crypto_afalg"
|
||||||
echo "GlusterFS support $glusterfs"
|
echo "GlusterFS support $glusterfs"
|
||||||
echo "gcov $gcov_tool"
|
echo "gcov $gcov_tool"
|
||||||
echo "gcov enabled $gcov"
|
echo "gcov enabled $gcov"
|
||||||
|
@ -5844,6 +5877,10 @@ if test "$debug_stack_usage" = "yes" ; then
|
||||||
echo "CONFIG_DEBUG_STACK_USAGE=y" >> $config_host_mak
|
echo "CONFIG_DEBUG_STACK_USAGE=y" >> $config_host_mak
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if test "$crypto_afalg" = "yes" ; then
|
||||||
|
echo "CONFIG_AF_ALG=y" >> $config_host_mak
|
||||||
|
fi
|
||||||
|
|
||||||
if test "$open_by_handle_at" = "yes" ; then
|
if test "$open_by_handle_at" = "yes" ; then
|
||||||
echo "CONFIG_OPEN_BY_HANDLE=y" >> $config_host_mak
|
echo "CONFIG_OPEN_BY_HANDLE=y" >> $config_host_mak
|
||||||
fi
|
fi
|
||||||
|
|
|
@ -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 += aes.o
|
||||||
crypto-obj-y += desrfb.o
|
crypto-obj-y += desrfb.o
|
||||||
crypto-obj-y += cipher.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 += tlscreds.o
|
||||||
crypto-obj-y += tlscredsanon.o
|
crypto-obj-y += tlscredsanon.o
|
||||||
crypto-obj-y += tlscredsx509.o
|
crypto-obj-y += tlscredsx509.o
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
|
@ -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
|
|
@ -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,
|
||||||
|
};
|
|
@ -22,6 +22,7 @@
|
||||||
#include "crypto/aes.h"
|
#include "crypto/aes.h"
|
||||||
#include "crypto/desrfb.h"
|
#include "crypto/desrfb.h"
|
||||||
#include "crypto/xts.h"
|
#include "crypto/xts.h"
|
||||||
|
#include "cipherpriv.h"
|
||||||
|
|
||||||
typedef struct QCryptoCipherBuiltinAESContext QCryptoCipherBuiltinAESContext;
|
typedef struct QCryptoCipherBuiltinAESContext QCryptoCipherBuiltinAESContext;
|
||||||
struct QCryptoCipherBuiltinAESContext {
|
struct QCryptoCipherBuiltinAESContext {
|
||||||
|
@ -235,23 +236,24 @@ static int qcrypto_cipher_setiv_aes(QCryptoCipher *cipher,
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static int qcrypto_cipher_init_aes(QCryptoCipher *cipher,
|
static QCryptoCipherBuiltin *
|
||||||
const uint8_t *key, size_t nkey,
|
qcrypto_cipher_init_aes(QCryptoCipherMode mode,
|
||||||
Error **errp)
|
const uint8_t *key, size_t nkey,
|
||||||
|
Error **errp)
|
||||||
{
|
{
|
||||||
QCryptoCipherBuiltin *ctxt;
|
QCryptoCipherBuiltin *ctxt;
|
||||||
|
|
||||||
if (cipher->mode != QCRYPTO_CIPHER_MODE_CBC &&
|
if (mode != QCRYPTO_CIPHER_MODE_CBC &&
|
||||||
cipher->mode != QCRYPTO_CIPHER_MODE_ECB &&
|
mode != QCRYPTO_CIPHER_MODE_ECB &&
|
||||||
cipher->mode != QCRYPTO_CIPHER_MODE_XTS) {
|
mode != QCRYPTO_CIPHER_MODE_XTS) {
|
||||||
error_setg(errp, "Unsupported cipher mode %s",
|
error_setg(errp, "Unsupported cipher mode %s",
|
||||||
QCryptoCipherMode_lookup[cipher->mode]);
|
QCryptoCipherMode_lookup[mode]);
|
||||||
return -1;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
ctxt = g_new0(QCryptoCipherBuiltin, 1);
|
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) {
|
if (AES_set_encrypt_key(key, nkey * 4, &ctxt->state.aes.key.enc) != 0) {
|
||||||
error_setg(errp, "Failed to set encryption key");
|
error_setg(errp, "Failed to set encryption key");
|
||||||
goto error;
|
goto error;
|
||||||
|
@ -291,13 +293,11 @@ static int qcrypto_cipher_init_aes(QCryptoCipher *cipher,
|
||||||
ctxt->encrypt = qcrypto_cipher_encrypt_aes;
|
ctxt->encrypt = qcrypto_cipher_encrypt_aes;
|
||||||
ctxt->decrypt = qcrypto_cipher_decrypt_aes;
|
ctxt->decrypt = qcrypto_cipher_decrypt_aes;
|
||||||
|
|
||||||
cipher->opaque = ctxt;
|
return ctxt;
|
||||||
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
error:
|
error:
|
||||||
g_free(ctxt);
|
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,
|
static QCryptoCipherBuiltin *
|
||||||
const uint8_t *key, size_t nkey,
|
qcrypto_cipher_init_des_rfb(QCryptoCipherMode mode,
|
||||||
Error **errp)
|
const uint8_t *key, size_t nkey,
|
||||||
|
Error **errp)
|
||||||
{
|
{
|
||||||
QCryptoCipherBuiltin *ctxt;
|
QCryptoCipherBuiltin *ctxt;
|
||||||
|
|
||||||
if (cipher->mode != QCRYPTO_CIPHER_MODE_ECB) {
|
if (mode != QCRYPTO_CIPHER_MODE_ECB) {
|
||||||
error_setg(errp, "Unsupported cipher mode %s",
|
error_setg(errp, "Unsupported cipher mode %s",
|
||||||
QCryptoCipherMode_lookup[cipher->mode]);
|
QCryptoCipherMode_lookup[mode]);
|
||||||
return -1;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
ctxt = g_new0(QCryptoCipherBuiltin, 1);
|
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->encrypt = qcrypto_cipher_encrypt_des_rfb;
|
||||||
ctxt->decrypt = qcrypto_cipher_decrypt_des_rfb;
|
ctxt->decrypt = qcrypto_cipher_decrypt_des_rfb;
|
||||||
|
|
||||||
cipher->opaque = ctxt;
|
return ctxt;
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -426,12 +425,13 @@ bool qcrypto_cipher_supports(QCryptoCipherAlgorithm alg,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
QCryptoCipher *qcrypto_cipher_new(QCryptoCipherAlgorithm alg,
|
static QCryptoCipherBuiltin *qcrypto_cipher_ctx_new(QCryptoCipherAlgorithm alg,
|
||||||
QCryptoCipherMode mode,
|
QCryptoCipherMode mode,
|
||||||
const uint8_t *key, size_t nkey,
|
const uint8_t *key,
|
||||||
Error **errp)
|
size_t nkey,
|
||||||
|
Error **errp)
|
||||||
{
|
{
|
||||||
QCryptoCipher *cipher;
|
QCryptoCipherBuiltin *ctxt;
|
||||||
|
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
case QCRYPTO_CIPHER_MODE_ECB:
|
case QCRYPTO_CIPHER_MODE_ECB:
|
||||||
|
@ -444,60 +444,45 @@ QCryptoCipher *qcrypto_cipher_new(QCryptoCipherAlgorithm alg,
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
cipher = g_new0(QCryptoCipher, 1);
|
|
||||||
cipher->alg = alg;
|
|
||||||
cipher->mode = mode;
|
|
||||||
|
|
||||||
if (!qcrypto_cipher_validate_key_length(alg, mode, nkey, errp)) {
|
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:
|
case QCRYPTO_CIPHER_ALG_DES_RFB:
|
||||||
if (qcrypto_cipher_init_des_rfb(cipher, key, nkey, errp) < 0) {
|
ctxt = qcrypto_cipher_init_des_rfb(mode, key, nkey, errp);
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case QCRYPTO_CIPHER_ALG_AES_128:
|
case QCRYPTO_CIPHER_ALG_AES_128:
|
||||||
case QCRYPTO_CIPHER_ALG_AES_192:
|
case QCRYPTO_CIPHER_ALG_AES_192:
|
||||||
case QCRYPTO_CIPHER_ALG_AES_256:
|
case QCRYPTO_CIPHER_ALG_AES_256:
|
||||||
if (qcrypto_cipher_init_aes(cipher, key, nkey, errp) < 0) {
|
ctxt = qcrypto_cipher_init_aes(mode, key, nkey, errp);
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
error_setg(errp,
|
error_setg(errp,
|
||||||
"Unsupported cipher algorithm %s",
|
"Unsupported cipher algorithm %s",
|
||||||
QCryptoCipherAlgorithm_lookup[cipher->alg]);
|
QCryptoCipherAlgorithm_lookup[alg]);
|
||||||
goto error;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return cipher;
|
return ctxt;
|
||||||
|
|
||||||
error:
|
|
||||||
g_free(cipher);
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void qcrypto_cipher_free(QCryptoCipher *cipher)
|
static void
|
||||||
|
qcrypto_builtin_cipher_ctx_free(QCryptoCipher *cipher)
|
||||||
{
|
{
|
||||||
QCryptoCipherBuiltin *ctxt;
|
QCryptoCipherBuiltin *ctxt;
|
||||||
|
|
||||||
if (!cipher) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ctxt = cipher->opaque;
|
ctxt = cipher->opaque;
|
||||||
ctxt->free(cipher);
|
ctxt->free(cipher);
|
||||||
g_free(cipher);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int qcrypto_cipher_encrypt(QCryptoCipher *cipher,
|
static int
|
||||||
const void *in,
|
qcrypto_builtin_cipher_encrypt(QCryptoCipher *cipher,
|
||||||
void *out,
|
const void *in,
|
||||||
size_t len,
|
void *out,
|
||||||
Error **errp)
|
size_t len,
|
||||||
|
Error **errp)
|
||||||
{
|
{
|
||||||
QCryptoCipherBuiltin *ctxt = cipher->opaque;
|
QCryptoCipherBuiltin *ctxt = cipher->opaque;
|
||||||
|
|
||||||
|
@ -511,11 +496,12 @@ int qcrypto_cipher_encrypt(QCryptoCipher *cipher,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int qcrypto_cipher_decrypt(QCryptoCipher *cipher,
|
static int
|
||||||
const void *in,
|
qcrypto_builtin_cipher_decrypt(QCryptoCipher *cipher,
|
||||||
void *out,
|
const void *in,
|
||||||
size_t len,
|
void *out,
|
||||||
Error **errp)
|
size_t len,
|
||||||
|
Error **errp)
|
||||||
{
|
{
|
||||||
QCryptoCipherBuiltin *ctxt = cipher->opaque;
|
QCryptoCipherBuiltin *ctxt = cipher->opaque;
|
||||||
|
|
||||||
|
@ -529,11 +515,20 @@ int qcrypto_cipher_decrypt(QCryptoCipher *cipher,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int qcrypto_cipher_setiv(QCryptoCipher *cipher,
|
static int
|
||||||
const uint8_t *iv, size_t niv,
|
qcrypto_builtin_cipher_setiv(QCryptoCipher *cipher,
|
||||||
Error **errp)
|
const uint8_t *iv, size_t niv,
|
||||||
|
Error **errp)
|
||||||
{
|
{
|
||||||
QCryptoCipherBuiltin *ctxt = cipher->opaque;
|
QCryptoCipherBuiltin *ctxt = cipher->opaque;
|
||||||
|
|
||||||
return ctxt->setiv(cipher, iv, niv, errp);
|
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,
|
||||||
|
};
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
|
|
||||||
#include "qemu/osdep.h"
|
#include "qemu/osdep.h"
|
||||||
#include "crypto/xts.h"
|
#include "crypto/xts.h"
|
||||||
|
#include "cipherpriv.h"
|
||||||
|
|
||||||
#include <gcrypt.h>
|
#include <gcrypt.h>
|
||||||
|
|
||||||
|
@ -64,12 +65,29 @@ struct QCryptoCipherGcrypt {
|
||||||
uint8_t *iv;
|
uint8_t *iv;
|
||||||
};
|
};
|
||||||
|
|
||||||
QCryptoCipher *qcrypto_cipher_new(QCryptoCipherAlgorithm alg,
|
static void
|
||||||
QCryptoCipherMode mode,
|
qcrypto_gcrypt_cipher_free_ctx(QCryptoCipherGcrypt *ctx,
|
||||||
const uint8_t *key, size_t nkey,
|
QCryptoCipherMode mode)
|
||||||
Error **errp)
|
{
|
||||||
|
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;
|
QCryptoCipherGcrypt *ctx;
|
||||||
gcry_error_t err;
|
gcry_error_t err;
|
||||||
int gcryalg, gcrymode;
|
int gcryalg, gcrymode;
|
||||||
|
@ -146,10 +164,6 @@ QCryptoCipher *qcrypto_cipher_new(QCryptoCipherAlgorithm alg,
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
cipher = g_new0(QCryptoCipher, 1);
|
|
||||||
cipher->alg = alg;
|
|
||||||
cipher->mode = mode;
|
|
||||||
|
|
||||||
ctx = g_new0(QCryptoCipherGcrypt, 1);
|
ctx = g_new0(QCryptoCipherGcrypt, 1);
|
||||||
|
|
||||||
err = gcry_cipher_open(&ctx->handle, gcryalg, gcrymode, 0);
|
err = gcry_cipher_open(&ctx->handle, gcryalg, gcrymode, 0);
|
||||||
|
@ -158,7 +172,7 @@ QCryptoCipher *qcrypto_cipher_new(QCryptoCipherAlgorithm alg,
|
||||||
gcry_strerror(err));
|
gcry_strerror(err));
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
if (cipher->mode == QCRYPTO_CIPHER_MODE_XTS) {
|
if (mode == QCRYPTO_CIPHER_MODE_XTS) {
|
||||||
err = gcry_cipher_open(&ctx->tweakhandle, gcryalg, gcrymode, 0);
|
err = gcry_cipher_open(&ctx->tweakhandle, gcryalg, gcrymode, 0);
|
||||||
if (err != 0) {
|
if (err != 0) {
|
||||||
error_setg(errp, "Cannot initialize cipher: %s",
|
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
|
/* We're using standard DES cipher from gcrypt, so we need
|
||||||
* to munge the key so that the results are the same as the
|
* to munge the key so that the results are the same as the
|
||||||
* bizarre RFB variant of DES :-)
|
* bizarre RFB variant of DES :-)
|
||||||
|
@ -177,7 +191,7 @@ QCryptoCipher *qcrypto_cipher_new(QCryptoCipherAlgorithm alg,
|
||||||
g_free(rfbkey);
|
g_free(rfbkey);
|
||||||
ctx->blocksize = 8;
|
ctx->blocksize = 8;
|
||||||
} else {
|
} else {
|
||||||
if (cipher->mode == QCRYPTO_CIPHER_MODE_XTS) {
|
if (mode == QCRYPTO_CIPHER_MODE_XTS) {
|
||||||
nkey /= 2;
|
nkey /= 2;
|
||||||
err = gcry_cipher_setkey(ctx->handle, key, nkey);
|
err = gcry_cipher_setkey(ctx->handle, key, nkey);
|
||||||
if (err != 0) {
|
if (err != 0) {
|
||||||
|
@ -194,7 +208,7 @@ QCryptoCipher *qcrypto_cipher_new(QCryptoCipherAlgorithm alg,
|
||||||
gcry_strerror(err));
|
gcry_strerror(err));
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
switch (cipher->alg) {
|
switch (alg) {
|
||||||
case QCRYPTO_CIPHER_ALG_AES_128:
|
case QCRYPTO_CIPHER_ALG_AES_128:
|
||||||
case QCRYPTO_CIPHER_ALG_AES_192:
|
case QCRYPTO_CIPHER_ALG_AES_192:
|
||||||
case QCRYPTO_CIPHER_ALG_AES_256:
|
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) {
|
if (ctx->blocksize != XTS_BLOCK_SIZE) {
|
||||||
error_setg(errp,
|
error_setg(errp,
|
||||||
"Cipher block size %zu must equal XTS block size %d",
|
"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);
|
ctx->iv = g_new0(uint8_t, ctx->blocksize);
|
||||||
}
|
}
|
||||||
|
|
||||||
cipher->opaque = ctx;
|
return ctx;
|
||||||
return cipher;
|
|
||||||
|
|
||||||
error:
|
error:
|
||||||
gcry_cipher_close(ctx->handle);
|
qcrypto_gcrypt_cipher_free_ctx(ctx, mode);
|
||||||
if (cipher->mode == QCRYPTO_CIPHER_MODE_XTS) {
|
|
||||||
gcry_cipher_close(ctx->tweakhandle);
|
|
||||||
}
|
|
||||||
g_free(ctx);
|
|
||||||
g_free(cipher);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void qcrypto_cipher_free(QCryptoCipher *cipher)
|
static void
|
||||||
|
qcrypto_gcrypt_cipher_ctx_free(QCryptoCipher *cipher)
|
||||||
{
|
{
|
||||||
QCryptoCipherGcrypt *ctx;
|
qcrypto_gcrypt_cipher_free_ctx(cipher->opaque, cipher->mode);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -275,11 +273,12 @@ static void qcrypto_gcrypt_xts_decrypt(const void *ctx,
|
||||||
g_assert(err == 0);
|
g_assert(err == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int qcrypto_cipher_encrypt(QCryptoCipher *cipher,
|
static int
|
||||||
const void *in,
|
qcrypto_gcrypt_cipher_encrypt(QCryptoCipher *cipher,
|
||||||
void *out,
|
const void *in,
|
||||||
size_t len,
|
void *out,
|
||||||
Error **errp)
|
size_t len,
|
||||||
|
Error **errp)
|
||||||
{
|
{
|
||||||
QCryptoCipherGcrypt *ctx = cipher->opaque;
|
QCryptoCipherGcrypt *ctx = cipher->opaque;
|
||||||
gcry_error_t err;
|
gcry_error_t err;
|
||||||
|
@ -310,11 +309,12 @@ int qcrypto_cipher_encrypt(QCryptoCipher *cipher,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int qcrypto_cipher_decrypt(QCryptoCipher *cipher,
|
static int
|
||||||
const void *in,
|
qcrypto_gcrypt_cipher_decrypt(QCryptoCipher *cipher,
|
||||||
void *out,
|
const void *in,
|
||||||
size_t len,
|
void *out,
|
||||||
Error **errp)
|
size_t len,
|
||||||
|
Error **errp)
|
||||||
{
|
{
|
||||||
QCryptoCipherGcrypt *ctx = cipher->opaque;
|
QCryptoCipherGcrypt *ctx = cipher->opaque;
|
||||||
gcry_error_t err;
|
gcry_error_t err;
|
||||||
|
@ -344,9 +344,10 @@ int qcrypto_cipher_decrypt(QCryptoCipher *cipher,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int qcrypto_cipher_setiv(QCryptoCipher *cipher,
|
static int
|
||||||
const uint8_t *iv, size_t niv,
|
qcrypto_gcrypt_cipher_setiv(QCryptoCipher *cipher,
|
||||||
Error **errp)
|
const uint8_t *iv, size_t niv,
|
||||||
|
Error **errp)
|
||||||
{
|
{
|
||||||
QCryptoCipherGcrypt *ctx = cipher->opaque;
|
QCryptoCipherGcrypt *ctx = cipher->opaque;
|
||||||
gcry_error_t err;
|
gcry_error_t err;
|
||||||
|
@ -380,3 +381,11 @@ int qcrypto_cipher_setiv(QCryptoCipher *cipher,
|
||||||
|
|
||||||
return 0;
|
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,
|
||||||
|
};
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
|
|
||||||
#include "qemu/osdep.h"
|
#include "qemu/osdep.h"
|
||||||
#include "crypto/xts.h"
|
#include "crypto/xts.h"
|
||||||
|
#include "cipherpriv.h"
|
||||||
|
|
||||||
#include <nettle/nettle-types.h>
|
#include <nettle/nettle-types.h>
|
||||||
#include <nettle/aes.h>
|
#include <nettle/aes.h>
|
||||||
|
@ -249,12 +250,26 @@ bool qcrypto_cipher_supports(QCryptoCipherAlgorithm alg,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
QCryptoCipher *qcrypto_cipher_new(QCryptoCipherAlgorithm alg,
|
static void
|
||||||
QCryptoCipherMode mode,
|
qcrypto_nettle_cipher_free_ctx(QCryptoCipherNettle *ctx)
|
||||||
const uint8_t *key, size_t nkey,
|
{
|
||||||
Error **errp)
|
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;
|
QCryptoCipherNettle *ctx;
|
||||||
uint8_t *rfbkey;
|
uint8_t *rfbkey;
|
||||||
|
|
||||||
|
@ -274,12 +289,7 @@ QCryptoCipher *qcrypto_cipher_new(QCryptoCipherAlgorithm alg,
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
cipher = g_new0(QCryptoCipher, 1);
|
|
||||||
cipher->alg = alg;
|
|
||||||
cipher->mode = mode;
|
|
||||||
|
|
||||||
ctx = g_new0(QCryptoCipherNettle, 1);
|
ctx = g_new0(QCryptoCipherNettle, 1);
|
||||||
cipher->opaque = ctx;
|
|
||||||
|
|
||||||
switch (alg) {
|
switch (alg) {
|
||||||
case QCRYPTO_CIPHER_ALG_DES_RFB:
|
case QCRYPTO_CIPHER_ALG_DES_RFB:
|
||||||
|
@ -423,36 +433,30 @@ QCryptoCipher *qcrypto_cipher_new(QCryptoCipherAlgorithm alg,
|
||||||
|
|
||||||
ctx->iv = g_new0(uint8_t, ctx->blocksize);
|
ctx->iv = g_new0(uint8_t, ctx->blocksize);
|
||||||
|
|
||||||
return cipher;
|
return ctx;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
qcrypto_cipher_free(cipher);
|
qcrypto_nettle_cipher_free_ctx(ctx);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void qcrypto_cipher_free(QCryptoCipher *cipher)
|
static void
|
||||||
|
qcrypto_nettle_cipher_ctx_free(QCryptoCipher *cipher)
|
||||||
{
|
{
|
||||||
QCryptoCipherNettle *ctx;
|
QCryptoCipherNettle *ctx;
|
||||||
|
|
||||||
if (!cipher) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx = cipher->opaque;
|
ctx = cipher->opaque;
|
||||||
g_free(ctx->iv);
|
qcrypto_nettle_cipher_free_ctx(ctx);
|
||||||
g_free(ctx->ctx);
|
|
||||||
g_free(ctx->ctx_tweak);
|
|
||||||
g_free(ctx);
|
|
||||||
g_free(cipher);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int qcrypto_cipher_encrypt(QCryptoCipher *cipher,
|
static int
|
||||||
const void *in,
|
qcrypto_nettle_cipher_encrypt(QCryptoCipher *cipher,
|
||||||
void *out,
|
const void *in,
|
||||||
size_t len,
|
void *out,
|
||||||
Error **errp)
|
size_t len,
|
||||||
|
Error **errp)
|
||||||
{
|
{
|
||||||
QCryptoCipherNettle *ctx = cipher->opaque;
|
QCryptoCipherNettle *ctx = cipher->opaque;
|
||||||
|
|
||||||
|
@ -494,11 +498,12 @@ int qcrypto_cipher_encrypt(QCryptoCipher *cipher,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int qcrypto_cipher_decrypt(QCryptoCipher *cipher,
|
static int
|
||||||
const void *in,
|
qcrypto_nettle_cipher_decrypt(QCryptoCipher *cipher,
|
||||||
void *out,
|
const void *in,
|
||||||
size_t len,
|
void *out,
|
||||||
Error **errp)
|
size_t len,
|
||||||
|
Error **errp)
|
||||||
{
|
{
|
||||||
QCryptoCipherNettle *ctx = cipher->opaque;
|
QCryptoCipherNettle *ctx = cipher->opaque;
|
||||||
|
|
||||||
|
@ -538,9 +543,10 @@ int qcrypto_cipher_decrypt(QCryptoCipher *cipher,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int qcrypto_cipher_setiv(QCryptoCipher *cipher,
|
static int
|
||||||
const uint8_t *iv, size_t niv,
|
qcrypto_nettle_cipher_setiv(QCryptoCipher *cipher,
|
||||||
Error **errp)
|
const uint8_t *iv, size_t niv,
|
||||||
|
Error **errp)
|
||||||
{
|
{
|
||||||
QCryptoCipherNettle *ctx = cipher->opaque;
|
QCryptoCipherNettle *ctx = cipher->opaque;
|
||||||
if (niv != ctx->blocksize) {
|
if (niv != ctx->blocksize) {
|
||||||
|
@ -551,3 +557,11 @@ int qcrypto_cipher_setiv(QCryptoCipher *cipher,
|
||||||
memcpy(ctx->iv, iv, niv);
|
memcpy(ctx->iv, iv, niv);
|
||||||
return 0;
|
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,
|
||||||
|
};
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#include "qemu/osdep.h"
|
#include "qemu/osdep.h"
|
||||||
#include "qapi/error.h"
|
#include "qapi/error.h"
|
||||||
#include "crypto/cipher.h"
|
#include "crypto/cipher.h"
|
||||||
|
#include "cipherpriv.h"
|
||||||
|
|
||||||
|
|
||||||
static size_t alg_key_len[QCRYPTO_CIPHER_ALG__MAX] = {
|
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
|
#else
|
||||||
#include "crypto/cipher-builtin.c"
|
#include "crypto/cipher-builtin.c"
|
||||||
#endif
|
#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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -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
|
|
@ -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,
|
||||||
|
};
|
|
@ -22,6 +22,7 @@
|
||||||
#include <gcrypt.h>
|
#include <gcrypt.h>
|
||||||
#include "qapi/error.h"
|
#include "qapi/error.h"
|
||||||
#include "crypto/hash.h"
|
#include "crypto/hash.h"
|
||||||
|
#include "hashpriv.h"
|
||||||
|
|
||||||
|
|
||||||
static int qcrypto_hash_alg_map[QCRYPTO_HASH_ALG__MAX] = {
|
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,
|
static int
|
||||||
const struct iovec *iov,
|
qcrypto_gcrypt_hash_bytesv(QCryptoHashAlgorithm alg,
|
||||||
size_t niov,
|
const struct iovec *iov,
|
||||||
uint8_t **result,
|
size_t niov,
|
||||||
size_t *resultlen,
|
uint8_t **result,
|
||||||
Error **errp)
|
size_t *resultlen,
|
||||||
|
Error **errp)
|
||||||
{
|
{
|
||||||
int i, ret;
|
int i, ret;
|
||||||
gcry_md_hd_t md;
|
gcry_md_hd_t md;
|
||||||
|
@ -107,3 +109,8 @@ int qcrypto_hash_bytesv(QCryptoHashAlgorithm alg,
|
||||||
gcry_md_close(md);
|
gcry_md_close(md);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
QCryptoHashDriver qcrypto_hash_lib_driver = {
|
||||||
|
.hash_bytesv = qcrypto_gcrypt_hash_bytesv,
|
||||||
|
};
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#include "qemu/osdep.h"
|
#include "qemu/osdep.h"
|
||||||
#include "qapi/error.h"
|
#include "qapi/error.h"
|
||||||
#include "crypto/hash.h"
|
#include "crypto/hash.h"
|
||||||
|
#include "hashpriv.h"
|
||||||
|
|
||||||
|
|
||||||
static int qcrypto_hash_alg_map[QCRYPTO_HASH_ALG__MAX] = {
|
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,
|
static int
|
||||||
const struct iovec *iov,
|
qcrypto_glib_hash_bytesv(QCryptoHashAlgorithm alg,
|
||||||
size_t niov,
|
const struct iovec *iov,
|
||||||
uint8_t **result,
|
size_t niov,
|
||||||
size_t *resultlen,
|
uint8_t **result,
|
||||||
Error **errp)
|
size_t *resultlen,
|
||||||
|
Error **errp)
|
||||||
{
|
{
|
||||||
int i, ret;
|
int i, ret;
|
||||||
GChecksum *cs;
|
GChecksum *cs;
|
||||||
|
@ -95,3 +97,8 @@ int qcrypto_hash_bytesv(QCryptoHashAlgorithm alg,
|
||||||
g_checksum_free(cs);
|
g_checksum_free(cs);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
QCryptoHashDriver qcrypto_hash_lib_driver = {
|
||||||
|
.hash_bytesv = qcrypto_glib_hash_bytesv,
|
||||||
|
};
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#include "qemu/osdep.h"
|
#include "qemu/osdep.h"
|
||||||
#include "qapi/error.h"
|
#include "qapi/error.h"
|
||||||
#include "crypto/hash.h"
|
#include "crypto/hash.h"
|
||||||
|
#include "hashpriv.h"
|
||||||
#include <nettle/md5.h>
|
#include <nettle/md5.h>
|
||||||
#include <nettle/sha.h>
|
#include <nettle/sha.h>
|
||||||
#include <nettle/ripemd160.h>
|
#include <nettle/ripemd160.h>
|
||||||
|
@ -103,12 +104,13 @@ gboolean qcrypto_hash_supports(QCryptoHashAlgorithm alg)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int qcrypto_hash_bytesv(QCryptoHashAlgorithm alg,
|
static int
|
||||||
const struct iovec *iov,
|
qcrypto_nettle_hash_bytesv(QCryptoHashAlgorithm alg,
|
||||||
size_t niov,
|
const struct iovec *iov,
|
||||||
uint8_t **result,
|
size_t niov,
|
||||||
size_t *resultlen,
|
uint8_t **result,
|
||||||
Error **errp)
|
size_t *resultlen,
|
||||||
|
Error **errp)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
union qcrypto_hash_ctx ctx;
|
union qcrypto_hash_ctx ctx;
|
||||||
|
@ -152,3 +154,8 @@ int qcrypto_hash_bytesv(QCryptoHashAlgorithm alg,
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
QCryptoHashDriver qcrypto_hash_lib_driver = {
|
||||||
|
.hash_bytesv = qcrypto_nettle_hash_bytesv,
|
||||||
|
};
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#include "qemu/osdep.h"
|
#include "qemu/osdep.h"
|
||||||
#include "qapi/error.h"
|
#include "qapi/error.h"
|
||||||
#include "crypto/hash.h"
|
#include "crypto/hash.h"
|
||||||
|
#include "hashpriv.h"
|
||||||
|
|
||||||
static size_t qcrypto_hash_alg_size[QCRYPTO_HASH_ALG__MAX] = {
|
static size_t qcrypto_hash_alg_size[QCRYPTO_HASH_ALG__MAX] = {
|
||||||
[QCRYPTO_HASH_ALG_MD5] = 16,
|
[QCRYPTO_HASH_ALG_MD5] = 16,
|
||||||
|
@ -38,6 +39,35 @@ size_t qcrypto_hash_digest_len(QCryptoHashAlgorithm alg)
|
||||||
return qcrypto_hash_alg_size[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,
|
int qcrypto_hash_bytes(QCryptoHashAlgorithm alg,
|
||||||
const char *buf,
|
const char *buf,
|
||||||
|
|
|
@ -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
|
|
@ -15,6 +15,7 @@
|
||||||
#include "qemu/osdep.h"
|
#include "qemu/osdep.h"
|
||||||
#include "qapi/error.h"
|
#include "qapi/error.h"
|
||||||
#include "crypto/hmac.h"
|
#include "crypto/hmac.h"
|
||||||
|
#include "hmacpriv.h"
|
||||||
#include <gcrypt.h>
|
#include <gcrypt.h>
|
||||||
|
|
||||||
static int qcrypto_hmac_alg_map[QCRYPTO_HASH_ALG__MAX] = {
|
static int qcrypto_hmac_alg_map[QCRYPTO_HASH_ALG__MAX] = {
|
||||||
|
@ -42,11 +43,10 @@ bool qcrypto_hmac_supports(QCryptoHashAlgorithm alg)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
QCryptoHmac *qcrypto_hmac_new(QCryptoHashAlgorithm alg,
|
void *qcrypto_hmac_ctx_new(QCryptoHashAlgorithm alg,
|
||||||
const uint8_t *key, size_t nkey,
|
const uint8_t *key, size_t nkey,
|
||||||
Error **errp)
|
Error **errp)
|
||||||
{
|
{
|
||||||
QCryptoHmac *hmac;
|
|
||||||
QCryptoHmacGcrypt *ctx;
|
QCryptoHmacGcrypt *ctx;
|
||||||
gcry_error_t err;
|
gcry_error_t err;
|
||||||
|
|
||||||
|
@ -56,9 +56,6 @@ QCryptoHmac *qcrypto_hmac_new(QCryptoHashAlgorithm alg,
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
hmac = g_new0(QCryptoHmac, 1);
|
|
||||||
hmac->alg = alg;
|
|
||||||
|
|
||||||
ctx = g_new0(QCryptoHmacGcrypt, 1);
|
ctx = g_new0(QCryptoHmacGcrypt, 1);
|
||||||
|
|
||||||
err = gcry_mac_open(&ctx->handle, qcrypto_hmac_alg_map[alg],
|
err = gcry_mac_open(&ctx->handle, qcrypto_hmac_alg_map[alg],
|
||||||
|
@ -73,39 +70,35 @@ QCryptoHmac *qcrypto_hmac_new(QCryptoHashAlgorithm alg,
|
||||||
if (err != 0) {
|
if (err != 0) {
|
||||||
error_setg(errp, "Cannot set key: %s",
|
error_setg(errp, "Cannot set key: %s",
|
||||||
gcry_strerror(err));
|
gcry_strerror(err));
|
||||||
|
gcry_mac_close(ctx->handle);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
hmac->opaque = ctx;
|
return ctx;
|
||||||
return hmac;
|
|
||||||
|
|
||||||
error:
|
error:
|
||||||
g_free(ctx);
|
g_free(ctx);
|
||||||
g_free(hmac);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void qcrypto_hmac_free(QCryptoHmac *hmac)
|
static void
|
||||||
|
qcrypto_gcrypt_hmac_ctx_free(QCryptoHmac *hmac)
|
||||||
{
|
{
|
||||||
QCryptoHmacGcrypt *ctx;
|
QCryptoHmacGcrypt *ctx;
|
||||||
|
|
||||||
if (!hmac) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx = hmac->opaque;
|
ctx = hmac->opaque;
|
||||||
gcry_mac_close(ctx->handle);
|
gcry_mac_close(ctx->handle);
|
||||||
|
|
||||||
g_free(ctx);
|
g_free(ctx);
|
||||||
g_free(hmac);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int qcrypto_hmac_bytesv(QCryptoHmac *hmac,
|
static int
|
||||||
const struct iovec *iov,
|
qcrypto_gcrypt_hmac_bytesv(QCryptoHmac *hmac,
|
||||||
size_t niov,
|
const struct iovec *iov,
|
||||||
uint8_t **result,
|
size_t niov,
|
||||||
size_t *resultlen,
|
uint8_t **result,
|
||||||
Error **errp)
|
size_t *resultlen,
|
||||||
|
Error **errp)
|
||||||
{
|
{
|
||||||
QCryptoHmacGcrypt *ctx;
|
QCryptoHmacGcrypt *ctx;
|
||||||
gcry_error_t err;
|
gcry_error_t err;
|
||||||
|
@ -150,3 +143,8 @@ int qcrypto_hmac_bytesv(QCryptoHmac *hmac,
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QCryptoHmacDriver qcrypto_hmac_lib_driver = {
|
||||||
|
.hmac_bytesv = qcrypto_gcrypt_hmac_bytesv,
|
||||||
|
.hmac_free = qcrypto_gcrypt_hmac_ctx_free,
|
||||||
|
};
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
#include "qemu/osdep.h"
|
#include "qemu/osdep.h"
|
||||||
#include "qapi/error.h"
|
#include "qapi/error.h"
|
||||||
#include "crypto/hmac.h"
|
#include "crypto/hmac.h"
|
||||||
|
#include "hmacpriv.h"
|
||||||
|
|
||||||
/* Support for HMAC Algos has been added in GLib 2.30 */
|
/* Support for HMAC Algos has been added in GLib 2.30 */
|
||||||
#if GLIB_CHECK_VERSION(2, 30, 0)
|
#if GLIB_CHECK_VERSION(2, 30, 0)
|
||||||
|
@ -49,11 +50,10 @@ bool qcrypto_hmac_supports(QCryptoHashAlgorithm alg)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
QCryptoHmac *qcrypto_hmac_new(QCryptoHashAlgorithm alg,
|
void *qcrypto_hmac_ctx_new(QCryptoHashAlgorithm alg,
|
||||||
const uint8_t *key, size_t nkey,
|
const uint8_t *key, size_t nkey,
|
||||||
Error **errp)
|
Error **errp)
|
||||||
{
|
{
|
||||||
QCryptoHmac *hmac;
|
|
||||||
QCryptoHmacGlib *ctx;
|
QCryptoHmacGlib *ctx;
|
||||||
|
|
||||||
if (!qcrypto_hmac_supports(alg)) {
|
if (!qcrypto_hmac_supports(alg)) {
|
||||||
|
@ -62,9 +62,6 @@ QCryptoHmac *qcrypto_hmac_new(QCryptoHashAlgorithm alg,
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
hmac = g_new0(QCryptoHmac, 1);
|
|
||||||
hmac->alg = alg;
|
|
||||||
|
|
||||||
ctx = g_new0(QCryptoHmacGlib, 1);
|
ctx = g_new0(QCryptoHmacGlib, 1);
|
||||||
|
|
||||||
ctx->ghmac = g_hmac_new(qcrypto_hmac_alg_map[alg],
|
ctx->ghmac = g_hmac_new(qcrypto_hmac_alg_map[alg],
|
||||||
|
@ -74,36 +71,31 @@ QCryptoHmac *qcrypto_hmac_new(QCryptoHashAlgorithm alg,
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
hmac->opaque = ctx;
|
return ctx;
|
||||||
return hmac;
|
|
||||||
|
|
||||||
error:
|
error:
|
||||||
g_free(ctx);
|
g_free(ctx);
|
||||||
g_free(hmac);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void qcrypto_hmac_free(QCryptoHmac *hmac)
|
static void
|
||||||
|
qcrypto_glib_hmac_ctx_free(QCryptoHmac *hmac)
|
||||||
{
|
{
|
||||||
QCryptoHmacGlib *ctx;
|
QCryptoHmacGlib *ctx;
|
||||||
|
|
||||||
if (!hmac) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx = hmac->opaque;
|
ctx = hmac->opaque;
|
||||||
g_hmac_unref(ctx->ghmac);
|
g_hmac_unref(ctx->ghmac);
|
||||||
|
|
||||||
g_free(ctx);
|
g_free(ctx);
|
||||||
g_free(hmac);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int qcrypto_hmac_bytesv(QCryptoHmac *hmac,
|
static int
|
||||||
const struct iovec *iov,
|
qcrypto_glib_hmac_bytesv(QCryptoHmac *hmac,
|
||||||
size_t niov,
|
const struct iovec *iov,
|
||||||
uint8_t **result,
|
size_t niov,
|
||||||
size_t *resultlen,
|
uint8_t **result,
|
||||||
Error **errp)
|
size_t *resultlen,
|
||||||
|
Error **errp)
|
||||||
{
|
{
|
||||||
QCryptoHmacGlib *ctx;
|
QCryptoHmacGlib *ctx;
|
||||||
int i, ret;
|
int i, ret;
|
||||||
|
@ -141,26 +133,33 @@ bool qcrypto_hmac_supports(QCryptoHashAlgorithm alg)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
QCryptoHmac *qcrypto_hmac_new(QCryptoHashAlgorithm alg,
|
void *qcrypto_hmac_ctx_new(QCryptoHashAlgorithm alg,
|
||||||
const uint8_t *key, size_t nkey,
|
const uint8_t *key, size_t nkey,
|
||||||
Error **errp)
|
Error **errp)
|
||||||
{
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void qcrypto_hmac_free(QCryptoHmac *hmac)
|
static void
|
||||||
|
qcrypto_glib_hmac_ctx_free(QCryptoHmac *hmac)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int qcrypto_hmac_bytesv(QCryptoHmac *hmac,
|
static int
|
||||||
const struct iovec *iov,
|
qcrypto_glib_hmac_bytesv(QCryptoHmac *hmac,
|
||||||
size_t niov,
|
const struct iovec *iov,
|
||||||
uint8_t **result,
|
size_t niov,
|
||||||
size_t *resultlen,
|
uint8_t **result,
|
||||||
Error **errp)
|
size_t *resultlen,
|
||||||
|
Error **errp)
|
||||||
{
|
{
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
QCryptoHmacDriver qcrypto_hmac_lib_driver = {
|
||||||
|
.hmac_bytesv = qcrypto_glib_hmac_bytesv,
|
||||||
|
.hmac_free = qcrypto_glib_hmac_ctx_free,
|
||||||
|
};
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
#include "qemu/osdep.h"
|
#include "qemu/osdep.h"
|
||||||
#include "qapi/error.h"
|
#include "qapi/error.h"
|
||||||
#include "crypto/hmac.h"
|
#include "crypto/hmac.h"
|
||||||
|
#include "hmacpriv.h"
|
||||||
#include <nettle/hmac.h>
|
#include <nettle/hmac.h>
|
||||||
|
|
||||||
typedef void (*qcrypto_nettle_hmac_setkey)(void *ctx,
|
typedef void (*qcrypto_nettle_hmac_setkey)(void *ctx,
|
||||||
|
@ -97,11 +98,10 @@ bool qcrypto_hmac_supports(QCryptoHashAlgorithm alg)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
QCryptoHmac *qcrypto_hmac_new(QCryptoHashAlgorithm alg,
|
void *qcrypto_hmac_ctx_new(QCryptoHashAlgorithm alg,
|
||||||
const uint8_t *key, size_t nkey,
|
const uint8_t *key, size_t nkey,
|
||||||
Error **errp)
|
Error **errp)
|
||||||
{
|
{
|
||||||
QCryptoHmac *hmac;
|
|
||||||
QCryptoHmacNettle *ctx;
|
QCryptoHmacNettle *ctx;
|
||||||
|
|
||||||
if (!qcrypto_hmac_supports(alg)) {
|
if (!qcrypto_hmac_supports(alg)) {
|
||||||
|
@ -110,38 +110,29 @@ QCryptoHmac *qcrypto_hmac_new(QCryptoHashAlgorithm alg,
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
hmac = g_new0(QCryptoHmac, 1);
|
|
||||||
hmac->alg = alg;
|
|
||||||
|
|
||||||
ctx = g_new0(QCryptoHmacNettle, 1);
|
ctx = g_new0(QCryptoHmacNettle, 1);
|
||||||
|
|
||||||
qcrypto_hmac_alg_map[alg].setkey(&ctx->u, nkey, key);
|
qcrypto_hmac_alg_map[alg].setkey(&ctx->u, nkey, key);
|
||||||
|
|
||||||
hmac->opaque = ctx;
|
return ctx;
|
||||||
|
|
||||||
return hmac;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void qcrypto_hmac_free(QCryptoHmac *hmac)
|
static void
|
||||||
|
qcrypto_nettle_hmac_ctx_free(QCryptoHmac *hmac)
|
||||||
{
|
{
|
||||||
QCryptoHmacNettle *ctx;
|
QCryptoHmacNettle *ctx;
|
||||||
|
|
||||||
if (!hmac) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx = hmac->opaque;
|
ctx = hmac->opaque;
|
||||||
|
|
||||||
g_free(ctx);
|
g_free(ctx);
|
||||||
g_free(hmac);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int qcrypto_hmac_bytesv(QCryptoHmac *hmac,
|
static int
|
||||||
const struct iovec *iov,
|
qcrypto_nettle_hmac_bytesv(QCryptoHmac *hmac,
|
||||||
size_t niov,
|
const struct iovec *iov,
|
||||||
uint8_t **result,
|
size_t niov,
|
||||||
size_t *resultlen,
|
uint8_t **result,
|
||||||
Error **errp)
|
size_t *resultlen,
|
||||||
|
Error **errp)
|
||||||
{
|
{
|
||||||
QCryptoHmacNettle *ctx;
|
QCryptoHmacNettle *ctx;
|
||||||
int i;
|
int i;
|
||||||
|
@ -173,3 +164,8 @@ int qcrypto_hmac_bytesv(QCryptoHmac *hmac,
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QCryptoHmacDriver qcrypto_hmac_lib_driver = {
|
||||||
|
.hmac_bytesv = qcrypto_nettle_hmac_bytesv,
|
||||||
|
.hmac_free = qcrypto_nettle_hmac_ctx_free,
|
||||||
|
};
|
||||||
|
|
|
@ -12,9 +12,22 @@
|
||||||
#include "qemu/osdep.h"
|
#include "qemu/osdep.h"
|
||||||
#include "qapi/error.h"
|
#include "qapi/error.h"
|
||||||
#include "crypto/hmac.h"
|
#include "crypto/hmac.h"
|
||||||
|
#include "hmacpriv.h"
|
||||||
|
|
||||||
static const char hex[] = "0123456789abcdef";
|
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,
|
int qcrypto_hmac_bytes(QCryptoHmac *hmac,
|
||||||
const char *buf,
|
const char *buf,
|
||||||
size_t len,
|
size_t len,
|
||||||
|
@ -70,3 +83,48 @@ int qcrypto_hmac_digest(QCryptoHmac *hmac,
|
||||||
|
|
||||||
return qcrypto_hmac_digestv(hmac, &iov, 1, digest, errp);
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -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
|
|
@ -80,6 +80,7 @@ struct QCryptoCipher {
|
||||||
QCryptoCipherAlgorithm alg;
|
QCryptoCipherAlgorithm alg;
|
||||||
QCryptoCipherMode mode;
|
QCryptoCipherMode mode;
|
||||||
void *opaque;
|
void *opaque;
|
||||||
|
void *driver;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -18,6 +18,7 @@ typedef struct QCryptoHmac QCryptoHmac;
|
||||||
struct QCryptoHmac {
|
struct QCryptoHmac {
|
||||||
QCryptoHashAlgorithm alg;
|
QCryptoHashAlgorithm alg;
|
||||||
void *opaque;
|
void *opaque;
|
||||||
|
void *driver;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
|
@ -1,4 +1,7 @@
|
||||||
atomic_add-bench
|
atomic_add-bench
|
||||||
|
benchmark-crypto-cipher
|
||||||
|
benchmark-crypto-hash
|
||||||
|
benchmark-crypto-hmac
|
||||||
check-qdict
|
check-qdict
|
||||||
check-qnum
|
check-qnum
|
||||||
check-qjson
|
check-qjson
|
||||||
|
|
|
@ -97,8 +97,11 @@ gcov-files-test-keyval-y = util/keyval.c
|
||||||
check-unit-y += tests/test-write-threshold$(EXESUF)
|
check-unit-y += tests/test-write-threshold$(EXESUF)
|
||||||
gcov-files-test-write-threshold-y = block/write-threshold.c
|
gcov-files-test-write-threshold-y = block/write-threshold.c
|
||||||
check-unit-y += tests/test-crypto-hash$(EXESUF)
|
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-unit-y += tests/test-crypto-hmac$(EXESUF)
|
||||||
|
check-speed-y += tests/benchmark-crypto-hmac$(EXESUF)
|
||||||
check-unit-y += tests/test-crypto-cipher$(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-y += tests/test-crypto-secret$(EXESUF)
|
||||||
check-unit-$(CONFIG_GNUTLS) += tests/test-crypto-tlscredsx509$(EXESUF)
|
check-unit-$(CONFIG_GNUTLS) += tests/test-crypto-tlscredsx509$(EXESUF)
|
||||||
check-unit-$(CONFIG_GNUTLS) += tests/test-crypto-tlssession$(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 \
|
test-qapi-obj-y = tests/test-qapi-visit.o tests/test-qapi-types.o \
|
||||||
tests/test-qapi-event.o tests/test-qmp-introspect.o \
|
tests/test-qapi-event.o tests/test-qmp-introspect.o \
|
||||||
$(test-qom-obj-y)
|
$(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-crypto-obj-y = $(crypto-obj-y) $(test-qom-obj-y)
|
||||||
test-io-obj-y = $(io-obj-y) $(test-crypto-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
|
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-bitops$(EXESUF): tests/test-bitops.o $(test-util-obj-y)
|
||||||
tests/test-bitcnt$(EXESUF): tests/test-bitcnt.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/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/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/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-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)
|
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-TARGET Run qtest tests for given target"
|
||||||
@echo " make check-qtest Run qtest tests"
|
@echo " make check-qtest Run qtest tests"
|
||||||
@echo " make check-unit Run qobject 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-qapi-schema Run QAPI schema tests"
|
||||||
@echo " make check-block Run block tests"
|
@echo " make check-block Run block tests"
|
||||||
@echo " make check-report.html Generates an HTML test report"
|
@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`; \
|
$(GCOV) $(GCOV_OPTIONS) $$f -o `dirname $$f`; \
|
||||||
done,)
|
done,)
|
||||||
|
|
||||||
.PHONY: $(patsubst %, check-%, $(check-unit-y))
|
.PHONY: $(patsubst %, check-%, $(check-unit-y) $(check-speed-y))
|
||||||
$(patsubst %, check-%, $(check-unit-y)): check-%: %
|
$(patsubst %, check-%, $(check-unit-y) $(check-speed-y)): check-%: %
|
||||||
$(if $(CONFIG_GCOV),@rm -f *.gcda */*.gcda */*/*.gcda */*/*/*.gcda,)
|
$(if $(CONFIG_GCOV),@rm -f *.gcda */*.gcda */*/*.gcda */*/*/*.gcda,)
|
||||||
$(call quiet-command, \
|
$(call quiet-command, \
|
||||||
MALLOC_PERTURB_=$${MALLOC_PERTURB_:-$$((RANDOM % 255 + 1))} \
|
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-qapi-schema: $(patsubst %,check-%, $(check-qapi-schema-y)) check-tests/qapi-schema/doc-good.texi
|
||||||
check-qtest: $(patsubst %,check-qtest-%, $(QTEST_TARGETS))
|
check-qtest: $(patsubst %,check-qtest-%, $(QTEST_TARGETS))
|
||||||
check-unit: $(patsubst %,check-%, $(check-unit-y))
|
check-unit: $(patsubst %,check-%, $(check-unit-y))
|
||||||
|
check-speed: $(patsubst %,check-%, $(check-speed-y))
|
||||||
check-block: $(patsubst %,check-%, $(check-block-y))
|
check-block: $(patsubst %,check-%, $(check-block-y))
|
||||||
check: check-qapi-schema check-unit check-qtest
|
check: check-qapi-schema check-unit check-qtest
|
||||||
check-clean:
|
check-clean:
|
||||||
|
|
|
@ -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();
|
||||||
|
}
|
|
@ -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();
|
||||||
|
}
|
|
@ -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();
|
||||||
|
}
|
Loading…
Reference in New Issue