| // 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; | |
| } |