libmicrohttpd2

HTTP server C library (MHD 2.x, alpha)
Log | Files | Refs | README | LICENSE

commit 4b7f569c79a1d785ae0b2e6f7c49ee2f5a837be4
parent f17b51ab9ea757c59f209a042bac818d9a0b6287
Author: Christian Grothoff <christian@grothoff.org>
Date:   Sun, 23 Nov 2025 22:39:30 +0100

add md5 unit test

Diffstat:
Msrc/mhd2/Makefile.am | 19++++++++++++++++++-
Msrc/tests/unit/Makefile.am | 22++++++++++++++++++++++
Asrc/tests/unit/unit_md5.c | 276+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 316 insertions(+), 1 deletion(-)

diff --git a/src/mhd2/Makefile.am b/src/mhd2/Makefile.am @@ -19,6 +19,7 @@ lib_LTLIBRARIES = \ libmicrohttpd2.la crypt_LDFLAGS = $(MHD_TLS_LIB_LDFLAGS) +crypt_LIBDEPS = $(MHD_TLS_LIBDEPS) noinst_DATA = MOSTLYCLEANFILES = @@ -167,16 +168,22 @@ if MHD_SUPPORT_OPENSSL md5_ext_openssl.c crypt_LDFLAGS += \ $(OPENSSL_LDFLAGS) + crypt_LIBDEPS += \ + $(OPENSSL_LIBS) else if MHD_SUPPORT_GNUTLS md5_OPTSOURCES += \ md5_ext_gnutls.c crypt_LDFLAGS += \ $(GNUTLS_LDFLAGS) + crypt_LIBDEPS += \ + $(GNUTLS_LIBS) else md5_OPTSOURCES += \ md5_ext_mbedtls.c crypt_LDFLAGS += \ + $(MBEDTLS_LDFLAGS) + crypt_LIBDEPS += \ -lmbedcrypto endif endif @@ -196,16 +203,22 @@ if MHD_SUPPORT_OPENSSL sha256_ext_openssl.c crypt_LDFLAGS += \ $(OPENSSL_LDFLAGS) + crypt_LIBDEPS += \ + $(OPENSSL_LIBS) else if MHD_SUPPORT_GNUTLS sha256_OPTSOURCES += \ sha256_ext_gnutls.c crypt_LDFLAGS += \ $(GNUTLS_LDFLAGS) + crypt_LIBDEPS += \ + $(GNUTLS_LIBS) else sha256_OPTSOURCES += \ sha256_ext_mbedtls.c crypt_LDFLAGS += \ + $(MBEDTLS_LDFLAGS) + crypt_LIBDEPS += \ -lmbedcrypto endif endif @@ -226,10 +239,14 @@ if MHD_SUPPORT_OPENSSL sha512_256_ext_openssl.c crypt_LDFLAGS += \ $(OPENSSL_LDFLAGS) + crypt_LIBDEPS += \ + $(OPENSSL_LIBS) else sha256_OPTSOURCES += \ sha512_256_ext_mbedtls.c crypt_LDFLAGS += \ + $(MBEDTLS_LDFLAGS) + crypt_LIBDEPS += \ -lmbedcrypto endif else @@ -334,7 +351,7 @@ libmicrohttpd2_la_LDFLAGS = \ -export-dynamic -no-undefined \ -version-info @LIB_VER_CURRENT@:@LIB_VER_REVISION@:@LIB_VER_AGE@ libmicrohttpd2_la_LIBADD = \ - $(MHD_LIBDEPS) $(MHD_TLS_LIBDEPS) + $(MHD_LIBDEPS) $(MHD_TLS_LIBDEPS) $(crypt_LIBDEPS) libmicrohttpd2_la_SHORTNAME = mhd2 diff --git a/src/tests/unit/Makefile.am b/src/tests/unit/Makefile.am @@ -39,6 +39,11 @@ check_PROGRAMS += \ $(EMPTY_ITEM) endif +if MHD_SUPPORT_MD5 +check_PROGRAMS += \ + unit_md5 +endif + TESTS = $(check_PROGRAMS) unit_h2_huffman_encode_SOURCES = \ @@ -58,3 +63,20 @@ unit_hpack_tables_dynamic_SOURCES = \ unit_hpack_tables_static_SOURCES = $(unit_hpack_tables_dynamic_SOURCES) unit_hpack_tables_combined_SOURCES = $(unit_hpack_tables_dynamic_SOURCES) + +unit_md5_SOURCES = unit_md5.c + +if MHD_MD5_EXTR +if MHD_SUPPORT_OPENSSL +unit_md5_LDFLAGS = $(OPENSSL_LDFLAGS) +unit_md5_LDADD = $(OPENSSL_LDFLAGS) +else +if MHD_SUPPORT_GNUTLS +unit_md5_LDFLAGS = $(GNUTLS_LDFLAGS) +unit_md5_LDADD = $(GNUTLS_LIBS) +else +unit_md5_LDFLAGS = $(MBEDTLS_LDFLAGS) +unit_md5_LDADD = -lmbedcrypto +endif +endif +endif diff --git a/src/tests/unit/unit_md5.c b/src/tests/unit/unit_md5.c @@ -0,0 +1,276 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later OR (GPL-2.0-or-later WITH eCos-exception-2.0) */ +/* + This file is part of GNU libmicrohttpd. + Copyright (C) 2025 Christian Grothoff + + GNU libmicrohttpd is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + GNU libmicrohttpd is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + Alternatively, you can redistribute GNU libmicrohttpd and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of + the License, or (at your option) any later version, together + with the eCos exception, as follows: + + As a special exception, if other files instantiate templates or + use macros or inline functions from this file, or you compile this + file and link it with other works to produce a work based on this + file, this file does not by itself cause the resulting work to be + covered by the GNU General Public License. However the source code + for this file must still be made available in accordance with + section (3) of the GNU General Public License v2. + + This exception does not invalidate any other reasons why a work + based on this file might be covered by the GNU General Public + License. + + You should have received copies of the GNU Lesser General Public + License and the GNU General Public License along with this library; + if not, see <https://www.gnu.org/licenses/>. +*/ + +/** + * @file src/test/unit/unit_md5.c + * @brief The tests for MD5 + * @author Christian Grothoff + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <stdint.h> + +#include "mhd_sys_options.h" + +#if MHD_MD5_EXTR_GNUTLS +#include "../mhd2/md5_ext_gnutls.c" +#elif MHD_MD5_EXTR_MBEDTLS +#include "../mhd2/md5_ext_mbedtls.c" +#elif MHD_MD5_EXTR_OPENSSL +#include "../mhd2/md5_ext_openssl.c" +#else +#include "../mhd2/md5_int.c" +#endif + +#include "../mhd2/mhd_md5.h" + + +/* Define to 1 if libmicrohttpd is compiled with MD5 hashing by OpenSSL. */ +/* #undef MHD_MD5_EXTR_OPENSSL */ + +/* Helper function to convert hex string to binary */ +static size_t +hex2bin (const char *hex, + uint8_t *bin, + size_t max_len) +{ + size_t len = strlen (hex) / 2; + + if (len > max_len) + len = max_len; + for (size_t i = 0; i < len; i++) + { + sscanf (hex + 2 * i, + "%2hhx", + &bin[i]); + } + return len; +} + + +/* Helper function to compare digest with expected hex string */ +static int +check_digest (const uint8_t *digest, + size_t digest_len, + const char *expected_hex, + const char *test_name) +{ + uint8_t expected[64]; + size_t expected_len = hex2bin (expected_hex, + expected, + sizeof(expected)); + + if (expected_len != digest_len) + { + printf ("FAIL: %s - length mismatch\n", + test_name); + return 0; + } + + if (0 != + memcmp (digest, + expected, + digest_len)) + { + printf ("FAIL: %s\n", + test_name); + printf (" Expected: %s\n", + expected_hex); + printf (" Got: "); + for (size_t i = 0; i < digest_len; i++) + { + printf ("%02x", + digest[i]); + } + printf ("\n"); + return 0; + } + return 1; +} + + +int +main (void) +{ + struct Test + { + const char *name; + const char *input; + const char *digest; + } tests[] = { + { "Empty string (RFC 1321)", + "", + "d41d8cd98f00b204e9800998ecf8427e" }, + { "a (RFC 1321)", + "61", + "0cc175b9c0f1b6a831c399e269772661" }, + { "abc (RFC 1321)", + "616263", + "900150983cd24fb0d6963f7d28e17f72" }, + { "a (RFC 1321)", + "61", + "0cc175b9c0f1b6a831c399e269772661" }, + { "message digest (RFC 1321)", + "6d65737361676520646967657374", + "f96b697d7cb7938d525a2f31aaf161d0" }, + { "abcdefghijklmnopqrstuvwxyz (RFC 1321)", + "6162636465666768696A6B6C6D6E6F707172737475767778797A", + "c3fcd3d76192e4007dfb496cca67e13b" }, + { "A-Za-z0-9 (RFC 1321)", + "4142434445464748494A4B4C4D4E4F505152535455565758595A6162636465666768696A6B6C6D6E6F707172737475767778797A30313233343536373839", + "d174ab98d277d9f5a5611c2c9f419d9f" }, + { "8 repetitions of 1234567890 (RFC 1321)", + "3132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930313233343536373839303132333435363738393031323334353637383930", + "57edf4a22be3c955ac49da2e2107b67a" }, + { "The quick brown fox jumps over the lazy dog (Wikipedia MD5 article)", + "54686520717569636B2062726F776E20666F78206A756D7073206F76657220746865206C617A7920646F67", + "9e107d9d372bb6826bd81d3542a419d6" }, + { "0x00", + "00", + "93b885adfe0da089cdf634904fd59f71" }, + { "Two bytes 0x00 0x00", + "0000", + "c4103f122d27677c9db144cae1394a66" }, + { NULL, NULL, NULL } + }; + struct mhd_Md5Ctx ctx; + uint8_t digest[mhd_MD5_DIGEST_SIZE]; + uint8_t data[1024]; + size_t data_len; + unsigned int passed = 0; + unsigned int total = 0; + + while (NULL != tests[total].name) + { + const struct Test *t = &tests[total]; + + mhd_MD5_init_one_time (&ctx); + if (! mhd_MD5_has_err (&ctx)) + { + data_len = hex2bin (t->input, + data, + sizeof(data)); + if (0 != data_len) + mhd_MD5_update (&ctx, + data_len, + data); + mhd_MD5_finish_deinit (&ctx, + digest); + if (! mhd_MD5_has_err (&ctx)) + { + if (check_digest (digest, + mhd_MD5_DIGEST_SIZE, + t->digest, + t->name)) + passed++; + } + else + { + printf ("FAIL: %s - error in finish\n", + t->name); + } + } + else + { + printf ("FAIL: %s - error in init\n", + t->name); + } + total++; + } + + /* + * Test update functionality + */ + total++; + mhd_MD5_init_one_time (&ctx); + if (! mhd_MD5_has_err (&ctx)) + { + data[0] = 'a'; + mhd_MD5_update (&ctx, 1, data); + data[0] = 'b'; + mhd_MD5_update (&ctx, 1, data); + data[0] = 'c'; + mhd_MD5_update (&ctx, 1, data); + mhd_MD5_finish_deinit (&ctx, digest); + if (! mhd_MD5_has_err (&ctx)) + { + if (check_digest (digest, + mhd_MD5_DIGEST_SIZE, + "900150983cd24fb0d6963f7d28e17f72", + "Multi-update: a + b + c")) + passed++; + } + } + + /* + * Tests finish_reset and reuse of context + */ + total++; + mhd_MD5_init_one_time (&ctx); + if (! mhd_MD5_has_err (&ctx)) + { + /* First hash */ + data_len = hex2bin ("616263", + data, + sizeof(data)); /* "abc" */ + mhd_MD5_update (&ctx, data_len, data); + mhd_MD5_finish_reset (&ctx, digest); + + /* Second hash on same context */ + data_len = hex2bin ("616263", data, sizeof(data)); /* "abc" again */ + mhd_MD5_update (&ctx, data_len, data); + mhd_MD5_finish_deinit (&ctx, digest); + + if (! mhd_MD5_has_err (&ctx)) + { + if (check_digest (digest, + mhd_MD5_DIGEST_SIZE, + "900150983cd24fb0d6963f7d28e17f72", + "Reset and reuse context")) + passed++; + } + } + + printf ("Results: %d/%d tests passed\n", + passed, + total); + + return (passed == total) ? 0 : 1; +}