libxcrypt/libxcrypt-4.2.2-to_develop.patch
2018-10-25 16:28:21 +02:00

3946 lines
132 KiB
Diff
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

From 9bae80381beabc1b08b0fd89d2a4e6e15e3e5da0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bj=C3=B6rn=20Esser?= <besser82@fedoraproject.org>
Date: Thu, 18 Oct 2018 21:24:10 +0200
Subject: [PATCH 01/17] Bump tarball version to 4.2.3 and update NEWS.
---
NEWS | 2 ++
configure.ac | 2 +-
2 files changed, 3 insertions(+), 1 deletion(-)
diff --git a/NEWS b/NEWS
index 5b2795e..ef7c244 100644
--- a/NEWS
+++ b/NEWS
@@ -3,6 +3,8 @@ libxcrypt NEWS -- history of user-visible changes.
Please send bug reports, questions and suggestions to
<https://github.com/besser82/libxcrypt/issues>.
+Version 4.2.3
+
Version 4.2.2
* Convert existing manpages to BSD mdoc format.
diff --git a/configure.ac b/configure.ac
index efbd2e7..3ba313c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,7 +1,7 @@
# Process this file with autoconf to produce a configure script.
m4_include([m4/zw_automodern.m4])
AC_INIT([xcrypt],
- [4.2.2],
+ [4.2.3],
[https://github.com/besser82/libxcrypt/issues],
[libxcrypt],
[https://github.com/besser82/libxcrypt])
From ed11116c6e4b5b80ef8f6f57fe8db4aa3604a53b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bj=C3=B6rn=20Esser?= <besser82@fedoraproject.org>
Date: Thu, 18 Oct 2018 22:23:19 +0200
Subject: [PATCH 02/17] Add bootstrap script.
---
.travis.yml | 6 +++---
NEWS | 1 +
bootstrap | 33 +++++++++++++++++++++++++++++++++
3 files changed, 37 insertions(+), 3 deletions(-)
create mode 100755 bootstrap
diff --git a/.travis.yml b/.travis.yml
index 78a3f0a..acb186c 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -181,9 +181,9 @@ before_install:
- docker exec -t buildenv /bin/sh -c 'for i in `seq 0 99`; do dnf -y upgrade && i= && break || sleep 1; done; [ -z "$i" ]'
- docker exec -t buildenv /bin/sh -c 'for i in `seq 0 99`; do dnf -y swap coreutils-single coreutils && i= && break || sleep 1; done; [ -z "$i" ]'
- docker exec -t buildenv /bin/sh -c 'for i in `seq 0 99`; do dnf -y groups install buildsys-build && i= && break || sleep 1; done; [ -z "$i" ]'
- - docker exec -t buildenv /bin/sh -c 'for i in `seq 0 99`; do dnf -y install libtool valgrind && i= && break || sleep 1; done; [ -z "$i" ]'
+ - docker exec -t buildenv /bin/sh -c 'for i in `seq 0 99`; do dnf -y install git libtool valgrind && i= && break || sleep 1; done; [ -z "$i" ]'
- if [[ "$CC" == "clang" ]] ; then docker exec -t buildenv /bin/sh -c 'for i in `seq 0 99`; do dnf -y install clang && i= && break || sleep 1; done; [ -z "$i" ]' ; fi
- - if [[ "$CODECOV" == "1" ]] ; then docker exec -t buildenv /bin/sh -c 'for i in `seq 0 99`; do dnf -y install git lcov python3-pip && i= && break || sleep 1; done; [ -z "$i" ]' ; fi
+ - if [[ "$CODECOV" == "1" ]] ; then docker exec -t buildenv /bin/sh -c 'for i in `seq 0 99`; do dnf -y install lcov python3-pip && i= && break || sleep 1; done; [ -z "$i" ]' ; fi
- if [[ "$CODECOV" == "1" ]] ; then docker exec -t buildenv /bin/sh -c "pip3 install codecov" ; fi
- docker exec -t buildenv /bin/sh -c 'for i in `seq 0 99`; do dnf -y autoremove && i= && break || sleep 1; done; [ -z "$i" ]'
@@ -201,7 +201,7 @@ script:
- export NPROCS="$((`nproc --all` * 2))" ; echo paralleism is $NPROCS
- if [[ "$CODECOV" == "1" ]] ; then export CFLAGS="-O0 -g --coverage" ; export CXXFLAGS="$CFLAGS" ; export LDFLAGS="--coverage" ; fi
- docker exec -t buildenv /bin/sh -c "cat /etc/redhat-release"
- - docker exec -t buildenv /bin/sh -c "cd /opt/libxcrypt && autoreconf -fiv -Wall -Werror"
+ - docker exec -t buildenv /bin/sh -c "cd /opt/libxcrypt && ./bootstrap"
- docker exec -t buildenv /bin/sh -c "cd /opt/libxcrypt && CFLAGS=\"$CFLAGS\" CXXFLAGS=\"$CXXFLAGS\" LDFLAGS=\"$LDFLAGS\" ./configure --prefix=/opt/libxcrypt --disable-silent-rules --enable-shared --enable-static $CONF"
- docker exec -t buildenv /bin/sh -c "make -C /opt/libxcrypt -j$NPROCS"
- docker exec -t buildenv /bin/sh -c "make -C /opt/libxcrypt install"
diff --git a/NEWS b/NEWS
index ef7c244..7847c86 100644
--- a/NEWS
+++ b/NEWS
@@ -4,6 +4,7 @@ Please send bug reports, questions and suggestions to
<https://github.com/besser82/libxcrypt/issues>.
Version 4.2.3
+* Add bootstrap script.
Version 4.2.2
* Convert existing manpages to BSD mdoc format.
diff --git a/bootstrap b/bootstrap
new file mode 100755
index 0000000..af6433a
--- /dev/null
+++ b/bootstrap
@@ -0,0 +1,33 @@
+#!/bin/sh
+#
+# Copyright (C) 2018 Björn Esser <besser82@fedoraproject.org>
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+
+set -efu
+LANG=C
+
+run_cmd()
+{
+ echo "bootstrap: running: $@"
+ "$@"
+}
+
+if [ -d .git ]; then
+ run_cmd git clean -dfX
+fi
+
+run_cmd autoreconf -iv -Wall,error
From a19bb7e1ae3e954b8852f50fd70ca496839989b5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bj=C3=B6rn=20Esser?= <besser82@fedoraproject.org>
Date: Fri, 19 Oct 2018 00:01:16 +0200
Subject: [PATCH 03/17] Recommend the bootstrap script over autoreconf.
---
NEWS | 3 ++-
README.md | 2 +-
2 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/NEWS b/NEWS
index 7847c86..c55a971 100644
--- a/NEWS
+++ b/NEWS
@@ -4,7 +4,8 @@ Please send bug reports, questions and suggestions to
<https://github.com/besser82/libxcrypt/issues>.
Version 4.2.3
-* Add bootstrap script.
+* Add bootstrap script. If building from a Git checkout instead of a
+ tarball release, use './bootstrap' to create the configure script.
Version 4.2.2
* Convert existing manpages to BSD mdoc format.
diff --git a/README.md b/README.md
index a32b1b1..102127a 100644
--- a/README.md
+++ b/README.md
@@ -62,7 +62,7 @@ these things before building the software.
Building from a Git checkout additionally requires the Autotools
suite: `autoconf`, `automake`, `libtool`, and `pkg-config`.
-Run `autoreconf -i` at the top level of the source tree, and then
+Run `./bootstrap` at the top level of the source tree, and then
follow the instructions in `INSTALL` (which is created by that command).
The oldest versions of Autotools components that are known to work
From 4bb73c595925a4603393ff25751ada66921919d9 Mon Sep 17 00:00:00 2001
From: Zack Weinberg <zackw@panix.com>
Date: Sat, 20 Oct 2018 12:36:02 -0400
Subject: [PATCH 04/17] Revise the to-do list.
---
TODO | 57 +----------------------------
TODO.md | 109 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 110 insertions(+), 56 deletions(-)
mode change 100644 => 120000 TODO
create mode 100644 TODO.md
diff --git a/TODO b/TODO
deleted file mode 100644
index 66db86b..0000000
--- a/TODO
+++ /dev/null
@@ -1,56 +0,0 @@
-to-do list for libxcrypt
-------------------------
-
-* Near future:
- * Update all of the default cost parameters
- * relevant benchmarking at
- <https://pthree.org/2016/06/28/lets-talk-password-hashing/>
- * the default used by `crypt_gensalt_*` for new hashes should be
- controllable independently from the default used if there is no
- rounds= annotation in a setting string
- * Make the crypt and crypt_gensalt static state thread-specific?
- * if allocated on first use, this would also shave 32kB of
- data segment off the shared library
- * Factor out all of the repetitive base64 code
- * get rid of the de/serialization code in crypt-bcrypt.c that
- still does dodgy things with type punning
- * Attempt to determine the copyright holders and intended licensing
- of the test suite
- * Moar tests
- * Make sure the symbol versioning macros work with all of the compilers
- that anyone needs (they use GCC extensions that clang also supports).
-
-* Longer term:
- * Hash algorithms newer than bcrypt tend to want to allocate and
- scribble all over a large (tens of megabytes at a minimum) block
- of memory, to make brute force hard in a way that GPUs and ASICs
- can't easily accelerate. The existing API cannot handle this for
- three reasons:
- * `crypt_gensalt` only takes a single cost parameter, some
- algorithms have several
- * With everything except `crypt_ra`, all of the memory is
- allocated by the caller and there's no way for algorithms to say
- how much they need
- * There is no destructor function, even with `crypt_ra` - callers
- just pass the block to `free`
-
- So we need to invent a new API that allows for more variety in
- cost parameters and allocations. It could also make the "all the
- sensitive data, including stack scratch, is in crypt_data which we
- auto-erase" feature more robust by adding guard bands and calling
- mlock().
-
- * Additional hashes to investigate adding:
- * scrypt <https://www.tarsnap.com/scrypt.html>
- * Argon2 <https://password-hashing.net/>
- * ...?
-
- * Support for "pepper" (an additional piece of information, _not_
- stored in the password file, that you need to check a password)
-
- * Reading passphrases from the terminal is finicky and there are
- several competing, poorly portable, questionably sound library
- functions to do it (`getpass`, `readpassphrase`, etc) -- should we
- incorporate one?
- * If we do, should it know how to trigger the trusted-path
- password prompt in modern GUI environments? (probably)
diff --git a/TODO b/TODO
new file mode 120000
index 0000000..cde952b
--- /dev/null
+++ b/TODO
@@ -0,0 +1 @@
+TODO.md
\ No newline at end of file
diff --git a/TODO.md b/TODO.md
new file mode 100644
index 0000000..30c0372
--- /dev/null
+++ b/TODO.md
@@ -0,0 +1,109 @@
+to-do list for libxcrypt
+------------------------
+
+This list is categorized but not in any kind of priority order.
+It was last updated 20 October 2018.
+
+* Code cleanliness
+ * Find and remove any code that still does dodgy things with type punning
+ * Factor out all of the repetitive base64 code
+ * Factor out the multiple implementations of HMAC and PBKDF
+
+* Testsuite improvements
+ * Line coverage is inadequate for `alg-yescrypt-common.c` and
+ `alg-yescrypt-opt.c`
+ * Investigate branch coverage
+ * Do some API fuzz testing and add missing cases to the testsuite
+ * Many of the `test-crypt-*.c` files repeat more or less the same
+ code with different data, consider merging them
+
+* Portability
+ * Make sure the symbol versioning macros work with all of the
+ compilers that anyone needs (they use GCC extensions that clang
+ also supports).
+ * `alg-yescrypt-common.c` contains #ifdeffage for use of
+ `posix_memalign` that isnt wired up to autoconf
+ * possibly this should just be removed; does anything have
+ `posix_memalign` but not `mmap`? its only a compile-time
+ fallback, not a runtime fallback
+
+* Hardening
+ * bcrypt-like selftest/memory scribble for all hashing methods
+ * how do we know the memory scribble is doing its job?
+ * build out of the box with compiler hardening features turned on
+ * something bespoke for not having to write serialization and
+ deserialization logic for hash strings by hand, as this is
+ probably the most error-prone part of writing a hashing method
+
+ * the most sensitive piece of data handled by this library is a
+ cleartext passphrase. OS may have trusted-path facilities for
+ prompting the user for a passphrase and feeding it to a KDF
+ without its ever being accessible in normal memory. investigate
+ whether we can use these.
+
+* Additional hashing methods
+ * Argon2 <https://password-hashing.net/>
+ * ...?
+
+* Runtime configurability (in progress on the [crypt.conf branch][])
+ * allow installations to enable or disable specific hash methods
+ without rebuilding the library
+ * make the default cost parameter used by `crypt_gensalt_*` for new
+ hashes configurable
+ * update the compiled-in defaults used by `crypt_gensalt_*` (not the
+ defaults used when no explicit cost parameter is present in a
+ hash; those cant be changed without breaking existing stored hashes)
+ * relevant benchmarking at
+ <https://pthree.org/2016/06/28/lets-talk-password-hashing/>
+ * offer a way to tune cost parameters for a specific installation
+ * N.B. Solaris 11 has all of these features but our implementation will
+ probably not match them (they have a `crypt.conf` but its not the
+ same, and their `crypt_gensalt` is API-incompatible anyway).
+
+[crypt.conf branch]: https://github.com/besser82/libxcrypt/tree/zack/crypt.conf
+
+* Potential API enhancements:
+
+ * Support for "pepper" (an additional piece of information, _not_
+ stored in the password file, that you need to check a password)
+
+ * Reading passphrases from the terminal is finicky and there are
+ several competing, poorly portable, questionably sound library
+ functions to do it (`getpass`, `readpassphrase`, etc) -- should we
+ incorporate one?
+ * If we do, should it know how to trigger the trusted-path
+ password prompt in modern GUI environments? (probably)
+
+ * Make the crypt and crypt_gensalt static state thread-specific?
+ * Solaris 11 may have done this (its `crypt(3)` manpage describes
+ it as MT-Safe and I dont see any other way they could have
+ accomplished that).
+ * if allocated on first use, this would also shave 32kB of
+ data segment off the shared library
+ * alternatively, add a global lock and *crash the program* if we
+ detect concurrent calls
+
+ * Allow access to more of yescrypts tunable parameters and ROM
+ feature, in a way thats generic enough that we could also use it
+ for e.g. Argon2s tunable parameters
+
+ * Other yescrypt-inspired features relevant to using this library to
+ back a “dedicated authentication service,” e.g. preallocation of
+ large blocks of scratch memory
+ * the main obstacles here are that `struct crypt_data` has a fixed
+ size which is either too big or too small depending how you look
+ at it, and no destructor function
+
+* Permissive relicensing, to encourage use beyond the GNU ecosystem?
+ * Replace remaining (L)GPLed crypto primitives (MD5, SHA512) with
+ permissively licensed equivalents (e.g. from Openwall)
+ * Replace crypt-md5.c with original md5crypt from FreeBSD?
+ * Other files subject to the (L)GPL are crypt.c, crypt-static.c,
+ crypt-gensalt-static.c, crypt-obsolete.h, crypt-port.h,
+ crypt-private.h, test-badsalt.c. It is not clear to me how much
+ material originally assigned to the FSF remains in these files.
+ Several of them are API definitions and trivial wrappers that
+ could not be meaningfully changed without breaking them (so are
+ arguably uncopyrightable).
+ * Most of the test suite lacks any license or even authorship
+ information. We would have to track down the original authors.
From 9787b0be83a077c8c1a4e9b460b6b6e3698002d4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bj=C3=B6rn=20Esser?= <besser82@fedoraproject.org>
Date: Sun, 21 Oct 2018 12:18:25 +0200
Subject: [PATCH 05/17] Generate included header files before any other target.
If we use a dummy target that depends on targets generating
commonly used header files and that creates an empty file,
which is included in the Makefile later, the header files are
guaranteed to be generated before any other target in the same
Makefile.
---
.gitignore | 1 +
Makefile.am | 16 +++++++++-------
2 files changed, 10 insertions(+), 7 deletions(-)
diff --git a/.gitignore b/.gitignore
index 1e9e605..e0b13cf 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,6 +1,7 @@
# http://www.gnu.org/software/automake
/Makefile
+/Makefile.deps
/Makefile.in
/.deps/
/.libs/
diff --git a/Makefile.am b/Makefile.am
index 2cb07ca..acab882 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -71,13 +71,19 @@ libcrypt_la_CPPFLAGS = $(AM_CPPFLAGS) -DIN_LIBCRYPT
CONFIG_STATUS_DEPENDENCIES = libcrypt.minver
EXTRA_libcrypt_la_DEPENDENCIES = libcrypt.map
-CLEANFILES = libcrypt.map libcrypt.map.T \
+CLEANFILES = Makefile.deps.T Makefile.deps \
+ libcrypt.map libcrypt.map.T \
crypt-symbol-vers.h crypt-symbol-vers.h.T \
crypt-hashes.h crypt-hashes.h.T \
crypt.h crypt.h.T
DISTCLEANFILES = .deps/*.Plo
+# Empty target to have needed headers pre-generated before any other target.
+Makefile.deps: crypt-hashes.h crypt-symbol-vers.h
+ $(AM_V_GEN)LC_ALL=C echo "# Deps" > Makefile.deps.T
+ $(AM_V_at)mv -f Makefile.deps.T Makefile.deps
+
libcrypt.map: libcrypt.map.in gen-map.awk Makefile
$(AM_V_GEN)LC_ALL=C $(AWK) \
-v SYMVER_MIN=$(SYMVER_MIN) \
@@ -230,12 +236,8 @@ endif
# Every object file depends on crypt-symbol-vers.h and crypt-hashes.h,
# which are generated files, so automatic dependency generation is not
-# sufficient. Most of the test programs depend on either libcrypt.la
-# or one of its components, so they do not need an explicit dependency
-# (after the first *successful* build, automatic dependency generation
-# will reveal the direct dependency) but a few don't.
-$(libcrypt_la_OBJECTS): crypt-symbol-vers.h crypt-hashes.h
-$(test_byteorder_OBJECTS): crypt-symbol-vers.h crypt-hashes.h
+# sufficient.
+include $(builddir)/Makefile.deps
# Add additional targets
.PHONY: $(phony_targets)
From d32b170da3d4b65e9b23bb1c9a50e027ec090c5a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bj=C3=B6rn=20Esser?= <besser82@fedoraproject.org>
Date: Sun, 21 Oct 2018 12:53:13 +0200
Subject: [PATCH 06/17] Include crypt.h from crypt-port.h.
Since we have a guaranteed way to make sure all generated header
files are always present before any object file is compiled, we
can drop crypt-base.h and include the local version of crypt.h
through crypt-port.h.
---
.gitignore | 2 +-
LICENSING | 2 +-
Makefile.am | 10 +++++-----
configure.ac | 2 +-
crypt-gensalt-static.c | 1 -
crypt-obsolete.h | 1 -
crypt-port.h | 6 ++++--
crypt-private.h | 1 -
crypt-static.c | 1 -
crypt-base.h.in => crypt.h.in.in | 0
gen-crypt-h.awk | 2 +-
test-crypt-bcrypt.c | 1 -
test-crypt-des.c | 1 -
test-crypt-md5.c | 1 -
test-crypt-nthash.c | 1 -
test-crypt-pbkdf1-sha1.c | 1 -
test-crypt-scrypt.c | 1 -
test-crypt-sha256.c | 1 -
test-crypt-sha512.c | 1 -
test-crypt-sunmd5.c | 1 -
test-crypt-yescrypt.c | 1 -
test-des-obsolete.c | 1 -
test-des-obsolete_r.c | 1 -
test-gensalt.c | 1 -
24 files changed, 13 insertions(+), 28 deletions(-)
rename crypt-base.h.in => crypt.h.in.in (100%)
diff --git a/.gitignore b/.gitignore
index e0b13cf..e46e4c2 100644
--- a/.gitignore
+++ b/.gitignore
@@ -19,7 +19,7 @@
/config.status
/m4/config.sub
/configure
-/crypt-base.h
+/crypt.h.in
/m4/depcomp
/m4/install-sh
/libtool
diff --git a/LICENSING b/LICENSING
index 17ae41e..bf0c514 100644
--- a/LICENSING
+++ b/LICENSING
@@ -12,7 +12,7 @@ source tree. For specific licensing terms consult the files themselves.
crypt.c, crypt-static.c, crypt-gensalt-static.c, crypt-port.h
* Copyright Free Software Foundation, Inc.; LGPL (v2.1 or later):
- crypt-base.h, crypt-obsolete.h, crypt-private.h
+ crypt.h, crypt-obsolete.h, crypt-private.h
alg-md5.h, alg-md5.c, crypt-md5.c,
alg-sha512.h, alg-sha512.c,
test-crypt-badsalt.c, test-crypt-nonnull.c
diff --git a/Makefile.am b/Makefile.am
index acab882..498c48f 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -14,7 +14,7 @@ TEST_EXTENSIONS = .sh
EXTRA_DIST = \
LICENSING THANKS \
- crypt-base.h.in libcrypt.map.in libcrypt.minver \
+ crypt.h.in.in libcrypt.map.in libcrypt.minver \
gen-map.awk gen-vers.awk gen-crypt-h.awk \
gen-hashes.awk sel-hashes.awk hashes.lst
@@ -24,7 +24,7 @@ notrans_dist_man3_MANS = \
notrans_dist_man5_MANS = crypt.5
nodist_include_HEADERS = crypt.h
-nodist_noinst_HEADERS = crypt-hashes.h crypt-base.h
+nodist_noinst_HEADERS = crypt-hashes.h
noinst_HEADERS = \
alg-des.h alg-hmac-sha1.h alg-md4.h alg-md5.h \
alg-sha1.h alg-sha256.h alg-sha512.h \
@@ -80,7 +80,7 @@ CLEANFILES = Makefile.deps.T Makefile.deps \
DISTCLEANFILES = .deps/*.Plo
# Empty target to have needed headers pre-generated before any other target.
-Makefile.deps: crypt-hashes.h crypt-symbol-vers.h
+Makefile.deps: crypt.h
$(AM_V_GEN)LC_ALL=C echo "# Deps" > Makefile.deps.T
$(AM_V_at)mv -f Makefile.deps.T Makefile.deps
@@ -101,9 +101,9 @@ crypt-symbol-vers.h: libcrypt.map.in gen-vers.awk Makefile
$(srcdir)/libcrypt.map.in > crypt-symbol-vers.h.T
$(AM_V_at)mv -f crypt-symbol-vers.h.T crypt-symbol-vers.h
-crypt.h: crypt-base.h gen-crypt-h.awk config.h
+crypt.h: crypt.h.in crypt-hashes.h crypt-symbol-vers.h gen-crypt-h.awk config.h
$(AM_V_GEN)LC_ALL=C $(AWK) \
- -f $(srcdir)/gen-crypt-h.awk config.h $(builddir)/crypt-base.h \
+ -f $(srcdir)/gen-crypt-h.awk config.h $(builddir)/crypt.h.in \
> crypt.h.T
$(AM_V_at)mv -f crypt.h.T crypt.h
diff --git a/configure.ac b/configure.ac
index 3ba313c..5da8aa8 100644
--- a/configure.ac
+++ b/configure.ac
@@ -11,8 +11,8 @@ AC_CONFIG_SRCDIR([crypt.c])
AC_CONFIG_HEADERS([config.h])
AC_CONFIG_FILES([
Makefile
+ crypt.h.in
libxcrypt.pc
- crypt-base.h
])
AM_INIT_AUTOMAKE
diff --git a/crypt-gensalt-static.c b/crypt-gensalt-static.c
index 14f271e..590ee83 100644
--- a/crypt-gensalt-static.c
+++ b/crypt-gensalt-static.c
@@ -15,7 +15,6 @@
<https://www.gnu.org/licenses/>. */
#include "crypt-port.h"
-#include "crypt-base.h"
/* The functions that use global state objects are isolated in their
own files so that a statically-linked program that doesn't use them
diff --git a/crypt-obsolete.h b/crypt-obsolete.h
index d1acdea..4ecd969 100644
--- a/crypt-obsolete.h
+++ b/crypt-obsolete.h
@@ -19,7 +19,6 @@
#ifndef _CRYPT_OBSOLETE_H
#define _CRYPT_OBSOLETE_H 1
-#include "crypt-base.h"
/* These functions are obsolete and should never be used, but we have to
keep providing them for binary backward compatibility. */
diff --git a/crypt-port.h b/crypt-port.h
index f139efa..5f4d55f 100644
--- a/crypt-port.h
+++ b/crypt-port.h
@@ -44,8 +44,8 @@
#endif
/* While actually compiling the library, suppress the __nonnull tags
- on the functions in crypt-base.h, so that internal checks for NULL
- are not deleted by the compiler. */
+ on the functions in crypt.h, so that internal checks for NULL are
+ not deleted by the compiler. */
#undef __nonnull
#define __nonnull(param) /* nothing */
@@ -292,4 +292,6 @@ _xcrypt_strcpy_or_abort (void *dst, const size_t d_size,
#define libcperciva_SHA256_Buf _crypt_SHA256_Buf
#endif
+#include "crypt.h"
+
#endif /* crypt-port.h */
diff --git a/crypt-private.h b/crypt-private.h
index 5e18030..306879d 100644
--- a/crypt-private.h
+++ b/crypt-private.h
@@ -20,7 +20,6 @@
#ifndef _CRYPT_PRIVATE_H
#define _CRYPT_PRIVATE_H 1
-#include "crypt-base.h"
/* Utility functions */
diff --git a/crypt-static.c b/crypt-static.c
index fb9a953..d7598d1 100644
--- a/crypt-static.c
+++ b/crypt-static.c
@@ -15,7 +15,6 @@
<https://www.gnu.org/licenses/>. */
#include "crypt-port.h"
-#include "crypt-base.h"
/* The functions that use global state objects are isolated in their
own files so that a statically-linked program that doesn't use them
diff --git a/crypt-base.h.in b/crypt.h.in.in
similarity index 100%
rename from crypt-base.h.in
rename to crypt.h.in.in
diff --git a/gen-crypt-h.awk b/gen-crypt-h.awk
index 70fc5fa..8b3f4f5 100644
--- a/gen-crypt-h.awk
+++ b/gen-crypt-h.awk
@@ -1,4 +1,4 @@
-# Generation of crypt.h from crypt-base.h and config.h.
+# Generation of crypt.h from crypt.h.in and config.h.
#
# Written by Zack Weinberg <zackw at panix.com> in 2017.
# To the extent possible under law, Zack Weinberg has waived all
diff --git a/test-crypt-bcrypt.c b/test-crypt-bcrypt.c
index bf149b4..5cf90c1 100644
--- a/test-crypt-bcrypt.c
+++ b/test-crypt-bcrypt.c
@@ -15,7 +15,6 @@
*/
#include "crypt-port.h"
-#include "crypt-base.h"
#include <errno.h>
#include <stdio.h>
diff --git a/test-crypt-des.c b/test-crypt-des.c
index 1b5463e..f01fee7 100644
--- a/test-crypt-des.c
+++ b/test-crypt-des.c
@@ -1,5 +1,4 @@
#include "crypt-port.h"
-#include "crypt-base.h"
#include <stdio.h>
diff --git a/test-crypt-md5.c b/test-crypt-md5.c
index 3035c39..d42b529 100644
--- a/test-crypt-md5.c
+++ b/test-crypt-md5.c
@@ -1,5 +1,4 @@
#include "crypt-port.h"
-#include "crypt-base.h"
#if INCLUDE_md5
diff --git a/test-crypt-nthash.c b/test-crypt-nthash.c
index 9bf7d28..b344d86 100644
--- a/test-crypt-nthash.c
+++ b/test-crypt-nthash.c
@@ -1,5 +1,4 @@
#include "crypt-port.h"
-#include "crypt-base.h"
#include <stdio.h>
diff --git a/test-crypt-pbkdf1-sha1.c b/test-crypt-pbkdf1-sha1.c
index 677e5bf..7a0c826 100644
--- a/test-crypt-pbkdf1-sha1.c
+++ b/test-crypt-pbkdf1-sha1.c
@@ -1,5 +1,4 @@
#include "crypt-port.h"
-#include "crypt-base.h"
#include <errno.h>
#include <stdio.h>
diff --git a/test-crypt-scrypt.c b/test-crypt-scrypt.c
index df64774..0cf8da3 100644
--- a/test-crypt-scrypt.c
+++ b/test-crypt-scrypt.c
@@ -18,7 +18,6 @@
*/
#include "crypt-port.h"
-#include "crypt-base.h"
#include <stdio.h>
diff --git a/test-crypt-sha256.c b/test-crypt-sha256.c
index 05135ff..9331d14 100644
--- a/test-crypt-sha256.c
+++ b/test-crypt-sha256.c
@@ -1,5 +1,4 @@
#include "crypt-port.h"
-#include "crypt-base.h"
#include <stdio.h>
diff --git a/test-crypt-sha512.c b/test-crypt-sha512.c
index bef271b..88c5643 100644
--- a/test-crypt-sha512.c
+++ b/test-crypt-sha512.c
@@ -1,5 +1,4 @@
#include "crypt-port.h"
-#include "crypt-base.h"
#include <stdio.h>
diff --git a/test-crypt-sunmd5.c b/test-crypt-sunmd5.c
index d0d85e3..88e8ecf 100644
--- a/test-crypt-sunmd5.c
+++ b/test-crypt-sunmd5.c
@@ -1,5 +1,4 @@
#include "crypt-port.h"
-#include "crypt-base.h"
#include <stdio.h>
#include <stdlib.h>
diff --git a/test-crypt-yescrypt.c b/test-crypt-yescrypt.c
index da6b694..a635f94 100644
--- a/test-crypt-yescrypt.c
+++ b/test-crypt-yescrypt.c
@@ -17,7 +17,6 @@
*/
#include "crypt-port.h"
-#include "crypt-base.h"
#include <stdio.h>
diff --git a/test-des-obsolete.c b/test-des-obsolete.c
index d5e3cc0..4588c75 100644
--- a/test-des-obsolete.c
+++ b/test-des-obsolete.c
@@ -7,7 +7,6 @@
*/
#include "crypt-port.h"
-#include "crypt-base.h"
#include "crypt-obsolete.h"
#include "test-des-cases.h"
diff --git a/test-des-obsolete_r.c b/test-des-obsolete_r.c
index d635b2a..9efd0fb 100644
--- a/test-des-obsolete_r.c
+++ b/test-des-obsolete_r.c
@@ -7,7 +7,6 @@
*/
#include "crypt-port.h"
-#include "crypt-base.h"
#include "crypt-obsolete.h"
#include "test-des-cases.h"
diff --git a/test-gensalt.c b/test-gensalt.c
index a6d3621..40fe66c 100644
--- a/test-gensalt.c
+++ b/test-gensalt.c
@@ -1,5 +1,4 @@
#include "crypt-port.h"
-#include "crypt-base.h"
#include <errno.h>
#include <stdio.h>
From a5f8acd51acb267d989ea3375ab17e29a0857059 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bj=C3=B6rn=20Esser?= <besser82@fedoraproject.org>
Date: Sun, 21 Oct 2018 13:06:59 +0200
Subject: [PATCH 07/17] Add crypt-symbol-vers.h to nodist_noinst_HEADERS.
---
Makefile.am | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Makefile.am b/Makefile.am
index 498c48f..a09e6a4 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -24,7 +24,7 @@ notrans_dist_man3_MANS = \
notrans_dist_man5_MANS = crypt.5
nodist_include_HEADERS = crypt.h
-nodist_noinst_HEADERS = crypt-hashes.h
+nodist_noinst_HEADERS = crypt-hashes.h crypt-symbol-vers.h
noinst_HEADERS = \
alg-des.h alg-hmac-sha1.h alg-md4.h alg-md5.h \
alg-sha1.h alg-sha256.h alg-sha512.h \
From 6adbd465a6003cf856e4c9debe0e6049746c685a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bj=C3=B6rn=20Esser?= <besser82@fedoraproject.org>
Date: Sun, 21 Oct 2018 16:11:30 +0200
Subject: [PATCH 08/17] Add gen-des-tables to noinst_PROGRAMS.
---
.gitignore | 1 +
Makefile.am | 2 ++
2 files changed, 3 insertions(+)
diff --git a/.gitignore b/.gitignore
index e46e4c2..8aead50 100644
--- a/.gitignore
+++ b/.gitignore
@@ -48,6 +48,7 @@
/crypt-hashes.h
/crypt-symbol-vers.h
/libcrypt.map
+/gen-des-tables
/test-alg-des
/test-alg-hmac-sha1
/test-alg-md4
diff --git a/Makefile.am b/Makefile.am
index a09e6a4..e7d5c6d 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -31,6 +31,8 @@ noinst_HEADERS = \
alg-yescrypt.h alg-yescrypt-sysendian.h byteorder.h \
crypt-obsolete.h crypt-private.h crypt-port.h test-des-cases.h
+noinst_PROGRAMS = gen-des-tables
+
lib_LTLIBRARIES = libcrypt.la
libcrypt_la_SOURCES = \
alg-des.c alg-des-tables.c alg-hmac-sha1.c alg-md4.c alg-md5.c \
From 323e5e097f643641f41f24969227b073470e186e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bj=C3=B6rn=20Esser?= <besser82@fedoraproject.org>
Date: Mon, 22 Oct 2018 13:08:36 +0200
Subject: [PATCH 09/17] Use sha512 implementation from Colin Percival.
Thus we now have a sha512 implementation under the BSD license.
---
LICENSING | 4 +-
NEWS | 2 +
TODO.md | 2 +-
alg-sha512.c | 566 +++++++++++++++++++++------------------
alg-sha512.h | 121 +++++----
alg-yescrypt-sysendian.h | 12 +
crypt-port.h | 7 +-
crypt-sha512.c | 56 ++--
test-alg-sha512.c | 23 +-
9 files changed, 441 insertions(+), 352 deletions(-)
diff --git a/LICENSING b/LICENSING
index bf0c514..31f704c 100644
--- a/LICENSING
+++ b/LICENSING
@@ -14,7 +14,6 @@ source tree. For specific licensing terms consult the files themselves.
* Copyright Free Software Foundation, Inc.; LGPL (v2.1 or later):
crypt.h, crypt-obsolete.h, crypt-private.h
alg-md5.h, alg-md5.c, crypt-md5.c,
- alg-sha512.h, alg-sha512.c,
test-crypt-badsalt.c, test-crypt-nonnull.c
* Copyright David Burren et al.; 3-clause BSD:
@@ -34,6 +33,9 @@ source tree. For specific licensing terms consult the files themselves.
alg-sha256.c, alg-sha256.h, alg-yescrypt.h, alg-yescrypt-opt.c,
alg-yescrypt-sysendian.h
+ * Copyright Colin Percival; 2-clause BSD:
+ alg-sha512.h, alg-sha512.c
+
* Copyright Alexander Peslyak, Björn Esser; 0-clause BSD:
crypt-scrypt.c
diff --git a/NEWS b/NEWS
index c55a971..c4b04da 100644
--- a/NEWS
+++ b/NEWS
@@ -6,6 +6,8 @@ Please send bug reports, questions and suggestions to
Version 4.2.3
* Add bootstrap script. If building from a Git checkout instead of a
tarball release, use './bootstrap' to create the configure script.
+* Use sha512 implementation from Colin Percival. Thus we now have a
+ sha512 implementation under the BSD license.
Version 4.2.2
* Convert existing manpages to BSD mdoc format.
diff --git a/TODO.md b/TODO.md
index 30c0372..c4e2799 100644
--- a/TODO.md
+++ b/TODO.md
@@ -95,7 +95,7 @@ It was last updated 20 October 2018.
at it, and no destructor function
* Permissive relicensing, to encourage use beyond the GNU ecosystem?
- * Replace remaining (L)GPLed crypto primitives (MD5, SHA512) with
+ * Replace remaining (L)GPLed crypto primitives (MD5) with
permissively licensed equivalents (e.g. from Openwall)
* Replace crypt-md5.c with original md5crypt from FreeBSD?
* Other files subject to the (L)GPL are crypt.c, crypt-static.c,
diff --git a/alg-sha512.c b/alg-sha512.c
index 60c1877..0d24301 100644
--- a/alg-sha512.c
+++ b/alg-sha512.c
@@ -1,289 +1,335 @@
-/* Functions to compute SHA512 message digest of files or memory blocks.
- according to the definition of SHA512 in FIPS 180-2.
- Copyright (C) 2007-2017 Free Software Foundation, Inc.
+/*-
+ * Copyright 2005 Colin Percival
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public License
- as published by the Free Software Foundation; either version 2.1 of
- the License, or (at your option) any later version.
+#include "crypt-port.h"
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Lesser General Public License for more details.
+#if INCLUDE_sha512
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, see
- <https://www.gnu.org/licenses/>. */
+#include "alg-sha512.h"
+#include "alg-yescrypt-sysendian.h"
-/* Written by Ulrich Drepper <drepper@redhat.com>, 2007. */
+#if IS_BIGENDIAN
+/* Copy a vector of big-endian uint64_t into a vector of bytes */
+#define be64enc_vect(dst, src, len) \
+ memcpy((void *)dst, (const void *)src, (size_t)len)
-#include "crypt-port.h"
-#include "alg-sha512.h"
-#include "byteorder.h"
+/* Copy a vector of bytes into a vector of big-endian uint64_t */
+#define be64dec_vect(dst, src, len) \
+ memcpy((void *)dst, (const void *)src, (size_t)len)
-#if INCLUDE_sha512
+#else /* IS_BIGENDIAN */
-/* Constants for SHA512 from FIPS 180-2:4.2.3. */
-static const uint64_t K[80] =
+/*
+ * Encode a length len/4 vector of (uint64_t) into a length len vector of
+ * (unsigned char) in big-endian form. Assumes len is a multiple of 8.
+ */
+static void
+be64enc_vect(unsigned char *dst, const uint64_t *src, size_t len)
{
- UINT64_C (0x428a2f98d728ae22), UINT64_C (0x7137449123ef65cd),
- UINT64_C (0xb5c0fbcfec4d3b2f), UINT64_C (0xe9b5dba58189dbbc),
- UINT64_C (0x3956c25bf348b538), UINT64_C (0x59f111f1b605d019),
- UINT64_C (0x923f82a4af194f9b), UINT64_C (0xab1c5ed5da6d8118),
- UINT64_C (0xd807aa98a3030242), UINT64_C (0x12835b0145706fbe),
- UINT64_C (0x243185be4ee4b28c), UINT64_C (0x550c7dc3d5ffb4e2),
- UINT64_C (0x72be5d74f27b896f), UINT64_C (0x80deb1fe3b1696b1),
- UINT64_C (0x9bdc06a725c71235), UINT64_C (0xc19bf174cf692694),
- UINT64_C (0xe49b69c19ef14ad2), UINT64_C (0xefbe4786384f25e3),
- UINT64_C (0x0fc19dc68b8cd5b5), UINT64_C (0x240ca1cc77ac9c65),
- UINT64_C (0x2de92c6f592b0275), UINT64_C (0x4a7484aa6ea6e483),
- UINT64_C (0x5cb0a9dcbd41fbd4), UINT64_C (0x76f988da831153b5),
- UINT64_C (0x983e5152ee66dfab), UINT64_C (0xa831c66d2db43210),
- UINT64_C (0xb00327c898fb213f), UINT64_C (0xbf597fc7beef0ee4),
- UINT64_C (0xc6e00bf33da88fc2), UINT64_C (0xd5a79147930aa725),
- UINT64_C (0x06ca6351e003826f), UINT64_C (0x142929670a0e6e70),
- UINT64_C (0x27b70a8546d22ffc), UINT64_C (0x2e1b21385c26c926),
- UINT64_C (0x4d2c6dfc5ac42aed), UINT64_C (0x53380d139d95b3df),
- UINT64_C (0x650a73548baf63de), UINT64_C (0x766a0abb3c77b2a8),
- UINT64_C (0x81c2c92e47edaee6), UINT64_C (0x92722c851482353b),
- UINT64_C (0xa2bfe8a14cf10364), UINT64_C (0xa81a664bbc423001),
- UINT64_C (0xc24b8b70d0f89791), UINT64_C (0xc76c51a30654be30),
- UINT64_C (0xd192e819d6ef5218), UINT64_C (0xd69906245565a910),
- UINT64_C (0xf40e35855771202a), UINT64_C (0x106aa07032bbd1b8),
- UINT64_C (0x19a4c116b8d2d0c8), UINT64_C (0x1e376c085141ab53),
- UINT64_C (0x2748774cdf8eeb99), UINT64_C (0x34b0bcb5e19b48a8),
- UINT64_C (0x391c0cb3c5c95a63), UINT64_C (0x4ed8aa4ae3418acb),
- UINT64_C (0x5b9cca4f7763e373), UINT64_C (0x682e6ff3d6b2b8a3),
- UINT64_C (0x748f82ee5defb2fc), UINT64_C (0x78a5636f43172f60),
- UINT64_C (0x84c87814a1f0ab72), UINT64_C (0x8cc702081a6439ec),
- UINT64_C (0x90befffa23631e28), UINT64_C (0xa4506cebde82bde9),
- UINT64_C (0xbef9a3f7b2c67915), UINT64_C (0xc67178f2e372532b),
- UINT64_C (0xca273eceea26619c), UINT64_C (0xd186b8c721c0c207),
- UINT64_C (0xeada7dd6cde0eb1e), UINT64_C (0xf57d4f7fee6ed178),
- UINT64_C (0x06f067aa72176fba), UINT64_C (0x0a637dc5a2c898a6),
- UINT64_C (0x113f9804bef90dae), UINT64_C (0x1b710b35131c471b),
- UINT64_C (0x28db77f523047d84), UINT64_C (0x32caab7b40c72493),
- UINT64_C (0x3c9ebe0a15c9bebc), UINT64_C (0x431d67c49c100d4c),
- UINT64_C (0x4cc5d4becb3e42b6), UINT64_C (0x597f299cfc657e2a),
- UINT64_C (0x5fcb6fab3ad6faec), UINT64_C (0x6c44198c4a475817)
-};
+ size_t i;
+ for (i = 0; i < len / 8; i++)
+ be64enc(dst + i * 8, src[i]);
+}
-/* Process LEN bytes of BUFFER, accumulating context into CTX.
- It is assumed that LEN % 128 == 0. */
+/*
+ * Decode a big-endian length len vector of (unsigned char) into a length
+ * len/4 vector of (uint64_t). Assumes len is a multiple of 8.
+ */
static void
-sha512_process_block (const void *buffer, size_t len, struct sha512_ctx *ctx)
+be64dec_vect(uint64_t *dst, const unsigned char *src, size_t len)
{
- unsigned int t;
- const unsigned char *p = buffer;
- size_t nwords = len / sizeof (uint64_t);
- uint64_t a = ctx->H[0];
- uint64_t b = ctx->H[1];
- uint64_t c = ctx->H[2];
- uint64_t d = ctx->H[3];
- uint64_t e = ctx->H[4];
- uint64_t f = ctx->H[5];
- uint64_t g = ctx->H[6];
- uint64_t h = ctx->H[7];
-
- /* First increment the byte count. FIPS 180-2 specifies the possible
- length of the file up to 2^128 bits. Here we only compute the
- number of bytes. Do a double word increment. */
- ctx->total[0] += len;
- if (ctx->total[0] < len)
- ++ctx->total[1];
-
- /* Process all bytes in the buffer with 128 bytes in each round of
- the loop. */
- while (nwords > 0)
- {
- uint64_t W[80];
- uint64_t a_save = a;
- uint64_t b_save = b;
- uint64_t c_save = c;
- uint64_t d_save = d;
- uint64_t e_save = e;
- uint64_t f_save = f;
- uint64_t g_save = g;
- uint64_t h_save = h;
-
- /* Operators defined in FIPS 180-2:4.1.2. */
-#define Ch(x, y, z) ((x & y) ^ (~x & z))
-#define Maj(x, y, z) ((x & y) ^ (x & z) ^ (y & z))
-#define S0(x) (CYCLIC (x, 28) ^ CYCLIC (x, 34) ^ CYCLIC (x, 39))
-#define S1(x) (CYCLIC (x, 14) ^ CYCLIC (x, 18) ^ CYCLIC (x, 41))
-#define R0(x) (CYCLIC (x, 1) ^ CYCLIC (x, 8) ^ (x >> 7))
-#define R1(x) (CYCLIC (x, 19) ^ CYCLIC (x, 61) ^ (x >> 6))
-
- /* It is unfortunate that C does not provide an operator for
- cyclic rotation. Hope the C compiler is smart enough. */
-#define CYCLIC(w, s) ((w >> s) | (w << (64 - s)))
-
- /* Compute the message schedule according to FIPS 180-2:6.3.2 step 2. */
- for (t = 0; t < 16; ++t)
- {
- W[t] = be64_to_cpu (p);
- p += 8;
- }
- for (t = 16; t < 80; ++t)
- W[t] = R1 (W[t - 2]) + W[t - 7] + R0 (W[t - 15]) + W[t - 16];
-
- /* The actual computation according to FIPS 180-2:6.3.2 step 3. */
- for (t = 0; t < 80; ++t)
- {
- uint64_t T1 = h + S1 (e) + Ch (e, f, g) + K[t] + W[t];
- uint64_t T2 = S0 (a) + Maj (a, b, c);
- h = g;
- g = f;
- f = e;
- e = d + T1;
- d = c;
- c = b;
- b = a;
- a = T1 + T2;
- }
-
- /* Add the starting values of the context according to FIPS 180-2:6.3.2
- step 4. */
- a += a_save;
- b += b_save;
- c += c_save;
- d += d_save;
- e += e_save;
- f += f_save;
- g += g_save;
- h += h_save;
-
- /* Prepare for the next round. */
- nwords -= 16;
- }
-
- /* Put checksum in context given as argument. */
- ctx->H[0] = a;
- ctx->H[1] = b;
- ctx->H[2] = c;
- ctx->H[3] = d;
- ctx->H[4] = e;
- ctx->H[5] = f;
- ctx->H[6] = g;
- ctx->H[7] = h;
+ size_t i;
+
+ for (i = 0; i < len / 8; i++)
+ dst[i] = be64dec(src + i * 8);
}
+#endif /* IS_BIGENDIAN */
+
+/* Elementary functions used by SHA512 */
+#define Ch(x, y, z) ((x & (y ^ z)) ^ z)
+#define Maj(x, y, z) ((x & (y | z)) | (y & z))
+#define SHR(x, n) (x >> n)
+#define ROTR(x, n) ((x >> n) | (x << (64 - n)))
+#define S0(x) (ROTR(x, 28) ^ ROTR(x, 34) ^ ROTR(x, 39))
+#define S1(x) (ROTR(x, 14) ^ ROTR(x, 18) ^ ROTR(x, 41))
+#define s0(x) (ROTR(x, 1) ^ ROTR(x, 8) ^ SHR(x, 7))
+#define s1(x) (ROTR(x, 19) ^ ROTR(x, 61) ^ SHR(x, 6))
+
+/* SHA512 round function */
+#define RND(a, b, c, d, e, f, g, h, k) \
+ t0 = h + S1(e) + Ch(e, f, g) + k; \
+ t1 = S0(a) + Maj(a, b, c); \
+ d += t0; \
+ h = t0 + t1;
+
+/* Adjusted round function for rotating state */
+#define RNDr(S, W, i, k) \
+ RND(S[(80 - i) % 8], S[(81 - i) % 8], \
+ S[(82 - i) % 8], S[(83 - i) % 8], \
+ S[(84 - i) % 8], S[(85 - i) % 8], \
+ S[(86 - i) % 8], S[(87 - i) % 8], \
+ W[i] + k)
+
+/*
+ * SHA512 block compression function. The 512-bit state is transformed via
+ * the 512-bit input block to produce a new state.
+ */
+static void
+SHA512_Transform(uint64_t * state, const unsigned char block[128])
+{
+ uint64_t W[80];
+ uint64_t S[8];
+ uint64_t t0, t1;
+ int i;
+
+ /* 1. Prepare message schedule W. */
+ be64dec_vect(W, block, 128);
+ for (i = 16; i < 80; i++)
+ W[i] = s1(W[i - 2]) + W[i - 7] + s0(W[i - 15]) + W[i - 16];
+
+ /* 2. Initialize working variables. */
+ memcpy(S, state, 64);
+
+ /* 3. Mix. */
+ RNDr(S, W, 0, 0x428a2f98d728ae22ULL);
+ RNDr(S, W, 1, 0x7137449123ef65cdULL);
+ RNDr(S, W, 2, 0xb5c0fbcfec4d3b2fULL);
+ RNDr(S, W, 3, 0xe9b5dba58189dbbcULL);
+ RNDr(S, W, 4, 0x3956c25bf348b538ULL);
+ RNDr(S, W, 5, 0x59f111f1b605d019ULL);
+ RNDr(S, W, 6, 0x923f82a4af194f9bULL);
+ RNDr(S, W, 7, 0xab1c5ed5da6d8118ULL);
+ RNDr(S, W, 8, 0xd807aa98a3030242ULL);
+ RNDr(S, W, 9, 0x12835b0145706fbeULL);
+ RNDr(S, W, 10, 0x243185be4ee4b28cULL);
+ RNDr(S, W, 11, 0x550c7dc3d5ffb4e2ULL);
+ RNDr(S, W, 12, 0x72be5d74f27b896fULL);
+ RNDr(S, W, 13, 0x80deb1fe3b1696b1ULL);
+ RNDr(S, W, 14, 0x9bdc06a725c71235ULL);
+ RNDr(S, W, 15, 0xc19bf174cf692694ULL);
+ RNDr(S, W, 16, 0xe49b69c19ef14ad2ULL);
+ RNDr(S, W, 17, 0xefbe4786384f25e3ULL);
+ RNDr(S, W, 18, 0x0fc19dc68b8cd5b5ULL);
+ RNDr(S, W, 19, 0x240ca1cc77ac9c65ULL);
+ RNDr(S, W, 20, 0x2de92c6f592b0275ULL);
+ RNDr(S, W, 21, 0x4a7484aa6ea6e483ULL);
+ RNDr(S, W, 22, 0x5cb0a9dcbd41fbd4ULL);
+ RNDr(S, W, 23, 0x76f988da831153b5ULL);
+ RNDr(S, W, 24, 0x983e5152ee66dfabULL);
+ RNDr(S, W, 25, 0xa831c66d2db43210ULL);
+ RNDr(S, W, 26, 0xb00327c898fb213fULL);
+ RNDr(S, W, 27, 0xbf597fc7beef0ee4ULL);
+ RNDr(S, W, 28, 0xc6e00bf33da88fc2ULL);
+ RNDr(S, W, 29, 0xd5a79147930aa725ULL);
+ RNDr(S, W, 30, 0x06ca6351e003826fULL);
+ RNDr(S, W, 31, 0x142929670a0e6e70ULL);
+ RNDr(S, W, 32, 0x27b70a8546d22ffcULL);
+ RNDr(S, W, 33, 0x2e1b21385c26c926ULL);
+ RNDr(S, W, 34, 0x4d2c6dfc5ac42aedULL);
+ RNDr(S, W, 35, 0x53380d139d95b3dfULL);
+ RNDr(S, W, 36, 0x650a73548baf63deULL);
+ RNDr(S, W, 37, 0x766a0abb3c77b2a8ULL);
+ RNDr(S, W, 38, 0x81c2c92e47edaee6ULL);
+ RNDr(S, W, 39, 0x92722c851482353bULL);
+ RNDr(S, W, 40, 0xa2bfe8a14cf10364ULL);
+ RNDr(S, W, 41, 0xa81a664bbc423001ULL);
+ RNDr(S, W, 42, 0xc24b8b70d0f89791ULL);
+ RNDr(S, W, 43, 0xc76c51a30654be30ULL);
+ RNDr(S, W, 44, 0xd192e819d6ef5218ULL);
+ RNDr(S, W, 45, 0xd69906245565a910ULL);
+ RNDr(S, W, 46, 0xf40e35855771202aULL);
+ RNDr(S, W, 47, 0x106aa07032bbd1b8ULL);
+ RNDr(S, W, 48, 0x19a4c116b8d2d0c8ULL);
+ RNDr(S, W, 49, 0x1e376c085141ab53ULL);
+ RNDr(S, W, 50, 0x2748774cdf8eeb99ULL);
+ RNDr(S, W, 51, 0x34b0bcb5e19b48a8ULL);
+ RNDr(S, W, 52, 0x391c0cb3c5c95a63ULL);
+ RNDr(S, W, 53, 0x4ed8aa4ae3418acbULL);
+ RNDr(S, W, 54, 0x5b9cca4f7763e373ULL);
+ RNDr(S, W, 55, 0x682e6ff3d6b2b8a3ULL);
+ RNDr(S, W, 56, 0x748f82ee5defb2fcULL);
+ RNDr(S, W, 57, 0x78a5636f43172f60ULL);
+ RNDr(S, W, 58, 0x84c87814a1f0ab72ULL);
+ RNDr(S, W, 59, 0x8cc702081a6439ecULL);
+ RNDr(S, W, 60, 0x90befffa23631e28ULL);
+ RNDr(S, W, 61, 0xa4506cebde82bde9ULL);
+ RNDr(S, W, 62, 0xbef9a3f7b2c67915ULL);
+ RNDr(S, W, 63, 0xc67178f2e372532bULL);
+ RNDr(S, W, 64, 0xca273eceea26619cULL);
+ RNDr(S, W, 65, 0xd186b8c721c0c207ULL);
+ RNDr(S, W, 66, 0xeada7dd6cde0eb1eULL);
+ RNDr(S, W, 67, 0xf57d4f7fee6ed178ULL);
+ RNDr(S, W, 68, 0x06f067aa72176fbaULL);
+ RNDr(S, W, 69, 0x0a637dc5a2c898a6ULL);
+ RNDr(S, W, 70, 0x113f9804bef90daeULL);
+ RNDr(S, W, 71, 0x1b710b35131c471bULL);
+ RNDr(S, W, 72, 0x28db77f523047d84ULL);
+ RNDr(S, W, 73, 0x32caab7b40c72493ULL);
+ RNDr(S, W, 74, 0x3c9ebe0a15c9bebcULL);
+ RNDr(S, W, 75, 0x431d67c49c100d4cULL);
+ RNDr(S, W, 76, 0x4cc5d4becb3e42b6ULL);
+ RNDr(S, W, 77, 0x597f299cfc657e2aULL);
+ RNDr(S, W, 78, 0x5fcb6fab3ad6faecULL);
+ RNDr(S, W, 79, 0x6c44198c4a475817ULL);
+
+ /* 4. Mix local working variables into global state */
+ for (i = 0; i < 8; i++)
+ state[i] += S[i];
+}
-/* Initialize structure containing state of computation.
- (FIPS 180-2:5.3.3) */
-void
-sha512_init_ctx (struct sha512_ctx *ctx)
+static unsigned char PAD[128] = {
+ 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+/* Add padding and terminating bit-count. */
+static void
+SHA512_Pad(SHA512_CTX * ctx)
{
- ctx->H[0] = UINT64_C (0x6a09e667f3bcc908);
- ctx->H[1] = UINT64_C (0xbb67ae8584caa73b);
- ctx->H[2] = UINT64_C (0x3c6ef372fe94f82b);
- ctx->H[3] = UINT64_C (0xa54ff53a5f1d36f1);
- ctx->H[4] = UINT64_C (0x510e527fade682d1);
- ctx->H[5] = UINT64_C (0x9b05688c2b3e6c1f);
- ctx->H[6] = UINT64_C (0x1f83d9abfb41bd6b);
- ctx->H[7] = UINT64_C (0x5be0cd19137e2179);
-
- ctx->total[0] = ctx->total[1] = 0;
- ctx->buflen = 0;
+ unsigned char len[16];
+ uint64_t r, plen;
+
+ /*
+ * Convert length to a vector of bytes -- we do this now rather
+ * than later because the length will change after we pad.
+ */
+ be64enc_vect(len, ctx->count, 16);
+
+ /* Add 1--128 bytes so that the resulting length is 112 mod 128 */
+ r = (ctx->count[1] >> 3) & 0x7f;
+ plen = (r < 112) ? (112 - r) : (240 - r);
+ SHA512_Update(ctx, PAD, (size_t)plen);
+
+ /* Add the terminating bit-count */
+ SHA512_Update(ctx, len, 16);
}
+/* SHA-512 initialization. Begins a SHA-512 operation. */
+void
+SHA512_Init(SHA512_CTX * ctx)
+{
-/* Process the remaining bytes in the internal buffer and the usual
- prolog according to the standard and write the result to RESBUF.
+ /* Zero bits processed so far */
+ ctx->count[0] = ctx->count[1] = 0;
+
+ /* Magic initialization constants */
+ ctx->state[0] = 0x6a09e667f3bcc908ULL;
+ ctx->state[1] = 0xbb67ae8584caa73bULL;
+ ctx->state[2] = 0x3c6ef372fe94f82bULL;
+ ctx->state[3] = 0xa54ff53a5f1d36f1ULL;
+ ctx->state[4] = 0x510e527fade682d1ULL;
+ ctx->state[5] = 0x9b05688c2b3e6c1fULL;
+ ctx->state[6] = 0x1f83d9abfb41bd6bULL;
+ ctx->state[7] = 0x5be0cd19137e2179ULL;
+}
- IMPORTANT: On some systems it is required that RESBUF is correctly
- aligned for a 32 bits value. */
-void *
-sha512_finish_ctx (struct sha512_ctx *ctx, void *resbuf)
+/* Add bytes into the hash */
+void
+SHA512_Update(SHA512_CTX * ctx, const void *in, size_t len)
{
- /* Take yet unprocessed bytes into account. */
- uint32_t bytes = ctx->buflen;
- size_t pad;
- unsigned int i;
- unsigned char *rp = resbuf;
-
- /* Now count remaining bytes. */
- ctx->total[0] += bytes;
- if (ctx->total[0] < bytes)
- ++ctx->total[1];
-
- pad = bytes >= 112 ? 128 + 112 - bytes : 112 - bytes;
- /* The first byte of padding should be 0x80 and the rest should be
- zero. (FIPS 180-2:5.1.2) */
- ctx->buffer[bytes] = 0x80u;
- XCRYPT_SECURE_MEMSET (&ctx->buffer[bytes+1], pad-1);
-
- /* Put the 128-bit file length in big-endian *bits* at the end of
- the buffer. */
- cpu_to_be64 (&ctx->buffer[bytes + pad],
- (ctx->total[1] << 3) | (ctx->total[0] >> 61));
- cpu_to_be64 (&ctx->buffer[bytes + pad + 8],
- ctx->total[0] << 3);
-
- /* Process last bytes. */
- sha512_process_block (ctx->buffer, bytes + pad + 16, ctx);
-
- /* Put result from CTX in first 64 bytes following RESBUF. */
- for (i = 0; i < 8; ++i)
- cpu_to_be64 (rp + i*8, ctx->H[i]);
-
- XCRYPT_SECURE_MEMSET (ctx, sizeof (struct sha512_ctx));
- return resbuf;
+ uint64_t bitlen[2];
+ uint64_t r;
+ const unsigned char *src = in;
+
+ /* Number of bytes left in the buffer from previous updates */
+ r = (ctx->count[1] >> 3) & 0x7f;
+
+ /* Convert the length into a number of bits */
+ bitlen[1] = ((uint64_t)len) << 3;
+ bitlen[0] = ((uint64_t)len) >> 61;
+
+ /* Update number of bits */
+ if ((ctx->count[1] += bitlen[1]) < bitlen[1])
+ ctx->count[0]++;
+ ctx->count[0] += bitlen[0];
+
+ /* Handle the case where we don't need to perform any transforms */
+ if (len < 128 - r) {
+ memcpy(&ctx->buf[r], src, len);
+ return;
+ }
+
+ /* Finish the current block */
+ memcpy(&ctx->buf[r], src, 128 - r);
+ SHA512_Transform(ctx->state, ctx->buf);
+ src += 128 - r;
+ len -= 128 - r;
+
+ /* Perform complete blocks */
+ while (len >= 128) {
+ SHA512_Transform(ctx->state, src);
+ src += 128;
+ len -= 128;
+ }
+
+ /* Copy left over data into buffer */
+ memcpy(ctx->buf, src, len);
}
+/*
+ * SHA-512 finalization. Pads the input data, exports the hash value,
+ * and clears the context state.
+ */
+void
+SHA512_Final(unsigned char digest[64], SHA512_CTX * ctx)
+{
+
+ /* Add padding */
+ SHA512_Pad(ctx);
+ /* Write the hash */
+ be64enc_vect(digest, ctx->state, 64);
+
+ /* Clear the context state */
+ XCRYPT_SECURE_MEMSET(ctx, sizeof (*ctx));
+}
+
+/**
+ * SHA512_Buf(in, len, digest):
+ * Compute the SHA512 hash of ${len} bytes from ${in} and write it to ${digest}.
+ */
void
-sha512_process_bytes (const void *buffer, size_t len, struct sha512_ctx *ctx)
+SHA512_Buf(const void * in, size_t len, uint8_t digest[64])
{
- /* When we already have some bits in our internal buffer concatenate
- both inputs first. */
- if (ctx->buflen != 0)
- {
- uint32_t left_over = ctx->buflen;
- uint32_t add = 256 - left_over > len ? (uint32_t)len : 256 - left_over;
-
- memcpy (&ctx->buffer[left_over], buffer, add);
- ctx->buflen += add;
-
- if (ctx->buflen > 128)
- {
- sha512_process_block (ctx->buffer, ctx->buflen & ~127u, ctx);
-
- ctx->buflen &= 127;
- /* The regions in the following copy operation cannot overlap. */
- memcpy (ctx->buffer, &ctx->buffer[(left_over + add) & ~127u],
- ctx->buflen);
- }
-
- buffer = (const char *) buffer + add;
- len -= add;
- }
-
- /* Process available complete blocks. */
- if (len > 128)
- {
- sha512_process_block (buffer, len & ~127u, ctx);
- buffer = (const char *) buffer + (len & ~127u);
- len &= 127;
- }
-
- /* Move remaining bytes into internal buffer. */
- if (len > 0)
- {
- size_t left_over = ctx->buflen;
-
- memcpy (&ctx->buffer[left_over], buffer, len);
- left_over += len;
- if (left_over >= 128)
- {
- sha512_process_block (ctx->buffer, 128, ctx);
- left_over -= 128;
- memcpy (ctx->buffer, &ctx->buffer[128], left_over);
- }
- ctx->buflen = (uint32_t)left_over;
- }
+ SHA512_CTX ctx;
+
+ SHA512_Init(&ctx);
+ SHA512_Update(&ctx, in, len);
+ SHA512_Final(digest, &ctx);
+
+ /* Clean the stack. */
+ XCRYPT_SECURE_MEMSET(&ctx, sizeof(SHA512_CTX));
}
#endif
diff --git a/alg-sha512.h b/alg-sha512.h
index c11329e..c591bb1 100644
--- a/alg-sha512.h
+++ b/alg-sha512.h
@@ -1,46 +1,75 @@
-/* Declaration of functions and data types used for SHA512 sum computing
- library functions.
- Copyright (C) 2007-2017 Free Software Foundation, Inc.
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public License
- as published by the Free Software Foundation; either version 2.1 of
- the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, see
- <https://www.gnu.org/licenses/>. */
-
-#ifndef _CRYPT_ALG_SHA512_H
-#define _CRYPT_ALG_SHA512_H 1
-
-/* Structure to save state of computation between the single steps. */
-struct sha512_ctx
-{
- uint64_t H[8];
-
- uint64_t total[2];
- uint32_t buflen;
- unsigned char buffer[256];
-};
-
-/* Initialize structure containing state of computation.
- (FIPS 180-2: 5.3.3) */
-extern void sha512_init_ctx (struct sha512_ctx *ctx);
-
-/* Starting with the result of former calls of this function (or the
- initialization function) update the context for the next LEN bytes
- starting at BUFFER. LEN does not need to be a multiple of 128. */
-extern void sha512_process_bytes (const void *buffer, size_t len,
- struct sha512_ctx *ctx);
-
-/* Process the remaining bytes in the buffer and write the finalized
- hash to RESBUF, which should point to 64 bytes of storage. */
-extern void *sha512_finish_ctx (struct sha512_ctx *ctx, void *resbuf);
-
-#endif /* alg-sha512.h */
+/*-
+ * Copyright 2005 Colin Percival
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _SHA512_H_
+#define _SHA512_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+/*
+ * Use #defines in order to avoid namespace collisions with anyone else's
+ * SHA512 code (e.g., the code in OpenSSL).
+ */
+#define SHA512_Init libcperciva_SHA512_Init
+#define SHA512_Update libcperciva_SHA512_Update
+#define SHA512_Final libcperciva_SHA512_Final
+#define SHA512_Buf libcperciva_SHA512_Buf
+#define SHA512_CTX libcperciva_SHA512_CTX
+
+/* Context structure for SHA512 operations. */
+typedef struct {
+ uint64_t state[8];
+ uint64_t count[2];
+ uint8_t buf[128];
+} SHA512_CTX;
+
+/**
+ * SHA512_Init(ctx):
+ * Initialize the SHA512 context ${ctx}.
+ */
+void SHA512_Init(SHA512_CTX *);
+
+/**
+ * SHA512_Update(ctx, in, len):
+ * Input ${len} bytes from ${in} into the SHA512 context ${ctx}.
+ */
+void SHA512_Update(SHA512_CTX *, const void *, size_t);
+
+/**
+ * SHA512_Final(digest, ctx):
+ * Output the SHA512 hash of the data input to the context ${ctx} into the
+ * buffer ${digest}.
+ */
+void SHA512_Final(uint8_t[64], SHA512_CTX *);
+
+/**
+ * SHA512_Buf(in, len, digest):
+ * Compute the SHA512 hash of ${len} bytes from ${in} and write it to ${digest}.
+ */
+void SHA512_Buf(const void *, size_t, uint8_t[64]);
+
+#endif /* !_SHA512_H_ */
diff --git a/alg-yescrypt-sysendian.h b/alg-yescrypt-sysendian.h
index e2e41cd..b877e07 100644
--- a/alg-yescrypt-sysendian.h
+++ b/alg-yescrypt-sysendian.h
@@ -37,6 +37,7 @@
/* Avoid namespace collisions with BSD <sys/endian.h>. */
#define be32dec libcperciva_be32dec
#define be32enc libcperciva_be32enc
+#define be64dec libcperciva_be64dec
#define be64enc libcperciva_be64enc
#define le32dec libcperciva_le32dec
#define le32enc libcperciva_le32enc
@@ -61,6 +62,17 @@ be32enc(void * pp, uint32_t x)
p[0] = (x >> 24) & 0xff;
}
+static inline uint64_t
+be64dec(const void *pp)
+{
+ const uint8_t *p = (uint8_t const *)pp;
+
+ return ((uint64_t)(p[7]) + ((uint64_t)(p[6]) << 8) +
+ ((uint64_t)(p[5]) << 16) + ((uint64_t)(p[4]) << 24) +
+ ((uint64_t)(p[3]) << 32) + ((uint64_t)(p[2]) << 40) +
+ ((uint64_t)(p[1]) << 48) + ((uint64_t)(p[0]) << 56));
+}
+
static inline void
be64enc(void * pp, uint64_t x)
{
diff --git a/crypt-port.h b/crypt-port.h
index 5f4d55f..a2c64b3 100644
--- a/crypt-port.h
+++ b/crypt-port.h
@@ -260,9 +260,10 @@ _xcrypt_strcpy_or_abort (void *dst, const size_t d_size,
#endif
#if INCLUDE_sha512
-#define sha512_finish_ctx _crypt_sha512_finish_ctx
-#define sha512_init_ctx _crypt_sha512_init_ctx
-#define sha512_process_bytes _crypt_sha512_process_bytes
+#define libcperciva_SHA512_Init _crypt_SHA512_Init
+#define libcperciva_SHA512_Update _crypt_SHA512_Update
+#define libcperciva_SHA512_Final _crypt_SHA512_Final
+#define libcperciva_SHA512_Buf _crypt_SHA512_Buf
#endif
#if INCLUDE_md5 || INCLUDE_sha256 || INCLUDE_sha512
diff --git a/crypt-sha512.c b/crypt-sha512.c
index 39ec0b5..2b6b444 100644
--- a/crypt-sha512.c
+++ b/crypt-sha512.c
@@ -58,7 +58,7 @@ static_assert (SHA512_HASH_LENGTH <= CRYPT_OUTPUT_SIZE,
/* A sha512_buffer holds all of the sensitive intermediate data. */
struct sha512_buffer
{
- struct sha512_ctx ctx;
+ SHA512_CTX ctx;
uint8_t result[64];
uint8_t p_bytes[64];
uint8_t s_bytes[64];
@@ -77,12 +77,12 @@ static const char b64t[] =
indefinitely. */
static void
sha512_process_recycled_bytes (unsigned char block[64], size_t len,
- struct sha512_ctx *ctx)
+ SHA512_CTX *ctx)
{
size_t cnt;
for (cnt = len; cnt >= 64; cnt -= 64)
- sha512_process_bytes (block, 64, ctx);
- sha512_process_bytes (block, cnt, ctx);
+ SHA512_Update (ctx, block, 64);
+ SHA512_Update (ctx, block, cnt);
}
void
@@ -100,7 +100,7 @@ crypt_sha512_rn (const char *phrase, size_t phr_size,
}
struct sha512_buffer *buf = scratch;
- struct sha512_ctx *ctx = &buf->ctx;
+ SHA512_CTX *ctx = &buf->ctx;
uint8_t *result = buf->result;
uint8_t *p_bytes = buf->p_bytes;
uint8_t *s_bytes = buf->s_bytes;
@@ -158,80 +158,80 @@ crypt_sha512_rn (const char *phrase, size_t phr_size,
/* Compute alternate SHA512 sum with input PHRASE, SALT, and PHRASE. The
final result will be added to the first context. */
- sha512_init_ctx (ctx);
+ SHA512_Init (ctx);
/* Add phrase. */
- sha512_process_bytes (phrase, phr_size, ctx);
+ SHA512_Update (ctx, phrase, phr_size);
/* Add salt. */
- sha512_process_bytes (salt, salt_size, ctx);
+ SHA512_Update (ctx, salt, salt_size);
/* Add phrase again. */
- sha512_process_bytes (phrase, phr_size, ctx);
+ SHA512_Update (ctx, phrase, phr_size);
/* Now get result of this (64 bytes) and add it to the other
context. */
- sha512_finish_ctx (ctx, result);
+ SHA512_Final (result, ctx);
/* Prepare for the real work. */
- sha512_init_ctx (ctx);
+ SHA512_Init (ctx);
/* Add the phrase string. */
- sha512_process_bytes (phrase, phr_size, ctx);
+ SHA512_Update (ctx, phrase, phr_size);
/* The last part is the salt string. This must be at most 8
characters and it ends at the first `$' character (for
compatibility with existing implementations). */
- sha512_process_bytes (salt, salt_size, ctx);
+ SHA512_Update (ctx, salt, salt_size);
/* Add for any character in the phrase one byte of the alternate sum. */
for (cnt = phr_size; cnt > 64; cnt -= 64)
- sha512_process_bytes (result, 64, ctx);
- sha512_process_bytes (result, cnt, ctx);
+ SHA512_Update (ctx, result, 64);
+ SHA512_Update (ctx, result, cnt);
/* Take the binary representation of the length of the phrase and for every
1 add the alternate sum, for every 0 the phrase. */
for (cnt = phr_size; cnt > 0; cnt >>= 1)
if ((cnt & 1) != 0)
- sha512_process_bytes (result, 64, ctx);
+ SHA512_Update (ctx, result, 64);
else
- sha512_process_bytes (phrase, phr_size, ctx);
+ SHA512_Update (ctx, phrase, phr_size);
/* Create intermediate result. */
- sha512_finish_ctx (ctx, result);
+ SHA512_Final (result, ctx);
/* Start computation of P byte sequence. */
- sha512_init_ctx (ctx);
+ SHA512_Init (ctx);
/* For every character in the password add the entire password. */
for (cnt = 0; cnt < phr_size; ++cnt)
- sha512_process_bytes (phrase, phr_size, ctx);
+ SHA512_Update (ctx, phrase, phr_size);
/* Finish the digest. */
- sha512_finish_ctx (ctx, p_bytes);
+ SHA512_Final (p_bytes, ctx);
/* Start computation of S byte sequence. */
- sha512_init_ctx (ctx);
+ SHA512_Init (ctx);
/* For every character in the password add the entire password. */
for (cnt = 0; cnt < (size_t) 16 + (size_t) result[0]; ++cnt)
- sha512_process_bytes (salt, salt_size, ctx);
+ SHA512_Update (ctx, salt, salt_size);
/* Finish the digest. */
- sha512_finish_ctx (ctx, s_bytes);
+ SHA512_Final (s_bytes, ctx);
/* Repeatedly run the collected hash value through SHA512 to burn
CPU cycles. */
for (cnt = 0; cnt < rounds; ++cnt)
{
/* New context. */
- sha512_init_ctx (ctx);
+ SHA512_Init (ctx);
/* Add phrase or last result. */
if ((cnt & 1) != 0)
sha512_process_recycled_bytes (p_bytes, phr_size, ctx);
else
- sha512_process_bytes (result, 64, ctx);
+ SHA512_Update (ctx, result, 64);
/* Add salt for numbers not divisible by 3. */
if (cnt % 3 != 0)
@@ -243,12 +243,12 @@ crypt_sha512_rn (const char *phrase, size_t phr_size,
/* Add phrase or last result. */
if ((cnt & 1) != 0)
- sha512_process_bytes (result, 64, ctx);
+ SHA512_Update (ctx, result, 64);
else
sha512_process_recycled_bytes (p_bytes, phr_size, ctx);
/* Create intermediate result. */
- sha512_finish_ctx (ctx, result);
+ SHA512_Final (result, ctx);
}
/* Now we can construct the result string. It consists of four
diff --git a/test-alg-sha512.c b/test-alg-sha512.c
index b6d4fc6..5f9af9c 100644
--- a/test-alg-sha512.c
+++ b/test-alg-sha512.c
@@ -84,7 +84,7 @@ static const struct
static void
report_failure(int n, const char *tag,
- const char expected[64], const char actual[64])
+ const char expected[64], const uint8_t actual[64])
{
int i;
printf ("FAIL: test %d (%s):\n exp:", n, tag);
@@ -112,28 +112,25 @@ report_failure(int n, const char *tag,
int
main (void)
{
- struct sha512_ctx ctx;
- char sum[64];
+ SHA512_CTX ctx;
+ uint8_t sum[64];
int result = 0;
int cnt;
int i;
for (cnt = 0; cnt < (int) ARRAY_SIZE (tests); ++cnt)
{
- sha512_init_ctx (&ctx);
- sha512_process_bytes (tests[cnt].input, strlen (tests[cnt].input),
- &ctx);
- sha512_finish_ctx (&ctx, sum);
+ SHA512_Buf (tests[cnt].input, strlen (tests[cnt].input), sum);
if (memcmp (tests[cnt].result, sum, 64) != 0)
{
report_failure (cnt, "all at once", tests[cnt].result, sum);
result = 1;
}
- sha512_init_ctx (&ctx);
+ SHA512_Init (&ctx);
for (i = 0; tests[cnt].input[i] != '\0'; ++i)
- sha512_process_bytes (&tests[cnt].input[i], 1, &ctx);
- sha512_finish_ctx (&ctx, sum);
+ SHA512_Update (&ctx, &tests[cnt].input[i], 1);
+ SHA512_Final (sum, &ctx);
if (memcmp (tests[cnt].result, sum, 64) != 0)
{
report_failure (cnt, "byte by byte", tests[cnt].result, sum);
@@ -144,10 +141,10 @@ main (void)
/* Test vector from FIPS 180-2: appendix C.3. */
char buf[1000];
memset (buf, 'a', sizeof (buf));
- sha512_init_ctx (&ctx);
+ SHA512_Init (&ctx);
for (i = 0; i < 1000; ++i)
- sha512_process_bytes (buf, sizeof (buf), &ctx);
- sha512_finish_ctx (&ctx, sum);
+ SHA512_Update (&ctx, buf, sizeof (buf));
+ SHA512_Final (sum, &ctx);
static const char expected[64] =
"\xe7\x18\x48\x3d\x0c\xe7\x69\x64\x4e\x2e\x42\xc7\xbc\x15\xb4\x63"
"\x8e\x1f\x98\xb1\x3b\x20\x44\x28\x56\x32\xa8\x03\xaf\xa9\x73\xeb"
From 4964877dbf96d951b3f45b2dba97459404d1dff8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bj=C3=B6rn=20Esser?= <besser82@fedoraproject.org>
Date: Mon, 22 Oct 2018 13:48:34 +0200
Subject: [PATCH 10/17] Use md5 implementation from Alexander Peslyak.
Thus we now have a md5 implementation in the public domain.
---
LICENSING | 5 +-
NEWS | 2 +
TODO.md | 2 -
alg-md5.c | 539 ++++++++++++++++++++++++-------------------------
alg-md5.h | 79 ++++----
crypt-md5.c | 47 +++--
crypt-port.h | 6 +-
crypt-sunmd5.c | 20 +-
test-alg-md5.c | 24 +--
9 files changed, 349 insertions(+), 375 deletions(-)
diff --git a/LICENSING b/LICENSING
index 31f704c..0ed22f5 100644
--- a/LICENSING
+++ b/LICENSING
@@ -13,7 +13,7 @@ source tree. For specific licensing terms consult the files themselves.
* Copyright Free Software Foundation, Inc.; LGPL (v2.1 or later):
crypt.h, crypt-obsolete.h, crypt-private.h
- alg-md5.h, alg-md5.c, crypt-md5.c,
+ crypt-md5.c,
test-crypt-badsalt.c, test-crypt-nonnull.c
* Copyright David Burren et al.; 3-clause BSD:
@@ -24,7 +24,8 @@ source tree. For specific licensing terms consult the files themselves.
crypt-sha256.c, crypt-sha512.c
* Public domain, written by Solar Designer et al.:
- alg-md4.h, alg-md4.c, crypt-bcrypt.c, crypt-gensalt.c, test-crypt-bcrypt.c
+ alg-md4.h, alg-md4.c, alg-md5.h, alg-md5.c,
+ crypt-bcrypt.c, crypt-gensalt.c, test-crypt-bcrypt.c
* Copyright Solar Designer, Colin Percival; 0-clause BSD:
alg-yescrypt-common.c, alg-yescrypt-platform.c
diff --git a/NEWS b/NEWS
index c4b04da..e48b0d1 100644
--- a/NEWS
+++ b/NEWS
@@ -8,6 +8,8 @@ Version 4.2.3
tarball release, use './bootstrap' to create the configure script.
* Use sha512 implementation from Colin Percival. Thus we now have a
sha512 implementation under the BSD license.
+* Use md5 implementation from Alexander Peslyak. Thus we now have a
+ md5 implementation in the public domain.
Version 4.2.2
* Convert existing manpages to BSD mdoc format.
diff --git a/TODO.md b/TODO.md
index c4e2799..7df4ca5 100644
--- a/TODO.md
+++ b/TODO.md
@@ -95,8 +95,6 @@ It was last updated 20 October 2018.
at it, and no destructor function
* Permissive relicensing, to encourage use beyond the GNU ecosystem?
- * Replace remaining (L)GPLed crypto primitives (MD5) with
- permissively licensed equivalents (e.g. from Openwall)
* Replace crypt-md5.c with original md5crypt from FreeBSD?
* Other files subject to the (L)GPL are crypt.c, crypt-static.c,
crypt-gensalt-static.c, crypt-obsolete.h, crypt-port.h,
diff --git a/alg-md5.c b/alg-md5.c
index 9d9e4e3..8382b98 100644
--- a/alg-md5.c
+++ b/alg-md5.c
@@ -1,308 +1,291 @@
-/* Functions to compute MD5 message digest of files or memory blocks.
- according to the definition of MD5 in RFC 1321 from April 1992.
-
- Copyright (C) 1995-2017 Free Software Foundation, Inc.
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public License
- as published by the Free Software Foundation; either version 2.1 of
- the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, see
- <https://www.gnu.org/licenses/>. */
-
-/* Written by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995. */
+/*
+ * This is an OpenSSL-compatible implementation of the RSA Data Security, Inc.
+ * MD5 Message-Digest Algorithm (RFC 1321).
+ *
+ * Homepage:
+ * http://openwall.info/wiki/people/solar/software/public-domain-source-code/md5
+ *
+ * Author:
+ * Alexander Peslyak, better known as Solar Designer <solar at openwall.com>
+ *
+ * This software was written by Alexander Peslyak in 2001. No copyright is
+ * claimed, and the software is hereby placed in the public domain.
+ * In case this attempt to disclaim copyright and place the software in the
+ * public domain is deemed null and void, then the software is
+ * Copyright (c) 2001 Alexander Peslyak and it is hereby released to the
+ * general public under the following terms:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted.
+ *
+ * There's ABSOLUTELY NO WARRANTY, express or implied.
+ *
+ * (This is a heavily cut-down "BSD license".)
+ *
+ * This differs from Colin Plumb's older public domain implementation in that
+ * no exactly 32-bit integer data type is required (any 32-bit or wider
+ * unsigned integer data type will do), there's no compile-time endianness
+ * configuration, and the function prototypes match OpenSSL's. No code from
+ * Colin Plumb's implementation has been reused; this comment merely compares
+ * the properties of the two independent implementations.
+ *
+ * The primary goals of this implementation are portability and ease of use.
+ * It is meant to be fast, but not as fast as possible. Some known
+ * optimizations are not included to reduce source code size and avoid
+ * compile-time configuration.
+ */
#include "crypt-port.h"
-#include "alg-md5.h"
-#include "byteorder.h"
#if INCLUDE_md5 || INCLUDE_sunmd5
-static void md5_process_block (const void *buffer, size_t len,
- struct md5_ctx *ctx);
+#include "alg-md5.h"
-/* Initialize structure containing state of computation.
- (RFC 1321, 3.3: Step 3) */
-void
-md5_init_ctx (struct md5_ctx *ctx)
-{
- ctx->A = 0x67452301;
- ctx->B = 0xefcdab89;
- ctx->C = 0x98badcfe;
- ctx->D = 0x10325476;
+/*
+ * The basic MD5 functions.
+ *
+ * F and G are optimized compared to their RFC 1321 definitions for
+ * architectures that lack an AND-NOT instruction, just like in Colin Plumb's
+ * implementation.
+ */
+#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
+#define G(x, y, z) ((y) ^ ((z) & ((x) ^ (y))))
+#define H(x, y, z) (((x) ^ (y)) ^ (z))
+#define H2(x, y, z) ((x) ^ ((y) ^ (z)))
+#define I(x, y, z) ((y) ^ ((x) | ~(z)))
+
+/*
+ * The MD5 transformation for all four rounds.
+ */
+#define STEP(f, a, b, c, d, x, t, s) \
+ (a) += f((b), (c), (d)) + (x) + (t); \
+ (a) = (((a) << (s)) | (((a) & 0xffffffff) >> (32 - (s)))); \
+ (a) += (b);
+
+/*
+ * SET reads 4 input bytes in little-endian byte order and stores them in a
+ * properly aligned word in host byte order.
+ *
+ * The check for little-endian architectures that tolerate unaligned memory
+ * accesses is just an optimization. Nothing will break if it fails to detect
+ * a suitable architecture.
+ *
+ * Unfortunately, this optimization may be a C strict aliasing rules violation
+ * if the caller's data buffer has effective type that cannot be aliased by
+ * MD5_u32plus. In practice, this problem may occur if these MD5 routines are
+ * inlined into a calling function, or with future and dangerously advanced
+ * link-time optimizations. For the time being, keeping these MD5 routines in
+ * their own translation unit avoids the problem.
+ */
+#if defined(__i386__) || defined(__x86_64__) || defined(__vax__)
+#define SET(n) \
+ (*(const MD5_u32plus *)&ptr[(n) * 4])
+#define GET(n) \
+ SET(n)
+#else
+#define SET(n) \
+ (ctx->block[(n)] = \
+ (MD5_u32plus)ptr[(n) * 4] | \
+ ((MD5_u32plus)ptr[(n) * 4 + 1] << 8) | \
+ ((MD5_u32plus)ptr[(n) * 4 + 2] << 16) | \
+ ((MD5_u32plus)ptr[(n) * 4 + 3] << 24))
+#define GET(n) \
+ (ctx->block[(n)])
+#endif
- ctx->total = 0;
- ctx->buflen = 0;
+/*
+ * This processes one or more 64-byte data blocks, but does NOT update the bit
+ * counters. There are no alignment requirements.
+ */
+static const void *body(MD5_CTX *ctx, const void *data, unsigned long size)
+{
+ const unsigned char *ptr;
+ MD5_u32plus a, b, c, d;
+ MD5_u32plus saved_a, saved_b, saved_c, saved_d;
+
+ ptr = (const unsigned char *)data;
+
+ a = ctx->a;
+ b = ctx->b;
+ c = ctx->c;
+ d = ctx->d;
+
+ do {
+ saved_a = a;
+ saved_b = b;
+ saved_c = c;
+ saved_d = d;
+
+/* Round 1 */
+ STEP(F, a, b, c, d, SET(0), 0xd76aa478, 7)
+ STEP(F, d, a, b, c, SET(1), 0xe8c7b756, 12)
+ STEP(F, c, d, a, b, SET(2), 0x242070db, 17)
+ STEP(F, b, c, d, a, SET(3), 0xc1bdceee, 22)
+ STEP(F, a, b, c, d, SET(4), 0xf57c0faf, 7)
+ STEP(F, d, a, b, c, SET(5), 0x4787c62a, 12)
+ STEP(F, c, d, a, b, SET(6), 0xa8304613, 17)
+ STEP(F, b, c, d, a, SET(7), 0xfd469501, 22)
+ STEP(F, a, b, c, d, SET(8), 0x698098d8, 7)
+ STEP(F, d, a, b, c, SET(9), 0x8b44f7af, 12)
+ STEP(F, c, d, a, b, SET(10), 0xffff5bb1, 17)
+ STEP(F, b, c, d, a, SET(11), 0x895cd7be, 22)
+ STEP(F, a, b, c, d, SET(12), 0x6b901122, 7)
+ STEP(F, d, a, b, c, SET(13), 0xfd987193, 12)
+ STEP(F, c, d, a, b, SET(14), 0xa679438e, 17)
+ STEP(F, b, c, d, a, SET(15), 0x49b40821, 22)
+
+/* Round 2 */
+ STEP(G, a, b, c, d, GET(1), 0xf61e2562, 5)
+ STEP(G, d, a, b, c, GET(6), 0xc040b340, 9)
+ STEP(G, c, d, a, b, GET(11), 0x265e5a51, 14)
+ STEP(G, b, c, d, a, GET(0), 0xe9b6c7aa, 20)
+ STEP(G, a, b, c, d, GET(5), 0xd62f105d, 5)
+ STEP(G, d, a, b, c, GET(10), 0x02441453, 9)
+ STEP(G, c, d, a, b, GET(15), 0xd8a1e681, 14)
+ STEP(G, b, c, d, a, GET(4), 0xe7d3fbc8, 20)
+ STEP(G, a, b, c, d, GET(9), 0x21e1cde6, 5)
+ STEP(G, d, a, b, c, GET(14), 0xc33707d6, 9)
+ STEP(G, c, d, a, b, GET(3), 0xf4d50d87, 14)
+ STEP(G, b, c, d, a, GET(8), 0x455a14ed, 20)
+ STEP(G, a, b, c, d, GET(13), 0xa9e3e905, 5)
+ STEP(G, d, a, b, c, GET(2), 0xfcefa3f8, 9)
+ STEP(G, c, d, a, b, GET(7), 0x676f02d9, 14)
+ STEP(G, b, c, d, a, GET(12), 0x8d2a4c8a, 20)
+
+/* Round 3 */
+ STEP(H, a, b, c, d, GET(5), 0xfffa3942, 4)
+ STEP(H2, d, a, b, c, GET(8), 0x8771f681, 11)
+ STEP(H, c, d, a, b, GET(11), 0x6d9d6122, 16)
+ STEP(H2, b, c, d, a, GET(14), 0xfde5380c, 23)
+ STEP(H, a, b, c, d, GET(1), 0xa4beea44, 4)
+ STEP(H2, d, a, b, c, GET(4), 0x4bdecfa9, 11)
+ STEP(H, c, d, a, b, GET(7), 0xf6bb4b60, 16)
+ STEP(H2, b, c, d, a, GET(10), 0xbebfbc70, 23)
+ STEP(H, a, b, c, d, GET(13), 0x289b7ec6, 4)
+ STEP(H2, d, a, b, c, GET(0), 0xeaa127fa, 11)
+ STEP(H, c, d, a, b, GET(3), 0xd4ef3085, 16)
+ STEP(H2, b, c, d, a, GET(6), 0x04881d05, 23)
+ STEP(H, a, b, c, d, GET(9), 0xd9d4d039, 4)
+ STEP(H2, d, a, b, c, GET(12), 0xe6db99e5, 11)
+ STEP(H, c, d, a, b, GET(15), 0x1fa27cf8, 16)
+ STEP(H2, b, c, d, a, GET(2), 0xc4ac5665, 23)
+
+/* Round 4 */
+ STEP(I, a, b, c, d, GET(0), 0xf4292244, 6)
+ STEP(I, d, a, b, c, GET(7), 0x432aff97, 10)
+ STEP(I, c, d, a, b, GET(14), 0xab9423a7, 15)
+ STEP(I, b, c, d, a, GET(5), 0xfc93a039, 21)
+ STEP(I, a, b, c, d, GET(12), 0x655b59c3, 6)
+ STEP(I, d, a, b, c, GET(3), 0x8f0ccc92, 10)
+ STEP(I, c, d, a, b, GET(10), 0xffeff47d, 15)
+ STEP(I, b, c, d, a, GET(1), 0x85845dd1, 21)
+ STEP(I, a, b, c, d, GET(8), 0x6fa87e4f, 6)
+ STEP(I, d, a, b, c, GET(15), 0xfe2ce6e0, 10)
+ STEP(I, c, d, a, b, GET(6), 0xa3014314, 15)
+ STEP(I, b, c, d, a, GET(13), 0x4e0811a1, 21)
+ STEP(I, a, b, c, d, GET(4), 0xf7537e82, 6)
+ STEP(I, d, a, b, c, GET(11), 0xbd3af235, 10)
+ STEP(I, c, d, a, b, GET(2), 0x2ad7d2bb, 15)
+ STEP(I, b, c, d, a, GET(9), 0xeb86d391, 21)
+
+ a += saved_a;
+ b += saved_b;
+ c += saved_c;
+ d += saved_d;
+
+ ptr += 64;
+ } while (size -= 64);
+
+ ctx->a = a;
+ ctx->b = b;
+ ctx->c = c;
+ ctx->d = d;
+
+ return ptr;
}
-/* Put result from CTX in first 16 bytes following RESBUF. The result
- will be in little endian byte order. */
-static void *
-md5_read_ctx (struct md5_ctx *ctx, void *resbuf)
+void MD5_Init(MD5_CTX *ctx)
{
- unsigned char *buf = resbuf;
- cpu_to_le32 (buf + 0, ctx->A);
- cpu_to_le32 (buf + 4, ctx->B);
- cpu_to_le32 (buf + 8, ctx->C);
- cpu_to_le32 (buf + 12, ctx->D);
- XCRYPT_SECURE_MEMSET (ctx, sizeof(*ctx));
- return resbuf;
-}
+ ctx->a = 0x67452301;
+ ctx->b = 0xefcdab89;
+ ctx->c = 0x98badcfe;
+ ctx->d = 0x10325476;
-/* Process the remaining bytes in the internal buffer and the usual
- prolog according to the standard and write the result to RESBUF. */
+ ctx->lo = 0;
+ ctx->hi = 0;
+}
-void *
-md5_finish_ctx (struct md5_ctx *ctx, void *resbuf)
+void MD5_Update(MD5_CTX *ctx, const void *data, size_t size)
{
- /* Take yet unprocessed bytes into account. */
- uint32_t bytes = ctx->buflen;
- size_t pad;
+ MD5_u32plus saved_lo;
+ unsigned long used, available;
+
+ saved_lo = ctx->lo;
+ if ((ctx->lo = (saved_lo + size) & 0x1fffffff) < saved_lo)
+ ctx->hi++;
+ ctx->hi += (MD5_u32plus) size >> 29;
- /* Now count remaining bytes. */
- ctx->total += bytes;
+ used = saved_lo & 0x3f;
- pad = bytes >= 56 ? 64 + 56 - bytes : 56 - bytes;
+ if (used) {
+ available = 64 - used;
- /* The first byte of padding should be 0x80 and the rest should be
- zero. (RFC 1321, 3.1: Step 1) */
- ctx->buffer[bytes] = 0x80u;
- XCRYPT_SECURE_MEMSET (&ctx->buffer[bytes+1], pad-1);
+ if (size < available) {
+ memcpy(&ctx->buffer[used], data, size);
+ return;
+ }
- /* Put the 64-bit file length in little-endian *bits* at the end of
- the buffer. */
- cpu_to_le64 (&ctx->buffer[bytes + pad], ctx->total << 3);
+ memcpy(&ctx->buffer[used], data, available);
+ data = (const unsigned char *)data + available;
+ size -= available;
+ body(ctx, ctx->buffer, 64);
+ }
- /* Process last bytes. */
- md5_process_block (ctx->buffer, bytes + pad + 8, ctx);
+ if (size >= 64) {
+ data = body(ctx, data, size & ~(unsigned long)0x3f);
+ size &= 0x3f;
+ }
- return md5_read_ctx (ctx, resbuf);
+ memcpy(ctx->buffer, data, size);
}
+#define OUT(dst, src) \
+ (dst)[0] = (unsigned char)(src); \
+ (dst)[1] = (unsigned char)((src) >> 8); \
+ (dst)[2] = (unsigned char)((src) >> 16); \
+ (dst)[3] = (unsigned char)((src) >> 24);
-void
-md5_process_bytes (const void *buffer, size_t len, struct md5_ctx *ctx)
+void MD5_Final(uint8_t result[16], MD5_CTX *ctx)
{
- /* When we already have some bits in our internal buffer concatenate
- both inputs first. */
- if (ctx->buflen != 0)
- {
- uint32_t left_over = ctx->buflen;
- uint32_t add = 128 - left_over > len ? (uint32_t)len : 128 - left_over;
-
- memcpy (&ctx->buffer[left_over], buffer, add);
- ctx->buflen += add;
-
- if (ctx->buflen > 64)
- {
- md5_process_block (ctx->buffer, ctx->buflen & ~63u, ctx);
-
- ctx->buflen &= 63;
- /* The regions in the following copy operation cannot overlap. */
- memcpy (ctx->buffer, &ctx->buffer[(left_over + add) & ~63u],
- ctx->buflen);
- }
-
- buffer = (const char *) buffer + add;
- len -= add;
- }
-
- /* Process available complete blocks. */
- if (len > 64)
- {
- md5_process_block (buffer, len & ~63u, ctx);
- buffer = (const char *) buffer + (len & ~63u);
- len &= 63;
- }
-
- /* Move remaining bytes in internal buffer. */
- if (len > 0)
- {
- uint32_t left_over = ctx->buflen;
-
- memcpy (&ctx->buffer[left_over], buffer, len);
- left_over += (uint32_t)len;
- if (left_over >= 64)
- {
- md5_process_block (ctx->buffer, 64, ctx);
- left_over -= 64;
- memcpy (ctx->buffer, &ctx->buffer[64], left_over);
- }
- ctx->buflen = left_over;
- }
-}
+ unsigned long used, available;
+ used = ctx->lo & 0x3f;
-/* These are the four functions used in the four steps of the MD5 algorithm
- and defined in the RFC 1321. The first function is a little bit optimized
- (as found in Colin Plumbs public domain implementation). */
-/* #define FF(b, c, d) ((b & c) | (~b & d)) */
-#define FF(b, c, d) (d ^ (b & (c ^ d)))
-#define FG(b, c, d) FF (d, b, c)
-#define FH(b, c, d) (b ^ c ^ d)
-#define FI(b, c, d) (c ^ (b | ~d))
+ ctx->buffer[used++] = 0x80;
-/* Process LEN bytes of BUFFER, accumulating context into CTX.
- It is assumed that LEN % 64 == 0. */
+ available = 64 - used;
-static void
-md5_process_block (const void *buffer, size_t len, struct md5_ctx *ctx)
-{
- const unsigned char *p = buffer;
- const unsigned char *endp = p + len;
- uint32_t A = ctx->A;
- uint32_t B = ctx->B;
- uint32_t C = ctx->C;
- uint32_t D = ctx->D;
-
- /* First increment the byte count. RFC 1321 specifies the possible
- length of the file up to 2^64 bits. Here we only compute the
- number of bytes. */
- ctx->total += len;
-
- /* Process all bytes in the buffer with 64 bytes in each round of
- the loop. */
- while (p < endp)
- {
- uint32_t *cwp = ctx->correct_words;
- uint32_t A_save = A;
- uint32_t B_save = B;
- uint32_t C_save = C;
- uint32_t D_save = D;
-
- /* First round: using the given function, the context and a constant
- the next context is computed. Because the algorithms processing
- unit is a 32-bit word and it is determined to work on words in
- little endian byte order we perhaps have to change the byte order
- before the computation. To reduce the work for the next steps
- we store the swapped words in the array CORRECT_WORDS. */
-
-#define OP(a, b, c, d, s, T) \
- do \
- { \
- uint32_t word = le32_to_cpu (p); \
- p += 4; \
- *cwp++ = word; \
- a += FF (b, c, d) + word + T; \
- CYCLIC (a, s); \
- a += b; \
- } \
- while (0)
-
- /* It is unfortunate that C does not provide an operator for
- cyclic rotation. Hope the C compiler is smart enough. */
-#define CYCLIC(w, s) (w = (w << s) | (w >> (32 - s)))
-
- /* Before we start, one word to the strange constants.
- They are defined in RFC 1321 as
-
- T[i] = (int) (4294967296.0 * fabs (sin (i))), i=1..64
- */
-
- /* Round 1. */
- OP (A, B, C, D, 7, 0xd76aa478);
- OP (D, A, B, C, 12, 0xe8c7b756);
- OP (C, D, A, B, 17, 0x242070db);
- OP (B, C, D, A, 22, 0xc1bdceee);
- OP (A, B, C, D, 7, 0xf57c0faf);
- OP (D, A, B, C, 12, 0x4787c62a);
- OP (C, D, A, B, 17, 0xa8304613);
- OP (B, C, D, A, 22, 0xfd469501);
- OP (A, B, C, D, 7, 0x698098d8);
- OP (D, A, B, C, 12, 0x8b44f7af);
- OP (C, D, A, B, 17, 0xffff5bb1);
- OP (B, C, D, A, 22, 0x895cd7be);
- OP (A, B, C, D, 7, 0x6b901122);
- OP (D, A, B, C, 12, 0xfd987193);
- OP (C, D, A, B, 17, 0xa679438e);
- OP (B, C, D, A, 22, 0x49b40821);
-
- /* For the second to fourth round we have the possibly swapped words
- in CORRECT_WORDS. Redefine the macro to take an additional first
- argument specifying the function to use. */
-#undef OP
-#define OP(f, a, b, c, d, k, s, T) \
- do \
- { \
- a += f (b, c, d) + ctx->correct_words[k] + T; \
- CYCLIC (a, s); \
- a += b; \
- } \
- while (0)
-
- /* Round 2. */
- OP (FG, A, B, C, D, 1, 5, 0xf61e2562);
- OP (FG, D, A, B, C, 6, 9, 0xc040b340);
- OP (FG, C, D, A, B, 11, 14, 0x265e5a51);
- OP (FG, B, C, D, A, 0, 20, 0xe9b6c7aa);
- OP (FG, A, B, C, D, 5, 5, 0xd62f105d);
- OP (FG, D, A, B, C, 10, 9, 0x02441453);
- OP (FG, C, D, A, B, 15, 14, 0xd8a1e681);
- OP (FG, B, C, D, A, 4, 20, 0xe7d3fbc8);
- OP (FG, A, B, C, D, 9, 5, 0x21e1cde6);
- OP (FG, D, A, B, C, 14, 9, 0xc33707d6);
- OP (FG, C, D, A, B, 3, 14, 0xf4d50d87);
- OP (FG, B, C, D, A, 8, 20, 0x455a14ed);
- OP (FG, A, B, C, D, 13, 5, 0xa9e3e905);
- OP (FG, D, A, B, C, 2, 9, 0xfcefa3f8);
- OP (FG, C, D, A, B, 7, 14, 0x676f02d9);
- OP (FG, B, C, D, A, 12, 20, 0x8d2a4c8a);
-
- /* Round 3. */
- OP (FH, A, B, C, D, 5, 4, 0xfffa3942);
- OP (FH, D, A, B, C, 8, 11, 0x8771f681);
- OP (FH, C, D, A, B, 11, 16, 0x6d9d6122);
- OP (FH, B, C, D, A, 14, 23, 0xfde5380c);
- OP (FH, A, B, C, D, 1, 4, 0xa4beea44);
- OP (FH, D, A, B, C, 4, 11, 0x4bdecfa9);
- OP (FH, C, D, A, B, 7, 16, 0xf6bb4b60);
- OP (FH, B, C, D, A, 10, 23, 0xbebfbc70);
- OP (FH, A, B, C, D, 13, 4, 0x289b7ec6);
- OP (FH, D, A, B, C, 0, 11, 0xeaa127fa);
- OP (FH, C, D, A, B, 3, 16, 0xd4ef3085);
- OP (FH, B, C, D, A, 6, 23, 0x04881d05);
- OP (FH, A, B, C, D, 9, 4, 0xd9d4d039);
- OP (FH, D, A, B, C, 12, 11, 0xe6db99e5);
- OP (FH, C, D, A, B, 15, 16, 0x1fa27cf8);
- OP (FH, B, C, D, A, 2, 23, 0xc4ac5665);
-
- /* Round 4. */
- OP (FI, A, B, C, D, 0, 6, 0xf4292244);
- OP (FI, D, A, B, C, 7, 10, 0x432aff97);
- OP (FI, C, D, A, B, 14, 15, 0xab9423a7);
- OP (FI, B, C, D, A, 5, 21, 0xfc93a039);
- OP (FI, A, B, C, D, 12, 6, 0x655b59c3);
- OP (FI, D, A, B, C, 3, 10, 0x8f0ccc92);
- OP (FI, C, D, A, B, 10, 15, 0xffeff47d);
- OP (FI, B, C, D, A, 1, 21, 0x85845dd1);
- OP (FI, A, B, C, D, 8, 6, 0x6fa87e4f);
- OP (FI, D, A, B, C, 15, 10, 0xfe2ce6e0);
- OP (FI, C, D, A, B, 6, 15, 0xa3014314);
- OP (FI, B, C, D, A, 13, 21, 0x4e0811a1);
- OP (FI, A, B, C, D, 4, 6, 0xf7537e82);
- OP (FI, D, A, B, C, 11, 10, 0xbd3af235);
- OP (FI, C, D, A, B, 2, 15, 0x2ad7d2bb);
- OP (FI, B, C, D, A, 9, 21, 0xeb86d391);
-
- /* Add the starting values of the context. */
- A += A_save;
- B += B_save;
- C += C_save;
- D += D_save;
- }
-
- /* Put checksum in context given as argument. */
- ctx->A = A;
- ctx->B = B;
- ctx->C = C;
- ctx->D = D;
+ if (available < 8) {
+ XCRYPT_SECURE_MEMSET(&ctx->buffer[used], available);
+ body(ctx, ctx->buffer, 64);
+ used = 0;
+ available = 64;
+ }
+
+ XCRYPT_SECURE_MEMSET(&ctx->buffer[used], available - 8);
+
+ ctx->lo <<= 3;
+ OUT(&ctx->buffer[56], ctx->lo)
+ OUT(&ctx->buffer[60], ctx->hi)
+
+ body(ctx, ctx->buffer, 64);
+
+ OUT(&result[0], ctx->a)
+ OUT(&result[4], ctx->b)
+ OUT(&result[8], ctx->c)
+ OUT(&result[12], ctx->d)
+
+ XCRYPT_SECURE_MEMSET(ctx, sizeof(*ctx));
}
#endif
diff --git a/alg-md5.h b/alg-md5.h
index a56aba9..1947eb3 100644
--- a/alg-md5.h
+++ b/alg-md5.h
@@ -1,52 +1,43 @@
-/* Declaration of functions and data types used for MD5 sum computing
- library functions.
-
- Copyright (C) 1995-2017 Free Software Foundation, Inc.
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public License
- as published by the Free Software Foundation; either version 2.1 of
- the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, see
- <https://www.gnu.org/licenses/>. */
+/*
+ * This is an OpenSSL-compatible implementation of the RSA Data Security, Inc.
+ * MD5 Message-Digest Algorithm (RFC 1321).
+ *
+ * Homepage:
+ * http://openwall.info/wiki/people/solar/software/public-domain-source-code/md5
+ *
+ * Author:
+ * Alexander Peslyak, better known as Solar Designer <solar at openwall.com>
+ *
+ * This software was written by Alexander Peslyak in 2001. No copyright is
+ * claimed, and the software is hereby placed in the public domain.
+ * In case this attempt to disclaim copyright and place the software in the
+ * public domain is deemed null and void, then the software is
+ * Copyright (c) 2001 Alexander Peslyak and it is hereby released to the
+ * general public under the following terms:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted.
+ *
+ * There's ABSOLUTELY NO WARRANTY, express or implied.
+ *
+ * See md5.c for more information.
+ */
#ifndef _CRYPT_ALG_MD5_H
#define _CRYPT_ALG_MD5_H 1
-/* Structure to save state of computation between the single steps. */
-struct md5_ctx
-{
- uint32_t A;
- uint32_t B;
- uint32_t C;
- uint32_t D;
-
- uint64_t total;
- uint32_t buflen;
- uint32_t correct_words[16];
- unsigned char buffer[128];
-};
-
-/* Initialize structure containing state of computation.
- (RFC 1321, 3.3: Step 3) */
-extern void md5_init_ctx (struct md5_ctx *ctx);
+/* Any 32-bit or wider unsigned integer data type will do */
+typedef uint32_t MD5_u32plus;
-/* Starting with the result of former calls of this function (or the
- initialization function) update the context for the next LEN bytes
- starting at BUFFER. LEN does not need to be a multiple of 64. */
-extern void md5_process_bytes (const void *buffer, size_t len,
- struct md5_ctx *ctx);
+typedef struct {
+ MD5_u32plus lo, hi;
+ MD5_u32plus a, b, c, d;
+ uint8_t buffer[64];
+ MD5_u32plus block[16];
+} MD5_CTX;
-/* Process the remaining bytes in the buffer and write the finalized
- hash to RESBUF, which should point to 16 bytes of storage. All
- data written to CTX is erased before returning from the function. */
-extern void *md5_finish_ctx (struct md5_ctx *ctx, void *resbuf);
+extern void MD5_Init(MD5_CTX *ctx);
+extern void MD5_Update(MD5_CTX *ctx, const void *data, size_t size);
+extern void MD5_Final(uint8_t result[16], MD5_CTX *ctx);
#endif /* alg-md5.h */
diff --git a/crypt-md5.c b/crypt-md5.c
index f64b6fc..108c31c 100644
--- a/crypt-md5.c
+++ b/crypt-md5.c
@@ -50,7 +50,7 @@ static_assert (MD5_HASH_LENGTH <= CRYPT_OUTPUT_SIZE,
/* An md5_buffer holds all of the sensitive intermediate data. */
struct md5_buffer
{
- struct md5_ctx ctx;
+ MD5_CTX ctx;
uint8_t result[16];
};
@@ -74,7 +74,7 @@ crypt_md5_rn (const char *phrase, size_t phr_size,
}
struct md5_buffer *buf = scratch;
- struct md5_ctx *ctx = &buf->ctx;
+ MD5_CTX *ctx = &buf->ctx;
uint8_t *result = buf->result;
char *cp = (char *)output;
const char *salt = setting;
@@ -99,40 +99,40 @@ crypt_md5_rn (const char *phrase, size_t phr_size,
/* Compute alternate MD5 sum with input PHRASE, SALT, and PHRASE. The
final result will be added to the first context. */
- md5_init_ctx (ctx);
+ MD5_Init (ctx);
/* Add phrase. */
- md5_process_bytes (phrase, phr_size, ctx);
+ MD5_Update (ctx, phrase, phr_size);
/* Add salt. */
- md5_process_bytes (salt, salt_size, ctx);
+ MD5_Update (ctx, salt, salt_size);
/* Add phrase again. */
- md5_process_bytes (phrase, phr_size, ctx);
+ MD5_Update (ctx, phrase, phr_size);
/* Now get result of this (16 bytes). */
- md5_finish_ctx (ctx, result);
+ MD5_Final (result, ctx);
/* Prepare for the real work. */
- md5_init_ctx (ctx);
+ MD5_Init (ctx);
/* Add the phrase string. */
- md5_process_bytes (phrase, phr_size, ctx);
+ MD5_Update (ctx, phrase, phr_size);
/* Because the SALT argument need not always have the salt prefix we
add it separately. */
- md5_process_bytes (md5_salt_prefix, sizeof (md5_salt_prefix) - 1, ctx);
+ MD5_Update (ctx, md5_salt_prefix, sizeof (md5_salt_prefix) - 1);
/* The last part is the salt string. This must be at most 8
characters and it ends at the first `$' character (for
compatibility with existing implementations). */
- md5_process_bytes (salt, salt_size, ctx);
+ MD5_Update (ctx, salt, salt_size);
/* Add for any character in the phrase one byte of the alternate sum. */
for (cnt = phr_size; cnt > 16; cnt -= 16)
- md5_process_bytes (result, 16, ctx);
- md5_process_bytes (result, cnt, ctx);
+ MD5_Update (ctx, result, 16);
+ MD5_Update (ctx, result, cnt);
/* For the following code we need a NUL byte. */
*result = '\0';
@@ -142,11 +142,10 @@ crypt_md5_rn (const char *phrase, size_t phr_size,
bit the first character of the phrase. This does not seem to be
what was intended but we have to follow this to be compatible. */
for (cnt = phr_size; cnt > 0; cnt >>= 1)
- md5_process_bytes ((cnt & 1) != 0 ? (const char *) result : phrase, 1,
- ctx);
+ MD5_Update (ctx, (cnt & 1) != 0 ? (const char *) result : phrase, 1);
/* Create intermediate result. */
- md5_finish_ctx (ctx, result);
+ MD5_Final (result, ctx);
/* Now comes another weirdness. In fear of password crackers here
comes a quite long loop which just processes the output of the
@@ -154,30 +153,30 @@ crypt_md5_rn (const char *phrase, size_t phr_size,
for (cnt = 0; cnt < 1000; ++cnt)
{
/* New context. */
- md5_init_ctx (ctx);
+ MD5_Init (ctx);
/* Add phrase or last result. */
if ((cnt & 1) != 0)
- md5_process_bytes (phrase, phr_size, ctx);
+ MD5_Update (ctx, phrase, phr_size);
else
- md5_process_bytes (result, 16, ctx);
+ MD5_Update (ctx, result, 16);
/* Add salt for numbers not divisible by 3. */
if (cnt % 3 != 0)
- md5_process_bytes (salt, salt_size, ctx);
+ MD5_Update (ctx, salt, salt_size);
/* Add phrase for numbers not divisible by 7. */
if (cnt % 7 != 0)
- md5_process_bytes (phrase, phr_size, ctx);
+ MD5_Update (ctx, phrase, phr_size);
/* Add phrase or last result. */
if ((cnt & 1) != 0)
- md5_process_bytes (result, 16, ctx);
+ MD5_Update (ctx, result, 16);
else
- md5_process_bytes (phrase, phr_size, ctx);
+ MD5_Update (ctx, phrase, phr_size);
/* Create intermediate result. */
- md5_finish_ctx (ctx, result);
+ MD5_Final (result, ctx);
}
/* Now we can construct the result string. It consists of three
diff --git a/crypt-port.h b/crypt-port.h
index a2c64b3..2571c94 100644
--- a/crypt-port.h
+++ b/crypt-port.h
@@ -247,9 +247,9 @@ _xcrypt_strcpy_or_abort (void *dst, const size_t d_size,
#endif
#if INCLUDE_md5 || INCLUDE_sunmd5
-#define md5_finish_ctx _crypt_md5_finish_ctx
-#define md5_init_ctx _crypt_md5_init_ctx
-#define md5_process_bytes _crypt_md5_process_bytes
+#define MD5_Init _crypt_MD5_Init
+#define MD5_Update _crypt_MD5_Update
+#define MD5_Final _crypt_MD5_Final
#endif
#if INCLUDE_sha1
diff --git a/crypt-sunmd5.c b/crypt-sunmd5.c
index 9f76ed1..7a30aae 100644
--- a/crypt-sunmd5.c
+++ b/crypt-sunmd5.c
@@ -165,7 +165,7 @@ crypt_sunmd5_rn (const char *phrase, size_t phr_size,
{
struct crypt_sunmd5_scratch
{
- struct md5_ctx ctx;
+ MD5_CTX ctx;
uint8_t dg[16];
char rn[16];
};
@@ -238,27 +238,27 @@ crypt_sunmd5_rn (const char *phrase, size_t phr_size,
struct crypt_sunmd5_scratch *s = scratch;
/* Initial round. */
- md5_init_ctx (&s->ctx);
- md5_process_bytes (phrase, phr_size, &s->ctx);
- md5_process_bytes (setting, saltlen, &s->ctx);
- md5_finish_ctx (&s->ctx, s->dg);
+ MD5_Init (&s->ctx);
+ MD5_Update (&s->ctx, phrase, phr_size);
+ MD5_Update (&s->ctx, setting, saltlen);
+ MD5_Final (s->dg, &s->ctx);
/* Stretching rounds. */
for (unsigned int i = 0; i < nrounds; i++)
{
- md5_init_ctx (&s->ctx);
+ MD5_Init (&s->ctx);
- md5_process_bytes (s->dg, sizeof s->dg, &s->ctx);
+ MD5_Update (&s->ctx, s->dg, sizeof s->dg);
/* The trailing nul is intentionally included. */
if (muffet_coin_toss (s->dg, i))
- md5_process_bytes (hamlet_quotation, sizeof hamlet_quotation, &s->ctx);
+ MD5_Update (&s->ctx, hamlet_quotation, sizeof hamlet_quotation);
int nwritten = snprintf (s->rn, sizeof s->rn, "%u", i);
assert (nwritten >= 1 && (unsigned int)nwritten + 1 <= sizeof s->rn);
- md5_process_bytes (s->rn, (unsigned int)nwritten, &s->ctx);
+ MD5_Update (&s->ctx, s->rn, (unsigned int)nwritten);
- md5_finish_ctx (&s->ctx, s->dg);
+ MD5_Final (s->dg, &s->ctx);
}
memcpy (output, setting, saltlen);
diff --git a/test-alg-md5.c b/test-alg-md5.c
index dabc6ba..21c4309 100644
--- a/test-alg-md5.c
+++ b/test-alg-md5.c
@@ -52,7 +52,7 @@ static const struct
static void
report_failure(int n, const char *tag,
- const char expected[16], const char actual[16])
+ const char expected[16], uint8_t actual[16])
{
int i;
printf ("FAIL: test %d (%s):\n exp:", n, tag);
@@ -76,27 +76,27 @@ report_failure(int n, const char *tag,
int
main (void)
{
- struct md5_ctx ctx;
- char sum[16];
+ MD5_CTX ctx;
+ uint8_t sum[16];
int result = 0;
int cnt;
int i;
for (cnt = 0; cnt < (int) ARRAY_SIZE (tests); ++cnt)
{
- md5_init_ctx (&ctx);
- md5_process_bytes (tests[cnt].input, strlen (tests[cnt].input), &ctx);
- md5_finish_ctx (&ctx, sum);
+ MD5_Init (&ctx);
+ MD5_Update (&ctx, tests[cnt].input, strlen (tests[cnt].input));
+ MD5_Final (sum, &ctx);
if (memcmp (tests[cnt].result, sum, 16))
{
report_failure (cnt, "all at once", tests[cnt].result, sum);
result = 1;
}
- md5_init_ctx (&ctx);
+ MD5_Init (&ctx);
for (i = 0; tests[cnt].input[i] != '\0'; ++i)
- md5_process_bytes (&tests[cnt].input[i], 1, &ctx);
- md5_finish_ctx (&ctx, sum);
+ MD5_Update (&ctx, &tests[cnt].input[i], 1);
+ MD5_Final (sum, &ctx);
if (memcmp (tests[cnt].result, sum, 16))
{
report_failure (cnt, "byte by byte", tests[cnt].result, sum);
@@ -108,10 +108,10 @@ main (void)
<https://www.nist.gov/itl/ssd/software-quality-group/nsrl-test-data>. */
char buf[1000];
memset (buf, 'a', sizeof (buf));
- md5_init_ctx (&ctx);
+ MD5_Init (&ctx);
for (i = 0; i < 1000; ++i)
- md5_process_bytes (buf, sizeof (buf), &ctx);
- md5_finish_ctx (&ctx, sum);
+ MD5_Update (&ctx, buf, sizeof (buf));
+ MD5_Final (sum, &ctx);
static const char expected[64] =
"\x77\x07\xd6\xae\x4e\x02\x7c\x70\xee\xa2\xa9\x35\xc2\x29\x6f\x21";
if (memcmp (expected, sum, 16) != 0)
From 6fcd7eb3324b67b22b39626cf587013437707efc Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bj=C3=B6rn=20Esser?= <besser82@fedoraproject.org>
Date: Mon, 22 Oct 2018 14:16:22 +0200
Subject: [PATCH 11/17] Use unmodified md4 implementation from Alexander
Peslyak.
---
alg-md4.c | 428 +++++++++++++++++++++++++------------------------
alg-md4.h | 61 +++----
crypt-nthash.c | 24 +--
crypt-port.h | 6 +-
test-alg-md4.c | 18 +--
5 files changed, 278 insertions(+), 259 deletions(-)
diff --git a/alg-md4.c b/alg-md4.c
index c1c4075..482b6f4 100644
--- a/alg-md4.c
+++ b/alg-md4.c
@@ -1,256 +1,270 @@
/*
- * MD4 (RFC-1320) message digest.
- * Modified from MD5 code by Andrey Panin <pazke@donpac.ru>
+ * This is an OpenSSL-compatible implementation of the RSA Data Security, Inc.
+ * MD4 Message-Digest Algorithm (RFC 1320).
*
- * Written by Solar Designer <solar@openwall.com> in 2001, and placed in
- * the public domain. There's absolutely no warranty.
+ * Homepage:
+ * http://openwall.info/wiki/people/solar/software/public-domain-source-code/md4
*
- * This differs from Colin Plumb's older public domain implementation in
- * that no 32-bit integer data type is required, there's no compile-time
- * endianness configuration.
- * The primary goals are portability and ease of use.
+ * Author:
+ * Alexander Peslyak, better known as Solar Designer <solar at openwall.com>
*
- * This implementation is meant to be fast, but not as fast as possible.
- * Some known optimizations are not included to reduce source code size
- * and avoid compile-time configuration.
+ * This software was written by Alexander Peslyak in 2001. No copyright is
+ * claimed, and the software is hereby placed in the public domain.
+ * In case this attempt to disclaim copyright and place the software in the
+ * public domain is deemed null and void, then the software is
+ * Copyright (c) 2001 Alexander Peslyak and it is hereby released to the
+ * general public under the following terms:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted.
+ *
+ * There's ABSOLUTELY NO WARRANTY, express or implied.
+ *
+ * (This is a heavily cut-down "BSD license".)
+ *
+ * This differs from Colin Plumb's older public domain implementation in that
+ * no exactly 32-bit integer data type is required (any 32-bit or wider
+ * unsigned integer data type will do), there's no compile-time endianness
+ * configuration, and the function prototypes match OpenSSL's. No code from
+ * Colin Plumb's implementation has been reused; this comment merely compares
+ * the properties of the two independent implementations.
+ *
+ * The primary goals of this implementation are portability and ease of use.
+ * It is meant to be fast, but not as fast as possible. Some known
+ * optimizations are not included to reduce source code size and avoid
+ * compile-time configuration.
*/
#include "crypt-port.h"
-#include "alg-md4.h"
-#include "byteorder.h"
#if INCLUDE_nthash
+#include "alg-md4.h"
+
/*
* The basic MD4 functions.
+ *
+ * F and G are optimized compared to their RFC 1320 definitions, with the
+ * optimization for F borrowed from Colin Plumb's MD5 implementation.
*/
-#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
-#define G(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z)))
-#define H(x, y, z) ((x) ^ (y) ^ (z))
+#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
+#define G(x, y, z) (((x) & ((y) | (z))) | ((y) & (z)))
+#define H(x, y, z) ((x) ^ (y) ^ (z))
/*
- * The MD4 transformation for all four rounds.
+ * The MD4 transformation for all three rounds.
*/
#define STEP(f, a, b, c, d, x, s) \
- (a) += f((b), (c), (d)) + (x); \
- (a) = ((a) << (s)) | ((a) >> (32 - (s)))
+ (a) += f((b), (c), (d)) + (x); \
+ (a) = (((a) << (s)) | (((a) & 0xffffffff) >> (32 - (s))));
/*
- * SET reads 4 input bytes in little-endian byte order and stores them
- * in a properly aligned word in host byte order.
+ * SET reads 4 input bytes in little-endian byte order and stores them in a
+ * properly aligned word in host byte order.
*
- * The check for little-endian architectures which tolerate unaligned
- * memory accesses is just an optimization. Nothing will break if it
- * doesn't work.
+ * The check for little-endian architectures that tolerate unaligned memory
+ * accesses is just an optimization. Nothing will break if it fails to detect
+ * a suitable architecture.
+ *
+ * Unfortunately, this optimization may be a C strict aliasing rules violation
+ * if the caller's data buffer has effective type that cannot be aliased by
+ * MD4_u32plus. In practice, this problem may occur if these MD4 routines are
+ * inlined into a calling function, or with future and dangerously advanced
+ * link-time optimizations. For the time being, keeping these MD4 routines in
+ * their own translation unit avoids the problem.
*/
+#if defined(__i386__) || defined(__x86_64__) || defined(__vax__)
+#define SET(n) \
+ (*(const MD4_u32plus *)&ptr[(n) * 4])
+#define GET(n) \
+ SET(n)
+#else
#define SET(n) \
- (ctx->block[(n)] = le32_to_cpu (&ptr[(n) * 4]))
+ (ctx->block[(n)] = \
+ (MD4_u32plus)ptr[(n) * 4] | \
+ ((MD4_u32plus)ptr[(n) * 4 + 1] << 8) | \
+ ((MD4_u32plus)ptr[(n) * 4 + 2] << 16) | \
+ ((MD4_u32plus)ptr[(n) * 4 + 3] << 24))
#define GET(n) \
- (ctx->block[(n)])
+ (ctx->block[(n)])
+#endif
/*
- * This processes one or more 64-byte data blocks, but does NOT update
- * the bit counters. There're no alignment requirements.
+ * This processes one or more 64-byte data blocks, but does NOT update the bit
+ * counters. There are no alignment requirements.
*/
-static const unsigned char *
-body (struct md4_ctx *ctx, const unsigned char *data, size_t size)
+static const void *body(MD4_CTX *ctx, const void *data, unsigned long size)
{
- const unsigned char *ptr;
- uint32_t a, b, c, d;
- uint32_t saved_a, saved_b, saved_c, saved_d;
-
- ptr = data;
-
- a = ctx->a;
- b = ctx->b;
- c = ctx->c;
- d = ctx->d;
-
- do
- {
- saved_a = a;
- saved_b = b;
- saved_c = c;
- saved_d = d;
-
- /* Round 1 */
- STEP(F, a, b, c, d, SET( 0), 3);
- STEP(F, d, a, b, c, SET( 1), 7);
- STEP(F, c, d, a, b, SET( 2), 11);
- STEP(F, b, c, d, a, SET( 3), 19);
-
- STEP(F, a, b, c, d, SET( 4), 3);
- STEP(F, d, a, b, c, SET( 5), 7);
- STEP(F, c, d, a, b, SET( 6), 11);
- STEP(F, b, c, d, a, SET( 7), 19);
-
- STEP(F, a, b, c, d, SET( 8), 3);
- STEP(F, d, a, b, c, SET( 9), 7);
- STEP(F, c, d, a, b, SET(10), 11);
- STEP(F, b, c, d, a, SET(11), 19);
-
- STEP(F, a, b, c, d, SET(12), 3);
- STEP(F, d, a, b, c, SET(13), 7);
- STEP(F, c, d, a, b, SET(14), 11);
- STEP(F, b, c, d, a, SET(15), 19);
-
- /* Round 2 */
- STEP(G, a, b, c, d, GET( 0) + 0x5A827999, 3);
- STEP(G, d, a, b, c, GET( 4) + 0x5A827999, 5);
- STEP(G, c, d, a, b, GET( 8) + 0x5A827999, 9);
- STEP(G, b, c, d, a, GET(12) + 0x5A827999, 13);
-
- STEP(G, a, b, c, d, GET( 1) + 0x5A827999, 3);
- STEP(G, d, a, b, c, GET( 5) + 0x5A827999, 5);
- STEP(G, c, d, a, b, GET( 9) + 0x5A827999, 9);
- STEP(G, b, c, d, a, GET(13) + 0x5A827999, 13);
-
- STEP(G, a, b, c, d, GET( 2) + 0x5A827999, 3);
- STEP(G, d, a, b, c, GET( 6) + 0x5A827999, 5);
- STEP(G, c, d, a, b, GET(10) + 0x5A827999, 9);
- STEP(G, b, c, d, a, GET(14) + 0x5A827999, 13);
-
- STEP(G, a, b, c, d, GET( 3) + 0x5A827999, 3);
- STEP(G, d, a, b, c, GET( 7) + 0x5A827999, 5);
- STEP(G, c, d, a, b, GET(11) + 0x5A827999, 9);
- STEP(G, b, c, d, a, GET(15) + 0x5A827999, 13);
-
- /* Round 3 */
- STEP(H, a, b, c, d, GET( 0) + 0x6ED9EBA1, 3);
- STEP(H, d, a, b, c, GET( 8) + 0x6ED9EBA1, 9);
- STEP(H, c, d, a, b, GET( 4) + 0x6ED9EBA1, 11);
- STEP(H, b, c, d, a, GET(12) + 0x6ED9EBA1, 15);
-
- STEP(H, a, b, c, d, GET( 2) + 0x6ED9EBA1, 3);
- STEP(H, d, a, b, c, GET(10) + 0x6ED9EBA1, 9);
- STEP(H, c, d, a, b, GET( 6) + 0x6ED9EBA1, 11);
- STEP(H, b, c, d, a, GET(14) + 0x6ED9EBA1, 15);
-
- STEP(H, a, b, c, d, GET( 1) + 0x6ED9EBA1, 3);
- STEP(H, d, a, b, c, GET( 9) + 0x6ED9EBA1, 9);
- STEP(H, c, d, a, b, GET( 5) + 0x6ED9EBA1, 11);
- STEP(H, b, c, d, a, GET(13) + 0x6ED9EBA1, 15);
-
- STEP(H, a, b, c, d, GET( 3) + 0x6ED9EBA1, 3);
- STEP(H, d, a, b, c, GET(11) + 0x6ED9EBA1, 9);
- STEP(H, c, d, a, b, GET( 7) + 0x6ED9EBA1, 11);
- STEP(H, b, c, d, a, GET(15) + 0x6ED9EBA1, 15);
-
- a += saved_a;
- b += saved_b;
- c += saved_c;
- d += saved_d;
-
- ptr += 64;
- }
- while (size -= 64);
-
- ctx->a = a;
- ctx->b = b;
- ctx->c = c;
- ctx->d = d;
-
- return ptr;
+ const unsigned char *ptr;
+ MD4_u32plus a, b, c, d;
+ MD4_u32plus saved_a, saved_b, saved_c, saved_d;
+ const MD4_u32plus ac1 = 0x5a827999, ac2 = 0x6ed9eba1;
+
+ ptr = (const unsigned char *)data;
+
+ a = ctx->a;
+ b = ctx->b;
+ c = ctx->c;
+ d = ctx->d;
+
+ do {
+ saved_a = a;
+ saved_b = b;
+ saved_c = c;
+ saved_d = d;
+
+/* Round 1 */
+ STEP(F, a, b, c, d, SET(0), 3)
+ STEP(F, d, a, b, c, SET(1), 7)
+ STEP(F, c, d, a, b, SET(2), 11)
+ STEP(F, b, c, d, a, SET(3), 19)
+ STEP(F, a, b, c, d, SET(4), 3)
+ STEP(F, d, a, b, c, SET(5), 7)
+ STEP(F, c, d, a, b, SET(6), 11)
+ STEP(F, b, c, d, a, SET(7), 19)
+ STEP(F, a, b, c, d, SET(8), 3)
+ STEP(F, d, a, b, c, SET(9), 7)
+ STEP(F, c, d, a, b, SET(10), 11)
+ STEP(F, b, c, d, a, SET(11), 19)
+ STEP(F, a, b, c, d, SET(12), 3)
+ STEP(F, d, a, b, c, SET(13), 7)
+ STEP(F, c, d, a, b, SET(14), 11)
+ STEP(F, b, c, d, a, SET(15), 19)
+
+/* Round 2 */
+ STEP(G, a, b, c, d, GET(0) + ac1, 3)
+ STEP(G, d, a, b, c, GET(4) + ac1, 5)
+ STEP(G, c, d, a, b, GET(8) + ac1, 9)
+ STEP(G, b, c, d, a, GET(12) + ac1, 13)
+ STEP(G, a, b, c, d, GET(1) + ac1, 3)
+ STEP(G, d, a, b, c, GET(5) + ac1, 5)
+ STEP(G, c, d, a, b, GET(9) + ac1, 9)
+ STEP(G, b, c, d, a, GET(13) + ac1, 13)
+ STEP(G, a, b, c, d, GET(2) + ac1, 3)
+ STEP(G, d, a, b, c, GET(6) + ac1, 5)
+ STEP(G, c, d, a, b, GET(10) + ac1, 9)
+ STEP(G, b, c, d, a, GET(14) + ac1, 13)
+ STEP(G, a, b, c, d, GET(3) + ac1, 3)
+ STEP(G, d, a, b, c, GET(7) + ac1, 5)
+ STEP(G, c, d, a, b, GET(11) + ac1, 9)
+ STEP(G, b, c, d, a, GET(15) + ac1, 13)
+
+/* Round 3 */
+ STEP(H, a, b, c, d, GET(0) + ac2, 3)
+ STEP(H, d, a, b, c, GET(8) + ac2, 9)
+ STEP(H, c, d, a, b, GET(4) + ac2, 11)
+ STEP(H, b, c, d, a, GET(12) + ac2, 15)
+ STEP(H, a, b, c, d, GET(2) + ac2, 3)
+ STEP(H, d, a, b, c, GET(10) + ac2, 9)
+ STEP(H, c, d, a, b, GET(6) + ac2, 11)
+ STEP(H, b, c, d, a, GET(14) + ac2, 15)
+ STEP(H, a, b, c, d, GET(1) + ac2, 3)
+ STEP(H, d, a, b, c, GET(9) + ac2, 9)
+ STEP(H, c, d, a, b, GET(5) + ac2, 11)
+ STEP(H, b, c, d, a, GET(13) + ac2, 15)
+ STEP(H, a, b, c, d, GET(3) + ac2, 3)
+ STEP(H, d, a, b, c, GET(11) + ac2, 9)
+ STEP(H, c, d, a, b, GET(7) + ac2, 11)
+ STEP(H, b, c, d, a, GET(15) + ac2, 15)
+
+ a += saved_a;
+ b += saved_b;
+ c += saved_c;
+ d += saved_d;
+
+ ptr += 64;
+ } while (size -= 64);
+
+ ctx->a = a;
+ ctx->b = b;
+ ctx->c = c;
+ ctx->d = d;
+
+ return ptr;
}
-/* Put result from CTX in first 16 bytes following RESBUF. The result
- will be in little endian byte order. */
-static void *
-md4_read_ctx (struct md4_ctx *ctx, void *resbuf)
+void MD4_Init(MD4_CTX *ctx)
{
- unsigned char *buf = resbuf;
- cpu_to_le32 (buf + 0, ctx->a);
- cpu_to_le32 (buf + 4, ctx->b);
- cpu_to_le32 (buf + 8, ctx->c);
- cpu_to_le32 (buf + 12, ctx->d);
- XCRYPT_SECURE_MEMSET (ctx, sizeof(struct md4_ctx));
- return resbuf;
+ ctx->a = 0x67452301;
+ ctx->b = 0xefcdab89;
+ ctx->c = 0x98badcfe;
+ ctx->d = 0x10325476;
+
+ ctx->lo = 0;
+ ctx->hi = 0;
}
-void
-md4_init_ctx (struct md4_ctx *ctx)
+void MD4_Update(MD4_CTX *ctx, const void *data, size_t size)
{
- ctx->a = 0x67452301;
- ctx->b = 0xefcdab89;
- ctx->c = 0x98badcfe;
- ctx->d = 0x10325476;
+ MD4_u32plus saved_lo;
+ unsigned long used, available;
- ctx->lo = 0;
- ctx->hi = 0;
-}
+ saved_lo = ctx->lo;
+ if ((ctx->lo = (saved_lo + size) & 0x1fffffff) < saved_lo)
+ ctx->hi++;
+ ctx->hi += (MD4_u32plus) size >> 29;
-void
-md4_process_bytes (const void *buffer, struct md4_ctx *ctx, size_t size)
-{
- uint32_t saved_lo;
- size_t used, free;
-
- saved_lo = ctx->lo;
- if ((ctx->lo = (saved_lo + size) & 0x1fffffff) < saved_lo)
- ctx->hi++;
- ctx->hi += (uint32_t)(size >> 29);
-
- used = saved_lo & 0x3f;
-
- if (used)
- {
- free = 64 - used;
-
- if (size < free)
- {
- memcpy(&ctx->buffer[used], buffer, size);
- return;
- }
-
- memcpy(&ctx->buffer[used], buffer, free);
- buffer = (const unsigned char *) buffer + free;
- size -= free;
- body(ctx, ctx->buffer, 64);
- }
-
- if (size >= 64)
- {
- buffer = body(ctx, buffer, size & ~(uint32_t)0x3f);
- size &= 0x3f;
- }
-
- memcpy(ctx->buffer, buffer, size);
+ used = saved_lo & 0x3f;
+
+ if (used) {
+ available = 64 - used;
+
+ if (size < available) {
+ memcpy(&ctx->buffer[used], data, size);
+ return;
+ }
+
+ memcpy(&ctx->buffer[used], data, available);
+ data = (const unsigned char *)data + available;
+ size -= available;
+ body(ctx, ctx->buffer, 64);
+ }
+
+ if (size >= 64) {
+ data = body(ctx, data, size & ~(unsigned long)0x3f);
+ size &= 0x3f;
+ }
+
+ memcpy(ctx->buffer, data, size);
}
-void *
-md4_finish_ctx (struct md4_ctx *ctx, void *resbuf)
+#define OUT(dst, src) \
+ (dst)[0] = (unsigned char)(src); \
+ (dst)[1] = (unsigned char)((src) >> 8); \
+ (dst)[2] = (unsigned char)((src) >> 16); \
+ (dst)[3] = (unsigned char)((src) >> 24);
+
+void MD4_Final(uint8_t result[16], MD4_CTX *ctx)
{
- size_t used, free;
+ unsigned long used, available;
+
+ used = ctx->lo & 0x3f;
- used = ctx->lo & 0x3f;
+ ctx->buffer[used++] = 0x80;
- ctx->buffer[used++] = 0x80;
+ available = 64 - used;
- free = 64 - used;
+ if (available < 8) {
+ XCRYPT_SECURE_MEMSET(&ctx->buffer[used], available);
+ body(ctx, ctx->buffer, 64);
+ used = 0;
+ available = 64;
+ }
- if (free < 8)
- {
- XCRYPT_SECURE_MEMSET (&ctx->buffer[used], free);
- body(ctx, ctx->buffer, 64);
- used = 0;
- free = 64;
- }
+ XCRYPT_SECURE_MEMSET(&ctx->buffer[used], available - 8);
- XCRYPT_SECURE_MEMSET (&ctx->buffer[used], free - 8);
+ ctx->lo <<= 3;
+ OUT(&ctx->buffer[56], ctx->lo)
+ OUT(&ctx->buffer[60], ctx->hi)
- ctx->lo <<= 3;
- ctx->buffer[56] = (unsigned char)((ctx->lo) & 0xff);
- ctx->buffer[57] = (unsigned char)((ctx->lo >> 8) & 0xff);
- ctx->buffer[58] = (unsigned char)((ctx->lo >> 16) & 0xff);
- ctx->buffer[59] = (unsigned char)((ctx->lo >> 24) & 0xff);
- ctx->buffer[60] = (unsigned char)((ctx->hi) & 0xff);
- ctx->buffer[61] = (unsigned char)((ctx->hi >> 8) & 0xff);
- ctx->buffer[62] = (unsigned char)((ctx->hi >> 16) & 0xff);
- ctx->buffer[63] = (unsigned char)((ctx->hi >> 24) & 0xff);
+ body(ctx, ctx->buffer, 64);
- body(ctx, ctx->buffer, 64);
+ OUT(&result[0], ctx->a)
+ OUT(&result[4], ctx->b)
+ OUT(&result[8], ctx->c)
+ OUT(&result[12], ctx->d)
- return md4_read_ctx (ctx, resbuf);
+ XCRYPT_SECURE_MEMSET(ctx, sizeof(*ctx));
}
#endif
diff --git a/alg-md4.h b/alg-md4.h
index 4c3e29c..473930e 100644
--- a/alg-md4.h
+++ b/alg-md4.h
@@ -1,38 +1,43 @@
/*
- * This is an implementation of the RSA Data Security, Inc.
- * MD4 Message-Digest Algorithm.
+ * This is an OpenSSL-compatible implementation of the RSA Data Security, Inc.
+ * MD4 Message-Digest Algorithm (RFC 1320).
*
- * Written by Solar Designer <solar@openwall.com> in 2001, and placed in
- * the public domain. See md4.c for more information.
+ * Homepage:
+ * http://openwall.info/wiki/people/solar/software/public-domain-source-code/md4
+ *
+ * Author:
+ * Alexander Peslyak, better known as Solar Designer <solar at openwall.com>
+ *
+ * This software was written by Alexander Peslyak in 2001. No copyright is
+ * claimed, and the software is hereby placed in the public domain.
+ * In case this attempt to disclaim copyright and place the software in the
+ * public domain is deemed null and void, then the software is
+ * Copyright (c) 2001 Alexander Peslyak and it is hereby released to the
+ * general public under the following terms:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted.
+ *
+ * There's ABSOLUTELY NO WARRANTY, express or implied.
+ *
+ * See md4.c for more information.
*/
#ifndef _CRYPT_ALG_MD4_H
#define _CRYPT_ALG_MD4_H 1
-#include <stddef.h>
-#include <stdint.h>
-
-/* Structure to save state of computation between the single steps. */
-struct md4_ctx
-{
- uint32_t lo, hi;
- uint32_t a, b, c, d;
- unsigned char buffer[64];
- uint32_t block[16];
-};
-
-/* Initialize structure containing state of computation.
- (RFC 1320, 3.3: Step 3) */
-extern void md4_init_ctx (struct md4_ctx *ctx);
+/* Any 32-bit or wider unsigned integer data type will do */
+typedef uint32_t MD4_u32plus;
-/* Starting with the result of former calls of this function (or the
- initialization function) update the context for the next LEN bytes
- starting at BUFFER. LEN does not need to be a multiple of 64. */
-extern void md4_process_bytes (const void *buffer, struct md4_ctx *ctx, size_t size);
+typedef struct {
+ MD4_u32plus lo, hi;
+ MD4_u32plus a, b, c, d;
+ uint8_t buffer[64];
+ MD4_u32plus block[16];
+} MD4_CTX;
-/* Process the remaining bytes in the buffer and write the finalized
- hash to RESBUF, which should point to 16 bytes of storage. All
- data written to CTX is erased before returning from the function. */
-extern void *md4_finish_ctx (struct md4_ctx *ctx, void *resbuf);
+extern void MD4_Init(MD4_CTX *ctx);
+extern void MD4_Update(MD4_CTX *ctx, const void *data, size_t size);
+extern void MD4_Final(uint8_t result[16], MD4_CTX *ctx);
-#endif
+#endif /* alg-md4.h */
diff --git a/crypt-nthash.c b/crypt-nthash.c
index 5a715de..db6f17e 100644
--- a/crypt-nthash.c
+++ b/crypt-nthash.c
@@ -61,10 +61,10 @@ crypt_nthash_rn (const char *phrase, size_t ARG_UNUSED (phr_size),
uint16_t unipw[128];
unsigned char hash[16];
const char *s;
- struct md4_ctx *ctx = scratch;
+ MD4_CTX *ctx = scratch;
if ((out_size < 4 + 32) ||
- (scr_size < sizeof (struct md4_ctx)))
+ (scr_size < sizeof (MD4_CTX)))
{
errno = ERANGE;
return;
@@ -83,9 +83,9 @@ crypt_nthash_rn (const char *phrase, size_t ARG_UNUSED (phr_size),
unipw[unipwLen++] = htons((uint16_t)(*s << 8));
/* Compute MD4 of Unicode password */
- md4_init_ctx (ctx);
- md4_process_bytes ((unsigned char *)unipw, ctx, unipwLen*sizeof(uint16_t));
- md4_finish_ctx (ctx, hash);
+ MD4_Init (ctx);
+ MD4_Update (ctx, unipw, unipwLen*sizeof(uint16_t));
+ MD4_Final (hash, ctx);
output = (uint8_t *)stpcpy ((char *)output, magic);
*output++ = '$';
@@ -111,7 +111,7 @@ gensalt_nthash_rn (unsigned long count,
size_t o_size)
{
static const char *salt = "$3$__not_used__";
- struct md4_ctx ctx;
+ MD4_CTX ctx;
unsigned char hashbuf[16];
char hashstr[14 + 1];
unsigned long i;
@@ -131,15 +131,15 @@ gensalt_nthash_rn (unsigned long count,
return;
}
- md4_init_ctx (&ctx);
+ MD4_Init (&ctx);
for (i = 0; i < 20; i++)
{
- md4_process_bytes (salt, &ctx, (i % 15) + 1);
- md4_process_bytes (rbytes, &ctx, nrbytes);
- md4_process_bytes (salt, &ctx, 15);
- md4_process_bytes (salt, &ctx, 15 - (i % 15));
+ MD4_Update (&ctx, salt, (i % 15) + 1);
+ MD4_Update (&ctx, rbytes, nrbytes);
+ MD4_Update (&ctx, salt, 15);
+ MD4_Update (&ctx, salt, 15 - (i % 15));
}
- md4_finish_ctx (&ctx, &hashbuf);
+ MD4_Final (hashbuf, &ctx);
for (i = 0; i < 7; i++)
sprintf (&(hashstr[i * 2]), "%02x", hashbuf[i]);
diff --git a/crypt-port.h b/crypt-port.h
index 2571c94..fa30e8e 100644
--- a/crypt-port.h
+++ b/crypt-port.h
@@ -241,9 +241,9 @@ _xcrypt_strcpy_or_abort (void *dst, const size_t d_size,
#endif
#if INCLUDE_nthash
-#define md4_finish_ctx _crypt_md4_finish_ctx
-#define md4_init_ctx _crypt_md4_init_ctx
-#define md4_process_bytes _crypt_md4_process_bytes
+#define MD4_Init _crypt_MD4_Init
+#define MD4_Update _crypt_MD4_Update
+#define MD4_Final _crypt_MD4_Final
#endif
#if INCLUDE_md5 || INCLUDE_sunmd5
diff --git a/test-alg-md4.c b/test-alg-md4.c
index 1b1b828..595e0bb 100644
--- a/test-alg-md4.c
+++ b/test-alg-md4.c
@@ -45,7 +45,7 @@ static const struct
static void
report_failure(int n, const char *tag,
- const char expected[16], const char actual[16])
+ const char expected[16], uint8_t actual[16])
{
int i;
printf ("FAIL: test %d (%s):\n exp:", n, tag);
@@ -69,27 +69,27 @@ report_failure(int n, const char *tag,
int
main (void)
{
- struct md4_ctx ctx;
- char sum[16];
+ MD4_CTX ctx;
+ uint8_t sum[16];
int result = 0;
int cnt;
int i;
for (cnt = 0; cnt < (int) ARRAY_SIZE (tests); ++cnt)
{
- md4_init_ctx (&ctx);
- md4_process_bytes ((const unsigned char*)tests[cnt].input, &ctx, strlen (tests[cnt].input));
- md4_finish_ctx (&ctx, (unsigned char*)sum);
+ MD4_Init (&ctx);
+ MD4_Update (&ctx, tests[cnt].input, strlen (tests[cnt].input));
+ MD4_Final (sum, &ctx);
if (memcmp (tests[cnt].result, sum, 16))
{
report_failure (cnt, "all at once", tests[cnt].result, sum);
result = 1;
}
- md4_init_ctx (&ctx);
+ MD4_Init (&ctx);
for (i = 0; tests[cnt].input[i] != '\0'; ++i)
- md4_process_bytes ((const unsigned char*)&tests[cnt].input[i], &ctx, 1);
- md4_finish_ctx (&ctx, (unsigned char*)sum);
+ MD4_Update (&ctx, &tests[cnt].input[i], 1);
+ MD4_Final (sum, &ctx);
if (memcmp (tests[cnt].result, sum, 16))
{
report_failure (cnt, "byte by byte", tests[cnt].result, sum);
From 6fc8102f7727f8e4115a87070d2e4a36b55ea1bc Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bj=C3=B6rn=20Esser?= <besser82@fedoraproject.org>
Date: Mon, 22 Oct 2018 19:51:57 +0200
Subject: [PATCH 12/17] Fix -Wcast-align.
---
alg-md4.c | 2 +-
alg-md5.c | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/alg-md4.c b/alg-md4.c
index 482b6f4..a6e1072 100644
--- a/alg-md4.c
+++ b/alg-md4.c
@@ -73,7 +73,7 @@
* link-time optimizations. For the time being, keeping these MD4 routines in
* their own translation unit avoids the problem.
*/
-#if defined(__i386__) || defined(__x86_64__) || defined(__vax__)
+#if 0 /* defined(__i386__) || defined(__x86_64__) || defined(__vax__) */
#define SET(n) \
(*(const MD4_u32plus *)&ptr[(n) * 4])
#define GET(n) \
diff --git a/alg-md5.c b/alg-md5.c
index 8382b98..5502539 100644
--- a/alg-md5.c
+++ b/alg-md5.c
@@ -77,7 +77,7 @@
* link-time optimizations. For the time being, keeping these MD5 routines in
* their own translation unit avoids the problem.
*/
-#if defined(__i386__) || defined(__x86_64__) || defined(__vax__)
+#if 0 /* defined(__i386__) || defined(__x86_64__) || defined(__vax__) */
#define SET(n) \
(*(const MD5_u32plus *)&ptr[(n) * 4])
#define GET(n) \
From cc50dde05be214caace8af493fe869832a1d3d68 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bj=C3=B6rn=20Esser?= <besser82@fedoraproject.org>
Date: Mon, 22 Oct 2018 20:03:03 +0200
Subject: [PATCH 13/17] Remove unused file.
---
m4/.git_keep_dir | 0
1 file changed, 0 insertions(+), 0 deletions(-)
delete mode 100644 m4/.git_keep_dir
diff --git a/m4/.git_keep_dir b/m4/.git_keep_dir
deleted file mode 100644
index e69de29..0000000
From 1cf317228655013c516090a20e70d81656516580 Mon Sep 17 00:00:00 2001
From: Vitaly Chikunov <vt@altlinux.org>
Date: Wed, 24 Oct 2018 05:24:47 +0300
Subject: [PATCH 14/17] yescrypt: Add more tests.
Test that crypt() with hashed password in place of settings works the
same as settings.
---
test-crypt-yescrypt.c | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/test-crypt-yescrypt.c b/test-crypt-yescrypt.c
index a635f94..9d67b92 100644
--- a/test-crypt-yescrypt.c
+++ b/test-crypt-yescrypt.c
@@ -43,8 +43,16 @@ test(const char *p, const char *s, const char *m)
int
main (void)
{
- int result = test("pleaseletmein", "$y$jD5.7$LdJMENpBABJJ3hIHjB1Bi.",
- "$y$jD5.7$LdJMENpBABJJ3hIHjB1Bi.$HboGM6qPrsK.StKYGt6KErmUYtioHreJd98oIugoNB6");
+ int result = 0;
+
+#define YSETTINGS "$y$jD5.7$LdJMENpBABJJ3hIHjB1Bi."
+#define YHASHPART "HboGM6qPrsK.StKYGt6KErmUYtioHreJd98oIugoNB6"
+#define YFULLHASH YSETTINGS "$" YHASHPART
+ result |= test("pleaseletmein", YSETTINGS, YFULLHASH);
+ result |= test("pleaseletmein", YFULLHASH, YFULLHASH);
+ result |= test("pleaseletmein", YSETTINGS "$", YFULLHASH);
+ result |= test("pleaseletmein", YSETTINGS "$garbage", YFULLHASH);
+
result |= test("", "$y$jD5.7$", "$y$jD5.7$$JD8dsR.nt1ty0ltQ2HHwauaDRoOUIEaA5i.vpj2nyL.");
result |= test("", "$y$jD5.7$$", "$y$jD5.7$$JD8dsR.nt1ty0ltQ2HHwauaDRoOUIEaA5i.vpj2nyL.");
From 232b217faba35064ca30120751f788d649cb3020 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bj=C3=B6rn=20Esser?= <besser82@fedoraproject.org>
Date: Wed, 24 Oct 2018 15:54:12 +0200
Subject: [PATCH 15/17] Use bzip2 and xz compression for distribution tarballs,
too.
---
Makefile.am | 2 +-
NEWS | 2 ++
2 files changed, 3 insertions(+), 1 deletion(-)
diff --git a/Makefile.am b/Makefile.am
index e7d5c6d..8cb3807 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -4,7 +4,7 @@
# Author: Thorsten Kukuk <kukuk@suse.de>
#
-AUTOMAKE_OPTIONS = 1.14 gnits
+AUTOMAKE_OPTIONS = 1.14 gnits dist-bzip2 dist-xz
ACLOCAL_AMFLAGS = -I m4
AM_CFLAGS = $(WARN_CFLAGS)
diff --git a/NEWS b/NEWS
index e48b0d1..8af68ff 100644
--- a/NEWS
+++ b/NEWS
@@ -10,6 +10,8 @@ Version 4.2.3
sha512 implementation under the BSD license.
* Use md5 implementation from Alexander Peslyak. Thus we now have a
md5 implementation in the public domain.
+* 'make dist' now generates bzip2 and xz compressed tarballs along
+ with the default gzip compressed tarball.
Version 4.2.2
* Convert existing manpages to BSD mdoc format.
From a17c2d75c5642d164e04748ddb93f8f426c7ed5c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bj=C3=B6rn=20Esser?= <besser82@fedoraproject.org>
Date: Thu, 25 Oct 2018 13:47:04 +0200
Subject: [PATCH 16/17] Add Badge for Coverity Scan.
---
README.md | 1 +
1 file changed, 1 insertion(+)
diff --git a/README.md b/README.md
index 102127a..9a91ad5 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,6 @@
[![Build Status](https://travis-ci.org/besser82/libxcrypt.svg?branch=develop)](https://travis-ci.org/besser82/libxcrypt)
[![codecov](https://codecov.io/gh/besser82/libxcrypt/branch/develop/graph/badge.svg)](https://codecov.io/gh/besser82/libxcrypt)
+[![Coverity Scan Build Status](https://scan.coverity.com/projects/17073/badge.svg)](https://scan.coverity.com/projects/besser82-libxcrypt)
README for libxcrypt
====================
From 8b1ff5c38f316bc301e57a5a307fd11b8984e494 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bj=C3=B6rn=20Esser?= <besser82@fedoraproject.org>
Date: Thu, 25 Oct 2018 14:06:01 +0200
Subject: [PATCH 17/17] Add labels to TravisCI builds.
---
.travis.yml | 75 +++++++++++++++++++++++++++++++++++------------------
1 file changed, 50 insertions(+), 25 deletions(-)
diff --git a/.travis.yml b/.travis.yml
index acb186c..2e7a746 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -15,153 +15,178 @@ sudo: true
matrix:
fast_finish: true
include:
- - compiler: gcc
+ - name: "Fedora Rawhide, GCC, Codecov"
+ compiler: gcc
os: linux
services: docker
env:
- CONF="--enable-obsolete-api --enable-hashes=all"
- FCVER="rawhide"
- CODECOV=1
- - compiler: gcc
+ - name: "Fedora Rawhide, GCC, all hashes, obsolete API"
+ compiler: gcc
os: linux
services: docker
env:
- CONF="--enable-obsolete-api --enable-hashes=all"
- FCVER="rawhide"
- DISTCHECK=1
- - compiler: clang
+ - name: "Fedora Rawhide, Clang, all hashes, obsolete API"
+ compiler: clang
os: linux
services: docker
env:
- CONF="--enable-obsolete-api --enable-hashes=all"
- FCVER="rawhide"
- - compiler: gcc
+ - name: "Fedora stable, GCC, all hashes, obsolete API"
+ compiler: gcc
os: linux
services: docker
env:
- CONF="--enable-obsolete-api --enable-hashes=all"
- FCVER="latest"
- - compiler: clang
+ - name: "Fedora stable, Clang, all hashes, obsolete API"
+ compiler: clang
os: linux
services: docker
env:
- CONF="--enable-obsolete-api --enable-hashes=all"
- FCVER="latest"
- - compiler: gcc
+ - name: "Fedora Rawhide, GCC, all hashes, obsolete API, no failure-tokens"
+ compiler: gcc
os: linux
services: docker
env:
- CONF="--disable-failure-tokens --enable-obsolete-api --enable-hashes=all"
- FCVER="rawhide"
- - compiler: clang
+ - name: "Fedora Rawhide, Clang, all hashes, obsolete API, no failure-tokens"
+ compiler: clang
os: linux
services: docker
env:
- CONF="--disable-failure-tokens --enable-obsolete-api --enable-hashes=all"
- FCVER="rawhide"
- - compiler: gcc
+ - name: "Fedora stable, GCC, all hashes, obsolete API, no failure-tokens"
+ compiler: gcc
os: linux
services: docker
env:
- CONF="--disable-failure-tokens --enable-obsolete-api --enable-hashes=all"
- FCVER="latest"
- - compiler: clang
+ - name: "Fedora stable, Clang, all hashes, obsolete API, no failure-tokens"
+ compiler: clang
os: linux
services: docker
env:
- CONF="--disable-failure-tokens --enable-obsolete-api --enable-hashes=all"
- FCVER="latest"
- - compiler: gcc
+ - name: "Fedora Rawhide, GCC, all hashes, no obsolete API"
+ compiler: gcc
os: linux
services: docker
env:
- CONF="--disable-obsolete-api --enable-hashes=all"
- FCVER="rawhide"
- - compiler: clang
+ - name: "Fedora Rawhide, Clang, all hashes, no obsolete API"
+ compiler: clang
os: linux
services: docker
env:
- CONF="--disable-obsolete-api --enable-hashes=all"
- FCVER="rawhide"
- - compiler: gcc
+ - name: "Fedora stable, GCC, all hashes, no obsolete API"
+ compiler: gcc
os: linux
services: docker
env:
- CONF="--disable-obsolete-api --enable-hashes=all"
- FCVER="latest"
- - compiler: clang
+ - name: "Fedora stable, Clang, all hashes, no obsolete API"
+ compiler: clang
os: linux
services: docker
env:
- CONF="--disable-obsolete-api --enable-hashes=all"
- FCVER="latest"
- - compiler: gcc
+ - name: "Fedora Rawhide, GCC, strong hashes, no obsolete API"
+ compiler: gcc
os: linux
services: docker
env:
- CONF="--disable-obsolete-api --enable-hashes=strong"
- FCVER="rawhide"
- - compiler: clang
+ - name: "Fedora Rawhide, Clang, strong hashes, no obsolete API"
+ compiler: clang
os: linux
services: docker
env:
- CONF="--disable-obsolete-api --enable-hashes=strong"
- FCVER="rawhide"
- - compiler: gcc
+ - name: "Fedora stable, GCC, strong hashes, no obsolete API"
+ compiler: gcc
os: linux
services: docker
env:
- CONF="--disable-obsolete-api --enable-hashes=strong"
- FCVER="latest"
- - compiler: clang
+ - name: "Fedora stable, Clang, strong hashes, no obsolete API"
+ compiler: clang
os: linux
services: docker
env:
- CONF="--disable-obsolete-api --enable-hashes=strong"
- FCVER="latest"
- - compiler: gcc
+ - name: "Fedora Rawhide, GCC, glibc hashes, obsolete API"
+ compiler: gcc
os: linux
services: docker
env:
- CONF="--enable-obsolete-api --enable-hashes=glibc"
- FCVER="rawhide"
- - compiler: clang
+ - name: "Fedora Rawhide, Clang, glibc hashes, obsolete API"
+ compiler: clang
os: linux
services: docker
env:
- CONF="--enable-obsolete-api --enable-hashes=glibc"
- FCVER="rawhide"
- - compiler: gcc
+ - name: "Fedora stable, GCC, glibc hashes, obsolete API"
+ compiler: gcc
os: linux
services: docker
env:
- CONF="--enable-obsolete-api --enable-hashes=glibc"
- FCVER="latest"
- - compiler: clang
+ - name: "Fedora stable, Clang, glibc hashes, obsolete API"
+ compiler: clang
os: linux
services: docker
env:
- CONF="--enable-obsolete-api --enable-hashes=glibc"
- FCVER="latest"
- - compiler: gcc
+ - name: "Fedora Rawhide, GCC, glibc and strong hashes, obsolete API for glibc"
+ compiler: gcc
os: linux
services: docker
env:
- CONF="--enable-obsolete-api=glibc --enable-hashes=strong,glibc"
- FCVER="rawhide"
- - compiler: clang
+ - name: "Fedora Rawhide, Clang, glibc and strong hashes, obsolete API for glibc"
+ compiler: clang
os: linux
services: docker
env:
- CONF="--enable-obsolete-api=glibc --enable-hashes=strong,glibc"
- FCVER="rawhide"
- - compiler: gcc
+ - name: "Fedora stable, GCC, glibc and strong hashes, obsolete API for glibc"
+ compiler: gcc
os: linux
services: docker
env:
- CONF="--enable-obsolete-api=glibc --enable-hashes=strong,glibc"
- FCVER="latest"
- - compiler: clang
+ - name: "Fedora stable, Clang, glibc and strong hashes, obsolete API for glibc"
+ compiler: clang
os: linux
services: docker
env: