aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2025-08-12 11:59:30 +0100
committerRon Yorston <rmy@pobox.com>2025-08-12 11:59:30 +0100
commitaed19625ff874bb2fc95480a6f684a9acc1bf2c9 (patch)
treedf216d2ebb6aefba5928336b2bdd66b82d14b29a
parent4e6b0b3e8b8f819bc9e2f69b0c267abecfe30968 (diff)
downloadbusybox-w32-aed19625ff874bb2fc95480a6f684a9acc1bf2c9.tar.gz
busybox-w32-aed19625ff874bb2fc95480a6f684a9acc1bf2c9.tar.bz2
busybox-w32-aed19625ff874bb2fc95480a6f684a9acc1bf2c9.zip
Post-merge fixes
Upstream has moved some functions from networking/tls.c to a new file, libbb/hash_hmac.c. The merge didn't adjust this code to allow it to work with the native Windows checksum API. This only matters if FEATURE_USE_CNG_API is enabled and CONFIG_FEATURE_TLS_SCHANNEL isn't. In that case the wget applet fails to handle https. None of the default configurations has this combination, but it should work. Make it so. The Windows code doesn't implement hmac_block(), as that's only used for password encryption which isn't currently supported. The variadic function hmac_peek_hash() isn't declared FAST_FUNC, as that causes clang to issue many warnings.
-rw-r--r--include/libbb.h34
-rw-r--r--libbb/hash_hmac.c49
-rw-r--r--networking/tls.c12
3 files changed, 88 insertions, 7 deletions
diff --git a/include/libbb.h b/include/libbb.h
index 7a375f4d2..8dc4e4992 100644
--- a/include/libbb.h
+++ b/include/libbb.h
@@ -281,12 +281,26 @@ PUSH_AND_SET_FUNCTION_VISIBILITY_TO_HIDDEN
281# endif 281# endif
282#endif 282#endif
283 283
284#if ENABLE_FEATURE_TLS_SCHANNEL 284#if ENABLE_FEATURE_TLS_SCHANNEL || ENABLE_FEATURE_USE_CNG_API
285# define SECURITY_WIN32 285# define SECURITY_WIN32
286# include <windows.h> 286# include <windows.h>
287# include <security.h> 287# include <security.h>
288#endif 288#endif
289 289
290#if ENABLE_FEATURE_USE_CNG_API
291# include <bcrypt.h>
292
293// these work on Windows >= 10
294# define BCRYPT_HMAC_SHA1_ALG_HANDLE ((BCRYPT_ALG_HANDLE) 0x000000a1)
295# define BCRYPT_HMAC_SHA256_ALG_HANDLE ((BCRYPT_ALG_HANDLE) 0x000000b1)
296# define sha1_begin_hmac BCRYPT_HMAC_SHA1_ALG_HANDLE
297# define sha256_begin_hmac BCRYPT_HMAC_SHA256_ALG_HANDLE
298#else
299# define sha1_begin_hmac sha1_begin
300# define sha256_begin_hmac sha256_begin
301# define hmac_uninit(...) ((void)0)
302#endif
303
290/* Tested to work correctly with all int types (IIRC :]) */ 304/* Tested to work correctly with all int types (IIRC :]) */
291#define MAXINT(T) (T)( \ 305#define MAXINT(T) (T)( \
292 ((T)-1) > 0 \ 306 ((T)-1) > 0 \
@@ -2444,12 +2458,17 @@ typedef struct md5_ctx_t md5sha_ctx_t;
2444#endif 2458#endif
2445 2459
2446/* RFC 2104 HMAC (hash-based message authentication code) */ 2460/* RFC 2104 HMAC (hash-based message authentication code) */
2461#if !ENABLE_FEATURE_USE_CNG_API
2447typedef struct hmac_ctx { 2462typedef struct hmac_ctx {
2448 md5sha_ctx_t hashed_key_xor_ipad; 2463 md5sha_ctx_t hashed_key_xor_ipad;
2449 md5sha_ctx_t hashed_key_xor_opad; 2464 md5sha_ctx_t hashed_key_xor_opad;
2450} hmac_ctx_t; 2465} hmac_ctx_t;
2466#else
2467typedef struct bcrypt_hash_ctx_t hmac_ctx_t;
2468#endif
2451#define HMAC_ONLY_SHA256 (!ENABLE_FEATURE_TLS_SHA1) 2469#define HMAC_ONLY_SHA256 (!ENABLE_FEATURE_TLS_SHA1)
2452typedef void md5sha_begin_func(md5sha_ctx_t *ctx) FAST_FUNC; 2470typedef void md5sha_begin_func(md5sha_ctx_t *ctx) FAST_FUNC;
2471#if !ENABLE_FEATURE_USE_CNG_API
2453#if HMAC_ONLY_SHA256 2472#if HMAC_ONLY_SHA256
2454#define hmac_begin(ctx,key,key_size,begin) \ 2473#define hmac_begin(ctx,key,key_size,begin) \
2455 hmac_begin(ctx,key,key_size) 2474 hmac_begin(ctx,key,key_size)
@@ -2459,6 +2478,17 @@ static ALWAYS_INLINE void hmac_hash(hmac_ctx_t *ctx, const void *in, size_t len)
2459{ 2478{
2460 md5sha_hash(&ctx->hashed_key_xor_ipad, in, len); 2479 md5sha_hash(&ctx->hashed_key_xor_ipad, in, len);
2461} 2480}
2481#else
2482# if HMAC_ONLY_SHA256
2483# define hmac_begin(pre,key,key_size,begin) \
2484 _hmac_begin(pre, key, key_size, sha256_begin_hmac)
2485# else
2486# define hmac_begin _hmac_begin
2487# endif
2488void _hmac_begin(hmac_ctx_t *pre, uint8_t *key, unsigned key_size,
2489 BCRYPT_ALG_HANDLE alg_handle);
2490void hmac_uninit(hmac_ctx_t *pre);
2491#endif
2462unsigned FAST_FUNC hmac_end(hmac_ctx_t *ctx, uint8_t *out); 2492unsigned FAST_FUNC hmac_end(hmac_ctx_t *ctx, uint8_t *out);
2463#if HMAC_ONLY_SHA256 2493#if HMAC_ONLY_SHA256
2464#define hmac_block(key,key_size,begin,in,sz,out) \ 2494#define hmac_block(key,key_size,begin,in,sz,out) \
@@ -2470,7 +2500,7 @@ unsigned FAST_FUNC hmac_block(const uint8_t *key, unsigned key_size,
2470 uint8_t *out); 2500 uint8_t *out);
2471/* HMAC helpers for TLS: */ 2501/* HMAC helpers for TLS: */
2472void FAST_FUNC hmac_hash_v(hmac_ctx_t *ctx, va_list va); 2502void FAST_FUNC hmac_hash_v(hmac_ctx_t *ctx, va_list va);
2473unsigned FAST_FUNC hmac_peek_hash(hmac_ctx_t *ctx, uint8_t *out, ...); 2503unsigned hmac_peek_hash(hmac_ctx_t *ctx, uint8_t *out, ...);
2474 2504
2475extern uint32_t *global_crc32_table; 2505extern uint32_t *global_crc32_table;
2476uint32_t *crc32_filltable(uint32_t *tbl256, int endian) FAST_FUNC; 2506uint32_t *crc32_filltable(uint32_t *tbl256, int endian) FAST_FUNC;
diff --git a/libbb/hash_hmac.c b/libbb/hash_hmac.c
index 9e48e0f51..b3138029f 100644
--- a/libbb/hash_hmac.c
+++ b/libbb/hash_hmac.c
@@ -18,6 +18,7 @@
18// if we often need HMAC hmac with the same key. 18// if we often need HMAC hmac with the same key.
19// 19//
20// text is often given in disjoint pieces. 20// text is often given in disjoint pieces.
21#if !ENABLE_FEATURE_USE_CNG_API
21void FAST_FUNC hmac_begin(hmac_ctx_t *ctx, const uint8_t *key, unsigned key_size, md5sha_begin_func *begin) 22void FAST_FUNC hmac_begin(hmac_ctx_t *ctx, const uint8_t *key, unsigned key_size, md5sha_begin_func *begin)
22{ 23{
23#if HMAC_ONLY_SHA256 24#if HMAC_ONLY_SHA256
@@ -89,12 +90,58 @@ void FAST_FUNC hmac_hash_v(
89 md5sha_hash(&ctx->hashed_key_xor_ipad, in, size); 90 md5sha_hash(&ctx->hashed_key_xor_ipad, in, size);
90 } 91 }
91} 92}
93#else
94void _hmac_begin(hmac_ctx_t *ctx, uint8_t *key, unsigned key_size,
95 BCRYPT_ALG_HANDLE alg_handle) {
96 DWORD hash_object_length = 0;
97 ULONG _unused;
98 NTSTATUS status;
99
100 status = BCryptGetProperty(alg_handle, BCRYPT_OBJECT_LENGTH,
101 (PUCHAR)&hash_object_length, sizeof(DWORD), &_unused, 0);
102 mingw_die_if_error(status, "BCryptGetProperty");
103 status = BCryptGetProperty(alg_handle, BCRYPT_HASH_LENGTH,
104 (PUCHAR)&ctx->output_size, sizeof(DWORD), &_unused, 0);
105 mingw_die_if_error(status, "BCryptGetProperty");
106
107 ctx->hash_obj = xmalloc(hash_object_length);
108
109 status = BCryptCreateHash(alg_handle, &ctx->handle, ctx->hash_obj,
110 hash_object_length, key, key_size, BCRYPT_HASH_REUSABLE_FLAG);
111 mingw_die_if_error(status, "BCryptCreateHash");
112}
113
114unsigned FAST_FUNC hmac_end(hmac_ctx_t *ctx, uint8_t *out)
115{
116 NTSTATUS status;
117
118 status = BCryptFinishHash(ctx->handle, out, ctx->output_size, 0);
119 mingw_die_if_error(status, "BCryptFinishHash");
120
121 return ctx->output_size;
122}
123
124void FAST_FUNC hmac_hash_v(hmac_ctx_t *ctx, va_list va)
125{
126 uint8_t *in;
127
128 while ((in = va_arg(va, uint8_t*)) != NULL) {
129 unsigned size = va_arg(va, unsigned);
130 BCryptHashData(ctx->handle, in, size, 0);
131 }
132}
133
134void hmac_uninit(hmac_ctx_t *ctx) {
135 BCryptDestroyHash(ctx->handle);
136 free(ctx->hash_obj);
137}
138#endif
92 139
93/* Using HMAC state, make a copy of it (IOW: without affecting this state!) 140/* Using HMAC state, make a copy of it (IOW: without affecting this state!)
94 * hash in the list of (ptr,size) blocks, and finish the HMAC to out[] buffer. 141 * hash in the list of (ptr,size) blocks, and finish the HMAC to out[] buffer.
95 * This function is useful for TLS PRF. 142 * This function is useful for TLS PRF.
96 */ 143 */
97unsigned FAST_FUNC hmac_peek_hash(hmac_ctx_t *ctx, uint8_t *out, ...) 144unsigned hmac_peek_hash(hmac_ctx_t *ctx, uint8_t *out, ...)
98{ 145{
99 hmac_ctx_t tmpctx = *ctx; /* struct copy */ 146 hmac_ctx_t tmpctx = *ctx; /* struct copy */
100 va_list va; 147 va_list va;
diff --git a/networking/tls.c b/networking/tls.c
index 13bdc0423..9c05364ea 100644
--- a/networking/tls.c
+++ b/networking/tls.c
@@ -418,7 +418,7 @@ static void prf_hmac_sha256(/*tls_state_t *tls,*/
418#define SEED label, label_size, seed, seed_size 418#define SEED label, label_size, seed, seed_size
419#define A a, MAC_size 419#define A a, MAC_size
420 420
421 hmac_begin(&ctx, secret, secret_size, sha256_begin); 421 hmac_begin(&ctx, secret, secret_size, sha256_begin_hmac);
422 422
423 /* A(1) = HMAC_hash(secret, seed) */ 423 /* A(1) = HMAC_hash(secret, seed) */
424 hmac_peek_hash(&ctx, a, SEED, NULL); 424 hmac_peek_hash(&ctx, a, SEED, NULL);
@@ -430,6 +430,7 @@ static void prf_hmac_sha256(/*tls_state_t *tls,*/
430 /* (use a[] as temp buffer) */ 430 /* (use a[] as temp buffer) */
431 hmac_peek_hash(&ctx, a, A, SEED, NULL); 431 hmac_peek_hash(&ctx, a, A, SEED, NULL);
432 memcpy(out_p, a, outbuf_size); 432 memcpy(out_p, a, outbuf_size);
433 hmac_uninit(&ctx);
433 return; 434 return;
434 } 435 }
435 /* Not last block. Store directly to result buffer */ 436 /* Not last block. Store directly to result buffer */
@@ -513,18 +514,21 @@ static unsigned hmac_blocks(tls_state_t *tls, uint8_t *out, uint8_t *key, unsign
513{ 514{
514 hmac_ctx_t ctx; 515 hmac_ctx_t ctx;
515 va_list va; 516 va_list va;
517 unsigned len;
516 518
517 hmac_begin(&ctx, key, key_size, 519 hmac_begin(&ctx, key, key_size,
518 (ENABLE_FEATURE_TLS_SHA1 && tls->MAC_size == SHA1_OUTSIZE) 520 (ENABLE_FEATURE_TLS_SHA1 && tls->MAC_size == SHA1_OUTSIZE)
519 ? sha1_begin 521 ? sha1_begin_hmac
520 : sha256_begin 522 : sha256_begin_hmac
521 ); 523 );
522 524
523 va_start(va, key_size); 525 va_start(va, key_size);
524 hmac_hash_v(&ctx, va); 526 hmac_hash_v(&ctx, va);
525 va_end(va); 527 va_end(va);
526 528
527 return hmac_end(&ctx, out); 529 len = hmac_end(&ctx, out);
530 hmac_uninit(&ctx);
531 return len;
528} 532}
529 533
530static void xwrite_encrypted_and_hmac_signed(tls_state_t *tls, unsigned size, unsigned type) 534static void xwrite_encrypted_and_hmac_signed(tls_state_t *tls, unsigned size, unsigned type)