DeterministicESPAsyncWebServer v6.27.1
Zero-allocation, bounded-execution async HTTP server for ESP32
Loading...
Searching...
No Matches
ssh_hmac_sha256.h
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_sha256.h
6 * @brief HMAC-SHA2-256 (RFC 2104 + FIPS 198-1).
7 *
8 * Used for SSH binary packet MAC in both directions after key exchange.
9 *
10 * MAC computation (RFC 4253 §6.4):
11 * mac = HMAC-SHA256(mac_key, uint32_be(seq_num) || plaintext_packet)
12 *
13 * where plaintext_packet = packet_length || padding_length || payload || padding
14 * (the unencrypted bytes - MAC is computed over plaintext before encryption).
15 *
16 * SECURITY NOTE - MAC must be verified before plaintext is acted upon.
17 * ssh_packet.cpp enforces this order: decrypt → verify → dispatch. The
18 * functions in this file are pure crypto; the ordering guarantee lives in
19 * the packet layer.
20 *
21 * @author Douglas Quigg (dstroy0)
22 * @date 2026
23 */
24
25#ifndef DETERMINISTICESPASYNCWEBSERVER_SSH_HMAC_SHA256_H
26#define DETERMINISTICESPASYNCWEBSERVER_SSH_HMAC_SHA256_H
27
29#include <stddef.h>
30#include <stdint.h>
31
32/** @brief HMAC-SHA2-256 output length in bytes. */
33#define SSH_HMAC_SHA256_LEN 32
34
35/**
36 * @brief Compute HMAC-SHA2-256 over a single contiguous buffer.
37 *
38 * Equivalent to calling the streaming variant with one update call.
39 *
40 * @param key MAC key bytes.
41 * @param key_len Key length in bytes (must be ≤ 64; keys > 64 bytes are
42 * pre-hashed per RFC 2104; keys ≤ 64 bytes are zero-padded
43 * to the block length). SSH-derived keys are always 32 bytes.
44 * @param data Input bytes.
45 * @param len Input length.
46 * @param mac Output buffer, must be SSH_HMAC_SHA256_LEN bytes.
47 */
48void ssh_hmac_sha256(const uint8_t *key, size_t key_len, const uint8_t *data, size_t len,
49 uint8_t mac[SSH_HMAC_SHA256_LEN]);
50
51/**
52 * @brief Streaming HMAC-SHA2-256 context.
53 *
54 * For the packet MAC where data arrives in two separate pieces:
55 * 1. 4-byte big-endian sequence number
56 * 2. plaintext packet bytes
57 *
58 * Usage:
59 * ssh_hmac_sha256_init(&ctx, key);
60 * ssh_hmac_sha256_update(&ctx, seq_bytes, 4);
61 * ssh_hmac_sha256_update(&ctx, packet, pkt_len);
62 * ssh_hmac_sha256_final(&ctx, mac_out);
63 */
65{
66 SshSha256Ctx inner; ///< Inner hash context (key XOR ipad prepended).
67 uint8_t okey[64]; ///< Outer key block (key XOR opad), stored for final step.
68};
69
70/**
71 * @brief Initialize a streaming HMAC-SHA2-256 context.
72 *
73 * @param ctx Context to initialize.
74 * @param key Key bytes (≤ 64; keys > 64 are pre-hashed per RFC 2104).
75 * @param key_len Length of key in bytes.
76 */
77void ssh_hmac_sha256_init(SshHmacCtx *ctx, const uint8_t *key, size_t key_len);
78
79/** @brief Feed @p len bytes into the running HMAC. */
80void ssh_hmac_sha256_update(SshHmacCtx *ctx, const uint8_t *data, size_t len);
81
82/** @brief Finalize and write the 32-byte MAC. */
84
85#endif // DETERMINISTICESPASYNCWEBSERVER_SSH_HMAC_SHA256_H
void ssh_hmac_sha256_final(SshHmacCtx *ctx, uint8_t mac[SSH_HMAC_SHA256_LEN])
Finalize and write the 32-byte MAC.
void ssh_hmac_sha256_init(SshHmacCtx *ctx, const uint8_t *key, size_t key_len)
Initialize a streaming HMAC-SHA2-256 context.
#define SSH_HMAC_SHA256_LEN
HMAC-SHA2-256 output length in bytes.
void ssh_hmac_sha256_update(SshHmacCtx *ctx, const uint8_t *data, size_t len)
Feed len bytes into the running HMAC.
void ssh_hmac_sha256(const uint8_t *key, size_t key_len, const uint8_t *data, size_t len, uint8_t mac[SSH_HMAC_SHA256_LEN])
Compute HMAC-SHA2-256 over a single contiguous buffer.
SHA-256 (FIPS 180-4) - streaming context and one-shot API.
Streaming HMAC-SHA2-256 context.
SshSha256Ctx inner
Inner hash context (key XOR ipad prepended).
uint8_t okey[64]
Outer key block (key XOR opad), stored for final step.
Streaming SHA-256 context.
Definition ssh_sha256.h:44