2809 lines
103 KiB
Diff
2809 lines
103 KiB
Diff
|
From 0e5a38cde2ede896e4dca6d85f133d9e23ec72cc Mon Sep 17 00:00:00 2001
|
||
|
From: =?UTF-8?q?Bj=C3=B6rn=20Esser?= <besser82@fedoraproject.org>
|
||
|
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
|
||
|
<https://github.com/besser82/libxcrypt/issues>.
|
||
|
|
||
|
+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?= <besser82@fedoraproject.org>
|
||
|
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
|
||
|
<https://github.com/besser82/libxcrypt/issues>.
|
||
|
|
||
|
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-<tool>, 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 <philip.withnall@collabora.co.uk>
|
||
|
+#
|
||
|
+# 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?= <besser82@fedoraproject.org>
|
||
|
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 <drepper@redhat.com>.
|
||
|
|
||
|
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
|
||
|
- <https://www.gnu.org/licenses/>. */
|
||
|
+/* One way encryption based on the SHA256-based Unix crypt implementation.
|
||
|
+ *
|
||
|
+ * Written by Ulrich Drepper <drepper at redhat.com> 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?= <besser82@fedoraproject.org>
|
||
|
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 <drepper at redhat.com> in 2007 [1].
|
||
|
- * To the extent possible under law, Ulrich Drepper has waived all
|
||
|
+ * Modified by Zack Weinberg <zackw at panix.com> in 2017, 2018.
|
||
|
+ * Composed by Björn Esser <besser82 at fedoraproject.org> 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?= <besser82@fedoraproject.org>
|
||
|
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 <drepper@redhat.com>.
|
||
|
|
||
|
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
|
||
|
- <https://www.gnu.org/licenses/>. */
|
||
|
+/* One way encryption based on the SHA512-based Unix crypt implementation.
|
||
|
+ *
|
||
|
+ * Written by Ulrich Drepper <drepper at redhat.com> 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?= <besser82@fedoraproject.org>
|
||
|
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 <drepper at redhat.com> in 2007 [1].
|
||
|
- * To the extent possible under law, Ulrich Drepper has waived all
|
||
|
+ * Modified by Zack Weinberg <zackw at panix.com> in 2017, 2018.
|
||
|
+ * Composed by Björn Esser <besser82 at fedoraproject.org> 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?= <besser82@fedoraproject.org>
|
||
|
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?= <besser82@fedoraproject.org>
|
||
|
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?= <besser82@fedoraproject.org>
|
||
|
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 <zackw@panix.com>
|
||
|
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",
|