libmicrohttpd

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

test_dauth_userdigest.c (21460B)


      1 /*
      2   This file is part of libmicrohttpd
      3   Copyright (C) 2022 Evgeny Grin (Karlson2)
      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_dauth_userdigest.c
     22  * @brief  Tests for Digest Auth calculations of userdigest
     23  * @author Karlson2k (Evgeny Grin)
     24  */
     25 
     26 #include "mhd_options.h"
     27 #include <stdio.h>
     28 #include <stdlib.h>
     29 #include <string.h>
     30 #include "microhttpd.h"
     31 #include "test_helpers.h"
     32 
     33 /* Turn any MHD_PANIC() or failing mhd_assert() reached from this
     34    test into a marked, classifiable test error (TESTING.md, P5). */
     35 #include "mhd_panic_tripwire.h"
     36 
     37 #if defined(MHD_HTTPS_REQUIRE_GCRYPT) && \
     38   (defined(MHD_SHA256_TLSLIB) || defined(MHD_MD5_TLSLIB))
     39 #define NEED_GCRYP_INIT 1
     40 #include <gcrypt.h>
     41 #endif /* MHD_HTTPS_REQUIRE_GCRYPT && (MHD_SHA256_TLSLIB || MHD_MD5_TLSLIB) */
     42 
     43 static int verbose = 1; /* verbose level (0-1)*/
     44 
     45 /* Declarations and data */
     46 
     47 struct data_md5
     48 {
     49   unsigned int line_num;
     50   const char *const username;
     51   const char *const realm;
     52   const char *const password;
     53   const uint8_t hash[MHD_MD5_DIGEST_SIZE];
     54 };
     55 
     56 
     57 static const struct data_md5 md5_tests[] = {
     58   {__LINE__,
     59    "u", "r", "p",
     60    {0x44, 0xad, 0xd2, 0x2b, 0x6f, 0x31, 0x79, 0xb7, 0x51, 0xea, 0xfd, 0x68,
     61     0xee, 0x37, 0x0f, 0x7d}},
     62   {__LINE__,
     63    "testuser", "testrealm", "testpass",
     64    {0xeb, 0xff, 0x22, 0x5e, 0x1c, 0xeb, 0x73, 0xe0, 0x26, 0xfc, 0xc6, 0x45,
     65     0xaf, 0x3e, 0x84, 0xf6}},
     66   {__LINE__,  /* Values from testcurl/test_digestauth2.c */
     67    "test_user", "TestRealm", "test pass",
     68    {0xd8, 0xb4, 0xa6, 0xd0, 0x01, 0x13, 0x07, 0xb7, 0x67, 0x94, 0xea, 0x66,
     69     0x86, 0x03, 0x6b, 0x43}},
     70   {__LINE__,
     71    "Mufasa", "myhost@testrealm.com", "CircleOfLife",
     72    {0x7e, 0xbe, 0xcc, 0x07, 0x18, 0xa5, 0x4a, 0xb4, 0x7e, 0x21, 0x65, 0x69,
     73     0x07, 0x66, 0x41, 0x6a}},
     74   {__LINE__,
     75    "Mufasa", "myhost@example.com", "Circle Of Life",
     76    {0x6a, 0x6d, 0x4e, 0x7c, 0xd7, 0x15, 0x18, 0x68, 0xf9, 0xb8, 0xc7, 0xc8,
     77     0xd1, 0xcd, 0xd4, 0xe0}},
     78   {__LINE__,
     79    "Mufasa", "http-auth@example.org", "Circle of Life",
     80    {0x3d, 0x78, 0x80, 0x7d, 0xef, 0xe7, 0xde, 0x21, 0x57, 0xe2, 0xb0, 0xb6,
     81     0x57, 0x3a, 0x85, 0x5f}},
     82   {__LINE__,
     83    "J" "\xC3\xA4" "s" "\xC3\xB8" "n Doe" /* "Jäsøn Doe" */,
     84    "api@example.org", "Secret, or not?",
     85    {0x83, 0xa3, 0xf7, 0xf6, 0xb8, 0x3f, 0x71, 0xc5, 0xc2, 0xeb, 0x7c, 0x6d,
     86     0xd2, 0xdd, 0x4c, 0x4b}}
     87 };
     88 
     89 struct data_sha256
     90 {
     91   unsigned int line_num;
     92   const char *const username;
     93   const char *const realm;
     94   const char *const password;
     95   const uint8_t hash[MHD_SHA256_DIGEST_SIZE];
     96 };
     97 
     98 static const struct data_sha256 sha256_tests[] = {
     99   {__LINE__,
    100    "u", "r", "p",
    101    {0xdc, 0xb0, 0x21, 0x10, 0x2e, 0x49, 0x1e, 0x70, 0x1a, 0x4a, 0x23, 0x6d,
    102     0xaa, 0x89, 0x23, 0xaf, 0x21, 0x61, 0x44, 0x7b, 0xce, 0x7b, 0xb7, 0x26,
    103     0x0a, 0x35, 0x1e, 0xe8, 0x3e, 0x9f, 0x81, 0x54}},
    104   {__LINE__,
    105    "testuser", "testrealm", "testpass",
    106    {0xa9, 0x2e, 0xf6, 0x3b, 0x3d, 0xec, 0x38, 0x95, 0xb0, 0x8f, 0x3d, 0x4d,
    107     0x67, 0x33, 0xf0, 0x70, 0x74, 0xcb, 0xe6, 0xd4, 0xa0, 0x01, 0x27, 0xf5,
    108     0x74, 0x1a, 0x77, 0x4f, 0x05, 0xf9, 0xd4, 0x99}},
    109   {__LINE__,  /* Values from testcurl/test_digestauth2.c */
    110    "test_user", "TestRealm", "test pass",
    111    {0xc3, 0x4e, 0x16, 0x5a, 0x17, 0x0f, 0xe5, 0xac, 0x04, 0xf1, 0x6e, 0x46,
    112     0x48, 0x2b, 0xa0, 0xc6, 0x56, 0xc1, 0xfb, 0x8f, 0x66, 0xa6, 0xd6, 0x3f,
    113     0x91, 0x12, 0xf8, 0x56, 0xa5, 0xec, 0x6d, 0x6d}},
    114   {__LINE__,
    115    "Mufasa", "myhost@testrealm.com", "CircleOfLife",
    116    {0x8e, 0x64, 0x1f, 0xaa, 0x71, 0x7d, 0x20, 0x70, 0x5a, 0xd7, 0x3c, 0x54,
    117     0xfb, 0x04, 0x9e, 0x32, 0x6a, 0xe1, 0x1c, 0x80, 0xd6, 0x05, 0x9f, 0xc3,
    118     0x7e, 0xbb, 0x2d, 0x7b, 0x60, 0x6c, 0x11, 0xb9}},
    119   {__LINE__,
    120    "Mufasa", "myhost@example.com", "Circle Of Life",
    121    {0x8b, 0xc5, 0xa8, 0xed, 0xe3, 0x02, 0x15, 0x6b, 0x9f, 0x51, 0xce, 0x97,
    122     0x81, 0xb5, 0x26, 0xff, 0x99, 0x29, 0x0b, 0xb2, 0xc3, 0xe4, 0x41, 0x71,
    123     0x8e, 0xa3, 0xa1, 0x7e, 0x5a, 0xd9, 0xd6, 0x49}},
    124   {__LINE__,
    125    "Mufasa", "http-auth@example.org", "Circle of Life",
    126    {0x79, 0x87, 0xc6, 0x4c, 0x30, 0xe2, 0x5f, 0x1b, 0x74, 0xbe, 0x53, 0xf9,
    127     0x66, 0xb4, 0x9b, 0x90, 0xf2, 0x80, 0x8a, 0xa9, 0x2f, 0xaf, 0x9a, 0x00,
    128     0x26, 0x23, 0x92, 0xd7, 0xb4, 0x79, 0x42, 0x32}},
    129   {__LINE__,
    130    "J" "\xC3\xA4" "s" "\xC3\xB8" "n Doe" /* "Jäsøn Doe" */,
    131    "api@example.org", "Secret, or not?",
    132    {0xfd, 0x0b, 0xe3, 0x93, 0x9d, 0xca, 0x4b, 0x5c, 0x2d, 0x46, 0xe8, 0xfa,
    133     0x6a, 0x3d, 0x16, 0xdb, 0xea, 0x82, 0x47, 0x4c, 0xb9, 0xa5, 0x88, 0xd4,
    134     0xcb, 0x14, 0x9c, 0x54, 0xf3, 0x7c, 0xff, 0x37}}
    135 };
    136 
    137 struct data_sha512_256
    138 {
    139   unsigned int line_num;
    140   const char *const username;
    141   const char *const realm;
    142   const char *const password;
    143   const uint8_t hash[MHD_SHA512_256_DIGEST_SIZE];
    144 };
    145 
    146 static const struct data_sha512_256 sha512_256_tests[] = {
    147   {__LINE__,
    148    "u", "r", "p",
    149    {0xd5, 0xe8, 0xe7, 0x3b, 0xa3, 0x47, 0xb9, 0xad, 0xf0, 0xe4, 0x7a, 0x9a,
    150     0xce, 0x43, 0xb7, 0x08, 0x2a, 0xbc, 0x8d, 0x27, 0x27, 0x2e, 0x38, 0x7d,
    151     0x1d, 0x9c, 0xe2, 0x44, 0x25, 0x68, 0x74, 0x04}},
    152   {__LINE__,
    153    "testuser", "testrealm", "testpass",
    154    {0x41, 0x7d, 0xf9, 0x60, 0x7c, 0xc9, 0x60, 0x28, 0x44, 0x74, 0x75, 0xf7,
    155     0x7b, 0x78, 0xe7, 0x60, 0xec, 0x9a, 0xe1, 0x62, 0xd4, 0x95, 0x82, 0x61,
    156     0x68, 0xa7, 0x94, 0xe8, 0x3b, 0xdf, 0x8d, 0x59}},
    157   {__LINE__,  /* Values from testcurl/test_digestauth2.c */
    158    "test_user", "TestRealm", "test pass",
    159    {0xe7, 0xa1, 0x9e, 0x27, 0xf6, 0x73, 0x88, 0xb2, 0xde, 0xa4, 0xe2, 0x66,
    160     0xc5, 0x16, 0x37, 0x17, 0x4d, 0x29, 0xcc, 0xa3, 0xc1, 0xf5, 0xb2, 0x49,
    161     0x20, 0xc1, 0x05, 0xc9, 0x20, 0x13, 0x3c, 0x3d}},
    162   {__LINE__,
    163    "Mufasa", "myhost@testrealm.com", "CircleOfLife",
    164    {0x44, 0xbc, 0xd2, 0xb1, 0x1f, 0x6f, 0x7d, 0xd3, 0xae, 0xa6, 0x66, 0x8a,
    165     0x24, 0x84, 0x4b, 0x87, 0x7d, 0xe1, 0x80, 0x24, 0x9a, 0x26, 0x6b, 0xe6,
    166     0xdb, 0x7f, 0xe3, 0xc8, 0x7a, 0xf9, 0x75, 0x64}},
    167   {__LINE__,
    168    "Mufasa", "myhost@example.com", "Circle Of Life",
    169    {0xd5, 0xf6, 0x25, 0x7c, 0x64, 0xe4, 0x01, 0xd2, 0x87, 0xd5, 0xaa, 0x19,
    170     0xae, 0xf0, 0xa2, 0xa2, 0xce, 0x4e, 0x5d, 0xfc, 0x77, 0x70, 0x0b, 0x72,
    171     0x90, 0x43, 0x96, 0xd2, 0x95, 0x6e, 0x83, 0x0a}},
    172   {__LINE__,
    173    "Mufasa", "http-auth@example.org", "Circle of Life",
    174    {0xfb, 0x17, 0x4f, 0x5c, 0x3c, 0x78, 0x02, 0x72, 0x15, 0x17, 0xca, 0xe1,
    175     0x3b, 0x98, 0xe2, 0xb8, 0xda, 0xe2, 0xe0, 0x11, 0x8c, 0xb7, 0x05, 0xd9,
    176     0x4e, 0xe2, 0x99, 0x46, 0x31, 0x92, 0x04, 0xce}},
    177   {__LINE__,
    178    "J" "\xC3\xA4" "s" "\xC3\xB8" "n Doe" /* "Jäsøn Doe" */,
    179    "api@example.org", "Secret, or not?",
    180    {0x2d, 0x3d, 0x9f, 0x12, 0xc9, 0xf3, 0xd3, 0x00, 0x11, 0x25, 0x9d, 0xc5,
    181     0xfe, 0xce, 0xe0, 0x05, 0xae, 0x24, 0xde, 0x40, 0xe3, 0xe1, 0xf6, 0x18,
    182     0x06, 0xd0, 0x3e, 0x65, 0xf1, 0xe6, 0x02, 0x4f}}
    183 };
    184 
    185 
    186 /*
    187  *  Helper functions
    188  */
    189 
    190 /**
    191  * Print bin as lower case hex
    192  *
    193  * @param bin binary data
    194  * @param len number of bytes in bin
    195  * @param hex pointer to len*2+1 bytes buffer
    196  */
    197 static void
    198 bin2hex (const uint8_t *bin,
    199          size_t len,
    200          char *hex)
    201 {
    202   while (len-- > 0)
    203   {
    204     unsigned int b1, b2;
    205     b1 = (*bin >> 4) & 0xf;
    206     *hex++ = (char) ((b1 > 9) ? (b1 + 'a' - 10) : (b1 + '0'));
    207     b2 = *bin++ & 0xf;
    208     *hex++ = (char) ((b2 > 9) ? (b2 + 'a' - 10) : (b2 + '0'));
    209   }
    210   *hex = 0;
    211 }
    212 
    213 
    214 /* Tests */
    215 
    216 static unsigned int
    217 check_md5 (const struct data_md5 *const data)
    218 {
    219   static const enum MHD_DigestAuthAlgo3 algo3 = MHD_DIGEST_AUTH_ALGO3_MD5;
    220   uint8_t hash_bin[MHD_MD5_DIGEST_SIZE];
    221   char hash_hex[MHD_MD5_DIGEST_SIZE * 2 + 1];
    222   char expected_hex[MHD_MD5_DIGEST_SIZE * 2 + 1];
    223   const char *func_name;
    224   unsigned int failed = 0;
    225 
    226   func_name = "MHD_digest_auth_calc_userdigest";
    227   if (MHD_YES != MHD_digest_auth_calc_userdigest (algo3,
    228                                                   data->username,
    229                                                   data->realm,
    230                                                   data->password,
    231                                                   hash_bin, sizeof(hash_bin)))
    232   {
    233     failed++;
    234     fprintf (stderr,
    235              "FAILED: %s() has not returned MHD_YES.\n",
    236              func_name);
    237   }
    238   else if (0 != memcmp (hash_bin, data->hash, sizeof(data->hash)))
    239   {
    240     failed++;
    241     bin2hex (hash_bin, sizeof(hash_bin), hash_hex);
    242     bin2hex (data->hash, sizeof(data->hash), expected_hex);
    243     fprintf (stderr,
    244              "FAILED: %s() produced wrong hash. "
    245              "Calculated digest %s, expected digest %s.\n",
    246              func_name,
    247              hash_hex, expected_hex);
    248   }
    249 
    250   if (failed)
    251   {
    252     fprintf (stderr,
    253              "The check failed for data located at line: %u.\n",
    254              data->line_num);
    255     fflush (stderr);
    256   }
    257   else if (verbose)
    258   {
    259     printf ("PASSED: check for data at line: %u.\n",
    260             data->line_num);
    261   }
    262   return failed ? 1 : 0;
    263 }
    264 
    265 
    266 static unsigned int
    267 test_md5 (void)
    268 {
    269   unsigned int num_failed = 0;
    270   size_t i;
    271 
    272   for (i = 0; i < sizeof(md5_tests) / sizeof(md5_tests[0]); i++)
    273     num_failed += check_md5 (md5_tests + i);
    274   return num_failed;
    275 }
    276 
    277 
    278 static unsigned int
    279 test_md5_failure (void)
    280 {
    281   static const enum MHD_DigestAuthAlgo3 algo3 = MHD_DIGEST_AUTH_ALGO3_MD5;
    282   uint8_t hash_bin[MHD_MD5_DIGEST_SIZE];
    283   const char *func_name;
    284   unsigned int failed = 0;
    285 
    286   func_name = "MHD_digest_auth_calc_userdigest";
    287   if (MHD_NO != MHD_digest_auth_calc_userdigest (algo3,
    288                                                  "u", "r", "p",
    289                                                  hash_bin, sizeof(hash_bin)
    290                                                  - 1))
    291   {
    292     failed++;
    293     fprintf (stderr,
    294              "FAILED: %s() has not returned MHD_NO at line: %u.\n",
    295              func_name, (unsigned) __LINE__);
    296   }
    297   if (MHD_NO != MHD_digest_auth_calc_userdigest (algo3,
    298                                                  "u", "r", "p",
    299                                                  hash_bin, 0))
    300   {
    301     failed++;
    302     fprintf (stderr,
    303              "FAILED: %s() has not returned MHD_NO at line: %u.\n",
    304              func_name, (unsigned) __LINE__);
    305   }
    306   if (MHD_NO == MHD_is_feature_supported (MHD_FEATURE_DIGEST_AUTH_MD5))
    307   {
    308     if (MHD_NO != MHD_digest_auth_calc_userdigest (algo3,
    309                                                    "u", "r", "p",
    310                                                    hash_bin, sizeof(hash_bin)))
    311     {
    312       failed++;
    313       fprintf (stderr,
    314                "FAILED: %s() has not returned MHD_NO at line: %u.\n",
    315                func_name, (unsigned) __LINE__);
    316     }
    317   }
    318 
    319   if (! failed && verbose)
    320   {
    321     printf ("PASSED: all checks with expected MHD_NO result near line: %u.\n",
    322             (unsigned) __LINE__);
    323   }
    324   return failed ? 1 : 0;
    325 }
    326 
    327 
    328 static unsigned int
    329 check_sha256 (const struct data_sha256 *const data)
    330 {
    331   static const enum MHD_DigestAuthAlgo3 algo3 = MHD_DIGEST_AUTH_ALGO3_SHA256;
    332   uint8_t hash_bin[MHD_SHA256_DIGEST_SIZE];
    333   char hash_hex[MHD_SHA256_DIGEST_SIZE * 2 + 1];
    334   char expected_hex[MHD_SHA256_DIGEST_SIZE * 2 + 1];
    335   const char *func_name;
    336   unsigned int failed = 0;
    337 
    338   func_name = "MHD_digest_auth_calc_userdigest";
    339   if (MHD_YES != MHD_digest_auth_calc_userdigest (algo3,
    340                                                   data->username,
    341                                                   data->realm,
    342                                                   data->password,
    343                                                   hash_bin, sizeof(hash_bin)))
    344   {
    345     failed++;
    346     fprintf (stderr,
    347              "FAILED: %s() has not returned MHD_YES.\n",
    348              func_name);
    349   }
    350   else if (0 != memcmp (hash_bin, data->hash, sizeof(data->hash)))
    351   {
    352     failed++;
    353     bin2hex (hash_bin, sizeof(hash_bin), hash_hex);
    354     bin2hex (data->hash, sizeof(data->hash), expected_hex);
    355     fprintf (stderr,
    356              "FAILED: %s() produced wrong hash. "
    357              "Calculated digest %s, expected digest %s.\n",
    358              func_name,
    359              hash_hex, expected_hex);
    360   }
    361 
    362   if (failed)
    363   {
    364     fprintf (stderr,
    365              "The check failed for data located at line: %u.\n",
    366              data->line_num);
    367     fflush (stderr);
    368   }
    369   else if (verbose)
    370   {
    371     printf ("PASSED: check for data at line: %u.\n",
    372             data->line_num);
    373   }
    374   return failed ? 1 : 0;
    375 }
    376 
    377 
    378 static unsigned int
    379 test_sha256 (void)
    380 {
    381   unsigned int num_failed = 0;
    382   size_t i;
    383 
    384   for (i = 0; i < sizeof(sha256_tests) / sizeof(sha256_tests[0]); i++)
    385     num_failed += check_sha256 (sha256_tests + i);
    386   return num_failed;
    387 }
    388 
    389 
    390 static unsigned int
    391 test_sha256_failure (void)
    392 {
    393   static const enum MHD_DigestAuthAlgo3 algo3 = MHD_DIGEST_AUTH_ALGO3_SHA256;
    394   uint8_t hash_bin[MHD_SHA256_DIGEST_SIZE];
    395   char hash_hex[MHD_SHA256_DIGEST_SIZE * 2 + 1];
    396   const char *func_name;
    397   unsigned int failed = 0;
    398 
    399   func_name = "MHD_digest_auth_calc_userhash";
    400   if (MHD_NO != MHD_digest_auth_calc_userhash (algo3,
    401                                                "u", "r",
    402                                                hash_bin, sizeof(hash_bin) - 1))
    403   {
    404     failed++;
    405     fprintf (stderr,
    406              "FAILED: %s() has not returned MHD_NO at line: %u.\n",
    407              func_name, (unsigned) __LINE__);
    408   }
    409   if (MHD_NO != MHD_digest_auth_calc_userhash (algo3,
    410                                                "u", "r",
    411                                                hash_bin, 0))
    412   {
    413     failed++;
    414     fprintf (stderr,
    415              "FAILED: %s() has not returned MHD_NO at line: %u.\n",
    416              func_name, (unsigned) __LINE__);
    417   }
    418   if (MHD_NO == MHD_is_feature_supported (MHD_FEATURE_DIGEST_AUTH_SHA256))
    419   {
    420     if (MHD_NO != MHD_digest_auth_calc_userhash (algo3,
    421                                                  "u", "r",
    422                                                  hash_bin, sizeof(hash_bin)))
    423     {
    424       failed++;
    425       fprintf (stderr,
    426                "FAILED: %s() has not returned MHD_NO at line: %u.\n",
    427                func_name, (unsigned) __LINE__);
    428     }
    429   }
    430 
    431   func_name = "MHD_digest_auth_calc_userhash_hex";
    432   if (MHD_NO !=
    433       MHD_digest_auth_calc_userhash_hex (algo3,
    434                                          "u", "r",
    435                                          hash_hex, sizeof(hash_hex) - 1))
    436   {
    437     failed++;
    438     fprintf (stderr,
    439              "FAILED: %s() has not returned MHD_NO at line: %u.\n",
    440              func_name, (unsigned) __LINE__);
    441   }
    442   if (MHD_NO !=
    443       MHD_digest_auth_calc_userhash_hex (algo3,
    444                                          "u", "r",
    445                                          hash_hex, 0))
    446   {
    447     failed++;
    448     fprintf (stderr,
    449              "FAILED: %s() has not returned MHD_NO at line: %u.\n",
    450              func_name, (unsigned) __LINE__);
    451   }
    452   if (MHD_NO == MHD_is_feature_supported (MHD_FEATURE_DIGEST_AUTH_SHA256))
    453   {
    454     if (MHD_NO !=
    455         MHD_digest_auth_calc_userhash_hex (algo3,
    456                                            "u", "r",
    457                                            hash_hex, sizeof(hash_hex)))
    458     {
    459       failed++;
    460       fprintf (stderr,
    461                "FAILED: %s() has not returned MHD_NO at line: %u.\n",
    462                func_name, (unsigned) __LINE__);
    463     }
    464   }
    465 
    466   if (! failed && verbose)
    467   {
    468     printf ("PASSED: all checks with expected MHD_NO result near line: %u.\n",
    469             (unsigned) __LINE__);
    470   }
    471   return failed ? 1 : 0;
    472 }
    473 
    474 
    475 static unsigned int
    476 check_sha512_256 (const struct data_sha512_256 *const data)
    477 {
    478   static const enum MHD_DigestAuthAlgo3 algo3 =
    479     MHD_DIGEST_AUTH_ALGO3_SHA512_256;
    480   uint8_t hash_bin[MHD_SHA512_256_DIGEST_SIZE];
    481   char hash_hex[MHD_SHA512_256_DIGEST_SIZE * 2 + 1];
    482   char expected_hex[MHD_SHA512_256_DIGEST_SIZE * 2 + 1];
    483   const char *func_name;
    484   unsigned int failed = 0;
    485 
    486   func_name = "MHD_digest_auth_calc_userdigest";
    487   if (MHD_YES != MHD_digest_auth_calc_userdigest (algo3,
    488                                                   data->username,
    489                                                   data->realm,
    490                                                   data->password,
    491                                                   hash_bin, sizeof(hash_bin)))
    492   {
    493     failed++;
    494     fprintf (stderr,
    495              "FAILED: %s() has not returned MHD_YES.\n",
    496              func_name);
    497   }
    498   else if (0 != memcmp (hash_bin, data->hash, sizeof(data->hash)))
    499   {
    500     failed++;
    501     bin2hex (hash_bin, sizeof(hash_bin), hash_hex);
    502     bin2hex (data->hash, sizeof(data->hash), expected_hex);
    503     fprintf (stderr,
    504              "FAILED: %s() produced wrong hash. "
    505              "Calculated digest %s, expected digest %s.\n",
    506              func_name,
    507              hash_hex, expected_hex);
    508   }
    509 
    510   if (failed)
    511   {
    512     fprintf (stderr,
    513              "The check failed for data located at line: %u.\n",
    514              data->line_num);
    515     fflush (stderr);
    516   }
    517   else if (verbose)
    518   {
    519     printf ("PASSED: check for data at line: %u.\n",
    520             data->line_num);
    521   }
    522   return failed ? 1 : 0;
    523 }
    524 
    525 
    526 static unsigned int
    527 test_sha512_256 (void)
    528 {
    529   unsigned int num_failed = 0;
    530   size_t i;
    531 
    532   for (i = 0; i < sizeof(sha512_256_tests) / sizeof(sha512_256_tests[0]); i++)
    533     num_failed += check_sha512_256 (sha512_256_tests + i);
    534   return num_failed;
    535 }
    536 
    537 
    538 static unsigned int
    539 test_sha512_256_failure (void)
    540 {
    541   static const enum MHD_DigestAuthAlgo3 algo3 =
    542     MHD_DIGEST_AUTH_ALGO3_SHA512_256;
    543   static const enum MHD_FEATURE feature = MHD_FEATURE_DIGEST_AUTH_SHA512_256;
    544   uint8_t hash_bin[MHD_SHA512_256_DIGEST_SIZE];
    545   char hash_hex[MHD_SHA512_256_DIGEST_SIZE * 2 + 1];
    546   const char *func_name;
    547   unsigned int failed = 0;
    548 
    549   func_name = "MHD_digest_auth_calc_userhash";
    550   if (MHD_NO != MHD_digest_auth_calc_userhash (algo3,
    551                                                "u", "r",
    552                                                hash_bin, sizeof(hash_bin) - 1))
    553   {
    554     failed++;
    555     fprintf (stderr,
    556              "FAILED: %s() has not returned MHD_NO at line: %u.\n",
    557              func_name, (unsigned) __LINE__);
    558   }
    559   if (MHD_NO != MHD_digest_auth_calc_userhash (algo3,
    560                                                "u", "r",
    561                                                hash_bin, 0))
    562   {
    563     failed++;
    564     fprintf (stderr,
    565              "FAILED: %s() has not returned MHD_NO at line: %u.\n",
    566              func_name, (unsigned) __LINE__);
    567   }
    568   if (MHD_NO == MHD_is_feature_supported (feature))
    569   {
    570     if (MHD_NO != MHD_digest_auth_calc_userhash (algo3,
    571                                                  "u", "r",
    572                                                  hash_bin, sizeof(hash_bin)))
    573     {
    574       failed++;
    575       fprintf (stderr,
    576                "FAILED: %s() has not returned MHD_NO at line: %u.\n",
    577                func_name, (unsigned) __LINE__);
    578     }
    579   }
    580 
    581   func_name = "MHD_digest_auth_calc_userhash_hex";
    582   if (MHD_NO !=
    583       MHD_digest_auth_calc_userhash_hex (algo3,
    584                                          "u", "r",
    585                                          hash_hex, sizeof(hash_hex) - 1))
    586   {
    587     failed++;
    588     fprintf (stderr,
    589              "FAILED: %s() has not returned MHD_NO at line: %u.\n",
    590              func_name, (unsigned) __LINE__);
    591   }
    592   if (MHD_NO !=
    593       MHD_digest_auth_calc_userhash_hex (algo3,
    594                                          "u", "r",
    595                                          hash_hex, 0))
    596   {
    597     failed++;
    598     fprintf (stderr,
    599              "FAILED: %s() has not returned MHD_NO at line: %u.\n",
    600              func_name, (unsigned) __LINE__);
    601   }
    602   if (MHD_NO == MHD_is_feature_supported (feature))
    603   {
    604     if (MHD_NO !=
    605         MHD_digest_auth_calc_userhash_hex (algo3,
    606                                            "u", "r",
    607                                            hash_hex, sizeof(hash_hex)))
    608     {
    609       failed++;
    610       fprintf (stderr,
    611                "FAILED: %s() has not returned MHD_NO at line: %u.\n",
    612                func_name, (unsigned) __LINE__);
    613     }
    614   }
    615 
    616   if (! failed && verbose)
    617   {
    618     printf ("PASSED: all checks with expected MHD_NO result near line: %u.\n",
    619             (unsigned) __LINE__);
    620   }
    621   return failed ? 1 : 0;
    622 }
    623 
    624 
    625 int
    626 main (int argc, char *argv[])
    627 {
    628   unsigned int num_failed = 0;
    629   (void) has_in_name; /* Mute compiler warning. */
    630   if (has_param (argc, argv, "-s") || has_param (argc, argv, "--silent"))
    631     verbose = 0;
    632 
    633 #ifdef NEED_GCRYP_INIT
    634   gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0);
    635 #ifdef GCRYCTL_INITIALIZATION_FINISHED
    636   gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
    637 #endif /* GCRYCTL_INITIALIZATION_FINISHED */
    638 #endif /* NEED_GCRYP_INIT */
    639 
    640   if (MHD_is_feature_supported (MHD_FEATURE_DIGEST_AUTH_MD5))
    641     num_failed += test_md5 ();
    642   num_failed += test_md5_failure ();
    643   if (MHD_is_feature_supported (MHD_FEATURE_DIGEST_AUTH_SHA256))
    644     num_failed += test_sha256 ();
    645   num_failed += test_sha256_failure ();
    646   if (MHD_is_feature_supported (MHD_FEATURE_DIGEST_AUTH_SHA512_256))
    647     num_failed += test_sha512_256 ();
    648   num_failed += test_sha512_256_failure ();
    649 
    650   return num_failed ? 1 : 0;
    651 }