3. SecOC PDU格式详解:头部结构、数据载荷与填充机制

好,咱们今天来啃一块硬骨头——SecOC PDU的格式。说实话,我在刚接触SecOC那会儿,看着协议栈里那一串十六进制数据,头都是大的。但后来我发现,只要把PDU拆成三块来看,其实没那么复杂。

SecOC PDU说白了就三个部分:头部(Header)数据载荷(Payload)填充(Padding)。咱们一个一个说。

3.1 SecOC PDU头部结构

头部是SecOC的灵魂。它包含两个关键字段:Freshness Value(新鲜度值)Auth Tag(认证标签)。我习惯把Freshness Value比作“身份证有效期”,把Auth Tag比作“防伪码”。

3.1.1 Freshness Value(新鲜度值)

Freshness Value的作用是什么?防止重放攻击。你想想看,如果攻击者截获了一条合法的CAN报文,然后不断重发,ECU怎么知道这是不是过期的消息?Freshness Value就是干这个的。

它的结构通常包含两部分:

  • 时间戳(Timestamp):比如从某个基准时间开始的毫秒数
  • 计数器(Counter):比如一个单调递增的序列号

在实际项目中,我见过两种主流配置:

配置类型 长度 典型场景
纯计数器 4字节 低成本ECU,无RTC硬件
时间戳+计数器 8字节 网关、域控制器
我的经验: 我个人习惯在网关节点上用8字节的Freshness Value。为什么?因为网关要处理大量跨域消息,纯计数器容易溢出。我曾经在一个项目里吃过亏——计数器回绕后,ECU把旧消息当新的处理了,那叫一个尴尬。

3.1.2 Auth Tag(认证标签)

Auth Tag是SecOC的“签名”。它通过MAC算法(比如CMAC、HMAC)对PDU的其余部分计算得出。接收方收到后,用同样的密钥和算法重新计算,比对是否一致。

Auth Tag的长度取决于安全等级:

  • 4字节:最低安全要求,常用于CAN FD
  • 8字节:推荐配置,平衡安全性和带宽
  • 16字节:最高安全等级,用于关键控制消息
注意: Auth Tag不是越长越好。我曾经见过一个团队把Auth Tag设成16字节,结果CAN报文塞不下了,只能拆成两帧发。你想想看,拆帧带来的延迟和复杂度,反而降低了安全性。所以,8字节是大多数场景的“甜点”。

3.2 数据载荷(Payload)

数据载荷就是原始的应用数据。比如一个车窗控制指令、一个车速信号。SecOC不对载荷内容做任何修改,它只负责“包装”。

这里有个关键点:载荷长度必须是固定的。为什么?因为接收方需要知道从哪里开始解析Auth Tag。如果载荷长度可变,那解析逻辑就复杂了。

嗯,这里要注意:有些协议栈允许载荷长度变化,但必须在PDU头部显式声明长度。我个人不建议这么做——增加复杂度,容易出bug。

3.3 填充机制(Padding)

填充机制是SecOC里最容易被忽视的部分。它的作用有两个:

  1. 对齐:让PDU总长度符合底层通信协议的要求(比如CAN FD的64字节对齐)
  2. 防长度分析:防止攻击者通过PDU长度推断消息类型

填充的规则其实很简单:

  • 填充值通常用 0x000xFF
  • 填充位置在Auth Tag之后
  • 接收方收到后,先去掉填充,再验证Auth Tag
避坑指南: 我曾经在一个项目里遇到一个诡异的问题——两台ECU用同样的SecOC配置,但就是验证失败。查了两天才发现,发送方填充用的是0x00,接收方期望的是0xFF。所以,填充值必须在设计阶段就明确约定,别想当然。

3.4 完整的SecOC PDU结构示例

咱们来看一个实际的例子。假设我们要发送一条车窗控制消息:

原始载荷: 0x01 0x02 0x03 0x04 (4字节)
Freshness Value: 0x00000001 (4字节计数器)
Auth Tag: 0xA1B2C3D4 (4字节)
填充: 0x00 0x00 (2字节,对齐到10字节)

完整的SecOC PDU:
0x00 0x00 0x00 0x01  |  Freshness Value (4字节)
0x01 0x02 0x03 0x04  |  数据载荷 (4字节)
0xA1 0xB2 0xC3 0xD4  |  Auth Tag (4字节)
0x00 0x00             |  填充 (2字节)

你看,接收方收到后,先根据协议约定知道Freshness Value是4字节,载荷是4字节,Auth Tag是4字节,剩下的就是填充。去掉填充后,用同样的密钥计算Auth Tag,比对一致,就说明消息是合法的。

3.5 总结与建议

SecOC PDU的设计,说白了就是“在有限带宽里做最安全的事”。我个人建议:

  • Freshness Value:能用8字节就别用4字节,除非你的计数器永远不会回绕
  • Auth Tag:8字节是黄金配置,别盲目追求16字节
  • 填充:设计阶段就定好填充值和规则,别留到集成阶段再扯皮

我记得有一次评审,一个同事问:“为什么SecOC不直接用TLS?” 我笑了笑说:“你想想看,CAN总线上跑TLS,光握手就要几秒钟,车都撞上了还在握手呢。” 所以,SecOC的设计哲学就是——轻量、高效、够用就好。

下一章咱们聊聊SecOC的密钥管理,那又是一个大坑。嗯,到时候我给你们讲讲我在密钥分发上踩过的雷。