嵌入式安全概述

随着 IoT 设备爆炸式增长,嵌入式系统安全已成为关乎国家安全、企业命脉和个人隐私的核心议题。据统计,2025 年全球 IoT 设备数量突破 300 亿台,而其中超过 60% 的设备存在严重安全漏洞。从智能家居摄像头被黑客入侵,到工业控制系统遭受勒索软件攻击,安全事件频发警示我们:嵌入式安全不再是可选项,而是必选项

本文深入探讨嵌入式安全开发的完整体系,涵盖安全启动、加密通信、安全存储、防攻击技术和安全开发生命周期,帮助开发者构建真正安全的嵌入式系统。

1.1 嵌入式安全威胁 landscape

威胁类型 典型攻击 影响 案例
固件篡改 恶意固件注入 设备被控制 Mirai 僵尸网络
数据窃取 内存 dump、总线嗅探 隐私泄露 医疗数据泄露
侧信道攻击 功耗分析、时序分析 密钥泄露 智能卡破解
物理攻击 探针、FIB、激光注入 系统突破 游戏机越狱
供应链攻击 恶意组件、后门植入 系统性风险 SolarWinds 事件

1.2 安全设计原则

嵌入式安全设计应遵循以下核心原则:

  1. 纵深防御(Defense in Depth):多层防护,单点失效不导致系统崩溃
  2. 最小权限(Least Privilege):每个组件只拥有完成任务所需的最小权限
  3. 失效安全(Fail Secure):系统故障时进入安全状态
  4. 安全默认配置(Secure by Default):出厂即安全,无需用户配置
  5. 安全更新(Secure Update):支持安全可靠的远程升级

安全启动(Secure Boot)

2.1 安全启动原理

安全启动的核心思想是信任链(Chain of Trust):从硬件固化的根信任开始,逐级验证每一级代码的完整性和真实性,确保只有可信代码能够执行。

┌─────────────────────────────────────────────────────────────┐
│                    安全启动信任链                            │
├─────────────────────────────────────────────────────────────┤
│  ┌─────────────┐                                            │
│  │ 硬件根信任   │  ← 固化在 ROM 中,不可篡改                  │
│  │ (Root of    │                                            │
│  │  Trust)     │                                            │
│  └──────┬──────┘                                            │
│         │ 验证签名                                           │
│         ▼                                                    │
│  ┌─────────────┐                                            │
│  │ Bootloader  │  ← 一级引导程序(验证二级引导)              │
│  │  Stage 1    │                                            │
│  └──────┬──────┘                                            │
│         │ 验证签名                                           │
│         ▼                                                    │
│  ┌─────────────┐                                            │
│  │ Bootloader  │  ← 二级引导程序(验证应用固件)              │
│  │  Stage 2    │                                            │
│  └──────┬──────┘                                            │
│         │ 验证签名                                           │
│         ▼                                                    │
│  ┌─────────────┐                                            │
│  │ 应用固件     │  ← 最终执行代码                            │
│  │ (Firmware)  │                                            │
│  └─────────────┘                                            │
└─────────────────────────────────────────────────────────────┘

2.2 加密算法选择

安全启动依赖非对称加密算法进行签名验证:

算法 密钥长度 签名大小 验证速度 推荐场景
RSA-2048 2048 位 256 字节 中等 通用场景
RSA-3072 3072 位 384 字节 较慢 高安全场景
ECDSA-P256 256 位 64 字节 资源受限
ECDSA-P384 384 位 96 字节 中等 平衡场景
Ed25519 256 位 64 字节 最快 推荐首选

2026 年推荐:优先选择 Ed25519 或 ECDSA-P256,在安全性和性能之间取得最佳平衡。

2.3 安全启动实现

// 安全启动验证流程(伪代码)
#include <mbedtls/rsa.h>
#include <mbedtls/sha256.h>
#include <mbedtls/pk.h>

// 公钥(固化在 Bootloader 中)
static const uint8_t public_key[] = {
    // Ed25519 公钥(64 字节)
    0x12, 0x34, 0x56, 0x78, ... 
};

