[git commit] libbb/yescrypt: remove redundant SHA256 HMAC implementation

Denys Vlasenko vda.linux at googlemail.com
Mon Jul 7 06:21:44 UTC 2025


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

function                                             old     new   delta
hmac_blocks                                            -      88     +88
static.PBKDF2_SHA256                                 176     213     +37
yescrypt_kdf32_body                                 1046    1052      +6
static.smix                                          759     762      +3
hmac_block                                            88      64     -24
HMAC_SHA256_Final                                     53       -     -53
HMAC_SHA256_Buf                                       58       -     -58
HMAC_SHA256_Init                                     159       -    -159
------------------------------------------------------------------------------
(add/remove: 1/3 grow/shrink: 3/1 up/down: 134/-294)         Total: -160 bytes

Signed-off-by: Denys Vlasenko <vda.linux at googlemail.com>
---
 include/libbb.h                   | 10 ++++-
 libbb/hash_hmac.c                 | 10 ++++-
 libbb/yescrypt/alg-sha256.c       | 94 ++++-----------------------------------
 libbb/yescrypt/alg-yescrypt-kdf.c | 24 +++++++---
 networking/tls.c                  |  8 ++--
 5 files changed, 48 insertions(+), 98 deletions(-)

diff --git a/include/libbb.h b/include/libbb.h
index 3f60acaa0..cbf723f7e 100644
--- a/include/libbb.h
+++ b/include/libbb.h
@@ -2253,12 +2253,20 @@ typedef void md5sha_begin_func(md5sha_ctx_t *ctx) FAST_FUNC;
 #define hmac_begin(ctx,key,key_size,begin) \
 	hmac_begin(ctx,key,key_size)
 #endif
-void FAST_FUNC hmac_begin(hmac_ctx_t *ctx, uint8_t *key, unsigned key_size, md5sha_begin_func *begin);
+void FAST_FUNC hmac_begin(hmac_ctx_t *ctx, const uint8_t *key, unsigned key_size, md5sha_begin_func *begin);
 static ALWAYS_INLINE void hmac_hash(hmac_ctx_t *ctx, const void *in, size_t len)
 {
 	md5sha_hash(&ctx->hashed_key_xor_ipad, in, len);
 }
 unsigned FAST_FUNC hmac_end(hmac_ctx_t *ctx, uint8_t *out);
+#if HMAC_ONLY_SHA256
+#define hmac_block(key,key_size,begin,in,sz,out) \
+        hmac_block(key,key_size,in,sz,out)
+#endif
+unsigned FAST_FUNC hmac_block(const uint8_t *key, unsigned key_size,
+		md5sha_begin_func *begin,
+		const void *in, unsigned sz,
+		uint8_t *out);
 /* HMAC helpers for TLS: */
 void FAST_FUNC hmac_hash_v(hmac_ctx_t *ctx, va_list va);
 unsigned FAST_FUNC hmac_peek_hash(hmac_ctx_t *ctx, uint8_t *out, ...);
diff --git a/libbb/hash_hmac.c b/libbb/hash_hmac.c
index 8cf936949..9e48e0f51 100644
--- a/libbb/hash_hmac.c
+++ b/libbb/hash_hmac.c
@@ -18,7 +18,7 @@
 // if we often need HMAC hmac with the same key.
 //
 // text is often given in disjoint pieces.
-void FAST_FUNC hmac_begin(hmac_ctx_t *ctx, uint8_t *key, unsigned key_size, md5sha_begin_func *begin)
+void FAST_FUNC hmac_begin(hmac_ctx_t *ctx, const uint8_t *key, unsigned key_size, md5sha_begin_func *begin)
 {
 #if HMAC_ONLY_SHA256
 #define begin sha256_begin
@@ -64,6 +64,14 @@ unsigned FAST_FUNC hmac_end(hmac_ctx_t *ctx, uint8_t *out)
 	return sha_end(&ctx->hashed_key_xor_opad, out);
 }
 
