diff options
| author | Peter Maydell <peter.maydell@linaro.org> | 2017-07-19 20:45:37 +0100 |
|---|---|---|
| committer | Peter Maydell <peter.maydell@linaro.org> | 2017-07-19 20:45:37 +0100 |
| commit | d4e59218ab80e86015753782fb5378767a51ccd0 (patch) | |
| tree | c68daa77cf82483496bd9f1c4c8a582fd4ed517d /crypto/hash-afalg.c | |
| parent | 824dbfb45d4834c6538f6f70737014b1f19e2e55 (diff) | |
| parent | c7a9af4b450c863cd84ad245ebc52a831c661392 (diff) | |
| download | focaccia-qemu-d4e59218ab80e86015753782fb5378767a51ccd0.tar.gz focaccia-qemu-d4e59218ab80e86015753782fb5378767a51ccd0.zip | |
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>
Diffstat (limited to 'crypto/hash-afalg.c')
| -rw-r--r-- | crypto/hash-afalg.c | 214 |
1 files changed, 214 insertions, 0 deletions
diff --git a/crypto/hash-afalg.c b/crypto/hash-afalg.c new file mode 100644 index 0000000000..cf34c694af --- /dev/null +++ b/crypto/hash-afalg.c @@ -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, +}; |