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 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"
24 #include <nettle/md5.h>
25 #include <nettle/sha.h>
26 #include <nettle/ripemd160.h>
28 typedef void (*qcrypto_nettle_init
)(void *ctx
);
29 typedef void (*qcrypto_nettle_write
)(void *ctx
,
32 typedef void (*qcrypto_nettle_result
)(void *ctx
,
36 union qcrypto_hash_ctx
{
39 struct sha224_ctx sha224
;
40 struct sha256_ctx sha256
;
41 struct sha384_ctx sha384
;
42 struct sha512_ctx sha512
;
43 struct ripemd160_ctx ripemd160
;
46 struct qcrypto_hash_alg
{
47 qcrypto_nettle_init init
;
48 qcrypto_nettle_write write
;
49 qcrypto_nettle_result result
;
51 } qcrypto_hash_alg_map
[] = {
52 [QCRYPTO_HASH_ALG_MD5
] = {
53 .init
= (qcrypto_nettle_init
)md5_init
,
54 .write
= (qcrypto_nettle_write
)md5_update
,
55 .result
= (qcrypto_nettle_result
)md5_digest
,
56 .len
= MD5_DIGEST_SIZE
,
58 [QCRYPTO_HASH_ALG_SHA1
] = {
59 .init
= (qcrypto_nettle_init
)sha1_init
,
60 .write
= (qcrypto_nettle_write
)sha1_update
,
61 .result
= (qcrypto_nettle_result
)sha1_digest
,
62 .len
= SHA1_DIGEST_SIZE
,
64 [QCRYPTO_HASH_ALG_SHA224
] = {
65 .init
= (qcrypto_nettle_init
)sha224_init
,
66 .write
= (qcrypto_nettle_write
)sha224_update
,
67 .result
= (qcrypto_nettle_result
)sha224_digest
,
68 .len
= SHA224_DIGEST_SIZE
,
70 [QCRYPTO_HASH_ALG_SHA256
] = {
71 .init
= (qcrypto_nettle_init
)sha256_init
,
72 .write
= (qcrypto_nettle_write
)sha256_update
,
73 .result
= (qcrypto_nettle_result
)sha256_digest
,
74 .len
= SHA256_DIGEST_SIZE
,
76 [QCRYPTO_HASH_ALG_SHA384
] = {
77 .init
= (qcrypto_nettle_init
)sha384_init
,
78 .write
= (qcrypto_nettle_write
)sha384_update
,
79 .result
= (qcrypto_nettle_result
)sha384_digest
,
80 .len
= SHA384_DIGEST_SIZE
,
82 [QCRYPTO_HASH_ALG_SHA512
] = {
83 .init
= (qcrypto_nettle_init
)sha512_init
,
84 .write
= (qcrypto_nettle_write
)sha512_update
,
85 .result
= (qcrypto_nettle_result
)sha512_digest
,
86 .len
= SHA512_DIGEST_SIZE
,
88 [QCRYPTO_HASH_ALG_RIPEMD160
] = {
89 .init
= (qcrypto_nettle_init
)ripemd160_init
,
90 .write
= (qcrypto_nettle_write
)ripemd160_update
,
91 .result
= (qcrypto_nettle_result
)ripemd160_digest
,
92 .len
= RIPEMD160_DIGEST_SIZE
,
96 gboolean
qcrypto_hash_supports(QCryptoHashAlgorithm alg
)
98 if (alg
< G_N_ELEMENTS(qcrypto_hash_alg_map
) &&
99 qcrypto_hash_alg_map
[alg
].init
!= NULL
) {
106 int qcrypto_hash_bytesv(QCryptoHashAlgorithm alg
,
107 const struct iovec
*iov
,
114 union qcrypto_hash_ctx ctx
;
116 if (alg
>= G_N_ELEMENTS(qcrypto_hash_alg_map
) ||
117 qcrypto_hash_alg_map
[alg
].init
== NULL
) {
119 "Unknown hash algorithm %d",
124 qcrypto_hash_alg_map
[alg
].init(&ctx
);
126 for (i
= 0; i
< niov
; i
++) {
127 /* Some versions of nettle have functions
128 * declared with 'int' instead of 'size_t'
129 * so to be safe avoid writing more than
130 * UINT_MAX bytes at a time
132 size_t len
= iov
[i
].iov_len
;
133 uint8_t *base
= iov
[i
].iov_base
;
135 size_t shortlen
= MIN(len
, UINT_MAX
);
136 qcrypto_hash_alg_map
[alg
].write(&ctx
, len
, base
);
142 if (*resultlen
== 0) {
143 *resultlen
= qcrypto_hash_alg_map
[alg
].len
;
144 *result
= g_new0(uint8_t, *resultlen
);
145 } else if (*resultlen
!= qcrypto_hash_alg_map
[alg
].len
) {
147 "Result buffer size %zu is smaller than hash %zu",
148 *resultlen
, qcrypto_hash_alg_map
[alg
].len
);
152 qcrypto_hash_alg_map
[alg
].result(&ctx
, *resultlen
, *result
);