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:
@@ -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));
|
||||
}
|
||||
Reference in New Issue
Block a user