1ddbb0d09SDaniel P. Berrange /*
2ddbb0d09SDaniel P. Berrange * QEMU Crypto hash algorithms
3ddbb0d09SDaniel P. Berrange *
4e3c07527SAlejandro Zeise * Copyright (c) 2024 Seagate Technology LLC and/or its Affiliates
5ddbb0d09SDaniel P. Berrange * Copyright (c) 2015 Red Hat, Inc.
6ddbb0d09SDaniel P. Berrange *
7ddbb0d09SDaniel P. Berrange * This library is free software; you can redistribute it and/or
8ddbb0d09SDaniel P. Berrange * modify it under the terms of the GNU Lesser General Public
9ddbb0d09SDaniel P. Berrange * License as published by the Free Software Foundation; either
10b7cbb874SThomas Huth * version 2.1 of the License, or (at your option) any later version.
11ddbb0d09SDaniel P. Berrange *
12ddbb0d09SDaniel P. Berrange * This library is distributed in the hope that it will be useful,
13ddbb0d09SDaniel P. Berrange * but WITHOUT ANY WARRANTY; without even the implied warranty of
14ddbb0d09SDaniel P. Berrange * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15ddbb0d09SDaniel P. Berrange * Lesser General Public License for more details.
16ddbb0d09SDaniel P. Berrange *
17ddbb0d09SDaniel P. Berrange * You should have received a copy of the GNU Lesser General Public
18ddbb0d09SDaniel P. Berrange * License along with this library; if not, see <http://www.gnu.org/licenses/>.
19ddbb0d09SDaniel P. Berrange *
20ddbb0d09SDaniel P. Berrange */
21ddbb0d09SDaniel P. Berrange
2242f7a448SPeter Maydell #include "qemu/osdep.h"
23e3c07527SAlejandro Zeise #include "qapi/error.h"
24e3c07527SAlejandro Zeise #include "qapi-types-crypto.h"
25ddbb0d09SDaniel P. Berrange #include "crypto/hash.h"
26aa8efad9SLongpeng(Mike) #include "hashpriv.h"
27ddbb0d09SDaniel P. Berrange
28ef834aa2SMarkus Armbruster static size_t qcrypto_hash_alg_size[QCRYPTO_HASH_ALGO__MAX] = {
29ef834aa2SMarkus Armbruster [QCRYPTO_HASH_ALGO_MD5] = QCRYPTO_HASH_DIGEST_LEN_MD5,
30ef834aa2SMarkus Armbruster [QCRYPTO_HASH_ALGO_SHA1] = QCRYPTO_HASH_DIGEST_LEN_SHA1,
31ef834aa2SMarkus Armbruster [QCRYPTO_HASH_ALGO_SHA224] = QCRYPTO_HASH_DIGEST_LEN_SHA224,
32ef834aa2SMarkus Armbruster [QCRYPTO_HASH_ALGO_SHA256] = QCRYPTO_HASH_DIGEST_LEN_SHA256,
33ef834aa2SMarkus Armbruster [QCRYPTO_HASH_ALGO_SHA384] = QCRYPTO_HASH_DIGEST_LEN_SHA384,
34ef834aa2SMarkus Armbruster [QCRYPTO_HASH_ALGO_SHA512] = QCRYPTO_HASH_DIGEST_LEN_SHA512,
35ef834aa2SMarkus Armbruster [QCRYPTO_HASH_ALGO_RIPEMD160] = QCRYPTO_HASH_DIGEST_LEN_RIPEMD160,
36*d078da86Sliequan che #ifdef CONFIG_CRYPTO_SM3
37*d078da86Sliequan che [QCRYPTO_HASH_ALGO_SM3] = QCRYPTO_HASH_DIGEST_LEN_SM3,
38*d078da86Sliequan che #endif
397b36064cSDaniel P. Berrange };
407b36064cSDaniel P. Berrange
qcrypto_hash_digest_len(QCryptoHashAlgo alg)41ef834aa2SMarkus Armbruster size_t qcrypto_hash_digest_len(QCryptoHashAlgo alg)
42c0377a7cSDaniel P. Berrange {
43b35c1f33SPaolo Bonzini assert(alg < G_N_ELEMENTS(qcrypto_hash_alg_size));
44c0377a7cSDaniel P. Berrange return qcrypto_hash_alg_size[alg];
45c0377a7cSDaniel P. Berrange }
46c0377a7cSDaniel P. Berrange
qcrypto_hash_bytesv(QCryptoHashAlgo alg,const struct iovec * iov,size_t niov,uint8_t ** result,size_t * resultlen,Error ** errp)47ef834aa2SMarkus Armbruster int qcrypto_hash_bytesv(QCryptoHashAlgo alg,
48aa8efad9SLongpeng(Mike) const struct iovec *iov,
49aa8efad9SLongpeng(Mike) size_t niov,
50aa8efad9SLongpeng(Mike) uint8_t **result,
51aa8efad9SLongpeng(Mike) size_t *resultlen,
52aa8efad9SLongpeng(Mike) Error **errp)
53aa8efad9SLongpeng(Mike) {
54e3c07527SAlejandro Zeise g_autoptr(QCryptoHash) ctx = qcrypto_hash_new(alg, errp);
559a059773SLongpeng(Mike)
56e3c07527SAlejandro Zeise if (!ctx) {
57e3c07527SAlejandro Zeise return -1;
58e3c07527SAlejandro Zeise }
59e3c07527SAlejandro Zeise
60e3c07527SAlejandro Zeise if (qcrypto_hash_updatev(ctx, iov, niov, errp) < 0 ||
61e3c07527SAlejandro Zeise qcrypto_hash_finalize_bytes(ctx, result, resultlen, errp) < 0) {
62e3c07527SAlejandro Zeise return -1;
63e3c07527SAlejandro Zeise }
64e3c07527SAlejandro Zeise
65e3c07527SAlejandro Zeise return 0;
66aa8efad9SLongpeng(Mike) }
67aa8efad9SLongpeng(Mike)
68c0377a7cSDaniel P. Berrange
qcrypto_hash_bytes(QCryptoHashAlgo alg,const char * buf,size_t len,uint8_t ** result,size_t * resultlen,Error ** errp)69ef834aa2SMarkus Armbruster int qcrypto_hash_bytes(QCryptoHashAlgo alg,
70ddbb0d09SDaniel P. Berrange const char *buf,
71ddbb0d09SDaniel P. Berrange size_t len,
72ddbb0d09SDaniel P. Berrange uint8_t **result,
73ddbb0d09SDaniel P. Berrange size_t *resultlen,
74ddbb0d09SDaniel P. Berrange Error **errp)
75ddbb0d09SDaniel P. Berrange {
76ddbb0d09SDaniel P. Berrange struct iovec iov = { .iov_base = (char *)buf,
77ddbb0d09SDaniel P. Berrange .iov_len = len };
78ddbb0d09SDaniel P. Berrange return qcrypto_hash_bytesv(alg, &iov, 1, result, resultlen, errp);
79ddbb0d09SDaniel P. Berrange }
80ddbb0d09SDaniel P. Berrange
qcrypto_hash_updatev(QCryptoHash * hash,const struct iovec * iov,size_t niov,Error ** errp)81e3c07527SAlejandro Zeise int qcrypto_hash_updatev(QCryptoHash *hash,
82e3c07527SAlejandro Zeise const struct iovec *iov,
83e3c07527SAlejandro Zeise size_t niov,
84e3c07527SAlejandro Zeise Error **errp)
85e3c07527SAlejandro Zeise {
86e3c07527SAlejandro Zeise QCryptoHashDriver *drv = hash->driver;
87e3c07527SAlejandro Zeise
88e3c07527SAlejandro Zeise return drv->hash_update(hash, iov, niov, errp);
89e3c07527SAlejandro Zeise }
90e3c07527SAlejandro Zeise
qcrypto_hash_update(QCryptoHash * hash,const char * buf,size_t len,Error ** errp)91e3c07527SAlejandro Zeise int qcrypto_hash_update(QCryptoHash *hash,
92e3c07527SAlejandro Zeise const char *buf,
93e3c07527SAlejandro Zeise size_t len,
94e3c07527SAlejandro Zeise Error **errp)
95e3c07527SAlejandro Zeise {
96e3c07527SAlejandro Zeise struct iovec iov = { .iov_base = (char *)buf, .iov_len = len };
97e3c07527SAlejandro Zeise
98e3c07527SAlejandro Zeise return qcrypto_hash_updatev(hash, &iov, 1, errp);
99e3c07527SAlejandro Zeise }
100e3c07527SAlejandro Zeise
qcrypto_hash_new(QCryptoHashAlgo alg,Error ** errp)101e3c07527SAlejandro Zeise QCryptoHash *qcrypto_hash_new(QCryptoHashAlgo alg, Error **errp)
102e3c07527SAlejandro Zeise {
103e3c07527SAlejandro Zeise QCryptoHash *hash = NULL;
104e3c07527SAlejandro Zeise
105e3c07527SAlejandro Zeise if (!qcrypto_hash_supports(alg)) {
106e3c07527SAlejandro Zeise error_setg(errp, "Unsupported hash algorithm %s",
107e3c07527SAlejandro Zeise QCryptoHashAlgo_str(alg));
108e3c07527SAlejandro Zeise return NULL;
109e3c07527SAlejandro Zeise }
110e3c07527SAlejandro Zeise
111e3c07527SAlejandro Zeise #ifdef CONFIG_AF_ALG
112e3c07527SAlejandro Zeise hash = qcrypto_hash_afalg_driver.hash_new(alg, NULL);
113e3c07527SAlejandro Zeise if (hash) {
114e3c07527SAlejandro Zeise hash->driver = &qcrypto_hash_afalg_driver;
115e3c07527SAlejandro Zeise return hash;
116e3c07527SAlejandro Zeise }
117e3c07527SAlejandro Zeise #endif
118e3c07527SAlejandro Zeise
119e3c07527SAlejandro Zeise hash = qcrypto_hash_lib_driver.hash_new(alg, errp);
120e3c07527SAlejandro Zeise if (!hash) {
121e3c07527SAlejandro Zeise return NULL;
122e3c07527SAlejandro Zeise }
123e3c07527SAlejandro Zeise
124e3c07527SAlejandro Zeise hash->driver = &qcrypto_hash_lib_driver;
125e3c07527SAlejandro Zeise return hash;
126e3c07527SAlejandro Zeise }
127e3c07527SAlejandro Zeise
qcrypto_hash_free(QCryptoHash * hash)128e3c07527SAlejandro Zeise void qcrypto_hash_free(QCryptoHash *hash)
129e3c07527SAlejandro Zeise {
130e3c07527SAlejandro Zeise QCryptoHashDriver *drv;
131e3c07527SAlejandro Zeise
132e3c07527SAlejandro Zeise if (hash) {
133e3c07527SAlejandro Zeise drv = hash->driver;
134e3c07527SAlejandro Zeise drv->hash_free(hash);
135e3c07527SAlejandro Zeise }
136e3c07527SAlejandro Zeise }
137e3c07527SAlejandro Zeise
qcrypto_hash_finalize_bytes(QCryptoHash * hash,uint8_t ** result,size_t * result_len,Error ** errp)138e3c07527SAlejandro Zeise int qcrypto_hash_finalize_bytes(QCryptoHash *hash,
139e3c07527SAlejandro Zeise uint8_t **result,
140e3c07527SAlejandro Zeise size_t *result_len,
141e3c07527SAlejandro Zeise Error **errp)
142e3c07527SAlejandro Zeise {
143e3c07527SAlejandro Zeise QCryptoHashDriver *drv = hash->driver;
144e3c07527SAlejandro Zeise
145e3c07527SAlejandro Zeise return drv->hash_finalize(hash, result, result_len, errp);
146e3c07527SAlejandro Zeise }
147e3c07527SAlejandro Zeise
148ddbb0d09SDaniel P. Berrange static const char hex[] = "0123456789abcdef";
149ddbb0d09SDaniel P. Berrange
qcrypto_hash_finalize_digest(QCryptoHash * hash,char ** digest,Error ** errp)150e3c07527SAlejandro Zeise int qcrypto_hash_finalize_digest(QCryptoHash *hash,
151e3c07527SAlejandro Zeise char **digest,
152e3c07527SAlejandro Zeise Error **errp)
153e3c07527SAlejandro Zeise {
154e3c07527SAlejandro Zeise int ret;
155e3c07527SAlejandro Zeise g_autofree uint8_t *result = NULL;
156e3c07527SAlejandro Zeise size_t resultlen = 0;
157e3c07527SAlejandro Zeise size_t i;
158e3c07527SAlejandro Zeise
159e3c07527SAlejandro Zeise ret = qcrypto_hash_finalize_bytes(hash, &result, &resultlen, errp);
160e3c07527SAlejandro Zeise if (ret == 0) {
161e3c07527SAlejandro Zeise *digest = g_new0(char, (resultlen * 2) + 1);
162e3c07527SAlejandro Zeise for (i = 0 ; i < resultlen ; i++) {
163e3c07527SAlejandro Zeise (*digest)[(i * 2)] = hex[(result[i] >> 4) & 0xf];
164e3c07527SAlejandro Zeise (*digest)[(i * 2) + 1] = hex[result[i] & 0xf];
165e3c07527SAlejandro Zeise }
166e3c07527SAlejandro Zeise (*digest)[resultlen * 2] = '\0';
167e3c07527SAlejandro Zeise }
168e3c07527SAlejandro Zeise
169e3c07527SAlejandro Zeise return ret;
170e3c07527SAlejandro Zeise }
171e3c07527SAlejandro Zeise
qcrypto_hash_finalize_base64(QCryptoHash * hash,char ** base64,Error ** errp)172e3c07527SAlejandro Zeise int qcrypto_hash_finalize_base64(QCryptoHash *hash,
173e3c07527SAlejandro Zeise char **base64,
174e3c07527SAlejandro Zeise Error **errp)
175e3c07527SAlejandro Zeise {
176e3c07527SAlejandro Zeise int ret;
177e3c07527SAlejandro Zeise g_autofree uint8_t *result = NULL;
178e3c07527SAlejandro Zeise size_t resultlen = 0;
179e3c07527SAlejandro Zeise
180e3c07527SAlejandro Zeise ret = qcrypto_hash_finalize_bytes(hash, &result, &resultlen, errp);
181e3c07527SAlejandro Zeise if (ret == 0) {
182e3c07527SAlejandro Zeise *base64 = g_base64_encode(result, resultlen);
183e3c07527SAlejandro Zeise }
184e3c07527SAlejandro Zeise
185e3c07527SAlejandro Zeise return ret;
186e3c07527SAlejandro Zeise }
187e3c07527SAlejandro Zeise
qcrypto_hash_digestv(QCryptoHashAlgo alg,const struct iovec * iov,size_t niov,char ** digest,Error ** errp)188ef834aa2SMarkus Armbruster int qcrypto_hash_digestv(QCryptoHashAlgo alg,
189ddbb0d09SDaniel P. Berrange const struct iovec *iov,
190ddbb0d09SDaniel P. Berrange size_t niov,
191ddbb0d09SDaniel P. Berrange char **digest,
192ddbb0d09SDaniel P. Berrange Error **errp)
193ddbb0d09SDaniel P. Berrange {
194e3c07527SAlejandro Zeise g_autoptr(QCryptoHash) ctx = qcrypto_hash_new(alg, errp);
195ddbb0d09SDaniel P. Berrange
196e3c07527SAlejandro Zeise if (!ctx) {
197ddbb0d09SDaniel P. Berrange return -1;
198ddbb0d09SDaniel P. Berrange }
199ddbb0d09SDaniel P. Berrange
200e3c07527SAlejandro Zeise if (qcrypto_hash_updatev(ctx, iov, niov, errp) < 0 ||
201e3c07527SAlejandro Zeise qcrypto_hash_finalize_digest(ctx, digest, errp) < 0) {
202e3c07527SAlejandro Zeise return -1;
203ddbb0d09SDaniel P. Berrange }
204e3c07527SAlejandro Zeise
205ddbb0d09SDaniel P. Berrange return 0;
206ddbb0d09SDaniel P. Berrange }
207ddbb0d09SDaniel P. Berrange
qcrypto_hash_digest(QCryptoHashAlgo alg,const char * buf,size_t len,char ** digest,Error ** errp)208ef834aa2SMarkus Armbruster int qcrypto_hash_digest(QCryptoHashAlgo alg,
209ddbb0d09SDaniel P. Berrange const char *buf,
210ddbb0d09SDaniel P. Berrange size_t len,
211ddbb0d09SDaniel P. Berrange char **digest,
212ddbb0d09SDaniel P. Berrange Error **errp)
213ddbb0d09SDaniel P. Berrange {
214ddbb0d09SDaniel P. Berrange struct iovec iov = { .iov_base = (char *)buf, .iov_len = len };
215ddbb0d09SDaniel P. Berrange
216ddbb0d09SDaniel P. Berrange return qcrypto_hash_digestv(alg, &iov, 1, digest, errp);
217ddbb0d09SDaniel P. Berrange }
218ddbb0d09SDaniel P. Berrange
qcrypto_hash_base64v(QCryptoHashAlgo alg,const struct iovec * iov,size_t niov,char ** base64,Error ** errp)219ef834aa2SMarkus Armbruster int qcrypto_hash_base64v(QCryptoHashAlgo alg,
220ddbb0d09SDaniel P. Berrange const struct iovec *iov,
221ddbb0d09SDaniel P. Berrange size_t niov,
222ddbb0d09SDaniel P. Berrange char **base64,
223ddbb0d09SDaniel P. Berrange Error **errp)
224ddbb0d09SDaniel P. Berrange {
225e3c07527SAlejandro Zeise g_autoptr(QCryptoHash) ctx = qcrypto_hash_new(alg, errp);
226ddbb0d09SDaniel P. Berrange
227e3c07527SAlejandro Zeise if (!ctx) {
228ddbb0d09SDaniel P. Berrange return -1;
229ddbb0d09SDaniel P. Berrange }
230ddbb0d09SDaniel P. Berrange
231e3c07527SAlejandro Zeise if (qcrypto_hash_updatev(ctx, iov, niov, errp) < 0 ||
232e3c07527SAlejandro Zeise qcrypto_hash_finalize_base64(ctx, base64, errp) < 0) {
233e3c07527SAlejandro Zeise return -1;
234e3c07527SAlejandro Zeise }
235e3c07527SAlejandro Zeise
236ddbb0d09SDaniel P. Berrange return 0;
237ddbb0d09SDaniel P. Berrange }
238ddbb0d09SDaniel P. Berrange
qcrypto_hash_base64(QCryptoHashAlgo alg,const char * buf,size_t len,char ** base64,Error ** errp)239ef834aa2SMarkus Armbruster int qcrypto_hash_base64(QCryptoHashAlgo alg,
240ddbb0d09SDaniel P. Berrange const char *buf,
241ddbb0d09SDaniel P. Berrange size_t len,
242ddbb0d09SDaniel P. Berrange char **base64,
243ddbb0d09SDaniel P. Berrange Error **errp)
244ddbb0d09SDaniel P. Berrange {
245ddbb0d09SDaniel P. Berrange struct iovec iov = { .iov_base = (char *)buf, .iov_len = len };
246ddbb0d09SDaniel P. Berrange
247ddbb0d09SDaniel P. Berrange return qcrypto_hash_base64v(alg, &iov, 1, base64, errp);
248ddbb0d09SDaniel P. Berrange }
249