gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[GNUnet-SVN] [libmicrohttpd] branch master updated: preliminary implemen


From: gnunet
Subject: [GNUnet-SVN] [libmicrohttpd] branch master updated: preliminary implementation for RFC 7616 support
Date: Sat, 08 Dec 2018 17:35:39 +0100

This is an automated email from the git hooks/post-receive script.

grothoff pushed a commit to branch master
in repository libmicrohttpd.

The following commit(s) were added to refs/heads/master by this push:
     new bcba3f58 preliminary implementation for RFC 7616 support
bcba3f58 is described below

commit bcba3f58c5fc9b4a3776494d3edddceb244ab110
Author: Christian Grothoff <address@hidden>
AuthorDate: Sat Dec 8 17:35:37 2018 +0100

    preliminary implementation for RFC 7616 support
---
 ChangeLog                   |   4 +
 src/include/microhttpd.h    | 114 ++++++-
 src/microhttpd/Makefile.am  |   9 +-
 src/microhttpd/digestauth.c | 779 +++++++++++++++++++++++++++++---------------
 src/microhttpd/md5.c        | 130 +++++---
 src/microhttpd/md5.h        |  37 ++-
 src/microhttpd/sha256.c     |  88 ++---
 src/microhttpd/sha256.h     |  45 ++-
 8 files changed, 805 insertions(+), 401 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 53a72733..352cdc8e 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+Sat Dec  8 17:34:58 CET 2018
+       Adding support for RFC 7616, experimental, needs
+       testing and documentation still! -CG
+
 Fri Dec  7 12:37:17 CET 2018
        Add option to build MHD without any threads
        and MHD_FEATURE_THREADS to test for it.  -CG
diff --git a/src/include/microhttpd.h b/src/include/microhttpd.h
index b9a9bcf9..7591bdc4 100644
--- a/src/include/microhttpd.h
+++ b/src/include/microhttpd.h
@@ -3192,7 +3192,30 @@ MHD_free (void *ptr);
 
 
 /**
- * Authenticates the authorization header sent by the client
+ * Which digest algorithm should MHD use for HTTP digest authentication?
+ */
+enum MHD_DigestAuthAlgorithm {
+
+  /**
+   * MHD should pick (currently defaults to SHA-256).
+   */
+  MHD_DIGEST_ALG_AUTO = 0,
+
+  /**
+   * Force use of MD5.
+   */
+  MHD_DIGEST_ALG_MD5,
+
+  /**
+   * Force use of SHA-256.
+   */
+  MHD_DIGEST_ALG_SHA256
+
+};
+
+
+/**
+ * Authenticates the authorization header sent by the client.
  *
  * @param connection The MHD connection structure
  * @param realm The realm presented to the client
@@ -3200,11 +3223,39 @@ MHD_free (void *ptr);
  * @param password The password used in the authentication
  * @param nonce_timeout The amount of time for a nonce to be
  *                     invalid in seconds
+ * @param algo digest algorithms allowed for verification
  * @return #MHD_YES if authenticated, #MHD_NO if not,
  *                     #MHD_INVALID_NONCE if nonce is invalid
  * @ingroup authentication
  */
 _MHD_EXTERN int
