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