summaryrefslogtreecommitdiff
path: root/lib/crypt/crypt.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/crypt/crypt.c')
-rw-r--r--lib/crypt/crypt.c73
1 files changed, 73 insertions, 0 deletions
diff --git a/lib/crypt/crypt.c b/lib/crypt/crypt.c
new file mode 100644
index 0000000000..4ec6079768
--- /dev/null
+++ b/lib/crypt/crypt.c
@@ -0,0 +1,73 @@
+// 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 void (*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;
+}
+
+void crypt_compare(const char *should, const char *passphrase, int *equal)
+{
+ u8 output[CRYPT_OUTPUT_SIZE], scratch[ALG_SPECIFIC_SIZE];
+ size_t n;
+ struct {
+ const char *prefix;
+ crypt_fn crypt;
+ } crypt_algos[] = {
+#if defined(CONFIG_CRYPT_PW_SHA256)
+ { "$5$", crypt_sha256crypt_rn },
+#endif
+#if defined(CONFIG_CRYPT_PW_SHA512)
+ { "$6$", crypt_sha512crypt_rn },
+#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;
+
+ 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 (errno == ERANGE || errno == EINVAL)
+ return;
+
+ equals_constant_time(should, output, strlen((const char *)output),
+ equal);
+
+ memset(scratch, 0, sizeof(scratch));
+ memset(output, 0, sizeof(output));
+}