mbed TLS:OpenHarmony 安全能力的"共同底座"

导读:打开 OpenHarmony 的依赖关系图,你会发现 third_party/mbedtls 是少有的"被安全链路反复引用"的第三方库——从系统初始化、应用验签、密钥管理到 OTA 升级,几乎每一条安全关键路径都从它这里获取密码学能力。这篇我们把它拆开看:它是什么、在 OpenHarmony 里怎么落地、又是怎么被裁剪和复用的。

一、写在前面:为什么安全能力需要一个"底座"

一个操作系统无论 UI 多流畅、生态多丰富,一旦安全基石不稳,一切都无从谈起。OpenHarmony 支持从几十 KB 内存的轻量设备到标准系统,这意味着安全能力必须既能扛住标准系统的完整需求,又能在资源受限的轻量设备上"瘦身"运行。这就要求底层密码学库具备两个特质:

  1. 模块化——算法可以按需启用,不用的代码不进固件;
  2. 可移植——能适配不同内核、不同编译器和不同架构。

mbed TLS 正是这样一套库,这也是它被 OpenHarmony 选中、并成为三档系统(mini / small / standard)通用安全组件的原因。

二、mbed TLS 是什么

mbed TLS 是一套开源的、可移植的、易用的、代码可读性极强的 SSL/TLS 安全库,纯 C 语言编写,采用 Apache License V2.0 许可。OpenHarmony 当前引入的版本是 v3.6.5

它最常被误会的地方是"mbed TLS 就是做 TLS 握手的"。实际上它是一个完整的安全工具箱,能力覆盖三层:

能力层 主要内容 典型用途
SSL/TLS 与 DTLS TLS 1.2 / TLS 1.3、DTLS、会话缓存、会话票据、Cookie 网络通信加密、客户端/服务端双向认证
密码学算法 对称加密 AES / ARIA / Camellia / Chacha20;哈希 MD5 / SHA-1 / SHA-256 / SHA-512 / SHA3;非对称 RSA / DHM / ECDH / ECDSA 签名、验签、密钥协商、完整性校验
X.509 证书 证书解析、CSR 创建、CRT 签发 证书链校验、身份认证

它的核心优势一句话概括:**"小而全"**——算法种类覆盖全面,但每一个模块都可以独立裁剪,裁剪后可以在资源极度受限的环境里运行。

三、在 OpenHarmony 源码树中长什么样

mbed TLS 在 OpenHarmony 中位于 third_party/mbedtls,目录结构清晰:

third_party/mbedtls
├── library/        # 算法库实现源码(aes.c、sha256.c、rsa.c、ecp.c、ssl_tls.c ...)
├── include/        # 对外公开头文件(mbedtls/md.h、mbedtls/rsa.h、mbedtls/x509.h ...)
├── port/           # OpenHarmony 移植层
│   ├── config/     # 分内核配置文件
│   ├── include/    # 移植辅助头文件(日志、TLS 客户端、证书)
│   └── src/        # 移植辅助实现
├── programs/       # 自带的示例程序与工具
├── tests/          # 自带测试
├── configs/        # 上游提供的配置模板
├── BUILD.gn        # OpenHarmony 构建脚本
├── mbedtls.gni     # 源码清单
├── mbedtls_feature.gni  # 功能化裁剪开关
└── bundle.json     # 部件清单与依赖声明

其中 port/ 是整个移植的关键:上游 mbed TLS 无法直接满足 OpenHarmony 的差异化需求,OpenHarmony 在 port 层做了两层适配。

3.1 分内核的配置裁剪

OpenHarmony 有 liteos_a、liteos_m 等多个轻量内核,不同内核资源差异巨大,因此 port 下提供了多套 mbed TLS 配置文件:

port/config/
├── config_liteos_a.h       # LiteOS-A 内核配置
├── config_liteos_m.h       # LiteOS-M 内核配置(最精简)
├── config_standard_feature.h  # 标准系统功能配置
├── config_lite_feature.h   # 轻量系统功能配置
└── config_feature_base.h   # 公共基础配置

构建时通过编译宏选择配置,例如:

if (ohos_kernel_type == "liteos_m") {
  defines += [
    "__unix__",
    "MBEDTLS_CONFIG_FILE=<../port/config/config_liteos_m.h>",
  ]
}
if (ohos_kernel_type == "liteos_a") {
  defines += [ "MBEDTLS_CONFIG_FILE=<../port/config/config_liteos_a.h>" ]
}

mbed TLS 原生的裁剪机制是"编译前修改 config.h",而 OpenHarmony 用构建参数注入 MBEDTLS_CONFIG_FILE 的方式,在不改动上游代码的前提下,实现了一套源码、多套配置。

3.2 统一的对外输出

通过 bundle.jsoninner_kits,把最常用的三组能力对外输出:

  • mbedtls/md.h —— 消息摘要(哈希)
  • mbedtls/rsa.h —— RSA 公钥密码
  • mbedtls/x509.h —— X.509 证书

同时产出 mbedtls_shared(动态库)与 mbedtls_static(静态库)两种形态,上层组件按需选择,动态库能减小单包体积、静态库则便于链接期裁剪。

四、功能化裁剪:把"要不要"交给开关