// 验证固件签名
int verify_firmware_signature(const uint8_t *firmware, 
                               size_t firmware_size,
                               const uint8_t *signature,
                               size_t signature_size) {
    mbedtls_pk_context pk;
    mbedtls_pk_init(&pk);
    
    // 1. 加载公钥
    int ret = mbedtls_pk_parse_public_key(&pk, public_key, sizeof(public_key));
    if (ret != 0) {
        return -1;  // 公钥解析失败
    }
    
    // 2. 计算固件哈希(SHA-256)
    uint8_t hash[32];
    ret = mbedtls_sha256_ret(firmware, firmware_size, hash, 0);
    if (ret != 0) {
        mbedtls_pk_free(&pk);
        return -2;  // 哈希计算失败
    }
    
    // 3. 验证签名
    ret = mbedtls_pk_verify(&pk, MBEDTLS_MD_SHA256, 
                            hash, sizeof(hash),
                            signature, signature_size);
    
    mbedtls_pk_free(&pk);
    
    if (ret == 0) {
        return 0;  // 验证成功
    } else {
        return -3;  // 签名验证失败
    }
}

// 启动流程
void secure_boot(void) {
    firmware_header_t *header = (firmware_header_t*)FIRMWARE_ADDR;
    
    // 1. 验证头部魔数
    if (header->magic != FIRMWARE_MAGIC) {
        halt_system("Invalid firmware magic");
    }
    
    // 2. 验证签名
    if (verify_firmware_signature(header->payload, 
                                   header->payload_size,
                                   header->signature,
                                   header->sig_size) != 0) {
        halt_system("Signature verification failed");
    }
    
    // 3. 验证通过,跳转到应用固件
    jump_to_application(FIRMWARE_ADDR + header->header_size);
}

2.4 安全启动配置(STM32 示例)

// STM32H7 安全启动配置
void SecureBoot_Config(void) {
    // 1. 启用 Flash 读保护(RDP Level 2)
    FLASH_OBProgramInitTypeDef OBInit;
    OBInit.OptionType = OPTIONBYTE_RDP;
    OBInit.RDPLevel = OB_RDP_LEVEL_2;  // 最高级别,调试接口永久禁用
    HAL_FLASHEx_OBProgram(&OBInit);
    
    // 2. 配置 PCROP(专有代码读保护)
    OBInit.OptionType = OPTIONBYTE_PCROP;
    OBInit.PCROPConfig = PCROP_ZONE_A;
    OBInit.PCROPStartAddr = BOOTLOADER_END_ADDR;
    OBInit.PCROPEndAddr = FIRMWARE_START_ADDR;
    HAL_FLASHEx_OBProgram(&OBInit);
    
    // 3. 启用写保护
    OBInit.OptionType = OPTIONBYTE_WRP;
    OBInit.WRPArea = OB_WRPAREA_BANK1;
    OBInit.WRPStartOffset = 0;
    OBInit.WRPEndOffset = BOOTLOADER_PAGES - 1;
    HAL_FLASHEx_OBProgram(&OBInit);
    
    // 4. 锁定选项字节
    HAL_FLASH_OB_Launch();
}

加密通信

3.1 TLS/DTLS 协议选择

协议 传输层 特点 适用场景
TLS 1.3 TCP 最安全、低延迟 WiFi、以太网
DTLS 1.3 UDP 支持丢包、低开销 NB-IoT、LoRaWAN
mTLS TCP/UDP 双向认证 高安全场景

3.2 mTLS 双向认证实现

// mTLS 客户端配置(mbedTLS)
#include <mbedtls/ssl.h>
#include <mbedtls/ctr_drbg.h>
#include <mbedtls/entropy.h>

