replace old and ugly crypt implementation

the new version is largely the work of Solar Designer, with minor
changes for integration with musl. compared to the old code, text size
is reduced by about 7k, stack space usage by about 70k, and
performance is greatly improved by avoiding expensive calculation of
constant tables on each run.

this version also adds support for extended des-based password hashes,
which allow for unlimited key (password) length and configurable
iteration counts.

i've also published the interface for crypt_r in a new crypt.h header.
especially since this is not a standard interface, i did not feel
compelled to match the glibc abi for the crypt_data structure. the
glibc structure is way too big to allocate on the stack; in fact it's
so big that the first usage may cause the main thread to exceed its
pre-committed stack size of 128k and thus could cause the program to
crash even on systems with overcommit disabled. the only legitimate
use of crypt_data for crypt_r is to store the hash string to return,
so i've reserved 256 bytes, which should be more than sufficient
(longest known password hashes are ~60 characters, and beyond that is
possibly even exceeding some implementations' passwd file field size
limit).
This commit is contained in:
Rich Felker 2012-06-29 00:56:37 -04:00
parent 9abab94b21
commit cdf51506ce
4 changed files with 1075 additions and 2574 deletions

20
include/crypt.h Normal file
View File

@ -0,0 +1,20 @@
#ifndef _CRYPT_H
#define _CRYPT_H
#ifdef __cplusplus
extern "C" {
#endif
struct crypt_data {
int initialized;
char __buf[256];
};
char *crypt(const char *, const char *);
char *crypt_r(const char *, const char *, struct crypt_data *);
#ifdef __cplusplus
}
#endif
#endif

File diff suppressed because it is too large Load Diff

1024
src/misc/crypt_des.c Normal file

File diff suppressed because it is too large Load Diff

24
src/misc/crypt_r.c Normal file
View File

@ -0,0 +1,24 @@
#include <crypt.h>
#include "libc.h"
struct crypt_data;
char *__crypt_des(const char *, const char *, char *);
char *__crypt_md5(const char *, const char *, char *);
char *__crypt_r(const char *key, const char *salt, struct crypt_data *data)
{
char *output = (char *)data;
#if 0
/* MD5 or SHA? */
if (salt[0] == '$' && salt[1] && salt[2] == '$') {
if (salt[1] == '1')
return __crypt_md5((char *)data, key, salt);
else
return "x";
}
#endif
return __crypt_des(key, salt, output);
}
weak_alias(__crypt_r, crypt_r);