Linux メモリ保護機能の実装 (mlock, MADV_DONTDUMP, MADV_WIPEONFORK)
セキュリティ強化のため、Linux 固有のメモリ保護機能を追加: ### 実装した保護機能 1. **mlock()** - スワップ防止 - センシティブなメモリをディスクへのスワップから保護 - 権限不足の場合は警告出力の上継続(フォールバック) 2. **MADV_DONTDUMP** - コアダンプ漏洩防止 - コアダンプ生成時にメモリ内容を除外 - プライベート鍵がダンプに含まれないようにする 3. **MADV_WIPEONFORK** - fork() 子プロセス漏洩防止 - fork() 後の子プロセスからメモリ内容を消去 - 子プロセスへの鍵漏洩を防止 ### 変更ファイル - src/se050_scp03.c - SCP03 コンテキストのメモリ保護 - src/se050_keystore.c - キーストアコンテキストのメモリ保護 ### 実装詳細 - Linux 環境でのみ有効(#ifdef __linux__) - 非 Linux プラットフォームではフォールバック - mlock 失敗時は警告のみ出力(処理継続) - madvise 失敗時はエラーログ出力(非致命的) ### 注意事項 - mlock には CAP_IPC_LOCK 権限または RLIMIT_MEMLOCK クォータが必要 - 権限不足の場合でも機能は動作(保護なしで継続) - 本番環境では適切な権限設定を推奨
This commit is contained in:
+4
-3
@@ -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;
|
||||
|
||||
Binary file not shown.
+83
-1
@@ -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 <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
/* Linux memory protection */
|
||||
#ifdef __linux__
|
||||
#include <sys/mman.h>
|
||||
#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);
|
||||
}
|
||||
|
||||
Binary file not shown.
@@ -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 <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
/* Linux memory protection */
|
||||
#ifdef __linux__
|
||||
#include <sys/mman.h>
|
||||
#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);
|
||||
}
|
||||
|
||||
Binary file not shown.
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user