xref: /openbmc/qemu/crypto/hash-glib.c (revision 2165477c0f65d20fdfbdb2ddcd4e0e7fe8f61df5)
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