diff mbox

[RESEND,2/6] crypto: add AEAD algorithms framework

Message ID 1483577381-38088-3-git-send-email-longpeng2@huawei.com (mailing list archive)
State New, archived
Headers show

Commit Message

Longpeng(Mike) Jan. 5, 2017, 12:49 a.m. UTC
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

Comments

Daniel P. Berrangé Jan. 6, 2017, 11:28 a.m. UTC | #1
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
Longpeng(Mike) Jan. 7, 2017, 7:33 a.m. UTC | #2
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
diff mbox

Patch

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']}
 
 
 ##