[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
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [GNUnet-SVN] [libmicrohttpd] branch master updated: preliminary implementation for RFC 7616 support,
gnunet <=