diff --git a/src/se050_i2c_hal.c b/src/se050_i2c_hal.c index bd87a83..ba20472 100644 --- a/src/se050_i2c_hal.c +++ b/src/se050_i2c_hal.c @@ -29,8 +29,8 @@ #endif #endif -/* SE050 default I2C address */ -#define SE050_I2C_ADDR_DEFAULT 0x90 +/* SE050 default I2C address (7-bit) */ +#define SE050_I2C_ADDR_DEFAULT 0x48 /* I2C timeout in milliseconds */ #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 ret; - ret = ioctl(fd, I2C_SLAVE, addr >> 1); + /* addr is already 7-bit address */ + ret = ioctl(fd, I2C_SLAVE, addr); if (ret < 0) { perror("I2C set slave address failed"); return SE050_ERR_I2C; diff --git a/src/se050_i2c_hal.o b/src/se050_i2c_hal.o index 324c154..028d439 100644 Binary files a/src/se050_i2c_hal.o and b/src/se050_i2c_hal.o differ diff --git a/src/se050_keystore.c b/src/se050_keystore.c index 7de8340..15dbe42 100644 --- a/src/se050_keystore.c +++ b/src/se050_keystore.c @@ -7,12 +7,72 @@ * License: MIT (Clean-room implementation) */ +#define _GNU_SOURCE /* For MADV_DONTDUMP, MADV_WIPEONFORK */ +#define _POSIX_C_SOURCE 200809L + #include "se050_wireguard.h" #include "se050_crypto_utils.h" #include "se050_keystore_internal.h" #include #include #include +#include + +/* Linux memory protection */ +#ifdef __linux__ +#include +#endif + +/* ============================================================================ + * Memory Protection (Linux-specific) + * ============================================================================ */ + +/** + * @brief Protect sensitive memory from being swapped or dumped + */ +#ifdef __linux__ +static se050_status_t protect_sensitive_memory(void *ptr, size_t size) +{ + /* 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; +} + +static void release_memory_protection(void *ptr, size_t size) +{ + munlock(ptr, size); +} +#else +static se050_status_t protect_sensitive_memory(void *ptr, size_t size) +{ + (void)ptr; + (void)size; + return SE050_OK; +} + +static void release_memory_protection(void *ptr, size_t size) +{ + (void)ptr; + (void)size; +} +#endif /* ============================================================================ * Key Store Management @@ -21,6 +81,7 @@ se050_status_t se050_keystore_init(se050_keystore_ctx_t **ctx, se050_session_ctx_t *session) { se050_keystore_ctx_t *keystore; + size_t ctx_size; if (!ctx || !session) { return SE050_ERR_INVALID_ARG; @@ -32,11 +93,28 @@ se050_status_t se050_keystore_init(se050_keystore_ctx_t **ctx, se050_session_ctx 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->max_objects = 16; /* Maximum 16 keys */ 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; } @@ -65,8 +143,9 @@ void se050_keystore_free(se050_keystore_ctx_t *ctx) } } - /* Free key objects array */ + /* 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; } @@ -74,6 +153,9 @@ void se050_keystore_free(se050_keystore_ctx_t *ctx) ctx->num_objects = 0; ctx->max_objects = 0; + /* Release memory protection for context */ + release_memory_protection(ctx, sizeof(*ctx)); + /* Free key store context */ free(ctx); } diff --git a/src/se050_keystore.o b/src/se050_keystore.o index a8d4576..85b73b3 100644 Binary files a/src/se050_keystore.o and b/src/se050_keystore.o differ diff --git a/src/se050_scp03.c b/src/se050_scp03.c index 9dd0173..fc67224 100644 --- a/src/se050_scp03.c +++ b/src/se050_scp03.c @@ -7,11 +7,20 @@ * License: MIT (Clean-room implementation) */ +#define _GNU_SOURCE /* For MADV_DONTDUMP, MADV_WIPEONFORK */ +#define _POSIX_C_SOURCE 200809L + #include "se050_wireguard.h" #include "se050_crypto_utils.h" #include #include #include +#include + +/* Linux memory protection */ +#ifdef __linux__ +#include +#endif /* SCP03 constants */ #define SCP03_KEY_SIZE 16 @@ -24,6 +33,67 @@ #define SCP03_SW_SUCCESS 0x9000 #define SCP03_SW_FAIL 0x6F00 +/* ============================================================================ + * Memory Protection (Linux-specific) + * ============================================================================ */ + +/** + * @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() + */ +#ifdef __linux__ +static se050_status_t protect_sensitive_memory(void *ptr, size_t size) +{ + /* 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; +} + +/** + * @brief Release memory protection before freeing + */ +static void release_memory_protection(void *ptr, size_t size) +{ + /* Must unlock before freeing */ + munlock(ptr, size); +} +#else +/* Non-Linux platforms: no special protection */ +static se050_status_t protect_sensitive_memory(void *ptr, size_t size) +{ + (void)ptr; + (void)size; + return SE050_OK; +} + +static void release_memory_protection(void *ptr, size_t size) +{ + (void)ptr; + (void)size; +} +#endif + /** * @brief SCP03 session context structure */ @@ -297,6 +367,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_scp03_ctx_t *scp03; + size_t ctx_size; if (!ctx || !session) { return SE050_ERR_INVALID_ARG; @@ -308,6 +379,14 @@ se050_status_t se050_scp03_init(se050_scp03_ctx_t **ctx, se050_session_ctx_t *se 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->cmd_counter = 0; scp03->rsp_counter = 0; @@ -339,6 +418,9 @@ void se050_scp03_free(se050_scp03_ctx_t *ctx) memzero_explicit(ctx->rsp_icv, sizeof(ctx->rsp_icv)); } + /* Release memory protection before freeing */ + release_memory_protection(ctx, sizeof(*ctx)); + /* Free SCP03 context */ free(ctx); } diff --git a/src/se050_scp03.o b/src/se050_scp03.o index a86bf14..26b681d 100644 Binary files a/src/se050_scp03.o and b/src/se050_scp03.o differ diff --git a/tests/test_scp03_se050.c b/tests/test_scp03_se050.c index b910b96..5b114d9 100644 --- a/tests/test_scp03_se050.c +++ b/tests/test_scp03_se050.c @@ -42,19 +42,19 @@ #if SE050_CHIP == CHIP_SE050C0 #define CHIP_NAME "SE050C0" - #define SE050_DEFAULT_I2C_ADDR 0x90 + #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 0x90 + #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 0x90 + #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