summaryrefslogtreecommitdiff
path: root/lib/crypt/crypt.c
diff options
context:
space:
mode:
authorTom Rini <trini@konsulko.com>2021-07-23 14:50:43 -0400
committerTom Rini <trini@konsulko.com>2021-07-23 14:50:43 -0400
commitedecc15eb9593b94dcd6a5f4f5ea5f134125b6a0 (patch)
tree1c8f414dc7ae2d0e914a706e3dd8aaebb945c946 /lib/crypt/crypt.c
parentf534d93cbf34f1d1762b04eb5680e84bef5e1fe1 (diff)
parent25c8b9f298e46ea6048b5308f7ee207c6461c36a (diff)
Merge branch '2021-07-23-reboot-mode-and-cryptfs-passwd-support'
- A new driver uclass is created to handle the reboot mode control. - Add support for libcrypt-style passwords for autoboot
Diffstat (limited to 'lib/crypt/crypt.c')
-rw-r--r--lib/crypt/crypt.c76
1 files changed, 76 insertions, 0 deletions
diff --git a/lib/crypt/crypt.c b/lib/crypt/crypt.c
new file mode 100644
index 00000000000..247c34b2a9c
--- /dev/null
+++ b/lib/crypt/crypt.c
@@ -0,0 +1,76 @@
+// SPDX-License-Identifier: GPL-2.0+
+/* Copyright (C) 2020 Steffen Jaeckel <jaeckel-floss@eyet-services.de> */
+
+#include <common.h>
+#include <crypt.h>
+#include "crypt-port.h"
+
+typedef int (*crypt_fn)(const char *, size_t, const char *, size_t, uint8_t *,
+ size_t, void *, size_t);
+
+const unsigned char ascii64[65] =
+ "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
+
+static void equals_constant_time(const void *a_, const void *b_, size_t len,
+ int *equal)
+{
+ u8 ret = 0;
+ const u8 *a = a_, *b = b_;
+ int i;
+
+ for (i = 0; i < len; i++)
+ ret |= a[i] ^ b[i];
+
+ ret |= ret >> 4;
+ ret |= ret >> 2;
+ ret |= ret >> 1;
+ ret &= 1;
+
+ *equal = ret ^ 1;
+}
+
+int crypt_compare(const char *should, const char *passphrase, int *equal)
+{
+ u8 output[CRYPT_OUTPUT_SIZE], scratch[ALG_SPECIFIC_SIZE];
+ size_t n;
+ int err;
+ struct {
+ const char *prefix;
+ crypt_fn crypt;
+ } crypt_algos[] = {
+#if defined(CONFIG_CRYPT_PW_SHA256)
+ { "$5$", crypt_sha256crypt_rn_wrapped },
+#endif
+#if defined(CONFIG_CRYPT_PW_SHA512)
+ { "$6$", crypt_sha512crypt_rn_wrapped },
+#endif
+ { NULL, NULL }
+ };
+
+ *equal = 0;
+
+ for (n = 0; n < ARRAY_SIZE(crypt_algos); ++n) {
+ if (!crypt_algos[n].prefix)
+ continue;
+ if (strncmp(should, crypt_algos[n].prefix, 3) == 0)
+ break;
+ }
+
+ if (n >= ARRAY_SIZE(crypt_algos))
+ return -EINVAL;
+
+ err = crypt_algos[n].crypt(passphrase, strlen(passphrase), should, 0,
+ output, sizeof(output), scratch,
+ sizeof(scratch));
+ /* early return on error, nothing really happened inside the crypt() function */
+ if (err)
+ return err;
+
+ equals_constant_time(should, output, strlen((const char *)output),
+ equal);
+
+ memset(scratch, 0, sizeof(scratch));
+ memset(output, 0, sizeof(output));
+
+ return 0;
+}