好的,遵照您的指令,我们继续深度拆解 3GPP TS 31.101 规范。这是本系列的第十篇文章,我们将进入规范的“执行”部分,全面解析UICC与终端之间沟通的语言——APDU。


深度解析 3GPP TS 31.101:第10章 命令与响应结构 (APDU:UICC世界的通用语)

本文技术原理深度参考了3GPP TS 31.101 V19.0.0 (2025-10) Release 19规范中,关于“Chapter 10 Structure of commands and responses”的核心章节,旨在为读者深入剖析APDU(应用协议数据单元)的精巧结构,理解终端与UICC之间每一次精确“对话”的编码艺术与信息传递机制。

引言:从“做什么”到“怎么说”

经过对第8章(文件结构)和第9章(安全特性)的学习,新人工程师小林已经像一位资深架构师,完全掌握了UICC这座“数据仓库”的蓝图和安保体系。他知道数据存放在哪里,也知道访问这些数据需要遵守哪些严苛的规则。

然而,知道规则,不等于会执行。导师老王把小林叫到会议室,在白板上画了两个对话框,一个代表终端,一个代表UICC。老王说:“小林,你现在是这座仓库的‘首席安全官’,知道所有的规章制度。但如果你想命令你的机器人叉车(协议栈)去执行一个任务,比如‘去A区3号货架取5号货物’,你必须把这个指令翻译成机器能懂的、毫无歧义的‘机器语言’。这门语言,就是APDU。第10章,就是这门语言的‘语法书’。你必须精通它,才能将你的意图,准确无误地传达给UICC。”

APDU(Application Protocol Data Unit),是UICC世界的“通用语(Lingua Franca)”。无论底层是传统的接触式接口还是高速USB,无论上层应用是USIM还是银行卡,最终的逻辑交互都必须通过这门结构严谨的语言来完成。今天,我们将化身“语言学家”,深入剖析APDU的每一个字节,理解其背后的设计哲学。

1. APDU的核心交互模型:一问一答的严谨对话

原文引用 (Chapter 10 Structure of commands and responses):

The provisions of ETSI TS 102 221 clause 10 apply.

整个APDU的交互模型非常简洁,就是一个严格的**命令-响应 (Command-Response)**对。

  • 命令APDU (C-APDU): 由终端(或更广义的接口设备IFD)发送给UICC。它包含了终端希望UICC执行的一个明确指令。

  • 响应APDU (R-APDU): 由UICC返回给终端。它包含了命令的执行结果,以及终端请求的数据(如果有的话)。

这个模型保证了通信的同步性和可预测性。终端每发出一个C-APDU,都必须等待一个R-APDU回来,才能知道操作是否成功,然后才能决定下一步做什么。绝不允许终端连续发送多个C-APDU而UICC还未响应。

2. 命令APDU (C-APDU) 结构全解析 - 如何精确下达指令

一个C-APDU由一个强制的4字节头部和一个可选的3部分主体组成。这种结构既紧凑又灵活。

Header (CLA, INS, P1, P2) + Body (Lc, Data, Le)

2.1 强制头部 (Header):指令的核心

头部是每个C-APDU都必须包含的部分,它定义了命令的本质。

CLA (Class byte) - 命令的“籍贯”

  • 结构: 1字节。

  • 功能: 用于标识该命令属于哪个规范或应用类别,避免不同标准之间的命令冲突。

  • 深度解析:

    • '0X' / '8X' / '9X' / 'AX': 这些值由ISO/IEC 7816-4定义,用于区分不同的命令结构和安全报文。

    • 3GPP特定值: 在GSM时代,CLA='A0'被用于所有GSM SIM卡的命令。而在3G及以后,为了支持逻辑信道,CLA的编码变得更加复杂,低几位可以用来指定逻辑信道的编号。例如,'00'通常表示在0号逻辑信道上,使用ISO/IEC 7816-4定义的标准命令。

    • 'FF': 这是一个专为PPS协商保留的特殊值。

INS (Instruction byte) - 命令的“动词”

  • 结构: 1字节。

  • 功能: 定义了具体要执行的操作。这是APDU中最核心的“动词”。

  • 经典案例:

    • 'A4': SELECT (选择文件)

    • 'B0': READ BINARY (读取二进制文件)

    • '20': VERIFY (验证PIN码)

    • '88': AUTHENTICATE (执行鉴权)

P1, P2 (Parameter bytes 1 & 2) - 命令的“状语”和“宾语”

  • 结构: 各1字节。

  • 功能: 用于为INS提供更详细的参数,细化命令的行为。P1和P2的具体含义,完全由INS决定。

  • 场景演绎:

    • SELECT命令: P1可以用来指定选择方式(如按ID、按AID),P2可以用来指定FCP的返回策略。例如,P1='04', P2='00'可能就表示“通过AID来选择一个应用,并请返回该应用的FCP”。

    • READ BINARY命令: P1和P2通常组合起来,构成一个16位的偏移量(offset),告诉UICC从文件的哪个位置开始读取。