+MHD_digest_auth_check2 (struct MHD_Connection *connection,
+                       const char *realm,
+                       const char *username,
+                       const char *password,
+                       unsigned int nonce_timeout,
+                       enum MHD_DigestAuthAlgorithm algo);
+
+
+/**
+ * Authenticates the authorization header sent by the client.
+ * Uses #MHD_DIGEST_ALG_MD5 (for now, for backwards-compatibility).
+ * Note that this MAY change to #MHD_DIGEST_ALG_AUTO in the future.
+ * If you want to be sure you get MD5, use #MHD_digest_auth_check2()
+ * and specifiy MD5 explicitly.
+ *
+ * @param connection The MHD connection structure
+ * @param realm The realm presented to the client
+ * @param username The username needs to be authenticated
+ * @param password The password used in the authentication
+ * @param nonce_timeout The amount of time for a nonce to be
+ *                     invalid in seconds
+ * @return #MHD_YES if authenticated, #MHD_NO if not,
+ *                     #MHD_INVALID_NONCE if nonce is invalid
+ * @ingroup authentication
+ * @deprecated use MHD_digest_auth_check2()
+ */
+_MHD_EXTERN int
 MHD_digest_auth_check (struct MHD_Connection *connection,
                       const char *realm,
                       const char *username,
@@ -3213,21 +3264,51 @@ MHD_digest_auth_check (struct MHD_Connection 
*connection,
 
 
 /**
- * Authenticates the authorization header sent by the client
+ * Authenticates the authorization header sent by the client.
  *
  * @param connection The MHD connection structure
  * @param realm The realm presented to the client
  * @param username The username needs to be authenticated
  * @param digest An `unsigned char *' pointer to the binary MD5 sum
  *                     for the precalculated hash value 
"username:realm:password"
- *                     of #MHD_MD5_DIGEST_SIZE bytes
+ *                     of @a digest_size bytes
+ * @param digest_size number of bytes in @a digest (size must match @a algo!)
  * @param nonce_timeout The amount of time for a nonce to be
  *                     invalid in seconds
+ * @param algo digest algorithms allowed for verification
  * @return #MHD_YES if authenticated, #MHD_NO if not,
  *                     #MHD_INVALID_NONCE if nonce is invalid
  * @ingroup authentication
  */
 _MHD_EXTERN int
+MHD_digest_auth_check_digest2 (struct MHD_Connection *connection,
+                              const char *realm,
+                              const char *username,
+                              const uint8_t *digest,
+                               size_t digest_size,
+                              unsigned int nonce_timeout,
+                              enum MHD_DigestAuthAlgorithm algo);
+
+
+/**
+ * Authenticates the authorization header sent by the client
+ * Uses #MHD_DIGEST_ALG_MD5 (required, as @a digest is of fixed
+ * size).
+ *
+ * @param connection The MHD connection structure
+ * @param realm The realm presented to the client
+ * @param username The username needs to be authenticated
+ * @param digest An `unsigned char *' pointer to the binary hash
+ *             for the precalculated hash value "username:realm:password";
+ *             length must be #MHD_MD5_DIGEST_SIZE bytes
+ * @param nonce_timeout The amount of time for a nonce to be
+ *                     invalid in seconds
+ * @return #MHD_YES if authenticated, #MHD_NO if not,
+ *                     #MHD_INVALID_NONCE if nonce is invalid
+ * @ingroup authentication
+ * @deprecated use #MHD_digest_auth_check_digest2()
+ */
+_MHD_EXTERN int
 MHD_digest_auth_check_digest (struct MHD_Connection *connection,
                              const char *realm,
                              const char *username,
@@ -3239,6 +3320,32 @@ MHD_digest_auth_check_digest (struct MHD_Connection 
*connection,
  * Queues a response to request authentication from the client
  *
  * @param connection The MHD connection structure
+ * @param realm the realm presented to the client
+ * @param opaque string to user for opaque value
+ * @param response reply to send; should contain the "access denied"
+ *        body; note that this function will set the "WWW Authenticate"
+ *        header and that the caller should not do this
+ * @param signal_stale #MHD_YES if the nonce is invalid to add
+ *                     'stale=true' to the authentication header
+ * @param algo digest algorithm to use
+ * @return #MHD_YES on success, #MHD_NO otherwise
+ * @ingroup authentication
+ */
+int
+MHD_queue_auth_fail_response2 (struct MHD_Connection *connection,
+                              const char *realm,
+                              const char *opaque,
+                              struct MHD_Response *response,
+                              int signal_stale,
+                              enum MHD_DigestAuthAlgorithm algo);
+
+
+/**
+ * Queues a response to request authentication from the client
+ * For now uses MD5 (for backwards-compatibility). Still, if you
+ * need to be sure, use #MHD_queue_fail_auth_response2().
+ *
+ * @param connection The MHD connection structure
  * @param realm The realm presented to the client
  * @param opaque string to user for opaque value
  * @param response reply to send; should contain the "access denied"
@@ -3248,6 +3355,7 @@ MHD_digest_auth_check_digest (struct MHD_Connection 
*connection,
  *                     'stale=true' to the authentication header
  * @return #MHD_YES on success, #MHD_NO otherwise
  * @ingroup authentication
+ * @deprecated use MHD_queue_auth_fail_response2()
  */
 _MHD_EXTERN int
 MHD_queue_auth_fail_response (struct MHD_Connection *connection,
diff --git a/src/microhttpd/Makefile.am b/src/microhttpd/Makefile.am
index 2c59876a..22b6100d 100644
--- a/src/microhttpd/Makefile.am
+++ b/src/microhttpd/Makefile.am
@@ -133,7 +133,8 @@ endif
 if ENABLE_DAUTH
 libmicrohttpd_la_SOURCES += \
   digestauth.c \
-  md5.c md5.h
+  md5.c md5.h \
+  sha256.c sha256.h
 endif
 
 if ENABLE_BAUTH
@@ -160,18 +161,18 @@ check_PROGRAMS = \
 
 if HAVE_POSIX_THREADS
 if ENABLE_UPGRADE
-if USE_POSIX_THREADS 
+if USE_POSIX_THREADS
   check_PROGRAMS += test_upgrade
 endif
 if USE_W32_THREADS
   check_PROGRAMS += test_upgrade
 endif
 if ENABLE_HTTPS
-if USE_POSIX_THREADS 
+if USE_POSIX_THREADS
 check_PROGRAMS += test_upgrade_tls
 endif
 if USE_W32_THREADS
-check_PROGRAMS += test_upgrade_tls     
+check_PROGRAMS += test_upgrade_tls
 endif
 endif
 endif
diff --git a/src/microhttpd/digestauth.c b/src/microhttpd/digestauth.c
index 80cba836..424c3761 100644
--- a/src/microhttpd/digestauth.c
+++ b/src/microhttpd/digestauth.c
@@ -21,11 +21,13 @@
  * @brief Implements HTTP digest authentication
  * @author Amr Ali
  * @author Matthieu Speder
+ * @author Christian Grothoff (RFC 7616 support)
  */
 #include "platform.h"
 #include "mhd_limits.h"
 #include "internal.h"
 #include "md5.h"
+#include "sha256.h"
 #include "mhd_mono_clock.h"
 #include "mhd_str.h"
 #include "mhd_compat.h"
@@ -37,13 +39,18 @@
 #include <windows.h>
 #endif /* MHD_W32_MUTEX_ */
 
-#define HASH_MD5_HEX_LEN (2 * MHD_MD5_DIGEST_SIZE)
-/* 32 bit value is 4 bytes */
+/**
+ * 32 bit value is 4 bytes
+ */
 #define TIMESTAMP_BIN_SIZE 4
-#define TIMESTAMP_HEX_LEN (2 * TIMESTAMP_BIN_SIZE)
 
-/* Standard server nonce length, not including terminating null */
-#define NONCE_STD_LEN (HASH_MD5_HEX_LEN + TIMESTAMP_HEX_LEN)
+/**
+ * Standard server nonce length, not including terminating null,
+ *
+ * @param digest_size digest size
+ */
+#define NONCE_STD_LEN(digest_size) \
+  ((digest_size) * 2 + TIMESTAMP_BIN_SIZE * 2)
 
 /**
  * Beginning string for any valid Digest authentication header.
@@ -63,7 +70,66 @@
 /**
  * Maximum length of the response in digest authentication.
  */
-#define MAX_AUTH_RESPONSE_LENGTH 128
+#define MAX_AUTH_RESPONSE_LENGTH 256
+
+
+/**
+ * Context passed to functions that need to calculate
+ * a digest but are orthogonal to the specific
+ * algorithm.
+ */
+struct DigestAlgorithm
+{
+  /**
+   * Size of the final digest returned by @e digest.
+   */
+  unsigned int digest_size;
+
+  /**
+   * A context for the digest algorithm, already initialized to be
+   * useful for @e init, @e update and @e digest.
+   */
+  void *ctx;
+
+  /**
+   * Name of the algorithm, "md5" or "sha-256"
+   */
+  const char *alg;
+
+  /**
+   * Buffer of @e digest_size * 2 + 1 bytes.
+   */
+  char *sessionkey;
+
+  /**
+   * Call to initialize @e ctx.
+   */
+  void
+  (*init)(void *ctx);
+
+  /**
+   * Feed more data into the digest function.
+   *
+   * @param ctx context to feed
+   * @param length number of bytes in @a data
+   * @param data data to add
+   */
+  void
+  (*update)(void *ctx,
+           const uint8_t *data,
+            size_t length);
+
+  /**
+   * Compute final @a digest.
+   *
+   * @param ctx context to use
+   * @param digest[out] where to write the result,
+   *        must be @e digest_length bytes long
+   */
+  void
+  (*digest)(void *ctx,
+           uint8_t *digest);
+};
 
 
 /**
@@ -97,54 +163,57 @@ cvthex (const unsigned char *bin,
  * and store the * result in 'sessionkey'.
  *
  * @param alg The hash algorithm used, can be "md5" or "md5-sess"
+ *            or "sha-256" or "sha-256-sess"
+ *    Note that the rest of the code does not support the the "-sess" variants!
+ * @param da[in,out] digest implementation, must match @a alg; the
+ *          da->sessionkey will be initialized to the digest in HEX
  * @param digest An `unsigned char *' pointer to the binary MD5 sum
  *                     for the precalculated hash value 
"username:realm:password"
- *                     of #MHD_MD5_DIGEST_SIZE bytes
+ *                     of #MHD_MD5_DIGEST_SIZE or #MHD_SHA256_DIGEST_SIZE bytes
  * @param nonce A `char *' pointer to the nonce value
  * @param cnonce A `char *' pointer to the cnonce value
- * @param sessionkey pointer to buffer of HASH_MD5_HEX_LEN+1 bytes
  */
 static void
 digest_calc_ha1_from_digest (const char *alg,
-                            const uint8_t digest[MHD_MD5_DIGEST_SIZE],
+                             struct DigestAlgorithm *da,
+                            const uint8_t *digest,
                             const char *nonce,
-                            const char *cnonce,
-                            char sessionkey[HASH_MD5_HEX_LEN + 1])
+                            const char *cnonce)
 {
-  struct MD5Context md5;
-
-  if (MHD_str_equal_caseless_(alg,
-                              "md5-sess"))
+  if ( (MHD_str_equal_caseless_(alg,
+                                "md5-sess")) ||
+       (MHD_str_equal_caseless_(alg,
+                                "sha-256-sess")) )
     {
-      unsigned char ha1[MHD_MD5_DIGEST_SIZE];
-
-      MD5Init (&md5);
-      MD5Update (&md5,
-                digest,
-                 MHD_MD5_DIGEST_SIZE);
-      MD5Update (&md5,
+      uint8_t dig[da->digest_size];
+
+      da->init (da->ctx);
+      da->update (da->ctx,
+                  digest,
+                  MHD_MD5_DIGEST_SIZE);
+      da->update (da->ctx,
+                  (const unsigned char *) ":",
+                  1);
+      da->update (da->ctx,
+                  (const unsigned char *) nonce,
+                  strlen (nonce));
+      da->update (da->ctx,
                  (const unsigned char *) ":",
                  1);
-      MD5Update (&md5,
-                 (const unsigned char *) nonce,
-                 strlen (nonce));
-      MD5Update (&md5,
-                 (const unsigned char *) ":",
-                 1);
-      MD5Update (&md5,
-                 (const unsigned char *) cnonce,
-                 strlen (cnonce));
-      MD5Final (ha1,
-                &md5);
-      cvthex (ha1,
-              sizeof (ha1),
-              sessionkey);
+      da->update (da->ctx,
+                  (const unsigned char *) cnonce,
+                  strlen (cnonce));
+      da->digest (da->ctx,
+                  dig);
+      cvthex (dig,
+              sizeof (dig),
+              da->sessionkey);
     }
   else
     {
       cvthex (digest,
-             MHD_MD5_DIGEST_SIZE,
-             sessionkey);
+             da->digest_size,
+             da->sessionkey);
     }
 }
 
@@ -154,12 +223,14 @@ digest_calc_ha1_from_digest (const char *alg,
  * and store the result in 'sessionkey'.
  *
  * @param alg The hash algorithm used, can be "md5" or "md5-sess"
+ *             or "sha-256" or "sha-256-sess"
  * @param username A `char *' pointer to the username value
  * @param realm A `char *' pointer to the realm value
  * @param password A `char *' pointer to the password value
  * @param nonce A `char *' pointer to the nonce value
  * @param cnonce A `char *' pointer to the cnonce value
- * @param sessionkey pointer to buffer of HASH_MD5_HEX_LEN+1 bytes
+ * @param da[in,out] digest algorithm to use, and where to write
+ *         the sessionkey to
  */
 static void
 digest_calc_ha1_from_user (const char *alg,
@@ -168,52 +239,54 @@ digest_calc_ha1_from_user (const char *alg,
                           const char *password,
                           const char *nonce,
                           const char *cnonce,
-                          char sessionkey[HASH_MD5_HEX_LEN + 1])
+                           struct DigestAlgorithm *da)
 {
-  struct MD5Context md5;
-  unsigned char ha1[MHD_MD5_DIGEST_SIZE];
+  unsigned char ha1[da->digest_size];
 
-  MD5Init (&md5);
-  MD5Update (&md5,
+  da->init (da->ctx);
+  da->update (da->ctx,
              (const unsigned char *) username,
              strlen (username));
-  MD5Update (&md5,
-             (const unsigned char *) ":",
-             1);
-  MD5Update (&md5,
-             (const unsigned char *) realm,
-             strlen (realm));
-  MD5Update (&md5,
-             (const unsigned char *) ":",
-             1);
-  MD5Update (&md5,
-             (const unsigned char *) password,
-             strlen (password));
-  MD5Final (ha1,
-            &md5);
-  digest_calc_ha1_from_digest(alg,
-                             ha1,
-                             nonce,
-                             cnonce,
-                             sessionkey);
+  da->update (da->ctx,
+              (const unsigned char *) ":",
+              1);
+  da->update (da->ctx,
+              (const unsigned char *) realm,
+              strlen (realm));
+  da->update (da->ctx,
+              (const unsigned char *) ":",
+              1);
+  da->update (da->ctx,
+              (const unsigned char *) password,
+              strlen (password));
+  da->digest (da->ctx,
+              ha1);
+  digest_calc_ha1_from_digest (alg,
+                               da,
+                               ha1,
+                               nonce,
+                               cnonce);
 }
 
 
 /**
- * Calculate request-digest/response-digest as per RFC2617 spec
+ * Calculate request-digest/response-digest as per RFC2617 / RFC7616
+ * spec.
  *
- * @param ha1 H(A1)
+ * @param ha1 H(A1), twice the @a da->digest_size + 1 bytes (0-terminated),
+ *        MUST NOT be aliased with `da->sessionkey`!
  * @param nonce nonce from server
  * @param noncecount 8 hex digits
  * @param cnonce client nonce
- * @param qop qop-value: "", "auth" or "auth-int"
+ * @param qop qop-value: "", "auth" or "auth-int" (NOTE: only 'auth' is 
supported today.)
  * @param method method from request
  * @param uri requested URL
  * @param hentity H(entity body) if qop="auth-int"
- * @param response request-digest or response-digest
+ * @param da[in,out] digest algorithm to use, also
+ *        we write da->sessionkey (set to response request-digest or 
response-digest)
  */
 static void
-digest_calc_response (const char ha1[HASH_MD5_HEX_LEN + 1],
+digest_calc_response (const char *ha1,
                      const char *nonce,
                      const char *noncecount,
                      const char *cnonce,
@@ -221,87 +294,85 @@ digest_calc_response (const char ha1[HASH_MD5_HEX_LEN + 
1],
                      const char *method,
                      const char *uri,
                      const char *hentity,
-                     char response[HASH_MD5_HEX_LEN + 1])
+                     struct DigestAlgorithm *da)
 {
-  struct MD5Context md5;
-  unsigned char ha2[MHD_MD5_DIGEST_SIZE];
-  unsigned char resphash[MHD_MD5_DIGEST_SIZE];
-  char ha2hex[HASH_MD5_HEX_LEN + 1];
-  (void)hentity; /* Unused. Silent compiler warning. */
-
-  MD5Init (&md5);
-  MD5Update (&md5,
-             (const unsigned char *) method,
-             strlen (method));
-  MD5Update (&md5,
-             (const unsigned char *) ":",
-             1);
-  MD5Update (&md5,
+  unsigned char ha2[da->digest_size];
+  unsigned char resphash[da->digest_size];
+  (void)hentity; /* Unused. Silence compiler warning. */
+
+  da->init (da->ctx);
+  da->update (da->ctx,
+              (const unsigned char *) method,
+              strlen (method));
+  da->update (da->ctx,
+              (const unsigned char *) ":",
+              1);
+  da->update (da->ctx,
              (const unsigned char *) uri,
              strlen (uri));
 #if 0
-  if (0 == strcasecmp(qop,
-                      "auth-int"))
+  if (0 == strcasecmp (qop,
+                       "auth-int"))
     {
       /* This is dead code since the rest of this module does
         not support auth-int. */
-      MD5Update (&md5,
-                 ":",
-                 1);
+      da->update (da->ctx,
+                  ":",
+                  1);
       if (NULL != hentity)
-       MD5Update (&md5,
-                   hentity,
-                   strlen (hentity));
+       da->update (da->ctx,
+                    hentity,
+                    strlen (hentity));
     }
 #endif
-  MD5Final (ha2,
-            &md5);
+  da->digest (da->ctx,
+              ha2);
   cvthex (ha2,
-          MHD_MD5_DIGEST_SIZE,
-          ha2hex);
-  MD5Init (&md5);
+          da->digest_size,
+          da->sessionkey);
+  da->init (da->ctx);
   /* calculate response */
-  MD5Update (&md5,
-             (const unsigned char *) ha1,
-             HASH_MD5_HEX_LEN);
-  MD5Update (&md5,
-             (const unsigned char *) ":",
-             1);
-  MD5Update (&md5,
-             (const unsigned char *) nonce,
-             strlen (nonce));
-  MD5Update (&md5,
-             (const unsigned char*) ":",
-             1);
+  da->update (da->ctx,
+              (const unsigned char *) ha1,
+              da->digest_size * 2);
+  da->update (da->ctx,
+              (const unsigned char *) ":",
+              1);
+  da->update (da->ctx,
+              (const unsigned char *) nonce,
+              strlen (nonce));
+  da->update (da->ctx,
+              (const unsigned char*) ":",
+              1);
   if ('\0' != *qop)
     {
-      MD5Update (&md5,
-                 (const unsigned char *) noncecount,
-                 strlen (noncecount));
-      MD5Update (&md5,
-                 (const unsigned char *) ":",
-                 1);
-      MD5Update (&md5,
-                 (const unsigned char *) cnonce,
-                 strlen (cnonce));
-      MD5Update (&md5,
-                 (const unsigned char *) ":",
-                 1);
-      MD5Update (&md5,
-                 (const unsigned char *) qop,
-                 strlen (qop));
-      MD5Update (&md5,
-                 (const unsigned char *) ":",
-                 1);
+      da->update (da->ctx,
+                  (const unsigned char *) noncecount,
+                  strlen (noncecount));
+      da->update (da->ctx,
+                  (const unsigned char *) ":",
+                  1);
+      da->update (da->ctx,
+                  (const unsigned char *) cnonce,
+                  strlen (cnonce));
+      da->update (da->ctx,
+                  (const unsigned char *) ":",
+                  1);
+      da->update (da->ctx,
+                  (const unsigned char *) qop,
+                  strlen (qop));
+      da->update (da->ctx,
+                  (const unsigned char *) ":",
+                  1);
     }
-  MD5Update (&md5,
-             (const unsigned char *) ha2hex,
-             HASH_MD5_HEX_LEN);
-  MD5Final (resphash,
-            &md5);
+  da->update (da->ctx,
+              (const unsigned char *) da->sessionkey,
+              da->digest_size * 2);
+  da->digest (da->ctx,
+              resphash);
   cvthex (resphash,
           sizeof(resphash),
-          response);
+          da->sessionkey);
 }
 
 
@@ -552,7 +623,9 @@ MHD_digest_auth_get_username(struct MHD_Connection 
*connection)
  * @param rnd_size The size of the random seed array @a rnd
  * @param uri HTTP URI (in MHD, without the arguments ("?k=v")
  * @param realm A string of characters that describes the realm of auth.
- * @param nonce A pointer to a character array for the nonce to put in
+ * @param da digest algorithm to use
+ * @param nonce A pointer to a character array for the nonce to put in,
+ *        must provide NONCE_STD_LEN(da->digest_size)+1 bytes
  */
 static void
 calculate_nonce (uint32_t nonce_time,
@@ -561,48 +634,48 @@ calculate_nonce (uint32_t nonce_time,
                 size_t rnd_size,
                 const char *uri,
                 const char *realm,
-                char nonce[NONCE_STD_LEN + 1])
+                 struct DigestAlgorithm *da,
+                char *nonce)
 {
-  struct MD5Context md5;
   unsigned char timestamp[TIMESTAMP_BIN_SIZE];
-  unsigned char tmpnonce[MHD_MD5_DIGEST_SIZE];
-  char timestamphex[TIMESTAMP_HEX_LEN + 1];
+  unsigned char tmpnonce[da->digest_size];
+  char timestamphex[TIMESTAMP_BIN_SIZE * 2 + 1];
 
-  MD5Init (&md5);
+  da->init (da->ctx);
   timestamp[0] = (unsigned char)((nonce_time & 0xff000000) >> 0x18);
   timestamp[1] = (unsigned char)((nonce_time & 0x00ff0000) >> 0x10);
   timestamp[2] = (unsigned char)((nonce_time & 0x0000ff00) >> 0x08);
   timestamp[3] = (unsigned char)((nonce_time & 0x000000ff));
-  MD5Update (&md5,
-             timestamp,
-             sizeof (timestamp));
-  MD5Update (&md5,
-             (const unsigned char *) ":",
-             1);
-  MD5Update (&md5,
-             (const unsigned char *) method,
-             strlen (method));
-  MD5Update (&md5,
-             (const unsigned char *) ":",
-             1);
+  da->update (da->ctx,
+              timestamp,
+              sizeof (timestamp));
+  da->update (da->ctx,
+              (const unsigned char *) ":",
+              1);
+  da->update (da->ctx,
+              (const unsigned char *) method,
+              strlen (method));
+  da->update (da->ctx,
+              (const unsigned char *) ":",
+              1);
   if (rnd_size > 0)
-    MD5Update (&md5,
-               (const unsigned char *) rnd,
-               rnd_size);
-  MD5Update (&md5,
-             (const unsigned char *) ":",
-             1);
-  MD5Update (&md5,
-             (const unsigned char *) uri,
-             strlen (uri));
-  MD5Update (&md5,
-             (const unsigned char *) ":",
-             1);
-  MD5Update (&md5,
-             (const unsigned char *) realm,
-             strlen (realm));
-  MD5Final (tmpnonce,
-            &md5);
+    da->update (da->ctx,
+                (const unsigned char *) rnd,
+                rnd_size);
+  da->update (da->ctx,
+              (const unsigned char *) ":",
+              1);
+  da->update (da->ctx,
+              (const unsigned char *) uri,
+              strlen (uri));
+  da->update (da->ctx,
+              (const unsigned char *) ":",
+              1);
+  da->update (da->ctx,
+              (const unsigned char *) realm,
+              strlen (realm));
+  da->digest (da->ctx,
+              tmpnonce);
   cvthex (tmpnonce,
           sizeof (tmpnonce),
           nonce);
@@ -713,12 +786,15 @@ check_argument_match (struct MHD_Connection *connection,
  * Authenticates the authorization header sent by the client
  *
  * @param connection The MHD connection structure
+ * @param da[in,out] digest algorithm to use for checking (written to as
+ *         part of the calculations, but the values left in the struct
+ *         are not actually expected to be useful for the caller)
  * @param realm The realm presented to the client
  * @param username The username needs to be authenticated
  * @param password The password used in the authentication
- * @param digest An optional `unsigned char *' pointer to the binary MD5 sum
- *                     for the precalculated hash value 
"username:realm:password"
- *                     of #MHD_MD5_DIGEST_SIZE bytes
+ * @param digest An optional binary hash
+ *              of the precalculated hash value "username:realm:password"
+ *              (must contain "da->digest_size" bytes or be NULL)
  * @param nonce_timeout The amount of time for a nonce to be
  *                     invalid in seconds
  * @return #MHD_YES if authenticated, #MHD_NO if not,
@@ -727,10 +803,11 @@ check_argument_match (struct MHD_Connection *connection,
  */
 static int
 digest_auth_check_all (struct MHD_Connection *connection,
+                       struct DigestAlgorithm *da,
                       const char *realm,
                       const char *username,
                       const char *password,
-                      const uint8_t digest[MHD_MD5_DIGEST_SIZE],
+                      const uint8_t *digest,
                       unsigned int nonce_timeout)
 {
   struct MHD_Daemon *daemon = connection->daemon;
@@ -738,13 +815,12 @@ digest_auth_check_all (struct MHD_Connection *connection,
   const char *header;
   char nonce[MAX_NONCE_LENGTH];
   char cnonce[MAX_NONCE_LENGTH];
+  char ha1[da->digest_size * 2 + 1];
   char qop[15]; /* auth,auth-int */
   char nc[20];
   char response[MAX_AUTH_RESPONSE_LENGTH];
   const char *hentity = NULL; /* "auth-int" is not supported */
-  char ha1[HASH_MD5_HEX_LEN + 1];
-  char respexp[HASH_MD5_HEX_LEN + 1];
-  char noncehashexp[NONCE_STD_LEN + 1];
+  char noncehashexp[NONCE_STD_LEN(da->digest_size) + 1];
   uint32_t nonce_time;
   uint32_t t;
   size_t left; /* number of characters left in 'header' for 'uri' */
@@ -807,9 +883,9 @@ digest_auth_check_all (struct MHD_Connection *connection,
        header value. */
     return MHD_NO;
   }
-  if (TIMESTAMP_HEX_LEN !=
-      MHD_strx_to_uint32_n_ (nonce + len - TIMESTAMP_HEX_LEN,
-                             TIMESTAMP_HEX_LEN,
+  if (TIMESTAMP_BIN_SIZE * 2 !=
+      MHD_strx_to_uint32_n_ (nonce + len - TIMESTAMP_BIN_SIZE * 2,
+                             TIMESTAMP_BIN_SIZE * 2,
                              &nonce_time))
     {
 #ifdef HAVE_MESSAGES
@@ -837,6 +913,7 @@ digest_auth_check_all (struct MHD_Connection *connection,
                    daemon->digest_auth_rand_size,
                    connection->url,
                    realm,
+                   da,
                    noncehashexp);
   /*
    * Second level vetting for the nonce validity
@@ -848,7 +925,8 @@ digest_auth_check_all (struct MHD_Connection *connection,
    * very hard to achieve.
    */
 
-  if (0 != strcmp (nonce, noncehashexp))
+  if (0 != strcmp (nonce,
+                   noncehashexp))
     {
       return MHD_INVALID_NONCE;
     }
@@ -908,40 +986,45 @@ digest_auth_check_all (struct MHD_Connection *connection,
 
     uri = malloc (left + 1);
     if (NULL == uri)
-    {
+      {
 #ifdef HAVE_MESSAGES
-      MHD_DLOG(daemon,
-               _("Failed to allocate memory for auth header processing\n"));
+        MHD_DLOG(daemon,
+                 _("Failed to allocate memory for auth header processing\n"));
 #endif /* HAVE_MESSAGES */
-      return MHD_NO;
-    }
+        return MHD_NO;
+      }
     if (0 == lookup_sub_value (uri,
                                left + 1,
                                header,
                                "uri"))
-    {
-      free (uri);
-      return MHD_NO;
-    }
-
+      {
+        free (uri);
+        return MHD_NO;
+      }
     if (NULL != digest)
       {
-       digest_calc_ha1_from_digest ("md5",
+        /* This will initialize da->sessionkey (ha1) */
+       digest_calc_ha1_from_digest (da->alg,
+                                     da,
                                     digest,
                                     nonce,
-                                    cnonce,
-                                    ha1);
+                                    cnonce);
       }
     else
       {
-       digest_calc_ha1_from_user ("md5",
+        /* This will initialize da->sessionkey (ha1) */
+       digest_calc_ha1_from_user (da->alg,
                                   username,
                                   realm,
                                   password,
                                   nonce,
                                   cnonce,
-                                  ha1);
+                                   da);
       }
+    memcpy (ha1,
+            da->sessionkey,
+            sizeof (ha1));
+    /* This will initialize da->sessionkey (respexp) */
     digest_calc_response (ha1,
                          nonce,
                          nc,
@@ -950,7 +1033,7 @@ digest_auth_check_all (struct MHD_Connection *connection,
                          connection->method,
                          uri,
                          hentity,
-                         respexp);
+                         da);
 
 
     /* Need to unescape URI before comparing with connection->url */
@@ -991,7 +1074,7 @@ digest_auth_check_all (struct MHD_Connection *connection,
     }
     free (uri);
     return (0 == strcmp (response,
-                         respexp))
+                         da->sessionkey))
       ? MHD_YES
       : MHD_NO;
   }
@@ -999,7 +1082,11 @@ digest_auth_check_all (struct MHD_Connection *connection,
 
 
 /**
- * Authenticates the authorization header sent by the client
+ * Authenticates the authorization header sent by the client.
+ * Uses #MHD_DIGEST_ALG_MD5 (for now, for backwards-compatibility).
+ * Note that this MAY change to #MHD_DIGEST_ALG_AUTO in the future.
+ * If you want to be sure you get MD5, use #MHD_digest_auth_check2
+ * and specifiy MD5 explicitly.
  *
  * @param connection The MHD connection structure
  * @param realm The realm presented to the client
@@ -1018,7 +1105,85 @@ MHD_digest_auth_check (struct MHD_Connection *connection,
                       const char *password,
                       unsigned int nonce_timeout)
 {
+  return MHD_digest_auth_check2 (connection,
+                                 realm,
+                                 username,
+                                 password,
+                                 nonce_timeout,
+                                 MHD_DIGEST_ALG_MD5);
+}
+
+
+/**
+ * Setup digest authentication data structures (on the
+ * stack, hence must be done inline!).  Initializes a
+ * "struct DigestAlgorithm da" for algorithm @a algo.
+ *
+ * @param algo digest algorithm to provide
+ * @param da data structure to setup
+ */
+#define SETUP_DA(algo,da)                         \
+  union {                                         \
+    struct MD5Context md5;                        \
+    struct sha256_ctx sha256;                     \
+  } ctx;                                          \
+  union {                                         \
+    char md5[MD5_DIGEST_SIZE * 2 + 1];            \
+    char sha256[SHA256_DIGEST_SIZE * 2 + 1];      \
+  } skey;                                         \
+  struct DigestAlgorithm da;                      \
+                                                  \
+  switch (algo) {                                 \
+  case MHD_DIGEST_ALG_MD5:                        \
+    da.digest_size = MD5_DIGEST_SIZE;             \
+    da.ctx = &ctx.md5;                            \
+    da.alg = "md5";                               \
+    da.sessionkey = skey.md5;                     \
+    da.init = &MD5Init;                           \
+    da.update = &MD5Update;                       \
+    da.digest = &MD5Final;                        \
+    break;                                        \
+  case MHD_DIGEST_ALG_AUTO:                             \
+    /* auto == SHA256, fall-though thus intentional! */ \
+  case MHD_DIGEST_ALG_SHA256:                           \
+    da.digest_size = SHA256_DIGEST_SIZE;                \
+    da.ctx = &ctx.sha256;                               \
+    da.alg = "sha-256";                                 \
+    da.sessionkey = skey.sha256;                        \
+    da.init = &sha256_init;                             \
+    da.update = &sha256_update;                         \
+    da.digest = &sha256_digest;                         \
+    break;                                              \
+  }
+
+
+
+/**
+ * Authenticates the authorization header sent by the client.
+ *
+ * @param connection The MHD connection structure
+ * @param realm The realm presented to the client
+ * @param username The username needs to be authenticated
+ * @param password The password used in the authentication
+ * @param nonce_timeout The amount of time for a nonce to be
+ *                     invalid in seconds
+ * @param algo digest algorithms allowed for verification
+ * @return #MHD_YES if authenticated, #MHD_NO if not,
+ *                     #MHD_INVALID_NONCE if nonce is invalid
+ * @ingroup authentication
+ */
+_MHD_EXTERN int
+MHD_digest_auth_check2 (struct MHD_Connection *connection,
+                       const char *realm,
+                       const char *username,
+                       const char *password,
+                       unsigned int nonce_timeout,
+                       enum MHD_DigestAuthAlgorithm algo)
+{
+  SETUP_DA (algo, da);
+
   return digest_auth_check_all (connection,
+                                &da,
                                 realm,
                                 username,
                                 password,
@@ -1028,7 +1193,7 @@ MHD_digest_auth_check (struct MHD_Connection *connection,
 
 
 /**
- * Authenticates the authorization header sent by the client
+ * Authenticates the authorization header sent by the client.
  *
  * @param connection The MHD connection structure
  * @param realm The realm presented to the client
@@ -1036,20 +1201,29 @@ MHD_digest_auth_check (struct MHD_Connection 
*connection,
  * @param digest An `unsigned char *' pointer to the binary MD5 sum
  *                     for the precalculated hash value 
"username:realm:password"
  *                     of #MHD_MD5_DIGEST_SIZE bytes
+ * @param digest_size number of bytes in @a digest
  * @param nonce_timeout The amount of time for a nonce to be
  *                     invalid in seconds
+ * @param algo digest algorithms allowed for verification
  * @return #MHD_YES if authenticated, #MHD_NO if not,
  *                     #MHD_INVALID_NONCE if nonce is invalid
  * @ingroup authentication
  */
 _MHD_EXTERN int
-MHD_digest_auth_check_digest (struct MHD_Connection *connection,
-                             const char *realm,
-                             const char *username,
-                             const uint8_t digest[MD5_DIGEST_SIZE],
-                             unsigned int nonce_timeout)
+MHD_digest_auth_check_digest2 (struct MHD_Connection *connection,
+                              const char *realm,
+                              const char *username,
+                              const uint8_t *digest,
+                               size_t digest_size,
+                              unsigned int nonce_timeout,
+                              enum MHD_DigestAuthAlgorithm algo)
 {
+  SETUP_DA (algo, da);
+
+  if (da.digest_size != digest_size)
+    MHD_PANIC (_("digest size missmatch")); /* API violation! */
   return digest_auth_check_all (connection,
+                                &da,
                                realm,
                                username,
                                NULL,
@@ -1059,6 +1233,40 @@ MHD_digest_auth_check_digest (struct MHD_Connection 
*connection,
 
 
 /**
+ * Authenticates the authorization header sent by the client.
+ * Uses #MHD_DIGEST_ALG_MD5 (required, as @a digest is of fixed
+ * size).
+ *
+ * @param connection The MHD connection structure
+ * @param realm The realm presented to the client
+ * @param username The username needs to be authenticated
+ * @param digest An `unsigned char *' pointer to the binary digest
+ *                     for the precalculated hash value 
"username:realm:password"
+ *                     of @a digest_size bytes
+ * @param nonce_timeout The amount of time for a nonce to be
+ *                     invalid in seconds
+ * @return #MHD_YES if authenticated, #MHD_NO if not,
+ *                     #MHD_INVALID_NONCE if nonce is invalid
+ * @ingroup authentication
+ */
+_MHD_EXTERN int
+MHD_digest_auth_check_digest (struct MHD_Connection *connection,
+                             const char *realm,
+                             const char *username,
+                             const uint8_t digest[MHD_MD5_DIGEST_SIZE],
+                             unsigned int nonce_timeout)
+{
+  return MHD_digest_auth_check_digest2 (connection,
+                                        realm,
+                                        username,
+                                        digest,
+                                        MHD_MD5_DIGEST_SIZE,
+                                        nonce_timeout,
+                                        MHD_DIGEST_ALG_MD5);
+}
+
+
+/**
  * Queues a response to request authentication from the client
  *
  * @param connection The MHD connection structure
@@ -1069,81 +1277,90 @@ MHD_digest_auth_check_digest (struct MHD_Connection 
*connection,
  *        header and that the caller should not do this
  * @param signal_stale #MHD_YES if the nonce is invalid to add
  *                     'stale=true' to the authentication header
+ * @param algo digest algorithm to use
  * @return #MHD_YES on success, #MHD_NO otherwise
  * @ingroup authentication
  */
 int
-MHD_queue_auth_fail_response (struct MHD_Connection *connection,
-                             const char *realm,
-                             const char *opaque,
-                             struct MHD_Response *response,
-                             int signal_stale)
+MHD_queue_auth_fail_response2 (struct MHD_Connection *connection,
+                              const char *realm,
+                              const char *opaque,
+                              struct MHD_Response *response,
+                              int signal_stale,
+                              enum MHD_DigestAuthAlgorithm algo)
 {
   int ret;
   int hlen;
-  char nonce[NONCE_STD_LEN + 1];
-
-  /* Generating the server nonce */
-  calculate_nonce ((uint32_t) MHD_monotonic_sec_counter(),
-                  connection->method,
-                  connection->daemon->digest_auth_random,
-                  connection->daemon->digest_auth_rand_size,
-                  connection->url,
-                  realm,
-                  nonce);
-  if (MHD_YES !=
-      check_nonce_nc (connection,
-                      nonce,
-                      0))
-    {
+  SETUP_DA (algo, da);
+
+  {
+    char nonce[NONCE_STD_LEN(da.digest_size) + 1];
+    /* Generating the server nonce */
+    calculate_nonce ((uint32_t) MHD_monotonic_sec_counter(),
+                     connection->method,
+                     connection->daemon->digest_auth_random,
+                     connection->daemon->digest_auth_rand_size,
+                     connection->url,
+                     realm,
+                     &da,
+                     nonce);
+    if (MHD_YES !=
+        check_nonce_nc (connection,
+                        nonce,
+                        0))
+      {
 #ifdef HAVE_MESSAGES
-      MHD_DLOG (connection->daemon,
-               _("Could not register nonce (is the nonce array size 
zero?).\n"));
+        MHD_DLOG (connection->daemon,
+                  _("Could not register nonce (is the nonce array size 
zero?).\n"));
 #endif
-      return MHD_NO;
-    }
-  /* Building the authentication header */
-  hlen = MHD_snprintf_ (NULL,
-                        0,
-                        "Digest 
realm=\"%s\",qop=\"auth\",nonce=\"%s\",opaque=\"%s\"%s",
-                        realm,
-                        nonce,
-                        opaque,
-                        signal_stale
-                        ? ",stale=\"true\""
-                        : "");
-  if (hlen > 0)
-    {
-      char *header;
+        return MHD_NO;
+      }
+    /* Building the authentication header */
+    hlen = MHD_snprintf_ (NULL,
+                          0,
+                          "Digest 
realm=\"%s\",qop=\"auth\",nonce=\"%s\",opaque=\"%s\",algorithm=%s%s",
+                          realm,
+                          nonce,
+                          opaque,
+                          da.alg,
+                          signal_stale
+                          ? ",stale=\"true\""
+                          : "");
+    if (hlen > 0)
+      {
+        char *header;
 
-      header = MHD_calloc_ (1, hlen + 1);
-      if (NULL == header)
-        {
+        header = MHD_calloc_ (1,
+                              hlen + 1);
+        if (NULL == header)
+          {
 #ifdef HAVE_MESSAGES
-          MHD_DLOG(connection->daemon,
-                   _("Failed to allocate memory for auth response header\n"));
+            MHD_DLOG(connection->daemon,
+                     _("Failed to allocate memory for auth response 
header\n"));
 #endif /* HAVE_MESSAGES */
-          return MHD_NO;
-        }
-
-      if (MHD_snprintf_ (header,
-                         hlen + 1,
-                         "Digest 
realm=\"%s\",qop=\"auth\",nonce=\"%s\",opaque=\"%s\"%s",
-                         realm,
-                         nonce,
-                         opaque,
-                         signal_stale
-                         ? ",stale=\"true\""
-                         : "") == hlen)
-        ret = MHD_add_response_header(response,
-                                      MHD_HTTP_HEADER_WWW_AUTHENTICATE,
-                                      header);
-      else
-        ret = MHD_NO;
-      free (header);
-    }
-  else
-    ret = MHD_NO;
+            return MHD_NO;
+          }
+
+        if (MHD_snprintf_ (header,
+                           hlen + 1,
+                           "Digest 
realm=\"%s\",qop=\"auth\",nonce=\"%s\",opaque=\"%s\",algorithm=%s%s",
+                           realm,
+                           nonce,
+                           opaque,
+                           da.alg,
+                           signal_stale
+                           ? ",stale=\"true\""
+                           : "") == hlen)
+          ret = MHD_add_response_header(response,
+                                        MHD_HTTP_HEADER_WWW_AUTHENTICATE,
+                                        header);
+        else
+          ret = MHD_NO;
+        free (header);
+      }
+    else
+      ret = MHD_NO;
+  }
 
   if (MHD_YES == ret)
     {
@@ -1162,4 +1379,36 @@ MHD_queue_auth_fail_response (struct MHD_Connection 
*connection,
 }
 
 
+/**
+ * Queues a response to request authentication from the client.
+ * For now uses MD5 (for backwards-compatibility). Still, if you
+ * need to be sure, use #MHD_queue_fail_auth_response2().
+ *
+ * @param connection The MHD connection structure
+ * @param realm the realm presented to the client
+ * @param opaque string to user for opaque value
+ * @param response reply to send; should contain the "access denied"
+ *        body; note that this function will set the "WWW Authenticate"
+ *        header and that the caller should not do this
+ * @param signal_stale #MHD_YES if the nonce is invalid to add
+ *                     'stale=true' to the authentication header
+ * @return #MHD_YES on success, #MHD_NO otherwise
+ * @ingroup authentication
+ */
+int
+MHD_queue_auth_fail_response (struct MHD_Connection *connection,
+                             const char *realm,
+                             const char *opaque,
+                             struct MHD_Response *response,
+                             int signal_stale)
+{
+  return MHD_queue_auth_fail_response2 (connection,
+                                        realm,
+                                        opaque,
+                                        response,
+                                        signal_stale,
+                                        MHD_DIGEST_ALG_MD5);
+}
+
+
 /* end of digestauth.c */
diff --git a/src/microhttpd/md5.c b/src/microhttpd/md5.c
index d92a42ee..6a8819c9 100644
--- a/src/microhttpd/md5.c
+++ b/src/microhttpd/md5.c
@@ -42,16 +42,20 @@ static uint8_t PADDING[MD5_BLOCK_SIZE] = {
   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
 };
 
-/*
+
+/**
  * Start MD5 accumulation.  Set bit count to 0 and buffer to mysterious
  * initialization constants.
+ *
+ * @param ctx must be a `struct MD5Context *`
  */
 void
-MD5Init(struct MD5Context *ctx)
+MD5Init (void *ctx_)
 {
+  struct MD5Context *ctx = ctx_;
+
   if (!ctx)
     return;
-
   ctx->count = 0;
   ctx->state[0] = 0x67452301;
   ctx->state[1] = 0xefcdab89;
@@ -59,56 +63,13 @@ MD5Init(struct MD5Context *ctx)
   ctx->state[3] = 0x10325476;
 }
 
-/*
- * Update context to reflect the concatenation of another buffer full
- * of bytes.
- */
-void
-MD5Update(struct MD5Context *ctx, const unsigned char *input, size_t len)
-{
-  size_t have, need;
-
-  if (!ctx || !input)
-    return;
-
-  /* Check how many bytes we already have and how many more we need. */
-  have = (size_t)((ctx->count >> 3) & (MD5_BLOCK_SIZE - 1));
-  need = MD5_BLOCK_SIZE - have;
-
-  /* Update bitcount */
-  ctx->count += (uint64_t)len << 3;
-
-  if (len >= need)
-  {
-    if (have != 0)
-    {
-      memcpy(ctx->buffer + have, input, need);
-      MD5Transform(ctx->state, ctx->buffer);
-      input += need;
-      len -= need;
-      have = 0;
-    }
 
-    /* Process data in MD5_BLOCK_SIZE-byte chunks. */
-    while (len >= MD5_BLOCK_SIZE)
-    {
-      MD5Transform(ctx->state, input);
-      input += MD5_BLOCK_SIZE;
-      len -= MD5_BLOCK_SIZE;
-    }
-  }
-
-  /* Handle any remaining bytes of data. */
-  if (len != 0)
-    memcpy(ctx->buffer + have, input, len);
-}
-
-/*
+/**
  * Pad pad to 64-byte boundary with the bit pattern
  * 1 0* (64-bit count of bits processed, MSB-first)
  */
-void
-MD5Pad(struct MD5Context *ctx)
+static void
+MD5Pad (struct MD5Context *ctx)
 {
   uint8_t count[8];
   size_t padlen;
@@ -128,12 +89,17 @@ MD5Pad(struct MD5Context *ctx)
   MD5Update(ctx, count, 8);
 }
 
-/*
+
+/**
  * Final wrapup--call MD5Pad, fill in digest and zero out ctx.
+ *
+ * @param ctx must be a `struct MD5Context *`
  */
 void
-MD5Final(unsigned char digest[MD5_DIGEST_SIZE], struct MD5Context *ctx)
+MD5Final (void *ctx_,
+          unsigned char digest[MD5_DIGEST_SIZE])
 {
+  struct MD5Context *ctx = ctx_;
   int i;
 
   if (!ctx || !digest)
@@ -159,13 +125,14 @@ MD5Final(unsigned char digest[MD5_DIGEST_SIZE], struct 
MD5Context *ctx)
 #define MD5STEP(f, w, x, y, z, data, s) \
        ( w += f(x, y, z) + data,  w = w<<s | w>>(32-s),  w += x )
 
-/*
+/**
  * The core of the MD5 algorithm, this alters an existing MD5 hash to
  * reflect the addition of 16 longwords of new data.  MD5Update blocks
  * the data and converts bytes into longwords for this routine.
  */
-void
-MD5Transform(uint32_t state[4], const uint8_t block[MD5_BLOCK_SIZE])
+static void
+MD5Transform (uint32_t state[4],
+              const uint8_t block[MD5_BLOCK_SIZE])
 {
   uint32_t a, b, c, d, in[MD5_BLOCK_SIZE / 4];
 
@@ -261,4 +228,59 @@ MD5Transform(uint32_t state[4], const uint8_t 
block[MD5_BLOCK_SIZE])
   state[3] += d;
 }
 
+
+/**
+ * Update context to reflect the concatenation of another buffer full
+ * of bytes.
+ */
+void
+MD5Update (void *ctx_,
+           const uint8_t *input,
+           size_t len)
+{
+  struct MD5Context *ctx = ctx_;
+  size_t have, need;
+
+  if (!ctx || !input)
+    return;
+
+  /* Check how many bytes we already have and how many more we need. */
+  have = (size_t)((ctx->count >> 3) & (MD5_BLOCK_SIZE - 1));
+  need = MD5_BLOCK_SIZE - have;
+
+  /* Update bitcount */
+  ctx->count += (uint64_t)len << 3;
+
+  if (len >= need)
+  {
+    if (have != 0)
+    {
+      memcpy (ctx->buffer + have,
+              input,
+              need);
+      MD5Transform(ctx->state, ctx->buffer);
+      input += need;
+      len -= need;
+      have = 0;
+    }
+
+    /* Process data in MD5_BLOCK_SIZE-byte chunks. */
+    while (len >= MD5_BLOCK_SIZE)
+    {
+      MD5Transform (ctx->state,
+                    (const unsigned char *) input);
+      input += MD5_BLOCK_SIZE;
+      len -= MD5_BLOCK_SIZE;
+    }
+  }
+
+  /* Handle any remaining bytes of data. */
+  if (0 != len)
+    memcpy (ctx->buffer + have,
+            input,
+            len);
+}
+
+
+
 /* end of md5.c */
diff --git a/src/microhttpd/md5.h b/src/microhttpd/md5.h
index ad1151e9..3bbfd79e 100644
--- a/src/microhttpd/md5.h
+++ b/src/microhttpd/md5.h
@@ -31,34 +31,37 @@ struct MD5Context
   uint8_t buffer[MD5_BLOCK_SIZE];      /* input buffer */
 };
 
-/*
+
+/**
  * Start MD5 accumulation.  Set bit count to 0 and buffer to mysterious
  * initialization constants.
+ *
+ * @param ctx_ must be a `struct MD5Context *`
  */
-void MD5Init(struct MD5Context *ctx);
+void
+MD5Init (void *ctx_);
 
-/*
+
+/**
  * Update context to reflect the concatenation of another buffer full
  * of bytes.
+ *
+ * @param ctx_ must be a `struct MD5Context *`
  */
-void MD5Update(struct MD5Context *ctx, const unsigned char *input, size_t len);
+void
+MD5Update (void *ctx_,
+           const uint8_t *input,
+           size_t len);
 
-/*
- * Pad pad to 64-byte boundary with the bit pattern
- * 1 0* (64-bit count of bits processed, MSB-first)
- */
-void MD5Pad(struct MD5Context *ctx);
 
-/*
+/**
  * Final wrapup--call MD5Pad, fill in digest and zero out ctx.
+ *
+ * @param ctx_ must be a `struct MD5Context *`
  */
-void MD5Final(unsigned char digest[MD5_DIGEST_SIZE], struct MD5Context *ctx);
+void
+MD5Final (void *ctx_,
+          unsigned char digest[MD5_DIGEST_SIZE]);
 
-/*
- * The core of the MD5 algorithm, this alters an existing MD5 hash to
- * reflect the addition of 16 longwords of new data.  MD5Update blocks
- * the data and converts bytes into longwords for this routine.
- */
-void MD5Transform(uint32_t state[4], const uint8_t block[MD5_BLOCK_SIZE]);
 
 #endif /* !MHD_MD5_H */
diff --git a/src/microhttpd/sha256.c b/src/microhttpd/sha256.c
index 12675a73..977296f9 100644
--- a/src/microhttpd/sha256.c
+++ b/src/microhttpd/sha256.c
@@ -48,22 +48,22 @@
 static const uint32_t
 K[64] =
 {
-  0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL, 
-  0x3956c25bUL, 0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL, 
-  0xd807aa98UL, 0x12835b01UL, 0x243185beUL, 0x550c7dc3UL, 
-  0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL, 0xc19bf174UL, 
-  0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL, 
-  0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL, 
-  0x983e5152UL, 0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL, 
-  0xc6e00bf3UL, 0xd5a79147UL, 0x06ca6351UL, 0x14292967UL, 
-  0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL, 0x53380d13UL, 
-  0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL, 
-  0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL, 
-  0xd192e819UL, 0xd6990624UL, 0xf40e3585UL, 0x106aa070UL, 
-  0x19a4c116UL, 0x1e376c08UL, 0x2748774cUL, 0x34b0bcb5UL, 
-  0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL, 0x682e6ff3UL, 
-  0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL, 
-  0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL, 
+  0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL,
+  0x3956c25bUL, 0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL,
+  0xd807aa98UL, 0x12835b01UL, 0x243185beUL, 0x550c7dc3UL,
+  0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL, 0xc19bf174UL,
+  0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL,
+  0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL,
+  0x983e5152UL, 0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL,
+  0xc6e00bf3UL, 0xd5a79147UL, 0x06ca6351UL, 0x14292967UL,
+  0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL, 0x53380d13UL,
+  0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL,
+  0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL,
+  0xd192e819UL, 0xd6990624UL, 0xf40e3585UL, 0x106aa070UL,
+  0x19a4c116UL, 0x1e376c08UL, 0x2748774cUL, 0x34b0bcb5UL,
+  0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL, 0x682e6ff3UL,
+  0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL,
+  0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL,
 };
 
 
@@ -77,11 +77,11 @@ K[64] =
    this */
 
 /* #define Choice(x,y,z) ( ( (x) & (y) ) | ( ~(x) & (z) ) ) */
-#define Choice(x,y,z)   ( (z) ^ ( (x) & ( (y) ^ (z) ) ) ) 
+#define Choice(x,y,z)   ( (z) ^ ( (x) & ( (y) ^ (z) ) ) )
 /* #define Majority(x,y,z) ( ((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)) ) */
 #define Majority(x,y,z) ( ((x) & (y)) ^ ((z) & ((x) ^ (y))) )
 
-#define S0(x) (ROTL32(30,(x)) ^ ROTL32(19,(x)) ^ ROTL32(10,(x))) 
+#define S0(x) (ROTL32(30,(x)) ^ ROTL32(19,(x)) ^ ROTL32(10,(x)))
 #define S1(x) (ROTL32(26,(x)) ^ ROTL32(21,(x)) ^ ROTL32(7,(x)))
 
 #define s0(x) (ROTL32(25,(x)) ^ ROTL32(14,(x)) ^ ((x) >> 3))
@@ -182,22 +182,22 @@ _nettle_sha256_compress(uint32_t *state, const uint8_t 
*input, const uint32_t *k
   F = state[5];
   G = state[6];
   H = state[7];
-  
+
   /* Heavy mangling */
   /* First 16 subrounds that act on the original data */
 
   for (i = 0, d = data; i<16; i+=8, k += 8, d+= 8)
     {
-      ROUND(A, B, C, D, E, F, G, H, k[0], d[0]); 
-      ROUND(H, A, B, C, D, E, F, G, k[1], d[1]); 
+      ROUND(A, B, C, D, E, F, G, H, k[0], d[0]);
+      ROUND(H, A, B, C, D, E, F, G, k[1], d[1]);
       ROUND(G, H, A, B, C, D, E, F, k[2], d[2]);
       ROUND(F, G, H, A, B, C, D, E, k[3], d[3]);
       ROUND(E, F, G, H, A, B, C, D, k[4], d[4]);
       ROUND(D, E, F, G, H, A, B, C, k[5], d[5]);
-      ROUND(C, D, E, F, G, H, A, B, k[6], d[6]); 
-      ROUND(B, C, D, E, F, G, H, A, k[7], d[7]); 
+      ROUND(C, D, E, F, G, H, A, B, k[6], d[6]);
+      ROUND(B, C, D, E, F, G, H, A, k[7], d[7]);
     }
-  
+
   for (; i<64; i += 16, k+= 16)
     {
       ROUND(A, B, C, D, E, F, G, H, k[ 0], EXPAND(data,  0));
@@ -235,20 +235,21 @@ _nettle_sha256_compress(uint32_t *state, const uint8_t 
*input, const uint32_t *k
 /* Initialize the SHA values */
 
 void
-sha256_init(struct sha256_ctx *ctx)
+sha256_init (void *ctx_)
 {
   /* Initial values, also generated by the shadata program. */
   static const uint32_t H0[_SHA256_DIGEST_LENGTH] =
   {
-    0x6a09e667UL, 0xbb67ae85UL, 0x3c6ef372UL, 0xa54ff53aUL, 
-    0x510e527fUL, 0x9b05688cUL, 0x1f83d9abUL, 0x5be0cd19UL, 
+    0x6a09e667UL, 0xbb67ae85UL, 0x3c6ef372UL, 0xa54ff53aUL,
+    0x510e527fUL, 0x9b05688cUL, 0x1f83d9abUL, 0x5be0cd19UL,
   };
+  struct sha256_ctx *ctx = ctx_;
 
   memcpy(ctx->state, H0, sizeof(H0));
 
   /* Initialize bit count */
   ctx->count = 0;
-  
+
   /* Initialize buffer */
   ctx->index = 0;
 }
@@ -322,9 +323,11 @@ sha256_init(struct sha256_ctx *ctx)
 
 
 void
-sha256_update(struct sha256_ctx *ctx,
-             size_t length, const uint8_t *data)
+sha256_update (void *ctx_,
+               const uint8_t *data,
+               size_t length)
 {
+  struct sha256_ctx *ctx = ctx_;
   MD_UPDATE (ctx, length, data, COMPRESS, ctx->count++);
 }
 
@@ -337,7 +340,7 @@ _nettle_write_be32(size_t length, uint8_t *dst,
   size_t i;
   size_t words;
   unsigned leftover;
-  
+
   words = length / 4;
   leftover = length % 4;
 
@@ -348,9 +351,9 @@ _nettle_write_be32(size_t length, uint8_t *dst,
     {
       uint32_t word;
       unsigned j = leftover;
-      
+
       word = src[i];
-      
+
       switch (leftover)
        {
        default:
@@ -369,9 +372,9 @@ _nettle_write_be32(size_t length, uint8_t *dst,
 
 
 static void
-sha256_write_digest(struct sha256_ctx *ctx,
-                   size_t length,
-                   uint8_t *digest)
+sha256_write_digest (struct sha256_ctx *ctx,
+                     size_t length,
+                     uint8_t *digest)
 {
   uint64_t bit_count;
 
@@ -379,7 +382,7 @@ sha256_write_digest(struct sha256_ctx *ctx,
 
   MD_PAD(ctx, 8, COMPRESS);
 
-  /* There are 512 = 2^9 bits in one block */  
+  /* There are 512 = 2^9 bits in one block */
   bit_count = (ctx->count << 9) | (ctx->index << 3);
 
   /* This is slightly inefficient, as the numbers are converted to
@@ -392,10 +395,13 @@ sha256_write_digest(struct sha256_ctx *ctx,
 }
 
 void
-sha256_digest(struct sha256_ctx *ctx,
-             size_t length,
+sha256_digest (void *ctx_,
              uint8_t *digest)
 {
-  sha256_write_digest(ctx, length, digest);
-  sha256_init(ctx);
+  struct sha256_ctx *ctx = ctx_;
+
+  sha256_write_digest (ctx,
+                       SHA256_DIGEST_SIZE,
+                       digest);
+  sha256_init (ctx);
 }
diff --git a/src/microhttpd/sha256.h b/src/microhttpd/sha256.h
index 6d36ebef..5eee4a41 100644
--- a/src/microhttpd/sha256.h
+++ b/src/microhttpd/sha256.h
@@ -32,14 +32,10 @@
    the GNU Lesser General Public License along with this program.  If
    not, see http://www.gnu.org/licenses/.
 */
- 
+
 #ifndef NETTLE_SHA2_H_INCLUDED
 #define NETTLE_SHA2_H_INCLUDED
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 #define SHA256_DIGEST_SIZE 32
 #define SHA256_BLOCK_SIZE 64
 
@@ -54,21 +50,36 @@ struct sha256_ctx
   unsigned int index;                       /* index into buffer */
 };
 
-void
-sha256_init(struct sha256_ctx *ctx);
 
+/**
+ * Start SHA256 calculation.
+ *
+ * @param ctx_ must be a `struct sha256_ctx *`
+ */
 void
-sha256_update(struct sha256_ctx *ctx,
-             size_t length,
-             const uint8_t *data);
+sha256_init (void *ctx_);
 
-void
-sha256_digest(struct sha256_ctx *ctx,
-             size_t length,
-             uint8_t *digest);
 
-#ifdef __cplusplus
-}
-#endif
+/**
+ * Update hash calculation.
+ *
+ * @param ctx_ must be a `struct sha256_ctx *`
+ * @param length number of bytes in @a data
+ * @param data bytes to add to hash
+ */
+void
+sha256_update (void *ctx_,
+               const uint8_t *data,
+               size_t length);
+
+/**
+ * Complete SHA256 calculation.
+ *
+ * @param ctx_ must be a `struct sha256_ctx *`
+ * @param digest[out] set to the hash, must be #SHA256_DIGEST_SIZE bytes
+ */
+void
+sha256_digest (void *ctx_,
+               uint8_t digest[SHA256_DIGEST_SIZE]);
 
 #endif /* NETTLE_SHA2_H_INCLUDED */

-- 
To stop receiving notification emails like this one, please contact
address@hidden



reply via email to

[Prev in Thread] Current Thread [Next in Thread]