int setup_mtls_client(mbedtls_ssl_context *ssl,
                      const uint8_t *client_cert,
                      const uint8_t *client_key,
                      const uint8_t *ca_cert) {
    mbedtls_ssl_config conf;
    mbedtls_x509_crt cacert;
    mbedtls_x509_crt clicert;
    mbedtls_pk_context pkey;
    mbedtls_entropy_context entropy;
    mbedtls_ctr_drbg_context ctr_drbg;
    
    // 初始化
    mbedtls_ssl_config_init(&conf);
    mbedtls_x509_crt_init(&cacert);
    mbedtls_x509_crt_init(&clicert);
    mbedtls_pk_init(&pkey);
    mbedtls_entropy_init(&entropy);
    mbedtls_ctr_drbg_init(&ctr_drbg);
    
    // 1. 配置随机数生成器
    const char *pers = "mtls_client";
    mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy,
                          (const uint8_t *) pers, strlen(pers));
    
    // 2. 加载 CA 证书
    int ret = mbedtls_x509_crt_parse(&cacert, ca_cert, CA_CERT_LEN);
    if (ret != 0) return -1;
    
    // 3. 加载客户端证书
    ret = mbedtls_x509_crt_parse(&clicert, client_cert, CLIENT_CERT_LEN);
    if (ret != 0) return -2;
    
    // 4. 加载客户端私钥
    ret = mbedtls_pk_parse_key(&pkey, client_key, CLIENT_KEY_LEN, NULL, 0);
    if (ret != 0) return -3;
    
    // 5. 配置 SSL
    mbedtls_ssl_config_defaults(&conf,
        MBEDTLS_SSL_IS_CLIENT,
        MBEDTLS_SSL_TRANSPORT_STREAM,  // TLS
        MBEDTLS_SSL_PRESET_DEFAULT);
    
    // 6. 配置认证模式(强制双向认证)
    mbedtls_ssl_conf_authmode(&conf, MBEDTLS_SSL_VERIFY_REQUIRED);
    mbedtls_ssl_conf_ca_chain(&conf, &cacert, NULL);
    
    // 7. 配置客户端证书和私钥
    ret = mbedtls_ssl_conf_own_cert(&conf, &clicert, &pkey);
    if (ret != 0) return -4;
    
    // 8. 配置随机数生成器
    mbedtls_ssl_conf_rng(&conf, mbedtls_ctr_drbg_random, &ctr_drbg);
    
    // 9. 应用配置
    ret = mbedtls_ssl_setup(ssl, &conf);
    if (ret != 0) return -5;
    
    return 0;
}

3.3 轻量级加密协议

对于资源极度受限的设备,可考虑以下轻量级方案:

协议 密钥长度 RAM 占用 适用场景
ChaCha20-Poly1305 256 位 ~2KB ARM Cortex-M0/M3
AES-128-CCM 128 位 ~3KB 通用 IoT
Speck-Simon 64-128 位 ~1KB 超低功耗
// ChaCha20-Poly1305 加密示例
#include <chacha20poly1305.h>

void encrypt_message(const uint8_t *plaintext, size_t len,
                     const uint8_t *key, const uint8_t *nonce,
                     uint8_t *ciphertext, uint8_t *tag) {
    chacha20poly1305_state state;
    
    // 初始化
    chacha20poly1305_init(&state, key, 32);
    
    // 加密
    chacha20poly1305_encrypt(&state, nonce, plaintext, len,
                             ciphertext, tag);
    
    // 清理状态
    chacha20poly1305_cleanup(&state);
}

安全存储

4.1 安全存储架构

安全区域(TrustZone / Secure Enclave) 密钥存储 加密引擎 随机数生成 非安全区域(Normal World) 应用代码 文件系统 网络栈 安全调用(SMC)
安全存储架构图

4.2 密钥管理

// 密钥派生(PBKDF2)
#include <mbedtls/pkcs5.h>

void derive_key(const uint8_t *password, size_t pwd_len,
                const uint8_t *salt, size_t salt_len,
                uint8_t *derived_key, size_t key_len) {
    mbedtls_md_context_t md_ctx;
    mbedtls_md_init(&md_ctx);
    mbedtls_md_setup(&md_ctx, mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), 1);
    
    // PBKDF2-HMAC-SHA256,迭代 100000 次
    mbedtls_pkcs5_pbkdf2_hmac(&md_ctx, password, pwd_len,
                              salt, salt_len, 100000,
                              key_len, derived_key);
    
    mbedtls_md_free(&md_ctx);
}

