1 /* 2 * QEMU Crypto hash algorithms 3 * 4 * Copyright (c) 2024 Seagate Technology LLC and/or its Affiliates 5 * Copyright (c) 2016 Red Hat, Inc. 6 * 7 * This library is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU Lesser General Public 9 * License as published by the Free Software Foundation; either 10 * version 2.1 of the License, or (at your option) any later version. 11 * 12 * This library is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * Lesser General Public License for more details. 16 * 17 * You should have received a copy of the GNU Lesser General Public 18 * License along with this library; if not, see <http://www.gnu.org/licenses/>. 19 * 20 */ 21 22 #include "qemu/osdep.h" 23 #include "qapi/error.h" 24 #include "crypto/hash.h" 25 #include "hashpriv.h" 26 27 28 static int qcrypto_hash_alg_map[QCRYPTO_HASH_ALGO__MAX] = { 29 [QCRYPTO_HASH_ALGO_MD5] = G_CHECKSUM_MD5, 30 [QCRYPTO_HASH_ALGO_SHA1] = G_CHECKSUM_SHA1, 31 [QCRYPTO_HASH_ALGO_SHA224] = -1, 32 [QCRYPTO_HASH_ALGO_SHA256] = G_CHECKSUM_SHA256, 33 [QCRYPTO_HASH_ALGO_SHA384] = G_CHECKSUM_SHA384, 34 [QCRYPTO_HASH_ALGO_SHA512] = G_CHECKSUM_SHA512, 35 [QCRYPTO_HASH_ALGO_RIPEMD160] = -1, 36 }; 37 38 gboolean qcrypto_hash_supports(QCryptoHashAlgo alg) 39 { 40 if (alg < G_N_ELEMENTS(qcrypto_hash_alg_map) && 41 qcrypto_hash_alg_map[alg] != -1) { 42 return true; 43 } 44 return false; 45 } 46 47 static 48 QCryptoHash *qcrypto_glib_hash_new(QCryptoHashAlgo alg, 49 Error **errp) 50 { 51 QCryptoHash *hash; 52 53 hash = g_new(QCryptoHash, 1); 54 hash->alg = alg; 55 hash->opaque = g_checksum_new(qcrypto_hash_alg_map[alg]); 56 57 return hash; 58 } 59 60 static 61 void qcrypto_glib_hash_free(QCryptoHash *hash) 62 { 63 if (hash->opaque) { 64 g_checksum_free(hash->opaque); 65 } 66 67 g_free(hash); 68 } 69 70 71 static 72 int qcrypto_glib_hash_update(QCryptoHash *hash, 73 const struct iovec *iov, 74 size_t niov, 75 Error **errp) 76 { 77 GChecksum *ctx = hash->opaque; 78 79 for (int i = 0; i < niov; i++) { 80 g_checksum_update(ctx, iov[i].iov_base, iov[i].iov_len); 81 } 82 83 return 0; 84 } 85 86 static 87 int qcrypto_glib_hash_finalize(QCryptoHash *hash, 88 uint8_t **result, 89 size_t *result_len, 90 Error **errp) 91 { 92 int ret; 93 GChecksum *ctx = hash->opaque; 94 95 ret = g_checksum_type_get_length(qcrypto_hash_alg_map[hash->alg]); 96 if (ret < 0) { 97 error_setg(errp, "Unable to get hash length"); 98 *result_len = 0; 99 return -1; 100 } 101 102 *result_len = ret; 103 *result = g_new(uint8_t, *result_len); 104 105 g_checksum_get_digest(ctx, *result, result_len); 106 return 0; 107 } 108 109 QCryptoHashDriver qcrypto_hash_lib_driver = { 110 .hash_new = qcrypto_glib_hash_new, 111 .hash_update = qcrypto_glib_hash_update, 112 .hash_finalize = qcrypto_glib_hash_finalize, 113 .hash_free = qcrypto_glib_hash_free, 114 }; 115