2 * QEMU Crypto hash algorithms
4 * Copyright (c) 2016 Red Hat, Inc.
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.
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.
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/>.
21 #include "qemu/osdep.h"
22 #include "qapi/error.h"
23 #include "crypto/hash.h"
25 #include <nettle/md5.h>
26 #include <nettle/sha.h>
27 #include <nettle/ripemd160.h>
29 typedef void (*qcrypto_nettle_init
)(void *ctx
);
30 typedef void (*qcrypto_nettle_write
)(void *ctx
,
33 typedef void (*qcrypto_nettle_result
)(void *ctx
,
37 union qcrypto_hash_ctx
{
40 struct sha224_ctx sha224
;
41 struct sha256_ctx sha256
;
42 struct sha384_ctx sha384
;
43 struct sha512_ctx sha512
;
44 struct ripemd160_ctx ripemd160
;
47 struct qcrypto_hash_alg
{
48 qcrypto_nettle_init init
;
49 qcrypto_nettle_write write
;
50 qcrypto_nettle_result result
;
52 } qcrypto_hash_alg_map
[] = {
53 [QCRYPTO_HASH_ALG_MD5
] = {
54 .init
= (qcrypto_nettle_init
)md5_init
,
55 .write
= (qcrypto_nettle_write
)md5_update
,
56 .result
= (qcrypto_nettle_result
)md5_digest
,
57 .len
= MD5_DIGEST_SIZE
,
59 [QCRYPTO_HASH_ALG_SHA1
] = {
60 .init
= (qcrypto_nettle_init
)sha1_init
,
61 .write
= (qcrypto_nettle_write
)sha1_update
,
62 .result
= (qcrypto_nettle_result
)sha1_digest
,
63 .len
= SHA1_DIGEST_SIZE
,
65 [QCRYPTO_HASH_ALG_SHA224
] = {
66 .init
= (qcrypto_nettle_init
)sha224_init
,
67 .write
= (qcrypto_nettle_write
)sha224_update
,
68 .result
= (qcrypto_nettle_result
)sha224_digest
,
69 .len
= SHA224_DIGEST_SIZE
,
71 [QCRYPTO_HASH_ALG_SHA256
] = {
72 .init
= (qcrypto_nettle_init
)sha256_init
,
73 .write
= (qcrypto_nettle_write
)sha256_update
,
74 .result
= (qcrypto_nettle_result
)sha256_digest
,
75 .len
= SHA256_DIGEST_SIZE
,
77 [QCRYPTO_HASH_ALG_SHA384
] = {
78 .init
= (qcrypto_nettle_init
)sha384_init
,
79 .write
= (qcrypto_nettle_write
)sha384_update
,
80 .result
= (qcrypto_nettle_result
)sha384_digest
,
81 .len
= SHA384_DIGEST_SIZE
,
83 [QCRYPTO_HASH_ALG_SHA512
] = {
84 .init
= (qcrypto_nettle_init
)sha512_init
,
85 .write
= (qcrypto_nettle_write
)sha512_update
,
86 .result
= (qcrypto_nettle_result
)sha512_digest
,
87 .len
= SHA512_DIGEST_SIZE
,
89 [QCRYPTO_HASH_ALG_RIPEMD160
] = {
90 .init
= (qcrypto_nettle_init
)ripemd160_init
,
91 .write
= (qcrypto_nettle_write
)ripemd160_update
,
92 .result
= (qcrypto_nettle_result
)ripemd160_digest
,
93 .len
= RIPEMD160_DIGEST_SIZE
,
97 gboolean
qcrypto_hash_supports(QCryptoHashAlgorithm alg
)
99 if (alg
< G_N_ELEMENTS(qcrypto_hash_alg_map
) &&
100 qcrypto_hash_alg_map
[alg
].init
!= NULL
) {
108 qcrypto_nettle_hash_bytesv(QCryptoHashAlgorithm alg
,
109 const struct iovec
*iov
,
116 union qcrypto_hash_ctx ctx
;
118 if (!qcrypto_hash_supports(alg
)) {
120 "Unknown hash algorithm %d",
125 qcrypto_hash_alg_map
[alg
].init(&ctx
);
127 for (i
= 0; i
< niov
; i
++) {
128 /* Some versions of nettle have functions
129 * declared with 'int' instead of 'size_t'
130 * so to be safe avoid writing more than
131 * UINT_MAX bytes at a time
133 size_t len
= iov
[i
].iov_len
;
134 uint8_t *base
= iov
[i
].iov_base
;
136 size_t shortlen
= MIN(len
, UINT_MAX
);
137 qcrypto_hash_alg_map
[alg
].write(&ctx
, len
, base
);
143 if (*resultlen
== 0) {
144 *resultlen
= qcrypto_hash_alg_map
[alg
].len
;
145 *result
= g_new0(uint8_t, *resultlen
);
146 } else if (*resultlen
!= qcrypto_hash_alg_map
[alg
].len
) {
148 "Result buffer size %zu is smaller than hash %zu",
149 *resultlen
, qcrypto_hash_alg_map
[alg
].len
);
153 qcrypto_hash_alg_map
[alg
].result(&ctx
, *resultlen
, *result
);
159 QCryptoHashDriver qcrypto_hash_lib_driver
= {
160 .hash_bytesv
= qcrypto_nettle_hash_bytesv
,