// 安全存储密钥(加密后存储)
void store_encrypted_key(const uint8_t *key, size_t key_len,
                         const uint8_t *wrapping_key,
                         uint8_t *encrypted_key) {
    mbedtls_aes_context aes;
    mbedtls_aes_init(&aes);
    mbedtls_aes_setkey_enc(&aes, wrapping_key, 256);
    
    // AES-KW(密钥包裹)
    mbedtls_aes_wrap_key(&aes, key_len / 8, encrypted_key, key);
    
    mbedtls_aes_free(&aes);
}

4.3 安全元素(SE)集成

// 通过 I2C 访问安全元素(如 ATECC608A)
#include <i2c.h>
#include <atecc608a.h>

int se_generate_key(uint8_t slot_id, uint8_t *public_key) {
    // 1. 生成 ECC P256 密钥对
    uint8_t command[] = {0x47, 0x40, slot_id};  // GenKey 命令
    uint8_t response[67];
    
    i2c_write(ATECC_ADDR, command, sizeof(command));
    i2c_read(ATECC_ADDR, response, sizeof(response));
    
    // 2. 提取公钥
    memcpy(public_key, response + 1, 64);
    
    return 0;
}

int se_sign_data(uint8_t slot_id, const uint8_t *data, size_t len,
                 uint8_t *signature) {
    // 1. 计算 SHA-256 哈希
    uint8_t hash[32];
    mbedtls_sha256_ret(data, len, hash, 0);
    
    // 2. 使用 SE 签名
    uint8_t command[36] = {0x41, 0x4A, slot_id};
    memcpy(command + 3, hash, 32);
    
    i2c_write(ATECC_ADDR, command, sizeof(command));
    i2c_read(ATECC_ADDR, signature, 64);  // ECDSA 签名(R + S)
    
    return 0;
}

防攻击技术

5.1 侧信道攻击防护

(1)功耗分析攻击(DPA/SPA)

攻击原理:通过分析设备功耗变化推断密钥信息。

防护措施

// 恒定时间实现(避免条件分支泄露信息)
uint8_t constant_time_compare(const uint8_t *a, const uint8_t *b, size_t len) {
    uint8_t result = 0;
    
    for (size_t i = 0; i < len; i++) {
        result |= a[i] ^ b[i];  // 位运算,无条件分支
    }
    
    return (result == 0);  // 0 = 相等,1 = 不等
}

// 掩码技术(随机化中间值)
void masked_aes_encrypt(const uint8_t *input, uint8_t *output,
                        const uint8_t *key, const uint8_t *mask) {
    uint8_t masked_input[16];
    
    // 输入掩码
    for (int i = 0; i < 16; i++) {
        masked_input[i] = input[i] ^ mask[i];
    }
    
    // 加密(使用掩码密钥)
    aes_encrypt_masked(masked_input, output, key, mask);
    
    // 输出解掩码
    for (int i = 0; i < 16; i++) {
        output[i] ^= mask[i];
    }
}

(2)时序攻击防护

// 恒定时间字符串比较(防止时序攻击)
int secure_strcmp(const char *a, const char *b) {
    volatile const char *pa = (volatile const char *)a;
    volatile const char *pb = (volatile const char *)b;
    volatile size_t i = 0;
    volatile unsigned char result = 0;
    
    while (pa[i] != '\0' || pb[i] != '\0') {
        result |= pa[i] ^ pb[i];
        i++;
    }
    
    return (result == 0) ? 0 : 1;
}

5.2 物理攻击防护

攻击方式 描述 防护措施
探针攻击 物理探针读取总线信号 总线加密、屏蔽层
FIB 攻击 聚焦离子束修改电路 主动屏蔽层、传感器
激光注入 激光诱导故障 光传感器、金属层
温度攻击 极端温度诱导故障 温度传感器、自毁
// 主动屏蔽层检测
void check_active_shield(void) {
    uint32_t shield_pattern = READ_SHIELD_REGISTER();
    
    if (shield_pattern != EXPECTED_PATTERN) {
        // 屏蔽层被破坏,清除敏感数据
        secure_erase_keys();
        system_halt();
    }
}

