Administrator
发布于 2026-10-16 / 0 阅读
0
0

OpenWrt 24 + lpac 实现 eUICC 写号

一、背景与目标

设备信息

  • 路由器:GL-XE 300,已刷入 OpenWrt 24.10.8

  • 蜂窝模组:Quectel EC20

  • eUICC 卡:标准 GSMA 白卡

  • 目标:通过 lpac 远程下载并写入 eSIM profile

核心链路:路由器 CPU → QMI 协议 → EC20 模组 → eUICC 卡。lpac 通过 OpenWrt 的 uqmi 工具与 EC20 通信,uqmi 再将 APDU 指令透传给卡。

二、安装 lpac

1、通过 opkg 安装

opkg update
opkg install lpac

2、验证安装

lpac version

返回 {"code":0,"message":"success"} 即安装成功。版本显示 v0.0.0-unknown 是 OpenWrt 打包时的正常现象,不影响功能。

三、配置 uqmi 后端

1、确认 EC20 的 QMI 设备节点

ls /dev/cdc-wdm0

如果这个设备不存在,说明 EC20 没有以 QMI 模式工作,需要先检查模组的 USB 模式配置。

2、直接验证 lpac 与 eUICC 通信

路由器上插入 eUICC 卡,重启后执行:

LPAC_APDU=uqmi lpac chip info

返回包含 eidValue 的 JSON,即说明 EC20 的 QMI 通道和 uqmi 后端都在正常工作。

预期成功输出(包含关键字段):

{
  "eidValue": "89086030...",
  "EuiccConfiguredAddresses": {
    "rootDsAddress": "lpa.ds.gsma.com"
  },
  "EUICCInfo2": {
    "freeNonVolatileMemory": 280833,
    "rspCapability": ["additionalProfile", ...]
  }
}

关键判断:

  • eidValue 有值 → 卡被正确识别

  • rspCapability 包含 additionalProfile → 支持写入新 profile

  • freeNonVolatileMemory 数值充足 → 有空间存储 profile

3、踩坑:插卡后运行报 euicc_init

{"code":-1,"message":"euicc_init","data":""}

原因:EC20 固件在热插拔场景下不会主动初始化 eUICC 卡。卡虽然物理上在位,但逻辑上未激活。lpac 尝试打开逻辑通道并选中 ISD-R 应用时,卡端无响应,导致初始化超时。

解决:重启路由器,让 EC20 执行完整的启动序列,强制对 eUICC 执行 UIM Power On 和 Card Reset,之后 lpac 即可正常通信。

补充说明:这个问题在 EC20 上表现为“必须重启路由器才能首次成功”。重启后 chip info 一次通过,后续只要不拔卡、不重启模组,lpac 的命令都能正常执行。因此插卡操作应在路由器关机状态下完成,或插卡后重启路由器再开始写卡。

四、下载并写入 Profile

1、下载命令

LPAC_APDU=uqmi lpac profile download -a 'LPA:1$<SM-DP+域名>$<匹配ID>'

示例(红茶移动 CSL 香港卡):

LPAC_APDU=uqmi lpac profile download -a 'LPA:1$rsp-eu.redteamobile.com$47ExxxxxFBA62287'

LPAC_APDU=uqmi lpac profile download -a "LPA:1\$rsp-eu.redteamobile.com\$47ExxxxxFBA62287"

注意:$ 是 shell 特殊字符,需要用反斜杠 \ 转义,或者用单引号包裹整个激活码,避免被 shell 解析。

2、成功输出(完整流程)

{"code":0,"message":"es10b_get_euicc_challenge_and_info"}
{"code":0,"message":"es9p_initiate_authentication"}
{"code":0,"message":"es10b_authenticate_server"}
{"code":0,"message":"es9p_authenticate_client"}
{"code":0,"message":"es8p_meatadata_parse","data":{"iccid":"898520...","profileName":"CSL_45400_Release"}}
{"code":0,"message":"es10b_prepare_download"}
{"code":0,"message":"es9p_get_bound_profile_package"}
{"code":0,"message":"es10b_load_bound_profile_package"}
{"code":0,"message":"success","data":null}

最终 {"code":0,"message":"success"} 即写入成功。

3、解决 TLS 握手失败(核心踩坑)

(1)问题现象

执行 profile 下载时,在 es9p_initiate_authentication 阶段报错:

curl_easy_perform() failed: Error
{"code":-1,"message":"es9p_initiate_authentication","data":"HTTP transport failed"}

(2)根本原因

OpenWrt 默认的 libcurl 使用 mbedTLS 作为 SSL 后端。mbedTLS 在处理部分 SM-DP+ 服务器的证书链时存在限制,无法完成 TLS 握手。OpenWrt 官方 Issue 确认了这一问题:mbedTLS 难以读取 GSMA Root CA(使用 ECDSA-SHA256 签名),且可能不支持服务器要求的部分加密套件(如 TLS 1.3 的 TLS_AES_256_GCM_SHA384)。

(3)解决办法:替换 gnutils 版 libcurl

opkg install libcurl-gnutls4

安装后,将 libcurl 的符号链接指向 gnutls 版本:

cd /usr/lib
rm -f libcurl.so.4
ln -s libcurl-gnutls.so.4 libcurl.so.4

验证替换生效:

ls -l /usr/lib/libcurl.so.4
# 应显示: libcurl.so.4 -> libcurl-gnutls.so.4

注意:libcurl-gnutls4 会额外占用约 6MB 闪存空间。XE300 的 128MB NAND 足够容纳,无需担心。

(4)如果 opkg 找不到 libcurl-gnutls4

手动下载对应架构的 ipk 文件(mips_24kc):

https://downloads.openwrt.org/releases/24.10.8/packages/mips_24kc/packages/

搜索 libcurl-gnutls4,下载后通过 SCP 传到路由器:

# 加 -O 参数强制使用旧版 SCP 协议
scp -O libcurl-gnutls4_*.ipk root@192.168.1.1:/tmp/
opkg install /tmp/libcurl-gnutls4_*.ipk

五、管理 Profile

1、列出卡内所有 Profile

LPAC_APDU=uqmi lpac profile list

结果示例:

{"type":"lpa","payload":{"code":0,"message":"success","data":[{"iccid":"898520002xx","isdpAid":"a0000005591010ffffffff8900001200","profileState":"enabled","profileNickname":null,"serviceProviderName":"eSIM","profileName":"CSL_45400_Release","iconType":null,"icon":null,"profileClass":"operational"}]}}

输出中包含每个 profile 的 iccid、profileName、profileState(enabled / disabled)。

2、启用 Profile

LPAC_APDU=uqmi lpac profile enable <ICCID>

成功返回 {"code":0,"message":"success"}。同一时间只能有一个 profile 处于 enabled 状态。

3、设置别名(可选)

LPAC_APDU=uqmi lpac profile nickname <ICCID> "我的香港卡"


评论