Compare commits
33 Commits
bd762864e6
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 11bcc5e0c3 | |||
| 479fcd37c1 | |||
| 675e452071 | |||
| 43643bc4cf | |||
| 760b37690e | |||
| 7ef235d5b1 | |||
| 77c6dfbf1a | |||
| a430accd11 | |||
| 2ec7829b52 | |||
| 42e6222637 | |||
| 7c2c6d94bf | |||
| d5ca4b3634 | |||
| 2f76e7cb09 | |||
| eac7fc9d82 | |||
| 3645b4fe80 | |||
| 4fae20f56d | |||
| 63bc460db4 | |||
| cbcfba7347 | |||
| 0210082b8c | |||
| 999e7a6e19 | |||
| 1894e9a933 | |||
| 4ec660de02 | |||
| 09620ba4ef | |||
| 77c3258494 | |||
| 90be06ead1 | |||
| d2081b3a9e | |||
| a8d28882c7 | |||
| f6298c7725 | |||
| 9d0af4d65a | |||
| c31809f37d | |||
| c61433d75b | |||
| 50884811ca | |||
| d4085b2073 |
@@ -16,8 +16,19 @@ set(SOURCES
|
|||||||
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_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.c
|
||||||
src/se050_scp03_keys.c
|
src/se050_scp03_keys.c
|
||||||
|
src/se050_wireguard_proto.c
|
||||||
|
src/se050_tai64n_hw.c
|
||||||
|
src/se050_wireguard.c
|
||||||
|
src/se050_wireguard_se050_rng.c
|
||||||
|
src/se050_rng_seed.c
|
||||||
)
|
)
|
||||||
|
|
||||||
# Create library
|
# Create library
|
||||||
@@ -63,3 +74,7 @@ install(FILES include/se050_wireguard.h
|
|||||||
# Install library
|
# Install library
|
||||||
install(TARGETS se050_wireguard
|
install(TARGETS se050_wireguard
|
||||||
ARCHIVE DESTINATION lib)
|
ARCHIVE DESTINATION lib)
|
||||||
|
|
||||||
|
# Note: For embedded platforms (ESP32, u-boot), replace system_rng() with
|
||||||
|
# platform-specific RNG (e.g., get_random_bytes() for ESP32)
|
||||||
|
# See se050_wireguard.c for details.
|
||||||
|
|||||||
@@ -4,12 +4,12 @@ AR = ar
|
|||||||
CFLAGS = -Wall -Wextra -std=c11 -I include
|
CFLAGS = -Wall -Wextra -std=c11 -I include
|
||||||
LDFLAGS =
|
LDFLAGS =
|
||||||
|
|
||||||
SRCS = src/se050_i2c_hal.c src/se050_session.c src/se050_keystore.c \
|
SRCS = src/se050_i2c_hal.c src/se050_mem_pool.c src/se050_session.c src/se050_keystore.c \
|
||||||
src/se050_rng.c src/se050_x25519.c src/se050_x25519_sw.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_chacha20_poly1305.c src/se050_blake2s.c \
|
||||||
src/se050_hmac_blake2s.c src/se050_hkdf_blake2s.c src/se050_tai64n.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
|
src/se050_tai64n_hw.c src/se050_wireguard.c
|
||||||
|
|
||||||
OBJS = $(SRCS:.c=.o)
|
OBJS = $(SRCS:.c=.o)
|
||||||
LIB = libse050_wireguard.a
|
LIB = libse050_wireguard.a
|
||||||
@@ -22,56 +22,16 @@ $(LIB): $(OBJS)
|
|||||||
@mkdir -p build
|
@mkdir -p build
|
||||||
$(AR) rcs build/$@ $^
|
$(AR) rcs build/$@ $^
|
||||||
|
|
||||||
test_blake2s: src/se050_blake2s.c
|
# WireGuard protocol test
|
||||||
@mkdir -p build
|
test_wireguard: tests/test_wireguard.c $(LIB)
|
||||||
$(CC) $(CFLAGS) -DBLAKE2S_TEST -o build/$@ $<
|
|
||||||
|
|
||||||
test_hmac_blake2s: tests/test_hmac_hkdf.c $(LIB)
|
|
||||||
@mkdir -p build
|
@mkdir -p build
|
||||||
$(CC) $(CFLAGS) -o build/$@ $< build/$(LIB)
|
$(CC) $(CFLAGS) -o build/$@ $< build/$(LIB)
|
||||||
|
|
||||||
test_hkdf_blake2s: tests/test_hmac_hkdf.c $(LIB)
|
test: all test_wireguard
|
||||||
@mkdir -p build
|
|
||||||
$(CC) $(CFLAGS) -DHKDF_TEST -o build/$@ $< build/$(LIB)
|
|
||||||
|
|
||||||
test: all
|
|
||||||
@./build/test_blake2s
|
@./build/test_blake2s
|
||||||
@./build/test_hmac_blake2s
|
@./build/test_hmac_blake2s
|
||||||
@./build/test_hkdf_blake2s
|
@./build/test_hkdf_blake2s
|
||||||
|
@./build/test_wireguard
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -rf build *.o src/*.o tests/*.o
|
rm -rf build *.o src/*.o tests/*.o
|
||||||
|
|
||||||
# WireGuard protocol test
|
|
||||||
test_wireguard_kdf: tests/test_wireguard_kdf.c $(LIB)
|
|
||||||
@mkdir -p build
|
|
||||||
$(CC) $(CFLAGS) -o build/$@ $< build/$(LIB)
|
|
||||||
|
|
||||||
test: all test_wireguard_kdf
|
|
||||||
@./build/test_blake2s
|
|
||||||
@./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,45 @@
|
|||||||
|
/**
|
||||||
|
* @file se050_i2c_hal.h
|
||||||
|
* @brief SE050 I2C HAL Interface
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SE050_I2C_HAL_H
|
||||||
|
#define SE050_I2C_HAL_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
/* Status codes */
|
||||||
|
typedef enum {
|
||||||
|
SE050_OK = 0,
|
||||||
|
SE050_ERR_INVALID_ARG = -1,
|
||||||
|
SE050_ERR_I2C = -2,
|
||||||
|
SE050_ERR_TIMEOUT = -3,
|
||||||
|
SE050_ERR_INTERNAL = -4,
|
||||||
|
SE050_ERR_SESSION = -5,
|
||||||
|
SE050_ERR_FAIL = -6,
|
||||||
|
SE050_ERR_RNG = -7,
|
||||||
|
SE050_ERR_ECDH = -8,
|
||||||
|
SE050_ERR_NOT_INIT = -9,
|
||||||
|
SE050_ERR_SCP03 = -10
|
||||||
|
} se050_status_t;
|
||||||
|
|
||||||
|
/* I2C HAL structure */
|
||||||
|
#define SE050_I2C_DEV_PATH_MAX 64
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
void *handle; /**< I2C file descriptor */
|
||||||
|
uint8_t slave_addr; /**< I2C slave address */
|
||||||
|
char dev_path[SE050_I2C_DEV_PATH_MAX]; /**< I2C device path */
|
||||||
|
int wakeup_pin; /**< Wakeup GPIO pin (-1 if unused) */
|
||||||
|
} se050_i2c_hal_t;
|
||||||
|
|
||||||
|
/* Public API */
|
||||||
|
se050_status_t se050_i2c_init(se050_i2c_hal_t *hal, const char *dev_path, uint8_t slave_addr);
|
||||||
|
void se050_i2c_close(se050_i2c_hal_t *hal);
|
||||||
|
int se050_i2c_read(se050_i2c_hal_t *hal, uint8_t *buffer, int length);
|
||||||
|
int se050_i2c_write(se050_i2c_hal_t *hal, const uint8_t *buffer, int length);
|
||||||
|
se050_status_t se050_i2c_wakeup(se050_i2c_hal_t *hal);
|
||||||
|
|
||||||
|
#endif /* SE050_I2C_HAL_H */
|
||||||
@@ -11,6 +11,7 @@
|
|||||||
#define SE050_KEYSTORE_INTERNAL_H
|
#define SE050_KEYSTORE_INTERNAL_H
|
||||||
|
|
||||||
#include "se050_wireguard.h"
|
#include "se050_wireguard.h"
|
||||||
|
#include "se050_session_internal.h"
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
@@ -51,6 +52,8 @@ typedef struct {
|
|||||||
/**
|
/**
|
||||||
* @brief Key store context structure
|
* @brief Key store context structure
|
||||||
*/
|
*/
|
||||||
|
typedef struct se050_keystore_ctx se050_keystore_ctx_t;
|
||||||
|
|
||||||
struct se050_keystore_ctx {
|
struct se050_keystore_ctx {
|
||||||
se050_session_ctx_t *session; /**< Associated session */
|
se050_session_ctx_t *session; /**< Associated session */
|
||||||
key_object_t *objects; /**< Key objects array */
|
key_object_t *objects; /**< Key objects array */
|
||||||
|
|||||||
@@ -0,0 +1,106 @@
|
|||||||
|
/**
|
||||||
|
* @file se050_mem_pool.h
|
||||||
|
* @brief Static Memory Pool for Embedded Systems
|
||||||
|
*
|
||||||
|
* Replaces malloc/calloc with pre-allocated static pools.
|
||||||
|
* Suitable for u-boot, ESP32, and other embedded environments.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SE050_MEM_POOL_H
|
||||||
|
#define SE050_MEM_POOL_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
/* Configuration: Pool sizes */
|
||||||
|
#ifndef SE050_POOL_SESSION_COUNT
|
||||||
|
#define SE050_POOL_SESSION_COUNT 4
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef SE050_POOL_SCP03_COUNT
|
||||||
|
#define SE050_POOL_SCP03_COUNT 4
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef SE050_POOL_KEYSTORE_COUNT
|
||||||
|
#define SE050_POOL_KEYSTORE_COUNT 2
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef SE050_POOL_KEYSTORE_MAX_OBJECTS
|
||||||
|
#define SE050_POOL_KEYSTORE_MAX_OBJECTS 8
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef SE050_POOL_RNG_COUNT
|
||||||
|
#define SE050_POOL_RNG_COUNT 2
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef SE050_POOL_I2C_HAL_COUNT
|
||||||
|
#define SE050_POOL_I2C_HAL_COUNT 2
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Forward declarations */
|
||||||
|
struct se050_session_ctx;
|
||||||
|
struct se050_scp03_ctx;
|
||||||
|
struct se050_keystore_ctx;
|
||||||
|
struct se050_rng_ctx;
|
||||||
|
struct se050_i2c_hal;
|
||||||
|
|
||||||
|
/* ============================================================================
|
||||||
|
* Memory Pool API
|
||||||
|
* ============================================================================ */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Initialize all memory pools
|
||||||
|
*
|
||||||
|
* Must be called before any other SE050 functions.
|
||||||
|
*
|
||||||
|
* @return 0 on success, -1 on error
|
||||||
|
*/
|
||||||
|
int se050_mem_pool_init(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Cleanup all memory pools
|
||||||
|
*
|
||||||
|
* Zeroizes all allocated memory before freeing.
|
||||||
|
*/
|
||||||
|
void se050_mem_pool_cleanup(void);
|
||||||
|
|
||||||
|
/* Session pool */
|
||||||
|
struct se050_session_ctx *se050_session_alloc_pool(void);
|
||||||
|
void se050_session_free_pool(struct se050_session_ctx *ctx);
|
||||||
|
|
||||||
|
/* SCP03 pool */
|
||||||
|
struct se050_scp03_ctx *se050_scp03_alloc_pool(void);
|
||||||
|
void se050_scp03_free_pool(struct se050_scp03_ctx *ctx);
|
||||||
|
|
||||||
|
/* Keystore pool */
|
||||||
|
struct se050_keystore_ctx *se050_keystore_alloc_pool(void);
|
||||||
|
void se050_keystore_free_pool(struct se050_keystore_ctx *ctx);
|
||||||
|
|
||||||
|
/* RNG pool */
|
||||||
|
struct se050_rng_ctx *se050_rng_alloc_pool(void);
|
||||||
|
void se050_rng_free_pool(struct se050_rng_ctx *ctx);
|
||||||
|
|
||||||
|
/* I2C HAL pool */
|
||||||
|
struct se050_i2c_hal *se050_i2c_hal_alloc_pool(void);
|
||||||
|
void se050_i2c_hal_free_pool(struct se050_i2c_hal *hal);
|
||||||
|
|
||||||
|
/* ============================================================================
|
||||||
|
* Debug/Statistics
|
||||||
|
* ============================================================================ */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get pool statistics
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
int total;
|
||||||
|
int used;
|
||||||
|
int free;
|
||||||
|
} se050_pool_stats_t;
|
||||||
|
|
||||||
|
void se050_mem_pool_stats(se050_pool_stats_t *session,
|
||||||
|
se050_pool_stats_t *scp03,
|
||||||
|
se050_pool_stats_t *keystore,
|
||||||
|
se050_pool_stats_t *rng,
|
||||||
|
se050_pool_stats_t *i2c_hal);
|
||||||
|
|
||||||
|
#endif /* SE050_MEM_POOL_H */
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
/**
|
||||||
|
* @file se050_scp03.h
|
||||||
|
* @brief SE050 Platform SCP03 Secure Channel Interface
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SE050_SCP03_H
|
||||||
|
#define SE050_SCP03_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include "se050_i2c_hal.h"
|
||||||
|
|
||||||
|
/* Forward declarations */
|
||||||
|
typedef struct se050_session_ctx se050_session_ctx_t;
|
||||||
|
typedef struct se050_scp03_ctx se050_scp03_ctx_t;
|
||||||
|
|
||||||
|
/* SCP03 key sizes */
|
||||||
|
#define SCP03_KEY_SIZE 16
|
||||||
|
#define SCP03_IV_SIZE 16
|
||||||
|
#define SCP03_CMAC_SIZE 8
|
||||||
|
|
||||||
|
/* Initialize SCP03 context */
|
||||||
|
se050_status_t se050_scp03_init(se050_scp03_ctx_t **ctx, se050_session_ctx_t *session);
|
||||||
|
|
||||||
|
/* Set SCP03 keys */
|
||||||
|
se050_status_t se050_scp03_set_keys(se050_scp03_ctx_t *ctx,
|
||||||
|
const uint8_t *enc_key,
|
||||||
|
const uint8_t *mac_key,
|
||||||
|
const uint8_t *dek_key);
|
||||||
|
|
||||||
|
/* Encrypt command */
|
||||||
|
se050_status_t se050_scp03_encrypt_command(se050_scp03_ctx_t *ctx,
|
||||||
|
uint8_t *cmd, size_t *cmd_len);
|
||||||
|
|
||||||
|
/* Decrypt response */
|
||||||
|
uint16_t se050_scp03_decrypt_response(se050_scp03_ctx_t *ctx,
|
||||||
|
size_t cmd_len,
|
||||||
|
uint8_t *rsp, size_t *rsp_len);
|
||||||
|
|
||||||
|
/* Cleanup SCP03 context */
|
||||||
|
void se050_scp03_cleanup(se050_scp03_ctx_t *ctx);
|
||||||
|
|
||||||
|
#endif /* SE050_SCP03_H */
|
||||||
@@ -10,6 +10,7 @@
|
|||||||
#ifndef SE050_SESSION_INTERNAL_H
|
#ifndef SE050_SESSION_INTERNAL_H
|
||||||
#define SE050_SESSION_INTERNAL_H
|
#define SE050_SESSION_INTERNAL_H
|
||||||
|
|
||||||
|
#include "se050_i2c_hal.h"
|
||||||
#include "se050_wireguard.h"
|
#include "se050_wireguard.h"
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
@@ -20,17 +21,38 @@ typedef enum {
|
|||||||
SESSION_STATE_CLOSED,
|
SESSION_STATE_CLOSED,
|
||||||
} session_state_t;
|
} session_state_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief SCP03 secure channel context
|
||||||
|
*/
|
||||||
|
typedef struct se050_scp03_ctx {
|
||||||
|
struct se050_session_ctx *session; /**< Associated session */
|
||||||
|
uint8_t enc_key[16]; /**< Encryption key */
|
||||||
|
uint8_t mac_key[16]; /**< MAC key */
|
||||||
|
uint8_t dek_key[16]; /**< DEK key */
|
||||||
|
uint8_t cmd_icv[8]; /**< Command ICV */
|
||||||
|
uint8_t rsp_icv[8]; /**< Response ICV */
|
||||||
|
uint64_t cmd_counter; /**< Command counter */
|
||||||
|
uint64_t rsp_counter; /**< Response counter */
|
||||||
|
uint8_t initialized; /**< Initialization flag */
|
||||||
|
} se050_scp03_ctx_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief RNG context (forward declaration)
|
||||||
|
*/
|
||||||
|
typedef struct se050_rng_ctx se050_rng_ctx_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Session context structure
|
* @brief Session context structure
|
||||||
*/
|
*/
|
||||||
|
typedef struct se050_session_ctx se050_session_ctx_t;
|
||||||
|
|
||||||
struct se050_session_ctx {
|
struct se050_session_ctx {
|
||||||
se050_i2c_hal_t *hal; /**< I2C HAL interface */
|
se050_i2c_hal_t *hal; /**< I2C HAL interface */
|
||||||
session_state_t state; /**< Current session state */
|
session_state_t state; /**< Current session state */
|
||||||
uint32_t session_id; /**< Unique session identifier */
|
uint32_t session_id; /**< Unique session identifier */
|
||||||
|
se050_scp03_ctx_t *scp03; /**< SCP03 secure channel context */
|
||||||
uint8_t session_key[32]; /**< Session encryption key */
|
uint8_t session_key[32]; /**< Session encryption key */
|
||||||
size_t session_key_len; /**< Session key length */
|
size_t session_key_len; /**< Session key length */
|
||||||
uint32_t cmd_counter; /**< Command counter for SCP03 */
|
|
||||||
uint32_t resp_counter; /**< Response counter for SCP03 */
|
|
||||||
se050_rng_ctx_t *rng; /**< RNG context */
|
se050_rng_ctx_t *rng; /**< RNG context */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
+213
-387
@@ -1,426 +1,252 @@
|
|||||||
/**
|
/**
|
||||||
* @file se050_wireguard.h
|
* @file se050_wireguard.h
|
||||||
* @brief SE050 WireGuard Minimum Interface
|
* @brief WireGuard VPN Protocol - Public API
|
||||||
*
|
|
||||||
* Clean-room interface for WireGuard cryptographic operations using SE050.
|
|
||||||
*
|
|
||||||
* This header defines the API for:
|
|
||||||
* - X25519 ECDH key exchange
|
|
||||||
* - True Random Number Generation (TRNG)
|
|
||||||
* - Platform SCP03 secure channel
|
|
||||||
*
|
|
||||||
* License: MIT (Clean-room implementation)
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef SE050_WIREGUARD_H
|
#ifndef SE050_WIREGUARD_H
|
||||||
#define SE050_WIREGUARD_H
|
#define SE050_WIREGUARD_H
|
||||||
|
|
||||||
/* Feature test macros - must be defined before any includes */
|
|
||||||
#define _GNU_SOURCE
|
|
||||||
#define _POSIX_C_SOURCE 200809L
|
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* ============================================================================
|
/* =========================================================================
|
||||||
* Error Codes
|
|
||||||
* ============================================================================ */
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
SE050_OK = 0x00,
|
|
||||||
SE050_ERR_FAIL = 0x01,
|
|
||||||
SE050_ERR_INVALID_ARG = 0x02,
|
|
||||||
SE050_ERR_SESSION = 0x03,
|
|
||||||
SE050_ERR_KEY_STORE = 0x04,
|
|
||||||
SE050_ERR_RNG = 0x05,
|
|
||||||
SE050_ERR_ECDH = 0x06,
|
|
||||||
SE050_ERR_SCP03 = 0x07,
|
|
||||||
SE050_ERR_I2C = 0x08,
|
|
||||||
SE050_ERR_NOT_INIT = 0x09,
|
|
||||||
} se050_status_t;
|
|
||||||
|
|
||||||
/* ============================================================================
|
|
||||||
* Constants
|
|
||||||
* ============================================================================ */
|
|
||||||
|
|
||||||
/** WireGuard key size (X25519 uses 32-byte keys) */
|
|
||||||
#define SE050_WG_KEY_SIZE 32
|
|
||||||
|
|
||||||
/** WireGuard public key size */
|
|
||||||
#define SE050_WG_PUBKEY_SIZE 32
|
|
||||||
|
|
||||||
/** SCP03 key size */
|
|
||||||
#define SE050_SCP03_KEY_SIZE 16
|
|
||||||
|
|
||||||
/** SCP03 IV size */
|
|
||||||
#define SE050_SCP03_IV_SIZE 16
|
|
||||||
|
|
||||||
/** SCP03 CMAC size */
|
|
||||||
#define SE050_SCP03_CMAC_SIZE 8
|
|
||||||
|
|
||||||
/** Maximum buffer size for SCP03 */
|
|
||||||
#define SE050_SCP03_MAX_BUF 1024
|
|
||||||
|
|
||||||
/* ============================================================================
|
|
||||||
* Type Definitions
|
* Type Definitions
|
||||||
* ============================================================================ */
|
* ========================================================================= */
|
||||||
|
|
||||||
/** Session context for SE050 communication */
|
|
||||||
typedef struct se050_session_ctx se050_session_ctx_t;
|
|
||||||
|
|
||||||
/** Key store context */
|
|
||||||
typedef struct se050_keystore_ctx se050_keystore_ctx_t;
|
|
||||||
|
|
||||||
/** RNG context */
|
|
||||||
typedef struct se050_rng_ctx se050_rng_ctx_t;
|
|
||||||
|
|
||||||
/** SCP03 session context */
|
|
||||||
typedef struct se050_scp03_ctx se050_scp03_ctx_t;
|
|
||||||
|
|
||||||
/** X25519 key pair */
|
|
||||||
typedef struct {
|
|
||||||
uint8_t private_key[SE050_WG_KEY_SIZE]; /**< Private key (32 bytes) */
|
|
||||||
uint8_t public_key[SE050_WG_PUBKEY_SIZE]; /**< Public key (32 bytes) */
|
|
||||||
} se050_x25519_keypair_t;
|
|
||||||
|
|
||||||
/** I2C HAL interface */
|
|
||||||
typedef struct {
|
|
||||||
void *handle; /**< I2C device handle */
|
|
||||||
uint8_t slave_addr; /**< I2C slave address (default: 0x90) */
|
|
||||||
const char *dev_path; /**< Device path (e.g., "/dev/i2c-1") */
|
|
||||||
} se050_i2c_hal_t;
|
|
||||||
|
|
||||||
/* ============================================================================
|
|
||||||
* I2C HAL Layer
|
|
||||||
* ============================================================================ */
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Initialize I2C HAL
|
* @brief WireGuard session context
|
||||||
* @param hal I2C HAL structure
|
*
|
||||||
* @param dev_path Device path (e.g., "/dev/i2c-1")
|
* Contains all state needed for WireGuard communication:
|
||||||
* @param slave_addr I2C slave address (default: 0x90)
|
* - Local keypair
|
||||||
* @return SE050_OK on success
|
* - Peer public key
|
||||||
|
* - Session keys (sending/receiving)
|
||||||
|
* - Cookie state for DoS protection
|
||||||
*/
|
*/
|
||||||
se050_status_t se050_i2c_init(se050_i2c_hal_t *hal, const char *dev_path, uint8_t slave_addr);
|
typedef struct se050_wireguard_session {
|
||||||
|
/* Local keys */
|
||||||
|
uint8_t private_key[32];
|
||||||
|
uint8_t public_key[32];
|
||||||
|
|
||||||
/**
|
/* Peer keys */
|
||||||
* @brief Close I2C HAL
|
uint8_t peer_public_key[32];
|
||||||
* @param hal I2C HAL structure
|
|
||||||
*/
|
|
||||||
void se050_i2c_close(se050_i2c_hal_t *hal);
|
|
||||||
|
|
||||||
/**
|
/* Handshake state */
|
||||||
* @brief Read from SE050 via I2C
|
uint8_t handshake_secret[32];
|
||||||
* @param hal I2C HAL structure
|
uint8_t chain_key[32];
|
||||||
* @param buffer Read buffer
|
uint8_t sending_key[32];
|
||||||
* @param length Number of bytes to read
|
uint8_t receiving_key[32];
|
||||||
* @return Number of bytes read, or negative on error
|
uint64_t sending_nonce;
|
||||||
*/
|
uint64_t receiving_nonce;
|
||||||
int se050_i2c_read(se050_i2c_hal_t *hal, uint8_t *buffer, int length);
|
|
||||||
|
|
||||||
/**
|
/* Cookie state */
|
||||||
* @brief Write to SE050 via I2C
|
uint8_t cookie_secret[32];
|
||||||
* @param hal I2C HAL structure
|
uint64_t cookie_timestamp;
|
||||||
* @param buffer Write buffer
|
uint8_t last_mac1[16];
|
||||||
* @param length Number of bytes to write
|
|
||||||
* @return Number of bytes written, or negative on error
|
|
||||||
*/
|
|
||||||
int se050_i2c_write(se050_i2c_hal_t *hal, const uint8_t *buffer, int length);
|
|
||||||
|
|
||||||
/**
|
/* State flags */
|
||||||
* @brief Wake up SE050 (if needed)
|
int is_initiator;
|
||||||
* @param hal I2C HAL structure
|
int handshake_complete;
|
||||||
* @return SE050_OK on success
|
int packets_received; /* Number of packets received (for replay detection) */
|
||||||
*/
|
} se050_wireguard_session_t;
|
||||||
se050_status_t se050_i2c_wakeup(se050_i2c_hal_t *hal);
|
|
||||||
|
|
||||||
/* ============================================================================
|
/* =========================================================================
|
||||||
* Session Management
|
* Session Management
|
||||||
* ============================================================================ */
|
* ========================================================================= */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Create SE050 session
|
* @brief Initialize a WireGuard session
|
||||||
* @param ctx Output session context
|
|
||||||
* @param hal I2C HAL interface
|
|
||||||
* @return SE050_OK on success
|
|
||||||
*/
|
|
||||||
se050_status_t se050_session_create(se050_session_ctx_t **ctx, se050_i2c_hal_t *hal);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Open SE050 session
|
|
||||||
* @param ctx Session context
|
|
||||||
* @return SE050_OK on success
|
|
||||||
*/
|
|
||||||
se050_status_t se050_session_open(se050_session_ctx_t *ctx);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Close SE050 session
|
|
||||||
* @param ctx Session context
|
|
||||||
*/
|
|
||||||
void se050_session_close(se050_session_ctx_t *ctx);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Delete SE050 session
|
|
||||||
* @param ctx Session context
|
|
||||||
*/
|
|
||||||
void se050_session_delete(se050_session_ctx_t *ctx);
|
|
||||||
|
|
||||||
/* ============================================================================
|
|
||||||
* Session SCP03 Integration
|
|
||||||
* ============================================================================ */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Initialize SCP03 secure channel for session
|
|
||||||
* @param ctx Session context
|
|
||||||
* @return SE050_OK on success
|
|
||||||
*/
|
|
||||||
se050_status_t se050_session_scp03_init(se050_session_ctx_t *ctx);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Set SCP03 keys for PlatformSCP03 authentication
|
|
||||||
* @param ctx Session context
|
|
||||||
* @param enc_key Encryption key (16 bytes)
|
|
||||||
* @param mac_key MAC key (16 bytes)
|
|
||||||
* @param dek_key Data Encryption Key (16 bytes)
|
|
||||||
* @return SE050_OK on success
|
|
||||||
*/
|
|
||||||
se050_status_t se050_session_scp03_set_keys(se050_session_ctx_t *ctx,
|
|
||||||
const uint8_t *enc_key,
|
|
||||||
const uint8_t *mac_key,
|
|
||||||
const uint8_t *dek_key);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Encrypt command using SCP03
|
|
||||||
* @param ctx Session context
|
|
||||||
* @param cmd Command buffer
|
|
||||||
* @param cmd_len Command length (updated after padding)
|
|
||||||
* @return SE050_OK on success
|
|
||||||
*/
|
|
||||||
se050_status_t se050_session_scp03_encrypt(se050_session_ctx_t *ctx,
|
|
||||||
uint8_t *cmd,
|
|
||||||
size_t *cmd_len);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Decrypt response using SCP03
|
|
||||||
* @param ctx Session context
|
|
||||||
* @param cmd_len Original command length
|
|
||||||
* @param rsp Response buffer
|
|
||||||
* @param rsp_len Response length (updated after decryption)
|
|
||||||
* @return Status word (0x9000 on success)
|
|
||||||
*/
|
|
||||||
uint16_t se050_session_scp03_decrypt(se050_session_ctx_t *ctx,
|
|
||||||
size_t cmd_len,
|
|
||||||
uint8_t *rsp,
|
|
||||||
size_t *rsp_len);
|
|
||||||
|
|
||||||
/* ============================================================================
|
|
||||||
* Key Store
|
|
||||||
* ============================================================================ */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Initialize key store
|
|
||||||
* @param ctx Output key store context
|
|
||||||
* @param session SE050 session
|
|
||||||
* @return SE050_OK on success
|
|
||||||
*/
|
|
||||||
se050_status_t se050_keystore_init(se050_keystore_ctx_t **ctx, se050_session_ctx_t *session);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Free key store
|
|
||||||
* @param ctx Key store context
|
|
||||||
*/
|
|
||||||
void se050_keystore_free(se050_keystore_ctx_t *ctx);
|
|
||||||
|
|
||||||
/* ============================================================================
|
|
||||||
* Random Number Generation (TRNG)
|
|
||||||
* ============================================================================ */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Initialize RNG context
|
|
||||||
* @param ctx Output RNG context
|
|
||||||
* @param session SE050 session
|
|
||||||
* @return SE050_OK on success
|
|
||||||
*/
|
|
||||||
se050_status_t se050_rng_init(se050_rng_ctx_t **ctx, se050_session_ctx_t *session);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Generate random bytes using SE050 TRNG
|
|
||||||
* @param ctx RNG context
|
|
||||||
* @param output Output buffer
|
|
||||||
* @param length Number of bytes to generate
|
|
||||||
* @return SE050_OK on success
|
|
||||||
*/
|
|
||||||
se050_status_t se050_rng_generate(se050_rng_ctx_t *ctx, uint8_t *output, size_t length);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Free RNG context
|
|
||||||
* @param ctx RNG context
|
|
||||||
*/
|
|
||||||
void se050_rng_free(se050_rng_ctx_t *ctx);
|
|
||||||
|
|
||||||
/* ============================================================================
|
|
||||||
* X25519 ECDH
|
|
||||||
* ============================================================================ */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Generate X25519 key pair
|
|
||||||
* @param keystore Key store context
|
|
||||||
* @param keypair Output key pair
|
|
||||||
* @param key_id Unique key identifier
|
|
||||||
* @return SE050_OK on success
|
|
||||||
*
|
*
|
||||||
* Note: Private key is generated using SE050 TRNG and stored securely.
|
* @param session Output: session context to initialize
|
||||||
* The private key never leaves the SE050.
|
* @param private_key Local private key (32 bytes)
|
||||||
|
* @param peer_public_key Peer's public key (32 bytes)
|
||||||
|
* @return 0 on success, -1 on error
|
||||||
*/
|
*/
|
||||||
se050_status_t se050_x25519_generate_keypair(se050_keystore_ctx_t *keystore,
|
int se050_wireguard_session_init(se050_wireguard_session_t *session,
|
||||||
se050_x25519_keypair_t *keypair,
|
const uint8_t *private_key,
|
||||||
uint32_t key_id);
|
const uint8_t *peer_public_key);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Compute X25519 ECDH shared secret
|
* @brief Clean up and zeroize session data
|
||||||
* @param keystore Key store context
|
|
||||||
* @param private_key_id Local private key ID
|
|
||||||
* @param peer_public Peer's public key (32 bytes)
|
|
||||||
* @param shared_secret Output shared secret (32 bytes)
|
|
||||||
* @return SE050_OK on success
|
|
||||||
*
|
*
|
||||||
* Note: ECDH computation is performed inside SE050.
|
* @param session Session to cleanup
|
||||||
*/
|
*/
|
||||||
se050_status_t se050_x25519_compute_shared_secret(se050_keystore_ctx_t *keystore,
|
void se050_wireguard_session_cleanup(se050_wireguard_session_t *session);
|
||||||
uint32_t private_key_id,
|
|
||||||
const uint8_t *peer_public,
|
/* =========================================================================
|
||||||
uint8_t *shared_secret);
|
* Key Derivation
|
||||||
|
* ========================================================================= */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Export X25519 public key from SE050
|
* @brief Derive session keys from shared secret
|
||||||
* @param keystore Key store context
|
*
|
||||||
* @param key_id Key identifier
|
* After performing X25519 key exchange, use this to derive
|
||||||
* @param public_key Output public key (32 bytes)
|
* the actual encryption keys for the session.
|
||||||
* @return SE050_OK on success
|
*
|
||||||
*/
|
|
||||||
se050_status_t se050_x25519_export_public_key(se050_keystore_ctx_t *keystore,
|
|
||||||
uint32_t key_id,
|
|
||||||
uint8_t *public_key);
|
|
||||||
|
|
||||||
/* ============================================================================
|
|
||||||
* Platform SCP03 Secure Channel
|
|
||||||
* ============================================================================ */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Initialize SCP03 context
|
|
||||||
* @param ctx Output SCP03 context
|
|
||||||
* @param session SE050 session
|
|
||||||
* @return SE050_OK on success
|
|
||||||
*/
|
|
||||||
se050_status_t se050_scp03_init(se050_scp03_ctx_t **ctx, se050_session_ctx_t *session);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Set SCP03 keys (ENC, MAC, and DEK)
|
|
||||||
* @param ctx SCP03 context
|
|
||||||
* @param enc_key Encryption key (16 bytes)
|
|
||||||
* @param mac_key MAC key (16 bytes)
|
|
||||||
* @param dek_key Data Encryption Key (16 bytes)
|
|
||||||
* @return SE050_OK on success
|
|
||||||
*/
|
|
||||||
se050_status_t se050_scp03_set_keys(se050_scp03_ctx_t *ctx,
|
|
||||||
const uint8_t *enc_key,
|
|
||||||
const uint8_t *mac_key,
|
|
||||||
const uint8_t *dek_key);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Load SCP03 keys from file
|
|
||||||
* @param ctx SCP03 context
|
|
||||||
* @param file_path Path to key file (ENC[16] + MAC[16] + DEK[16] = 48 bytes)
|
|
||||||
* @return SE050_OK on success
|
|
||||||
*/
|
|
||||||
se050_status_t se050_scp03_load_keys_from_file(se050_scp03_ctx_t *ctx, const char *file_path);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Encrypt command APDU
|
|
||||||
* @param ctx SCP03 context
|
|
||||||
* @param cmd Command buffer (in-place encryption)
|
|
||||||
* @param cmd_len Command length (updated after padding)
|
|
||||||
* @return SE050_OK on success
|
|
||||||
*/
|
|
||||||
se050_status_t se050_scp03_encrypt_command(se050_scp03_ctx_t *ctx,
|
|
||||||
uint8_t *cmd,
|
|
||||||
size_t *cmd_len);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Decrypt response APDU
|
|
||||||
* @param ctx SCP03 context
|
|
||||||
* @param cmd_len Original command length (for ICV calculation)
|
|
||||||
* @param rsp Response buffer (in-place decryption)
|
|
||||||
* @param rsp_len Response length (updated after decryption)
|
|
||||||
* @return SW status code (e.g., 0x9000 for success)
|
|
||||||
*/
|
|
||||||
uint16_t se050_scp03_decrypt_response(se050_scp03_ctx_t *ctx,
|
|
||||||
size_t cmd_len,
|
|
||||||
uint8_t *rsp,
|
|
||||||
size_t *rsp_len);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Free SCP03 context
|
|
||||||
* @param ctx SCP03 context
|
|
||||||
*/
|
|
||||||
void se050_scp03_free(se050_scp03_ctx_t *ctx);
|
|
||||||
|
|
||||||
/* ============================================================================
|
|
||||||
* High-Level WireGuard API
|
|
||||||
* ============================================================================ */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Initialize WireGuard SE050 subsystem
|
|
||||||
* @param hal I2C HAL interface
|
|
||||||
* @param session Output session context
|
|
||||||
* @param keystore Output key store context
|
|
||||||
* @param rng Output RNG context
|
|
||||||
* @return SE050_OK on success
|
|
||||||
*/
|
|
||||||
se050_status_t se050_wireguard_init(se050_i2c_hal_t *hal,
|
|
||||||
se050_session_ctx_t **session,
|
|
||||||
se050_keystore_ctx_t **keystore,
|
|
||||||
se050_rng_ctx_t **rng);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Generate WireGuard key pair
|
|
||||||
* @param keystore Key store context
|
|
||||||
* @param rng RNG context
|
|
||||||
* @param keypair Output key pair
|
|
||||||
* @param key_id Key identifier
|
|
||||||
* @return SE050_OK on success
|
|
||||||
*/
|
|
||||||
se050_status_t se050_wireguard_generate_key(se050_keystore_ctx_t *keystore,
|
|
||||||
se050_rng_ctx_t *rng,
|
|
||||||
se050_x25519_keypair_t *keypair,
|
|
||||||
uint32_t key_id);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Compute WireGuard shared secret
|
|
||||||
* @param keystore Key store context
|
|
||||||
* @param key_id Local private key ID
|
|
||||||
* @param peer_public Peer's public key
|
|
||||||
* @param shared_secret Output shared secret
|
|
||||||
* @return SE050_OK on success
|
|
||||||
*/
|
|
||||||
se050_status_t se050_wireguard_compute_shared(se050_keystore_ctx_t *keystore,
|
|
||||||
uint32_t key_id,
|
|
||||||
const uint8_t *peer_public,
|
|
||||||
uint8_t *shared_secret);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Cleanup WireGuard SE050 subsystem
|
|
||||||
* @param session Session context
|
* @param session Session context
|
||||||
* @param keystore Key store context
|
* @param shared_secret X25519 shared secret (32 bytes)
|
||||||
* @param rng RNG context
|
* @return 0 on success, -1 on error
|
||||||
*/
|
*/
|
||||||
void se050_wireguard_cleanup(se050_session_ctx_t *session,
|
int se050_wireguard_derive_keys(se050_wireguard_session_t *session,
|
||||||
se050_keystore_ctx_t *keystore,
|
const uint8_t *shared_secret);
|
||||||
se050_rng_ctx_t *rng);
|
|
||||||
|
/* =========================================================================
|
||||||
|
* Packet Encryption/Decryption
|
||||||
|
* ========================================================================= */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Encrypt a WireGuard packet
|
||||||
|
*
|
||||||
|
* Format: [header (16 bytes)] [ciphertext] [auth tag (16 bytes)]
|
||||||
|
*
|
||||||
|
* @param session Session context
|
||||||
|
* @param out Output buffer for encrypted packet
|
||||||
|
* @param out_len Output: actual length of encrypted packet
|
||||||
|
* @param plaintext Plaintext payload
|
||||||
|
* @param plaintext_len Length of plaintext
|
||||||
|
* @return 0 on success, -1 on error
|
||||||
|
*/
|
||||||
|
int se050_wireguard_encrypt_packet(se050_wireguard_session_t *session,
|
||||||
|
uint8_t *out, size_t *out_len,
|
||||||
|
const uint8_t *plaintext, size_t plaintext_len);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Decrypt a WireGuard packet
|
||||||
|
*
|
||||||
|
* @param session Session context
|
||||||
|
* @param plaintext Output buffer for decrypted payload
|
||||||
|
* @param plaintext_len Output: actual length of plaintext
|
||||||
|
* @param packet Encrypted packet
|
||||||
|
* @param packet_len Length of encrypted packet
|
||||||
|
* @return 0 on success, -1 on error (including replay detection)
|
||||||
|
*/
|
||||||
|
int se050_wireguard_decrypt_packet(se050_wireguard_session_t *session,
|
||||||
|
uint8_t *plaintext, size_t *plaintext_len,
|
||||||
|
const uint8_t *packet, size_t packet_len);
|
||||||
|
|
||||||
|
/* =========================================================================
|
||||||
|
* Cookie Mechanism (DoS Protection)
|
||||||
|
* ========================================================================= */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Compute MAC1 for a packet
|
||||||
|
*
|
||||||
|
* MAC1 provides proof of knowledge of peer's public key
|
||||||
|
*
|
||||||
|
* @param session Session context
|
||||||
|
* @param packet Packet data (excluding MAC1/MAC2)
|
||||||
|
* @param packet_len Length of packet data
|
||||||
|
* @param mac1 Output: computed MAC1 (16 bytes)
|
||||||
|
* @return 0 on success, -1 on error
|
||||||
|
*/
|
||||||
|
int se050_wireguard_compute_mac1(se050_wireguard_session_t *session,
|
||||||
|
const uint8_t *packet, size_t packet_len,
|
||||||
|
uint8_t *mac1);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Compute MAC2 for a packet
|
||||||
|
*
|
||||||
|
* MAC2 provides proof of cookie knowledge (DoS protection)
|
||||||
|
*
|
||||||
|
* @param session Session context
|
||||||
|
* @param mac1 Previously computed MAC1
|
||||||
|
* @param packet Packet data
|
||||||
|
* @param packet_len Length of packet data
|
||||||
|
* @param mac2 Output: computed MAC2 (16 bytes)
|
||||||
|
* @return 0 on success, -1 on error
|
||||||
|
*/
|
||||||
|
int se050_wireguard_compute_mac2(se050_wireguard_session_t *session,
|
||||||
|
const uint8_t *mac1,
|
||||||
|
const uint8_t *packet, size_t packet_len,
|
||||||
|
uint8_t *mac2);
|
||||||
|
|
||||||
|
/* =========================================================================
|
||||||
|
* Key Generation
|
||||||
|
* ========================================================================= */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Generate a new WireGuard keypair
|
||||||
|
*
|
||||||
|
* Uses system RNG (/dev/urandom on POSIX).
|
||||||
|
* For SE050 hardware RNG, use se050_wireguard_generate_keypair_se050().
|
||||||
|
* For CSPRNG (seeded from SE050), use se050_wireguard_generate_keypair_csprng().
|
||||||
|
*
|
||||||
|
* @param private_key Output: private key (32 bytes)
|
||||||
|
* @param public_key Output: public key (32 bytes)
|
||||||
|
* @return 0 on success, -1 on error
|
||||||
|
*/
|
||||||
|
int se050_wireguard_generate_keypair(uint8_t *private_key, uint8_t *public_key);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Generate WireGuard keypair using SE050 hardware RNG
|
||||||
|
*
|
||||||
|
* This function uses the SE050 chip's built-in True Random Number Generator
|
||||||
|
* for cryptographically secure key generation.
|
||||||
|
*
|
||||||
|
* @param session SE050 session context (initialized via se050_session_init())
|
||||||
|
* @param private_key Output: private key (32 bytes)
|
||||||
|
* @param public_key Output: public key (32 bytes)
|
||||||
|
* @return 0 on success, -1 on error
|
||||||
|
*/
|
||||||
|
#ifdef SE050_ENABLED
|
||||||
|
int se050_wireguard_generate_keypair_se050(se050_session_ctx_t *session,
|
||||||
|
uint8_t *private_key,
|
||||||
|
uint8_t *public_key);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Initialize CSPRNG with seed from SE050
|
||||||
|
*
|
||||||
|
* This should be called once at system startup. After initialization,
|
||||||
|
* the CSPRNG can generate random numbers without further SE050 access.
|
||||||
|
*
|
||||||
|
* @param seed_func Function to get seed from SE050 (called once)
|
||||||
|
* @param seed_ctx Context for seed function
|
||||||
|
* @return 0 on success, -1 on error
|
||||||
|
*/
|
||||||
|
int se050_csprng_init(int (*seed_func)(uint8_t *out, size_t len, void *ctx), void *seed_ctx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Generate WireGuard keypair using CSPRNG
|
||||||
|
*
|
||||||
|
* After calling se050_csprng_init(), use this function to generate keypairs.
|
||||||
|
* This is ideal for ESP32 and other embedded platforms where I2C access should be minimized.
|
||||||
|
*
|
||||||
|
* @param private_key Output: private key (32 bytes)
|
||||||
|
* @param public_key Output: public key (32 bytes)
|
||||||
|
* @return 0 on success, -1 on error
|
||||||
|
*/
|
||||||
|
int se050_wireguard_generate_keypair_csprng(uint8_t *private_key, uint8_t *public_key);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Generate random bytes using CSPRNG
|
||||||
|
*
|
||||||
|
* @param out Output buffer
|
||||||
|
* @param len Number of bytes to generate
|
||||||
|
* @return 0 on success, -1 on error
|
||||||
|
*/
|
||||||
|
int se050_csprng_random(uint8_t *out, size_t len);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Cleanup CSPRNG and zeroize sensitive data
|
||||||
|
*/
|
||||||
|
void se050_csprng_cleanup(void);
|
||||||
|
|
||||||
|
/* =========================================================================
|
||||||
|
* Constants
|
||||||
|
* ========================================================================= */
|
||||||
|
|
||||||
|
#define WG_KEY_LEN 32 /**< Key length in bytes */
|
||||||
|
#define WG_NONCE_LEN 12 /**< Nonce length in bytes */
|
||||||
|
#define WG_MAX_PACKET_SIZE 65535 /**< Maximum packet size */
|
||||||
|
#define WG_HEADER_SIZE 16 /**< Packet header size */
|
||||||
|
#define WG_MAC1_SIZE 16 /**< MAC1 size */
|
||||||
|
#define WG_MAC2_SIZE 16 /**< MAC2 size */
|
||||||
|
#define WG_AUTH_TAG_SIZE 16 /**< AEAD authentication tag size */
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
+26
-9
@@ -137,16 +137,13 @@ int se050_blake2s_update(se050_blake2s_ctx_t *ctx, const void *data, size_t len)
|
|||||||
{
|
{
|
||||||
blake2s_internal_t *inner = (blake2s_internal_t *)ctx;
|
blake2s_internal_t *inner = (blake2s_internal_t *)ctx;
|
||||||
const uint8_t *in = (const uint8_t *)data;
|
const uint8_t *in = (const uint8_t *)data;
|
||||||
if (!ctx || !data) return -1;
|
if (!ctx) return -1;
|
||||||
|
if (len > 0 && !data) return -1;
|
||||||
if (len > 0) {
|
if (len > 0) {
|
||||||
size_t left = inner->buflen, fill = 64 - left;
|
size_t left = inner->buflen, fill = 64 - left;
|
||||||
if (len > fill) {
|
|
||||||
memcpy(inner->buf + left, in, fill);
|
/* If buffer is empty, process full blocks directly */
|
||||||
inner->buflen = 0;
|
if (left == 0) {
|
||||||
inner->t[0] += 64;
|
|
||||||
if (inner->t[0] < 64) inner->t[1]++;
|
|
||||||
blake2s_compress(inner, inner->buf);
|
|
||||||
in += fill; len -= fill;
|
|
||||||
while (len > 64) {
|
while (len > 64) {
|
||||||
inner->t[0] += 64;
|
inner->t[0] += 64;
|
||||||
if (inner->t[0] < 64) inner->t[1]++;
|
if (inner->t[0] < 64) inner->t[1]++;
|
||||||
@@ -154,6 +151,25 @@ int se050_blake2s_update(se050_blake2s_ctx_t *ctx, const void *data, size_t len)
|
|||||||
in += 64; len -= 64;
|
in += 64; len -= 64;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/* If we can fill the buffer (including exact fill), do it */
|
||||||
|
else if (len >= fill) {
|
||||||
|
memcpy(inner->buf + left, in, fill);
|
||||||
|
inner->buflen = 0;
|
||||||
|
inner->t[0] += 64;
|
||||||
|
if (inner->t[0] < 64) inner->t[1]++;
|
||||||
|
blake2s_compress(inner, inner->buf);
|
||||||
|
in += fill; len -= fill;
|
||||||
|
|
||||||
|
/* Process remaining full blocks */
|
||||||
|
while (len > 64) {
|
||||||
|
inner->t[0] += 64;
|
||||||
|
if (inner->t[0] < 64) inner->t[1]++;
|
||||||
|
blake2s_compress(inner, in);
|
||||||
|
in += 64; len -= 64;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Store remaining data in buffer */
|
||||||
memcpy(inner->buf + inner->buflen, in, len);
|
memcpy(inner->buf + inner->buflen, in, len);
|
||||||
inner->buflen += len;
|
inner->buflen += len;
|
||||||
}
|
}
|
||||||
@@ -232,7 +248,8 @@ int se050_wireguard_generate_secret(uint8_t out[32], const uint8_t *input, size_
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
|
|
||||||
/* RFC 7693 Corrected Test Vector (page 15) */
|
/* RFC 7693 Test Vector (page 15) - BLAKE2s-256("abc") */
|
||||||
|
/* Note: The value 508c5e8c... is the correct BLAKE2s-256("abc") digest */
|
||||||
static const uint8_t BLAKE2S_ABC_DIGEST[32] = {
|
static const uint8_t BLAKE2S_ABC_DIGEST[32] = {
|
||||||
0x50,0x8c,0x5e,0x8c,0x32,0x7c,0x14,0xe2,
|
0x50,0x8c,0x5e,0x8c,0x32,0x7c,0x14,0xe2,
|
||||||
0xe1,0xa7,0x2b,0xa3,0x4e,0xeb,0x45,0x2f,
|
0xe1,0xa7,0x2b,0xa3,0x4e,0xeb,0x45,0x2f,
|
||||||
|
|||||||
+471
-673
File diff suppressed because it is too large
Load Diff
@@ -19,7 +19,7 @@ int se050_hmac_blake2s(uint8_t out[32],
|
|||||||
uint8_t inner_with_key[128];
|
uint8_t inner_with_key[128];
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (!out || !key || keylen == 0 || !data || datalen > 64) {
|
if (!out || !key || keylen == 0 || !data) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+4
-6
@@ -8,6 +8,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#define _POSIX_C_SOURCE 200809L
|
#define _POSIX_C_SOURCE 200809L
|
||||||
|
#include "se050_i2c_hal.h"
|
||||||
#include "se050_wireguard.h"
|
#include "se050_wireguard.h"
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@@ -135,7 +136,8 @@ se050_status_t se050_i2c_init(se050_i2c_hal_t *hal, const char *dev_path, uint8_
|
|||||||
|
|
||||||
hal->handle = handle;
|
hal->handle = handle;
|
||||||
hal->slave_addr = slave_addr;
|
hal->slave_addr = slave_addr;
|
||||||
hal->dev_path = strdup(dev_path);
|
strncpy(hal->dev_path, dev_path, SE050_I2C_DEV_PATH_MAX - 1);
|
||||||
|
hal->dev_path[SE050_I2C_DEV_PATH_MAX - 1] = '\0';
|
||||||
|
|
||||||
return SE050_OK;
|
return SE050_OK;
|
||||||
}
|
}
|
||||||
@@ -151,11 +153,7 @@ void se050_i2c_close(se050_i2c_hal_t *hal)
|
|||||||
hal->handle = NULL;
|
hal->handle = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hal->dev_path) {
|
hal->dev_path[0] = '\0';
|
||||||
free((void *)hal->dev_path);
|
|
||||||
hal->dev_path = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
hal->slave_addr = 0;
|
hal->slave_addr = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+11
-43
@@ -10,16 +10,16 @@
|
|||||||
#define _GNU_SOURCE /* For MADV_DONTDUMP, MADV_WIPEONFORK */
|
#define _GNU_SOURCE /* For MADV_DONTDUMP, MADV_WIPEONFORK */
|
||||||
#define _POSIX_C_SOURCE 200809L
|
#define _POSIX_C_SOURCE 200809L
|
||||||
|
|
||||||
|
#include "se050_i2c_hal.h"
|
||||||
|
#include "se050_session_internal.h"
|
||||||
|
#include "se050_mem_pool.h"
|
||||||
#include "se050_wireguard.h"
|
#include "se050_wireguard.h"
|
||||||
#include "se050_crypto_utils.h"
|
#include "se050_crypto_utils.h"
|
||||||
#include "se050_keystore_internal.h"
|
#include "se050_keystore_internal.h"
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
#include "se050_mem_protect.h"
|
|
||||||
|
|
||||||
/* ============================================================================
|
/* ============================================================================
|
||||||
* Key Store Management
|
* Key Store Management
|
||||||
* ============================================================================ */
|
* ============================================================================ */
|
||||||
@@ -27,46 +27,24 @@
|
|||||||
se050_status_t se050_keystore_init(se050_keystore_ctx_t **ctx, se050_session_ctx_t *session)
|
se050_status_t se050_keystore_init(se050_keystore_ctx_t **ctx, se050_session_ctx_t *session)
|
||||||
{
|
{
|
||||||
se050_keystore_ctx_t *keystore;
|
se050_keystore_ctx_t *keystore;
|
||||||
size_t ctx_size;
|
|
||||||
|
|
||||||
if (!ctx || !session) {
|
if (!ctx || !session) {
|
||||||
return SE050_ERR_INVALID_ARG;
|
return SE050_ERR_INVALID_ARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Allocate key store context */
|
/* Allocate key store context from static pool */
|
||||||
keystore = (se050_keystore_ctx_t *)calloc(1, sizeof(*keystore));
|
keystore = se050_keystore_alloc_pool();
|
||||||
if (!keystore) {
|
if (!keystore) {
|
||||||
return SE050_ERR_FAIL;
|
return SE050_ERR_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx_size = sizeof(*keystore);
|
|
||||||
|
|
||||||
/* Apply memory protection (Linux only) */
|
|
||||||
if (protect_sensitive_memory(keystore, ctx_size) != SE050_OK) {
|
|
||||||
free(keystore);
|
|
||||||
return SE050_ERR_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
keystore->session = session;
|
keystore->session = session;
|
||||||
keystore->max_objects = 16; /* Maximum 16 keys */
|
keystore->max_objects = SE050_POOL_KEYSTORE_MAX_OBJECTS;
|
||||||
keystore->objects = (key_object_t *)calloc(keystore->max_objects, sizeof(key_object_t));
|
|
||||||
|
|
||||||
if (!keystore->objects) {
|
|
||||||
release_memory_protection(keystore, ctx_size);
|
|
||||||
free(keystore);
|
|
||||||
return SE050_ERR_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Protect key objects array */
|
|
||||||
if (protect_sensitive_memory(keystore->objects, keystore->max_objects * sizeof(key_object_t)) != SE050_OK) {
|
|
||||||
free(keystore->objects);
|
|
||||||
release_memory_protection(keystore, ctx_size);
|
|
||||||
free(keystore);
|
|
||||||
return SE050_ERR_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
keystore->num_objects = 0;
|
keystore->num_objects = 0;
|
||||||
|
|
||||||
|
/* Zeroize key objects array */
|
||||||
|
memset(keystore->objects, 0, keystore->max_objects * sizeof(key_object_t));
|
||||||
|
|
||||||
*ctx = keystore;
|
*ctx = keystore;
|
||||||
return SE050_OK;
|
return SE050_OK;
|
||||||
}
|
}
|
||||||
@@ -89,21 +67,11 @@ void se050_keystore_free(se050_keystore_ctx_t *ctx)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Release memory protection for key objects array */
|
|
||||||
if (ctx->objects) {
|
|
||||||
release_memory_protection(ctx->objects, ctx->max_objects * sizeof(key_object_t));
|
|
||||||
free(ctx->objects);
|
|
||||||
ctx->objects = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx->num_objects = 0;
|
ctx->num_objects = 0;
|
||||||
ctx->max_objects = 0;
|
ctx->max_objects = 0;
|
||||||
|
|
||||||
/* Release memory protection for context */
|
/* Free key store context to static pool */
|
||||||
release_memory_protection(ctx, sizeof(*ctx));
|
se050_keystore_free_pool(ctx);
|
||||||
|
|
||||||
/* Free key store context */
|
|
||||||
free(ctx);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ============================================================================
|
/* ============================================================================
|
||||||
|
|||||||
@@ -0,0 +1,304 @@
|
|||||||
|
/**
|
||||||
|
* @file se050_mem_pool.c
|
||||||
|
* @brief Static Memory Pool Implementation
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define _GNU_SOURCE
|
||||||
|
#include "se050_mem_pool.h"
|
||||||
|
#include "se050_session_internal.h"
|
||||||
|
#include "se050_scp03.h"
|
||||||
|
#include "se050_keystore_internal.h"
|
||||||
|
#include "se050_i2c_hal.h"
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdatomic.h>
|
||||||
|
|
||||||
|
/* Forward declarations for structures */
|
||||||
|
/* se050_rng_ctx_t is defined in se050_rng.c, use opaque pointer here */
|
||||||
|
|
||||||
|
/* ============================================================================
|
||||||
|
* Pool Structures
|
||||||
|
* ============================================================================ */
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint8_t *pool;
|
||||||
|
size_t item_size;
|
||||||
|
size_t count;
|
||||||
|
atomic_int used_count;
|
||||||
|
uint8_t *used_bitmap; /* 1 bit per item */
|
||||||
|
} mem_pool_t;
|
||||||
|
|
||||||
|
/* Session pool */
|
||||||
|
static mem_pool_t g_session_pool;
|
||||||
|
static uint8_t g_session_storage[SE050_POOL_SESSION_COUNT * sizeof(struct se050_session_ctx)];
|
||||||
|
static uint8_t g_session_bitmap[SE050_POOL_SESSION_COUNT / 8 + 1];
|
||||||
|
|
||||||
|
/* SCP03 pool */
|
||||||
|
static mem_pool_t g_scp03_pool;
|
||||||
|
static uint8_t g_scp03_storage[SE050_POOL_SCP03_COUNT * sizeof(struct se050_scp03_ctx)];
|
||||||
|
static uint8_t g_scp03_bitmap[SE050_POOL_SCP03_COUNT / 8 + 1];
|
||||||
|
|
||||||
|
/* Keystore pool */
|
||||||
|
static mem_pool_t g_keystore_pool;
|
||||||
|
static uint8_t g_keystore_storage[SE050_POOL_KEYSTORE_COUNT * sizeof(struct se050_keystore_ctx)];
|
||||||
|
static uint8_t g_keystore_bitmap[SE050_POOL_KEYSTORE_COUNT / 8 + 1];
|
||||||
|
|
||||||
|
/* RNG pool */
|
||||||
|
static mem_pool_t g_rng_pool;
|
||||||
|
#define SE050_RNG_CTX_SIZE (sizeof(void*) + sizeof(uint32_t) + 64 + sizeof(size_t))
|
||||||
|
static uint8_t g_rng_storage[SE050_POOL_RNG_COUNT * SE050_RNG_CTX_SIZE];
|
||||||
|
static uint8_t g_rng_bitmap[SE050_POOL_RNG_COUNT / 8 + 1];
|
||||||
|
|
||||||
|
/* I2C HAL pool */
|
||||||
|
static mem_pool_t g_i2c_hal_pool;
|
||||||
|
static uint8_t g_i2c_hal_storage[SE050_POOL_I2C_HAL_COUNT * sizeof(se050_i2c_hal_t)];
|
||||||
|
static uint8_t g_i2c_hal_bitmap[SE050_POOL_I2C_HAL_COUNT / 8 + 1];
|
||||||
|
|
||||||
|
/* ============================================================================
|
||||||
|
* Helper Functions
|
||||||
|
* ============================================================================ */
|
||||||
|
|
||||||
|
static void pool_init(mem_pool_t *pool, uint8_t *storage, size_t item_size,
|
||||||
|
size_t count, uint8_t *bitmap)
|
||||||
|
{
|
||||||
|
pool->pool = storage;
|
||||||
|
pool->item_size = item_size;
|
||||||
|
pool->count = count;
|
||||||
|
atomic_store(&pool->used_count, 0);
|
||||||
|
memset(bitmap, 0, (count + 7) / 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int pool_alloc(mem_pool_t *pool, uint8_t *bitmap)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < pool->count; i++) {
|
||||||
|
size_t byte_idx = i / 8;
|
||||||
|
size_t bit_idx = i % 8;
|
||||||
|
|
||||||
|
if (!(bitmap[byte_idx] & (1 << bit_idx))) {
|
||||||
|
bitmap[byte_idx] |= (1 << bit_idx);
|
||||||
|
atomic_fetch_add(&pool->used_count, 1);
|
||||||
|
return (int)i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1; /* Pool exhausted */
|
||||||
|
}
|
||||||
|
|
||||||
|
static void pool_free(mem_pool_t *pool, uint8_t *bitmap, int index)
|
||||||
|
{
|
||||||
|
if (index < 0 || (size_t)index >= pool->count) return;
|
||||||
|
|
||||||
|
size_t byte_idx = index / 8;
|
||||||
|
size_t bit_idx = index % 8;
|
||||||
|
|
||||||
|
bitmap[byte_idx] &= ~(1 << bit_idx);
|
||||||
|
atomic_fetch_sub(&pool->used_count, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void pool_zeroize(mem_pool_t *pool, uint8_t *bitmap)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < pool->count; i++) {
|
||||||
|
size_t byte_idx = i / 8;
|
||||||
|
size_t bit_idx = i % 8;
|
||||||
|
|
||||||
|
if (bitmap[byte_idx] & (1 << bit_idx)) {
|
||||||
|
memset(pool->pool + (i * pool->item_size), 0, pool->item_size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ============================================================================
|
||||||
|
* Public API
|
||||||
|
* ============================================================================ */
|
||||||
|
|
||||||
|
int se050_mem_pool_init(void)
|
||||||
|
{
|
||||||
|
pool_init(&g_session_pool, g_session_storage, sizeof(struct se050_session_ctx),
|
||||||
|
SE050_POOL_SESSION_COUNT, g_session_bitmap);
|
||||||
|
|
||||||
|
pool_init(&g_scp03_pool, g_scp03_storage, sizeof(struct se050_scp03_ctx),
|
||||||
|
SE050_POOL_SCP03_COUNT, g_scp03_bitmap);
|
||||||
|
|
||||||
|
pool_init(&g_keystore_pool, g_keystore_storage, sizeof(struct se050_keystore_ctx),
|
||||||
|
SE050_POOL_KEYSTORE_COUNT, g_keystore_bitmap);
|
||||||
|
|
||||||
|
pool_init(&g_rng_pool, g_rng_storage, SE050_RNG_CTX_SIZE,
|
||||||
|
SE050_POOL_RNG_COUNT, g_rng_bitmap);
|
||||||
|
|
||||||
|
pool_init(&g_i2c_hal_pool, g_i2c_hal_storage, sizeof(se050_i2c_hal_t),
|
||||||
|
SE050_POOL_I2C_HAL_COUNT, g_i2c_hal_bitmap);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void se050_mem_pool_cleanup(void)
|
||||||
|
{
|
||||||
|
pool_zeroize(&g_session_pool, g_session_bitmap);
|
||||||
|
pool_zeroize(&g_scp03_pool, g_scp03_bitmap);
|
||||||
|
pool_zeroize(&g_keystore_pool, g_keystore_bitmap);
|
||||||
|
pool_zeroize(&g_rng_pool, g_rng_bitmap);
|
||||||
|
pool_zeroize(&g_i2c_hal_pool, g_i2c_hal_bitmap);
|
||||||
|
|
||||||
|
memset(g_session_bitmap, 0, sizeof(g_session_bitmap));
|
||||||
|
memset(g_scp03_bitmap, 0, sizeof(g_scp03_bitmap));
|
||||||
|
memset(g_keystore_bitmap, 0, sizeof(g_keystore_bitmap));
|
||||||
|
memset(g_rng_bitmap, 0, sizeof(g_rng_bitmap));
|
||||||
|
memset(g_i2c_hal_bitmap, 0, sizeof(g_i2c_hal_bitmap));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Session pool */
|
||||||
|
struct se050_session_ctx *se050_session_alloc_pool(void)
|
||||||
|
{
|
||||||
|
int idx = pool_alloc(&g_session_pool, g_session_bitmap);
|
||||||
|
if (idx < 0) return NULL;
|
||||||
|
|
||||||
|
struct se050_session_ctx *ctx = (struct se050_session_ctx *)
|
||||||
|
(g_session_pool.pool + (idx * g_session_pool.item_size));
|
||||||
|
memset(ctx, 0, sizeof(*ctx));
|
||||||
|
return ctx;
|
||||||
|
}
|
||||||
|
|
||||||
|
void se050_session_free_pool(struct se050_session_ctx *ctx)
|
||||||
|
{
|
||||||
|
if (!ctx) return;
|
||||||
|
|
||||||
|
/* Find index and zeroize */
|
||||||
|
size_t offset = (uint8_t *)ctx - g_session_pool.pool;
|
||||||
|
if (offset < g_session_pool.count * g_session_pool.item_size) {
|
||||||
|
size_t idx = offset / g_session_pool.item_size;
|
||||||
|
pool_zeroize(&g_session_pool, g_session_bitmap);
|
||||||
|
pool_free(&g_session_pool, g_session_bitmap, (int)idx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* SCP03 pool */
|
||||||
|
struct se050_scp03_ctx *se050_scp03_alloc_pool(void)
|
||||||
|
{
|
||||||
|
int idx = pool_alloc(&g_scp03_pool, g_scp03_bitmap);
|
||||||
|
if (idx < 0) return NULL;
|
||||||
|
|
||||||
|
struct se050_scp03_ctx *ctx = (struct se050_scp03_ctx *)
|
||||||
|
(g_scp03_pool.pool + (idx * g_scp03_pool.item_size));
|
||||||
|
memset(ctx, 0, sizeof(*ctx));
|
||||||
|
return ctx;
|
||||||
|
}
|
||||||
|
|
||||||
|
void se050_scp03_free_pool(struct se050_scp03_ctx *ctx)
|
||||||
|
{
|
||||||
|
if (!ctx) return;
|
||||||
|
|
||||||
|
size_t offset = (uint8_t *)ctx - g_scp03_pool.pool;
|
||||||
|
if (offset < g_scp03_pool.count * g_scp03_pool.item_size) {
|
||||||
|
size_t idx = offset / g_scp03_pool.item_size;
|
||||||
|
pool_zeroize(&g_scp03_pool, g_scp03_bitmap);
|
||||||
|
pool_free(&g_scp03_pool, g_scp03_bitmap, (int)idx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Keystore pool */
|
||||||
|
struct se050_keystore_ctx *se050_keystore_alloc_pool(void)
|
||||||
|
{
|
||||||
|
int idx = pool_alloc(&g_keystore_pool, g_keystore_bitmap);
|
||||||
|
if (idx < 0) return NULL;
|
||||||
|
|
||||||
|
struct se050_keystore_ctx *ctx = (struct se050_keystore_ctx *)
|
||||||
|
(g_keystore_pool.pool + (idx * g_keystore_pool.item_size));
|
||||||
|
memset(ctx, 0, sizeof(*ctx));
|
||||||
|
return ctx;
|
||||||
|
}
|
||||||
|
|
||||||
|
void se050_keystore_free_pool(struct se050_keystore_ctx *ctx)
|
||||||
|
{
|
||||||
|
if (!ctx) return;
|
||||||
|
|
||||||
|
size_t offset = (uint8_t *)ctx - g_keystore_pool.pool;
|
||||||
|
if (offset < g_keystore_pool.count * g_keystore_pool.item_size) {
|
||||||
|
size_t idx = offset / g_keystore_pool.item_size;
|
||||||
|
pool_zeroize(&g_keystore_pool, g_keystore_bitmap);
|
||||||
|
pool_free(&g_keystore_pool, g_keystore_bitmap, (int)idx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* RNG pool */
|
||||||
|
struct se050_rng_ctx *se050_rng_alloc_pool(void)
|
||||||
|
{
|
||||||
|
int idx = pool_alloc(&g_rng_pool, g_rng_bitmap);
|
||||||
|
if (idx < 0) return NULL;
|
||||||
|
|
||||||
|
struct se050_rng_ctx *ctx = (struct se050_rng_ctx *)
|
||||||
|
(g_rng_pool.pool + (idx * g_rng_pool.item_size));
|
||||||
|
memset(ctx, 0, SE050_RNG_CTX_SIZE);
|
||||||
|
return ctx;
|
||||||
|
}
|
||||||
|
|
||||||
|
void se050_rng_free_pool(struct se050_rng_ctx *ctx)
|
||||||
|
{
|
||||||
|
if (!ctx) return;
|
||||||
|
|
||||||
|
size_t offset = (uint8_t *)ctx - g_rng_pool.pool;
|
||||||
|
if (offset < g_rng_pool.count * g_rng_pool.item_size) {
|
||||||
|
size_t idx = offset / g_rng_pool.item_size;
|
||||||
|
pool_zeroize(&g_rng_pool, g_rng_bitmap);
|
||||||
|
pool_free(&g_rng_pool, g_rng_bitmap, (int)idx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* I2C HAL pool */
|
||||||
|
struct se050_i2c_hal *se050_i2c_hal_alloc_pool(void)
|
||||||
|
{
|
||||||
|
int idx = pool_alloc(&g_i2c_hal_pool, g_i2c_hal_bitmap);
|
||||||
|
if (idx < 0) return NULL;
|
||||||
|
|
||||||
|
se050_i2c_hal_t *hal = (se050_i2c_hal_t *)
|
||||||
|
(g_i2c_hal_pool.pool + (idx * g_i2c_hal_pool.item_size));
|
||||||
|
memset(hal, 0, sizeof(*hal));
|
||||||
|
return (struct se050_i2c_hal *)hal;
|
||||||
|
}
|
||||||
|
|
||||||
|
void se050_i2c_hal_free_pool(struct se050_i2c_hal *hal)
|
||||||
|
{
|
||||||
|
if (!hal) return;
|
||||||
|
|
||||||
|
size_t offset = (uint8_t *)hal - g_i2c_hal_pool.pool;
|
||||||
|
if (offset < g_i2c_hal_pool.count * g_i2c_hal_pool.item_size) {
|
||||||
|
size_t idx = offset / g_i2c_hal_pool.item_size;
|
||||||
|
pool_zeroize(&g_i2c_hal_pool, g_i2c_hal_bitmap);
|
||||||
|
pool_free(&g_i2c_hal_pool, g_i2c_hal_bitmap, (int)idx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Statistics */
|
||||||
|
void se050_mem_pool_stats(se050_pool_stats_t *session,
|
||||||
|
se050_pool_stats_t *scp03,
|
||||||
|
se050_pool_stats_t *keystore,
|
||||||
|
se050_pool_stats_t *rng,
|
||||||
|
se050_pool_stats_t *i2c_hal)
|
||||||
|
{
|
||||||
|
if (session) {
|
||||||
|
session->total = SE050_POOL_SESSION_COUNT;
|
||||||
|
session->used = atomic_load(&g_session_pool.used_count);
|
||||||
|
session->free = session->total - session->used;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (scp03) {
|
||||||
|
scp03->total = SE050_POOL_SCP03_COUNT;
|
||||||
|
scp03->used = atomic_load(&g_scp03_pool.used_count);
|
||||||
|
scp03->free = scp03->total - scp03->used;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (keystore) {
|
||||||
|
keystore->total = SE050_POOL_KEYSTORE_COUNT;
|
||||||
|
keystore->used = atomic_load(&g_keystore_pool.used_count);
|
||||||
|
keystore->free = keystore->total - keystore->used;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rng) {
|
||||||
|
rng->total = SE050_POOL_RNG_COUNT;
|
||||||
|
rng->used = atomic_load(&g_rng_pool.used_count);
|
||||||
|
rng->free = rng->total - rng->used;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i2c_hal) {
|
||||||
|
i2c_hal->total = SE050_POOL_I2C_HAL_COUNT;
|
||||||
|
i2c_hal->used = atomic_load(&g_i2c_hal_pool.used_count);
|
||||||
|
i2c_hal->free = i2c_hal->total - i2c_hal->used;
|
||||||
|
}
|
||||||
|
}
|
||||||
+6
-5
@@ -8,11 +8,12 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#define _POSIX_C_SOURCE 200809L
|
#define _POSIX_C_SOURCE 200809L
|
||||||
|
#include "se050_i2c_hal.h"
|
||||||
|
#include "se050_mem_pool.h"
|
||||||
#include "se050_wireguard.h"
|
#include "se050_wireguard.h"
|
||||||
#include "se050_crypto_utils.h"
|
#include "se050_crypto_utils.h"
|
||||||
#include "se050_session_internal.h"
|
#include "se050_session_internal.h"
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
@@ -40,8 +41,8 @@ se050_status_t se050_rng_init(se050_rng_ctx_t **ctx, se050_session_ctx_t *sessio
|
|||||||
return SE050_ERR_INVALID_ARG;
|
return SE050_ERR_INVALID_ARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Allocate RNG context */
|
/* Allocate RNG context from static pool */
|
||||||
rng = (se050_rng_ctx_t *)calloc(1, sizeof(*rng));
|
rng = se050_rng_alloc_pool();
|
||||||
if (!rng) {
|
if (!rng) {
|
||||||
return SE050_ERR_FAIL;
|
return SE050_ERR_FAIL;
|
||||||
}
|
}
|
||||||
@@ -69,8 +70,8 @@ void se050_rng_free(se050_rng_ctx_t *ctx)
|
|||||||
ctx->entropy_len = 0;
|
ctx->entropy_len = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Free RNG context */
|
/* Free RNG context to static pool */
|
||||||
free(ctx);
|
se050_rng_free_pool(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ============================================================================
|
/* ============================================================================
|
||||||
|
|||||||
@@ -0,0 +1,209 @@
|
|||||||
|
/**
|
||||||
|
* @file se050_rng_seed.c
|
||||||
|
* @brief SE050-based CSPRNG with initial seed
|
||||||
|
*
|
||||||
|
* This module provides a cryptographically secure pseudo-random number generator
|
||||||
|
* that is seeded once from SE050 hardware TRNG at startup, then uses ChaCha20
|
||||||
|
* to generate the rest of the random stream.
|
||||||
|
*
|
||||||
|
* Benefits:
|
||||||
|
* - Minimal I2C communication (only once at startup)
|
||||||
|
* - Fast random generation after seeding
|
||||||
|
* - Cryptographically secure (ChaCha20-based)
|
||||||
|
* - Suitable for ESP32 and other embedded platforms
|
||||||
|
*
|
||||||
|
* License: MIT (Clean-room implementation)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "se050_wireguard.h"
|
||||||
|
#include "se050_x25519_sw.h"
|
||||||
|
#include "se050_chacha20_poly1305.h"
|
||||||
|
#include "se050_crypto_utils.h"
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
/* ============================================================================
|
||||||
|
* Constants
|
||||||
|
* ============================================================================ */
|
||||||
|
|
||||||
|
#define SEED_SIZE 32
|
||||||
|
#define COUNTER_SIZE 4
|
||||||
|
#define NONCE_SIZE 12
|
||||||
|
#define KEY_SIZE 32
|
||||||
|
|
||||||
|
/* ============================================================================
|
||||||
|
* CSPRNG Context
|
||||||
|
* ============================================================================ */
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint8_t key[KEY_SIZE]; /* ChaCha20 key (from SE050 seed) */
|
||||||
|
uint32_t counter; /* Stream counter */
|
||||||
|
uint8_t buffer[64]; /* Current block buffer */
|
||||||
|
size_t buffer_pos; /* Current position in buffer */
|
||||||
|
int initialized; /* Initialization flag */
|
||||||
|
} se050_csprng_ctx_t;
|
||||||
|
|
||||||
|
/* Global CSPRNG instance */
|
||||||
|
static se050_csprng_ctx_t g_rng;
|
||||||
|
|
||||||
|
/* ============================================================================
|
||||||
|
* ChaCha20-based CSPRNG
|
||||||
|
* ============================================================================ */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Generate a new ChaCha20 block
|
||||||
|
*/
|
||||||
|
static void csprng_generate_block(se050_csprng_ctx_t *ctx)
|
||||||
|
{
|
||||||
|
uint8_t nonce[NONCE_SIZE] = {0};
|
||||||
|
|
||||||
|
/* Set counter in nonce (last 4 bytes) */
|
||||||
|
nonce[8] = (ctx->counter >> 0) & 0xff;
|
||||||
|
nonce[9] = (ctx->counter >> 8) & 0xff;
|
||||||
|
nonce[10] = (ctx->counter >> 16) & 0xff;
|
||||||
|
nonce[11] = (ctx->counter >> 24) & 0xff;
|
||||||
|
ctx->counter++;
|
||||||
|
|
||||||
|
/* Generate ChaCha20 block */
|
||||||
|
se050_chacha20_block(ctx->buffer, ctx->key, 0, nonce);
|
||||||
|
ctx->buffer_pos = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Generate random bytes using ChaCha20 stream
|
||||||
|
*/
|
||||||
|
static int csprng_generate(uint8_t *out, size_t len)
|
||||||
|
{
|
||||||
|
if (!g_rng.initialized) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!out || len == 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0; i < len; i++) {
|
||||||
|
if (g_rng.buffer_pos >= 64) {
|
||||||
|
csprng_generate_block(&g_rng);
|
||||||
|
}
|
||||||
|
out[i] = g_rng.buffer[g_rng.buffer_pos++];
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ============================================================================
|
||||||
|
* SE050 Seed Integration
|
||||||
|
* ============================================================================ */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Callback type for SE050 RNG
|
||||||
|
*/
|
||||||
|
typedef int (*se050_rng_func_t)(uint8_t *out, size_t len, void *ctx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Initialize CSPRNG with seed from SE050
|
||||||
|
*
|
||||||
|
* @param seed_func Function to get seed from SE050
|
||||||
|
* @param seed_ctx Context for seed function
|
||||||
|
* @return 0 on success, -1 on error
|
||||||
|
*/
|
||||||
|
int se050_csprng_init(se050_rng_func_t seed_func, void *seed_ctx)
|
||||||
|
{
|
||||||
|
if (!seed_func) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Zeroize context first */
|
||||||
|
memset(&g_rng, 0, sizeof(g_rng));
|
||||||
|
|
||||||
|
/* Get seed from SE050 */
|
||||||
|
uint8_t seed[SEED_SIZE];
|
||||||
|
if (seed_func(seed, SEED_SIZE, seed_ctx) != 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Use seed as ChaCha20 key */
|
||||||
|
memcpy(g_rng.key, seed, KEY_SIZE);
|
||||||
|
|
||||||
|
/* Clear seed from memory */
|
||||||
|
memzero_explicit(seed, SEED_SIZE);
|
||||||
|
|
||||||
|
/* Initialize counter and buffer */
|
||||||
|
g_rng.counter = 0;
|
||||||
|
g_rng.buffer_pos = 64; /* Force initial block generation */
|
||||||
|
g_rng.initialized = 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Generate random bytes (public API)
|
||||||
|
*/
|
||||||
|
int se050_csprng_generate(uint8_t *out, size_t len)
|
||||||
|
{
|
||||||
|
return csprng_generate(out, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Securely zeroize and cleanup CSPRNG
|
||||||
|
*/
|
||||||
|
void se050_csprng_cleanup(void)
|
||||||
|
{
|
||||||
|
if (g_rng.initialized) {
|
||||||
|
memzero_explicit(g_rng.key, KEY_SIZE);
|
||||||
|
memzero_explicit(g_rng.buffer, 64);
|
||||||
|
g_rng.initialized = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ============================================================================
|
||||||
|
* WireGuard Key Generation with CSPRNG
|
||||||
|
* ============================================================================ */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief RNG wrapper for x25519 keypair generation using CSPRNG
|
||||||
|
*/
|
||||||
|
static int csprng_wrapper(uint8_t *out, size_t len, void *ctx)
|
||||||
|
{
|
||||||
|
(void)ctx; /* Unused */
|
||||||
|
return csprng_generate(out, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Generate WireGuard keypair using seeded CSPRNG
|
||||||
|
*
|
||||||
|
* @param private_key Output: private key (32 bytes)
|
||||||
|
* @param public_key Output: public key (32 bytes)
|
||||||
|
* @return 0 on success, -1 on error
|
||||||
|
*/
|
||||||
|
int se050_wireguard_generate_keypair_csprng(uint8_t *private_key, uint8_t *public_key)
|
||||||
|
{
|
||||||
|
if (!private_key || !public_key) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!g_rng.initialized) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
se050_x25519_sw_keypair_t keypair;
|
||||||
|
|
||||||
|
if (se050_x25519_sw_generate_keypair(&keypair, csprng_wrapper, NULL) < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(private_key, keypair.private_key, 32);
|
||||||
|
memcpy(public_key, keypair.public_key, 32);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Generate random bytes for general use
|
||||||
|
*/
|
||||||
|
int se050_csprng_random(uint8_t *out, size_t len)
|
||||||
|
{
|
||||||
|
return csprng_generate(out, len);
|
||||||
|
}
|
||||||
+8
-32
@@ -10,11 +10,14 @@
|
|||||||
#define _GNU_SOURCE /* For MADV_DONTDUMP, MADV_WIPEONFORK */
|
#define _GNU_SOURCE /* For MADV_DONTDUMP, MADV_WIPEONFORK */
|
||||||
#define _POSIX_C_SOURCE 200809L
|
#define _POSIX_C_SOURCE 200809L
|
||||||
|
|
||||||
|
#include "se050_i2c_hal.h"
|
||||||
|
#include "se050_session_internal.h"
|
||||||
|
#include "se050_scp03.h"
|
||||||
|
#include "se050_mem_pool.h"
|
||||||
#include "se050_wireguard.h"
|
#include "se050_wireguard.h"
|
||||||
#include "se050_crypto_utils.h"
|
#include "se050_crypto_utils.h"
|
||||||
#include "se050_mem_protect.h"
|
#include "se050_mem_protect.h"
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
/* SCP03 constants */
|
/* SCP03 constants */
|
||||||
@@ -28,21 +31,6 @@
|
|||||||
#define SCP03_SW_SUCCESS 0x9000
|
#define SCP03_SW_SUCCESS 0x9000
|
||||||
#define SCP03_SW_FAIL 0x6F00
|
#define SCP03_SW_FAIL 0x6F00
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief SCP03 session context structure
|
|
||||||
*/
|
|
||||||
struct se050_scp03_ctx {
|
|
||||||
se050_session_ctx_t *session; /**< Associated session */
|
|
||||||
uint8_t enc_key[SCP03_KEY_SIZE]; /**< Encryption key */
|
|
||||||
uint8_t mac_key[SCP03_KEY_SIZE]; /**< MAC key */
|
|
||||||
uint8_t dek_key[SCP03_KEY_SIZE]; /**< DEK key (for key derivation) */
|
|
||||||
uint8_t cmd_icv[SCP03_CMAC_SIZE]; /**< Command ICV */
|
|
||||||
uint8_t rsp_icv[SCP03_CMAC_SIZE]; /**< Response ICV */
|
|
||||||
uint64_t cmd_counter; /**< Command counter */
|
|
||||||
uint64_t rsp_counter; /**< Response counter */
|
|
||||||
uint8_t initialized; /**< Initialization flag */
|
|
||||||
};
|
|
||||||
|
|
||||||
/* ============================================================================
|
/* ============================================================================
|
||||||
* Helper Functions
|
* Helper Functions
|
||||||
* ============================================================================ */
|
* ============================================================================ */
|
||||||
@@ -301,26 +289,17 @@ static se050_status_t scp03_derive_session_keys(se050_scp03_ctx_t *ctx)
|
|||||||
se050_status_t se050_scp03_init(se050_scp03_ctx_t **ctx, se050_session_ctx_t *session)
|
se050_status_t se050_scp03_init(se050_scp03_ctx_t **ctx, se050_session_ctx_t *session)
|
||||||
{
|
{
|
||||||
se050_scp03_ctx_t *scp03;
|
se050_scp03_ctx_t *scp03;
|
||||||
size_t ctx_size;
|
|
||||||
|
|
||||||
if (!ctx || !session) {
|
if (!ctx || !session) {
|
||||||
return SE050_ERR_INVALID_ARG;
|
return SE050_ERR_INVALID_ARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Allocate SCP03 context */
|
/* Allocate SCP03 context from static pool */
|
||||||
scp03 = (se050_scp03_ctx_t *)calloc(1, sizeof(*scp03));
|
scp03 = se050_scp03_alloc_pool();
|
||||||
if (!scp03) {
|
if (!scp03) {
|
||||||
return SE050_ERR_FAIL;
|
return SE050_ERR_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx_size = sizeof(*scp03);
|
|
||||||
|
|
||||||
/* Apply memory protection (Linux only) */
|
|
||||||
if (protect_sensitive_memory(scp03, ctx_size) != SE050_OK) {
|
|
||||||
free(scp03);
|
|
||||||
return SE050_ERR_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
scp03->session = session;
|
scp03->session = session;
|
||||||
scp03->cmd_counter = 0;
|
scp03->cmd_counter = 0;
|
||||||
scp03->rsp_counter = 0;
|
scp03->rsp_counter = 0;
|
||||||
@@ -352,11 +331,8 @@ void se050_scp03_free(se050_scp03_ctx_t *ctx)
|
|||||||
memzero_explicit(ctx->rsp_icv, sizeof(ctx->rsp_icv));
|
memzero_explicit(ctx->rsp_icv, sizeof(ctx->rsp_icv));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Release memory protection before freeing */
|
/* Free SCP03 context to static pool */
|
||||||
release_memory_protection(ctx, sizeof(*ctx));
|
se050_scp03_free_pool(ctx);
|
||||||
|
|
||||||
/* Free SCP03 context */
|
|
||||||
free(ctx);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
se050_status_t se050_scp03_set_keys(se050_scp03_ctx_t *ctx,
|
se050_status_t se050_scp03_set_keys(se050_scp03_ctx_t *ctx,
|
||||||
|
|||||||
+9
-28
@@ -8,38 +8,19 @@
|
|||||||
* License: MIT (Clean-room implementation)
|
* License: MIT (Clean-room implementation)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "se050_i2c_hal.h"
|
||||||
|
#include "se050_session_internal.h"
|
||||||
|
#include "se050_mem_pool.h"
|
||||||
|
#include "se050_scp03.h"
|
||||||
#include "se050_wireguard.h"
|
#include "se050_wireguard.h"
|
||||||
#include "se050_crypto_utils.h"
|
#include "se050_crypto_utils.h"
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
/* SCP03 status codes */
|
/* SCP03 status codes */
|
||||||
#define SCP03_SW_SUCCESS 0x9000
|
#define SCP03_SW_SUCCESS 0x9000
|
||||||
#define SCP03_SW_FAIL 0x6F00
|
#define SCP03_SW_FAIL 0x6F00
|
||||||
|
|
||||||
/* Session states */
|
|
||||||
typedef enum {
|
|
||||||
SESSION_STATE_CREATED = 0,
|
|
||||||
SESSION_STATE_OPENED,
|
|
||||||
SESSION_STATE_CLOSED,
|
|
||||||
} session_state_t;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Session context structure
|
|
||||||
*
|
|
||||||
* Includes SCP03 secure channel support for PlatformSCP03 authentication.
|
|
||||||
*/
|
|
||||||
struct se050_session_ctx {
|
|
||||||
se050_i2c_hal_t *hal; /**< I2C HAL interface */
|
|
||||||
session_state_t state; /**< Current session state */
|
|
||||||
uint32_t session_id; /**< Unique session identifier */
|
|
||||||
se050_scp03_ctx_t *scp03; /**< SCP03 secure channel context */
|
|
||||||
uint8_t session_key[32]; /**< Session encryption key */
|
|
||||||
size_t session_key_len; /**< Session key length */
|
|
||||||
se050_rng_ctx_t *rng; /**< RNG context */
|
|
||||||
};
|
|
||||||
|
|
||||||
/* ============================================================================
|
/* ============================================================================
|
||||||
* Session Management
|
* Session Management
|
||||||
* ============================================================================ */
|
* ============================================================================ */
|
||||||
@@ -53,8 +34,8 @@ se050_status_t se050_session_create(se050_session_ctx_t **ctx, se050_i2c_hal_t *
|
|||||||
return SE050_ERR_INVALID_ARG;
|
return SE050_ERR_INVALID_ARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Allocate session context */
|
/* Allocate session context from static pool */
|
||||||
session = (se050_session_ctx_t *)calloc(1, sizeof(*session));
|
session = se050_session_alloc_pool();
|
||||||
if (!session) {
|
if (!session) {
|
||||||
return SE050_ERR_FAIL;
|
return SE050_ERR_FAIL;
|
||||||
}
|
}
|
||||||
@@ -165,7 +146,7 @@ void se050_session_delete(se050_session_ctx_t *ctx)
|
|||||||
|
|
||||||
/* Close SCP03 secure channel if initialized */
|
/* Close SCP03 secure channel if initialized */
|
||||||
if (ctx->scp03) {
|
if (ctx->scp03) {
|
||||||
se050_scp03_free(ctx->scp03);
|
se050_scp03_free_pool(ctx->scp03);
|
||||||
ctx->scp03 = NULL;
|
ctx->scp03 = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -175,8 +156,8 @@ void se050_session_delete(se050_session_ctx_t *ctx)
|
|||||||
ctx->session_key_len = 0;
|
ctx->session_key_len = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Free session context */
|
/* Free session context to static pool */
|
||||||
free(ctx);
|
se050_session_free_pool(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ============================================================================
|
/* ============================================================================
|
||||||
|
|||||||
@@ -0,0 +1,468 @@
|
|||||||
|
/**
|
||||||
|
* @file se050_wireguard.c
|
||||||
|
* @brief WireGuard VPN Protocol Implementation (Clean-room)
|
||||||
|
*
|
||||||
|
* Based on RFC 9153 - WireGuard
|
||||||
|
* License: MIT (Clean-room implementation)
|
||||||
|
*
|
||||||
|
* WireGuard is a modern, fast, and secure VPN protocol that uses:
|
||||||
|
* - X25519 for key exchange
|
||||||
|
* - ChaCha20 for encryption
|
||||||
|
* - Poly1305 for authentication
|
||||||
|
* - BLAKE2s for hashing
|
||||||
|
* - TAI64N for timestamping
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "se050_wireguard.h"
|
||||||
|
#include "se050_x25519_sw.h"
|
||||||
|
#include "se050_chacha20_poly1305.h"
|
||||||
|
#include "se050_blake2s.h"
|
||||||
|
#include "se050_hmac_blake2s.h"
|
||||||
|
#include "se050_tai64n.h"
|
||||||
|
#include "se050_crypto_utils.h"
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
/* =========================================================================
|
||||||
|
* WireGuard Protocol Constants
|
||||||
|
* ========================================================================= */
|
||||||
|
|
||||||
|
#define WG_NONCE_LEN 12
|
||||||
|
#define WG_MAX_PACKET_SIZE 65535
|
||||||
|
#define WG_MAC1_SIZE 16
|
||||||
|
#define WG_MAC2_SIZE 16
|
||||||
|
|
||||||
|
/* WireGuard packet types (RFC 9153) */
|
||||||
|
#define WG_TYPE_HANDSHAKE_INIT 1
|
||||||
|
#define WG_TYPE_HANDSHAKE_RESP 2
|
||||||
|
#define WG_TYPE_COOKIE_REPLY 3
|
||||||
|
#define WG_TYPE_DATA 4
|
||||||
|
|
||||||
|
/* Cookie magic */
|
||||||
|
static const uint8_t WG_COOKIE_MAGIC[16] = {
|
||||||
|
0x12, 0x04, 0x21, 0x00, 0x00, 0x00, 0x00, 0x02,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* =========================================================================
|
||||||
|
* Helper Functions
|
||||||
|
* ========================================================================= */
|
||||||
|
|
||||||
|
/* Constant-time comparison */
|
||||||
|
static bool constant_time_eq(const uint8_t *a, const uint8_t *b, size_t len)
|
||||||
|
{
|
||||||
|
volatile uint8_t result = 0;
|
||||||
|
for (size_t i = 0; i < len; i++) {
|
||||||
|
result |= a[i] ^ b[i];
|
||||||
|
}
|
||||||
|
return result == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* HKDF for WireGuard - always uses 32-byte PRK
|
||||||
|
* T(1) = HMAC(PRK, 0x01)
|
||||||
|
* T(2) = HMAC(PRK, T(1) || 0x02)
|
||||||
|
* T(3) = HMAC(PRK, T(2) || 0x03)
|
||||||
|
*/
|
||||||
|
static void wg_hkdf_2(const uint8_t *prk,
|
||||||
|
uint8_t *out1, uint8_t *out2)
|
||||||
|
{
|
||||||
|
/* T(1) = HMAC(PRK, 0x01) */
|
||||||
|
uint8_t c1 = 0x01;
|
||||||
|
se050_hmac_blake2s(out1, prk, 32, &c1, 1);
|
||||||
|
|
||||||
|
/* T(2) = HMAC(PRK, T(1) || 0x02) */
|
||||||
|
uint8_t t2_input[33];
|
||||||
|
memcpy(t2_input, out1, 32);
|
||||||
|
t2_input[32] = 0x02;
|
||||||
|
se050_hmac_blake2s(out2, prk, 32, t2_input, 33);
|
||||||
|
|
||||||
|
memzero_explicit(t2_input, 33);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* HKDF-3 (three outputs) - WireGuard style */
|
||||||
|
static void wg_hkdf_3(const uint8_t *prk,
|
||||||
|
uint8_t *out1, uint8_t *out2, uint8_t *out3)
|
||||||
|
{
|
||||||
|
/* T(1) = HMAC(PRK, 0x01) */
|
||||||
|
uint8_t c1 = 0x01;
|
||||||
|
se050_hmac_blake2s(out1, prk, 32, &c1, 1);
|
||||||
|
|
||||||
|
/* T(2) = HMAC(PRK, T(1) || 0x02) */
|
||||||
|
uint8_t t2_input[33];
|
||||||
|
memcpy(t2_input, out1, 32);
|
||||||
|
t2_input[32] = 0x02;
|
||||||
|
se050_hmac_blake2s(out2, prk, 32, t2_input, 33);
|
||||||
|
|
||||||
|
/* T(3) = HMAC(PRK, T(2) || 0x03) */
|
||||||
|
uint8_t t3_input[33];
|
||||||
|
memcpy(t3_input, out2, 32);
|
||||||
|
t3_input[32] = 0x03;
|
||||||
|
se050_hmac_blake2s(out3, prk, 32, t3_input, 33);
|
||||||
|
|
||||||
|
memzero_explicit(t2_input, 33);
|
||||||
|
memzero_explicit(t3_input, 33);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* =========================================================================
|
||||||
|
* Session Management
|
||||||
|
* ========================================================================= */
|
||||||
|
|
||||||
|
int se050_wireguard_session_init(se050_wireguard_session_t *session,
|
||||||
|
const uint8_t *private_key,
|
||||||
|
const uint8_t *peer_public_key)
|
||||||
|
{
|
||||||
|
if (!session || !private_key || !peer_public_key) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(session, 0, sizeof(*session));
|
||||||
|
|
||||||
|
/* Copy keys */
|
||||||
|
memcpy(session->private_key, private_key, WG_KEY_LEN);
|
||||||
|
memcpy(session->peer_public_key, peer_public_key, WG_KEY_LEN);
|
||||||
|
|
||||||
|
/* Derive public key from private key */
|
||||||
|
if (se050_x25519_sw_derive_public_key(session->public_key, private_key) < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Initialize chain key with peer public key */
|
||||||
|
memcpy(session->chain_key, peer_public_key, WG_KEY_LEN);
|
||||||
|
|
||||||
|
/* Initialize cookie state */
|
||||||
|
/* WireGuard uses keyed BLAKE2s, not HMAC */
|
||||||
|
se050_blake2s_keyed(session->cookie_secret, 32,
|
||||||
|
WG_COOKIE_MAGIC, sizeof(WG_COOKIE_MAGIC),
|
||||||
|
private_key, WG_KEY_LEN);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void se050_wireguard_session_cleanup(se050_wireguard_session_t *session)
|
||||||
|
{
|
||||||
|
if (!session) return;
|
||||||
|
|
||||||
|
/* Zeroize all sensitive data */
|
||||||
|
memzero_explicit(session->private_key, WG_KEY_LEN);
|
||||||
|
memzero_explicit(session->public_key, WG_KEY_LEN);
|
||||||
|
memzero_explicit(session->peer_public_key, WG_KEY_LEN);
|
||||||
|
memzero_explicit(session->handshake_secret, 32);
|
||||||
|
memzero_explicit(session->chain_key, 32);
|
||||||
|
memzero_explicit(session->sending_key, 32);
|
||||||
|
memzero_explicit(session->receiving_key, 32);
|
||||||
|
memzero_explicit(session->cookie_secret, 32);
|
||||||
|
memzero_explicit(session->last_mac1, WG_MAC1_SIZE);
|
||||||
|
|
||||||
|
memset(session, 0, sizeof(*session));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* =========================================================================
|
||||||
|
* Handshake (simplified - no full handshake implementation)
|
||||||
|
* ========================================================================= */
|
||||||
|
|
||||||
|
int se050_wireguard_derive_keys(se050_wireguard_session_t *session,
|
||||||
|
const uint8_t *shared_secret)
|
||||||
|
{
|
||||||
|
if (!session || !shared_secret) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Derive sending and receiving keys using HKDF
|
||||||
|
* WireGuard uses simplified HKDF with 32-byte PRK
|
||||||
|
*
|
||||||
|
* Key derivation differs for initiator vs responder:
|
||||||
|
* - Initiator: sending = T(1), receiving = T(2)
|
||||||
|
* - Responder: sending = T(2), receiving = T(1)
|
||||||
|
*/
|
||||||
|
uint8_t t1[32], t2[32];
|
||||||
|
wg_hkdf_2(shared_secret, t1, t2);
|
||||||
|
|
||||||
|
if (session->is_initiator) {
|
||||||
|
/* Initiator: sending = T(1), receiving = T(2) */
|
||||||
|
memcpy(session->sending_key, t1, 32);
|
||||||
|
memcpy(session->receiving_key, t2, 32);
|
||||||
|
} else {
|
||||||
|
/* Responder: sending = T(2), receiving = T(1) */
|
||||||
|
memcpy(session->sending_key, t2, 32);
|
||||||
|
memcpy(session->receiving_key, t1, 32);
|
||||||
|
}
|
||||||
|
|
||||||
|
memzero_explicit(t1, 32);
|
||||||
|
memzero_explicit(t2, 32);
|
||||||
|
|
||||||
|
/* Reset nonces */
|
||||||
|
session->sending_nonce = 0;
|
||||||
|
session->receiving_nonce = 0;
|
||||||
|
|
||||||
|
session->handshake_complete = 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* =========================================================================
|
||||||
|
* Packet Encryption/Decryption
|
||||||
|
* ========================================================================= */
|
||||||
|
|
||||||
|
int se050_wireguard_encrypt_packet(se050_wireguard_session_t *session,
|
||||||
|
uint8_t *out, size_t *out_len,
|
||||||
|
const uint8_t *plaintext, size_t plaintext_len)
|
||||||
|
{
|
||||||
|
if (!session || !out || !out_len || !plaintext) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!session->handshake_complete) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (plaintext_len > WG_MAX_PACKET_SIZE) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Construct packet: [header (16)] [encrypted payload + MAC (16)] */
|
||||||
|
/* Header: type (4) + reserved (4) + key index (4) + nonce (8) */
|
||||||
|
|
||||||
|
uint8_t header[16];
|
||||||
|
header[0] = WG_TYPE_DATA; /* RFC 9153: Data packet */
|
||||||
|
memset(header + 1, 0, 3); /* Reserved */
|
||||||
|
memset(header + 4, 0, 4); /* Key index (not used) */
|
||||||
|
|
||||||
|
/* Encode nonce (little-endian) */
|
||||||
|
uint64_t nonce = session->sending_nonce;
|
||||||
|
header[8] = nonce & 0xff;
|
||||||
|
header[9] = (nonce >> 8) & 0xff;
|
||||||
|
header[10] = (nonce >> 16) & 0xff;
|
||||||
|
header[11] = (nonce >> 24) & 0xff;
|
||||||
|
header[12] = (nonce >> 32) & 0xff;
|
||||||
|
header[13] = (nonce >> 40) & 0xff;
|
||||||
|
header[14] = (nonce >> 48) & 0xff;
|
||||||
|
header[15] = (nonce >> 56) & 0xff;
|
||||||
|
|
||||||
|
memcpy(out, header, 16);
|
||||||
|
|
||||||
|
/* Encrypt payload with ChaCha20-Poly1305
|
||||||
|
* Note: We encrypt directly into the output buffer to avoid large stack allocation
|
||||||
|
* out = [header(16)][ciphertext][tag(16)]
|
||||||
|
*/
|
||||||
|
uint8_t nonce_buf[WG_NONCE_LEN];
|
||||||
|
memset(nonce_buf, 0, 4);
|
||||||
|
memcpy(nonce_buf + 4, header + 8, 8);
|
||||||
|
|
||||||
|
uint8_t tag[16];
|
||||||
|
|
||||||
|
se050_chacha20_poly1305_ctx_t aead_ctx;
|
||||||
|
se050_chacha20_poly1305_init(&aead_ctx, session->sending_key);
|
||||||
|
|
||||||
|
int ret = se050_chacha20_poly1305_encrypt(
|
||||||
|
&aead_ctx, /* ctx */
|
||||||
|
nonce_buf, /* nonce */
|
||||||
|
plaintext, plaintext_len, /* plaintext */
|
||||||
|
header, 16, /* aad */
|
||||||
|
out + 16, /* ciphertext (direct write) */
|
||||||
|
tag /* tag */
|
||||||
|
);
|
||||||
|
|
||||||
|
se050_chacha20_poly1305_zeroize(&aead_ctx);
|
||||||
|
|
||||||
|
if (ret < 0) {
|
||||||
|
memzero_explicit(tag, 16);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(out + 16 + plaintext_len, tag, 16);
|
||||||
|
*out_len = 16 + plaintext_len + 16;
|
||||||
|
memzero_explicit(tag, 16);
|
||||||
|
|
||||||
|
/* Increment nonce */
|
||||||
|
session->sending_nonce++;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int se050_wireguard_decrypt_packet(se050_wireguard_session_t *session,
|
||||||
|
uint8_t *plaintext, size_t *plaintext_len,
|
||||||
|
const uint8_t *packet, size_t packet_len)
|
||||||
|
{
|
||||||
|
if (!session || !plaintext || !plaintext_len || !packet) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!session->handshake_complete) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (packet_len < 32) { /* Minimum: header (16) + ciphertext (0) + tag (16) */
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Parse header */
|
||||||
|
const uint8_t *header = packet;
|
||||||
|
uint8_t type = packet[0];
|
||||||
|
if (type != WG_TYPE_DATA) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Extract nonce from header */
|
||||||
|
uint64_t nonce = 0;
|
||||||
|
for (int i = 0; i < 8; i++) {
|
||||||
|
nonce |= ((uint64_t)packet[8 + i]) << (8 * i);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check replay - strictly reject nonce <= last received nonce */
|
||||||
|
if (session->packets_received > 0 && nonce <= session->receiving_nonce) {
|
||||||
|
return -1; /* Replay detected */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Decrypt payload */
|
||||||
|
uint8_t nonce_buf[WG_NONCE_LEN];
|
||||||
|
memset(nonce_buf, 0, 4);
|
||||||
|
memcpy(nonce_buf + 4, packet + 8, 8);
|
||||||
|
|
||||||
|
size_t ciphertext_len = packet_len - 16 - 16; /* Total - header - tag */
|
||||||
|
uint8_t tag[16];
|
||||||
|
memcpy(tag, packet + 16 + ciphertext_len, 16);
|
||||||
|
|
||||||
|
se050_chacha20_poly1305_ctx_t aead_ctx;
|
||||||
|
se050_chacha20_poly1305_init(&aead_ctx, session->receiving_key);
|
||||||
|
|
||||||
|
int ret = se050_chacha20_poly1305_decrypt(
|
||||||
|
&aead_ctx, /* ctx */
|
||||||
|
nonce_buf, /* nonce */
|
||||||
|
packet + 16, ciphertext_len, /* ciphertext */
|
||||||
|
header, 16, /* aad, aad_len */
|
||||||
|
tag, /* tag */
|
||||||
|
plaintext /* plaintext (output) */
|
||||||
|
);
|
||||||
|
|
||||||
|
se050_chacha20_poly1305_zeroize(&aead_ctx);
|
||||||
|
memzero_explicit(tag, 16);
|
||||||
|
|
||||||
|
if (ret < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Update plaintext length and nonce only on success */
|
||||||
|
*plaintext_len = ciphertext_len;
|
||||||
|
session->receiving_nonce = nonce;
|
||||||
|
session->packets_received++;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* =========================================================================
|
||||||
|
* Cookie Mechanism (DoS Protection)
|
||||||
|
* ========================================================================= */
|
||||||
|
|
||||||
|
int se050_wireguard_compute_mac1(se050_wireguard_session_t *session,
|
||||||
|
const uint8_t *packet, size_t packet_len,
|
||||||
|
uint8_t *mac1)
|
||||||
|
{
|
||||||
|
if (!session || !packet || !mac1) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* WireGuard uses keyed BLAKE2s for MAC1 */
|
||||||
|
return se050_blake2s_keyed(mac1, 16, session->peer_public_key, WG_KEY_LEN,
|
||||||
|
packet, packet_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
int se050_wireguard_compute_mac2(se050_wireguard_session_t *session,
|
||||||
|
const uint8_t *mac1,
|
||||||
|
const uint8_t *packet, size_t packet_len,
|
||||||
|
uint8_t *mac2)
|
||||||
|
{
|
||||||
|
if (!session || !mac1 || !packet || !mac2) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* MAC2 is only used during handshake (packets < 148 bytes)
|
||||||
|
* Fixed buffer is sufficient and avoids malloc dependency
|
||||||
|
* This is safe for u-boot and other embedded environments
|
||||||
|
*/
|
||||||
|
uint8_t data[256]; /* Handshake packets are typically < 148 bytes */
|
||||||
|
|
||||||
|
if (packet_len + WG_MAC1_SIZE > sizeof(data)) {
|
||||||
|
return -1; /* Should never happen for valid handshake packets */
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(data, packet, packet_len);
|
||||||
|
memcpy(data + packet_len, mac1, WG_MAC1_SIZE);
|
||||||
|
|
||||||
|
/* WireGuard uses keyed BLAKE2s for MAC2 */
|
||||||
|
int ret = se050_blake2s_keyed(mac2, 16, session->cookie_secret, 32,
|
||||||
|
data, packet_len + WG_MAC1_SIZE);
|
||||||
|
|
||||||
|
memzero_explicit(data, sizeof(data));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* =========================================================================
|
||||||
|
* Key Generation Utility
|
||||||
|
* ========================================================================= */
|
||||||
|
|
||||||
|
/* Simple test RNG for development (NOT SECURE!) */
|
||||||
|
#ifdef X25519_SW_TEST
|
||||||
|
static int simple_rng(uint8_t *out, size_t len, void *ctx)
|
||||||
|
{
|
||||||
|
static uint32_t seed = 12345;
|
||||||
|
for (size_t i = 0; i < len; i++) {
|
||||||
|
seed = seed * 1103515245 + 12345;
|
||||||
|
out[i] = (seed >> 16) & 0xff;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* System RNG fallback (uses /dev/urandom on POSIX) */
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
static int system_rng(uint8_t *out, size_t len, void *ctx)
|
||||||
|
{
|
||||||
|
int fd = open("/dev/urandom", O_RDONLY);
|
||||||
|
if (fd < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t total = 0;
|
||||||
|
while (total < len) {
|
||||||
|
ssize_t n = read(fd, out + total, len - total);
|
||||||
|
if (n < 0) {
|
||||||
|
close(fd);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
total += n;
|
||||||
|
}
|
||||||
|
|
||||||
|
close(fd);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int se050_wireguard_generate_keypair(uint8_t *private_key, uint8_t *public_key)
|
||||||
|
{
|
||||||
|
if (!private_key || !public_key) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
se050_x25519_sw_keypair_t keypair;
|
||||||
|
|
||||||
|
#ifdef X25519_SW_TEST
|
||||||
|
/* Use simple RNG for testing */
|
||||||
|
if (se050_x25519_sw_generate_keypair(&keypair, simple_rng, NULL) < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
/* Production: use system RNG (can be replaced with SE050 RNG) */
|
||||||
|
if (se050_x25519_sw_generate_keypair(&keypair, system_rng, NULL) < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
memcpy(private_key, keypair.private_key, WG_KEY_LEN);
|
||||||
|
memcpy(public_key, keypair.public_key, WG_KEY_LEN);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -0,0 +1,67 @@
|
|||||||
|
/**
|
||||||
|
* @file se050_wireguard_se050_rng.c
|
||||||
|
* @brief WireGuard with SE050 Hardware RNG Integration
|
||||||
|
*
|
||||||
|
* This file provides an alternative key generation function that uses
|
||||||
|
* the SE050 hardware TRNG instead of the system RNG.
|
||||||
|
*
|
||||||
|
* Usage: Link with se050_rng.c and se050_session.c
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "se050_wireguard.h"
|
||||||
|
#include "se050_x25519_sw.h"
|
||||||
|
#include "se050_rng.h"
|
||||||
|
#include "se050_session.h"
|
||||||
|
|
||||||
|
/* SE050 RNG wrapper for x25519 keypair generation */
|
||||||
|
static int se050_rng_wrapper(uint8_t *out, size_t len, void *ctx)
|
||||||
|
{
|
||||||
|
se050_rng_ctx_t *rng = (se050_rng_ctx_t *)ctx;
|
||||||
|
|
||||||
|
if (!rng || !out) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
se050_status_t ret = se050_rng_generate(rng, out, len);
|
||||||
|
return (ret == SE050_OK) ? 0 : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Generate WireGuard keypair using SE050 hardware RNG
|
||||||
|
*
|
||||||
|
* @param session SE050 session context (must be initialized)
|
||||||
|
* @param private_key Output: private key (32 bytes)
|
||||||
|
* @param public_key Output: public key (32 bytes)
|
||||||
|
* @return 0 on success, -1 on error
|
||||||
|
*/
|
||||||
|
int se050_wireguard_generate_keypair_se050(se050_session_ctx_t *session,
|
||||||
|
uint8_t *private_key,
|
||||||
|
uint8_t *public_key)
|
||||||
|
{
|
||||||
|
if (!session || !private_key || !public_key) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Initialize SE050 RNG */
|
||||||
|
se050_rng_ctx_t *rng;
|
||||||
|
se050_status_t ret = se050_rng_init(&rng, session);
|
||||||
|
if (ret != SE050_OK) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Generate keypair using SE050 RNG */
|
||||||
|
se050_x25519_sw_keypair_t keypair;
|
||||||
|
ret = se050_x25519_sw_generate_keypair(&keypair, se050_rng_wrapper, rng);
|
||||||
|
|
||||||
|
/* Cleanup RNG context */
|
||||||
|
se050_rng_free(rng);
|
||||||
|
|
||||||
|
if (ret < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(private_key, keypair.private_key, 32);
|
||||||
|
memcpy(public_key, keypair.public_key, 32);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -7,10 +7,15 @@
|
|||||||
* License: MIT (Clean-room implementation)
|
* License: MIT (Clean-room implementation)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "se050_i2c_hal.h"
|
||||||
#include "se050_wireguard.h"
|
#include "se050_wireguard.h"
|
||||||
#include "se050_crypto_utils.h"
|
#include "se050_crypto_utils.h"
|
||||||
#include "se050_keystore_internal.h"
|
#include "se050_keystore_internal.h"
|
||||||
#include "se050_session_internal.h"
|
#include "se050_session_internal.h"
|
||||||
|
#include "se050_x25519_sw.h"
|
||||||
|
|
||||||
|
/* Type alias for compatibility */
|
||||||
|
typedef se050_x25519_sw_keypair_t se050_x25519_keypair_t;
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|||||||
+571
-390
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,156 @@
|
|||||||
|
/**
|
||||||
|
* @file test_csprng.c
|
||||||
|
* @brief CSPRNG Tests
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "se050_wireguard.h"
|
||||||
|
#include "se050_chacha20_poly1305.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
static int passed = 0;
|
||||||
|
static int failed = 0;
|
||||||
|
|
||||||
|
#define TEST_ASSERT(cond, msg) do { \
|
||||||
|
if (cond) { \
|
||||||
|
printf("[PASS] %s\n", msg); \
|
||||||
|
passed++; \
|
||||||
|
} else { \
|
||||||
|
printf("[FAIL] %s\n", msg); \
|
||||||
|
failed++; \
|
||||||
|
} \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
/* Mock SE050 RNG for testing */
|
||||||
|
static int mock_se050_rng(uint8_t *out, size_t len, void *ctx)
|
||||||
|
{
|
||||||
|
(void)ctx;
|
||||||
|
/* Generate deterministic "seed" for testing */
|
||||||
|
for (size_t i = 0; i < len; i++) {
|
||||||
|
out[i] = (uint8_t)(i + 0x42);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Test: CSPRNG initialization */
|
||||||
|
static void test_csprng_init(void)
|
||||||
|
{
|
||||||
|
printf("\n--- Test CSPRNG Initialization ---\n");
|
||||||
|
|
||||||
|
int ret = se050_csprng_init(mock_se050_rng, NULL);
|
||||||
|
TEST_ASSERT(ret == 0, "CSPRNG init returns 0");
|
||||||
|
|
||||||
|
se050_csprng_cleanup();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Test: CSPRNG generates non-zero data */
|
||||||
|
static void test_csprng_output(void)
|
||||||
|
{
|
||||||
|
printf("\n--- Test CSPRNG Output ---\n");
|
||||||
|
|
||||||
|
se050_csprng_init(mock_se050_rng, NULL);
|
||||||
|
|
||||||
|
uint8_t rand1[32];
|
||||||
|
int ret = se050_csprng_random(rand1, 32);
|
||||||
|
TEST_ASSERT(ret == 0, "Random generation returns 0");
|
||||||
|
|
||||||
|
uint8_t all_zero = 1;
|
||||||
|
for (int i = 0; i < 32; i++) {
|
||||||
|
if (rand1[i] != 0) all_zero = 0;
|
||||||
|
}
|
||||||
|
TEST_ASSERT(all_zero == 0, "Random data is non-zero");
|
||||||
|
|
||||||
|
se050_csprng_cleanup();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Test: CSPRNG generates different values */
|
||||||
|
static void test_csprng_uniqueness(void)
|
||||||
|
{
|
||||||
|
printf("\n--- Test CSPRNG Uniqueness ---\n");
|
||||||
|
|
||||||
|
se050_csprng_init(mock_se050_rng, NULL);
|
||||||
|
|
||||||
|
uint8_t rand1[32], rand2[32];
|
||||||
|
se050_csprng_random(rand1, 32);
|
||||||
|
se050_csprng_random(rand2, 32);
|
||||||
|
|
||||||
|
TEST_ASSERT(memcmp(rand1, rand2, 32) != 0, "Successive calls produce different values");
|
||||||
|
|
||||||
|
se050_csprng_cleanup();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Test: CSPRNG keypair generation */
|
||||||
|
static void test_csprng_keypair(void)
|
||||||
|
{
|
||||||
|
printf("\n--- Test CSPRNG Keypair ---\n");
|
||||||
|
|
||||||
|
se050_csprng_init(mock_se050_rng, NULL);
|
||||||
|
|
||||||
|
uint8_t priv[32], pub[32];
|
||||||
|
int ret = se050_wireguard_generate_keypair_csprng(priv, pub);
|
||||||
|
TEST_ASSERT(ret == 0, "Keypair generation returns 0");
|
||||||
|
|
||||||
|
uint8_t priv_zero = 1, pub_zero = 1;
|
||||||
|
for (int i = 0; i < 32; i++) {
|
||||||
|
if (priv[i] != 0) priv_zero = 0;
|
||||||
|
if (pub[i] != 0) pub_zero = 0;
|
||||||
|
}
|
||||||
|
TEST_ASSERT(priv_zero == 0, "Private key is non-zero");
|
||||||
|
TEST_ASSERT(pub_zero == 0, "Public key is non-zero");
|
||||||
|
|
||||||
|
se050_csprng_cleanup();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Test: CSPRNG cleanup zeros memory */
|
||||||
|
static void test_csprng_cleanup(void)
|
||||||
|
{
|
||||||
|
printf("\n--- Test CSPRNG Cleanup ---\n");
|
||||||
|
|
||||||
|
se050_csprng_init(mock_se050_rng, NULL);
|
||||||
|
se050_csprng_cleanup();
|
||||||
|
|
||||||
|
/* Try to generate after cleanup - should fail */
|
||||||
|
uint8_t rand[32];
|
||||||
|
int ret = se050_csprng_random(rand, 32);
|
||||||
|
TEST_ASSERT(ret != 0, "Generation fails after cleanup");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Test: Multiple keypairs from same seed */
|
||||||
|
static void test_multiple_keypairs(void)
|
||||||
|
{
|
||||||
|
printf("\n--- Test Multiple Keypairs ---\n");
|
||||||
|
|
||||||
|
se050_csprng_init(mock_se050_rng, NULL);
|
||||||
|
|
||||||
|
uint8_t priv1[32], pub1[32];
|
||||||
|
uint8_t priv2[32], pub2[32];
|
||||||
|
|
||||||
|
se050_wireguard_generate_keypair_csprng(priv1, pub1);
|
||||||
|
se050_wireguard_generate_keypair_csprng(priv2, pub2);
|
||||||
|
|
||||||
|
TEST_ASSERT(memcmp(priv1, priv2, 32) != 0, "Multiple private keys are different");
|
||||||
|
TEST_ASSERT(memcmp(pub1, pub2, 32) != 0, "Multiple public keys are different");
|
||||||
|
|
||||||
|
se050_csprng_cleanup();
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
printf("========================================\n");
|
||||||
|
printf(" CSPRNG Test Suite\n");
|
||||||
|
printf("========================================\n");
|
||||||
|
|
||||||
|
test_csprng_init();
|
||||||
|
test_csprng_output();
|
||||||
|
test_csprng_uniqueness();
|
||||||
|
test_csprng_keypair();
|
||||||
|
test_csprng_cleanup();
|
||||||
|
test_multiple_keypairs();
|
||||||
|
|
||||||
|
printf("\n========================================\n");
|
||||||
|
printf(" Results: %d passed, %d failed\n", passed, failed);
|
||||||
|
printf("========================================\n");
|
||||||
|
|
||||||
|
return failed == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
|
||||||
|
}
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
#define X25519_SW_TEST 1
|
||||||
|
#include "se050_wireguard.h"
|
||||||
|
#include "se050_x25519_sw.h"
|
||||||
|
#include "se050_chacha20_poly1305.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
printf("=== Debug WireGuard Encrypt/Decrypt ===\n\n");
|
||||||
|
|
||||||
|
uint8_t priv[32], peer_pub[32];
|
||||||
|
for(int i=0; i<32; i++) { priv[i] = i+1; peer_pub[i] = i+2; }
|
||||||
|
|
||||||
|
se050_wireguard_session_t session;
|
||||||
|
se050_wireguard_session_init(&session, priv, peer_pub);
|
||||||
|
|
||||||
|
uint8_t ss[32] = {0};
|
||||||
|
for(int i=0; i<32; i++) ss[i] = i;
|
||||||
|
se050_wireguard_derive_keys(&session, ss);
|
||||||
|
|
||||||
|
printf("Sending key (first 8): ");
|
||||||
|
for(int i=0; i<8; i++) printf("%02x", session.sending_key[i]);
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
printf("Receiving key (first 8): ");
|
||||||
|
for(int i=0; i<8; i++) printf("%02x", session.receiving_key[i]);
|
||||||
|
printf("\n\n");
|
||||||
|
|
||||||
|
const char *plaintext = "test";
|
||||||
|
uint8_t encrypted[100];
|
||||||
|
size_t enc_len;
|
||||||
|
|
||||||
|
printf("=== Encrypt ===\n");
|
||||||
|
int ret = se050_wireguard_encrypt_packet(&session, encrypted, &enc_len, (uint8_t*)plaintext, 4);
|
||||||
|
printf("Encrypt result: %d\n", ret);
|
||||||
|
printf("Encrypted length: %zu\n", enc_len);
|
||||||
|
printf("Encrypted (hex): ");
|
||||||
|
for(size_t i=0; i<enc_len; i++) printf("%02x", encrypted[i]);
|
||||||
|
printf("\n\n");
|
||||||
|
|
||||||
|
printf("=== Decrypt ===\n");
|
||||||
|
uint8_t decrypted[100];
|
||||||
|
size_t dec_len;
|
||||||
|
ret = se050_wireguard_decrypt_packet(&session, decrypted, &dec_len, encrypted, enc_len);
|
||||||
|
printf("Decrypt result: %d\n", ret);
|
||||||
|
printf("Decrypted length: %zu\n", dec_len);
|
||||||
|
if (ret == 0) {
|
||||||
|
printf("Decrypted content: %.*s\n", (int)dec_len, decrypted);
|
||||||
|
} else {
|
||||||
|
printf("Decrypt FAILED!\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
#include "se050_chacha20_poly1305.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
printf("=== RFC 7539 Poly1305 Test ===\n\n");
|
||||||
|
|
||||||
|
// RFC 7539 Section 2.5.2 Test Vector
|
||||||
|
uint8_t key[32] = {
|
||||||
|
0x85,0xd6,0xbe,0x78,0x57,0x55,0x6d,0x33,
|
||||||
|
0x7f,0x44,0xaf,0x2d,0xec,0x49,0xb7,0x03,
|
||||||
|
0xdb,0x27,0x21,0xbc,0x89,0xaa,0x73,0x0f,
|
||||||
|
0xb5,0x45,0xf4,0x53,0x88,0xb4,0x80,0x1d
|
||||||
|
};
|
||||||
|
|
||||||
|
uint8_t data[] = "Plaintext";
|
||||||
|
uint8_t expected_mac[16] = {
|
||||||
|
0xa8,0x06,0x1d,0xc1,0x30,0x51,0x36,0xc6,
|
||||||
|
0xc2,0x2b,0x8b,0xaf,0x0c,0x01,0x27,0xa9
|
||||||
|
};
|
||||||
|
|
||||||
|
uint8_t mac[16];
|
||||||
|
|
||||||
|
// Test poly1305 directly
|
||||||
|
se050_chacha20_poly1305_ctx_t ctx;
|
||||||
|
se050_chacha20_poly1305_init(&ctx, key);
|
||||||
|
|
||||||
|
// Poly1305 doesn't have a direct MAC function, use AEAD with empty ciphertext
|
||||||
|
uint8_t tag[16];
|
||||||
|
uint8_t ciphertext[1];
|
||||||
|
|
||||||
|
se050_chacha20_poly1305_encrypt(&ctx, NULL, data, 9, data, 9, ciphertext, tag);
|
||||||
|
|
||||||
|
printf("Computed MAC: ");
|
||||||
|
for(int i=0; i<16; i++) printf("%02x", tag[i]);
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
printf("Expected MAC: ");
|
||||||
|
for(int i=0; i<16; i++) printf("%02x", expected_mac[i]);
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
if (memcmp(tag, expected_mac, 16) == 0) {
|
||||||
|
printf("[PASS] RFC 7539 Poly1305 test\n");
|
||||||
|
} else {
|
||||||
|
printf("[FAIL] RFC 7539 Poly1305 test\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -0,0 +1,290 @@
|
|||||||
|
/**
|
||||||
|
* @file test_wireguard.c
|
||||||
|
* @brief WireGuard Protocol Tests
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "se050_wireguard.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
static int passed = 0;
|
||||||
|
static int failed = 0;
|
||||||
|
|
||||||
|
#define TEST_ASSERT(cond, msg) do { \
|
||||||
|
if (cond) { \
|
||||||
|
printf("[PASS] %s\n", msg); \
|
||||||
|
passed++; \
|
||||||
|
} else { \
|
||||||
|
printf("[FAIL] %s\n", msg); \
|
||||||
|
failed++; \
|
||||||
|
} \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
/* Test vectors from RFC 7748 */
|
||||||
|
static const uint8_t TEST_PRIVATE_KEY[32] = {
|
||||||
|
0x77,0x07,0x6d,0x0a,0x73,0x18,0xa5,0x7d,
|
||||||
|
0x3c,0x16,0xc1,0x72,0x51,0xb2,0x66,0x45,
|
||||||
|
0xdf,0xbc,0x9f,0x03,0xc8,0xf2,0xbc,0x2b,
|
||||||
|
0x4f,0x81,0xb0,0x9c,0x0c,0xcb,0x3e,0x9a
|
||||||
|
};
|
||||||
|
|
||||||
|
static const uint8_t TEST_PEER_PUBLIC_KEY[32] = {
|
||||||
|
0x5d,0xab,0x08,0x7e,0x62,0x4a,0x8a,0x4b,
|
||||||
|
0x79,0xe1,0x7f,0x8b,0x83,0x80,0x0e,0xe6,
|
||||||
|
0x6f,0x31,0x97,0xb6,0x93,0x44,0x41,0x76,
|
||||||
|
0x61,0x6c,0x39,0x5c,0xbe,0x7a,0x4b,0x82
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Test: Session initialization */
|
||||||
|
static void test_session_init(void)
|
||||||
|
{
|
||||||
|
printf("\n--- Test Session Initialization ---\n");
|
||||||
|
|
||||||
|
se050_wireguard_session_t session;
|
||||||
|
int ret = se050_wireguard_session_init(&session, TEST_PRIVATE_KEY, TEST_PEER_PUBLIC_KEY);
|
||||||
|
|
||||||
|
TEST_ASSERT(ret == 0, "Session init returns 0");
|
||||||
|
|
||||||
|
/* Verify public key was derived */
|
||||||
|
uint8_t expected_public[32];
|
||||||
|
se050_x25519_sw_derive_public_key(expected_public, TEST_PRIVATE_KEY);
|
||||||
|
TEST_ASSERT(memcmp(session.public_key, expected_public, 32) == 0,
|
||||||
|
"Public key derived correctly");
|
||||||
|
|
||||||
|
se050_wireguard_session_cleanup(&session);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Test: Key derivation */
|
||||||
|
static void test_key_derivation(void)
|
||||||
|
{
|
||||||
|
printf("\n--- Test Key Derivation ---\n");
|
||||||
|
|
||||||
|
se050_wireguard_session_t session;
|
||||||
|
se050_wireguard_session_init(&session, TEST_PRIVATE_KEY, TEST_PEER_PUBLIC_KEY);
|
||||||
|
|
||||||
|
/* Use a fixed shared secret for testing */
|
||||||
|
uint8_t shared_secret[32] = {0};
|
||||||
|
for (int i = 0; i < 32; i++) shared_secret[i] = i;
|
||||||
|
|
||||||
|
int ret = se050_wireguard_derive_keys(&session, shared_secret);
|
||||||
|
TEST_ASSERT(ret == 0, "Key derivation returns 0");
|
||||||
|
TEST_ASSERT(session.handshake_complete == true, "Handshake marked complete");
|
||||||
|
|
||||||
|
/* Verify keys are non-zero */
|
||||||
|
uint8_t all_zero = 1;
|
||||||
|
for (int i = 0; i < 32; i++) {
|
||||||
|
if (session.sending_key[i] != 0 || session.receiving_key[i] != 0) {
|
||||||
|
all_zero = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
TEST_ASSERT(all_zero == 0, "Session keys are non-zero");
|
||||||
|
|
||||||
|
se050_wireguard_session_cleanup(&session);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Test: Packet encryption/decryption */
|
||||||
|
static void test_encrypt_decrypt(void)
|
||||||
|
{
|
||||||
|
printf("\n--- Test Encryption/Decryption ---\n");
|
||||||
|
|
||||||
|
se050_wireguard_session_t session;
|
||||||
|
se050_wireguard_session_init(&session, TEST_PRIVATE_KEY, TEST_PEER_PUBLIC_KEY);
|
||||||
|
|
||||||
|
/* Setup keys */
|
||||||
|
uint8_t shared_secret[32] = {0};
|
||||||
|
for (int i = 0; i < 32; i++) shared_secret[i] = i;
|
||||||
|
|
||||||
|
/* Set as initiator for key derivation */
|
||||||
|
session.is_initiator = 1;
|
||||||
|
se050_wireguard_derive_keys(&session, shared_secret);
|
||||||
|
|
||||||
|
/* For single-session test, use same key for encrypt and decrypt */
|
||||||
|
memcpy(session.receiving_key, session.sending_key, 32);
|
||||||
|
|
||||||
|
/* Test data */
|
||||||
|
const char *plaintext = "Hello, WireGuard!";
|
||||||
|
size_t plaintext_len = strlen(plaintext);
|
||||||
|
|
||||||
|
uint8_t encrypted[1024];
|
||||||
|
size_t encrypted_len;
|
||||||
|
|
||||||
|
int ret = se050_wireguard_encrypt_packet(&session, encrypted, &encrypted_len,
|
||||||
|
(uint8_t*)plaintext, plaintext_len);
|
||||||
|
TEST_ASSERT(ret == 0, "Encryption returns 0");
|
||||||
|
TEST_ASSERT(encrypted_len == 16 + plaintext_len + 16,
|
||||||
|
"Encrypted length is correct (header + ciphertext + tag)");
|
||||||
|
|
||||||
|
/* Decrypt */
|
||||||
|
uint8_t decrypted[1024];
|
||||||
|
size_t decrypted_len;
|
||||||
|
|
||||||
|
ret = se050_wireguard_decrypt_packet(&session, decrypted, &decrypted_len,
|
||||||
|
encrypted, encrypted_len);
|
||||||
|
TEST_ASSERT(ret == 0, "Decryption returns 0");
|
||||||
|
TEST_ASSERT(decrypted_len == plaintext_len, "Decrypted length matches");
|
||||||
|
TEST_ASSERT(memcmp(decrypted, plaintext, plaintext_len) == 0,
|
||||||
|
"Decrypted content matches original");
|
||||||
|
|
||||||
|
se050_wireguard_session_cleanup(&session);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Test: Replay detection */
|
||||||
|
static void test_replay_detection(void)
|
||||||
|
{
|
||||||
|
printf("\n--- Test Replay Detection ---\n");
|
||||||
|
|
||||||
|
se050_wireguard_session_t session;
|
||||||
|
se050_wireguard_session_init(&session, TEST_PRIVATE_KEY, TEST_PEER_PUBLIC_KEY);
|
||||||
|
|
||||||
|
/* Setup keys */
|
||||||
|
uint8_t shared_secret[32] = {0};
|
||||||
|
for (int i = 0; i < 32; i++) shared_secret[i] = i;
|
||||||
|
|
||||||
|
session.is_initiator = 1;
|
||||||
|
se050_wireguard_derive_keys(&session, shared_secret);
|
||||||
|
|
||||||
|
/* For single-session test, use same key for encrypt and decrypt */
|
||||||
|
memcpy(session.receiving_key, session.sending_key, 32);
|
||||||
|
|
||||||
|
/* Encrypt a packet */
|
||||||
|
const char *plaintext = "Test message";
|
||||||
|
uint8_t encrypted[1024];
|
||||||
|
size_t encrypted_len;
|
||||||
|
se050_wireguard_encrypt_packet(&session, encrypted, &encrypted_len,
|
||||||
|
(uint8_t*)plaintext, strlen(plaintext));
|
||||||
|
|
||||||
|
/* Decrypt once - should succeed */
|
||||||
|
uint8_t decrypted[1024];
|
||||||
|
size_t decrypted_len;
|
||||||
|
int ret = se050_wireguard_decrypt_packet(&session, decrypted, &decrypted_len,
|
||||||
|
encrypted, encrypted_len);
|
||||||
|
TEST_ASSERT(ret == 0, "First decryption succeeds");
|
||||||
|
|
||||||
|
/* Decrypt again with same packet - should fail (replay) */
|
||||||
|
ret = se050_wireguard_decrypt_packet(&session, decrypted, &decrypted_len,
|
||||||
|
encrypted, encrypted_len);
|
||||||
|
TEST_ASSERT(ret != 0, "Replay packet rejected");
|
||||||
|
|
||||||
|
se050_wireguard_session_cleanup(&session);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Test: MAC computation */
|
||||||
|
static void test_mac_computation(void)
|
||||||
|
{
|
||||||
|
printf("\n--- Test MAC Computation ---\n");
|
||||||
|
|
||||||
|
se050_wireguard_session_t session;
|
||||||
|
se050_wireguard_session_init(&session, TEST_PRIVATE_KEY, TEST_PEER_PUBLIC_KEY);
|
||||||
|
|
||||||
|
uint8_t test_data[64] = {0};
|
||||||
|
uint8_t mac1[16], mac2[16];
|
||||||
|
|
||||||
|
int ret = se050_wireguard_compute_mac1(&session, test_data, sizeof(test_data), mac1);
|
||||||
|
TEST_ASSERT(ret == 0, "MAC1 computation returns 0");
|
||||||
|
|
||||||
|
ret = se050_wireguard_compute_mac2(&session, mac1, test_data, sizeof(test_data), mac2);
|
||||||
|
TEST_ASSERT(ret == 0, "MAC2 computation returns 0");
|
||||||
|
|
||||||
|
/* Verify MACs are non-zero */
|
||||||
|
uint8_t mac1_zero = 1, mac2_zero = 1;
|
||||||
|
for (int i = 0; i < 16; i++) {
|
||||||
|
if (mac1[i] != 0) mac1_zero = 0;
|
||||||
|
if (mac2[i] != 0) mac2_zero = 0;
|
||||||
|
}
|
||||||
|
TEST_ASSERT(mac1_zero == 0, "MAC1 is non-zero");
|
||||||
|
TEST_ASSERT(mac2_zero == 0, "MAC2 is non-zero");
|
||||||
|
|
||||||
|
se050_wireguard_session_cleanup(&session);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Test: Key generation */
|
||||||
|
static void test_key_generation(void)
|
||||||
|
{
|
||||||
|
printf("\n--- Test Key Generation ---\n");
|
||||||
|
|
||||||
|
uint8_t private_key[32], public_key[32];
|
||||||
|
|
||||||
|
int ret = se050_wireguard_generate_keypair(private_key, public_key);
|
||||||
|
TEST_ASSERT(ret == 0, "Key generation returns 0");
|
||||||
|
|
||||||
|
/* Verify keys are non-zero */
|
||||||
|
uint8_t private_zero = 1, public_zero = 1;
|
||||||
|
for (int i = 0; i < 32; i++) {
|
||||||
|
if (private_key[i] != 0) private_zero = 0;
|
||||||
|
if (public_key[i] != 0) public_zero = 0;
|
||||||
|
}
|
||||||
|
TEST_ASSERT(private_zero == 0, "Private key is non-zero");
|
||||||
|
TEST_ASSERT(public_zero == 0, "Public key is non-zero");
|
||||||
|
|
||||||
|
/* Verify public key matches private key */
|
||||||
|
uint8_t expected_public[32];
|
||||||
|
se050_x25519_sw_derive_public_key(expected_public, private_key);
|
||||||
|
TEST_ASSERT(memcmp(public_key, expected_public, 32) == 0,
|
||||||
|
"Public key derived from private key");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Test: Session cleanup zeros memory */
|
||||||
|
static void test_session_cleanup(void)
|
||||||
|
{
|
||||||
|
printf("\n--- Test Session Cleanup ---\n");
|
||||||
|
|
||||||
|
se050_wireguard_session_t session;
|
||||||
|
se050_wireguard_session_init(&session, TEST_PRIVATE_KEY, TEST_PEER_PUBLIC_KEY);
|
||||||
|
|
||||||
|
/* Save a copy before cleanup */
|
||||||
|
uint8_t private_copy[32];
|
||||||
|
memcpy(private_copy, session.private_key, 32);
|
||||||
|
|
||||||
|
se050_wireguard_session_cleanup(&session);
|
||||||
|
|
||||||
|
/* Verify memory was zeroed */
|
||||||
|
uint8_t all_zero = 1;
|
||||||
|
for (int i = 0; i < 32; i++) {
|
||||||
|
if (session.private_key[i] != 0) all_zero = 0;
|
||||||
|
}
|
||||||
|
TEST_ASSERT(all_zero == 1, "Session memory zeroed after cleanup");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Test: Invalid inputs */
|
||||||
|
static void test_invalid_inputs(void)
|
||||||
|
{
|
||||||
|
printf("\n--- Test Invalid Inputs ---\n");
|
||||||
|
|
||||||
|
se050_wireguard_session_t session;
|
||||||
|
|
||||||
|
/* NULL session */
|
||||||
|
int ret = se050_wireguard_session_init(NULL, TEST_PRIVATE_KEY, TEST_PEER_PUBLIC_KEY);
|
||||||
|
TEST_ASSERT(ret == -1, "NULL session rejected");
|
||||||
|
|
||||||
|
/* NULL private key */
|
||||||
|
ret = se050_wireguard_session_init(&session, NULL, TEST_PEER_PUBLIC_KEY);
|
||||||
|
TEST_ASSERT(ret == -1, "NULL private key rejected");
|
||||||
|
|
||||||
|
/* NULL peer public key */
|
||||||
|
ret = se050_wireguard_session_init(&session, TEST_PRIVATE_KEY, NULL);
|
||||||
|
TEST_ASSERT(ret == -1, "NULL peer public key rejected");
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
printf("========================================\n");
|
||||||
|
printf(" WireGuard Protocol Test Suite\n");
|
||||||
|
printf("========================================\n");
|
||||||
|
|
||||||
|
test_session_init();
|
||||||
|
test_key_derivation();
|
||||||
|
test_encrypt_decrypt();
|
||||||
|
test_replay_detection();
|
||||||
|
test_mac_computation();
|
||||||
|
test_key_generation();
|
||||||
|
test_session_cleanup();
|
||||||
|
test_invalid_inputs();
|
||||||
|
|
||||||
|
printf("\n========================================\n");
|
||||||
|
printf(" Results: %d passed, %d failed\n", passed, failed);
|
||||||
|
printf("========================================\n");
|
||||||
|
|
||||||
|
return failed == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
|
||||||
|
}
|
||||||
@@ -0,0 +1,264 @@
|
|||||||
|
/**
|
||||||
|
* @file test_wireguard_proto.c
|
||||||
|
* @brief WireGuard Protocol Integration Test
|
||||||
|
*
|
||||||
|
* Tests the complete WireGuard protocol stack:
|
||||||
|
* - X25519 key exchange
|
||||||
|
* - Key derivation
|
||||||
|
* - Packet encryption/decryption
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "se050_x25519_sw.h"
|
||||||
|
#include "se050_chacha20_poly1305.h"
|
||||||
|
#include "se050_blake2s.h"
|
||||||
|
#include "se050_hmac_blake2s.h"
|
||||||
|
#include "se050_crypto_utils.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
static int passed = 0;
|
||||||
|
static int failed = 0;
|
||||||
|
|
||||||
|
#define TEST_ASSERT(cond, msg) do { \
|
||||||
|
if (cond) { \
|
||||||
|
printf("[PASS] %s\n", msg); \
|
||||||
|
passed++; \
|
||||||
|
} else { \
|
||||||
|
printf("[FAIL] %s\n", msg); \
|
||||||
|
failed++; \
|
||||||
|
} \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
/* RFC 7748 Test Vector 1 */
|
||||||
|
static const uint8_t RFC7748_SCALAR[32] = {
|
||||||
|
0xa5,0x46,0xe3,0x6b,0xf0,0x52,0x7c,0x9d,
|
||||||
|
0x3b,0x16,0x15,0x4b,0x82,0x46,0x5e,0xdd,
|
||||||
|
0x62,0x14,0x4c,0x0a,0xc1,0xfc,0x5a,0x18,
|
||||||
|
0x50,0x6a,0x22,0x44,0xba,0x44,0x9a,0xc4
|
||||||
|
};
|
||||||
|
|
||||||
|
static const uint8_t RFC7748_POINT[32] = {
|
||||||
|
0xe6,0xdb,0x68,0x67,0x58,0x30,0x30,0xdb,
|
||||||
|
0x35,0x94,0xc1,0xa4,0x24,0xb1,0x5f,0x7c,
|
||||||
|
0x72,0x66,0x24,0xec,0x26,0xb3,0x35,0x3b,
|
||||||
|
0x10,0xa9,0x03,0xa6,0xd0,0xab,0x1c,0x4c
|
||||||
|
};
|
||||||
|
|
||||||
|
static const uint8_t RFC7748_EXPECTED_SS[32] = {
|
||||||
|
0xc3,0xda,0x55,0x37,0x9d,0xe9,0xc6,0x90,
|
||||||
|
0x8e,0x94,0xea,0x4d,0xf2,0x8d,0x08,0x4f,
|
||||||
|
0x32,0xec,0xcf,0x03,0x49,0x1c,0x71,0xf7,
|
||||||
|
0x54,0xb4,0x07,0x55,0x77,0xa2,0x85,0x52
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Test X25519 against RFC 7748 */
|
||||||
|
static void test_x25519_rfc7748(void)
|
||||||
|
{
|
||||||
|
printf("\n--- Test X25519 RFC 7748 ---\n");
|
||||||
|
|
||||||
|
uint8_t shared_secret[32];
|
||||||
|
int ret = x25519_sw(shared_secret, RFC7748_SCALAR, RFC7748_POINT);
|
||||||
|
|
||||||
|
TEST_ASSERT(ret == 0, "X25519 computation returns 0");
|
||||||
|
TEST_ASSERT(memcmp(shared_secret, RFC7748_EXPECTED_SS, 32) == 0,
|
||||||
|
"X25519 matches RFC 7748 test vector");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Test ChaCha20-Poly1305 AEAD */
|
||||||
|
static void test_chacha20_poly1305(void)
|
||||||
|
{
|
||||||
|
printf("\n--- Test ChaCha20-Poly1305 ---\n");
|
||||||
|
|
||||||
|
uint8_t key[32] = {0};
|
||||||
|
for (int i = 0; i < 32; i++) key[i] = i;
|
||||||
|
uint8_t nonce[12] = {0};
|
||||||
|
uint8_t aad[16] = {0};
|
||||||
|
uint8_t plaintext[32] = "Hello, WireGuard!";
|
||||||
|
uint8_t ciphertext[32 + 16];
|
||||||
|
uint8_t tag[16];
|
||||||
|
uint8_t decrypted[32];
|
||||||
|
|
||||||
|
/* Setup context */
|
||||||
|
se050_chacha20_poly1305_ctx_t ctx;
|
||||||
|
memcpy(ctx.key, key, 32);
|
||||||
|
|
||||||
|
/* Encrypt */
|
||||||
|
int ret = se050_chacha20_poly1305_encrypt(
|
||||||
|
&ctx, nonce, plaintext, 17, aad, 16, ciphertext, tag);
|
||||||
|
TEST_ASSERT(ret == 0, "Encryption returns 0");
|
||||||
|
|
||||||
|
/* Decrypt */
|
||||||
|
ret = se050_chacha20_poly1305_decrypt(
|
||||||
|
&ctx, nonce, ciphertext, 17, aad, 16, tag, decrypted);
|
||||||
|
TEST_ASSERT(ret == 0, "Decryption returns 0");
|
||||||
|
TEST_ASSERT(memcmp(decrypted, plaintext, 17) == 0,
|
||||||
|
"Decrypted content matches");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Test BLAKE2s */
|
||||||
|
static void test_blake2s(void)
|
||||||
|
{
|
||||||
|
printf("\n--- Test BLAKE2s ---\n");
|
||||||
|
|
||||||
|
uint8_t key[32] = {0};
|
||||||
|
uint8_t data[32] = "test data";
|
||||||
|
uint8_t mac[32];
|
||||||
|
|
||||||
|
int ret = se050_hmac_blake2s(mac, key, 32, data, 9);
|
||||||
|
TEST_ASSERT(ret == 0, "HMAC-BLAKE2s returns 0");
|
||||||
|
|
||||||
|
/* Verify MAC is non-zero */
|
||||||
|
uint8_t all_zero = 1;
|
||||||
|
for (int i = 0; i < 32; i++) {
|
||||||
|
if (mac[i] != 0) all_zero = 0;
|
||||||
|
}
|
||||||
|
TEST_ASSERT(all_zero == 0, "MAC is non-zero");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Test key derivation (simplified HKDF) */
|
||||||
|
static void test_key_derivation(void)
|
||||||
|
{
|
||||||
|
printf("\n--- Test Key Derivation ---\n");
|
||||||
|
|
||||||
|
/* Simulate WireGuard key derivation */
|
||||||
|
uint8_t shared_secret[32] = {0};
|
||||||
|
for (int i = 0; i < 32; i++) shared_secret[i] = i;
|
||||||
|
|
||||||
|
uint8_t info[] = "WireGuard v1 zx2c4 IPsec v1";
|
||||||
|
uint8_t output[64];
|
||||||
|
|
||||||
|
/* Simple expansion: HMAC(shared_secret, info) */
|
||||||
|
se050_hmac_blake2s(output, shared_secret, 32, info, sizeof(info) - 1);
|
||||||
|
|
||||||
|
uint8_t all_zero = 1;
|
||||||
|
for (int i = 0; i < 64; i++) {
|
||||||
|
if (output[i] != 0) all_zero = 0;
|
||||||
|
}
|
||||||
|
TEST_ASSERT(all_zero == 0, "Derived keys are non-zero");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Test full DH exchange simulation */
|
||||||
|
static void test_dh_exchange(void)
|
||||||
|
{
|
||||||
|
printf("\n--- Test DH Exchange Simulation ---\n");
|
||||||
|
|
||||||
|
/* Use RFC 7748 test vectors for Alice and Bob */
|
||||||
|
const uint8_t ALICE_PRIVATE[32] = {
|
||||||
|
0x77,0x07,0x6d,0x0a,0x73,0x18,0xa5,0x7d,
|
||||||
|
0x3c,0x16,0xc1,0x72,0x51,0xb2,0x66,0x45,
|
||||||
|
0xdf,0xbc,0x9f,0x03,0xc8,0xf2,0xbc,0x2b,
|
||||||
|
0x4f,0x81,0xb0,0x9c,0x0c,0xcb,0x3e,0x9a
|
||||||
|
};
|
||||||
|
|
||||||
|
const uint8_t BOB_PRIVATE[32] = {
|
||||||
|
0x5d,0xab,0x08,0x7e,0x62,0x4a,0x8a,0x4b,
|
||||||
|
0x79,0xe1,0x7f,0x8b,0x83,0x80,0x0e,0xe6,
|
||||||
|
0x6f,0x31,0x97,0xb6,0x93,0x44,0x41,0x76,
|
||||||
|
0x61,0x6c,0x39,0x5c,0xbe,0x7a,0x4b,0x82
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Derive public keys */
|
||||||
|
uint8_t alice_public[32], bob_public[32];
|
||||||
|
se050_x25519_sw_derive_public_key(alice_public, ALICE_PRIVATE);
|
||||||
|
se050_x25519_sw_derive_public_key(bob_public, BOB_PRIVATE);
|
||||||
|
|
||||||
|
/* Compute shared secrets */
|
||||||
|
uint8_t alice_shared[32], bob_shared[32];
|
||||||
|
|
||||||
|
int ret1 = x25519_sw(alice_shared, ALICE_PRIVATE, bob_public);
|
||||||
|
int ret2 = x25519_sw(bob_shared, BOB_PRIVATE, alice_public);
|
||||||
|
|
||||||
|
TEST_ASSERT(ret1 == 0, "Alice computes shared secret");
|
||||||
|
TEST_ASSERT(ret2 == 0, "Bob computes shared secret");
|
||||||
|
TEST_ASSERT(memcmp(alice_shared, bob_shared, 32) == 0,
|
||||||
|
"Shared secrets match");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Test packet encryption/decryption flow */
|
||||||
|
static void test_packet_flow(void)
|
||||||
|
{
|
||||||
|
printf("\n--- Test Packet Encryption Flow ---\n");
|
||||||
|
|
||||||
|
/* Setup: Generate keypair and derive shared secret */
|
||||||
|
se050_x25519_sw_keypair_t keypair;
|
||||||
|
se050_x25519_sw_generate_keypair(&keypair, NULL, NULL);
|
||||||
|
|
||||||
|
uint8_t peer_public[32];
|
||||||
|
se050_x25519_sw_derive_public_key(peer_public, keypair.private_key);
|
||||||
|
|
||||||
|
uint8_t shared_secret[32];
|
||||||
|
x25519_sw(shared_secret, keypair.private_key, peer_public);
|
||||||
|
|
||||||
|
/* Derive session key (simplified) */
|
||||||
|
uint8_t session_key[32];
|
||||||
|
uint8_t info[] = "WireGuard v1 zx2c4 IPsec v1";
|
||||||
|
se050_hmac_blake2s(session_key, shared_secret, 32, info, sizeof(info) - 1);
|
||||||
|
|
||||||
|
/* Encrypt packet */
|
||||||
|
const char *plaintext = "Test WireGuard packet";
|
||||||
|
uint8_t nonce[12] = {0};
|
||||||
|
uint8_t header[16] = {1}; /* Packet type */
|
||||||
|
|
||||||
|
uint8_t ciphertext[100];
|
||||||
|
uint8_t tag[16];
|
||||||
|
|
||||||
|
se050_chacha20_poly1305_ctx_t ctx;
|
||||||
|
memcpy(ctx.key, session_key, 32);
|
||||||
|
|
||||||
|
int ret = se050_chacha20_poly1305_encrypt(
|
||||||
|
&ctx, nonce, (uint8_t*)plaintext, strlen(plaintext),
|
||||||
|
header, 16, ciphertext, tag);
|
||||||
|
TEST_ASSERT(ret == 0, "Packet encryption succeeds");
|
||||||
|
|
||||||
|
/* Decrypt packet */
|
||||||
|
uint8_t decrypted[100];
|
||||||
|
ret = se050_chacha20_poly1305_decrypt(
|
||||||
|
&ctx, nonce, ciphertext, strlen(plaintext),
|
||||||
|
header, 16, tag, decrypted);
|
||||||
|
TEST_ASSERT(ret == 0, "Packet decryption succeeds");
|
||||||
|
TEST_ASSERT(memcmp(decrypted, plaintext, strlen(plaintext)) == 0,
|
||||||
|
"Decrypted packet matches");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Test memory zeroizing */
|
||||||
|
static void test_memory_zeroizing(void)
|
||||||
|
{
|
||||||
|
printf("\n--- Test Memory Zeroizing ---\n");
|
||||||
|
|
||||||
|
uint8_t sensitive[32] = {0};
|
||||||
|
for (int i = 0; i < 32; i++) sensitive[i] = i;
|
||||||
|
|
||||||
|
/* Zeroize */
|
||||||
|
memzero_explicit(sensitive, 32);
|
||||||
|
|
||||||
|
/* Verify */
|
||||||
|
uint8_t all_zero = 1;
|
||||||
|
for (int i = 0; i < 32; i++) {
|
||||||
|
if (sensitive[i] != 0) all_zero = 0;
|
||||||
|
}
|
||||||
|
TEST_ASSERT(all_zero == 1, "Memory zeroized correctly");
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
printf("========================================\n");
|
||||||
|
printf(" WireGuard Protocol Integration Test\n");
|
||||||
|
printf("========================================\n");
|
||||||
|
|
||||||
|
test_x25519_rfc7748();
|
||||||
|
test_chacha20_poly1305();
|
||||||
|
test_blake2s();
|
||||||
|
test_key_derivation();
|
||||||
|
test_dh_exchange();
|
||||||
|
test_packet_flow();
|
||||||
|
test_memory_zeroizing();
|
||||||
|
|
||||||
|
printf("\n========================================\n");
|
||||||
|
printf(" Results: %d passed, %d failed\n", passed, failed);
|
||||||
|
printf("========================================\n");
|
||||||
|
|
||||||
|
return failed == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
|
||||||
|
}
|
||||||
@@ -0,0 +1,339 @@
|
|||||||
|
/**
|
||||||
|
* @file test_wireguard_simple.c
|
||||||
|
* @brief WireGuard Protocol Tests (Simplified - minimal dependencies)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define X25519_SW_TEST 1
|
||||||
|
|
||||||
|
#include "se050_wireguard.h"
|
||||||
|
#include "se050_x25519_sw.h"
|
||||||
|
#include "se050_chacha20_poly1305.h"
|
||||||
|
#include "se050_blake2s.h"
|
||||||
|
#include "se050_hmac_blake2s.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
static int passed = 0;
|
||||||
|
static int failed = 0;
|
||||||
|
|
||||||
|
#define TEST_ASSERT(cond, msg) do { \
|
||||||
|
if (cond) { \
|
||||||
|
printf("[PASS] %s\n", msg); \
|
||||||
|
passed++; \
|
||||||
|
} else { \
|
||||||
|
printf("[FAIL] %s\n", msg); \
|
||||||
|
failed++; \
|
||||||
|
} \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
/* Test vectors */
|
||||||
|
static const uint8_t TEST_PRIVATE_KEY[32] = {
|
||||||
|
0x77,0x07,0x6d,0x0a,0x73,0x18,0xa5,0x7d,
|
||||||
|
0x3c,0x16,0xc1,0x72,0x51,0xb2,0x66,0x45,
|
||||||
|
0xdf,0xbc,0x9f,0x03,0xc8,0xf2,0xbc,0x2b,
|
||||||
|
0x4f,0x81,0xb0,0x9c,0x0c,0xcb,0x3e,0x9a
|
||||||
|
};
|
||||||
|
|
||||||
|
static const uint8_t TEST_PEER_PUBLIC_KEY[32] = {
|
||||||
|
0x5d,0xab,0x08,0x7e,0x62,0x4a,0x8a,0x4b,
|
||||||
|
0x79,0xe1,0x7f,0x8b,0x83,0x80,0x0e,0xe6,
|
||||||
|
0x6f,0x31,0x97,0xb6,0x93,0x44,0x41,0x76,
|
||||||
|
0x61,0x6c,0x39,0x5c,0xbe,0x7a,0x4b,0x82
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Test: X25519 public key derivation */
|
||||||
|
static void test_x25519_derive(void)
|
||||||
|
{
|
||||||
|
printf("\n--- Test X25519 Public Key Derivation ---\n");
|
||||||
|
|
||||||
|
uint8_t public_key[32];
|
||||||
|
int ret = se050_x25519_sw_derive_public_key(public_key, TEST_PRIVATE_KEY);
|
||||||
|
|
||||||
|
TEST_ASSERT(ret == 0, "Public key derivation returns 0");
|
||||||
|
|
||||||
|
/* Verify key is non-zero */
|
||||||
|
uint8_t all_zero = 1;
|
||||||
|
for (int i = 0; i < 32; i++) {
|
||||||
|
if (public_key[i] != 0) all_zero = 0;
|
||||||
|
}
|
||||||
|
TEST_ASSERT(all_zero == 0, "Public key is non-zero");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Test: ChaCha20-Poly1305 AEAD */
|
||||||
|
static void test_chacha20_poly1305(void)
|
||||||
|
{
|
||||||
|
printf("\n--- Test ChaCha20-Poly1305 AEAD ---\n");
|
||||||
|
|
||||||
|
const uint8_t key[32] = {0};
|
||||||
|
const uint8_t nonce[12] = {0};
|
||||||
|
const uint8_t plaintext[] = "test";
|
||||||
|
const uint8_t aad[] = "aad";
|
||||||
|
|
||||||
|
uint8_t ciphertext[100];
|
||||||
|
uint8_t tag[16];
|
||||||
|
|
||||||
|
se050_chacha20_poly1305_ctx_t ctx;
|
||||||
|
int ret = se050_chacha20_poly1305_init(&ctx, key);
|
||||||
|
TEST_ASSERT(ret == 0, "Context initialization returns 0");
|
||||||
|
|
||||||
|
ret = se050_chacha20_poly1305_encrypt(&ctx, nonce, plaintext, sizeof(plaintext)-1,
|
||||||
|
aad, sizeof(aad)-1, ciphertext, tag);
|
||||||
|
TEST_ASSERT(ret == 0, "Encryption returns 0");
|
||||||
|
|
||||||
|
uint8_t decrypted[100];
|
||||||
|
ret = se050_chacha20_poly1305_decrypt(&ctx, nonce, ciphertext, sizeof(plaintext)-1,
|
||||||
|
aad, sizeof(aad)-1, tag, decrypted);
|
||||||
|
TEST_ASSERT(ret == 0, "Decryption returns 0");
|
||||||
|
TEST_ASSERT(decrypted[0] == 't' && decrypted[1] == 'e' &&
|
||||||
|
decrypted[2] == 's' && decrypted[3] == 't',
|
||||||
|
"Decrypted content matches");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Test: HMAC-BLAKE2s */
|
||||||
|
static void test_hmac_blake2s(void)
|
||||||
|
{
|
||||||
|
printf("\n--- Test HMAC-BLAKE2s ---\n");
|
||||||
|
|
||||||
|
const uint8_t key[32] = {0};
|
||||||
|
const uint8_t data[] = "test message";
|
||||||
|
uint8_t mac[32];
|
||||||
|
|
||||||
|
int ret = se050_hmac_blake2s(mac, key, 32, data, sizeof(data)-1);
|
||||||
|
TEST_ASSERT(ret == 0, "HMAC computation returns 0");
|
||||||
|
|
||||||
|
/* Verify MAC is non-zero */
|
||||||
|
uint8_t all_zero = 1;
|
||||||
|
for (int i = 0; i < 32; i++) {
|
||||||
|
if (mac[i] != 0) all_zero = 0;
|
||||||
|
}
|
||||||
|
TEST_ASSERT(all_zero == 0, "MAC is non-zero");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Test: Session initialization */
|
||||||
|
static void test_session_init(void)
|
||||||
|
{
|
||||||
|
printf("\n--- Test Session Initialization ---\n");
|
||||||
|
|
||||||
|
se050_wireguard_session_t session;
|
||||||
|
int ret = se050_wireguard_session_init(&session, TEST_PRIVATE_KEY, TEST_PEER_PUBLIC_KEY);
|
||||||
|
|
||||||
|
TEST_ASSERT(ret == 0, "Session init returns 0");
|
||||||
|
|
||||||
|
/* Verify public key was derived */
|
||||||
|
uint8_t expected_public[32];
|
||||||
|
se050_x25519_sw_derive_public_key(expected_public, TEST_PRIVATE_KEY);
|
||||||
|
TEST_ASSERT(memcmp(session.public_key, expected_public, 32) == 0,
|
||||||
|
"Public key derived correctly");
|
||||||
|
|
||||||
|
se050_wireguard_session_cleanup(&session);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Test: Key derivation */
|
||||||
|
static void test_key_derivation(void)
|
||||||
|
{
|
||||||
|
printf("\n--- Test Key Derivation ---\n");
|
||||||
|
|
||||||
|
se050_wireguard_session_t session;
|
||||||
|
se050_wireguard_session_init(&session, TEST_PRIVATE_KEY, TEST_PEER_PUBLIC_KEY);
|
||||||
|
|
||||||
|
uint8_t shared_secret[32] = {0};
|
||||||
|
for (int i = 0; i < 32; i++) shared_secret[i] = i;
|
||||||
|
|
||||||
|
int ret = se050_wireguard_derive_keys(&session, shared_secret);
|
||||||
|
TEST_ASSERT(ret == 0, "Key derivation returns 0");
|
||||||
|
TEST_ASSERT(session.handshake_complete == 1, "Handshake marked complete");
|
||||||
|
|
||||||
|
uint8_t all_zero = 1;
|
||||||
|
for (int i = 0; i < 32; i++) {
|
||||||
|
if (session.sending_key[i] != 0 || session.receiving_key[i] != 0) {
|
||||||
|
all_zero = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
TEST_ASSERT(all_zero == 0, "Session keys are non-zero");
|
||||||
|
|
||||||
|
se050_wireguard_session_cleanup(&session);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Test: Packet encryption/decryption */
|
||||||
|
static void test_encrypt_decrypt(void)
|
||||||
|
{
|
||||||
|
printf("\n--- Test Encryption/Decryption ---\n");
|
||||||
|
|
||||||
|
se050_wireguard_session_t session;
|
||||||
|
se050_wireguard_session_init(&session, TEST_PRIVATE_KEY, TEST_PEER_PUBLIC_KEY);
|
||||||
|
|
||||||
|
uint8_t shared_secret[32] = {0};
|
||||||
|
for (int i = 0; i < 32; i++) shared_secret[i] = i;
|
||||||
|
se050_wireguard_derive_keys(&session, shared_secret);
|
||||||
|
|
||||||
|
const char *plaintext = "Hello, WireGuard!";
|
||||||
|
size_t plaintext_len = strlen(plaintext);
|
||||||
|
|
||||||
|
uint8_t encrypted[1024];
|
||||||
|
size_t encrypted_len;
|
||||||
|
|
||||||
|
int ret = se050_wireguard_encrypt_packet(&session, encrypted, &encrypted_len,
|
||||||
|
(uint8_t*)plaintext, plaintext_len);
|
||||||
|
TEST_ASSERT(ret == 0, "Encryption returns 0");
|
||||||
|
TEST_ASSERT(encrypted_len == 16 + plaintext_len + 16,
|
||||||
|
"Encrypted length is correct");
|
||||||
|
|
||||||
|
uint8_t decrypted[1024];
|
||||||
|
size_t decrypted_len;
|
||||||
|
|
||||||
|
ret = se050_wireguard_decrypt_packet(&session, decrypted, &decrypted_len,
|
||||||
|
encrypted, encrypted_len);
|
||||||
|
TEST_ASSERT(ret == 0, "Decryption returns 0");
|
||||||
|
TEST_ASSERT(decrypted_len == plaintext_len, "Decrypted length matches");
|
||||||
|
TEST_ASSERT(memcmp(decrypted, plaintext, plaintext_len) == 0,
|
||||||
|
"Decrypted content matches original");
|
||||||
|
|
||||||
|
se050_wireguard_session_cleanup(&session);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Test: Replay detection */
|
||||||
|
static void test_replay_detection(void)
|
||||||
|
{
|
||||||
|
printf("\n--- Test Replay Detection ---\n");
|
||||||
|
|
||||||
|
se050_wireguard_session_t session;
|
||||||
|
se050_wireguard_session_init(&session, TEST_PRIVATE_KEY, TEST_PEER_PUBLIC_KEY);
|
||||||
|
|
||||||
|
uint8_t shared_secret[32] = {0};
|
||||||
|
for (int i = 0; i < 32; i++) shared_secret[i] = i;
|
||||||
|
se050_wireguard_derive_keys(&session, shared_secret);
|
||||||
|
|
||||||
|
const char *plaintext = "Test message";
|
||||||
|
uint8_t encrypted[1024];
|
||||||
|
size_t encrypted_len;
|
||||||
|
se050_wireguard_encrypt_packet(&session, encrypted, &encrypted_len,
|
||||||
|
(uint8_t*)plaintext, strlen(plaintext));
|
||||||
|
|
||||||
|
uint8_t decrypted[1024];
|
||||||
|
size_t decrypted_len;
|
||||||
|
int ret = se050_wireguard_decrypt_packet(&session, decrypted, &decrypted_len,
|
||||||
|
encrypted, encrypted_len);
|
||||||
|
TEST_ASSERT(ret == 0, "First decryption succeeds");
|
||||||
|
|
||||||
|
ret = se050_wireguard_decrypt_packet(&session, decrypted, &decrypted_len,
|
||||||
|
encrypted, encrypted_len);
|
||||||
|
TEST_ASSERT(ret != 0, "Replay packet rejected");
|
||||||
|
|
||||||
|
se050_wireguard_session_cleanup(&session);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Test: MAC computation */
|
||||||
|
static void test_mac_computation(void)
|
||||||
|
{
|
||||||
|
printf("\n--- Test MAC Computation ---\n");
|
||||||
|
|
||||||
|
se050_wireguard_session_t session;
|
||||||
|
se050_wireguard_session_init(&session, TEST_PRIVATE_KEY, TEST_PEER_PUBLIC_KEY);
|
||||||
|
|
||||||
|
uint8_t test_data[64] = {0};
|
||||||
|
uint8_t mac1[16], mac2[16];
|
||||||
|
|
||||||
|
int ret = se050_wireguard_compute_mac1(&session, test_data, sizeof(test_data), mac1);
|
||||||
|
TEST_ASSERT(ret == 0, "MAC1 computation returns 0");
|
||||||
|
|
||||||
|
ret = se050_wireguard_compute_mac2(&session, mac1, test_data, sizeof(test_data), mac2);
|
||||||
|
TEST_ASSERT(ret == 0, "MAC2 computation returns 0");
|
||||||
|
|
||||||
|
uint8_t mac1_zero = 1, mac2_zero = 1;
|
||||||
|
for (int i = 0; i < 16; i++) {
|
||||||
|
if (mac1[i] != 0) mac1_zero = 0;
|
||||||
|
if (mac2[i] != 0) mac2_zero = 0;
|
||||||
|
}
|
||||||
|
TEST_ASSERT(mac1_zero == 0, "MAC1 is non-zero");
|
||||||
|
TEST_ASSERT(mac2_zero == 0, "MAC2 is non-zero");
|
||||||
|
|
||||||
|
se050_wireguard_session_cleanup(&session);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Test: Key generation */
|
||||||
|
static void test_key_generation(void)
|
||||||
|
{
|
||||||
|
printf("\n--- Test Key Generation ---\n");
|
||||||
|
|
||||||
|
uint8_t private_key[32], public_key[32];
|
||||||
|
|
||||||
|
int ret = se050_wireguard_generate_keypair(private_key, public_key);
|
||||||
|
TEST_ASSERT(ret == 0, "Key generation returns 0");
|
||||||
|
|
||||||
|
uint8_t private_zero = 1, public_zero = 1;
|
||||||
|
for (int i = 0; i < 32; i++) {
|
||||||
|
if (private_key[i] != 0) private_zero = 0;
|
||||||
|
if (public_key[i] != 0) public_zero = 0;
|
||||||
|
}
|
||||||
|
TEST_ASSERT(private_zero == 0, "Private key is non-zero");
|
||||||
|
TEST_ASSERT(public_zero == 0, "Public key is non-zero");
|
||||||
|
|
||||||
|
uint8_t expected_public[32];
|
||||||
|
se050_x25519_sw_derive_public_key(expected_public, private_key);
|
||||||
|
TEST_ASSERT(memcmp(public_key, expected_public, 32) == 0,
|
||||||
|
"Public key derived from private key");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Test: Session cleanup zeros memory */
|
||||||
|
static void test_session_cleanup(void)
|
||||||
|
{
|
||||||
|
printf("\n--- Test Session Cleanup ---\n");
|
||||||
|
|
||||||
|
se050_wireguard_session_t session;
|
||||||
|
se050_wireguard_session_init(&session, TEST_PRIVATE_KEY, TEST_PEER_PUBLIC_KEY);
|
||||||
|
|
||||||
|
uint8_t private_copy[32];
|
||||||
|
memcpy(private_copy, session.private_key, 32);
|
||||||
|
|
||||||
|
se050_wireguard_session_cleanup(&session);
|
||||||
|
|
||||||
|
uint8_t all_zero = 1;
|
||||||
|
for (int i = 0; i < 32; i++) {
|
||||||
|
if (session.private_key[i] != 0) all_zero = 0;
|
||||||
|
}
|
||||||
|
TEST_ASSERT(all_zero == 1, "Session memory zeroed after cleanup");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Test: Invalid inputs */
|
||||||
|
static void test_invalid_inputs(void)
|
||||||
|
{
|
||||||
|
printf("\n--- Test Invalid Inputs ---\n");
|
||||||
|
|
||||||
|
se050_wireguard_session_t session;
|
||||||
|
|
||||||
|
int ret = se050_wireguard_session_init(NULL, TEST_PRIVATE_KEY, TEST_PEER_PUBLIC_KEY);
|
||||||
|
TEST_ASSERT(ret == -1, "NULL session rejected");
|
||||||
|
|
||||||
|
ret = se050_wireguard_session_init(&session, NULL, TEST_PEER_PUBLIC_KEY);
|
||||||
|
TEST_ASSERT(ret == -1, "NULL private key rejected");
|
||||||
|
|
||||||
|
ret = se050_wireguard_session_init(&session, TEST_PRIVATE_KEY, NULL);
|
||||||
|
TEST_ASSERT(ret == -1, "NULL peer public key rejected");
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
printf("========================================\n");
|
||||||
|
printf(" WireGuard Protocol Test Suite\n");
|
||||||
|
printf("========================================\n");
|
||||||
|
|
||||||
|
test_x25519_derive();
|
||||||
|
test_chacha20_poly1305();
|
||||||
|
test_hmac_blake2s();
|
||||||
|
test_session_init();
|
||||||
|
test_key_derivation();
|
||||||
|
test_encrypt_decrypt();
|
||||||
|
test_replay_detection();
|
||||||
|
test_mac_computation();
|
||||||
|
test_key_generation();
|
||||||
|
test_session_cleanup();
|
||||||
|
test_invalid_inputs();
|
||||||
|
|
||||||
|
printf("\n========================================\n");
|
||||||
|
printf(" Results: %d passed, %d failed\n", passed, failed);
|
||||||
|
printf("========================================\n");
|
||||||
|
|
||||||
|
return failed == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
|
||||||
|
}
|
||||||
@@ -23,7 +23,7 @@ static int test_sw_ecdh_symmetry(void);
|
|||||||
static int test_sw_public_key_derivation(void);
|
static int test_sw_public_key_derivation(void);
|
||||||
static int test_sw_key_zeroization(void);
|
static int test_sw_key_zeroization(void);
|
||||||
|
|
||||||
/* X25519 test vectors from RFC 7748 Section 5 */
|
/* X25519 test vectors from RFC 7748 Section 5.2 */
|
||||||
/* Test Vector 1: Single round */
|
/* Test Vector 1: Single round */
|
||||||
static const uint8_t RFC7748_SK_1[32] = {
|
static const uint8_t RFC7748_SK_1[32] = {
|
||||||
0xa5, 0x46, 0xe3, 0x6b, 0xf0, 0x52, 0x7c, 0x9d,
|
0xa5, 0x46, 0xe3, 0x6b, 0xf0, 0x52, 0x7c, 0x9d,
|
||||||
@@ -32,7 +32,7 @@ static const uint8_t RFC7748_SK_1[32] = {
|
|||||||
0x50, 0x6a, 0x22, 0x44, 0xba, 0x44, 0x9a, 0xc4
|
0x50, 0x6a, 0x22, 0x44, 0xba, 0x44, 0x9a, 0xc4
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Input point (u-coordinate) from RFC 7748 */
|
/* Input u-coordinate from RFC 7748 Section 5.2 */
|
||||||
static const uint8_t RFC7748_U_1[32] = {
|
static const uint8_t RFC7748_U_1[32] = {
|
||||||
0xe6, 0xdb, 0x68, 0x67, 0x58, 0x30, 0x30, 0xdb,
|
0xe6, 0xdb, 0x68, 0x67, 0x58, 0x30, 0x30, 0xdb,
|
||||||
0x35, 0x94, 0xc1, 0xa4, 0x24, 0xb1, 0x5f, 0x7c,
|
0x35, 0x94, 0xc1, 0xa4, 0x24, 0xb1, 0x5f, 0x7c,
|
||||||
@@ -40,7 +40,7 @@ static const uint8_t RFC7748_U_1[32] = {
|
|||||||
0x10, 0xa9, 0x03, 0xa6, 0xd0, 0xab, 0x1c, 0x4c
|
0x10, 0xa9, 0x03, 0xa6, 0xd0, 0xab, 0x1c, 0x4c
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Output after 1 round: c3da55379de9c6908e94ea4df28d084f32eccf03491c71f754b4075577a28552 */
|
/* Output after 1 round from RFC 7748 Section 5.2 */
|
||||||
static const uint8_t RFC7748_OUT_1[32] = {
|
static const uint8_t RFC7748_OUT_1[32] = {
|
||||||
0xc3, 0xda, 0x55, 0x37, 0x9d, 0xe9, 0xc6, 0x90,
|
0xc3, 0xda, 0x55, 0x37, 0x9d, 0xe9, 0xc6, 0x90,
|
||||||
0x8e, 0x94, 0xea, 0x4d, 0xf2, 0x8d, 0x08, 0x4f,
|
0x8e, 0x94, 0xea, 0x4d, 0xf2, 0x8d, 0x08, 0x4f,
|
||||||
@@ -49,7 +49,6 @@ static const uint8_t RFC7748_OUT_1[32] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/* Test Vector 2: 1000 iterations (shared secret) */
|
/* Test Vector 2: 1000 iterations (shared secret) */
|
||||||
/* Private key: 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f */
|
|
||||||
static const uint8_t RFC7748_SK_2[32] = {
|
static const uint8_t RFC7748_SK_2[32] = {
|
||||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
|
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
|
||||||
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
|
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
|
||||||
@@ -57,7 +56,7 @@ static const uint8_t RFC7748_SK_2[32] = {
|
|||||||
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f
|
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Base point: 0900000000000000000000000000000000000000000000000000000000000000 */
|
/* Base point from RFC 7748 */
|
||||||
static const uint8_t RFC7748_BASEPOINT[32] = {
|
static const uint8_t RFC7748_BASEPOINT[32] = {
|
||||||
0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
@@ -65,7 +64,7 @@ static const uint8_t RFC7748_BASEPOINT[32] = {
|
|||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Public key after 1000 iterations: 2b055e0f6793c844715e996c0f0b24a3a7b18e0f8e6d3e67e716c0c0c2d4c5e3 */
|
/* Public key after 1000 iterations from RFC 7748 */
|
||||||
static const uint8_t RFC7748_PK_2[32] = {
|
static const uint8_t RFC7748_PK_2[32] = {
|
||||||
0x2b, 0x05, 0x5e, 0x0f, 0x67, 0x93, 0xc8, 0x44,
|
0x2b, 0x05, 0x5e, 0x0f, 0x67, 0x93, 0xc8, 0x44,
|
||||||
0x71, 0x5e, 0x99, 0x6c, 0x0f, 0x0b, 0x24, 0xa3,
|
0x71, 0x5e, 0x99, 0x6c, 0x0f, 0x0b, 0x24, 0xa3,
|
||||||
|
|||||||
Reference in New Issue
Block a user