Daniel P. Berrange | ddbb0d0 | 2015-07-01 18:10:29 +0100 | [diff] [blame] | 1 | /* |
| 2 | * QEMU Crypto hash algorithms |
| 3 | * |
| 4 | * Copyright (c) 2015 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 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 | |
Peter Maydell | 681c28a | 2016-02-08 18:08:51 +0000 | [diff] [blame] | 21 | #include "qemu/osdep.h" |
Daniel P. Berrange | ddbb0d0 | 2015-07-01 18:10:29 +0100 | [diff] [blame] | 22 | |
| 23 | #include "crypto/init.h" |
| 24 | #include "crypto/hash.h" |
| 25 | |
| 26 | #define INPUT_TEXT "Hiss hisss Hissss hiss Hiss hisss Hiss hiss" |
| 27 | #define INPUT_TEXT1 "Hiss hisss " |
| 28 | #define INPUT_TEXT2 "Hissss hiss " |
| 29 | #define INPUT_TEXT3 "Hiss hisss Hiss hiss" |
| 30 | |
| 31 | #define OUTPUT_MD5 "628d206371563035ab8ef62f492bdec9" |
| 32 | #define OUTPUT_SHA1 "b2e74f26758a3a421e509cee045244b78753cc02" |
Daniel P. Berrange | 9164b89 | 2016-03-11 18:33:08 +0000 | [diff] [blame] | 33 | #define OUTPUT_SHA224 "e2f7415aad33ef79f6516b0986d7175f" \ |
| 34 | "9ca3389a85bf6cfed078737b" |
Daniel P. Berrange | ddbb0d0 | 2015-07-01 18:10:29 +0100 | [diff] [blame] | 35 | #define OUTPUT_SHA256 "bc757abb0436586f392b437e5dd24096" \ |
| 36 | "f7f224de6b74d4d86e2abc6121b160d0" |
Daniel P. Berrange | 9164b89 | 2016-03-11 18:33:08 +0000 | [diff] [blame] | 37 | #define OUTPUT_SHA384 "887ce52efb4f46700376356583b7e279" \ |
| 38 | "4f612bd024e4495087ddb946c448c69d" \ |
| 39 | "56dbf7152a94a5e63a80f3ba9f0eed78" |
| 40 | #define OUTPUT_SHA512 "3a90d79638235ec6c4c11bebd84d83c0" \ |
| 41 | "549bc1e84edc4b6ec7086487641256cb" \ |
| 42 | "63b54e4cb2d2032b393994aa263c0dbb" \ |
| 43 | "e00a9f2fe9ef6037352232a1eec55ee7" |
| 44 | #define OUTPUT_RIPEMD160 "f3d658fad3fdfb2b52c9369cf0d441249ddfa8a0" |
Daniel P. Berrange | ddbb0d0 | 2015-07-01 18:10:29 +0100 | [diff] [blame] | 45 | |
| 46 | #define OUTPUT_MD5_B64 "Yo0gY3FWMDWrjvYvSSveyQ==" |
| 47 | #define OUTPUT_SHA1_B64 "sudPJnWKOkIeUJzuBFJEt4dTzAI=" |
Daniel P. Berrange | 9164b89 | 2016-03-11 18:33:08 +0000 | [diff] [blame] | 48 | #define OUTPUT_SHA224_B64 "4vdBWq0z73n2UWsJhtcXX5yjOJqFv2z+0Hhzew==" |
Daniel P. Berrange | ddbb0d0 | 2015-07-01 18:10:29 +0100 | [diff] [blame] | 49 | #define OUTPUT_SHA256_B64 "vHV6uwQ2WG85K0N+XdJAlvfyJN5rdNTYbiq8YSGxYNA=" |
Daniel P. Berrange | 9164b89 | 2016-03-11 18:33:08 +0000 | [diff] [blame] | 50 | #define OUTPUT_SHA384_B64 "iHzlLvtPRnADdjVlg7fieU9hK9Ak5ElQh925RsRI" \ |
| 51 | "xp1W2/cVKpSl5jqA87qfDu14" |
| 52 | #define OUTPUT_SHA512_B64 "OpDXljgjXsbEwRvr2E2DwFSbwehO3Etuxwhkh2QS" \ |
| 53 | "VstjtU5MstIDKzk5lKomPA274AqfL+nvYDc1IjKh" \ |
| 54 | "7sVe5w==" |
| 55 | #define OUTPUT_RIPEMD160_B64 "89ZY+tP9+ytSyTac8NRBJJ3fqKA=" |
Daniel P. Berrange | ddbb0d0 | 2015-07-01 18:10:29 +0100 | [diff] [blame] | 56 | |
| 57 | static const char *expected_outputs[] = { |
| 58 | [QCRYPTO_HASH_ALG_MD5] = OUTPUT_MD5, |
| 59 | [QCRYPTO_HASH_ALG_SHA1] = OUTPUT_SHA1, |
Daniel P. Berrange | 9164b89 | 2016-03-11 18:33:08 +0000 | [diff] [blame] | 60 | [QCRYPTO_HASH_ALG_SHA224] = OUTPUT_SHA224, |
Daniel P. Berrange | ddbb0d0 | 2015-07-01 18:10:29 +0100 | [diff] [blame] | 61 | [QCRYPTO_HASH_ALG_SHA256] = OUTPUT_SHA256, |
Daniel P. Berrange | 9164b89 | 2016-03-11 18:33:08 +0000 | [diff] [blame] | 62 | [QCRYPTO_HASH_ALG_SHA384] = OUTPUT_SHA384, |
| 63 | [QCRYPTO_HASH_ALG_SHA512] = OUTPUT_SHA512, |
| 64 | [QCRYPTO_HASH_ALG_RIPEMD160] = OUTPUT_RIPEMD160, |
Daniel P. Berrange | ddbb0d0 | 2015-07-01 18:10:29 +0100 | [diff] [blame] | 65 | }; |
| 66 | static const char *expected_outputs_b64[] = { |
| 67 | [QCRYPTO_HASH_ALG_MD5] = OUTPUT_MD5_B64, |
| 68 | [QCRYPTO_HASH_ALG_SHA1] = OUTPUT_SHA1_B64, |
Daniel P. Berrange | 9164b89 | 2016-03-11 18:33:08 +0000 | [diff] [blame] | 69 | [QCRYPTO_HASH_ALG_SHA224] = OUTPUT_SHA224_B64, |
Daniel P. Berrange | ddbb0d0 | 2015-07-01 18:10:29 +0100 | [diff] [blame] | 70 | [QCRYPTO_HASH_ALG_SHA256] = OUTPUT_SHA256_B64, |
Daniel P. Berrange | 9164b89 | 2016-03-11 18:33:08 +0000 | [diff] [blame] | 71 | [QCRYPTO_HASH_ALG_SHA384] = OUTPUT_SHA384_B64, |
| 72 | [QCRYPTO_HASH_ALG_SHA512] = OUTPUT_SHA512_B64, |
| 73 | [QCRYPTO_HASH_ALG_RIPEMD160] = OUTPUT_RIPEMD160_B64, |
Daniel P. Berrange | ddbb0d0 | 2015-07-01 18:10:29 +0100 | [diff] [blame] | 74 | }; |
| 75 | static const int expected_lens[] = { |
| 76 | [QCRYPTO_HASH_ALG_MD5] = 16, |
| 77 | [QCRYPTO_HASH_ALG_SHA1] = 20, |
Daniel P. Berrange | 9164b89 | 2016-03-11 18:33:08 +0000 | [diff] [blame] | 78 | [QCRYPTO_HASH_ALG_SHA224] = 28, |
Daniel P. Berrange | ddbb0d0 | 2015-07-01 18:10:29 +0100 | [diff] [blame] | 79 | [QCRYPTO_HASH_ALG_SHA256] = 32, |
Daniel P. Berrange | 9164b89 | 2016-03-11 18:33:08 +0000 | [diff] [blame] | 80 | [QCRYPTO_HASH_ALG_SHA384] = 48, |
| 81 | [QCRYPTO_HASH_ALG_SHA512] = 64, |
| 82 | [QCRYPTO_HASH_ALG_RIPEMD160] = 20, |
Daniel P. Berrange | ddbb0d0 | 2015-07-01 18:10:29 +0100 | [diff] [blame] | 83 | }; |
| 84 | |
| 85 | static const char hex[] = "0123456789abcdef"; |
| 86 | |
| 87 | /* Test with dynamic allocation */ |
| 88 | static void test_hash_alloc(void) |
| 89 | { |
| 90 | size_t i; |
| 91 | |
Daniel P. Berrange | ddbb0d0 | 2015-07-01 18:10:29 +0100 | [diff] [blame] | 92 | for (i = 0; i < G_N_ELEMENTS(expected_outputs) ; i++) { |
| 93 | uint8_t *result = NULL; |
| 94 | size_t resultlen = 0; |
| 95 | int ret; |
| 96 | size_t j; |
| 97 | |
Daniel P. Berrange | 0c16c05 | 2016-03-11 18:09:22 +0000 | [diff] [blame] | 98 | if (!qcrypto_hash_supports(i)) { |
| 99 | continue; |
| 100 | } |
| 101 | |
Daniel P. Berrange | ddbb0d0 | 2015-07-01 18:10:29 +0100 | [diff] [blame] | 102 | ret = qcrypto_hash_bytes(i, |
| 103 | INPUT_TEXT, |
| 104 | strlen(INPUT_TEXT), |
| 105 | &result, |
| 106 | &resultlen, |
| 107 | NULL); |
| 108 | g_assert(ret == 0); |
| 109 | g_assert(resultlen == expected_lens[i]); |
| 110 | |
| 111 | for (j = 0; j < resultlen; j++) { |
| 112 | g_assert(expected_outputs[i][j * 2] == hex[(result[j] >> 4) & 0xf]); |
| 113 | g_assert(expected_outputs[i][j * 2 + 1] == hex[result[j] & 0xf]); |
| 114 | } |
| 115 | g_free(result); |
| 116 | } |
| 117 | } |
| 118 | |
| 119 | /* Test with caller preallocating */ |
| 120 | static void test_hash_prealloc(void) |
| 121 | { |
| 122 | size_t i; |
| 123 | |
Daniel P. Berrange | ddbb0d0 | 2015-07-01 18:10:29 +0100 | [diff] [blame] | 124 | for (i = 0; i < G_N_ELEMENTS(expected_outputs) ; i++) { |
| 125 | uint8_t *result; |
| 126 | size_t resultlen; |
| 127 | int ret; |
| 128 | size_t j; |
| 129 | |
Daniel P. Berrange | 0c16c05 | 2016-03-11 18:09:22 +0000 | [diff] [blame] | 130 | if (!qcrypto_hash_supports(i)) { |
| 131 | continue; |
| 132 | } |
| 133 | |
Daniel P. Berrange | ddbb0d0 | 2015-07-01 18:10:29 +0100 | [diff] [blame] | 134 | resultlen = expected_lens[i]; |
| 135 | result = g_new0(uint8_t, resultlen); |
| 136 | |
| 137 | ret = qcrypto_hash_bytes(i, |
| 138 | INPUT_TEXT, |
| 139 | strlen(INPUT_TEXT), |
| 140 | &result, |
| 141 | &resultlen, |
| 142 | NULL); |
| 143 | g_assert(ret == 0); |
| 144 | |
| 145 | g_assert(resultlen == expected_lens[i]); |
| 146 | for (j = 0; j < resultlen; j++) { |
| 147 | g_assert(expected_outputs[i][j * 2] == hex[(result[j] >> 4) & 0xf]); |
| 148 | g_assert(expected_outputs[i][j * 2 + 1] == hex[result[j] & 0xf]); |
| 149 | } |
| 150 | g_free(result); |
| 151 | } |
| 152 | } |
| 153 | |
| 154 | |
| 155 | /* Test with dynamic allocation */ |
| 156 | static void test_hash_iov(void) |
| 157 | { |
| 158 | size_t i; |
| 159 | |
Daniel P. Berrange | ddbb0d0 | 2015-07-01 18:10:29 +0100 | [diff] [blame] | 160 | for (i = 0; i < G_N_ELEMENTS(expected_outputs) ; i++) { |
| 161 | struct iovec iov[3] = { |
| 162 | { .iov_base = (char *)INPUT_TEXT1, .iov_len = strlen(INPUT_TEXT1) }, |
| 163 | { .iov_base = (char *)INPUT_TEXT2, .iov_len = strlen(INPUT_TEXT2) }, |
| 164 | { .iov_base = (char *)INPUT_TEXT3, .iov_len = strlen(INPUT_TEXT3) }, |
| 165 | }; |
| 166 | uint8_t *result = NULL; |
| 167 | size_t resultlen = 0; |
| 168 | int ret; |
| 169 | size_t j; |
| 170 | |
Daniel P. Berrange | 0c16c05 | 2016-03-11 18:09:22 +0000 | [diff] [blame] | 171 | if (!qcrypto_hash_supports(i)) { |
| 172 | continue; |
| 173 | } |
| 174 | |
Daniel P. Berrange | ddbb0d0 | 2015-07-01 18:10:29 +0100 | [diff] [blame] | 175 | ret = qcrypto_hash_bytesv(i, |
| 176 | iov, 3, |
| 177 | &result, |
| 178 | &resultlen, |
| 179 | NULL); |
| 180 | g_assert(ret == 0); |
| 181 | g_assert(resultlen == expected_lens[i]); |
| 182 | for (j = 0; j < resultlen; j++) { |
| 183 | g_assert(expected_outputs[i][j * 2] == hex[(result[j] >> 4) & 0xf]); |
| 184 | g_assert(expected_outputs[i][j * 2 + 1] == hex[result[j] & 0xf]); |
| 185 | } |
| 186 | g_free(result); |
| 187 | } |
| 188 | } |
| 189 | |
| 190 | |
| 191 | /* Test with printable hashing */ |
| 192 | static void test_hash_digest(void) |
| 193 | { |
| 194 | size_t i; |
| 195 | |
Daniel P. Berrange | ddbb0d0 | 2015-07-01 18:10:29 +0100 | [diff] [blame] | 196 | for (i = 0; i < G_N_ELEMENTS(expected_outputs) ; i++) { |
| 197 | int ret; |
| 198 | char *digest; |
Daniel P. Berrange | 7b36064 | 2015-10-23 16:14:50 +0100 | [diff] [blame] | 199 | size_t digestsize; |
| 200 | |
Daniel P. Berrange | 0c16c05 | 2016-03-11 18:09:22 +0000 | [diff] [blame] | 201 | if (!qcrypto_hash_supports(i)) { |
| 202 | continue; |
| 203 | } |
| 204 | |
Daniel P. Berrange | 7b36064 | 2015-10-23 16:14:50 +0100 | [diff] [blame] | 205 | digestsize = qcrypto_hash_digest_len(i); |
| 206 | |
| 207 | g_assert_cmpint(digestsize * 2, ==, strlen(expected_outputs[i])); |
Daniel P. Berrange | ddbb0d0 | 2015-07-01 18:10:29 +0100 | [diff] [blame] | 208 | |
| 209 | ret = qcrypto_hash_digest(i, |
| 210 | INPUT_TEXT, |
| 211 | strlen(INPUT_TEXT), |
| 212 | &digest, |
| 213 | NULL); |
| 214 | g_assert(ret == 0); |
Daniel P. Berrange | 0c16c05 | 2016-03-11 18:09:22 +0000 | [diff] [blame] | 215 | g_assert_cmpstr(digest, ==, expected_outputs[i]); |
Daniel P. Berrange | ddbb0d0 | 2015-07-01 18:10:29 +0100 | [diff] [blame] | 216 | g_free(digest); |
| 217 | } |
| 218 | } |
| 219 | |
| 220 | /* Test with base64 encoding */ |
| 221 | static void test_hash_base64(void) |
| 222 | { |
| 223 | size_t i; |
| 224 | |
Daniel P. Berrange | ddbb0d0 | 2015-07-01 18:10:29 +0100 | [diff] [blame] | 225 | for (i = 0; i < G_N_ELEMENTS(expected_outputs) ; i++) { |
| 226 | int ret; |
| 227 | char *digest; |
| 228 | |
Daniel P. Berrange | 0c16c05 | 2016-03-11 18:09:22 +0000 | [diff] [blame] | 229 | if (!qcrypto_hash_supports(i)) { |
| 230 | continue; |
| 231 | } |
| 232 | |
Daniel P. Berrange | ddbb0d0 | 2015-07-01 18:10:29 +0100 | [diff] [blame] | 233 | ret = qcrypto_hash_base64(i, |
| 234 | INPUT_TEXT, |
| 235 | strlen(INPUT_TEXT), |
| 236 | &digest, |
| 237 | NULL); |
| 238 | g_assert(ret == 0); |
Daniel P. Berrange | 0c16c05 | 2016-03-11 18:09:22 +0000 | [diff] [blame] | 239 | g_assert_cmpstr(digest, ==, expected_outputs_b64[i]); |
Daniel P. Berrange | ddbb0d0 | 2015-07-01 18:10:29 +0100 | [diff] [blame] | 240 | g_free(digest); |
| 241 | } |
| 242 | } |
| 243 | |
| 244 | int main(int argc, char **argv) |
| 245 | { |
Daniel P. Berrange | d26d6b5 | 2016-09-29 12:43:35 +0100 | [diff] [blame] | 246 | g_assert(qcrypto_init(NULL) == 0); |
| 247 | |
Daniel P. Berrange | ddbb0d0 | 2015-07-01 18:10:29 +0100 | [diff] [blame] | 248 | g_test_init(&argc, &argv, NULL); |
| 249 | g_test_add_func("/crypto/hash/iov", test_hash_iov); |
| 250 | g_test_add_func("/crypto/hash/alloc", test_hash_alloc); |
| 251 | g_test_add_func("/crypto/hash/prealloc", test_hash_prealloc); |
| 252 | g_test_add_func("/crypto/hash/digest", test_hash_digest); |
| 253 | g_test_add_func("/crypto/hash/base64", test_hash_base64); |
| 254 | return g_test_run(); |
| 255 | } |