1 /*
2 * QEMU Crypto hash algorithms
3 *
4 * Copyright (c) 2024 Seagate Technology LLC and/or its Affiliates
5 * Copyright (c) 2015 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
24 #include "crypto/init.h"
25 #include "crypto/hash.h"
26
27 #define INPUT_TEXT "Hiss hisss Hissss hiss Hiss hisss Hiss hiss"
28 #define INPUT_TEXT1 "Hiss hisss "
29 #define INPUT_TEXT2 "Hissss hiss "
30 #define INPUT_TEXT3 "Hiss hisss Hiss hiss"
31
32 #define OUTPUT_MD5 "628d206371563035ab8ef62f492bdec9"
33 #define OUTPUT_SHA1 "b2e74f26758a3a421e509cee045244b78753cc02"
34 #define OUTPUT_SHA224 "e2f7415aad33ef79f6516b0986d7175f" \
35 "9ca3389a85bf6cfed078737b"
36 #define OUTPUT_SHA256 "bc757abb0436586f392b437e5dd24096" \
37 "f7f224de6b74d4d86e2abc6121b160d0"
38 #define OUTPUT_SHA384 "887ce52efb4f46700376356583b7e279" \
39 "4f612bd024e4495087ddb946c448c69d" \
40 "56dbf7152a94a5e63a80f3ba9f0eed78"
41 #define OUTPUT_SHA512 "3a90d79638235ec6c4c11bebd84d83c0" \
42 "549bc1e84edc4b6ec7086487641256cb" \
43 "63b54e4cb2d2032b393994aa263c0dbb" \
44 "e00a9f2fe9ef6037352232a1eec55ee7"
45 #define OUTPUT_RIPEMD160 "f3d658fad3fdfb2b52c9369cf0d441249ddfa8a0"
46 #ifdef CONFIG_CRYPTO_SM3
47 #define OUTPUT_SM3 "d4a97db105b477b84c4f20ec9c31a6c814e2705a0b83a5a89748d75f0ef456a1"
48 #endif
49
50 #define OUTPUT_MD5_B64 "Yo0gY3FWMDWrjvYvSSveyQ=="
51 #define OUTPUT_SHA1_B64 "sudPJnWKOkIeUJzuBFJEt4dTzAI="
52 #define OUTPUT_SHA224_B64 "4vdBWq0z73n2UWsJhtcXX5yjOJqFv2z+0Hhzew=="
53 #define OUTPUT_SHA256_B64 "vHV6uwQ2WG85K0N+XdJAlvfyJN5rdNTYbiq8YSGxYNA="
54 #define OUTPUT_SHA384_B64 "iHzlLvtPRnADdjVlg7fieU9hK9Ak5ElQh925RsRI" \
55 "xp1W2/cVKpSl5jqA87qfDu14"
56 #define OUTPUT_SHA512_B64 "OpDXljgjXsbEwRvr2E2DwFSbwehO3Etuxwhkh2QS" \
57 "VstjtU5MstIDKzk5lKomPA274AqfL+nvYDc1IjKh" \
58 "7sVe5w=="
59 #define OUTPUT_RIPEMD160_B64 "89ZY+tP9+ytSyTac8NRBJJ3fqKA="
60
61 #ifdef CONFIG_CRYPTO_SM3
62 #define OUTPUT_SM3_B64 "1Kl9sQW0d7hMTyDsnDGmyBTicFoLg6Wol0jXXw70VqE="
63 #endif
64
65 static const char *expected_outputs[] = {
66 [QCRYPTO_HASH_ALGO_MD5] = OUTPUT_MD5,
67 [QCRYPTO_HASH_ALGO_SHA1] = OUTPUT_SHA1,
68 [QCRYPTO_HASH_ALGO_SHA224] = OUTPUT_SHA224,
69 [QCRYPTO_HASH_ALGO_SHA256] = OUTPUT_SHA256,
70 [QCRYPTO_HASH_ALGO_SHA384] = OUTPUT_SHA384,
71 [QCRYPTO_HASH_ALGO_SHA512] = OUTPUT_SHA512,
72 [QCRYPTO_HASH_ALGO_RIPEMD160] = OUTPUT_RIPEMD160,
73 #ifdef CONFIG_CRYPTO_SM3
74 [QCRYPTO_HASH_ALGO_SM3] = OUTPUT_SM3,
75 #endif
76 };
77 static const char *expected_outputs_b64[] = {
78 [QCRYPTO_HASH_ALGO_MD5] = OUTPUT_MD5_B64,
79 [QCRYPTO_HASH_ALGO_SHA1] = OUTPUT_SHA1_B64,
80 [QCRYPTO_HASH_ALGO_SHA224] = OUTPUT_SHA224_B64,
81 [QCRYPTO_HASH_ALGO_SHA256] = OUTPUT_SHA256_B64,
82 [QCRYPTO_HASH_ALGO_SHA384] = OUTPUT_SHA384_B64,
83 [QCRYPTO_HASH_ALGO_SHA512] = OUTPUT_SHA512_B64,
84 [QCRYPTO_HASH_ALGO_RIPEMD160] = OUTPUT_RIPEMD160_B64,
85 #ifdef CONFIG_CRYPTO_SM3
86 [QCRYPTO_HASH_ALGO_SM3] = OUTPUT_SM3_B64,
87 #endif
88 };
89 static const int expected_lens[] = {
90 [QCRYPTO_HASH_ALGO_MD5] = 16,
91 [QCRYPTO_HASH_ALGO_SHA1] = 20,
92 [QCRYPTO_HASH_ALGO_SHA224] = 28,
93 [QCRYPTO_HASH_ALGO_SHA256] = 32,
94 [QCRYPTO_HASH_ALGO_SHA384] = 48,
95 [QCRYPTO_HASH_ALGO_SHA512] = 64,
96 [QCRYPTO_HASH_ALGO_RIPEMD160] = 20,
97 #ifdef CONFIG_CRYPTO_SM3
98 [QCRYPTO_HASH_ALGO_SM3] = 32,
99 #endif
100 };
101
102 static const char hex[] = "0123456789abcdef";
103
104 /* Test with dynamic allocation */
test_hash_alloc(void)105 static void test_hash_alloc(void)
106 {
107 size_t i;
108
109 for (i = 0; i < G_N_ELEMENTS(expected_outputs) ; i++) {
110 uint8_t *result = NULL;
111 size_t resultlen = 0;
112 int ret;
113 size_t j;
114
115 if (!qcrypto_hash_supports(i)) {
116 continue;
117 }
118
119 ret = qcrypto_hash_bytes(i,
120 INPUT_TEXT,
121 strlen(INPUT_TEXT),
122 &result,
123 &resultlen,
124 &error_fatal);
125 g_assert(ret == 0);
126 g_assert(resultlen == expected_lens[i]);
127
128 for (j = 0; j < resultlen; j++) {
129 g_assert(expected_outputs[i][j * 2] == hex[(result[j] >> 4) & 0xf]);
130 g_assert(expected_outputs[i][j * 2 + 1] == hex[result[j] & 0xf]);
131 }
132 g_free(result);
133 }
134 }
135
136 /* Test with caller preallocating */
test_hash_prealloc(void)137 static void test_hash_prealloc(void)
138 {
139 size_t i;
140
141 for (i = 0; i < G_N_ELEMENTS(expected_outputs) ; i++) {
142 uint8_t *result, *origresult;
143 size_t resultlen;
144 int ret;
145 size_t j;
146
147 if (!qcrypto_hash_supports(i)) {
148 continue;
149 }
150
151 resultlen = expected_lens[i];
152 origresult = result = g_new0(uint8_t, resultlen);
153
154 ret = qcrypto_hash_bytes(i,
155 INPUT_TEXT,
156 strlen(INPUT_TEXT),
157 &result,
158 &resultlen,
159 &error_fatal);
160 g_assert(ret == 0);
161 /* Validate that our pre-allocated pointer was not replaced */
162 g_assert(result == origresult);
163 g_assert(resultlen == expected_lens[i]);
164 for (j = 0; j < resultlen; j++) {
165 g_assert(expected_outputs[i][j * 2] == hex[(result[j] >> 4) & 0xf]);
166 g_assert(expected_outputs[i][j * 2 + 1] == hex[result[j] & 0xf]);
167 }
168 g_free(result);
169 }
170 }
171
172
173 /* Test with dynamic allocation */
test_hash_iov(void)174 static void test_hash_iov(void)
175 {
176 size_t i;
177
178 for (i = 0; i < G_N_ELEMENTS(expected_outputs) ; i++) {
179 struct iovec iov[3] = {
180 { .iov_base = (char *)INPUT_TEXT1, .iov_len = strlen(INPUT_TEXT1) },
181 { .iov_base = (char *)INPUT_TEXT2, .iov_len = strlen(INPUT_TEXT2) },
182 { .iov_base = (char *)INPUT_TEXT3, .iov_len = strlen(INPUT_TEXT3) },
183 };
184 uint8_t *result = NULL;
185 size_t resultlen = 0;
186 int ret;
187 size_t j;
188
189 if (!qcrypto_hash_supports(i)) {
190 continue;
191 }
192
193 ret = qcrypto_hash_bytesv(i,
194 iov, 3,
195 &result,
196 &resultlen,
197 &error_fatal);
198 g_assert(ret == 0);
199 g_assert(resultlen == expected_lens[i]);
200 for (j = 0; j < resultlen; j++) {
201 g_assert(expected_outputs[i][j * 2] == hex[(result[j] >> 4) & 0xf]);
202 g_assert(expected_outputs[i][j * 2 + 1] == hex[result[j] & 0xf]);
203 }
204 g_free(result);
205 }
206 }
207
208
209 /* Test with printable hashing */
test_hash_digest(void)210 static void test_hash_digest(void)
211 {
212 size_t i;
213
214 for (i = 0; i < G_N_ELEMENTS(expected_outputs) ; i++) {
215 int ret;
216 char *digest;
217 size_t digestsize;
218
219 if (!qcrypto_hash_supports(i)) {
220 continue;
221 }
222
223 digestsize = qcrypto_hash_digest_len(i);
224
225 g_assert_cmpint(digestsize * 2, ==, strlen(expected_outputs[i]));
226
227 ret = qcrypto_hash_digest(i,
228 INPUT_TEXT,
229 strlen(INPUT_TEXT),
230 &digest,
231 &error_fatal);
232 g_assert(ret == 0);
233 g_assert_cmpstr(digest, ==, expected_outputs[i]);
234 g_free(digest);
235 }
236 }
237
238 /* Test with base64 encoding */
test_hash_base64(void)239 static void test_hash_base64(void)
240 {
241 size_t i;
242
243 for (i = 0; i < G_N_ELEMENTS(expected_outputs) ; i++) {
244 int ret;
245 char *digest;
246
247 if (!qcrypto_hash_supports(i)) {
248 continue;
249 }
250
251 ret = qcrypto_hash_base64(i,
252 INPUT_TEXT,
253 strlen(INPUT_TEXT),
254 &digest,
255 &error_fatal);
256 g_assert(ret == 0);
257 g_assert_cmpstr(digest, ==, expected_outputs_b64[i]);
258 g_free(digest);
259 }
260 }
261
test_hash_accumulate(void)262 static void test_hash_accumulate(void)
263 {
264 size_t i;
265
266 for (i = 0; i < G_N_ELEMENTS(expected_outputs) ; i++) {
267 g_autoptr(QCryptoHash) hash = NULL;
268 struct iovec iov[] = {
269 { .iov_base = (char *)INPUT_TEXT1, .iov_len = strlen(INPUT_TEXT1) },
270 { .iov_base = (char *)INPUT_TEXT2, .iov_len = strlen(INPUT_TEXT2) },
271 { .iov_base = (char *)INPUT_TEXT3, .iov_len = strlen(INPUT_TEXT3) },
272 };
273 g_autofree uint8_t *result = NULL;
274 size_t resultlen = 0;
275 int ret;
276 size_t j;
277
278 if (!qcrypto_hash_supports(i)) {
279 continue;
280 }
281
282 hash = qcrypto_hash_new(i, &error_fatal);
283 g_assert(hash != NULL);
284
285 /* Add each iovec to the hash context separately */
286 for (j = 0; j < G_N_ELEMENTS(iov); j++) {
287 ret = qcrypto_hash_updatev(hash,
288 &iov[j], 1,
289 &error_fatal);
290
291 g_assert(ret == 0);
292 }
293
294 ret = qcrypto_hash_finalize_bytes(hash, &result, &resultlen,
295 &error_fatal);
296
297 g_assert(ret == 0);
298 g_assert(resultlen == expected_lens[i]);
299 for (j = 0; j < resultlen; j++) {
300 g_assert(expected_outputs[i][j * 2] == hex[(result[j] >> 4) & 0xf]);
301 g_assert(expected_outputs[i][j * 2 + 1] == hex[result[j] & 0xf]);
302 }
303 }
304 }
305
main(int argc,char ** argv)306 int main(int argc, char **argv)
307 {
308 int ret = qcrypto_init(&error_fatal);
309 g_assert(ret == 0);
310
311 g_test_init(&argc, &argv, NULL);
312 g_test_add_func("/crypto/hash/iov", test_hash_iov);
313 g_test_add_func("/crypto/hash/alloc", test_hash_alloc);
314 g_test_add_func("/crypto/hash/prealloc", test_hash_prealloc);
315 g_test_add_func("/crypto/hash/digest", test_hash_digest);
316 g_test_add_func("/crypto/hash/base64", test_hash_base64);
317 g_test_add_func("/crypto/hash/accumulate", test_hash_accumulate);
318 return g_test_run();
319 }
320