diff mbox series

[16/18] crypto: add gnutls hmac provider

Message ID 20210706095924.764117-17-berrange@redhat.com
State New
Headers show
Series crypto: misc cleanup and introduce gnutls backend driver | expand

Commit Message

Daniel P. Berrangé July 6, 2021, 9:59 a.m. UTC
This adds support for using gnutls as a provider of the crypto
hmac APIs.

Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
---
 crypto/hmac-gnutls.c | 136 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 136 insertions(+)
 create mode 100644 crypto/hmac-gnutls.c

Comments

Eric Blake July 8, 2021, 7:35 p.m. UTC | #1
On Tue, Jul 06, 2021 at 10:59:22AM +0100, Daniel P. Berrangé wrote:
> This adds support for using gnutls as a provider of the crypto
> hmac APIs.
> 
> Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
> ---
>  crypto/hmac-gnutls.c | 136 +++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 136 insertions(+)
>  create mode 100644 crypto/hmac-gnutls.c
> 
> diff --git a/crypto/hmac-gnutls.c b/crypto/hmac-gnutls.c
> new file mode 100644
> index 0000000000..ea33b5753b
> --- /dev/null
> +++ b/crypto/hmac-gnutls.c
> @@ -0,0 +1,136 @@
> +/*
> + * QEMU Crypto hmac algorithms
> + *
> + * Derived from hmac-gcrypt.c:
> + *
> + *   Copyright (c) 2016 HUAWEI TECHNOLOGIES CO., LTD.

Is this line correct?

> + *
> + * 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/hmac.h"
> +#include "hmacpriv.h"
> +#include <gnutls/crypto.h>

Should you favor floating this to be right after "qemu/osdep.h"?

Reviewed-by: Eric Blake <eblake@redhat.com>
Daniel P. Berrangé July 9, 2021, 2:03 p.m. UTC | #2
On Thu, Jul 08, 2021 at 02:35:19PM -0500, Eric Blake wrote:
> On Tue, Jul 06, 2021 at 10:59:22AM +0100, Daniel P. Berrangé wrote:
> > This adds support for using gnutls as a provider of the crypto
> > hmac APIs.
> > 
> > Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
> > ---
> >  crypto/hmac-gnutls.c | 136 +++++++++++++++++++++++++++++++++++++++++++
> >  1 file changed, 136 insertions(+)
> >  create mode 100644 crypto/hmac-gnutls.c
> > 
> > diff --git a/crypto/hmac-gnutls.c b/crypto/hmac-gnutls.c
> > new file mode 100644
> > index 0000000000..ea33b5753b
> > --- /dev/null
> > +++ b/crypto/hmac-gnutls.c
> > @@ -0,0 +1,136 @@
> > +/*
> > + * QEMU Crypto hmac algorithms
> > + *
> > + * Derived from hmac-gcrypt.c:
> > + *
> > + *   Copyright (c) 2016 HUAWEI TECHNOLOGIES CO., LTD.
> 
> Is this line correct?

This is referring to the statement above "Derived from..."


I should have /also/ added a Red Hat copyright before though

> 
> > + *
> > + * 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/hmac.h"
> > +#include "hmacpriv.h"
> > +#include <gnutls/crypto.h>
> 
> Should you favor floating this to be right after "qemu/osdep.h"?

yeah good idea

> 
> Reviewed-by: Eric Blake <eblake@redhat.com>
> 
> -- 
> Eric Blake, Principal Software Engineer
> Red Hat, Inc.           +1-919-301-3266
> Virtualization:  qemu.org | libvirt.org
> 

Regards,
Daniel
diff mbox series

Patch

diff --git a/crypto/hmac-gnutls.c b/crypto/hmac-gnutls.c
new file mode 100644
index 0000000000..ea33b5753b
--- /dev/null
+++ b/crypto/hmac-gnutls.c
@@ -0,0 +1,136 @@ 
+/*
+ * QEMU Crypto hmac algorithms
+ *
+ * Derived from hmac-gcrypt.c:
+ *
+ *   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.
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "crypto/hmac.h"
+#include "hmacpriv.h"
+#include <gnutls/crypto.h>
+
+static int qcrypto_hmac_alg_map[QCRYPTO_HASH_ALG__MAX] = {
+    [QCRYPTO_HASH_ALG_MD5] = GNUTLS_MAC_MD5,
+    [QCRYPTO_HASH_ALG_SHA1] = GNUTLS_MAC_SHA1,
+    [QCRYPTO_HASH_ALG_SHA224] = GNUTLS_MAC_SHA224,
+    [QCRYPTO_HASH_ALG_SHA256] = GNUTLS_MAC_SHA256,
+    [QCRYPTO_HASH_ALG_SHA384] = GNUTLS_MAC_SHA384,
+    [QCRYPTO_HASH_ALG_SHA512] = GNUTLS_MAC_SHA512,
+    [QCRYPTO_HASH_ALG_RIPEMD160] = GNUTLS_MAC_RMD160,
+};
+
+typedef struct QCryptoHmacGnutls QCryptoHmacGnutls;
+struct QCryptoHmacGnutls {
+    gnutls_hmac_hd_t handle;
+};
+
+bool qcrypto_hmac_supports(QCryptoHashAlgorithm alg)
+{
+    size_t i;
+    const gnutls_digest_algorithm_t *algs;
+    if (alg >= G_N_ELEMENTS(qcrypto_hmac_alg_map) ||
+        qcrypto_hmac_alg_map[alg] == GNUTLS_DIG_UNKNOWN) {
+        return false;
+    }
+    algs = gnutls_digest_list();
+    for (i = 0; algs[i] != GNUTLS_DIG_UNKNOWN; i++) {
+        if (algs[i] == qcrypto_hmac_alg_map[alg]) {
+            return true;
+        }
+    }
+    return false;
+}
+
+void *qcrypto_hmac_ctx_new(QCryptoHashAlgorithm alg,
+                           const uint8_t *key, size_t nkey,
+                           Error **errp)
+{
+    QCryptoHmacGnutls *ctx;
+    int err;
+
+    if (!qcrypto_hmac_supports(alg)) {
+        error_setg(errp, "Unsupported hmac algorithm %s",
+                   QCryptoHashAlgorithm_str(alg));
+        return NULL;
+    }
+
+    ctx = g_new0(QCryptoHmacGnutls, 1);
+
+    err = gnutls_hmac_init(&ctx->handle,
+                           qcrypto_hmac_alg_map[alg],
+                           (const void *)key, nkey);
+    if (err != 0) {
+        error_setg(errp, "Cannot initialize hmac: %s",
+                   gnutls_strerror(err));
+        goto error;
+    }
+
+    return ctx;
+
+error:
+    g_free(ctx);
+    return NULL;
+}
+
+static void
+qcrypto_gnutls_hmac_ctx_free(QCryptoHmac *hmac)
+{
+    QCryptoHmacGnutls *ctx;
+
+    ctx = hmac->opaque;
+    gnutls_hmac_deinit(ctx->handle, NULL);
+
+    g_free(ctx);
+}
+
+static int
+qcrypto_gnutls_hmac_bytesv(QCryptoHmac *hmac,
+                           const struct iovec *iov,
+                           size_t niov,
+                           uint8_t **result,
+                           size_t *resultlen,
+                           Error **errp)
+{
+    QCryptoHmacGnutls *ctx;
+    uint32_t ret;
+    int i;
+
+    ctx = hmac->opaque;
+
+    for (i = 0; i < niov; i++) {
+        gnutls_hmac(ctx->handle, iov[i].iov_base, iov[i].iov_len);
+    }
+
+    ret = gnutls_hmac_get_len(qcrypto_hmac_alg_map[hmac->alg]);
+    if (ret <= 0) {
+        error_setg(errp, "Unable to get hmac length: %s",
+                   gnutls_strerror(ret));
+        return -1;
+    }
+
+    if (*resultlen == 0) {
+        *resultlen = ret;
+        *result = g_new0(uint8_t, *resultlen);
+    } else if (*resultlen != ret) {
+        error_setg(errp, "Result buffer size %zu is smaller than hmac %d",
+                   *resultlen, ret);
+        return -1;
+    }
+
+    gnutls_hmac_output(ctx->handle, *result);
+
+    return 0;
+}
+
+QCryptoHmacDriver qcrypto_hmac_lib_driver = {
+    .hmac_bytesv = qcrypto_gnutls_hmac_bytesv,
+    .hmac_free = qcrypto_gnutls_hmac_ctx_free,
+};