diff --git a/include/se050_wireguard.h b/include/se050_wireguard.h index 43a6a17..da2b846 100644 --- a/include/se050_wireguard.h +++ b/include/se050_wireguard.h @@ -51,6 +51,7 @@ typedef struct se050_wireguard_session { /* State flags */ int is_initiator; int handshake_complete; + int packets_received; /* Number of packets received (for replay detection) */ } se050_wireguard_session_t; /* ========================================================================= diff --git a/src/se050_wireguard.c b/src/se050_wireguard.c index d6ed00e..5e9cb0e 100644 --- a/src/se050_wireguard.c +++ b/src/se050_wireguard.c @@ -89,6 +89,30 @@ static void wg_hkdf_1(const uint8_t *prk, size_t prk_len, wg_hkdf_expand(prk, prk_len, out1, out2); } +/* Compute HKDF-3 (three outputs) - WireGuard style */ +static void wg_hkdf_3(const uint8_t *prk, size_t prk_len, + uint8_t *out1, uint8_t *out2, uint8_t *out3) +{ + /* T(1) = HMAC(PRK, 0x01) */ + uint8_t c1 = 0x01; + se050_hmac_blake2s(out1, prk, prk_len, &c1, 1); + + /* T(2) = HMAC(PRK, T(1) || 0x02) */ + uint8_t t2_input[33]; + memcpy(t2_input, out1, 32); + t2_input[32] = 0x02; + se050_hmac_blake2s(out2, prk, prk_len, t2_input, 33); + + /* T(3) = HMAC(PRK, T(2) || 0x03) */ + uint8_t t3_input[33]; + memcpy(t3_input, out2, 32); + t3_input[32] = 0x03; + se050_hmac_blake2s(out3, prk, prk_len, t3_input, 33); + + memzero_explicit(t2_input, 33); + memzero_explicit(t3_input, 33); +} + /* ========================================================================= * Session Management * ========================================================================= */ @@ -273,9 +297,8 @@ int se050_wireguard_decrypt_packet(se050_wireguard_session_t *session, nonce |= ((uint64_t)packet[8 + i]) << (8 * i); } - /* Check replay (simple check - should use window in production) */ - /* Allow nonce == receiving_nonce for first packet (both start at 0) */ - if (nonce <= session->receiving_nonce && session->receiving_nonce != 0) { + /* Check replay - strictly reject nonce <= last received nonce */ + if (session->packets_received > 0 && nonce <= session->receiving_nonce) { return -1; /* Replay detected */ } @@ -310,6 +333,7 @@ int se050_wireguard_decrypt_packet(se050_wireguard_session_t *session, /* Update plaintext length and nonce */ *plaintext_len = ciphertext_len; session->receiving_nonce = nonce; + session->packets_received++; return 0; }