diff options
Diffstat (limited to 'crypto/hash-nettle.c')
| -rw-r--r-- | crypto/hash-nettle.c | 94 |
1 files changed, 50 insertions, 44 deletions
diff --git a/crypto/hash-nettle.c b/crypto/hash-nettle.c index 8b08a9c675..3b847aa60e 100644 --- a/crypto/hash-nettle.c +++ b/crypto/hash-nettle.c @@ -1,6 +1,7 @@ /* * QEMU Crypto hash algorithms * + * Copyright (c) 2024 Seagate Technology LLC and/or its Affiliates * Copyright (c) 2016 Red Hat, Inc. * * This library is free software; you can redistribute it and/or @@ -103,59 +104,64 @@ gboolean qcrypto_hash_supports(QCryptoHashAlgo alg) return false; } +static +QCryptoHash *qcrypto_nettle_hash_new(QCryptoHashAlgo alg, Error **errp) +{ + QCryptoHash *hash; + + hash = g_new(QCryptoHash, 1); + hash->alg = alg; + hash->opaque = g_new(union qcrypto_hash_ctx, 1); + + qcrypto_hash_alg_map[alg].init(hash->opaque); + return hash; +} -static int -qcrypto_nettle_hash_bytesv(QCryptoHashAlgo alg, - const struct iovec *iov, - size_t niov, - uint8_t **result, - size_t *resultlen, - Error **errp) +static +void qcrypto_nettle_hash_free(QCryptoHash *hash) { - size_t i; - union qcrypto_hash_ctx ctx; - - if (!qcrypto_hash_supports(alg)) { - error_setg(errp, - "Unknown hash algorithm %d", - alg); - return -1; - } + union qcrypto_hash_ctx *ctx = hash->opaque; - qcrypto_hash_alg_map[alg].init(&ctx); - - for (i = 0; i < niov; i++) { - /* Some versions of nettle have functions - * declared with 'int' instead of 'size_t' - * so to be safe avoid writing more than - * UINT_MAX bytes at a time - */ - size_t len = iov[i].iov_len; - uint8_t *base = iov[i].iov_base; - while (len) { - size_t shortlen = MIN(len, UINT_MAX); - qcrypto_hash_alg_map[alg].write(&ctx, len, base); - len -= shortlen; - base += len; - } - } + g_free(ctx); + g_free(hash); +} - if (*resultlen == 0) { - *resultlen = qcrypto_hash_alg_map[alg].len; - *result = g_new0(uint8_t, *resultlen); - } else if (*resultlen != qcrypto_hash_alg_map[alg].len) { - error_setg(errp, - "Result buffer size %zu is smaller than hash %zu", - *resultlen, qcrypto_hash_alg_map[alg].len); - return -1; - } +static +int qcrypto_nettle_hash_update(QCryptoHash *hash, + const struct iovec *iov, + size_t niov, + Error **errp) +{ + union qcrypto_hash_ctx *ctx = hash->opaque; - qcrypto_hash_alg_map[alg].result(&ctx, *resultlen, *result); + for (int i = 0; i < niov; i++) { + qcrypto_hash_alg_map[hash->alg].write(ctx, + iov[i].iov_len, + iov[i].iov_base); + } return 0; } +static +int qcrypto_nettle_hash_finalize(QCryptoHash *hash, + uint8_t **result, + size_t *result_len, + Error **errp) +{ + union qcrypto_hash_ctx *ctx = hash->opaque; + + *result_len = qcrypto_hash_alg_map[hash->alg].len; + *result = g_new(uint8_t, *result_len); + + qcrypto_hash_alg_map[hash->alg].result(ctx, *result_len, *result); + + return 0; +} QCryptoHashDriver qcrypto_hash_lib_driver = { - .hash_bytesv = qcrypto_nettle_hash_bytesv, + .hash_new = qcrypto_nettle_hash_new, + .hash_update = qcrypto_nettle_hash_update, + .hash_finalize = qcrypto_nettle_hash_finalize, + .hash_free = qcrypto_nettle_hash_free, }; |