xref: /openbmc/qemu/crypto/hash-nettle.c (revision 731d58b545ef66072d38b428fe0dcd1d691e364c)
10c16c056SDaniel P. Berrange /*
20c16c056SDaniel P. Berrange  * QEMU Crypto hash algorithms
30c16c056SDaniel P. Berrange  *
4278d5960SAlejandro Zeise  * Copyright (c) 2024 Seagate Technology LLC and/or its Affiliates
50c16c056SDaniel P. Berrange  * Copyright (c) 2016 Red Hat, Inc.
60c16c056SDaniel P. Berrange  *
70c16c056SDaniel P. Berrange  * This library is free software; you can redistribute it and/or
80c16c056SDaniel P. Berrange  * modify it under the terms of the GNU Lesser General Public
90c16c056SDaniel 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.
110c16c056SDaniel P. Berrange  *
120c16c056SDaniel P. Berrange  * This library is distributed in the hope that it will be useful,
130c16c056SDaniel P. Berrange  * but WITHOUT ANY WARRANTY; without even the implied warranty of
140c16c056SDaniel P. Berrange  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
150c16c056SDaniel P. Berrange  * Lesser General Public License for more details.
160c16c056SDaniel P. Berrange  *
170c16c056SDaniel P. Berrange  * You should have received a copy of the GNU Lesser General Public
180c16c056SDaniel P. Berrange  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
190c16c056SDaniel P. Berrange  *
200c16c056SDaniel P. Berrange  */
210c16c056SDaniel P. Berrange 
220c16c056SDaniel P. Berrange #include "qemu/osdep.h"
230c16c056SDaniel P. Berrange #include "qapi/error.h"
240c16c056SDaniel P. Berrange #include "crypto/hash.h"
25aa8efad9SLongpeng(Mike) #include "hashpriv.h"
260c16c056SDaniel P. Berrange #include <nettle/md5.h>
270c16c056SDaniel P. Berrange #include <nettle/sha.h>
289164b897SDaniel P. Berrange #include <nettle/ripemd160.h>
29*d078da86Sliequan che #ifdef CONFIG_CRYPTO_SM3
30*d078da86Sliequan che #include <nettle/sm3.h>
31*d078da86Sliequan che #endif
320c16c056SDaniel P. Berrange 
330c16c056SDaniel P. Berrange typedef void (*qcrypto_nettle_init)(void *ctx);
340c16c056SDaniel P. Berrange typedef void (*qcrypto_nettle_write)(void *ctx,
35115e4b70SDaniel P. Berrangé                                      size_t len,
360c16c056SDaniel P. Berrange                                      const uint8_t *buf);
370c16c056SDaniel P. Berrange typedef void (*qcrypto_nettle_result)(void *ctx,
38115e4b70SDaniel P. Berrangé                                       size_t len,
390c16c056SDaniel P. Berrange                                       uint8_t *buf);
400c16c056SDaniel P. Berrange 
410c16c056SDaniel P. Berrange union qcrypto_hash_ctx {
420c16c056SDaniel P. Berrange     struct md5_ctx md5;
430c16c056SDaniel P. Berrange     struct sha1_ctx sha1;
449164b897SDaniel P. Berrange     struct sha224_ctx sha224;
450c16c056SDaniel P. Berrange     struct sha256_ctx sha256;
469164b897SDaniel P. Berrange     struct sha384_ctx sha384;
479164b897SDaniel P. Berrange     struct sha512_ctx sha512;
489164b897SDaniel P. Berrange     struct ripemd160_ctx ripemd160;
49*d078da86Sliequan che #ifdef CONFIG_CRYPTO_SM3
50*d078da86Sliequan che     struct sm3_ctx sm3;
51*d078da86Sliequan che #endif
520c16c056SDaniel P. Berrange };
530c16c056SDaniel P. Berrange 
540c16c056SDaniel P. Berrange struct qcrypto_hash_alg {
550c16c056SDaniel P. Berrange     qcrypto_nettle_init init;
560c16c056SDaniel P. Berrange     qcrypto_nettle_write write;
570c16c056SDaniel P. Berrange     qcrypto_nettle_result result;
580c16c056SDaniel P. Berrange     size_t len;
590c16c056SDaniel P. Berrange } qcrypto_hash_alg_map[] = {
60ef834aa2SMarkus Armbruster     [QCRYPTO_HASH_ALGO_MD5] = {
610c16c056SDaniel P. Berrange         .init = (qcrypto_nettle_init)md5_init,
620c16c056SDaniel P. Berrange         .write = (qcrypto_nettle_write)md5_update,
630c16c056SDaniel P. Berrange         .result = (qcrypto_nettle_result)md5_digest,
640c16c056SDaniel P. Berrange         .len = MD5_DIGEST_SIZE,
650c16c056SDaniel P. Berrange     },
66ef834aa2SMarkus Armbruster     [QCRYPTO_HASH_ALGO_SHA1] = {
670c16c056SDaniel P. Berrange         .init = (qcrypto_nettle_init)sha1_init,
680c16c056SDaniel P. Berrange         .write = (qcrypto_nettle_write)sha1_update,
690c16c056SDaniel P. Berrange         .result = (qcrypto_nettle_result)sha1_digest,
700c16c056SDaniel P. Berrange         .len = SHA1_DIGEST_SIZE,
710c16c056SDaniel P. Berrange     },
72ef834aa2SMarkus Armbruster     [QCRYPTO_HASH_ALGO_SHA224] = {
739164b897SDaniel P. Berrange         .init = (qcrypto_nettle_init)sha224_init,
749164b897SDaniel P. Berrange         .write = (qcrypto_nettle_write)sha224_update,
759164b897SDaniel P. Berrange         .result = (qcrypto_nettle_result)sha224_digest,
769164b897SDaniel P. Berrange         .len = SHA224_DIGEST_SIZE,
779164b897SDaniel P. Berrange     },
78ef834aa2SMarkus Armbruster     [QCRYPTO_HASH_ALGO_SHA256] = {
790c16c056SDaniel P. Berrange         .init = (qcrypto_nettle_init)sha256_init,
800c16c056SDaniel P. Berrange         .write = (qcrypto_nettle_write)sha256_update,
810c16c056SDaniel P. Berrange         .result = (qcrypto_nettle_result)sha256_digest,
820c16c056SDaniel P. Berrange         .len = SHA256_DIGEST_SIZE,
830c16c056SDaniel P. Berrange     },
84ef834aa2SMarkus Armbruster     [QCRYPTO_HASH_ALGO_SHA384] = {
859164b897SDaniel P. Berrange         .init = (qcrypto_nettle_init)sha384_init,
869164b897SDaniel P. Berrange         .write = (qcrypto_nettle_write)sha384_update,
879164b897SDaniel P. Berrange         .result = (qcrypto_nettle_result)sha384_digest,
889164b897SDaniel P. Berrange         .len = SHA384_DIGEST_SIZE,
899164b897SDaniel P. Berrange     },
90ef834aa2SMarkus Armbruster     [QCRYPTO_HASH_ALGO_SHA512] = {
919164b897SDaniel P. Berrange         .init = (qcrypto_nettle_init)sha512_init,
929164b897SDaniel P. Berrange         .write = (qcrypto_nettle_write)sha512_update,
939164b897SDaniel P. Berrange         .result = (qcrypto_nettle_result)sha512_digest,
949164b897SDaniel P. Berrange         .len = SHA512_DIGEST_SIZE,
959164b897SDaniel P. Berrange     },
96ef834aa2SMarkus Armbruster     [QCRYPTO_HASH_ALGO_RIPEMD160] = {
979164b897SDaniel P. Berrange         .init = (qcrypto_nettle_init)ripemd160_init,
989164b897SDaniel P. Berrange         .write = (qcrypto_nettle_write)ripemd160_update,
999164b897SDaniel P. Berrange         .result = (qcrypto_nettle_result)ripemd160_digest,
1009164b897SDaniel P. Berrange         .len = RIPEMD160_DIGEST_SIZE,
1019164b897SDaniel P. Berrange     },
102*d078da86Sliequan che #ifdef CONFIG_CRYPTO_SM3
103*d078da86Sliequan che     [QCRYPTO_HASH_ALGO_SM3] = {
104*d078da86Sliequan che         .init = (qcrypto_nettle_init)sm3_init,
105*d078da86Sliequan che         .write = (qcrypto_nettle_write)sm3_update,
106*d078da86Sliequan che         .result = (qcrypto_nettle_result)sm3_digest,
107*d078da86Sliequan che         .len = SM3_DIGEST_SIZE,
108*d078da86Sliequan che     },
109*d078da86Sliequan che #endif
1100c16c056SDaniel P. Berrange };
1110c16c056SDaniel P. Berrange 
qcrypto_hash_supports(QCryptoHashAlgo alg)112ef834aa2SMarkus Armbruster gboolean qcrypto_hash_supports(QCryptoHashAlgo alg)
1130c16c056SDaniel P. Berrange {
1140c16c056SDaniel P. Berrange     if (alg < G_N_ELEMENTS(qcrypto_hash_alg_map) &&
1150c16c056SDaniel P. Berrange         qcrypto_hash_alg_map[alg].init != NULL) {
1160c16c056SDaniel P. Berrange         return true;
1170c16c056SDaniel P. Berrange     }
1180c16c056SDaniel P. Berrange     return false;
1190c16c056SDaniel P. Berrange }
1200c16c056SDaniel P. Berrange 
121278d5960SAlejandro Zeise static
qcrypto_nettle_hash_new(QCryptoHashAlgo alg,Error ** errp)122278d5960SAlejandro Zeise QCryptoHash *qcrypto_nettle_hash_new(QCryptoHashAlgo alg, Error **errp)
123278d5960SAlejandro Zeise {
124278d5960SAlejandro Zeise     QCryptoHash *hash;
125278d5960SAlejandro Zeise 
126278d5960SAlejandro Zeise     hash = g_new(QCryptoHash, 1);
127278d5960SAlejandro Zeise     hash->alg = alg;
128278d5960SAlejandro Zeise     hash->opaque = g_new(union qcrypto_hash_ctx, 1);
129278d5960SAlejandro Zeise 
130278d5960SAlejandro Zeise     qcrypto_hash_alg_map[alg].init(hash->opaque);
131278d5960SAlejandro Zeise     return hash;
132278d5960SAlejandro Zeise }
133278d5960SAlejandro Zeise 
134278d5960SAlejandro Zeise static
qcrypto_nettle_hash_free(QCryptoHash * hash)135278d5960SAlejandro Zeise void qcrypto_nettle_hash_free(QCryptoHash *hash)
136278d5960SAlejandro Zeise {
137278d5960SAlejandro Zeise     union qcrypto_hash_ctx *ctx = hash->opaque;
138278d5960SAlejandro Zeise 
139278d5960SAlejandro Zeise     g_free(ctx);
140278d5960SAlejandro Zeise     g_free(hash);
141278d5960SAlejandro Zeise }
142278d5960SAlejandro Zeise 
143278d5960SAlejandro Zeise static
qcrypto_nettle_hash_update(QCryptoHash * hash,const struct iovec * iov,size_t niov,Error ** errp)144278d5960SAlejandro Zeise int qcrypto_nettle_hash_update(QCryptoHash *hash,
145278d5960SAlejandro Zeise                                const struct iovec *iov,
146278d5960SAlejandro Zeise                                size_t niov,
147278d5960SAlejandro Zeise                                Error **errp)
148278d5960SAlejandro Zeise {
149278d5960SAlejandro Zeise     union qcrypto_hash_ctx *ctx = hash->opaque;
150278d5960SAlejandro Zeise 
151278d5960SAlejandro Zeise     for (int i = 0; i < niov; i++) {
15295cc223aSDaniel P. Berrangé         qcrypto_hash_alg_map[hash->alg].write(ctx,
15395cc223aSDaniel P. Berrangé                                               iov[i].iov_len,
15495cc223aSDaniel P. Berrangé                                               iov[i].iov_base);
155278d5960SAlejandro Zeise     }
156278d5960SAlejandro Zeise 
157278d5960SAlejandro Zeise     return 0;
158278d5960SAlejandro Zeise }
159278d5960SAlejandro Zeise 
160278d5960SAlejandro Zeise static
qcrypto_nettle_hash_finalize(QCryptoHash * hash,uint8_t ** result,size_t * result_len,Error ** errp)161278d5960SAlejandro Zeise int qcrypto_nettle_hash_finalize(QCryptoHash *hash,
162278d5960SAlejandro Zeise                                  uint8_t **result,
163278d5960SAlejandro Zeise                                  size_t *result_len,
164278d5960SAlejandro Zeise                                  Error **errp)
165278d5960SAlejandro Zeise {
166278d5960SAlejandro Zeise     union qcrypto_hash_ctx *ctx = hash->opaque;
167dde538c9SDaniel P. Berrangé     int ret = qcrypto_hash_alg_map[hash->alg].len;
168278d5960SAlejandro Zeise 
169dde538c9SDaniel P. Berrangé     if (*result_len == 0) {
170dde538c9SDaniel P. Berrangé         *result_len = ret;
171278d5960SAlejandro Zeise         *result = g_new(uint8_t, *result_len);
172dde538c9SDaniel P. Berrangé     } else if (*result_len != ret) {
173dde538c9SDaniel P. Berrangé         error_setg(errp,
174dde538c9SDaniel P. Berrangé                    "Result buffer size %zu is smaller than hash %d",
175dde538c9SDaniel P. Berrangé                    *result_len, ret);
176dde538c9SDaniel P. Berrangé         return -1;
177dde538c9SDaniel P. Berrangé     }
178278d5960SAlejandro Zeise 
179278d5960SAlejandro Zeise     qcrypto_hash_alg_map[hash->alg].result(ctx, *result_len, *result);
180278d5960SAlejandro Zeise 
181278d5960SAlejandro Zeise     return 0;
182278d5960SAlejandro Zeise }
183aa8efad9SLongpeng(Mike) 
184aa8efad9SLongpeng(Mike) QCryptoHashDriver qcrypto_hash_lib_driver = {
185278d5960SAlejandro Zeise     .hash_new      = qcrypto_nettle_hash_new,
186278d5960SAlejandro Zeise     .hash_update   = qcrypto_nettle_hash_update,
187278d5960SAlejandro Zeise     .hash_finalize = qcrypto_nettle_hash_finalize,
188278d5960SAlejandro Zeise     .hash_free     = qcrypto_nettle_hash_free,
189aa8efad9SLongpeng(Mike) };
190