【AutoSAR 网络安全】SecOC
- 1. SecOC简介
- 1.1 SecOC 在 AUTOSAR 架构中的位置
- 2 缩略语
- 2.1 缩写表
- 3 对其他模块的依赖
- 4 SecOC功能概述
- 4.1 SecOC的核心功能
- 4.2 安全报文
- Trip Counter
- Reset Counter
- Message Counter
- 4.3 加密算法
- 4.3.1 对称加密
- 4.3.2 非对称加密
- 4.3. 3 AES-128-CMAC算法
- 4.4 报文类型
- 4.4.1 SecOC同步报文
- 4.4.2 SecOC的同步请求报文
- 4.5 SecOC通信过程
- Secured IPdu的发送(构建)
- Secured IPdu的接收(验证)
- 4.6 FVM
- 4.6.1 新鲜度值的构建
- 4.6.2 FVM 接口
- 参考资料
1. SecOC简介
在车载网络中,CAN 总线作为常用的通讯总线之一,其大部分数据是以明文方式广播发送且无认证接收。这种方案具有低成本、高性能的优势,但是随着汽车网联化,智能化的业务需要,数据安全性被大家越来越重视。传统的针对报文添加Rolling Counter 和 Checksum的信息,实现的安全性十分有限,也容易被逆向破解,伪造报文控制车辆。
在AUTOSAR架构中对于网络安全的机制,有E2E(End to End)保护,另外还有SecOC,主要实现对车内敏感数据信息进行认证。
SecOC是在AUTOSAR软件包中添加的信息安全组件,该特性增加了加解密运算,密钥管理、新鲜值管理和分发等一系列功能和新要求。SecOC模块在PDU级别上为关键数据提供有效可行的身份验证机制。该规范主要使用带有消息认证码(MAC(Message Authentication Code))的对称认证方法。与不对称方法对比,他们使用更小的密钥实现了相同级别的安全性,并且可以在软件和硬件中紧凑高效地实现。但是,规范提供了两种必要的抽象级别,因此对称和非对称身份验证方法都可使用。由于非对称加密计算量大,目前主要都是采用对称加密。
1.1 SecOC 在 AUTOSAR 架构中的位置
更加详细一点就是:
① 获取完整新鲜度值:由 FVM 模块实现,这个是 SWC 模块实现的,也就是完全由软件工程师手写代码去实现的,这个没啥问题。
② CMAC:由加密相关模块实现,也就是说,对于 SecOC 功能,图中右边这么多加密相关的模块,目的只有一个:计算 CMAC。
2 缩略语
2.1 缩写表
| Abbreviation / Acronym | Description |
|---|---|
| CSM | AUTOSAR Crypto Service Manager |
| SecOC | Secure Onboard Communication |
| MAC | Message Authentication Code |
| FV | Freshness Value |
| FM | Freshness Manager |
3 对其他模块的依赖
| 模块 | 作用 |
|---|---|
| PduR | 路由 I-PDU,连接 SecOC 与 COM、底层接口 |
| CanIf/LinIf/FrIf/EthIf | 底层总线接口,提供收发函数 |
| Csm (Crypto Service Manager) | 密码服务调度,MAC 生成/验证接口 |
| CryIf (Crypto Interface) | 加密驱动抽象层 |
| Crypto Driver (HW/SW) | 实际执行 AES-CMAC 等算法,可借助 HSM(硬件安全模块) |
| NvM (NVRAM Manager) | 断电存储新鲜度值,防掉电后计数器回退导致重放漏洞 |
| IdsM (Intrusion Detection System Manager) | 接收 SecOC 上报的安全事件,用于入侵检测 |
| E2E保护 (可选) | 功能安全相关的端到端保护,可与 SecOC 叠加:先加 E2E 头,再作为 SecOC 原始数据保护 |
| EcuM/SchM | ECU状态管理与调度,SecOC需要周期性调用SecOC_MainFunction处理异步操作 |
4 SecOC功能概述
4.1 SecOC的核心功能
消息认证(Message Authentication)
- 使用对称密钥(由加密栈管理)和AES-CMAC等算法,为原始数据生成消息认证码(MAC)。
- 接收方通过相同的密钥和输入数据重新计算MAC,若与收到的MAC一致,则证明报文在传输过程中未被篡改,且确实来自持有合法密钥的发送方。
防重放攻击(Replay Protection)
- 每条受保护报文都绑定一个单调递增的新鲜度值(计数器或时间戳)。
- 接收方记录上一次成功验证的新鲜度值,新报文的取值必须大于该记录值(允许一定跳变窗口以容忍丢帧)。若新鲜度值过小或重复,则判定为重放攻击并丢弃报文。
新鲜度值管理(Freshness Management)
- 发送方:为每个安全PDU维护独立计数器,每次发送时递增。
- 接收方:维护预期新鲜度值窗口。当收到报文时,尝试用本地高位与报文中的截断低位合成完整新鲜度值,用于MAC验证和重放校验。
- 同步机制:若因掉电、干扰等导致双方新鲜度值偏差过大(超出窗口),SecOC可通过预设的恢复策略(如利用多次有效认证或存储于NVM的初始值)重新同步。
截断(Truncation)与可配置性
- 为节省带宽,新鲜度值可只传输其低位部分(如只传1~4字节),高位由接收方在本地维护。
- MAC也可截断为较短长度(如4~16字节),在安全强度与通信开销间取得平衡。
元数据绑定(Metadata Binding)
- MAC的计算输入除了原始数据和完整新鲜度值外,还可包含元数据(如CAN ID、源/目标地址等)。此功能可防止报文被拷贝到其他ID或通道上,将消息与其通信属性强绑定。
4.2 安全报文
在SecOC标准中,AUTOSAR主要基于两种手段来实现数据的真实性和完整性的校验:基于MAC的身份验证和基于Freshness的防重放攻击。
首先MAC(Message Authentication Code)是保障信息完整性和认证的密码学方法之一,其中CMAC(Cipher–based Message Authentication Code,CMAC一般用于对称加密,整车厂可在车辆下线刷写程序时静态分配密钥,也可选择使用云端服务器动态地给车辆分配密钥。)是车载总线加密认证常用方案。MAC的作用不是防止有效数据被泄露,而是为了保护数据不会被攻击方篡改,即完成数据来源的认证。如需保护通信数据不被攻击方监听,则报文的有效数据还需要进行额外的加密。
为了降低重复攻击的风险,则需要在Secured I-PDU中加入新鲜度值,Freshness Value是一个根据一定逻辑不断更新的数值,Freshness Value的更新方法多种多样,AUTOSAR 标准将计数器或基于时间的新鲜度值作为典型选项。具体使用何种和具体的加密方式,以及如何定义新鲜度度其实并不在标准之内,这就给OEM有了各自定制化方案的可选余地,因此OEM 在实施 SecOC 方案时需要定义和做好两个关键部分:新鲜度值管理和密钥管理。
安全报文由一个头和真实的I-PDU,新鲜度值和用新鲜度值创建的认证器(eg.MAC)组成。由于SecOC机制需要占用总线带宽,因此一般适用于CANFD通讯网络。其中身份验证器(例如MAC)是指使用密钥、安全I-PDU的数据标识符ID、真实有效负载和新鲜度值生成的唯一身份验证数据字符串。消息头可用来指明安全PDU的长度。
数据结构如下:
Authentic I-PDU是需要被保护的数据;Authenticator为认证信息(通常使用消息认证码,即Message Authentication Code,简称MAC);Secured I-PDU Header为可选用的报头;Freshness Value为可选用的新鲜度值。
安全报文由以下元素组成:
- 报头(header):可用来指明安全PDU的长度
- 真实的I-PDU(Authentic I-PDU):需要被保护的数据
- 新鲜度值(Freshness Value)和
- 身份验证器(Authenticator):通常使用消息认证码,即Message Authentication Code,简称MAC
由于SecOC机制需要占用总线带宽,因此一般适用于CANFD通讯网络。而在实际使用中,新鲜度值和MAC可能会使用较多长度的数据来提高安全性,但这又会消耗大量的带宽等资源,所以常使用截取的方式做平衡处理。
新鲜度值和MAC都按照完整的值来生成,但是在发送和认证的时候只会截取一部分。
新鲜度值管理:
在SecOC中,给出了多种新鲜度值管理方案:
- 基于Counter的递增,即包含了原有方案的机制
- 基于全局时间戳,源于时间戳的唯一性
- 基于同步的复合Counter
这里我们主要谈一下第三种方案。在此方案中,完整的新鲜度值包括同步计数器(Trip Counter)、重置计数器(Reset Counter)、消息计数器(Message Counter)和重置标志值(Reset Flag)。其中消息计数器又分为高值和低值,而真正在报文中发送的值只包含消息计数器的低值和重置标志值。
由图可见,新鲜度值总共由3个部分组成:
①TripCounter ②ResetCounter ③MessageCounter
明明图中还有最后一部分ResetFlag,为啥说实际上是3部分呢?
因为最后面的那个ResetFlag就是指ResetCounter的低位。(具体是最低的多少位,则取决于客户要求,有可能是最低1位,也可能是最低2位)。
可见,新鲜度值的组成是比较复杂的。
因此,需要有个模块专门管理这个新鲜度值,于是,大家常听到的FVM (Freshness Value Management) 就是指这个模块。
这里需要提一嘴的是,FVM并不是Autosar规范中BSW的某个模块(大家可以去官网找找,它是没有专门描述FVM模块的文档的)。
注: 对于TripCounter 和ResetCounter,交由master Ecu节点统一管理,而作为slave Ecu节点需要从master Ecu发送的同步报文中,同步这两个值。
Trip Counter
简单概括来说即如下几点:
- 当Trip Counter自身达到最大值时,重设为初始值。(ECU首次上电也会设初始值)
- Trip Counter初始值为0或者1。(具体是0还是1,我们后面再讲)
- 当ECU唤醒、复位,Trip Counter需要+1。
- Trip Counter的最大长度是24Bit,即3个Byte。
所以,所谓Trip Counter,你可以简单理解为:上电次数计数器。
这里其实你就看出来了,TripCnt这玩意在ECU没电的时候,它是需要一直存储起来的。
SecOC会涉及到存储(NvM)功能,实际上存的就是Trip Counter。
Reset Counter
- 当TripCnt+1时,Reset Counter重设为初始值。
- Reset Counter初始值为0或者1。(具体是0还是1,取决于ECU是Master还是Slave,这个我们后面再讲)
- 每固定的一个时间间隔计时达到时(例如每30秒Reset Counter+1),Reset Counter+1。
- Reset Counter的最大长度是24Bit,即3个Byte。
Message Counter
- 当ResetCnt+1或ResetCnt初始化时,MsgCnt设为初始值。
- Message Counter初始值为0。
- 报文发送后Message Counter + 1。
- Message Counter的最大长度是48Bit,即6个Byte。
我们前面讲新鲜度值的各个组成时候,提到过每个部分的最大长度,但是如果都用最大长度,总长度已经到10几个byte了,这是不允许的,因此,对于不同的项目,新鲜度值各个组成部分的长度是变化的。
完整新鲜度值各个部分长度举例如下图所示:
4.3 加密算法
4.3.1 对称加密
对称加密算法的加密和解密使用的密匙是相同的,也就是说如果通讯两方如果使用对称加密算法来加密通讯数据,那么通讯双方就需要都知道这个密匙,收到通讯数据后用这个密匙来解密数据。
4.3.2 非对称加密
非对称算法中用到的密匙有两个,分别是公匙和私匙,要求通讯双方都有自己的公匙和私匙,自己公匙加密的数据只有自己的私匙才能解开,自己私匙加密的数据也只有自己的公匙才能解开。公匙是可以公布在网络上的,相当于一个公共的电话簿,可以被其他人获取到的。
以一个通信的例子来说明非对称算法:
A 要和 B 进行通信,A在网络上获取到B的公匙,然后把数据用B的公匙进行加密发送给B,B收到了数据后就用自己的私匙进行解密数据,然后就可以看到数据内容了,即使在网络传输中加密数据被黑客截取,由于黑客没有对应的私匙,他也无法解密数据进行查看。
在通信中对称加密算法比较高效,但是需要告知对方加密钥匙,在实际运用时比较麻烦,所以一般都是用非对称加密算法来加密对称加密算法的钥匙,然后发送给对方,对方收到对称加密算法的钥匙后,后续通信就用对称加密算法来加密消息内容了。
4.3. 3 AES-128-CMAC算法
AES-128-CMAC算法是一个固定的标准算法(对称加密)。因此,当我们开发完SecOC功能要测试验证,就可以使用CANoe工具写测试脚本,在CAPL脚本中直接调用CANoe自带的AES-128-CMAC算法接口函数。
好了,我们看看AES-128-CMAC算法的接口:
AES_128_CMACCalculate(constuint8*Key,constuint8*InputData,uint32 Datalen,uint8*CmacOut);可以看到,总共有4个参数:①Key,②InputData,③DataLen,④CmacOut
1、Key:密钥, 实际就是一串固定16Byte的数据。
在实际项目中,一般车企都会对这个Key又加一层额外操作:
比如车企会要求,最终的Key是通过原始Key、VIN码以及另外的算法,算出来的。(具体什么算法,我们不用管,车企会直接给算法代码)
通过这样的方式,使得Key更加复杂、强度更高。
2、InputData:输入数据,就是会参与CMAC计算的数据。
①对于SecOC的安全报文来说,InputData组成如下:
②对于SecOC的同步报文来说,InputData组成如下:
需要注意的是,DataID一般是报文的CANID。
3、DataLen:即数据长度,它指的是InputData的总长度。
4、CmacOut:即AES-128-CMAC计算输出结果。
需要注意的是,这个算法的计算结果长度固定是16Byte。
4.4 报文类型
如果每个ECU都自己管理自己的新鲜度值,都以自己的新鲜度值为准。这就会导致一些问题。就以ResetCnt的计时来说,总线上由数十个ECU,如果每个ECU都自己计时自己的,那么,各个ECU的计时偏差一定是存在的,ECU单次运行的越久,偏差则越大。因此,SecOC功能中规定,新鲜度值的TripCnt和ResetCnt只由总线中固定1个ECU管理。
而这个管理新鲜度值的TripCnt和ResetCnt的ECU,就是主节点(Master),其它的ECU则是从节点(Slave)。
4.4.1 SecOC同步报文
主节点通过发送同步报文的方式告诉从节点当前的TripCnt和ResetCnt,否则从节点搞不到完整的新鲜度值,就要罢工了。
同步报文的结构如下:
需要注意的是,同步报文也是跟其它SecOC报文一样,是需要被加密的。
即跟我们前面说的SecOC报文一样,同步报文也是由:待校验数据 + 校验结果组成。
同步报文中的TripCounter和ResetCounter是完整的,不是截取的。
关于TripCnt和ResetCnt,Master和Slave的初始值是不一样。
TripCnt和ResetCnt,对于Master ECU,初始值都是1,对于Slave ECU,初始值都是0。
并且,无论主从节点,TripCnt都需要实现下电存储(只要发送方不存 TripCnt,所有上电前的有效报文都可以被重放,接收方不存,则会拒绝服务或者被重放攻击)。
同步报文如上图所示,包含行程计数器和重置计数器以及授权码,授权码由SecOC计算追加,用于校验同步计数器“TripCnt |ResetCnt”值的完整性和真实性校验。
行程计数器:主节点每次上电、唤醒(可包含复位)和检测到新的通讯安全从节点加入网络通信时使发送的行程计数器 1,第二帧和第三帧保持不变,连发三帧,间隔50ms;之后按1s周期发送。发送属性根据项目需求可自定义。
重置计数器:同步报文每次发送第一帧时加1,第二帧第三帧保持不变。
同步报文发送时序图:
同步报文接收时序图:
4.4.2 SecOC的同步请求报文
如果某个时刻,有个Slave节点出现了BusOff,并且BusOff好几分钟,然后恢复了。而这个Slave节点恢复之后是需要发送或者接收SecOC报文的,但是Slave节点记录着的新鲜度值早就“不新鲜”了。这可咋办,Slave节点总不能先罢工,干等着Master下一次发同步报文吧。
因此,Slave节点这时就需要主动去请求Master发同步报文。这条报文就叫做同步请求报文。至于同步请求报文的格式,这个就完全看项目了。但一般情况下,同步报文都是不需要进行加密的。
如同步请求报文格式可以为:CANID为0x450,报文长度固定为8,Byte0固定为0x88,Byte1~Byte7固定为0x00。
当Master节点收到同步请求时,立即向外发送同步报文,且ResetCnt+1。
4.5 SecOC通信过程
Secured IPdu的发送(构建)
创建一个Secured IPdu分为以下六步:
- 准备Secured IPdu,分配所需buffer
- 获取待构建数据,也即Data ID,Authentic IPdu还有新鲜值
- 生成验证码
- 构建Secured IPdu
- 增加新鲜值
- 发送Secured IPdu
Secured IPdu的接收(验证)
Secured IPdu的验证也分为六步:
- 解析Authentic IPdu,新鲜值和验证码
- 从新鲜值管理器获取新鲜值
- 获取待验证数据
- 检查验证信息
- 给新鲜值管理器发送确认
- 将Authentic IPdu传给上层
4.6 FVM
4.6.1 新鲜度值的构建
先了解一下下面几个名词:
1、 Latest value:最新的值,来自于主节点的同步消息,包括: TripCnt, RstCnt;
2.、Previous value:先前的值,成功发送和成功接收安全报文时维护的新鲜度值;
3、 Receive value:接收的安全报文的值,包括: MsgCnt Lower, Reset Flag;
对于发送报文的新鲜值构建:
对于接收报文的新鲜值维护:
主要分为三个步骤
step1 : 先比较ResetFlag,判断同步消息和接收数据的关系:
| 情况 | 数量关系 (Received Value 相对于 Latest Value) | 状态描述 | 丢失同步实体 & 次数 |
|---|---|---|---|
| 1 | Received = Latest | 同一个 RstCycle 内正常接收数据,完全同步。 | 无丢失 |
| 2 | Received = Latest - 1 | RstCycle 临界点(如发送方刚复位),发送方还未更新计数器;或线路丢帧。 | 发送方丢失一次同步 |
| 3 | Received = Latest + 1 | RstCycle 临界点(如接收方刚复位),接收方还未更新记录,而发送方已正常递增。 | 接收方丢失一次同步 |
| 4 | Received = Latest - 2 | 发送方连续丢帧或滞后,接收到的值比记录值小 2。 | 发送方丢失两次同步 |
| 5 | Received = Latest + 2 | 接收方连续丢帧或滞后,收到的值比记录值大 2。 | 接收方丢失两次同步 |
step2: 比较Trip counter and reset counter
step3: 比较Message counter (lower end)
对接受节点的新鲜度值构造做一个总结:
- 比较接受到的Reset Flag和最新的Reset Flag,获得差值X(哪个节点存在同步消息丢失)
- 代入X并比较最新的TripRest和先前的TripReset,判断是否更新Trip,Reset
- 比较接受的MsgCnt Lower和先前的MsgCnt Lower,判断是否进位MsgCnt Upper
4.6.2 FVM 接口
Std_ReturnTypeFvm_SetTripResetSyncMsg(uint16 syncId,uint32 tripcnt,uint32 resetCnt);Std_ReturnTypeFvm_GetTripResetSyncMsg(uint16 syncId,uint32*tripCnt,uint32*resetCnt);voidFvm_ResetTripCounter(void);uint32Fvm_IncreaseTripCounter(uint16 syncId);voidFvm_Init(constFvm_RWFunc*func);typedefStd_ReturnType(*Fvm_WriteTripFunc)(uint16 tripId,uint32 tripCounter);typedefStd_ReturnType(*Fvm_ReadTripFunc)(uint16 tripId,uint32*tripCounter);uint32Fvm_GetRxMsgCnt(uint16 freshnessValueID);参考资料
- 一文读懂 AUTOSAR SecOC 通讯