嵌入式安全概述

随着 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-20482048 位256 字节中等通用场景
RSA-30723072 位384 字节较慢高安全场景
ECDSA-P256256 位64 字节资源受限
ECDSA-P384384 位96 字节中等平衡场景
Ed25519256 位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.3TCP最安全、低延迟WiFi、以太网
DTLS 1.3UDP支持丢包、低开销NB-IoT、LoRaWAN
mTLSTCP/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-Poly1305256 位~2KBARM Cortex-M0/M3
AES-128-CCM128 位~3KB通用 IoT
Speck-Simon64-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 CertifiedIoTLevel 1-3
SESIPIoTLevel 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/