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
37
configure
vendored
37
configure
vendored
@ -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
|
||||
|
@ -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
116
crypto/afalg.c
Normal 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
64
crypto/afalgpriv.h
Normal 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
226
crypto/cipher-afalg.c
Normal 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,
|
||||
};
|
@ -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,
|
||||
};
|
||||
|
@ -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,
|
||||
};
|
||||
|
@ -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,
|
||||
};
|
||||
|
@ -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
56
crypto/cipherpriv.h
Normal 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
214
crypto/hash-afalg.c
Normal 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,
|
||||
};
|
@ -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,
|
||||
};
|
||||
|
@ -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,
|
||||
};
|
||||
|
@ -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,
|
||||
};
|
||||
|
@ -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
39
crypto/hashpriv.h
Normal 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
|
@ -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,
|
||||
};
|
||||
|
@ -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,
|
||||
};
|
||||
|
@ -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,
|
||||
};
|
||||
|
@ -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
48
crypto/hmacpriv.h
Normal 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
|
@ -80,6 +80,7 @@ struct QCryptoCipher {
|
||||
QCryptoCipherAlgorithm alg;
|
||||
QCryptoCipherMode mode;
|
||||
void *opaque;
|
||||
void *driver;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -18,6 +18,7 @@ typedef struct QCryptoHmac QCryptoHmac;
|
||||
struct QCryptoHmac {
|
||||
QCryptoHashAlgorithm alg;
|
||||
void *opaque;
|
||||
void *driver;
|
||||
};
|
||||
|
||||
/**
|
3
tests/.gitignore
vendored
3
tests/.gitignore
vendored
@ -1,4 +1,7 @@
|
||||
atomic_add-bench
|
||||
benchmark-crypto-cipher
|
||||
benchmark-crypto-hash
|
||||
benchmark-crypto-hmac
|
||||
check-qdict
|
||||
check-qnum
|
||||
check-qjson
|
||||
|
@ -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:
|
||||
|
88
tests/benchmark-crypto-cipher.c
Normal file
88
tests/benchmark-crypto-cipher.c
Normal 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();
|
||||
}
|
67
tests/benchmark-crypto-hash.c
Normal file
67
tests/benchmark-crypto-hash.c
Normal 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();
|
||||
}
|
82
tests/benchmark-crypto-hmac.c
Normal file
82
tests/benchmark-crypto-hmac.c
Normal 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();
|
||||
}
|
Loading…
Reference in New Issue
Block a user