mirror of
https://git.busybox.net/busybox
synced 2025-08-28 13:05:22 +02:00
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@googlemail.com>
107 lines
3.2 KiB
C
107 lines
3.2 KiB
C
/*
|
|
* Copyright (C) 2025 Denys Vlasenko
|
|
*
|
|
* Licensed under GPLv2, see file LICENSE in this source tree.
|
|
*/
|
|
//kbuild:lib-$(CONFIG_TLS) += hash_hmac.o
|
|
//kbuild:lib-$(CONFIG_USE_BB_CRYPT_YES) += hash_hmac.o
|
|
|
|
#include "libbb.h"
|
|
|
|
// RFC 2104:
|
|
// HMAC(key, text) based on a hash H (say, sha256) is:
|
|
// ipad = [0x36 x INSIZE]
|
|
// opad = [0x5c x INSIZE]
|
|
// HMAC(key, text) = H((key XOR opad) + H((key XOR ipad) + text))
|
|
//
|
|
// H(key XOR opad) and H(key XOR ipad) can be precomputed
|
|
// 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, const uint8_t *key, unsigned key_size, md5sha_begin_func *begin)
|
|
{
|
|
#if HMAC_ONLY_SHA256
|
|
#define begin sha256_begin
|
|
#endif
|
|
uint8_t key_xor_ipad[SHA2_INSIZE];
|
|
uint8_t key_xor_opad[SHA2_INSIZE];
|
|
unsigned i;
|
|
|
|
// "The authentication key can be of any length up to INSIZE, the
|
|
// block length of the hash function. Applications that use keys longer
|
|
// than INSIZE bytes will first hash the key using H and then use the
|
|
// resultant OUTSIZE byte string as the actual key to HMAC."
|
|
if (key_size > SHA2_INSIZE) {
|
|
uint8_t tempkey[SHA1_OUTSIZE < SHA256_OUTSIZE ? SHA256_OUTSIZE : SHA1_OUTSIZE];
|
|
/* use ctx->hashed_key_xor_ipad as scratch ctx */
|
|
begin(&ctx->hashed_key_xor_ipad);
|
|
md5sha_hash(&ctx->hashed_key_xor_ipad, key, key_size);
|
|
key_size = sha_end(&ctx->hashed_key_xor_ipad, tempkey);
|
|
key = tempkey;
|
|
}
|
|
|
|
for (i = 0; i < key_size; i++) {
|
|
key_xor_ipad[i] = key[i] ^ 0x36;
|
|
key_xor_opad[i] = key[i] ^ 0x5c;
|
|
}
|
|
for (; i < SHA2_INSIZE; i++) {
|
|
key_xor_ipad[i] = 0x36;
|
|
key_xor_opad[i] = 0x5c;
|
|
}
|
|
|
|
begin(&ctx->hashed_key_xor_ipad);
|
|
begin(&ctx->hashed_key_xor_opad);
|
|
md5sha_hash(&ctx->hashed_key_xor_ipad, key_xor_ipad, SHA2_INSIZE);
|
|
md5sha_hash(&ctx->hashed_key_xor_opad, key_xor_opad, SHA2_INSIZE);
|
|
}
|
|
#undef begin
|
|
|
|
unsigned FAST_FUNC hmac_end(hmac_ctx_t *ctx, uint8_t *out)
|
|
{
|
|
unsigned len = sha_end(&ctx->hashed_key_xor_ipad, out);
|
|
/* out = H((key XOR opad) + out) */
|
|
md5sha_hash(&ctx->hashed_key_xor_opad, out, len);
|
|
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(
|
|
hmac_ctx_t *ctx,
|
|
va_list va)
|
|
{
|
|
uint8_t *in;
|
|
|
|
/* ctx->hashed_key_xor_ipad contains unclosed "H((key XOR ipad) +" state */
|
|
/* ctx->hashed_key_xor_opad contains unclosed "H((key XOR opad) +" state */
|
|
|
|
/* calculate out = H((key XOR ipad) + text) */
|
|
while ((in = va_arg(va, uint8_t*)) != NULL) {
|
|
unsigned size = va_arg(va, unsigned);
|
|
md5sha_hash(&ctx->hashed_key_xor_ipad, in, size);
|
|
}
|
|
}
|
|
|
|
/* Using HMAC state, make a copy of it (IOW: without affecting this state!)
|
|
* hash in the list of (ptr,size) blocks, and finish the HMAC to out[] buffer.
|
|
* This function is useful for TLS PRF.
|
|
*/
|
|
unsigned FAST_FUNC hmac_peek_hash(hmac_ctx_t *ctx, uint8_t *out, ...)
|
|
{
|
|
hmac_ctx_t tmpctx = *ctx; /* struct copy */
|
|
va_list va;
|
|
|
|
va_start(va, out);
|
|
hmac_hash_v(&tmpctx, va);
|
|
va_end(va);
|
|
|
|
return hmac_end(&tmpctx, out);
|
|
}
|