29 uint8_t secret[32] = {};
30 size_t secret_len = 0;
38bool ct_equal(
const char *a,
const char *b,
size_t n)
41 for (
size_t i = 0; i < n; i++)
42 diff |= (uint8_t)(a[i] ^ b[i]);
47void sign_nonce(
const CsrfCtx &c,
const uint8_t *nonce,
size_t nlen,
char *sig_hex)
56void csrf_set_secret(
const uint8_t *secret,
size_t len)
60 s_csrf.secret_len = 0;
63 s_csrf.secret_len = len >
sizeof(s_csrf.secret) ?
sizeof(s_csrf.secret) : len;
64 memcpy(s_csrf.secret, secret, s_csrf.secret_len);
67int csrf_issue(
char *out,
size_t cap)
69 if (s_csrf.secret_len == 0 || !out || cap < CSRF_TOKEN_BUF)
72 uint8_t nonce[CSRF_NONCE_BYTES];
73 uint64_t c = ++s_csrf.counter;
74 for (
size_t i = 0; i < CSRF_NONCE_BYTES; i++)
75 nonce[i] = (uint8_t)(c >> (8 * i));
77 char nhex[CSRF_NONCE_BYTES * 2 + 1];
78 char shex[CSRF_SIG_BYTES * 2 + 1];
80 sign_nonce(s_csrf, nonce, CSRF_NONCE_BYTES, shex);
82 int n = snprintf(out, cap,
"%s.%s", nhex, shex);
83 return (n > 0 && (
size_t)n < cap) ? n : 0;
86bool csrf_verify(
const char *token)
88 if (s_csrf.secret_len == 0 || !token)
91 const char *dot = strchr(token,
'.');
95 size_t nhexlen = (size_t)(dot - token);
96 if (nhexlen != CSRF_NONCE_BYTES * 2)
99 uint8_t nonce[CSRF_NONCE_BYTES];
100 if (
det_hex_decode(token, nhexlen, nonce,
sizeof(nonce)) != CSRF_NONCE_BYTES)
103 const char *sig = dot + 1;
104 if (strnlen(sig, CSRF_SIG_BYTES * 2 + 1) != CSRF_SIG_BYTES * 2)
107 char expect[CSRF_SIG_BYTES * 2 + 1];
108 sign_nonce(s_csrf, nonce, CSRF_NONCE_BYTES, expect);
109 return ct_equal(sig, expect, CSRF_SIG_BYTES * 2);
114 memset(s_csrf.secret, 0,
sizeof(s_csrf.secret));
115 s_csrf.secret_len = 0;
Stateless HMAC-signed CSRF token (DETWS_ENABLE_CSRF).
Tiny no-stdlib hex encode / decode / nibble helpers (one shared copy).
int det_hex_decode(const char *in, size_t hexlen, uint8_t *out, size_t out_cap)
Decode exactly hexlen hex chars into out (hexlen/2 bytes).
void det_hex_encode(const uint8_t *in, size_t n, char *out, bool upper=false)
Encode n bytes as 2*n hex chars + NUL into out (needs cap >= 2*n+1).
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.
HMAC-SHA2-256 (RFC 2104 + FIPS 198-1).
#define SSH_HMAC_SHA256_LEN
HMAC-SHA2-256 output length in bytes.