[git commit] libbb/yescrypt: actually, largest allowed salt is 86 chars, support that

Denys Vlasenko vda.linux at googlemail.com
Thu Jul 17 15:01:40 UTC 2025


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

function                                             old     new   delta
yescrypt_r                                           767     756     -11

Signed-off-by: Denys Vlasenko <vda.linux at googlemail.com>
---
 libbb/yescrypt/alg-yescrypt-common.c | 26 +++++++++++++++-----------
 libbb/yescrypt/alg-yescrypt.h        |  2 +-
 testsuite/cryptpw.tests              | 10 +++++++---
 3 files changed, 23 insertions(+), 15 deletions(-)

diff --git a/libbb/yescrypt/alg-yescrypt-common.c b/libbb/yescrypt/alg-yescrypt-common.c
index 1c063b895..c51823787 100644
--- a/libbb/yescrypt/alg-yescrypt-common.c
+++ b/libbb/yescrypt/alg-yescrypt-common.c
@@ -152,13 +152,13 @@ static const uint8_t *decode64(
 		uint8_t *dst, size_t *dstlen,
 		const uint8_t *src)
 {
-	size_t dstpos = 0;
+	unsigned dstpos = 0;
 
 	dbg_dec64("src:'%s'", src);
 	for (;;) {
 		uint32_t c, value = 0;
 		int bits = 0;
-		while (*src && *src != '$') {
+		while (*src != '\0' && *src != '$') {
 			c = a2i64(*src);
 			if (c > 63) { /* bad ascii64 char, stop decoding at it */
 				break;
@@ -174,9 +174,11 @@ static const uint8_t *decode64(
 			break;
 		/* else: we got last, partial bit block - store it */
  store:
-		dbg_dec64(" storing bits:%d v:%08x", bits, (int)SWAP_BE32(value)); //BE to see lsb first
-		while (dstpos < *dstlen) {
-			if ((!*src || *src == '$') && value == 0 && bits < 8) {
+		dbg_dec64(" storing bits:%d dstpos:%u v:%08x", bits, dstpos, (int)SWAP_BE32(value)); //BE to see lsb first
+		for (;;) {
+			if ((*src == '\0' || *src == '$')
+			 && value == 0 && bits < 8
+			) {
 				/* Example: mkpasswd PWD '$y$j9T$123':
 				 * the "123" is bits:18 value:03,51,00
 				 * is considered to be 2 bytes, not 3!
@@ -190,17 +192,18 @@ static const uint8_t *decode64(
 				 */
 				goto end;
 			}
-			dstpos++;
+			if (dstpos >= *dstlen) {
+				dbg_dec64(" ERR: bits:%d dstpos:%u dst[] is too small", bits, dstpos);
+				goto fail;
+			}
 			*dst++ = value;
+			dstpos++;
 			value >>= 8;
 			bits -= 8;
 			if (bits <= 0) /* can get negative, if we e.g. had 6 bits */
-				goto next;
+				break;
 		}
-		dbg_dec64(" ERR: bits:%d dst[] is too small", bits);
-		goto fail;
- next:
-		if (!*src || *src == '$')
+		if (*src == '\0' || *src == '$')
 			break;
 	}
  end:
@@ -376,6 +379,7 @@ char *yescrypt_r(
 	saltend = decode64(yctx->salt, &yctx->saltlen, src);
 	if (!saltend || (*saltend != '\0' && *saltend != '$'))
 		goto fail; /* salt[] is too small, or bad char during decode */
+	dbg_dec64("salt is %d ascii64 chars -> %d bytes (in binary)", (int)(saltend - src), (int)yctx->saltlen);
 
 	prefixlen = saltend - setting;
 	need = prefixlen + 1 + YESCRYPT_HASH_LEN + 1;
diff --git a/libbb/yescrypt/alg-yescrypt.h b/libbb/yescrypt/alg-yescrypt.h
index 0b93945af..5051efbb4 100644
--- a/libbb/yescrypt/alg-yescrypt.h
+++ b/libbb/yescrypt/alg-yescrypt.h
@@ -139,7 +139,7 @@
 #define YESCRYPT_GATHER_8		0x018 //gg=11
 #define YESCRYPT_SIMPLE_1		0x000 //ss=00
 #define YESCRYPT_SIMPLE_2		0x020 //ss=01
-#define YESCRYPT_SIMPLE_4		0x040 //ss=11
+#define YESCRYPT_SIMPLE_4		0x040 //ss=10
 #define YESCRYPT_SIMPLE_8		0x060 //ss=11
 #define YESCRYPT_SBOX_6K		0x000 //sbox=0000
 #define YESCRYPT_SBOX_12K		0x080 //sbox=0001
diff --git a/testsuite/cryptpw.tests b/testsuite/cryptpw.tests
index beac35efe..83bfde521 100755
--- a/testsuite/cryptpw.tests
+++ b/testsuite/cryptpw.tests
@@ -97,9 +97,13 @@ testing 'cryptpw yescrypt with 4-char salt "...."' \
 	'cryptpw -m yescrypt qweRTY123 at -+ j9T\$....' \
 	'$y$j9T$....$wOnauYL2/NEtr6YQi9pi8AtV7L57sEbVOAnWJIcP9q2\n' \
 	'' ''
-testing 'cryptpw yescrypt with 84-char salt (max size)' \
-	'cryptpw -m yescrypt qweRTY123 at -+ j9T\$123456789012345678901234567890123456789012345678901234567890123456789012345678901234' \
-	'$y$j9T$123456789012345678901234567890123456789012345678901234567890123456789012345678901234$ubrUuPCpI97LIMlVMt/A0Mhs/kBK2UBJYcQSxEZSlz4\n' \
+# 84 chars = 21 4-char blocks which decode into 21*3 = 63 bytes.
+# The last byte of the maximum allowed salt size has to come from an incomplete
+# char block. E.g. "z/" encodes byte 0x7f. "z1" is 0xff.
+# Anything larger (e.g. "z2") is an error (it encodes 0x13f).
+testing 'cryptpw yescrypt with 86-char salt (max size)' \
+	'cryptpw -m yescrypt qweRTY123 at -+ j9T\$123456789012345678901234567890123456789012345678901234567890123456789012345678901234z/' \
+	'$y$j9T$123456789012345678901234567890123456789012345678901234567890123456789012345678901234z/$Exxe8IoPXiddFsqj7iqCanRf8FyquAoB0/uceLmLjG.\n' \
 	'' ''
 testing 'cryptpw yescrypt implicit' \
 	'cryptpw qweRTY123 at -+ \$y\$j9T\$123456789012345678901234' \


More information about the busybox-cvs mailing list