diff --git a/libxcrypt-4.1.1_add_other_manpages.patch b/libxcrypt-4.1.1_add_other_manpages.patch deleted file mode 100644 index 0c634f3..0000000 --- a/libxcrypt-4.1.1_add_other_manpages.patch +++ /dev/null @@ -1,78 +0,0 @@ -From cc1806e214b89403152c2c53932d8d0b8aeb1e91 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Bj=C3=B6rn=20Esser?= -Date: Sat, 4 Aug 2018 13:02:03 +0200 -Subject: [PATCH] Add alias man-pages for other crypt functions. - ---- - Makefile.am | 3 ++- - crypt.3 | 1 + - crypt.5 | 2 ++ - crypt_gensalt.3 | 2 ++ - crypt_r.3 | 1 + - crypt_ra.3 | 1 + - 6 files changed, 9 insertions(+), 1 deletion(-) - create mode 100644 crypt.3 - create mode 100644 crypt_r.3 - create mode 100644 crypt_ra.3 - -diff --git a/Makefile.am b/Makefile.am -index 874db12..41ca783 100644 ---- a/Makefile.am -+++ b/Makefile.am -@@ -18,7 +18,8 @@ EXTRA_DIST = \ - gen-map.awk gen-vers.awk gen-crypt-h.awk \ - gen-hashes.awk sel-hashes.awk hashes.lst - --notrans_dist_man3_MANS = crypt_rn.3 crypt_gensalt.3 -+notrans_dist_man3_MANS = crypt.3 crypt_r.3 crypt_ra.3 \ -+ crypt_rn.3 crypt_gensalt.3 - notrans_dist_man5_MANS = crypt.5 - - nodist_include_HEADERS = crypt.h -diff --git a/crypt.3 b/crypt.3 -new file mode 100644 -index 0000000..430e48f ---- /dev/null -+++ b/crypt.3 -@@ -0,0 +1 @@ -+.so man3/crypt_rn.3 -diff --git a/crypt.5 b/crypt.5 -index 5db9c92..7fe4609 100644 ---- a/crypt.5 -+++ b/crypt.5 -@@ -279,6 +279,8 @@ that will work on an old operating system that supports nothing else. - .hash "$3$" "\e$3\e$\e$[0-9a-f]{32}" unlimited 8 256 256 0 1 - .SH SEE ALSO - .BR crypt (3), -+.BR crypt_r (3), -+.BR crypt_ra (3), - .BR crypt_rn (3), - .BR crypt_gensalt (3), - .BR getpwent (3), -diff --git a/crypt_gensalt.3 b/crypt_gensalt.3 -index ebfff28..3109740 100644 ---- a/crypt_gensalt.3 -+++ b/crypt_gensalt.3 -@@ -223,6 +223,8 @@ T} Thread safety MT-Safe - .SH SEE ALSO - .ad l - .BR crypt (3), -+.BR crypt_r (3), -+.BR crypt_ra (3), - .BR crypt_rn (3), - .BR getpass (3), - .BR getpwent (3), -diff --git a/crypt_r.3 b/crypt_r.3 -new file mode 100644 -index 0000000..430e48f ---- /dev/null -+++ b/crypt_r.3 -@@ -0,0 +1 @@ -+.so man3/crypt_rn.3 -diff --git a/crypt_ra.3 b/crypt_ra.3 -new file mode 100644 -index 0000000..430e48f ---- /dev/null -+++ b/crypt_ra.3 -@@ -0,0 +1 @@ -+.so man3/crypt_rn.3 diff --git a/libxcrypt-4.1.1_to_master.patch b/libxcrypt-4.1.1_to_master.patch new file mode 100644 index 0000000..21db174 --- /dev/null +++ b/libxcrypt-4.1.1_to_master.patch @@ -0,0 +1,2808 @@ +From 0e5a38cde2ede896e4dca6d85f133d9e23ec72cc Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Bj=C3=B6rn=20Esser?= +Date: Wed, 1 Aug 2018 11:51:23 +0200 +Subject: [PATCH 01/10] Bump tarball version to 4.1.2 and update NEWS. + +--- + NEWS | 2 ++ + configure.ac | 2 +- + 2 files changed, 3 insertions(+), 1 deletion(-) + +diff --git a/NEWS b/NEWS +index 0288c44..40effdc 100644 +--- a/NEWS ++++ b/NEWS +@@ -3,6 +3,8 @@ libxcrypt NEWS -- history of user-visible changes. + Please send bug reports, questions and suggestions to + . + ++Version 4.1.2 ++ + Version 4.1.1 + * --enable-hashes now supports additional groups of hashing methods: + 'freebsd', 'netbsd', 'openbsd', 'osx', and 'solaris', which select +diff --git a/configure.ac b/configure.ac +index a22a592..8940e2d 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.1.1], ++ [4.1.2], + [https://github.com/besser82/libxcrypt/issues], + [libxcrypt], + [https://github.com/besser82/libxcrypt]) + +From 7281ceb60e404e8734784670490aaf7d95ffb970 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Bj=C3=B6rn=20Esser?= +Date: Thu, 2 Aug 2018 09:44:07 +0200 +Subject: [PATCH 02/10] Use valgrind memcheck if available to test for memory + leaks. + +--- + .travis.yml | 5 +- + Makefile.am | 11 +- + NEWS | 1 + + configure.ac | 13 +- + m4/ax_valgrind_check.m4 | 239 ++++++++++++++++++ + test-symbols-compat => test-symbols-compat.sh | 0 + ...symbols-renames => test-symbols-renames.sh | 0 + test-symbols-static => test-symbols-static.sh | 0 + 8 files changed, 261 insertions(+), 8 deletions(-) + create mode 100644 m4/ax_valgrind_check.m4 + rename test-symbols-compat => test-symbols-compat.sh (100%) + rename test-symbols-renames => test-symbols-renames.sh (100%) + rename test-symbols-static => test-symbols-static.sh (100%) + +diff --git a/.travis.yml b/.travis.yml +index db45ded..1f8e224 100644 +--- a/.travis.yml ++++ b/.travis.yml +@@ -155,7 +155,7 @@ before_install: + - docker exec -t buildenv /bin/sh -c 'for i in `seq 0 99`; do dnf makecache && i= && break || sleep 1; done; [ -z "$i" ]' + - 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 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 && 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" ]' + - 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 '/usr/bin/git' '/usr/bin/lcov' '/usr/bin/pip3' && i= && break || sleep 1; done; [ -z "$i" ]' ; fi + - if [[ "$CODECOV" == "1" ]] ; then docker exec -t buildenv /bin/sh -c "pip3 install codecov" ; fi +@@ -178,6 +178,7 @@ script: + - docker exec -t buildenv /bin/sh -c "make -C /opt/libxcrypt -j$((`nproc --all` * 2))" + - docker exec -t buildenv /bin/sh -c "make -C /opt/libxcrypt install" + - docker exec -t buildenv /bin/sh -c "(make -C /opt/libxcrypt -j$((`nproc --all` * 2)) check || (cat /opt/libxcrypt/test-suite.log && exit 1))" ++ - docker exec -t buildenv /bin/sh -c "(make -C /opt/libxcrypt -j$((`nproc --all` * 2)) check-valgrind-memcheck || (cat /opt/libxcrypt/test-suite-memcheck.log && exit 1))" + + after_success: +- - if [[ "$CODECOV" == "1" ]] ; then docker exec -t buildenv /bin/sh -c "make -C /opt/libxcrypt check && cd /opt/libxcrypt && lcov --directory . --capture --output-file all_coverage.info && lcov --remove all_coverage.info '/usr/*' '*test*' > coverage.info && rm all_coverage.info && codecov -X gcov" ; fi ++ - if [[ "$CODECOV" == "1" ]] ; then docker exec -t buildenv /bin/sh -c "cd /opt/libxcrypt && lcov --directory . --capture --output-file all_coverage.info && lcov --remove all_coverage.info '/usr/*' '*test*' > coverage.info && rm all_coverage.info && codecov -X gcov" ; fi +diff --git a/Makefile.am b/Makefile.am +index 201dea5..874db12 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -9,6 +9,9 @@ ACLOCAL_AMFLAGS = -I m4 + + AM_CFLAGS = $(WARN_CFLAGS) + ++@VALGRIND_CHECK_RULES@ ++TEST_EXTENSIONS = .sh ++ + EXTRA_DIST = \ + LICENSING THANKS \ + libcrypt.map.in libcrypt.minver \ +@@ -158,15 +161,15 @@ endif + + TESTS = $(check_PROGRAMS) + if ENABLE_STATIC +-TESTS += test-symbols-static ++TESTS += test-symbols-static.sh + if HAVE_CPP_dD +-TESTS += test-symbols-renames ++TESTS += test-symbols-renames.sh + endif + endif + if ENABLE_OBSOLETE_API +-TESTS += test-symbols-compat ++TESTS += test-symbols-compat.sh + endif +-EXTRA_DIST += test-symbols-static test-symbols-compat test-symbols-renames ++EXTRA_DIST += test-symbols-static.sh test-symbols-compat.sh test-symbols-renames.sh + + AM_TESTS_ENVIRONMENT = \ + lib_la="./libcrypt.la"; lib_map="$(srcdir)/libcrypt.map.in"; \ +diff --git a/NEWS b/NEWS +index 40effdc..77b556f 100644 +--- a/NEWS ++++ b/NEWS +@@ -4,6 +4,7 @@ Please send bug reports, questions and suggestions to + . + + Version 4.1.2 ++* Add optional 'check-valgrind' target to the Makefile. + + Version 4.1.1 + * --enable-hashes now supports additional groups of hashing methods: +diff --git a/configure.ac b/configure.ac +index 8940e2d..9ea30f6 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -51,7 +51,6 @@ AC_C_BIGENDIAN( + AC_DEFINE([IS_BIGENDIAN], 0, + [Define to 0 if system's architecture is little-endian.]) + ) +- + # One of the test scripts needs to use -dD. + AC_CACHE_CHECK([whether the preprocessor ($CPP) supports -dD], + [ac_cv_prog_cc_dD], +@@ -151,8 +150,18 @@ AC_CHECK_FUNCS_ONCE([ + syscall + ]) + +-# Configure options. ++# Disable valgrind tools for checking multithreaded ++# programs, as we don't use them in checks. ++AX_VALGRIND_DFLT([drd], [off]) ++AX_VALGRIND_DFLT([helgrind], [off]) ++ ++# Valgrind's sgcheck is b0rk3n upstream. ++AX_VALGRIND_DFLT([sgcheck], [off]) + ++# Add a target to run testsuite with valgrind. ++AX_VALGRIND_CHECK() ++ ++# Configure options. + AC_ARG_ENABLE([obsolete-api], + AS_HELP_STRING( + [--enable-obsolete-api[=ARG]], +diff --git a/m4/ax_valgrind_check.m4 b/m4/ax_valgrind_check.m4 +new file mode 100644 +index 0000000..7033798 +--- /dev/null ++++ b/m4/ax_valgrind_check.m4 +@@ -0,0 +1,239 @@ ++# =========================================================================== ++# https://www.gnu.org/software/autoconf-archive/ax_valgrind_check.html ++# =========================================================================== ++# ++# SYNOPSIS ++# ++# AX_VALGRIND_DFLT(memcheck|helgrind|drd|sgcheck, on|off) ++# AX_VALGRIND_CHECK() ++# ++# DESCRIPTION ++# ++# AX_VALGRIND_CHECK checks whether Valgrind is present and, if so, allows ++# running `make check` under a variety of Valgrind tools to check for ++# memory and threading errors. ++# ++# Defines VALGRIND_CHECK_RULES which should be substituted in your ++# Makefile; and $enable_valgrind which can be used in subsequent configure ++# output. VALGRIND_ENABLED is defined and substituted, and corresponds to ++# the value of the --enable-valgrind option, which defaults to being ++# enabled if Valgrind is installed and disabled otherwise. Individual ++# Valgrind tools can be disabled via --disable-valgrind-, the ++# default is configurable via the AX_VALGRIND_DFLT command or is to use ++# all commands not disabled via AX_VALGRIND_DFLT. All AX_VALGRIND_DFLT ++# calls must be made before the call to AX_VALGRIND_CHECK. ++# ++# If unit tests are written using a shell script and automake's ++# LOG_COMPILER system, the $(VALGRIND) variable can be used within the ++# shell scripts to enable Valgrind, as described here: ++# ++# https://www.gnu.org/software/gnulib/manual/html_node/Running-self_002dtests-under-valgrind.html ++# ++# Usage example: ++# ++# configure.ac: ++# ++# AX_VALGRIND_DFLT([sgcheck], [off]) ++# AX_VALGRIND_CHECK ++# ++# in each Makefile.am with tests: ++# ++# @VALGRIND_CHECK_RULES@ ++# VALGRIND_SUPPRESSIONS_FILES = my-project.supp ++# EXTRA_DIST = my-project.supp ++# ++# This results in a "check-valgrind" rule being added. Running `make ++# check-valgrind` in that directory will recursively run the module's test ++# suite (`make check`) once for each of the available Valgrind tools (out ++# of memcheck, helgrind and drd) while the sgcheck will be skipped unless ++# enabled again on the commandline with --enable-valgrind-sgcheck. The ++# results for each check will be output to test-suite-$toolname.log. The ++# target will succeed if there are zero errors and fail otherwise. ++# ++# Alternatively, a "check-valgrind-$TOOL" rule will be added, for $TOOL in ++# memcheck, helgrind, drd and sgcheck. These are useful because often only ++# some of those tools can be ran cleanly on a codebase. ++# ++# The macro supports running with and without libtool. ++# ++# LICENSE ++# ++# Copyright (c) 2014, 2015, 2016 Philip Withnall ++# ++# Copying and distribution of this file, with or without modification, are ++# permitted in any medium without royalty provided the copyright notice ++# and this notice are preserved. This file is offered as-is, without any ++# warranty. ++ ++#serial 17 ++ ++dnl Configured tools ++m4_define([valgrind_tool_list], [[memcheck], [helgrind], [drd], [sgcheck]]) ++m4_set_add_all([valgrind_exp_tool_set], [sgcheck]) ++m4_foreach([vgtool], [valgrind_tool_list], ++ [m4_define([en_dflt_valgrind_]vgtool, [on])]) ++ ++AC_DEFUN([AX_VALGRIND_DFLT],[ ++ m4_define([en_dflt_valgrind_$1], [$2]) ++])dnl ++ ++AM_EXTRA_RECURSIVE_TARGETS([check-valgrind]) ++m4_foreach([vgtool], [valgrind_tool_list], ++ [AM_EXTRA_RECURSIVE_TARGETS([check-valgrind-]vgtool)]) ++ ++AC_DEFUN([AX_VALGRIND_CHECK],[ ++ dnl Check for --enable-valgrind ++ AC_ARG_ENABLE([valgrind], ++ [AS_HELP_STRING([--enable-valgrind], [Whether to enable Valgrind on the unit tests])], ++ [enable_valgrind=$enableval],[enable_valgrind=]) ++ ++ AS_IF([test "$enable_valgrind" != "no"],[ ++ # Check for Valgrind. ++ AC_CHECK_PROG([VALGRIND],[valgrind],[valgrind]) ++ AS_IF([test "$VALGRIND" = ""],[ ++ AS_IF([test "$enable_valgrind" = "yes"],[ ++ AC_MSG_ERROR([Could not find valgrind; either install it or reconfigure with --disable-valgrind]) ++ ],[ ++ enable_valgrind=no ++ ]) ++ ],[ ++ enable_valgrind=yes ++ ]) ++ ]) ++ ++ AM_CONDITIONAL([VALGRIND_ENABLED],[test "$enable_valgrind" = "yes"]) ++ AC_SUBST([VALGRIND_ENABLED],[$enable_valgrind]) ++ ++ # Check for Valgrind tools we care about. ++ [valgrind_enabled_tools=] ++ m4_foreach([vgtool],[valgrind_tool_list],[ ++ AC_ARG_ENABLE([valgrind-]vgtool, ++ m4_if(m4_defn([en_dflt_valgrind_]vgtool),[off],dnl ++[AS_HELP_STRING([--enable-valgrind-]vgtool, [Whether to use ]vgtool[ during the Valgrind tests])],dnl ++[AS_HELP_STRING([--disable-valgrind-]vgtool, [Whether to skip ]vgtool[ during the Valgrind tests])]), ++ [enable_valgrind_]vgtool[=$enableval], ++ [enable_valgrind_]vgtool[=]) ++ AS_IF([test "$enable_valgrind" = "no"],[ ++ enable_valgrind_]vgtool[=no], ++ [test "$enable_valgrind_]vgtool[" ]dnl ++m4_if(m4_defn([en_dflt_valgrind_]vgtool), [off], [= "yes"], [!= "no"]),[ ++ AC_CACHE_CHECK([for Valgrind tool ]vgtool, ++ [ax_cv_valgrind_tool_]vgtool,[ ++ ax_cv_valgrind_tool_]vgtool[=no ++ m4_set_contains([valgrind_exp_tool_set],vgtool, ++ [m4_define([vgtoolx],[exp-]vgtool)], ++ [m4_define([vgtoolx],vgtool)]) ++ AS_IF([`$VALGRIND --tool=]vgtoolx[ --help >/dev/null 2>&1`],[ ++ ax_cv_valgrind_tool_]vgtool[=yes ++ ]) ++ ]) ++ AS_IF([test "$ax_cv_valgrind_tool_]vgtool[" = "no"],[ ++ AS_IF([test "$enable_valgrind_]vgtool[" = "yes"],[ ++ AC_MSG_ERROR([Valgrind does not support ]vgtool[; reconfigure with --disable-valgrind-]vgtool) ++ ],[ ++ enable_valgrind_]vgtool[=no ++ ]) ++ ],[ ++ enable_valgrind_]vgtool[=yes ++ ]) ++ ]) ++ AS_IF([test "$enable_valgrind_]vgtool[" = "yes"],[ ++ valgrind_enabled_tools="$valgrind_enabled_tools ]m4_bpatsubst(vgtool,[^exp-])[" ++ ]) ++ AC_SUBST([ENABLE_VALGRIND_]vgtool,[$enable_valgrind_]vgtool) ++ ]) ++ AC_SUBST([valgrind_tools],["]m4_join([ ], valgrind_tool_list)["]) ++ AC_SUBST([valgrind_enabled_tools],[$valgrind_enabled_tools]) ++ ++[VALGRIND_CHECK_RULES=' ++# Valgrind check ++# ++# Optional: ++# - VALGRIND_SUPPRESSIONS_FILES: Space-separated list of Valgrind suppressions ++# files to load. (Default: empty) ++# - VALGRIND_FLAGS: General flags to pass to all Valgrind tools. ++# (Default: --num-callers=30) ++# - VALGRIND_$toolname_FLAGS: Flags to pass to Valgrind $toolname (one of: ++# memcheck, helgrind, drd, sgcheck). (Default: various) ++ ++# Optional variables ++VALGRIND_SUPPRESSIONS ?= $(addprefix --suppressions=,$(VALGRIND_SUPPRESSIONS_FILES)) ++VALGRIND_FLAGS ?= --num-callers=30 ++VALGRIND_memcheck_FLAGS ?= --leak-check=full --show-reachable=no ++VALGRIND_helgrind_FLAGS ?= --history-level=approx ++VALGRIND_drd_FLAGS ?= ++VALGRIND_sgcheck_FLAGS ?= ++ ++# Internal use ++valgrind_log_files = $(addprefix test-suite-,$(addsuffix .log,$(valgrind_tools))) ++ ++valgrind_memcheck_flags = --tool=memcheck $(VALGRIND_memcheck_FLAGS) ++valgrind_helgrind_flags = --tool=helgrind $(VALGRIND_helgrind_FLAGS) ++valgrind_drd_flags = --tool=drd $(VALGRIND_drd_FLAGS) ++valgrind_sgcheck_flags = --tool=exp-sgcheck $(VALGRIND_sgcheck_FLAGS) ++ ++valgrind_quiet = $(valgrind_quiet_$(V)) ++valgrind_quiet_ = $(valgrind_quiet_$(AM_DEFAULT_VERBOSITY)) ++valgrind_quiet_0 = --quiet ++valgrind_v_use = $(valgrind_v_use_$(V)) ++valgrind_v_use_ = $(valgrind_v_use_$(AM_DEFAULT_VERBOSITY)) ++valgrind_v_use_0 = @echo " USE " $(patsubst check-valgrind-%-am,%,$''@):; ++ ++# Support running with and without libtool. ++ifneq ($(LIBTOOL),) ++valgrind_lt = $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=execute ++else ++valgrind_lt = ++endif ++ ++# Use recursive makes in order to ignore errors during check ++check-valgrind-am: ++ifeq ($(VALGRIND_ENABLED),yes) ++ $(A''M_V_at)$(MAKE) $(AM_MAKEFLAGS) -k \ ++ $(foreach tool, $(valgrind_enabled_tools), check-valgrind-$(tool)) ++else ++ @echo "Need to reconfigure with --enable-valgrind" ++endif ++ ++# Valgrind running ++VALGRIND_TESTS_ENVIRONMENT = \ ++ $(TESTS_ENVIRONMENT) \ ++ env VALGRIND=$(VALGRIND) \ ++ G_SLICE=always-malloc,debug-blocks \ ++ G_DEBUG=fatal-warnings,fatal-criticals,gc-friendly ++ ++VALGRIND_LOG_COMPILER = \ ++ $(valgrind_lt) \ ++ $(VALGRIND) $(VALGRIND_SUPPRESSIONS) --error-exitcode=1 $(VALGRIND_FLAGS) ++ ++define valgrind_tool_rule ++check-valgrind-$(1)-am: ++ifeq ($$(VALGRIND_ENABLED)-$$(ENABLE_VALGRIND_$(1)),yes-yes) ++ifneq ($$(TESTS),) ++ $$(valgrind_v_use)$$(MAKE) check-TESTS \ ++ TESTS_ENVIRONMENT="$$(VALGRIND_TESTS_ENVIRONMENT)" \ ++ LOG_COMPILER="$$(VALGRIND_LOG_COMPILER)" \ ++ LOG_FLAGS="$$(valgrind_$(1)_flags)" \ ++ TEST_SUITE_LOG=test-suite-$(1).log ++endif ++else ifeq ($$(VALGRIND_ENABLED),yes) ++ @echo "Need to reconfigure with --enable-valgrind-$(1)" ++else ++ @echo "Need to reconfigure with --enable-valgrind" ++endif ++endef ++ ++$(foreach tool,$(valgrind_tools),$(eval $(call valgrind_tool_rule,$(tool)))) ++ ++A''M_DISTCHECK_CONFIGURE_FLAGS ?= ++A''M_DISTCHECK_CONFIGURE_FLAGS += --disable-valgrind ++ ++MOSTLYCLEANFILES ?= ++MOSTLYCLEANFILES += $(valgrind_log_files) ++ ++.PHONY: check-valgrind $(add-prefix check-valgrind-,$(valgrind_tools)) ++'] ++ ++ AC_SUBST([VALGRIND_CHECK_RULES]) ++ m4_ifdef([_AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE([VALGRIND_CHECK_RULES])]) ++]) +diff --git a/test-symbols-compat b/test-symbols-compat.sh +similarity index 100% +rename from test-symbols-compat +rename to test-symbols-compat.sh +diff --git a/test-symbols-renames b/test-symbols-renames.sh +similarity index 100% +rename from test-symbols-renames +rename to test-symbols-renames.sh +diff --git a/test-symbols-static b/test-symbols-static.sh +similarity index 100% +rename from test-symbols-static +rename to test-symbols-static.sh + +From 307c223a0f8c7b52678bf3fed59685932ec57c18 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Bj=C3=B6rn=20Esser?= +Date: Sat, 14 Jul 2018 20:36:30 +0200 +Subject: [PATCH 03/10] Replace crypt-sha256.c with an implementation in the + Public Domain. + +This implementation is based on the SHA256-based Unix crypt +implementation. Released into the Public Domain [1] by +Ulrich Drepper . + +This file is a modified except from [2], lines 648 up to 909. + +[1] https://www.akkadia.org/drepper/sha-crypt.html +[2] https://www.akkadia.org/drepper/SHA-crypt.txt +--- + crypt-sha256.c | 351 +++++++++++++++++++++++++------------------------ + 1 file changed, 176 insertions(+), 175 deletions(-) + +diff --git a/crypt-sha256.c b/crypt-sha256.c +index e8d3808..c2954a4 100644 +--- a/crypt-sha256.c ++++ b/crypt-sha256.c +@@ -1,20 +1,17 @@ +-/* One way encryption based on SHA256 sum. +- +- 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 +- . */ ++/* One way encryption based on the SHA256-based Unix crypt implementation. ++ * ++ * Written by Ulrich Drepper in 2007 [1]. ++ * To the extent possible under law, Ulrich Drepper has waived all ++ * copyright and related or neighboring rights to this work. ++ * ++ * See https://creativecommons.org/publicdomain/zero/1.0/ for further ++ * details. ++ * ++ * This file is an except from [2], lines 648 up to 909. ++ * ++ * [1] https://www.akkadia.org/drepper/sha-crypt.html ++ * [2] https://www.akkadia.org/drepper/SHA-crypt.txt ++ */ + + #include "crypt-port.h" + #include "crypt-private.h" +@@ -42,35 +39,8 @@ static const char sha256_rounds_prefix[] = "rounds="; + /* Maximum number of rounds. */ + #define ROUNDS_MAX 999999999 + +-/* The maximum possible length of a SHA256-hashed password string, +- including the terminating NUL character. Prefix (including its NUL) +- + rounds tag ("rounds=$" = "rounds=\0") + strlen(ROUNDS_MAX) +- + salt (up to SALT_LEN_MAX chars) + '$' + hash (43 chars). */ +- +-#define LENGTH_OF_NUMBER(n) (sizeof #n - 1) +- +-#define SHA256_HASH_LENGTH \ +- (sizeof (sha256_salt_prefix) + sizeof (sha256_rounds_prefix) + \ +- LENGTH_OF_NUMBER (ROUNDS_MAX) + SALT_LEN_MAX + 1 + 43) +- +-static_assert (SHA256_HASH_LENGTH <= CRYPT_OUTPUT_SIZE, +- "CRYPT_OUTPUT_SIZE is too small for SHA256"); +- +-/* A sha256_buffer holds all of the sensitive intermediate data. */ +-struct sha256_buffer +-{ +- struct sha256_ctx ctx; +- uint8_t result[32]; +- uint8_t p_bytes[32]; +- uint8_t s_bytes[32]; +-}; +- +-static_assert (sizeof (struct sha256_buffer) <= ALG_SPECIFIC_SIZE, +- "ALG_SPECIFIC_SIZE is too small for SHA256"); +- +- + /* Table with characters for base64 transformation. */ +-static const char b64t[] = ++static const char b64t[64] = + "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; + + /* Subroutine of _xcrypt_crypt_sha256_rn: Feed CTX with LEN bytes of a +@@ -86,30 +56,23 @@ sha256_process_recycled_bytes (unsigned char block[32], size_t len, + sha256_process_bytes (block, cnt, ctx); + } + +-void +-crypt_sha256_rn (const char *phrase, size_t phr_size, +- const char *setting, size_t ARG_UNUSED (set_size), +- uint8_t *output, size_t out_size, +- void *scratch, size_t scr_size) ++static char * ++sha256_crypt_r (const char *key, const char *salt, char *buffer, int buflen) + { +- /* This shouldn't ever happen, but... */ +- if (out_size < SHA256_HASH_LENGTH +- || scr_size < sizeof (struct sha256_buffer)) +- { +- errno = ERANGE; +- return; +- } +- +- struct sha256_buffer *buf = scratch; +- struct sha256_ctx *ctx = &buf->ctx; +- uint8_t *result = buf->result; +- uint8_t *p_bytes = buf->p_bytes; +- uint8_t *s_bytes = buf->s_bytes; +- char *cp = (char *)output; +- const char *salt = setting; +- +- size_t salt_size; ++ unsigned char alt_result[32] ++ __attribute__ ((__aligned__ (__alignof__ (uint32_t)))); ++ unsigned char temp_result[32] ++ __attribute__ ((__aligned__ (__alignof__ (uint32_t)))); ++ struct sha256_ctx ctx; ++ struct sha256_ctx alt_ctx; ++ size_t salt_len; ++ size_t key_len; + size_t cnt; ++ char *cp; ++ char *copied_key = NULL; ++ char *copied_salt = NULL; ++ char *p_bytes; ++ char *s_bytes; + /* Default number of rounds. */ + size_t rounds = ROUNDS_DEFAULT; + bool rounds_custom = false; +@@ -124,176 +87,214 @@ crypt_sha256_rn (const char *phrase, size_t phr_size, + == 0) + { + const char *num = salt + sizeof (sha256_rounds_prefix) - 1; +- /* Do not allow an explicit setting of zero rounds, nor of the +- default number of rounds, nor leading zeroes on the rounds. */ +- if (!(*num >= '1' && *num <= '9')) +- { +- errno = EINVAL; +- return; +- } +- +- errno = 0; + char *endp; +- rounds = strtoul (num, &endp, 10); +- if (endp == num || *endp != '$' +- || rounds < ROUNDS_MIN +- || rounds > ROUNDS_MAX +- || errno) ++ unsigned long int srounds = strtoul (num, &endp, 10); ++ if (*endp == '$') + { +- errno = EINVAL; +- return; ++ salt = endp + 1; ++ rounds = MAX (ROUNDS_MIN, MIN (srounds, ROUNDS_MAX)); ++ rounds_custom = true; + } +- salt = endp + 1; +- rounds_custom = true; + } + +- salt_size = strspn (salt, b64t); +- if (salt[salt_size] && salt[salt_size] != '$') ++ salt_len = MIN (strcspn (salt, "$"), SALT_LEN_MAX); ++ key_len = strlen (key); ++ ++ if ((key - (char *) 0) % __alignof__ (uint32_t) != 0) + { +- errno = EINVAL; +- return; ++ char *tmp = (char *) alloca (key_len + __alignof__ (uint32_t)); ++ key = copied_key = ++ memcpy (tmp + __alignof__ (uint32_t) ++ - (tmp - (char *) 0) % __alignof__ (uint32_t), ++ key, key_len); + } +- if (salt_size > SALT_LEN_MAX) +- salt_size = SALT_LEN_MAX; + +- /* Compute alternate SHA256 sum with input PHRASE, SALT, and PHRASE. The +- final result will be added to the first context. */ +- sha256_init_ctx (ctx); ++ if ((salt - (char *) 0) % __alignof__ (uint32_t) != 0) ++ { ++ char *tmp = (char *) alloca (salt_len + __alignof__ (uint32_t)); ++ salt = copied_salt = ++ memcpy (tmp + __alignof__ (uint32_t) ++ - (tmp - (char *) 0) % __alignof__ (uint32_t), ++ salt, salt_len); ++ } + +- /* Add phrase. */ +- sha256_process_bytes (phrase, phr_size, ctx); ++ /* Prepare for the real work. */ ++ sha256_init_ctx (&ctx); + +- /* Add salt. */ +- sha256_process_bytes (salt, salt_size, ctx); ++ /* Add the key string. */ ++ sha256_process_bytes (key, key_len, &ctx); + +- /* Add phrase again. */ +- sha256_process_bytes (phrase, phr_size, ctx); ++ /* The last part is the salt string. This must be at most 16 ++ characters and it ends at the first `$' character (for ++ compatibility with existing implementations). */ ++ sha256_process_bytes (salt, salt_len, &ctx); + +- /* Now get result of this (32 bytes). */ +- sha256_finish_ctx (ctx, result); ++ /* Compute alternate SHA256 sum with input KEY, SALT, and KEY. The ++ final result will be added to the first context. */ ++ sha256_init_ctx (&alt_ctx); + +- /* Prepare for the real work. */ +- sha256_init_ctx (ctx); ++ /* Add key. */ ++ sha256_process_bytes (key, key_len, &alt_ctx); + +- /* Add the phrase string. */ +- sha256_process_bytes (phrase, phr_size, ctx); ++ /* Add salt. */ ++ sha256_process_bytes (salt, salt_len, &alt_ctx); + +- /* 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). */ +- sha256_process_bytes (salt, salt_size, ctx); ++ /* Add key again. */ ++ sha256_process_bytes (key, key_len, &alt_ctx); ++ ++ /* Now get result of this (32 bytes) and add it to the other ++ context. */ ++ sha256_finish_ctx (&alt_ctx, alt_result); + +- /* Add for any character in the phrase one byte of the alternate sum. */ +- for (cnt = phr_size; cnt > 32; cnt -= 32) +- sha256_process_bytes (result, 32, ctx); +- sha256_process_bytes (result, cnt, ctx); ++ /* Add for any character in the key one byte of the alternate sum. */ ++ for (cnt = key_len; cnt > 32; cnt -= 32) ++ sha256_process_bytes (alt_result, 32, &ctx); ++ sha256_process_bytes (alt_result, cnt, &ctx); + +- /* 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) ++ /* Take the binary representation of the length of the key and for every ++ 1 add the alternate sum, for every 0 the key. */ ++ for (cnt = key_len; cnt > 0; cnt >>= 1) + if ((cnt & 1) != 0) +- sha256_process_bytes (result, 32, ctx); ++ sha256_process_bytes (alt_result, 32, &ctx); + else +- sha256_process_bytes (phrase, phr_size, ctx); ++ sha256_process_bytes (key, key_len, &ctx); + + /* Create intermediate result. */ +- sha256_finish_ctx (ctx, result); ++ sha256_finish_ctx (&ctx, alt_result); + + /* Start computation of P byte sequence. */ +- sha256_init_ctx (ctx); ++ sha256_init_ctx (&alt_ctx); + + /* For every character in the password add the entire password. */ +- for (cnt = 0; cnt < phr_size; ++cnt) +- sha256_process_bytes (phrase, phr_size, ctx); ++ for (cnt = 0; cnt < key_len; ++cnt) ++ sha256_process_bytes (key, key_len, &alt_ctx); + + /* Finish the digest. */ +- sha256_finish_ctx (ctx, p_bytes); ++ sha256_finish_ctx (&alt_ctx, temp_result); ++ ++ /* Create byte sequence P. */ ++ cp = p_bytes = alloca (key_len); ++ for (cnt = key_len; cnt >= 32; cnt -= 32) ++ cp = mempcpy (cp, temp_result, 32); ++ memcpy (cp, temp_result, cnt); + + /* Start computation of S byte sequence. */ +- sha256_init_ctx (ctx); ++ sha256_init_ctx (&alt_ctx); + + /* For every character in the password add the entire password. */ +- for (cnt = 0; cnt < (size_t) 16 + (size_t) result[0]; ++cnt) +- sha256_process_bytes (salt, salt_size, ctx); ++ for (cnt = 0; cnt < 16 + alt_result[0]; ++cnt) ++ sha256_process_bytes (salt, salt_len, &alt_ctx); + + /* Finish the digest. */ +- sha256_finish_ctx (ctx, s_bytes); ++ sha256_finish_ctx (&alt_ctx, temp_result); ++ ++ /* Create byte sequence S. */ ++ cp = s_bytes = alloca (salt_len); ++ for (cnt = salt_len; cnt >= 32; cnt -= 32) ++ cp = mempcpy (cp, temp_result, 32); ++ memcpy (cp, temp_result, cnt); + + /* Repeatedly run the collected hash value through SHA256 to burn + CPU cycles. */ + for (cnt = 0; cnt < rounds; ++cnt) + { + /* New context. */ +- sha256_init_ctx (ctx); ++ sha256_init_ctx (&ctx); + +- /* Add phrase or last result. */ ++ /* Add key or last result. */ + if ((cnt & 1) != 0) +- sha256_process_recycled_bytes (p_bytes, phr_size, ctx); ++ sha256_process_bytes (p_bytes, key_len, &ctx); + else +- sha256_process_bytes (result, 32, ctx); ++ sha256_process_bytes (alt_result, 32, &ctx); + + /* Add salt for numbers not divisible by 3. */ + if (cnt % 3 != 0) +- sha256_process_recycled_bytes (s_bytes, salt_size, ctx); ++ sha256_process_bytes (s_bytes, salt_len, &ctx); + +- /* Add phrase for numbers not divisible by 7. */ ++ /* Add key for numbers not divisible by 7. */ + if (cnt % 7 != 0) +- sha256_process_recycled_bytes (p_bytes, phr_size, ctx); ++ sha256_process_bytes (p_bytes, key_len, &ctx); + +- /* Add phrase or last result. */ ++ /* Add key or last result. */ + if ((cnt & 1) != 0) +- sha256_process_bytes (result, 32, ctx); ++ sha256_process_bytes (alt_result, 32, &ctx); + else +- sha256_process_recycled_bytes (p_bytes, phr_size, ctx); ++ sha256_process_bytes (p_bytes, key_len, &ctx); + + /* Create intermediate result. */ +- sha256_finish_ctx (ctx, result); ++ sha256_finish_ctx (&ctx, alt_result); + } + +- /* Now we can construct the result string. It consists of four +- parts, one of which is optional. We already know that there +- is sufficient space at CP for the longest possible result string. */ +- memcpy (cp, sha256_salt_prefix, sizeof (sha256_salt_prefix) - 1); +- cp += sizeof (sha256_salt_prefix) - 1; ++ /* Now we can construct the result string. It consists of three ++ parts. */ ++ cp = stpncpy (buffer, sha256_salt_prefix, MAX (0, buflen)); ++ buflen -= sizeof (sha256_salt_prefix) - 1; + + if (rounds_custom) + { +- int n = snprintf (cp, +- SHA256_HASH_LENGTH - (sizeof (sha256_salt_prefix) - 1), +- "%s%zu$", sha256_rounds_prefix, rounds); ++ int n = snprintf (cp, MAX (0, buflen), "%s%zu$", ++ sha256_rounds_prefix, rounds); + cp += n; ++ buflen -= n; + } + +- memcpy (cp, salt, salt_size); +- cp += salt_size; +- *cp++ = '$'; +- +-#define b64_from_24bit(B2, B1, B0, N) \ +- do { \ +- unsigned int w = ((((unsigned int)(B2)) << 16) | \ +- (((unsigned int)(B1)) << 8) | \ +- ((unsigned int)(B0))); \ +- int n = (N); \ +- while (n-- > 0) \ +- { \ +- *cp++ = b64t[w & 0x3f]; \ +- w >>= 6; \ +- } \ ++ cp = stpncpy (cp, salt, MIN ((size_t) MAX (0, buflen), salt_len)); ++ buflen -= MIN ((size_t) MAX (0, buflen), salt_len); ++ ++ if (buflen > 0) ++ { ++ *cp++ = '$'; ++ --buflen; ++ } ++ ++#define b64_from_24bit(B2, B1, B0, N) \ ++ do { \ ++ unsigned int w = ((B2) << 16) | ((B1) << 8) | (B0); \ ++ int n = (N); \ ++ while (n-- > 0 && buflen > 0) \ ++ { \ ++ *cp++ = b64t[w & 0x3f]; \ ++ --buflen; \ ++ w >>= 6; \ ++ } \ + } while (0) + +- b64_from_24bit (result[0], result[10], result[20], 4); +- b64_from_24bit (result[21], result[1], result[11], 4); +- b64_from_24bit (result[12], result[22], result[2], 4); +- b64_from_24bit (result[3], result[13], result[23], 4); +- b64_from_24bit (result[24], result[4], result[14], 4); +- b64_from_24bit (result[15], result[25], result[5], 4); +- b64_from_24bit (result[6], result[16], result[26], 4); +- b64_from_24bit (result[27], result[7], result[17], 4); +- b64_from_24bit (result[18], result[28], result[8], 4); +- b64_from_24bit (result[9], result[19], result[29], 4); +- b64_from_24bit (0, result[31], result[30], 3); +- +- *cp = '\0'; ++ b64_from_24bit (alt_result[0], alt_result[10], alt_result[20], 4); ++ b64_from_24bit (alt_result[21], alt_result[1], alt_result[11], 4); ++ b64_from_24bit (alt_result[12], alt_result[22], alt_result[2], 4); ++ b64_from_24bit (alt_result[3], alt_result[13], alt_result[23], 4); ++ b64_from_24bit (alt_result[24], alt_result[4], alt_result[14], 4); ++ b64_from_24bit (alt_result[15], alt_result[25], alt_result[5], 4); ++ b64_from_24bit (alt_result[6], alt_result[16], alt_result[26], 4); ++ b64_from_24bit (alt_result[27], alt_result[7], alt_result[17], 4); ++ b64_from_24bit (alt_result[18], alt_result[28], alt_result[8], 4); ++ b64_from_24bit (alt_result[9], alt_result[19], alt_result[29], 4); ++ b64_from_24bit (0, alt_result[31], alt_result[30], 3); ++ if (buflen <= 0) ++ { ++ errno = ERANGE; ++ buffer = NULL; ++ } ++ else ++ *cp = '\0'; /* Terminate the string. */ ++ ++ /* Clear the buffer for the intermediate result so that people ++ attaching to processes or reading core dumps cannot get any ++ information. We do it in this way to clear correct_words[] ++ inside the SHA256 implementation as well. */ ++ sha256_init_ctx (&ctx); ++ sha256_finish_ctx (&ctx, alt_result); ++ memset (temp_result, '\0', sizeof (temp_result)); ++ memset (p_bytes, '\0', key_len); ++ memset (s_bytes, '\0', salt_len); ++ memset (&ctx, '\0', sizeof (ctx)); ++ memset (&alt_ctx, '\0', sizeof (alt_ctx)); ++ if (copied_key != NULL) ++ memset (copied_key, '\0', key_len); ++ if (copied_salt != NULL) ++ memset (copied_salt, '\0', salt_len); ++ ++ return buffer; + } + + void + +From 40a0d88687d7944ae618b1f507e6a0adc532399c Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Bj=C3=B6rn=20Esser?= +Date: Sat, 14 Jul 2018 21:00:10 +0200 +Subject: [PATCH 04/10] crypt-sha256.c: Apply previous commits from Zack + Weinberg + +This patch summarizes the changes from: + + * 4a1152b4f9bc900d0488b473e20daed95025f4b0 + * ccc833b4b2c60cefd74cb91a05f1ce7628179657 + * 118abc2c5c08542fe528a1193328b161a756db90 + * 9483c648978378a9cd128382049a88055d5b2a61 + * a67c7cd73c19592315ae184fe8dee155ef6ebd31 + * 4856729bd75c78e4e1e4e35ab5afd7cef6c66afc + * a2d558581c3cd9b3d62f916825405cebd708f268 + * b46a39a57e4801f5c41b1bac207239b6ed8e31a5 + * cbdf27e254b0a113f0bea87071177f083e3f2545 + * 00ec9369ac4875a8e3903d6e41ae785bbc8e8b26 + * 114d4200eaa572525089795cf7990c3dafd5028c + * ed4be6afa7b34fe0d827cc3f7f9608de0d9325cd + * a7f9df50cecec46bb8176382faa685ce35ca72be + * 15d1e3bf3d259ea262f3d34e8c225a3abfabaa09 +--- + crypt-sha256.c | 326 ++++++++++++++++++++++++------------------------- + 1 file changed, 162 insertions(+), 164 deletions(-) + +diff --git a/crypt-sha256.c b/crypt-sha256.c +index c2954a4..e036a18 100644 +--- a/crypt-sha256.c ++++ b/crypt-sha256.c +@@ -1,13 +1,15 @@ + /* One way encryption based on the SHA256-based Unix crypt implementation. + * + * Written by Ulrich Drepper in 2007 [1]. +- * To the extent possible under law, Ulrich Drepper has waived all ++ * Modified by Zack Weinberg in 2017, 2018. ++ * Composed by Björn Esser in 2018. ++ * To the extent possible under law, the named authors have waived all + * copyright and related or neighboring rights to this work. + * + * See https://creativecommons.org/publicdomain/zero/1.0/ for further + * details. + * +- * This file is an except from [2], lines 648 up to 909. ++ * This file is a modified except from [2], lines 648 up to 909. + * + * [1] https://www.akkadia.org/drepper/sha-crypt.html + * [2] https://www.akkadia.org/drepper/SHA-crypt.txt +@@ -39,8 +41,35 @@ static const char sha256_rounds_prefix[] = "rounds="; + /* Maximum number of rounds. */ + #define ROUNDS_MAX 999999999 + ++/* The maximum possible length of a SHA256-hashed password string, ++ including the terminating NUL character. Prefix (including its NUL) ++ + rounds tag ("rounds=$" = "rounds=\0") + strlen(ROUNDS_MAX) ++ + salt (up to SALT_LEN_MAX chars) + '$' + hash (43 chars). */ ++ ++#define LENGTH_OF_NUMBER(n) (sizeof #n - 1) ++ ++#define SHA256_HASH_LENGTH \ ++ (sizeof (sha256_salt_prefix) + sizeof (sha256_rounds_prefix) + \ ++ LENGTH_OF_NUMBER (ROUNDS_MAX) + SALT_LEN_MAX + 1 + 43) ++ ++static_assert (SHA256_HASH_LENGTH <= CRYPT_OUTPUT_SIZE, ++ "CRYPT_OUTPUT_SIZE is too small for SHA256"); ++ ++/* A sha256_buffer holds all of the sensitive intermediate data. */ ++struct sha256_buffer ++{ ++ struct sha256_ctx ctx; ++ uint8_t result[32]; ++ uint8_t p_bytes[32]; ++ uint8_t s_bytes[32]; ++}; ++ ++static_assert (sizeof (struct sha256_buffer) <= ALG_SPECIFIC_SIZE, ++ "ALG_SPECIFIC_SIZE is too small for SHA256"); ++ ++ + /* Table with characters for base64 transformation. */ +-static const char b64t[64] = ++static const char b64t[] = + "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; + + /* Subroutine of _xcrypt_crypt_sha256_rn: Feed CTX with LEN bytes of a +@@ -56,23 +85,30 @@ sha256_process_recycled_bytes (unsigned char block[32], size_t len, + sha256_process_bytes (block, cnt, ctx); + } + +-static char * +-sha256_crypt_r (const char *key, const char *salt, char *buffer, int buflen) ++void ++crypt_sha256_rn (const char *phrase, size_t phr_size, ++ const char *setting, size_t ARG_UNUSED (set_size), ++ uint8_t *output, size_t out_size, ++ void *scratch, size_t scr_size) + { +- unsigned char alt_result[32] +- __attribute__ ((__aligned__ (__alignof__ (uint32_t)))); +- unsigned char temp_result[32] +- __attribute__ ((__aligned__ (__alignof__ (uint32_t)))); +- struct sha256_ctx ctx; +- struct sha256_ctx alt_ctx; +- size_t salt_len; +- size_t key_len; ++ /* This shouldn't ever happen, but... */ ++ if (out_size < SHA256_HASH_LENGTH ++ || scr_size < sizeof (struct sha256_buffer)) ++ { ++ errno = ERANGE; ++ return; ++ } ++ ++ struct sha256_buffer *buf = scratch; ++ struct sha256_ctx *ctx = &buf->ctx; ++ uint8_t *result = buf->result; ++ uint8_t *p_bytes = buf->p_bytes; ++ uint8_t *s_bytes = buf->s_bytes; ++ char *cp = (char *)output; ++ const char *salt = setting; ++ ++ size_t salt_size; + size_t cnt; +- char *cp; +- char *copied_key = NULL; +- char *copied_salt = NULL; +- char *p_bytes; +- char *s_bytes; + /* Default number of rounds. */ + size_t rounds = ROUNDS_DEFAULT; + bool rounds_custom = false; +@@ -87,214 +123,176 @@ sha256_crypt_r (const char *key, const char *salt, char *buffer, int buflen) + == 0) + { + const char *num = salt + sizeof (sha256_rounds_prefix) - 1; +- char *endp; +- unsigned long int srounds = strtoul (num, &endp, 10); +- if (*endp == '$') ++ /* Do not allow an explicit setting of zero rounds, nor of the ++ default number of rounds, nor leading zeroes on the rounds. */ ++ if (!(*num >= '1' && *num <= '9')) + { +- salt = endp + 1; +- rounds = MAX (ROUNDS_MIN, MIN (srounds, ROUNDS_MAX)); +- rounds_custom = true; ++ errno = EINVAL; ++ return; + } +- } +- +- salt_len = MIN (strcspn (salt, "$"), SALT_LEN_MAX); +- key_len = strlen (key); + +- if ((key - (char *) 0) % __alignof__ (uint32_t) != 0) +- { +- char *tmp = (char *) alloca (key_len + __alignof__ (uint32_t)); +- key = copied_key = +- memcpy (tmp + __alignof__ (uint32_t) +- - (tmp - (char *) 0) % __alignof__ (uint32_t), +- key, key_len); ++ errno = 0; ++ char *endp; ++ rounds = strtoul (num, &endp, 10); ++ if (endp == num || *endp != '$' ++ || rounds < ROUNDS_MIN ++ || rounds > ROUNDS_MAX ++ || errno) ++ { ++ errno = EINVAL; ++ return; ++ } ++ salt = endp + 1; ++ rounds_custom = true; + } + +- if ((salt - (char *) 0) % __alignof__ (uint32_t) != 0) ++ salt_size = strspn (salt, b64t); ++ if (salt[salt_size] && salt[salt_size] != '$') + { +- char *tmp = (char *) alloca (salt_len + __alignof__ (uint32_t)); +- salt = copied_salt = +- memcpy (tmp + __alignof__ (uint32_t) +- - (tmp - (char *) 0) % __alignof__ (uint32_t), +- salt, salt_len); ++ errno = EINVAL; ++ return; + } ++ if (salt_size > SALT_LEN_MAX) ++ salt_size = SALT_LEN_MAX; + +- /* Prepare for the real work. */ +- sha256_init_ctx (&ctx); ++ /* Compute alternate SHA256 sum with input PHRASE, SALT, and PHRASE. The ++ final result will be added to the first context. */ ++ sha256_init_ctx (ctx); + +- /* Add the key string. */ +- sha256_process_bytes (key, key_len, &ctx); ++ /* Add phrase. */ ++ sha256_process_bytes (phrase, phr_size, ctx); + +- /* The last part is the salt string. This must be at most 16 +- characters and it ends at the first `$' character (for +- compatibility with existing implementations). */ +- sha256_process_bytes (salt, salt_len, &ctx); ++ /* Add salt. */ ++ sha256_process_bytes (salt, salt_size, ctx); + +- /* Compute alternate SHA256 sum with input KEY, SALT, and KEY. The +- final result will be added to the first context. */ +- sha256_init_ctx (&alt_ctx); ++ /* Add phrase again. */ ++ sha256_process_bytes (phrase, phr_size, ctx); + +- /* Add key. */ +- sha256_process_bytes (key, key_len, &alt_ctx); ++ /* Now get result of this (32 bytes). */ ++ sha256_finish_ctx (ctx, result); + +- /* Add salt. */ +- sha256_process_bytes (salt, salt_len, &alt_ctx); ++ /* Prepare for the real work. */ ++ sha256_init_ctx (ctx); + +- /* Add key again. */ +- sha256_process_bytes (key, key_len, &alt_ctx); ++ /* Add the phrase string. */ ++ sha256_process_bytes (phrase, phr_size, ctx); + +- /* Now get result of this (32 bytes) and add it to the other +- context. */ +- sha256_finish_ctx (&alt_ctx, alt_result); ++ /* 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). */ ++ sha256_process_bytes (salt, salt_size, ctx); + +- /* Add for any character in the key one byte of the alternate sum. */ +- for (cnt = key_len; cnt > 32; cnt -= 32) +- sha256_process_bytes (alt_result, 32, &ctx); +- sha256_process_bytes (alt_result, cnt, &ctx); ++ /* Add for any character in the phrase one byte of the alternate sum. */ ++ for (cnt = phr_size; cnt > 32; cnt -= 32) ++ sha256_process_bytes (result, 32, ctx); ++ sha256_process_bytes (result, cnt, ctx); + +- /* Take the binary representation of the length of the key and for every +- 1 add the alternate sum, for every 0 the key. */ +- for (cnt = key_len; cnt > 0; cnt >>= 1) ++ /* 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) +- sha256_process_bytes (alt_result, 32, &ctx); ++ sha256_process_bytes (result, 32, ctx); + else +- sha256_process_bytes (key, key_len, &ctx); ++ sha256_process_bytes (phrase, phr_size, ctx); + + /* Create intermediate result. */ +- sha256_finish_ctx (&ctx, alt_result); ++ sha256_finish_ctx (ctx, result); + + /* Start computation of P byte sequence. */ +- sha256_init_ctx (&alt_ctx); ++ sha256_init_ctx (ctx); + + /* For every character in the password add the entire password. */ +- for (cnt = 0; cnt < key_len; ++cnt) +- sha256_process_bytes (key, key_len, &alt_ctx); ++ for (cnt = 0; cnt < phr_size; ++cnt) ++ sha256_process_bytes (phrase, phr_size, ctx); + + /* Finish the digest. */ +- sha256_finish_ctx (&alt_ctx, temp_result); +- +- /* Create byte sequence P. */ +- cp = p_bytes = alloca (key_len); +- for (cnt = key_len; cnt >= 32; cnt -= 32) +- cp = mempcpy (cp, temp_result, 32); +- memcpy (cp, temp_result, cnt); ++ sha256_finish_ctx (ctx, p_bytes); + + /* Start computation of S byte sequence. */ +- sha256_init_ctx (&alt_ctx); ++ sha256_init_ctx (ctx); + + /* For every character in the password add the entire password. */ +- for (cnt = 0; cnt < 16 + alt_result[0]; ++cnt) +- sha256_process_bytes (salt, salt_len, &alt_ctx); ++ for (cnt = 0; cnt < (size_t) 16 + (size_t) result[0]; ++cnt) ++ sha256_process_bytes (salt, salt_size, ctx); + + /* Finish the digest. */ +- sha256_finish_ctx (&alt_ctx, temp_result); +- +- /* Create byte sequence S. */ +- cp = s_bytes = alloca (salt_len); +- for (cnt = salt_len; cnt >= 32; cnt -= 32) +- cp = mempcpy (cp, temp_result, 32); +- memcpy (cp, temp_result, cnt); ++ sha256_finish_ctx (ctx, s_bytes); + + /* Repeatedly run the collected hash value through SHA256 to burn + CPU cycles. */ + for (cnt = 0; cnt < rounds; ++cnt) + { + /* New context. */ +- sha256_init_ctx (&ctx); ++ sha256_init_ctx (ctx); + +- /* Add key or last result. */ ++ /* Add phrase or last result. */ + if ((cnt & 1) != 0) +- sha256_process_bytes (p_bytes, key_len, &ctx); ++ sha256_process_recycled_bytes (p_bytes, phr_size, ctx); + else +- sha256_process_bytes (alt_result, 32, &ctx); ++ sha256_process_bytes (result, 32, ctx); + + /* Add salt for numbers not divisible by 3. */ + if (cnt % 3 != 0) +- sha256_process_bytes (s_bytes, salt_len, &ctx); ++ sha256_process_recycled_bytes (s_bytes, salt_size, ctx); + +- /* Add key for numbers not divisible by 7. */ ++ /* Add phrase for numbers not divisible by 7. */ + if (cnt % 7 != 0) +- sha256_process_bytes (p_bytes, key_len, &ctx); ++ sha256_process_recycled_bytes (p_bytes, phr_size, ctx); + +- /* Add key or last result. */ ++ /* Add phrase or last result. */ + if ((cnt & 1) != 0) +- sha256_process_bytes (alt_result, 32, &ctx); ++ sha256_process_bytes (result, 32, ctx); + else +- sha256_process_bytes (p_bytes, key_len, &ctx); ++ sha256_process_recycled_bytes (p_bytes, phr_size, ctx); + + /* Create intermediate result. */ +- sha256_finish_ctx (&ctx, alt_result); ++ sha256_finish_ctx (ctx, result); + } + +- /* Now we can construct the result string. It consists of three +- parts. */ +- cp = stpncpy (buffer, sha256_salt_prefix, MAX (0, buflen)); +- buflen -= sizeof (sha256_salt_prefix) - 1; ++ /* Now we can construct the result string. It consists of four ++ parts, one of which is optional. We already know that there ++ is sufficient space at CP for the longest possible result string. */ ++ memcpy (cp, sha256_salt_prefix, sizeof (sha256_salt_prefix) - 1); ++ cp += sizeof (sha256_salt_prefix) - 1; + + if (rounds_custom) + { +- int n = snprintf (cp, MAX (0, buflen), "%s%zu$", +- sha256_rounds_prefix, rounds); ++ int n = snprintf (cp, ++ SHA256_HASH_LENGTH - (sizeof (sha256_salt_prefix) - 1), ++ "%s%zu$", sha256_rounds_prefix, rounds); + cp += n; +- buflen -= n; +- } +- +- cp = stpncpy (cp, salt, MIN ((size_t) MAX (0, buflen), salt_len)); +- buflen -= MIN ((size_t) MAX (0, buflen), salt_len); +- +- if (buflen > 0) +- { +- *cp++ = '$'; +- --buflen; + } + +-#define b64_from_24bit(B2, B1, B0, N) \ +- do { \ +- unsigned int w = ((B2) << 16) | ((B1) << 8) | (B0); \ +- int n = (N); \ +- while (n-- > 0 && buflen > 0) \ +- { \ +- *cp++ = b64t[w & 0x3f]; \ +- --buflen; \ +- w >>= 6; \ +- } \ ++ memcpy (cp, salt, salt_size); ++ cp += salt_size; ++ *cp++ = '$'; ++ ++#define b64_from_24bit(B2, B1, B0, N) \ ++ do { \ ++ unsigned int w = ((((unsigned int)(B2)) << 16) | \ ++ (((unsigned int)(B1)) << 8) | \ ++ ((unsigned int)(B0))); \ ++ int n = (N); \ ++ while (n-- > 0) \ ++ { \ ++ *cp++ = b64t[w & 0x3f]; \ ++ w >>= 6; \ ++ } \ + } while (0) + +- b64_from_24bit (alt_result[0], alt_result[10], alt_result[20], 4); +- b64_from_24bit (alt_result[21], alt_result[1], alt_result[11], 4); +- b64_from_24bit (alt_result[12], alt_result[22], alt_result[2], 4); +- b64_from_24bit (alt_result[3], alt_result[13], alt_result[23], 4); +- b64_from_24bit (alt_result[24], alt_result[4], alt_result[14], 4); +- b64_from_24bit (alt_result[15], alt_result[25], alt_result[5], 4); +- b64_from_24bit (alt_result[6], alt_result[16], alt_result[26], 4); +- b64_from_24bit (alt_result[27], alt_result[7], alt_result[17], 4); +- b64_from_24bit (alt_result[18], alt_result[28], alt_result[8], 4); +- b64_from_24bit (alt_result[9], alt_result[19], alt_result[29], 4); +- b64_from_24bit (0, alt_result[31], alt_result[30], 3); +- if (buflen <= 0) +- { +- errno = ERANGE; +- buffer = NULL; +- } +- else +- *cp = '\0'; /* Terminate the string. */ +- +- /* Clear the buffer for the intermediate result so that people +- attaching to processes or reading core dumps cannot get any +- information. We do it in this way to clear correct_words[] +- inside the SHA256 implementation as well. */ +- sha256_init_ctx (&ctx); +- sha256_finish_ctx (&ctx, alt_result); +- memset (temp_result, '\0', sizeof (temp_result)); +- memset (p_bytes, '\0', key_len); +- memset (s_bytes, '\0', salt_len); +- memset (&ctx, '\0', sizeof (ctx)); +- memset (&alt_ctx, '\0', sizeof (alt_ctx)); +- if (copied_key != NULL) +- memset (copied_key, '\0', key_len); +- if (copied_salt != NULL) +- memset (copied_salt, '\0', salt_len); +- +- return buffer; ++ b64_from_24bit (result[0], result[10], result[20], 4); ++ b64_from_24bit (result[21], result[1], result[11], 4); ++ b64_from_24bit (result[12], result[22], result[2], 4); ++ b64_from_24bit (result[3], result[13], result[23], 4); ++ b64_from_24bit (result[24], result[4], result[14], 4); ++ b64_from_24bit (result[15], result[25], result[5], 4); ++ b64_from_24bit (result[6], result[16], result[26], 4); ++ b64_from_24bit (result[27], result[7], result[17], 4); ++ b64_from_24bit (result[18], result[28], result[8], 4); ++ b64_from_24bit (result[9], result[19], result[29], 4); ++ b64_from_24bit (0, result[31], result[30], 3); ++ ++ *cp = '\0'; + } + + void + +From 989f1faae098a9345855bf733b8f35f92cefcf23 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Bj=C3=B6rn=20Esser?= +Date: Sat, 14 Jul 2018 21:40:34 +0200 +Subject: [PATCH 05/10] Replace crypt-sha512.c with an implementation in the + Public Domain. + +This implementation is based on the SHA512-based Unix crypt +implementation. Released into the Public Domain [1] by +Ulrich Drepper . + +This file is a modified except from [2], lines 1403 up to 1676. + +[1] https://www.akkadia.org/drepper/sha-crypt.html +[2] https://www.akkadia.org/drepper/SHA-crypt.txt +--- + crypt-sha512.c | 383 ++++++++++++++++++++++++------------------------- + 1 file changed, 191 insertions(+), 192 deletions(-) + +diff --git a/crypt-sha512.c b/crypt-sha512.c +index 955a27b..f3798a0 100644 +--- a/crypt-sha512.c ++++ b/crypt-sha512.c +@@ -1,20 +1,17 @@ +-/* One way encryption based on SHA512 sum. +- +- 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 +- . */ ++/* One way encryption based on the SHA512-based Unix crypt implementation. ++ * ++ * Written by Ulrich Drepper in 2007 [1]. ++ * To the extent possible under law, Ulrich Drepper has waived all ++ * copyright and related or neighboring rights to this work. ++ * ++ * See https://creativecommons.org/publicdomain/zero/1.0/ for further ++ * details. ++ * ++ * This file is a modified except from [2], lines 1403 up to 1676. ++ * ++ * [1] https://www.akkadia.org/drepper/sha-crypt.html ++ * [2] https://www.akkadia.org/drepper/SHA-crypt.txt ++ */ + + #include "crypt-port.h" + #include "crypt-private.h" +@@ -42,36 +39,9 @@ static const char sha512_rounds_prefix[] = "rounds="; + /* Maximum number of rounds. */ + #define ROUNDS_MAX 999999999 + +-/* The maximum possible length of a SHA512-hashed password string, +- including the terminating NUL character. Prefix (including its NUL) +- + rounds tag ("rounds=$" = "rounds=\0") + strlen(ROUNDS_MAX) +- + salt (up to SALT_LEN_MAX chars) + '$' + hash (86 chars). */ +- +-#define LENGTH_OF_NUMBER(n) (sizeof #n - 1) +- +-#define SHA512_HASH_LENGTH \ +- (sizeof (sha512_salt_prefix) + sizeof (sha512_rounds_prefix) + \ +- LENGTH_OF_NUMBER (ROUNDS_MAX) + SALT_LEN_MAX + 1 + 86) +- +-static_assert (SHA512_HASH_LENGTH <= CRYPT_OUTPUT_SIZE, +- "CRYPT_OUTPUT_SIZE is too small for SHA512"); +- +-/* A sha512_buffer holds all of the sensitive intermediate data. */ +-struct sha512_buffer +-{ +- struct sha512_ctx ctx; +- uint8_t result[64]; +- uint8_t p_bytes[64]; +- uint8_t s_bytes[64]; +-}; +- +-static_assert (sizeof (struct sha512_buffer) <= ALG_SPECIFIC_SIZE, +- "ALG_SPECIFIC_SIZE is too small for SHA512"); +- +- + /* Table with characters for base64 transformation. */ +-static const char b64t[] = +- "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; ++static const char b64t[64] = ++"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; + + /* Subroutine of _xcrypt_crypt_sha512_rn: Feed CTX with LEN bytes of a + virtual byte sequence consisting of BLOCK repeated over and over +@@ -86,30 +56,23 @@ sha512_process_recycled_bytes (unsigned char block[64], size_t len, + sha512_process_bytes (block, cnt, ctx); + } + +-void +-crypt_sha512_rn (const char *phrase, size_t phr_size, +- const char *setting, size_t ARG_UNUSED (set_size), +- uint8_t *output, size_t out_size, +- void *scratch, size_t scr_size) ++static char * ++sha512_crypt_r (const char *key, const char *salt, char *buffer, int buflen) + { +- /* This shouldn't ever happen, but... */ +- if (out_size < SHA512_HASH_LENGTH +- || scr_size < sizeof (struct sha512_buffer)) +- { +- errno = ERANGE; +- return; +- } +- +- struct sha512_buffer *buf = scratch; +- struct sha512_ctx *ctx = &buf->ctx; +- uint8_t *result = buf->result; +- uint8_t *p_bytes = buf->p_bytes; +- uint8_t *s_bytes = buf->s_bytes; +- char *cp = (char *)output; +- const char *salt = setting; +- +- size_t salt_size; ++ unsigned char alt_result[64] ++ __attribute__ ((__aligned__ (__alignof__ (uint64_t)))); ++ unsigned char temp_result[64] ++ __attribute__ ((__aligned__ (__alignof__ (uint64_t)))); ++ struct sha512_ctx ctx; ++ struct sha512_ctx alt_ctx; ++ size_t salt_len; ++ size_t key_len; + size_t cnt; ++ char *cp; ++ char *copied_key = NULL; ++ char *copied_salt = NULL; ++ char *p_bytes; ++ char *s_bytes; + /* Default number of rounds. */ + size_t rounds = ROUNDS_DEFAULT; + bool rounds_custom = false; +@@ -124,191 +87,227 @@ crypt_sha512_rn (const char *phrase, size_t phr_size, + == 0) + { + const char *num = salt + sizeof (sha512_rounds_prefix) - 1; +- /* Do not allow an explicit setting of zero rounds, nor of the +- default number of rounds, nor leading zeroes on the rounds. */ +- if (!(*num >= '1' && *num <= '9')) +- { +- errno = EINVAL; +- return; +- } +- +- errno = 0; + char *endp; +- rounds = strtoul (num, &endp, 10); +- if (endp == num || *endp != '$' +- || rounds < ROUNDS_MIN +- || rounds > ROUNDS_MAX +- || errno) +- { +- errno = EINVAL; +- return; +- } +- salt = endp + 1; +- rounds_custom = true; ++ unsigned long int srounds = strtoul (num, &endp, 10); ++ if (*endp == '$') ++ { ++ salt = endp + 1; ++ rounds = MAX (ROUNDS_MIN, MIN (srounds, ROUNDS_MAX)); ++ rounds_custom = true; ++ } ++ } ++ ++ salt_len = MIN (strcspn (salt, "$"), SALT_LEN_MAX); ++ key_len = strlen (key); ++ ++ if ((key - (char *) 0) % __alignof__ (uint64_t) != 0) ++ { ++ char *tmp = (char *) alloca (key_len + __alignof__ (uint64_t)); ++ key = copied_key = ++ memcpy (tmp + __alignof__ (uint64_t) ++ - (tmp - (char *) 0) % __alignof__ (uint64_t), ++ key, key_len); + } + +- salt_size = strspn (salt, b64t); +- if (salt[salt_size] && salt[salt_size] != '$') ++ if ((salt - (char *) 0) % __alignof__ (uint64_t) != 0) + { +- errno = EINVAL; +- return; ++ char *tmp = (char *) alloca (salt_len + __alignof__ (uint64_t)); ++ salt = copied_salt = ++ memcpy (tmp + __alignof__ (uint64_t) ++ - (tmp - (char *) 0) % __alignof__ (uint64_t), ++ salt, salt_len); + } +- if (salt_size > SALT_LEN_MAX) +- salt_size = SALT_LEN_MAX; +- phr_size = strlen (phrase); + +- /* Compute alternate SHA512 sum with input PHRASE, SALT, and PHRASE. The ++ /* Prepare for the real work. */ ++ sha512_init_ctx (&ctx); ++ ++ /* Add the key string. */ ++ sha512_process_bytes (key, key_len, &ctx); ++ ++ /* The last part is the salt string. This must be at most 16 ++ characters and it ends at the first `$' character (for ++ compatibility with existing implementations). */ ++ sha512_process_bytes (salt, salt_len, &ctx); ++ ++ ++ /* Compute alternate SHA512 sum with input KEY, SALT, and KEY. The + final result will be added to the first context. */ +- sha512_init_ctx (ctx); ++ sha512_init_ctx (&alt_ctx); + +- /* Add phrase. */ +- sha512_process_bytes (phrase, phr_size, ctx); ++ /* Add key. */ ++ sha512_process_bytes (key, key_len, &alt_ctx); + + /* Add salt. */ +- sha512_process_bytes (salt, salt_size, ctx); ++ sha512_process_bytes (salt, salt_len, &alt_ctx); + +- /* Add phrase again. */ +- sha512_process_bytes (phrase, phr_size, ctx); ++ /* Add key again. */ ++ sha512_process_bytes (key, key_len, &alt_ctx); + + /* Now get result of this (64 bytes) and add it to the other + context. */ +- sha512_finish_ctx (ctx, result); +- +- /* Prepare for the real work. */ +- sha512_init_ctx (ctx); ++ sha512_finish_ctx (&alt_ctx, alt_result); + +- /* Add the phrase string. */ +- sha512_process_bytes (phrase, phr_size, ctx); +- +- /* 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); ++ /* Add for any character in the key one byte of the alternate sum. */ ++ for (cnt = key_len; cnt > 64; cnt -= 64) ++ sha512_process_bytes (alt_result, 64, &ctx); ++ sha512_process_bytes (alt_result, cnt, &ctx); + +- /* 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); +- +- /* 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) ++ /* Take the binary representation of the length of the key and for every ++ 1 add the alternate sum, for every 0 the key. */ ++ for (cnt = key_len; cnt > 0; cnt >>= 1) + if ((cnt & 1) != 0) +- sha512_process_bytes (result, 64, ctx); ++ sha512_process_bytes (alt_result, 64, &ctx); + else +- sha512_process_bytes (phrase, phr_size, ctx); ++ sha512_process_bytes (key, key_len, &ctx); + + /* Create intermediate result. */ +- sha512_finish_ctx (ctx, result); ++ sha512_finish_ctx (&ctx, alt_result); + + /* Start computation of P byte sequence. */ +- sha512_init_ctx (ctx); ++ sha512_init_ctx (&alt_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); ++ for (cnt = 0; cnt < key_len; ++cnt) ++ sha512_process_bytes (key, key_len, &alt_ctx); + + /* Finish the digest. */ +- sha512_finish_ctx (ctx, p_bytes); ++ sha512_finish_ctx (&alt_ctx, temp_result); ++ ++ /* Create byte sequence P. */ ++ cp = p_bytes = alloca (key_len); ++ for (cnt = key_len; cnt >= 64; cnt -= 64) ++ cp = mempcpy (cp, temp_result, 64); ++ memcpy (cp, temp_result, cnt); + + /* Start computation of S byte sequence. */ +- sha512_init_ctx (ctx); ++ sha512_init_ctx (&alt_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); ++ for (cnt = 0; cnt < 16 + alt_result[0]; ++cnt) ++ sha512_process_bytes (salt, salt_len, &alt_ctx); + + /* Finish the digest. */ +- sha512_finish_ctx (ctx, s_bytes); ++ sha512_finish_ctx (&alt_ctx, temp_result); ++ ++ /* Create byte sequence S. */ ++ cp = s_bytes = alloca (salt_len); ++ for (cnt = salt_len; cnt >= 64; cnt -= 64) ++ cp = mempcpy (cp, temp_result, 64); ++ memcpy (cp, temp_result, cnt); + + /* 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 (&ctx); + +- /* Add phrase or last result. */ ++ /* Add key or last result. */ + if ((cnt & 1) != 0) +- sha512_process_recycled_bytes (p_bytes, phr_size, ctx); ++ sha512_process_bytes (p_bytes, key_len, &ctx); + else +- sha512_process_bytes (result, 64, ctx); ++ sha512_process_bytes (alt_result, 64, &ctx); + + /* Add salt for numbers not divisible by 3. */ + if (cnt % 3 != 0) +- sha512_process_recycled_bytes (s_bytes, salt_size, ctx); ++ sha512_process_bytes (s_bytes, salt_len, &ctx); + +- /* Add phrase for numbers not divisible by 7. */ ++ /* Add key for numbers not divisible by 7. */ + if (cnt % 7 != 0) +- sha512_process_recycled_bytes (p_bytes, phr_size, ctx); ++ sha512_process_bytes (p_bytes, key_len, &ctx); + +- /* Add phrase or last result. */ ++ /* Add key or last result. */ + if ((cnt & 1) != 0) +- sha512_process_bytes (result, 64, ctx); ++ sha512_process_bytes (alt_result, 64, &ctx); + else +- sha512_process_recycled_bytes (p_bytes, phr_size, ctx); ++ sha512_process_bytes (p_bytes, key_len, &ctx); + + /* Create intermediate result. */ +- sha512_finish_ctx (ctx, result); ++ sha512_finish_ctx (&ctx, alt_result); + } + +- /* Now we can construct the result string. It consists of four +- parts, one of which is optional. We already know that buflen is +- at least sha512_hash_length, therefore none of the string bashing +- below can overflow the buffer. */ +- +- memcpy (cp, sha512_salt_prefix, sizeof (sha512_salt_prefix) - 1); +- cp += sizeof (sha512_salt_prefix) - 1; ++ /* Now we can construct the result string. It consists of three ++ parts. */ ++ cp = __stpncpy (buffer, sha512_salt_prefix, MAX (0, buflen)); ++ buflen -= sizeof (sha512_salt_prefix) - 1; + + if (rounds_custom) + { +- int n = snprintf (cp, +- SHA512_HASH_LENGTH - (sizeof (sha512_salt_prefix) - 1), +- "%s%zu$", sha512_rounds_prefix, rounds); ++ int n = snprintf (cp, MAX (0, buflen), "%s%zu$", ++ sha512_rounds_prefix, rounds); + cp += n; ++ buflen -= n; + } + +- memcpy (cp, salt, salt_size); +- cp += salt_size; +- *cp++ = '$'; +- +-#define b64_from_24bit(B2, B1, B0, N) \ +- do { \ +- unsigned int w = ((((unsigned int)(B2)) << 16) | \ +- (((unsigned int)(B1)) << 8) | \ +- ((unsigned int)(B0))); \ +- int n = (N); \ +- while (n-- > 0) \ +- { \ +- *cp++ = b64t[w & 0x3f]; \ +- w >>= 6; \ +- } \ ++ cp = __stpncpy (cp, salt, MIN ((size_t) MAX (0, buflen), salt_len)); ++ buflen -= MIN ((size_t) MAX (0, buflen), salt_len); ++ ++ if (buflen > 0) ++ { ++ *cp++ = '$'; ++ --buflen; ++ } ++ ++#define b64_from_24bit(B2, B1, B0, N) \ ++ do { \ ++ unsigned int w = ((B2) << 16) | ((B1) << 8) | (B0); \ ++ int n = (N); \ ++ while (n-- > 0 && buflen > 0) \ ++ { \ ++ *cp++ = b64t[w & 0x3f]; \ ++ --buflen; \ ++ w >>= 6; \ ++ } \ + } while (0) + +- b64_from_24bit (result[0], result[21], result[42], 4); +- b64_from_24bit (result[22], result[43], result[1], 4); +- b64_from_24bit (result[44], result[2], result[23], 4); +- b64_from_24bit (result[3], result[24], result[45], 4); +- b64_from_24bit (result[25], result[46], result[4], 4); +- b64_from_24bit (result[47], result[5], result[26], 4); +- b64_from_24bit (result[6], result[27], result[48], 4); +- b64_from_24bit (result[28], result[49], result[7], 4); +- b64_from_24bit (result[50], result[8], result[29], 4); +- b64_from_24bit (result[9], result[30], result[51], 4); +- b64_from_24bit (result[31], result[52], result[10], 4); +- b64_from_24bit (result[53], result[11], result[32], 4); +- b64_from_24bit (result[12], result[33], result[54], 4); +- b64_from_24bit (result[34], result[55], result[13], 4); +- b64_from_24bit (result[56], result[14], result[35], 4); +- b64_from_24bit (result[15], result[36], result[57], 4); +- b64_from_24bit (result[37], result[58], result[16], 4); +- b64_from_24bit (result[59], result[17], result[38], 4); +- b64_from_24bit (result[18], result[39], result[60], 4); +- b64_from_24bit (result[40], result[61], result[19], 4); +- b64_from_24bit (result[62], result[20], result[41], 4); +- b64_from_24bit (0, 0, result[63], 2); +- +- *cp = '\0'; ++ b64_from_24bit (alt_result[0], alt_result[21], alt_result[42], 4); ++ b64_from_24bit (alt_result[22], alt_result[43], alt_result[1], 4); ++ b64_from_24bit (alt_result[44], alt_result[2], alt_result[23], 4); ++ b64_from_24bit (alt_result[3], alt_result[24], alt_result[45], 4); ++ b64_from_24bit (alt_result[25], alt_result[46], alt_result[4], 4); ++ b64_from_24bit (alt_result[47], alt_result[5], alt_result[26], 4); ++ b64_from_24bit (alt_result[6], alt_result[27], alt_result[48], 4); ++ b64_from_24bit (alt_result[28], alt_result[49], alt_result[7], 4); ++ b64_from_24bit (alt_result[50], alt_result[8], alt_result[29], 4); ++ b64_from_24bit (alt_result[9], alt_result[30], alt_result[51], 4); ++ b64_from_24bit (alt_result[31], alt_result[52], alt_result[10], 4); ++ b64_from_24bit (alt_result[53], alt_result[11], alt_result[32], 4); ++ b64_from_24bit (alt_result[12], alt_result[33], alt_result[54], 4); ++ b64_from_24bit (alt_result[34], alt_result[55], alt_result[13], 4); ++ b64_from_24bit (alt_result[56], alt_result[14], alt_result[35], 4); ++ b64_from_24bit (alt_result[15], alt_result[36], alt_result[57], 4); ++ b64_from_24bit (alt_result[37], alt_result[58], alt_result[16], 4); ++ b64_from_24bit (alt_result[59], alt_result[17], alt_result[38], 4); ++ b64_from_24bit (alt_result[18], alt_result[39], alt_result[60], 4); ++ b64_from_24bit (alt_result[40], alt_result[61], alt_result[19], 4); ++ b64_from_24bit (alt_result[62], alt_result[20], alt_result[41], 4); ++ b64_from_24bit (0, 0, alt_result[63], 2); ++ ++ if (buflen <= 0) ++ { ++ errno = ERANGE; ++ buffer = NULL; ++ } ++ else ++ *cp = '\0'; /* Terminate the string. */ ++ ++ /* Clear the buffer for the intermediate result so that people ++ attaching to processes or reading core dumps cannot get any ++ information. We do it in this way to clear correct_words[] ++ inside the SHA512 implementation as well. */ ++ sha512_init_ctx (&ctx); ++ sha512_finish_ctx (&ctx, alt_result); ++ memset (temp_result, '\0', sizeof (temp_result)); ++ memset (p_bytes, '\0', key_len); ++ memset (s_bytes, '\0', salt_len); ++ memset (&ctx, '\0', sizeof (ctx)); ++ memset (&alt_ctx, '\0', sizeof (alt_ctx)); ++ if (copied_key != NULL) ++ memset (copied_key, '\0', key_len); ++ if (copied_salt != NULL) ++ memset (copied_salt, '\0', salt_len); ++ ++ return buffer; + } + + void + +From 16abeb10230f3762c2c820b43bdb262013f2e17a Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Bj=C3=B6rn=20Esser?= +Date: Sat, 14 Jul 2018 21:44:21 +0200 +Subject: [PATCH 06/10] crypt-sha512.c: Apply previous commits from Zack + Weinberg + +This patch summarizes the changes from: + + * 4a1152b4f9bc900d0488b473e20daed95025f4b0 + * ccc833b4b2c60cefd74cb91a05f1ce7628179657 + * 118abc2c5c08542fe528a1193328b161a756db90 + * 9483c648978378a9cd128382049a88055d5b2a61 + * 4856729bd75c78e4e1e4e35ab5afd7cef6c66afc + * a2d558581c3cd9b3d62f916825405cebd708f268 + * b46a39a57e4801f5c41b1bac207239b6ed8e31a5 + * cbdf27e254b0a113f0bea87071177f083e3f2545 + * 00ec9369ac4875a8e3903d6e41ae785bbc8e8b26 + * 114d4200eaa572525089795cf7990c3dafd5028c + * ed4be6afa7b34fe0d827cc3f7f9608de0d9325cd + * a7f9df50cecec46bb8176382faa685ce35ca72be + * 15d1e3bf3d259ea262f3d34e8c225a3abfabaa09 +--- + crypt-sha512.c | 356 ++++++++++++++++++++++++------------------------- + 1 file changed, 178 insertions(+), 178 deletions(-) + +diff --git a/crypt-sha512.c b/crypt-sha512.c +index f3798a0..39ec0b5 100644 +--- a/crypt-sha512.c ++++ b/crypt-sha512.c +@@ -1,7 +1,9 @@ + /* One way encryption based on the SHA512-based Unix crypt implementation. + * + * Written by Ulrich Drepper in 2007 [1]. +- * To the extent possible under law, Ulrich Drepper has waived all ++ * Modified by Zack Weinberg in 2017, 2018. ++ * Composed by Björn Esser in 2018. ++ * To the extent possible under law, the named authors have waived all + * copyright and related or neighboring rights to this work. + * + * See https://creativecommons.org/publicdomain/zero/1.0/ for further +@@ -39,9 +41,36 @@ static const char sha512_rounds_prefix[] = "rounds="; + /* Maximum number of rounds. */ + #define ROUNDS_MAX 999999999 + ++/* The maximum possible length of a SHA512-hashed password string, ++ including the terminating NUL character. Prefix (including its NUL) ++ + rounds tag ("rounds=$" = "rounds=\0") + strlen(ROUNDS_MAX) ++ + salt (up to SALT_LEN_MAX chars) + '$' + hash (86 chars). */ ++ ++#define LENGTH_OF_NUMBER(n) (sizeof #n - 1) ++ ++#define SHA512_HASH_LENGTH \ ++ (sizeof (sha512_salt_prefix) + sizeof (sha512_rounds_prefix) + \ ++ LENGTH_OF_NUMBER (ROUNDS_MAX) + SALT_LEN_MAX + 1 + 86) ++ ++static_assert (SHA512_HASH_LENGTH <= CRYPT_OUTPUT_SIZE, ++ "CRYPT_OUTPUT_SIZE is too small for SHA512"); ++ ++/* A sha512_buffer holds all of the sensitive intermediate data. */ ++struct sha512_buffer ++{ ++ struct sha512_ctx ctx; ++ uint8_t result[64]; ++ uint8_t p_bytes[64]; ++ uint8_t s_bytes[64]; ++}; ++ ++static_assert (sizeof (struct sha512_buffer) <= ALG_SPECIFIC_SIZE, ++ "ALG_SPECIFIC_SIZE is too small for SHA512"); ++ ++ + /* Table with characters for base64 transformation. */ +-static const char b64t[64] = +-"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; ++static const char b64t[] = ++ "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; + + /* Subroutine of _xcrypt_crypt_sha512_rn: Feed CTX with LEN bytes of a + virtual byte sequence consisting of BLOCK repeated over and over +@@ -56,23 +85,30 @@ sha512_process_recycled_bytes (unsigned char block[64], size_t len, + sha512_process_bytes (block, cnt, ctx); + } + +-static char * +-sha512_crypt_r (const char *key, const char *salt, char *buffer, int buflen) ++void ++crypt_sha512_rn (const char *phrase, size_t phr_size, ++ const char *setting, size_t ARG_UNUSED (set_size), ++ uint8_t *output, size_t out_size, ++ void *scratch, size_t scr_size) + { +- unsigned char alt_result[64] +- __attribute__ ((__aligned__ (__alignof__ (uint64_t)))); +- unsigned char temp_result[64] +- __attribute__ ((__aligned__ (__alignof__ (uint64_t)))); +- struct sha512_ctx ctx; +- struct sha512_ctx alt_ctx; +- size_t salt_len; +- size_t key_len; ++ /* This shouldn't ever happen, but... */ ++ if (out_size < SHA512_HASH_LENGTH ++ || scr_size < sizeof (struct sha512_buffer)) ++ { ++ errno = ERANGE; ++ return; ++ } ++ ++ struct sha512_buffer *buf = scratch; ++ struct sha512_ctx *ctx = &buf->ctx; ++ uint8_t *result = buf->result; ++ uint8_t *p_bytes = buf->p_bytes; ++ uint8_t *s_bytes = buf->s_bytes; ++ char *cp = (char *)output; ++ const char *salt = setting; ++ ++ size_t salt_size; + size_t cnt; +- char *cp; +- char *copied_key = NULL; +- char *copied_salt = NULL; +- char *p_bytes; +- char *s_bytes; + /* Default number of rounds. */ + size_t rounds = ROUNDS_DEFAULT; + bool rounds_custom = false; +@@ -87,227 +123,191 @@ sha512_crypt_r (const char *key, const char *salt, char *buffer, int buflen) + == 0) + { + const char *num = salt + sizeof (sha512_rounds_prefix) - 1; ++ /* Do not allow an explicit setting of zero rounds, nor of the ++ default number of rounds, nor leading zeroes on the rounds. */ ++ if (!(*num >= '1' && *num <= '9')) ++ { ++ errno = EINVAL; ++ return; ++ } ++ ++ errno = 0; + char *endp; +- unsigned long int srounds = strtoul (num, &endp, 10); +- if (*endp == '$') +- { +- salt = endp + 1; +- rounds = MAX (ROUNDS_MIN, MIN (srounds, ROUNDS_MAX)); +- rounds_custom = true; +- } ++ rounds = strtoul (num, &endp, 10); ++ if (endp == num || *endp != '$' ++ || rounds < ROUNDS_MIN ++ || rounds > ROUNDS_MAX ++ || errno) ++ { ++ errno = EINVAL; ++ return; ++ } ++ salt = endp + 1; ++ rounds_custom = true; + } + +- salt_len = MIN (strcspn (salt, "$"), SALT_LEN_MAX); +- key_len = strlen (key); +- +- if ((key - (char *) 0) % __alignof__ (uint64_t) != 0) ++ salt_size = strspn (salt, b64t); ++ if (salt[salt_size] && salt[salt_size] != '$') + { +- char *tmp = (char *) alloca (key_len + __alignof__ (uint64_t)); +- key = copied_key = +- memcpy (tmp + __alignof__ (uint64_t) +- - (tmp - (char *) 0) % __alignof__ (uint64_t), +- key, key_len); ++ errno = EINVAL; ++ return; + } ++ if (salt_size > SALT_LEN_MAX) ++ salt_size = SALT_LEN_MAX; ++ phr_size = strlen (phrase); + +- if ((salt - (char *) 0) % __alignof__ (uint64_t) != 0) +- { +- char *tmp = (char *) alloca (salt_len + __alignof__ (uint64_t)); +- salt = copied_salt = +- memcpy (tmp + __alignof__ (uint64_t) +- - (tmp - (char *) 0) % __alignof__ (uint64_t), +- salt, salt_len); +- } +- +- /* Prepare for the real work. */ +- sha512_init_ctx (&ctx); +- +- /* Add the key string. */ +- sha512_process_bytes (key, key_len, &ctx); +- +- /* The last part is the salt string. This must be at most 16 +- characters and it ends at the first `$' character (for +- compatibility with existing implementations). */ +- sha512_process_bytes (salt, salt_len, &ctx); +- +- +- /* Compute alternate SHA512 sum with input KEY, SALT, and KEY. The ++ /* Compute alternate SHA512 sum with input PHRASE, SALT, and PHRASE. The + final result will be added to the first context. */ +- sha512_init_ctx (&alt_ctx); ++ sha512_init_ctx (ctx); + +- /* Add key. */ +- sha512_process_bytes (key, key_len, &alt_ctx); ++ /* Add phrase. */ ++ sha512_process_bytes (phrase, phr_size, ctx); + + /* Add salt. */ +- sha512_process_bytes (salt, salt_len, &alt_ctx); ++ sha512_process_bytes (salt, salt_size, ctx); + +- /* Add key again. */ +- sha512_process_bytes (key, key_len, &alt_ctx); ++ /* Add phrase again. */ ++ sha512_process_bytes (phrase, phr_size, ctx); + + /* Now get result of this (64 bytes) and add it to the other + context. */ +- sha512_finish_ctx (&alt_ctx, alt_result); ++ sha512_finish_ctx (ctx, result); ++ ++ /* Prepare for the real work. */ ++ sha512_init_ctx (ctx); ++ ++ /* Add the phrase string. */ ++ sha512_process_bytes (phrase, phr_size, ctx); ++ ++ /* 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); + +- /* Add for any character in the key one byte of the alternate sum. */ +- for (cnt = key_len; cnt > 64; cnt -= 64) +- sha512_process_bytes (alt_result, 64, &ctx); +- sha512_process_bytes (alt_result, cnt, &ctx); ++ /* 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); + +- /* Take the binary representation of the length of the key and for every +- 1 add the alternate sum, for every 0 the key. */ +- for (cnt = key_len; cnt > 0; cnt >>= 1) ++ /* 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 (alt_result, 64, &ctx); ++ sha512_process_bytes (result, 64, ctx); + else +- sha512_process_bytes (key, key_len, &ctx); ++ sha512_process_bytes (phrase, phr_size, ctx); + + /* Create intermediate result. */ +- sha512_finish_ctx (&ctx, alt_result); ++ sha512_finish_ctx (ctx, result); + + /* Start computation of P byte sequence. */ +- sha512_init_ctx (&alt_ctx); ++ sha512_init_ctx (ctx); + + /* For every character in the password add the entire password. */ +- for (cnt = 0; cnt < key_len; ++cnt) +- sha512_process_bytes (key, key_len, &alt_ctx); ++ for (cnt = 0; cnt < phr_size; ++cnt) ++ sha512_process_bytes (phrase, phr_size, ctx); + + /* Finish the digest. */ +- sha512_finish_ctx (&alt_ctx, temp_result); +- +- /* Create byte sequence P. */ +- cp = p_bytes = alloca (key_len); +- for (cnt = key_len; cnt >= 64; cnt -= 64) +- cp = mempcpy (cp, temp_result, 64); +- memcpy (cp, temp_result, cnt); ++ sha512_finish_ctx (ctx, p_bytes); + + /* Start computation of S byte sequence. */ +- sha512_init_ctx (&alt_ctx); ++ sha512_init_ctx (ctx); + + /* For every character in the password add the entire password. */ +- for (cnt = 0; cnt < 16 + alt_result[0]; ++cnt) +- sha512_process_bytes (salt, salt_len, &alt_ctx); ++ for (cnt = 0; cnt < (size_t) 16 + (size_t) result[0]; ++cnt) ++ sha512_process_bytes (salt, salt_size, ctx); + + /* Finish the digest. */ +- sha512_finish_ctx (&alt_ctx, temp_result); +- +- /* Create byte sequence S. */ +- cp = s_bytes = alloca (salt_len); +- for (cnt = salt_len; cnt >= 64; cnt -= 64) +- cp = mempcpy (cp, temp_result, 64); +- memcpy (cp, temp_result, cnt); ++ sha512_finish_ctx (ctx, s_bytes); + + /* 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 (ctx); + +- /* Add key or last result. */ ++ /* Add phrase or last result. */ + if ((cnt & 1) != 0) +- sha512_process_bytes (p_bytes, key_len, &ctx); ++ sha512_process_recycled_bytes (p_bytes, phr_size, ctx); + else +- sha512_process_bytes (alt_result, 64, &ctx); ++ sha512_process_bytes (result, 64, ctx); + + /* Add salt for numbers not divisible by 3. */ + if (cnt % 3 != 0) +- sha512_process_bytes (s_bytes, salt_len, &ctx); ++ sha512_process_recycled_bytes (s_bytes, salt_size, ctx); + +- /* Add key for numbers not divisible by 7. */ ++ /* Add phrase for numbers not divisible by 7. */ + if (cnt % 7 != 0) +- sha512_process_bytes (p_bytes, key_len, &ctx); ++ sha512_process_recycled_bytes (p_bytes, phr_size, ctx); + +- /* Add key or last result. */ ++ /* Add phrase or last result. */ + if ((cnt & 1) != 0) +- sha512_process_bytes (alt_result, 64, &ctx); ++ sha512_process_bytes (result, 64, ctx); + else +- sha512_process_bytes (p_bytes, key_len, &ctx); ++ sha512_process_recycled_bytes (p_bytes, phr_size, ctx); + + /* Create intermediate result. */ +- sha512_finish_ctx (&ctx, alt_result); ++ sha512_finish_ctx (ctx, result); + } + +- /* Now we can construct the result string. It consists of three +- parts. */ +- cp = __stpncpy (buffer, sha512_salt_prefix, MAX (0, buflen)); +- buflen -= sizeof (sha512_salt_prefix) - 1; ++ /* Now we can construct the result string. It consists of four ++ parts, one of which is optional. We already know that buflen is ++ at least sha512_hash_length, therefore none of the string bashing ++ below can overflow the buffer. */ ++ ++ memcpy (cp, sha512_salt_prefix, sizeof (sha512_salt_prefix) - 1); ++ cp += sizeof (sha512_salt_prefix) - 1; + + if (rounds_custom) + { +- int n = snprintf (cp, MAX (0, buflen), "%s%zu$", +- sha512_rounds_prefix, rounds); ++ int n = snprintf (cp, ++ SHA512_HASH_LENGTH - (sizeof (sha512_salt_prefix) - 1), ++ "%s%zu$", sha512_rounds_prefix, rounds); + cp += n; +- buflen -= n; +- } +- +- cp = __stpncpy (cp, salt, MIN ((size_t) MAX (0, buflen), salt_len)); +- buflen -= MIN ((size_t) MAX (0, buflen), salt_len); +- +- if (buflen > 0) +- { +- *cp++ = '$'; +- --buflen; + } + +-#define b64_from_24bit(B2, B1, B0, N) \ +- do { \ +- unsigned int w = ((B2) << 16) | ((B1) << 8) | (B0); \ +- int n = (N); \ +- while (n-- > 0 && buflen > 0) \ +- { \ +- *cp++ = b64t[w & 0x3f]; \ +- --buflen; \ +- w >>= 6; \ +- } \ ++ memcpy (cp, salt, salt_size); ++ cp += salt_size; ++ *cp++ = '$'; ++ ++#define b64_from_24bit(B2, B1, B0, N) \ ++ do { \ ++ unsigned int w = ((((unsigned int)(B2)) << 16) | \ ++ (((unsigned int)(B1)) << 8) | \ ++ ((unsigned int)(B0))); \ ++ int n = (N); \ ++ while (n-- > 0) \ ++ { \ ++ *cp++ = b64t[w & 0x3f]; \ ++ w >>= 6; \ ++ } \ + } while (0) + +- b64_from_24bit (alt_result[0], alt_result[21], alt_result[42], 4); +- b64_from_24bit (alt_result[22], alt_result[43], alt_result[1], 4); +- b64_from_24bit (alt_result[44], alt_result[2], alt_result[23], 4); +- b64_from_24bit (alt_result[3], alt_result[24], alt_result[45], 4); +- b64_from_24bit (alt_result[25], alt_result[46], alt_result[4], 4); +- b64_from_24bit (alt_result[47], alt_result[5], alt_result[26], 4); +- b64_from_24bit (alt_result[6], alt_result[27], alt_result[48], 4); +- b64_from_24bit (alt_result[28], alt_result[49], alt_result[7], 4); +- b64_from_24bit (alt_result[50], alt_result[8], alt_result[29], 4); +- b64_from_24bit (alt_result[9], alt_result[30], alt_result[51], 4); +- b64_from_24bit (alt_result[31], alt_result[52], alt_result[10], 4); +- b64_from_24bit (alt_result[53], alt_result[11], alt_result[32], 4); +- b64_from_24bit (alt_result[12], alt_result[33], alt_result[54], 4); +- b64_from_24bit (alt_result[34], alt_result[55], alt_result[13], 4); +- b64_from_24bit (alt_result[56], alt_result[14], alt_result[35], 4); +- b64_from_24bit (alt_result[15], alt_result[36], alt_result[57], 4); +- b64_from_24bit (alt_result[37], alt_result[58], alt_result[16], 4); +- b64_from_24bit (alt_result[59], alt_result[17], alt_result[38], 4); +- b64_from_24bit (alt_result[18], alt_result[39], alt_result[60], 4); +- b64_from_24bit (alt_result[40], alt_result[61], alt_result[19], 4); +- b64_from_24bit (alt_result[62], alt_result[20], alt_result[41], 4); +- b64_from_24bit (0, 0, alt_result[63], 2); +- +- if (buflen <= 0) +- { +- errno = ERANGE; +- buffer = NULL; +- } +- else +- *cp = '\0'; /* Terminate the string. */ +- +- /* Clear the buffer for the intermediate result so that people +- attaching to processes or reading core dumps cannot get any +- information. We do it in this way to clear correct_words[] +- inside the SHA512 implementation as well. */ +- sha512_init_ctx (&ctx); +- sha512_finish_ctx (&ctx, alt_result); +- memset (temp_result, '\0', sizeof (temp_result)); +- memset (p_bytes, '\0', key_len); +- memset (s_bytes, '\0', salt_len); +- memset (&ctx, '\0', sizeof (ctx)); +- memset (&alt_ctx, '\0', sizeof (alt_ctx)); +- if (copied_key != NULL) +- memset (copied_key, '\0', key_len); +- if (copied_salt != NULL) +- memset (copied_salt, '\0', salt_len); +- +- return buffer; ++ b64_from_24bit (result[0], result[21], result[42], 4); ++ b64_from_24bit (result[22], result[43], result[1], 4); ++ b64_from_24bit (result[44], result[2], result[23], 4); ++ b64_from_24bit (result[3], result[24], result[45], 4); ++ b64_from_24bit (result[25], result[46], result[4], 4); ++ b64_from_24bit (result[47], result[5], result[26], 4); ++ b64_from_24bit (result[6], result[27], result[48], 4); ++ b64_from_24bit (result[28], result[49], result[7], 4); ++ b64_from_24bit (result[50], result[8], result[29], 4); ++ b64_from_24bit (result[9], result[30], result[51], 4); ++ b64_from_24bit (result[31], result[52], result[10], 4); ++ b64_from_24bit (result[53], result[11], result[32], 4); ++ b64_from_24bit (result[12], result[33], result[54], 4); ++ b64_from_24bit (result[34], result[55], result[13], 4); ++ b64_from_24bit (result[56], result[14], result[35], 4); ++ b64_from_24bit (result[15], result[36], result[57], 4); ++ b64_from_24bit (result[37], result[58], result[16], 4); ++ b64_from_24bit (result[59], result[17], result[38], 4); ++ b64_from_24bit (result[18], result[39], result[60], 4); ++ b64_from_24bit (result[40], result[61], result[19], 4); ++ b64_from_24bit (result[62], result[20], result[41], 4); ++ b64_from_24bit (0, 0, result[63], 2); ++ ++ *cp = '\0'; + } + + void + +From c76847e3be40c4ac0d78bc8518502418c6207144 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Bj=C3=B6rn=20Esser?= +Date: Wed, 1 Aug 2018 19:34:53 +0200 +Subject: [PATCH 07/10] Update LICENSING and NEWS for changes in previous + commits. + +crypt-sha{256,512}.c have been replaced with an implementation +in the Public Domain. +--- + LICENSING | 7 +++++-- + NEWS | 2 ++ + 2 files changed, 7 insertions(+), 2 deletions(-) + +diff --git a/LICENSING b/LICENSING +index b9df920..3efbed0 100644 +--- a/LICENSING ++++ b/LICENSING +@@ -14,14 +14,17 @@ source tree. For specific licensing terms consult the files themselves. + * Copyright Free Software Foundation, Inc.; LGPL (v2.1 or later): + crypt-base.h, crypt-obsolete.h, crypt-private.h + alg-md5.h, alg-md5.c, crypt-md5.c, +- alg-sha256.h, alg-sha256.c, crypt-sha256.c, +- alg-sha512.h, alg-sha512.c, crypt-sha256.c, ++ alg-sha256.h, alg-sha256.c, ++ alg-sha512.h, alg-sha512.c, + test-crypt-badsalt, test-crypt-nonnull + + * Copyright David Burren et al.; 3-clause BSD: + alg-des.h, alg-des.c, alg-des-tables.c, + crypt-des.c, crypt-des-obsolete.c, gen-des-tables.c + ++ * Public domain, written by Ulrich Drepper et al.: ++ 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 + +diff --git a/NEWS b/NEWS +index 77b556f..8acf032 100644 +--- a/NEWS ++++ b/NEWS +@@ -5,6 +5,8 @@ Please send bug reports, questions and suggestions to + + Version 4.1.2 + * Add optional 'check-valgrind' target to the Makefile. ++* Replace crypt-sha{256,512}.c with an implementation in the Public ++ Domain. + + Version 4.1.1 + * --enable-hashes now supports additional groups of hashing methods: + +From cc1806e214b89403152c2c53932d8d0b8aeb1e91 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Bj=C3=B6rn=20Esser?= +Date: Sat, 4 Aug 2018 13:02:03 +0200 +Subject: [PATCH 08/10] Add alias man-pages for other crypt functions. + +--- + Makefile.am | 3 ++- + crypt.3 | 1 + + crypt.5 | 2 ++ + crypt_gensalt.3 | 2 ++ + crypt_r.3 | 1 + + crypt_ra.3 | 1 + + 6 files changed, 9 insertions(+), 1 deletion(-) + create mode 100644 crypt.3 + create mode 100644 crypt_r.3 + create mode 100644 crypt_ra.3 + +diff --git a/Makefile.am b/Makefile.am +index 874db12..41ca783 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -18,7 +18,8 @@ EXTRA_DIST = \ + gen-map.awk gen-vers.awk gen-crypt-h.awk \ + gen-hashes.awk sel-hashes.awk hashes.lst + +-notrans_dist_man3_MANS = crypt_rn.3 crypt_gensalt.3 ++notrans_dist_man3_MANS = crypt.3 crypt_r.3 crypt_ra.3 \ ++ crypt_rn.3 crypt_gensalt.3 + notrans_dist_man5_MANS = crypt.5 + + nodist_include_HEADERS = crypt.h +diff --git a/crypt.3 b/crypt.3 +new file mode 100644 +index 0000000..430e48f +--- /dev/null ++++ b/crypt.3 +@@ -0,0 +1 @@ ++.so man3/crypt_rn.3 +diff --git a/crypt.5 b/crypt.5 +index 5db9c92..7fe4609 100644 +--- a/crypt.5 ++++ b/crypt.5 +@@ -279,6 +279,8 @@ that will work on an old operating system that supports nothing else. + .hash "$3$" "\e$3\e$\e$[0-9a-f]{32}" unlimited 8 256 256 0 1 + .SH SEE ALSO + .BR crypt (3), ++.BR crypt_r (3), ++.BR crypt_ra (3), + .BR crypt_rn (3), + .BR crypt_gensalt (3), + .BR getpwent (3), +diff --git a/crypt_gensalt.3 b/crypt_gensalt.3 +index ebfff28..3109740 100644 +--- a/crypt_gensalt.3 ++++ b/crypt_gensalt.3 +@@ -223,6 +223,8 @@ T} Thread safety MT-Safe + .SH SEE ALSO + .ad l + .BR crypt (3), ++.BR crypt_r (3), ++.BR crypt_ra (3), + .BR crypt_rn (3), + .BR getpass (3), + .BR getpwent (3), +diff --git a/crypt_r.3 b/crypt_r.3 +new file mode 100644 +index 0000000..430e48f +--- /dev/null ++++ b/crypt_r.3 +@@ -0,0 +1 @@ ++.so man3/crypt_rn.3 +diff --git a/crypt_ra.3 b/crypt_ra.3 +new file mode 100644 +index 0000000..430e48f +--- /dev/null ++++ b/crypt_ra.3 +@@ -0,0 +1 @@ ++.so man3/crypt_rn.3 + +From 6679d3427645da43140e5c5297f46985590b8e08 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Bj=C3=B6rn=20Esser?= +Date: Sat, 4 Aug 2018 20:45:42 +0200 +Subject: [PATCH 09/10] Update NEWS. + +--- + NEWS | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/NEWS b/NEWS +index 8acf032..7e1d526 100644 +--- a/NEWS ++++ b/NEWS +@@ -7,6 +7,7 @@ Version 4.1.2 + * Add optional 'check-valgrind' target to the Makefile. + * Replace crypt-sha{256,512}.c with an implementation in the Public + Domain. ++* Add alias man-pages for other crypt functions. + + Version 4.1.1 + * --enable-hashes now supports additional groups of hashing methods: + +From 8596e298f761c32cecff45424f5242cd14269292 Mon Sep 17 00:00:00 2001 +From: Zack Weinberg +Date: Tue, 7 Aug 2018 21:35:12 -0400 +Subject: [PATCH 10/10] Add configure option --disable-failure-tokens. + +When this option is given, crypt and crypt_r will return NULL on +failure, instead of a special "failure token" string that isn't the +hash of any passphrase. This was the historical behavior of glibc, +FreeBSD libc, and several other implementations. +--- + NEWS | 8 ++++++ + configure.ac | 20 +++++++++++++ + crypt.c | 4 +++ + crypt_rn.3 | 35 +++++++++++++---------- + test-badsalt.c | 18 +++++++++++- + test-crypt-badargs.c | 68 +++++++++++++++++++++++++------------------- + test-crypt-bcrypt.c | 6 +++- + 7 files changed, 112 insertions(+), 47 deletions(-) + +diff --git a/NEWS b/NEWS +index 7e1d526..de91957 100644 +--- a/NEWS ++++ b/NEWS +@@ -8,6 +8,14 @@ Version 4.1.2 + * Replace crypt-sha{256,512}.c with an implementation in the Public + Domain. + * Add alias man-pages for other crypt functions. ++* Add configure option --disable-failure-tokens, which causes crypt ++ and crypt_r to return NULL on failure, as crypt_rn and crypt_ra do, ++ instead of a special "failure token". Using this option improves ++ compatibility with programs written on the assumption that, like ++ most C library functions, crypt and crypt_r will return NULL on ++ failure; but it breaks compatibility with programs that assume these ++ functions never return NULL. We're not sure which type of program ++ is more common. Please let us know if you encounter either. + + Version 4.1.1 + * --enable-hashes now supports additional groups of hashing methods: +diff --git a/configure.ac b/configure.ac +index 9ea30f6..84d3ad9 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -162,6 +162,26 @@ AX_VALGRIND_DFLT([sgcheck], [off]) + AX_VALGRIND_CHECK() + + # Configure options. ++AC_ARG_ENABLE([failure-tokens], ++ AS_HELP_STRING( ++ [--disable-failure-tokens], ++ [Make crypt and crypt_r return NULL on failure, instead of a ++ special "failure token" string that isn't the hash of any ++ passphrase. This matches the behavior of several other ++ crypt implementations, but will break programs that assume these ++ functions never return NULL. crypt_rn and crypt_ra are not affected ++ by this option, and will always return NULL on failure.] ++ ), ++ [case "$enableval" in ++ yes) enable_failure_tokens=1;; ++ no) enable_failure_tokens=0;; ++ *) AC_MSG_ERROR([bad value ${enableval} for --enable-failure-tokens]);; ++ esac], ++ [enable_failure_tokens=1]) ++AC_DEFINE_UNQUOTED([ENABLE_FAILURE_TOKENS], [$enable_failure_tokens], ++ [Define to 1 if crypt and crypt_r should return a "failure token" on ++ failure, or 0 if they should return NULL.]) ++ + AC_ARG_ENABLE([obsolete-api], + AS_HELP_STRING( + [--enable-obsolete-api[=ARG]], +diff --git a/crypt.c b/crypt.c +index 9a3e192..839763a 100644 +--- a/crypt.c ++++ b/crypt.c +@@ -235,7 +235,11 @@ crypt_r (const char *phrase, const char *setting, struct crypt_data *data) + { + make_failure_token (setting, data->output, sizeof data->output); + do_crypt (phrase, setting, data); ++#if ENABLE_FAILURE_TOKENS + return data->output; ++#else ++ return data->output[0] == '*' ? 0 : data->output; ++#endif + } + SYMVER_crypt_r; + #endif +diff --git a/crypt_rn.3 b/crypt_rn.3 +index 24da44c..d021c4e 100644 +--- a/crypt_rn.3 ++++ b/crypt_rn.3 +@@ -204,17 +204,31 @@ multiple threads simultaneously, as long as a separate + object is used for each thread. + .PP + Upon error, +-.B crypt +-and +-.B crypt_r +-return a pointer to an ++.BR crypt_r ", " crypt_rn ", and " crypt_ra ++write an + .I invalid +-hashed passphrase. ++hashed passphrase to the ++.I output ++field of their ++.I crypt_data ++object, and ++.B crypt ++writes an invalid hash to its static storage area. + This string will be shorter than 13 characters, + will begin with a \(oq\fB*\fR\(cq, + and will not compare equal to + .IR setting . +-(This peculiar behavior is for compatibility ++.PP ++Upon error, ++.BR crypt_rn " and " crypt_ra ++return a null pointer. ++.BR crypt_r " and " crypt ++may also return a null pointer, ++or they may return a pointer to the invalid hash, ++depending on how ++.I libcrypt ++was configured. ++(The option to return the invalid hash is for compatibility + with old applications that assume that + .B crypt + cannot return a null pointer. +@@ -222,15 +236,6 @@ See + .B "PORTABILITY NOTES" + below.) + .PP +-.B crypt_rn +-and +-.B crypt_ra +-also write an invalid hashed passphrase to the +-.I output +-field of their +-.I crypt_data +-object when they fail, but they return a null pointer. +-.PP + All four functions set + .I errno + when they fail. +diff --git a/test-badsalt.c b/test-badsalt.c +index b274337..3d2e47a 100644 +--- a/test-badsalt.c ++++ b/test-badsalt.c +@@ -222,12 +222,28 @@ check_crypt (const char *label, const char *fn, + const char *retval, const char *setting, + bool expected_to_succeed) + { +- /* crypt/crypt_r should never return null */ ++#if ENABLE_FAILURE_TOKENS ++ /* crypt/crypt_r never return null when failure tokens are enabled */ + if (!retval) + { + printf ("FAIL: %s/%s/%s: returned NULL\n", label, setting, fn); + return false; + } ++#else ++ if (expected_to_succeed && !retval) ++ { ++ printf ("FAIL: %s/%s/%s: returned NULL\n", label, setting, fn); ++ return false; ++ } ++ else if (!expected_to_succeed && retval) ++ { ++ printf ("FAIL: %s/%s/%s: returned %p, should be NULL\n", ++ label, setting, fn, (const void *)retval); ++ return false; ++ } ++ else if (!expected_to_succeed && !retval) ++ return true; ++#endif + if (!check_results (label, fn, retval, setting, + expected_to_succeed)) + return false; +diff --git a/test-crypt-badargs.c b/test-crypt-badargs.c +index 0e6af16..6be24a9 100644 +--- a/test-crypt-badargs.c ++++ b/test-crypt-badargs.c +@@ -169,6 +169,14 @@ test_crypt_ra (const char *tag, + check (tag, expect, got); + } + ++#if ENABLE_FAILURE_TOKENS ++# define FT0 "*0" ++# define FT1 "*1" ++#else ++# define FT0 0 ++# define FT1 0 ++#endif ++ + /* PAGE should point to PAGESIZE bytes of read-write memory followed + by another PAGESIZE bytes of inaccessible memory. */ + +@@ -187,55 +195,55 @@ do_tests(char *page, size_t pagesize) + size_t i; + + /* When SETTING is null, it shouldn't matter what PHRASE is. */ +- expect_no_fault ("0.0.crypt", 0, 0, "*0", test_crypt); +- expect_no_fault ("0.0.crypt_r", 0, 0, "*0", test_crypt_r); ++ expect_no_fault ("0.0.crypt", 0, 0, FT0, test_crypt); ++ expect_no_fault ("0.0.crypt_r", 0, 0, FT0, test_crypt_r); + expect_no_fault ("0.0.crypt_rn", 0, 0, 0, test_crypt_rn); + expect_no_fault ("0.0.crypt_ra", 0, 0, 0, test_crypt_ra); + +- expect_no_fault ("''.0.crypt", "", 0, "*0", test_crypt); +- expect_no_fault ("''.0.crypt_r", "", 0, "*0", test_crypt_r); ++ expect_no_fault ("''.0.crypt", "", 0, FT0, test_crypt); ++ expect_no_fault ("''.0.crypt_r", "", 0, FT0, test_crypt_r); + expect_no_fault ("''.0.crypt_rn", "", 0, 0, test_crypt_rn); + expect_no_fault ("''.0.crypt_ra", "", 0, 0, test_crypt_ra); + +- expect_no_fault ("ph.0.crypt", phrase, 0, "*0", test_crypt); +- expect_no_fault ("ph.0.crypt_r", phrase, 0, "*0", test_crypt_r); ++ expect_no_fault ("ph.0.crypt", phrase, 0, FT0, test_crypt); ++ expect_no_fault ("ph.0.crypt_r", phrase, 0, FT0, test_crypt_r); + expect_no_fault ("ph.0.crypt_rn", phrase, 0, 0, test_crypt_rn); + expect_no_fault ("ph.0.crypt_ra", phrase, 0, 0, test_crypt_ra); + +- expect_no_fault ("p1.0.crypt", p1, 0, "*0", test_crypt); +- expect_no_fault ("p1.0.crypt_r", p1, 0, "*0", test_crypt_r); ++ expect_no_fault ("p1.0.crypt", p1, 0, FT0, test_crypt); ++ expect_no_fault ("p1.0.crypt_r", p1, 0, FT0, test_crypt_r); + expect_no_fault ("p1.0.crypt_rn", p1, 0, 0, test_crypt_rn); + expect_no_fault ("p1.0.crypt_ra", p1, 0, 0, test_crypt_ra); + +- expect_no_fault ("p2.0.crypt", p2, 0, "*0", test_crypt); +- expect_no_fault ("p2.0.crypt_r", p2, 0, "*0", test_crypt_r); ++ expect_no_fault ("p2.0.crypt", p2, 0, FT0, test_crypt); ++ expect_no_fault ("p2.0.crypt_r", p2, 0, FT0, test_crypt_r); + expect_no_fault ("p2.0.crypt_rn", p2, 0, 0, test_crypt_rn); + expect_no_fault ("p2.0.crypt_ra", p2, 0, 0, test_crypt_ra); + + /* Conversely, when PHRASE is null, + it shouldn't matter what SETTING is... */ +- expect_no_fault ("0.''.crypt", 0, "", "*0", test_crypt); +- expect_no_fault ("0.''.crypt_r", 0, "", "*0", test_crypt_r); ++ expect_no_fault ("0.''.crypt", 0, "", FT0, test_crypt); ++ expect_no_fault ("0.''.crypt_r", 0, "", FT0, test_crypt_r); + expect_no_fault ("0.''.crypt_rn", 0, "", 0, test_crypt_rn); + expect_no_fault ("0.''.crypt_ra", 0, "", 0, test_crypt_ra); + +- expect_no_fault ("0.'*'.crypt", 0, "*", "*0", test_crypt); +- expect_no_fault ("0.'*'.crypt_r", 0, "*", "*0", test_crypt_r); ++ expect_no_fault ("0.'*'.crypt", 0, "*", FT0, test_crypt); ++ expect_no_fault ("0.'*'.crypt_r", 0, "*", FT0, test_crypt_r); + expect_no_fault ("0.'*'.crypt_rn", 0, "*", 0, test_crypt_rn); + expect_no_fault ("0.'*'.crypt_ra", 0, "*", 0, test_crypt_ra); + +- expect_no_fault ("0.'*0'.crypt", 0, "*0", "*1", test_crypt); +- expect_no_fault ("0.'*0'.crypt_r", 0, "*0", "*1", test_crypt_r); ++ expect_no_fault ("0.'*0'.crypt", 0, "*0", FT1, test_crypt); ++ expect_no_fault ("0.'*0'.crypt_r", 0, "*0", FT1, test_crypt_r); + expect_no_fault ("0.'*0'.crypt_rn", 0, "*0", 0, test_crypt_rn); + expect_no_fault ("0.'*0'.crypt_ra", 0, "*0", 0, test_crypt_ra); + +- expect_no_fault ("0.'*1'.crypt", 0, "*1", "*0", test_crypt); +- expect_no_fault ("0.'*1'.crypt_r", 0, "*1", "*0", test_crypt_r); ++ expect_no_fault ("0.'*1'.crypt", 0, "*1", FT0, test_crypt); ++ expect_no_fault ("0.'*1'.crypt_r", 0, "*1", FT0, test_crypt_r); + expect_no_fault ("0.'*1'.crypt_rn", 0, "*1", 0, test_crypt_rn); + expect_no_fault ("0.'*1'.crypt_ra", 0, "*1", 0, test_crypt_ra); + +- expect_no_fault ("0.p1.crypt", 0, p1, "*0", test_crypt); +- expect_no_fault ("0.p1.crypt_r", 0, p1, "*0", test_crypt_r); ++ expect_no_fault ("0.p1.crypt", 0, p1, FT0, test_crypt); ++ expect_no_fault ("0.p1.crypt_r", 0, p1, FT0, test_crypt_r); + expect_no_fault ("0.p1.crypt_rn", 0, p1, 0, test_crypt_rn); + expect_no_fault ("0.p1.crypt_ra", 0, p1, 0, test_crypt_ra); + +@@ -245,8 +253,8 @@ do_tests(char *page, size_t pagesize) + bug, but it's impractical to fix without breaking the property + that 'crypt' _never_ creates a failure token that is equal to the + setting string, which is more important than this corner case. */ +- expect_a_fault ("0.p2.crypt", 0, p2, "*0", test_crypt); +- expect_a_fault ("0.p2.crypt_r", 0, p2, "*0", test_crypt_r); ++ expect_a_fault ("0.p2.crypt", 0, p2, FT0, test_crypt); ++ expect_a_fault ("0.p2.crypt_r", 0, p2, FT0, test_crypt_r); + expect_a_fault ("0.p2.crypt_rn", 0, p2, 0, test_crypt_rn); + expect_a_fault ("0.p2.crypt_ra", 0, p2, 0, test_crypt_ra); + +@@ -257,9 +265,9 @@ do_tests(char *page, size_t pagesize) + strcpy (page, "p1.'"); + strcat (page, settings[i]); + strcat (page, "'.crypt"); +- expect_a_fault (page, p1, settings[i], "*0", test_crypt); ++ expect_a_fault (page, p1, settings[i], FT0, test_crypt); + strcat (page, "_r"); +- expect_a_fault (page, p1, settings[i], "*0", test_crypt_r); ++ expect_a_fault (page, p1, settings[i], FT0, test_crypt_r); + strcat (page, "n"); + expect_a_fault (page, p1, settings[i], 0, test_crypt_rn); + page [strlen (page) - 1] = 'a'; +@@ -268,9 +276,9 @@ do_tests(char *page, size_t pagesize) + strcpy (page, "p2.'"); + strcat (page, settings[i]); + strcat (page, "'.crypt"); +- expect_a_fault (page, p2, settings[i], "*0", test_crypt); ++ expect_a_fault (page, p2, settings[i], FT0, test_crypt); + strcat (page, "_r"); +- expect_a_fault (page, p2, settings[i], "*0", test_crypt_r); ++ expect_a_fault (page, p2, settings[i], FT0, test_crypt_r); + strcat (page, "n"); + expect_a_fault (page, p2, settings[i], 0, test_crypt_rn); + page [strlen (page) - 1] = 'a'; +@@ -279,8 +287,8 @@ do_tests(char *page, size_t pagesize) + + /* Conversely, when PHRASE is valid, passing an invalid string as SETTING + should crash reliably. */ +- expect_a_fault ("ph.p2.crypt", phrase, p2, "*0", test_crypt); +- expect_a_fault ("ph.p2.crypt_r", phrase, p2, "*0", test_crypt_r); ++ expect_a_fault ("ph.p2.crypt", phrase, p2, FT0, test_crypt); ++ expect_a_fault ("ph.p2.crypt_r", phrase, p2, FT0, test_crypt_r); + expect_a_fault ("ph.p2.crypt_rn", phrase, p2, 0, test_crypt_rn); + expect_a_fault ("ph.p2.crypt_ra", phrase, p2, 0, test_crypt_ra); + +@@ -292,9 +300,9 @@ do_tests(char *page, size_t pagesize) + strcpy (page, "ph.'"); + strcat (page, settings[i]); + strcat (page, ".crypt"); +- expect_a_fault (page, phrase, p1, "*0", test_crypt); ++ expect_a_fault (page, phrase, p1, FT0, test_crypt); + strcat (page, "_r"); +- expect_a_fault (page, phrase, p1, "*0", test_crypt_r); ++ expect_a_fault (page, phrase, p1, FT0, test_crypt_r); + strcat (page, "n"); + expect_a_fault (page, phrase, p1, 0, test_crypt_rn); + page [strlen (page) - 1] = 'a'; +diff --git a/test-crypt-bcrypt.c b/test-crypt-bcrypt.c +index c984e4d..bf149b4 100644 +--- a/test-crypt-bcrypt.c ++++ b/test-crypt-bcrypt.c +@@ -194,8 +194,12 @@ main (void) + errno = 0; + p = crypt (key, setting); + errnm = errno; ++#if ENABLE_FAILURE_TOKENS + match = strcmp (p, hash); +- if ((!ok && !errno) || strcmp (p, hash)) ++#else ++ match = (ok ? strcmp (p, hash) : p != 0); ++#endif ++ if ((!ok && !errno) || match) + { + printf ("FAIL: %d/crypt.1: key=%s setting=%s: xhash=%s xerr=%d, " + "p=%s match=%d err=%s\n", diff --git a/libxcrypt.spec b/libxcrypt.spec index 169a165..1274a60 100644 --- a/libxcrypt.spec +++ b/libxcrypt.spec @@ -19,7 +19,7 @@ Name: libxcrypt Version: 4.1.1 -Release: 2%{?dist} +Release: 3%{?dist} Summary: Extended crypt library for DES, MD5, Blowfish and others # For explicit license breakdown, see the @@ -28,10 +28,11 @@ License: LGPLv2+ and BSD and Public Domain URL: https://github.com/besser82/%{name} Source0: %{url}/archive/v%{version}.tar.gz#/%{name}-%{version}.tar.gz -Patch0: %{url}/commit/cc1806e214b8.patch#/%{name}-4.1.1_add_other_manpages.patch +Patch0: %{url}/compare/v4.1.1...develop.patch#/%{name}-4.1.1_to_master.patch BuildRequires: fipscheck BuildRequires: libtool +BuildRequires: valgrind Requires: glibc%{_isa} >= 2.26.9000-46 @@ -117,6 +118,7 @@ is highly discouraged. --disable-silent-rules \ --enable-shared \ --enable-static \ + --disable-failure-tokens \ --enable-hashes=all \ --enable-obsolete-api=glibc \ --with-pkgconfigdir=%{_libdir}/pkgconfig @@ -144,6 +146,15 @@ is highly discouraged. exit $rc; } +%make_build check-valgrind-memcheck || \ + { + rc=$?; + echo "-----BEGIN TESTLOG-----"; + %{__cat} test-suite.log; + echo "-----END TESTLOG-----"; + exit $rc; + } + %ldconfig_scriptlets @@ -180,8 +191,12 @@ is highly discouraged. %changelog +* Wed Aug 08 2018 Björn Esser - 4.1.1-3 +- Make crypt{,_r} return NULL on failure (#1611784) +- Use valgrind to check for memory leaks + * Sat Aug 04 2018 Björn Esser - 4.1.1-2 -- Add manpages for crypt{,_r_ra}.3 (#1610307) +- Add manpages for crypt{,_r,_ra}.3 (#1610307) * Wed Aug 01 2018 Björn Esser - 4.1.1-1 - New upstream release