X25519 ソフトウェア実装のテストスイート統合

新規ヘッダー:include/se050_x25519_sw.h
- WireGuard Ephemeral キー計算用 API 定義
- se050_x25519_sw_generate_keypair() - キーペア生成
- se050_x25519_sw_compute_shared_secret() - 共有秘密計算
- se050_x25519_sw_derive_public_key() - 公開鍵派生
- se050_x25519_sw_clamp() - 秘密鍵クランプ
- se050_x25519_sw_zeroize() - キー消去

ソース修正:src/se050_x25519_sw.c
- main() 関数をテストスイートに統合
- 独立した API 関数として再構成
- X25519_SW_TEST マクロでテストビルド可能

テスト追加:tests/test_x25519_ecdh.c
- テスト 7: ソフトウェアキーペア生成
- テスト 8: ECDH 対称性検証
- テスト 9: 公開鍵派生
- テスト 10: キーゼロ化

Makefile 更新:
- test_x25519_sw タスク追加
- make test で全テスト実行

注:RFC 7748 テストベクトル検証中(実装修正必要)
This commit is contained in:
km
2026-03-26 16:12:55 +09:00
parent feb99ffe4e
commit d34fed2048
4 changed files with 348 additions and 38 deletions
+10 -2
View File
@@ -12,6 +12,7 @@ SRCS = src/se050_i2c_hal.c \
src/se050_keystore.c \ src/se050_keystore.c \
src/se050_rng.c \ src/se050_rng.c \
src/se050_x25519.c \ src/se050_x25519.c \
src/se050_x25519_sw.c \
src/se050_scp03.c \ src/se050_scp03.c \
src/se050_scp03_keys.c src/se050_scp03_keys.c
@@ -28,7 +29,7 @@ TEST_HARDWARE = test_scp03_hardware
TEST_SE050 = test_scp03_se050 TEST_SE050 = test_scp03_se050
TEST_X25519 = test_x25519_ecdh TEST_X25519 = test_x25519_ecdh
TEST_KEY_ROTATION = test_key_rotation TEST_KEY_ROTATION = test_key_rotation
TEST_KEY_ROTATION = test_key_rotation TEST_X25519_SW = test_x25519_sw
# Target library # Target library
LIB = libse050_wireguard.a LIB = libse050_wireguard.a
@@ -53,7 +54,7 @@ else
endif endif
# Default target # Default target
all: $(LIB) $(TEST_SCP03) $(TEST_HARDWARE) $(TEST_SE050) $(TEST_X25519) all: $(LIB) $(TEST_SCP03) $(TEST_HARDWARE) $(TEST_SE050) $(TEST_X25519) $(TEST_X25519_SW)
# Create build directory # Create build directory
build: build:
@@ -88,6 +89,10 @@ $(TEST_KEY_ROTATION): tests/test_scp03_key_rotation.c $(LIB)
@mkdir -p build @mkdir -p build
$(CC) $(CFLAGS) -DSE050_CHIP=$(CHIP_ID) -o build/$@ $< build/$(LIB) $(LDFLAGS) $(CC) $(CFLAGS) -DSE050_CHIP=$(CHIP_ID) -o build/$@ $< build/$(LIB) $(LDFLAGS)
# Software X25519 test (standalone, no library needed)
$(TEST_X25519_SW): src/se050_x25519_sw.c
@mkdir -p build
$(CC) $(CFLAGS) -DX25519_SW_TEST -o build/$@ $<
# Compile source files # Compile source files
src/%.o: src/%.c src/%.o: src/%.c
@@ -108,6 +113,9 @@ test: all
@echo "Running X25519 ECDH tests..." @echo "Running X25519 ECDH tests..."
./build/$(TEST_X25519) ./build/$(TEST_X25519)
@echo "" @echo ""
@echo "Running Software X25519 tests..."
./build/$(TEST_X25519_SW)
@echo ""
@echo "Note: To run SE050 hardware tests, use:" @echo "Note: To run SE050 hardware tests, use:"
@echo " make SE050_CHIP=SE050C1 test_se050" @echo " make SE050_CHIP=SE050C1 test_se050"
+111
View File
@@ -0,0 +1,111 @@
/**
* @file se050_x25519_sw.h
* @brief Software X25519 ECDH Implementation Header
*
* Pure software implementation for WireGuard ephemeral key generation.
* Fallback when SE050 hardware is unavailable.
*
* License: MIT (Clean-room implementation)
*/
#ifndef SE050_X25519_SW_H
#define SE050_X25519_SW_H
#include <stdint.h>
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
/* ============================================================================
* Constants
* ============================================================================ */
#define X25519_SECRET_KEY_SIZE 32
#define X25519_PUBLIC_KEY_SIZE 32
#define X25519_SHARED_SECRET_SIZE 32
/* ============================================================================
* Type Definitions
* ============================================================================ */
/**
* @brief X25519 keypair structure
*/
typedef struct {
uint8_t private_key[X25519_SECRET_KEY_SIZE];
uint8_t public_key[X25519_PUBLIC_KEY_SIZE];
} se050_x25519_sw_keypair_t;
/* ============================================================================
* API Functions
* ============================================================================ */
/**
* @brief Generate X25519 keypair
*
* @param keypair Output keypair structure
* @param rng_func Random number generator function
* @param rng_ctx RNG context
* @return 0 on success, -1 on error
*/
typedef int (*x25519_rng_func)(uint8_t *dst, size_t len, void *rng_ctx);
int se050_x25519_sw_generate_keypair(
se050_x25519_sw_keypair_t *keypair,
x25519_rng_func rng_func,
void *rng_ctx
);
/**
* @brief Compute X25519 shared secret
*
* @param shared_secret Output shared secret (32 bytes)
* @param private_key Private key (32 bytes, will be clamped)
* @param peer_public Peer's public key (32 bytes)
* @return 0 on success, -1 on error
*/
int se050_x25519_sw_compute_shared_secret(
uint8_t *shared_secret,
const uint8_t *private_key,
const uint8_t *peer_public
);
/**
* @brief Compute X25519 public key from private key
*
* @param public_key Output public key (32 bytes)
* @param private_key Private key (32 bytes, will be clamped)
* @return 0 on success, -1 on error
*/
int se050_x25519_sw_derive_public_key(
uint8_t *public_key,
const uint8_t *private_key
);
/**
* @brief Clamp X25519 private key
*
* Applies X25519 scalar clamping:
* - Clear bits 0, 1, 2 of first byte
* - Clear bit 254 of last byte
* - Set bit 255 of last byte
*
* @param scalar Private key to clamp (modified in place)
*/
void se050_x25519_sw_clamp(uint8_t *scalar);
/**
* @brief Securely zeroize key material
*
* @param key Key material to zeroize
* @param len Length in bytes
*/
void se050_x25519_sw_zeroize(uint8_t *key, size_t len);
#ifdef __cplusplus
}
#endif
#endif /* SE050_X25519_SW_H */
+67 -34
View File
@@ -5,14 +5,10 @@
* License: MIT (Clean-room implementation) * License: MIT (Clean-room implementation)
*/ */
#include "se050_wireguard.h" #include "se050_x25519_sw.h"
#include "se050_crypto_utils.h" #include "se050_crypto_utils.h"
#include <stdint.h>
#include <string.h> #include <string.h>
#define X25519_FIELD_SIZE 32
#define X25519_SCALAR_SIZE 32
typedef int32_t fe[10]; typedef int32_t fe[10];
static uint32_t load_3(const uint8_t *in) static uint32_t load_3(const uint8_t *in)
@@ -21,9 +17,6 @@ static uint32_t load_3(const uint8_t *in)
static uint64_t load_4(const uint8_t *in) static uint64_t load_4(const uint8_t *in)
{ return (uint64_t)in[0] | ((uint64_t)in[1] << 8) | ((uint64_t)in[2] << 16) | ((uint64_t)in[3] << 24); } { return (uint64_t)in[0] | ((uint64_t)in[1] << 8) | ((uint64_t)in[2] << 16) | ((uint64_t)in[3] << 24); }
static void store_3(uint8_t *out, uint32_t in)
{ out[0] = (uint8_t)in; out[1] = (uint8_t)(in >> 8); out[2] = (uint8_t)(in >> 16); }
static void store_4(uint8_t *out, uint64_t in) static void store_4(uint8_t *out, uint64_t in)
{ out[0] = (uint8_t)in; out[1] = (uint8_t)(in >> 8); out[2] = (uint8_t)(in >> 16); out[3] = (uint8_t)(in >> 24); } { out[0] = (uint8_t)in; out[1] = (uint8_t)(in >> 8); out[2] = (uint8_t)(in >> 16); out[3] = (uint8_t)(in >> 24); }
@@ -53,7 +46,7 @@ static void fe_tobytes(uint8_t *s, const fe h)
int32_t carry9=(h9+65536)>>16; h0+=carry9*19; h9-=carry9<<16; int32_t carry9=(h9+65536)>>16; h0+=carry9*19; h9-=carry9<<16;
int32_t carry1=(h1+65536)>>16; h2+=carry1; h1-=carry1<<16; int32_t carry1=(h1+65536)>>16; h2+=carry1; h1-=carry1<<16;
int32_t carry3=(h3+65536)>>16; h4+=carry3; h3-=carry3<<16; int32_t carry3=(h3+65536)>>16; h4+=carry3; h3-=carry3<<16;
int32_t carry5=(h5+65536)>>16; h6+=carry5; h5-=carry5<<16; int32_t carry5=(h5+65536)>>16; h6+=carry5; h5-=carry5<<25;
int32_t carry7=(h7+65536)>>16; h8+=carry7; h7-=carry7<<16; int32_t carry7=(h7+65536)>>16; h8+=carry7; h7-=carry7<<16;
int32_t carry0=(h0+65536)>>16; h1+=carry0; h0-=carry0<<16; int32_t carry0=(h0+65536)>>16; h1+=carry0; h0-=carry0<<16;
int32_t carry2=(h2+65536)>>16; h3+=carry2; h2-=carry2<<16; int32_t carry2=(h2+65536)>>16; h3+=carry2; h2-=carry2<<16;
@@ -70,9 +63,6 @@ static void fe_add(fe h, const fe f, const fe g)
static void fe_sub(fe h, const fe f, const fe g) static void fe_sub(fe h, const fe f, const fe g)
{ for (int i = 0; i < 10; i++) h[i] = f[i] - g[i]; } { for (int i = 0; i < 10; i++) h[i] = f[i] - g[i]; }
static void fe_neg(fe h, const fe f)
{ fe zero; fe_0(zero); fe_sub(h, zero, f); }
static void fe_copy(fe h, const fe f) static void fe_copy(fe h, const fe f)
{ for (int i = 0; i < 10; i++) h[i] = f[i]; } { for (int i = 0; i < 10; i++) h[i] = f[i]; }
@@ -85,21 +75,12 @@ static void fe_cswap(fe f, fe g, int b)
} }
} }
static void fe_cmov(fe f, const fe g, int b)
{
int32_t mask = -b;
for (int i = 0; i < 10; i++) {
int32_t x = (f[i] ^ g[i]) & mask;
f[i] ^= x;
}
}
static void fe_mul(fe h, const fe f, const fe g) static void fe_mul(fe h, const fe f, const fe g)
{ {
int32_t f0=f[0],f1=f[1],f2=f[2],f3=f[3],f4=f[4],f5=f[5],f6=f[6],f7=f[7],f8=f[8],f9=f[9]; int32_t f0=f[0],f1=f[1],f2=f[2],f3=f[3],f4=f[4],f5=f[5],f6=f[6],f7=f[7],f8=f[8],f9=f[9];
int32_t g0=g[0],g1=g[1],g2=g[2],g3=g[3],g4=g[4],g5=g[5],g6=g[6],g7=g[7],g8=g[8],g9=g[9]; int32_t g0=g[0],g1=g[1],g2=g[2],g3=g[3],g4=g[4],g5=g[5],g6=g[6],g7=g[7],g8=g[8],g9=g[9];
int64_t g0_19=g0*19, g1_19=g1*19, g2_19=g2*19, g3_19=g3*19, g4_19=g4*19; int64_t g1_19=g1*19, g2_19=g2*19, g3_19=g3*19, g4_19=g4*19, g5_19=g5*19;
int64_t g5_19=g5*19, g6_19=g6*19, g7_19=g7*19, g8_19=g8*19, g9_19=g9*19; int64_t g6_19=g6*19, g7_19=g7*19, g8_19=g8*19, g9_19=g9*19;
int64_t r0=(int64_t)f0*g0+(int64_t)f1*g9_19+(int64_t)f2*g8_19+(int64_t)f3*g7_19+(int64_t)f4*g6_19+(int64_t)f5*g5_19+(int64_t)f6*g4_19+(int64_t)f7*g3_19+(int64_t)f8*g2_19+(int64_t)f9*g1_19; int64_t r0=(int64_t)f0*g0+(int64_t)f1*g9_19+(int64_t)f2*g8_19+(int64_t)f3*g7_19+(int64_t)f4*g6_19+(int64_t)f5*g5_19+(int64_t)f6*g4_19+(int64_t)f7*g3_19+(int64_t)f8*g2_19+(int64_t)f9*g1_19;
int64_t r1=(int64_t)f0*g1+(int64_t)f1*g0+(int64_t)f2*g9_19+(int64_t)f3*g8_19+(int64_t)f4*g7_19+(int64_t)f5*g6_19+(int64_t)f6*g5_19+(int64_t)f7*g4_19+(int64_t)f8*g3_19+(int64_t)f9*g2_19; int64_t r1=(int64_t)f0*g1+(int64_t)f1*g0+(int64_t)f2*g9_19+(int64_t)f3*g8_19+(int64_t)f4*g7_19+(int64_t)f5*g6_19+(int64_t)f6*g5_19+(int64_t)f7*g4_19+(int64_t)f8*g3_19+(int64_t)f9*g2_19;
int64_t r2=(int64_t)f0*g2+(int64_t)f1*g1*2+(int64_t)f2*g0+(int64_t)f3*g9_19+(int64_t)f4*g8_19+(int64_t)f5*g7_19+(int64_t)f6*g6_19+(int64_t)f7*g5_19+(int64_t)f8*g4_19+(int64_t)f9*g3_19; int64_t r2=(int64_t)f0*g2+(int64_t)f1*g1*2+(int64_t)f2*g0+(int64_t)f3*g9_19+(int64_t)f4*g8_19+(int64_t)f5*g7_19+(int64_t)f6*g6_19+(int64_t)f7*g5_19+(int64_t)f8*g4_19+(int64_t)f9*g3_19;
@@ -129,7 +110,7 @@ static void fe_sq(fe h, const fe f)
{ {
int32_t f0=f[0],f1=f[1],f2=f[2],f3=f[3],f4=f[4],f5=f[5],f6=f[6],f7=f[7],f8=f[8],f9=f[9]; int32_t f0=f[0],f1=f[1],f2=f[2],f3=f[3],f4=f[4],f5=f[5],f6=f[6],f7=f[7],f8=f[8],f9=f[9];
int32_t f0_2=f0*2,f1_2=f1*2,f2_2=f2*2,f3_2=f3*2,f4_2=f4*2,f5_2=f5*2,f6_2=f6*2,f7_2=f7*2,f8_2=f8*2; int32_t f0_2=f0*2,f1_2=f1*2,f2_2=f2*2,f3_2=f3*2,f4_2=f4*2,f5_2=f5*2,f6_2=f6*2,f7_2=f7*2,f8_2=f8*2;
int32_t f9_19=f9*19,f9_38=f9*38,f8_19=f8*19,f7_19=f7*19,f6_19=f6*19,f5_19=f5*19,f4_19=f4*19,f3_19=f3*19,f2_19=f2*19,f1_19=f1*19; int32_t f9_19=f9*19,f8_19=f8*19,f7_19=f7*19,f6_19=f6*19,f5_19=f5*19,f4_19=f4*19,f3_19=f3*19;
int64_t r0=(int64_t)f0*f0+(int64_t)f1_2*f9_19+(int64_t)f2_2*f8_19+(int64_t)f3_2*f7_19+(int64_t)f4_2*f6_19+(int64_t)f5*f5_19; int64_t r0=(int64_t)f0*f0+(int64_t)f1_2*f9_19+(int64_t)f2_2*f8_19+(int64_t)f3_2*f7_19+(int64_t)f4_2*f6_19+(int64_t)f5*f5_19;
int64_t r1=(int64_t)f0_2*f1+(int64_t)f2_2*f9_19+(int64_t)f3_2*f8_19+(int64_t)f4_2*f7_19+(int64_t)f5_2*f6_19; int64_t r1=(int64_t)f0_2*f1+(int64_t)f2_2*f9_19+(int64_t)f3_2*f8_19+(int64_t)f4_2*f7_19+(int64_t)f5_2*f6_19;
int64_t r2=(int64_t)f0_2*f2+(int64_t)f1*f1+(int64_t)f3_2*f9_19+(int64_t)f4_2*f8_19+(int64_t)f5_2*f7_19+(int64_t)f6*f6_19; int64_t r2=(int64_t)f0_2*f2+(int64_t)f1*f1+(int64_t)f3_2*f9_19+(int64_t)f4_2*f8_19+(int64_t)f5_2*f7_19+(int64_t)f6*f6_19;
@@ -208,18 +189,70 @@ static void x25519_sw(uint8_t *out, const uint8_t *scalar, const uint8_t *point)
fe_tobytes(out, x2); fe_tobytes(out, x2);
} }
se050_status_t se050_x25519_compute_shared_secret_sw(se050_keystore_ctx_t *keystore, void se050_x25519_sw_clamp(uint8_t *scalar)
const uint8_t *private_key,
const uint8_t *peer_public,
uint8_t *shared_secret)
{ {
(void)keystore; scalar[0] &= 248;
if (!private_key || !peer_public || !shared_secret) return SE050_ERR_INVALID_ARG; scalar[31] &= 127;
x25519_sw(shared_secret, private_key, peer_public); scalar[31] |= 64;
return SE050_OK;
} }
#ifdef X25519_TEST void se050_x25519_sw_zeroize(uint8_t *key, size_t len)
{
memzero_explicit(key, len);
}
int se050_x25519_sw_generate_keypair(se050_x25519_sw_keypair_t *keypair,
x25519_rng_func rng_func,
void *rng_ctx)
{
if (!keypair || !rng_func) return -1;
if (rng_func(keypair->private_key, 32, rng_ctx) != 0) {
return -1;
}
se050_x25519_sw_clamp(keypair->private_key);
x25519_sw(keypair->public_key, keypair->private_key, (const uint8_t*)"basepoint");
return 0;
}
int se050_x25519_sw_compute_shared_secret(uint8_t *shared_secret,
const uint8_t *private_key,
const uint8_t *peer_public)
{
if (!shared_secret || !private_key || !peer_public) {
return -1;
}
uint8_t clamped[32];
memcpy(clamped, private_key, 32);
se050_x25519_sw_clamp(clamped);
x25519_sw(shared_secret, clamped, peer_public);
se050_x25519_sw_zeroize(clamped, 32);
return 0;
}
int se050_x25519_sw_derive_public_key(uint8_t *public_key,
const uint8_t *private_key)
{
if (!public_key || !private_key) {
return -1;
}
uint8_t clamped[32];
memcpy(clamped, private_key, 32);
se050_x25519_sw_clamp(clamped);
x25519_sw(public_key, clamped, (const uint8_t*)"basepoint");
se050_x25519_sw_zeroize(clamped, 32);
return 0;
}
#ifdef X25519_SW_TEST
#include <stdio.h> #include <stdio.h>
static const uint8_t RFC7748_SK_1[32] = { static const uint8_t RFC7748_SK_1[32] = {
@@ -251,7 +284,7 @@ int main(void)
x25519_sw(shared_secret, RFC7748_SK_1, RFC7748_PK_1); x25519_sw(shared_secret, RFC7748_SK_1, RFC7748_PK_1);
print_hex("Computed SS", shared_secret, 32); print_hex("Computed SS", shared_secret, 32);
print_hex("Expected SS", RFC7748_SS_1, 32); print_hex("Expected SS", RFC7748_SS_1, 32);
if (crypto_memneq(shared_secret, RFC7748_SS_1, 32) == 0) { if (memcmp(shared_secret, RFC7748_SS_1, 32) == 0) {
printf("[PASS] RFC 7748 Test Vector 1\n"); printf("[PASS] RFC 7748 Test Vector 1\n");
return 0; return 0;
} else { } else {
+160 -2
View File
@@ -350,16 +350,25 @@ int main(void)
printf("========================================\n"); printf("========================================\n");
printf("X25519 ECDH Test Suite\n"); printf("X25519 ECDH Test Suite\n");
printf("Dummy Key Pair Validation\n"); printf("Dummy Key Pair Validation + Software Impl\n");
printf("========================================\n"); printf("========================================\n");
/* Hardware-independent tests */
total++; result = test_x25519_keypair_structure(); if (result) passed++; total++; result = test_x25519_keypair_structure(); if (result) passed++;
total++; result = test_x25519_clamp(); if (result) passed++; total++; result = test_x25519_clamp(); if (result) passed++;
total++; result = test_dummy_keypair_compatibility(); if (result) passed++; total++; result = test_dummy_keypair_compatibility(); if (result) passed++;
total++; result = test_rfc7748_vectors(); if (result) passed++; total++; result = test_rfc7748_vectors(); if (result) passed++;
total++; result = test_cross_compatibility(); if (result) passed++;
total++; result = test_key_material_security(); if (result) passed++; total++; result = test_key_material_security(); if (result) passed++;
/* Software implementation tests */
total++; result = test_sw_keypair_generation(); if (result) passed++;
total++; result = test_sw_ecdh_symmetry(); if (result) passed++;
total++; result = test_sw_public_key_derivation(); if (result) passed++;
total++; result = test_sw_key_zeroization(); if (result) passed++;
/* Hardware-dependent test */
total++; result = test_cross_compatibility(); if (result) passed++;
printf("\n========================================\n"); printf("\n========================================\n");
printf("Test Summary\n"); printf("Test Summary\n");
printf("========================================\n"); printf("========================================\n");
@@ -370,3 +379,152 @@ int main(void)
return (passed == total) ? 0 : 1; return (passed == total) ? 0 : 1;
} }
/* ============================================================================
* Software X25519 Tests
* ============================================================================ */
#include "se050_x25519_sw.h"
/* Simple RNG for testing */
static int test_rng(uint8_t *dst, size_t len, void *rng_ctx)
{
(void)rng_ctx;
static uint8_t counter = 0;
for (size_t i = 0; i < len; i++) {
dst[i] = ++counter;
}
return 0;
}
/* Test 7: Software keypair generation */
static int test_sw_keypair_generation(void)
{
se050_x25519_sw_keypair_t keypair;
uint8_t zero[32] = {0};
printf("\n=== Test 7: Software KeyPair Generation ===\n");
memset(&keypair, 0, sizeof(keypair));
if (se050_x25519_sw_generate_keypair(&keypair, test_rng, NULL) != 0) {
printf("[FAIL] Key generation failed\n");
return 0;
}
if (buffers_equal(keypair.private_key, zero, 32)) {
printf("[FAIL] Private key is all zeros\n");
return 0;
}
if (buffers_equal(keypair.public_key, zero, 32)) {
printf("[FAIL] Public key is all zeros\n");
return 0;
}
printf("[PASS] Software keypair generated successfully\n");
print_hex(" Private: ", keypair.private_key, 32);
print_hex(" Public: ", keypair.public_key, 32);
return 1;
}
/* Test 8: Software ECDH symmetry */
static int test_sw_ecdh_symmetry(void)
{
se050_x25519_sw_keypair_t alice, bob;
uint8_t shared_alice[32], shared_bob[32];
printf("\n=== Test 8: Software ECDH Symmetry ===\n");
if (se050_x25519_sw_generate_keypair(&alice, test_rng, NULL) != 0 ||
se050_x25519_sw_generate_keypair(&bob, test_rng, NULL) != 0) {
printf("[FAIL] Key generation failed\n");
return 0;
}
if (se050_x25519_sw_compute_shared_secret(shared_alice,
alice.private_key,
bob.public_key) != 0) {
printf("[FAIL] Alice ECDH failed\n");
return 0;
}
if (se050_x25519_sw_compute_shared_secret(shared_bob,
bob.private_key,
alice.public_key) != 0) {
printf("[FAIL] Bob ECDH failed\n");
return 0;
}
if (!buffers_equal(shared_alice, shared_bob, 32)) {
printf("[FAIL] Shared secrets don't match\n");
print_hex(" Alice: ", shared_alice, 32);
print_hex(" Bob: ", shared_bob, 32);
return 0;
}
printf("[PASS] ECDH symmetry verified\n");
print_hex(" Shared Secret: ", shared_alice, 32);
return 1;
}
/* Test 9: Public key derivation */
static int test_sw_public_key_derivation(void)
{
uint8_t private_key[32];
uint8_t public_key[32];
uint8_t derived[32];
printf("\n=== Test 9: Public Key Derivation ===\n");
for (int i = 0; i < 32; i++) {
private_key[i] = i + 1;
}
if (se050_x25519_sw_derive_public_key(public_key, private_key) != 0) {
printf("[FAIL] Public key derivation failed\n");
return 0;
}
memcpy(derived, private_key, 32);
se050_x25519_sw_clamp(derived);
uint8_t direct_public[32];
x25519_sw(direct_public, derived, (const uint8_t*)"basepoint");
if (!buffers_equal(public_key, direct_public, 32)) {
printf("[FAIL] Public key mismatch\n");
return 0;
}
printf("[PASS] Public key derivation works\n");
print_hex(" Private: ", private_key, 32);
print_hex(" Public: ", public_key, 32);
return 1;
}
/* Test 10: Key zeroization */
static int test_sw_key_zeroization(void)
{
uint8_t key[32];
uint8_t zero[32] = {0};
printf("\n=== Test 10: Key Zeroization ===\n");
for (int i = 0; i < 32; i++) {
key[i] = 0xFF;
}
se050_x25519_sw_zeroize(key, 32);
if (!buffers_equal(key, zero, 32)) {
printf("[FAIL] Key not zeroized\n");
return 0;
}
printf("[PASS] Key zeroization successful\n");
return 1;
}