unit_md5.c (26950B)
1 /* SPDX-License-Identifier: LGPL-2.1-or-later OR (GPL-2.0-or-later WITH eCos-exception-2.0) */ 2 /* 3 This file is part of GNU libmicrohttpd. 4 Copyright (C) 2025 Christian Grothoff 5 6 GNU libmicrohttpd 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 GNU libmicrohttpd 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 Alternatively, you can redistribute GNU libmicrohttpd and/or 17 modify it under the terms of the GNU General Public License as 18 published by the Free Software Foundation; either version 2 of 19 the License, or (at your option) any later version, together 20 with the eCos exception, as follows: 21 22 As a special exception, if other files instantiate templates or 23 use macros or inline functions from this file, or you compile this 24 file and link it with other works to produce a work based on this 25 file, this file does not by itself cause the resulting work to be 26 covered by the GNU General Public License. However the source code 27 for this file must still be made available in accordance with 28 section (3) of the GNU General Public License v2. 29 30 This exception does not invalidate any other reasons why a work 31 based on this file might be covered by the GNU General Public 32 License. 33 34 You should have received copies of the GNU Lesser General Public 35 License and the GNU General Public License along with this library; 36 if not, see <https://www.gnu.org/licenses/>. 37 */ 38 39 /** 40 * @file src/test/unit/unit_md5.c 41 * @brief Unit tests for md5 functions 42 * @author Karlson2k (Evgeny Grin) & Christian Grothoff 43 */ 44 45 #include <stdio.h> 46 #include <stdlib.h> 47 #include <string.h> 48 #include <stdint.h> 49 50 #include "mhd_sys_options.h" 51 52 #if MHD_MD5_EXTR_OPENSSL 53 #include "../mhd2/md5_ext_openssl.c" 54 #elif MHD_MD5_EXTR_GNUTLS 55 #include "../mhd2/md5_ext_gnutls.c" 56 #elif MHD_MD5_EXTR_MBEDTLS 57 #include "../mhd2/md5_ext_mbedtls.c" 58 #else 59 #include "../mhd2/md5_int.c" 60 #endif 61 62 #include "../mhd2/mhd_md5.h" 63 64 #define MD5_DIGEST_STRING_SIZE (mhd_MD5_DIGEST_SIZE * 2 + 1) 65 66 /** 67 * Verbose output? 68 */ 69 static int verbose; 70 71 72 /** 73 * Check whether one of strings in array is equal to @a param. 74 * String @a argv[0] is ignored. 75 * @param argc number of strings in @a argv, as passed to main function 76 * @param argv array of strings, as passed to main function 77 * @param param parameter to look for. 78 * @return zero if @a argv is NULL, @a param is NULL or empty string, 79 * @a argc is less then 2 or @a param is not found in @a argv, 80 * non-zero if one of strings in @a argv is equal to @a param. 81 */ 82 static int 83 has_param (int argc, char *const argv[], const char *param) 84 { 85 int i; 86 if (! argv || ! param || ! param[0]) 87 return 0; 88 89 for (i = 1; i < argc; i++) 90 { 91 if (argv[i] && (strcmp (argv[i], param) == 0) ) 92 return ! 0; 93 } 94 95 return 0; 96 } 97 98 99 /* Define to 1 if libmicrohttpd is compiled with MD5 hashing by OpenSSL. */ 100 /* #undef MHD_MD5_EXTR_OPENSSL */ 101 102 /* Helper function to convert hex string to binary */ 103 static size_t 104 hex2bin (const char *hex, 105 uint8_t *bin, 106 size_t max_len) 107 { 108 size_t len = strlen (hex) / 2; 109 110 if (len > max_len) 111 len = max_len; 112 for (size_t i = 0; i < len; i++) 113 { 114 sscanf (hex + 2 * i, 115 "%2hhx", 116 &bin[i]); 117 } 118 return len; 119 } 120 121 122 /* 123 * Helper functions 124 */ 125 126 /** 127 * Print bin as hex 128 * 129 * @param bin binary data 130 * @param len number of bytes in bin 131 * @param hex pointer to len*2+1 bytes buffer 132 */ 133 static void 134 bin2hex (const uint8_t *bin, 135 size_t len, 136 char *hex) 137 { 138 while (len-- > 0) 139 { 140 unsigned int b1, b2; 141 b1 = (*bin >> 4) & 0xf; 142 *hex++ = (char) ((b1 > 9) ? (b1 + 'A' - 10) : (b1 + '0')); 143 b2 = *bin++ & 0xf; 144 *hex++ = (char) ((b2 > 9) ? (b2 + 'A' - 10) : (b2 + '0')); 145 } 146 *hex = 0; 147 } 148 149 150 static int 151 check_result (const char *test_name, 152 unsigned int check_num, 153 const uint8_t calculated[mhd_MD5_DIGEST_SIZE], 154 const uint8_t expected[mhd_MD5_DIGEST_SIZE]) 155 { 156 int failed = memcmp (calculated, 157 expected, 158 mhd_MD5_DIGEST_SIZE); 159 160 check_num++; /* Print 1-based numbers */ 161 if (failed) 162 { 163 char calc_str[MD5_DIGEST_STRING_SIZE]; 164 char expc_str[MD5_DIGEST_STRING_SIZE]; 165 166 bin2hex (calculated, 167 mhd_MD5_DIGEST_SIZE, 168 calc_str); 169 bin2hex (expected, 170 mhd_MD5_DIGEST_SIZE, 171 expc_str); 172 fprintf (stderr, 173 "FAILED: %s check %u: calculated digest %s, expected digest %s.\n", 174 test_name, 175 check_num, 176 calc_str, 177 expc_str); 178 fflush (stderr); 179 return 1; 180 } 181 if (verbose) 182 { 183 char calc_str[MD5_DIGEST_STRING_SIZE]; 184 185 bin2hex (calculated, 186 mhd_MD5_DIGEST_SIZE, 187 calc_str); 188 fprintf (stderr, 189 "PASSED: %s check %u: calculated digest %s " 190 "matches expected digest.\n", 191 test_name, 192 check_num, 193 calc_str); 194 fflush (stdout); 195 } 196 return 0; 197 } 198 199 200 struct str_with_len 201 { 202 const char *const str; 203 const size_t len; 204 }; 205 206 #define D_STR_W_LEN(s) {(s), (sizeof((s)) / sizeof(char)) - 1} 207 208 struct data_unit1 209 { 210 const struct str_with_len str_l; 211 const uint8_t digest[mhd_MD5_DIGEST_SIZE]; 212 }; 213 214 215 static const struct data_unit1 data_units1[] = { 216 {D_STR_W_LEN ("1234567890!@~%&$@#{}[]\\/!?`."), 217 {0x1c, 0x68, 0xc2, 0xe5, 0x1f, 0x63, 0xc9, 0x5f, 0x17, 0xab, 0x1f, 0x20, 218 0x8b, 0x86, 0x39, 0x57}}, 219 {D_STR_W_LEN ("Simple string."), 220 {0xf1, 0x2b, 0x7c, 0xad, 0xa0, 0x41, 0xfe, 0xde, 0x4e, 0x68, 0x16, 0x63, 221 0xb4, 0x60, 0x5d, 0x78}}, 222 {D_STR_W_LEN ("abcdefghijklmnopqrstuvwxyz"), 223 {0xc3, 0xfc, 0xd3, 0xd7, 0x61, 0x92, 0xe4, 0x00, 0x7d, 0xfb, 0x49, 0x6c, 224 0xca, 0x67, 0xe1, 0x3b}}, 225 {D_STR_W_LEN ("zyxwvutsrqponMLKJIHGFEDCBA"), 226 {0x05, 0x61, 0x3a, 0x6b, 0xde, 0x75, 0x3a, 0x45, 0x91, 0xa8, 0x81, 0xb0, 227 0xa7, 0xe2, 0xe2, 0x0e}}, 228 {D_STR_W_LEN ("abcdefghijklmnopqrstuvwxyzzyxwvutsrqponMLKJIHGFEDCBA" \ 229 "abcdefghijklmnopqrstuvwxyzzyxwvutsrqponMLKJIHGFEDCBA"), 230 {0xaf, 0xab, 0xc7, 0xe9, 0xe7, 0x17, 0xbe, 0xd6, 0xc0, 0x0f, 0x78, 0x8c, 231 0xde, 0xdd, 0x11, 0xd1}}, 232 {D_STR_W_LEN ("/long/long/long/long/long/long/long/long/long/long/long" \ 233 "/long/long/long/long/long/long/long/long/long/long/long" \ 234 "/long/long/long/long/long/long/long/long/long/long/long" \ 235 "/long/long/long/long/long/long/long/long/long/long/long" \ 236 "/long/long/long/long/long/long/long/long/long/long/long" \ 237 "/long/long/long/long/long/long/long/long/long/long/long" \ 238 "/long/long/long/long/path?with%20some=parameters"), 239 {0x7e, 0xe6, 0xdb, 0xe2, 0x76, 0x49, 0x1a, 0xd8, 0xaf, 0xf3, 0x52, 0x2d, 240 0xd8, 0xfc, 0x89, 0x1e}}, 241 {D_STR_W_LEN (""), 242 {0xd4, 0x1d, 0x8c, 0xd9, 0x8f, 0x00, 0xb2, 0x04, 0xe9, 0x80, 0x09, 0x98, 243 0xec, 0xf8, 0x42, 0x7e}}, 244 {D_STR_W_LEN ("a"), 245 {0x0c, 0xc1, 0x75, 0xb9, 0xc0, 0xf1, 0xb6, 0xa8, 0x31, 0xc3, 0x99, 0xe2, 246 0x69, 0x77, 0x26, 0x61}}, 247 {D_STR_W_LEN ("abc"), 248 {0x90, 0x01, 0x50, 0x98, 0x3c, 0xd2, 0x4f, 0xb0, 0xd6, 0x96, 0x3f, 0x7d, 249 0x28, 0xe1, 0x7f, 0x72}}, 250 {D_STR_W_LEN ("message digest"), 251 {0xf9, 0x6b, 0x69, 0x7d, 0x7c, 0xb7, 0x93, 0x8d, 0x52, 0x5a, 0x2f, 0x31, 252 0xaa, 0xf1, 0x61, 0xd0}}, 253 {D_STR_W_LEN ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" \ 254 "0123456789"), 255 {0xd1, 0x74, 0xab, 0x98, 0xd2, 0x77, 0xd9, 0xf5, 0xa5, 0x61, 0x1c, 0x2c, 256 0x9f, 0x41, 0x9d, 0x9f}}, 257 {D_STR_W_LEN ("12345678901234567890123456789012345678901234567890" \ 258 "123456789012345678901234567890"), 259 {0x57, 0xed, 0xf4, 0xa2, 0x2b, 0xe3, 0xc9, 0x55, 0xac, 0x49, 0xda, 0x2e, 260 0x21, 0x07, 0xb6, 0x7a}} 261 }; 262 263 static const size_t units1_num = sizeof(data_units1) / sizeof(data_units1[0]); 264 265 /* Calculated MD5 as one pass for whole data */ 266 static int 267 test1_str (void) 268 { 269 unsigned int i; 270 int num_failed = 0; 271 struct mhd_Md5Ctx ctx; 272 273 mhd_MD5_init_one_time (&ctx); 274 for (i = 0; i < units1_num; i++) 275 { 276 uint8_t digest[mhd_MD5_DIGEST_SIZE]; 277 278 mhd_MD5_update (&ctx, 279 data_units1[i].str_l.len, 280 (const uint8_t *) data_units1[i].str_l.str); 281 mhd_MD5_finish_reset (&ctx, 282 digest); 283 if (mhd_MD5_has_err (&ctx)) 284 { 285 fprintf (stderr, 286 "External hashing error: %d.\n", 287 ctx.ext_error); 288 exit (99); 289 } 290 num_failed += check_result (MHD_FUNC_, 291 i, 292 digest, 293 data_units1[i].digest); 294 } 295 mhd_MD5_deinit (&ctx); 296 return num_failed; 297 } 298 299 300 struct bin_with_len 301 { 302 const uint8_t bin[512]; 303 const size_t len; 304 }; 305 306 struct data_unit2 307 { 308 const struct bin_with_len bin_l; 309 const uint8_t digest[mhd_MD5_DIGEST_SIZE]; 310 }; 311 312 313 static const struct data_unit2 data_units2[] = { 314 { { {97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 315 112, 113, 114, 115, 116, 316 117, 118, 119, 120, 121, 122}, 26}, /* a..z ASCII sequence */ 317 {0xc3, 0xfc, 0xd3, 0xd7, 0x61, 0x92, 0xe4, 0x00, 0x7d, 0xfb, 0x49, 0x6c, 318 0xca, 0x67, 0xe1, 0x3b}}, 319 { { {65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 320 65, 65, 65, 65, 65, 65, 321 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 322 65, 65, 65, 65, 65, 65, 323 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 324 65, 65, 65, 65, 65, 65}, 72 },/* 'A' x 72 times */ 325 {0x24, 0xa5, 0xef, 0x36, 0x82, 0x80, 0x3a, 0x06, 0x2f, 0xea, 0xad, 0xad, 326 0x76, 0xda, 0xbd, 0xa8}}, 327 { { {19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 328 37, 38, 39, 40, 41, 42, 329 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 330 61, 62, 63, 64, 65, 66, 67, 331 68, 69, 70, 71, 72, 73}, 55}, /* 19..73 sequence */ 332 {0x6d, 0x2e, 0x6e, 0xde, 0x5d, 0x64, 0x6a, 0x17, 0xf1, 0x09, 0x2c, 0xac, 333 0x19, 0x10, 0xe3, 0xd6}}, 334 { { {7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 335 26, 27, 28, 29, 30, 31, 336 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 337 50, 51, 52, 53, 54, 55, 56, 338 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69}, 63}, /* 7..69 sequence */ 339 {0x88, 0x13, 0x48, 0x47, 0x73, 0xaa, 0x92, 0xf2, 0xc9, 0xdd, 0x69, 0xb3, 340 0xac, 0xf4, 0xba, 0x6e}}, 341 { { {38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 342 56, 57, 58, 59, 60, 61, 343 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 344 80, 81, 82, 83, 84, 85, 86, 345 87, 88, 89, 90, 91, 92}, 55}, /* 38..92 sequence */ 346 {0x80, 0xf0, 0x05, 0x7e, 0xa2, 0xf7, 0xc8, 0x43, 0x12, 0xd3, 0xb1, 0x61, 347 0xab, 0x52, 0x3b, 0xaf}}, 348 { { {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 349 21, 22, 23, 24, 25, 26, 27, 350 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 351 46, 47, 48, 49, 50, 51, 52, 352 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 353 71, 72}, 354 72},/* 1..72 sequence */ 355 {0xc3, 0x28, 0xc5, 0xad, 0xc9, 0x26, 0xa9, 0x99, 0x95, 0x4a, 0x5e, 0x25, 356 0x50, 0x34, 0x51, 0x73}}, 357 { { {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 358 21, 22, 23, 24, 25, 26, 359 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 360 45, 46, 47, 48, 49, 50, 51, 361 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 362 70, 71, 72, 73, 74, 75, 76, 363 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 364 95, 96, 97, 98, 99, 100, 365 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 366 115, 116, 117, 118, 119, 120, 367 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 368 135, 136, 137, 138, 139, 140, 369 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 370 155, 156, 157, 158, 159, 160, 371 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 372 175, 176, 177, 178, 179, 180, 373 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 374 195, 196, 197, 198, 199, 200, 375 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 376 215, 216, 217, 218, 219, 220, 377 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 378 235, 236, 237, 238, 239, 240, 379 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 380 255}, 256}, /* 0..255 sequence */ 381 {0xe2, 0xc8, 0x65, 0xdb, 0x41, 0x62, 0xbe, 0xd9, 0x63, 0xbf, 0xaa, 0x9e, 382 0xf6, 0xac, 0x18, 0xf0}}, 383 { { {199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 384 185, 184, 183, 182, 181, 180, 385 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 386 165, 164, 163, 162, 161, 160, 387 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 388 145, 144, 143, 142, 141, 140, 389 139}, 61}, /* 199..139 sequence */ 390 {0xbb, 0x3f, 0xdb, 0x4a, 0x96, 0x03, 0x36, 0x37, 0x38, 0x78, 0x5e, 0x44, 391 0xbf, 0x3a, 0x85, 0x51}}, 392 { { {255, 254, 253, 252, 251, 250, 249, 248, 247, 246, 245, 244, 243, 242, 393 241, 240, 239, 238, 237, 236, 394 235, 234, 233, 232, 231, 230, 229, 228, 227, 226, 225, 224, 223, 222, 395 221, 220, 219, 218, 217, 216, 396 215, 214, 213, 212, 211, 210, 209, 208, 207, 206, 205, 204, 203, 202, 397 201, 200, 199, 198, 197, 196, 398 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 399 181, 180, 179, 178, 177, 176, 400 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 401 161, 160, 159, 158, 157, 156, 402 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142, 403 141, 140, 139, 138, 137, 136, 404 135, 134, 133, 132, 131, 130, 129, 128, 127, 126, 125, 124, 123, 122, 405 121, 120, 119, 118, 117, 116, 406 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, 407 101, 100, 99, 98, 97, 96, 95, 408 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 409 76, 75, 74, 73, 72, 71, 70, 410 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 411 51, 50, 49, 48, 47, 46, 45, 412 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 413 26, 25, 24, 23, 22, 21, 20, 414 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1}, 255}, /* 255..1 sequence */ 415 {0x52, 0x21, 0xa5, 0x83, 0x4f, 0x38, 0x7c, 0x73, 0xba, 0x18, 0x22, 0xb1, 416 0xf9, 0x7e, 0xae, 0x8b}}, 417 { { {41, 35, 190, 132, 225, 108, 214, 174, 82, 144, 73, 241, 241, 187, 233, 418 235, 179, 166, 219, 60, 135, 419 12, 62, 153, 36, 94, 13, 28, 6, 183, 71, 222, 179, 18, 77, 200, 67, 187, 420 139, 166, 31, 3, 90, 125, 9, 421 56, 37, 31, 93, 212, 203, 252, 150, 245, 69, 59, 19, 13, 137, 10, 28, 422 219, 174, 50, 32, 154, 80, 238, 423 64, 120, 54, 253, 18, 73, 50, 246, 158, 125, 73, 220, 173, 79, 20, 242, 424 68, 64, 102, 208, 107, 196, 425 48, 183, 50, 59, 161, 34, 246, 34, 145, 157, 225, 139, 31, 218, 176, 202, 426 153, 2, 185, 114, 157, 73, 427 44, 128, 126, 197, 153, 213, 233, 128, 178, 234, 201, 204, 83, 191, 103, 428 214, 191, 20, 214, 126, 45, 429 220, 142, 102, 131, 239, 87, 73, 97, 255, 105, 143, 97, 205, 209, 30, 430 157, 156, 22, 114, 114, 230, 431 29, 240, 132, 79, 74, 119, 2, 215, 232, 57, 44, 83, 203, 201, 18, 30, 51, 432 116, 158, 12, 244, 213, 433 212, 159, 212, 164, 89, 126, 53, 207, 50, 34, 244, 204, 207, 211, 144, 434 45, 72, 211, 143, 117, 230, 435 217, 29, 42, 229, 192, 247, 43, 120, 129, 135, 68, 14, 95, 80, 0, 212, 436 97, 141, 190, 123, 5, 21, 7, 437 59, 51, 130, 31, 24, 112, 146, 218, 100, 84, 206, 177, 133, 62, 105, 21, 438 248, 70, 106, 4, 150, 115, 439 14, 217, 22, 47, 103, 104, 212, 247, 74, 74, 208, 87, 104}, 255}, /* pseudo-random data */ 440 {0x55, 0x61, 0x2c, 0xeb, 0x29, 0xee, 0xa8, 0xb2, 0xf6, 0x10, 0x7b, 0xc1, 441 0x5b, 0x0f, 0x01, 0x95}} 442 }; 443 static const size_t units2_num = sizeof(data_units2) / sizeof(data_units2[0]); 444 445 446 static int 447 test1_bin (void) 448 { 449 unsigned int i; 450 int num_failed = 0; 451 struct mhd_Md5Ctx ctx; 452 453 mhd_MD5_init_one_time (&ctx); 454 for (i = 0; i < units2_num; i++) 455 { 456 uint8_t digest[mhd_MD5_DIGEST_SIZE]; 457 458 mhd_MD5_update (&ctx, 459 data_units2[i].bin_l.len, 460 data_units2[i].bin_l.bin); 461 mhd_MD5_finish_reset (&ctx, 462 digest); 463 if (mhd_MD5_has_err (&ctx)) 464 { 465 fprintf (stderr, 466 "External hashing error: %d.\n", 467 ctx.ext_error); 468 exit (99); 469 } 470 num_failed += check_result (MHD_FUNC_, 471 i, 472 digest, 473 data_units2[i].digest); 474 } 475 mhd_MD5_deinit (&ctx); 476 return num_failed; 477 } 478 479 480 /* Calculated MD5 as two iterations for whole data */ 481 static int 482 test2_str (void) 483 { 484 unsigned int i; 485 int num_failed = 0; 486 struct mhd_Md5Ctx ctx; 487 488 mhd_MD5_init_one_time (&ctx); 489 for (i = 0; i < units1_num; i++) 490 { 491 uint8_t digest[mhd_MD5_DIGEST_SIZE]; 492 size_t part_s = data_units1[i].str_l.len / 4; 493 494 mhd_MD5_update (&ctx, 495 0, 496 (const uint8_t *) ""); 497 mhd_MD5_update (&ctx, 498 part_s, 499 (const uint8_t *) data_units1[i].str_l.str); 500 mhd_MD5_update (&ctx, 501 0, 502 (const uint8_t *) ""); 503 mhd_MD5_update (&ctx, 504 data_units1[i].str_l.len - part_s, 505 (const uint8_t *) data_units1[i].str_l.str + part_s); 506 mhd_MD5_update (&ctx, 507 0, 508 (const uint8_t *) ""); 509 mhd_MD5_finish_reset (&ctx, 510 digest); 511 if (mhd_MD5_has_err (&ctx)) 512 { 513 fprintf (stderr, 514 "External hashing error: %d.\n", 515 ctx.ext_error); 516 exit (99); 517 } 518 num_failed += check_result (MHD_FUNC_, 519 i, 520 digest, 521 data_units1[i].digest); 522 } 523 mhd_MD5_deinit (&ctx); 524 return num_failed; 525 } 526 527 528 static int 529 test2_bin (void) 530 { 531 unsigned int i; 532 int num_failed = 0; 533 struct mhd_Md5Ctx ctx; 534 535 mhd_MD5_init_one_time (&ctx); 536 537 for (i = 0; i < units2_num; i++) 538 { 539 uint8_t digest[mhd_MD5_DIGEST_SIZE]; 540 size_t part_s = data_units2[i].bin_l.len * 2 / 3; 541 542 mhd_MD5_update (&ctx, 543 part_s, 544 data_units2[i].bin_l.bin); 545 mhd_MD5_update (&ctx, 546 0, 547 (const uint8_t *) ""); 548 mhd_MD5_update (&ctx, 549 data_units2[i].bin_l.len - part_s, 550 data_units2[i].bin_l.bin + part_s); 551 mhd_MD5_finish_reset (&ctx, 552 digest); 553 if (mhd_MD5_has_err (&ctx)) 554 { 555 fprintf (stderr, 556 "External hashing error: %d.\n", 557 ctx.ext_error); 558 exit (99); 559 } 560 num_failed += check_result (MHD_FUNC_, 561 i, 562 digest, 563 data_units2[i].digest); 564 } 565 mhd_MD5_deinit (&ctx); 566 return num_failed; 567 } 568 569 570 /* Use data set number 7 as it has the longest sequence */ 571 #define DATA_POS 6 572 #define MAX_OFFSET 31 573 574 static int 575 test_unaligned (void) 576 { 577 const struct data_unit2 *const tdata = data_units2 + DATA_POS; 578 int num_failed = 0; 579 unsigned int offset; 580 uint8_t *buf; 581 uint8_t *digest_buf; 582 struct mhd_Md5Ctx ctx; 583 584 buf = malloc (tdata->bin_l.len + MAX_OFFSET); 585 digest_buf = malloc (mhd_MD5_DIGEST_SIZE + MAX_OFFSET); 586 if ( (NULL == buf) || 587 (NULL == digest_buf) ) 588 exit (99); 589 590 mhd_MD5_init_one_time (&ctx); 591 592 for (offset = MAX_OFFSET; offset >= 1; --offset) 593 { 594 uint8_t *unaligned_digest; 595 uint8_t *unaligned_buf; 596 597 unaligned_buf = buf + offset; 598 memcpy (unaligned_buf, 599 tdata->bin_l.bin, 600 tdata->bin_l.len); 601 unaligned_digest = digest_buf + MAX_OFFSET - offset; 602 memset (unaligned_digest, 603 0, 604 mhd_MD5_DIGEST_SIZE); 605 mhd_MD5_update (&ctx, 606 tdata->bin_l.len, 607 unaligned_buf); 608 mhd_MD5_finish_reset (&ctx, 609 unaligned_digest); 610 if (mhd_MD5_has_err (&ctx)) 611 { 612 fprintf (stderr, 613 "External hashing error: %d.\n", 614 ctx.ext_error); 615 exit (99); 616 } 617 num_failed += check_result (MHD_FUNC_, 618 MAX_OFFSET - offset, 619 unaligned_digest, 620 tdata->digest); 621 } 622 mhd_MD5_deinit (&ctx); 623 free (digest_buf); 624 free (buf); 625 return num_failed; 626 } 627 628 629 /* Helper function to compare digest with expected hex string */ 630 static int 631 check_digest (const uint8_t *digest, 632 size_t digest_len, 633 const char *expected_hex, 634 const char *test_name) 635 { 636 uint8_t expected[64]; 637 size_t expected_len = hex2bin (expected_hex, 638 expected, 639 sizeof(expected)); 640 641 if (expected_len != digest_len) 642 { 643 printf ("FAIL: %s - length mismatch\n", 644 test_name); 645 return 0; 646 } 647 648 if (0 != 649 memcmp (digest, 650 expected, 651 digest_len)) 652 { 653 printf ("FAIL: %s\n", 654 test_name); 655 printf (" Expected: %s\n", 656 expected_hex); 657 printf (" Got: "); 658 for (size_t i = 0; i < digest_len; i++) 659 { 660 printf ("%02x", 661 digest[i]); 662 } 663 printf ("\n"); 664 return 0; 665 } 666 return 1; 667 } 668 669 670 int 671 main (int argc, 672 char **argv) 673 { 674 struct Test 675 { 676 const char *name; 677 const char *input; 678 const char *digest; 679 } tests[] = { 680 { "Empty string (RFC 1321)", 681 "", 682 "d41d8cd98f00b204e9800998ecf8427e" }, 683 { "a (RFC 1321)", 684 "61", 685 "0cc175b9c0f1b6a831c399e269772661" }, 686 { "abc (RFC 1321)", 687 "616263", 688 "900150983cd24fb0d6963f7d28e17f72" }, 689 { "a (RFC 1321)", 690 "61", 691 "0cc175b9c0f1b6a831c399e269772661" }, 692 { "message digest (RFC 1321)", 693 "6d65737361676520646967657374", 694 "f96b697d7cb7938d525a2f31aaf161d0" }, 695 { "abcdefghijklmnopqrstuvwxyz (RFC 1321)", 696 "6162636465666768696A6B6C6D6E6F707172737475767778797A", 697 "c3fcd3d76192e4007dfb496cca67e13b" }, 698 { "A-Za-z0-9 (RFC 1321)", 699 "4142434445464748494A4B4C4D4E4F505152535455565758595A6162636465666768696A6B6C6D6E6F707172737475767778797A30313233343536373839", 700 "d174ab98d277d9f5a5611c2c9f419d9f" }, 701 { "8 repetitions of 1234567890 (RFC 1321)", 702 "3132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930", 703 "57edf4a22be3c955ac49da2e2107b67a" }, 704 { "The quick brown fox jumps over the lazy dog (Wikipedia MD5 article)", 705 "54686520717569636B2062726F776E20666F78206A756D7073206F76657220746865206C617A7920646F67", 706 "9e107d9d372bb6826bd81d3542a419d6" }, 707 { "0x00", 708 "00", 709 "93b885adfe0da089cdf634904fd59f71" }, 710 { "Two bytes 0x00 0x00", 711 "0000", 712 "c4103f122d27677c9db144cae1394a66" }, 713 { NULL, NULL, NULL } 714 }; 715 struct mhd_Md5Ctx ctx; 716 uint8_t digest[mhd_MD5_DIGEST_SIZE]; 717 uint8_t data[1024]; 718 size_t data_len; 719 unsigned int passed = 0; 720 unsigned int total = 0; 721 unsigned int num_failed; 722 723 if (has_param (argc, argv, "-v") || 724 has_param (argc, argv, "--verbose")) 725 verbose = 1; 726 while (NULL != tests[total].name) 727 { 728 const struct Test *t = &tests[total]; 729 730 mhd_MD5_init_one_time (&ctx); 731 if (! mhd_MD5_has_err (&ctx)) 732 { 733 data_len = hex2bin (t->input, 734 data, 735 sizeof(data)); 736 if (0 != data_len) 737 mhd_MD5_update (&ctx, 738 data_len, 739 data); 740 mhd_MD5_finish_deinit (&ctx, 741 digest); 742 if (! mhd_MD5_has_err (&ctx)) 743 { 744 if (check_digest (digest, 745 mhd_MD5_DIGEST_SIZE, 746 t->digest, 747 t->name)) 748 passed++; 749 } 750 else 751 { 752 printf ("FAIL: %s - error in finish\n", 753 t->name); 754 } 755 } 756 else 757 { 758 printf ("FAIL: %s - error in init\n", 759 t->name); 760 } 761 total++; 762 } 763 764 /* 765 * Test update functionality 766 */ 767 total++; 768 mhd_MD5_init_one_time (&ctx); 769 if (! mhd_MD5_has_err (&ctx)) 770 { 771 data[0] = 'a'; 772 mhd_MD5_update (&ctx, 773 1, 774 data); 775 data[0] = 'b'; 776 mhd_MD5_update (&ctx, 777 1, 778 data); 779 data[0] = 'c'; 780 mhd_MD5_update (&ctx, 781 1, 782 data); 783 mhd_MD5_finish_deinit (&ctx, 784 digest); 785 if (! mhd_MD5_has_err (&ctx)) 786 { 787 if (check_digest (digest, 788 mhd_MD5_DIGEST_SIZE, 789 "900150983cd24fb0d6963f7d28e17f72", 790 "Multi-update: a + b + c")) 791 passed++; 792 } 793 } 794 795 /* 796 * Tests finish_reset and reuse of context 797 */ 798 total++; 799 mhd_MD5_init_one_time (&ctx); 800 if (! mhd_MD5_has_err (&ctx)) 801 { 802 /* First hash */ 803 data_len = hex2bin ("616263", 804 data, 805 sizeof(data)); /* "abc" */ 806 mhd_MD5_update (&ctx, data_len, data); 807 mhd_MD5_finish_reset (&ctx, digest); 808 809 /* Second hash on same context */ 810 data_len = hex2bin ("616263", data, sizeof(data)); /* "abc" again */ 811 mhd_MD5_update (&ctx, data_len, data); 812 mhd_MD5_finish_deinit (&ctx, digest); 813 814 if (! mhd_MD5_has_err (&ctx)) 815 { 816 if (check_digest (digest, 817 mhd_MD5_DIGEST_SIZE, 818 "900150983cd24fb0d6963f7d28e17f72", 819 "Reset and reuse context")) 820 passed++; 821 } 822 } 823 824 num_failed = total - passed; 825 num_failed += test1_str (); 826 num_failed += test1_bin (); 827 num_failed += test2_str (); 828 num_failed += test2_bin (); 829 num_failed += test_unaligned (); 830 831 printf ("Results: %u tests failed\n", 832 num_failed); 833 834 return (0 == num_failed) ? 0 : 1; 835 }