[git commit] libbb/yescrypt: use common ACSII char-to-64 conversion code

Denys Vlasenko vda.linux at googlemail.com
Sun Jul 6 17:08:57 UTC 2025


commit: https://git.busybox.net/busybox/commit/?id=23b5527f5c400a300c56afa36a6a5abaa81adbb7
branch: https://git.busybox.net/busybox/commit/?id=refs/heads/master

function                                             old     new   delta
a2i64                                                  -      46     +46
yescrypt_r                                          1215    1235     +20
decode64_uint32                                      167     177     +10
atoi64                                                25       -     -25
ascii_to_bin                                          53       -     -53
static.atoi64_partial                                 77       -     -77
------------------------------------------------------------------------------
(add/remove: 1/3 grow/shrink: 2/0 up/down: 76/-155)           Total: -79 bytes

Signed-off-by: Denys Vlasenko <vda.linux at googlemail.com>
---
 include/libbb.h                      |  1 +
 libbb/pw_encrypt.c                   | 25 +++++++++++++++++++++++++
 libbb/pw_encrypt_des.c               | 23 ++---------------------
 libbb/yescrypt/alg-yescrypt-common.c | 22 +++-------------------
 4 files changed, 31 insertions(+), 40 deletions(-)

diff --git a/include/libbb.h b/include/libbb.h
index e88499a80..1c23d2f66 100644
--- a/include/libbb.h
+++ b/include/libbb.h
@@ -2190,6 +2190,7 @@ char *decode_base32(char *dst, const char **pp_src) FAST_FUNC;
 void read_base64(FILE *src_stream, FILE *dst_stream, int flags) FAST_FUNC;
 
 int FAST_FUNC i2a64(int i);
+int FAST_FUNC a2i64(char c);
 
 typedef struct md5_ctx_t {
 	uint8_t wbuffer[64]; /* always correctly aligned for uint64_t */
diff --git a/libbb/pw_encrypt.c b/libbb/pw_encrypt.c
index 71f7731fd..af84606bf 100644
--- a/libbb/pw_encrypt.c
+++ b/libbb/pw_encrypt.c
@@ -30,6 +30,31 @@ int FAST_FUNC i2a64(int i)
 	return ('a' - 38 + i);
 }
 
+/* Returns >=64 for invalid chars */
+int FAST_FUNC a2i64(char c)
+{
+	unsigned char ch = c;
+	if (ch >= 'a')
+		/* "a..z" to 38..63 */
+		/* anything after "z": positive int >= 64 */
+		return (ch - 'a' + 38);
+
+	if (ch > 'Z')
+		/* after "Z" but before "a": positive byte >= 64 */
+		return ch;
+
+	if (ch >= 'A')
+		/* "A..Z" to 12..37 */
+		return (ch - 'A' + 12);
+
+	if (ch > '9')
+		return 64;
+
+	/* "./0123456789" to 0,1,2..11 */
+	/* anything before "." becomes positive byte >= 64 */
+	return (unsigned char)(ch - '.');
+}
+
 int FAST_FUNC crypt_make_rand64encoded(char *p, int cnt /*, int x */)
 {
 	/* was: x += ... */
diff --git a/libbb/pw_encrypt_des.c b/libbb/pw_encrypt_des.c
index c836ab684..8b5edaaed 100644
--- a/libbb/pw_encrypt_des.c
+++ b/libbb/pw_encrypt_des.c
@@ -200,25 +200,6 @@ static const uint32_t bits32[32] ALIGN4 = {
 static const uint8_t bits8[8] ALIGN1 = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 };
 
 
-static int
-ascii_to_bin(char ch)
-{
-	if (ch > 'z')
-		return 0;
-	if (ch >= 'a')
-		return (ch - 'a' + 38);
-	if (ch > 'Z')
-		return 0;
-	if (ch >= 'A')
-		return (ch - 'A' + 12);
-	if (ch > '9')
-		return 0;
-	if (ch >= '.')
-		return (ch - '.');
-	return 0;
-}
-
-
 /* Static stuff that stays resident and doesn't change after
  * being initialized, and therefore doesn't need to be made
  * reentrant. */
@@ -740,8 +721,8 @@ des_crypt(struct des_ctx *ctx, char output[DES_OUT_BUFSIZE],
 	 */
 	output[0] = salt_str[0];
 	output[1] = salt_str[1];
-	salt = (ascii_to_bin(salt_str[1]) << 6)
-	     |  ascii_to_bin(salt_str[0]);
+	salt = (a2i64(salt_str[1]) << 6)
+	     |  a2i64(salt_str[0]);
 	setup_salt(ctx, salt); /* set ctx->saltbits for do_des() */
 
 	/* Do it. */
diff --git a/libbb/yescrypt/alg-yescrypt-common.c b/libbb/yescrypt/alg-yescrypt-common.c
index 7a1e92cab..b9a5c51ac 100644
--- a/libbb/yescrypt/alg-yescrypt-common.c
+++ b/libbb/yescrypt/alg-yescrypt-common.c
@@ -23,22 +23,6 @@
  * yescrypt_params_t field, and convert salt ti binary -
  * both of these are negligible compared to main hashing operation
  */
-static NOINLINE uint32_t atoi64(uint8_t src)
-{
-	static const uint8_t atoi64_partial[77] = {
-		0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
-		64, 64, 64, 64, 64, 64, 64,
-		12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
-		25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37,
-		64, 64, 64, 64, 64, 64,
-		38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50,
-		51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63
-	};
-	if (src >= '.' && src <= 'z')
-		return atoi64_partial[src - '.'];
-	return 64;
-}
-
 static NOINLINE const uint8_t *decode64_uint32(
 		uint32_t *dst,
 		const uint8_t *src, uint32_t val)
@@ -49,7 +33,7 @@ static NOINLINE const uint8_t *decode64_uint32(
 	if (!src) /* prevous decode failed already? */
 		goto fail;
 
-	c = atoi64(*src++);
+	c = a2i64(*src++);
 	if (c > 63)
 		goto fail;
 
@@ -64,7 +48,7 @@ static NOINLINE const uint8_t *decode64_uint32(
 	val += (c - start) << bits;
 
 	while (--chars) {
-		c = atoi64(*src++);
+		c = a2i64(*src++);
 		if (c > 63)
 			goto fail;
 		bits -= 6;
@@ -138,7 +122,7 @@ static const uint8_t *decode64(
 	while (dstpos <= *dstlen && srclen) {
 		uint32_t value = 0, bits = 0;
 		while (srclen--) {
-			uint32_t c = atoi64(*src);
+			uint32_t c = a2i64(*src);
 			if (c > 63) {
 				srclen = 0;
 				break;


More information about the busybox-cvs mailing list