12165477cSDaniel P. Berrange /* 22165477cSDaniel P. Berrange * QEMU Crypto hash algorithms 32165477cSDaniel P. Berrange * 42165477cSDaniel P. Berrange * Copyright (c) 2016 Red Hat, Inc. 52165477cSDaniel P. Berrange * 62165477cSDaniel P. Berrange * This library is free software; you can redistribute it and/or 72165477cSDaniel P. Berrange * modify it under the terms of the GNU Lesser General Public 82165477cSDaniel P. Berrange * License as published by the Free Software Foundation; either 92165477cSDaniel P. Berrange * version 2 of the License, or (at your option) any later version. 102165477cSDaniel P. Berrange * 112165477cSDaniel P. Berrange * This library is distributed in the hope that it will be useful, 122165477cSDaniel P. Berrange * but WITHOUT ANY WARRANTY; without even the implied warranty of 132165477cSDaniel P. Berrange * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 142165477cSDaniel P. Berrange * Lesser General Public License for more details. 152165477cSDaniel P. Berrange * 162165477cSDaniel P. Berrange * You should have received a copy of the GNU Lesser General Public 172165477cSDaniel P. Berrange * License along with this library; if not, see <http://www.gnu.org/licenses/>. 182165477cSDaniel P. Berrange * 192165477cSDaniel P. Berrange */ 202165477cSDaniel P. Berrange 212165477cSDaniel P. Berrange #include "qemu/osdep.h" 222165477cSDaniel P. Berrange #include "qapi/error.h" 232165477cSDaniel P. Berrange #include "crypto/hash.h" 24*aa8efad9SLongpeng(Mike) #include "hashpriv.h" 252165477cSDaniel P. Berrange 262165477cSDaniel P. Berrange 272165477cSDaniel P. Berrange static int qcrypto_hash_alg_map[QCRYPTO_HASH_ALG__MAX] = { 282165477cSDaniel P. Berrange [QCRYPTO_HASH_ALG_MD5] = G_CHECKSUM_MD5, 292165477cSDaniel P. Berrange [QCRYPTO_HASH_ALG_SHA1] = G_CHECKSUM_SHA1, 302165477cSDaniel P. Berrange [QCRYPTO_HASH_ALG_SHA224] = -1, 312165477cSDaniel P. Berrange [QCRYPTO_HASH_ALG_SHA256] = G_CHECKSUM_SHA256, 322165477cSDaniel P. Berrange [QCRYPTO_HASH_ALG_SHA384] = -1, 332165477cSDaniel P. Berrange #if GLIB_CHECK_VERSION(2, 36, 0) 342165477cSDaniel P. Berrange [QCRYPTO_HASH_ALG_SHA512] = G_CHECKSUM_SHA512, 352165477cSDaniel P. Berrange #else 362165477cSDaniel P. Berrange [QCRYPTO_HASH_ALG_SHA512] = -1, 372165477cSDaniel P. Berrange #endif 382165477cSDaniel P. Berrange [QCRYPTO_HASH_ALG_RIPEMD160] = -1, 392165477cSDaniel P. Berrange }; 402165477cSDaniel P. Berrange 412165477cSDaniel P. Berrange gboolean qcrypto_hash_supports(QCryptoHashAlgorithm alg) 422165477cSDaniel P. Berrange { 432165477cSDaniel P. Berrange if (alg < G_N_ELEMENTS(qcrypto_hash_alg_map) && 442165477cSDaniel P. Berrange qcrypto_hash_alg_map[alg] != -1) { 452165477cSDaniel P. Berrange return true; 462165477cSDaniel P. Berrange } 472165477cSDaniel P. Berrange return false; 482165477cSDaniel P. Berrange } 492165477cSDaniel P. Berrange 502165477cSDaniel P. Berrange 51*aa8efad9SLongpeng(Mike) static int 52*aa8efad9SLongpeng(Mike) qcrypto_glib_hash_bytesv(QCryptoHashAlgorithm alg, 532165477cSDaniel P. Berrange const struct iovec *iov, 542165477cSDaniel P. Berrange size_t niov, 552165477cSDaniel P. Berrange uint8_t **result, 562165477cSDaniel P. Berrange size_t *resultlen, 572165477cSDaniel P. Berrange Error **errp) 582165477cSDaniel P. Berrange { 592165477cSDaniel P. Berrange int i, ret; 602165477cSDaniel P. Berrange GChecksum *cs; 612165477cSDaniel P. Berrange 6276032897SDaniel P. Berrange if (!qcrypto_hash_supports(alg)) { 632165477cSDaniel P. Berrange error_setg(errp, 642165477cSDaniel P. Berrange "Unknown hash algorithm %d", 652165477cSDaniel P. Berrange alg); 662165477cSDaniel P. Berrange return -1; 672165477cSDaniel P. Berrange } 682165477cSDaniel P. Berrange 692165477cSDaniel P. Berrange cs = g_checksum_new(qcrypto_hash_alg_map[alg]); 702165477cSDaniel P. Berrange 712165477cSDaniel P. Berrange for (i = 0; i < niov; i++) { 722165477cSDaniel P. Berrange g_checksum_update(cs, iov[i].iov_base, iov[i].iov_len); 732165477cSDaniel P. Berrange } 742165477cSDaniel P. Berrange 752165477cSDaniel P. Berrange ret = g_checksum_type_get_length(qcrypto_hash_alg_map[alg]); 762165477cSDaniel P. Berrange if (ret < 0) { 772165477cSDaniel P. Berrange error_setg(errp, "%s", 782165477cSDaniel P. Berrange "Unable to get hash length"); 792165477cSDaniel P. Berrange goto error; 802165477cSDaniel P. Berrange } 812165477cSDaniel P. Berrange if (*resultlen == 0) { 822165477cSDaniel P. Berrange *resultlen = ret; 832165477cSDaniel P. Berrange *result = g_new0(uint8_t, *resultlen); 842165477cSDaniel P. Berrange } else if (*resultlen != ret) { 852165477cSDaniel P. Berrange error_setg(errp, 862165477cSDaniel P. Berrange "Result buffer size %zu is smaller than hash %d", 872165477cSDaniel P. Berrange *resultlen, ret); 882165477cSDaniel P. Berrange goto error; 892165477cSDaniel P. Berrange } 902165477cSDaniel P. Berrange 912165477cSDaniel P. Berrange g_checksum_get_digest(cs, *result, resultlen); 922165477cSDaniel P. Berrange 932165477cSDaniel P. Berrange g_checksum_free(cs); 942165477cSDaniel P. Berrange return 0; 952165477cSDaniel P. Berrange 962165477cSDaniel P. Berrange error: 972165477cSDaniel P. Berrange g_checksum_free(cs); 982165477cSDaniel P. Berrange return -1; 992165477cSDaniel P. Berrange } 100*aa8efad9SLongpeng(Mike) 101*aa8efad9SLongpeng(Mike) 102*aa8efad9SLongpeng(Mike) QCryptoHashDriver qcrypto_hash_lib_driver = { 103*aa8efad9SLongpeng(Mike) .hash_bytesv = qcrypto_glib_hash_bytesv, 104*aa8efad9SLongpeng(Mike) }; 105