DeterministicESPAsyncWebServer v6.27.1
Zero-allocation, bounded-execution async HTTP server for ESP32
Loading...
Searching...
No Matches
ssh_hmac_sha512.cpp
Go to the documentation of this file.
1// Copyright (C) 2026 Douglas Quigg (dstroy0) <dquigg123@gmail.com>
2// SPDX-License-Identifier: AGPL-3.0-or-later
3
4/**
5 * @file ssh_hmac_sha512.cpp
6 * @brief HMAC-SHA2-512 implementation (RFC 2104). See ssh_hmac_sha512.h.
7 *
8 * HMAC(K, m) = H((K XOR opad) || H((K XOR ipad) || m)), H = SHA-512, block = 128 bytes,
9 * ipad = 0x36 repeated, opad = 0x5c repeated.
10 */
11
13
14namespace
15{
16// One 128-byte HMAC key block: keys > 128 bytes are pre-hashed (RFC 2104), else zero-padded.
17void build_key_block(const uint8_t *key, size_t key_len, uint8_t block[SSH_SHA512_BLOCK_LEN], uint8_t pad_byte)
18{
19 uint8_t k[SSH_SHA512_BLOCK_LEN] = {0};
20 if (key_len > SSH_SHA512_BLOCK_LEN)
21 {
22 ssh_sha512(key, key_len, k); // 64-byte digest; the remaining 64 bytes stay zero
23 }
24 else
25 {
26 for (size_t i = 0; i < key_len; i++)
27 k[i] = key[i];
28 }
29 for (int i = 0; i < SSH_SHA512_BLOCK_LEN; i++)
30 block[i] = (uint8_t)(k[i] ^ pad_byte);
31}
32} // namespace
33
34void ssh_hmac_sha512_init(SshHmacSha512Ctx *ctx, const uint8_t *key, size_t key_len)
35{
36 uint8_t ikey[SSH_SHA512_BLOCK_LEN];
37 build_key_block(key, key_len, ikey, 0x36u); // ipad
38 build_key_block(key, key_len, ctx->okey, 0x5cu); // opad (kept for the final step)
41}
42
43void ssh_hmac_sha512_update(SshHmacSha512Ctx *ctx, const uint8_t *data, size_t len)
44{
45 ssh_sha512_update(&ctx->inner, data, len);
46}
47
49{
50 uint8_t inner_digest[SSH_SHA512_DIGEST_LEN];
51 ssh_sha512_final(&ctx->inner, inner_digest);
52 SshSha512Ctx outer;
53 ssh_sha512_init(&outer);
55 ssh_sha512_update(&outer, inner_digest, SSH_SHA512_DIGEST_LEN);
56 ssh_sha512_final(&outer, mac);
57}
58
59void ssh_hmac_sha512(const uint8_t *key, size_t key_len, const uint8_t *data, size_t len,
60 uint8_t mac[SSH_HMAC_SHA512_LEN])
61{
63 ssh_hmac_sha512_init(&ctx, key, key_len);
64 ssh_hmac_sha512_update(&ctx, data, len);
65 ssh_hmac_sha512_final(&ctx, mac);
66}
void ssh_hmac_sha512_final(SshHmacSha512Ctx *ctx, uint8_t mac[SSH_HMAC_SHA512_LEN])
Finish, writing the 64-byte MAC.
void ssh_hmac_sha512(const uint8_t *key, size_t key_len, const uint8_t *data, size_t len, uint8_t mac[SSH_HMAC_SHA512_LEN])
One-shot HMAC-SHA2-512 over a single buffer.
void ssh_hmac_sha512_init(SshHmacSha512Ctx *ctx, const uint8_t *key, size_t key_len)
Begin an HMAC-SHA2-512 over key (keys > 128 bytes are pre-hashed per RFC 2104).
void ssh_hmac_sha512_update(SshHmacSha512Ctx *ctx, const uint8_t *data, size_t len)
Feed len message bytes.
HMAC-SHA2-512 (RFC 2104 + FIPS 198-1).
#define SSH_HMAC_SHA512_LEN
HMAC-SHA2-512 output length in bytes.
void ssh_sha512_final(SshSha512Ctx *ctx, uint8_t digest[SSH_SHA512_DIGEST_LEN])
Finalize the hash and write the 64-byte digest. The context is undefined afterwards; call init() agai...
void ssh_sha512_init(SshSha512Ctx *ctx)
Initialize a streaming SHA-512 context (ctx must not be NULL).
void ssh_sha512(const uint8_t *data, size_t len, uint8_t digest[SSH_SHA512_DIGEST_LEN])
One-shot SHA-512: hash len bytes of data into digest (64 bytes).
void ssh_sha512_update(SshSha512Ctx *ctx, const uint8_t *data, size_t len)
Feed len bytes of data into the running hash.
#define SSH_SHA512_DIGEST_LEN
SHA-512 digest length in bytes.
Definition ssh_sha512.h:24
#define SSH_SHA512_BLOCK_LEN
SHA-512 block size in bytes.
Definition ssh_sha512.h:27
Streaming HMAC-SHA2-512 context (stores the opad key block + inner hash state).
SshSha512Ctx inner
inner hash: H((key XOR ipad) || message)
uint8_t okey[SSH_SHA512_BLOCK_LEN]
(key XOR opad), applied in the final step
Streaming SHA-512 context.
Definition ssh_sha512.h:33