libmicrohttpd

HTTP/1.x server C library (MHD 1.x, stable)
Log | Files | Refs | Submodules | README | LICENSE

test_md5.c (18707B)


      1 /*
      2   This file is part of libmicrohttpd
      3   Copyright (C) 2019-2023 Evgeny Grin (Karlson2k)
      4 
      5   This test tool is free software; you can redistribute it and/or
      6   modify it under the terms of the GNU General Public License as
      7   published by the Free Software Foundation; either version 2, or
      8   (at your option) any later version.
      9 
     10   This test tool is distributed in the hope that it will be useful,
     11   but WITHOUT ANY WARRANTY; without even the implied warranty of
     12   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     13   Lesser General Public License for more details.
     14 
     15   You should have received a copy of the GNU Lesser General Public
     16   License along with this library; if not, write to the Free Software
     17   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
     18 */
     19 
     20 /**
     21  * @file microhttpd/test_md5.h
     22  * @brief  Unit tests for md5 functions
     23  * @author Karlson2k (Evgeny Grin)
     24  */
     25 
     26 #include "mhd_options.h"
     27 #include "mhd_md5_wrap.h"
     28 #include "test_helpers.h"
     29 #include <stdio.h>
     30 #include <stdlib.h>
     31 
     32 /* Turn any MHD_PANIC() or failing mhd_assert() reached from this
     33    test into a marked, classifiable test error (TESTING.md, P5). */
     34 #include "mhd_panic_tripwire.h"
     35 
     36 #if defined(MHD_MD5_TLSLIB) && defined(MHD_HTTPS_REQUIRE_GCRYPT)
     37 #define NEED_GCRYP_INIT 1
     38 #include <gcrypt.h>
     39 #endif /* MHD_MD5_TLSLIB && MHD_HTTPS_REQUIRE_GCRYPT */
     40 
     41 static int verbose = 0; /* verbose level (0-1)*/
     42 
     43 
     44 struct str_with_len
     45 {
     46   const char *const str;
     47   const size_t len;
     48 };
     49 
     50 #define D_STR_W_LEN(s) {(s), (sizeof((s)) / sizeof(char)) - 1}
     51 
     52 struct data_unit1
     53 {
     54   const struct str_with_len str_l;
     55   const uint8_t digest[MD5_DIGEST_SIZE];
     56 };
     57 
     58 static const struct data_unit1 data_units1[] = {
     59   {D_STR_W_LEN ("1234567890!@~%&$@#{}[]\\/!?`."),
     60    {0x1c, 0x68, 0xc2, 0xe5, 0x1f, 0x63, 0xc9, 0x5f, 0x17, 0xab, 0x1f, 0x20,
     61     0x8b, 0x86, 0x39, 0x57}},
     62   {D_STR_W_LEN ("Simple string."),
     63    {0xf1, 0x2b, 0x7c, 0xad, 0xa0, 0x41, 0xfe, 0xde, 0x4e, 0x68, 0x16, 0x63,
     64     0xb4, 0x60, 0x5d, 0x78}},
     65   {D_STR_W_LEN ("abcdefghijklmnopqrstuvwxyz"),
     66    {0xc3, 0xfc, 0xd3, 0xd7, 0x61, 0x92, 0xe4, 0x00, 0x7d, 0xfb, 0x49, 0x6c,
     67     0xca, 0x67, 0xe1, 0x3b}},
     68   {D_STR_W_LEN ("zyxwvutsrqponMLKJIHGFEDCBA"),
     69    {0x05, 0x61, 0x3a, 0x6b, 0xde, 0x75, 0x3a, 0x45, 0x91, 0xa8, 0x81, 0xb0,
     70     0xa7, 0xe2, 0xe2, 0x0e}},
     71   {D_STR_W_LEN ("abcdefghijklmnopqrstuvwxyzzyxwvutsrqponMLKJIHGFEDCBA" \
     72                 "abcdefghijklmnopqrstuvwxyzzyxwvutsrqponMLKJIHGFEDCBA"),
     73    {0xaf, 0xab, 0xc7, 0xe9, 0xe7, 0x17, 0xbe, 0xd6, 0xc0, 0x0f, 0x78, 0x8c,
     74     0xde, 0xdd, 0x11, 0xd1}},
     75   {D_STR_W_LEN ("/long/long/long/long/long/long/long/long/long/long/long" \
     76                 "/long/long/long/long/long/long/long/long/long/long/long" \
     77                 "/long/long/long/long/long/long/long/long/long/long/long" \
     78                 "/long/long/long/long/long/long/long/long/long/long/long" \
     79                 "/long/long/long/long/long/long/long/long/long/long/long" \
     80                 "/long/long/long/long/long/long/long/long/long/long/long" \
     81                 "/long/long/long/long/path?with%20some=parameters"),
     82    {0x7e, 0xe6, 0xdb, 0xe2, 0x76, 0x49, 0x1a, 0xd8, 0xaf, 0xf3, 0x52, 0x2d,
     83     0xd8, 0xfc, 0x89, 0x1e}},
     84   {D_STR_W_LEN (""),
     85    {0xd4, 0x1d, 0x8c, 0xd9, 0x8f, 0x00, 0xb2, 0x04, 0xe9, 0x80, 0x09, 0x98,
     86     0xec, 0xf8, 0x42, 0x7e}},
     87   {D_STR_W_LEN ("a"),
     88    {0x0c, 0xc1, 0x75, 0xb9, 0xc0, 0xf1, 0xb6, 0xa8, 0x31, 0xc3, 0x99, 0xe2,
     89     0x69, 0x77, 0x26, 0x61}},
     90   {D_STR_W_LEN ("abc"),
     91    {0x90, 0x01, 0x50, 0x98, 0x3c, 0xd2, 0x4f, 0xb0, 0xd6, 0x96, 0x3f, 0x7d,
     92     0x28, 0xe1, 0x7f, 0x72}},
     93   {D_STR_W_LEN ("message digest"),
     94    {0xf9, 0x6b, 0x69, 0x7d, 0x7c, 0xb7, 0x93, 0x8d, 0x52, 0x5a, 0x2f, 0x31,
     95     0xaa, 0xf1, 0x61, 0xd0}},
     96   {D_STR_W_LEN ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" \
     97                 "0123456789"),
     98    {0xd1, 0x74, 0xab, 0x98, 0xd2, 0x77, 0xd9, 0xf5, 0xa5, 0x61, 0x1c, 0x2c,
     99     0x9f, 0x41, 0x9d, 0x9f}},
    100   {D_STR_W_LEN ("12345678901234567890123456789012345678901234567890" \
    101                 "123456789012345678901234567890"),
    102    {0x57, 0xed, 0xf4, 0xa2, 0x2b, 0xe3, 0xc9, 0x55, 0xac, 0x49, 0xda, 0x2e,
    103     0x21, 0x07, 0xb6, 0x7a}}
    104 };
    105 
    106 static const size_t units1_num = sizeof(data_units1) / sizeof(data_units1[0]);
    107 
    108 struct bin_with_len
    109 {
    110   const uint8_t bin[512];
    111   const size_t len;
    112 };
    113 
    114 struct data_unit2
    115 {
    116   const struct bin_with_len bin_l;
    117   const uint8_t digest[MD5_DIGEST_SIZE];
    118 };
    119 
    120 static const struct data_unit2 data_units2[] = {
    121   { { {97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
    122        112, 113, 114, 115, 116,
    123        117, 118, 119, 120, 121, 122}, 26}, /* a..z ASCII sequence */
    124     {0xc3, 0xfc, 0xd3, 0xd7, 0x61, 0x92, 0xe4, 0x00, 0x7d, 0xfb, 0x49, 0x6c,
    125      0xca, 0x67, 0xe1, 0x3b}},
    126   { { {65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
    127        65, 65, 65, 65, 65, 65,
    128        65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
    129        65, 65, 65, 65, 65, 65,
    130        65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
    131        65, 65, 65, 65, 65, 65}, 72 },/* 'A' x 72 times */
    132     {0x24, 0xa5, 0xef, 0x36, 0x82, 0x80, 0x3a, 0x06, 0x2f, 0xea, 0xad, 0xad,
    133      0x76, 0xda, 0xbd, 0xa8}},
    134   { { {19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36,
    135        37, 38, 39, 40, 41, 42,
    136        43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60,
    137        61, 62, 63, 64, 65, 66, 67,
    138        68, 69, 70, 71, 72, 73}, 55}, /* 19..73 sequence */
    139     {0x6d, 0x2e, 0x6e, 0xde, 0x5d, 0x64, 0x6a, 0x17, 0xf1, 0x09, 0x2c, 0xac,
    140      0x19, 0x10, 0xe3, 0xd6}},
    141   { { {7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
    142        26, 27, 28, 29, 30, 31,
    143        32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
    144        50, 51, 52, 53, 54, 55, 56,
    145        57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69}, 63}, /* 7..69 sequence */
    146     {0x88, 0x13, 0x48, 0x47, 0x73, 0xaa, 0x92, 0xf2, 0xc9, 0xdd, 0x69, 0xb3,
    147      0xac, 0xf4, 0xba, 0x6e}},
    148   { { {38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55,
    149        56, 57, 58, 59, 60, 61,
    150        62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
    151        80, 81, 82, 83, 84, 85, 86,
    152        87, 88, 89, 90, 91, 92}, 55}, /* 38..92 sequence */
    153     {0x80, 0xf0, 0x05, 0x7e, 0xa2, 0xf7, 0xc8, 0x43, 0x12, 0xd3, 0xb1, 0x61,
    154      0xab, 0x52, 0x3b, 0xaf}},
    155   { { {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
    156        21, 22, 23, 24, 25, 26, 27,
    157        28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45,
    158        46, 47, 48, 49, 50, 51, 52,
    159        53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70,
    160        71, 72},
    161       72},/* 1..72 sequence */
    162     {0xc3, 0x28, 0xc5, 0xad, 0xc9, 0x26, 0xa9, 0x99, 0x95, 0x4a, 0x5e, 0x25,
    163      0x50, 0x34, 0x51, 0x73}},
    164   { { {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
    165        21, 22, 23, 24, 25, 26,
    166        27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44,
    167        45, 46, 47, 48, 49, 50, 51,
    168        52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69,
    169        70, 71, 72, 73, 74, 75, 76,
    170        77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94,
    171        95, 96, 97, 98, 99, 100,
    172        101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114,
    173        115, 116, 117, 118, 119, 120,
    174        121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134,
    175        135, 136, 137, 138, 139, 140,
    176        141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154,
    177        155, 156, 157, 158, 159, 160,
    178        161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174,
    179        175, 176, 177, 178, 179, 180,
    180        181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194,
    181        195, 196, 197, 198, 199, 200,
    182        201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214,
    183        215, 216, 217, 218, 219, 220,
    184        221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234,
    185        235, 236, 237, 238, 239, 240,
    186        241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254,
    187        255}, 256},                                                                        /* 0..255 sequence */
    188     {0xe2, 0xc8, 0x65, 0xdb, 0x41, 0x62, 0xbe, 0xd9, 0x63, 0xbf, 0xaa, 0x9e,
    189      0xf6, 0xac, 0x18, 0xf0}},
    190   { { {199, 198, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186,
    191        185, 184, 183, 182, 181, 180,
    192        179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166,
    193        165, 164, 163, 162, 161, 160,
    194        159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146,
    195        145, 144, 143, 142, 141, 140,
    196        139}, 61},  /* 199..139 sequence */
    197     {0xbb, 0x3f, 0xdb, 0x4a, 0x96, 0x03, 0x36, 0x37, 0x38, 0x78, 0x5e, 0x44,
    198      0xbf, 0x3a, 0x85, 0x51}},
    199   { { {255, 254, 253, 252, 251, 250, 249, 248, 247, 246, 245, 244, 243, 242,
    200        241, 240, 239, 238, 237, 236,
    201        235, 234, 233, 232, 231, 230, 229, 228, 227, 226, 225, 224, 223, 222,
    202        221, 220, 219, 218, 217, 216,
    203        215, 214, 213, 212, 211, 210, 209, 208, 207, 206, 205, 204, 203, 202,
    204        201, 200, 199, 198, 197, 196,
    205        195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182,
    206        181, 180, 179, 178, 177, 176,
    207        175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162,
    208        161, 160, 159, 158, 157, 156,
    209        155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 143, 142,
    210        141, 140, 139, 138, 137, 136,
    211        135, 134, 133, 132, 131, 130, 129, 128, 127, 126, 125, 124, 123, 122,
    212        121, 120, 119, 118, 117, 116,
    213        115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, 103, 102,
    214        101, 100, 99, 98, 97, 96, 95,
    215        94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77,
    216        76, 75, 74, 73, 72, 71, 70,
    217        69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52,
    218        51, 50, 49, 48, 47, 46, 45,
    219        44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27,
    220        26, 25, 24, 23, 22, 21, 20,
    221        19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1}, 255},  /* 255..1 sequence */
    222     {0x52, 0x21, 0xa5, 0x83, 0x4f, 0x38, 0x7c, 0x73, 0xba, 0x18, 0x22, 0xb1,
    223      0xf9, 0x7e, 0xae, 0x8b}},
    224   { { {41, 35, 190, 132, 225, 108, 214, 174, 82, 144, 73, 241, 241, 187, 233,
    225        235, 179, 166, 219, 60, 135,
    226        12, 62, 153, 36, 94, 13, 28, 6, 183, 71, 222, 179, 18, 77, 200, 67, 187,
    227        139, 166, 31, 3, 90, 125, 9,
    228        56, 37, 31, 93, 212, 203, 252, 150, 245, 69, 59, 19, 13, 137, 10, 28,
    229        219, 174, 50, 32, 154, 80, 238,
    230        64, 120, 54, 253, 18, 73, 50, 246, 158, 125, 73, 220, 173, 79, 20, 242,
    231        68, 64, 102, 208, 107, 196,
    232        48, 183, 50, 59, 161, 34, 246, 34, 145, 157, 225, 139, 31, 218, 176, 202,
    233        153, 2, 185, 114, 157, 73,
    234        44, 128, 126, 197, 153, 213, 233, 128, 178, 234, 201, 204, 83, 191, 103,
    235        214, 191, 20, 214, 126, 45,
    236        220, 142, 102, 131, 239, 87, 73, 97, 255, 105, 143, 97, 205, 209, 30,
    237        157, 156, 22, 114, 114, 230,
    238        29, 240, 132, 79, 74, 119, 2, 215, 232, 57, 44, 83, 203, 201, 18, 30, 51,
    239        116, 158, 12, 244, 213,
    240        212, 159, 212, 164, 89, 126, 53, 207, 50, 34, 244, 204, 207, 211, 144,
    241        45, 72, 211, 143, 117, 230,
    242        217, 29, 42, 229, 192, 247, 43, 120, 129, 135, 68, 14, 95, 80, 0, 212,
    243        97, 141, 190, 123, 5, 21, 7,
    244        59, 51, 130, 31, 24, 112, 146, 218, 100, 84, 206, 177, 133, 62, 105, 21,
    245        248, 70, 106, 4, 150, 115,
    246        14, 217, 22, 47, 103, 104, 212, 247, 74, 74, 208, 87, 104}, 255},  /* pseudo-random data */
    247     {0x55, 0x61, 0x2c, 0xeb, 0x29, 0xee, 0xa8, 0xb2, 0xf6, 0x10, 0x7b, 0xc1,
    248      0x5b, 0x0f, 0x01, 0x95}}
    249 };
    250 
    251 static const size_t units2_num = sizeof(data_units2) / sizeof(data_units2[0]);
    252 
    253 
    254 /*
    255  *  Helper functions
    256  */
    257 
    258 /**
    259  * Print bin as hex
    260  *
    261  * @param bin binary data
    262  * @param len number of bytes in bin
    263  * @param hex pointer to len*2+1 bytes buffer
    264  */
    265 static void
    266 bin2hex (const uint8_t *bin,
    267          size_t len,
    268          char *hex)
    269 {
    270   while (len-- > 0)
    271   {
    272     unsigned int b1, b2;
    273     b1 = (*bin >> 4) & 0xf;
    274     *hex++ = (char) ((b1 > 9) ? (b1 + 'A' - 10) : (b1 + '0'));
    275     b2 = *bin++ & 0xf;
    276     *hex++ = (char) ((b2 > 9) ? (b2 + 'A' - 10) : (b2 + '0'));
    277   }
    278   *hex = 0;
    279 }
    280 
    281 
    282 static int
    283 check_result (const char *test_name,
    284               unsigned int check_num,
    285               const uint8_t calculated[MD5_DIGEST_SIZE],
    286               const uint8_t expected[MD5_DIGEST_SIZE])
    287 {
    288   int failed = memcmp (calculated, expected, MD5_DIGEST_SIZE);
    289   check_num++; /* Print 1-based numbers */
    290   if (failed)
    291   {
    292     char calc_str[MD5_DIGEST_STRING_SIZE];
    293     char expc_str[MD5_DIGEST_STRING_SIZE];
    294     bin2hex (calculated, MD5_DIGEST_SIZE, calc_str);
    295     bin2hex (expected, MD5_DIGEST_SIZE, expc_str);
    296     fprintf (stderr,
    297              "FAILED: %s check %u: calculated digest %s, expected digest %s.\n",
    298              test_name, check_num, calc_str, expc_str);
    299     fflush (stderr);
    300   }
    301   else if (verbose)
    302   {
    303     char calc_str[MD5_DIGEST_STRING_SIZE];
    304     bin2hex (calculated, MD5_DIGEST_SIZE, calc_str);
    305     printf ("PASSED: %s check %u: calculated digest %s "
    306             "matches expected digest.\n",
    307             test_name, check_num, calc_str);
    308     fflush (stdout);
    309   }
    310   return failed ? 1 : 0;
    311 }
    312 
    313 
    314 /*
    315  *  Tests
    316  */
    317 
    318 /* Calculated MD5 as one pass for whole data */
    319 static int
    320 test1_str (void)
    321 {
    322   unsigned int i;
    323   int num_failed = 0;
    324   struct Md5CtxWr ctx;
    325 
    326   MHD_MD5_init_one_time (&ctx);
    327 
    328   for (i = 0; i < units1_num; i++)
    329   {
    330     uint8_t digest[MD5_DIGEST_SIZE];
    331 
    332     MHD_MD5_update (&ctx, (const uint8_t *) data_units1[i].str_l.str,
    333                     data_units1[i].str_l.len);
    334     MHD_MD5_finish_reset (&ctx, digest);
    335 #ifdef MHD_MD5_HAS_EXT_ERROR
    336     if (0 != ctx.ext_error)
    337     {
    338       fprintf (stderr, "External hashing error: %d.\n", ctx.ext_error);
    339       exit (99);
    340     }
    341 #endif
    342     num_failed += check_result (MHD_FUNC_, i, digest,
    343                                 data_units1[i].digest);
    344   }
    345   MHD_MD5_deinit (&ctx);
    346   return num_failed;
    347 }
    348 
    349 
    350 static int
    351 test1_bin (void)
    352 {
    353   unsigned int i;
    354   int num_failed = 0;
    355   struct Md5CtxWr ctx;
    356 
    357   MHD_MD5_init_one_time (&ctx);
    358 
    359   for (i = 0; i < units2_num; i++)
    360   {
    361     uint8_t digest[MD5_DIGEST_SIZE];
    362 
    363     MHD_MD5_update (&ctx, data_units2[i].bin_l.bin, data_units2[i].bin_l.len);
    364     MHD_MD5_finish_reset (&ctx, digest);
    365 #ifdef MHD_MD5_HAS_EXT_ERROR
    366     if (0 != ctx.ext_error)
    367     {
    368       fprintf (stderr, "External hashing error: %d.\n", ctx.ext_error);
    369       exit (99);
    370     }
    371 #endif
    372     num_failed += check_result (MHD_FUNC_, i, digest,
    373                                 data_units2[i].digest);
    374   }
    375   MHD_MD5_deinit (&ctx);
    376   return num_failed;
    377 }
    378 
    379 
    380 /* Calculated MD5 as two iterations for whole data */
    381 static int
    382 test2_str (void)
    383 {
    384   unsigned int i;
    385   int num_failed = 0;
    386   struct Md5CtxWr ctx;
    387 
    388   MHD_MD5_init_one_time (&ctx);
    389 
    390   for (i = 0; i < units1_num; i++)
    391   {
    392     uint8_t digest[MD5_DIGEST_SIZE];
    393     size_t part_s = data_units1[i].str_l.len / 4;
    394 
    395     MHD_MD5_update (&ctx, (const uint8_t *) "", 0);
    396     MHD_MD5_update (&ctx, (const uint8_t *) data_units1[i].str_l.str, part_s);
    397     MHD_MD5_update (&ctx, (const uint8_t *) "", 0);
    398     MHD_MD5_update (&ctx, (const uint8_t *) data_units1[i].str_l.str + part_s,
    399                     data_units1[i].str_l.len - part_s);
    400     MHD_MD5_update (&ctx, (const uint8_t *) "", 0);
    401     MHD_MD5_finish_reset (&ctx, digest);
    402 #ifdef MHD_MD5_HAS_EXT_ERROR
    403     if (0 != ctx.ext_error)
    404     {
    405       fprintf (stderr, "External hashing error: %d.\n", ctx.ext_error);
    406       exit (99);
    407     }
    408 #endif
    409     num_failed += check_result (MHD_FUNC_, i, digest,
    410                                 data_units1[i].digest);
    411   }
    412   MHD_MD5_deinit (&ctx);
    413   return num_failed;
    414 }
    415 
    416 
    417 static int
    418 test2_bin (void)
    419 {
    420   unsigned int i;
    421   int num_failed = 0;
    422   struct Md5CtxWr ctx;
    423 
    424   MHD_MD5_init_one_time (&ctx);
    425 
    426   for (i = 0; i < units2_num; i++)
    427   {
    428     uint8_t digest[MD5_DIGEST_SIZE];
    429     size_t part_s = data_units2[i].bin_l.len * 2 / 3;
    430 
    431     MHD_MD5_update (&ctx, data_units2[i].bin_l.bin, part_s);
    432     MHD_MD5_update (&ctx, (const uint8_t *) "", 0);
    433     MHD_MD5_update (&ctx, data_units2[i].bin_l.bin + part_s,
    434                     data_units2[i].bin_l.len - part_s);
    435     MHD_MD5_finish_reset (&ctx, digest);
    436 #ifdef MHD_MD5_HAS_EXT_ERROR
    437     if (0 != ctx.ext_error)
    438     {
    439       fprintf (stderr, "External hashing error: %d.\n", ctx.ext_error);
    440       exit (99);
    441     }
    442 #endif
    443     num_failed += check_result (MHD_FUNC_, i, digest,
    444                                 data_units2[i].digest);
    445   }
    446   MHD_MD5_deinit (&ctx);
    447   return num_failed;
    448 }
    449 
    450 
    451 /* Use data set number 7 as it has the longest sequence */
    452 #define DATA_POS 6
    453 #define MAX_OFFSET 31
    454 
    455 static int
    456 test_unaligned (void)
    457 {
    458   int num_failed = 0;
    459   unsigned int offset;
    460   uint8_t *buf;
    461   uint8_t *digest_buf;
    462   struct Md5CtxWr ctx;
    463 
    464   const struct data_unit2 *const tdata = data_units2 + DATA_POS;
    465 
    466   buf = malloc (tdata->bin_l.len + MAX_OFFSET);
    467   digest_buf = malloc (MD5_DIGEST_SIZE + MAX_OFFSET);
    468   if ((NULL == buf) || (NULL == digest_buf))
    469     exit (99);
    470 
    471   MHD_MD5_init_one_time (&ctx);
    472 
    473   for (offset = MAX_OFFSET; offset >= 1; --offset)
    474   {
    475     uint8_t *unaligned_digest;
    476     uint8_t *unaligned_buf;
    477 
    478     unaligned_buf = buf + offset;
    479     memcpy (unaligned_buf, tdata->bin_l.bin, tdata->bin_l.len);
    480     unaligned_digest = digest_buf + MAX_OFFSET - offset;
    481     memset (unaligned_digest, 0, MD5_DIGEST_SIZE);
    482 
    483     MHD_MD5_update (&ctx, unaligned_buf, tdata->bin_l.len);
    484     MHD_MD5_finish_reset (&ctx, unaligned_digest);
    485 #ifdef MHD_MD5_HAS_EXT_ERROR
    486     if (0 != ctx.ext_error)
    487     {
    488       fprintf (stderr, "External hashing error: %d.\n", ctx.ext_error);
    489       exit (99);
    490     }
    491 #endif
    492     num_failed += check_result (MHD_FUNC_, MAX_OFFSET - offset,
    493                                 unaligned_digest, tdata->digest);
    494   }
    495   MHD_MD5_deinit (&ctx);
    496   free (digest_buf);
    497   free (buf);
    498   return num_failed;
    499 }
    500 
    501 
    502 int
    503 main (int argc, char *argv[])
    504 {
    505   int num_failed = 0;
    506   (void) has_in_name; /* Mute compiler warning. */
    507   if (has_param (argc, argv, "-v") || has_param (argc, argv, "--verbose"))
    508     verbose = 1;
    509 
    510 #ifdef NEED_GCRYP_INIT
    511   gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0);
    512 #ifdef GCRYCTL_INITIALIZATION_FINISHED
    513   gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
    514 #endif /* GCRYCTL_INITIALIZATION_FINISHED */
    515 #endif /* NEED_GCRYP_INIT */
    516 
    517   num_failed += test1_str ();
    518   num_failed += test1_bin ();
    519 
    520   num_failed += test2_str ();
    521   num_failed += test2_bin ();
    522 
    523   num_failed += test_unaligned ();
    524 
    525   return num_failed ? 1 : 0;
    526 }