// 温度监控
void check_temperature(void) {
    int32_t temp = read_temperature_sensor();
    
    if (temp < -20 || temp > 85) {
        // 超出正常工作温度,可能遭受攻击
        secure_erase_keys();
        system_halt();
    }
}

5.3 防重放攻击

// 时间戳 + 随机数防重放
typedef struct {
    uint32_t timestamp;
    uint8_t nonce[16];
    uint8_t payload[];
} secure_message_t;

void send_secure_message(const uint8_t *payload, size_t len) {
    secure_message_t *msg = pvPortMalloc(sizeof(secure_message_t) + len);
    
    // 1. 设置时间戳(防止旧消息重放)
    msg->timestamp = get_secure_timestamp();
    
    // 2. 生成随机数(防止同时间戳重放)
    generate_random_nonce(msg->nonce, sizeof(msg->nonce));
    
    // 3. 复制 payload
    memcpy(msg->payload, payload, len);
    
    // 4. 计算 MAC
    uint8_t mac[16];
    calculate_hmac(msg, sizeof(secure_message_t) + len, mac);
    
    // 5. 发送
    transmit(msg, sizeof(secure_message_t) + len, mac, sizeof(mac));
    
    vPortFree(msg);
}

int verify_message(const secure_message_t *msg, const uint8_t *mac) {
    // 1. 验证时间戳(拒绝 5 分钟前的消息)
    uint32_t current_time = get_secure_timestamp();
    if (current_time - msg->timestamp > 300) {
        return -1;  // 消息过期
    }
    
    // 2. 检查随机数是否已使用(防重放)
    if (is_nonce_used(msg->nonce)) {
        return -2;  // 重放攻击
    }
    
    // 3. 验证 MAC
    uint8_t expected_mac[16];
    calculate_hmac(msg, sizeof(secure_message_t) + msg->len, expected_mac);
    
    if (constant_time_compare(mac, expected_mac, 16) != 0) {
        return -3;  // MAC 验证失败
    }
    
    // 4. 标记随机数为已使用
    mark_nonce_as_used(msg->nonce);
    
    return 0;
}

安全开发生命周期(SDL)

6.1 SDL 流程

┌─────────────────────────────────────────────────────────────┐
│              安全开发生命周期(SDL)                         │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  ┌───────────┐                                              │
│  │ 1. 培训   │ ← 所有开发人员接受安全培训                    │
│  └─────┬─────┘                                              │
│        │                                                    │
│  ┌─────▼─────┐                                              │
│  │ 2. 需求   │ ← 识别安全需求、合规要求                      │
│  └─────┬─────┘                                              │
│        │                                                    │
│  ┌─────▼─────┐                                              │
│  │ 3. 设计   │ ← 威胁建模、安全架构设计                      │
│  └─────┬─────┘                                              │
│        │                                                    │
│  ┌─────▼─────┐                                              │
│  │ 4. 实现   │ ← 安全编码规范、代码审查                      │
│  └─────┬─────┘                                              │
│        │                                                    │
│  ┌─────▼─────┐                                              │
│  │ 5. 验证   │ ← 渗透测试、模糊测试、静态分析                │
│  └─────┬─────┘                                              │
│        │                                                    │
│  ┌─────▼─────┐                                              │
│  │ 6. 发布   │ ← 安全配置、漏洞响应计划                      │
│  └─────┬─────┘                                              │
│        │                                                    │
│  ┌─────▼─────┐                                              │
│  │ 7. 响应   │ ← 漏洞披露、补丁发布、OTA 更新                 │
│  └───────────┘                                              │
│                                                             │
└─────────────────────────────────────────────────────────────┘

6.2 威胁建模(STRIDE)

威胁类型 描述 示例 缓解措施
Spoofing(欺骗) 冒充合法实体 伪造设备 ID 双向认证
Tampering(篡改) 修改数据/代码 固件篡改 数字签名
Repudiation(抵赖) 否认已执行操作 日志删除 审计日志
Information Disclosure(信息泄露) 未授权数据访问 密钥泄露 加密存储
Denial of Service(拒绝服务) 使服务不可用 DDoS 攻击 限流、看门狗
Elevation of Privilege(权限提升) 获取未授权权限 缓冲区溢出 边界检查