2.2 可选主体 (Body):指令的附加信息

根据命令是否需要发送数据给UICC,或者期望从UICC接收数据,C-APDU可以有四种不同的结构(Case 1, 2, 3, 4)。

Case 1: Header (无数据交换)

  • 结构: 只有4字节的头部。

  • 场景: 执行一个不需要参数、也不返回数据的简单操作。例如,一个用于“使文件失效”的DEACTIVATE FILE命令。

Case 2: Header + Le (只接收数据)

  • 结构: 头部之后跟着一个Le字节,表示期望从UICC接收数据的最大长度。

  • Le (Length expected): 1或3字节。Le='00'表示期望接收256字节。

  • 场景: READ BINARY命令。终端告诉UICC:“从P1P2指定的偏移量开始,请给我最多Le个字节的数据。”

Case 3: Header + Lc + Data (只发送数据)

  • 结构: 头部之后跟着Lc字节和实际的数据。

  • Lc (Length of command data): 1或3字节,表示后面Data字段的长度。

  • Data: 实际要发送给UICC的数据。

  • 场景: UPDATE BINARY命令。终端说:“请将我提供的这Lc个字节的数据,写入到P1P2指定的偏移量位置。”

Case 4: Header + Lc + Data + Le (既发送又接收数据)

  • 结构: 包含了所有部分,是最完整的形态。

  • 场景: 一些复杂的安全命令,比如终端发送一个加密挑战(Data),并期望UICC返回一个加密响应(Response Data)。

场景总结:一次UPDATE BINARY的完整C-APDU构建

小林需要将字符串”HELLO”(ASCII编码为48 45 4C 4C 4F)写入当前选定文件(一个透明EF)的第10个字节偏移处。

  1. CLA: 使用'00' (标准命令,0号信道)。

  2. INS: 使用'D6' (UPDATE BINARY)。

  3. P1, P2: 偏移量10,即'00 0A'

  4. Lc: 数据长度为5,即'05'

  5. Data: '48 45 4C 4C 4F'

  6. Le: 该命令不期望返回数据,无Le。

最终的C-APDU为:00 D6 00 0A 05 48 45 4C 4C 4F。这串字节,就是终端对UICC下达的一条精确、无歧义的指令。

3. 响应APDU (R-APDU) 结构全解析 - 如何解读执行结果

UICC在执行完C-APDU后,必须返回一个R-APDU。R-APDU的结构相对简单。

Body (Data) + Trailer (SW1, SW2)

3.1 可选主体 (Data):请求的“战利品”

  • 结构: 变长数据。

  • 功能: 如果C-APDU是一个请求数据的命令(Case 2或4),那么UICC会在这里返回请求的数据。

  • 场景: 对于一个READ BINARY命令,这里就是从文件中读出的实际内容。对于SELECT命令,这里就是文件的FCP信息。

3.2 强制尾部 (Trailer):结果的“最终裁定”

这是每个R-APDU都必须包含的、最重要的部分。它由2个字节的状态字(Status Words)组成。

SW1, SW2 - 状态字:命令执行的“晴雨表”

  • 结构: SW1和SW2各1字节。

  • 功能: 明确告知终端,刚刚的命令执行情况如何。

  • 深度解析: 状态字是对ISO/IEC 7816-4中定义的数百个可能结果的精炼编码。作为工程师,必须熟悉几个最关键的状态字。

10.2.1 状态条件的分类 (Status conditions returned by the UICC)

老王在白板上画了一个状态分类图,帮助小林记忆:

  • 正常处理 (Normal processing):

    • 90 00: 命令成功完成。这是工程师最希望看到的状态字。它意味着一切顺利,如果请求了数据,数据也已经在前面返回了。

    • 91 XX: 命令成功,但UICC有额外信息要提供(比如USAT主动命令)。

  • 警告 (Warnings):

    • 62 XX / 63 XX: 命令已执行,但可能存在一些非致命问题。

    • 63 CX: PIN验证失败,还剩X次机会。例如,63 C2表示密码错误,还剩2次尝试机会。这是一个非常重要且常用的状态字。

  • 执行错误 (Execution errors):

    • 69 XX / 6A XX: 命令因某些条件不满足而无法执行。

    • 6A 82: 文件未找到 (File not found)

    • 6A 88: 引用的数据未找到 (Referenced data not found),比如读取一条不存在的记录。

    • 69 82: 安全条件不满足 (Security condition not satisfied)。比如,一个文件需要PIN1权限,但PIN1未验证。

    • 69 85: 使用条件不满足 (Conditions of use not satisfied)。比如文件已被禁用。

  • 检查错误 (Checking errors):

    • 67 00: 长度错误 (Wrong length)

    • 6B 00: P1/P2参数错误 (Wrong parameters P1-P2)

    • 6D 00: 指令不支持 (Instruction code not supported)

    • 6E 00: 类别不支持 (Class not supported),我们在第4章的GSM/USIM互斥原则中见过它。

10.2.2 状态字与命令的对应关系

