libmicrohttpd

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

test_dauth_userdigest.c (21293B)


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