Dashboard/Issues/OH-2026-HUKS-001
SubmittedCWE-321 — Use of Hard-coded Cryptographic Key

HUKS 设备认证签名路径硬编码 RSA-2048 私钥

View Upstream Issuegitcode.com/openharmony/security_huks/issues/1529
CWE:CWE-321 — Use of Hard-coded Cryptographic Key
Repository:security_huks
Date:2026-04-29
Reporter:Zirui

漏洞编号:

CWE-321 (Use of Hard-coded Cryptographic Key)

漏洞归属组件

漏洞归属版本

CVSS V3.0分值

漏洞简述

涉及文件:

  • services/huks_standard/huks_engine/main/device_cert_manager/include/dcm_certs_and_key.h(密钥定义)
  • services/huks_standard/huks_engine/main/device_cert_manager/src/dcm_attest.c(签名路径)
  • services/huks_standard/huks_engine/main/core/src/hks_core_service_key_attest.c(公共入口)

完整调用链

Step 1 — 公共入口:HksCoreAttestKey

// hks_core_service_key_attest.c:73 — 公共 API 入口
int32_t HksCoreAttestKey(const struct HksBlob *key, const struct HksParamSet *paramSet, ...) {
    // line 102: 读取 HKS_TAG_ATTESTATION_MODE 参数
    // line 110: 若为 ANONYMOUS → CreateAttestCertChain(true, ...)
    // line 112: 否则 → CreateAttestCertChain(false, ...)  ← 默认路径,使用 RSA 密钥
}

默认路径(非匿名认证)传入 isAnonAttest = false

Step 2 — 构建认证规范,加载硬编码密钥

// dcm_attest.c:1419-1437 — GetCertAndKey()
static int32_t GetCertAndKey(struct HksAttestSpec *attestSpec) {
    int32_t ret;
    if (!attestSpec->isAnonAttest) {
        ret = GetCertOrKey(HKS_DEVICE_CERT, &attestSpec->devCert);  // line 1423: 加载设备证书
        HKS_IF_NOT_SUCC_LOGE_RETURN(ret, ret, "get devCert fail")

        ret = GetCertOrKey(HKS_DEVICE_KEY, &attestSpec->devKey);    // line 1426: 加载硬编码 RSA 私钥
        HKS_IF_NOT_SUCC_LOGE_RETURN(ret, ret, "get devKey fail")
    }
    // ...
}

Step 3 — 从静态数组直接复制(无任何运行时覆盖机制)

// dcm_attest.c:1396-1400 — GetCertOrKey()
static int32_t GetCertOrKey(enum HksCertType type, struct HksBlob *out) {
    switch (type) {
        case HKS_DEVICE_KEY:
            return ReadCertOrKey(g_deviceKey, sizeof(g_deviceKey), out);  // line 1400: 直接从硬编码数组读取
        // ...
    }
}

// dcm_attest.c:1381-1394 — ReadCertOrKey()
static int32_t ReadCertOrKey(const uint8_t *inData, uint32_t size, struct HksBlob *out) {
    uint8_t *data = HksMalloc(size);
    if (memcpy_s(data, size, inData, size) != EOK) {  // line 1386: 纯 memcpy,无文件读取、无配置检查
        // ...
    }
    out->size = size;
    out->data = data;
    return HKS_SUCCESS;
}

Step 4 — 使用硬编码私钥签名认证证书

// dcm_attest.c:1020-1022 — CreateAttestCert() 中
struct HksBlob signature = { sizeof(sigBuf), sigBuf };
ret = SignTbs(&signature, &tbs, &attestSpec->devKey, signAlg);  // line 1022: 用 devKey 签名
// → HksCryptoHalSign(&priKey, &usageSpec, &message, sig);     // line 1003: 底层签名调用

硬编码密钥内容

// dcm_certs_and_key.h:190-254 — 1190 字节 DER 编码 RSA-2048 PKCS#1 私钥
static const uint8_t g_deviceKey[] = {
    0x30, 0x82, 0x04, 0xA4, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01, 0x01, 0x00, 0xBC, 0x1C, 0x78, 0x55,
    // ... 共 1190 字节,含完整 RSA CRT 参数 (n, e, d, p, q, dp, dq, qInv)
};

// 对应证书 dcm_certs_and_key.h:154-167
// CN = "helloworld111", O = "helloworld" — 明确为测试占位身份
static const uint8_t g_deviceCert[] = { /* ... DER 编码 X.509 证书 ... */ };

为什么无法被覆盖

  1. 无文件回退ReadCertOrKey() 仅执行 malloc + memcpy_s,无任何文件 I/O
  2. 无编译开关:唯一编译守卫 #ifdef HKS_SUPPORT_API_ATTEST_KEYhks_config.h:28hks_config_base.h:172 中无条件定义
  3. 无头文件覆盖机制#ifndef HKS_CERTS_AND_KEY 不提供外部替换途径
  4. 从未被修补:该文件仅 2 次 commit —— 初始创建和 2025-01 添加匿名认证密钥。硬编码 RSA 密钥自创建以来从未轮换

触发条件

  1. 任何调用 huks 接口进行设备认证的流程(非匿名模式,即默认路径)
  2. GetCertAndKey() 被无条件调用,g_deviceKey 直接复制到 attestSpec->devKey
  3. 该密钥用于签名 TBS 证书,生成设备认证签名

影响性分析说明

影响

  • 认证签名可伪造:私钥公开于 Apache 2.0 开源代码中,任何人可提取并伪造设备认证签名
  • 影响范围广:所有使用此代码且未做设备级密钥置备(provisioning)的设备均受影响
  • 信任链失效:依赖设备认证的远程验证方(如企业 MDM、支付系统)将接受伪造签名

原理分析

受影响版本

规避方案或消减措施

建议修复

  1. 移除源码中的硬编码私钥 g_deviceKey
  2. GetCertAndKey() 中添加运行时检查:若无可用的置备密钥,拒绝认证而非回退到硬编码密钥
  3. 在设备制造阶段实现设备特定密钥置备机制
  4. 轮换已被公开的密钥对