diff options
Diffstat (limited to 'lib/crypt/crypt.c')
-rw-r--r-- | lib/crypt/crypt.c | 76 |
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; +} |