WireGuard プロトコル層実装

鍵導出チェーン (KDF):
- wg_kdf_init(): 初期化(ゼロ鍵)
- wg_kdf1(): IKM -> CK1, TK1(最初の導出)
- wg_kdf2(): CK, TK1 -> CK2, TK2(2 番目の導出)
- wg_kdf3(): CK, TK2, data -> CK3(データ混合)

ハンドシェイクメッセージ構造:
- wg_handshake_init (148 bytes): Initiation message
- wg_handshake_resp (92 bytes): Response message
- wg_cookie_reply (64 bytes): Cookie reply

実装詳細:
- RFC 5861 HKDF ベース
- WireGuard 固有ラベル (K1, K2, K3)
- チェーン鍵 (Ck) とセッション鍵 (tk) の導出

テスト:
- tests/test_wireguard_kdf.c (5/5 PASS)
- 完全なハンドシェイクチェーンシミュレーション
This commit is contained in:
km
2026-03-26 21:17:38 +09:00
parent 0c9237324e
commit c9844dc0ba
4 changed files with 318 additions and 1 deletions
+104
View File
@@ -0,0 +1,104 @@
/**
* @file se050_wireguard_proto.c
* @brief WireGuard Protocol Layer Implementation
* Key derivation chains and handshake processing
*/
#include "se050_wireguard_proto.h"
#include "se050_hkdf_blake2s.h"
#include "se050_tai64n.h"
#include <string.h>
#define WG_LABEL_K1 "WireGuard key K1"
#define WG_LABEL_K2 "WireGuard key K2"
#define WG_LABEL_K3 "WireGuard key K3"
void wg_kdf_init(uint8_t ck[32], uint8_t tk[32])
{
memset(ck, 0, 32);
if (tk) {
memset(tk, 0, 32);
}
}
void wg_kdf1(uint8_t ck[32], uint8_t tk1[32],
const uint8_t ikm[32], size_t ikmlen)
{
uint8_t prk[32];
uint8_t okm[64];
/* HKDF-Extract */
se050_hkdf_extract(prk, NULL, 0, ikm, ikmlen);
/* HKDF-Expand with label K1 */
se050_hkdf_expand(okm, 64, prk,
(const uint8_t*)WG_LABEL_K1,
sizeof(WG_LABEL_K1) - 1);
memcpy(ck, okm, 32);
memcpy(tk1, okm + 32, 32);
memset(prk, 0, 32);
memset(okm, 0, 64);
}
void wg_kdf2(uint8_t ck[32], uint8_t tk2[32],
const uint8_t ck_old[32], const uint8_t tk1[32])
{
uint8_t prk[32];
uint8_t okm[64];
uint8_t input[64];
/* Mix old chain key with temp key */
memcpy(input, ck_old, 32);
memcpy(input + 32, tk1, 32);
/* HKDF-Extract */
se050_hkdf_extract(prk, NULL, 0, input, 64);
/* HKDF-Expand with label K2 */
se050_hkdf_expand(okm, 64, prk,
(const uint8_t*)WG_LABEL_K2,
sizeof(WG_LABEL_K2) - 1);
memcpy(ck, okm, 32);
memcpy(tk2, okm + 32, 32);
memset(prk, 0, 32);
memset(okm, 0, 64);
memset(input, 0, 64);
}
void wg_kdf3(uint8_t ck[32], uint8_t tk3[32],
const uint8_t ck_old[32], const uint8_t tk2[32],
const uint8_t *data, size_t datalen)
{
uint8_t prk[32];
uint8_t okm[32];
uint8_t input[64];
/* Mix old chain key with temp key */
memcpy(input, ck_old, 32);
memcpy(input + 32, tk2, 32);
/* HKDF-Extract with data */
se050_hkdf_extract(prk, NULL, 0, input, 64);
/* HKDF-Expand with label K3 and data */
uint8_t info[64 + sizeof(WG_LABEL_K3)];
memcpy(info, WG_LABEL_K3, sizeof(WG_LABEL_K3) - 1);
if (data && datalen > 0) {
memcpy(info + sizeof(WG_LABEL_K3) - 1, data, datalen);
}
se050_hkdf_expand(okm, 32, prk,
info,
sizeof(WG_LABEL_K3) - 1 + datalen);
memcpy(ck, okm, 32);
memset(tk3, 0, 32); /* tk3 is not used, just zero */
memset(prk, 0, 32);
memset(okm, 0, 32);
memset(input, 0, 64);
memset(info, 0, sizeof(info));
}