1 /* 2 * QEMU Crypto hash algorithms 3 * 4 * Copyright (c) 2016 Red Hat, Inc. 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 2 of the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library; if not, see <http://www.gnu.org/licenses/>. 18 * 19 */ 20 21 #include "qemu/osdep.h" 22 #include "qapi/error.h" 23 #include "crypto/hash.h" 24 #include "hashpriv.h" 25 26 27 static int qcrypto_hash_alg_map[QCRYPTO_HASH_ALG__MAX] = { 28 [QCRYPTO_HASH_ALG_MD5] = G_CHECKSUM_MD5, 29 [QCRYPTO_HASH_ALG_SHA1] = G_CHECKSUM_SHA1, 30 [QCRYPTO_HASH_ALG_SHA224] = -1, 31 [QCRYPTO_HASH_ALG_SHA256] = G_CHECKSUM_SHA256, 32 [QCRYPTO_HASH_ALG_SHA384] = -1, 33 [QCRYPTO_HASH_ALG_SHA512] = G_CHECKSUM_SHA512, 34 [QCRYPTO_HASH_ALG_RIPEMD160] = -1, 35 }; 36 37 gboolean qcrypto_hash_supports(QCryptoHashAlgorithm alg) 38 { 39 if (alg < G_N_ELEMENTS(qcrypto_hash_alg_map) && 40 qcrypto_hash_alg_map[alg] != -1) { 41 return true; 42 } 43 return false; 44 } 45 46 47 static int 48 qcrypto_glib_hash_bytesv(QCryptoHashAlgorithm alg, 49 const struct iovec *iov, 50 size_t niov, 51 uint8_t **result, 52 size_t *resultlen, 53 Error **errp) 54 { 55 int i, ret; 56 GChecksum *cs; 57 58 if (!qcrypto_hash_supports(alg)) { 59 error_setg(errp, 60 "Unknown hash algorithm %d", 61 alg); 62 return -1; 63 } 64 65 cs = g_checksum_new(qcrypto_hash_alg_map[alg]); 66 67 for (i = 0; i < niov; i++) { 68 g_checksum_update(cs, iov[i].iov_base, iov[i].iov_len); 69 } 70 71 ret = g_checksum_type_get_length(qcrypto_hash_alg_map[alg]); 72 if (ret < 0) { 73 error_setg(errp, "%s", 74 "Unable to get hash length"); 75 goto error; 76 } 77 if (*resultlen == 0) { 78 *resultlen = ret; 79 *result = g_new0(uint8_t, *resultlen); 80 } else if (*resultlen != ret) { 81 error_setg(errp, 82 "Result buffer size %zu is smaller than hash %d", 83 *resultlen, ret); 84 goto error; 85 } 86 87 g_checksum_get_digest(cs, *result, resultlen); 88 89 g_checksum_free(cs); 90 return 0; 91 92 error: 93 g_checksum_free(cs); 94 return -1; 95 } 96 97 98 QCryptoHashDriver qcrypto_hash_lib_driver = { 99 .hash_bytesv = qcrypto_glib_hash_bytesv, 100 }; 101