summaryrefslogtreecommitdiff
path: root/src/shared/libcrypt-util.c
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2019-11-13 23:13:42 +0100
committerLennart Poettering <lennart@poettering.net>2020-01-15 15:26:27 +0100
commit42f3b2f97510ab364717154c01a03f5ddd9541a1 (patch)
tree06849d5179287878f3e53890573fbec197cedd0b /src/shared/libcrypt-util.c
parent2ee4b118fa72d1dd119dc7b8915307ed86df5b14 (diff)
downloadsystemd-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.c75
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
+}