目录
1.为什么要提SecOC
2.SecOC基本原理
2.1 参与到MAC计算的数据有哪些
2.2 新鲜度值如何管理
3.SecOC与各模块关联关系
1.为什么要提SecOC
在车载网络技术里,大家基本都是从CAN开始入门。在CAN DBC里,我们总能看到有些报文除了自带有效payload外,还携带Checksum和Rolling counter等信号。例如,标准CAN报文Byte0用于存放checksum,Byte7低4位用于存放Rolling Counter,如下:
Rolling counter一般是一个循环单调递增计数器,例如在0~15循环递增,可以用于分析发送方是否出现死机、报文是否丢帧等问题;Checksum主要对有效信号和counter进行计算得到一个校验值,用于确认有效信号是否完整。
但是我们回过头来想,该机制不仅仅可以针对板端之间的报文级别进行保护,在同一中ECU中不同功能安全等级任务进行数据交互时,也可以进行针对信号级别的数据进行保护。
因此该机制在AUTOSAR中得到了进一步升华,那就是我们做功能安全必须考虑的E2E(End to End) Transformer,该模块保证了即使在QM等级通信栈的数据传输也是安全可靠,如下图所示:
但是随着汽车信息安全在车控类ECU的普及,E2E机制出现了一些小小的漏洞,例如,
- 如何证明接收到的报文的身份有效性?
- 如何以公认的方式来证明checksum计算机制没有后门或者漏洞?
- 如何保证在CanFD组包中没有受E2E保护的信号的数据完整性?
这些问题可以在后续SecOC(Secure Onboard Communication)讲解中得到答案。
2.SecOC基本原理
首先给出AutoSAR E2E和SecOC各自的用法:
- E2E:面向功能安全(Safety),用于保护与功能安全相关的数据传输,颗粒度可以到信号Signal级别;
- SecOC:面向信息安全(Security),为PDU级别的关键数据提供数据完整性和身份的认证机制。
SecOC针对PDU级别的数据完整性和身份认证,在文档中是使用MAC验证的的对称身份方法,其原理如下图:
发送方将待认证数据(I-PDU)、SecoOC内部Data ID结合新鲜度值(Freshness),使用对称密钥计算得到一个MAC值,然后将原始数据、截断后的FV、截断后的MAC组成一个完整报文后发送给接收方;
接收方接收到完整报文后,首先判断新鲜度值是否满足条件,满足后将原始数据结合内部维护对应PUD-ID、新鲜度值使用相同密钥进行MAC计算,最后根据配置截断MAC值,与接收到的MAC进行比较,从而确认接收报文的完整性和身份有效性。
下图为DBC中带SecOC属性的报文示例:
在上述过程中,我们可以发现,SecOC能够有效保证数据安全最关键的步骤有如下几方面:
- 参与到MAC计算的数据有哪些?
- MAC计算使用什么算法?
- 报文新鲜度值管理方式
2.1 参与到MAC计算的数据有哪些
根据文档说明,参与到MAC计算的数据包括:SecOC DataID、原始真实数据(Authentic I-PDU data)、完整的新鲜度值,如下图:
- Data ID表示的是对应的PDU ID,例如上图示例SCP_Data ID 683;
- Authentic I-PDU data表示真实原始数据;
- Freshness表示当前报文的新鲜度值,主要用于防止报文的重放攻击;
最关键的在于报文新鲜度值的管理,很多时候我们遇到SecOC报文校验失败的问题都来源于报文新鲜度值的问题。
2.2 新鲜度值如何管理
新鲜度值提出的目的主要为了防止重放攻击、判断是否出现丢帧等情况,常见的表达方式有基于计数(Freshness Counter,和rolling counter很类似)、基于时间戳(Timestamp)。
在实际工程应用时,常见的SecOC通讯场景多为域间的通信,如下:
这就存在一个问题:如何保证新鲜度值在初始状态是统一的?
为此,SecOC提出了新鲜度值同步报文的概念。一般来讲,发送新鲜度值同步报文的节点叫做 FvM Master ECU, 接收新鲜度值同步报文的节点叫FvM Slave ECU。Slave接收到同步报文后会根据报文内容更新各种新鲜度值计数器值,从而保证后续新鲜度值的基准是统一且有身份认证的。
新鲜度值同步报文的格式如下:
这里面有两个非常关键的计数器,Trip Counter和Reset Counter,先记住它,验证码其实就是使用同样密钥和对称算法进行的MAC计算,整体报文在DBC layout如下图所示:
因此,我们在分析SecOC相关问题时,首先确认Master ECU(多为网关)是否发送了同步报文,确认Master和Slave完成握手同步后再分析是否是MAC、密钥、FvM计数等问题。
在了解同步报文作用之后,我们来看看新鲜度值到底长什么样。
在SecOC文档里,Freshness Value Management建议由SWC进行实现,但在我们实际遇到的基础软件包里,大多都集成了FvM这个模块,并且普遍推荐基于计数的方式(其他两种方式暂不在本文范围内),因此首先来看看新鲜度值在SecOC文档如何定义的。
在11.4.1.1章节,新鲜度值结构定义如下:
新鲜度值长度总计为8个Bytes,在该结构里定义了多种计数器,将标准里的示例总结如下(如有不同,请参考自家定义的用法),如下表所示:
- Trip Counter:同步计数器,由Master ECU自增,Slave ECU仍需保存和维护;该计数器一般是IG-ON或者FvM初始化自增1,主要表征一个上电周期,很利于问题分析;
- Reset Counter:重置计数器,也是由Master ECU周期自增1,一般这个周期为秒级;
- Message Counter:消息计数器,发送方每次成功发送报文后自增1;
- Reset Flag:与Reset Counter低位同步。
根据之前对新鲜度值同步报文的介绍,Trip Counter和Reset Counter均是由Master ECU同步给Slave,但是Slave仍要保持上述两值到NvM中,以便比较Master ECU给过来的值是否符合逻辑(实车时经常发现Mater ECU Trip Counter小于Slave的情况)。
Message Counter又分为MsgCntUpper和MsgCntLower,其中比较关键的是MsgCntLower,因为它要与Reset Flag作为被截断的Fv,参与到最终安全PDU的组包当中。
新鲜度值最终是需要参与到SecOC模块构建发送PDU、校验接收安全PDU,因此针对报文的新鲜度值构建过程就尤为重要,以构建发送消息为例:
在新鲜度值同步成功之后(重置周期内),正常情况下,TripCnt和ResetCnt都会保持不变,此时用于发送的安全PDU构建新鲜度值,就只会有一个变化,就是MsgCnt会自增1,发送出去的新鲜度值(假设14bitMsgCnt低位+2bit重置低位)会出现每次自增4的现象。
在达到重置周期后,TripCnt不变,ResetCnt自增1,那么新鲜度值会出现如下现象:
3.SecOC与各模块关联关系
SecOC作为一个信息安全校验模块,其在基础软件层次结构如下:
以接收安全PDU为例:CAN报文经由CanIf传到PduR层,再有PduR路由至SecOC模块,SecOC从FvM获取目标CAN报文新鲜度值后构建待校验数据,再调用Crypto Stack相关接口,经由CSM->CryIf->Crypto Driver,将数据进行MAC计算,最终比较MAC值,如不一致直接丢弃。
作为科普,到这个程度已经差不多了,如果要深入到相关开发,那就必须仔细研究FvM的机制,例如Master、Slave ECU对于FvM的处理机制,对于新鲜度值同步报文的处理方式,例如Slave没有收到Master的同步报文应该如何处理?Master同步报文的计数器比Slave的存的计数器值还小该如何处理?接收的安全PDU的MsgCnt出现了异常是直接丢弃还是需要继续做逻辑处理?
这些问题后面有时间再具体详谈吧!