TAI64N ハードウェア実装追加
- SE050 モノトニックカウンタ使用 - リプレイ防止用タイムスタンプ - テスト実装済み
This commit is contained in:
@@ -8,7 +8,8 @@ SRCS = src/se050_i2c_hal.c src/se050_session.c src/se050_keystore.c \
|
||||
src/se050_rng.c src/se050_x25519.c src/se050_x25519_sw.c \
|
||||
src/se050_chacha20_poly1305.c src/se050_blake2s.c \
|
||||
src/se050_hmac_blake2s.c src/se050_hkdf_blake2s.c src/se050_tai64n.c \
|
||||
src/se050_scp03.c src/se050_scp03_keys.c src/se050_wireguard_proto.c
|
||||
src/se050_scp03.c src/se050_scp03_keys.c src/se050_wireguard_proto.c \
|
||||
src/se050_tai64n_hw.c
|
||||
|
||||
OBJS = $(SRCS:.c=.o)
|
||||
LIB = libse050_wireguard.a
|
||||
@@ -51,3 +52,26 @@ test: all test_wireguard_kdf
|
||||
@./build/test_hmac_blake2s
|
||||
@./build/test_hkdf_blake2s
|
||||
@./build/test_wireguard_kdf
|
||||
|
||||
# SE050 Hardware TAI64N test
|
||||
test_tai64n_hw: tests/test_tai64n_hw.c $(LIB)
|
||||
@mkdir -p build
|
||||
$(CC) $(CFLAGS) -DTEST_MODE -o build/$@ $< build/$(LIB)
|
||||
|
||||
test: all test_wireguard_kdf test_tai64n_hw
|
||||
@./build/test_blake2s
|
||||
@./build/test_hmac_blake2s
|
||||
@./build/test_hkdf_blake2s
|
||||
@./build/test_wireguard_kdf
|
||||
@./build/test_tai64n_hw
|
||||
|
||||
# X25519 software test
|
||||
test_x25519_sw: tests/test_x25519_ecdh.c $(LIB)
|
||||
@mkdir -p build
|
||||
$(CC) $(CFLAGS) -DX25519_SW_TEST -o build/$@ $< build/$(LIB)
|
||||
|
||||
test: all test_x25519_sw test_tai64n_hw
|
||||
@./build/test_blake2s
|
||||
@./build/test_hmac_blake2s
|
||||
@./build/test_hkdf_blake2s
|
||||
@./build/test_x25519_sw
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
/**
|
||||
* @file se050_tai64n_hw.h
|
||||
* @brief TAI64N using SE050 Hardware Monotonic Counter
|
||||
*
|
||||
* Uses SE050's built-in monotonic counter for replay prevention.
|
||||
* Object ID: SE05X_OBJ_ID_MONOTONIC_COUNTER (0x7FFF0203)
|
||||
*/
|
||||
|
||||
#ifndef SE050_TAI64N_HW_H
|
||||
#define SE050_TAI64N_HW_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define TAI64N_HW_SIZE 12
|
||||
#define SE050_MONOTONIC_COUNTER_ID 0x7FFF0203
|
||||
|
||||
/* Session handle type (opaque) */
|
||||
typedef void* se050_session_t;
|
||||
|
||||
/* Mock session for testing */
|
||||
typedef struct {
|
||||
uint32_t counter;
|
||||
} mock_session_t;
|
||||
|
||||
/**
|
||||
* @brief Read SE050 monotonic counter and encode as TAI64N
|
||||
* @param session SE050 session handle
|
||||
* @param out Output buffer (12 bytes)
|
||||
* @return 0 on success, -1 on error
|
||||
*/
|
||||
int se050_tai64n_hw_now(void *session, uint8_t out[12]);
|
||||
|
||||
/**
|
||||
* @brief Read SE050 monotonic counter only (32-bit)
|
||||
* @param session SE050 session handle
|
||||
* @param counter Output counter value
|
||||
* @return 0 on success, -1 on error
|
||||
*/
|
||||
int se050_tai64n_hw_read_counter(void *session, uint32_t *counter);
|
||||
|
||||
/**
|
||||
* @brief Increment SE050 monotonic counter
|
||||
* @param session SE050 session handle
|
||||
* @return 0 on success, -1 on error
|
||||
*/
|
||||
int se050_tai64n_hw_increment(void *session);
|
||||
|
||||
/**
|
||||
* @brief Check if timestamp is within acceptable window
|
||||
* @param timestamp Received TAI64N timestamp
|
||||
* @param current Current TAI64N timestamp
|
||||
* @param window Acceptable window in seconds
|
||||
* @return 1 if valid, 0 if expired/replay, -1 on error
|
||||
*/
|
||||
int se050_tai64n_hw_check_window(const uint8_t timestamp[12],
|
||||
const uint8_t current[12],
|
||||
uint32_t window);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* SE050_TAI64N_HW_H */
|
||||
@@ -0,0 +1,121 @@
|
||||
/**
|
||||
* @file se050_tai64n_hw.c
|
||||
* @brief TAI64N using SE050 Hardware Monotonic Counter
|
||||
*/
|
||||
|
||||
#include "se050_tai64n_hw.h"
|
||||
#include <string.h>
|
||||
|
||||
/* SE050 API - defined in test file or linked from SE050 library */
|
||||
extern int Se05x_API_ReadCounter(void *session, uint32_t obj_id, uint32_t *counter);
|
||||
extern int Se05x_API_IncrementCounter(void *session, uint32_t obj_id);
|
||||
|
||||
#define TAI64N_BASE_UPPER 0x40000000ULL
|
||||
|
||||
static void store64_be(uint8_t *out, uint64_t val)
|
||||
{
|
||||
out[0] = (uint8_t)(val >> 56);
|
||||
out[1] = (uint8_t)(val >> 48);
|
||||
out[2] = (uint8_t)(val >> 40);
|
||||
out[3] = (uint8_t)(val >> 32);
|
||||
out[4] = (uint8_t)(val >> 24);
|
||||
out[5] = (uint8_t)(val >> 16);
|
||||
out[6] = (uint8_t)(val >> 8);
|
||||
out[7] = (uint8_t)(val);
|
||||
}
|
||||
|
||||
static uint32_t load32_be(const uint8_t *in)
|
||||
{
|
||||
return ((uint32_t)in[0] << 24) |
|
||||
((uint32_t)in[1] << 16) |
|
||||
((uint32_t)in[2] << 8) |
|
||||
((uint32_t)in[3]);
|
||||
}
|
||||
|
||||
int se050_tai64n_hw_read_counter(void *session, uint32_t *counter)
|
||||
{
|
||||
if (!session || !counter) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* SE050 API call to read monotonic counter */
|
||||
/* This uses the actual SE050 hardware counter */
|
||||
uint32_t obj_id = SE050_MONOTONIC_COUNTER_ID;
|
||||
int status = Se05x_API_ReadCounter(session, obj_id, counter);
|
||||
|
||||
if (status != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int se050_tai64n_hw_increment(void *session)
|
||||
{
|
||||
if (!session) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* SE050 API call to increment counter */
|
||||
uint32_t obj_id = SE050_MONOTONIC_COUNTER_ID;
|
||||
int status = Se05x_API_IncrementCounter(session, obj_id);
|
||||
|
||||
if (status != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int se050_tai64n_hw_now(void *session, uint8_t out[12])
|
||||
{
|
||||
uint32_t counter;
|
||||
uint64_t tai64_upper;
|
||||
uint32_t unix_sec;
|
||||
|
||||
if (!session || !out) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Read SE050 monotonic counter */
|
||||
if (se050_tai64n_hw_read_counter(session, &counter) != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Use counter as lower 32 bits of nanoseconds */
|
||||
/* Upper 32 bits: TAI base + approximate Unix seconds */
|
||||
unix_sec = counter / 1000000000UL; /* Approximate seconds from counter */
|
||||
tai64_upper = TAI64N_BASE_UPPER + unix_sec;
|
||||
|
||||
/* Encode as TAI64N: 64-bit TAI + 32-bit nanoseconds */
|
||||
store64_be(out, tai64_upper << 32);
|
||||
store64_be(out + 8, counter);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int se050_tai64n_hw_check_window(const uint8_t timestamp[12],
|
||||
const uint8_t current[12],
|
||||
uint32_t window)
|
||||
{
|
||||
uint32_t ts_counter, curr_counter;
|
||||
int32_t diff;
|
||||
|
||||
if (!timestamp || !current) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Compare monotonic counter values (lower 32 bits) */
|
||||
ts_counter = load32_be(timestamp + 8);
|
||||
curr_counter = load32_be(current + 8);
|
||||
|
||||
/* Check if within window (counter difference) */
|
||||
diff = (int32_t)(curr_counter - ts_counter);
|
||||
if (diff < 0) diff = -diff;
|
||||
|
||||
/* Window in counter units (assuming ~1 increment per nanosecond) */
|
||||
/* For practical use: window in seconds * 1000000000 */
|
||||
uint32_t window_units = window * 1000000000UL;
|
||||
|
||||
return (diff <= (int32_t)window_units) ? 1 : 0;
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include "se050_tai64n_hw.h"
|
||||
|
||||
/* Mock SE050 API functions */
|
||||
int Se05x_API_ReadCounter(void *session, uint32_t obj_id, uint32_t *counter)
|
||||
{
|
||||
(void)obj_id;
|
||||
if (session) {
|
||||
mock_session_t *s = (mock_session_t*)session;
|
||||
*counter = s->counter;
|
||||
} else {
|
||||
*counter = 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Se05x_API_IncrementCounter(void *session, uint32_t obj_id)
|
||||
{
|
||||
(void)session;
|
||||
(void)obj_id;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void print_hex(const char *label, const uint8_t *buf, size_t len)
|
||||
{
|
||||
printf("%s: ", label);
|
||||
for (size_t i = 0; i < len; i++) printf("%02x", buf[i]);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
uint8_t tai64n[12];
|
||||
uint32_t counter;
|
||||
uint8_t current[12];
|
||||
int passed = 0;
|
||||
|
||||
printf("SE050 Hardware TAI64N Test Suite\n");
|
||||
printf("==================================\n\n");
|
||||
|
||||
printf("Test 1: Read Counter\n");
|
||||
mock_session_t session = { .counter = 1234567890UL };
|
||||
if (se050_tai64n_hw_read_counter(&session, &counter) == 0) {
|
||||
printf("Counter: %u (0x%08x)\n", counter, counter);
|
||||
printf("[PASS]\n\n"); passed++;
|
||||
} else {
|
||||
printf("[FAIL]\n\n");
|
||||
}
|
||||
|
||||
printf("Test 2: TAI64N Now\n");
|
||||
if (se050_tai64n_hw_now(&session, tai64n) == 0) {
|
||||
print_hex("TAI64N", tai64n, 12);
|
||||
printf("[PASS]\n\n"); passed++;
|
||||
} else {
|
||||
printf("[FAIL]\n\n");
|
||||
}
|
||||
|
||||
printf("Test 3: Increment Counter\n");
|
||||
uint32_t before = session.counter;
|
||||
if (se050_tai64n_hw_increment(&session) == 0) {
|
||||
printf("Before: %u, After: %u\n", before, session.counter);
|
||||
printf("[PASS]\n\n"); passed++;
|
||||
} else {
|
||||
printf("[FAIL]\n\n");
|
||||
}
|
||||
|
||||
printf("Test 4: Window Check\n");
|
||||
se050_tai64n_hw_now(&session, tai64n);
|
||||
se050_tai64n_hw_now(&session, current);
|
||||
int result = se050_tai64n_hw_check_window(tai64n, current, 60);
|
||||
printf("Window check (60s): %s\n",
|
||||
result == 1 ? "PASS (within window)" : "FAIL");
|
||||
if (result == 1) {
|
||||
printf("[PASS]\n\n"); passed++;
|
||||
} else {
|
||||
printf("[FAIL]\n\n");
|
||||
}
|
||||
|
||||
printf("Test 5: Replay Detection\n");
|
||||
uint8_t old_timestamp[12];
|
||||
session.counter = 1000000000UL; /* Reset to old value (1 second) */
|
||||
se050_tai64n_hw_now(&session, old_timestamp);
|
||||
|
||||
session.counter = 1060000000UL; /* 60 seconds later */
|
||||
se050_tai64n_hw_now(&session, current);
|
||||
|
||||
result = se050_tai64n_hw_check_window(old_timestamp, current, 30);
|
||||
printf("Old timestamp (60s old), window=30s: %s\n",
|
||||
result == 0 ? "REJECTED (expired)" : "ACCEPTED");
|
||||
if (result == 0) {
|
||||
printf("[PASS] Replay correctly detected\n\n"); passed++;
|
||||
} else {
|
||||
printf("[FAIL]\n\n");
|
||||
}
|
||||
|
||||
printf("==================================\n");
|
||||
printf("Passed: %d/5\n", passed);
|
||||
printf("==================================\n");
|
||||
|
||||
return (passed == 5) ? 0 : 1;
|
||||
}
|
||||
Reference in New Issue
Block a user