6.3 安全编码规范

// 1. 始终检查返回值
int ret = mbedtls_ssl_read(ssl, buf, len);
if (ret < 0) {
    if (ret != MBEDTLS_ERR_SSL_WANT_READ &&
        ret != MBEDTLS_ERR_SSL_WANT_WRITE) {
        // 处理错误
        handle_error(ret);
    }
}

// 2. 边界检查(防止缓冲区溢出)
void safe_copy(char *dest, const char *src, size_t dest_size) {
    if (dest == NULL || src == NULL || dest_size == 0) {
        return;
    }
    
    size_t src_len = strlen(src);
    size_t copy_len = (src_len < dest_size - 1) ? src_len : dest_size - 1;
    
    memcpy(dest, src, copy_len);
    dest[copy_len] = '\0';
}

// 3. 初始化所有变量
uint8_t key[32] = {0};  // 显式初始化为 0
mbedtls_aes_context aes;
mbedtls_aes_init(&aes);  // 初始化结构体

// 4. 及时清理敏感数据
void process_key(const uint8_t *key, size_t len) {
    uint8_t temp[32];
    
    // 处理密钥
    encrypt_data(key, temp);
    
    // 清理临时数据
    mbedtls_zeroize(temp, sizeof(temp));
}

// 5. 使用安全的随机数生成器
void generate_secure_random(uint8_t *buf, size_t len) {
    // 不要使用 rand()!
    // 使用加密安全的 RNG
    mbedtls_ctr_drbg_random(&ctr_drbg, buf, len);
}

6.4 安全测试清单

测试类型 工具 频率
静态分析 Coverity、SonarQube 每次提交
动态分析 Valgrind、AddressSanitizer 每次构建
模糊测试 AFL、libFuzzer 每周
渗透测试 手动 + 自动化 每季度
代码审计 第三方安全公司 每年

安全认证与合规

7.1 常见安全认证

认证 适用领域 级别 成本
Common Criteria 通用 EAL1-EAL7
FIPS 140-2/3 美国政府 Level 1-4
PSA Certified IoT Level 1-3
SESIP IoT Level 1-3
IEC 62443 工业 SL1-SL4
ISO/SAE 21434 汽车 -

7.2 合规要求

法规 适用范围 要求
GDPR 欧盟 数据保护、隐私权
CCPA 美国加州 消费者隐私
网络安全法 中国 关键信息基础设施保护
ETSI EN 303 645 欧盟 IoT 基线安全要求
NIST IR 8259 美国 IoT 网络安全能力

总结

嵌入式安全开发的核心要点:

  1. 安全启动:建立信任链,确保只有可信代码执行
  2. 加密通信:使用 TLS/mTLS 保护数据传输
  3. 安全存储:加密敏感数据,使用安全元素
  4. 防攻击:侧信道防护、物理防护、防重放
  5. SDL:贯穿整个开发周期的安全实践
  6. 合规认证:满足行业标准和法规要求

安全不是一蹴而就的,而是一个持续的过程。从设计阶段就考虑安全,在开发过程中践行安全编码,在发布后进行持续监控和更新,才能构建真正安全的嵌入式系统。


本文基于 NIST、ENISA 安全指南、ARM PSA 认证框架和实际项目经验整理,结合 2026 年最新安全威胁态势编写。

参考资料

  1. NIST Cybersecurity for IoT Program - https://www.nist.gov/cybersecurity-iot
  2. ARM Platform Security Architecture (PSA) - https://developer.arm.com/Architecture/Security-Features/Platform-Security-Architecture
  3. Embedded Systems Security: Practical Strategies for Success (2025)
  4. IoT Security: Foundation to Cloud-to-Device (2026)
  5. mbedTLS Documentation - https://tls.mbed.org/
  6. Common Criteria Portal - https://www.commoncriteriaportal.org/