第10章还提供了一个非常实用的表格,列出了每个具体命令(如SELECT, READ RECORD等)可能返回的所有状态字及其含义。这张表,是终端协议栈工程师进行错误处理和状态机设计的“圣经”。

结论:一套精确、高效的机器对话体系

小林结束了对APDU“语法”的学习,心中豁然开朗。他向老王总结道:

“王工,我现在明白了,APDU是UICC世界的‘机器法律’和‘外交辞令’。第10章,为我们定义了这门语言的全部语法。

  1. C-APDU 像是一份结构严谨的法律诉状。CLA定义了案件的管辖法院,INS是诉讼请求,P1/P2是请求的详细参数,Lc和Data是呈堂证供,Le则是期望的判决结果。这套结构确保了终端的每一个意图,都能被无歧义地表达。

  2. R-APDU 则是法院的判决书。前面的Data是判决的具体内容(如赔偿金),而最后的SW1/SW2状态字,则是最终的、不可置疑的判决结果——‘胜诉’(90 00)、‘警告’(63 CX)或‘败诉’(6A 82)。

  3. 状态字体系,更像是一部完整的**‘错误法典’**。它将所有可能的失败原因都进行了精确的编码,使得终端协议栈能够进行智能的、精细化的错误处理,而不是简单地报告‘失败’。

精通APDU这门语言,是成为一名合格UICC/终端协议工程师的基础。它让我们能够‘倾听’并‘理解’UICC的每一次响应,从而编写出稳健、可靠的通信软件。”

老王满意地笑了:“非常好。你已经掌握了‘语法’。下一步,就是学习‘词汇’了——也就是第11章,我们将逐一学习每个具体APDU命令的详细用法和语义。”


FAQ 环节

Q1:C-APDU中的Lc和Le字段为什么可以是1字节或3字节?

A1:这是为了处理大数据块的传输。最初的ISO/IEC 7816规范中,Lc和Le都只有1个字节,能表示的长度范围是1-256字节(‘00’代表256)。这在早期是足够的。但随着应用需求的发展,需要一次性传输更长的数据(如eSIM Profile),1字节的长度就不够了。因此,规范引入了**扩展长度(Extended Length)**机制。当需要表示超过256字节的长度时,会使用一个3字节的格式:第一个字节固定为'00',后两个字节组成一个16位的长度值,最大可以表示65536字节。

Q2:如果我发送一个Case 2的C-APDU(请求数据),Le值设为'10'(16字节),但UICC实际只有5字节数据可返回,会发生什么?

A2:UICC会返回它实际拥有的5个字节的数据,并且状态字(SW1/SW2)会是**6C 05**。这个特殊的状态字6C XX是一个非常有用的反馈机制,它的意思是:“命令本身是正确的,但你期望的长度Le有问题。我实际拥有的数据长度是XX。请用这个正确的长度重新发送命令。” 这是一个“建设性”的错误提示,指导终端如何正确地再次请求。

Q3:为什么90 00状态字如此重要?

A3:90 00是唯一明确表示“命令已按预期成功完成,且无任何异常”的状态字。对于终端协议栈的状态机来说,收到90 00是驱动流程进入下一个成功状态的关键触发条件。所有其他的状态字,都意味着需要进入警告处理、错误恢复或流程终止等异常分支。因此,在调试中,看到90 00是每个工程师最开心的时刻。

Q4:终端协议栈应该如何设计对各种状态字的错误处理?

A4:一个稳健的协议栈需要对状态字进行分类处理:

  • 成功 (90 00): 流程继续。

  • 可恢复的警告/错误:

    • 63 CX (PIN错误): 递减重试计数器,再次向用户请求输入。

    • 6C XX (长度错误): 使用返回的正确长度XX,重新发送命令。

  • 不可恢复的执行错误:

    • 69 82 (安全条件不满足): 放弃当前操作,转去执行满足安全条件所需的操作(如先去验证PIN)。

    • 6A 82 (文件未找到): 放弃操作,向上层应用报告文件不存在。

  • 致命的检查错误:

    • 6D 00/6E 00 (指令/类别不支持): 记录日志,标记该卡不支持此功能,并终止相关流程。

通过这种精细化的处理,协议栈可以表现得非常“智能”和“有韧性”,而不是一遇错误就崩溃。

Q5:ISO/IEC 7816-4和3GPP TS 31.101在APDU定义上是什么关系?

A5:ISO/IEC 7816-4是“母法”,它定义了智能卡命令的通用框架、基础命令集(如SELECT, READ/UPDATE BINARY等)以及状态字的通用含义。3GPP TS 31.101是“特别法”,它:

  1. 选用了ISO/IEC 7816-4中的一个子集作为其基础命令。

  2. 对某些通用命令的P1/P2参数在3GPP场景下的具体含义,进行了更详细的规定。

  3. 新增了一些电信业务所特有的命令,如AUTHENTICATE

  4. 对某些状态字在特定命令下的具体解释,进行了补充说明。

因此,开发3GPP应用时,需要以31.101为准,但其背后的原理和基础定义,都源于ISO/IEC 7816-4。