diff options
author | Steffen Jaeckel <jaeckel-floss@eyet-services.de> | 2021-07-08 15:57:33 +0200 |
---|---|---|
committer | Tom Rini <trini@konsulko.com> | 2021-07-23 13:36:14 -0400 |
commit | 26dd9936574864155b989b9f14319ca2779f0598 (patch) | |
tree | 41fe3ce1471a80916ea6cc91d8a6e7c956c8e2d9 /lib/crypt/crypt.c | |
parent | c74675bd904b6ce9d5820a80f27793c0583fd54c (diff) |
lib: add crypt subsystem
Add the basic functionality required to support the standard crypt
format.
The files crypt-sha256.c and crypt-sha512.c originate from libxcrypt and
their formatting is therefor retained.
The integration is done via a crypt_compare() function in crypt.c.
```
libxcrypt $ git describe --long --always --all
tags/v4.4.17-0-g6b110bc
```
Signed-off-by: Steffen Jaeckel <jaeckel-floss@eyet-services.de>
Reviewed-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Heiko Schocher <hs@denx.de>
Diffstat (limited to 'lib/crypt/crypt.c')
-rw-r--r-- | lib/crypt/crypt.c | 73 |
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)); +} |