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