1 /* 2 * QEMU Crypto hash algorithms 3 * 4 * Copyright (c) 2024 Seagate Technology LLC and/or its Affiliates 5 * Copyright (c) 2016 Red Hat, Inc. 6 * 7 * This library is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU Lesser General Public 9 * License as published by the Free Software Foundation; either 10 * version 2.1 of the License, or (at your option) any later version. 11 * 12 * This library is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * Lesser General Public License for more details. 16 * 17 * You should have received a copy of the GNU Lesser General Public 18 * License along with this library; if not, see <http://www.gnu.org/licenses/>. 19 * 20 */ 21 22 #include "qemu/osdep.h" 23 #include "qapi/error.h" 24 #include "crypto/hash.h" 25 #include "hashpriv.h" 26 #include <nettle/md5.h> 27 #include <nettle/sha.h> 28 #include <nettle/ripemd160.h> 29 #ifdef CONFIG_CRYPTO_SM3 30 #include <nettle/sm3.h> 31 #endif 32 33 typedef void (*qcrypto_nettle_init)(void *ctx); 34 typedef void (*qcrypto_nettle_write)(void *ctx, 35 size_t len, 36 const uint8_t *buf); 37 typedef void (*qcrypto_nettle_result)(void *ctx, 38 size_t len, 39 uint8_t *buf); 40 41 union qcrypto_hash_ctx { 42 struct md5_ctx md5; 43 struct sha1_ctx sha1; 44 struct sha224_ctx sha224; 45 struct sha256_ctx sha256; 46 struct sha384_ctx sha384; 47 struct sha512_ctx sha512; 48 struct ripemd160_ctx ripemd160; 49 #ifdef CONFIG_CRYPTO_SM3 50 struct sm3_ctx sm3; 51 #endif 52 }; 53 54 struct qcrypto_hash_alg { 55 qcrypto_nettle_init init; 56 qcrypto_nettle_write write; 57 qcrypto_nettle_result result; 58 size_t len; 59 } qcrypto_hash_alg_map[] = { 60 [QCRYPTO_HASH_ALGO_MD5] = { 61 .init = (qcrypto_nettle_init)md5_init, 62 .write = (qcrypto_nettle_write)md5_update, 63 .result = (qcrypto_nettle_result)md5_digest, 64 .len = MD5_DIGEST_SIZE, 65 }, 66 [QCRYPTO_HASH_ALGO_SHA1] = { 67 .init = (qcrypto_nettle_init)sha1_init, 68 .write = (qcrypto_nettle_write)sha1_update, 69 .result = (qcrypto_nettle_result)sha1_digest, 70 .len = SHA1_DIGEST_SIZE, 71 }, 72 [QCRYPTO_HASH_ALGO_SHA224] = { 73 .init = (qcrypto_nettle_init)sha224_init, 74 .write = (qcrypto_nettle_write)sha224_update, 75 .result = (qcrypto_nettle_result)sha224_digest, 76 .len = SHA224_DIGEST_SIZE, 77 }, 78 [QCRYPTO_HASH_ALGO_SHA256] = { 79 .init = (qcrypto_nettle_init)sha256_init, 80 .write = (qcrypto_nettle_write)sha256_update, 81 .result = (qcrypto_nettle_result)sha256_digest, 82 .len = SHA256_DIGEST_SIZE, 83 }, 84 [QCRYPTO_HASH_ALGO_SHA384] = { 85 .init = (qcrypto_nettle_init)sha384_init, 86 .write = (qcrypto_nettle_write)sha384_update, 87 .result = (qcrypto_nettle_result)sha384_digest, 88 .len = SHA384_DIGEST_SIZE, 89 }, 90 [QCRYPTO_HASH_ALGO_SHA512] = { 91 .init = (qcrypto_nettle_init)sha512_init, 92 .write = (qcrypto_nettle_write)sha512_update, 93 .result = (qcrypto_nettle_result)sha512_digest, 94 .len = SHA512_DIGEST_SIZE, 95 }, 96 [QCRYPTO_HASH_ALGO_RIPEMD160] = { 97 .init = (qcrypto_nettle_init)ripemd160_init, 98 .write = (qcrypto_nettle_write)ripemd160_update, 99 .result = (qcrypto_nettle_result)ripemd160_digest, 100 .len = RIPEMD160_DIGEST_SIZE, 101 }, 102 #ifdef CONFIG_CRYPTO_SM3 103 [QCRYPTO_HASH_ALGO_SM3] = { 104 .init = (qcrypto_nettle_init)sm3_init, 105 .write = (qcrypto_nettle_write)sm3_update, 106 .result = (qcrypto_nettle_result)sm3_digest, 107 .len = SM3_DIGEST_SIZE, 108 }, 109 #endif 110 }; 111 112 gboolean qcrypto_hash_supports(QCryptoHashAlgo alg) 113 { 114 if (alg < G_N_ELEMENTS(qcrypto_hash_alg_map) && 115 qcrypto_hash_alg_map[alg].init != NULL) { 116 return true; 117 } 118 return false; 119 } 120 121 static 122 QCryptoHash *qcrypto_nettle_hash_new(QCryptoHashAlgo alg, Error **errp) 123 { 124 QCryptoHash *hash; 125 126 hash = g_new(QCryptoHash, 1); 127 hash->alg = alg; 128 hash->opaque = g_new(union qcrypto_hash_ctx, 1); 129 130 qcrypto_hash_alg_map[alg].init(hash->opaque); 131 return hash; 132 } 133 134 static 135 void qcrypto_nettle_hash_free(QCryptoHash *hash) 136 { 137 union qcrypto_hash_ctx *ctx = hash->opaque; 138 139 g_free(ctx); 140 g_free(hash); 141 } 142 143 static 144 int qcrypto_nettle_hash_update(QCryptoHash *hash, 145 const struct iovec *iov, 146 size_t niov, 147 Error **errp) 148 { 149 union qcrypto_hash_ctx *ctx = hash->opaque; 150 151 for (int i = 0; i < niov; i++) { 152 qcrypto_hash_alg_map[hash->alg].write(ctx, 153 iov[i].iov_len, 154 iov[i].iov_base); 155 } 156 157 return 0; 158 } 159 160 static 161 int qcrypto_nettle_hash_finalize(QCryptoHash *hash, 162 uint8_t **result, 163 size_t *result_len, 164 Error **errp) 165 { 166 union qcrypto_hash_ctx *ctx = hash->opaque; 167 int ret = qcrypto_hash_alg_map[hash->alg].len; 168 169 if (*result_len == 0) { 170 *result_len = ret; 171 *result = g_new(uint8_t, *result_len); 172 } else if (*result_len != ret) { 173 error_setg(errp, 174 "Result buffer size %zu is smaller than hash %d", 175 *result_len, ret); 176 return -1; 177 } 178 179 qcrypto_hash_alg_map[hash->alg].result(ctx, *result_len, *result); 180 181 return 0; 182 } 183 184 QCryptoHashDriver qcrypto_hash_lib_driver = { 185 .hash_new = qcrypto_nettle_hash_new, 186 .hash_update = qcrypto_nettle_hash_update, 187 .hash_finalize = qcrypto_nettle_hash_finalize, 188 .hash_free = qcrypto_nettle_hash_free, 189 }; 190