From 39add4476f5daba3e3e2d99fdd382c66d1d7c834 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20B=C3=BChler?= Date: Tue, 27 Oct 2015 20:50:53 +0000 Subject: [PATCH] [mod_secdownload] use a hopefully constant time comparison to check hash (fixes #2679) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Stefan Bühler git-svn-id: svn://svn.lighttpd.net/lighttpd/branches/lighttpd-1.4.x@3048 152afb58-edef-0310-8abb-c4023f1b3aa9 --- NEWS | 1 + src/mod_secure_download.c | 12 +++++++++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 006ba741..f57eae8d 100644 --- a/NEWS +++ b/NEWS @@ -11,6 +11,7 @@ NEWS * [mod_auth] implement and use safe_memclear, using memset_s or explicit_bzero if available (thx loganaden) * [core] don't buffer request bodies smaller than 64k on disk * add force_assert for many allocations and function results + * [mod_secdownload] use a hopefully constant time comparison to check hash (fixes #2679) - 1.4.37 - 2015-08-30 * [mod_proxy] remove debug log line from error log (fixes #2659) diff --git a/src/mod_secure_download.c b/src/mod_secure_download.c index d85872d4..34539da6 100644 --- a/src/mod_secure_download.c +++ b/src/mod_secure_download.c @@ -42,6 +42,16 @@ typedef struct { plugin_config conf; } plugin_data; +static int const_time_memeq(const char *a, const char *b, size_t len) { + /* constant time memory compare, unless the compiler figures it out */ + char diff = 0; + size_t i; + for (i = 0; i < len; ++i) { + diff |= (a[i] ^ b[i]); + } + return 0 == diff; +} + /* init the plugin data */ INIT_FUNC(mod_secdownload_init) { plugin_data *p; @@ -264,7 +274,7 @@ URIHANDLER_FUNC(mod_secdownload_uri_handler) { buffer_copy_string_hex(p->md5, (char *)HA1, 16); - if (0 != strncasecmp(md5_str, p->md5->ptr, 32)) { + if (!const_time_memeq(md5_str, p->md5->ptr, 32)) { con->http_status = 403; log_error_write(srv, __FILE__, __LINE__, "sss",