diff options
| author | Ron Yorston <rmy@pobox.com> | 2025-08-12 11:59:30 +0100 |
|---|---|---|
| committer | Ron Yorston <rmy@pobox.com> | 2025-08-12 11:59:30 +0100 |
| commit | aed19625ff874bb2fc95480a6f684a9acc1bf2c9 (patch) | |
| tree | df216d2ebb6aefba5928336b2bdd66b82d14b29a | |
| parent | 4e6b0b3e8b8f819bc9e2f69b0c267abecfe30968 (diff) | |
| download | busybox-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.h | 34 | ||||
| -rw-r--r-- | libbb/hash_hmac.c | 49 | ||||
| -rw-r--r-- | networking/tls.c | 12 |
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 | ||
| 2447 | typedef struct hmac_ctx { | 2462 | typedef 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 | ||
| 2467 | typedef 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) |
| 2452 | typedef void md5sha_begin_func(md5sha_ctx_t *ctx) FAST_FUNC; | 2470 | typedef 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 | ||
| 2488 | void _hmac_begin(hmac_ctx_t *pre, uint8_t *key, unsigned key_size, | ||
| 2489 | BCRYPT_ALG_HANDLE alg_handle); | ||
| 2490 | void hmac_uninit(hmac_ctx_t *pre); | ||
| 2491 | #endif | ||
| 2462 | unsigned FAST_FUNC hmac_end(hmac_ctx_t *ctx, uint8_t *out); | 2492 | unsigned 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: */ |
| 2472 | void FAST_FUNC hmac_hash_v(hmac_ctx_t *ctx, va_list va); | 2502 | void FAST_FUNC hmac_hash_v(hmac_ctx_t *ctx, va_list va); |
| 2473 | unsigned FAST_FUNC hmac_peek_hash(hmac_ctx_t *ctx, uint8_t *out, ...); | 2503 | unsigned hmac_peek_hash(hmac_ctx_t *ctx, uint8_t *out, ...); |
| 2474 | 2504 | ||
| 2475 | extern uint32_t *global_crc32_table; | 2505 | extern uint32_t *global_crc32_table; |
| 2476 | uint32_t *crc32_filltable(uint32_t *tbl256, int endian) FAST_FUNC; | 2506 | uint32_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 | ||
| 21 | void FAST_FUNC hmac_begin(hmac_ctx_t *ctx, const uint8_t *key, unsigned key_size, md5sha_begin_func *begin) | 22 | void 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 | ||
| 94 | void _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 | |||
| 114 | unsigned 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 | |||
| 124 | void 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 | |||
| 134 | void 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 | */ |
| 97 | unsigned FAST_FUNC hmac_peek_hash(hmac_ctx_t *ctx, uint8_t *out, ...) | 144 | unsigned 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 | ||
| 530 | static void xwrite_encrypted_and_hmac_signed(tls_state_t *tls, unsigned size, unsigned type) | 534 | static void xwrite_encrypted_and_hmac_signed(tls_state_t *tls, unsigned size, unsigned type) |
