dfadaf092c
変更内容: 1. SE050C2 のサポート追加 - se050_scp03_keys.h: SE050C2 は SE050C1 と同じキーを使用 - test_scp03_se050.c: SE050C2 チップ選択追加 - Makefile: SE050C2 の CHIP_ID=2, SE050E2=3 に更新 2. キー管理の明確化 - test_scp03_se050.c に詳細コメント追加 - キーは実行時置き換えではなく、コンパイル時選択を明記 - 異なるキーでテストするには再コンパイルが必要と説明 3. 使い方の明確化 make SE050_CHIP=SE050C0 test_se050 # SE050C0 キー make SE050_CHIP=SE050C1 test_se050 # SE050C1 キー make SE050_CHIP=SE050C2 test_se050 # SE050C2 キー (SE050C1 と同じ) make SE050_CHIP=SE050E2 test_se050 # SE050E2 キー 注記: - 実行時キー置換機能は未実装 - 動的キー切り替えが必要な場合は、se050_session_scp03_set_keys() を使用して実装可能(現状では各テスト関数でコンパイル時キーを直接使用)
482 lines
15 KiB
C
482 lines
15 KiB
C
/**
|
|
* @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
|
|
*
|
|
* Important: This test uses chip-specific PlatformSCP03 keys at compile time.
|
|
* The keys are NOT replaced at runtime - they are selected via SE050_CHIP macro.
|
|
*
|
|
* To test with different keys:
|
|
* make SE050_CHIP=SE050C0 test_se050 # Use SE050C0 default keys
|
|
* make SE050_CHIP=SE050C1 test_se050 # Use SE050C1 default keys
|
|
* make SE050_CHIP=SE050E2 test_se050 # Use SE050E2 default keys
|
|
*
|
|
* For custom keys, modify se050_scp03_keys.h or pass custom keys at runtime
|
|
* via se050_session_scp03_set_keys() (not implemented in this test).
|
|
* ============================================================================ */
|
|
|
|
#ifndef SE050_CHIP
|
|
#define SE050_CHIP 0 /* Default: SE050C0 */
|
|
#endif
|
|
|
|
/* Chip type constants */
|
|
#define CHIP_SE050C0 0
|
|
#define CHIP_SE050C1 1
|
|
#define CHIP_SE050C2 2
|
|
#define CHIP_SE050E2 3
|
|
|
|
#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_SE050C2
|
|
#define CHIP_NAME "SE050C2"
|
|
#define SE050_DEFAULT_I2C_ADDR 0x48 /* 7-bit address */
|
|
#define ENC_KEY SE050C2_ENC_KEY
|
|
#define MAC_KEY SE050C2_MAC_KEY
|
|
#define DEK_KEY SE050C2_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, SE050C2, 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;
|
|
}
|