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