SOME/IP开源库Vsomeip E2E保护实现分析
1. 背景
E2E保护是autosar标准中定义的,主要是为了保护通信安全(功能安全相关)。因此在原有的通信协议上增加了对应E2E的保护头部分。相关E2E会修改整体的通信协议的payload部分,因此如果需要支持E2E保护,那么通信双方都需要增加E2E的保护机制。
E2E保护其实主要是在原有的包中增加了CRC校验的部分来保证消息的完整性(从安全角度来说,并不能完全保证),以及增加对应的引用计数,来判断消息是否有缺失,重复等等现象。
1.1. autosar描述profile4
在E2E profile4中,用户数据布局(要保护的数据的布局)不受端到端加密配置文件4的约束——只有一个要求,即要保护的数据长度是1字节的倍数。
上面所示的位编号表示位传输的顺序。 端到端加密报头字段(例如端到端加密计数器)被编码为:
1. 大端(最重要的字节在前面)-由profile规定
2. LSB第一(字节内最低有效位第一)——由TCPIP总线强制
例如,端到端加密计数器的16位按照以下顺序(数字越大,意义越大)传输:8 9 10 11 12 13 14 15 0 12 3 4 5 6 7。
通过配置整个端到端加密头的偏移量,头可以放置在受保护数据中的特定位置。
1.1.1. Counter
在 E2E Profile 4 中,计数器由 E2E Profile 初始化、递增、重置和检查。 计数器不被 E2E 监管的调用者操纵或使用。
[PRS_E2E_00478] 在 E2E 配置文件 4 中,在发送方,对于数据元素的第一个传输请求,计数器应初始化为 0,并应为每个后续发送请求递增 1。 当计数器达到最大值(0xFF’FF)时,它会以 0 重新开始下一次发送请求。(RS_E2E_08539)
注意:此规范以前被错误地标识为 PRS_E2EProtocol_00324。
请注意,计数器值 0xFF’FF 并未保留为特殊的无效值,而是用作普通计数器值。
1.1.2. Data ID
唯一的Data id用于验证每个传输的与安全相关的数据元素的身份。
[PRS_E2E_00326] 在端到端加密配置文件4中,数据ID需要明确的传输,即作为传输端到端加密头的一部分。
[PRS_E2E_UC_00327] 在端到端配置文件4中,数据id应该在通信系统网络中是全局唯一的(由多个ecu组成,每个ecu发送不同的数据)。
在使用端到端监管来保护数据元素(即来自RTE的调用)的情况下,由于通信的多重性(1:1或1:N),数据元素的消费者只期望一个特定的数据元素,该数据元素由端到端监管使用数据ID检查。
在使用端到端加密监管来保护消息(例如来自COM的调用)的情况下,接收端COM只希望收到一个特定的消息,该消息由端到端加密监管使用数据ID进行检查。
1.1.3. Length
引入Length字段是为了支持可变大小的长度——存储序列化数据的Data[]数组在每个周期中可能有不同的长度。 长度包括用户数据+端到端加密头(CRC + Counter + Length + DataID)。
1.1.4. CRC
E2E Profile 4 使用 32 位 CRC,以确保高检测率和高汉明距离。
[PRS_E2E_00329] dE2E Profile 4 应使用 SWS CRC Supervision 的 Crc_CalculateCRC32P4() 函数来计算 CRC.c(RS_E2E_08528, RS_E2E_- 08539)
注意:E2E Profile 4 使用的 CRC 与 FlexRay、CAN 和 TCP/IP 使用的 CRC 不同。 它还由不同的软件模块提供(FlexRay、CAN 和 TCP/IP 堆栈 CRC/校验和由通信控制器中的硬件支持或通信堆栈软件提供,但不由 CRC Supervision 提供)。
[PRS_E2E_00330] d在 E2E Profile 4 中,CRC 应在整个 E2E 标头(不包括 CRC 字节)和用户数据上计算。c(RS_E2E_08531)
1.1.5. Timeout detection
前面提到的机制(CRC、计数器、数据 ID、长度)能够检查接收到的数据元素的有效性,当接收器独立于数据传输执行时,即当接收器没有被阻塞等待数据元素或消息时,但是 相反,如果接收器读取当前可用的数据(即检查新数据是否可用)。 然后,通过计数器,接收器可以检测到通信丢失和超时。
1.1.6. 创建E2E-header
1.1.6.1. E2E_P04Protect
函数 E2E_P04Protect() 执行本节中以下九个图表指定的步骤。
[PRS_E2E_00362] d 函数 E2E_P04Protect() 应具有如图 6.28.c (RS_E2E_08539) 所示的整体行为
[PRS_E2E_00363] d E2E_P04Protect() 中的“验证保护功能的输入”步骤的行为如图 6.29.c (RS_E2E_08539)
[PRS_E2E_00376] d E2E_P04Protect()、E2E_P04Forward()和E2E_P04Check()中的“计算偏移量”步骤的行为如图6.30.c (RS_E2E_08539)所示。
[PRS_E2E_00364] d E2E_P04Protect()和E2E_P04Forward()中的步骤“Write Length”的行为如图6.31.c (RS_E2E_08539)所示。
offset 计算本地变量Uint16偏移量。 单位是[byte]
2. 现状
目前vsomeip主要以插件的形式增加了E2E保护的相关机制
3. 初始化
通过代码可以看到,整个E2E保护的部分,主要加载在routing进程中,因此对于客户端来说,无需关注具体E2E的实现,只需要在使用时打开对应的开关即可。
3.1. 加载E2E插件
#ifndef ANDROID//e2e功能是否配置了if( configuration_->is_e2e_enabled()) {VSOMEIP_INFO << "E2E protection enabled.";const char *its_e2e_module = getenv(VSOMEIP_ENV_E2E_PROTECTION_MODULE);//这里没有指定对应的E2E库的话,默认使用someip的std::string plugin_name = its_e2e_module != nullptr ? its_e2e_module : VSOMEIP_E2E_LIBRARY;auto its_plugin = plugin_manager::get()->get_plugin(plugin_type_e::APPLICATION_PLUGIN, plugin_name);if (its_plugin) {VSOMEIP_INFO << "E2E module loaded.";e2e_provider_ = std::dynamic_pointer_cast<e2e::e2e_provider>(its_plugin);}}if(e2e_provider_) {std::map<e2exf::data_identifier_t, std::shared_ptr<cfg::e2e>> its_e2e_configuration = configuration_->get_e2e_configuration();for (auto &identifier : its_e2e_configuration) {//添加对应的配置信息if(!e2e_provider_->add_configuration(identifier.second)) {VSOMEIP_INFO << "Unknown E2E profile: " << identifier.second->profile << ", skipping ...";}}}
#endif
3.2. 通过配置文件确定需要加载的profile
//根据配置信息确定使用的profile
bool e2e_provider_impl::add_configuration(std::shared_ptr<cfg::e2e> config)
{if (config->profile == "CRC8" || config->profile == "P01") {process_e2e_profile<profile01::profile_config, profile01::profile_01_checker, profile01::protector>(config);return true;}if (config->profile == "CRC32" || config->profile == "CSTM") {process_e2e_profile<profile_custom::profile_config, profile_custom::profile_custom_checker, profile_custom::protector>(config);return true;}if (config->profile == "P04") {process_e2e_profile<profile04::profile_config, profile04::profile_04_checker, profile04::protector>(config);return true;}return false;
}
4. 消息保护
由于E2E主要时保护跨设备进行通信的,因此对于vsomeip整体的架构,本地的IPC通信就不需要E2E的保护了。
bool routing_manager_impl::send(client_t _client, const byte_t *_data,length_t _size, instance_t _instance, bool _reliable,client_t _bound_client,credentials_t _credentials,uint8_t _status_check, bool _sent_from_remote)
E2E保护部分代码实现。首先根据之前加载的配置文件中的信息判断当前的serviceid和methodid是否需要E2E保护。其次通过调用E2E的protect函数计算出E2E的头部信息,然后增加在data前面。
if (e2e_provider_) {if ( !is_service_discovery) {service_t its_service = VSOMEIP_BYTES_TO_WORD(_data[VSOMEIP_SERVICE_POS_MIN], _data[VSOMEIP_SERVICE_POS_MAX]);method_t its_method = VSOMEIP_BYTES_TO_WORD(_data[VSOMEIP_METHOD_POS_MIN], _data[VSOMEIP_METHOD_POS_MAX]);
#ifndef ANDROIDif (e2e_provider_->is_protected({its_service, its_method})) {// Find out where the protected area startssize_t its_base = e2e_provider_->get_protection_base({its_service, its_method});// Build a corresponding bufferits_buffer.assign(_data + its_base, _data + _size);e2e_provider_->protect({ its_service, its_method }, its_buffer, _instance);// Prepend headerits_buffer.insert(its_buffer.begin(), _data, _data + its_base);_data = its_buffer.data();}
#endif}}
5. 消息验证
消息的验证主要是在收到消息阶段,因此也是在routing进程里面。
void routing_manager_impl::on_message(const byte_t *_data, length_t _size,endpoint *_receiver, const boost::asio::ip::address &_destination,client_t _bound_client, credentials_t _credentials,const boost::asio::ip::address &_remote_address,std::uint16_t _remote_port) {
收到消息后,进行验证
if (e2e_provider_) {its_method = VSOMEIP_BYTES_TO_WORD(_data[VSOMEIP_METHOD_POS_MIN],_data[VSOMEIP_METHOD_POS_MAX]);
#ifndef ANDROIDif (e2e_provider_->is_checked({its_service, its_method})) {auto its_base = e2e_provider_->get_protection_base({its_service, its_method});e2e_buffer its_buffer(_data + its_base, _data + _size);e2e_provider_->check({its_service, its_method},its_buffer, its_instance, its_check_status);if (its_check_status != e2e::profile_interface::generic_check_status::E2E_OK) {VSOMEIP_INFO << "E2E protection: CRC check failed for service: "<< std::hex << its_service << " method: " << its_method;}}
#endif}
6. 配置文件
相关的配置文件例子可以直接看源码目录下:test/e2e_tests/conf下面
service的配置:
"e2e": {"e2e_enabled": "true","protected": [{"service_id": "0x0011","event_id": "0x0033","profile": "P04","variant": "protector","crc_offset" : "64","data_id" : "0x2d"}]}
client的配置:
"e2e": {"e2e_enabled": "true","protected": [{"service_id": "0x0011","event_id": "0x0033","profile": "P04","variant": "checker","crc_offset" : "64","data_id" : "0x2d"}]}
7. 包结构
在没有加入E2E保护时的包内容如下:
client发出来的request包
server发送的response包:
加入E2E之后的包内容:
原始数据:
service回复的内容:
可以看到加上E2E保护时,根据profile4的标准长度,是会覆盖掉data的前12个字节。(这部分查了好久,以为是bug了。结果去看了对应的e2e的测试用例才发现,这里是需要开发者自己关注的,在数据前需要预留足够的空间给到E2E头的位置)。
这里还有一个问题,就是profile4用的someip head是8byte,因此在计算CRC的时候,offset必须指定大于64,否则会覆盖掉部分头信息。
SOME/IP开源库Vsomeip E2E保护实现分析相关推荐
- SOME/IP开源库Vsomeip分析4-服务注册过程
前言 前面主要对vsomeip中helloworld程序运行进行了分析,本篇文章主要针对helloworld运行时的服务注册过程进行深入分析. hello_world_service::offer_s ...
- 再见ip.taobao,全网显示 IP 归属地,用上这个开源库,实现也太简单了!
细心的朋友应该会发现,最近,继新浪微博之后,头条.腾讯.抖音.知乎.快手.小红书等各大平台陆陆续续都上线了"网络用户IP地址显示功能",境外用户显示的是国家,国内的用户显示的省份, ...
- 全网显示 IP 归属地,用上这个开源库,实现也太简单了
细心的小伙伴可能会发现,最近蘑菇新上线了 IP 属地的功能,小伙伴在发表动态.发表评论以及聊天的时候,都会显示自己的 IP 属地信息 编辑切换为居中 添加图片注释,不超过 140 字(可选) 动态 ...
- 全网显示 IP 归属地,可以考虑这个开源库
最近微博等平台都上线 IP 属地功能. 下面,我就来讲讲,Java 中是如何获取 IP 属地的,主要分为以下几步 通过 HttpServletRequest 对象,获取用户的 IP 地址 通过 IP ...
- 银行木马卷土重来、开发者破坏开源库影响数千应用程序|1月10日全球网络安全热点
安全资讯报告 银行木马Flubot Android恶意软件卷土重来 FluBot是一种适用于Android的银行恶意软件,它通过向全球多家银行提供覆盖登录表单来窃取密码.新的攻击假冒Adobe应用程序 ...
- 【整理】PJSIP开源库详解
PJSIP是一个包含了SIP.SDP.RTP.RTCP.STUN.ICE等协议实现的开源库.它把基于信令协议SIP的多媒体框架和NAT穿透功能整合成高层次.抽象的多媒体通信API,这套API能够很容易 ...
- C++流媒体开源库Live555详细介绍
目录 1.Live555简介 2.Live555源码目录说明 3.Live555中的关键概念与流程介绍 3.1.liveMedia的运转 3.2.RTSP介绍 3.3.RTSP连接的建立 3.4.DE ...
- 推荐一些嵌入式、C/C++的开源库和项目
前言 想用代码实现一个功能时,我们可以先看看是否有前辈已经实现了该功能,并且开源分享在网上.一般我们自己造出来的轮子的可用性基本上是很难和大神们造的轮子相比的. 因此多了解一下优秀的开源库的使用,可以 ...
- 常用C/C++开源库
1. 框架 Apache C++ Standard Library : 是一系列算法,容器,迭代器和其他基本组件的集合 ASL : Adobe源代码库提供了同行的评审和可移植的C++源代码库. Boo ...
最新文章
- MySQL-入门安装
- oracle 库not null,oracle平添not null约束
- caffe:制作自己的数据集train.txt和val.txt,生成lmdb文件
- python中的ftplib模块
- excel实时获取基金信息的实现方法
- JavaScript之全局函数详解
- 攻防世界 Web_php_include write up
- lammps教程:单原子温度计算及输出方法
- 如何搭建一个uni-app项目并运行
- 单片机引脚浮空输入注意事项-STM32
- 【WinHex篇】WinHex跳过坏扇区制作磁盘镜像
- 电商后台管理系统订单列表模块
- ftp服务器的搭建与使用
- java实现生成二维码
- 开发你自己的Android 授权管理器 (AccountManager的使用以及应用场景)
- 罗素问题 ——来自知乎大神
- Linux 命令(212)—— ssh-add 命令
- web前端高级JavaScript - 前端web高级开发知识体系课程大纲
- L9935_二相步进电机驱动器
- 计算机网可靠性,计算机网络可靠性分析