[git commit] libbb/yescrypt: reduce the number of function parameters
Denys Vlasenko
vda.linux at googlemail.com
Sun Jul 6 04:05:08 UTC 2025
commit: https://git.busybox.net/busybox/commit/?id=736589f877be576274503fdcd066aff4b5c12949
branch: https://git.busybox.net/busybox/commit/?id=refs/heads/master
function old new delta
yescrypt_kdf32_body - 1077 +1077
static.smix 739 753 +14
yescrypt_init_local 34 - -34
yes_crypt 87 50 -37
yescrypt_free_local 49 - -49
yescrypt_r 1288 1217 -71
static.yescrypt_kdf_body 1166 - -1166
------------------------------------------------------------------------------
(add/remove: 1/3 grow/shrink: 1/2 up/down: 1091/-1357) Total: -266 bytes
Signed-off-by: Denys Vlasenko <vda.linux at googlemail.com>
---
libbb/yescrypt/alg-yescrypt-common.c | 74 ++++++++++-------------
libbb/yescrypt/alg-yescrypt-kdf.c | 104 ++++++++++++++++-----------------
libbb/yescrypt/alg-yescrypt-platform.c | 37 +++++-------
libbb/yescrypt/alg-yescrypt.h | 87 ++++++++++++---------------
4 files changed, 136 insertions(+), 166 deletions(-)
diff --git a/libbb/yescrypt/alg-yescrypt-common.c b/libbb/yescrypt/alg-yescrypt-common.c
index 8d75fa051..ebc531b08 100644
--- a/libbb/yescrypt/alg-yescrypt-common.c
+++ b/libbb/yescrypt/alg-yescrypt-common.c
@@ -179,62 +179,64 @@ fail:
}
uint8_t *yescrypt_r(
- yescrypt_local_t *local,
const uint8_t *passwd, size_t passwdlen,
const uint8_t *setting,
uint8_t *buf, size_t buflen)
{
- unsigned char saltbin[64], hashbin[32];
+ yescrypt_ctx_t yctx[1];
+ unsigned char hashbin32[32];
const uint8_t *src, *saltstr, *saltend;
uint8_t *dst;
- size_t need, prefixlen, saltstrlen, saltlen;
+ size_t need, prefixlen, saltstrlen;
uint32_t flavor, N_log2;
- yescrypt_params_t params = { .p = 1 };
+
+ memset(yctx, 0, sizeof(yctx));
+ yctx->param.p = 1;
/* we assume setting starts with "$y$" (caller must ensure this) */
src = setting + 3;
src = decode64_uint32(&flavor, src, 0);
//if (!src)
- // return NULL;
+ // goto fail;
if (flavor < YESCRYPT_RW) {
- params.flags = flavor;
+ yctx->param.flags = flavor;
} else if (flavor <= YESCRYPT_RW + (YESCRYPT_RW_FLAVOR_MASK >> 2)) {
- params.flags = YESCRYPT_RW + ((flavor - YESCRYPT_RW) << 2);
+ yctx->param.flags = YESCRYPT_RW + ((flavor - YESCRYPT_RW) << 2);
} else {
- return NULL;
+ goto fail;
}
src = decode64_uint32(&N_log2, src, 1);
if (/*!src ||*/ N_log2 > 63)
- return NULL;
- params.N = (uint64_t)1 << N_log2;
+ goto fail;
+ yctx->param.N = (uint64_t)1 << N_log2;
- src = decode64_uint32(¶ms.r, src, 1);
+ src = decode64_uint32(&yctx->param.r, src, 1);
if (!src)
- return NULL;
+ goto fail;
if (*src != '$') {
uint32_t have;
src = decode64_uint32(&have, src, 1);
if (have & 1)
- src = decode64_uint32(¶ms.p, src, 2);
+ src = decode64_uint32(&yctx->param.p, src, 2);
if (have & 2)
- src = decode64_uint32(¶ms.t, src, 1);
+ src = decode64_uint32(&yctx->param.t, src, 1);
if (have & 4)
- src = decode64_uint32(¶ms.g, src, 1);
+ src = decode64_uint32(&yctx->param.g, src, 1);
if (have & 8) {
uint32_t NROM_log2;
src = decode64_uint32(&NROM_log2, src, 1);
if (/*!src ||*/ NROM_log2 > 63)
- return NULL;
- params.NROM = (uint64_t)1 << NROM_log2;
+ goto fail;
+ yctx->param.NROM = (uint64_t)1 << NROM_log2;
}
}
if (!src)
- return NULL;
+ goto fail;
if (*src != '$')
- return NULL;
+ goto fail;
saltstr = src + 1;
src = (uint8_t *)strchrnul((char *)saltstr, '$');
@@ -242,8 +244,8 @@ uint8_t *yescrypt_r(
saltstrlen = src - saltstr; /* len("<salt>") */
/* src points to end of salt ('$' or NUL byte), won't be used past this point */
- saltlen = sizeof(saltbin);
- saltend = decode64(saltbin, &saltlen, saltstr, saltstrlen);
+ yctx->saltlen = sizeof(yctx->salt);
+ saltend = decode64(yctx->salt, &yctx->saltlen, saltstr, saltstrlen);
if (saltend != saltstr + saltstrlen)
goto fail; /* saltbin[] is too small, or bad char during decode */
@@ -251,34 +253,22 @@ uint8_t *yescrypt_r(
if (need > buflen || need < prefixlen)
goto fail;
- if (yescrypt_kdf(local, passwd, passwdlen, saltbin, saltlen,
- ¶ms, hashbin, sizeof(hashbin)))
+ if (yescrypt_kdf32(yctx, passwd, passwdlen, hashbin32))
goto fail;
dst = mempcpy(buf, setting, prefixlen);
*dst++ = '$';
- dst = encode64(dst, buflen - (dst - buf), hashbin, sizeof(hashbin));
- explicit_bzero(hashbin, sizeof(hashbin));
+ dst = encode64(dst, buflen - (dst - buf), hashbin32, sizeof(hashbin32));
if (!dst || dst >= buf + buflen)
- return NULL;
+ goto fail;
*dst = 0; /* NUL termination */
-
+ ret:
+ free_region(yctx->local);
+ explicit_bzero(yctx, sizeof(yctx));
+ explicit_bzero(hashbin32, sizeof(hashbin32));
return buf;
-
fail:
- explicit_bzero(saltbin, sizeof(saltbin));
- explicit_bzero(hashbin, sizeof(hashbin));
- return NULL;
-}
-
-int yescrypt_init_local(yescrypt_local_t *local)
-{
- init_region(local);
- return 0;
-}
-
-int yescrypt_free_local(yescrypt_local_t *local)
-{
- return free_region(local);
+ buf = NULL;
+ goto ret;
}
diff --git a/libbb/yescrypt/alg-yescrypt-kdf.c b/libbb/yescrypt/alg-yescrypt-kdf.c
index 3ee9bfa43..2b84564b9 100644
--- a/libbb/yescrypt/alg-yescrypt-kdf.c
+++ b/libbb/yescrypt/alg-yescrypt-kdf.c
@@ -798,29 +798,27 @@ static void smix(uint8_t *B, size_t r, uint32_t N, uint32_t p, uint32_t t,
* This optimized implementation currently limits N to the range from 4 to
* 2^31, but other implementations might not.
*/
-static int yescrypt_kdf_body(
- yescrypt_local_t *local,
- const uint8_t *passwd, size_t passwdlen,
- const uint8_t *salt, size_t saltlen,
- yescrypt_flags_t flags, uint64_t N, uint32_t r, uint32_t p, uint32_t t,
- uint64_t NROM,
- uint8_t *buf, size_t buflen)
+static int yescrypt_kdf32_body(
+ yescrypt_ctx_t *yctx,
+ const uint8_t *passwd, size_t passwdlen,
+ yescrypt_flags_t flags, uint64_t N, uint32_t t,
+ uint8_t *buf32)
{
const salsa20_blk_t *VROM;
size_t B_size, V_size, XY_size, need;
uint8_t *B, *S;
salsa20_blk_t *V, *XY;
uint8_t sha256[32];
- uint8_t dk[sizeof(sha256)], *dkp = buf;
+ uint8_t dk[sizeof(sha256)], *dkp = buf32;
/* Sanity-check parameters */
switch (flags & YESCRYPT_MODE_MASK) {
case 0: /* classic scrypt - can't have anything non-standard */
- if (flags || t || NROM)
+ if (flags || t || yctx->param.NROM)
goto out_EINVAL;
break;
case YESCRYPT_WORM:
- if (flags != YESCRYPT_WORM || NROM)
+ if (flags != YESCRYPT_WORM || yctx->param.NROM)
goto out_EINVAL;
break;
case YESCRYPT_RW:
@@ -842,6 +840,9 @@ static int yescrypt_kdf_body(
if (buflen > (((uint64_t)1 << 32) - 1) * 32)
goto out_EINVAL;
#endif
+ {
+ const uint32_t r = yctx->param.r;
+ const uint32_t p = yctx->param.p;
if ((uint64_t)r * (uint64_t)p >= 1 << 30)
goto out_EINVAL;
if (N > UINT32_MAX)
@@ -862,7 +863,7 @@ static int yescrypt_kdf_body(
}
VROM = NULL;
- if (NROM)
+ if (yctx->param.NROM)
goto out_EINVAL;
/* Allocate memory */
@@ -883,15 +884,14 @@ static int yescrypt_kdf_body(
if (need < S_size)
goto out_EINVAL;
}
- if (local->aligned_size < need) {
- if (free_region(local))
- return -1;
- if (!alloc_region(local, need))
- return -1;
+ if (yctx->local->aligned_size < need) {
+ free_region(yctx->local);
+ alloc_region(yctx->local, need);
+ dbg("allocated local:%u", need);
}
if (flags & YESCRYPT_ALLOC_ONLY)
return -3; /* expected "failure" */
- B = (uint8_t *)local->aligned;
+ B = (uint8_t *)yctx->local->aligned;
V = (salsa20_blk_t *)((uint8_t *)B + B_size);
XY = (salsa20_blk_t *)((uint8_t *)V + V_size);
S = NULL;
@@ -906,28 +906,28 @@ static int yescrypt_kdf_body(
passwdlen = sizeof(sha256);
}
- PBKDF2_SHA256(passwd, passwdlen, salt, saltlen, 1, B, B_size);
+ PBKDF2_SHA256(passwd, passwdlen, yctx->salt, yctx->saltlen, 1, B, B_size);
if (flags)
memcpy(sha256, B, sizeof(sha256));
if (p == 1 || (flags & YESCRYPT_RW)) {
- smix(B, r, N, p, t, flags, V, NROM, VROM, XY, S, sha256);
+ smix(B, r, N, p, t, flags, V, yctx->param.NROM, VROM, XY, S, sha256);
} else {
uint32_t i;
for (i = 0; i < p; i++) {
smix(&B[(size_t)128 * r * i], r, N, 1, t, flags, V,
- NROM, VROM, XY, NULL, NULL);
+ yctx->param.NROM, VROM, XY, NULL, NULL);
}
}
- dkp = buf;
- if (flags && buflen < sizeof(dk)) {
+ dkp = buf32;
+ if (flags && /*buflen:*/32 < sizeof(dk)) {
PBKDF2_SHA256(passwd, passwdlen, B, B_size, 1, dk, sizeof(dk));
dkp = dk;
}
- PBKDF2_SHA256(passwd, passwdlen, B, B_size, 1, buf, buflen);
+ PBKDF2_SHA256(passwd, passwdlen, B, B_size, 1, buf32, /*buflen:*/32);
/*
* Except when computing classic scrypt, allow all computation so far
@@ -941,11 +941,11 @@ static int yescrypt_kdf_body(
HMAC_SHA256_Buf(dkp, sizeof(dk), "Client Key", 10, sha256);
/* Compute StoredKey */
{
- size_t clen = buflen;
+ size_t clen = /*buflen:*/32;
if (clen > sizeof(dk))
clen = sizeof(dk);
SHA256_Buf(sha256, sizeof(sha256), dk);
- memcpy(buf, dk, clen);
+ memcpy(buf32, dk, clen);
}
}
@@ -960,6 +960,7 @@ static int yescrypt_kdf_body(
out_EINVAL:
errno = EINVAL;
return -1;
+ }
}
/**
@@ -970,21 +971,18 @@ out_EINVAL:
* the addition of g, which controls hash upgrades (0 for no upgrades so far).
*/
static
-int yescrypt_kdf(
- yescrypt_local_t *local,
+int yescrypt_kdf32(
+ yescrypt_ctx_t *yctx,
const uint8_t *passwd, size_t passwdlen,
- const uint8_t *salt, size_t saltlen,
- const yescrypt_params_t *params,
- uint8_t *buf, size_t buflen)
+ uint8_t *buf32)
{
- yescrypt_flags_t flags = params->flags;
- uint64_t N = params->N;
- uint32_t r = params->r;
- uint32_t p = params->p;
- uint32_t t = params->t;
- uint32_t g = params->g;
- uint64_t NROM = params->NROM;
- uint8_t dk[32];
+ yescrypt_flags_t flags = yctx->param.flags;
+ uint64_t N = yctx->param.N;
+ uint32_t r = yctx->param.r;
+ uint32_t p = yctx->param.p;
+ uint32_t t = yctx->param.t;
+ uint32_t g = yctx->param.g;
+ uint8_t dk32[32];
int retval;
/* Support for hash upgrades has been temporarily removed */
@@ -998,30 +996,30 @@ int yescrypt_kdf(
&& N / p >= 0x100
&& N / p * r >= 0x20000
) {
- if (yescrypt_kdf_body(local,
- passwd, passwdlen, salt, saltlen,
- flags | YESCRYPT_ALLOC_ONLY, N, r, p, t, NROM,
- buf, buflen) != -3
+ if (yescrypt_kdf32_body(yctx,
+ passwd, passwdlen,
+ flags | YESCRYPT_ALLOC_ONLY, N, t,
+ buf32) != -3
) {
errno = EINVAL;
return -1;
}
- retval = yescrypt_kdf_body(local,
- passwd, passwdlen, salt, saltlen,
- flags | YESCRYPT_PREHASH, N >> 6, r, p, 0, NROM,
- dk, sizeof(dk));
+ retval = yescrypt_kdf32_body(yctx,
+ passwd, passwdlen,
+ flags | YESCRYPT_PREHASH, N >> 6, 0,
+ dk32);
if (retval)
return retval;
- passwd = dk;
- passwdlen = sizeof(dk);
+ passwd = dk32;
+ passwdlen = sizeof(dk32);
}
- retval = yescrypt_kdf_body(local,
- passwd, passwdlen, salt, saltlen,
- flags, N, r, p, t, NROM, buf, buflen);
+ retval = yescrypt_kdf32_body(yctx,
+ passwd, passwdlen,
+ flags, N, t, buf32);
#ifndef SKIP_MEMZERO
- if (passwd == dk)
- explicit_bzero(dk, sizeof(dk));
+ if (passwd == dk32)
+ explicit_bzero(dk32, sizeof(dk32));
#endif
return retval;
}
diff --git a/libbb/yescrypt/alg-yescrypt-platform.c b/libbb/yescrypt/alg-yescrypt-platform.c
index 09809c4b0..41627df2d 100644
--- a/libbb/yescrypt/alg-yescrypt-platform.c
+++ b/libbb/yescrypt/alg-yescrypt-platform.c
@@ -18,7 +18,7 @@
* SUCH DAMAGE.
*/
-static void *alloc_region(yescrypt_region_t *region, size_t size)
+static void alloc_region(yescrypt_region_t *region, size_t size)
{
size_t base_size = size;
uint8_t *base, *aligned;
@@ -27,39 +27,32 @@ static void *alloc_region(yescrypt_region_t *region, size_t size)
//(if defined(MAP_HUGETLB) && defined(MAP_HUGE_2MB)) using 2MB pages
#else /* mmap not available */
base = aligned = NULL;
- if (size + 63 < size) {
- errno = ENOMEM;
- } else {
- base = malloc(size + 63);
- if (base) {
- aligned = base + 63;
- aligned -= (uintptr_t)aligned & 63;
- }
+ if (size + 63 < size)
+ bb_die_memory_exhausted();
+ base = malloc(size + 63);
+ if (base) {
+ aligned = base + 63;
+ aligned -= (uintptr_t)aligned & 63;
}
#endif
region->base = base;
region->aligned = aligned;
region->base_size = base ? base_size : 0;
region->aligned_size = base ? size : 0;
- return aligned;
}
-static inline void init_region(yescrypt_region_t *region)
+static void free_region(yescrypt_region_t *region)
{
- region->base = region->aligned = NULL;
- region->base_size = region->aligned_size = 0;
-}
-
-static int free_region(yescrypt_region_t *region)
-{
- if (region->base) {
#if 0 //def MAP_ANON
+ if (region->base) {
if (munmap(region->base, region->base_size))
return -1;
+ }
#else
- free(region->base);
+ free(region->base);
#endif
- }
- init_region(region);
- return 0;
+ region->base = NULL;
+ region->aligned = NULL;
+ region->base_size = 0;
+ region->aligned_size = 0;
}
diff --git a/libbb/yescrypt/alg-yescrypt.h b/libbb/yescrypt/alg-yescrypt.h
index 7f2b7f471..cac1959f9 100644
--- a/libbb/yescrypt/alg-yescrypt.h
+++ b/libbb/yescrypt/alg-yescrypt.h
@@ -27,21 +27,13 @@
* This file was originally written by Colin Percival as part of the Tarsnap
* online backup system.
*/
-
-/**
- * Internal type used by the memory allocator. Please do not use it directly.
- * Use yescrypt_shared_t and yescrypt_local_t as appropriate instead, since
- * they might differ from each other in a future version.
- */
-typedef struct {
- void *base, *aligned;
- size_t base_size, aligned_size;
-} yescrypt_region_t;
-
-/**
- * Types for shared (ROM) and thread-local (RAM) data structures.
- */
-typedef yescrypt_region_t yescrypt_local_t;
+#ifdef YESCRYPT_INTERNAL
+# if 1
+# define dbg(...) ((void)0)
+# else
+# define dbg(...) bb_error_msg(__VA_ARGS__)
+# endif
+#endif
/**
* Two 64-bit tags placed 48 bytes to the end of a ROM in host byte endianness
@@ -100,6 +92,16 @@ typedef uint32_t yescrypt_flags_t;
YESCRYPT_ALLOC_ONLY | YESCRYPT_PREHASH)
#endif
+/**
+ * Internal type used by the memory allocator. Please do not use it directly.
+ * Use yescrypt_shared_t and yescrypt_local_t as appropriate instead, since
+ * they might differ from each other in a future version.
+ */
+typedef struct {
+ void *base, *aligned;
+ size_t base_size, aligned_size;
+} yescrypt_region_t;
+
/**
* yescrypt parameters combined into one struct. N, r, p are the same as in
* classic scrypt, except that the meaning of p changes when YESCRYPT_RW is
@@ -112,6 +114,19 @@ typedef struct {
uint64_t NROM;
} yescrypt_params_t;
+typedef struct {
+ yescrypt_params_t param;
+
+ /* salt in binary form */
+ /* stored here to cut down on the amont of function paramaters */
+ unsigned char salt[64];
+ size_t saltlen;
+
+ /* used by the memory allocator */
+ //yescrypt_region_t shared[1];
+ yescrypt_region_t local[1];
+} yescrypt_ctx_t;
+
/* How many chars base-64 encoded bytes require? */
#define BYTES2CHARS(bytes) ((((bytes) * 8) + 5) / 6)
/* The /etc/passwd-style hash is "<prefix>$<hash><NUL>" */
@@ -125,28 +140,6 @@ typedef struct {
#define HASH_SIZE 32
#define HASH_LEN BYTES2CHARS(HASH_SIZE)
-/**
- * yescrypt_init_local(local):
- * Initialize the thread-local (RAM) data structure. Actual memory allocation
- * is currently fully postponed until a call to yescrypt_kdf() or yescrypt_r().
- *
- * Return 0 on success; or -1 on error.
- *
- * MT-safe as long as local is local to the thread.
- */
-extern int yescrypt_init_local(yescrypt_local_t *local);
-
-/**
- * yescrypt_free_local(local):
- * Free memory that may have been allocated for an initialized thread-local
- * (RAM) data structure.
- *
- * Return 0 on success; or -1 on error.
- *
- * MT-safe as long as local is local to the thread.
- */
-extern int yescrypt_free_local(yescrypt_local_t *local);
-
/**
* yescrypt_kdf(shared, local, passwd, passwdlen, salt, saltlen, params,
* buf, buflen):
@@ -180,17 +173,13 @@ extern int yescrypt_free_local(yescrypt_local_t *local);
* and shared->aligned_size fields may optionally be set by the caller directly
* (e.g., to a mapped SysV shm segment), without using yescrypt_init_shared().
*
- * local must be initialized with yescrypt_init_local().
- *
* MT-safe as long as local and buf are local to the thread.
*/
#ifdef YESCRYPT_INTERNAL
-static int yescrypt_kdf(
- yescrypt_local_t *local,
- const uint8_t *passwd, size_t passwdlen,
- const uint8_t *salt, size_t saltlen,
- const yescrypt_params_t *params,
- uint8_t *buf, size_t buflen);
+static int yescrypt_kdf32(
+ yescrypt_ctx_t *yctx,
+ const uint8_t *passwd, size_t passwdlen,
+ uint8_t *buf32);
#endif
/**
@@ -209,7 +198,7 @@ static int yescrypt_kdf(
* MT-safe as long as local and buf are local to the thread.
*/
extern uint8_t *yescrypt_r(
- yescrypt_local_t *local,
- const uint8_t *passwd, size_t passwdlen,
- const uint8_t *setting,
- uint8_t *buf, size_t buflen);
+ const uint8_t *passwd, size_t passwdlen,
+ const uint8_t *setting,
+ uint8_t *buf, size_t buflen
+);
More information about the busybox-cvs
mailing list