HMAC-BLAKE2s, HKDF, TAI64N 実装追加

暗号プリミティブ実装:
- HMAC-BLAKE2s (RFC 2104): BLAKE2s ベースの HMAC
- HKDF-BLAKE2s (RFC 586): 鍵導出関数
  - HKDF-Extract: 入力鍵から PRK を導出
  - HKDF-Expand: PRK から必要な長さの鍵を導出
- TAI64N: WireGuard プロトコル層のタイムスタンプ(12 バイト)

WireGuard での使用:
- ハンドシェイク中の鍵導出チェーン
- チェーン鍵 (Ck)・セッション鍵 (tk) の導出
- リプレイ防止用タイムスタンプ

テスト:
- test_hmac_blake2s: HMAC-BLAKE2s 検証 
- test_hkdf_blake2s: HKDF 検証 
- test_tai64n: TAI64N エンコード/デコード 
This commit is contained in:
km
2026-03-26 21:03:27 +09:00
parent b83394f37b
commit c892e6ca01
11 changed files with 695 additions and 3 deletions
+63
View File
@@ -0,0 +1,63 @@
/**
* @file se050_hkdf_blake2s.h
* @brief HKDF Implementation using HMAC-BLAKE2s (RFC 586)
*/
#ifndef SE050_HKDF_BLAKE2S_H
#define SE050_HKDF_BLAKE2S_H
#include <stdint.h>
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief HKDF-Extract (RFC 586 Section 2.2)
* @param prk Output pseudorandom key (32 bytes)
* @param salt Salt value (can be NULL for zero salt)
* @param saltlen Salt length
* @param ikm Input keying material
* @param ikmlen Input keying material length
* @return 0 on success, -1 on error
*/
int se050_hkdf_extract(uint8_t prk[32],
const uint8_t *salt, size_t saltlen,
const uint8_t *ikm, size_t ikmlen);
/**
* @brief HKDF-Expand (RFC 586 Section 2.3)
* @param okm Output keying material
* @param okmlen Output keying material length (max 255 * 32 bytes)
* @param prk Pseudorandom key from Extract
* @param info Application-specific context
* @param infolen Info length
* @return 0 on success, -1 on error
*/
int se050_hkdf_expand(uint8_t *okm, size_t okmlen,
const uint8_t prk[32],
const uint8_t *info, size_t infolen);
/**
* @brief HKDF (combined Extract + Expand)
* @param okm Output keying material
* @param okmlen Output keying material length
* @param salt Salt value (can be NULL)
* @param saltlen Salt length
* @param ikm Input keying material
* @param ikmlen Input keying material length
* @param info Application-specific context
* @param infolen Info length
* @return 0 on success, -1 on error
*/
int se050_hkdf(uint8_t *okm, size_t okmlen,
const uint8_t *salt, size_t saltlen,
const uint8_t *ikm, size_t ikmlen,
const uint8_t *info, size_t infolen);
#ifdef __cplusplus
}
#endif
#endif /* SE050_HKDF_BLAKE2S_H */
+50
View File
@@ -0,0 +1,50 @@
/**
* @file se050_hmac_blake2s.h
* @brief HMAC-BLAKE2s Implementation (RFC 2104)
*/
#ifndef SE050_HMAC_BLAKE2S_H
#define SE050_HMAC_BLAKE2S_H
#include <stdint.h>
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
#define HMAC_BLAKE2S_BLOCK_SIZE 64
#define HMAC_BLAKE2S_DIGEST_SIZE 32
/**
* @brief Compute HMAC-BLAKE2s
* @param out Output buffer (32 bytes)
* @param key Key data
* @param keylen Key length (1-64 bytes)
* @param data Input data
* @param datalen Input data length
* @return 0 on success, -1 on error
*/
int se050_hmac_blake2s(uint8_t out[32],
const uint8_t *key, size_t keylen,
const uint8_t *data, size_t datalen);
/**
* @brief One-shot HMAC-BLAKE2s with variable output length
* @param out Output buffer
* @param outlen Output length (1-32 bytes)
* @param key Key data
* @param keylen Key length
* @param data Input data
* @param datalen Input data length
* @return 0 on success, -1 on error
*/
int se050_hmac_blake2s_variable(uint8_t *out, size_t outlen,
const uint8_t *key, size_t keylen,
const uint8_t *data, size_t datalen);
#ifdef __cplusplus
}
#endif
#endif /* SE050_HMAC_BLAKE2S_H */
+68
View File
@@ -0,0 +1,68 @@
/**
* @file se050_tai64n.h
* @brief TAI64N Timestamp Encoding (WireGuard Protocol Layer)
* RFC 7539 Section 7.2.1
*/
#ifndef SE050_TAI64N_H
#define SE050_TAI64N_H
#include <stdint.h>
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
#define TAI64N_SIZE 12
#define TAI64_BASE 0x4000000000000010ULL
/**
* @brief TAI64N timestamp structure (12 bytes)
*/
typedef struct {
uint64_t tai64; /* TAI64 timestamp (8 bytes) */
uint32_t nanosec; /* Nanoseconds (4 bytes) */
} __attribute__((packed)) tai64n_t;
/**
* @brief Encode current time as TAI64N
* @param out Output buffer (12 bytes)
* @return 0 on success, -1 on error
*/
int se050_tai64n_now(uint8_t out[TAI64N_SIZE]);
/**
* @brief Encode a TAI64N timestamp
* @param out Output buffer (12 bytes)
* @param seconds Unix timestamp (seconds since 1970-01-01)
* @param nanoseconds Nanoseconds (0-999999999)
* @return 0 on success, -1 on error
*/
int se050_tai64n_encode(uint8_t out[TAI64N_SIZE],
uint64_t seconds, uint32_t nanoseconds);
/**
* @brief Decode a TAI64N timestamp
* @param seconds Output Unix timestamp (seconds)
* @param nanoseconds Output nanoseconds
* @param in Input buffer (12 bytes)
* @return 0 on success, -1 on error
*/
int se050_tai64n_decode(uint64_t *seconds, uint32_t *nanoseconds,
const uint8_t in[TAI64N_SIZE]);
/**
* @brief Check if TAI64N timestamp is within acceptable window
* @param timestamp Timestamp to check
* @param window_sec Acceptable window in seconds
* @return 0 if within window, -1 if too old, -2 if too far in future
*/
int se050_tai64n_check_window(const uint8_t timestamp[TAI64N_SIZE],
uint32_t window_sec);
#ifdef __cplusplus
}
#endif
#endif /* SE050_TAI64N_H */