diff options
author | Lennart Poettering <lennart@poettering.net> | 2019-11-13 23:13:42 +0100 |
---|---|---|
committer | Lennart Poettering <lennart@poettering.net> | 2020-01-15 15:26:27 +0100 |
commit | 42f3b2f97510ab364717154c01a03f5ddd9541a1 (patch) | |
tree | 06849d5179287878f3e53890573fbec197cedd0b /src/shared/libcrypt-util.c | |
parent | 2ee4b118fa72d1dd119dc7b8915307ed86df5b14 (diff) | |
download | systemd-42f3b2f97510ab364717154c01a03f5ddd9541a1.tar.gz |
shared: split out crypt() specific helpers into its own .c/.h in src/shared/
This way we can use libxcrypt specific functionality such as
crypt_gensalt() and thus take benefit of the newer algorithms libxcrypt
implements. (Also adds support for a new env var $SYSTEMD_CRYPT_PREFIX
which may be used to select the hash algorithm to use for libxcrypt.)
Also, let's move the weird crypt.h inclusion into libcrypt.h so that
there's a single place for it.
Diffstat (limited to 'src/shared/libcrypt-util.c')
-rw-r--r-- | src/shared/libcrypt-util.c | 75 |
1 files changed, 75 insertions, 0 deletions
diff --git a/src/shared/libcrypt-util.c b/src/shared/libcrypt-util.c new file mode 100644 index 0000000000..b1a8168030 --- /dev/null +++ b/src/shared/libcrypt-util.c @@ -0,0 +1,75 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ + +#include <errno.h> +#include <stdlib.h> + +#include "alloc-util.h" +#include "libcrypt-util.h" +#include "log.h" +#include "macro.h" +#include "missing_stdlib.h" +#include "random-util.h" +#include "string-util.h" +#include "strv.h" + +int make_salt(char **ret) { + +#ifdef XCRYPT_VERSION_MAJOR + const char *e; + char *salt; + + /* If we have libxcrypt we default to the "preferred method" (i.e. usually yescrypt), and generate it + * with crypt_gensalt_ra(). */ + + e = secure_getenv("SYSTEMD_CRYPT_PREFIX"); + if (!e) + e = crypt_preferred_method(); + + log_debug("Generating salt for hash prefix: %s", e); + + salt = crypt_gensalt_ra(e, 0, NULL, 0); + if (!salt) + return -errno; + + *ret = salt; + return 0; +#else + /* If libxcrypt is not used, we use SHA512 and generate the salt on our own since crypt_gensalt_ra() + * is not available. */ + + static const char table[] = + "abcdefghijklmnopqrstuvwxyz" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "0123456789" + "./"; + + uint8_t raw[16]; + char *salt, *j; + size_t i; + int r; + + /* This is a bit like crypt_gensalt_ra(), but doesn't require libcrypt, and doesn't do anything but + * SHA512, i.e. is legacy-free and minimizes our deps. */ + + assert_cc(sizeof(table) == 64U + 1U); + + /* Insist on the best randomness by setting RANDOM_BLOCK, this is about keeping passwords secret after all. */ + r = genuine_random_bytes(raw, sizeof(raw), RANDOM_BLOCK); + if (r < 0) + return r; + + salt = new(char, 3+sizeof(raw)+1+1); + if (!salt) + return -ENOMEM; + + /* We only bother with SHA512 hashed passwords, the rest is legacy, and we don't do legacy. */ + j = stpcpy(salt, "$6$"); + for (i = 0; i < sizeof(raw); i++) + j[i] = table[raw[i] & 63]; + j[i++] = '$'; + j[i] = 0; + + *ret = salt; + return 0; +#endif +} |