summaryrefslogtreecommitdiff
path: root/crypt-sunmd5.c
AgeCommit message (Collapse)AuthorFilesLines
2019-03-01Move code, documentation, and tests into subdirectories.Zack Weinberg1-314/+0
There are enough files now that it’s getting confusing to have everything at the top level. Create subdirectories ‘lib’, ‘doc’, and ‘test’. Move all of the code linked into libcrypt.a into ‘lib’. Move all the manpages into ‘doc’. Move all of the test programs into ‘test’. There is still only one Makefile at top level. Automake doesn’t make nonrecursive makefiles as easy as it could, but everything that was written in http://aegis.sourceforge.net/auug97.pdf back in 1997(!) is still true. https://www.microsoft.com/en-us/research/wp-content/uploads/2016/03/hadrian.pdf has an interesting counterpoint but I don’t think we’re anywhere near the scale where those problems are relevant.
2019-01-11crypt-sunmd5: Fix the valueof SUNMD5_MAX_ROUNDS.Björn Esser1-1/+1
2018-11-19Move the base64 encoding table to crypt-common.Björn Esser1-4/+0
2018-11-03Remove 'crypt-private.h' and merge it into 'crypt-port.h'.Björn Esser1-1/+0
2018-10-22Use md5 implementation from Alexander Peslyak.Björn Esser1-10/+10
Thus we now have a md5 implementation in the public domain.
2018-08-21Improved handling of out-of-range cost parameters in gensalt.Zack Weinberg1-1/+1
While working on something else, I discovered that crypt_gensalt would divide by zero and crash if passed prefix="$sha1" and rounds<4. This was easy to fix, but while writing tests for similar problems, I discovered that the handling of out-of-range cost parameters was inconsistent among all the hash methods. The behavior is now: - for hashes with a fixed cost parameter (DES/trad, DES/big, NTHASH, MD5/bsd), crypt_gensalt only accepts 0 as the rounds argument. - for hashes with a linear cost parameter (DES/bsdi, MD5/sun, SHA1, SHA256, SHA512), crypt_gensalt accepts 0 or any value in the range [1, ULONG_MAX] and clips it to the actual valid range for the hash function, if necessary. In the case of DES/bsdi, even numbers become odd, as well. - for hashes with an exponential cost parameter (bcrypt), crypt_gensalt only accepts 0 or a value in the actual valid range. - the documented valid range for SHA1 is now [4, 4294967295] instead of [1, 4294967295]. - all of this is tested.
2018-07-26Issue #15: predictable behavior when crypt args are NULL or invalid.Zack Weinberg1-9/+7
This patch introduces the following semantics for NULL or invalid `phrase` and `setting` arguments to the `crypt*` functions: - If `setting` is NULL, all of the functions will fail (in their usual manner) with errno set to EINVAL, regardless of what `phrase` is. (For crypt_r/rn/ra, problems with the `data` argument may be detected first.) - If `setting` is a valid string (in the sense that calling `strlen` on it will not crash the program), but `phrase` is NULL, again all of the functions will fail with errno set to EINVAL. - If both `setting` and `phrase` are non-NULL, and one of them is an _invalid_ string (in the sense that calling `strlen` on it _will_ crash the program), then the program will crash. The crash is guaranteed to happen before any code from a hashing method is executed. - If `phrase` is NULL and `setting` is an invalid string, then it is unspecified whether the function will fail or whether the program will crash, but it will be one of those two things, and, again, no code from a hashing method will be executed. (The actual behavior right now is that the function will fail *unless* `setting` is non-NULL and there are fewer than two readable bytes at that memory location, but I don't want to make that a contract.) I would somewhat prefer the simpler semantics of always crashing on NULL as well as on invalid strings, but there was some sentiment in favor of returning failure for NULL, so I've done this to the maximum extent that is practical. The complicated behavior when `phrase` is NULL but `setting` is invalid is not practical to avoid without breaking an existing guarantee, viz. that a "failure token" never compares equal to the `setting` string, no matter what; I think that guarantee is significantly more important than corner-case behavior like this. Note also that we have __nonnull annotations on all the pointer arguments to all these functions, which means the C compiler unconditionally treats passing NULL as any of those arguments as provoking undefined behavior; I actually had to make crypt-port.h suppress those annotations when building the library, in order to get the tests to pass.
2018-07-13Fix several test failures on x86-64 with -m32.Zack Weinberg1-3/+3
- more fixes for crypt-sunmd5.c when 'unsigned long' and 'unsigned int' are the same - test-getrandom-fallbacks needs to interpose open64 as well as open - test-short-outbuf.c can use %zu instead of %lu to avoid casting - glibc for x86-64/-m32 uses the same symbol versions as glibc/i386 also, libcrypt.minver is now in alphabetical order by host_cpu pattern within each block of architectures with the same minimum symbol version.
2018-07-13crypt-sunmd5.c: Fix possible overflow on 32 bit archesBjörn Esser1-1/+1
2018-07-11Add more tests based on gaps in line coverage.Zack Weinberg1-2/+2
We were not adequately testing invalid-argument error paths within crypt_gensalt, and we were also not adequately testing a variety of corner cases related to non-default round parameters After this change, I believe that all of the non-covered lines fall into three categories: genuinely impossible to hit from the public API (usually these are double-checks for preconditions already verified at a higher level); checks for memory allocation failure; and fallback paths within get_random_bytes. The first two of these, IMHO, are fine to leave as is. It would probably be worth writing a test that exercises the get_random_bytes fallbacks but it'd involve getting one's hands dirty with ELF. I may do it eventually if no one else does. This change makes us pickier about non-default round parameters to $5$ and $6$ hashes; numbers outside the valid range are now rejected, as are numbers with leading zeroes and an explicit request for the default number of rounds. This is in keeping with the observation, in the Passlib documentation, that allowing more than one valid crypt output string for any given (rounds, salt, phrase) triple is asking for trouble. This partially reverts commit a7f9df50cecec46bb8176382faa685ce35ca72be, which accidentally caused us to fail to reject invalid DES setting strings. Because of this, a few lines in crypt-des.c cease to be covered; they are in category 1 (double-checks of preconditions).
2018-07-10Replace crypt-sunmd5.c with BSD-licensed cleanroom reimplementation.Zack Weinberg1-326/+217
This eliminates all CDDL-licensed code from the library, as requested in issue #7 because of GPL incompatibility. The new implementation was based exclusively on the prose description of the algorithm in the Passlib v1.7.1 documentation, which should be adequately arms-length for copyright purposes. (N.B. the lengthy quotation from _Hamlet_ is used as input to MD5, so it must remain byte-for-byte identical to achieve interoperability with the original; also, the play itself is in the public domain.) The new implementation is also fully deterministic (that is, its gensalt procedure draws randomness only from its rbytes argument) and does not call malloc.
2018-07-09Make salt validation pickier.Zack Weinberg1-34/+38
This started out as a patch to fold together test-crypt-badsalt.c and test-crypt-nonnull.c (which were almost the same program) and extend their testing from DES to all of the supported hashes. That revealed that many of the supported hash functions do not validate the contents of their salt strings very carefully. This patch has a low but nonzero backward compatibility risk, because now we reject certain calls to crypt*() that we would previously have accepted. In particular, setting strings of the form $5$xxxxxxx*xxxxxxxx$ where x stands for any "itoa64" character and * for any non-"itoa64" character, would formerly be accepted but are now rejected. Some of the hash algorithms that were lenient about the contents of the salt would echo back the salt verbatim, and others would convert it to the base64 alphabet somehow. I think it's unlikely that this occurs in real password files but I don't have a lot of data to base that on.
2018-07-04Make it possible to disable individual hashes at configure time.Zack Weinberg1-0/+5
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.
2018-05-16crypt-sunmd5: Fix 'Werror=format-truncation=' (Fixes #2)Björn Esser1-1/+1
2017-10-26<string.h> gets imported through <crypt-port.h> nowBjörn Esser1-1/+0
2017-10-24crypt-sunmd5: Fix -Werror=sign-compareBjörn Esser1-1/+1
2017-10-24Add support for SUNMD5 ($md5[,rounds=%u]$salt$) from (Open)SolarisBjörn Esser1-0/+422
This algorithm was developed by Alec Muffett for Solaris, as a replacement for the aging des_crypt. It was introduced in Solaris 9u2. While based on the MD5 message digest, it has very little at all in common with the md5_crypt algorithm. It supports 32 bit variable rounds and an 8 character salt. The gensalt() function for this algorithm is modified to always return a new setting with a sane, but random, default amount of rounds for the corresponding crypt() function. Besides this it follows the original implementation from (Open)Solaris. Its use is not recommended, as today it is easily broken.