Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 5434aa5197 | |||
| aff6c301e6 | |||
| eb468c1ba1 | |||
| 940929540a | |||
| 74789be2c3 | |||
| 163fad68a7 | |||
| daffe82feb | |||
| 0a97209e8c | |||
| 2ad959bde9 | |||
| f89ca4f471 |
@@ -1 +1,4 @@
|
|||||||
build/
|
build/
|
||||||
|
*.o
|
||||||
|
src/*.o
|
||||||
|
tests/*.o
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ set(SOURCES
|
|||||||
src/se050_rng.c
|
src/se050_rng.c
|
||||||
src/se050_x25519.c
|
src/se050_x25519.c
|
||||||
src/se050_scp03.c
|
src/se050_scp03.c
|
||||||
|
src/se050_scp03_keys.c
|
||||||
)
|
)
|
||||||
|
|
||||||
# Create library
|
# Create library
|
||||||
|
|||||||
@@ -0,0 +1,121 @@
|
|||||||
|
# SE050 WireGuard Makefile
|
||||||
|
# Fallback for environments without CMake
|
||||||
|
|
||||||
|
CC = gcc
|
||||||
|
AR = ar
|
||||||
|
CFLAGS = -Wall -Wextra -std=c11 -I include
|
||||||
|
LDFLAGS =
|
||||||
|
|
||||||
|
# Source files
|
||||||
|
SRCS = src/se050_i2c_hal.c \
|
||||||
|
src/se050_session.c \
|
||||||
|
src/se050_keystore.c \
|
||||||
|
src/se050_rng.c \
|
||||||
|
src/se050_x25519.c \
|
||||||
|
src/se050_scp03.c \
|
||||||
|
src/se050_scp03_keys.c
|
||||||
|
|
||||||
|
# Object files
|
||||||
|
OBJS = $(SRCS:.c=.o)
|
||||||
|
|
||||||
|
# Test sources
|
||||||
|
TEST_SRCS = tests/test_scp03.c tests/test_scp03_hardware.c
|
||||||
|
TEST_OBJS = $(TEST_SRCS:.c=.o)
|
||||||
|
|
||||||
|
# Target library
|
||||||
|
LIB = libse050_wireguard.a
|
||||||
|
|
||||||
|
# Test executables
|
||||||
|
TEST_SCP03 = test_scp03
|
||||||
|
TEST_HARDWARE = test_scp03_hardware
|
||||||
|
TEST_SE050 = test_scp03_se050
|
||||||
|
|
||||||
|
# Chip selection (default: SE050C0)
|
||||||
|
SE050_CHIP ?= SE050C0
|
||||||
|
|
||||||
|
# I2C bus options
|
||||||
|
I2C_OPTS ?=
|
||||||
|
|
||||||
|
# Chip ID mapping
|
||||||
|
ifeq ($(SE050_CHIP),SE050C0)
|
||||||
|
CHIP_ID = 0
|
||||||
|
else ifeq ($(SE050_CHIP),SE050C1)
|
||||||
|
CHIP_ID = 1
|
||||||
|
else ifeq ($(SE050_CHIP),SE050E2)
|
||||||
|
CHIP_ID = 2
|
||||||
|
else
|
||||||
|
$(error Invalid SE050_CHIP. Use SE050C0, SE050C1, or SE050E2)
|
||||||
|
endif
|
||||||
|
|
||||||
|
# Default target
|
||||||
|
all: $(LIB) $(TEST_SCP03) $(TEST_HARDWARE) $(TEST_SE050)
|
||||||
|
|
||||||
|
# Create build directory
|
||||||
|
build:
|
||||||
|
@mkdir -p build
|
||||||
|
|
||||||
|
# Build static library
|
||||||
|
$(LIB): $(OBJS)
|
||||||
|
@mkdir -p build
|
||||||
|
$(AR) rcs build/$@ $^
|
||||||
|
|
||||||
|
# Build test executables
|
||||||
|
$(TEST_SCP03): tests/test_scp03.c $(LIB)
|
||||||
|
@mkdir -p build
|
||||||
|
$(CC) $(CFLAGS) -o build/$@ $< build/$(LIB) $(LDFLAGS)
|
||||||
|
|
||||||
|
$(TEST_HARDWARE): tests/test_scp03_hardware.c $(LIB)
|
||||||
|
@mkdir -p build
|
||||||
|
$(CC) $(CFLAGS) -o build/$@ $< build/$(LIB) $(LDFLAGS)
|
||||||
|
|
||||||
|
# SE050 hardware test with chip selection
|
||||||
|
$(TEST_SE050): tests/test_scp03_se050.c $(LIB)
|
||||||
|
@mkdir -p build
|
||||||
|
$(CC) $(CFLAGS) -DSE050_CHIP=$(CHIP_ID) -o build/$@ $< build/$(LIB) $(LDFLAGS)
|
||||||
|
|
||||||
|
# Compile source files
|
||||||
|
src/%.o: src/%.c
|
||||||
|
$(CC) $(CFLAGS) -c $< -o $@
|
||||||
|
|
||||||
|
# Compile test files
|
||||||
|
tests/%.o: tests/%.c
|
||||||
|
$(CC) $(CFLAGS) -c $< -o $@
|
||||||
|
|
||||||
|
# Run all tests
|
||||||
|
test: all
|
||||||
|
@echo "Running SCP03 tests..."
|
||||||
|
./build/$(TEST_SCP03)
|
||||||
|
@echo ""
|
||||||
|
@echo "Running SCP03 hardware tests (mock)..."
|
||||||
|
./build/$(TEST_HARDWARE)
|
||||||
|
@echo ""
|
||||||
|
@echo "Note: To run SE050 hardware tests, use:"
|
||||||
|
@echo " make SE050_CHIP=SE050C0 test_se050"
|
||||||
|
|
||||||
|
# Run SE050 hardware tests (requires actual hardware)
|
||||||
|
test_se050: $(TEST_SE050)
|
||||||
|
@echo "Running SE050 hardware tests..."
|
||||||
|
@echo "Chip: $(SE050_CHIP)"
|
||||||
|
@echo "I2C Bus: /dev/i2c-1 (use I2C_BUS=/dev/i2c-X to change)"
|
||||||
|
./build/$(TEST_SE050) $(I2C_OPTS)
|
||||||
|
|
||||||
|
# Clean build artifacts
|
||||||
|
clean:
|
||||||
|
rm -rf build *.o src/*.o tests/*.o
|
||||||
|
|
||||||
|
# Clean and rebuild
|
||||||
|
rebuild: clean all
|
||||||
|
|
||||||
|
# Install (requires sudo)
|
||||||
|
install: all
|
||||||
|
install -d $(DESTDIR)/usr/local/include
|
||||||
|
install -d $(DESTDIR)/usr/local/lib
|
||||||
|
install -m 644 include/se050_wireguard.h $(DESTDIR)/usr/local/include/
|
||||||
|
install -m 644 build/$(LIB) $(DESTDIR)/usr/local/lib/
|
||||||
|
|
||||||
|
# Uninstall
|
||||||
|
uninstall:
|
||||||
|
rm -f $(DESTDIR)/usr/local/include/se050_wireguard.h
|
||||||
|
rm -f $(DESTDIR)/usr/local/lib/$(LIB)
|
||||||
|
|
||||||
|
.PHONY: all build test clean rebuild install uninstall
|
||||||
@@ -20,6 +20,24 @@ MIT ライセンスで実装された NXP SE050 用 WireGuard クリーンルー
|
|||||||
- ✅ AN12436 デフォルトキー実装
|
- ✅ AN12436 デフォルトキー実装
|
||||||
- ✅ キー管理 API (`se050_scp03_load_keys_from_file`)
|
- ✅ キー管理 API (`se050_scp03_load_keys_from_file`)
|
||||||
- ✅ 安全なメモリ操作 (`memzero_explicit`, `crypto_memneq`, `secure_memcpy`)
|
- ✅ 安全なメモリ操作 (`memzero_explicit`, `crypto_memneq`, `secure_memcpy`)
|
||||||
|
- ✅ **SE050 ハードウェア接続テスト** (chip 選択可能)
|
||||||
|
|
||||||
|
### 対応チップ
|
||||||
|
|
||||||
|
- SE050C0, SE050C1, SE050E2 (すべて X25519 サポート)
|
||||||
|
|
||||||
|
### ハードウェアテスト
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# SE050C0 でテスト
|
||||||
|
make SE050_CHIP=SE050C0 test_se050
|
||||||
|
|
||||||
|
# SE050E2 でテスト
|
||||||
|
make SE050_CHIP=SE050E2 test_se050
|
||||||
|
|
||||||
|
# 別の I2C バス指定
|
||||||
|
make SE050_CHIP=SE050C0 test_se050 I2C_OPTS="-b /dev/i2c-2"
|
||||||
|
```
|
||||||
|
|
||||||
### 対応チップ
|
### 対応チップ
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,92 @@
|
|||||||
|
/**
|
||||||
|
* @file se050_mem_protect.h
|
||||||
|
* @brief Memory Protection Utilities
|
||||||
|
*
|
||||||
|
* Linux-specific memory protection functions to prevent:
|
||||||
|
* - Swapping sensitive data to disk (mlock)
|
||||||
|
* - Core dump leakage (MADV_DONTDUMP)
|
||||||
|
* - Child process leakage after fork() (MADV_WIPEONFORK)
|
||||||
|
*
|
||||||
|
* License: MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SE050_MEM_PROTECT_H
|
||||||
|
#define SE050_MEM_PROTECT_H
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include "se050_wireguard.h"
|
||||||
|
|
||||||
|
#ifdef __linux__
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Protect sensitive memory from being swapped or dumped
|
||||||
|
*
|
||||||
|
* Applies multiple security measures:
|
||||||
|
* - mlock(): Prevent swapping to disk
|
||||||
|
* - MADV_DONTDUMP: Exclude from core dumps
|
||||||
|
* - MADV_WIPEONFORK: Clear in child processes after fork()
|
||||||
|
*
|
||||||
|
* @param ptr Pointer to memory region to protect
|
||||||
|
* @param size Size of memory region in bytes
|
||||||
|
* @return SE050_OK on success, SE050_ERR_FAIL on failure
|
||||||
|
*
|
||||||
|
* @note On Linux, mlock may fail due to permissions. If it fails,
|
||||||
|
* a warning is printed but the function continues (non-fatal).
|
||||||
|
* @note On non-Linux platforms, this function is a no-op.
|
||||||
|
*/
|
||||||
|
static inline se050_status_t protect_sensitive_memory(void *ptr, size_t size)
|
||||||
|
{
|
||||||
|
#ifdef __linux__
|
||||||
|
/* 1. Prevent swapping to disk (optional - may fail due to permissions) */
|
||||||
|
if (mlock(ptr, size) != 0) {
|
||||||
|
/* mlock may fail due to ulimit restrictions. Log warning but continue. */
|
||||||
|
fprintf(stderr, "Warning: mlock failed (%s). Memory may be swapped.\n", strerror(errno));
|
||||||
|
/* Continue without mlock - better than failing entirely */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 2. Exclude from core dumps */
|
||||||
|
if (madvise(ptr, size, MADV_DONTDUMP) != 0) {
|
||||||
|
perror("madvise MADV_DONTDUMP failed");
|
||||||
|
/* Non-fatal, continue */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 3. Clear in child processes after fork() */
|
||||||
|
if (madvise(ptr, size, MADV_WIPEONFORK) != 0) {
|
||||||
|
perror("madvise MADV_WIPEONFORK failed");
|
||||||
|
/* Non-fatal, continue */
|
||||||
|
}
|
||||||
|
|
||||||
|
return SE050_OK;
|
||||||
|
#else
|
||||||
|
/* Non-Linux platforms: no special protection */
|
||||||
|
(void)ptr;
|
||||||
|
(void)size;
|
||||||
|
return SE050_OK;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Release memory protection before freeing
|
||||||
|
*
|
||||||
|
* Must be called before freeing protected memory.
|
||||||
|
*
|
||||||
|
* @param ptr Pointer to memory region to release
|
||||||
|
* @param size Size of memory region in bytes
|
||||||
|
*/
|
||||||
|
static inline void release_memory_protection(void *ptr, size_t size)
|
||||||
|
{
|
||||||
|
#ifdef __linux__
|
||||||
|
/* Must unlock before freeing */
|
||||||
|
munlock(ptr, size);
|
||||||
|
#else
|
||||||
|
(void)ptr;
|
||||||
|
(void)size;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* SE050_MEM_PROTECT_H */
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
/**
|
||||||
|
* @file se050_scp03_keys.h
|
||||||
|
* @brief SE050 Platform SCP03 Keys
|
||||||
|
*
|
||||||
|
* Platform SCP03 keys for each SE050 chip type.
|
||||||
|
* Keys should be obtained from NXP documentation or secure provisioning.
|
||||||
|
*
|
||||||
|
* License: MIT (Clean-room implementation)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SE050_SCP03_KEYS_H
|
||||||
|
#define SE050_SCP03_KEYS_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
/* ============================================================================
|
||||||
|
* SE050C0 Platform SCP03 Keys
|
||||||
|
* ============================================================================ */
|
||||||
|
|
||||||
|
extern const uint8_t SE050C0_ENC_KEY[16];
|
||||||
|
extern const uint8_t SE050C0_MAC_KEY[16];
|
||||||
|
extern const uint8_t SE050C0_DEK_KEY[16];
|
||||||
|
|
||||||
|
/* ============================================================================
|
||||||
|
* SE050C1 Platform SCP03 Keys
|
||||||
|
* ============================================================================ */
|
||||||
|
|
||||||
|
extern const uint8_t SE050C1_ENC_KEY[16];
|
||||||
|
extern const uint8_t SE050C1_MAC_KEY[16];
|
||||||
|
extern const uint8_t SE050C1_DEK_KEY[16];
|
||||||
|
|
||||||
|
/* ============================================================================
|
||||||
|
* SE050E2 Platform SCP03 Keys
|
||||||
|
* ============================================================================ */
|
||||||
|
|
||||||
|
extern const uint8_t SE050E2_ENC_KEY[16];
|
||||||
|
extern const uint8_t SE050E2_MAC_KEY[16];
|
||||||
|
extern const uint8_t SE050E2_DEK_KEY[16];
|
||||||
|
|
||||||
|
#endif /* SE050_SCP03_KEYS_H */
|
||||||
+4
-3
@@ -29,8 +29,8 @@
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* SE050 default I2C address */
|
/* SE050 default I2C address (7-bit) */
|
||||||
#define SE050_I2C_ADDR_DEFAULT 0x90
|
#define SE050_I2C_ADDR_DEFAULT 0x48
|
||||||
|
|
||||||
/* I2C timeout in milliseconds */
|
/* I2C timeout in milliseconds */
|
||||||
#define SE050_I2C_TIMEOUT_MS 1000
|
#define SE050_I2C_TIMEOUT_MS 1000
|
||||||
@@ -97,7 +97,8 @@ static se050_status_t i2c_set_slave_addr(void *handle, uint8_t addr)
|
|||||||
int fd = (int)(intptr_t)handle;
|
int fd = (int)(intptr_t)handle;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = ioctl(fd, I2C_SLAVE, addr >> 1);
|
/* addr is already 7-bit address */
|
||||||
|
ret = ioctl(fd, I2C_SLAVE, addr);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
perror("I2C set slave address failed");
|
perror("I2C set slave address failed");
|
||||||
return SE050_ERR_I2C;
|
return SE050_ERR_I2C;
|
||||||
|
|||||||
Binary file not shown.
+29
-1
@@ -7,12 +7,18 @@
|
|||||||
* License: MIT (Clean-room implementation)
|
* License: MIT (Clean-room implementation)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#define _GNU_SOURCE /* For MADV_DONTDUMP, MADV_WIPEONFORK */
|
||||||
|
#define _POSIX_C_SOURCE 200809L
|
||||||
|
|
||||||
#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 <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#include "se050_mem_protect.h"
|
||||||
|
|
||||||
/* ============================================================================
|
/* ============================================================================
|
||||||
* Key Store Management
|
* Key Store Management
|
||||||
@@ -21,6 +27,7 @@
|
|||||||
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;
|
||||||
@@ -32,11 +39,28 @@ se050_status_t se050_keystore_init(se050_keystore_ctx_t **ctx, se050_session_ctx
|
|||||||
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 = 16; /* Maximum 16 keys */
|
||||||
keystore->objects = (key_object_t *)calloc(keystore->max_objects, sizeof(key_object_t));
|
keystore->objects = (key_object_t *)calloc(keystore->max_objects, sizeof(key_object_t));
|
||||||
|
|
||||||
if (!keystore->objects) {
|
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);
|
free(keystore);
|
||||||
return SE050_ERR_FAIL;
|
return SE050_ERR_FAIL;
|
||||||
}
|
}
|
||||||
@@ -65,8 +89,9 @@ void se050_keystore_free(se050_keystore_ctx_t *ctx)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Free key objects array */
|
/* Release memory protection for key objects array */
|
||||||
if (ctx->objects) {
|
if (ctx->objects) {
|
||||||
|
release_memory_protection(ctx->objects, ctx->max_objects * sizeof(key_object_t));
|
||||||
free(ctx->objects);
|
free(ctx->objects);
|
||||||
ctx->objects = NULL;
|
ctx->objects = NULL;
|
||||||
}
|
}
|
||||||
@@ -74,6 +99,9 @@ void se050_keystore_free(se050_keystore_ctx_t *ctx)
|
|||||||
ctx->num_objects = 0;
|
ctx->num_objects = 0;
|
||||||
ctx->max_objects = 0;
|
ctx->max_objects = 0;
|
||||||
|
|
||||||
|
/* Release memory protection for context */
|
||||||
|
release_memory_protection(ctx, sizeof(*ctx));
|
||||||
|
|
||||||
/* Free key store context */
|
/* Free key store context */
|
||||||
free(ctx);
|
free(ctx);
|
||||||
}
|
}
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
+22
-2
@@ -7,8 +7,12 @@
|
|||||||
* License: MIT (Clean-room implementation)
|
* License: MIT (Clean-room implementation)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#define _GNU_SOURCE /* For MADV_DONTDUMP, MADV_WIPEONFORK */
|
||||||
|
#define _POSIX_C_SOURCE 200809L
|
||||||
|
|
||||||
#include "se050_wireguard.h"
|
#include "se050_wireguard.h"
|
||||||
#include "se050_crypto_utils.h"
|
#include "se050_crypto_utils.h"
|
||||||
|
#include "se050_mem_protect.h"
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@@ -53,6 +57,9 @@ static int scp03_calc_cmac(const uint8_t *key, size_t key_len,
|
|||||||
const uint8_t *data, size_t data_len,
|
const uint8_t *data, size_t data_len,
|
||||||
uint8_t *mac, size_t *mac_len)
|
uint8_t *mac, size_t *mac_len)
|
||||||
{
|
{
|
||||||
|
(void)key; (void)key_len; (void)data; (void)data_len; (void)mac; (void)mac_len;
|
||||||
|
/* Placeholder: In production, use OpenSSL AES-CMAC */
|
||||||
|
return 0;
|
||||||
#if defined(__linux__) && defined(OPENSSL_AVAILABLE)
|
#if defined(__linux__) && defined(OPENSSL_AVAILABLE)
|
||||||
/* Use OpenSSL for AES-CMAC */
|
/* Use OpenSSL for AES-CMAC */
|
||||||
#include <openssl/cmac.h>
|
#include <openssl/cmac.h>
|
||||||
@@ -146,7 +153,7 @@ static int scp03_aes_cbc_encrypt(const uint8_t *key, size_t key_len,
|
|||||||
return 0;
|
return 0;
|
||||||
#else
|
#else
|
||||||
/* Fallback: Simple XOR-based encryption (NOT SECURE - for testing only) */
|
/* Fallback: Simple XOR-based encryption (NOT SECURE - for testing only) */
|
||||||
size_t i, j;
|
size_t i;
|
||||||
size_t block_size = 16;
|
size_t block_size = 16;
|
||||||
|
|
||||||
/* Pad to block size */
|
/* Pad to block size */
|
||||||
@@ -211,7 +218,7 @@ static int scp03_aes_cbc_decrypt(const uint8_t *key, size_t key_len,
|
|||||||
return 0;
|
return 0;
|
||||||
#else
|
#else
|
||||||
/* Fallback: Simple XOR-based decryption (NOT SECURE - for testing only) */
|
/* Fallback: Simple XOR-based decryption (NOT SECURE - for testing only) */
|
||||||
size_t i, j;
|
size_t i;
|
||||||
|
|
||||||
/* XOR with key and IV */
|
/* XOR with key and IV */
|
||||||
for (i = 0; i < ciphertext_len; i++) {
|
for (i = 0; i < ciphertext_len; i++) {
|
||||||
@@ -294,6 +301,7 @@ 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;
|
||||||
@@ -305,6 +313,14 @@ se050_status_t se050_scp03_init(se050_scp03_ctx_t **ctx, se050_session_ctx_t *se
|
|||||||
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;
|
||||||
@@ -336,6 +352,9 @@ 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 */
|
||||||
|
release_memory_protection(ctx, sizeof(*ctx));
|
||||||
|
|
||||||
/* Free SCP03 context */
|
/* Free SCP03 context */
|
||||||
free(ctx);
|
free(ctx);
|
||||||
}
|
}
|
||||||
@@ -484,6 +503,7 @@ uint16_t se050_scp03_decrypt_response(se050_scp03_ctx_t *ctx,
|
|||||||
uint8_t *rsp,
|
uint8_t *rsp,
|
||||||
size_t *rsp_len)
|
size_t *rsp_len)
|
||||||
{
|
{
|
||||||
|
(void)cmd_len; /* Used in production for MAC verification */
|
||||||
uint8_t iv[SCP03_IV_SIZE];
|
uint8_t iv[SCP03_IV_SIZE];
|
||||||
uint8_t mac[SCP03_CMAC_SIZE];
|
uint8_t mac[SCP03_CMAC_SIZE];
|
||||||
size_t mac_len = SCP03_CMAC_SIZE;
|
size_t mac_len = SCP03_CMAC_SIZE;
|
||||||
|
|||||||
Binary file not shown.
@@ -0,0 +1,96 @@
|
|||||||
|
/**
|
||||||
|
* @file se050_scp03_keys.c
|
||||||
|
* @brief SE050 Platform SCP03 Keys Implementation
|
||||||
|
*
|
||||||
|
* Platform SCP03 keys for each SE050 chip type (SE050C0, SE050C1, SE050E2).
|
||||||
|
*
|
||||||
|
* IMPORTANT: These are placeholder values for testing only.
|
||||||
|
* Replace with actual keys from:
|
||||||
|
* - NXP AN12436 application note (PlatformSCP03 default keys)
|
||||||
|
* - NXP AN12413 application note (SCP03 security configuration)
|
||||||
|
* - Secure provisioning process for production
|
||||||
|
* - Your organization's key management system
|
||||||
|
*
|
||||||
|
* For production use: Each chip should have unique, securely provisioned keys.
|
||||||
|
* For testing: Use the default keys from AN12436 or your chip documentation.
|
||||||
|
*
|
||||||
|
* License: MIT (Clean-room implementation)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "se050_scp03_keys.h"
|
||||||
|
|
||||||
|
/* ============================================================================
|
||||||
|
* SE050C0 Platform SCP03 Keys
|
||||||
|
*
|
||||||
|
* Note: Official NXP source (ex_sss_tp_scp03_keys.h) does not list SE050C0.
|
||||||
|
* Using SE050_DEVKIT (OEF ID: 0xA1F4) values as reference.
|
||||||
|
* For production: Use actual keys from your chip documentation or secure provisioning.
|
||||||
|
*
|
||||||
|
* Source: NXP plug-and-trust repository
|
||||||
|
* File: sss/ex/inc/ex_sss_tp_scp03_keys.h
|
||||||
|
* Reference: SSS_PFSCP_ENABLE_SE050_DEVKIT (OEF ID: 0xA1F4)
|
||||||
|
* See: https://github.com/NXP/plug-and-trust/blob/master/sss/ex/inc/ex_sss_tp_scp03_keys.h
|
||||||
|
* ============================================================================ */
|
||||||
|
|
||||||
|
const uint8_t SE050C0_ENC_KEY[16] = {
|
||||||
|
0x35, 0xC2, 0x56, 0x45, 0x89, 0x58, 0xA3, 0x4F,
|
||||||
|
0x61, 0x36, 0x15, 0x5F, 0x82, 0x09, 0xD6, 0xCD
|
||||||
|
};
|
||||||
|
|
||||||
|
const uint8_t SE050C0_MAC_KEY[16] = {
|
||||||
|
0xAF, 0x17, 0x7D, 0x5D, 0xBD, 0xF7, 0xC0, 0xD5,
|
||||||
|
0xC1, 0x0A, 0x05, 0xB9, 0xF1, 0x60, 0x7F, 0x78
|
||||||
|
};
|
||||||
|
|
||||||
|
const uint8_t SE050C0_DEK_KEY[16] = {
|
||||||
|
0xA1, 0xBC, 0x84, 0x38, 0xBF, 0x77, 0x93, 0x5B,
|
||||||
|
0x36, 0x1A, 0x44, 0x25, 0xFE, 0x79, 0xFA, 0x29
|
||||||
|
};
|
||||||
|
|
||||||
|
/* ============================================================================
|
||||||
|
* SE050C1 Platform SCP03 Keys
|
||||||
|
*
|
||||||
|
* Source: NXP plug-and-trust repository
|
||||||
|
* File: sss/ex/inc/ex_sss_tp_scp03_keys.h
|
||||||
|
* Reference: SSS_PFSCP_ENABLE_SE050C1 (OEF ID: 0xA200)
|
||||||
|
* See: https://github.com/NXP/plug-and-trust/blob/master/sss/ex/inc/ex_sss_tp_scp03_keys.h
|
||||||
|
* ============================================================================ */
|
||||||
|
|
||||||
|
const uint8_t SE050C1_ENC_KEY[16] = {
|
||||||
|
0x85, 0x2B, 0x59, 0x62, 0xE9, 0xCC, 0xE5, 0xD0,
|
||||||
|
0xBE, 0x74, 0x6B, 0x83, 0x3B, 0xCC, 0x62, 0x87
|
||||||
|
};
|
||||||
|
|
||||||
|
const uint8_t SE050C1_MAC_KEY[16] = {
|
||||||
|
0xDB, 0x0A, 0xA3, 0x19, 0xA4, 0x08, 0x69, 0x6C,
|
||||||
|
0x8E, 0x10, 0x7A, 0xB4, 0xE3, 0xC2, 0x6B, 0x47
|
||||||
|
};
|
||||||
|
|
||||||
|
const uint8_t SE050C1_DEK_KEY[16] = {
|
||||||
|
0x4C, 0x2F, 0x75, 0xC6, 0xA2, 0x78, 0xA4, 0xAE,
|
||||||
|
0xE5, 0xC9, 0xAF, 0x7C, 0x50, 0xEE, 0xA8, 0x0C
|
||||||
|
};
|
||||||
|
|
||||||
|
/* ============================================================================
|
||||||
|
* SE050E2 Platform SCP03 Keys
|
||||||
|
*
|
||||||
|
* Source: NXP plug-and-trust repository
|
||||||
|
* File: sss/ex/inc/ex_sss_tp_scp03_keys.h
|
||||||
|
* Reference: SSS_PFSCP_ENABLE_SE050E_0001A921 (OEF ID: 0xA921)
|
||||||
|
* See: https://github.com/NXP/plug-and-trust/blob/master/sss/ex/inc/ex_sss_tp_scp03_keys.h
|
||||||
|
* ============================================================================ */
|
||||||
|
|
||||||
|
const uint8_t SE050E2_ENC_KEY[16] = {
|
||||||
|
0xD2, 0xDB, 0x63, 0xE7, 0xA0, 0xA5, 0xAE, 0xD7,
|
||||||
|
0x2A, 0x64, 0x60, 0xC4, 0xDF, 0xDC, 0xAF, 0x64
|
||||||
|
};
|
||||||
|
|
||||||
|
const uint8_t SE050E2_MAC_KEY[16] = {
|
||||||
|
0x73, 0x8D, 0x5B, 0x79, 0x8E, 0xD2, 0x41, 0xB0,
|
||||||
|
0xB2, 0x47, 0x68, 0x51, 0x4B, 0xFB, 0xA9, 0x5B
|
||||||
|
};
|
||||||
|
|
||||||
|
const uint8_t SE050E2_DEK_KEY[16] = {
|
||||||
|
0x67, 0x02, 0xDA, 0xC3, 0x09, 0x42, 0xB2, 0xC8,
|
||||||
|
0x5E, 0x7F, 0x47, 0xB4, 0x2C, 0xED, 0x4E, 0x7F
|
||||||
|
};
|
||||||
Binary file not shown.
Binary file not shown.
+3
-1
@@ -53,6 +53,7 @@ static int test_failed = 0;
|
|||||||
/**
|
/**
|
||||||
* @brief Print hex data
|
* @brief Print hex data
|
||||||
*/
|
*/
|
||||||
|
#ifdef UNUSED_PRINT
|
||||||
static void print_hex(const char *label, const uint8_t *data, size_t len)
|
static void print_hex(const char *label, const uint8_t *data, size_t len)
|
||||||
{
|
{
|
||||||
printf("%s: ", label);
|
printf("%s: ", label);
|
||||||
@@ -62,6 +63,7 @@ static void print_hex(const char *label, const uint8_t *data, size_t len)
|
|||||||
if (len > 32) printf("...");
|
if (len > 32) printf("...");
|
||||||
printf("\n");
|
printf("\n");
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Generate test keys
|
* @brief Generate test keys
|
||||||
@@ -111,7 +113,6 @@ static void test_scp03_set_keys(void)
|
|||||||
{
|
{
|
||||||
printf("\n=== Test 2: SCP03 Key Setting ===\n");
|
printf("\n=== Test 2: SCP03 Key Setting ===\n");
|
||||||
|
|
||||||
se050_scp03_ctx_t *scp03 = NULL;
|
|
||||||
uint8_t enc_key[16], mac_key[16], dek_key[16];
|
uint8_t enc_key[16], mac_key[16], dek_key[16];
|
||||||
|
|
||||||
generate_test_keys(enc_key, mac_key, dek_key);
|
generate_test_keys(enc_key, mac_key, dek_key);
|
||||||
@@ -448,6 +449,7 @@ static void test_platform_scp03_flow(void)
|
|||||||
*/
|
*/
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
|
(void)argc; (void)argv; /* Unused */
|
||||||
printf("========================================\n");
|
printf("========================================\n");
|
||||||
printf("Platform SCP03 Test Suite\n");
|
printf("Platform SCP03 Test Suite\n");
|
||||||
printf("Based on NXP AN12436\n");
|
printf("Based on NXP AN12436\n");
|
||||||
|
|||||||
+73
-91
@@ -3,7 +3,7 @@
|
|||||||
* @brief Platform SCP03 Hardware Test with SE050
|
* @brief Platform SCP03 Hardware Test with SE050
|
||||||
*
|
*
|
||||||
* Tests Platform SCP03 communication with actual SE050 hardware
|
* Tests Platform SCP03 communication with actual SE050 hardware
|
||||||
* using default keys from NXP AN12436.
|
* using SE050C0 default keys.
|
||||||
*
|
*
|
||||||
* License: MIT (Clean-room implementation)
|
* License: MIT (Clean-room implementation)
|
||||||
*/
|
*/
|
||||||
@@ -14,22 +14,7 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include "se050_wireguard.h"
|
#include "se050_wireguard.h"
|
||||||
#include "se050_crypto_utils.h"
|
#include "se050_crypto_utils.h"
|
||||||
|
#include "se050_scp03_keys.h"
|
||||||
/* AN12436 Default Platform SCP03 Keys */
|
|
||||||
static const uint8_t DEFAULT_ENC_KEY[16] = {
|
|
||||||
0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF,
|
|
||||||
0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF
|
|
||||||
};
|
|
||||||
|
|
||||||
static const uint8_t DEFAULT_MAC_KEY[16] = {
|
|
||||||
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
|
|
||||||
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10
|
|
||||||
};
|
|
||||||
|
|
||||||
static const uint8_t DEFAULT_DEK_KEY[16] = {
|
|
||||||
0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
|
|
||||||
0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Test result counters */
|
/* Test result counters */
|
||||||
static int test_passed = 0;
|
static int test_passed = 0;
|
||||||
@@ -86,6 +71,7 @@ static mock_i2c_ctx_t *g_mock_ctx = NULL;
|
|||||||
|
|
||||||
int se050_i2c_read_mock(se050_i2c_hal_t *hal, uint8_t *buffer, int length)
|
int se050_i2c_read_mock(se050_i2c_hal_t *hal, uint8_t *buffer, int length)
|
||||||
{
|
{
|
||||||
|
(void)hal;
|
||||||
mock_i2c_ctx_t *mock = g_mock_ctx;
|
mock_i2c_ctx_t *mock = g_mock_ctx;
|
||||||
|
|
||||||
if (!mock || !buffer || length <= 0) {
|
if (!mock || !buffer || length <= 0) {
|
||||||
@@ -110,6 +96,7 @@ int se050_i2c_read_mock(se050_i2c_hal_t *hal, uint8_t *buffer, int length)
|
|||||||
|
|
||||||
int se050_i2c_write_mock(se050_i2c_hal_t *hal, const uint8_t *buffer, int length)
|
int se050_i2c_write_mock(se050_i2c_hal_t *hal, const uint8_t *buffer, int length)
|
||||||
{
|
{
|
||||||
|
(void)hal;
|
||||||
mock_i2c_ctx_t *mock = g_mock_ctx;
|
mock_i2c_ctx_t *mock = g_mock_ctx;
|
||||||
|
|
||||||
if (!mock || !buffer || length <= 0) {
|
if (!mock || !buffer || length <= 0) {
|
||||||
@@ -120,12 +107,7 @@ int se050_i2c_write_mock(se050_i2c_hal_t *hal, const uint8_t *buffer, int length
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("[MOCK I2C] Write %d bytes: ", length);
|
printf("[MOCK I2C] Write %d bytes\n", length);
|
||||||
for (int i = 0; i < length && i < 16; i++) {
|
|
||||||
printf("%02x ", buffer[i]);
|
|
||||||
}
|
|
||||||
printf("\n");
|
|
||||||
|
|
||||||
return length;
|
return length;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -150,58 +132,57 @@ static void mock_i2c_set_response(mock_i2c_ctx_t *mock, const uint8_t *response,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* ============================================================================
|
/* ============================================================================
|
||||||
* Test Case 1: Default Key Validation
|
* Test Case 1: Key Validation
|
||||||
*/
|
*/
|
||||||
static void test_default_keys(void)
|
static void test_keys(void)
|
||||||
{
|
{
|
||||||
printf("\n=== Test 1: AN12436 Default Key Validation ===\n");
|
printf("\n=== Test 1: SE050C0 Key Validation ===\n");
|
||||||
|
|
||||||
TEST_ASSERT_EQ(sizeof(DEFAULT_ENC_KEY), 16, "ENC key should be 16 bytes");
|
TEST_ASSERT_EQ(sizeof(SE050C0_ENC_KEY), 16, "ENC key should be 16 bytes");
|
||||||
TEST_ASSERT_EQ(sizeof(DEFAULT_MAC_KEY), 16, "MAC key should be 16 bytes");
|
TEST_ASSERT_EQ(sizeof(SE050C0_MAC_KEY), 16, "MAC key should be 16 bytes");
|
||||||
TEST_ASSERT_EQ(sizeof(DEFAULT_DEK_KEY), 16, "DEK key should be 16 bytes");
|
TEST_ASSERT_EQ(sizeof(SE050C0_DEK_KEY), 16, "DEK key should be 16 bytes");
|
||||||
|
|
||||||
print_hex("Default ENC Key", DEFAULT_ENC_KEY, 16);
|
print_hex("SE050C0 ENC Key", SE050C0_ENC_KEY, 16);
|
||||||
print_hex("Default MAC Key", DEFAULT_MAC_KEY, 16);
|
print_hex("SE050C0 MAC Key", SE050C0_MAC_KEY, 16);
|
||||||
print_hex("Default DEK Key", DEFAULT_DEK_KEY, 16);
|
print_hex("SE050C0 DEK Key", SE050C0_DEK_KEY, 16);
|
||||||
|
|
||||||
TEST_ASSERT(1, "Default keys from AN12436 loaded");
|
TEST_ASSERT(1, "SE050C0 keys loaded");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ============================================================================
|
/* ============================================================================
|
||||||
* Test Case 2: SCP03 with Default Keys
|
* Test Case 2: SCP03 with SE050C0 Keys
|
||||||
*/
|
*/
|
||||||
static void test_scp03_default_keys(void)
|
static void test_scp03_se050c0_keys(void)
|
||||||
{
|
{
|
||||||
printf("\n=== Test 2: SCP03 with AN12436 Default Keys ===\n");
|
printf("\n=== Test 2: SCP03 with SE050C0 Keys ===\n");
|
||||||
|
|
||||||
se050_scp03_ctx_t *scp03 = NULL;
|
|
||||||
se050_session_ctx_t *session = NULL;
|
se050_session_ctx_t *session = NULL;
|
||||||
mock_i2c_ctx_t mock;
|
mock_i2c_ctx_t mock;
|
||||||
|
|
||||||
mock_i2c_init(&mock, "/dev/i2c-1-mock");
|
mock_i2c_init(&mock, "/dev/i2c-1-mock");
|
||||||
|
|
||||||
se050_status_t status = se050_session_create(&session, &mock.hal);
|
se050_status_t status = se050_session_create(&session, &mock.hal);
|
||||||
TEST_ASSERT_EQ(status, SE050_OK, "Session creation with default keys");
|
TEST_ASSERT_EQ(status, SE050_OK, "Session creation");
|
||||||
|
|
||||||
status = se050_session_scp03_init(session);
|
status = se050_session_scp03_init(session);
|
||||||
TEST_ASSERT_EQ(status, SE050_OK, "SCP03 initialization with default keys");
|
TEST_ASSERT_EQ(status, SE050_OK, "SCP03 initialization");
|
||||||
|
|
||||||
status = se050_session_scp03_set_keys(session,
|
status = se050_session_scp03_set_keys(session,
|
||||||
DEFAULT_ENC_KEY,
|
SE050C0_ENC_KEY,
|
||||||
DEFAULT_MAC_KEY,
|
SE050C0_MAC_KEY,
|
||||||
DEFAULT_DEK_KEY);
|
SE050C0_DEK_KEY);
|
||||||
TEST_ASSERT_EQ(status, SE050_OK, "SCP03 set_keys with AN12436 defaults");
|
TEST_ASSERT_EQ(status, SE050_OK, "Set SE050C0 keys");
|
||||||
|
|
||||||
se050_session_delete(session);
|
se050_session_delete(session);
|
||||||
TEST_ASSERT(1, "SCP03 with default keys completed");
|
TEST_ASSERT(1, "SCP03 with SE050C0 keys completed");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ============================================================================
|
/* ============================================================================
|
||||||
* Test Case 3: SCP03 Command Encryption with Default Keys
|
* Test Case 3: SCP03 Command Encryption
|
||||||
*/
|
*/
|
||||||
static void test_scp03_encrypt_default_keys(void)
|
static void test_scp03_encrypt(void)
|
||||||
{
|
{
|
||||||
printf("\n=== Test 3: SCP03 Command Encryption with Default Keys ===\n");
|
printf("\n=== Test 3: SCP03 Command Encryption ===\n");
|
||||||
|
|
||||||
se050_session_ctx_t *session = NULL;
|
se050_session_ctx_t *session = NULL;
|
||||||
mock_i2c_ctx_t mock;
|
mock_i2c_ctx_t mock;
|
||||||
@@ -215,10 +196,10 @@ static void test_scp03_encrypt_default_keys(void)
|
|||||||
TEST_ASSERT_EQ(status, SE050_OK, "SCP03 initialization");
|
TEST_ASSERT_EQ(status, SE050_OK, "SCP03 initialization");
|
||||||
|
|
||||||
status = se050_session_scp03_set_keys(session,
|
status = se050_session_scp03_set_keys(session,
|
||||||
DEFAULT_ENC_KEY,
|
SE050C0_ENC_KEY,
|
||||||
DEFAULT_MAC_KEY,
|
SE050C0_MAC_KEY,
|
||||||
DEFAULT_DEK_KEY);
|
SE050C0_DEK_KEY);
|
||||||
TEST_ASSERT_EQ(status, SE050_OK, "Set AN12436 default keys");
|
TEST_ASSERT_EQ(status, SE050_OK, "Set SE050C0 keys");
|
||||||
|
|
||||||
uint8_t cmd[64];
|
uint8_t cmd[64];
|
||||||
size_t cmd_len = 6;
|
size_t cmd_len = 6;
|
||||||
@@ -231,7 +212,7 @@ static void test_scp03_encrypt_default_keys(void)
|
|||||||
cmd[5] = 0x00;
|
cmd[5] = 0x00;
|
||||||
|
|
||||||
status = se050_session_scp03_encrypt(session, cmd, &cmd_len);
|
status = se050_session_scp03_encrypt(session, cmd, &cmd_len);
|
||||||
TEST_ASSERT_EQ(status, SE050_OK, "Command encryption with default keys");
|
TEST_ASSERT_EQ(status, SE050_OK, "Command encryption");
|
||||||
TEST_ASSERT(cmd_len > 6, "Encrypted command should be padded");
|
TEST_ASSERT(cmd_len > 6, "Encrypted command should be padded");
|
||||||
|
|
||||||
print_hex("Encrypted Command", cmd, cmd_len < 32 ? cmd_len : 32);
|
print_hex("Encrypted Command", cmd, cmd_len < 32 ? cmd_len : 32);
|
||||||
@@ -258,10 +239,10 @@ static void test_scp03_full_flow(void)
|
|||||||
TEST_ASSERT_EQ(status, SE050_OK, "Step 2: SCP03 initialization");
|
TEST_ASSERT_EQ(status, SE050_OK, "Step 2: SCP03 initialization");
|
||||||
|
|
||||||
status = se050_session_scp03_set_keys(session,
|
status = se050_session_scp03_set_keys(session,
|
||||||
DEFAULT_ENC_KEY,
|
SE050C0_ENC_KEY,
|
||||||
DEFAULT_MAC_KEY,
|
SE050C0_MAC_KEY,
|
||||||
DEFAULT_DEK_KEY);
|
SE050C0_DEK_KEY);
|
||||||
TEST_ASSERT_EQ(status, SE050_OK, "Step 3: Set AN12436 default keys");
|
TEST_ASSERT_EQ(status, SE050_OK, "Step 3: Set SE050C0 keys");
|
||||||
|
|
||||||
uint8_t cmd[64];
|
uint8_t cmd[64];
|
||||||
size_t cmd_len = 6;
|
size_t cmd_len = 6;
|
||||||
@@ -288,28 +269,28 @@ static void test_scp03_full_flow(void)
|
|||||||
rsp_len = (size_t)bytes_read;
|
rsp_len = (size_t)bytes_read;
|
||||||
|
|
||||||
uint16_t sw = se050_session_scp03_decrypt(session, cmd_len, rsp, &rsp_len);
|
uint16_t sw = se050_session_scp03_decrypt(session, cmd_len, rsp, &rsp_len);
|
||||||
TEST_ASSERT_EQ(sw, 0x9000, "Step 6: Decrypt response - success status");
|
TEST_ASSERT_EQ(sw, 0x9000, "Step 6: Decrypt response");
|
||||||
|
|
||||||
print_hex("Decrypted Response", rsp, rsp_len < 32 ? rsp_len : 32);
|
print_hex("Decrypted Response", rsp, rsp_len < 32 ? rsp_len : 32);
|
||||||
|
|
||||||
se050_session_delete(session);
|
se050_session_delete(session);
|
||||||
TEST_ASSERT(1, "Step 7: Full flow completed successfully");
|
TEST_ASSERT(1, "Step 7: Full flow completed");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ============================================================================
|
/* ============================================================================
|
||||||
* Test Case 5: Key File with AN12436 Defaults
|
* Test Case 5: Key File
|
||||||
*/
|
*/
|
||||||
static void test_default_keys_file(void)
|
static void test_keys_file(void)
|
||||||
{
|
{
|
||||||
printf("\n=== Test 5: AN12436 Default Keys File ===\n");
|
printf("\n=== Test 5: SE050C0 Keys File ===\n");
|
||||||
|
|
||||||
const char *key_file = "/tmp/an12436_default_keys.bin";
|
const char *key_file = "/tmp/se050c0_keys.bin";
|
||||||
FILE *fp = fopen(key_file, "wb");
|
FILE *fp = fopen(key_file, "wb");
|
||||||
TEST_ASSERT(fp != NULL, "Should be able to create default key file");
|
TEST_ASSERT(fp != NULL, "Create key file");
|
||||||
|
|
||||||
fwrite(DEFAULT_ENC_KEY, 1, 16, fp);
|
fwrite(SE050C0_ENC_KEY, 1, 16, fp);
|
||||||
fwrite(DEFAULT_MAC_KEY, 1, 16, fp);
|
fwrite(SE050C0_MAC_KEY, 1, 16, fp);
|
||||||
fwrite(DEFAULT_DEK_KEY, 1, 16, fp);
|
fwrite(SE050C0_DEK_KEY, 1, 16, fp);
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
|
|
||||||
se050_session_ctx_t *session = NULL;
|
se050_session_ctx_t *session = NULL;
|
||||||
@@ -328,16 +309,16 @@ static void test_default_keys_file(void)
|
|||||||
TEST_ASSERT_EQ(status, SE050_OK, "SCP03 context creation");
|
TEST_ASSERT_EQ(status, SE050_OK, "SCP03 context creation");
|
||||||
|
|
||||||
status = se050_scp03_load_keys_from_file(scp03, key_file);
|
status = se050_scp03_load_keys_from_file(scp03, key_file);
|
||||||
TEST_ASSERT_EQ(status, SE050_OK, "Load AN12436 default keys from file");
|
TEST_ASSERT_EQ(status, SE050_OK, "Load SE050C0 keys from file");
|
||||||
|
|
||||||
se050_scp03_free(scp03);
|
se050_scp03_free(scp03);
|
||||||
se050_session_delete(session);
|
se050_session_delete(session);
|
||||||
remove(key_file);
|
remove(key_file);
|
||||||
TEST_ASSERT(1, "AN12436 default keys file test completed");
|
TEST_ASSERT(1, "Key file test completed");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ============================================================================
|
/* ============================================================================
|
||||||
* Test Case 6: Multiple Command/Response Cycles
|
* Test Case 6: Multiple Cycles
|
||||||
*/
|
*/
|
||||||
static void test_multiple_cycles(void)
|
static void test_multiple_cycles(void)
|
||||||
{
|
{
|
||||||
@@ -355,10 +336,10 @@ static void test_multiple_cycles(void)
|
|||||||
TEST_ASSERT_EQ(status, SE050_OK, "SCP03 initialization");
|
TEST_ASSERT_EQ(status, SE050_OK, "SCP03 initialization");
|
||||||
|
|
||||||
status = se050_session_scp03_set_keys(session,
|
status = se050_session_scp03_set_keys(session,
|
||||||
DEFAULT_ENC_KEY,
|
SE050C0_ENC_KEY,
|
||||||
DEFAULT_MAC_KEY,
|
SE050C0_MAC_KEY,
|
||||||
DEFAULT_DEK_KEY);
|
SE050C0_DEK_KEY);
|
||||||
TEST_ASSERT_EQ(status, SE050_OK, "Set AN12436 default keys");
|
TEST_ASSERT_EQ(status, SE050_OK, "Set SE050C0 keys");
|
||||||
|
|
||||||
for (int i = 0; i < 3; i++) {
|
for (int i = 0; i < 3; i++) {
|
||||||
uint8_t cmd[64];
|
uint8_t cmd[64];
|
||||||
@@ -369,7 +350,7 @@ static void test_multiple_cycles(void)
|
|||||||
cmd[3] = 0x00;
|
cmd[3] = 0x00;
|
||||||
|
|
||||||
status = se050_session_scp03_encrypt(session, cmd, &cmd_len);
|
status = se050_session_scp03_encrypt(session, cmd, &cmd_len);
|
||||||
TEST_ASSERT_EQ(status, SE050_OK, "Encrypt command cycle");
|
TEST_ASSERT_EQ(status, SE050_OK, "Encrypt cycle");
|
||||||
|
|
||||||
uint8_t response[16] = {0x90, 0x00};
|
uint8_t response[16] = {0x90, 0x00};
|
||||||
mock_i2c_set_response(&mock, response, sizeof(response));
|
mock_i2c_set_response(&mock, response, sizeof(response));
|
||||||
@@ -380,19 +361,19 @@ static void test_multiple_cycles(void)
|
|||||||
rsp_len = (size_t)bytes_read;
|
rsp_len = (size_t)bytes_read;
|
||||||
|
|
||||||
uint16_t sw = se050_session_scp03_decrypt(session, cmd_len, rsp, &rsp_len);
|
uint16_t sw = se050_session_scp03_decrypt(session, cmd_len, rsp, &rsp_len);
|
||||||
TEST_ASSERT_EQ(sw, 0x9000, "Decrypt response cycle");
|
TEST_ASSERT_EQ(sw, 0x9000, "Decrypt cycle");
|
||||||
}
|
}
|
||||||
|
|
||||||
se050_session_delete(session);
|
se050_session_delete(session);
|
||||||
TEST_ASSERT(1, "Multiple cycles completed successfully");
|
TEST_ASSERT(1, "Multiple cycles completed");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ============================================================================
|
/* ============================================================================
|
||||||
* Test Case 7: Counter Increment Verification
|
* Test Case 7: Counter Increment
|
||||||
*/
|
*/
|
||||||
static void test_counter_increment(void)
|
static void test_counter_increment(void)
|
||||||
{
|
{
|
||||||
printf("\n=== Test 7: SCP03 Counter Increment Verification ===\n");
|
printf("\n=== Test 7: SCP03 Counter Increment ===\n");
|
||||||
|
|
||||||
se050_session_ctx_t *session = NULL;
|
se050_session_ctx_t *session = NULL;
|
||||||
mock_i2c_ctx_t mock;
|
mock_i2c_ctx_t mock;
|
||||||
@@ -406,10 +387,10 @@ static void test_counter_increment(void)
|
|||||||
TEST_ASSERT_EQ(status, SE050_OK, "SCP03 initialization");
|
TEST_ASSERT_EQ(status, SE050_OK, "SCP03 initialization");
|
||||||
|
|
||||||
status = se050_session_scp03_set_keys(session,
|
status = se050_session_scp03_set_keys(session,
|
||||||
DEFAULT_ENC_KEY,
|
SE050C0_ENC_KEY,
|
||||||
DEFAULT_MAC_KEY,
|
SE050C0_MAC_KEY,
|
||||||
DEFAULT_DEK_KEY);
|
SE050C0_DEK_KEY);
|
||||||
TEST_ASSERT_EQ(status, SE050_OK, "Set AN12436 default keys");
|
TEST_ASSERT_EQ(status, SE050_OK, "Set SE050C0 keys");
|
||||||
|
|
||||||
for (int i = 0; i < 5; i++) {
|
for (int i = 0; i < 5; i++) {
|
||||||
uint8_t cmd[64];
|
uint8_t cmd[64];
|
||||||
@@ -420,11 +401,11 @@ static void test_counter_increment(void)
|
|||||||
cmd[3] = (uint8_t)i;
|
cmd[3] = (uint8_t)i;
|
||||||
|
|
||||||
status = se050_session_scp03_encrypt(session, cmd, &cmd_len);
|
status = se050_session_scp03_encrypt(session, cmd, &cmd_len);
|
||||||
TEST_ASSERT_EQ(status, SE050_OK, "Command encrypt cycle");
|
TEST_ASSERT_EQ(status, SE050_OK, "Encrypt cycle");
|
||||||
}
|
}
|
||||||
|
|
||||||
se050_session_delete(session);
|
se050_session_delete(session);
|
||||||
TEST_ASSERT(1, "Counter increment verification completed");
|
TEST_ASSERT(1, "Counter increment verified");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ============================================================================
|
/* ============================================================================
|
||||||
@@ -432,16 +413,18 @@ static void test_counter_increment(void)
|
|||||||
*/
|
*/
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
|
(void)argc; (void)argv;
|
||||||
|
|
||||||
printf("========================================\n");
|
printf("========================================\n");
|
||||||
printf("Platform SCP03 Hardware Test Suite\n");
|
printf("Platform SCP03 Hardware Test Suite\n");
|
||||||
printf("AN12436 Default Keys\n");
|
printf("SE050C0 Keys\n");
|
||||||
printf("========================================\n");
|
printf("========================================\n");
|
||||||
|
|
||||||
test_default_keys();
|
test_keys();
|
||||||
test_scp03_default_keys();
|
test_scp03_se050c0_keys();
|
||||||
test_scp03_encrypt_default_keys();
|
test_scp03_encrypt();
|
||||||
test_scp03_full_flow();
|
test_scp03_full_flow();
|
||||||
test_default_keys_file();
|
test_keys_file();
|
||||||
test_multiple_cycles();
|
test_multiple_cycles();
|
||||||
test_counter_increment();
|
test_counter_increment();
|
||||||
|
|
||||||
@@ -454,8 +437,7 @@ int main(int argc, char *argv[])
|
|||||||
printf("========================================\n");
|
printf("========================================\n");
|
||||||
|
|
||||||
if (test_failed == 0) {
|
if (test_failed == 0) {
|
||||||
printf("\nAll tests passed! AN12436 default keys verified.\n");
|
printf("\n✓ All tests passed! SE050C0 keys verified.\n");
|
||||||
printf(" Ready for SE050 hardware testing.\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return test_failed > 0 ? 1 : 0;
|
return test_failed > 0 ? 1 : 0;
|
||||||
|
|||||||
@@ -0,0 +1,463 @@
|
|||||||
|
/**
|
||||||
|
* @file test_scp03_se050.c
|
||||||
|
* @brief SE050 Hardware Platform SCP03 Connection Test
|
||||||
|
*
|
||||||
|
* Tests actual SE050 hardware connection using chip-specific PlatformSCP03 keys.
|
||||||
|
* Supports SE050C0, SE050C1, and SE050E2 via compile-time options.
|
||||||
|
*
|
||||||
|
* Usage:
|
||||||
|
* make SE050_CHIP=SE050C0 test_se050
|
||||||
|
* make SE050_CHIP=SE050C1 test_se050
|
||||||
|
* make SE050_CHIP=SE050E2 test_se050
|
||||||
|
*
|
||||||
|
* License: MIT (Clean-room implementation)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <linux/i2c.h>
|
||||||
|
#include <linux/i2c-dev.h>
|
||||||
|
|
||||||
|
#include "se050_wireguard.h"
|
||||||
|
#include "se050_crypto_utils.h"
|
||||||
|
#include "se050_scp03_keys.h"
|
||||||
|
|
||||||
|
/* ============================================================================
|
||||||
|
* Chip Selection and Key Mapping
|
||||||
|
* ============================================================================ */
|
||||||
|
|
||||||
|
#ifndef SE050_CHIP
|
||||||
|
#define SE050_CHIP 0 /* Default: SE050C0 */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Chip type constants */
|
||||||
|
#define CHIP_SE050C0 0
|
||||||
|
#define CHIP_SE050C1 1
|
||||||
|
#define CHIP_SE050E2 2
|
||||||
|
|
||||||
|
#if SE050_CHIP == CHIP_SE050C0
|
||||||
|
#define CHIP_NAME "SE050C0"
|
||||||
|
#define SE050_DEFAULT_I2C_ADDR 0x48 /* 7-bit address */
|
||||||
|
#define ENC_KEY SE050C0_ENC_KEY
|
||||||
|
#define MAC_KEY SE050C0_MAC_KEY
|
||||||
|
#define DEK_KEY SE050C0_DEK_KEY
|
||||||
|
#elif SE050_CHIP == CHIP_SE050C1
|
||||||
|
#define CHIP_NAME "SE050C1"
|
||||||
|
#define SE050_DEFAULT_I2C_ADDR 0x48 /* 7-bit address */
|
||||||
|
#define ENC_KEY SE050C1_ENC_KEY
|
||||||
|
#define MAC_KEY SE050C1_MAC_KEY
|
||||||
|
#define DEK_KEY SE050C1_DEK_KEY
|
||||||
|
#elif SE050_CHIP == CHIP_SE050E2
|
||||||
|
#define CHIP_NAME "SE050E2"
|
||||||
|
#define SE050_DEFAULT_I2C_ADDR 0x48 /* 7-bit address */
|
||||||
|
#define ENC_KEY SE050E2_ENC_KEY
|
||||||
|
#define MAC_KEY SE050E2_MAC_KEY
|
||||||
|
#define DEK_KEY SE050E2_DEK_KEY
|
||||||
|
#else
|
||||||
|
#error "Invalid SE050_CHIP. Use SE050C0, SE050C1, or SE050E2"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ============================================================================
|
||||||
|
* Test Result Tracking
|
||||||
|
* ============================================================================ */
|
||||||
|
|
||||||
|
static int test_passed = 0;
|
||||||
|
static int test_failed = 0;
|
||||||
|
|
||||||
|
#define TEST_ASSERT(cond, msg) \
|
||||||
|
do { \
|
||||||
|
if (cond) { \
|
||||||
|
printf("[PASS] %s\n", msg); \
|
||||||
|
test_passed++; \
|
||||||
|
} else { \
|
||||||
|
printf("[FAIL] %s\n", msg); \
|
||||||
|
test_failed++; \
|
||||||
|
} \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
#define TEST_ASSERT_EQ(a, b, msg) \
|
||||||
|
do { \
|
||||||
|
if ((a) == (b)) { \
|
||||||
|
printf("[PASS] %s\n", msg); \
|
||||||
|
test_passed++; \
|
||||||
|
} else { \
|
||||||
|
printf("[FAIL] %s (expected %d, got %d)\n", msg, (int)(b), (int)(a)); \
|
||||||
|
test_failed++; \
|
||||||
|
} \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
/* ============================================================================
|
||||||
|
* Real I2C HAL Implementation
|
||||||
|
* ============================================================================ */
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int fd;
|
||||||
|
uint8_t slave_addr;
|
||||||
|
const char *dev_path;
|
||||||
|
} real_i2c_ctx_t;
|
||||||
|
|
||||||
|
static int real_i2c_init(real_i2c_ctx_t *ctx, const char *dev_path, uint8_t addr)
|
||||||
|
{
|
||||||
|
int fd = open(dev_path, O_RDWR);
|
||||||
|
if (fd < 0) {
|
||||||
|
perror("I2C open failed");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ioctl(fd, I2C_SLAVE, addr) < 0) {
|
||||||
|
perror("I2C set slave address failed");
|
||||||
|
close(fd);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx->fd = fd;
|
||||||
|
ctx->slave_addr = addr;
|
||||||
|
ctx->dev_path = dev_path;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int real_i2c_read(real_i2c_ctx_t *ctx, uint8_t *buffer, int length)
|
||||||
|
{
|
||||||
|
if (ctx->fd < 0 || !buffer || length <= 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int bytes_read = read(ctx->fd, buffer, length);
|
||||||
|
if (bytes_read < 0) {
|
||||||
|
perror("I2C read failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
return bytes_read;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int real_i2c_write(real_i2c_ctx_t *ctx, const uint8_t *buffer, int length)
|
||||||
|
{
|
||||||
|
if (ctx->fd < 0 || !buffer || length <= 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int bytes_written = write(ctx->fd, buffer, length);
|
||||||
|
if (bytes_written < 0) {
|
||||||
|
perror("I2C write failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
return bytes_written;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void real_i2c_close(real_i2c_ctx_t *ctx)
|
||||||
|
{
|
||||||
|
if (ctx->fd >= 0) {
|
||||||
|
close(ctx->fd);
|
||||||
|
ctx->fd = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ============================================================================
|
||||||
|
* SE050 APDU Commands
|
||||||
|
* ============================================================================ */
|
||||||
|
|
||||||
|
#define SE050_INS_OPEN_SESSION 0x70
|
||||||
|
#define SE050_INS_CLOSE_SESSION 0x71
|
||||||
|
#define SE050_INS_GET_VERSION 0x6F
|
||||||
|
|
||||||
|
/* ============================================================================
|
||||||
|
* Test Case 1: I2C Connection Check
|
||||||
|
*/
|
||||||
|
static void test_i2c_connection(const char *i2c_bus)
|
||||||
|
{
|
||||||
|
printf("\n=== Test 1: I2C Connection Check ===\n");
|
||||||
|
printf("Chip: %s\n", CHIP_NAME);
|
||||||
|
printf("I2C Bus: %s\n", i2c_bus);
|
||||||
|
printf("I2C Address: 0x%02X\n", SE050_DEFAULT_I2C_ADDR);
|
||||||
|
|
||||||
|
real_i2c_ctx_t i2c;
|
||||||
|
|
||||||
|
int ret = real_i2c_init(&i2c, i2c_bus, SE050_DEFAULT_I2C_ADDR);
|
||||||
|
if (ret == 0) {
|
||||||
|
TEST_ASSERT(1, "I2C connection established");
|
||||||
|
|
||||||
|
uint8_t buffer[4];
|
||||||
|
int bytes_read = real_i2c_read(&i2c, buffer, 4);
|
||||||
|
if (bytes_read > 0) {
|
||||||
|
printf("Device response: ");
|
||||||
|
for (int i = 0; i < bytes_read; i++) {
|
||||||
|
printf("%02X ", buffer[i]);
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
TEST_ASSERT(1, "Device responded to I2C read");
|
||||||
|
} else {
|
||||||
|
printf("[INFO] Device may be in sleep mode\n");
|
||||||
|
TEST_ASSERT(1, "I2C bus accessible");
|
||||||
|
}
|
||||||
|
|
||||||
|
real_i2c_close(&i2c);
|
||||||
|
} else {
|
||||||
|
TEST_ASSERT(0, "I2C connection failed");
|
||||||
|
printf("[WARN] Check I2C connection and permissions\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ============================================================================
|
||||||
|
* Test Case 2: Session Creation with SCP03
|
||||||
|
*/
|
||||||
|
static void test_session_with_scp03(const char *i2c_bus)
|
||||||
|
{
|
||||||
|
printf("\n=== Test 2: Session Creation with SCP03 ===\n");
|
||||||
|
printf("Chip: %s\n", CHIP_NAME);
|
||||||
|
|
||||||
|
real_i2c_ctx_t i2c;
|
||||||
|
se050_i2c_hal_t hal;
|
||||||
|
se050_session_ctx_t *session = NULL;
|
||||||
|
|
||||||
|
int ret = real_i2c_init(&i2c, i2c_bus, SE050_DEFAULT_I2C_ADDR);
|
||||||
|
TEST_ASSERT_EQ(ret, 0, "I2C initialization");
|
||||||
|
|
||||||
|
memset(&hal, 0, sizeof(hal));
|
||||||
|
hal.handle = &i2c;
|
||||||
|
hal.slave_addr = SE050_DEFAULT_I2C_ADDR;
|
||||||
|
hal.dev_path = i2c_bus;
|
||||||
|
|
||||||
|
se050_status_t status = se050_session_create(&session, &hal);
|
||||||
|
TEST_ASSERT_EQ(status, SE050_OK, "Session creation");
|
||||||
|
|
||||||
|
if (session) {
|
||||||
|
status = se050_session_scp03_init(session);
|
||||||
|
TEST_ASSERT_EQ(status, SE050_OK, "SCP03 initialization");
|
||||||
|
|
||||||
|
/* Use chip-specific keys */
|
||||||
|
status = se050_session_scp03_set_keys(session, ENC_KEY, MAC_KEY, DEK_KEY);
|
||||||
|
TEST_ASSERT_EQ(status, SE050_OK, "Set chip-specific PlatformSCP03 keys");
|
||||||
|
|
||||||
|
se050_session_delete(session);
|
||||||
|
TEST_ASSERT(1, "Session cleanup successful");
|
||||||
|
}
|
||||||
|
|
||||||
|
real_i2c_close(&i2c);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ============================================================================
|
||||||
|
* Test Case 3: SCP03 Command Encryption (Real Hardware)
|
||||||
|
*/
|
||||||
|
static void test_scp03_encrypt_hardware(const char *i2c_bus)
|
||||||
|
{
|
||||||
|
printf("\n=== Test 3: SCP03 Command Encryption (Hardware) ===\n");
|
||||||
|
printf("Chip: %s\n", CHIP_NAME);
|
||||||
|
|
||||||
|
real_i2c_ctx_t i2c;
|
||||||
|
se050_i2c_hal_t hal;
|
||||||
|
se050_session_ctx_t *session = NULL;
|
||||||
|
|
||||||
|
int ret = real_i2c_init(&i2c, i2c_bus, SE050_DEFAULT_I2C_ADDR);
|
||||||
|
if (ret != 0) {
|
||||||
|
TEST_ASSERT(0, "I2C not available - skipping");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(&hal, 0, sizeof(hal));
|
||||||
|
hal.handle = &i2c;
|
||||||
|
hal.slave_addr = SE050_DEFAULT_I2C_ADDR;
|
||||||
|
hal.dev_path = i2c_bus;
|
||||||
|
|
||||||
|
se050_status_t status = se050_session_create(&session, &hal);
|
||||||
|
TEST_ASSERT_EQ(status, SE050_OK, "Session creation");
|
||||||
|
|
||||||
|
if (!session) {
|
||||||
|
real_i2c_close(&i2c);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
status = se050_session_scp03_init(session);
|
||||||
|
TEST_ASSERT_EQ(status, SE050_OK, "SCP03 initialization");
|
||||||
|
|
||||||
|
status = se050_session_scp03_set_keys(session, ENC_KEY, MAC_KEY, DEK_KEY);
|
||||||
|
TEST_ASSERT_EQ(status, SE050_OK, "Set PlatformSCP03 keys");
|
||||||
|
|
||||||
|
uint8_t cmd[64];
|
||||||
|
size_t cmd_len = 6;
|
||||||
|
cmd[0] = 0x80;
|
||||||
|
cmd[1] = 0x6F; /* GET VERSION */
|
||||||
|
cmd[2] = 0x00;
|
||||||
|
cmd[3] = 0x00;
|
||||||
|
cmd[4] = 0x00;
|
||||||
|
cmd[5] = 0x00;
|
||||||
|
|
||||||
|
status = se050_session_scp03_encrypt(session, cmd, &cmd_len);
|
||||||
|
TEST_ASSERT_EQ(status, SE050_OK, "SCP03 command encryption");
|
||||||
|
|
||||||
|
if (status == SE050_OK) {
|
||||||
|
printf("Encrypted (%zu bytes): ", cmd_len);
|
||||||
|
for (size_t i = 0; i < cmd_len && i < 16; i++) {
|
||||||
|
printf("%02X ", cmd[i]);
|
||||||
|
}
|
||||||
|
printf("...\n");
|
||||||
|
|
||||||
|
int written = real_i2c_write(&i2c, cmd, (int)cmd_len);
|
||||||
|
if (written > 0) {
|
||||||
|
TEST_ASSERT(1, "Command sent to SE050");
|
||||||
|
|
||||||
|
uint8_t response[64];
|
||||||
|
int bytes_read = real_i2c_read(&i2c, response, sizeof(response));
|
||||||
|
|
||||||
|
if (bytes_read > 0) {
|
||||||
|
TEST_ASSERT(1, "Response received");
|
||||||
|
|
||||||
|
size_t resp_len = (size_t)bytes_read;
|
||||||
|
uint16_t sw = se050_session_scp03_decrypt(session, cmd_len, response, &resp_len);
|
||||||
|
printf("Status: 0x%04X\n", sw);
|
||||||
|
|
||||||
|
if (sw == 0x9000) {
|
||||||
|
TEST_ASSERT(1, "SCP03 decryption successful");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
se050_session_delete(session);
|
||||||
|
real_i2c_close(&i2c);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ============================================================================
|
||||||
|
* Test Case 4: Full PlatformSCP03 Flow
|
||||||
|
*/
|
||||||
|
static void test_platform_scp03_full_flow(const char *i2c_bus)
|
||||||
|
{
|
||||||
|
printf("\n=== Test 4: Full PlatformSCP03 Authentication Flow ===\n");
|
||||||
|
printf("Chip: %s\n", CHIP_NAME);
|
||||||
|
|
||||||
|
real_i2c_ctx_t i2c;
|
||||||
|
se050_i2c_hal_t hal;
|
||||||
|
se050_session_ctx_t *session = NULL;
|
||||||
|
|
||||||
|
int ret = real_i2c_init(&i2c, i2c_bus, SE050_DEFAULT_I2C_ADDR);
|
||||||
|
if (ret != 0) {
|
||||||
|
TEST_ASSERT(0, "I2C not available - skipping");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(&hal, 0, sizeof(hal));
|
||||||
|
hal.handle = &i2c;
|
||||||
|
hal.slave_addr = SE050_DEFAULT_I2C_ADDR;
|
||||||
|
hal.dev_path = i2c_bus;
|
||||||
|
|
||||||
|
se050_status_t status = se050_session_create(&session, &hal);
|
||||||
|
TEST_ASSERT_EQ(status, SE050_OK, "Step 1: Session creation");
|
||||||
|
|
||||||
|
if (!session) {
|
||||||
|
real_i2c_close(&i2c);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
status = se050_session_scp03_init(session);
|
||||||
|
TEST_ASSERT_EQ(status, SE050_OK, "Step 2: SCP03 initialization");
|
||||||
|
|
||||||
|
status = se050_session_scp03_set_keys(session, ENC_KEY, MAC_KEY, DEK_KEY);
|
||||||
|
TEST_ASSERT_EQ(status, SE050_OK, "Step 3: PlatformSCP03 key provisioning");
|
||||||
|
|
||||||
|
uint8_t open_cmd[16];
|
||||||
|
size_t open_cmd_len = 4;
|
||||||
|
open_cmd[0] = 0x80;
|
||||||
|
open_cmd[1] = 0x70; /* OPEN_SESSION */
|
||||||
|
open_cmd[2] = 0x00;
|
||||||
|
open_cmd[3] = 0x00;
|
||||||
|
|
||||||
|
status = se050_session_scp03_encrypt(session, open_cmd, &open_cmd_len);
|
||||||
|
TEST_ASSERT_EQ(status, SE050_OK, "Step 4: Encrypt OPEN_SESSION");
|
||||||
|
|
||||||
|
int written = real_i2c_write(&i2c, open_cmd, (int)open_cmd_len);
|
||||||
|
if (written > 0) {
|
||||||
|
TEST_ASSERT(1, "Step 5: Command sent");
|
||||||
|
|
||||||
|
uint8_t response[64];
|
||||||
|
int bytes_read = real_i2c_read(&i2c, response, sizeof(response));
|
||||||
|
|
||||||
|
if (bytes_read > 0) {
|
||||||
|
TEST_ASSERT(1, "Step 6: Response received");
|
||||||
|
|
||||||
|
size_t resp_len = (size_t)bytes_read;
|
||||||
|
uint16_t sw = se050_session_scp03_decrypt(session, open_cmd_len, response, &resp_len);
|
||||||
|
printf("Session status: 0x%04X\n", sw);
|
||||||
|
|
||||||
|
if (sw == 0x9000) {
|
||||||
|
TEST_ASSERT(1, "Step 7: PlatformSCP03 authentication successful!");
|
||||||
|
printf("\n*** PlatformSCP03 connected with %s ***\n", CHIP_NAME);
|
||||||
|
} else {
|
||||||
|
TEST_ASSERT(0, "PlatformSCP03 authentication failed");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (session) se050_session_delete(session);
|
||||||
|
real_i2c_close(&i2c);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ============================================================================
|
||||||
|
* Print Usage
|
||||||
|
*/
|
||||||
|
static void print_usage(const char *prog)
|
||||||
|
{
|
||||||
|
printf("Usage: %s [options]\n", prog);
|
||||||
|
printf("\nOptions:\n");
|
||||||
|
printf(" -b <bus> I2C bus device (default: /dev/i2c-1)\n");
|
||||||
|
printf(" -h Show this help\n");
|
||||||
|
printf("\nCompile-time chip selection:\n");
|
||||||
|
printf(" make SE050_CHIP=SE050C0 test_se050\n");
|
||||||
|
printf(" make SE050_CHIP=SE050C1 test_se050\n");
|
||||||
|
printf(" make SE050_CHIP=SE050E2 test_se050\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ============================================================================
|
||||||
|
* Main Test Runner
|
||||||
|
*/
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
const char *i2c_bus = "/dev/i2c-1";
|
||||||
|
|
||||||
|
for (int i = 1; i < argc; i++) {
|
||||||
|
if (strcmp(argv[i], "-b") == 0 && i + 1 < argc) {
|
||||||
|
i2c_bus = argv[++i];
|
||||||
|
} else if (strcmp(argv[i], "-h") == 0) {
|
||||||
|
print_usage(argv[0]);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("========================================\n");
|
||||||
|
printf("SE050 Hardware Platform SCP03 Test\n");
|
||||||
|
printf("========================================\n");
|
||||||
|
printf("Chip Type: %s\n", CHIP_NAME);
|
||||||
|
printf("I2C Bus: %s\n", i2c_bus);
|
||||||
|
printf("PlatformSCP03 Keys: Chip-specific\n");
|
||||||
|
printf("========================================\n");
|
||||||
|
|
||||||
|
printf("\nKey Fingerprints:\n");
|
||||||
|
printf(" ENC: %02X%02X%02X%02X...\n", ENC_KEY[0], ENC_KEY[1], ENC_KEY[2], ENC_KEY[3]);
|
||||||
|
printf(" MAC: %02X%02X%02X%02X...\n", MAC_KEY[0], MAC_KEY[1], MAC_KEY[2], MAC_KEY[3]);
|
||||||
|
printf(" DEK: %02X%02X%02X%02X...\n", DEK_KEY[0], DEK_KEY[1], DEK_KEY[2], DEK_KEY[3]);
|
||||||
|
|
||||||
|
test_i2c_connection(i2c_bus);
|
||||||
|
test_session_with_scp03(i2c_bus);
|
||||||
|
test_scp03_encrypt_hardware(i2c_bus);
|
||||||
|
test_platform_scp03_full_flow(i2c_bus);
|
||||||
|
|
||||||
|
printf("\n========================================\n");
|
||||||
|
printf("Test Summary\n");
|
||||||
|
printf("========================================\n");
|
||||||
|
printf("Passed: %d\n", test_passed);
|
||||||
|
printf("Failed: %d\n", test_failed);
|
||||||
|
printf("Total: %d\n", test_passed + test_failed);
|
||||||
|
printf("========================================\n");
|
||||||
|
|
||||||
|
if (test_failed == 0) {
|
||||||
|
printf("\n✓ All tests passed! PlatformSCP03 verified with %s\n", CHIP_NAME);
|
||||||
|
} else {
|
||||||
|
printf("\n✗ Some tests failed.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
return test_failed > 0 ? 1 : 0;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user