mirror of
git://sourceware.org/git/glibc.git
synced 2024-11-21 01:12:26 +08:00
crypt: Remove libcrypt support
All the crypt related functions, cryptographic algorithms, and make requirements are removed, with only the exception of md5 implementation which is moved to locale folder since it is required by localedef for integrity protection (libc's locale-reading code does not check these, but localedef does generate them). Besides thec code itself, both internal documentation and the manual is also adjusted. This allows to remove both --enable-crypt and --enable-nss-crypt configure options. Checked with a build for all affected ABIs. Co-authored-by: Zack Weinberg <zack@owlfolio.org> Reviewed-by: Carlos O'Donell <carlos@redhat.com>
This commit is contained in:
parent
bb2ff12abd
commit
e6e3c66688
@ -24,21 +24,6 @@ catgets/gencat.c:
|
||||
catgets/open_catalog.c:
|
||||
Contributed by Ulrich Drepper, <drepper@gnu.org>.
|
||||
|
||||
crypt/md5-crypt.c:
|
||||
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
|
||||
|
||||
crypt/sha256-crypt.c:
|
||||
Contributed by Ulrich Drepper <drepper@redhat.com>, 2007.
|
||||
|
||||
crypt/sha256.c:
|
||||
Written by Ulrich Drepper <drepper@redhat.com>, 2007.
|
||||
|
||||
crypt/sha512-crypt.c:
|
||||
Contributed by Ulrich Drepper <drepper@redhat.com>, 2007.
|
||||
|
||||
crypt/sha512.c:
|
||||
Written by Ulrich Drepper <drepper@redhat.com>, 2007.
|
||||
|
||||
debug/backtrace.c:
|
||||
Contributed by Jakub Jelinek <jakub@redhat.com>, 2003.
|
||||
|
||||
|
13
INSTALL
13
INSTALL
@ -228,19 +228,6 @@ if ‘CFLAGS’ is specified it must enable optimization. For example:
|
||||
By default for x86_64, the GNU C Library is built with the vector
|
||||
math library. Use this option to disable the vector math library.
|
||||
|
||||
‘--enable-crypt’
|
||||
Install the legacy passphrase-hashing library ‘libcrypt’ and the
|
||||
header file ‘crypt.h’. ‘unistd.h’ will declare the function
|
||||
‘crypt’ regardless of this option. Using this option does not
|
||||
change the set of programs that may need to be linked with
|
||||
‘-lcrypt’; it only means that the GNU C Library will provide that
|
||||
library.
|
||||
|
||||
This option is for hackers and distributions who may not yet be
|
||||
able to use libcrypt alternatives such as libxcrypt and need this
|
||||
legacy implementation as a temporary workaround. Note that
|
||||
libcrypt may be removed in a future release.
|
||||
|
||||
‘--disable-scv’
|
||||
Disable using ‘scv’ instruction for syscalls. All syscalls will
|
||||
use ‘sc’ instead, even if the kernel supports ‘scv’. PowerPC only.
|
||||
|
@ -1357,11 +1357,6 @@ all-subdirs = csu assert ctype locale intl catgets math setjmp signal \
|
||||
localedata timezone rt conform debug mathvec support \
|
||||
dlfcn elf
|
||||
|
||||
ifeq ($(build-crypt),yes)
|
||||
all-subdirs += crypt
|
||||
rpath-dirs += crypt
|
||||
endif
|
||||
|
||||
ifndef avoid-generated
|
||||
# sysd-sorted itself will contain rules making the sysd-sorted target
|
||||
# depend on Depend files. But if you just added a Depend file to an
|
||||
|
16
NEWS
16
NEWS
@ -44,6 +44,22 @@ Deprecated and removed features, and other changes affecting compatibility:
|
||||
".tmp", to avoid examining temporary files created by the RPM and dpkg
|
||||
package managers.
|
||||
|
||||
* libcrypt has been removed from the GNU C Library. The configure
|
||||
options "--enable-crypt" and "--enable-nss-crypt" are no longer
|
||||
available. <crypt.h>, libcrypt.a, and libcrypt.so.1 will not be
|
||||
installed, and <unistd.h> will not declare the crypt function.
|
||||
|
||||
The replacement for libcrypt is libxcrypt, maintained separately from
|
||||
GNU libc, but available under compatible licensing terms, and providing
|
||||
binary backward compatibility with the former libcrypt. It is currently
|
||||
distributed from <https://github.com/besser82/libxcrypt/>.
|
||||
|
||||
As a consequence of this removal, GNU libc no longer makes any use of
|
||||
the NSS cryptography library (Network Security Services; not to be
|
||||
confused with Name Service Switch). Distributors of binary packages
|
||||
of GNU libc are advised to check whether their build processes can be
|
||||
simplified.
|
||||
|
||||
Changes to build and runtime requirements:
|
||||
|
||||
* Building on LoongArch requires at a minimum binutils 2.41 for vector
|
||||
|
@ -27,8 +27,6 @@ gnulib:
|
||||
argp/argp-pvh.c
|
||||
argp/argp-xinl.c
|
||||
argp/argp.h
|
||||
crypt/md5.c
|
||||
crypt/md5.h
|
||||
dirent/alphasort.c
|
||||
dirent/scandir.c
|
||||
# Merged from gnulib 2021-09-21
|
||||
|
@ -80,16 +80,12 @@ mach-interface-list = @mach_interface_list@
|
||||
|
||||
memory-tagging = @memory_tagging@
|
||||
|
||||
nss-crypt = @libc_cv_nss_crypt@
|
||||
static-nss-crypt = @libc_cv_static_nss_crypt@
|
||||
|
||||
# Configuration options.
|
||||
build-shared = @shared@
|
||||
build-profile = @profile@
|
||||
build-static-nss = @static_nss@
|
||||
cross-compiling = @cross_compiling@
|
||||
force-install = @force_install@
|
||||
build-crypt = @build_crypt@
|
||||
build-nscd = @build_nscd@
|
||||
use-nscd = @use_nscd@
|
||||
build-hardcoded-path-in-tests= @hardcoded_path_in_tests@
|
||||
|
126
configure
vendored
126
configure
vendored
@ -700,9 +700,6 @@ INSTALL_PROGRAM
|
||||
base_machine
|
||||
build_pt_chown
|
||||
build_nscd
|
||||
libc_cv_static_nss_crypt
|
||||
libc_cv_nss_crypt
|
||||
build_crypt
|
||||
memory_tagging
|
||||
enable_werror
|
||||
force_install
|
||||
@ -806,8 +803,6 @@ enable_kernel
|
||||
enable_werror
|
||||
enable_multi_arch
|
||||
enable_memory_tagging
|
||||
enable_crypt
|
||||
enable_nss_crypt
|
||||
enable_systemtap
|
||||
enable_build_nscd
|
||||
enable_nscd
|
||||
@ -1481,9 +1476,6 @@ Optional Features:
|
||||
architectures
|
||||
--enable-memory-tagging enable memory tagging if supported by the
|
||||
architecture [default=no]
|
||||
--enable-crypt build and install the legacy passphrase hashing
|
||||
library, libcrypt
|
||||
--enable-nss-crypt enable libcrypt to use nss
|
||||
--enable-systemtap enable systemtap static probe points [default=no]
|
||||
--disable-build-nscd disable building and installing the nscd daemon
|
||||
--disable-nscd library functions will not contact the nscd daemon
|
||||
@ -4561,124 +4553,6 @@ if test "$memory_tagging" = yes; then
|
||||
fi
|
||||
|
||||
|
||||
# Check whether --enable-crypt was given.
|
||||
if test ${enable_crypt+y}
|
||||
then :
|
||||
enableval=$enable_crypt; build_crypt=$enableval
|
||||
else $as_nop
|
||||
build_crypt=no
|
||||
fi
|
||||
|
||||
|
||||
|
||||
# Check whether --enable-nss-crypt was given.
|
||||
if test ${enable_nss_crypt+y}
|
||||
then :
|
||||
enableval=$enable_nss_crypt; nss_crypt=$enableval
|
||||
else $as_nop
|
||||
nss_crypt=no
|
||||
fi
|
||||
|
||||
if test x$build_libcrypt = xno && test x$nss_crypt = xyes; then
|
||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: --enable-nss-crypt has no effect when libcrypt is disabled" >&5
|
||||
printf "%s\n" "$as_me: WARNING: --enable-nss-crypt has no effect when libcrypt is disabled" >&2;}
|
||||
nss_crypt=no
|
||||
fi
|
||||
if test x$nss_crypt = xyes; then
|
||||
nss_includes=-I$(nss-config --includedir 2>/dev/null)
|
||||
if test $? -ne 0; then
|
||||
as_fn_error $? "cannot find include directory with nss-config" "$LINENO" 5
|
||||
fi
|
||||
nspr_includes=-I$(nspr-config --includedir 2>/dev/null)
|
||||
if test $? -ne 0; then
|
||||
as_fn_error $? "cannot find include directory with nspr-config" "$LINENO" 5
|
||||
fi
|
||||
old_CFLAGS="$CFLAGS"
|
||||
CFLAGS="$CFLAGS $nss_includes $nspr_includes"
|
||||
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
typedef int PRBool;
|
||||
#include <hasht.h>
|
||||
#include <nsslowhash.h>
|
||||
void f (void) { NSSLOW_Init (); }
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
if ac_fn_c_try_compile "$LINENO"
|
||||
then :
|
||||
libc_cv_nss_crypt=yes
|
||||
else $as_nop
|
||||
as_fn_error $? "
|
||||
cannot find NSS headers with lowlevel hash function interfaces" "$LINENO" 5
|
||||
fi
|
||||
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
|
||||
old_LIBS="$LIBS"
|
||||
old_LDFLAGS="$LDFLAGS"
|
||||
LIBS="$LIBS -lfreebl3"
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
typedef int PRBool;
|
||||
#include <hasht.h>
|
||||
#include <nsslowhash.h>
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
NSSLOW_Init();
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
if ac_fn_c_try_link "$LINENO"
|
||||
then :
|
||||
libc_cv_nss_crypt=yes
|
||||
else $as_nop
|
||||
as_fn_error $? "
|
||||
cannot link program using lowlevel NSS hash functions" "$LINENO" 5
|
||||
fi
|
||||
rm -f core conftest.err conftest.$ac_objext conftest.beam \
|
||||
conftest$ac_exeext conftest.$ac_ext
|
||||
# Check to see if there is a static NSS cryptographic library.
|
||||
# If there isn't then we can't link anything with libcrypt.a,
|
||||
# and that might mean disabling some static tests.
|
||||
LDFLAGS="$LDFLAGS -static"
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
typedef int PRBool;
|
||||
#include <hasht.h>
|
||||
#include <nsslowhash.h>
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
NSSLOW_Init();
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
if ac_fn_c_try_link "$LINENO"
|
||||
then :
|
||||
libc_cv_static_nss_crypt=yes
|
||||
else $as_nop
|
||||
libc_cv_static_nss_crypt=no
|
||||
fi
|
||||
rm -f core conftest.err conftest.$ac_objext conftest.beam \
|
||||
conftest$ac_exeext conftest.$ac_ext
|
||||
LDFLAGS="$old_LDFLAGS"
|
||||
CFLAGS="$old_CFLAGS"
|
||||
LIBS="$old_LIBS"
|
||||
else
|
||||
libc_cv_nss_crypt=no
|
||||
libc_cv_static_nss_crypt=no
|
||||
fi
|
||||
|
||||
|
||||
|
||||
|
||||
# Check whether --enable-systemtap was given.
|
||||
if test ${enable_systemtap+y}
|
||||
then :
|
||||
|
65
configure.ac
65
configure.ac
@ -305,71 +305,6 @@ if test "$memory_tagging" = yes; then
|
||||
fi
|
||||
AC_SUBST(memory_tagging)
|
||||
|
||||
AC_ARG_ENABLE([crypt],
|
||||
AS_HELP_STRING([--enable-crypt],
|
||||
[build and install the legacy passphrase hashing library, libcrypt]),
|
||||
[build_crypt=$enableval],
|
||||
[build_crypt=no])
|
||||
AC_SUBST(build_crypt)
|
||||
|
||||
AC_ARG_ENABLE([nss-crypt],
|
||||
AS_HELP_STRING([--enable-nss-crypt],
|
||||
[enable libcrypt to use nss]),
|
||||
[nss_crypt=$enableval],
|
||||
[nss_crypt=no])
|
||||
if test x$build_libcrypt = xno && test x$nss_crypt = xyes; then
|
||||
AC_MSG_WARN([--enable-nss-crypt has no effect when libcrypt is disabled])
|
||||
nss_crypt=no
|
||||
fi
|
||||
if test x$nss_crypt = xyes; then
|
||||
nss_includes=-I$(nss-config --includedir 2>/dev/null)
|
||||
if test $? -ne 0; then
|
||||
AC_MSG_ERROR([cannot find include directory with nss-config])
|
||||
fi
|
||||
nspr_includes=-I$(nspr-config --includedir 2>/dev/null)
|
||||
if test $? -ne 0; then
|
||||
AC_MSG_ERROR([cannot find include directory with nspr-config])
|
||||
fi
|
||||
old_CFLAGS="$CFLAGS"
|
||||
CFLAGS="$CFLAGS $nss_includes $nspr_includes"
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([typedef int PRBool;
|
||||
#include <hasht.h>
|
||||
#include <nsslowhash.h>
|
||||
void f (void) { NSSLOW_Init (); }])],
|
||||
libc_cv_nss_crypt=yes,
|
||||
AC_MSG_ERROR([
|
||||
cannot find NSS headers with lowlevel hash function interfaces]))
|
||||
old_LIBS="$LIBS"
|
||||
old_LDFLAGS="$LDFLAGS"
|
||||
LIBS="$LIBS -lfreebl3"
|
||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([typedef int PRBool;
|
||||
#include <hasht.h>
|
||||
#include <nsslowhash.h>],
|
||||
[NSSLOW_Init();])],
|
||||
libc_cv_nss_crypt=yes,
|
||||
AC_MSG_ERROR([
|
||||
cannot link program using lowlevel NSS hash functions]))
|
||||
# Check to see if there is a static NSS cryptographic library.
|
||||
# If there isn't then we can't link anything with libcrypt.a,
|
||||
# and that might mean disabling some static tests.
|
||||
LDFLAGS="$LDFLAGS -static"
|
||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([typedef int PRBool;
|
||||
#include <hasht.h>
|
||||
#include <nsslowhash.h>],
|
||||
[NSSLOW_Init();])],
|
||||
libc_cv_static_nss_crypt=yes,
|
||||
libc_cv_static_nss_crypt=no)
|
||||
LDFLAGS="$old_LDFLAGS"
|
||||
CFLAGS="$old_CFLAGS"
|
||||
LIBS="$old_LIBS"
|
||||
else
|
||||
libc_cv_nss_crypt=no
|
||||
libc_cv_static_nss_crypt=no
|
||||
fi
|
||||
AC_SUBST(libc_cv_nss_crypt)
|
||||
AC_SUBST(libc_cv_static_nss_crypt)
|
||||
|
||||
|
||||
AC_ARG_ENABLE([systemtap],
|
||||
[AS_HELP_STRING([--enable-systemtap],
|
||||
[enable systemtap static probe points @<:@default=no@:>@])],
|
||||
|
@ -212,11 +212,6 @@ linknamespace-libs-XOPEN2K8 = $(linknamespace-libs-xsi)
|
||||
linknamespace-libs = $(foreach std,$(conformtest-standards),\
|
||||
$(linknamespace-libs-$(std)))
|
||||
|
||||
ifeq ($(build-crypt),yes)
|
||||
linknamespace-libs-xsi += $(common-objpfx)crypt/libcrypt.a
|
||||
linknamespace-libs-XPG4 += $(common-objpfx)crypt/libcrypt.a
|
||||
endif
|
||||
|
||||
$(linknamespace-symlist-stdlibs-tests): $(objpfx)symlist-stdlibs-%: \
|
||||
$(linknamespace-libs)
|
||||
LC_ALL=C $(READELF) -W -s $(linknamespace-libs-$*) > $@; \
|
||||
|
@ -1,69 +0,0 @@
|
||||
# Copyright (C) 1996-2023 Free Software Foundation, Inc.
|
||||
# This file is part of the GNU C Library.
|
||||
|
||||
# The GNU C 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.
|
||||
|
||||
# The GNU C 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 the GNU C Library; if not, see
|
||||
# <https://www.gnu.org/licenses/>.
|
||||
|
||||
#
|
||||
# Sub-makefile for crypt() portion of the library.
|
||||
#
|
||||
subdir := crypt
|
||||
|
||||
include ../Makeconfig
|
||||
|
||||
headers := crypt.h
|
||||
|
||||
extra-libs := libcrypt
|
||||
extra-libs-others := $(extra-libs)
|
||||
|
||||
libcrypt-routines := crypt-entry md5-crypt sha256-crypt sha512-crypt crypt \
|
||||
crypt_util
|
||||
|
||||
tests := cert md5c-test sha256c-test sha512c-test badsalttest
|
||||
|
||||
ifeq ($(nss-crypt),yes)
|
||||
nss-cpp-flags := -DUSE_NSS \
|
||||
-I$(shell nss-config --includedir) -I$(shell nspr-config --includedir)
|
||||
CPPFLAGS-sha256-crypt.c += $(nss-cpp-flags)
|
||||
CPPFLAGS-sha512-crypt.c += $(nss-cpp-flags)
|
||||
CPPFLAGS-md5-crypt.c += $(nss-cpp-flags)
|
||||
LDLIBS-crypt.so = -lfreebl3
|
||||
else
|
||||
libcrypt-routines += md5 sha256 sha512
|
||||
|
||||
tests += md5test sha256test sha512test
|
||||
|
||||
# The test md5test-giant uses up to 400 MB of RSS and runs on a fast
|
||||
# machine over a minute.
|
||||
xtests = md5test-giant
|
||||
endif
|
||||
|
||||
include ../Rules
|
||||
|
||||
ifneq ($(nss-crypt),yes)
|
||||
md5-routines := md5 $(filter md5%,$(libcrypt-sysdep_routines))
|
||||
sha256-routines := sha256 $(filter sha256%,$(libcrypt-sysdep_routines))
|
||||
sha512-routines := sha512 $(filter sha512%,$(libcrypt-sysdep_routines))
|
||||
|
||||
$(objpfx)md5test: $(patsubst %, $(objpfx)%.o,$(md5-routines))
|
||||
$(objpfx)md5test-giant: $(patsubst %, $(objpfx)%.o,$(md5-routines))
|
||||
$(objpfx)sha256test: $(patsubst %, $(objpfx)%.o,$(sha256-routines))
|
||||
$(objpfx)sha512test: $(patsubst %, $(objpfx)%.o,$(sha512-routines))
|
||||
endif
|
||||
|
||||
ifeq (yes,$(build-shared))
|
||||
$(addprefix $(objpfx),$(tests)): $(objpfx)libcrypt.so
|
||||
else
|
||||
$(addprefix $(objpfx),$(tests)): $(objpfx)libcrypt.a
|
||||
endif
|
@ -1,135 +0,0 @@
|
||||
The following is the README for UFC-crypt, with those portions deleted
|
||||
that are known to be incorrect for the implementation used with the
|
||||
GNU C library.
|
||||
|
||||
|
||||
UFC-crypt: ultra fast 'crypt' implementation
|
||||
============================================
|
||||
|
||||
@(#)README 2.27 11 Sep 1996
|
||||
|
||||
Design goals/non goals:
|
||||
----------------------
|
||||
|
||||
- Crypt implementation plugin compatible with crypt(3)/fcrypt.
|
||||
|
||||
- High performance when used for password cracking.
|
||||
|
||||
- Portable to most 32/64 bit machines.
|
||||
|
||||
- Startup time/mixed salt performance not critical.
|
||||
|
||||
Features of the implementation:
|
||||
------------------------------
|
||||
|
||||
- On most machines, UFC-crypt runs 30-60 times faster than crypt(3) when
|
||||
invoked repeated times with the same salt and varying passwords.
|
||||
|
||||
- With mostly constant salts, performance is about two to three times
|
||||
that of the default fcrypt implementation shipped with Alec
|
||||
Muffets 'Crack' password cracker. For instructions on how to
|
||||
plug UFC-crypt into 'Crack', see below.
|
||||
|
||||
- With alternating salts, performance is only about twice
|
||||
that of crypt(3).
|
||||
|
||||
- Requires 165 kb for tables.
|
||||
|
||||
Author & licensing etc
|
||||
----------------------
|
||||
|
||||
UFC-crypt is created by Michael Glad, email: glad@daimi.aau.dk, and has
|
||||
been donated to the Free Software Foundation, Inc. It is covered by the
|
||||
GNU library license version 2, see the file 'COPYING.LIB'.
|
||||
|
||||
NOTES FOR USERS OUTSIDE THE US:
|
||||
------------------------------
|
||||
|
||||
The US government limits the export of DES based software/hardware.
|
||||
This software is written in Aarhus, Denmark. It can therefore be retrieved
|
||||
from ftp sites outside the US without breaking US law. Please do not
|
||||
ftp it from american sites.
|
||||
|
||||
Benchmark table:
|
||||
---------------
|
||||
|
||||
The table shows how many operations per second UFC-crypt can
|
||||
do on various machines.
|
||||
|
||||
|--------------|-------------------------------------------|
|
||||
|Machine | SUN* SUN* HP* DecStation HP |
|
||||
| | 3/50 ELC 9000/425e 3100 9000/720 |
|
||||
|--------------|-------------------------------------------|
|
||||
| Crypt(3)/sec | 4.6 30 15 25 57 |
|
||||
| Ufc/sec | 220 990 780 1015 3500 |
|
||||
|--------------|-------------------------------------------|
|
||||
| Speedup | 48 30 52 40 60 |
|
||||
|--------------|-------------------------------------------|
|
||||
|
||||
*) Compiled using special assembly language support module.
|
||||
|
||||
It seems as if performance is limited by CPU bus and data cache capacity.
|
||||
This also makes the benchmarks debatable compared to a real test with
|
||||
UFC-crypt wired into Crack. However, the table gives an outline of
|
||||
what can be expected.
|
||||
|
||||
Optimizations:
|
||||
-------------
|
||||
|
||||
Here are the optimizations used relative to an ordinary implementation
|
||||
such as the one said to be used in crypt(3).
|
||||
|
||||
Major optimizations
|
||||
*******************
|
||||
|
||||
- Keep data packed as bits in integer variables -- allows for
|
||||
fast permutations & parallel xor's in CPU hardware.
|
||||
|
||||
- Let adjacent final & initial permutations collapse.
|
||||
|
||||
- Keep working data in 'E expanded' format all the time.
|
||||
|
||||
- Implement DES 'f' function mostly by table lookup
|
||||
|
||||
- Calculate the above function on 12 bit basis rather than 6
|
||||
as would be the most natural.
|
||||
|
||||
- Implement setup routines so that performance is limited by the DES
|
||||
inner loops only.
|
||||
|
||||
- Instead of doing salting in the DES inner loops, modify the above tables
|
||||
each time a new salt is seen. According to the BSD crypt code this is
|
||||
ugly :-)
|
||||
|
||||
Minor (dirty) optimizations
|
||||
***************************
|
||||
|
||||
- combine iterations of DES inner loop so that DES only loops
|
||||
8 times. This saves a lot of variable swapping.
|
||||
|
||||
- Implement key access by a walking pointer rather than coding
|
||||
as array indexing.
|
||||
|
||||
- As described, the table based f function uses a 3 dimensional array:
|
||||
|
||||
sb ['number of 12 bit segment']['12 bit index']['48 bit half index']
|
||||
|
||||
Code the routine with 4 (one dimensional) vectors.
|
||||
|
||||
- Design the internal data format & uglify the DES loops so that
|
||||
the compiler does not need to do bit shifts when indexing vectors.
|
||||
|
||||
Revision history
|
||||
****************
|
||||
|
||||
UFC patchlevel 0: base version; released to alt.sources on Sep 24 1991
|
||||
UFC patchlevel 1: patch released to alt.sources on Sep 27 1991.
|
||||
No longer rebuilds sb tables when seeing a new salt.
|
||||
UFC-crypt pl0: Essentially UFC pl 1. Released to comp.sources.misc
|
||||
on Oct 22 1991.
|
||||
UFC-crypt pl1: Released to comp.sources.misc in march 1992
|
||||
* setkey/encrypt routines added
|
||||
* added validation/benchmarking programs
|
||||
* reworked keyschedule setup code
|
||||
* memory demands reduced
|
||||
* 64 bit support added
|
@ -1,5 +0,0 @@
|
||||
libcrypt {
|
||||
GLIBC_2.0 {
|
||||
crypt; crypt_r; encrypt; encrypt_r; fcrypt; setkey; setkey_r;
|
||||
}
|
||||
}
|
@ -1,54 +0,0 @@
|
||||
/* Test program for bad DES salt detection in crypt.
|
||||
Copyright (C) 2012-2023 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
The GNU C 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.
|
||||
|
||||
The GNU C 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 the GNU C Library; if not, see
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <array_length.h>
|
||||
#include <stddef.h>
|
||||
#include <crypt.h>
|
||||
|
||||
#include <support/check.h>
|
||||
|
||||
static const char *tests[][2] =
|
||||
{
|
||||
{ "no salt", "" },
|
||||
{ "single char", "/" },
|
||||
{ "first char bad", "!x" },
|
||||
{ "second char bad", "Z%" },
|
||||
{ "both chars bad", ":@" },
|
||||
{ "unsupported algorithm", "$2$" },
|
||||
{ "unsupported_algorithm", "_1" },
|
||||
};
|
||||
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
struct crypt_data cd;
|
||||
|
||||
/* Mark cd as initialized before first call to crypt_r. */
|
||||
cd.initialized = 0;
|
||||
|
||||
for (size_t i = 0; i < array_length (tests); i++)
|
||||
{
|
||||
TEST_VERIFY (crypt (tests[i][0], tests[i][1]) == NULL);
|
||||
|
||||
TEST_VERIFY (crypt_r (tests[i][0], tests[i][1], &cd) == NULL);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#include <support/test-driver.c>
|
135
crypt/cert.c
135
crypt/cert.c
@ -1,135 +0,0 @@
|
||||
|
||||
/*
|
||||
* This crypt(3) validation program shipped with UFC-crypt
|
||||
* is derived from one distributed with Phil Karns PD DES package.
|
||||
*
|
||||
* @(#)cert.c 1.8 11 Aug 1996
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "crypt.h"
|
||||
|
||||
/* This file tests the deprecated setkey/encrypt interface. */
|
||||
#include <shlib-compat.h>
|
||||
#if TEST_COMPAT (libcrypt, GLIBC_2_0, GLIBC_2_28)
|
||||
|
||||
#define libcrypt_version_reference(symbol, version) \
|
||||
_libcrypt_version_reference (symbol, VERSION_libcrypt_##version)
|
||||
#define _libcrypt_version_reference(symbol, version) \
|
||||
__libcrypt_version_reference (symbol, version)
|
||||
#define __libcrypt_version_reference(symbol, version) \
|
||||
__asm__ (".symver " #symbol ", " #symbol "@" #version)
|
||||
|
||||
extern void setkey (const char *);
|
||||
extern void encrypt (const char *, int);
|
||||
libcrypt_version_reference (setkey, GLIBC_2_0);
|
||||
libcrypt_version_reference (encrypt, GLIBC_2_0);
|
||||
|
||||
int totfails = 0;
|
||||
|
||||
int main (int argc, char *argv[]);
|
||||
void get8 (char *cp);
|
||||
void put8 (char *cp);
|
||||
void good_bye (void) __attribute__ ((noreturn));
|
||||
|
||||
void
|
||||
good_bye (void)
|
||||
{
|
||||
if(totfails == 0) {
|
||||
printf("Passed DES validation suite\n");
|
||||
exit(0);
|
||||
} else {
|
||||
printf("%d failures during DES validation suite!!!\n", totfails);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
char key[64],plain[64],cipher[64],answer[64];
|
||||
int i;
|
||||
int fail;
|
||||
|
||||
for(;!feof(stdin);){
|
||||
|
||||
get8(key);
|
||||
printf(" K: "); put8(key);
|
||||
setkey(key);
|
||||
|
||||
get8(plain);
|
||||
printf(" P: "); put8(plain);
|
||||
|
||||
get8(answer);
|
||||
printf(" C: "); put8(answer);
|
||||
|
||||
for(i=0;i<64;i++)
|
||||
cipher[i] = plain[i];
|
||||
encrypt(cipher, 0);
|
||||
|
||||
for(i=0;i<64;i++)
|
||||
if(cipher[i] != answer[i])
|
||||
break;
|
||||
fail = 0;
|
||||
if(i != 64){
|
||||
printf(" Encrypt FAIL");
|
||||
fail++; totfails++;
|
||||
}
|
||||
|
||||
encrypt(cipher, 1);
|
||||
|
||||
for(i=0;i<64;i++)
|
||||
if(cipher[i] != plain[i])
|
||||
break;
|
||||
if(i != 64){
|
||||
printf(" Decrypt FAIL");
|
||||
fail++; totfails++;
|
||||
}
|
||||
|
||||
if(fail == 0)
|
||||
printf(" OK");
|
||||
printf("\n");
|
||||
}
|
||||
good_bye();
|
||||
}
|
||||
void
|
||||
get8 (char *cp)
|
||||
{
|
||||
int i,j,t;
|
||||
|
||||
for(i=0;i<8;i++){
|
||||
if (scanf("%2x",&t) < 1)
|
||||
{
|
||||
if(ferror(stdin))
|
||||
totfails++;
|
||||
}
|
||||
if(feof(stdin))
|
||||
good_bye();
|
||||
for(j=0; j<8 ; j++) {
|
||||
*cp++ = (t & (0x01 << (7-j))) != 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
void
|
||||
put8 (char *cp)
|
||||
{
|
||||
int i,j,t;
|
||||
|
||||
for(i=0;i<8;i++){
|
||||
t = 0;
|
||||
for(j = 0; j<8; j++)
|
||||
t = (t<<1) | *cp++;
|
||||
printf("%02x", t);
|
||||
}
|
||||
}
|
||||
|
||||
#else /* encrypt and setkey are not available. */
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
return 77; /* UNSUPPORTED */
|
||||
}
|
||||
|
||||
#endif
|
171
crypt/cert.input
171
crypt/cert.input
@ -1,171 +0,0 @@
|
||||
0101010101010101 95f8a5e5dd31d900 8000000000000000
|
||||
0101010101010101 dd7f121ca5015619 4000000000000000
|
||||
0101010101010101 2e8653104f3834ea 2000000000000000
|
||||
0101010101010101 4bd388ff6cd81d4f 1000000000000000
|
||||
0101010101010101 20b9e767b2fb1456 0800000000000000
|
||||
0101010101010101 55579380d77138ef 0400000000000000
|
||||
0101010101010101 6cc5defaaf04512f 0200000000000000
|
||||
0101010101010101 0d9f279ba5d87260 0100000000000000
|
||||
0101010101010101 d9031b0271bd5a0a 0080000000000000
|
||||
0101010101010101 424250b37c3dd951 0040000000000000
|
||||
0101010101010101 b8061b7ecd9a21e5 0020000000000000
|
||||
0101010101010101 f15d0f286b65bd28 0010000000000000
|
||||
0101010101010101 add0cc8d6e5deba1 0008000000000000
|
||||
0101010101010101 e6d5f82752ad63d1 0004000000000000
|
||||
0101010101010101 ecbfe3bd3f591a5e 0002000000000000
|
||||
0101010101010101 f356834379d165cd 0001000000000000
|
||||
0101010101010101 2b9f982f20037fa9 0000800000000000
|
||||
0101010101010101 889de068a16f0be6 0000400000000000
|
||||
0101010101010101 e19e275d846a1298 0000200000000000
|
||||
0101010101010101 329a8ed523d71aec 0000100000000000
|
||||
0101010101010101 e7fce22557d23c97 0000080000000000
|
||||
0101010101010101 12a9f5817ff2d65d 0000040000000000
|
||||
0101010101010101 a484c3ad38dc9c19 0000020000000000
|
||||
0101010101010101 fbe00a8a1ef8ad72 0000010000000000
|
||||
0101010101010101 750d079407521363 0000008000000000
|
||||
0101010101010101 64feed9c724c2faf 0000004000000000
|
||||
0101010101010101 f02b263b328e2b60 0000002000000000
|
||||
0101010101010101 9d64555a9a10b852 0000001000000000
|
||||
0101010101010101 d106ff0bed5255d7 0000000800000000
|
||||
0101010101010101 e1652c6b138c64a5 0000000400000000
|
||||
0101010101010101 e428581186ec8f46 0000000200000000
|
||||
0101010101010101 aeb5f5ede22d1a36 0000000100000000
|
||||
0101010101010101 e943d7568aec0c5c 0000000080000000
|
||||
0101010101010101 df98c8276f54b04b 0000000040000000
|
||||
0101010101010101 b160e4680f6c696f 0000000020000000
|
||||
0101010101010101 fa0752b07d9c4ab8 0000000010000000
|
||||
0101010101010101 ca3a2b036dbc8502 0000000008000000
|
||||
0101010101010101 5e0905517bb59bcf 0000000004000000
|
||||
0101010101010101 814eeb3b91d90726 0000000002000000
|
||||
0101010101010101 4d49db1532919c9f 0000000001000000
|
||||
0101010101010101 25eb5fc3f8cf0621 0000000000800000
|
||||
0101010101010101 ab6a20c0620d1c6f 0000000000400000
|
||||
0101010101010101 79e90dbc98f92cca 0000000000200000
|
||||
0101010101010101 866ecedd8072bb0e 0000000000100000
|
||||
0101010101010101 8b54536f2f3e64a8 0000000000080000
|
||||
0101010101010101 ea51d3975595b86b 0000000000040000
|
||||
0101010101010101 caffc6ac4542de31 0000000000020000
|
||||
0101010101010101 8dd45a2ddf90796c 0000000000010000
|
||||
0101010101010101 1029d55e880ec2d0 0000000000008000
|
||||
0101010101010101 5d86cb23639dbea9 0000000000004000
|
||||
0101010101010101 1d1ca853ae7c0c5f 0000000000002000
|
||||
0101010101010101 ce332329248f3228 0000000000001000
|
||||
0101010101010101 8405d1abe24fb942 0000000000000800
|
||||
0101010101010101 e643d78090ca4207 0000000000000400
|
||||
0101010101010101 48221b9937748a23 0000000000000200
|
||||
0101010101010101 dd7c0bbd61fafd54 0000000000000100
|
||||
0101010101010101 2fbc291a570db5c4 0000000000000080
|
||||
0101010101010101 e07c30d7e4e26e12 0000000000000040
|
||||
0101010101010101 0953e2258e8e90a1 0000000000000020
|
||||
0101010101010101 5b711bc4ceebf2ee 0000000000000010
|
||||
0101010101010101 cc083f1e6d9e85f6 0000000000000008
|
||||
0101010101010101 d2fd8867d50d2dfe 0000000000000004
|
||||
0101010101010101 06e7ea22ce92708f 0000000000000002
|
||||
0101010101010101 166b40b44aba4bd6 0000000000000001
|
||||
8001010101010101 0000000000000000 95a8d72813daa94d
|
||||
4001010101010101 0000000000000000 0eec1487dd8c26d5
|
||||
2001010101010101 0000000000000000 7ad16ffb79c45926
|
||||
1001010101010101 0000000000000000 d3746294ca6a6cf3
|
||||
0801010101010101 0000000000000000 809f5f873c1fd761
|
||||
0401010101010101 0000000000000000 c02faffec989d1fc
|
||||
0201010101010101 0000000000000000 4615aa1d33e72f10
|
||||
0180010101010101 0000000000000000 2055123350c00858
|
||||
0140010101010101 0000000000000000 df3b99d6577397c8
|
||||
0120010101010101 0000000000000000 31fe17369b5288c9
|
||||
0110010101010101 0000000000000000 dfdd3cc64dae1642
|
||||
0108010101010101 0000000000000000 178c83ce2b399d94
|
||||
0104010101010101 0000000000000000 50f636324a9b7f80
|
||||
0102010101010101 0000000000000000 a8468ee3bc18f06d
|
||||
0101800101010101 0000000000000000 a2dc9e92fd3cde92
|
||||
0101400101010101 0000000000000000 cac09f797d031287
|
||||
0101200101010101 0000000000000000 90ba680b22aeb525
|
||||
0101100101010101 0000000000000000 ce7a24f350e280b6
|
||||
0101080101010101 0000000000000000 882bff0aa01a0b87
|
||||
0101040101010101 0000000000000000 25610288924511c2
|
||||
0101020101010101 0000000000000000 c71516c29c75d170
|
||||
0101018001010101 0000000000000000 5199c29a52c9f059
|
||||
0101014001010101 0000000000000000 c22f0a294a71f29f
|
||||
0101012001010101 0000000000000000 ee371483714c02ea
|
||||
0101011001010101 0000000000000000 a81fbd448f9e522f
|
||||
0101010801010101 0000000000000000 4f644c92e192dfed
|
||||
0101010401010101 0000000000000000 1afa9a66a6df92ae
|
||||
0101010201010101 0000000000000000 b3c1cc715cb879d8
|
||||
0101010180010101 0000000000000000 19d032e64ab0bd8b
|
||||
0101010140010101 0000000000000000 3cfaa7a7dc8720dc
|
||||
0101010120010101 0000000000000000 b7265f7f447ac6f3
|
||||
0101010110010101 0000000000000000 9db73b3c0d163f54
|
||||
0101010108010101 0000000000000000 8181b65babf4a975
|
||||
0101010104010101 0000000000000000 93c9b64042eaa240
|
||||
0101010102010101 0000000000000000 5570530829705592
|
||||
0101010101800101 0000000000000000 8638809e878787a0
|
||||
0101010101400101 0000000000000000 41b9a79af79ac208
|
||||
0101010101200101 0000000000000000 7a9be42f2009a892
|
||||
0101010101100101 0000000000000000 29038d56ba6d2745
|
||||
0101010101080101 0000000000000000 5495c6abf1e5df51
|
||||
0101010101040101 0000000000000000 ae13dbd561488933
|
||||
0101010101020101 0000000000000000 024d1ffa8904e389
|
||||
0101010101018001 0000000000000000 d1399712f99bf02e
|
||||
0101010101014001 0000000000000000 14c1d7c1cffec79e
|
||||
0101010101012001 0000000000000000 1de5279dae3bed6f
|
||||
0101010101011001 0000000000000000 e941a33f85501303
|
||||
0101010101010801 0000000000000000 da99dbbc9a03f379
|
||||
0101010101010401 0000000000000000 b7fc92f91d8e92e9
|
||||
0101010101010201 0000000000000000 ae8e5caa3ca04e85
|
||||
0101010101010180 0000000000000000 9cc62df43b6eed74
|
||||
0101010101010140 0000000000000000 d863dbb5c59a91a0
|
||||
0101010101010120 0000000000000000 a1ab2190545b91d7
|
||||
0101010101010110 0000000000000000 0875041e64c570f7
|
||||
0101010101010108 0000000000000000 5a594528bebef1cc
|
||||
0101010101010104 0000000000000000 fcdb3291de21f0c0
|
||||
0101010101010102 0000000000000000 869efd7f9f265a09
|
||||
1046913489980131 0000000000000000 88d55e54f54c97b4
|
||||
1007103489988020 0000000000000000 0c0cc00c83ea48fd
|
||||
10071034c8980120 0000000000000000 83bc8ef3a6570183
|
||||
1046103489988020 0000000000000000 df725dcad94ea2e9
|
||||
1086911519190101 0000000000000000 e652b53b550be8b0
|
||||
1086911519580101 0000000000000000 af527120c485cbb0
|
||||
5107b01519580101 0000000000000000 0f04ce393db926d5
|
||||
1007b01519190101 0000000000000000 c9f00ffc74079067
|
||||
3107915498080101 0000000000000000 7cfd82a593252b4e
|
||||
3107919498080101 0000000000000000 cb49a2f9e91363e3
|
||||
10079115b9080140 0000000000000000 00b588be70d23f56
|
||||
3107911598080140 0000000000000000 406a9a6ab43399ae
|
||||
1007d01589980101 0000000000000000 6cb773611dca9ada
|
||||
9107911589980101 0000000000000000 67fd21c17dbb5d70
|
||||
9107d01589190101 0000000000000000 9592cb4110430787
|
||||
1007d01598980120 0000000000000000 a6b7ff68a318ddd3
|
||||
1007940498190101 0000000000000000 4d102196c914ca16
|
||||
0107910491190401 0000000000000000 2dfa9f4573594965
|
||||
0107910491190101 0000000000000000 b46604816c0e0774
|
||||
0107940491190401 0000000000000000 6e7e6221a4f34e87
|
||||
19079210981a0101 0000000000000000 aa85e74643233199
|
||||
1007911998190801 0000000000000000 2e5a19db4d1962d6
|
||||
10079119981a0801 0000000000000000 23a866a809d30894
|
||||
1007921098190101 0000000000000000 d812d961f017d320
|
||||
100791159819010b 0000000000000000 055605816e58608f
|
||||
1004801598190101 0000000000000000 abd88e8b1b7716f1
|
||||
1004801598190102 0000000000000000 537ac95be69da1e1
|
||||
1004801598190108 0000000000000000 aed0f6ae3c25cdd8
|
||||
1002911598100104 0000000000000000 b3e35a5ee53e7b8d
|
||||
1002911598190104 0000000000000000 61c79c71921a2ef8
|
||||
1002911598100201 0000000000000000 e2f5728f0995013c
|
||||
1002911698100101 0000000000000000 1aeac39a61f0a464
|
||||
7ca110454a1a6e57 01a1d6d039776742 690f5b0d9a26939b
|
||||
0131d9619dc1376e 5cd54ca83def57da 7a389d10354bd271
|
||||
07a1133e4a0b2686 0248d43806f67172 868ebb51cab4599a
|
||||
3849674c2602319e 51454b582ddf440a 7178876e01f19b2a
|
||||
04b915ba43feb5b6 42fd443059577fa2 af37fb421f8c4095
|
||||
0113b970fd34f2ce 059b5e0851cf143a 86a560f10ec6d85b
|
||||
0170f175468fb5e6 0756d8e0774761d2 0cd3da020021dc09
|
||||
43297fad38e373fe 762514b829bf486a ea676b2cb7db2b7a
|
||||
07a7137045da2a16 3bdd119049372802 dfd64a815caf1a0f
|
||||
04689104c2fd3b2f 26955f6835af609a 5c513c9c4886c088
|
||||
37d06bb516cb7546 164d5e404f275232 0a2aeeae3ff4ab77
|
||||
1f08260d1ac2465e 6b056e18759f5cca ef1bf03e5dfa575a
|
||||
584023641aba6176 004bd6ef09176062 88bf0db6d70dee56
|
||||
025816164629b007 480d39006ee762f2 a1f9915541020b56
|
||||
49793ebc79b3258f 437540c8698f3cfa 6fbf1cafcffd0556
|
||||
4fb05e1515ab73a7 072d43a077075292 2f22e49bab7ca1ac
|
||||
49e95d6d4ca229bf 02fe55778117f12a 5a6b612cc26cce4a
|
||||
018310dc409b26d6 1d9d5c5018f728c2 5f4c038ed12b2e41
|
||||
1c587f1c13924fef 305532286d6f295a 63fac0d034d9f793
|
@ -1,183 +0,0 @@
|
||||
/*
|
||||
* UFC-crypt: ultra fast crypt(3) implementation
|
||||
*
|
||||
* Copyright (C) 1991-2023 Free Software Foundation, Inc.
|
||||
*
|
||||
* The GNU C 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.
|
||||
*
|
||||
* The GNU C 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 the GNU C Library; if not, see
|
||||
* <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* crypt entry points
|
||||
*
|
||||
* @(#)crypt-entry.c 1.2 12/20/96
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef DEBUG
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <fips-private.h>
|
||||
|
||||
#ifndef STATIC
|
||||
#define STATIC static
|
||||
#endif
|
||||
|
||||
#include "crypt-private.h"
|
||||
#include <shlib-compat.h>
|
||||
|
||||
/* Prototypes for local functions. */
|
||||
#ifndef __GNU_LIBRARY__
|
||||
void _ufc_clearmem (char *start, int cnt);
|
||||
#else
|
||||
#define _ufc_clearmem(start, cnt) memset(start, 0, cnt)
|
||||
#endif
|
||||
extern char *__md5_crypt_r (const char *key, const char *salt, char *buffer,
|
||||
int buflen);
|
||||
extern char *__md5_crypt (const char *key, const char *salt);
|
||||
extern char *__sha256_crypt_r (const char *key, const char *salt,
|
||||
char *buffer, int buflen);
|
||||
extern char *__sha256_crypt (const char *key, const char *salt);
|
||||
extern char *__sha512_crypt_r (const char *key, const char *salt,
|
||||
char *buffer, int buflen);
|
||||
extern char *__sha512_crypt (const char *key, const char *salt);
|
||||
|
||||
/* Define our magic string to mark salt for MD5 encryption
|
||||
replacement. This is meant to be the same as for other MD5 based
|
||||
encryption implementations. */
|
||||
static const char md5_salt_prefix[] = "$1$";
|
||||
|
||||
/* Magic string for SHA256 encryption. */
|
||||
static const char sha256_salt_prefix[] = "$5$";
|
||||
|
||||
/* Magic string for SHA512 encryption. */
|
||||
static const char sha512_salt_prefix[] = "$6$";
|
||||
|
||||
/* For use by the old, non-reentrant routines (crypt/encrypt/setkey) */
|
||||
extern struct crypt_data _ufc_foobar;
|
||||
|
||||
/*
|
||||
* UNIX crypt function
|
||||
*/
|
||||
|
||||
char *
|
||||
__crypt_r (const char *key, const char *salt,
|
||||
struct crypt_data * __restrict data)
|
||||
{
|
||||
ufc_long res[4];
|
||||
char ktab[9];
|
||||
ufc_long xx = 25; /* to cope with GCC long long compiler bugs */
|
||||
|
||||
#ifdef _LIBC
|
||||
/* Try to find out whether we have to use MD5 encryption replacement. */
|
||||
if (strncmp (md5_salt_prefix, salt, sizeof (md5_salt_prefix) - 1) == 0)
|
||||
{
|
||||
/* FIPS rules out MD5 password encryption. */
|
||||
if (fips_enabled_p ())
|
||||
{
|
||||
__set_errno (EPERM);
|
||||
return NULL;
|
||||
}
|
||||
return __md5_crypt_r (key, salt, (char *) data,
|
||||
sizeof (struct crypt_data));
|
||||
}
|
||||
|
||||
/* Try to find out whether we have to use SHA256 encryption replacement. */
|
||||
if (strncmp (sha256_salt_prefix, salt, sizeof (sha256_salt_prefix) - 1) == 0)
|
||||
return __sha256_crypt_r (key, salt, (char *) data,
|
||||
sizeof (struct crypt_data));
|
||||
|
||||
/* Try to find out whether we have to use SHA512 encryption replacement. */
|
||||
if (strncmp (sha512_salt_prefix, salt, sizeof (sha512_salt_prefix) - 1) == 0)
|
||||
return __sha512_crypt_r (key, salt, (char *) data,
|
||||
sizeof (struct crypt_data));
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Hack DES tables according to salt
|
||||
*/
|
||||
if (!_ufc_setup_salt_r (salt, data))
|
||||
{
|
||||
__set_errno (EINVAL);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* FIPS rules out DES password encryption. */
|
||||
if (fips_enabled_p ())
|
||||
{
|
||||
__set_errno (EPERM);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Setup key schedule
|
||||
*/
|
||||
_ufc_clearmem (ktab, (int) sizeof (ktab));
|
||||
(void) strncpy (ktab, key, 8);
|
||||
_ufc_mk_keytab_r (ktab, data);
|
||||
|
||||
/*
|
||||
* Go for the 25 DES encryptions
|
||||
*/
|
||||
_ufc_clearmem ((char*) res, (int) sizeof (res));
|
||||
_ufc_doit_r (xx, data, &res[0]);
|
||||
|
||||
/*
|
||||
* Do final permutations
|
||||
*/
|
||||
_ufc_dofinalperm_r (res, data);
|
||||
|
||||
/*
|
||||
* And convert back to 6 bit ASCII
|
||||
*/
|
||||
_ufc_output_conversion_r (res[0], res[1], salt, data);
|
||||
|
||||
/*
|
||||
* Erase key-dependent intermediate data. Data dependent only on
|
||||
* the salt is not considered sensitive.
|
||||
*/
|
||||
explicit_bzero (ktab, sizeof (ktab));
|
||||
explicit_bzero (data->keysched, sizeof (data->keysched));
|
||||
explicit_bzero (res, sizeof (res));
|
||||
|
||||
return data->crypt_3_buf;
|
||||
}
|
||||
weak_alias (__crypt_r, crypt_r)
|
||||
|
||||
char *
|
||||
crypt (const char *key, const char *salt)
|
||||
{
|
||||
#ifdef _LIBC
|
||||
/* Try to find out whether we have to use MD5 encryption replacement. */
|
||||
if (strncmp (md5_salt_prefix, salt, sizeof (md5_salt_prefix) - 1) == 0
|
||||
/* Let __crypt_r deal with the error code if FIPS is enabled. */
|
||||
&& !fips_enabled_p ())
|
||||
return __md5_crypt (key, salt);
|
||||
|
||||
/* Try to find out whether we have to use SHA256 encryption replacement. */
|
||||
if (strncmp (sha256_salt_prefix, salt, sizeof (sha256_salt_prefix) - 1) == 0)
|
||||
return __sha256_crypt (key, salt);
|
||||
|
||||
/* Try to find out whether we have to use SHA512 encryption replacement. */
|
||||
if (strncmp (sha512_salt_prefix, salt, sizeof (sha512_salt_prefix) - 1) == 0)
|
||||
return __sha512_crypt (key, salt);
|
||||
#endif
|
||||
|
||||
return __crypt_r (key, salt, &_ufc_foobar);
|
||||
}
|
||||
|
||||
#if SHLIB_COMPAT (libcrypt, GLIBC_2_0, GLIBC_2_28)
|
||||
weak_alias (crypt, fcrypt)
|
||||
compat_symbol (libcrypt, fcrypt, fcrypt, GLIBC_2_0);
|
||||
#endif
|
@ -1,76 +0,0 @@
|
||||
/*
|
||||
* UFC-crypt: ultra fast crypt(3) implementation
|
||||
*
|
||||
* Copyright (C) 1991-2023 Free Software Foundation, Inc.
|
||||
*
|
||||
* The GNU C 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.
|
||||
*
|
||||
* The GNU C 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 the GNU C Library; if not, see
|
||||
* <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* @(#)crypt-private.h 1.4 12/20/96
|
||||
*/
|
||||
|
||||
/* Prototypes for local functions in libcrypt.a. */
|
||||
|
||||
#ifndef CRYPT_PRIVATE_H
|
||||
#define CRYPT_PRIVATE_H 1
|
||||
|
||||
#include <features.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifndef DOS
|
||||
#include "ufc-crypt.h"
|
||||
#else
|
||||
/*
|
||||
* Thanks to greg%wind@plains.NoDak.edu (Greg W. Wettstein)
|
||||
* for DOS patches
|
||||
*/
|
||||
#include "pl.h"
|
||||
#include "ufc.h"
|
||||
#endif
|
||||
#include "crypt.h"
|
||||
|
||||
/* crypt.c */
|
||||
extern void _ufc_doit_r (ufc_long itr, struct crypt_data * __restrict __data,
|
||||
ufc_long *res);
|
||||
|
||||
|
||||
/* crypt_util.c */
|
||||
extern void __init_des_r (struct crypt_data * __restrict __data);
|
||||
extern void __init_des (void);
|
||||
|
||||
extern bool _ufc_setup_salt_r (const char *s,
|
||||
struct crypt_data * __restrict __data);
|
||||
extern void _ufc_mk_keytab_r (const char *key,
|
||||
struct crypt_data * __restrict __data);
|
||||
extern void _ufc_dofinalperm_r (ufc_long *res,
|
||||
struct crypt_data * __restrict __data);
|
||||
extern void _ufc_output_conversion_r (ufc_long v1, ufc_long v2,
|
||||
const char *salt,
|
||||
struct crypt_data * __restrict __data);
|
||||
|
||||
extern void __setkey_r (const char *__key,
|
||||
struct crypt_data * __restrict __data);
|
||||
extern void __encrypt_r (char * __restrict __block, int __edflag,
|
||||
struct crypt_data * __restrict __data);
|
||||
|
||||
/* crypt-entry.c */
|
||||
extern char *__crypt_r (const char *__key, const char *__salt,
|
||||
struct crypt_data * __restrict __data);
|
||||
extern char *fcrypt (const char *key, const char *salt);
|
||||
|
||||
extern void __b64_from_24bit (char **cp, int *buflen,
|
||||
unsigned int b2, unsigned int b1, unsigned int b0,
|
||||
int n);
|
||||
|
||||
#endif /* crypt-private.h */
|
115
crypt/crypt.c
115
crypt/crypt.c
@ -1,115 +0,0 @@
|
||||
/*
|
||||
* UFC-crypt: ultra fast crypt(3) implementation
|
||||
*
|
||||
* Copyright (C) 1991-2023 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; see the file COPYING.LIB. If not,
|
||||
* see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* @(#)crypt.c 2.25 12/20/96
|
||||
*
|
||||
* Semiportable C version
|
||||
*
|
||||
*/
|
||||
|
||||
#include "crypt-private.h"
|
||||
|
||||
#ifdef _UFC_32_
|
||||
|
||||
/*
|
||||
* 32 bit version
|
||||
*/
|
||||
|
||||
#define SBA(sb, v) (*(long32*)((char*)(sb)+(v)))
|
||||
|
||||
void
|
||||
_ufc_doit_r (ufc_long itr, struct crypt_data * __restrict __data,
|
||||
ufc_long *res)
|
||||
{
|
||||
int i;
|
||||
long32 s, *k;
|
||||
long32 *sb01 = (long32*)__data->sb0;
|
||||
long32 *sb23 = (long32*)__data->sb2;
|
||||
long32 l1, l2, r1, r2;
|
||||
|
||||
l1 = (long32)res[0]; l2 = (long32)res[1];
|
||||
r1 = (long32)res[2]; r2 = (long32)res[3];
|
||||
|
||||
while(itr--) {
|
||||
k = (long32*)__data->keysched;
|
||||
for(i=8; i--; ) {
|
||||
s = *k++ ^ r1;
|
||||
l1 ^= SBA(sb01, s & 0xffff); l2 ^= SBA(sb01, (s & 0xffff)+4);
|
||||
l1 ^= SBA(sb01, s >>= 16 ); l2 ^= SBA(sb01, (s )+4);
|
||||
s = *k++ ^ r2;
|
||||
l1 ^= SBA(sb23, s & 0xffff); l2 ^= SBA(sb23, (s & 0xffff)+4);
|
||||
l1 ^= SBA(sb23, s >>= 16 ); l2 ^= SBA(sb23, (s )+4);
|
||||
|
||||
s = *k++ ^ l1;
|
||||
r1 ^= SBA(sb01, s & 0xffff); r2 ^= SBA(sb01, (s & 0xffff)+4);
|
||||
r1 ^= SBA(sb01, s >>= 16 ); r2 ^= SBA(sb01, (s )+4);
|
||||
s = *k++ ^ l2;
|
||||
r1 ^= SBA(sb23, s & 0xffff); r2 ^= SBA(sb23, (s & 0xffff)+4);
|
||||
r1 ^= SBA(sb23, s >>= 16 ); r2 ^= SBA(sb23, (s )+4);
|
||||
}
|
||||
s=l1; l1=r1; r1=s; s=l2; l2=r2; r2=s;
|
||||
}
|
||||
res[0] = l1; res[1] = l2; res[2] = r1; res[3] = r2;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef _UFC_64_
|
||||
|
||||
/*
|
||||
* 64 bit version
|
||||
*/
|
||||
|
||||
#define SBA(sb, v) (*(long64*)((char*)(sb)+(v)))
|
||||
|
||||
void
|
||||
_ufc_doit_r (ufc_long itr, struct crypt_data * __restrict __data,
|
||||
ufc_long *res)
|
||||
{
|
||||
int i;
|
||||
long64 l, r, s, *k;
|
||||
long64 *sb01 = (long64*)__data->sb0;
|
||||
long64 *sb23 = (long64*)__data->sb2;
|
||||
|
||||
l = (((long64)res[0]) << 32) | ((long64)res[1]);
|
||||
r = (((long64)res[2]) << 32) | ((long64)res[3]);
|
||||
|
||||
while(itr--) {
|
||||
k = (long64*)__data->keysched;
|
||||
for(i=8; i--; ) {
|
||||
s = *k++ ^ r;
|
||||
l ^= SBA(sb23, (s ) & 0xffff);
|
||||
l ^= SBA(sb23, (s >>= 16) & 0xffff);
|
||||
l ^= SBA(sb01, (s >>= 16) & 0xffff);
|
||||
l ^= SBA(sb01, (s >>= 16) );
|
||||
|
||||
s = *k++ ^ l;
|
||||
r ^= SBA(sb23, (s ) & 0xffff);
|
||||
r ^= SBA(sb23, (s >>= 16) & 0xffff);
|
||||
r ^= SBA(sb01, (s >>= 16) & 0xffff);
|
||||
r ^= SBA(sb01, (s >>= 16) );
|
||||
}
|
||||
s=l; l=r; r=s;
|
||||
}
|
||||
|
||||
res[0] = l >> 32; res[1] = l & 0xffffffff;
|
||||
res[2] = r >> 32; res[3] = r & 0xffffffff;
|
||||
}
|
||||
|
||||
#endif
|
@ -1,70 +0,0 @@
|
||||
/*
|
||||
* UFC-crypt: ultra fast crypt(3) implementation
|
||||
*
|
||||
* Copyright (C) 1991-2023 Free Software Foundation, Inc.
|
||||
*
|
||||
* The GNU C 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.
|
||||
*
|
||||
* The GNU C 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 the GNU C Library; if not, see
|
||||
* <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* @(#)crypt.h 1.5 12/20/96
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _CRYPT_H
|
||||
#define _CRYPT_H 1
|
||||
|
||||
#include <features.h>
|
||||
|
||||
__BEGIN_DECLS
|
||||
|
||||
/* One-way hash PHRASE, returning a string suitable for storage in the
|
||||
user database. SALT selects the one-way function to use, and
|
||||
ensures that no two users' hashes are the same, even if they use
|
||||
the same passphrase. The return value points to static storage
|
||||
which will be overwritten by the next call to crypt. */
|
||||
extern char *crypt (const char *__phrase, const char *__salt)
|
||||
__THROW __nonnull ((1, 2));
|
||||
|
||||
#ifdef __USE_GNU
|
||||
|
||||
/* This structure provides scratch and output buffers for 'crypt_r'.
|
||||
Its contents should not be accessed directly. */
|
||||
struct crypt_data
|
||||
{
|
||||
char keysched[16 * 8];
|
||||
char sb0[32768];
|
||||
char sb1[32768];
|
||||
char sb2[32768];
|
||||
char sb3[32768];
|
||||
/* end-of-aligment-critical-data */
|
||||
char crypt_3_buf[14];
|
||||
char current_salt[2];
|
||||
long int current_saltbits;
|
||||
int direction, initialized;
|
||||
};
|
||||
|
||||
/* Thread-safe version of 'crypt'.
|
||||
DATA must point to a 'struct crypt_data' allocated by the caller.
|
||||
Before the first call to 'crypt_r' with a new 'struct crypt_data',
|
||||
that object must be initialized to all zeroes. The pointer
|
||||
returned, if not NULL, will point within DATA. (It will still be
|
||||
overwritten by the next call to 'crypt_r' with the same DATA.) */
|
||||
extern char *crypt_r (const char *__phrase, const char *__salt,
|
||||
struct crypt_data * __restrict __data)
|
||||
__THROW __nonnull ((1, 2, 3));
|
||||
#endif
|
||||
|
||||
__END_DECLS
|
||||
|
||||
#endif /* crypt.h */
|
@ -1,946 +0,0 @@
|
||||
/*
|
||||
* UFC-crypt: ultra fast crypt(3) implementation
|
||||
*
|
||||
* Copyright (C) 1991-2023 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; see the file COPYING.LIB. If not,
|
||||
* see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* @(#)crypt_util.c 2.56 12/20/96
|
||||
*
|
||||
* Support routines
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef DEBUG
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
#include <atomic.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifndef STATIC
|
||||
#define STATIC static
|
||||
#endif
|
||||
|
||||
#include "crypt-private.h"
|
||||
#include <shlib-compat.h>
|
||||
|
||||
/* Prototypes for local functions. */
|
||||
#ifndef __GNU_LIBRARY__
|
||||
void _ufc_clearmem (char *start, int cnt);
|
||||
void _ufc_copymem (char *from, char *to, int cnt);
|
||||
#endif
|
||||
#ifdef _UFC_32_
|
||||
STATIC void shuffle_sb (long32 *k, ufc_long saltbits);
|
||||
#else
|
||||
STATIC void shuffle_sb (long64 *k, ufc_long saltbits);
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Permutation done once on the 56 bit
|
||||
* key derived from the original 8 byte ASCII key.
|
||||
*/
|
||||
static const int pc1[56] = {
|
||||
57, 49, 41, 33, 25, 17, 9, 1, 58, 50, 42, 34, 26, 18,
|
||||
10, 2, 59, 51, 43, 35, 27, 19, 11, 3, 60, 52, 44, 36,
|
||||
63, 55, 47, 39, 31, 23, 15, 7, 62, 54, 46, 38, 30, 22,
|
||||
14, 6, 61, 53, 45, 37, 29, 21, 13, 5, 28, 20, 12, 4
|
||||
};
|
||||
|
||||
/*
|
||||
* How much to rotate each 28 bit half of the pc1 permutated
|
||||
* 56 bit key before using pc2 to give the i' key
|
||||
*/
|
||||
static const int rots[16] = {
|
||||
1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1
|
||||
};
|
||||
|
||||
/*
|
||||
* Permutation giving the key
|
||||
* of the i' DES round
|
||||
*/
|
||||
static const int pc2[48] = {
|
||||
14, 17, 11, 24, 1, 5, 3, 28, 15, 6, 21, 10,
|
||||
23, 19, 12, 4, 26, 8, 16, 7, 27, 20, 13, 2,
|
||||
41, 52, 31, 37, 47, 55, 30, 40, 51, 45, 33, 48,
|
||||
44, 49, 39, 56, 34, 53, 46, 42, 50, 36, 29, 32
|
||||
};
|
||||
|
||||
/*
|
||||
* The E expansion table which selects
|
||||
* bits from the 32 bit intermediate result.
|
||||
*/
|
||||
static const int esel[48] = {
|
||||
32, 1, 2, 3, 4, 5, 4, 5, 6, 7, 8, 9,
|
||||
8, 9, 10, 11, 12, 13, 12, 13, 14, 15, 16, 17,
|
||||
16, 17, 18, 19, 20, 21, 20, 21, 22, 23, 24, 25,
|
||||
24, 25, 26, 27, 28, 29, 28, 29, 30, 31, 32, 1
|
||||
};
|
||||
|
||||
/*
|
||||
* Permutation done on the
|
||||
* result of sbox lookups
|
||||
*/
|
||||
static const int perm32[32] = {
|
||||
16, 7, 20, 21, 29, 12, 28, 17, 1, 15, 23, 26, 5, 18, 31, 10,
|
||||
2, 8, 24, 14, 32, 27, 3, 9, 19, 13, 30, 6, 22, 11, 4, 25
|
||||
};
|
||||
|
||||
/*
|
||||
* The sboxes
|
||||
*/
|
||||
static const int sbox[8][4][16]= {
|
||||
{ { 14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7 },
|
||||
{ 0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8 },
|
||||
{ 4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0 },
|
||||
{ 15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13 }
|
||||
},
|
||||
|
||||
{ { 15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10 },
|
||||
{ 3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5 },
|
||||
{ 0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15 },
|
||||
{ 13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9 }
|
||||
},
|
||||
|
||||
{ { 10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8 },
|
||||
{ 13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1 },
|
||||
{ 13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7 },
|
||||
{ 1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12 }
|
||||
},
|
||||
|
||||
{ { 7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15 },
|
||||
{ 13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9 },
|
||||
{ 10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4 },
|
||||
{ 3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14 }
|
||||
},
|
||||
|
||||
{ { 2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9 },
|
||||
{ 14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6 },
|
||||
{ 4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14 },
|
||||
{ 11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3 }
|
||||
},
|
||||
|
||||
{ { 12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11 },
|
||||
{ 10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8 },
|
||||
{ 9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6 },
|
||||
{ 4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13 }
|
||||
},
|
||||
|
||||
{ { 4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1 },
|
||||
{ 13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6 },
|
||||
{ 1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2 },
|
||||
{ 6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12 }
|
||||
},
|
||||
|
||||
{ { 13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7 },
|
||||
{ 1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2 },
|
||||
{ 7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8 },
|
||||
{ 2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11 }
|
||||
}
|
||||
};
|
||||
|
||||
#if SHLIB_COMPAT (libcrypt, GLIBC_2_0, GLIBC_2_28)
|
||||
/*
|
||||
* This is the initial
|
||||
* permutation matrix
|
||||
*/
|
||||
static const int initial_perm[64] = {
|
||||
58, 50, 42, 34, 26, 18, 10, 2, 60, 52, 44, 36, 28, 20, 12, 4,
|
||||
62, 54, 46, 38, 30, 22, 14, 6, 64, 56, 48, 40, 32, 24, 16, 8,
|
||||
57, 49, 41, 33, 25, 17, 9, 1, 59, 51, 43, 35, 27, 19, 11, 3,
|
||||
61, 53, 45, 37, 29, 21, 13, 5, 63, 55, 47, 39, 31, 23, 15, 7
|
||||
};
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This is the final
|
||||
* permutation matrix
|
||||
*/
|
||||
static const int final_perm[64] = {
|
||||
40, 8, 48, 16, 56, 24, 64, 32, 39, 7, 47, 15, 55, 23, 63, 31,
|
||||
38, 6, 46, 14, 54, 22, 62, 30, 37, 5, 45, 13, 53, 21, 61, 29,
|
||||
36, 4, 44, 12, 52, 20, 60, 28, 35, 3, 43, 11, 51, 19, 59, 27,
|
||||
34, 2, 42, 10, 50, 18, 58, 26, 33, 1, 41, 9, 49, 17, 57, 25
|
||||
};
|
||||
|
||||
#define ascii_to_bin(c) ((c)>='a'?(c-59):(c)>='A'?((c)-53):(c)-'.')
|
||||
#define bin_to_ascii(c) ((c)>=38?((c)-38+'a'):(c)>=12?((c)-12+'A'):(c)+'.')
|
||||
|
||||
static const ufc_long BITMASK[24] = {
|
||||
0x40000000, 0x20000000, 0x10000000, 0x08000000, 0x04000000, 0x02000000,
|
||||
0x01000000, 0x00800000, 0x00400000, 0x00200000, 0x00100000, 0x00080000,
|
||||
0x00004000, 0x00002000, 0x00001000, 0x00000800, 0x00000400, 0x00000200,
|
||||
0x00000100, 0x00000080, 0x00000040, 0x00000020, 0x00000010, 0x00000008
|
||||
};
|
||||
|
||||
static const unsigned char bytemask[8] = {
|
||||
0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01
|
||||
};
|
||||
|
||||
static const ufc_long longmask[32] = {
|
||||
0x80000000, 0x40000000, 0x20000000, 0x10000000,
|
||||
0x08000000, 0x04000000, 0x02000000, 0x01000000,
|
||||
0x00800000, 0x00400000, 0x00200000, 0x00100000,
|
||||
0x00080000, 0x00040000, 0x00020000, 0x00010000,
|
||||
0x00008000, 0x00004000, 0x00002000, 0x00001000,
|
||||
0x00000800, 0x00000400, 0x00000200, 0x00000100,
|
||||
0x00000080, 0x00000040, 0x00000020, 0x00000010,
|
||||
0x00000008, 0x00000004, 0x00000002, 0x00000001
|
||||
};
|
||||
|
||||
/*
|
||||
* do_pc1: permform pc1 permutation in the key schedule generation.
|
||||
*
|
||||
* The first index is the byte number in the 8 byte ASCII key
|
||||
* - second - - the two 28 bits halves of the result
|
||||
* - third - selects the 7 bits actually used of each byte
|
||||
*
|
||||
* The result is kept with 28 bit per 32 bit with the 4 most significant
|
||||
* bits zero.
|
||||
*/
|
||||
static ufc_long do_pc1[8][2][128];
|
||||
|
||||
/*
|
||||
* do_pc2: permform pc2 permutation in the key schedule generation.
|
||||
*
|
||||
* The first index is the septet number in the two 28 bit intermediate values
|
||||
* - second - - - septet values
|
||||
*
|
||||
* Knowledge of the structure of the pc2 permutation is used.
|
||||
*
|
||||
* The result is kept with 28 bit per 32 bit with the 4 most significant
|
||||
* bits zero.
|
||||
*/
|
||||
static ufc_long do_pc2[8][128];
|
||||
|
||||
/*
|
||||
* eperm32tab: do 32 bit permutation and E selection
|
||||
*
|
||||
* The first index is the byte number in the 32 bit value to be permuted
|
||||
* - second - is the value of this byte
|
||||
* - third - selects the two 32 bit values
|
||||
*
|
||||
* The table is used and generated internally in init_des to speed it up
|
||||
*/
|
||||
static ufc_long eperm32tab[4][256][2];
|
||||
|
||||
/*
|
||||
* efp: undo an extra e selection and do final
|
||||
* permutation giving the DES result.
|
||||
*
|
||||
* Invoked 6 bit a time on two 48 bit values
|
||||
* giving two 32 bit longs.
|
||||
*/
|
||||
static ufc_long efp[16][64][2];
|
||||
|
||||
/* Table with characters for base64 transformation. */
|
||||
static const char b64t[64] =
|
||||
"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
|
||||
|
||||
/*
|
||||
* For use by the old, non-reentrant routines
|
||||
* (crypt/encrypt/setkey)
|
||||
*/
|
||||
struct crypt_data _ufc_foobar;
|
||||
|
||||
#ifdef __GNU_LIBRARY__
|
||||
#include <libc-lock.h>
|
||||
|
||||
__libc_lock_define_initialized (static, _ufc_tables_lock)
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
void
|
||||
_ufc_prbits (ufc_long *a, int n)
|
||||
{
|
||||
ufc_long i, j, t, tmp;
|
||||
n /= 8;
|
||||
for(i = 0; i < n; i++) {
|
||||
tmp=0;
|
||||
for(j = 0; j < 8; j++) {
|
||||
t=8*i+j;
|
||||
tmp|=(a[t/24] & BITMASK[t % 24])?bytemask[j]:0;
|
||||
}
|
||||
(void)printf("%02lx ", tmp);
|
||||
}
|
||||
printf(" ");
|
||||
}
|
||||
|
||||
static void __attribute__ ((unused))
|
||||
_ufc_set_bits (ufc_long v, ufc_long *b)
|
||||
{
|
||||
ufc_long i;
|
||||
*b = 0;
|
||||
for(i = 0; i < 24; i++) {
|
||||
if(v & longmask[8 + i])
|
||||
*b |= BITMASK[i];
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef __GNU_LIBRARY__
|
||||
/*
|
||||
* Silly rewrites of 'bzero'/'memset'. I do so
|
||||
* because some machines don't have
|
||||
* bzero and some don't have memset.
|
||||
*/
|
||||
|
||||
void
|
||||
_ufc_clearmem (char *start, int cnt)
|
||||
{
|
||||
while(cnt--)
|
||||
*start++ = '\0';
|
||||
}
|
||||
|
||||
void
|
||||
_ufc_copymem (char *from, char *to, int cnt)
|
||||
{
|
||||
while(cnt--)
|
||||
*to++ = *from++;
|
||||
}
|
||||
#else
|
||||
#define _ufc_clearmem(start, cnt) memset(start, 0, cnt)
|
||||
#define _ufc_copymem(from, to, cnt) memcpy(to, from, cnt)
|
||||
#endif
|
||||
|
||||
/* lookup a 6 bit value in sbox */
|
||||
|
||||
#define s_lookup(i,s) sbox[(i)][(((s)>>4) & 0x2)|((s) & 0x1)][((s)>>1) & 0xf];
|
||||
|
||||
/*
|
||||
* Initialize unit - may be invoked directly
|
||||
* by fcrypt users.
|
||||
*/
|
||||
|
||||
void
|
||||
__init_des_r (struct crypt_data * __restrict __data)
|
||||
{
|
||||
int comes_from_bit;
|
||||
int bit, sg;
|
||||
ufc_long j;
|
||||
ufc_long mask1, mask2;
|
||||
int e_inverse[64];
|
||||
static volatile int small_tables_initialized = 0;
|
||||
|
||||
#ifdef _UFC_32_
|
||||
long32 *sb[4];
|
||||
sb[0] = (long32*)__data->sb0; sb[1] = (long32*)__data->sb1;
|
||||
sb[2] = (long32*)__data->sb2; sb[3] = (long32*)__data->sb3;
|
||||
#endif
|
||||
#ifdef _UFC_64_
|
||||
long64 *sb[4];
|
||||
sb[0] = (long64*)__data->sb0; sb[1] = (long64*)__data->sb1;
|
||||
sb[2] = (long64*)__data->sb2; sb[3] = (long64*)__data->sb3;
|
||||
#endif
|
||||
|
||||
if(small_tables_initialized == 0) {
|
||||
#ifdef __GNU_LIBRARY__
|
||||
__libc_lock_lock (_ufc_tables_lock);
|
||||
if(small_tables_initialized)
|
||||
goto small_tables_done;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Create the do_pc1 table used
|
||||
* to affect pc1 permutation
|
||||
* when generating keys
|
||||
*/
|
||||
_ufc_clearmem((char*)do_pc1, (int)sizeof(do_pc1));
|
||||
for(bit = 0; bit < 56; bit++) {
|
||||
comes_from_bit = pc1[bit] - 1;
|
||||
mask1 = bytemask[comes_from_bit % 8 + 1];
|
||||
mask2 = longmask[bit % 28 + 4];
|
||||
for(j = 0; j < 128; j++) {
|
||||
if(j & mask1)
|
||||
do_pc1[comes_from_bit / 8][bit / 28][j] |= mask2;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Create the do_pc2 table used
|
||||
* to affect pc2 permutation when
|
||||
* generating keys
|
||||
*/
|
||||
_ufc_clearmem((char*)do_pc2, (int)sizeof(do_pc2));
|
||||
for(bit = 0; bit < 48; bit++) {
|
||||
comes_from_bit = pc2[bit] - 1;
|
||||
mask1 = bytemask[comes_from_bit % 7 + 1];
|
||||
mask2 = BITMASK[bit % 24];
|
||||
for(j = 0; j < 128; j++) {
|
||||
if(j & mask1)
|
||||
do_pc2[comes_from_bit / 7][j] |= mask2;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Now generate the table used to do combined
|
||||
* 32 bit permutation and e expansion
|
||||
*
|
||||
* We use it because we have to permute 16384 32 bit
|
||||
* longs into 48 bit in order to initialize sb.
|
||||
*
|
||||
* Looping 48 rounds per permutation becomes
|
||||
* just too slow...
|
||||
*
|
||||
*/
|
||||
|
||||
_ufc_clearmem((char*)eperm32tab, (int)sizeof(eperm32tab));
|
||||
for(bit = 0; bit < 48; bit++) {
|
||||
ufc_long mask1,comes_from;
|
||||
comes_from = perm32[esel[bit]-1]-1;
|
||||
mask1 = bytemask[comes_from % 8];
|
||||
for(j = 256; j--;) {
|
||||
if(j & mask1)
|
||||
eperm32tab[comes_from / 8][j][bit / 24] |= BITMASK[bit % 24];
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Create an inverse matrix for esel telling
|
||||
* where to plug out bits if undoing it
|
||||
*/
|
||||
for(bit=48; bit--;) {
|
||||
e_inverse[esel[bit] - 1 ] = bit;
|
||||
e_inverse[esel[bit] - 1 + 32] = bit + 48;
|
||||
}
|
||||
|
||||
/*
|
||||
* create efp: the matrix used to
|
||||
* undo the E expansion and effect final permutation
|
||||
*/
|
||||
_ufc_clearmem((char*)efp, (int)sizeof efp);
|
||||
for(bit = 0; bit < 64; bit++) {
|
||||
int o_bit, o_long;
|
||||
ufc_long word_value, mask1, mask2;
|
||||
int comes_from_f_bit, comes_from_e_bit;
|
||||
int comes_from_word, bit_within_word;
|
||||
|
||||
/* See where bit i belongs in the two 32 bit long's */
|
||||
o_long = bit / 32; /* 0..1 */
|
||||
o_bit = bit % 32; /* 0..31 */
|
||||
|
||||
/*
|
||||
* And find a bit in the e permutated value setting this bit.
|
||||
*
|
||||
* Note: the e selection may have selected the same bit several
|
||||
* times. By the initialization of e_inverse, we only look
|
||||
* for one specific instance.
|
||||
*/
|
||||
comes_from_f_bit = final_perm[bit] - 1; /* 0..63 */
|
||||
comes_from_e_bit = e_inverse[comes_from_f_bit]; /* 0..95 */
|
||||
comes_from_word = comes_from_e_bit / 6; /* 0..15 */
|
||||
bit_within_word = comes_from_e_bit % 6; /* 0..5 */
|
||||
|
||||
mask1 = longmask[bit_within_word + 26];
|
||||
mask2 = longmask[o_bit];
|
||||
|
||||
for(word_value = 64; word_value--;) {
|
||||
if(word_value & mask1)
|
||||
efp[comes_from_word][word_value][o_long] |= mask2;
|
||||
}
|
||||
}
|
||||
atomic_write_barrier ();
|
||||
small_tables_initialized = 1;
|
||||
#ifdef __GNU_LIBRARY__
|
||||
small_tables_done:
|
||||
__libc_lock_unlock(_ufc_tables_lock);
|
||||
#endif
|
||||
} else
|
||||
atomic_read_barrier ();
|
||||
|
||||
/*
|
||||
* Create the sb tables:
|
||||
*
|
||||
* For each 12 bit segment of an 48 bit intermediate
|
||||
* result, the sb table precomputes the two 4 bit
|
||||
* values of the sbox lookups done with the two 6
|
||||
* bit halves, shifts them to their proper place,
|
||||
* sends them through perm32 and finally E expands
|
||||
* them so that they are ready for the next
|
||||
* DES round.
|
||||
*
|
||||
*/
|
||||
|
||||
if (__data->sb0 + sizeof (__data->sb0) == __data->sb1
|
||||
&& __data->sb1 + sizeof (__data->sb1) == __data->sb2
|
||||
&& __data->sb2 + sizeof (__data->sb2) == __data->sb3)
|
||||
_ufc_clearmem(__data->sb0,
|
||||
(int)sizeof(__data->sb0)
|
||||
+ (int)sizeof(__data->sb1)
|
||||
+ (int)sizeof(__data->sb2)
|
||||
+ (int)sizeof(__data->sb3));
|
||||
else {
|
||||
_ufc_clearmem(__data->sb0, (int)sizeof(__data->sb0));
|
||||
_ufc_clearmem(__data->sb1, (int)sizeof(__data->sb1));
|
||||
_ufc_clearmem(__data->sb2, (int)sizeof(__data->sb2));
|
||||
_ufc_clearmem(__data->sb3, (int)sizeof(__data->sb3));
|
||||
}
|
||||
|
||||
for(sg = 0; sg < 4; sg++) {
|
||||
int j1, j2;
|
||||
int s1, s2;
|
||||
|
||||
for(j1 = 0; j1 < 64; j1++) {
|
||||
s1 = s_lookup(2 * sg, j1);
|
||||
for(j2 = 0; j2 < 64; j2++) {
|
||||
ufc_long to_permute, inx;
|
||||
|
||||
s2 = s_lookup(2 * sg + 1, j2);
|
||||
to_permute = (((ufc_long)s1 << 4) |
|
||||
(ufc_long)s2) << (24 - 8 * (ufc_long)sg);
|
||||
|
||||
#ifdef _UFC_32_
|
||||
inx = ((j1 << 6) | j2) << 1;
|
||||
sb[sg][inx ] = eperm32tab[0][(to_permute >> 24) & 0xff][0];
|
||||
sb[sg][inx+1] = eperm32tab[0][(to_permute >> 24) & 0xff][1];
|
||||
sb[sg][inx ] |= eperm32tab[1][(to_permute >> 16) & 0xff][0];
|
||||
sb[sg][inx+1] |= eperm32tab[1][(to_permute >> 16) & 0xff][1];
|
||||
sb[sg][inx ] |= eperm32tab[2][(to_permute >> 8) & 0xff][0];
|
||||
sb[sg][inx+1] |= eperm32tab[2][(to_permute >> 8) & 0xff][1];
|
||||
sb[sg][inx ] |= eperm32tab[3][(to_permute) & 0xff][0];
|
||||
sb[sg][inx+1] |= eperm32tab[3][(to_permute) & 0xff][1];
|
||||
#endif
|
||||
#ifdef _UFC_64_
|
||||
inx = ((j1 << 6) | j2);
|
||||
sb[sg][inx] =
|
||||
((long64)eperm32tab[0][(to_permute >> 24) & 0xff][0] << 32) |
|
||||
(long64)eperm32tab[0][(to_permute >> 24) & 0xff][1];
|
||||
sb[sg][inx] |=
|
||||
((long64)eperm32tab[1][(to_permute >> 16) & 0xff][0] << 32) |
|
||||
(long64)eperm32tab[1][(to_permute >> 16) & 0xff][1];
|
||||
sb[sg][inx] |=
|
||||
((long64)eperm32tab[2][(to_permute >> 8) & 0xff][0] << 32) |
|
||||
(long64)eperm32tab[2][(to_permute >> 8) & 0xff][1];
|
||||
sb[sg][inx] |=
|
||||
((long64)eperm32tab[3][(to_permute) & 0xff][0] << 32) |
|
||||
(long64)eperm32tab[3][(to_permute) & 0xff][1];
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
__data->current_saltbits = 0;
|
||||
__data->current_salt[0] = 0;
|
||||
__data->current_salt[1] = 0;
|
||||
__data->initialized++;
|
||||
}
|
||||
|
||||
void
|
||||
__init_des (void)
|
||||
{
|
||||
__init_des_r(&_ufc_foobar);
|
||||
}
|
||||
|
||||
/*
|
||||
* Process the elements of the sb table permuting the
|
||||
* bits swapped in the expansion by the current salt.
|
||||
*/
|
||||
|
||||
#ifdef _UFC_32_
|
||||
STATIC void
|
||||
shuffle_sb (long32 *k, ufc_long saltbits)
|
||||
{
|
||||
ufc_long j;
|
||||
long32 x;
|
||||
for(j=4096; j--;) {
|
||||
x = (k[0] ^ k[1]) & (long32)saltbits;
|
||||
*k++ ^= x;
|
||||
*k++ ^= x;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef _UFC_64_
|
||||
STATIC void
|
||||
shuffle_sb (long64 *k, ufc_long saltbits)
|
||||
{
|
||||
ufc_long j;
|
||||
long64 x;
|
||||
for(j=4096; j--;) {
|
||||
x = ((*k >> 32) ^ *k) & (long64)saltbits;
|
||||
*k++ ^= (x << 32) | x;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Return false iff C is in the specified alphabet for crypt salt.
|
||||
*/
|
||||
|
||||
static bool
|
||||
bad_for_salt (char c)
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case '0' ... '9':
|
||||
case 'A' ... 'Z':
|
||||
case 'a' ... 'z':
|
||||
case '.': case '/':
|
||||
return false;
|
||||
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Setup the unit for a new salt
|
||||
* Hopefully we'll not see a new salt in each crypt call.
|
||||
* Return false if an unexpected character was found in s[0] or s[1].
|
||||
*/
|
||||
|
||||
bool
|
||||
_ufc_setup_salt_r (const char *s, struct crypt_data * __restrict __data)
|
||||
{
|
||||
ufc_long i, j, saltbits;
|
||||
char s0, s1;
|
||||
|
||||
if(__data->initialized == 0)
|
||||
__init_des_r(__data);
|
||||
|
||||
s0 = s[0];
|
||||
if(bad_for_salt (s0))
|
||||
return false;
|
||||
|
||||
s1 = s[1];
|
||||
if(bad_for_salt (s1))
|
||||
return false;
|
||||
|
||||
if(s0 == __data->current_salt[0] && s1 == __data->current_salt[1])
|
||||
return true;
|
||||
|
||||
__data->current_salt[0] = s0;
|
||||
__data->current_salt[1] = s1;
|
||||
|
||||
/*
|
||||
* This is the only crypt change to DES:
|
||||
* entries are swapped in the expansion table
|
||||
* according to the bits set in the salt.
|
||||
*/
|
||||
saltbits = 0;
|
||||
for(i = 0; i < 2; i++) {
|
||||
long c=ascii_to_bin(s[i]);
|
||||
for(j = 0; j < 6; j++) {
|
||||
if((c >> j) & 0x1)
|
||||
saltbits |= BITMASK[6 * i + j];
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Permute the sb table values
|
||||
* to reflect the changed e
|
||||
* selection table
|
||||
*/
|
||||
#ifdef _UFC_32_
|
||||
#define LONGG long32*
|
||||
#endif
|
||||
#ifdef _UFC_64_
|
||||
#define LONGG long64*
|
||||
#endif
|
||||
|
||||
shuffle_sb((LONGG)__data->sb0, __data->current_saltbits ^ saltbits);
|
||||
shuffle_sb((LONGG)__data->sb1, __data->current_saltbits ^ saltbits);
|
||||
shuffle_sb((LONGG)__data->sb2, __data->current_saltbits ^ saltbits);
|
||||
shuffle_sb((LONGG)__data->sb3, __data->current_saltbits ^ saltbits);
|
||||
|
||||
__data->current_saltbits = saltbits;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
_ufc_mk_keytab_r (const char *key, struct crypt_data * __restrict __data)
|
||||
{
|
||||
ufc_long v1, v2, *k1;
|
||||
int i;
|
||||
#ifdef _UFC_32_
|
||||
long32 v, *k2;
|
||||
k2 = (long32*)__data->keysched;
|
||||
#endif
|
||||
#ifdef _UFC_64_
|
||||
long64 v, *k2;
|
||||
k2 = (long64*)__data->keysched;
|
||||
#endif
|
||||
|
||||
v1 = v2 = 0; k1 = &do_pc1[0][0][0];
|
||||
for(i = 8; i--;) {
|
||||
v1 |= k1[*key & 0x7f]; k1 += 128;
|
||||
v2 |= k1[*key++ & 0x7f]; k1 += 128;
|
||||
}
|
||||
|
||||
for(i = 0; i < 16; i++) {
|
||||
k1 = &do_pc2[0][0];
|
||||
|
||||
v1 = (v1 << rots[i]) | (v1 >> (28 - rots[i]));
|
||||
v = k1[(v1 >> 21) & 0x7f]; k1 += 128;
|
||||
v |= k1[(v1 >> 14) & 0x7f]; k1 += 128;
|
||||
v |= k1[(v1 >> 7) & 0x7f]; k1 += 128;
|
||||
v |= k1[(v1 ) & 0x7f]; k1 += 128;
|
||||
|
||||
#ifdef _UFC_32_
|
||||
*k2++ = (v | 0x00008000);
|
||||
v = 0;
|
||||
#endif
|
||||
#ifdef _UFC_64_
|
||||
v = (v << 32);
|
||||
#endif
|
||||
|
||||
v2 = (v2 << rots[i]) | (v2 >> (28 - rots[i]));
|
||||
v |= k1[(v2 >> 21) & 0x7f]; k1 += 128;
|
||||
v |= k1[(v2 >> 14) & 0x7f]; k1 += 128;
|
||||
v |= k1[(v2 >> 7) & 0x7f]; k1 += 128;
|
||||
v |= k1[(v2 ) & 0x7f];
|
||||
|
||||
#ifdef _UFC_32_
|
||||
*k2++ = (v | 0x00008000);
|
||||
#endif
|
||||
#ifdef _UFC_64_
|
||||
*k2++ = v | 0x0000800000008000l;
|
||||
#endif
|
||||
}
|
||||
|
||||
__data->direction = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Undo an extra E selection and do final permutations
|
||||
*/
|
||||
|
||||
void
|
||||
_ufc_dofinalperm_r (ufc_long *res, struct crypt_data * __restrict __data)
|
||||
{
|
||||
ufc_long v1, v2, x;
|
||||
ufc_long l1,l2,r1,r2;
|
||||
|
||||
l1 = res[0]; l2 = res[1];
|
||||
r1 = res[2]; r2 = res[3];
|
||||
|
||||
x = (l1 ^ l2) & __data->current_saltbits; l1 ^= x; l2 ^= x;
|
||||
x = (r1 ^ r2) & __data->current_saltbits; r1 ^= x; r2 ^= x;
|
||||
|
||||
v1=v2=0; l1 >>= 3; l2 >>= 3; r1 >>= 3; r2 >>= 3;
|
||||
|
||||
v1 |= efp[15][ r2 & 0x3f][0]; v2 |= efp[15][ r2 & 0x3f][1];
|
||||
v1 |= efp[14][(r2 >>= 6) & 0x3f][0]; v2 |= efp[14][ r2 & 0x3f][1];
|
||||
v1 |= efp[13][(r2 >>= 10) & 0x3f][0]; v2 |= efp[13][ r2 & 0x3f][1];
|
||||
v1 |= efp[12][(r2 >>= 6) & 0x3f][0]; v2 |= efp[12][ r2 & 0x3f][1];
|
||||
|
||||
v1 |= efp[11][ r1 & 0x3f][0]; v2 |= efp[11][ r1 & 0x3f][1];
|
||||
v1 |= efp[10][(r1 >>= 6) & 0x3f][0]; v2 |= efp[10][ r1 & 0x3f][1];
|
||||
v1 |= efp[ 9][(r1 >>= 10) & 0x3f][0]; v2 |= efp[ 9][ r1 & 0x3f][1];
|
||||
v1 |= efp[ 8][(r1 >>= 6) & 0x3f][0]; v2 |= efp[ 8][ r1 & 0x3f][1];
|
||||
|
||||
v1 |= efp[ 7][ l2 & 0x3f][0]; v2 |= efp[ 7][ l2 & 0x3f][1];
|
||||
v1 |= efp[ 6][(l2 >>= 6) & 0x3f][0]; v2 |= efp[ 6][ l2 & 0x3f][1];
|
||||
v1 |= efp[ 5][(l2 >>= 10) & 0x3f][0]; v2 |= efp[ 5][ l2 & 0x3f][1];
|
||||
v1 |= efp[ 4][(l2 >>= 6) & 0x3f][0]; v2 |= efp[ 4][ l2 & 0x3f][1];
|
||||
|
||||
v1 |= efp[ 3][ l1 & 0x3f][0]; v2 |= efp[ 3][ l1 & 0x3f][1];
|
||||
v1 |= efp[ 2][(l1 >>= 6) & 0x3f][0]; v2 |= efp[ 2][ l1 & 0x3f][1];
|
||||
v1 |= efp[ 1][(l1 >>= 10) & 0x3f][0]; v2 |= efp[ 1][ l1 & 0x3f][1];
|
||||
v1 |= efp[ 0][(l1 >>= 6) & 0x3f][0]; v2 |= efp[ 0][ l1 & 0x3f][1];
|
||||
|
||||
res[0] = v1; res[1] = v2;
|
||||
}
|
||||
|
||||
/*
|
||||
* crypt only: convert from 64 bit to 11 bit ASCII
|
||||
* prefixing with the salt
|
||||
*/
|
||||
|
||||
void
|
||||
_ufc_output_conversion_r (ufc_long v1, ufc_long v2, const char *salt,
|
||||
struct crypt_data * __restrict __data)
|
||||
{
|
||||
int i, s, shf;
|
||||
|
||||
__data->crypt_3_buf[0] = salt[0];
|
||||
__data->crypt_3_buf[1] = salt[1] ? salt[1] : salt[0];
|
||||
|
||||
for(i = 0; i < 5; i++) {
|
||||
shf = (26 - 6 * i); /* to cope with MSC compiler bug */
|
||||
__data->crypt_3_buf[i + 2] = bin_to_ascii((v1 >> shf) & 0x3f);
|
||||
}
|
||||
|
||||
s = (v2 & 0xf) << 2;
|
||||
v2 = (v2 >> 2) | ((v1 & 0x3) << 30);
|
||||
|
||||
for(i = 5; i < 10; i++) {
|
||||
shf = (56 - 6 * i);
|
||||
__data->crypt_3_buf[i + 2] = bin_to_ascii((v2 >> shf) & 0x3f);
|
||||
}
|
||||
|
||||
__data->crypt_3_buf[12] = bin_to_ascii(s);
|
||||
__data->crypt_3_buf[13] = 0;
|
||||
}
|
||||
|
||||
#if SHLIB_COMPAT (libcrypt, GLIBC_2_0, GLIBC_2_28)
|
||||
|
||||
/*
|
||||
* UNIX encrypt function. Takes a bitvector
|
||||
* represented by one byte per bit and
|
||||
* encrypt/decrypt according to edflag
|
||||
*/
|
||||
|
||||
void
|
||||
__encrypt_r (char *__block, int __edflag,
|
||||
struct crypt_data * __restrict __data)
|
||||
{
|
||||
ufc_long l1, l2, r1, r2, res[4];
|
||||
int i;
|
||||
#ifdef _UFC_32_
|
||||
long32 *kt;
|
||||
kt = (long32*)__data->keysched;
|
||||
#endif
|
||||
#ifdef _UFC_64_
|
||||
long64 *kt;
|
||||
kt = (long64*)__data->keysched;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Undo any salt changes to E expansion
|
||||
*/
|
||||
_ufc_setup_salt_r("..", __data);
|
||||
|
||||
/*
|
||||
* Reverse key table if
|
||||
* changing operation (encrypt/decrypt)
|
||||
*/
|
||||
if((__edflag == 0) != (__data->direction == 0)) {
|
||||
for(i = 0; i < 8; i++) {
|
||||
#ifdef _UFC_32_
|
||||
long32 x;
|
||||
x = kt[2 * (15-i)];
|
||||
kt[2 * (15-i)] = kt[2 * i];
|
||||
kt[2 * i] = x;
|
||||
|
||||
x = kt[2 * (15-i) + 1];
|
||||
kt[2 * (15-i) + 1] = kt[2 * i + 1];
|
||||
kt[2 * i + 1] = x;
|
||||
#endif
|
||||
#ifdef _UFC_64_
|
||||
long64 x;
|
||||
x = kt[15-i];
|
||||
kt[15-i] = kt[i];
|
||||
kt[i] = x;
|
||||
#endif
|
||||
}
|
||||
__data->direction = __edflag;
|
||||
}
|
||||
|
||||
/*
|
||||
* Do initial permutation + E expansion
|
||||
*/
|
||||
i = 0;
|
||||
for(l1 = 0; i < 24; i++) {
|
||||
if(__block[initial_perm[esel[i]-1]-1])
|
||||
l1 |= BITMASK[i];
|
||||
}
|
||||
for(l2 = 0; i < 48; i++) {
|
||||
if(__block[initial_perm[esel[i]-1]-1])
|
||||
l2 |= BITMASK[i-24];
|
||||
}
|
||||
|
||||
i = 0;
|
||||
for(r1 = 0; i < 24; i++) {
|
||||
if(__block[initial_perm[esel[i]-1+32]-1])
|
||||
r1 |= BITMASK[i];
|
||||
}
|
||||
for(r2 = 0; i < 48; i++) {
|
||||
if(__block[initial_perm[esel[i]-1+32]-1])
|
||||
r2 |= BITMASK[i-24];
|
||||
}
|
||||
|
||||
/*
|
||||
* Do DES inner loops + final conversion
|
||||
*/
|
||||
res[0] = l1; res[1] = l2;
|
||||
res[2] = r1; res[3] = r2;
|
||||
_ufc_doit_r((ufc_long)1, __data, &res[0]);
|
||||
|
||||
/*
|
||||
* Do final permutations
|
||||
*/
|
||||
_ufc_dofinalperm_r(res, __data);
|
||||
|
||||
/*
|
||||
* And convert to bit array
|
||||
*/
|
||||
l1 = res[0]; r1 = res[1];
|
||||
for(i = 0; i < 32; i++) {
|
||||
*__block++ = (l1 & longmask[i]) != 0;
|
||||
}
|
||||
for(i = 0; i < 32; i++) {
|
||||
*__block++ = (r1 & longmask[i]) != 0;
|
||||
}
|
||||
}
|
||||
weak_alias (__encrypt_r, encrypt_r)
|
||||
compat_symbol (libcrypt, encrypt_r, encrypt_r, GLIBC_2_0);
|
||||
|
||||
void
|
||||
encrypt (char *__block, int __edflag)
|
||||
{
|
||||
__encrypt_r(__block, __edflag, &_ufc_foobar);
|
||||
}
|
||||
compat_symbol (libcrypt, encrypt, encrypt, GLIBC_2_0);
|
||||
|
||||
|
||||
/*
|
||||
* UNIX setkey function. Take a 64 bit DES
|
||||
* key and setup the machinery.
|
||||
*/
|
||||
|
||||
void
|
||||
__setkey_r (const char *__key, struct crypt_data * __restrict __data)
|
||||
{
|
||||
int i,j;
|
||||
unsigned char c;
|
||||
unsigned char ktab[8];
|
||||
|
||||
_ufc_setup_salt_r("..", __data); /* be sure we're initialized */
|
||||
|
||||
for(i = 0; i < 8; i++) {
|
||||
for(j = 0, c = 0; j < 8; j++)
|
||||
c = c << 1 | *__key++;
|
||||
ktab[i] = c >> 1;
|
||||
}
|
||||
_ufc_mk_keytab_r((char *) ktab, __data);
|
||||
}
|
||||
weak_alias (__setkey_r, setkey_r)
|
||||
compat_symbol (libcrypt, setkey_r, setkey_r, GLIBC_2_0);
|
||||
|
||||
void
|
||||
setkey (const char *__key)
|
||||
{
|
||||
__setkey_r(__key, &_ufc_foobar);
|
||||
}
|
||||
compat_symbol (libcrypt, setkey, setkey, GLIBC_2_0);
|
||||
#endif /* SHLIB_COMPAT (libcrypt, GLIBC_2_0, GLIBC_2_28) */
|
||||
|
||||
void
|
||||
__b64_from_24bit (char **cp, int *buflen,
|
||||
unsigned int b2, unsigned int b1, unsigned int b0,
|
||||
int n)
|
||||
{
|
||||
unsigned int w = (b2 << 16) | (b1 << 8) | b0;
|
||||
while (n-- > 0 && (*buflen) > 0)
|
||||
{
|
||||
*(*cp)++ = b64t[w & 0x3f];
|
||||
--(*buflen);
|
||||
w >>= 6;
|
||||
}
|
||||
}
|
@ -1,331 +0,0 @@
|
||||
/* One way encryption based on MD5 sum.
|
||||
Compatible with the behavior of MD5 crypt introduced in FreeBSD 2.0.
|
||||
Copyright (C) 1996-2023 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
The GNU C 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.
|
||||
|
||||
The GNU C 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 the GNU C Library; if not, see
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/param.h>
|
||||
|
||||
#include "md5.h"
|
||||
#include "crypt-private.h"
|
||||
|
||||
|
||||
#ifdef USE_NSS
|
||||
typedef int PRBool;
|
||||
# include <hasht.h>
|
||||
# include <nsslowhash.h>
|
||||
|
||||
# define md5_init_ctx(ctxp, nss_ctxp) \
|
||||
do \
|
||||
{ \
|
||||
if (((nss_ctxp = NSSLOWHASH_NewContext (nss_ictx, HASH_AlgMD5)) \
|
||||
== NULL)) \
|
||||
{ \
|
||||
if (nss_ctx != NULL) \
|
||||
NSSLOWHASH_Destroy (nss_ctx); \
|
||||
if (nss_alt_ctx != NULL) \
|
||||
NSSLOWHASH_Destroy (nss_alt_ctx); \
|
||||
return NULL; \
|
||||
} \
|
||||
NSSLOWHASH_Begin (nss_ctxp); \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
# define md5_process_bytes(buf, len, ctxp, nss_ctxp) \
|
||||
NSSLOWHASH_Update (nss_ctxp, (const unsigned char *) buf, len)
|
||||
|
||||
# define md5_finish_ctx(ctxp, nss_ctxp, result) \
|
||||
do \
|
||||
{ \
|
||||
unsigned int ret; \
|
||||
NSSLOWHASH_End (nss_ctxp, result, &ret, sizeof (result)); \
|
||||
assert (ret == sizeof (result)); \
|
||||
NSSLOWHASH_Destroy (nss_ctxp); \
|
||||
nss_ctxp = NULL; \
|
||||
} \
|
||||
while (0)
|
||||
#else
|
||||
# define md5_init_ctx(ctxp, nss_ctxp) \
|
||||
__md5_init_ctx (ctxp)
|
||||
|
||||
# define md5_process_bytes(buf, len, ctxp, nss_ctxp) \
|
||||
__md5_process_bytes(buf, len, ctxp)
|
||||
|
||||
# define md5_finish_ctx(ctxp, nss_ctxp, result) \
|
||||
__md5_finish_ctx (ctxp, result)
|
||||
#endif
|
||||
|
||||
|
||||
/* Define our magic string to mark salt for MD5 "encryption"
|
||||
replacement. This is meant to be the same as for other MD5 based
|
||||
encryption implementations. */
|
||||
static const char md5_salt_prefix[] = "$1$";
|
||||
|
||||
|
||||
/* Prototypes for local functions. */
|
||||
extern char *__md5_crypt_r (const char *key, const char *salt,
|
||||
char *buffer, int buflen);
|
||||
extern char *__md5_crypt (const char *key, const char *salt);
|
||||
|
||||
|
||||
/* This entry point is equivalent to the `crypt' function in Unix
|
||||
libcs. */
|
||||
char *
|
||||
__md5_crypt_r (const char *key, const char *salt, char *buffer, int buflen)
|
||||
{
|
||||
unsigned char alt_result[16]
|
||||
__attribute__ ((__aligned__ (__alignof__ (md5_uint32))));
|
||||
size_t salt_len;
|
||||
size_t key_len;
|
||||
size_t cnt;
|
||||
char *cp;
|
||||
char *copied_key = NULL;
|
||||
char *copied_salt = NULL;
|
||||
char *free_key = NULL;
|
||||
size_t alloca_used = 0;
|
||||
|
||||
/* Find beginning of salt string. The prefix should normally always
|
||||
be present. Just in case it is not. */
|
||||
if (strncmp (md5_salt_prefix, salt, sizeof (md5_salt_prefix) - 1) == 0)
|
||||
/* Skip salt prefix. */
|
||||
salt += sizeof (md5_salt_prefix) - 1;
|
||||
|
||||
salt_len = MIN (strcspn (salt, "$"), 8);
|
||||
key_len = strlen (key);
|
||||
|
||||
if (((uintptr_t) key) % __alignof__ (md5_uint32) != 0)
|
||||
{
|
||||
char *tmp;
|
||||
|
||||
if (__libc_use_alloca (alloca_used + key_len + __alignof__ (md5_uint32)))
|
||||
tmp = (char *) alloca (key_len + __alignof__ (md5_uint32));
|
||||
else
|
||||
{
|
||||
free_key = tmp = (char *) malloc (key_len + __alignof__ (md5_uint32));
|
||||
if (tmp == NULL)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
key = copied_key =
|
||||
memcpy (tmp + __alignof__ (md5_uint32)
|
||||
- ((uintptr_t) tmp) % __alignof__ (md5_uint32),
|
||||
key, key_len);
|
||||
assert (((uintptr_t) key) % __alignof__ (md5_uint32) == 0);
|
||||
}
|
||||
|
||||
if (((uintptr_t) salt) % __alignof__ (md5_uint32) != 0)
|
||||
{
|
||||
char *tmp = (char *) alloca (salt_len + __alignof__ (md5_uint32));
|
||||
salt = copied_salt =
|
||||
memcpy (tmp + __alignof__ (md5_uint32)
|
||||
- ((uintptr_t) tmp) % __alignof__ (md5_uint32),
|
||||
salt, salt_len);
|
||||
assert (((uintptr_t) salt) % __alignof__ (md5_uint32) == 0);
|
||||
}
|
||||
|
||||
#ifdef USE_NSS
|
||||
/* Initialize libfreebl3. */
|
||||
NSSLOWInitContext *nss_ictx = NSSLOW_Init ();
|
||||
if (nss_ictx == NULL)
|
||||
{
|
||||
free (free_key);
|
||||
return NULL;
|
||||
}
|
||||
NSSLOWHASHContext *nss_ctx = NULL;
|
||||
NSSLOWHASHContext *nss_alt_ctx = NULL;
|
||||
#else
|
||||
struct md5_ctx ctx;
|
||||
struct md5_ctx alt_ctx;
|
||||
#endif
|
||||
|
||||
/* Prepare for the real work. */
|
||||
md5_init_ctx (&ctx, nss_ctx);
|
||||
|
||||
/* Add the key string. */
|
||||
md5_process_bytes (key, key_len, &ctx, nss_ctx);
|
||||
|
||||
/* Because the SALT argument need not always have the salt prefix we
|
||||
add it separately. */
|
||||
md5_process_bytes (md5_salt_prefix, sizeof (md5_salt_prefix) - 1,
|
||||
&ctx, nss_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). */
|
||||
md5_process_bytes (salt, salt_len, &ctx, nss_ctx);
|
||||
|
||||
|
||||
/* Compute alternate MD5 sum with input KEY, SALT, and KEY. The
|
||||
final result will be added to the first context. */
|
||||
md5_init_ctx (&alt_ctx, nss_alt_ctx);
|
||||
|
||||
/* Add key. */
|
||||
md5_process_bytes (key, key_len, &alt_ctx, nss_alt_ctx);
|
||||
|
||||
/* Add salt. */
|
||||
md5_process_bytes (salt, salt_len, &alt_ctx, nss_alt_ctx);
|
||||
|
||||
/* Add key again. */
|
||||
md5_process_bytes (key, key_len, &alt_ctx, nss_alt_ctx);
|
||||
|
||||
/* Now get result of this (16 bytes) and add it to the other
|
||||
context. */
|
||||
md5_finish_ctx (&alt_ctx, nss_alt_ctx, alt_result);
|
||||
|
||||
/* Add for any character in the key one byte of the alternate sum. */
|
||||
for (cnt = key_len; cnt > 16; cnt -= 16)
|
||||
md5_process_bytes (alt_result, 16, &ctx, nss_ctx);
|
||||
md5_process_bytes (alt_result, cnt, &ctx, nss_ctx);
|
||||
|
||||
/* For the following code we need a NUL byte. */
|
||||
*alt_result = '\0';
|
||||
|
||||
/* The original implementation now does something weird: for every 1
|
||||
bit in the key the first 0 is added to the buffer, for every 0
|
||||
bit the first character of the key. This does not seem to be
|
||||
what was intended but we have to follow this to be compatible. */
|
||||
for (cnt = key_len; cnt > 0; cnt >>= 1)
|
||||
md5_process_bytes ((cnt & 1) != 0
|
||||
? (const void *) alt_result : (const void *) key, 1,
|
||||
&ctx, nss_ctx);
|
||||
|
||||
/* Create intermediate result. */
|
||||
md5_finish_ctx (&ctx, nss_ctx, alt_result);
|
||||
|
||||
/* Now comes another weirdness. In fear of password crackers here
|
||||
comes a quite long loop which just processes the output of the
|
||||
previous round again. We cannot ignore this here. */
|
||||
for (cnt = 0; cnt < 1000; ++cnt)
|
||||
{
|
||||
/* New context. */
|
||||
md5_init_ctx (&ctx, nss_ctx);
|
||||
|
||||
/* Add key or last result. */
|
||||
if ((cnt & 1) != 0)
|
||||
md5_process_bytes (key, key_len, &ctx, nss_ctx);
|
||||
else
|
||||
md5_process_bytes (alt_result, 16, &ctx, nss_ctx);
|
||||
|
||||
/* Add salt for numbers not divisible by 3. */
|
||||
if (cnt % 3 != 0)
|
||||
md5_process_bytes (salt, salt_len, &ctx, nss_ctx);
|
||||
|
||||
/* Add key for numbers not divisible by 7. */
|
||||
if (cnt % 7 != 0)
|
||||
md5_process_bytes (key, key_len, &ctx, nss_ctx);
|
||||
|
||||
/* Add key or last result. */
|
||||
if ((cnt & 1) != 0)
|
||||
md5_process_bytes (alt_result, 16, &ctx, nss_ctx);
|
||||
else
|
||||
md5_process_bytes (key, key_len, &ctx, nss_ctx);
|
||||
|
||||
/* Create intermediate result. */
|
||||
md5_finish_ctx (&ctx, nss_ctx, alt_result);
|
||||
}
|
||||
|
||||
#ifdef USE_NSS
|
||||
/* Free libfreebl3 resources. */
|
||||
NSSLOW_Shutdown (nss_ictx);
|
||||
#endif
|
||||
|
||||
/* Now we can construct the result string. It consists of three
|
||||
parts. */
|
||||
cp = __stpncpy (buffer, md5_salt_prefix, MAX (0, buflen));
|
||||
buflen -= sizeof (md5_salt_prefix) - 1;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
__b64_from_24bit (&cp, &buflen,
|
||||
alt_result[0], alt_result[6], alt_result[12], 4);
|
||||
__b64_from_24bit (&cp, &buflen,
|
||||
alt_result[1], alt_result[7], alt_result[13], 4);
|
||||
__b64_from_24bit (&cp, &buflen,
|
||||
alt_result[2], alt_result[8], alt_result[14], 4);
|
||||
__b64_from_24bit (&cp, &buflen,
|
||||
alt_result[3], alt_result[9], alt_result[15], 4);
|
||||
__b64_from_24bit (&cp, &buflen,
|
||||
alt_result[4], alt_result[10], alt_result[5], 4);
|
||||
__b64_from_24bit (&cp, &buflen,
|
||||
0, 0, alt_result[11], 2);
|
||||
if (buflen <= 0)
|
||||
{
|
||||
__set_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 MD5 implementation as well. */
|
||||
#ifndef USE_NSS
|
||||
__md5_init_ctx (&ctx);
|
||||
__md5_finish_ctx (&ctx, alt_result);
|
||||
explicit_bzero (&ctx, sizeof (ctx));
|
||||
explicit_bzero (&alt_ctx, sizeof (alt_ctx));
|
||||
#endif
|
||||
if (copied_key != NULL)
|
||||
explicit_bzero (copied_key, key_len);
|
||||
if (copied_salt != NULL)
|
||||
explicit_bzero (copied_salt, salt_len);
|
||||
|
||||
free (free_key);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
static char *buffer;
|
||||
|
||||
char *
|
||||
__md5_crypt (const char *key, const char *salt)
|
||||
{
|
||||
/* We don't want to have an arbitrary limit in the size of the
|
||||
password. We can compute the size of the result in advance and
|
||||
so we can prepare the buffer we pass to `md5_crypt_r'. */
|
||||
static int buflen;
|
||||
int needed = 3 + strlen (salt) + 1 + 26 + 1;
|
||||
|
||||
if (buflen < needed)
|
||||
{
|
||||
char *new_buffer = (char *) realloc (buffer, needed);
|
||||
if (new_buffer == NULL)
|
||||
return NULL;
|
||||
|
||||
buffer = new_buffer;
|
||||
buflen = needed;
|
||||
}
|
||||
|
||||
return __md5_crypt_r (key, salt, buffer, buflen);
|
||||
}
|
||||
|
||||
static void
|
||||
__attribute__ ((__destructor__))
|
||||
free_mem (void)
|
||||
{
|
||||
free (buffer);
|
||||
}
|
@ -1,18 +0,0 @@
|
||||
#include <crypt.h>
|
||||
#include <string.h>
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
const char salt[] = "$1$saltstring";
|
||||
char *cp;
|
||||
int result = 0;
|
||||
|
||||
cp = crypt ("Hello world!", salt);
|
||||
|
||||
/* MD5 is disabled in FIPS mode. */
|
||||
if (cp)
|
||||
result |= strcmp ("$1$saltstri$YMyguxXMBpd2TEZ.vS/3q1", cp);
|
||||
|
||||
return result;
|
||||
}
|
@ -1,137 +0,0 @@
|
||||
/* Testcase for https://sourceware.org/bugzilla/show_bug.cgi?id=14090.
|
||||
Copyright (C) 2012-2023 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published
|
||||
by the Free Software Foundation; version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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 General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, see <https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
#include "md5.h"
|
||||
|
||||
/* This test will not work with 32-bit size_t, so let it succeed
|
||||
there. */
|
||||
#if SIZE_MAX <= UINT32_MAX
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
|
||||
# define CONST_2G 0x080000000
|
||||
# define CONST_10G 0x280000000
|
||||
|
||||
/* MD5 sum values of zero-filled blocks of specified sizes. */
|
||||
static const struct test_data_s
|
||||
{
|
||||
const char ref[16];
|
||||
size_t len;
|
||||
} test_data[] =
|
||||
{
|
||||
{ "\xd4\x1d\x8c\xd9\x8f\x00\xb2\x04\xe9\x80\x09\x98\xec\xf8\x42\x7e",
|
||||
0x000000000 },
|
||||
{ "\xa9\x81\x13\x0c\xf2\xb7\xe0\x9f\x46\x86\xdc\x27\x3c\xf7\x18\x7e",
|
||||
0x080000000 },
|
||||
{ "\xc9\xa5\xa6\x87\x8d\x97\xb4\x8c\xc9\x65\xc1\xe4\x18\x59\xf0\x34",
|
||||
0x100000000 },
|
||||
{ "\x58\xcf\x63\x8a\x73\x3f\x91\x90\x07\xb4\x28\x7c\xf5\x39\x6d\x0c",
|
||||
0x180000000 },
|
||||
{ "\xb7\x70\x35\x1f\xad\xae\x5a\x96\xbb\xaf\x97\x02\xed\x97\xd2\x8d",
|
||||
0x200000000 },
|
||||
{ "\x2d\xd2\x6c\x4d\x47\x99\xeb\xd2\x9f\xa3\x1e\x48\xd4\x9e\x8e\x53",
|
||||
0x280000000 },
|
||||
};
|
||||
|
||||
static int
|
||||
report (const char *id, const char *md5, size_t len, const char *ref)
|
||||
{
|
||||
if (memcmp (md5, ref, 16))
|
||||
{
|
||||
printf ("test %s with size %zd failed\n", id, len);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Test md5 in a single md5_process_bytes call. */
|
||||
static int
|
||||
test_single (void *buf, size_t len, const char *ref)
|
||||
{
|
||||
char sum[16];
|
||||
struct md5_ctx ctx;
|
||||
|
||||
__md5_init_ctx (&ctx);
|
||||
__md5_process_bytes (buf, len, &ctx);
|
||||
__md5_finish_ctx (&ctx, sum);
|
||||
|
||||
return report ("single", sum, len, ref);
|
||||
}
|
||||
|
||||
/* Test md5 with two md5_process_bytes calls to trigger a
|
||||
different path in md5_process_block for sizes > 2 GB. */
|
||||
static int
|
||||
test_double (void *buf, size_t len, const char *ref)
|
||||
{
|
||||
char sum[16];
|
||||
struct md5_ctx ctx;
|
||||
|
||||
__md5_init_ctx (&ctx);
|
||||
if (len >= CONST_2G)
|
||||
{
|
||||
__md5_process_bytes (buf, CONST_2G, &ctx);
|
||||
__md5_process_bytes (buf + CONST_2G, len - CONST_2G, &ctx);
|
||||
}
|
||||
else
|
||||
__md5_process_bytes (buf, len, &ctx);
|
||||
|
||||
__md5_finish_ctx (&ctx, sum);
|
||||
|
||||
return report ("double", sum, len, ref);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
void *buf;
|
||||
unsigned int j;
|
||||
int result = 0;
|
||||
|
||||
buf = mmap64 (0, CONST_10G, PROT_READ, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
|
||||
if (buf == MAP_FAILED)
|
||||
{
|
||||
puts ("Could not allocate 10 GB via mmap, skipping test.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (j = 0; j < sizeof (test_data) / sizeof (struct test_data_s); j++)
|
||||
{
|
||||
if (test_single (buf, test_data[j].len, test_data[j].ref))
|
||||
result = 1;
|
||||
if (test_double (buf, test_data[j].len, test_data[j].ref))
|
||||
result = 1;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* This needs on a fast machine 90s. */
|
||||
#define TIMEOUT 480
|
||||
#define TEST_FUNCTION do_test ()
|
||||
#include "../test-skeleton.c"
|
@ -1,53 +0,0 @@
|
||||
#include <string.h>
|
||||
#include "md5.h"
|
||||
|
||||
static const struct
|
||||
{
|
||||
const char *input;
|
||||
const char result[16];
|
||||
} tests[] =
|
||||
{
|
||||
{ "",
|
||||
"\xd4\x1d\x8c\xd9\x8f\x00\xb2\x04\xe9\x80\x09\x98\xec\xf8\x42\x7e" },
|
||||
{ "a",
|
||||
"\x0c\xc1\x75\xb9\xc0\xf1\xb6\xa8\x31\xc3\x99\xe2\x69\x77\x26\x61" },
|
||||
{ "abc",
|
||||
"\x90\x01\x50\x98\x3c\xd2\x4f\xb0\xd6\x96\x3f\x7d\x28\xe1\x7f\x72" },
|
||||
{ "message digest",
|
||||
"\xf9\x6b\x69\x7d\x7c\xb7\x93\x8d\x52\x5a\x2f\x31\xaa\xf1\x61\xd0" },
|
||||
{ "abcdefghijklmnopqrstuvwxyz",
|
||||
"\xc3\xfc\xd3\xd7\x61\x92\xe4\x00\x7d\xfb\x49\x6c\xca\x67\xe1\x3b" },
|
||||
{ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
|
||||
"\xd1\x74\xab\x98\xd2\x77\xd9\xf5\xa5\x61\x1c\x2c\x9f\x41\x9d\x9f" },
|
||||
{ "123456789012345678901234567890123456789012345678901234567890"
|
||||
"12345678901234567890",
|
||||
"\x57\xed\xf4\xa2\x2b\xe3\xc9\x55\xac\x49\xda\x2e\x21\x07\xb6\x7a" }
|
||||
};
|
||||
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
struct md5_ctx ctx;
|
||||
char sum[16];
|
||||
int result = 0;
|
||||
int cnt;
|
||||
|
||||
for (cnt = 0; cnt < (int) (sizeof (tests) / sizeof (tests[0])); ++cnt)
|
||||
{
|
||||
int i;
|
||||
|
||||
__md5_init_ctx (&ctx);
|
||||
__md5_process_bytes (tests[cnt].input, strlen (tests[cnt].input), &ctx);
|
||||
__md5_finish_ctx (&ctx, sum);
|
||||
result |= memcmp (tests[cnt].result, sum, 16);
|
||||
|
||||
__md5_init_ctx (&ctx);
|
||||
for (i = 0; tests[cnt].input[i] != '\0'; ++i)
|
||||
__md5_process_bytes (&tests[cnt].input[i], 1, &ctx);
|
||||
__md5_finish_ctx (&ctx, sum);
|
||||
result |= memcmp (tests[cnt].result, sum, 16);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
@ -1,98 +0,0 @@
|
||||
#include <stdint.h>
|
||||
|
||||
/* Process LEN bytes of BUFFER, accumulating context into CTX.
|
||||
It is assumed that LEN % 64 == 0. */
|
||||
void
|
||||
__sha256_process_block (const void *buffer, size_t len, struct sha256_ctx *ctx)
|
||||
{
|
||||
const uint32_t *words = buffer;
|
||||
size_t nwords = len / sizeof (uint32_t);
|
||||
uint32_t a = ctx->H[0];
|
||||
uint32_t b = ctx->H[1];
|
||||
uint32_t c = ctx->H[2];
|
||||
uint32_t d = ctx->H[3];
|
||||
uint32_t e = ctx->H[4];
|
||||
uint32_t f = ctx->H[5];
|
||||
uint32_t g = ctx->H[6];
|
||||
uint32_t h = ctx->H[7];
|
||||
|
||||
/* First increment the byte count. FIPS 180-2 specifies the possible
|
||||
length of the file up to 2^64 bits. Here we only compute the
|
||||
number of bytes. */
|
||||
ctx->total64 += len;
|
||||
|
||||
/* Process all bytes in the buffer with 64 bytes in each round of
|
||||
the loop. */
|
||||
while (nwords > 0)
|
||||
{
|
||||
uint32_t W[64];
|
||||
uint32_t a_save = a;
|
||||
uint32_t b_save = b;
|
||||
uint32_t c_save = c;
|
||||
uint32_t d_save = d;
|
||||
uint32_t e_save = e;
|
||||
uint32_t f_save = f;
|
||||
uint32_t g_save = g;
|
||||
uint32_t h_save = h;
|
||||
|
||||
/* Operators defined in FIPS 180-2:4.1.2. */
|
||||
#define Ch(x, y, z) ((x & y) ^ (~x & z))
|
||||
#define Maj(x, y, z) ((x & y) ^ (x & z) ^ (y & z))
|
||||
#define S0(x) (CYCLIC (x, 2) ^ CYCLIC (x, 13) ^ CYCLIC (x, 22))
|
||||
#define S1(x) (CYCLIC (x, 6) ^ CYCLIC (x, 11) ^ CYCLIC (x, 25))
|
||||
#define R0(x) (CYCLIC (x, 7) ^ CYCLIC (x, 18) ^ (x >> 3))
|
||||
#define R1(x) (CYCLIC (x, 17) ^ CYCLIC (x, 19) ^ (x >> 10))
|
||||
|
||||
/* It is unfortunate that C does not provide an operator for
|
||||
cyclic rotation. Hope the C compiler is smart enough. */
|
||||
#define CYCLIC(w, s) ((w >> s) | (w << (32 - s)))
|
||||
|
||||
/* Compute the message schedule according to FIPS 180-2:6.2.2 step 2. */
|
||||
for (unsigned int t = 0; t < 16; ++t)
|
||||
{
|
||||
W[t] = SWAP (*words);
|
||||
++words;
|
||||
}
|
||||
for (unsigned int t = 16; t < 64; ++t)
|
||||
W[t] = R1 (W[t - 2]) + W[t - 7] + R0 (W[t - 15]) + W[t - 16];
|
||||
|
||||
/* The actual computation according to FIPS 180-2:6.2.2 step 3. */
|
||||
for (unsigned int t = 0; t < 64; ++t)
|
||||
{
|
||||
uint32_t T1 = h + S1 (e) + Ch (e, f, g) + K[t] + W[t];
|
||||
uint32_t T2 = S0 (a) + Maj (a, b, c);
|
||||
h = g;
|
||||
g = f;
|
||||
f = e;
|
||||
e = d + T1;
|
||||
d = c;
|
||||
c = b;
|
||||
b = a;
|
||||
a = T1 + T2;
|
||||
}
|
||||
|
||||
/* Add the starting values of the context according to FIPS 180-2:6.2.2
|
||||
step 4. */
|
||||
a += a_save;
|
||||
b += b_save;
|
||||
c += c_save;
|
||||
d += d_save;
|
||||
e += e_save;
|
||||
f += f_save;
|
||||
g += g_save;
|
||||
h += h_save;
|
||||
|
||||
/* Prepare for the next round. */
|
||||
nwords -= 16;
|
||||
}
|
||||
|
||||
/* Put checksum in context given as argument. */
|
||||
ctx->H[0] = a;
|
||||
ctx->H[1] = b;
|
||||
ctx->H[2] = c;
|
||||
ctx->H[3] = d;
|
||||
ctx->H[4] = e;
|
||||
ctx->H[5] = f;
|
||||
ctx->H[6] = g;
|
||||
ctx->H[7] = h;
|
||||
}
|
@ -1,423 +0,0 @@
|
||||
/* One way encryption based on SHA256 sum.
|
||||
Copyright (C) 2007-2023 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
The GNU C 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.
|
||||
|
||||
The GNU C 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 the GNU C Library; if not, see
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/param.h>
|
||||
|
||||
#include "sha256.h"
|
||||
#include "crypt-private.h"
|
||||
|
||||
|
||||
#ifdef USE_NSS
|
||||
typedef int PRBool;
|
||||
# include <hasht.h>
|
||||
# include <nsslowhash.h>
|
||||
|
||||
# define sha256_init_ctx(ctxp, nss_ctxp) \
|
||||
do \
|
||||
{ \
|
||||
if (((nss_ctxp = NSSLOWHASH_NewContext (nss_ictx, HASH_AlgSHA256)) \
|
||||
== NULL)) \
|
||||
{ \
|
||||
if (nss_ctx != NULL) \
|
||||
NSSLOWHASH_Destroy (nss_ctx); \
|
||||
if (nss_alt_ctx != NULL) \
|
||||
NSSLOWHASH_Destroy (nss_alt_ctx); \
|
||||
return NULL; \
|
||||
} \
|
||||
NSSLOWHASH_Begin (nss_ctxp); \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
# define sha256_process_bytes(buf, len, ctxp, nss_ctxp) \
|
||||
NSSLOWHASH_Update (nss_ctxp, (const unsigned char *) buf, len)
|
||||
|
||||
# define sha256_finish_ctx(ctxp, nss_ctxp, result) \
|
||||
do \
|
||||
{ \
|
||||
unsigned int ret; \
|
||||
NSSLOWHASH_End (nss_ctxp, result, &ret, sizeof (result)); \
|
||||
assert (ret == sizeof (result)); \
|
||||
NSSLOWHASH_Destroy (nss_ctxp); \
|
||||
nss_ctxp = NULL; \
|
||||
} \
|
||||
while (0)
|
||||
#else
|
||||
# define sha256_init_ctx(ctxp, nss_ctxp) \
|
||||
__sha256_init_ctx (ctxp)
|
||||
|
||||
# define sha256_process_bytes(buf, len, ctxp, nss_ctxp) \
|
||||
__sha256_process_bytes(buf, len, ctxp)
|
||||
|
||||
# define sha256_finish_ctx(ctxp, nss_ctxp, result) \
|
||||
__sha256_finish_ctx (ctxp, result)
|
||||
#endif
|
||||
|
||||
|
||||
/* Define our magic string to mark salt for SHA256 "encryption"
|
||||
replacement. */
|
||||
static const char sha256_salt_prefix[] = "$5$";
|
||||
|
||||
/* Prefix for optional rounds specification. */
|
||||
static const char sha256_rounds_prefix[] = "rounds=";
|
||||
|
||||
/* Maximum salt string length. */
|
||||
#define SALT_LEN_MAX 16
|
||||
/* Default number of rounds if not explicitly specified. */
|
||||
#define ROUNDS_DEFAULT 5000
|
||||
/* Minimum number of rounds. */
|
||||
#define ROUNDS_MIN 1000
|
||||
/* Maximum number of rounds. */
|
||||
#define ROUNDS_MAX 999999999
|
||||
|
||||
|
||||
/* Prototypes for local functions. */
|
||||
extern char *__sha256_crypt_r (const char *key, const char *salt,
|
||||
char *buffer, int buflen);
|
||||
extern char *__sha256_crypt (const char *key, const char *salt);
|
||||
|
||||
|
||||
char *
|
||||
__sha256_crypt_r (const char *key, const char *salt, char *buffer, int buflen)
|
||||
{
|
||||
unsigned char alt_result[32]
|
||||
__attribute__ ((__aligned__ (__alignof__ (uint32_t))));
|
||||
unsigned char temp_result[32]
|
||||
__attribute__ ((__aligned__ (__alignof__ (uint32_t))));
|
||||
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;
|
||||
size_t alloca_used = 0;
|
||||
char *free_key = NULL;
|
||||
char *free_pbytes = NULL;
|
||||
|
||||
/* Find beginning of salt string. The prefix should normally always
|
||||
be present. Just in case it is not. */
|
||||
if (strncmp (sha256_salt_prefix, salt, sizeof (sha256_salt_prefix) - 1) == 0)
|
||||
/* Skip salt prefix. */
|
||||
salt += sizeof (sha256_salt_prefix) - 1;
|
||||
|
||||
if (strncmp (salt, sha256_rounds_prefix, sizeof (sha256_rounds_prefix) - 1)
|
||||
== 0)
|
||||
{
|
||||
const char *num = salt + sizeof (sha256_rounds_prefix) - 1;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
salt_len = MIN (strcspn (salt, "$"), SALT_LEN_MAX);
|
||||
key_len = strlen (key);
|
||||
|
||||
if (((uintptr_t) key) % __alignof__ (uint32_t) != 0)
|
||||
{
|
||||
char *tmp;
|
||||
|
||||
if (__libc_use_alloca (alloca_used + key_len + __alignof__ (uint32_t)))
|
||||
tmp = alloca_account (key_len + __alignof__ (uint32_t), alloca_used);
|
||||
else
|
||||
{
|
||||
free_key = tmp = (char *) malloc (key_len + __alignof__ (uint32_t));
|
||||
if (tmp == NULL)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
key = copied_key =
|
||||
memcpy (tmp + __alignof__ (uint32_t)
|
||||
- ((uintptr_t) tmp) % __alignof__ (uint32_t),
|
||||
key, key_len);
|
||||
assert (((uintptr_t) key) % __alignof__ (uint32_t) == 0);
|
||||
}
|
||||
|
||||
if (((uintptr_t) salt) % __alignof__ (uint32_t) != 0)
|
||||
{
|
||||
char *tmp = (char *) alloca (salt_len + __alignof__ (uint32_t));
|
||||
alloca_used += salt_len + __alignof__ (uint32_t);
|
||||
salt = copied_salt =
|
||||
memcpy (tmp + __alignof__ (uint32_t)
|
||||
- ((uintptr_t) tmp) % __alignof__ (uint32_t),
|
||||
salt, salt_len);
|
||||
assert (((uintptr_t) salt) % __alignof__ (uint32_t) == 0);
|
||||
}
|
||||
|
||||
#ifdef USE_NSS
|
||||
/* Initialize libfreebl3. */
|
||||
NSSLOWInitContext *nss_ictx = NSSLOW_Init ();
|
||||
if (nss_ictx == NULL)
|
||||
{
|
||||
free (free_key);
|
||||
return NULL;
|
||||
}
|
||||
NSSLOWHASHContext *nss_ctx = NULL;
|
||||
NSSLOWHASHContext *nss_alt_ctx = NULL;
|
||||
#else
|
||||
struct sha256_ctx ctx;
|
||||
struct sha256_ctx alt_ctx;
|
||||
#endif
|
||||
|
||||
/* Prepare for the real work. */
|
||||
sha256_init_ctx (&ctx, nss_ctx);
|
||||
|
||||
/* Add the key string. */
|
||||
sha256_process_bytes (key, key_len, &ctx, nss_ctx);
|
||||
|
||||
/* The last part is the salt string. This must be at most 16
|
||||
characters and it ends at the first `$' character. */
|
||||
sha256_process_bytes (salt, salt_len, &ctx, nss_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, nss_alt_ctx);
|
||||
|
||||
/* Add key. */
|
||||
sha256_process_bytes (key, key_len, &alt_ctx, nss_alt_ctx);
|
||||
|
||||
/* Add salt. */
|
||||
sha256_process_bytes (salt, salt_len, &alt_ctx, nss_alt_ctx);
|
||||
|
||||
/* Add key again. */
|
||||
sha256_process_bytes (key, key_len, &alt_ctx, nss_alt_ctx);
|
||||
|
||||
/* Now get result of this (32 bytes) and add it to the other
|
||||
context. */
|
||||
sha256_finish_ctx (&alt_ctx, nss_alt_ctx, alt_result);
|
||||
|
||||
/* 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, nss_ctx);
|
||||
sha256_process_bytes (alt_result, cnt, &ctx, nss_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)
|
||||
if ((cnt & 1) != 0)
|
||||
sha256_process_bytes (alt_result, 32, &ctx, nss_ctx);
|
||||
else
|
||||
sha256_process_bytes (key, key_len, &ctx, nss_ctx);
|
||||
|
||||
/* Create intermediate result. */
|
||||
sha256_finish_ctx (&ctx, nss_ctx, alt_result);
|
||||
|
||||
/* Start computation of P byte sequence. */
|
||||
sha256_init_ctx (&alt_ctx, nss_alt_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, nss_alt_ctx);
|
||||
|
||||
/* Finish the digest. */
|
||||
sha256_finish_ctx (&alt_ctx, nss_alt_ctx, temp_result);
|
||||
|
||||
/* Create byte sequence P. */
|
||||
if (__libc_use_alloca (alloca_used + key_len))
|
||||
cp = p_bytes = (char *) alloca (key_len);
|
||||
else
|
||||
{
|
||||
free_pbytes = cp = p_bytes = (char *)malloc (key_len);
|
||||
if (free_pbytes == NULL)
|
||||
{
|
||||
free (free_key);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
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 (&alt_ctx, nss_alt_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, nss_alt_ctx);
|
||||
|
||||
/* Finish the digest. */
|
||||
sha256_finish_ctx (&alt_ctx, nss_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, nss_ctx);
|
||||
|
||||
/* Add key or last result. */
|
||||
if ((cnt & 1) != 0)
|
||||
sha256_process_bytes (p_bytes, key_len, &ctx, nss_ctx);
|
||||
else
|
||||
sha256_process_bytes (alt_result, 32, &ctx, nss_ctx);
|
||||
|
||||
/* Add salt for numbers not divisible by 3. */
|
||||
if (cnt % 3 != 0)
|
||||
sha256_process_bytes (s_bytes, salt_len, &ctx, nss_ctx);
|
||||
|
||||
/* Add key for numbers not divisible by 7. */
|
||||
if (cnt % 7 != 0)
|
||||
sha256_process_bytes (p_bytes, key_len, &ctx, nss_ctx);
|
||||
|
||||
/* Add key or last result. */
|
||||
if ((cnt & 1) != 0)
|
||||
sha256_process_bytes (alt_result, 32, &ctx, nss_ctx);
|
||||
else
|
||||
sha256_process_bytes (p_bytes, key_len, &ctx, nss_ctx);
|
||||
|
||||
/* Create intermediate result. */
|
||||
sha256_finish_ctx (&ctx, nss_ctx, alt_result);
|
||||
}
|
||||
|
||||
#ifdef USE_NSS
|
||||
/* Free libfreebl3 resources. */
|
||||
NSSLOW_Shutdown (nss_ictx);
|
||||
#endif
|
||||
|
||||
/* 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, MAX (0, buflen), "%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;
|
||||
}
|
||||
|
||||
__b64_from_24bit (&cp, &buflen,
|
||||
alt_result[0], alt_result[10], alt_result[20], 4);
|
||||
__b64_from_24bit (&cp, &buflen,
|
||||
alt_result[21], alt_result[1], alt_result[11], 4);
|
||||
__b64_from_24bit (&cp, &buflen,
|
||||
alt_result[12], alt_result[22], alt_result[2], 4);
|
||||
__b64_from_24bit (&cp, &buflen,
|
||||
alt_result[3], alt_result[13], alt_result[23], 4);
|
||||
__b64_from_24bit (&cp, &buflen,
|
||||
alt_result[24], alt_result[4], alt_result[14], 4);
|
||||
__b64_from_24bit (&cp, &buflen,
|
||||
alt_result[15], alt_result[25], alt_result[5], 4);
|
||||
__b64_from_24bit (&cp, &buflen,
|
||||
alt_result[6], alt_result[16], alt_result[26], 4);
|
||||
__b64_from_24bit (&cp, &buflen,
|
||||
alt_result[27], alt_result[7], alt_result[17], 4);
|
||||
__b64_from_24bit (&cp, &buflen,
|
||||
alt_result[18], alt_result[28], alt_result[8], 4);
|
||||
__b64_from_24bit (&cp, &buflen,
|
||||
alt_result[9], alt_result[19], alt_result[29], 4);
|
||||
__b64_from_24bit (&cp, &buflen,
|
||||
0, alt_result[31], alt_result[30], 3);
|
||||
if (buflen <= 0)
|
||||
{
|
||||
__set_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. */
|
||||
#ifndef USE_NSS
|
||||
__sha256_init_ctx (&ctx);
|
||||
__sha256_finish_ctx (&ctx, alt_result);
|
||||
explicit_bzero (&ctx, sizeof (ctx));
|
||||
explicit_bzero (&alt_ctx, sizeof (alt_ctx));
|
||||
#endif
|
||||
explicit_bzero (temp_result, sizeof (temp_result));
|
||||
explicit_bzero (p_bytes, key_len);
|
||||
explicit_bzero (s_bytes, salt_len);
|
||||
if (copied_key != NULL)
|
||||
explicit_bzero (copied_key, key_len);
|
||||
if (copied_salt != NULL)
|
||||
explicit_bzero (copied_salt, salt_len);
|
||||
|
||||
free (free_key);
|
||||
free (free_pbytes);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
static char *buffer;
|
||||
|
||||
/* This entry point is equivalent to the `crypt' function in Unix
|
||||
libcs. */
|
||||
char *
|
||||
__sha256_crypt (const char *key, const char *salt)
|
||||
{
|
||||
/* We don't want to have an arbitrary limit in the size of the
|
||||
password. We can compute an upper bound for the size of the
|
||||
result in advance and so we can prepare the buffer we pass to
|
||||
`sha256_crypt_r'. */
|
||||
static int buflen;
|
||||
int needed = (sizeof (sha256_salt_prefix) - 1
|
||||
+ sizeof (sha256_rounds_prefix) + 9 + 1
|
||||
+ strlen (salt) + 1 + 43 + 1);
|
||||
|
||||
if (buflen < needed)
|
||||
{
|
||||
char *new_buffer = (char *) realloc (buffer, needed);
|
||||
if (new_buffer == NULL)
|
||||
return NULL;
|
||||
|
||||
buffer = new_buffer;
|
||||
buflen = needed;
|
||||
}
|
||||
|
||||
return __sha256_crypt_r (key, salt, buffer, buflen);
|
||||
}
|
||||
|
||||
static void
|
||||
__attribute__ ((__destructor__))
|
||||
free_mem (void)
|
||||
{
|
||||
free (buffer);
|
||||
}
|
193
crypt/sha256.c
193
crypt/sha256.c
@ -1,193 +0,0 @@
|
||||
/* Functions to compute SHA256 message digest of files or memory blocks.
|
||||
according to the definition of SHA256 in FIPS 180-2.
|
||||
Copyright (C) 2007-2023 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
The GNU C 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.
|
||||
|
||||
The GNU C 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 the GNU C Library; if not, see
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <endian.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "sha256.h"
|
||||
|
||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
# ifdef _LIBC
|
||||
# include <byteswap.h>
|
||||
# define SWAP(n) bswap_32 (n)
|
||||
# define SWAP64(n) bswap_64 (n)
|
||||
# else
|
||||
# define SWAP(n) \
|
||||
(((n) << 24) | (((n) & 0xff00) << 8) | (((n) >> 8) & 0xff00) | ((n) >> 24))
|
||||
# define SWAP64(n) \
|
||||
(((n) << 56) \
|
||||
| (((n) & 0xff00) << 40) \
|
||||
| (((n) & 0xff0000) << 24) \
|
||||
| (((n) & 0xff000000) << 8) \
|
||||
| (((n) >> 8) & 0xff000000) \
|
||||
| (((n) >> 24) & 0xff0000) \
|
||||
| (((n) >> 40) & 0xff00) \
|
||||
| ((n) >> 56))
|
||||
# endif
|
||||
#else
|
||||
# define SWAP(n) (n)
|
||||
# define SWAP64(n) (n)
|
||||
#endif
|
||||
|
||||
|
||||
/* This array contains the bytes used to pad the buffer to the next
|
||||
64-byte boundary. (FIPS 180-2:5.1.1) */
|
||||
static const unsigned char fillbuf[64] = { 0x80, 0 /* , 0, 0, ... */ };
|
||||
|
||||
|
||||
/* Constants for SHA256 from FIPS 180-2:4.2.2. */
|
||||
static const uint32_t K[64] =
|
||||
{
|
||||
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
|
||||
0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
|
||||
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
|
||||
0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
|
||||
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
|
||||
0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
|
||||
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
|
||||
0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
|
||||
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
|
||||
0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
|
||||
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
|
||||
0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
|
||||
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
|
||||
0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
|
||||
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
|
||||
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
|
||||
};
|
||||
|
||||
void __sha256_process_block (const void *, size_t, struct sha256_ctx *);
|
||||
|
||||
/* Initialize structure containing state of computation.
|
||||
(FIPS 180-2:5.3.2) */
|
||||
void
|
||||
__sha256_init_ctx (struct sha256_ctx *ctx)
|
||||
{
|
||||
ctx->H[0] = 0x6a09e667;
|
||||
ctx->H[1] = 0xbb67ae85;
|
||||
ctx->H[2] = 0x3c6ef372;
|
||||
ctx->H[3] = 0xa54ff53a;
|
||||
ctx->H[4] = 0x510e527f;
|
||||
ctx->H[5] = 0x9b05688c;
|
||||
ctx->H[6] = 0x1f83d9ab;
|
||||
ctx->H[7] = 0x5be0cd19;
|
||||
|
||||
ctx->total64 = 0;
|
||||
ctx->buflen = 0;
|
||||
}
|
||||
|
||||
|
||||
/* Process the remaining bytes in the internal buffer and the usual
|
||||
prolog according to the standard and write the result to RESBUF.
|
||||
|
||||
IMPORTANT: On some systems it is required that RESBUF is correctly
|
||||
aligned for a 32 bits value. */
|
||||
void *
|
||||
__sha256_finish_ctx (struct sha256_ctx *ctx, void *resbuf)
|
||||
{
|
||||
/* Take yet unprocessed bytes into account. */
|
||||
uint32_t bytes = ctx->buflen;
|
||||
size_t pad;
|
||||
|
||||
/* Now count remaining bytes. */
|
||||
ctx->total64 += bytes;
|
||||
|
||||
pad = bytes >= 56 ? 64 + 56 - bytes : 56 - bytes;
|
||||
memcpy (&ctx->buffer[bytes], fillbuf, pad);
|
||||
|
||||
/* Put the 64-bit file length in *bits* at the end of the buffer. */
|
||||
ctx->buffer32[(bytes + pad + 4) / 4] = SWAP (ctx->total[TOTAL64_low] << 3);
|
||||
ctx->buffer32[(bytes + pad) / 4] = SWAP ((ctx->total[TOTAL64_high] << 3)
|
||||
| (ctx->total[TOTAL64_low] >> 29));
|
||||
|
||||
/* Process last bytes. */
|
||||
__sha256_process_block (ctx->buffer, bytes + pad + 8, ctx);
|
||||
|
||||
/* Put result from CTX in first 32 bytes following RESBUF. */
|
||||
for (unsigned int i = 0; i < 8; ++i)
|
||||
((uint32_t *) resbuf)[i] = SWAP (ctx->H[i]);
|
||||
|
||||
return resbuf;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
__sha256_process_bytes (const void *buffer, size_t len, struct sha256_ctx *ctx)
|
||||
{
|
||||
/* When we already have some bits in our internal buffer concatenate
|
||||
both inputs first. */
|
||||
if (ctx->buflen != 0)
|
||||
{
|
||||
size_t left_over = ctx->buflen;
|
||||
size_t add = 128 - left_over > len ? len : 128 - left_over;
|
||||
|
||||
memcpy (&ctx->buffer[left_over], buffer, add);
|
||||
ctx->buflen += add;
|
||||
|
||||
if (ctx->buflen > 64)
|
||||
{
|
||||
__sha256_process_block (ctx->buffer, ctx->buflen & ~63, ctx);
|
||||
|
||||
ctx->buflen &= 63;
|
||||
/* The regions in the following copy operation cannot overlap. */
|
||||
memcpy (ctx->buffer, &ctx->buffer[(left_over + add) & ~63],
|
||||
ctx->buflen);
|
||||
}
|
||||
|
||||
buffer = (const char *) buffer + add;
|
||||
len -= add;
|
||||
}
|
||||
|
||||
/* Process available complete blocks. */
|
||||
if (len >= 64)
|
||||
{
|
||||
while (len > 64)
|
||||
{
|
||||
__sha256_process_block (memcpy (ctx->buffer, buffer, 64), 64, ctx);
|
||||
buffer = (const char *) buffer + 64;
|
||||
len -= 64;
|
||||
}
|
||||
}
|
||||
|
||||
/* Move remaining bytes into internal buffer. */
|
||||
if (len > 0)
|
||||
{
|
||||
size_t left_over = ctx->buflen;
|
||||
|
||||
memcpy (&ctx->buffer[left_over], buffer, len);
|
||||
left_over += len;
|
||||
if (left_over >= 64)
|
||||
{
|
||||
__sha256_process_block (ctx->buffer, 64, ctx);
|
||||
left_over -= 64;
|
||||
memcpy (ctx->buffer, &ctx->buffer[64], left_over);
|
||||
}
|
||||
ctx->buflen = left_over;
|
||||
}
|
||||
}
|
||||
|
||||
#include <sha256-block.c>
|
@ -1,69 +0,0 @@
|
||||
/* Declaration of functions and data types used for SHA256 sum computing
|
||||
library functions.
|
||||
Copyright (C) 2007-2023 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
The GNU C 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.
|
||||
|
||||
The GNU C 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 the GNU C Library; if not, see
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#ifndef _SHA256_H
|
||||
#define _SHA256_H 1
|
||||
|
||||
#include <limits.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <endian.h>
|
||||
|
||||
|
||||
/* Structure to save state of computation between the single steps. */
|
||||
struct sha256_ctx
|
||||
{
|
||||
uint32_t H[8];
|
||||
|
||||
union
|
||||
{
|
||||
uint64_t total64;
|
||||
#define TOTAL64_low (1 - (BYTE_ORDER == LITTLE_ENDIAN))
|
||||
#define TOTAL64_high (BYTE_ORDER == LITTLE_ENDIAN)
|
||||
uint32_t total[2];
|
||||
};
|
||||
uint32_t buflen;
|
||||
union
|
||||
{
|
||||
char buffer[128];
|
||||
uint32_t buffer32[32];
|
||||
uint64_t buffer64[16];
|
||||
};
|
||||
};
|
||||
|
||||
/* Initialize structure containing state of computation.
|
||||
(FIPS 180-2: 5.3.2) */
|
||||
extern void __sha256_init_ctx (struct sha256_ctx *ctx) __THROW;
|
||||
|
||||
/* Starting with the result of former calls of this function (or the
|
||||
initialization function update the context for the next LEN bytes
|
||||
starting at BUFFER.
|
||||
It is NOT required that LEN is a multiple of 64. */
|
||||
extern void __sha256_process_bytes (const void *buffer, size_t len,
|
||||
struct sha256_ctx *ctx) __THROW;
|
||||
|
||||
/* Process the remaining bytes in the buffer and put result from CTX
|
||||
in first 32 bytes following RESBUF.
|
||||
|
||||
IMPORTANT: On some systems it is required that RESBUF is correctly
|
||||
aligned for a 32 bits value. */
|
||||
extern void *__sha256_finish_ctx (struct sha256_ctx *ctx, void *resbuf)
|
||||
__THROW;
|
||||
|
||||
#endif /* sha256.h */
|
@ -1,61 +0,0 @@
|
||||
#include <crypt.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
static const struct
|
||||
{
|
||||
const char *salt;
|
||||
const char *input;
|
||||
const char *expected;
|
||||
} tests[] =
|
||||
{
|
||||
{ "$5$saltstring", "Hello world!",
|
||||
"$5$saltstring$5B8vYYiY.CVt1RlTTf8KbXBH3hsxY/GNooZaBBGWEc5" },
|
||||
{ "$5$rounds=10000$saltstringsaltstring", "Hello world!",
|
||||
"$5$rounds=10000$saltstringsaltst$3xv.VbSHBb41AL9AvLeujZkZRBAwqFMz2."
|
||||
"opqey6IcA" },
|
||||
{ "$5$rounds=5000$toolongsaltstring", "This is just a test",
|
||||
"$5$rounds=5000$toolongsaltstrin$Un/5jzAHMgOGZ5.mWJpuVolil07guHPvOW8"
|
||||
"mGRcvxa5" },
|
||||
{ "$5$rounds=1400$anotherlongsaltstring",
|
||||
"a very much longer text to encrypt. This one even stretches over more"
|
||||
"than one line.",
|
||||
"$5$rounds=1400$anotherlongsalts$Rx.j8H.h8HjEDGomFU8bDkXm3XIUnzyxf12"
|
||||
"oP84Bnq1" },
|
||||
{ "$5$rounds=77777$short",
|
||||
"we have a short salt string but not a short password",
|
||||
"$5$rounds=77777$short$JiO1O3ZpDAxGJeaDIuqCoEFysAe1mZNJRs3pw0KQRd/" },
|
||||
{ "$5$rounds=123456$asaltof16chars..", "a short string",
|
||||
"$5$rounds=123456$asaltof16chars..$gP3VQ/6X7UUEW3HkBn2w1/Ptq2jxPyzV/"
|
||||
"cZKmF/wJvD" },
|
||||
{ "$5$rounds=10$roundstoolow", "the minimum number is still observed",
|
||||
"$5$rounds=1000$roundstoolow$yfvwcWrQ8l/K0DAWyuPMDNHpIVlTQebY9l/gL97"
|
||||
"2bIC" },
|
||||
};
|
||||
#define ntests (sizeof (tests) / sizeof (tests[0]))
|
||||
|
||||
|
||||
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
int result = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ntests; ++i)
|
||||
{
|
||||
char *cp = crypt (tests[i].input, tests[i].salt);
|
||||
|
||||
if (strcmp (cp, tests[i].expected) != 0)
|
||||
{
|
||||
printf ("test %d: expected \"%s\", got \"%s\"\n",
|
||||
i, tests[i].expected, cp);
|
||||
result = 1;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#define TEST_FUNCTION do_test ()
|
||||
#include "../test-skeleton.c"
|
@ -1,102 +0,0 @@
|
||||
#include <string.h>
|
||||
#include "sha256.h"
|
||||
|
||||
static const struct
|
||||
{
|
||||
const char *input;
|
||||
const char result[32];
|
||||
} tests[] =
|
||||
{
|
||||
/* Test vectors from FIPS 180-2: appendix B.1. */
|
||||
{ "abc",
|
||||
"\xba\x78\x16\xbf\x8f\x01\xcf\xea\x41\x41\x40\xde\x5d\xae\x22\x23"
|
||||
"\xb0\x03\x61\xa3\x96\x17\x7a\x9c\xb4\x10\xff\x61\xf2\x00\x15\xad" },
|
||||
/* Test vectors from FIPS 180-2: appendix B.2. */
|
||||
{ "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
|
||||
"\x24\x8d\x6a\x61\xd2\x06\x38\xb8\xe5\xc0\x26\x93\x0c\x3e\x60\x39"
|
||||
"\xa3\x3c\xe4\x59\x64\xff\x21\x67\xf6\xec\xed\xd4\x19\xdb\x06\xc1" },
|
||||
/* Test vectors from the NESSIE project. */
|
||||
{ "",
|
||||
"\xe3\xb0\xc4\x42\x98\xfc\x1c\x14\x9a\xfb\xf4\xc8\x99\x6f\xb9\x24"
|
||||
"\x27\xae\x41\xe4\x64\x9b\x93\x4c\xa4\x95\x99\x1b\x78\x52\xb8\x55" },
|
||||
{ "a",
|
||||
"\xca\x97\x81\x12\xca\x1b\xbd\xca\xfa\xc2\x31\xb3\x9a\x23\xdc\x4d"
|
||||
"\xa7\x86\xef\xf8\x14\x7c\x4e\x72\xb9\x80\x77\x85\xaf\xee\x48\xbb" },
|
||||
{ "message digest",
|
||||
"\xf7\x84\x6f\x55\xcf\x23\xe1\x4e\xeb\xea\xb5\xb4\xe1\x55\x0c\xad"
|
||||
"\x5b\x50\x9e\x33\x48\xfb\xc4\xef\xa3\xa1\x41\x3d\x39\x3c\xb6\x50" },
|
||||
{ "abcdefghijklmnopqrstuvwxyz",
|
||||
"\x71\xc4\x80\xdf\x93\xd6\xae\x2f\x1e\xfa\xd1\x44\x7c\x66\xc9\x52"
|
||||
"\x5e\x31\x62\x18\xcf\x51\xfc\x8d\x9e\xd8\x32\xf2\xda\xf1\x8b\x73" },
|
||||
{ "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
|
||||
"\x24\x8d\x6a\x61\xd2\x06\x38\xb8\xe5\xc0\x26\x93\x0c\x3e\x60\x39"
|
||||
"\xa3\x3c\xe4\x59\x64\xff\x21\x67\xf6\xec\xed\xd4\x19\xdb\x06\xc1" },
|
||||
{ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
|
||||
"\xdb\x4b\xfc\xbd\x4d\xa0\xcd\x85\xa6\x0c\x3c\x37\xd3\xfb\xd8\x80"
|
||||
"\x5c\x77\xf1\x5f\xc6\xb1\xfd\xfe\x61\x4e\xe0\xa7\xc8\xfd\xb4\xc0" },
|
||||
{ "123456789012345678901234567890123456789012345678901234567890"
|
||||
"12345678901234567890",
|
||||
"\xf3\x71\xbc\x4a\x31\x1f\x2b\x00\x9e\xef\x95\x2d\xd8\x3c\xa8\x0e"
|
||||
"\x2b\x60\x02\x6c\x8e\x93\x55\x92\xd0\xf9\xc3\x08\x45\x3c\x81\x3e" }
|
||||
};
|
||||
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
struct sha256_ctx ctx;
|
||||
char sum[32];
|
||||
int result = 0;
|
||||
int cnt;
|
||||
|
||||
for (cnt = 0; cnt < (int) (sizeof (tests) / sizeof (tests[0])); ++cnt)
|
||||
{
|
||||
__sha256_init_ctx (&ctx);
|
||||
__sha256_process_bytes (tests[cnt].input, strlen (tests[cnt].input),
|
||||
&ctx);
|
||||
__sha256_finish_ctx (&ctx, sum);
|
||||
if (memcmp (tests[cnt].result, sum, 32) != 0)
|
||||
{
|
||||
printf ("test %d run %d failed\n", cnt, 1);
|
||||
result = 1;
|
||||
}
|
||||
|
||||
__sha256_init_ctx (&ctx);
|
||||
for (int i = 0; tests[cnt].input[i] != '\0'; ++i)
|
||||
__sha256_process_bytes (&tests[cnt].input[i], 1, &ctx);
|
||||
__sha256_finish_ctx (&ctx, sum);
|
||||
if (memcmp (tests[cnt].result, sum, 32) != 0)
|
||||
{
|
||||
printf ("test %d run %d failed\n", cnt, 2);
|
||||
result = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Test vector from FIPS 180-2: appendix B.3. */
|
||||
char buf[1000];
|
||||
memset (buf, 'a', sizeof (buf));
|
||||
__sha256_init_ctx (&ctx);
|
||||
for (int i = 0; i < 1000; ++i)
|
||||
__sha256_process_bytes (buf, sizeof (buf), &ctx);
|
||||
__sha256_finish_ctx (&ctx, sum);
|
||||
static const char expected[32] =
|
||||
"\xcd\xc7\x6e\x5c\x99\x14\xfb\x92\x81\xa1\xc7\xe2\x84\xd7\x3e\x67"
|
||||
"\xf1\x80\x9a\x48\xa4\x97\x20\x0e\x04\x6d\x39\xcc\xc7\x11\x2c\xd0";
|
||||
if (memcmp (expected, sum, 32) != 0)
|
||||
{
|
||||
printf ("test %d failed\n", cnt++);
|
||||
result = 1;
|
||||
}
|
||||
|
||||
__sha256_init_ctx (&ctx);
|
||||
for (int i = 0; i < 100000; ++i)
|
||||
__sha256_process_bytes (buf, 10, &ctx);
|
||||
__sha256_finish_ctx (&ctx, sum);
|
||||
if (memcmp (expected, sum, 32) != 0)
|
||||
{
|
||||
printf ("test %d failed\n", cnt++);
|
||||
result = 1;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
@ -1,105 +0,0 @@
|
||||
#include <stdint.h>
|
||||
|
||||
/* Process LEN bytes of BUFFER, accumulating context into CTX.
|
||||
It is assumed that LEN % 128 == 0. */
|
||||
void
|
||||
__sha512_process_block (const void *buffer, size_t len, struct sha512_ctx *ctx)
|
||||
{
|
||||
const uint64_t *words = buffer;
|
||||
size_t nwords = len / sizeof (uint64_t);
|
||||
uint64_t a = ctx->H[0];
|
||||
uint64_t b = ctx->H[1];
|
||||
uint64_t c = ctx->H[2];
|
||||
uint64_t d = ctx->H[3];
|
||||
uint64_t e = ctx->H[4];
|
||||
uint64_t f = ctx->H[5];
|
||||
uint64_t g = ctx->H[6];
|
||||
uint64_t h = ctx->H[7];
|
||||
|
||||
/* First increment the byte count. FIPS 180-2 specifies the possible
|
||||
length of the file up to 2^128 bits. Here we only compute the
|
||||
number of bytes. Do a double word increment. */
|
||||
#ifdef USE_TOTAL128
|
||||
ctx->total128 += len;
|
||||
#else
|
||||
uint64_t lolen = len;
|
||||
ctx->total[TOTAL128_low] += lolen;
|
||||
ctx->total[TOTAL128_high] += ((len >> 31 >> 31 >> 2)
|
||||
+ (ctx->total[TOTAL128_low] < lolen));
|
||||
#endif
|
||||
|
||||
/* Process all bytes in the buffer with 128 bytes in each round of
|
||||
the loop. */
|
||||
while (nwords > 0)
|
||||
{
|
||||
uint64_t W[80];
|
||||
uint64_t a_save = a;
|
||||
uint64_t b_save = b;
|
||||
uint64_t c_save = c;
|
||||
uint64_t d_save = d;
|
||||
uint64_t e_save = e;
|
||||
uint64_t f_save = f;
|
||||
uint64_t g_save = g;
|
||||
uint64_t h_save = h;
|
||||
|
||||
/* Operators defined in FIPS 180-2:4.1.2. */
|
||||
#define Ch(x, y, z) ((x & y) ^ (~x & z))
|
||||
#define Maj(x, y, z) ((x & y) ^ (x & z) ^ (y & z))
|
||||
#define S0(x) (CYCLIC (x, 28) ^ CYCLIC (x, 34) ^ CYCLIC (x, 39))
|
||||
#define S1(x) (CYCLIC (x, 14) ^ CYCLIC (x, 18) ^ CYCLIC (x, 41))
|
||||
#define R0(x) (CYCLIC (x, 1) ^ CYCLIC (x, 8) ^ (x >> 7))
|
||||
#define R1(x) (CYCLIC (x, 19) ^ CYCLIC (x, 61) ^ (x >> 6))
|
||||
|
||||
/* It is unfortunate that C does not provide an operator for
|
||||
cyclic rotation. Hope the C compiler is smart enough. */
|
||||
#define CYCLIC(w, s) ((w >> s) | (w << (64 - s)))
|
||||
|
||||
/* Compute the message schedule according to FIPS 180-2:6.3.2 step 2. */
|
||||
for (unsigned int t = 0; t < 16; ++t)
|
||||
{
|
||||
W[t] = SWAP (*words);
|
||||
++words;
|
||||
}
|
||||
for (unsigned int t = 16; t < 80; ++t)
|
||||
W[t] = R1 (W[t - 2]) + W[t - 7] + R0 (W[t - 15]) + W[t - 16];
|
||||
|
||||
/* The actual computation according to FIPS 180-2:6.3.2 step 3. */
|
||||
for (unsigned int t = 0; t < 80; ++t)
|
||||
{
|
||||
uint64_t T1 = h + S1 (e) + Ch (e, f, g) + K[t] + W[t];
|
||||
uint64_t T2 = S0 (a) + Maj (a, b, c);
|
||||
h = g;
|
||||
g = f;
|
||||
f = e;
|
||||
e = d + T1;
|
||||
d = c;
|
||||
c = b;
|
||||
b = a;
|
||||
a = T1 + T2;
|
||||
}
|
||||
|
||||
/* Add the starting values of the context according to FIPS 180-2:6.3.2
|
||||
step 4. */
|
||||
a += a_save;
|
||||
b += b_save;
|
||||
c += c_save;
|
||||
d += d_save;
|
||||
e += e_save;
|
||||
f += f_save;
|
||||
g += g_save;
|
||||
h += h_save;
|
||||
|
||||
/* Prepare for the next round. */
|
||||
nwords -= 16;
|
||||
}
|
||||
|
||||
/* Put checksum in context given as argument. */
|
||||
ctx->H[0] = a;
|
||||
ctx->H[1] = b;
|
||||
ctx->H[2] = c;
|
||||
ctx->H[3] = d;
|
||||
ctx->H[4] = e;
|
||||
ctx->H[5] = f;
|
||||
ctx->H[6] = g;
|
||||
ctx->H[7] = h;
|
||||
}
|
@ -1,445 +0,0 @@
|
||||
/* One way encryption based on SHA512 sum.
|
||||
Copyright (C) 2007-2023 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
The GNU C 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.
|
||||
|
||||
The GNU C 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 the GNU C Library; if not, see
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/param.h>
|
||||
|
||||
#include "sha512.h"
|
||||
#include "crypt-private.h"
|
||||
|
||||
|
||||
#ifdef USE_NSS
|
||||
typedef int PRBool;
|
||||
# include <hasht.h>
|
||||
# include <nsslowhash.h>
|
||||
|
||||
# define sha512_init_ctx(ctxp, nss_ctxp) \
|
||||
do \
|
||||
{ \
|
||||
if (((nss_ctxp = NSSLOWHASH_NewContext (nss_ictx, HASH_AlgSHA512)) \
|
||||
== NULL)) \
|
||||
{ \
|
||||
if (nss_ctx != NULL) \
|
||||
NSSLOWHASH_Destroy (nss_ctx); \
|
||||
if (nss_alt_ctx != NULL) \
|
||||
NSSLOWHASH_Destroy (nss_alt_ctx); \
|
||||
return NULL; \
|
||||
} \
|
||||
NSSLOWHASH_Begin (nss_ctxp); \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
# define sha512_process_bytes(buf, len, ctxp, nss_ctxp) \
|
||||
NSSLOWHASH_Update (nss_ctxp, (const unsigned char *) buf, len)
|
||||
|
||||
# define sha512_finish_ctx(ctxp, nss_ctxp, result) \
|
||||
do \
|
||||
{ \
|
||||
unsigned int ret; \
|
||||
NSSLOWHASH_End (nss_ctxp, result, &ret, sizeof (result)); \
|
||||
assert (ret == sizeof (result)); \
|
||||
NSSLOWHASH_Destroy (nss_ctxp); \
|
||||
nss_ctxp = NULL; \
|
||||
} \
|
||||
while (0)
|
||||
#else
|
||||
# define sha512_init_ctx(ctxp, nss_ctxp) \
|
||||
__sha512_init_ctx (ctxp)
|
||||
|
||||
# define sha512_process_bytes(buf, len, ctxp, nss_ctxp) \
|
||||
__sha512_process_bytes(buf, len, ctxp)
|
||||
|
||||
# define sha512_finish_ctx(ctxp, nss_ctxp, result) \
|
||||
__sha512_finish_ctx (ctxp, result)
|
||||
#endif
|
||||
|
||||
|
||||
/* Define our magic string to mark salt for SHA512 "encryption"
|
||||
replacement. */
|
||||
static const char sha512_salt_prefix[] = "$6$";
|
||||
|
||||
/* Prefix for optional rounds specification. */
|
||||
static const char sha512_rounds_prefix[] = "rounds=";
|
||||
|
||||
/* Maximum salt string length. */
|
||||
#define SALT_LEN_MAX 16
|
||||
/* Default number of rounds if not explicitly specified. */
|
||||
#define ROUNDS_DEFAULT 5000
|
||||
/* Minimum number of rounds. */
|
||||
#define ROUNDS_MIN 1000
|
||||
/* Maximum number of rounds. */
|
||||
#define ROUNDS_MAX 999999999
|
||||
|
||||
|
||||
/* Prototypes for local functions. */
|
||||
extern char *__sha512_crypt_r (const char *key, const char *salt,
|
||||
char *buffer, int buflen);
|
||||
extern char *__sha512_crypt (const char *key, const char *salt);
|
||||
|
||||
|
||||
char *
|
||||
__sha512_crypt_r (const char *key, const char *salt, char *buffer, int buflen)
|
||||
{
|
||||
unsigned char alt_result[64]
|
||||
__attribute__ ((__aligned__ (__alignof__ (uint64_t))));
|
||||
unsigned char temp_result[64]
|
||||
__attribute__ ((__aligned__ (__alignof__ (uint64_t))));
|
||||
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;
|
||||
size_t alloca_used = 0;
|
||||
char *free_key = NULL;
|
||||
char *free_pbytes = NULL;
|
||||
|
||||
/* Find beginning of salt string. The prefix should normally always
|
||||
be present. Just in case it is not. */
|
||||
if (strncmp (sha512_salt_prefix, salt, sizeof (sha512_salt_prefix) - 1) == 0)
|
||||
/* Skip salt prefix. */
|
||||
salt += sizeof (sha512_salt_prefix) - 1;
|
||||
|
||||
if (strncmp (salt, sha512_rounds_prefix, sizeof (sha512_rounds_prefix) - 1)
|
||||
== 0)
|
||||
{
|
||||
const char *num = salt + sizeof (sha512_rounds_prefix) - 1;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
salt_len = MIN (strcspn (salt, "$"), SALT_LEN_MAX);
|
||||
key_len = strlen (key);
|
||||
|
||||
if (((uintptr_t) key) % __alignof__ (uint64_t) != 0)
|
||||
{
|
||||
char *tmp;
|
||||
|
||||
if (__libc_use_alloca (alloca_used + key_len + __alignof__ (uint64_t)))
|
||||
tmp = alloca_account (key_len + __alignof__ (uint64_t), alloca_used);
|
||||
else
|
||||
{
|
||||
free_key = tmp = (char *) malloc (key_len + __alignof__ (uint64_t));
|
||||
if (tmp == NULL)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
key = copied_key =
|
||||
memcpy (tmp + __alignof__ (uint64_t)
|
||||
- ((uintptr_t) tmp) % __alignof__ (uint64_t),
|
||||
key, key_len);
|
||||
assert (((uintptr_t) key) % __alignof__ (uint64_t) == 0);
|
||||
}
|
||||
|
||||
if (((uintptr_t) salt) % __alignof__ (uint64_t) != 0)
|
||||
{
|
||||
char *tmp = (char *) alloca (salt_len + __alignof__ (uint64_t));
|
||||
salt = copied_salt =
|
||||
memcpy (tmp + __alignof__ (uint64_t)
|
||||
- ((uintptr_t) tmp) % __alignof__ (uint64_t),
|
||||
salt, salt_len);
|
||||
assert (((uintptr_t) salt) % __alignof__ (uint64_t) == 0);
|
||||
}
|
||||
|
||||
#ifdef USE_NSS
|
||||
/* Initialize libfreebl3. */
|
||||
NSSLOWInitContext *nss_ictx = NSSLOW_Init ();
|
||||
if (nss_ictx == NULL)
|
||||
{
|
||||
free (free_key);
|
||||
return NULL;
|
||||
}
|
||||
NSSLOWHASHContext *nss_ctx = NULL;
|
||||
NSSLOWHASHContext *nss_alt_ctx = NULL;
|
||||
#else
|
||||
struct sha512_ctx ctx;
|
||||
struct sha512_ctx alt_ctx;
|
||||
#endif
|
||||
|
||||
/* Prepare for the real work. */
|
||||
sha512_init_ctx (&ctx, nss_ctx);
|
||||
|
||||
/* Add the key string. */
|
||||
sha512_process_bytes (key, key_len, &ctx, nss_ctx);
|
||||
|
||||
/* The last part is the salt string. This must be at most 16
|
||||
characters and it ends at the first `$' character. */
|
||||
sha512_process_bytes (salt, salt_len, &ctx, nss_ctx);
|
||||
|
||||
|
||||
/* Compute alternate SHA512 sum with input KEY, SALT, and KEY. The
|
||||
final result will be added to the first context. */
|
||||
sha512_init_ctx (&alt_ctx, nss_alt_ctx);
|
||||
|
||||
/* Add key. */
|
||||
sha512_process_bytes (key, key_len, &alt_ctx, nss_alt_ctx);
|
||||
|
||||
/* Add salt. */
|
||||
sha512_process_bytes (salt, salt_len, &alt_ctx, nss_alt_ctx);
|
||||
|
||||
/* Add key again. */
|
||||
sha512_process_bytes (key, key_len, &alt_ctx, nss_alt_ctx);
|
||||
|
||||
/* Now get result of this (64 bytes) and add it to the other
|
||||
context. */
|
||||
sha512_finish_ctx (&alt_ctx, nss_alt_ctx, alt_result);
|
||||
|
||||
/* 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, nss_ctx);
|
||||
sha512_process_bytes (alt_result, cnt, &ctx, nss_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)
|
||||
if ((cnt & 1) != 0)
|
||||
sha512_process_bytes (alt_result, 64, &ctx, nss_ctx);
|
||||
else
|
||||
sha512_process_bytes (key, key_len, &ctx, nss_ctx);
|
||||
|
||||
/* Create intermediate result. */
|
||||
sha512_finish_ctx (&ctx, nss_ctx, alt_result);
|
||||
|
||||
/* Start computation of P byte sequence. */
|
||||
sha512_init_ctx (&alt_ctx, nss_alt_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, nss_alt_ctx);
|
||||
|
||||
/* Finish the digest. */
|
||||
sha512_finish_ctx (&alt_ctx, nss_alt_ctx, temp_result);
|
||||
|
||||
/* Create byte sequence P. */
|
||||
if (__libc_use_alloca (alloca_used + key_len))
|
||||
cp = p_bytes = (char *) alloca (key_len);
|
||||
else
|
||||
{
|
||||
free_pbytes = cp = p_bytes = (char *)malloc (key_len);
|
||||
if (free_pbytes == NULL)
|
||||
{
|
||||
free (free_key);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
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 (&alt_ctx, nss_alt_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, nss_alt_ctx);
|
||||
|
||||
/* Finish the digest. */
|
||||
sha512_finish_ctx (&alt_ctx, nss_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, nss_ctx);
|
||||
|
||||
/* Add key or last result. */
|
||||
if ((cnt & 1) != 0)
|
||||
sha512_process_bytes (p_bytes, key_len, &ctx, nss_ctx);
|
||||
else
|
||||
sha512_process_bytes (alt_result, 64, &ctx, nss_ctx);
|
||||
|
||||
/* Add salt for numbers not divisible by 3. */
|
||||
if (cnt % 3 != 0)
|
||||
sha512_process_bytes (s_bytes, salt_len, &ctx, nss_ctx);
|
||||
|
||||
/* Add key for numbers not divisible by 7. */
|
||||
if (cnt % 7 != 0)
|
||||
sha512_process_bytes (p_bytes, key_len, &ctx, nss_ctx);
|
||||
|
||||
/* Add key or last result. */
|
||||
if ((cnt & 1) != 0)
|
||||
sha512_process_bytes (alt_result, 64, &ctx, nss_ctx);
|
||||
else
|
||||
sha512_process_bytes (p_bytes, key_len, &ctx, nss_ctx);
|
||||
|
||||
/* Create intermediate result. */
|
||||
sha512_finish_ctx (&ctx, nss_ctx, alt_result);
|
||||
}
|
||||
|
||||
#ifdef USE_NSS
|
||||
/* Free libfreebl3 resources. */
|
||||
NSSLOW_Shutdown (nss_ictx);
|
||||
#endif
|
||||
|
||||
/* 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, MAX (0, buflen), "%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;
|
||||
}
|
||||
|
||||
__b64_from_24bit (&cp, &buflen,
|
||||
alt_result[0], alt_result[21], alt_result[42], 4);
|
||||
__b64_from_24bit (&cp, &buflen,
|
||||
alt_result[22], alt_result[43], alt_result[1], 4);
|
||||
__b64_from_24bit (&cp, &buflen,
|
||||
alt_result[44], alt_result[2], alt_result[23], 4);
|
||||
__b64_from_24bit (&cp, &buflen,
|
||||
alt_result[3], alt_result[24], alt_result[45], 4);
|
||||
__b64_from_24bit (&cp, &buflen,
|
||||
alt_result[25], alt_result[46], alt_result[4], 4);
|
||||
__b64_from_24bit (&cp, &buflen,
|
||||
alt_result[47], alt_result[5], alt_result[26], 4);
|
||||
__b64_from_24bit (&cp, &buflen,
|
||||
alt_result[6], alt_result[27], alt_result[48], 4);
|
||||
__b64_from_24bit (&cp, &buflen,
|
||||
alt_result[28], alt_result[49], alt_result[7], 4);
|
||||
__b64_from_24bit (&cp, &buflen,
|
||||
alt_result[50], alt_result[8], alt_result[29], 4);
|
||||
__b64_from_24bit (&cp, &buflen,
|
||||
alt_result[9], alt_result[30], alt_result[51], 4);
|
||||
__b64_from_24bit (&cp, &buflen,
|
||||
alt_result[31], alt_result[52], alt_result[10], 4);
|
||||
__b64_from_24bit (&cp, &buflen,
|
||||
alt_result[53], alt_result[11], alt_result[32], 4);
|
||||
__b64_from_24bit (&cp, &buflen,
|
||||
alt_result[12], alt_result[33], alt_result[54], 4);
|
||||
__b64_from_24bit (&cp, &buflen,
|
||||
alt_result[34], alt_result[55], alt_result[13], 4);
|
||||
__b64_from_24bit (&cp, &buflen,
|
||||
alt_result[56], alt_result[14], alt_result[35], 4);
|
||||
__b64_from_24bit (&cp, &buflen,
|
||||
alt_result[15], alt_result[36], alt_result[57], 4);
|
||||
__b64_from_24bit (&cp, &buflen,
|
||||
alt_result[37], alt_result[58], alt_result[16], 4);
|
||||
__b64_from_24bit (&cp, &buflen,
|
||||
alt_result[59], alt_result[17], alt_result[38], 4);
|
||||
__b64_from_24bit (&cp, &buflen,
|
||||
alt_result[18], alt_result[39], alt_result[60], 4);
|
||||
__b64_from_24bit (&cp, &buflen,
|
||||
alt_result[40], alt_result[61], alt_result[19], 4);
|
||||
__b64_from_24bit (&cp, &buflen,
|
||||
alt_result[62], alt_result[20], alt_result[41], 4);
|
||||
__b64_from_24bit (&cp, &buflen,
|
||||
0, 0, alt_result[63], 2);
|
||||
|
||||
if (buflen <= 0)
|
||||
{
|
||||
__set_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. */
|
||||
#ifndef USE_NSS
|
||||
__sha512_init_ctx (&ctx);
|
||||
__sha512_finish_ctx (&ctx, alt_result);
|
||||
explicit_bzero (&ctx, sizeof (ctx));
|
||||
explicit_bzero (&alt_ctx, sizeof (alt_ctx));
|
||||
#endif
|
||||
explicit_bzero (temp_result, sizeof (temp_result));
|
||||
explicit_bzero (p_bytes, key_len);
|
||||
explicit_bzero (s_bytes, salt_len);
|
||||
if (copied_key != NULL)
|
||||
explicit_bzero (copied_key, key_len);
|
||||
if (copied_salt != NULL)
|
||||
explicit_bzero (copied_salt, salt_len);
|
||||
|
||||
free (free_key);
|
||||
free (free_pbytes);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
static char *buffer;
|
||||
|
||||
/* This entry point is equivalent to the `crypt' function in Unix
|
||||
libcs. */
|
||||
char *
|
||||
__sha512_crypt (const char *key, const char *salt)
|
||||
{
|
||||
/* We don't want to have an arbitrary limit in the size of the
|
||||
password. We can compute an upper bound for the size of the
|
||||
result in advance and so we can prepare the buffer we pass to
|
||||
`sha512_crypt_r'. */
|
||||
static int buflen;
|
||||
int needed = (sizeof (sha512_salt_prefix) - 1
|
||||
+ sizeof (sha512_rounds_prefix) + 9 + 1
|
||||
+ strlen (salt) + 1 + 86 + 1);
|
||||
|
||||
if (buflen < needed)
|
||||
{
|
||||
char *new_buffer = (char *) realloc (buffer, needed);
|
||||
if (new_buffer == NULL)
|
||||
return NULL;
|
||||
|
||||
buffer = new_buffer;
|
||||
buflen = needed;
|
||||
}
|
||||
|
||||
return __sha512_crypt_r (key, salt, buffer, buflen);
|
||||
}
|
||||
|
||||
static void
|
||||
__attribute__ ((__destructor__))
|
||||
free_mem (void)
|
||||
{
|
||||
free (buffer);
|
||||
}
|
221
crypt/sha512.c
221
crypt/sha512.c
@ -1,221 +0,0 @@
|
||||
/* Functions to compute SHA512 message digest of files or memory blocks.
|
||||
according to the definition of SHA512 in FIPS 180-2.
|
||||
Copyright (C) 2007-2023 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
The GNU C 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.
|
||||
|
||||
The GNU C 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 the GNU C Library; if not, see
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <endian.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "sha512.h"
|
||||
|
||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
# ifdef _LIBC
|
||||
# include <byteswap.h>
|
||||
# define SWAP(n) bswap_64 (n)
|
||||
# else
|
||||
# define SWAP(n) \
|
||||
(((n) << 56) \
|
||||
| (((n) & 0xff00) << 40) \
|
||||
| (((n) & 0xff0000) << 24) \
|
||||
| (((n) & 0xff000000) << 8) \
|
||||
| (((n) >> 8) & 0xff000000) \
|
||||
| (((n) >> 24) & 0xff0000) \
|
||||
| (((n) >> 40) & 0xff00) \
|
||||
| ((n) >> 56))
|
||||
# endif
|
||||
#else
|
||||
# define SWAP(n) (n)
|
||||
#endif
|
||||
|
||||
|
||||
/* This array contains the bytes used to pad the buffer to the next
|
||||
64-byte boundary. (FIPS 180-2:5.1.2) */
|
||||
static const unsigned char fillbuf[128] = { 0x80, 0 /* , 0, 0, ... */ };
|
||||
|
||||
|
||||
/* Constants for SHA512 from FIPS 180-2:4.2.3. */
|
||||
static const uint64_t K[80] =
|
||||
{
|
||||
UINT64_C (0x428a2f98d728ae22), UINT64_C (0x7137449123ef65cd),
|
||||
UINT64_C (0xb5c0fbcfec4d3b2f), UINT64_C (0xe9b5dba58189dbbc),
|
||||
UINT64_C (0x3956c25bf348b538), UINT64_C (0x59f111f1b605d019),
|
||||
UINT64_C (0x923f82a4af194f9b), UINT64_C (0xab1c5ed5da6d8118),
|
||||
UINT64_C (0xd807aa98a3030242), UINT64_C (0x12835b0145706fbe),
|
||||
UINT64_C (0x243185be4ee4b28c), UINT64_C (0x550c7dc3d5ffb4e2),
|
||||
UINT64_C (0x72be5d74f27b896f), UINT64_C (0x80deb1fe3b1696b1),
|
||||
UINT64_C (0x9bdc06a725c71235), UINT64_C (0xc19bf174cf692694),
|
||||
UINT64_C (0xe49b69c19ef14ad2), UINT64_C (0xefbe4786384f25e3),
|
||||
UINT64_C (0x0fc19dc68b8cd5b5), UINT64_C (0x240ca1cc77ac9c65),
|
||||
UINT64_C (0x2de92c6f592b0275), UINT64_C (0x4a7484aa6ea6e483),
|
||||
UINT64_C (0x5cb0a9dcbd41fbd4), UINT64_C (0x76f988da831153b5),
|
||||
UINT64_C (0x983e5152ee66dfab), UINT64_C (0xa831c66d2db43210),
|
||||
UINT64_C (0xb00327c898fb213f), UINT64_C (0xbf597fc7beef0ee4),
|
||||
UINT64_C (0xc6e00bf33da88fc2), UINT64_C (0xd5a79147930aa725),
|
||||
UINT64_C (0x06ca6351e003826f), UINT64_C (0x142929670a0e6e70),
|
||||
UINT64_C (0x27b70a8546d22ffc), UINT64_C (0x2e1b21385c26c926),
|
||||
UINT64_C (0x4d2c6dfc5ac42aed), UINT64_C (0x53380d139d95b3df),
|
||||
UINT64_C (0x650a73548baf63de), UINT64_C (0x766a0abb3c77b2a8),
|
||||
UINT64_C (0x81c2c92e47edaee6), UINT64_C (0x92722c851482353b),
|
||||
UINT64_C (0xa2bfe8a14cf10364), UINT64_C (0xa81a664bbc423001),
|
||||
UINT64_C (0xc24b8b70d0f89791), UINT64_C (0xc76c51a30654be30),
|
||||
UINT64_C (0xd192e819d6ef5218), UINT64_C (0xd69906245565a910),
|
||||
UINT64_C (0xf40e35855771202a), UINT64_C (0x106aa07032bbd1b8),
|
||||
UINT64_C (0x19a4c116b8d2d0c8), UINT64_C (0x1e376c085141ab53),
|
||||
UINT64_C (0x2748774cdf8eeb99), UINT64_C (0x34b0bcb5e19b48a8),
|
||||
UINT64_C (0x391c0cb3c5c95a63), UINT64_C (0x4ed8aa4ae3418acb),
|
||||
UINT64_C (0x5b9cca4f7763e373), UINT64_C (0x682e6ff3d6b2b8a3),
|
||||
UINT64_C (0x748f82ee5defb2fc), UINT64_C (0x78a5636f43172f60),
|
||||
UINT64_C (0x84c87814a1f0ab72), UINT64_C (0x8cc702081a6439ec),
|
||||
UINT64_C (0x90befffa23631e28), UINT64_C (0xa4506cebde82bde9),
|
||||
UINT64_C (0xbef9a3f7b2c67915), UINT64_C (0xc67178f2e372532b),
|
||||
UINT64_C (0xca273eceea26619c), UINT64_C (0xd186b8c721c0c207),
|
||||
UINT64_C (0xeada7dd6cde0eb1e), UINT64_C (0xf57d4f7fee6ed178),
|
||||
UINT64_C (0x06f067aa72176fba), UINT64_C (0x0a637dc5a2c898a6),
|
||||
UINT64_C (0x113f9804bef90dae), UINT64_C (0x1b710b35131c471b),
|
||||
UINT64_C (0x28db77f523047d84), UINT64_C (0x32caab7b40c72493),
|
||||
UINT64_C (0x3c9ebe0a15c9bebc), UINT64_C (0x431d67c49c100d4c),
|
||||
UINT64_C (0x4cc5d4becb3e42b6), UINT64_C (0x597f299cfc657e2a),
|
||||
UINT64_C (0x5fcb6fab3ad6faec), UINT64_C (0x6c44198c4a475817)
|
||||
};
|
||||
|
||||
void __sha512_process_block (const void *buffer, size_t len,
|
||||
struct sha512_ctx *ctx);
|
||||
|
||||
/* Initialize structure containing state of computation.
|
||||
(FIPS 180-2:5.3.3) */
|
||||
void
|
||||
__sha512_init_ctx (struct sha512_ctx *ctx)
|
||||
{
|
||||
ctx->H[0] = UINT64_C (0x6a09e667f3bcc908);
|
||||
ctx->H[1] = UINT64_C (0xbb67ae8584caa73b);
|
||||
ctx->H[2] = UINT64_C (0x3c6ef372fe94f82b);
|
||||
ctx->H[3] = UINT64_C (0xa54ff53a5f1d36f1);
|
||||
ctx->H[4] = UINT64_C (0x510e527fade682d1);
|
||||
ctx->H[5] = UINT64_C (0x9b05688c2b3e6c1f);
|
||||
ctx->H[6] = UINT64_C (0x1f83d9abfb41bd6b);
|
||||
ctx->H[7] = UINT64_C (0x5be0cd19137e2179);
|
||||
|
||||
ctx->total[0] = ctx->total[1] = 0;
|
||||
ctx->buflen = 0;
|
||||
}
|
||||
|
||||
|
||||
/* Process the remaining bytes in the internal buffer and the usual
|
||||
prolog according to the standard and write the result to RESBUF.
|
||||
|
||||
IMPORTANT: On some systems it is required that RESBUF is correctly
|
||||
aligned for a 32 bits value. */
|
||||
void *
|
||||
__sha512_finish_ctx (struct sha512_ctx *ctx, void *resbuf)
|
||||
{
|
||||
/* Take yet unprocessed bytes into account. */
|
||||
uint64_t bytes = ctx->buflen;
|
||||
size_t pad;
|
||||
|
||||
/* Now count remaining bytes. */
|
||||
#ifdef USE_TOTAL128
|
||||
ctx->total128 += bytes;
|
||||
#else
|
||||
ctx->total[TOTAL128_low] += bytes;
|
||||
if (ctx->total[TOTAL128_low] < bytes)
|
||||
++ctx->total[TOTAL128_high];
|
||||
#endif
|
||||
|
||||
pad = bytes >= 112 ? 128 + 112 - bytes : 112 - bytes;
|
||||
memcpy (&ctx->buffer[bytes], fillbuf, pad);
|
||||
|
||||
/* Put the 128-bit file length in *bits* at the end of the buffer. */
|
||||
ctx->buffer64[(bytes + pad + 8) / 8] = SWAP (ctx->total[TOTAL128_low] << 3);
|
||||
ctx->buffer64[(bytes + pad) / 8] = SWAP ((ctx->total[TOTAL128_high] << 3)
|
||||
| (ctx->total[TOTAL128_low] >> 61));
|
||||
|
||||
/* Process last bytes. */
|
||||
__sha512_process_block (ctx->buffer, bytes + pad + 16, ctx);
|
||||
|
||||
/* Put result from CTX in first 64 bytes following RESBUF. */
|
||||
for (unsigned int i = 0; i < 8; ++i)
|
||||
((uint64_t *) resbuf)[i] = SWAP (ctx->H[i]);
|
||||
|
||||
return resbuf;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
__sha512_process_bytes (const void *buffer, size_t len, struct sha512_ctx *ctx)
|
||||
{
|
||||
/* When we already have some bits in our internal buffer concatenate
|
||||
both inputs first. */
|
||||
if (ctx->buflen != 0)
|
||||
{
|
||||
size_t left_over = ctx->buflen;
|
||||
size_t add = 256 - left_over > len ? len : 256 - left_over;
|
||||
|
||||
memcpy (&ctx->buffer[left_over], buffer, add);
|
||||
ctx->buflen += add;
|
||||
|
||||
if (ctx->buflen > 128)
|
||||
{
|
||||
__sha512_process_block (ctx->buffer, ctx->buflen & ~127, ctx);
|
||||
|
||||
ctx->buflen &= 127;
|
||||
/* The regions in the following copy operation cannot overlap. */
|
||||
memcpy (ctx->buffer, &ctx->buffer[(left_over + add) & ~127],
|
||||
ctx->buflen);
|
||||
}
|
||||
|
||||
buffer = (const char *) buffer + add;
|
||||
len -= add;
|
||||
}
|
||||
|
||||
/* Process available complete blocks. */
|
||||
if (len >= 128)
|
||||
{
|
||||
while (len > 128)
|
||||
{
|
||||
__sha512_process_block (memcpy (ctx->buffer, buffer, 128), 128,
|
||||
ctx);
|
||||
buffer = (const char *) buffer + 128;
|
||||
len -= 128;
|
||||
}
|
||||
}
|
||||
|
||||
/* Move remaining bytes into internal buffer. */
|
||||
if (len > 0)
|
||||
{
|
||||
size_t left_over = ctx->buflen;
|
||||
|
||||
memcpy (&ctx->buffer[left_over], buffer, len);
|
||||
left_over += len;
|
||||
if (left_over >= 128)
|
||||
{
|
||||
__sha512_process_block (ctx->buffer, 128, ctx);
|
||||
left_over -= 128;
|
||||
memcpy (ctx->buffer, &ctx->buffer[128], left_over);
|
||||
}
|
||||
ctx->buflen = left_over;
|
||||
}
|
||||
}
|
||||
|
||||
#include <sha512-block.c>
|
@ -1,72 +0,0 @@
|
||||
/* Declaration of functions and data types used for SHA512 sum computing
|
||||
library functions.
|
||||
Copyright (C) 2007-2023 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
The GNU C 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.
|
||||
|
||||
The GNU C 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 the GNU C Library; if not, see
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#ifndef _SHA512_H
|
||||
#define _SHA512_H 1
|
||||
|
||||
#include <limits.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <endian.h>
|
||||
#include <bits/wordsize.h>
|
||||
|
||||
|
||||
/* Structure to save state of computation between the single steps. */
|
||||
struct sha512_ctx
|
||||
{
|
||||
uint64_t H[8];
|
||||
|
||||
union
|
||||
{
|
||||
#if defined __GNUC__ && __WORDSIZE == 64
|
||||
# define USE_TOTAL128
|
||||
unsigned int total128 __attribute__ ((__mode__ (TI)));
|
||||
#endif
|
||||
#define TOTAL128_low (1 - (BYTE_ORDER == LITTLE_ENDIAN))
|
||||
#define TOTAL128_high (BYTE_ORDER == LITTLE_ENDIAN)
|
||||
uint64_t total[2];
|
||||
};
|
||||
uint64_t buflen;
|
||||
union
|
||||
{
|
||||
char buffer[256];
|
||||
uint64_t buffer64[32];
|
||||
};
|
||||
};
|
||||
|
||||
/* Initialize structure containing state of computation.
|
||||
(FIPS 180-2: 5.3.3) */
|
||||
extern void __sha512_init_ctx (struct sha512_ctx *ctx) __THROW;
|
||||
|
||||
/* Starting with the result of former calls of this function (or the
|
||||
initialization function update the context for the next LEN bytes
|
||||
starting at BUFFER.
|
||||
It is NOT required that LEN is a multiple of 128. */
|
||||
extern void __sha512_process_bytes (const void *buffer, size_t len,
|
||||
struct sha512_ctx *ctx) __THROW;
|
||||
|
||||
/* Process the remaining bytes in the buffer and put result from CTX
|
||||
in first 64 bytes following RESBUF.
|
||||
|
||||
IMPORTANT: On some systems it is required that RESBUF is correctly
|
||||
aligned for a 64 bits value. */
|
||||
extern void *__sha512_finish_ctx (struct sha512_ctx *ctx, void *resbuf)
|
||||
__THROW;
|
||||
|
||||
#endif /* sha512.h */
|
@ -1,63 +0,0 @@
|
||||
#include <crypt.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
static const struct
|
||||
{
|
||||
const char *salt;
|
||||
const char *input;
|
||||
const char *expected;
|
||||
} tests[] =
|
||||
{
|
||||
{ "$6$saltstring", "Hello world!",
|
||||
"$6$saltstring$svn8UoSVapNtMuq1ukKS4tPQd8iKwSMHWjl/O817G3uBnIFNjnQJu"
|
||||
"esI68u4OTLiBFdcbYEdFCoEOfaS35inz1" },
|
||||
{ "$6$rounds=10000$saltstringsaltstring", "Hello world!",
|
||||
"$6$rounds=10000$saltstringsaltst$OW1/O6BYHV6BcXZu8QVeXbDWra3Oeqh0sb"
|
||||
"HbbMCVNSnCM/UrjmM0Dp8vOuZeHBy/YTBmSK6H9qs/y3RnOaw5v." },
|
||||
{ "$6$rounds=5000$toolongsaltstring", "This is just a test",
|
||||
"$6$rounds=5000$toolongsaltstrin$lQ8jolhgVRVhY4b5pZKaysCLi0QBxGoNeKQ"
|
||||
"zQ3glMhwllF7oGDZxUhx1yxdYcz/e1JSbq3y6JMxxl8audkUEm0" },
|
||||
{ "$6$rounds=1400$anotherlongsaltstring",
|
||||
"a very much longer text to encrypt. This one even stretches over more"
|
||||
"than one line.",
|
||||
"$6$rounds=1400$anotherlongsalts$POfYwTEok97VWcjxIiSOjiykti.o/pQs.wP"
|
||||
"vMxQ6Fm7I6IoYN3CmLs66x9t0oSwbtEW7o7UmJEiDwGqd8p4ur1" },
|
||||
{ "$6$rounds=77777$short",
|
||||
"we have a short salt string but not a short password",
|
||||
"$6$rounds=77777$short$WuQyW2YR.hBNpjjRhpYD/ifIw05xdfeEyQoMxIXbkvr0g"
|
||||
"ge1a1x3yRULJ5CCaUeOxFmtlcGZelFl5CxtgfiAc0" },
|
||||
{ "$6$rounds=123456$asaltof16chars..", "a short string",
|
||||
"$6$rounds=123456$asaltof16chars..$BtCwjqMJGx5hrJhZywWvt0RLE8uZ4oPwc"
|
||||
"elCjmw2kSYu.Ec6ycULevoBK25fs2xXgMNrCzIMVcgEJAstJeonj1" },
|
||||
{ "$6$rounds=10$roundstoolow", "the minimum number is still observed",
|
||||
"$6$rounds=1000$roundstoolow$kUMsbe306n21p9R.FRkW3IGn.S9NPN0x50YhH1x"
|
||||
"hLsPuWGsUSklZt58jaTfF4ZEQpyUNGc0dqbpBYYBaHHrsX." },
|
||||
};
|
||||
#define ntests (sizeof (tests) / sizeof (tests[0]))
|
||||
|
||||
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
int result = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ntests; ++i)
|
||||
{
|
||||
char *cp = crypt (tests[i].input, tests[i].salt);
|
||||
|
||||
if (strcmp (cp, tests[i].expected) != 0)
|
||||
{
|
||||
printf ("test %d: expected \"%s\", got \"%s\"\n",
|
||||
i, tests[i].expected, cp);
|
||||
result = 1;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#define TIMEOUT 32
|
||||
#define TEST_FUNCTION do_test ()
|
||||
#include "../test-skeleton.c"
|
@ -1,113 +0,0 @@
|
||||
#include <string.h>
|
||||
#include "sha512.h"
|
||||
|
||||
static const struct
|
||||
{
|
||||
const char *input;
|
||||
const char result[64];
|
||||
} tests[] =
|
||||
{
|
||||
/* Test vectors from FIPS 180-2: appendix C.1. */
|
||||
{ "abc",
|
||||
"\xdd\xaf\x35\xa1\x93\x61\x7a\xba\xcc\x41\x73\x49\xae\x20\x41\x31"
|
||||
"\x12\xe6\xfa\x4e\x89\xa9\x7e\xa2\x0a\x9e\xee\xe6\x4b\x55\xd3\x9a"
|
||||
"\x21\x92\x99\x2a\x27\x4f\xc1\xa8\x36\xba\x3c\x23\xa3\xfe\xeb\xbd"
|
||||
"\x45\x4d\x44\x23\x64\x3c\xe8\x0e\x2a\x9a\xc9\x4f\xa5\x4c\xa4\x9f" },
|
||||
/* Test vectors from FIPS 180-2: appendix C.2. */
|
||||
{ "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn"
|
||||
"hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu",
|
||||
"\x8e\x95\x9b\x75\xda\xe3\x13\xda\x8c\xf4\xf7\x28\x14\xfc\x14\x3f"
|
||||
"\x8f\x77\x79\xc6\xeb\x9f\x7f\xa1\x72\x99\xae\xad\xb6\x88\x90\x18"
|
||||
"\x50\x1d\x28\x9e\x49\x00\xf7\xe4\x33\x1b\x99\xde\xc4\xb5\x43\x3a"
|
||||
"\xc7\xd3\x29\xee\xb6\xdd\x26\x54\x5e\x96\xe5\x5b\x87\x4b\xe9\x09" },
|
||||
/* Test vectors from the NESSIE project. */
|
||||
{ "",
|
||||
"\xcf\x83\xe1\x35\x7e\xef\xb8\xbd\xf1\x54\x28\x50\xd6\x6d\x80\x07"
|
||||
"\xd6\x20\xe4\x05\x0b\x57\x15\xdc\x83\xf4\xa9\x21\xd3\x6c\xe9\xce"
|
||||
"\x47\xd0\xd1\x3c\x5d\x85\xf2\xb0\xff\x83\x18\xd2\x87\x7e\xec\x2f"
|
||||
"\x63\xb9\x31\xbd\x47\x41\x7a\x81\xa5\x38\x32\x7a\xf9\x27\xda\x3e" },
|
||||
{ "a",
|
||||
"\x1f\x40\xfc\x92\xda\x24\x16\x94\x75\x09\x79\xee\x6c\xf5\x82\xf2"
|
||||
"\xd5\xd7\xd2\x8e\x18\x33\x5d\xe0\x5a\xbc\x54\xd0\x56\x0e\x0f\x53"
|
||||
"\x02\x86\x0c\x65\x2b\xf0\x8d\x56\x02\x52\xaa\x5e\x74\x21\x05\x46"
|
||||
"\xf3\x69\xfb\xbb\xce\x8c\x12\xcf\xc7\x95\x7b\x26\x52\xfe\x9a\x75" },
|
||||
{ "message digest",
|
||||
"\x10\x7d\xbf\x38\x9d\x9e\x9f\x71\xa3\xa9\x5f\x6c\x05\x5b\x92\x51"
|
||||
"\xbc\x52\x68\xc2\xbe\x16\xd6\xc1\x34\x92\xea\x45\xb0\x19\x9f\x33"
|
||||
"\x09\xe1\x64\x55\xab\x1e\x96\x11\x8e\x8a\x90\x5d\x55\x97\xb7\x20"
|
||||
"\x38\xdd\xb3\x72\xa8\x98\x26\x04\x6d\xe6\x66\x87\xbb\x42\x0e\x7c" },
|
||||
{ "abcdefghijklmnopqrstuvwxyz",
|
||||
"\x4d\xbf\xf8\x6c\xc2\xca\x1b\xae\x1e\x16\x46\x8a\x05\xcb\x98\x81"
|
||||
"\xc9\x7f\x17\x53\xbc\xe3\x61\x90\x34\x89\x8f\xaa\x1a\xab\xe4\x29"
|
||||
"\x95\x5a\x1b\xf8\xec\x48\x3d\x74\x21\xfe\x3c\x16\x46\x61\x3a\x59"
|
||||
"\xed\x54\x41\xfb\x0f\x32\x13\x89\xf7\x7f\x48\xa8\x79\xc7\xb1\xf1" },
|
||||
{ "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
|
||||
"\x20\x4a\x8f\xc6\xdd\xa8\x2f\x0a\x0c\xed\x7b\xeb\x8e\x08\xa4\x16"
|
||||
"\x57\xc1\x6e\xf4\x68\xb2\x28\xa8\x27\x9b\xe3\x31\xa7\x03\xc3\x35"
|
||||
"\x96\xfd\x15\xc1\x3b\x1b\x07\xf9\xaa\x1d\x3b\xea\x57\x78\x9c\xa0"
|
||||
"\x31\xad\x85\xc7\xa7\x1d\xd7\x03\x54\xec\x63\x12\x38\xca\x34\x45" },
|
||||
{ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
|
||||
"\x1e\x07\xbe\x23\xc2\x6a\x86\xea\x37\xea\x81\x0c\x8e\xc7\x80\x93"
|
||||
"\x52\x51\x5a\x97\x0e\x92\x53\xc2\x6f\x53\x6c\xfc\x7a\x99\x96\xc4"
|
||||
"\x5c\x83\x70\x58\x3e\x0a\x78\xfa\x4a\x90\x04\x1d\x71\xa4\xce\xab"
|
||||
"\x74\x23\xf1\x9c\x71\xb9\xd5\xa3\xe0\x12\x49\xf0\xbe\xbd\x58\x94" },
|
||||
{ "123456789012345678901234567890123456789012345678901234567890"
|
||||
"12345678901234567890",
|
||||
"\x72\xec\x1e\xf1\x12\x4a\x45\xb0\x47\xe8\xb7\xc7\x5a\x93\x21\x95"
|
||||
"\x13\x5b\xb6\x1d\xe2\x4e\xc0\xd1\x91\x40\x42\x24\x6e\x0a\xec\x3a"
|
||||
"\x23\x54\xe0\x93\xd7\x6f\x30\x48\xb4\x56\x76\x43\x46\x90\x0c\xb1"
|
||||
"\x30\xd2\xa4\xfd\x5d\xd1\x6a\xbb\x5e\x30\xbc\xb8\x50\xde\xe8\x43" }
|
||||
};
|
||||
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
struct sha512_ctx ctx;
|
||||
char sum[64];
|
||||
int result = 0;
|
||||
int cnt;
|
||||
|
||||
for (cnt = 0; cnt < (int) (sizeof (tests) / sizeof (tests[0])); ++cnt)
|
||||
{
|
||||
__sha512_init_ctx (&ctx);
|
||||
__sha512_process_bytes (tests[cnt].input, strlen (tests[cnt].input),
|
||||
&ctx);
|
||||
__sha512_finish_ctx (&ctx, sum);
|
||||
if (memcmp (tests[cnt].result, sum, 64) != 0)
|
||||
{
|
||||
printf ("test %d run %d failed\n", cnt, 1);
|
||||
result = 1;
|
||||
}
|
||||
|
||||
__sha512_init_ctx (&ctx);
|
||||
for (int i = 0; tests[cnt].input[i] != '\0'; ++i)
|
||||
__sha512_process_bytes (&tests[cnt].input[i], 1, &ctx);
|
||||
__sha512_finish_ctx (&ctx, sum);
|
||||
if (memcmp (tests[cnt].result, sum, 64) != 0)
|
||||
{
|
||||
printf ("test %d run %d failed\n", cnt, 2);
|
||||
result = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Test vector from FIPS 180-2: appendix C.3. */
|
||||
char buf[1000];
|
||||
memset (buf, 'a', sizeof (buf));
|
||||
__sha512_init_ctx (&ctx);
|
||||
for (int i = 0; i < 1000; ++i)
|
||||
__sha512_process_bytes (buf, sizeof (buf), &ctx);
|
||||
__sha512_finish_ctx (&ctx, sum);
|
||||
static const char expected[64] =
|
||||
"\xe7\x18\x48\x3d\x0c\xe7\x69\x64\x4e\x2e\x42\xc7\xbc\x15\xb4\x63"
|
||||
"\x8e\x1f\x98\xb1\x3b\x20\x44\x28\x56\x32\xa8\x03\xaf\xa9\x73\xeb"
|
||||
"\xde\x0f\xf2\x44\x87\x7e\xa6\x0a\x4c\xb0\x43\x2c\xe5\x77\xc3\x1b"
|
||||
"\xeb\x00\x9c\x5c\x2c\x49\xaa\x2e\x4e\xad\xb2\x17\xad\x8c\xc0\x9b";
|
||||
if (memcmp (expected, sum, 64) != 0)
|
||||
{
|
||||
printf ("test %d failed\n", cnt);
|
||||
result = 1;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
153
crypt/speeds.c
153
crypt/speeds.c
@ -1,153 +0,0 @@
|
||||
/*
|
||||
* This fcrypt/crypt speed testing program
|
||||
* is derived from one floating around in
|
||||
* the net. It's distributed along with
|
||||
* UFC-crypt but is not covered by any
|
||||
* licence.
|
||||
*
|
||||
* @(#)speeds.c 1.11 20 Aug 1996
|
||||
*/
|
||||
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#ifndef SIGVTALRM
|
||||
/*
|
||||
* patch from chip@chinacat.unicom.com (Chip Rosenthal):
|
||||
* you may enable it if your system does not include
|
||||
* a setitimer() function. You'll have to ensure the
|
||||
* existence an environment variable: HZ giving how many
|
||||
* ticks goes per second.
|
||||
* If not existing in your default environment 50, 60
|
||||
* or even 100 may be the right value. Perhaps you should
|
||||
* then use 'time ./ufc 10000' instead of guessing.
|
||||
*/
|
||||
#define NO_ITIMER
|
||||
#endif
|
||||
|
||||
#ifdef NO_ITIMER
|
||||
#include <sys/types.h>
|
||||
#include <sys/times.h>
|
||||
#else
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
|
||||
static int cnt;
|
||||
#ifdef NO_ITIMER
|
||||
char *hz;
|
||||
struct tms tstart, tfinish;
|
||||
#endif
|
||||
#define ITIME 10 /* Number of seconds to run test. */
|
||||
|
||||
char *crypt(), *fcrypt();
|
||||
|
||||
void
|
||||
Stop (void)
|
||||
{
|
||||
double elapsed;
|
||||
#ifdef NO_ITIMER
|
||||
(void) times(&tfinish);
|
||||
elapsed = ((tfinish.tms_utime + tfinish.tms_stime) -
|
||||
(tstart.tms_utime + tstart.tms_stime)) / atoi(hz);
|
||||
printf("elapsed time = %d sec, CPU time = %f sec\n", ITIME, elapsed);
|
||||
#else
|
||||
elapsed = ITIME;
|
||||
#endif
|
||||
printf ("Did %f %s()s per second.\n", ((float) cnt) / elapsed,
|
||||
#if defined(FCRYPT)
|
||||
"fcrypt"
|
||||
#else
|
||||
"crypt"
|
||||
#endif
|
||||
);
|
||||
exit (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Silly rewrite of 'bzero'. I do so
|
||||
* because some machines don't have
|
||||
* bzero and some don't have memset.
|
||||
*/
|
||||
|
||||
static void clearmem(start, cnt)
|
||||
char *start;
|
||||
int cnt;
|
||||
{ while(cnt--)
|
||||
*start++ = '\0';
|
||||
}
|
||||
|
||||
main (void)
|
||||
{
|
||||
char *s;
|
||||
#ifdef NO_ITIMER
|
||||
extern char *getenv();
|
||||
#else
|
||||
struct itimerval itv;
|
||||
#endif
|
||||
|
||||
#ifdef NO_ITIMER
|
||||
if ((hz = getenv("HZ")) == NULL) {
|
||||
fprintf(stderr, "HZ environment parameter undefined\n");
|
||||
exit(1);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef FCRYPT
|
||||
printf("\n");
|
||||
printf("Warning: this version of the speed program may run slower when\n");
|
||||
printf("benchmarking UFC-crypt than previous versions. This is because it\n");
|
||||
printf("stresses the CPU hardware cache in order to get benchmark figures\n");
|
||||
printf("that corresponds closer to the performance that can be expected in\n");
|
||||
printf("a password cracker.\n\n");
|
||||
#endif
|
||||
|
||||
printf ("Running %s for %d seconds of virtual time ...\n",
|
||||
#ifdef FCRYPT
|
||||
"UFC-crypt",
|
||||
#else
|
||||
"crypt(libc)",
|
||||
#endif
|
||||
ITIME);
|
||||
|
||||
#ifdef FCRYPT
|
||||
init_des ();
|
||||
#endif
|
||||
|
||||
#ifdef NO_ITIMER
|
||||
signal(SIGALRM, Stop);
|
||||
switch (fork()) {
|
||||
case -1:
|
||||
perror("fork failed");
|
||||
exit(1);
|
||||
case 0:
|
||||
sleep(10);
|
||||
kill(getppid(), SIGALRM);
|
||||
exit(0);
|
||||
default:
|
||||
(void) times(&tstart);
|
||||
}
|
||||
#else
|
||||
clearmem ((char*)&itv, (int)sizeof (itv));
|
||||
signal (SIGVTALRM, Stop);
|
||||
itv.it_value.tv_sec = ITIME;
|
||||
itv.it_value.tv_usec = 0;
|
||||
setitimer (ITIMER_VIRTUAL, &itv, NULL);
|
||||
#endif
|
||||
|
||||
|
||||
s = "fredred";
|
||||
for (cnt = 0;; cnt++)
|
||||
{
|
||||
#ifdef FCRYPT
|
||||
s = fcrypt (s, "eek");
|
||||
#else
|
||||
s = crypt (s, "eek");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -1,28 +0,0 @@
|
||||
/* Types for UFC-crypt.
|
||||
Copyright (C) 1998-2023 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
The GNU C 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.
|
||||
|
||||
The GNU C 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 the GNU C Library; if not, see
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef uint_fast32_t ufc_long;
|
||||
typedef uint64_t long64;
|
||||
typedef uint32_t long32;
|
||||
#if UINT_FAST32_MAX == UINT_FAST64_MAX
|
||||
# define _UFC_64_
|
||||
#else
|
||||
# define _UFC_32_
|
||||
#endif
|
54
crypt/ufc.c
54
crypt/ufc.c
@ -1,54 +0,0 @@
|
||||
/*
|
||||
* UFC-crypt: ultra fast crypt(3) implementation
|
||||
*
|
||||
* Copyright (C) 1991-2023 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 the GNU C Library; see the file COPYING.LIB. If not,
|
||||
* see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* @(#)ufc.c 2.7 9/10/96
|
||||
*
|
||||
* Stub main program for debugging
|
||||
* and benchmarking.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
char *crypt();
|
||||
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
{ char *s;
|
||||
unsigned long i,iterations;
|
||||
|
||||
if(argc != 2) {
|
||||
fprintf(stderr, "usage: ufc iterations\n");
|
||||
exit(1);
|
||||
}
|
||||
argv++;
|
||||
iterations = atoi(*argv);
|
||||
printf("ufc: running %d iterations\n", iterations);
|
||||
|
||||
for(i=0; i<iterations; i++)
|
||||
s=crypt("foob","ar");
|
||||
if(strcmp(s, "arlEKn0OzVJn.") == 0)
|
||||
printf("OK\n");
|
||||
else {
|
||||
printf("wrong result: %s!!\n", s);
|
||||
exit(1);
|
||||
}
|
||||
exit(0);
|
||||
}
|
38
elf/Makefile
38
elf/Makefile
@ -1217,23 +1217,6 @@ $(objpfx)tst-_dl_addr_inside_object: $(objpfx)dl-addr-obj.os
|
||||
CFLAGS-tst-_dl_addr_inside_object.c += $(PIE-ccflag)
|
||||
endif
|
||||
|
||||
# We can only test static libcrypt use if libcrypt has been built,
|
||||
# and either NSS crypto is not in use, or static NSS libraries are
|
||||
# available.
|
||||
ifeq ($(build-crypt),no)
|
||||
CFLAGS-tst-linkall-static.c += -DUSE_CRYPT=0
|
||||
else
|
||||
ifeq ($(nss-crypt),no)
|
||||
CFLAGS-tst-linkall-static.c += -DUSE_CRYPT=1
|
||||
else
|
||||
ifeq ($(static-nss-crypt),no)
|
||||
CFLAGS-tst-linkall-static.c += -DUSE_CRYPT=0
|
||||
else
|
||||
CFLAGS-tst-linkall-static.c += -DUSE_CRYPT=1
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
include ../Rules
|
||||
|
||||
ifeq (yes,$(build-shared))
|
||||
@ -1951,9 +1934,6 @@ endif
|
||||
ifeq ($(have-thread-library),yes)
|
||||
localplt-built-dso += $(filter-out %_nonshared.a, $(shared-thread-library))
|
||||
endif
|
||||
ifeq ($(build-crypt),yes)
|
||||
localplt-built-dso += $(addprefix $(common-objpfx), crypt/libcrypt.so)
|
||||
endif
|
||||
ifneq ($(pthread-in-libc),yes)
|
||||
localplt-built-dso += $(addprefix $(common-objpfx), rt/librt.so)
|
||||
endif
|
||||
@ -2438,24 +2418,6 @@ $(objpfx)tst-linkall-static: \
|
||||
$(common-objpfx)rt/librt.a \
|
||||
$(static-thread-library)
|
||||
|
||||
ifeq ($(build-crypt),yes)
|
||||
# If we are using NSS crypto and we have the ability to link statically
|
||||
# then we include libcrypt.a, otherwise we leave out libcrypt.a and
|
||||
# link as much as we can into the tst-linkall-static test. This assumes
|
||||
# that linking with libcrypt.a does everything required to include the
|
||||
# static NSS crypto library.
|
||||
ifeq (yesyes,$(nss-crypt)$(static-nss-crypt))
|
||||
$(objpfx)tst-linkall-static: \
|
||||
$(common-objpfx)crypt/libcrypt.a
|
||||
endif
|
||||
# If we are not using NSS crypto then we always have the ability to link
|
||||
# with libcrypt.a.
|
||||
ifeq (no,$(nss-crypt))
|
||||
$(objpfx)tst-linkall-static: \
|
||||
$(common-objpfx)crypt/libcrypt.a
|
||||
endif
|
||||
endif
|
||||
|
||||
LDFLAGS-nextmod3.so = -Wl,--version-script=nextmod3.map
|
||||
|
||||
# The application depends on the DSO, and the DSO loads the plugin.
|
||||
|
@ -18,9 +18,6 @@
|
||||
|
||||
#include <math.h>
|
||||
#include <pthread.h>
|
||||
#if USE_CRYPT
|
||||
# include <crypt.h>
|
||||
#endif
|
||||
#include <resolv.h>
|
||||
#include <dlfcn.h>
|
||||
#include <utmp.h>
|
||||
@ -34,9 +31,6 @@ void *references[] =
|
||||
{
|
||||
&pow, /* libm */
|
||||
&pthread_create, /* libpthread */
|
||||
#if USE_CRYPT
|
||||
&crypt, /* libcrypt */
|
||||
#endif
|
||||
&res_send, /* libresolv */
|
||||
&dlopen, /* libdl */
|
||||
&login, /* libutil */
|
||||
|
@ -1,3 +0,0 @@
|
||||
#ifndef _CRYPT_H
|
||||
# include <crypt/crypt.h>
|
||||
#endif /* _CRYPT_H */
|
@ -47,7 +47,7 @@ extra-libs-others = $(extra-libs)
|
||||
libBrokenLocale-routines = broken_cur_max
|
||||
|
||||
subdir-dirs = programs
|
||||
vpath %.c programs ../crypt
|
||||
vpath %.c programs
|
||||
vpath %.h programs
|
||||
vpath %.gperf programs
|
||||
|
||||
@ -69,8 +69,6 @@ endif
|
||||
|
||||
include ../Rules
|
||||
|
||||
CFLAGS-md5.c += -I../crypt
|
||||
|
||||
programs/%-kw.h: programs/%-kw.gperf
|
||||
cd programs \
|
||||
&& $(GPERF) $(GPERFFLAGS) -N $(@F:-kw.h=_hash) $(<F) > $(@F).new
|
||||
|
@ -41,7 +41,7 @@
|
||||
|
||||
#include <libc-mmap.h>
|
||||
#include <libc-pointer-arith.h>
|
||||
#include "../../crypt/md5.h"
|
||||
#include "md5.h"
|
||||
#include "../localeinfo.h"
|
||||
#include "../locarchive.h"
|
||||
#include "localedef.h"
|
||||
|
@ -30,13 +30,13 @@
|
||||
#include <assert.h>
|
||||
#include <wchar.h>
|
||||
|
||||
#include "../../crypt/md5.h"
|
||||
#include "localedef.h"
|
||||
#include "localeinfo.h"
|
||||
#include "locfile.h"
|
||||
#include "simple-hash.h"
|
||||
|
||||
#include "locfile-kw.h"
|
||||
#include "md5.h"
|
||||
|
||||
#define obstack_chunk_alloc xmalloc
|
||||
#define obstack_chunk_free free
|
||||
|
@ -19,36 +19,12 @@
|
||||
|
||||
/* Written by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995. */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#if STDC_HEADERS || defined _LIBC
|
||||
# include <stdlib.h>
|
||||
# include <string.h>
|
||||
#else
|
||||
# ifndef HAVE_MEMCPY
|
||||
# define memcpy(d, s, n) (bcopy ((s), (d), (n)), (d))
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
#include <endian.h>
|
||||
#include "md5.h"
|
||||
|
||||
#ifdef _LIBC
|
||||
# include <endian.h>
|
||||
# if __BYTE_ORDER == __BIG_ENDIAN
|
||||
# define WORDS_BIGENDIAN 1
|
||||
# endif
|
||||
/* We need to keep the namespace clean so define the MD5 function
|
||||
protected using leading __ . */
|
||||
# define md5_init_ctx __md5_init_ctx
|
||||
# define md5_process_bytes __md5_process_bytes
|
||||
# define md5_finish_ctx __md5_finish_ctx
|
||||
# define md5_read_ctx __md5_read_ctx
|
||||
# define md5_stream __md5_stream
|
||||
# define md5_buffer __md5_buffer
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||
# define WORDS_BIGENDIAN 1
|
||||
#endif
|
||||
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
@ -67,7 +43,7 @@ static const unsigned char fillbuf[64] = { 0x80, 0 /* , 0, 0, ... */ };
|
||||
/* Initialize structure containing state of computation.
|
||||
(RFC 1321, 3.3: Step 3) */
|
||||
void
|
||||
md5_init_ctx (struct md5_ctx *ctx)
|
||||
__md5_init_ctx (struct md5_ctx *ctx)
|
||||
{
|
||||
ctx->A = 0x67452301;
|
||||
ctx->B = 0xefcdab89;
|
||||
@ -84,7 +60,7 @@ md5_init_ctx (struct md5_ctx *ctx)
|
||||
IMPORTANT: On some systems it is required that RESBUF is correctly
|
||||
aligned for a 32 bits value. */
|
||||
void *
|
||||
md5_read_ctx (const struct md5_ctx *ctx, void *resbuf)
|
||||
__md5_read_ctx (const struct md5_ctx *ctx, void *resbuf)
|
||||
{
|
||||
((md5_uint32 *) resbuf)[0] = SWAP (ctx->A);
|
||||
((md5_uint32 *) resbuf)[1] = SWAP (ctx->B);
|
||||
@ -100,7 +76,7 @@ md5_read_ctx (const struct md5_ctx *ctx, void *resbuf)
|
||||
IMPORTANT: On some systems it is required that RESBUF is correctly
|
||||
aligned for a 32 bits value. */
|
||||
void *
|
||||
md5_finish_ctx (struct md5_ctx *ctx, void *resbuf)
|
||||
__md5_finish_ctx (struct md5_ctx *ctx, void *resbuf)
|
||||
{
|
||||
/* Take yet unprocessed bytes into account. */
|
||||
md5_uint32 bytes = ctx->buflen;
|
||||
@ -122,61 +98,7 @@ md5_finish_ctx (struct md5_ctx *ctx, void *resbuf)
|
||||
/* Process last bytes. */
|
||||
__md5_process_block (ctx->buffer, bytes + pad + 8, ctx);
|
||||
|
||||
return md5_read_ctx (ctx, resbuf);
|
||||
}
|
||||
|
||||
/* Compute MD5 message digest for bytes read from STREAM. The
|
||||
resulting message digest number will be written into the 16 bytes
|
||||
beginning at RESBLOCK. */
|
||||
int
|
||||
md5_stream (FILE *stream, void *resblock)
|
||||
{
|
||||
/* Important: BLOCKSIZE must be a multiple of 64. */
|
||||
#define BLOCKSIZE 4096
|
||||
struct md5_ctx ctx;
|
||||
char buffer[BLOCKSIZE + 72];
|
||||
size_t sum;
|
||||
|
||||
/* Initialize the computation context. */
|
||||
md5_init_ctx (&ctx);
|
||||
|
||||
/* Iterate over full file contents. */
|
||||
while (1)
|
||||
{
|
||||
/* We read the file in blocks of BLOCKSIZE bytes. One call of the
|
||||
computation function processes the whole buffer so that with the
|
||||
next round of the loop another block can be read. */
|
||||
size_t n;
|
||||
sum = 0;
|
||||
|
||||
/* Read block. Take care for partial reads. */
|
||||
do
|
||||
{
|
||||
n = fread (buffer + sum, 1, BLOCKSIZE - sum, stream);
|
||||
|
||||
sum += n;
|
||||
}
|
||||
while (sum < BLOCKSIZE && n != 0);
|
||||
if (n == 0 && ferror (stream))
|
||||
return 1;
|
||||
|
||||
/* If end of file is reached, end the loop. */
|
||||
if (n == 0)
|
||||
break;
|
||||
|
||||
/* Process buffer with BLOCKSIZE bytes. Note that
|
||||
BLOCKSIZE % 64 == 0
|
||||
*/
|
||||
__md5_process_block (buffer, BLOCKSIZE, &ctx);
|
||||
}
|
||||
|
||||
/* Add the last bytes if necessary. */
|
||||
if (sum > 0)
|
||||
md5_process_bytes (buffer, sum, &ctx);
|
||||
|
||||
/* Construct result in desired memory. */
|
||||
md5_finish_ctx (&ctx, resblock);
|
||||
return 0;
|
||||
return __md5_read_ctx (ctx, resbuf);
|
||||
}
|
||||
|
||||
/* Compute MD5 message digest for LEN bytes beginning at BUFFER. The
|
||||
@ -184,23 +106,23 @@ md5_stream (FILE *stream, void *resblock)
|
||||
output yields to the wanted ASCII representation of the message
|
||||
digest. */
|
||||
void *
|
||||
md5_buffer (const char *buffer, size_t len, void *resblock)
|
||||
__md5_buffer (const char *buffer, size_t len, void *resblock)
|
||||
{
|
||||
struct md5_ctx ctx;
|
||||
|
||||
/* Initialize the computation context. */
|
||||
md5_init_ctx (&ctx);
|
||||
__md5_init_ctx (&ctx);
|
||||
|
||||
/* Process whole buffer but last len % 64 bytes. */
|
||||
md5_process_bytes (buffer, len, &ctx);
|
||||
__md5_process_bytes (buffer, len, &ctx);
|
||||
|
||||
/* Put result in desired memory area. */
|
||||
return md5_finish_ctx (&ctx, resblock);
|
||||
return __md5_finish_ctx (&ctx, resblock);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
md5_process_bytes (const void *buffer, size_t len, struct md5_ctx *ctx)
|
||||
__md5_process_bytes (const void *buffer, size_t len, struct md5_ctx *ctx)
|
||||
{
|
||||
/* When we already have some bits in our internal buffer concatenate
|
||||
both inputs first. */
|
@ -20,12 +20,6 @@
|
||||
#ifndef _MD5_H
|
||||
#define _MD5_H 1
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#if defined HAVE_LIMITS_H || defined _LIBC
|
||||
# include <limits.h>
|
||||
#endif
|
||||
|
||||
#define MD5_DIGEST_SIZE 16
|
||||
#define MD5_BLOCK_SIZE 64
|
||||
|
||||
@ -36,41 +30,9 @@
|
||||
the resulting executable. Locally running cross-compiled executables
|
||||
is usually not possible. */
|
||||
|
||||
#ifdef _LIBC
|
||||
# include <stdint.h>
|
||||
#include <stdint.h>
|
||||
typedef uint32_t md5_uint32;
|
||||
typedef uintptr_t md5_uintptr;
|
||||
#else
|
||||
# define UINT_MAX_32_BITS 4294967295U
|
||||
|
||||
/* If UINT_MAX isn't defined, assume it's a 32-bit type.
|
||||
This should be valid for all systems GNU cares about because
|
||||
that doesn't include 16-bit systems, and only modern systems
|
||||
(that certainly have <limits.h>) have 64+-bit integral types. */
|
||||
|
||||
# ifndef UINT_MAX
|
||||
# define UINT_MAX UINT_MAX_32_BITS
|
||||
# endif
|
||||
|
||||
# if UINT_MAX == UINT_MAX_32_BITS
|
||||
typedef unsigned int md5_uint32;
|
||||
# else
|
||||
# if USHRT_MAX == UINT_MAX_32_BITS
|
||||
typedef unsigned short md5_uint32;
|
||||
# else
|
||||
# if ULONG_MAX == UINT_MAX_32_BITS
|
||||
typedef unsigned long md5_uint32;
|
||||
# else
|
||||
/* The following line is intended to evoke an error.
|
||||
Using #error is not portable enough. */
|
||||
"Cannot determine unsigned 32-bit data type."
|
||||
# endif
|
||||
# endif
|
||||
# endif
|
||||
/* We have to make a guess about the integer type equivalent in size
|
||||
to pointers which should always be correct. */
|
||||
typedef unsigned long int md5_uintptr;
|
||||
#endif
|
||||
|
||||
/* Structure to save state of computation between the single steps. */
|
||||
struct md5_ctx
|
||||
@ -130,12 +92,6 @@ extern void *__md5_finish_ctx (struct md5_ctx *ctx, void *resbuf) __THROW;
|
||||
aligned for a 32 bits value. */
|
||||
extern void *__md5_read_ctx (const struct md5_ctx *ctx, void *resbuf) __THROW;
|
||||
|
||||
|
||||
/* Compute MD5 message digest for bytes read from STREAM. The
|
||||
resulting message digest number will be written into the 16 bytes
|
||||
beginning at RESBLOCK. */
|
||||
extern int __md5_stream (FILE *stream, void *resblock) __THROW;
|
||||
|
||||
/* Compute MD5 message digest for LEN bytes beginning at BUFFER. The
|
||||
result is always in little endian byte order, so that a byte-wise
|
||||
output yields to the wanted ASCII representation of the message
|
@ -199,7 +199,7 @@ Romain Geissler for various fixes.
|
||||
|
||||
@item
|
||||
Michael Glad for the passphrase-hashing function @code{crypt} and related
|
||||
functions.
|
||||
functions (no longer part of glibc, but we still appreciate his work).
|
||||
|
||||
@item
|
||||
Wolfram Gloger for contributing the memory allocation functions
|
||||
|
@ -1,205 +1,18 @@
|
||||
@node Cryptographic Functions, Debugging Support, System Configuration, Top
|
||||
@chapter Cryptographic Functions
|
||||
@c %MENU% Passphrase storage and strongly unpredictable bytes.
|
||||
@c %MENU% A few functions to support cryptographic applications
|
||||
|
||||
@Theglibc{} includes only a few special-purpose cryptographic
|
||||
functions: one-way hash functions for passphrase storage, and access
|
||||
to a cryptographic randomness source, if one is provided by the
|
||||
operating system. Programs that need general-purpose cryptography
|
||||
should use a dedicated cryptography library, such as
|
||||
@Theglibc{} includes only one type of special-purpose cryptographic
|
||||
functions; these allow use of a source of cryptographically strong
|
||||
pseudorandom numbers, if such a source is provided by the operating
|
||||
system. Programs that need general-purpose cryptography should use
|
||||
a dedicated cryptography library, such as
|
||||
@uref{https://www.gnu.org/software/libgcrypt/,,libgcrypt}.
|
||||
|
||||
Many countries place legal restrictions on the import, export,
|
||||
possession, or use of cryptographic software. We deplore these
|
||||
restrictions, but we must still warn you that @theglibc{} may be
|
||||
subject to them, even if you do not use the functions in this chapter
|
||||
yourself. The restrictions vary from place to place and are changed
|
||||
often, so we cannot give any more specific advice than this warning.
|
||||
|
||||
@menu
|
||||
* Passphrase Storage:: One-way hashing for passphrases.
|
||||
* Unpredictable Bytes:: Randomness for cryptographic purposes.
|
||||
@end menu
|
||||
|
||||
@node Passphrase Storage
|
||||
@section Passphrase Storage
|
||||
@cindex passphrase hashing
|
||||
@cindex one-way hashing
|
||||
@cindex hashing, passphrase
|
||||
|
||||
Sometimes it is necessary to be sure that a user is authorized
|
||||
to use some service a machine provides---for instance, to log in as a
|
||||
particular user id (@pxref{Users and Groups}). One traditional way of
|
||||
doing this is for each user to choose a secret @dfn{passphrase}; then, the
|
||||
system can ask someone claiming to be a user what the user's passphrase
|
||||
is, and if the person gives the correct passphrase then the system can
|
||||
grant the appropriate privileges. (Traditionally, these were called
|
||||
``passwords,'' but nowadays a single word is too easy to guess.)
|
||||
|
||||
Programs that handle passphrases must take special care not to reveal
|
||||
them to anyone, no matter what. It is not enough to keep them in a
|
||||
file that is only accessible with special privileges. The file might
|
||||
be ``leaked'' via a bug or misconfiguration, and system administrators
|
||||
shouldn't learn everyone's passphrase even if they have to edit that
|
||||
file for some reason. To avoid this, passphrases should also be
|
||||
converted into @dfn{one-way hashes}, using a @dfn{one-way function},
|
||||
before they are stored.
|
||||
|
||||
A one-way function is easy to compute, but there is no known way to
|
||||
compute its inverse. This means the system can easily check
|
||||
passphrases, by hashing them and comparing the result with the stored
|
||||
hash. But an attacker who discovers someone's passphrase hash can
|
||||
only discover the passphrase it corresponds to by guessing and
|
||||
checking. The one-way functions are designed to make this process
|
||||
impractically slow, for all but the most obvious guesses. (Do not use
|
||||
a word from the dictionary as your passphrase.)
|
||||
|
||||
@Theglibc{} provides an interface to four one-way functions, based on
|
||||
the SHA-2-512, SHA-2-256, MD5, and DES cryptographic primitives. New
|
||||
passphrases should be hashed with either of the SHA-based functions.
|
||||
The others are too weak for newly set passphrases, but we continue to
|
||||
support them for verifying old passphrases. The DES-based hash is
|
||||
especially weak, because it ignores all but the first eight characters
|
||||
of its input.
|
||||
|
||||
@deftypefun {char *} crypt (const char *@var{phrase}, const char *@var{salt})
|
||||
@standards{X/Open, unistd.h}
|
||||
@standards{GNU, crypt.h}
|
||||
@safety{@prelim{}@mtunsafe{@mtasurace{:crypt}}@asunsafe{@asucorrupt{} @asulock{} @ascuheap{} @ascudlopen{}}@acunsafe{@aculock{} @acsmem{}}}
|
||||
@c Besides the obvious problem of returning a pointer into static
|
||||
@c storage, the DES initializer takes an internal lock with the usual
|
||||
@c set of problems for AS- and AC-Safety.
|
||||
@c The NSS implementations may leak file descriptors if cancelled.
|
||||
@c The MD5, SHA256 and SHA512 implementations will malloc on long keys,
|
||||
@c and NSS relies on dlopening, which brings about another can of worms.
|
||||
|
||||
The function @code{crypt} converts a passphrase string, @var{phrase},
|
||||
into a one-way hash suitable for storage in the user database. The
|
||||
string that it returns will consist entirely of printable ASCII
|
||||
characters. It will not contain whitespace, nor any of the characters
|
||||
@samp{:}, @samp{;}, @samp{*}, @samp{!}, or @samp{\}.
|
||||
|
||||
The @var{salt} parameter controls which one-way function is used, and
|
||||
it also ensures that the output of the one-way function is different
|
||||
for every user, even if they have the same passphrase. This makes it
|
||||
harder to guess passphrases from a large user database. Without salt,
|
||||
the attacker could make a guess, run @code{crypt} on it once, and
|
||||
compare the result with all the hashes. Salt forces the attacker to
|
||||
make separate calls to @code{crypt} for each user.
|
||||
|
||||
To verify a passphrase, pass the previously hashed passphrase as the
|
||||
@var{salt}. To hash a new passphrase for storage, set @var{salt} to a
|
||||
string consisting of a prefix plus a sequence of randomly chosen
|
||||
characters, according to this table:
|
||||
|
||||
@multitable @columnfractions .2 .1 .3
|
||||
@headitem One-way function @tab Prefix @tab Random sequence
|
||||
@item SHA-2-512
|
||||
@tab @samp{$6$}
|
||||
@tab 16 characters
|
||||
@item SHA-2-256
|
||||
@tab @samp{$5$}
|
||||
@tab 16 characters
|
||||
@item MD5
|
||||
@tab @samp{$1$}
|
||||
@tab 8 characters
|
||||
@item DES
|
||||
@tab @samp{}
|
||||
@tab 2 characters
|
||||
@end multitable
|
||||
|
||||
In all cases, the random characters should be chosen from the alphabet
|
||||
@code{./0-9A-Za-z}.
|
||||
|
||||
With all of the hash functions @emph{except} DES, @var{phrase} can be
|
||||
arbitrarily long, and all eight bits of each byte are significant.
|
||||
With DES, only the first eight characters of @var{phrase} affect the
|
||||
output, and the eighth bit of each byte is also ignored.
|
||||
|
||||
@code{crypt} can fail. Some implementations return @code{NULL} on
|
||||
failure, and others return an @emph{invalid} hashed passphrase, which
|
||||
will begin with a @samp{*} and will not be the same as @var{salt}. In
|
||||
either case, @code{errno} will be set to indicate the problem. Some
|
||||
of the possible error codes are:
|
||||
|
||||
@table @code
|
||||
@item EINVAL
|
||||
@var{salt} is invalid; neither a previously hashed passphrase, nor a
|
||||
well-formed new salt for any of the supported hash functions.
|
||||
|
||||
@item EPERM
|
||||
The system configuration forbids use of the hash function selected by
|
||||
@var{salt}.
|
||||
|
||||
@item ENOMEM
|
||||
Failed to allocate internal scratch storage.
|
||||
|
||||
@item ENOSYS
|
||||
@itemx EOPNOTSUPP
|
||||
Hashing passphrases is not supported at all, or the hash function
|
||||
selected by @var{salt} is not supported. @Theglibc{} does not use
|
||||
these error codes, but they may be encountered on other operating
|
||||
systems.
|
||||
@end table
|
||||
|
||||
@code{crypt} uses static storage for both internal scratchwork and the
|
||||
string it returns. It is not safe to call @code{crypt} from multiple
|
||||
threads simultaneously, and the string it returns will be overwritten
|
||||
by any subsequent call to @code{crypt}.
|
||||
|
||||
@code{crypt} is specified in the X/Open Portability Guide and is
|
||||
present on nearly all historical Unix systems. However, the XPG does
|
||||
not specify any one-way functions.
|
||||
|
||||
@code{crypt} is declared in @file{unistd.h}. @Theglibc{} also
|
||||
declares this function in @file{crypt.h}.
|
||||
@end deftypefun
|
||||
|
||||
@deftypefun {char *} crypt_r (const char *@var{phrase}, const char *@var{salt}, struct crypt_data *@var{data})
|
||||
@standards{GNU, crypt.h}
|
||||
@safety{@prelim{}@mtsafe{}@asunsafe{@asucorrupt{} @asulock{} @ascuheap{} @ascudlopen{}}@acunsafe{@aculock{} @acsmem{}}}
|
||||
@tindex struct crypt_data
|
||||
@c Compared with crypt, this function fixes the @mtasurace:crypt
|
||||
@c problem, but nothing else.
|
||||
|
||||
The function @code{crypt_r} is a thread-safe version of @code{crypt}.
|
||||
Instead of static storage, it uses the memory pointed to by its
|
||||
@var{data} argument for both scratchwork and the string it returns.
|
||||
It can safely be used from multiple threads, as long as different
|
||||
@var{data} objects are used in each thread. The string it returns
|
||||
will still be overwritten by another call with the same @var{data}.
|
||||
|
||||
@var{data} must point to a @code{struct crypt_data} object allocated
|
||||
by the caller. All of the fields of @code{struct crypt_data} are
|
||||
private, but before one of these objects is used for the first time,
|
||||
it must be initialized to all zeroes, using @code{memset} or similar.
|
||||
After that, it can be reused for many calls to @code{crypt_r} without
|
||||
erasing it again. @code{struct crypt_data} is very large, so it is
|
||||
best to allocate it with @code{malloc} rather than as a local
|
||||
variable. @xref{Memory Allocation}.
|
||||
|
||||
@code{crypt_r} is a GNU extension. It is declared in @file{crypt.h},
|
||||
as is @code{struct crypt_data}.
|
||||
@end deftypefun
|
||||
|
||||
The following program shows how to use @code{crypt} the first time a
|
||||
passphrase is entered. It uses @code{getentropy} to make the salt as
|
||||
unpredictable as possible; @pxref{Unpredictable Bytes}.
|
||||
|
||||
@smallexample
|
||||
@include genpass.c.texi
|
||||
@end smallexample
|
||||
|
||||
The next program demonstrates how to verify a passphrase. It checks a
|
||||
hash hardcoded into the program, because looking up real users' hashed
|
||||
passphrases may require special privileges (@pxref{User Database}).
|
||||
It also shows that different one-way functions produce different
|
||||
hashes for the same passphrase.
|
||||
|
||||
@smallexample
|
||||
@include testpass.c.texi
|
||||
@end smallexample
|
||||
|
||||
@node Unpredictable Bytes
|
||||
@section Generating Unpredictable Bytes
|
||||
@cindex randomness source
|
||||
@ -211,27 +24,24 @@ hashes for the same passphrase.
|
||||
@cindex CSPRNG
|
||||
@cindex DRBG
|
||||
|
||||
Cryptographic applications often need some random data that will be as
|
||||
difficult as possible for a hostile eavesdropper to guess. For
|
||||
instance, encryption keys should be chosen at random, and the ``salt''
|
||||
strings used by @code{crypt} (@pxref{Passphrase Storage}) should also
|
||||
be chosen at random.
|
||||
|
||||
Some pseudo-random number generators do not provide unpredictable-enough
|
||||
output for cryptographic applications; @pxref{Pseudo-Random Numbers}.
|
||||
Such applications need to use a @dfn{cryptographic random number
|
||||
generator} (CRNG), also sometimes called a @dfn{cryptographically strong
|
||||
pseudo-random number generator} (CSPRNG) or @dfn{deterministic random
|
||||
bit generator} (DRBG).
|
||||
Cryptographic applications often need random data that will be as
|
||||
difficult as possible for a hostile eavesdropper to guess.
|
||||
The pseudo-random number generators provided by @theglibc{}
|
||||
(@pxref{Pseudo-Random Numbers}) are not suitable for this purpose.
|
||||
They produce output that is @emph{statistically} random, but fails to
|
||||
be @emph{unpredictable}. Cryptographic applications require a
|
||||
@dfn{cryptographic random number generator} (CRNG), also known as a
|
||||
@dfn{cryptographically strong pseudo-random number generator} (CSPRNG)
|
||||
or a @dfn{deterministic random bit generator} (DRBG).
|
||||
|
||||
Currently, @theglibc{} does not provide a cryptographic random number
|
||||
generator, but it does provide functions that read random data from a
|
||||
@dfn{randomness source} supplied by the operating system. The
|
||||
randomness source is a CRNG at heart, but it also continually
|
||||
``re-seeds'' itself from physical sources of randomness, such as
|
||||
electronic noise and clock jitter. This means applications do not need
|
||||
to do anything to ensure that the random numbers it produces are
|
||||
different on each run.
|
||||
generator, but it does provide functions that read cryptographically
|
||||
strong random data from a @dfn{randomness source} supplied by the
|
||||
operating system. This randomness source is a CRNG at heart, but it
|
||||
also continually ``re-seeds'' itself from physical sources of
|
||||
randomness, such as electronic noise and clock jitter. This means
|
||||
applications do not need to do anything to ensure that the random
|
||||
numbers it produces are different on each run.
|
||||
|
||||
The catch, however, is that these functions will only produce
|
||||
relatively short random strings in any one call. Often this is not a
|
||||
|
@ -1,59 +0,0 @@
|
||||
/* Encrypting Passwords
|
||||
Copyright (C) 1991-2023 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program 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 General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <crypt.h>
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
unsigned char ubytes[16];
|
||||
char salt[20];
|
||||
const char *const saltchars =
|
||||
"./0123456789ABCDEFGHIJKLMNOPQRST"
|
||||
"UVWXYZabcdefghijklmnopqrstuvwxyz";
|
||||
char *hash;
|
||||
int i;
|
||||
|
||||
/* Retrieve 16 unpredictable bytes from the operating system. */
|
||||
if (getentropy (ubytes, sizeof ubytes))
|
||||
{
|
||||
perror ("getentropy");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Use them to fill in the salt string. */
|
||||
salt[0] = '$';
|
||||
salt[1] = '5'; /* SHA-256 */
|
||||
salt[2] = '$';
|
||||
for (i = 0; i < 16; i++)
|
||||
salt[3+i] = saltchars[ubytes[i] & 0x3f];
|
||||
salt[3+i] = '\0';
|
||||
|
||||
/* Read in the user's passphrase and hash it. */
|
||||
hash = crypt (getpass ("Enter new passphrase: "), salt);
|
||||
if (!hash || hash[0] == '*')
|
||||
{
|
||||
perror ("crypt");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Print the results. */
|
||||
puts (hash);
|
||||
return 0;
|
||||
}
|
@ -1,67 +0,0 @@
|
||||
/* Verify a passphrase.
|
||||
Copyright (C) 1991-2023 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program 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 General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <crypt.h>
|
||||
|
||||
/* @samp{GNU's Not Unix} hashed using SHA-256, MD5, and DES. */
|
||||
static const char hash_sha[] =
|
||||
"$5$DQ2z5NHf1jNJnChB$kV3ZTR0aUaosujPhLzR84Llo3BsspNSe4/tsp7VoEn6";
|
||||
static const char hash_md5[] = "$1$A3TxDv41$rtXVTUXl2LkeSV0UU5xxs1";
|
||||
static const char hash_des[] = "FgkTuF98w5DaI";
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
char *phrase;
|
||||
int status = 0;
|
||||
|
||||
/* Prompt for a passphrase. */
|
||||
phrase = getpass ("Enter passphrase: ");
|
||||
|
||||
/* Compare against the stored hashes. Any input that begins with
|
||||
@samp{GNU's No} will match the DES hash, but the other two will
|
||||
only match @samp{GNU's Not Unix}. */
|
||||
|
||||
if (strcmp (crypt (phrase, hash_sha), hash_sha))
|
||||
{
|
||||
puts ("SHA: not ok");
|
||||
status = 1;
|
||||
}
|
||||
else
|
||||
puts ("SHA: ok");
|
||||
|
||||
if (strcmp (crypt (phrase, hash_md5), hash_md5))
|
||||
{
|
||||
puts ("MD5: not ok");
|
||||
status = 1;
|
||||
}
|
||||
else
|
||||
puts ("MD5: ok");
|
||||
|
||||
if (strcmp (crypt (phrase, hash_des), hash_des))
|
||||
{
|
||||
puts ("DES: not ok");
|
||||
status = 1;
|
||||
}
|
||||
else
|
||||
puts ("DES: ok");
|
||||
|
||||
return status;
|
||||
}
|
@ -1731,8 +1731,8 @@ most systems, but on some systems a special network server gives access
|
||||
to it.
|
||||
|
||||
Historically, this database included one-way hashes of user
|
||||
passphrases (@pxref{Passphrase Storage}) as well as public information
|
||||
about each user (such as their user ID and full name). Many of the
|
||||
passphrases, as well as public information about each user
|
||||
(such as their user ID and full name). Many of the names of
|
||||
functions and data structures associated with this database, and the
|
||||
filename @file{/etc/passwd} itself, reflect this history. However,
|
||||
the information in this database is available to all users, and it is
|
||||
|
@ -1150,16 +1150,6 @@ ssize_t copy_file_range (int __infd, __off64_t *__pinoff,
|
||||
extern int fdatasync (int __fildes);
|
||||
#endif /* Use POSIX199309 */
|
||||
|
||||
#ifdef __USE_MISC
|
||||
/* One-way hash PHRASE, returning a string suitable for storage in the
|
||||
user database. SALT selects the one-way function to use, and
|
||||
ensures that no two users' hashes are the same, even if they use
|
||||
the same passphrase. The return value points to static storage
|
||||
which will be overwritten by the next call to crypt. */
|
||||
extern char *crypt (const char *__key, const char *__salt)
|
||||
__THROW __nonnull ((1, 2));
|
||||
#endif
|
||||
|
||||
#ifdef __USE_XOPEN
|
||||
/* Swab pairs bytes in the first N bytes of the area pointed to by
|
||||
FROM and copy the result to TO. The value of TO must not be in the
|
||||
|
@ -465,7 +465,6 @@ class Context(object):
|
||||
'--disable-profile',
|
||||
'--disable-timezone-tools',
|
||||
'--disable-mathvec',
|
||||
'--disable-crypt',
|
||||
'--disable-build-nscd',
|
||||
'--disable-nscd']},
|
||||
{'variant': 'no-pie',
|
||||
@ -486,9 +485,7 @@ class Context(object):
|
||||
{'arch': 'i586',
|
||||
'ccopts': '-m32 -march=i586'},
|
||||
{'variant': 'enable-fortify-source',
|
||||
'cfg': ['--enable-fortify-source']},
|
||||
{'variant': 'enable-crypt',
|
||||
'cfg': ['--enable-crypt']}])
|
||||
'cfg': ['--enable-fortify-source']}])
|
||||
self.add_config(arch='x86_64',
|
||||
os_name='gnu',
|
||||
gcc_cfg=['--disable-multilib'])
|
||||
|
@ -14,7 +14,7 @@ sed -e '/^__fpending$/d' -e '/^__flbf$/d' -e '/^__fbufsize$/d' |
|
||||
sed -e '/^alloca$/d' |
|
||||
sort -u > DOCUMENTED
|
||||
|
||||
nm --extern --define $bindir/libc.so $bindir/math/libm.so $bindir/rt/librt.so $bindir/linuxthreads/libpthread.so $bindir/dlfcn/libdl.so $bindir/crypt/libcrypt.so $bindir/login/libutil.so |
|
||||
nm --extern --define $bindir/libc.so $bindir/math/libm.so $bindir/rt/librt.so $bindir/linuxthreads/libpthread.so $bindir/dlfcn/libdl.so $bindir/login/libutil.so |
|
||||
grep -E " [TW] ([[:alpha:]]|_[[:alpha:]])" |
|
||||
sed 's/\(@.*\)//' |
|
||||
cut -b 12- |
|
||||
|
@ -50,9 +50,6 @@ libnss_db=2
|
||||
# Version for libnsl with YP and NIS+ functions.
|
||||
libnsl=1
|
||||
|
||||
# This defines the shared library version numbers we will install.
|
||||
libcrypt=1
|
||||
|
||||
# The gross patch for programs assuming broken locale implementations.
|
||||
libBrokenLocale=1
|
||||
|
||||
|
@ -74,7 +74,5 @@ libc {
|
||||
GLIBC_PRIVATE {
|
||||
# global variables
|
||||
_itoa_lower_digits;
|
||||
# Used in libcrypt.
|
||||
__snprintf;
|
||||
}
|
||||
}
|
||||
|
@ -1,36 +0,0 @@
|
||||
/* Dummy implementation of FIPS compliance status test.
|
||||
Copyright (C) 2012-2023 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
The GNU C 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.
|
||||
|
||||
The GNU C 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 the GNU C Library; if not, see
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#ifndef _FIPS_PRIVATE_H
|
||||
#define _FIPS_PRIVATE_H
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
/* Return true if compliance with the FIPS security standards is
|
||||
enabled.
|
||||
|
||||
This is only relevant within crypt, to tell whether MD5 and DES
|
||||
algorithms should be rejected. */
|
||||
|
||||
static inline bool
|
||||
fips_enabled_p (void)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif /* _FIPS_PRIVATE_H */
|
@ -50,9 +50,7 @@ mach-before-compile:
|
||||
before-compile += $(mach-before-compile)
|
||||
endif
|
||||
|
||||
ifeq (crypt,$(subdir))
|
||||
LDLIBS-crypt.so += $(objdir)/mach/libmachuser.so
|
||||
else ifeq (dlfcn,$(subdir))
|
||||
ifeq (dlfcn,$(subdir))
|
||||
LDLIBS-dl.so += $(objdir)/mach/libmachuser.so
|
||||
else ifeq (nis,$(subdir))
|
||||
LDLIBS-nsl.so += $(objdir)/mach/libmachuser.so
|
||||
|
@ -1,7 +0,0 @@
|
||||
GLIBC_2.2.6 crypt F
|
||||
GLIBC_2.2.6 crypt_r F
|
||||
GLIBC_2.2.6 encrypt F
|
||||
GLIBC_2.2.6 encrypt_r F
|
||||
GLIBC_2.2.6 fcrypt F
|
||||
GLIBC_2.2.6 setkey F
|
||||
GLIBC_2.2.6 setkey_r F
|
@ -1,2 +0,0 @@
|
||||
GLIBC_2.38 crypt F
|
||||
GLIBC_2.38 crypt_r F
|
@ -1,7 +0,0 @@
|
||||
GLIBC_2.17 crypt F
|
||||
GLIBC_2.17 crypt_r F
|
||||
GLIBC_2.17 encrypt F
|
||||
GLIBC_2.17 encrypt_r F
|
||||
GLIBC_2.17 fcrypt F
|
||||
GLIBC_2.17 setkey F
|
||||
GLIBC_2.17 setkey_r F
|
@ -1,7 +0,0 @@
|
||||
GLIBC_2.0 crypt F
|
||||
GLIBC_2.0 crypt_r F
|
||||
GLIBC_2.0 encrypt F
|
||||
GLIBC_2.0 encrypt_r F
|
||||
GLIBC_2.0 fcrypt F
|
||||
GLIBC_2.0 setkey F
|
||||
GLIBC_2.0 setkey_r F
|
@ -10,5 +10,4 @@ libutil=1.1
|
||||
libresolv=2.1
|
||||
|
||||
libnsl=1.1
|
||||
libcrypt=1.1
|
||||
libBrokenLocale=1.1
|
||||
|
@ -1,2 +0,0 @@
|
||||
GLIBC_2.32 crypt F
|
||||
GLIBC_2.32 crypt_r F
|
@ -17,10 +17,6 @@ endif
|
||||
|
||||
# Add a syscall function to each library that needs one.
|
||||
|
||||
ifeq ($(subdir),crypt)
|
||||
libcrypt-sysdep_routines += libc-do-syscall
|
||||
endif
|
||||
|
||||
ifeq ($(subdir),rt)
|
||||
librt-sysdep_routines += libc-do-syscall
|
||||
librt-shared-only-routines += libc-do-syscall
|
||||
|
@ -1,7 +0,0 @@
|
||||
GLIBC_2.4 crypt F
|
||||
GLIBC_2.4 crypt_r F
|
||||
GLIBC_2.4 encrypt F
|
||||
GLIBC_2.4 encrypt_r F
|
||||
GLIBC_2.4 fcrypt F
|
||||
GLIBC_2.4 setkey F
|
||||
GLIBC_2.4 setkey_r F
|
@ -1,7 +0,0 @@
|
||||
GLIBC_2.4 crypt F
|
||||
GLIBC_2.4 crypt_r F
|
||||
GLIBC_2.4 encrypt F
|
||||
GLIBC_2.4 encrypt_r F
|
||||
GLIBC_2.4 fcrypt F
|
||||
GLIBC_2.4 setkey F
|
||||
GLIBC_2.4 setkey_r F
|
@ -1,2 +0,0 @@
|
||||
GLIBC_2.29 crypt F
|
||||
GLIBC_2.29 crypt_r F
|
@ -1,74 +0,0 @@
|
||||
/* FIPS compliance status test for GNU/Linux systems.
|
||||
Copyright (C) 2012-2023 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
The GNU C 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.
|
||||
|
||||
The GNU C 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 the GNU C Library; if not, see
|
||||
<https://www.gnu.org/licenses/>. */
|
||||
|
||||
#ifndef _FIPS_PRIVATE_H
|
||||
#define _FIPS_PRIVATE_H
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <not-cancel.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
/* Return true if FIPS mode is enabled. See
|
||||
sysdeps/generic/fips-private.h for more information. */
|
||||
|
||||
static bool
|
||||
fips_enabled_p (void)
|
||||
{
|
||||
static enum
|
||||
{
|
||||
FIPS_UNTESTED = 0,
|
||||
FIPS_ENABLED = 1,
|
||||
FIPS_DISABLED = -1,
|
||||
FIPS_TEST_FAILED = -2
|
||||
} checked;
|
||||
|
||||
if (checked == FIPS_UNTESTED)
|
||||
{
|
||||
int fd = __open_nocancel ("/proc/sys/crypto/fips_enabled", O_RDONLY);
|
||||
|
||||
if (fd != -1)
|
||||
{
|
||||
/* This is more than enough, the file contains a single integer. */
|
||||
char buf[32];
|
||||
ssize_t n;
|
||||
n = TEMP_FAILURE_RETRY (__read_nocancel (fd, buf, sizeof (buf) - 1));
|
||||
__close_nocancel_nostatus (fd);
|
||||
|
||||
if (n > 0)
|
||||
{
|
||||
/* Terminate the string. */
|
||||
buf[n] = '\0';
|
||||
|
||||
char *endp;
|
||||
long int res = strtol (buf, &endp, 10);
|
||||
if (endp != buf && (*endp == '\0' || *endp == '\n'))
|
||||
checked = (res > 0) ? FIPS_ENABLED : FIPS_DISABLED;
|
||||
}
|
||||
}
|
||||
|
||||
if (checked == FIPS_UNTESTED)
|
||||
checked = FIPS_TEST_FAILED;
|
||||
}
|
||||
|
||||
return checked == FIPS_ENABLED;
|
||||
}
|
||||
|
||||
#endif /* _FIPS_PRIVATE_H */
|
@ -1,7 +0,0 @@
|
||||
GLIBC_2.0 crypt F
|
||||
GLIBC_2.0 crypt_r F
|
||||
GLIBC_2.0 encrypt F
|
||||
GLIBC_2.0 encrypt_r F
|
||||
GLIBC_2.0 fcrypt F
|
||||
GLIBC_2.0 setkey F
|
||||
GLIBC_2.0 setkey_r F
|
@ -1,7 +0,0 @@
|
||||
GLIBC_2.0 crypt F
|
||||
GLIBC_2.0 crypt_r F
|
||||
GLIBC_2.0 encrypt F
|
||||
GLIBC_2.0 encrypt_r F
|
||||
GLIBC_2.0 fcrypt F
|
||||
GLIBC_2.0 setkey F
|
||||
GLIBC_2.0 setkey_r F
|
@ -1,7 +0,0 @@
|
||||
GLIBC_2.0 crypt F
|
||||
GLIBC_2.0 crypt_r F
|
||||
GLIBC_2.0 encrypt F
|
||||
GLIBC_2.0 encrypt_r F
|
||||
GLIBC_2.0 fcrypt F
|
||||
GLIBC_2.0 setkey F
|
||||
GLIBC_2.0 setkey_r F
|
@ -1,2 +0,0 @@
|
||||
GLIBC_2.36 crypt F
|
||||
GLIBC_2.36 crypt_r F
|
@ -1,7 +0,0 @@
|
||||
GLIBC_2.4 crypt F
|
||||
GLIBC_2.4 crypt_r F
|
||||
GLIBC_2.4 encrypt F
|
||||
GLIBC_2.4 encrypt_r F
|
||||
GLIBC_2.4 fcrypt F
|
||||
GLIBC_2.4 setkey F
|
||||
GLIBC_2.4 setkey_r F
|
@ -1,7 +0,0 @@
|
||||
GLIBC_2.0 crypt F
|
||||
GLIBC_2.0 crypt_r F
|
||||
GLIBC_2.0 encrypt F
|
||||
GLIBC_2.0 encrypt_r F
|
||||
GLIBC_2.0 fcrypt F
|
||||
GLIBC_2.0 setkey F
|
||||
GLIBC_2.0 setkey_r F
|
@ -1,7 +0,0 @@
|
||||
GLIBC_2.18 crypt F
|
||||
GLIBC_2.18 crypt_r F
|
||||
GLIBC_2.18 encrypt F
|
||||
GLIBC_2.18 encrypt_r F
|
||||
GLIBC_2.18 fcrypt F
|
||||
GLIBC_2.18 setkey F
|
||||
GLIBC_2.18 setkey_r F
|
@ -1,7 +0,0 @@
|
||||
GLIBC_2.18 crypt F
|
||||
GLIBC_2.18 crypt_r F
|
||||
GLIBC_2.18 encrypt F
|
||||
GLIBC_2.18 encrypt_r F
|
||||
GLIBC_2.18 fcrypt F
|
||||
GLIBC_2.18 setkey F
|
||||
GLIBC_2.18 setkey_r F
|
@ -1,7 +0,0 @@
|
||||
GLIBC_2.0 crypt F
|
||||
GLIBC_2.0 crypt_r F
|
||||
GLIBC_2.0 encrypt F
|
||||
GLIBC_2.0 encrypt_r F
|
||||
GLIBC_2.0 fcrypt F
|
||||
GLIBC_2.0 setkey F
|
||||
GLIBC_2.0 setkey_r F
|
@ -1,7 +0,0 @@
|
||||
GLIBC_2.0 crypt F
|
||||
GLIBC_2.0 crypt_r F
|
||||
GLIBC_2.0 encrypt F
|
||||
GLIBC_2.0 encrypt_r F
|
||||
GLIBC_2.0 fcrypt F
|
||||
GLIBC_2.0 setkey F
|
||||
GLIBC_2.0 setkey_r F
|
@ -1,7 +0,0 @@
|
||||
GLIBC_2.21 crypt F
|
||||
GLIBC_2.21 crypt_r F
|
||||
GLIBC_2.21 encrypt F
|
||||
GLIBC_2.21 encrypt_r F
|
||||
GLIBC_2.21 fcrypt F
|
||||
GLIBC_2.21 setkey F
|
||||
GLIBC_2.21 setkey_r F
|
@ -1,2 +0,0 @@
|
||||
GLIBC_2.35 crypt F
|
||||
GLIBC_2.35 crypt_r F
|
@ -1,7 +0,0 @@
|
||||
GLIBC_2.0 crypt F
|
||||
GLIBC_2.0 crypt_r F
|
||||
GLIBC_2.0 encrypt F
|
||||
GLIBC_2.0 encrypt_r F
|
||||
GLIBC_2.0 fcrypt F
|
||||
GLIBC_2.0 setkey F
|
||||
GLIBC_2.0 setkey_r F
|
@ -1,7 +0,0 @@
|
||||
GLIBC_2.3 crypt F
|
||||
GLIBC_2.3 crypt_r F
|
||||
GLIBC_2.3 encrypt F
|
||||
GLIBC_2.3 encrypt_r F
|
||||
GLIBC_2.3 fcrypt F
|
||||
GLIBC_2.3 setkey F
|
||||
GLIBC_2.3 setkey_r F
|
@ -1,7 +0,0 @@
|
||||
GLIBC_2.17 crypt F
|
||||
GLIBC_2.17 crypt_r F
|
||||
GLIBC_2.17 encrypt F
|
||||
GLIBC_2.17 encrypt_r F
|
||||
GLIBC_2.17 fcrypt F
|
||||
GLIBC_2.17 setkey F
|
||||
GLIBC_2.17 setkey_r F
|
@ -1,2 +0,0 @@
|
||||
GLIBC_2.33 crypt F
|
||||
GLIBC_2.33 crypt_r F
|
@ -1,7 +0,0 @@
|
||||
GLIBC_2.27 crypt F
|
||||
GLIBC_2.27 crypt_r F
|
||||
GLIBC_2.27 encrypt F
|
||||
GLIBC_2.27 encrypt_r F
|
||||
GLIBC_2.27 fcrypt F
|
||||
GLIBC_2.27 setkey F
|
||||
GLIBC_2.27 setkey_r F
|
@ -1,7 +0,0 @@
|
||||
GLIBC_2.0 crypt F
|
||||
GLIBC_2.0 crypt_r F
|
||||
GLIBC_2.0 encrypt F
|
||||
GLIBC_2.0 encrypt_r F
|
||||
GLIBC_2.0 fcrypt F
|
||||
GLIBC_2.0 setkey F
|
||||
GLIBC_2.0 setkey_r F
|
@ -1,7 +0,0 @@
|
||||
GLIBC_2.2 crypt F
|
||||
GLIBC_2.2 crypt_r F
|
||||
GLIBC_2.2 encrypt F
|
||||
GLIBC_2.2 encrypt_r F
|
||||
GLIBC_2.2 fcrypt F
|
||||
GLIBC_2.2 setkey F
|
||||
GLIBC_2.2 setkey_r F
|
@ -1,7 +0,0 @@
|
||||
GLIBC_2.0 crypt F
|
||||
GLIBC_2.0 crypt_r F
|
||||
GLIBC_2.0 encrypt F
|
||||
GLIBC_2.0 encrypt_r F
|
||||
GLIBC_2.0 fcrypt F
|
||||
GLIBC_2.0 setkey F
|
||||
GLIBC_2.0 setkey_r F
|
@ -1,7 +0,0 @@
|
||||
GLIBC_2.0 crypt F
|
||||
GLIBC_2.0 crypt_r F
|
||||
GLIBC_2.0 encrypt F
|
||||
GLIBC_2.0 encrypt_r F
|
||||
GLIBC_2.0 fcrypt F
|
||||
GLIBC_2.0 setkey F
|
||||
GLIBC_2.0 setkey_r F
|
@ -1,7 +0,0 @@
|
||||
GLIBC_2.0 crypt F
|
||||
GLIBC_2.0 crypt_r F
|
||||
GLIBC_2.0 encrypt F
|
||||
GLIBC_2.0 encrypt_r F
|
||||
GLIBC_2.0 fcrypt F
|
||||
GLIBC_2.0 setkey F
|
||||
GLIBC_2.0 setkey_r F
|
@ -1,7 +0,0 @@
|
||||
GLIBC_2.0 crypt F
|
||||
GLIBC_2.0 crypt_r F
|
||||
GLIBC_2.0 encrypt F
|
||||
GLIBC_2.0 encrypt_r F
|
||||
GLIBC_2.0 fcrypt F
|
||||
GLIBC_2.0 setkey F
|
||||
GLIBC_2.0 setkey_r F
|
@ -1,7 +0,0 @@
|
||||
GLIBC_2.2.5 crypt F
|
||||
GLIBC_2.2.5 crypt_r F
|
||||
GLIBC_2.2.5 encrypt F
|
||||
GLIBC_2.2.5 encrypt_r F
|
||||
GLIBC_2.2.5 fcrypt F
|
||||
GLIBC_2.2.5 setkey F
|
||||
GLIBC_2.2.5 setkey_r F
|
@ -1,7 +0,0 @@
|
||||
GLIBC_2.16 crypt F
|
||||
GLIBC_2.16 crypt_r F
|
||||
GLIBC_2.16 encrypt F
|
||||
GLIBC_2.16 encrypt_r F
|
||||
GLIBC_2.16 fcrypt F
|
||||
GLIBC_2.16 setkey F
|
||||
GLIBC_2.16 setkey_r F
|
Loading…
Reference in New Issue
Block a user