* [Qemu-devel] [PATCH RESEND 1/6] configure: add CONFIG_GCRYPT/NETTLE_AEAD item
2017-01-05 0:49 [Qemu-devel] [PATCH RESEND 0/6] crypto:add AEAD algorithms support Longpeng(Mike)
@ 2017-01-05 0:49 ` Longpeng(Mike)
2017-01-05 0:49 ` [Qemu-devel] [PATCH RESEND 2/6] crypto: add AEAD algorithms framework Longpeng(Mike)
` (4 subsequent siblings)
5 siblings, 0 replies; 10+ messages in thread
From: Longpeng(Mike) @ 2017-01-05 0:49 UTC (permalink / raw)
To: berrange; +Cc: wu.wubin, jianjay.zhou, arei.gonglei, qemu-devel, Longpeng(Mike)
This item will be used for gcrypt/nettle backed AEAD algorithms.
It's hardly to decide which version of gcrypt/nettle started
supporting AEAD algorithms, but it's easily for us to making
a test in configure to know whether current gcrypt/nettle
support AEAD.
Signed-off-by: Longpeng(Mike) <longpeng2@huawei.com>
---
configure | 36 ++++++++++++++++++++++++++++++++++++
1 file changed, 36 insertions(+)
diff --git a/configure b/configure
index 218df87..14f558c 100755
--- a/configure
+++ b/configure
@@ -309,8 +309,10 @@ tls_priority="NORMAL"
gnutls=""
gnutls_rnd=""
nettle=""
+nettle_aead="no"
nettle_kdf="no"
gcrypt=""
+gcrypt_aead="no"
gcrypt_hmac="no"
gcrypt_kdf="no"
vte=""
@@ -2429,6 +2431,19 @@ EOF
if compile_prog "$gcrypt_cflags" "$gcrypt_libs" ; then
gcrypt_hmac=yes
fi
+
+ cat > $TMPC << EOF
+#include <gcrypt.h>
+int main(void) {
+ gcry_cipher_hd_t handle;
+ gcry_cipher_open(&handle, 0, 0, 0);
+ gcry_cipher_authenticate(handle, NULL, 0);
+ return 0;
+}
+EOF
+ if compile_prog "$gcrypt_cflags" "$gcrypt_libs" ; then
+ gcrypt_aead=yes
+ fi
else
if test "$gcrypt" = "yes"; then
feature_not_found "gcrypt" "Install gcrypt devel"
@@ -2460,6 +2475,21 @@ EOF
if compile_prog "$nettle_cflags" "$nettle_libs" ; then
nettle_kdf=yes
fi
+
+ cat > $TMPC << EOF
+#include <stddef.h>
+#include <nettle/aes.h>
+#include <nettle/ccm.h>
+#include <nettle/gcm.h>
+int main(void) {
+ ccm_aes128_encrypt(NULL, 0, NULL, NULL);
+ gcm_aes128_encrypt(NULL, 0, NULL, NULL);
+ return 0;
+}
+EOF
+ if compile_prog "$nettle_cflags" "$nettle_libs" ; then
+ nettle_aead=yes
+ fi
else
if test "$nettle" = "yes"; then
feature_not_found "nettle" "Install nettle devel"
@@ -5399,6 +5429,9 @@ if test "$gnutls_rnd" = "yes" ; then
fi
if test "$gcrypt" = "yes" ; then
echo "CONFIG_GCRYPT=y" >> $config_host_mak
+ if test "$gcrypt_aead" = "yes" ; then
+ echo "CONFIG_GCRYPT_AEAD=y" >> $config_host_mak
+ fi
if test "$gcrypt_hmac" = "yes" ; then
echo "CONFIG_GCRYPT_HMAC=y" >> $config_host_mak
fi
@@ -5409,6 +5442,9 @@ fi
if test "$nettle" = "yes" ; then
echo "CONFIG_NETTLE=y" >> $config_host_mak
echo "CONFIG_NETTLE_VERSION_MAJOR=${nettle_version%%.*}" >> $config_host_mak
+ if test "$nettle_aead" = "yes" ; then
+ echo "CONFIG_NETTLE_AEAD=y" >> $config_host_mak
+ fi
if test "$nettle_kdf" = "yes" ; then
echo "CONFIG_NETTLE_KDF=y" >> $config_host_mak
fi
--
1.8.3.1
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [Qemu-devel] [PATCH RESEND 2/6] crypto: add AEAD algorithms framework
2017-01-05 0:49 [Qemu-devel] [PATCH RESEND 0/6] crypto:add AEAD algorithms support Longpeng(Mike)
2017-01-05 0:49 ` [Qemu-devel] [PATCH RESEND 1/6] configure: add CONFIG_GCRYPT/NETTLE_AEAD item Longpeng(Mike)
@ 2017-01-05 0:49 ` Longpeng(Mike)
2017-01-06 11:28 ` Daniel P. Berrange
2017-01-05 0:49 ` [Qemu-devel] [PATCH RESEND 3/6] crypto: implement nettle-backed AEAD algorithms Longpeng(Mike)
` (3 subsequent siblings)
5 siblings, 1 reply; 10+ messages in thread
From: Longpeng(Mike) @ 2017-01-05 0:49 UTC (permalink / raw)
To: berrange; +Cc: wu.wubin, jianjay.zhou, arei.gonglei, qemu-devel, Longpeng(Mike)
This patch introduce AEAD algorithms framework.
We currently plan to support six basic AEAD algorithms,
ccm(aes128/192/256) and gcm(aes128/192/256), so we need
to add ccm/gcm mode in qapi/crypto.json simultaneously.
Signed-off-by: Longpeng(Mike) <longpeng2@huawei.com>
---
crypto/Makefile.objs | 3 +
crypto/aead-gcrypt.c | 70 ++++++++++++++++++++
crypto/aead-nettle.c | 72 +++++++++++++++++++++
crypto/aead.c | 84 ++++++++++++++++++++++++
crypto/aead.h | 180 +++++++++++++++++++++++++++++++++++++++++++++++++++
qapi/crypto.json | 4 +-
6 files changed, 412 insertions(+), 1 deletion(-)
create mode 100644 crypto/aead-gcrypt.c
create mode 100644 crypto/aead-nettle.c
create mode 100644 crypto/aead.c
create mode 100644 crypto/aead.h
diff --git a/crypto/Makefile.objs b/crypto/Makefile.objs
index 1f749f2..2c5243d 100644
--- a/crypto/Makefile.objs
+++ b/crypto/Makefile.objs
@@ -3,6 +3,9 @@ crypto-obj-y += hash.o
crypto-obj-$(CONFIG_NETTLE) += hash-nettle.o
crypto-obj-$(if $(CONFIG_NETTLE),n,$(CONFIG_GCRYPT)) += hash-gcrypt.o
crypto-obj-$(if $(CONFIG_NETTLE),n,$(if $(CONFIG_GCRYPT),n,y)) += hash-glib.o
+crypto-obj-y += aead.o
+crypto-obj-$(CONFIG_NETTLE_AEAD) += aead-nettle.o
+crypto-obj-$(if $(CONFIG_NETTLE_AEAD),n,$(CONFIG_GCRYPT_AEAD)) += aead-gcrypt.o
crypto-obj-y += hmac.o
crypto-obj-$(CONFIG_NETTLE) += hmac-nettle.o
crypto-obj-$(CONFIG_GCRYPT_HMAC) += hmac-gcrypt.o
diff --git a/crypto/aead-gcrypt.c b/crypto/aead-gcrypt.c
new file mode 100644
index 0000000..9465518
--- /dev/null
+++ b/crypto/aead-gcrypt.c
@@ -0,0 +1,70 @@
+/*
+ * QEMU Crypto aead algorithms (based on libgcrypt)
+ *
+ * Copyright (c) 2016 HUAWEI TECHNOLOGIES CO., LTD.
+ *
+ * Authors:
+ * Longpeng(Mike) <longpeng2@huawei.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or
+ * (at your option) any later version. See the COPYING file in the
+ * top-level directory.
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "crypto/aead.h"
+#include <gcrypt.h>
+
+QCryptoAead *qcrypto_aead_new(QCryptoCipherAlgorithm alg,
+ QCryptoCipherMode mode,
+ const uint8_t *key, size_t nkey,
+ Error **errp)
+{
+ return NULL;
+}
+
+void qcrypto_aead_free(QCryptoAead *aead)
+{
+ return;
+}
+
+int qcrypto_aead_set_nonce(QCryptoAead *aead,
+ const uint8_t *nonce, size_t nonce_len,
+ size_t aad_len, size_t in_len,
+ size_t tag_len,
+ Error **errp)
+{
+ return -1;
+}
+
+int qcrypto_aead_authenticate(QCryptoAead *aead,
+ const uint8_t *aad, size_t aad_len,
+ Error **errp)
+{
+ return -1;
+}
+
+int qcrypto_aead_encrypt(QCryptoAead *aead,
+ const uint8_t *in, size_t in_len,
+ uint8_t *out, size_t out_len,
+ Error **errp)
+{
+ return -1;
+}
+
+int qcrypto_aead_decrypt(QCryptoAead *aead,
+ const uint8_t *in, size_t in_len,
+ uint8_t *out, size_t out_len,
+ Error **errp)
+{
+ return -1;
+}
+
+int qcrypto_aead_get_tag(QCryptoAead *aead,
+ uint8_t *tag, size_t tag_len,
+ Error **errp)
+{
+ return -1;
+}
diff --git a/crypto/aead-nettle.c b/crypto/aead-nettle.c
new file mode 100644
index 0000000..cfb9d33
--- /dev/null
+++ b/crypto/aead-nettle.c
@@ -0,0 +1,72 @@
+/*
+ * QEMU Crypto aead algorithms (based on nettle)
+ *
+ * Copyright (c) 2016 HUAWEI TECHNOLOGIES CO., LTD.
+ *
+ * Authors:
+ * Longpeng(Mike) <longpeng2@huawei.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or
+ * (at your option) any later version. See the COPYING file in the
+ * top-level directory.
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "crypto/aead.h"
+#include <nettle/aes.h>
+#include <nettle/ccm.h>
+#include <nettle/gcm.h>
+
+QCryptoAead *qcrypto_aead_new(QCryptoCipherAlgorithm alg,
+ QCryptoCipherMode mode,
+ const uint8_t *key, size_t nkey,
+ Error **errp)
+{
+ return NULL;
+}
+
+void qcrypto_aead_free(QCryptoAead *aead)
+{
+ return;
+}
+
+int qcrypto_aead_set_nonce(QCryptoAead *aead,
+ const uint8_t *nonce, size_t nonce_len,
+ size_t aad_len, size_t in_len,
+ size_t tag_len,
+ Error **errp)
+{
+ return -1;
+}
+
+int qcrypto_aead_authenticate(QCryptoAead *aead,
+ const uint8_t *aad, size_t aad_len,
+ Error **errp)
+{
+ return -1;
+}
+
+int qcrypto_aead_encrypt(QCryptoAead *aead,
+ const uint8_t *in, size_t in_len,
+ uint8_t *out, size_t out_len,
+ Error **errp)
+{
+ return -1;
+}
+
+int qcrypto_aead_decrypt(QCryptoAead *aead,
+ const uint8_t *in, size_t in_len,
+ uint8_t *out, size_t out_len,
+ Error **errp)
+{
+ return -1;
+}
+
+int qcrypto_aead_get_tag(QCryptoAead *aead,
+ uint8_t *tag, size_t tag_len,
+ Error **errp)
+{
+ return -1;
+}
diff --git a/crypto/aead.c b/crypto/aead.c
new file mode 100644
index 0000000..47639b7
--- /dev/null
+++ b/crypto/aead.c
@@ -0,0 +1,84 @@
+/*
+ * QEMU Crypto aead algorithms
+ *
+ * Copyright (c) 2016 HUAWEI TECHNOLOGIES CO., LTD.
+ *
+ * Authors:
+ * Longpeng(Mike) <longpeng2@huawei.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or
+ * (at your option) any later version. See the COPYING file in the
+ * top-level directory.
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "crypto/aead.h"
+
+bool qcrypto_aead_supports(QCryptoCipherAlgorithm alg,
+ QCryptoCipherMode mode)
+{
+ return false;
+}
+
+size_t qcrypto_aead_get_key_len(QCryptoCipherAlgorithm alg)
+{
+ return -1;
+}
+
+#if !defined(CONFIG_NETTLE_AEAD) && !defined(CONFIG_GCRYPT_AEAD)
+
+QCryptoAead *qcrypto_aead_new(QCryptoCipherAlgorithm alg,
+ QCryptoCipherMode mode,
+ const uint8_t *key, size_t nkey,
+ Error **errp)
+{
+ return NULL;
+}
+
+void qcrypto_aead_free(QCryptoAead *aead)
+{
+ return;
+}
+
+int qcrypto_aead_set_nonce(QCryptoAead *aead,
+ const uint8_t *nonce, size_t nonce_len,
+ size_t aad_len, size_t in_len,
+ size_t tag_len,
+ Error **errp)
+{
+ return -1;
+}
+
+int qcrypto_aead_authenticate(QCryptoAead *aead,
+ const uint8_t *aad, size_t aad_len,
+ Error **errp)
+{
+ return -1;
+}
+
+int qcrypto_aead_encrypt(QCryptoAead *aead,
+ const uint8_t *in, size_t in_len,
+ uint8_t *out, size_t out_len,
+ Error **errp)
+{
+ return -1;
+}
+
+int qcrypto_aead_decrypt(QCryptoAead *aead,
+ const uint8_t *in, size_t in_len,
+ uint8_t *out, size_t out_len,
+ Error **errp)
+{
+ return -1;
+}
+
+int qcrypto_aead_get_tag(QCryptoAead *aead,
+ uint8_t *tag, size_t tag_len,
+ Error **errp)
+{
+ return -1;
+}
+
+#endif
diff --git a/crypto/aead.h b/crypto/aead.h
new file mode 100644
index 0000000..a868d0a
--- /dev/null
+++ b/crypto/aead.h
@@ -0,0 +1,180 @@
+/*
+ * QEMU Crypto aead algorithms
+ *
+ * Copyright (c) 2016 HUAWEI TECHNOLOGIES CO., LTD.
+ *
+ * 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_AEAD_H
+#define QCRYPTO_AEAD_H
+
+#include "qapi-types.h"
+
+/**
+ * We currently only support six basic aead algorithms,
+ * ccm(aes128/192/256) and gcm(aes128/192/256), so for
+ * some global arrays, like qcrypto_aead_alg_map, we use
+ * AEAD_ALG__MAX/AEAD_MODE__MAX as their size instead of
+ * CIPHER_ALG__MAX/CIPHER_MODE__MAX, in order to save memory.
+ *
+ * Note: this means that we must make sure ccm,gcm,ecb at
+ * the first three places in QCryptoCipherMode, and aes128,
+ * aes192,aes256,des-rfb at the first four places in
+ * QCryptoCipherAlgorithm.
+ */
+#define QCRYPTO_AEAD_ALG__MAX QCRYPTO_CIPHER_ALG_DES_RFB
+#define QCRYPTO_AEAD_MODE__MAX QCRYPTO_CIPHER_MODE_ECB
+
+typedef struct QCryptoAead QCryptoAead;
+struct QCryptoAead {
+ QCryptoCipherAlgorithm alg;
+ QCryptoCipherMode mode;
+ void *opaque;
+};
+
+/**
+ * qcrypto_aead_supports:
+ * @alg: the cipher algorithm
+ * @mode: the cipher mode
+ *
+ * Determine if @alg hmac algorithm is supported by
+ * the current configured build
+ *
+ * Returns:
+ * true if the algorithm is supported, false otherwise
+ */
+bool qcrypto_aead_supports(QCryptoCipherAlgorithm alg,
+ QCryptoCipherMode mode);
+
+/**
+ * qcrypto_aead_get_key_len:
+ * @alg: the cipher algorithm
+ *
+ * Get the required key size in bytes
+ *
+ * Returns: the key size in bytes
+ */
+size_t qcrypto_aead_get_key_len(QCryptoCipherAlgorithm alg);
+
+/**
+ * qcrypto_aead_new:
+ * @alg: the cipher algorithm
+ * @mode: the cipher usage mode
+ * @key: the private key bytes
+ * @nkey: the length of @key
+ * @errp: pointer to a NULL-initialized error object
+ *
+ * Creates a new aead object for encrypting/decrypting
+ * data with the algorithm @alg in the usage mode @mode.
+ *
+ * The returned aead object must be released with
+ * qcrypto_aead_free() when no longer required
+ *
+ * Returns:
+ * a new aead object, or NULL on error
+ */
+QCryptoAead *qcrypto_aead_new(QCryptoCipherAlgorithm alg,
+ QCryptoCipherMode mode,
+ const uint8_t *key, size_t nkey,
+ Error **errp);
+
+/**
+ * qcrypto_aead_free:
+ * @aead: the aead object
+ *
+ * Release the memory associated with @aead that
+ * was previously allocated by qcrypto_aead_new()
+ */
+void qcrypto_aead_free(QCryptoAead *aead);
+
+/**
+ * qcrypto_aead_set_nonce:
+ * @aead: the aead object
+ * @nonce: the nonce/iv data
+ * @nonce_len: the length of @nonce
+ * @aad_len: the length of associated data
+ * @in_len: the length of plain data
+ * @tag_len: the length of authentication tag
+ *
+ * Set the aead object's nonce/iv
+ *
+ * Returns:
+ * 0 if success, or -1 on error
+ */
+int qcrypto_aead_set_nonce(QCryptoAead *aead,
+ const uint8_t *nonce, size_t nonce_len,
+ size_t aad_len, size_t in_len,
+ size_t tag_len,
+ Error **errp);
+
+/**
+ * qcrypto_aead_authenticate:
+ * @aead: the aead object
+ * @aad: associated data
+ * @aad_len: the length of @add
+ *
+ * Set associated data to be authenticated
+ *
+ * Returns:
+ * 0 if success, or -1 on error
+ */
+int qcrypto_aead_authenticate(QCryptoAead *aead,
+ const uint8_t *aad, size_t aad_len,
+ Error **errp);
+
+/**
+ * qcrypto_aead_encrypt:
+ * @aead: the aead object
+ * @in: the plain data
+ * @in_len: the length of @in
+ * @out: the cipher data buffer
+ * @out_len: the length of @out
+ *
+ * Encrypts the input data
+ *
+ * Returns:
+ * 0 if success, or -1 on error
+ */
+int qcrypto_aead_encrypt(QCryptoAead *aead,
+ const uint8_t *in, size_t in_len,
+ uint8_t *out, size_t out_len,
+ Error **errp);
+
+/**
+ * qcrypto_aead_decrypt:
+ * @aead: the aead object
+ * @in: the cipher data
+ * @in_len: the length of @in
+ * @out: the plain data buffer
+ * @out_len: the length of @out
+ *
+ * Decrypts the input data
+ *
+ * Returns:
+ * 0 if success, or -1 on error
+ */
+int qcrypto_aead_decrypt(QCryptoAead *aead,
+ const uint8_t *in, size_t in_len,
+ uint8_t *out, size_t out_len,
+ Error **errp);
+
+/**
+ * qcrypto_aead_get_tag:
+ * @aead: the aead object
+ * @tag: the tag buffer
+ * @tag_len: the length of @tag
+ *
+ * Extracts the authentication tag
+ *
+ * Returns:
+ * 0 if success, or -1 on error
+ */
+int qcrypto_aead_get_tag(QCryptoAead *aead,
+ uint8_t *tag, size_t tag_len,
+ Error **errp);
+
+#endif
diff --git a/qapi/crypto.json b/qapi/crypto.json
index f4fd93b..edb2962 100644
--- a/qapi/crypto.json
+++ b/qapi/crypto.json
@@ -87,6 +87,8 @@
#
# The supported modes for content encryption ciphers
#
+# @ccm: Counter with CBC-MAC Mode (Since 2.9)
+# @gcm: Galois Counter Mode (Since 2.9)
# @ecb: Electronic Code Book
# @cbc: Cipher Block Chaining
# @xts: XEX with tweaked code book and ciphertext stealing
@@ -95,7 +97,7 @@
##
{ 'enum': 'QCryptoCipherMode',
'prefix': 'QCRYPTO_CIPHER_MODE',
- 'data': ['ecb', 'cbc', 'xts', 'ctr']}
+ 'data': ['ccm', 'gcm', 'ecb', 'cbc', 'xts', 'ctr']}
##
--
1.8.3.1
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [Qemu-devel] [PATCH RESEND 2/6] crypto: add AEAD algorithms framework
2017-01-05 0:49 ` [Qemu-devel] [PATCH RESEND 2/6] crypto: add AEAD algorithms framework Longpeng(Mike)
@ 2017-01-06 11:28 ` Daniel P. Berrange
2017-01-07 7:33 ` Longpeng (Mike)
0 siblings, 1 reply; 10+ messages in thread
From: Daniel P. Berrange @ 2017-01-06 11:28 UTC (permalink / raw)
To: Longpeng(Mike); +Cc: wu.wubin, jianjay.zhou, arei.gonglei, qemu-devel
On Thu, Jan 05, 2017 at 08:49:37AM +0800, Longpeng(Mike) wrote:
> This patch introduce AEAD algorithms framework.
So AEAD is essentially just encryption with extra metadata on
input and output stages. As such I don't think this should be
implemented via new objects in QEMU.
Instead, we should add the extra APIs to the existing
cipher.{c,h} file.
You've only implemented AES support here, so the code duplication
is not obvious, but if we were to extend AEAD to other algorithms
we'd see alot of duplication with the way you've done things.
So....
> +int qcrypto_aead_set_nonce(QCryptoAead *aead,
> + const uint8_t *nonce, size_t nonce_len,
> + size_t aad_len, size_t in_len,
> + size_t tag_len,
> + Error **errp);
> +int qcrypto_aead_authenticate(QCryptoAead *aead,
> + const uint8_t *aad, size_t aad_len,
> + Error **errp);
> +
> +int qcrypto_aead_get_tag(QCryptoAead *aead,
> + uint8_t *tag, size_t tag_len,
> + Error **errp);
> +
Just add these three methods to cipher.h instead
> diff --git a/qapi/crypto.json b/qapi/crypto.json
> index f4fd93b..edb2962 100644
> --- a/qapi/crypto.json
> +++ b/qapi/crypto.json
> @@ -87,6 +87,8 @@
> #
> # The supported modes for content encryption ciphers
> #
> +# @ccm: Counter with CBC-MAC Mode (Since 2.9)
> +# @gcm: Galois Counter Mode (Since 2.9)
> # @ecb: Electronic Code Book
> # @cbc: Cipher Block Chaining
> # @xts: XEX with tweaked code book and ciphertext stealing
> @@ -95,7 +97,7 @@
> ##
> { 'enum': 'QCryptoCipherMode',
> 'prefix': 'QCRYPTO_CIPHER_MODE',
> - 'data': ['ecb', 'cbc', 'xts', 'ctr']}
> + 'data': ['ccm', 'gcm', 'ecb', 'cbc', 'xts', 'ctr']}
This is fine.
Regards,
Daniel
--
|: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :|
|: http://libvirt.org -o- http://virt-manager.org :|
|: http://entangle-photo.org -o- http://search.cpan.org/~danberr/ :|
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [Qemu-devel] [PATCH RESEND 2/6] crypto: add AEAD algorithms framework
2017-01-06 11:28 ` Daniel P. Berrange
@ 2017-01-07 7:33 ` Longpeng (Mike)
0 siblings, 0 replies; 10+ messages in thread
From: Longpeng (Mike) @ 2017-01-07 7:33 UTC (permalink / raw)
To: Daniel P. Berrange; +Cc: wu.wubin, jianjay.zhou, arei.gonglei, qemu-devel
Hi Daniel,
On 2017/1/6 19:28, Daniel P. Berrange wrote:
> On Thu, Jan 05, 2017 at 08:49:37AM +0800, Longpeng(Mike) wrote:
>> This patch introduce AEAD algorithms framework.
>
> So AEAD is essentially just encryption with extra metadata on
> input and output stages. As such I don't think this should be
> implemented via new objects in QEMU.
>
> Instead, we should add the extra APIs to the existing
> cipher.{c,h} file.
>
> You've only implemented AES support here, so the code duplication
> is not obvious, but if we were to extend AEAD to other algorithms
> we'd see alot of duplication with the way you've done things.
>
> So....
>
All right, I will rework this recently. :)
>> ......
>> - 'data': ['ecb', 'cbc', 'xts', 'ctr']}
>> + 'data': ['ccm', 'gcm', 'ecb', 'cbc', 'xts', 'ctr']}
>
> This is fine.
>
> Regards,
> Daniel
--
Regards,
Longpeng(Mike)
^ permalink raw reply [flat|nested] 10+ messages in thread
* [Qemu-devel] [PATCH RESEND 3/6] crypto: implement nettle-backed AEAD algorithms
2017-01-05 0:49 [Qemu-devel] [PATCH RESEND 0/6] crypto:add AEAD algorithms support Longpeng(Mike)
2017-01-05 0:49 ` [Qemu-devel] [PATCH RESEND 1/6] configure: add CONFIG_GCRYPT/NETTLE_AEAD item Longpeng(Mike)
2017-01-05 0:49 ` [Qemu-devel] [PATCH RESEND 2/6] crypto: add AEAD algorithms framework Longpeng(Mike)
@ 2017-01-05 0:49 ` Longpeng(Mike)
2017-01-05 0:49 ` [Qemu-devel] [PATCH RESEND 4/6] crypto: implement gcrypt-backed " Longpeng(Mike)
` (2 subsequent siblings)
5 siblings, 0 replies; 10+ messages in thread
From: Longpeng(Mike) @ 2017-01-05 0:49 UTC (permalink / raw)
To: berrange; +Cc: wu.wubin, jianjay.zhou, arei.gonglei, qemu-devel, Longpeng(Mike)
This patch add nettle-backed AEAD algorithms
Signed-off-by: Longpeng(Mike) <longpeng2@huawei.com>
---
crypto/aead-nettle.c | 174 ++++++++++++++++++++++++++++++++++++++++++++++++---
1 file changed, 167 insertions(+), 7 deletions(-)
diff --git a/crypto/aead-nettle.c b/crypto/aead-nettle.c
index cfb9d33..7a2296d 100644
--- a/crypto/aead-nettle.c
+++ b/crypto/aead-nettle.c
@@ -19,17 +19,124 @@
#include <nettle/ccm.h>
#include <nettle/gcm.h>
+typedef void (*qcrypto_nettle_aead_setkey)(void *ctx,
+ const uint8_t *key);
+
+typedef void (*qcrypto_nettle_aead_setiv)(void *ctx,
+ size_t length, const uint8_t *iv);
+
+typedef void (*qcrypto_nettle_aead_setnonce)(void *ctx,
+ size_t length, const uint8_t *nonce,
+ size_t authlen, size_t msglen, size_t taglen);
+
+typedef void (*qcrypto_nettle_aead_update)(void *ctx,
+ size_t length, const uint8_t *data);
+
+typedef void (*qcrypto_nettle_aead_encrypt)(void *ctx,
+ size_t length, uint8_t *dst, const uint8_t *src);
+
+typedef void (*qcrypto_nettle_aead_decrypt)(void *ctx,
+ size_t length, uint8_t *dst, const uint8_t *src);
+
+typedef void (*qcrypto_nettle_aead_digest)(void *ctx,
+ size_t length, uint8_t *digest);
+
+#define NETTLE_AEAD_SET_CCM_FN(alg) { \
+ .setkey = (qcrypto_nettle_aead_setkey)ccm_##alg##_set_key, \
+ .u_op.setnonce = (qcrypto_nettle_aead_setnonce)ccm_##alg##_set_nonce, \
+ .update = (qcrypto_nettle_aead_update)ccm_##alg##_update, \
+ .encrypt = (qcrypto_nettle_aead_encrypt)ccm_##alg##_encrypt, \
+ .decrypt = (qcrypto_nettle_aead_decrypt)ccm_##alg##_decrypt, \
+ .digest = (qcrypto_nettle_aead_digest)ccm_##alg##_digest, \
+}
+
+#define NETTLE_AEAD_SET_GCM_FN(alg) { \
+ .setkey = (qcrypto_nettle_aead_setkey)gcm_##alg##_set_key, \
+ .u_op.setiv = (qcrypto_nettle_aead_setiv)gcm_##alg##_set_iv, \
+ .update = (qcrypto_nettle_aead_update)gcm_##alg##_update, \
+ .encrypt = (qcrypto_nettle_aead_encrypt)gcm_##alg##_encrypt, \
+ .decrypt = (qcrypto_nettle_aead_decrypt)gcm_##alg##_decrypt, \
+ .digest = (qcrypto_nettle_aead_digest)gcm_##alg##_digest, \
+}
+
+static struct qcrypto_nettle_aead_alg {
+ qcrypto_nettle_aead_setkey setkey;
+ union {
+ qcrypto_nettle_aead_setnonce setnonce;
+ qcrypto_nettle_aead_setiv setiv;
+ } u_op;
+ qcrypto_nettle_aead_update update;
+ qcrypto_nettle_aead_encrypt encrypt;
+ qcrypto_nettle_aead_decrypt decrypt;
+ qcrypto_nettle_aead_digest digest;
+} qcrypto_aead_alg_map[][QCRYPTO_AEAD_ALG__MAX] = {
+ {
+ [QCRYPTO_CIPHER_ALG_AES_128] = NETTLE_AEAD_SET_CCM_FN(aes128),
+ [QCRYPTO_CIPHER_ALG_AES_192] = NETTLE_AEAD_SET_CCM_FN(aes192),
+ [QCRYPTO_CIPHER_ALG_AES_256] = NETTLE_AEAD_SET_CCM_FN(aes256),
+ },
+ {
+ [QCRYPTO_CIPHER_ALG_AES_128] = NETTLE_AEAD_SET_GCM_FN(aes128),
+ [QCRYPTO_CIPHER_ALG_AES_192] = NETTLE_AEAD_SET_GCM_FN(aes192),
+ [QCRYPTO_CIPHER_ALG_AES_256] = NETTLE_AEAD_SET_GCM_FN(aes256),
+ }
+};
+
+typedef struct QCryptoAeadNettle QCryptoAeadNettle;
+struct QCryptoAeadNettle {
+ union qcrypto_nettle_aead_ctx {
+ struct ccm_aes128_ctx c_aes128_ctx;
+ struct ccm_aes192_ctx c_aes192_ctx;
+ struct ccm_aes256_ctx c_aes256_ctx;
+ struct gcm_aes128_ctx g_aes128_ctx;
+ struct gcm_aes192_ctx g_aes192_ctx;
+ struct gcm_aes256_ctx g_aes256_ctx;
+ } u;
+};
+
QCryptoAead *qcrypto_aead_new(QCryptoCipherAlgorithm alg,
QCryptoCipherMode mode,
const uint8_t *key, size_t nkey,
Error **errp)
{
- return NULL;
+ QCryptoAead *aead;
+ QCryptoAeadNettle *ctx;
+
+ if (!qcrypto_aead_supports(alg, mode)) {
+ return NULL;
+ }
+
+ if (nkey != qcrypto_aead_get_key_len(alg)) {
+ error_setg(errp, "Cipher key length %zu is invalid",
+ nkey);
+ return NULL;
+ }
+
+ aead = g_new0(QCryptoAead, 1);
+ aead->alg = alg;
+ aead->mode = mode;
+
+ ctx = g_new0(QCryptoAeadNettle, 1);
+
+ qcrypto_aead_alg_map[mode][alg].setkey(&ctx->u, key);
+
+ aead->opaque = ctx;
+
+ return aead;
}
void qcrypto_aead_free(QCryptoAead *aead)
{
- return;
+ QCryptoAeadNettle *ctx;
+
+ if (!aead) {
+ return;
+ }
+
+ ctx = aead->opaque;
+
+ g_free(ctx);
+ g_free(aead);
}
int qcrypto_aead_set_nonce(QCryptoAead *aead,
@@ -38,14 +145,43 @@ int qcrypto_aead_set_nonce(QCryptoAead *aead,
size_t tag_len,
Error **errp)
{
- return -1;
+ QCryptoAeadNettle *ctx;
+ struct qcrypto_nettle_aead_alg *aead_ops;
+
+ ctx = (QCryptoAeadNettle *)aead->opaque;
+
+ switch (aead->mode) {
+ case QCRYPTO_CIPHER_MODE_CCM:
+ aead_ops = &qcrypto_aead_alg_map[aead->mode][aead->alg];
+ aead_ops->u_op.setnonce(&ctx->u, nonce_len, nonce, aad_len,
+ in_len, tag_len);
+ break;
+ case QCRYPTO_CIPHER_MODE_GCM:
+ aead_ops = &qcrypto_aead_alg_map[aead->mode][aead->alg];
+ aead_ops->u_op.setiv(&ctx->u, nonce_len, nonce);
+ break;
+ default:
+ error_setg(errp, "Unsupported AEAD mode: %d",
+ aead->mode);
+ return -1;
+ }
+
+ return 0;
}
int qcrypto_aead_authenticate(QCryptoAead *aead,
const uint8_t *aad, size_t aad_len,
Error **errp)
{
- return -1;
+ QCryptoAeadNettle *ctx;
+ struct qcrypto_nettle_aead_alg *aead_ops;
+
+ ctx = (QCryptoAeadNettle *)aead->opaque;
+ aead_ops = &qcrypto_aead_alg_map[aead->mode][aead->alg];
+
+ aead_ops->update(&ctx->u, aad_len, aad);
+
+ return 0;
}
int qcrypto_aead_encrypt(QCryptoAead *aead,
@@ -53,7 +189,15 @@ int qcrypto_aead_encrypt(QCryptoAead *aead,
uint8_t *out, size_t out_len,
Error **errp)
{
- return -1;
+ QCryptoAeadNettle *ctx;
+ struct qcrypto_nettle_aead_alg *aead_ops;
+
+ ctx = (QCryptoAeadNettle *)aead->opaque;
+ aead_ops = &qcrypto_aead_alg_map[aead->mode][aead->alg];
+
+ aead_ops->encrypt(&ctx->u, in_len, out, in);
+
+ return 0;
}
int qcrypto_aead_decrypt(QCryptoAead *aead,
@@ -61,12 +205,28 @@ int qcrypto_aead_decrypt(QCryptoAead *aead,
uint8_t *out, size_t out_len,
Error **errp)
{
- return -1;
+ QCryptoAeadNettle *ctx;
+ struct qcrypto_nettle_aead_alg *aead_ops;
+
+ ctx = (QCryptoAeadNettle *)aead->opaque;
+ aead_ops = &qcrypto_aead_alg_map[aead->mode][aead->alg];
+
+ aead_ops->decrypt(&ctx->u, in_len, out, in);
+
+ return 0;
}
int qcrypto_aead_get_tag(QCryptoAead *aead,
uint8_t *tag, size_t tag_len,
Error **errp)
{
- return -1;
+ QCryptoAeadNettle *ctx;
+ struct qcrypto_nettle_aead_alg *aead_ops;
+
+ ctx = (QCryptoAeadNettle *)aead->opaque;
+ aead_ops = &qcrypto_aead_alg_map[aead->mode][aead->alg];
+
+ aead_ops->digest(&ctx->u, tag_len, tag);
+
+ return 0;
}
--
1.8.3.1
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [Qemu-devel] [PATCH RESEND 4/6] crypto: implement gcrypt-backed AEAD algorithms
2017-01-05 0:49 [Qemu-devel] [PATCH RESEND 0/6] crypto:add AEAD algorithms support Longpeng(Mike)
` (2 preceding siblings ...)
2017-01-05 0:49 ` [Qemu-devel] [PATCH RESEND 3/6] crypto: implement nettle-backed AEAD algorithms Longpeng(Mike)
@ 2017-01-05 0:49 ` Longpeng(Mike)
2017-01-05 0:49 ` [Qemu-devel] [PATCH RESEND 5/6] crypto: implement other common funcs for " Longpeng(Mike)
2017-01-05 0:49 ` [Qemu-devel] [PATCH RESEND 6/6] crypto: add AEAD algorithms testcases Longpeng(Mike)
5 siblings, 0 replies; 10+ messages in thread
From: Longpeng(Mike) @ 2017-01-05 0:49 UTC (permalink / raw)
To: berrange; +Cc: wu.wubin, jianjay.zhou, arei.gonglei, qemu-devel, Longpeng(Mike)
This patch add gcrypt-backed AEAD algorithms support
Signed-off-by: Longpeng(Mike) <longpeng2@huawei.com>
---
crypto/aead-gcrypt.c | 173 +++++++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 167 insertions(+), 6 deletions(-)
diff --git a/crypto/aead-gcrypt.c b/crypto/aead-gcrypt.c
index 9465518..9892e3b 100644
--- a/crypto/aead-gcrypt.c
+++ b/crypto/aead-gcrypt.c
@@ -17,17 +17,100 @@
#include "crypto/aead.h"
#include <gcrypt.h>
+typedef struct QCryptoAeadGcrypt QCryptoAeadGcrypt;
+struct QCryptoAeadGcrypt {
+ gcry_cipher_hd_t handle;
+};
+
QCryptoAead *qcrypto_aead_new(QCryptoCipherAlgorithm alg,
QCryptoCipherMode mode,
const uint8_t *key, size_t nkey,
Error **errp)
{
+ QCryptoAead *aead;
+ QCryptoAeadGcrypt *ctx;
+ gcry_error_t err;
+ int gcryalg, gcrymode;
+
+ switch (mode) {
+ case QCRYPTO_CIPHER_MODE_CCM:
+ gcrymode = GCRY_CIPHER_MODE_CCM;
+ break;
+ case QCRYPTO_CIPHER_MODE_GCM:
+ gcrymode = GCRY_CIPHER_MODE_GCM;
+ break;
+ default:
+ error_setg(errp, "Unsupported AEAD mode %s",
+ QCryptoCipherMode_lookup[mode]);
+ return NULL;
+ }
+
+ if (nkey != qcrypto_aead_get_key_len(alg)) {
+ error_setg(errp, "Cipher key length %zu is invalid",
+ nkey);
+ return NULL;
+ }
+
+ switch (alg) {
+ case QCRYPTO_CIPHER_ALG_AES_128:
+ gcryalg = GCRY_CIPHER_AES128;
+ break;
+ case QCRYPTO_CIPHER_ALG_AES_192:
+ gcryalg = GCRY_CIPHER_AES192;
+ break;
+ case QCRYPTO_CIPHER_ALG_AES_256:
+ gcryalg = GCRY_CIPHER_AES256;
+ break;
+ default:
+ error_setg(errp, "Unsupported AEAD algorithm %s",
+ QCryptoCipherAlgorithm_lookup[alg]);
+ return NULL;
+ }
+
+ aead = g_new0(QCryptoAead, 1);
+ aead->alg = alg;
+ aead->mode = mode;
+
+ ctx = g_new0(QCryptoAeadGcrypt, 1);
+
+ err = gcry_cipher_open(&ctx->handle, gcryalg, gcrymode, 0);
+ if (err) {
+ error_setg(errp, "Cannot initialize aead: %s",
+ gcry_strerror(err));
+ goto error;
+ }
+
+ err = gcry_cipher_setkey(ctx->handle, key, nkey);
+ if (err) {
+ error_setg(errp, "Cannot set key: %s",
+ gcry_strerror(err));
+ goto error;
+ }
+
+ aead->opaque = ctx;
+
+ return aead;
+
+error:
+ gcry_cipher_close(ctx->handle);
+ g_free(ctx);
+ g_free(aead);
return NULL;
}
void qcrypto_aead_free(QCryptoAead *aead)
{
- return;
+ QCryptoAeadGcrypt *ctx;
+
+ if (!aead) {
+ return;
+ }
+
+ ctx = aead->opaque;
+
+ gcry_cipher_close(ctx->handle);
+ g_free(ctx);
+ g_free(aead);
}
int qcrypto_aead_set_nonce(QCryptoAead *aead,
@@ -36,14 +119,54 @@ int qcrypto_aead_set_nonce(QCryptoAead *aead,
size_t tag_len,
Error **errp)
{
- return -1;
+ QCryptoAeadGcrypt *ctx;
+ gcry_error_t err;
+
+ ctx = aead->opaque;
+
+ err = gcry_cipher_setiv(ctx->handle, nonce, nonce_len);
+ if (err) {
+ error_setg(errp, "Cannot set iv/nonce: %s",
+ gcry_strerror(err));
+ return -1;
+ }
+
+ if (aead->mode == QCRYPTO_CIPHER_MODE_CCM) {
+ size_t ctl_para[3];
+
+ ctl_para[0] = in_len;
+ ctl_para[1] = aad_len;
+ ctl_para[2] = tag_len;
+
+ err = gcry_cipher_ctl(ctx->handle, GCRYCTL_SET_CCM_LENGTHS,
+ ctl_para, sizeof(ctl_para));
+ if (err) {
+ error_setg(errp, "Cannot set lengths: %s",
+ gcry_strerror(err));
+ return -1;
+ }
+ }
+
+ return 0;
}
int qcrypto_aead_authenticate(QCryptoAead *aead,
const uint8_t *aad, size_t aad_len,
Error **errp)
{
- return -1;
+ QCryptoAeadGcrypt *ctx;
+ gcry_error_t err;
+
+ ctx = aead->opaque;
+
+ err = gcry_cipher_authenticate(ctx->handle, aad, aad_len);
+ if (err) {
+ error_setg(errp, "Cannot set associated data: %s",
+ gcry_strerror(err));
+ return -1;
+ }
+
+ return 0;
}
int qcrypto_aead_encrypt(QCryptoAead *aead,
@@ -51,7 +174,20 @@ int qcrypto_aead_encrypt(QCryptoAead *aead,
uint8_t *out, size_t out_len,
Error **errp)
{
- return -1;
+ QCryptoAeadGcrypt *ctx;
+ gcry_error_t err;
+
+ ctx = aead->opaque;
+
+ err = gcry_cipher_encrypt(ctx->handle, out, out_len,
+ in, in_len);
+ if (err) {
+ error_setg(errp, "Cannot encrypt data: %s",
+ gcry_strerror(err));
+ return -1;
+ }
+
+ return 0;
}
int qcrypto_aead_decrypt(QCryptoAead *aead,
@@ -59,12 +195,37 @@ int qcrypto_aead_decrypt(QCryptoAead *aead,
uint8_t *out, size_t out_len,
Error **errp)
{
- return -1;
+ QCryptoAeadGcrypt *ctx;
+ gcry_error_t err;
+
+ ctx = aead->opaque;
+
+ err = gcry_cipher_decrypt(ctx->handle, out, out_len,
+ in, in_len);
+ if (err) {
+ error_setg(errp, "Cannot decrypt data: %s",
+ gcry_strerror(err));
+ return -1;
+ }
+
+ return 0;
}
int qcrypto_aead_get_tag(QCryptoAead *aead,
uint8_t *tag, size_t tag_len,
Error **errp)
{
- return -1;
+ QCryptoAeadGcrypt *ctx;
+ gcry_error_t err;
+
+ ctx = aead->opaque;
+
+ err = gcry_cipher_gettag(ctx->handle, tag, tag_len);
+ if (err) {
+ error_setg(errp, "Cannot get tag: %s",
+ gcry_strerror(err));
+ return -1;
+ }
+
+ return 0;
}
--
1.8.3.1
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [Qemu-devel] [PATCH RESEND 5/6] crypto: implement other common funcs for AEAD algorithms
2017-01-05 0:49 [Qemu-devel] [PATCH RESEND 0/6] crypto:add AEAD algorithms support Longpeng(Mike)
` (3 preceding siblings ...)
2017-01-05 0:49 ` [Qemu-devel] [PATCH RESEND 4/6] crypto: implement gcrypt-backed " Longpeng(Mike)
@ 2017-01-05 0:49 ` Longpeng(Mike)
2017-01-05 0:49 ` [Qemu-devel] [PATCH RESEND 6/6] crypto: add AEAD algorithms testcases Longpeng(Mike)
5 siblings, 0 replies; 10+ messages in thread
From: Longpeng(Mike) @ 2017-01-05 0:49 UTC (permalink / raw)
To: berrange; +Cc: wu.wubin, jianjay.zhou, arei.gonglei, qemu-devel, Longpeng(Mike)
If currently gcrypt/nettle doesn't support AEAD alg, then
we should implement some no-op funcs.
Signed-off-by: Longpeng(Mike) <longpeng2@huawei.com>
---
crypto/aead.c | 44 ++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 42 insertions(+), 2 deletions(-)
diff --git a/crypto/aead.c b/crypto/aead.c
index 47639b7..effe45e 100644
--- a/crypto/aead.c
+++ b/crypto/aead.c
@@ -16,18 +16,58 @@
#include "qapi/error.h"
#include "crypto/aead.h"
+#if defined(CONFIG_NETTLE_AEAD) || defined(CONFIG_GCRYPT_AEAD)
+
+static size_t alg_key_len[QCRYPTO_AEAD_ALG__MAX] = {
+ [QCRYPTO_CIPHER_ALG_AES_128] = 16,
+ [QCRYPTO_CIPHER_ALG_AES_192] = 24,
+ [QCRYPTO_CIPHER_ALG_AES_256] = 32,
+};
+
bool qcrypto_aead_supports(QCryptoCipherAlgorithm alg,
QCryptoCipherMode mode)
{
+ switch (alg) {
+ case QCRYPTO_CIPHER_ALG_AES_128:
+ case QCRYPTO_CIPHER_ALG_AES_192:
+ case QCRYPTO_CIPHER_ALG_AES_256:
+ break;
+ default:
+ return false;
+ }
+
+ switch (mode) {
+ case QCRYPTO_CIPHER_MODE_CCM:
+ case QCRYPTO_CIPHER_MODE_GCM:
+ return true;
+ default:
+ break;
+ }
+
return false;
}
size_t qcrypto_aead_get_key_len(QCryptoCipherAlgorithm alg)
{
- return -1;
+ if (alg > G_N_ELEMENTS(alg_key_len)) {
+ return 0;
+ }
+
+ return alg_key_len[alg];
}
-#if !defined(CONFIG_NETTLE_AEAD) && !defined(CONFIG_GCRYPT_AEAD)
+#else
+
+bool qcrypto_aead_supports(QCryptoCipherAlgorithm alg,
+ QCryptoCipherMode mode)
+{
+ return false;
+}
+
+size_t qcrypto_aead_get_key_len(QCryptoCipherAlgorithm alg)
+{
+ return -1;
+}
QCryptoAead *qcrypto_aead_new(QCryptoCipherAlgorithm alg,
QCryptoCipherMode mode,
--
1.8.3.1
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [Qemu-devel] [PATCH RESEND 6/6] crypto: add AEAD algorithms testcases
2017-01-05 0:49 [Qemu-devel] [PATCH RESEND 0/6] crypto:add AEAD algorithms support Longpeng(Mike)
` (4 preceding siblings ...)
2017-01-05 0:49 ` [Qemu-devel] [PATCH RESEND 5/6] crypto: implement other common funcs for " Longpeng(Mike)
@ 2017-01-05 0:49 ` Longpeng(Mike)
2017-01-06 11:28 ` Daniel P. Berrange
5 siblings, 1 reply; 10+ messages in thread
From: Longpeng(Mike) @ 2017-01-05 0:49 UTC (permalink / raw)
To: berrange; +Cc: wu.wubin, jianjay.zhou, arei.gonglei, qemu-devel, Longpeng(Mike)
This patch add some AEAD algorithms testcases
Signed-off-by: Longpeng(Mike) <longpeng2@huawei.com>
---
tests/Makefile.include | 2 +
tests/test-crypto-aead.c | 357 +++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 359 insertions(+)
create mode 100644 tests/test-crypto-aead.c
diff --git a/tests/Makefile.include b/tests/Makefile.include
index 4841d58..686ba30 100644
--- a/tests/Makefile.include
+++ b/tests/Makefile.include
@@ -93,6 +93,7 @@ gcov-files-test-write-threshold-y = block/write-threshold.c
check-unit-y += tests/test-crypto-hash$(EXESUF)
check-unit-y += tests/test-crypto-hmac$(EXESUF)
check-unit-y += tests/test-crypto-cipher$(EXESUF)
+check-unit-y += tests/test-crypto-aead$(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)
@@ -574,6 +575,7 @@ tests/test-bitops$(EXESUF): tests/test-bitops.o $(test-util-obj-y)
tests/test-crypto-hash$(EXESUF): tests/test-crypto-hash.o $(test-crypto-obj-y)
tests/test-crypto-hmac$(EXESUF): tests/test-crypto-hmac.o $(test-crypto-obj-y)
tests/test-crypto-cipher$(EXESUF): tests/test-crypto-cipher.o $(test-crypto-obj-y)
+tests/test-crypto-aead$(EXESUF): tests/test-crypto-aead.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)
diff --git a/tests/test-crypto-aead.c b/tests/test-crypto-aead.c
new file mode 100644
index 0000000..c757be3
--- /dev/null
+++ b/tests/test-crypto-aead.c
@@ -0,0 +1,357 @@
+/*
+ * QEMU Crypto aead algorithms testcase
+ *
+ * Copyright (c) 2016 HUAWEI TECHNOLOGIES CO., LTD.
+ *
+ * Authors:
+ * Longpeng(Mike) <longpeng2@huawei.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or
+ * (at your option) any later version. See the COPYING file in the
+ * top-level directory.
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "crypto/init.h"
+#include "crypto/aead.h"
+#include "qapi/error.h"
+
+typedef struct QCryptoAeadTestData QCryptoAeadTestData;
+struct QCryptoAeadTestData {
+ const char *path;
+ QCryptoCipherAlgorithm alg;
+ QCryptoCipherMode mode;
+ const char *hex_key;
+ const char *hex_nonce;
+ const char *hex_aad;
+ const char *hex_plain;
+ const char *hex_cipher;
+ const char *hex_tag;
+};
+
+static QCryptoAeadTestData test_data[] = {
+ {
+ /* Borrowed from libgcrypt */
+ .path = "/crypto/aead/gcm-aes-128",
+ .alg = QCRYPTO_CIPHER_ALG_AES_128,
+ .mode = QCRYPTO_CIPHER_MODE_GCM,
+ .hex_key = "0000000000000000"
+ "0000000000000000",
+ .hex_nonce = "0000000000000000"
+ "00000000",
+ .hex_aad = "",
+ .hex_plain = "0000000000000000"
+ "0000000000000000",
+ .hex_cipher = "0388dace60b6a392"
+ "f328c2b971b2fe78",
+ .hex_tag = "ab6e47d42cec13bd"
+ "f53a67b21257bddf",
+ },
+ {
+ /* Borrowed from libgcrypt */
+ .path = "/crypto/aead/gcm-aes-192",
+ .alg = QCRYPTO_CIPHER_ALG_AES_192,
+ .mode = QCRYPTO_CIPHER_MODE_GCM,
+ .hex_key = "feffe9928665731c"
+ "6d6a8f9467308308"
+ "feffe9928665731c",
+ .hex_nonce = "9313225df88406e5"
+ "55909c5aff5269aa"
+ "6a7a9538534f7da1"
+ "e4c303d2a318a728"
+ "c3c0c95156809539"
+ "fcf0e2429a6b5254"
+ "16aedbf5a0de6a57"
+ "a637b39b",
+ .hex_aad = "feedfacedeadbeef"
+ "feedfacedeadbeef"
+ "abaddad2",
+ .hex_plain = "d9313225f88406e5"
+ "a55909c5aff5269a"
+ "86a7a9531534f7da"
+ "2e4c303d8a318a72"
+ "1c3c0c9595680953"
+ "2fcf0e2449a6b525"
+ "b16aedf5aa0de657"
+ "ba637b39",
+ .hex_cipher = "d27e88681ce3243c"
+ "4830165a8fdcf9ff"
+ "1de9a1d8e6b447ef"
+ "6ef7b79828666e45"
+ "81e79012af34ddd9"
+ "e2f037589b292db3"
+ "e67c036745fa22e7"
+ "e9b7373b",
+ .hex_tag = "dcf566ff291c25bb"
+ "b8568fc3d376a6d9",
+ },
+ {
+ /* Borrowed from libgcrypt */
+ .path = "/crypto/aead/gcm-aes-256",
+ .alg = QCRYPTO_CIPHER_ALG_AES_256,
+ .mode = QCRYPTO_CIPHER_MODE_GCM,
+ .hex_key = "feffe9928665731c"
+ "6d6a8f9467308308"
+ "feffe9928665731c"
+ "6d6a8f9467308308",
+ .hex_nonce = "9313225df88406e5"
+ "55909c5aff5269aa"
+ "6a7a9538534f7da1"
+ "e4c303d2a318a728"
+ "c3c0c95156809539"
+ "fcf0e2429a6b5254"
+ "16aedbf5a0de6a57"
+ "a637b39b",
+ .hex_aad = "feedfacedeadbeef"
+ "feedfacedeadbeef"
+ "abaddad2",
+ .hex_plain = "d9313225f88406e5"
+ "a55909c5aff5269a"
+ "86a7a9531534f7da"
+ "2e4c303d8a318a72"
+ "1c3c0c9595680953"
+ "2fcf0e2449a6b525"
+ "b16aedf5aa0de657"
+ "ba637b39",
+ .hex_cipher = "5a8def2f0c9e53f1"
+ "f75d7853659e2a20"
+ "eeb2b22aafde6419"
+ "a058ab4f6f746bf4"
+ "0fc0c3b780f24445"
+ "2da3ebf1c5d82cde"
+ "a2418997200ef82e"
+ "44ae7e3f",
+ .hex_tag = "a44a8266ee1c8eb0"
+ "c8b5d4cf5ae9f19a",
+ },
+ {
+ /* Borrowed from libgcrypt */
+ .path = "/crypto/aead/ccm-aes-128",
+ .alg = QCRYPTO_CIPHER_ALG_AES_128,
+ .mode = QCRYPTO_CIPHER_MODE_CCM,
+ .hex_key = "c0c1c2c3c4c5c6c7"
+ "c8c9cacbcccdcecf",
+ .hex_nonce = "00000003020100a0"
+ "a1a2a3a4a5",
+ .hex_aad = "0001020304050607",
+ .hex_plain = "08090a0b0c0d0e0f"
+ "1011121314151617"
+ "18191a1b1c1d1e",
+ .hex_cipher = "588c979a61c663d2"
+ "f066d0c2c0f98980"
+ "6d5f6b61dac384",
+ .hex_tag = "17e8d12cfdf926e0",
+ },
+ {
+ .path = "/crypto/aead/ccm-aes-192",
+ .alg = QCRYPTO_CIPHER_ALG_AES_192,
+ .mode = QCRYPTO_CIPHER_MODE_CCM,
+ .hex_key = "56df5c8f263f0e42"
+ "ef7ad3cefc846062"
+ "cab440af5fc9c901",
+ .hex_nonce = "03d63c8c8684b6cd"
+ "ef092e94",
+ .hex_aad = "0265783ce9213091"
+ "b1b9da769a786d95"
+ "f28832a3f250cb4c"
+ "e300736984698779",
+ .hex_plain = "9fd2024b5249313c"
+ "43693a2d8e70ad7e"
+ "e0e54609808913b2"
+ "8c8bd93f86fbb56b",
+ .hex_cipher = "00161ecf83e37c91"
+ "ce8bdb138370e37a"
+ "d638efed5e3a8aed"
+ "1841db9f8654251d",
+ .hex_tag = "18219f9396f03723"
+ "c185f9781ec0a6ad",
+ },
+ {
+ /* Borrowed from nettle*/
+ .path = "/crypto/aead/ccm-aes-256",
+ .alg = QCRYPTO_CIPHER_ALG_AES_256,
+ .mode = QCRYPTO_CIPHER_MODE_CCM,
+ .hex_key = "4041424344454647"
+ "48494a4b4c4d4e4f"
+ "5051525354555657"
+ "58595a5b5c5d5e5f",
+ .hex_nonce = "1011121314151617"
+ "18191a1b",
+ .hex_aad = "0001020304050607"
+ "08090a0b0c0d0e0f"
+ "10111213",
+ .hex_plain = "2021222324252627"
+ "28292a2b2c2d2e2f"
+ "3031323334353637",
+ .hex_cipher = "04f883aeb3bd0730"
+ "eaf50bb6de4fa221"
+ "2034e4e41b0e75e5",
+ .hex_tag = "9bba3f3a107f3239"
+ "bd63902923f80371",
+ },
+};
+
+static inline int unhex(char c)
+{
+ if (c >= 'a' && c <= 'f') {
+ return 10 + (c - 'a');
+ }
+ if (c >= 'A' && c <= 'F') {
+ return 10 + (c - 'A');
+ }
+ return c - '0';
+}
+
+static inline char hex(int i)
+{
+ if (i < 10) {
+ return '0' + i;
+ }
+ return 'a' + (i - 10);
+}
+
+static size_t unhex_string(const char *hexstr,
+ uint8_t **data)
+{
+ size_t len;
+ size_t i;
+
+ if (!hexstr) {
+ *data = NULL;
+ return 0;
+ }
+
+ len = strlen(hexstr);
+ *data = g_new0(uint8_t, len / 2);
+
+ for (i = 0; i < len; i += 2) {
+ (*data)[i / 2] = (unhex(hexstr[i]) << 4)
+ | unhex(hexstr[i + 1]);
+ }
+ return len / 2;
+}
+
+static char *hex_string(const uint8_t *bytes,
+ size_t len)
+{
+ char *hexstr = g_new0(char, len * 2 + 1);
+ size_t i;
+
+ for (i = 0; i < len; i++) {
+ hexstr[i * 2] = hex((bytes[i] >> 4) & 0xf);
+ hexstr[i * 2 + 1] = hex(bytes[i] & 0xf);
+ }
+ hexstr[len * 2] = '\0';
+
+ return hexstr;
+}
+
+static void _test_aead(const QCryptoAeadTestData *data,
+ bool encrypt)
+{
+ QCryptoAead *aead;
+
+ uint8_t *key = NULL, *nonce = NULL;
+ uint8_t *aad = NULL, *in = NULL;
+ size_t key_len = 0, nonce_len = 0, aad_len = 0;
+ size_t in_len = 0, tag_len = 0;
+ uint8_t *hex_tmp = NULL;
+ uint8_t *out = NULL;
+ uint8_t out_len = 0;
+ Error *err = NULL;
+ int ret;
+
+ key_len = unhex_string(data->hex_key, &key);
+ nonce_len = unhex_string(data->hex_nonce, &nonce);
+ aad_len = unhex_string(data->hex_aad, &aad);
+ if (encrypt) {
+ in_len = unhex_string(data->hex_plain, &in);
+ } else {
+ in_len = unhex_string(data->hex_cipher, &in);
+ }
+
+ tag_len = strlen(data->hex_tag) / 2;
+ out_len = in_len + tag_len;
+ out = g_new0(uint8_t, out_len);
+
+ aead = qcrypto_aead_new(data->alg, data->mode,
+ key, key_len, &err);
+ g_assert(aead != NULL);
+
+ ret = qcrypto_aead_set_nonce(aead, nonce, nonce_len,
+ aad_len, in_len, tag_len,
+ &err);
+ g_assert(ret == 0);
+
+ ret = qcrypto_aead_authenticate(aead, aad, aad_len,
+ &err);
+ g_assert(ret == 0);
+
+ if (encrypt) {
+ ret = qcrypto_aead_encrypt(aead, in, in_len,
+ out, in_len, &err);
+ g_assert(ret == 0);
+
+ hex_tmp = (uint8_t *)hex_string(out, in_len);
+ g_assert_cmpstr((char *)hex_tmp, ==,
+ (char *)data->hex_cipher);
+ g_free(hex_tmp);
+ } else {
+ ret = qcrypto_aead_decrypt(aead, in, in_len,
+ out, in_len, &err);
+ g_assert(ret == 0);
+
+ hex_tmp = (uint8_t *)hex_string(out, in_len);
+ g_assert_cmpstr((char *)hex_tmp, ==,
+ (char *)data->hex_plain);
+ g_free(hex_tmp);
+ }
+
+ ret = qcrypto_aead_get_tag(aead, out + in_len,
+ tag_len, &err);
+ g_assert(ret == 0);
+
+ hex_tmp = (uint8_t *)hex_string(out + in_len,
+ tag_len);
+ g_assert_cmpstr((char *)hex_tmp, ==,
+ (char *)data->hex_tag);
+ g_free(hex_tmp);
+
+ g_free(out);
+ g_free(in);
+ g_free(aad);
+ g_free(nonce);
+ g_free(key);
+ qcrypto_aead_free(aead);
+}
+
+static void test_aead(const void *opaque)
+{
+ const QCryptoAeadTestData *data = opaque;
+
+ /* test encrypt */
+ _test_aead(data, 1);
+
+ /* test decrypt */
+ _test_aead(data, 0);
+}
+
+int main(int argc, char **argv)
+{
+ size_t i;
+
+ g_test_init(&argc, &argv, NULL);
+
+ g_assert(qcrypto_init(NULL) == 0);
+
+ for (i = 0; i < G_N_ELEMENTS(test_data); i++) {
+ if (qcrypto_aead_supports(test_data[i].alg,
+ test_data[i].mode)) {
+ g_test_add_data_func(test_data[i].path,
+ &test_data[i], test_aead);
+ }
+ }
+
+ return g_test_run();
+}
--
1.8.3.1
^ permalink raw reply related [flat|nested] 10+ messages in thread