12165477cSDaniel P. Berrange /* 22165477cSDaniel P. Berrange * QEMU Crypto hash algorithms 32165477cSDaniel P. Berrange * 4c6ccd2afSAlejandro Zeise * Copyright (c) 2024 Seagate Technology LLC and/or its Affiliates 52165477cSDaniel P. Berrange * Copyright (c) 2016 Red Hat, Inc. 62165477cSDaniel P. Berrange * 72165477cSDaniel P. Berrange * This library is free software; you can redistribute it and/or 82165477cSDaniel P. Berrange * modify it under the terms of the GNU Lesser General Public 92165477cSDaniel P. Berrange * License as published by the Free Software Foundation; either 10b7cbb874SThomas Huth * version 2.1 of the License, or (at your option) any later version. 112165477cSDaniel P. Berrange * 122165477cSDaniel P. Berrange * This library is distributed in the hope that it will be useful, 132165477cSDaniel P. Berrange * but WITHOUT ANY WARRANTY; without even the implied warranty of 142165477cSDaniel P. Berrange * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 152165477cSDaniel P. Berrange * Lesser General Public License for more details. 162165477cSDaniel P. Berrange * 172165477cSDaniel P. Berrange * You should have received a copy of the GNU Lesser General Public 182165477cSDaniel P. Berrange * License along with this library; if not, see <http://www.gnu.org/licenses/>. 192165477cSDaniel P. Berrange * 202165477cSDaniel P. Berrange */ 212165477cSDaniel P. Berrange 222165477cSDaniel P. Berrange #include "qemu/osdep.h" 232165477cSDaniel P. Berrange #include "qapi/error.h" 242165477cSDaniel P. Berrange #include "crypto/hash.h" 25aa8efad9SLongpeng(Mike) #include "hashpriv.h" 262165477cSDaniel P. Berrange 272165477cSDaniel P. Berrange 28ef834aa2SMarkus Armbruster static int qcrypto_hash_alg_map[QCRYPTO_HASH_ALGO__MAX] = { 29ef834aa2SMarkus Armbruster [QCRYPTO_HASH_ALGO_MD5] = G_CHECKSUM_MD5, 30ef834aa2SMarkus Armbruster [QCRYPTO_HASH_ALGO_SHA1] = G_CHECKSUM_SHA1, 31ef834aa2SMarkus Armbruster [QCRYPTO_HASH_ALGO_SHA224] = -1, 32ef834aa2SMarkus Armbruster [QCRYPTO_HASH_ALGO_SHA256] = G_CHECKSUM_SHA256, 33ef834aa2SMarkus Armbruster [QCRYPTO_HASH_ALGO_SHA384] = G_CHECKSUM_SHA384, 34ef834aa2SMarkus Armbruster [QCRYPTO_HASH_ALGO_SHA512] = G_CHECKSUM_SHA512, 35ef834aa2SMarkus Armbruster [QCRYPTO_HASH_ALGO_RIPEMD160] = -1, 362165477cSDaniel P. Berrange }; 372165477cSDaniel P. Berrange 38ef834aa2SMarkus Armbruster gboolean qcrypto_hash_supports(QCryptoHashAlgo alg) 392165477cSDaniel P. Berrange { 402165477cSDaniel P. Berrange if (alg < G_N_ELEMENTS(qcrypto_hash_alg_map) && 412165477cSDaniel P. Berrange qcrypto_hash_alg_map[alg] != -1) { 422165477cSDaniel P. Berrange return true; 432165477cSDaniel P. Berrange } 442165477cSDaniel P. Berrange return false; 452165477cSDaniel P. Berrange } 462165477cSDaniel P. Berrange 47c6ccd2afSAlejandro Zeise static 48c6ccd2afSAlejandro Zeise QCryptoHash *qcrypto_glib_hash_new(QCryptoHashAlgo alg, 49c6ccd2afSAlejandro Zeise Error **errp) 50c6ccd2afSAlejandro Zeise { 51c6ccd2afSAlejandro Zeise QCryptoHash *hash; 52c6ccd2afSAlejandro Zeise 53c6ccd2afSAlejandro Zeise hash = g_new(QCryptoHash, 1); 54c6ccd2afSAlejandro Zeise hash->alg = alg; 55c6ccd2afSAlejandro Zeise hash->opaque = g_checksum_new(qcrypto_hash_alg_map[alg]); 56c6ccd2afSAlejandro Zeise 57c6ccd2afSAlejandro Zeise return hash; 58c6ccd2afSAlejandro Zeise } 59c6ccd2afSAlejandro Zeise 60c6ccd2afSAlejandro Zeise static 61c6ccd2afSAlejandro Zeise void qcrypto_glib_hash_free(QCryptoHash *hash) 62c6ccd2afSAlejandro Zeise { 63c6ccd2afSAlejandro Zeise if (hash->opaque) { 64c6ccd2afSAlejandro Zeise g_checksum_free(hash->opaque); 65c6ccd2afSAlejandro Zeise } 66c6ccd2afSAlejandro Zeise 67c6ccd2afSAlejandro Zeise g_free(hash); 68c6ccd2afSAlejandro Zeise } 69c6ccd2afSAlejandro Zeise 70c6ccd2afSAlejandro Zeise 71c6ccd2afSAlejandro Zeise static 72c6ccd2afSAlejandro Zeise int qcrypto_glib_hash_update(QCryptoHash *hash, 73c6ccd2afSAlejandro Zeise const struct iovec *iov, 74c6ccd2afSAlejandro Zeise size_t niov, 75c6ccd2afSAlejandro Zeise Error **errp) 76c6ccd2afSAlejandro Zeise { 77c6ccd2afSAlejandro Zeise GChecksum *ctx = hash->opaque; 78c6ccd2afSAlejandro Zeise 79c6ccd2afSAlejandro Zeise for (int i = 0; i < niov; i++) { 80c6ccd2afSAlejandro Zeise g_checksum_update(ctx, iov[i].iov_base, iov[i].iov_len); 81c6ccd2afSAlejandro Zeise } 82c6ccd2afSAlejandro Zeise 83c6ccd2afSAlejandro Zeise return 0; 84c6ccd2afSAlejandro Zeise } 85c6ccd2afSAlejandro Zeise 86c6ccd2afSAlejandro Zeise static 87c6ccd2afSAlejandro Zeise int qcrypto_glib_hash_finalize(QCryptoHash *hash, 88c6ccd2afSAlejandro Zeise uint8_t **result, 89c6ccd2afSAlejandro Zeise size_t *result_len, 90c6ccd2afSAlejandro Zeise Error **errp) 91c6ccd2afSAlejandro Zeise { 92c6ccd2afSAlejandro Zeise int ret; 93c6ccd2afSAlejandro Zeise GChecksum *ctx = hash->opaque; 94c6ccd2afSAlejandro Zeise 95c6ccd2afSAlejandro Zeise ret = g_checksum_type_get_length(qcrypto_hash_alg_map[hash->alg]); 96c6ccd2afSAlejandro Zeise if (ret < 0) { 97c6ccd2afSAlejandro Zeise error_setg(errp, "Unable to get hash length"); 98c6ccd2afSAlejandro Zeise *result_len = 0; 99c6ccd2afSAlejandro Zeise return -1; 100c6ccd2afSAlejandro Zeise } 101c6ccd2afSAlejandro Zeise 102*dde538c9SDaniel P. Berrangé if (*result_len == 0) { 103c6ccd2afSAlejandro Zeise *result_len = ret; 104c6ccd2afSAlejandro Zeise *result = g_new(uint8_t, *result_len); 105*dde538c9SDaniel P. Berrangé } else if (*result_len != ret) { 106*dde538c9SDaniel P. Berrangé error_setg(errp, 107*dde538c9SDaniel P. Berrangé "Result buffer size %zu is smaller than hash %d", 108*dde538c9SDaniel P. Berrangé *result_len, ret); 109*dde538c9SDaniel P. Berrangé return -1; 110*dde538c9SDaniel P. Berrangé } 111c6ccd2afSAlejandro Zeise 112c6ccd2afSAlejandro Zeise g_checksum_get_digest(ctx, *result, result_len); 113c6ccd2afSAlejandro Zeise return 0; 114c6ccd2afSAlejandro Zeise } 115c6ccd2afSAlejandro Zeise 116aa8efad9SLongpeng(Mike) QCryptoHashDriver qcrypto_hash_lib_driver = { 117c6ccd2afSAlejandro Zeise .hash_new = qcrypto_glib_hash_new, 118c6ccd2afSAlejandro Zeise .hash_update = qcrypto_glib_hash_update, 119c6ccd2afSAlejandro Zeise .hash_finalize = qcrypto_glib_hash_finalize, 120c6ccd2afSAlejandro Zeise .hash_free = qcrypto_glib_hash_free, 121aa8efad9SLongpeng(Mike) }; 122