为了让不同的产品按需构建,OpenHarmony 为 mbed TLS 设计了按功能开关的源码级裁剪机制(见 mbedtls_feature.gni)。每个开关对应一组源码文件与一组宏定义,只有开关打开时对应算法才被编译进固件。

以密码层为例:

mbedtls_feature_aes      = true    # AES 对称加密
mbedtls_feature_sha256   = true    # SHA-256 哈希
mbedtls_feature_rsa      = true    # RSA 非对称
mbedtls_feature_ecp      = true    # 椭圆曲线基础
mbedtls_feature_ecdh     = true    # ECDH 密钥协商
mbedtls_feature_ecdsa    = true    # ECDSA 签名
mbedtls_feature_ssl_tls12 = false  # TLS1.2(按需开启)

开关与源码严格联动:

if (mbedtls_feature_sha256) {
  MBEDTLS_FEATURE_SOURCES += [ "library/sha256.c" ]
  _feature_defines += [ "MBEDTLS_SHA256_C=", "MBEDTLS_SHA224_C=" ]
}

这样做的好处非常直接:

  • 固件体积可控——不用的算法连源码都不进编译,从源头减小 ROM/RAM 占用;
  • 宏与源码一致——避免了"开了宏却没编对应源文件"这类经典的链接错误;
  • 依赖可校验——gni 里内置了一组 assert,专门检查功能间的依赖关系,例如 GCM 依赖 AES、ECDSA 依赖 ECP、X.509 依赖 PK 与编码层,配置出错在构建期就会报出来,而不是运行期才暴露:
assert(!mbedtls_feature_gcm || mbedtls_feature_aes,
       "mbedtls_feature_gcm requires mbedtls_feature_aes")
assert(!mbedtls_feature_ecdsa || mbedtls_feature_ecp,
       "mbedtls_feature_ecdsa requires mbedtls_feature_ecp")
assert(!mbedtls_feature_ssl_tls12 ||
       (mbedtls_feature_cipher && mbedtls_feature_sha256 &&
        mbedtls_feature_pk && mbedtls_feature_entropy),
       "mbedtls_feature_ssl_tls12 requires cipher, sha256, pk, entropy")

这套机制把"密码学库"变成了"可拼装的密码学积木",产品做 ROM 预算评估时可以精确到算法粒度。

五、谁在依赖它?——安全链路全景

在 OpenHarmony 源码中检索声明依赖 mbedtls 的组件,可以清晰看到它的"底座"地位:

  • base/security/huks —— 统一密钥管理服务:密钥的生成、导入、加解密、签名验签都依赖底层算法库;
  • base/security/appverify —— 应用签名校验:应用安装时对包进行验签,"裁判"用的是 mbed TLS;
  • base/startup/init —— 系统初始化:早期安全能力与启动流程的完整性校验;
  • base/update/sys_installer_lite —— 轻量系统升级安装:OTA 包校验、解压后的完整性保护;
  • test/xts/device_attest_lite —— 设备认证相关测试组件。

把链路串起来就是:设备上电 → init 完成早期校验 → HUKS 提供密钥能力 → 安装应用时 appverify 验签 → 系统升级时校验升级包——每一步的密码学计算,最终都落在 mbed TLS 上。

六、上手示例:一次简单的哈希计算

上层组件使用 mbed TLS 非常简单,包含头文件并链接库即可:

#include <stdio.h>
#include <string.h>
#include "mbedtls/md.h"

int main(void)
{
    unsigned char digest[32] = {0};
    const char *msg = "hello, OpenHarmony";

    /* 一次性计算 SHA-256 摘要 */
    int ret = mbedtls_md(
        mbedtls_md_info_from_type(MBEDTLS_MD_SHA256),
        (const unsigned char *)msg, strlen(msg), digest);
    if (ret != 0) {
        printf("md failed: -0x%04X\n", -ret);
        return ret;
    }

    /* digest 即为 32 字节的 SHA-256 摘要,可继续做完整性比对 */
    for (int i = 0; i < 32; i++) {
        printf("%02x", digest[i]);
    }
    printf("\n");
    return 0;
}

值得注意的是 mbed TLS 的错误码返回约定:函数失败时返回负的错误码(如 MBEDTLS_ERR_MD_BAD_INPUT_DATA),这是它区别于普通库的一个使用要点——判断成功与否要看 ret == 0

七、总结

mbed TLS 之于 OpenHarmony,就像楼宇的地基钢筋:平时看不见,但每一条安全链路都踩在它上面。它的价值体现在三点:

  1. 能力完整——TLS/密码学/X.509 全覆盖,满足从轻量到标准的全部需求;
  2. 裁剪友好——多内核配置 + 功能开关 + 依赖断言,把"安全"做成了可量化、可预算的工程;
  3. 接入标准——通过 inner_kits 统一输出头文件与双形态库,上层组件无需关心移植细节。

可以说,理解 OpenHarmony 的安全体系,从读懂 mbed TLS 的移植与裁剪机制开始。

相关源码位置:third_party/mbedtls
相关部件:mbedtls(子系统 thirdparty),特性项 mbedtls_porting_pathmbedtls_enable_ssl_srv

Logo

社区规范:仅讨论OpenHarmony相关问题。

更多推荐