163fad68a7
- ACTIVE_*マクロをシンプル化:チップ選択で ENC/MAC/DEK 全体が選択 - test_scp03_hardware.c: SE050C0 キーに整理 - SE050E0/E1 削除(実在しないため) - 対応チップ:SE050C0, SE050C1, SE050E2 のみ 変更前: ACTIVE_ENC_KEY = 条件付きマクロ 変更後: ENC_KEY = 選択チップのキー MAC_KEY = 選択チップのキー DEK_KEY = 選択チップのキー
460 lines
14 KiB
C
460 lines
14 KiB
C
/**
|
|
* @file test_scp03_hardware.c
|
|
* @brief Platform SCP03 Hardware Test with SE050
|
|
*
|
|
* Tests Platform SCP03 communication with actual SE050 hardware
|
|
* using SE050C0 default keys.
|
|
*
|
|
* License: MIT (Clean-room implementation)
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <stdint.h>
|
|
#include "se050_wireguard.h"
|
|
#include "se050_crypto_utils.h"
|
|
|
|
/* SE050C0 Default Platform SCP03 Keys */
|
|
static const uint8_t SE050C0_ENC_KEY[16] = {
|
|
0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF,
|
|
0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF
|
|
};
|
|
|
|
static const uint8_t SE050C0_MAC_KEY[16] = {
|
|
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
|
|
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10
|
|
};
|
|
|
|
static const uint8_t SE050C0_DEK_KEY[16] = {
|
|
0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
|
|
0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF
|
|
};
|
|
|
|
/* Test result counters */
|
|
static int test_passed = 0;
|
|
static int test_failed = 0;
|
|
|
|
/* Test macros */
|
|
#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 0x%04x, got 0x%04x)\n", msg, (uint16_t)(b), (uint16_t)(a)); \
|
|
test_failed++; \
|
|
} \
|
|
} while(0)
|
|
|
|
/**
|
|
* @brief Print hex data
|
|
*/
|
|
static void print_hex(const char *label, const uint8_t *data, size_t len)
|
|
{
|
|
printf("%s: ", label);
|
|
for (size_t i = 0; i < len && i < 32; i++) {
|
|
printf("%02x ", data[i]);
|
|
}
|
|
if (len > 32) printf("...");
|
|
printf("\n");
|
|
}
|
|
|
|
/* ============================================================================
|
|
* Mock I2C HAL for Testing Without Hardware
|
|
* ============================================================================ */
|
|
|
|
typedef struct {
|
|
se050_i2c_hal_t hal;
|
|
uint8_t se050_response[256];
|
|
size_t response_len;
|
|
int should_fail;
|
|
} mock_i2c_ctx_t;
|
|
|
|
static mock_i2c_ctx_t *g_mock_ctx = NULL;
|
|
|
|
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;
|
|
|
|
if (!mock || !buffer || length <= 0) {
|
|
return -1;
|
|
}
|
|
|
|
if (mock->should_fail) {
|
|
return -1;
|
|
}
|
|
|
|
size_t copy_len = (size_t)length < mock->response_len ? (size_t)length : mock->response_len;
|
|
memcpy(buffer, mock->se050_response, copy_len);
|
|
|
|
if (copy_len < (size_t)length) {
|
|
buffer[copy_len] = 0x90;
|
|
buffer[copy_len + 1] = 0x00;
|
|
copy_len += 2;
|
|
}
|
|
|
|
return (int)copy_len;
|
|
}
|
|
|
|
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;
|
|
|
|
if (!mock || !buffer || length <= 0) {
|
|
return -1;
|
|
}
|
|
|
|
if (mock->should_fail) {
|
|
return -1;
|
|
}
|
|
|
|
printf("[MOCK I2C] Write %d bytes\n", length);
|
|
return length;
|
|
}
|
|
|
|
static void mock_i2c_init(mock_i2c_ctx_t *mock, const char *dev_path)
|
|
{
|
|
memset(mock, 0, sizeof(*mock));
|
|
mock->hal.handle = (void *)dev_path;
|
|
mock->hal.slave_addr = 0x90;
|
|
mock->hal.dev_path = dev_path;
|
|
mock->response_len = 0;
|
|
mock->should_fail = 0;
|
|
g_mock_ctx = mock;
|
|
}
|
|
|
|
static void mock_i2c_set_response(mock_i2c_ctx_t *mock, const uint8_t *response, size_t len)
|
|
{
|
|
if (len > sizeof(mock->se050_response)) {
|
|
len = sizeof(mock->se050_response);
|
|
}
|
|
memcpy(mock->se050_response, response, len);
|
|
mock->response_len = len;
|
|
}
|
|
|
|
/* ============================================================================
|
|
* Test Case 1: Key Validation
|
|
*/
|
|
static void test_keys(void)
|
|
{
|
|
printf("\n=== Test 1: SE050C0 Key Validation ===\n");
|
|
|
|
TEST_ASSERT_EQ(sizeof(SE050C0_ENC_KEY), 16, "ENC key should be 16 bytes");
|
|
TEST_ASSERT_EQ(sizeof(SE050C0_MAC_KEY), 16, "MAC key should be 16 bytes");
|
|
TEST_ASSERT_EQ(sizeof(SE050C0_DEK_KEY), 16, "DEK key should be 16 bytes");
|
|
|
|
print_hex("SE050C0 ENC Key", SE050C0_ENC_KEY, 16);
|
|
print_hex("SE050C0 MAC Key", SE050C0_MAC_KEY, 16);
|
|
print_hex("SE050C0 DEK Key", SE050C0_DEK_KEY, 16);
|
|
|
|
TEST_ASSERT(1, "SE050C0 keys loaded");
|
|
}
|
|
|
|
/* ============================================================================
|
|
* Test Case 2: SCP03 with SE050C0 Keys
|
|
*/
|
|
static void test_scp03_se050c0_keys(void)
|
|
{
|
|
printf("\n=== Test 2: SCP03 with SE050C0 Keys ===\n");
|
|
|
|
se050_session_ctx_t *session = NULL;
|
|
mock_i2c_ctx_t mock;
|
|
|
|
mock_i2c_init(&mock, "/dev/i2c-1-mock");
|
|
|
|
se050_status_t status = se050_session_create(&session, &mock.hal);
|
|
TEST_ASSERT_EQ(status, SE050_OK, "Session creation");
|
|
|
|
status = se050_session_scp03_init(session);
|
|
TEST_ASSERT_EQ(status, SE050_OK, "SCP03 initialization");
|
|
|
|
status = se050_session_scp03_set_keys(session,
|
|
SE050C0_ENC_KEY,
|
|
SE050C0_MAC_KEY,
|
|
SE050C0_DEK_KEY);
|
|
TEST_ASSERT_EQ(status, SE050_OK, "Set SE050C0 keys");
|
|
|
|
se050_session_delete(session);
|
|
TEST_ASSERT(1, "SCP03 with SE050C0 keys completed");
|
|
}
|
|
|
|
/* ============================================================================
|
|
* Test Case 3: SCP03 Command Encryption
|
|
*/
|
|
static void test_scp03_encrypt(void)
|
|
{
|
|
printf("\n=== Test 3: SCP03 Command Encryption ===\n");
|
|
|
|
se050_session_ctx_t *session = NULL;
|
|
mock_i2c_ctx_t mock;
|
|
|
|
mock_i2c_init(&mock, "/dev/i2c-1-mock");
|
|
|
|
se050_status_t status = se050_session_create(&session, &mock.hal);
|
|
TEST_ASSERT_EQ(status, SE050_OK, "Session creation");
|
|
|
|
status = se050_session_scp03_init(session);
|
|
TEST_ASSERT_EQ(status, SE050_OK, "SCP03 initialization");
|
|
|
|
status = se050_session_scp03_set_keys(session,
|
|
SE050C0_ENC_KEY,
|
|
SE050C0_MAC_KEY,
|
|
SE050C0_DEK_KEY);
|
|
TEST_ASSERT_EQ(status, SE050_OK, "Set SE050C0 keys");
|
|
|
|
uint8_t cmd[64];
|
|
size_t cmd_len = 6;
|
|
|
|
cmd[0] = 0x80;
|
|
cmd[1] = 0x01;
|
|
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, "Command encryption");
|
|
TEST_ASSERT(cmd_len > 6, "Encrypted command should be padded");
|
|
|
|
print_hex("Encrypted Command", cmd, cmd_len < 32 ? cmd_len : 32);
|
|
|
|
se050_session_delete(session);
|
|
}
|
|
|
|
/* ============================================================================
|
|
* Test Case 4: SCP03 Full Flow Simulation
|
|
*/
|
|
static void test_scp03_full_flow(void)
|
|
{
|
|
printf("\n=== Test 4: SCP03 Full Flow Simulation ===\n");
|
|
|
|
se050_session_ctx_t *session = NULL;
|
|
mock_i2c_ctx_t mock;
|
|
|
|
mock_i2c_init(&mock, "/dev/i2c-1-mock");
|
|
|
|
se050_status_t status = se050_session_create(&session, &mock.hal);
|
|
TEST_ASSERT_EQ(status, SE050_OK, "Step 1: Session creation");
|
|
|
|
status = se050_session_scp03_init(session);
|
|
TEST_ASSERT_EQ(status, SE050_OK, "Step 2: SCP03 initialization");
|
|
|
|
status = se050_session_scp03_set_keys(session,
|
|
SE050C0_ENC_KEY,
|
|
SE050C0_MAC_KEY,
|
|
SE050C0_DEK_KEY);
|
|
TEST_ASSERT_EQ(status, SE050_OK, "Step 3: Set SE050C0 keys");
|
|
|
|
uint8_t cmd[64];
|
|
size_t cmd_len = 6;
|
|
cmd[0] = 0x80;
|
|
cmd[1] = 0x70;
|
|
cmd[2] = 0x00;
|
|
cmd[3] = 0x00;
|
|
|
|
status = se050_session_scp03_encrypt(session, cmd, &cmd_len);
|
|
TEST_ASSERT_EQ(status, SE050_OK, "Step 4: Encrypt command");
|
|
|
|
uint8_t response[32] = {
|
|
0x00, 0x01, 0x02, 0x03,
|
|
0x90, 0x00
|
|
};
|
|
mock_i2c_set_response(&mock, response, sizeof(response));
|
|
|
|
uint8_t rsp[64];
|
|
size_t rsp_len = sizeof(rsp);
|
|
|
|
int bytes_read = se050_i2c_read_mock(&mock.hal, rsp, (int)rsp_len);
|
|
TEST_ASSERT(bytes_read > 0, "Step 5: I2C read response");
|
|
|
|
rsp_len = (size_t)bytes_read;
|
|
|
|
uint16_t sw = se050_session_scp03_decrypt(session, cmd_len, rsp, &rsp_len);
|
|
TEST_ASSERT_EQ(sw, 0x9000, "Step 6: Decrypt response");
|
|
|
|
print_hex("Decrypted Response", rsp, rsp_len < 32 ? rsp_len : 32);
|
|
|
|
se050_session_delete(session);
|
|
TEST_ASSERT(1, "Step 7: Full flow completed");
|
|
}
|
|
|
|
/* ============================================================================
|
|
* Test Case 5: Key File
|
|
*/
|
|
static void test_keys_file(void)
|
|
{
|
|
printf("\n=== Test 5: SE050C0 Keys File ===\n");
|
|
|
|
const char *key_file = "/tmp/se050c0_keys.bin";
|
|
FILE *fp = fopen(key_file, "wb");
|
|
TEST_ASSERT(fp != NULL, "Create key file");
|
|
|
|
fwrite(SE050C0_ENC_KEY, 1, 16, fp);
|
|
fwrite(SE050C0_MAC_KEY, 1, 16, fp);
|
|
fwrite(SE050C0_DEK_KEY, 1, 16, fp);
|
|
fclose(fp);
|
|
|
|
se050_session_ctx_t *session = NULL;
|
|
se050_scp03_ctx_t *scp03 = NULL;
|
|
mock_i2c_ctx_t mock;
|
|
|
|
mock_i2c_init(&mock, "/dev/i2c-1-mock");
|
|
|
|
se050_status_t status = se050_session_create(&session, &mock.hal);
|
|
TEST_ASSERT_EQ(status, SE050_OK, "Session creation");
|
|
|
|
status = se050_session_scp03_init(session);
|
|
TEST_ASSERT_EQ(status, SE050_OK, "SCP03 initialization");
|
|
|
|
status = se050_scp03_init(&scp03, session);
|
|
TEST_ASSERT_EQ(status, SE050_OK, "SCP03 context creation");
|
|
|
|
status = se050_scp03_load_keys_from_file(scp03, key_file);
|
|
TEST_ASSERT_EQ(status, SE050_OK, "Load SE050C0 keys from file");
|
|
|
|
se050_scp03_free(scp03);
|
|
se050_session_delete(session);
|
|
remove(key_file);
|
|
TEST_ASSERT(1, "Key file test completed");
|
|
}
|
|
|
|
/* ============================================================================
|
|
* Test Case 6: Multiple Cycles
|
|
*/
|
|
static void test_multiple_cycles(void)
|
|
{
|
|
printf("\n=== Test 6: Multiple Command/Response Cycles ===\n");
|
|
|
|
se050_session_ctx_t *session = NULL;
|
|
mock_i2c_ctx_t mock;
|
|
|
|
mock_i2c_init(&mock, "/dev/i2c-1-mock");
|
|
|
|
se050_status_t status = se050_session_create(&session, &mock.hal);
|
|
TEST_ASSERT_EQ(status, SE050_OK, "Session creation");
|
|
|
|
status = se050_session_scp03_init(session);
|
|
TEST_ASSERT_EQ(status, SE050_OK, "SCP03 initialization");
|
|
|
|
status = se050_session_scp03_set_keys(session,
|
|
SE050C0_ENC_KEY,
|
|
SE050C0_MAC_KEY,
|
|
SE050C0_DEK_KEY);
|
|
TEST_ASSERT_EQ(status, SE050_OK, "Set SE050C0 keys");
|
|
|
|
for (int i = 0; i < 3; i++) {
|
|
uint8_t cmd[64];
|
|
size_t cmd_len = 6;
|
|
cmd[0] = 0x80;
|
|
cmd[1] = 0x01 + i;
|
|
cmd[2] = 0x00;
|
|
cmd[3] = 0x00;
|
|
|
|
status = se050_session_scp03_encrypt(session, cmd, &cmd_len);
|
|
TEST_ASSERT_EQ(status, SE050_OK, "Encrypt cycle");
|
|
|
|
uint8_t response[16] = {0x90, 0x00};
|
|
mock_i2c_set_response(&mock, response, sizeof(response));
|
|
|
|
uint8_t rsp[64];
|
|
size_t rsp_len = sizeof(rsp);
|
|
int bytes_read = se050_i2c_read_mock(&mock.hal, rsp, (int)rsp_len);
|
|
rsp_len = (size_t)bytes_read;
|
|
|
|
uint16_t sw = se050_session_scp03_decrypt(session, cmd_len, rsp, &rsp_len);
|
|
TEST_ASSERT_EQ(sw, 0x9000, "Decrypt cycle");
|
|
}
|
|
|
|
se050_session_delete(session);
|
|
TEST_ASSERT(1, "Multiple cycles completed");
|
|
}
|
|
|
|
/* ============================================================================
|
|
* Test Case 7: Counter Increment
|
|
*/
|
|
static void test_counter_increment(void)
|
|
{
|
|
printf("\n=== Test 7: SCP03 Counter Increment ===\n");
|
|
|
|
se050_session_ctx_t *session = NULL;
|
|
mock_i2c_ctx_t mock;
|
|
|
|
mock_i2c_init(&mock, "/dev/i2c-1-mock");
|
|
|
|
se050_status_t status = se050_session_create(&session, &mock.hal);
|
|
TEST_ASSERT_EQ(status, SE050_OK, "Session creation");
|
|
|
|
status = se050_session_scp03_init(session);
|
|
TEST_ASSERT_EQ(status, SE050_OK, "SCP03 initialization");
|
|
|
|
status = se050_session_scp03_set_keys(session,
|
|
SE050C0_ENC_KEY,
|
|
SE050C0_MAC_KEY,
|
|
SE050C0_DEK_KEY);
|
|
TEST_ASSERT_EQ(status, SE050_OK, "Set SE050C0 keys");
|
|
|
|
for (int i = 0; i < 5; i++) {
|
|
uint8_t cmd[64];
|
|
size_t cmd_len = 4;
|
|
cmd[0] = 0x80;
|
|
cmd[1] = 0x01;
|
|
cmd[2] = 0x00;
|
|
cmd[3] = (uint8_t)i;
|
|
|
|
status = se050_session_scp03_encrypt(session, cmd, &cmd_len);
|
|
TEST_ASSERT_EQ(status, SE050_OK, "Encrypt cycle");
|
|
}
|
|
|
|
se050_session_delete(session);
|
|
TEST_ASSERT(1, "Counter increment verified");
|
|
}
|
|
|
|
/* ============================================================================
|
|
* Main Test Runner
|
|
*/
|
|
int main(int argc, char *argv[])
|
|
{
|
|
(void)argc; (void)argv;
|
|
|
|
printf("========================================\n");
|
|
printf("Platform SCP03 Hardware Test Suite\n");
|
|
printf("SE050C0 Keys\n");
|
|
printf("========================================\n");
|
|
|
|
test_keys();
|
|
test_scp03_se050c0_keys();
|
|
test_scp03_encrypt();
|
|
test_scp03_full_flow();
|
|
test_keys_file();
|
|
test_multiple_cycles();
|
|
test_counter_increment();
|
|
|
|
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! SE050C0 keys verified.\n");
|
|
}
|
|
|
|
return test_failed > 0 ? 1 : 0;
|
|
}
|