+unsigned FAST_FUNC hmac_block(const uint8_t *key, unsigned key_size, md5sha_begin_func *begin, const void *in, unsigned sz, uint8_t *out)
+{
+	hmac_ctx_t ctx;
+	hmac_begin(&ctx, key, key_size, begin);
+	hmac_hash(&ctx, in, sz);
+	return hmac_end(&ctx, out);
+}
+
 /* TLS helpers */
 
 void FAST_FUNC hmac_hash_v(
diff --git a/libbb/yescrypt/alg-sha256.c b/libbb/yescrypt/alg-sha256.c
index f56b905ad..1ccffa1e5 100644
--- a/libbb/yescrypt/alg-sha256.c
+++ b/libbb/yescrypt/alg-sha256.c
@@ -25,82 +25,6 @@
  * SUCH DAMAGE.
  */
 
-/**
- * HMAC_SHA256_Init(ctx, K, Klen):
- * Initialize the HMAC-SHA256 context ${ctx} with ${Klen} bytes of key from
- * ${K}.
- */
-static void
-HMAC_SHA256_Init(HMAC_SHA256_CTX *ctx, const void *_K, size_t Klen)
-{
-	uint8_t pad[64];
-	uint8_t khash[32];
-	const uint8_t *K = _K;
-	size_t i;
-
-	/* If Klen > 64, the key is really SHA256(K). */
-	if (Klen > 64) {
-		sha256_block(K, Klen, khash);
-		K = khash;
-		Klen = 32;
-	}
-
-	/* Inner SHA256 operation is SHA256(K xor [block of 0x36] || data). */
-	sha256_begin(&ctx->ictx);
-	memset(pad, 0x36, 64);
-	for (i = 0; i < Klen; i++)
-		pad[i] ^= K[i];
-	sha256_hash(&ctx->ictx, pad, 64);
-
-	/* Outer SHA256 operation is SHA256(K xor [block of 0x5c] || hash). */
-	sha256_begin(&ctx->octx);
-	memset(pad, 0x5c, 64);
-	for (i = 0; i < Klen; i++)
-		pad[i] ^= K[i];
-	sha256_hash(&ctx->octx, pad, 64);
-}
-
-/**
- * HMAC_SHA256_Update(ctx, in, len):
- * Input ${len} bytes from ${in} into the HMAC-SHA256 context ${ctx}.
- */
-static void
-HMAC_SHA256_Update(HMAC_SHA256_CTX *ctx, const void *in, size_t len)
-{
-	/* Feed data to the inner SHA256 operation. */
-	sha256_hash(&ctx->ictx, in, len);
-}
-
-/**
- * HMAC_SHA256_Final(ctx, digest):
- * Output the HMAC-SHA256 of the data input to the context ${ctx} into the
- * buffer ${digest}.
- */
-static void
-HMAC_SHA256_Final(HMAC_SHA256_CTX *ctx, void *digest)
-{
-	/* Finish the inner SHA256 operation. */
-	sha256_end(&ctx->ictx, digest); /* using digest[] as scratch space */
-	/* Feed the inner hash to the outer SHA256 operation. */
-	sha256_hash(&ctx->octx, digest, 32); /* using digest[] as scratch space */
-	/* Finish the outer SHA256 operation. */
-	sha256_end(&ctx->octx, digest);
-}
-
-/**
- * HMAC_SHA256_Buf(K, Klen, in, len, digest):
- * Compute the HMAC-SHA256 of ${len} bytes from ${in} using the key ${K} of
- * length ${Klen}, and write the result to ${digest}.
- */
-static void
-HMAC_SHA256_Buf(const void *K, size_t Klen, const void *in, size_t len, void *digest)
-{
-	HMAC_SHA256_CTX ctx;
-	HMAC_SHA256_Init(&ctx, K, Klen);
-	HMAC_SHA256_Update(&ctx, in, len);
-	HMAC_SHA256_Final(&ctx, digest);
-}
-
 /**
  * PBKDF2_SHA256(passwd, passwdlen, salt, saltlen, c, buf, dkLen):
  * Compute PBKDF2(passwd, salt, c, dkLen) using HMAC-SHA256 as the PRF, and
@@ -111,15 +35,15 @@ PBKDF2_SHA256(const uint8_t *passwd, size_t passwdlen,
 		const uint8_t *salt, size_t saltlen,
 		uint64_t c, uint8_t *buf, size_t dkLen)
 {
-	HMAC_SHA256_CTX Phctx, PShctx, hctx;
+	hmac_ctx_t Phctx, PShctx;
 	size_t i;
 
 	/* Compute HMAC state after processing P. */
-	HMAC_SHA256_Init(&Phctx, passwd, passwdlen);
+	hmac_begin(&Phctx, passwd, passwdlen, sha256_begin);
 
 	/* Compute HMAC state after processing P and S. */
-	memcpy(&PShctx, &Phctx, sizeof(HMAC_SHA256_CTX));
-	HMAC_SHA256_Update(&PShctx, salt, saltlen);
+	PShctx = Phctx;
+	hmac_hash(&PShctx, salt, saltlen);
 
 	/* Iterate through the blocks. */
 	for (i = 0; dkLen != 0; i++) {
@@ -134,18 +58,16 @@ PBKDF2_SHA256(const uint8_t *passwd, size_t passwdlen,
 		ivec = SWAP_BE32((uint32_t)(i + 1));
 
 		/* Compute U_1 = PRF(P, S || INT(i)). */
-		hctx = PShctx;
-		HMAC_SHA256_Update(&hctx, &ivec, 4);
-		HMAC_SHA256_Final(&hctx, T);
+		hmac_peek_hash(&PShctx, (void*)T, &ivec, 4, NULL);
+//TODO: the above is a vararg function, might incur some ABI pain
+//does libbb need a non-vararg version with just one (buf,len)?
 
 		if (c > 1) {
 			/* T_i = U_1 ... */
 			memcpy(U, T, 32);
 			for (j = 2; j <= c; j++) {
 				/* Compute U_j. */
-				hctx = Phctx;
-				HMAC_SHA256_Update(&hctx, U, 32);
-				HMAC_SHA256_Final(&hctx, U);
+				hmac_peek_hash(&Phctx, (void*)U, U, 32, NULL);
 				/* ... xor U_j ... */
 				for (k = 0; k < 32 / 8; k++)
 					T[k] ^= U[k];
diff --git a/libbb/yescrypt/alg-yescrypt-kdf.c b/libbb/yescrypt/alg-yescrypt-kdf.c
index 27ef2caa4..f1f06621e 100644
--- a/libbb/yescrypt/alg-yescrypt-kdf.c
+++ b/libbb/yescrypt/alg-yescrypt-kdf.c
@@ -735,8 +735,12 @@ static void smix(uint8_t *B, size_t r, uint32_t N, uint32_t p, uint32_t t,
 			ctx_i->S0 = Si + Sbytes / 3 * 2;
 			ctx_i->w = 0;
 			if (i == 0)
-				HMAC_SHA256_Buf(Bp + (128 * r - 64), 64,
-				    passwd, 32, passwd);
+				hmac_block(
+				        /* key,len: */ Bp + (128 * r - 64), 64,
+					/* hash fn: */ sha256_begin,
+					/* in,len: */  passwd, 32,
+					/* outbuf: */  passwd
+				);
 		}
 		smix1(Bp, r, Np, flags, Vp, NROM, VROM, XYp, ctx_i);
 		smix2(Bp, r, p2floor(Np), Nloop_rw, flags, Vp,
@@ -907,9 +911,12 @@ static int yescrypt_kdf32_body(
 		S = (uint8_t *)XY + XY_size;
 
 	if (flags) {
-		HMAC_SHA256_Buf("yescrypt-prehash",
-		    (flags & YESCRYPT_PREHASH) ? 16 : 8,
-		    passwd, passwdlen, sha256);
+		hmac_block(
+			/* key,len: */ (const void*)"yescrypt-prehash", (flags & YESCRYPT_PREHASH) ? 16 : 8,
+			/* hash fn: */ sha256_begin,
+			/* in,len: */  passwd, passwdlen,
+			/* outbuf: */  sha256
+		);
 		passwd = sha256;
 		passwdlen = sizeof(sha256);
 	}
@@ -946,7 +953,12 @@ static int yescrypt_kdf32_body(
 	 */
 	if (flags && !(flags & YESCRYPT_PREHASH)) {
 		/* Compute ClientKey */
-		HMAC_SHA256_Buf(dkp, sizeof(dk), "Client Key", 10, sha256);
+		hmac_block(
+			/* key,len: */ dkp, sizeof(dk),
+			/* hash fn: */ sha256_begin,
+			/* in,len: */  "Client Key", 10,
+			/* outbuf: */  sha256
+		);
 		/* Compute StoredKey */
 		{
 			size_t clen = /*buflen:*/32;
diff --git a/networking/tls.c b/networking/tls.c
index b8caf1e4b..098cf7cac 100644
--- a/networking/tls.c
+++ b/networking/tls.c
@@ -533,10 +533,10 @@ static void *tls_get_zeroed_outbuf(tls_state_t *tls, int len)
 
 /* Calculate the HMAC over the list of blocks */
 #if !ENABLE_FEATURE_TLS_SHA1
-#define hmac_block(tls,out,key,key_size,...) \
-	hmac_block(out,key,key_size, __VA_ARGS__)
+#define hmac_blocks(tls,out,key,key_size,...) \
+	hmac_blocks(out,key,key_size, __VA_ARGS__)
 #endif
-static unsigned hmac_block(tls_state_t *tls, uint8_t *out, uint8_t *key, unsigned key_size, ...)
+static unsigned hmac_blocks(tls_state_t *tls, uint8_t *out, uint8_t *key, unsigned key_size, ...)
 {
 	hmac_ctx_t ctx;
 	va_list va;
@@ -575,7 +575,7 @@ static void xwrite_encrypted_and_hmac_signed(tls_state_t *tls, unsigned size, un
 	xhdr->len16_lo = size & 0xff;
 
 	/* Calculate MAC signature */
-	hmac_block(tls, buf + size, /* result */
+	hmac_blocks(tls, buf + size, /* result */
 		tls->client_write_MAC_key, TLS_MAC_SIZE(tls),
 		&tls->write_seq64_be, sizeof(tls->write_seq64_be),
 		xhdr, RECHDR_LEN,


More information about the busybox-cvs mailing list