Age | Commit message (Collapse) | Author | Files | Lines |
|
Most of the hashing methods had their own test-crypt-xxx.c program
that ran a short sequence of “known answer” tests:
crypt(phrase, salt) = expected for fixed values of phrase, salt, and
expected. The code involved was very repetitive, taken as a whole,
and many of the programs were not very thorough.
Consolidate all of these programs into a single program,
test-crypt-kat.c (kat = known answer test); test all the hashing
methods against the union of all the old programs’ input phrases;
test all four supported crypt* APIs for each case; test that for
each hash <- crypt(phrase, salt), hash == crypt(phrase, hash) as well.
The known answers are generated from a table of combinations, using
a Python program that uses an independent implementation of all the
hashing methods (passlib <https://passlib.readthedocs.io>, forced
to use its internal pure-Python reference implementations instead of
C accelerators that may have too much code in common with libxcrypt’s
implementations). This program is very slow, and passlib is not part
of the Python standard library, and we don’t currently depend on
Python during the build at all, so it is not run during a normal
build. You have to run it by hand if you change it, and check in the
output (test-crypt-kat.inc).
passlib currently can’t calculate yescrypt or gost-yescrypt hashes,
so we don’t have known answers to compare against for those, but we
do still crank all of the passphrases through the algorithm and make
sure the hash == crypt(phrase, hash) invariant holds for them.
test-crypt-gost-yescrypt.c performs some extra, GY-specific tests
as well as known-answer black box tests; that part of it is preserved.
It is necessary to increase the timeout for running the test suite
under valgrind on Travis, from 10 minutes to 60 minutes. This can’t
be done in the documented manner because the “command” you’re supposed
to use, travis_wait, is a bash function available in the parent script
but not in our .travis_script.sh; it is necessary to replicate that
logic in our script.
|
|
|
|
|
|
There are now separate INCLUDE_ macros for all four variants of
bcrypt. --enable-hashes=bcrypt enables only the preferred $2b$
variant. The $2x$ variant, which has a bug that makes collisions
easy to find for some passphrases, is no longer included in the STRONG
group, and the OS compatibility groups have been adjusted so that each
includes only the variants historically available on the OS we’re
being compatible with.
As a side-effect, this makes the “optional suffix on the name of the
gensalt_fn” column of hashes.lst unnecessary, and allows
simplification of gen-hashes.awk.
The bcrypt-related tests have not actually changed, but many entries
in test case arrays were rearranged to minimize the number of
additional ifdefs needed.
|
|
Since we have a guaranteed way to make sure all generated header
files are always present before any object file is compiled, we
can drop crypt-base.h and include the local version of crypt.h
through crypt-port.h.
|
|
When this option is given, crypt and crypt_r will return NULL on
failure, instead of a special "failure token" string that isn't the
hash of any passphrase. This was the historical behavior of glibc,
FreeBSD libc, and several other implementations.
|
|
The table of supported hash algorithms now lives in hashes.lst.
The configure script accepts an option --enable-hashes which takes a
comma-separated list of hash algorithms to include. We generate a
header that defines INCLUDE_ macros for each hash that is enabled,
and all of the code is conditionalized appropriately.
The default is --enable-hashes=all. --enable-hashes=strong is the
equivalent of the old --disable-weak-hashes. You could even do
--enable-hashes=bcrypt,des to get a binary-compatible libcrypt.so.1
that still supports almost nothing other than bcrypt.
|
|
|
|
|
|
|
|
|
|
Stop including crypt-symbols.h implicitly. It's a little too much
_spukhafte Fernwirkung_ for my taste, and it makes Emacs have trouble
parsing the compiler's error messages.
Also, rename crypt-symbols.h to crypt-port.h as this is more
consistent with its current function, and have it include stdbool.h,
stddef.h, and stdint.h for everyone; have configure bomb out if the
C99 headers we use are not available; and normalize the order of
inclusion in all files.
The value of CPPFLAGS passed to test scripts now includes every last
one of Automake's CPPFLAGS-fragment variables.
|
|
This allows us to cleanly use <sys/cdefs.h>'s definitions of
__BEGIN_DECLS, __END_DECLS, __THROW, and __nonnull, with fallbacks if
the header doesn't exist or doesn't provide the expected set of
declarations.
* crypt.h: Rename to crypt-base.h. Replace header and trailer
with marker comments.
* crypt-private.h: Include crypt-base.h and stddef.h, not crypt.h.
* crypt-symbols.h: Based on configure results, conditionally
include sys/cdefs.h and define __THROW and __nonnull.
* test-crypt-bcrypt.c, test-crypt-des.c, test-crypt-md5.c
* test-crypt-sha256.c, test-crypt-sha512.c, test-gensalt.c
* test-des-obsolete.c: Include crypt-base.h, not crypt.h.
* crypt-obsolete.h: Include crypt-base.h, not crypt.h.
Remove extern "C" wrapper and all uses of __THROW; this header is
not installed and never used from C++.
* gen-crypt-h.awk: New build script.
* Makefile.am (crypt.h): Generate from crypt-base.h and config.h,
using gen-crypt-h.awk.
* configure.ac: Add checks for sys/cdefs.h and the macros we
want from it.
(AC_CONFIG_SRCDIR): Key off crypt.c instead.
|
|
Move as much as possible of the sensitive intermediate data used by
bcrypt into a buffer allocated by the caller. This is finickier
than for the other hashes because the bcrypt code is more complicated;
in particular, because BF_crypt no longer takes a simple pointer to
where its output will be written, additional shuffling-around of data
inside crypt_bcrypt_rn is necessary to accommodate the self-test.
As a consequence of this change, it no longer makes sense for
test-crypt-bcrypt to pass "output" buffers of varying sizes to
crypt_rn.
|
|
This project is not big enough that it's a problem to have all the
source files at the top level, and this eliminates recursion in
'make all'.
|