Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Additions to cross-layer interfaces according to the ETSI standards #105

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions tools/benchmark/cases/security/signing.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ int SecuritySigningCase::execute()
EncapRequest initial_encap_request;
initial_encap_request.plaintext_payload = packet;
initial_encap_request.its_aid = aid::CA;
initial_encap_request.permissions = ByteBuffer { 1, 0, 0 };
security_entity.encapsulate_packet(std::move(initial_encap_request));
}

Expand All @@ -68,8 +69,10 @@ int SecuritySigningCase::execute()
EncapRequest encap_request;
encap_request.plaintext_payload = packet;
encap_request.its_aid = aid::CA;
encap_request.permissions = ByteBuffer { 1, 0, 0 };

EncapConfirm encap_confirm = security_entity.encapsulate_packet(std::move(encap_request));
assert(encap_confirm.sec_packet);
}

std::cout << "[Done]" << std::endl;
Expand Down
7 changes: 5 additions & 2 deletions tools/benchmark/cases/security/validation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ int SecurityValidationCase::execute()
EncapRequest initial_encap_request;
initial_encap_request.plaintext_payload = packet;
initial_encap_request.its_aid = aid::CA;
initial_encap_request.permissions = ByteBuffer { 1, 0, 0 };
entities[0]->encapsulate_packet(std::move(initial_encap_request));
}

Expand All @@ -81,10 +82,12 @@ int SecurityValidationCase::execute()
EncapRequest encap_request;
encap_request.plaintext_payload = packet;
encap_request.its_aid = aid::CA;
encap_request.permissions = ByteBuffer { 1, 0, 0 };

EncapConfirm encap_confirm = entities[i]->encapsulate_packet(std::move(encap_request));
secured_messages[i] = encap_confirm.sec_packet;
auto signer_info = encap_confirm.sec_packet.header_field<HeaderFieldType::Signer_Info>();
assert(encap_confirm.sec_packet);
secured_messages[i] = *encap_confirm.sec_packet;
auto signer_info = encap_confirm.sec_packet->header_field<HeaderFieldType::Signer_Info>();

if (signer_info_type == "hash") {
assert(signer_info && get_type(*signer_info) == SignerInfoType::Certificate_Digest_With_SHA256);
Expand Down
2 changes: 2 additions & 0 deletions tools/socktap/application.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,9 @@ void initialize_request(const Application::DataRequest& generic, geonet::DataReq
{
geonet.upper_protocol = geonet::UpperProtocol::BTP_B;
geonet.communication_profile = generic.communication_profile;
geonet.security_profile = generic.security_profile;
geonet.its_aid = generic.its_aid;
geonet.permissions = generic.permissions;
if (generic.maximum_lifetime) {
geonet.maximum_lifetime = generic.maximum_lifetime.get();
}
Expand Down
3 changes: 3 additions & 0 deletions tools/socktap/cam_application.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#include <vanetza/btp/ports.hpp>
#include <vanetza/asn1/cam.hpp>
#include <vanetza/asn1/packet_visitor.hpp>
#include <vanetza/common/byte_buffer.hpp>
#include <vanetza/facilities/cam_functions.hpp>
#include <boost/units/cmath.hpp>
#include <boost/units/systems/si/prefixes.hpp>
Expand Down Expand Up @@ -125,6 +126,8 @@ void CamApplication::on_timer(Clock::time_point)

DataRequest request;
request.its_aid = aid::CA;
request.permissions = ByteBuffer {1, 0, 0};
request.security_profile = security::SecurityProfile::Default;
request.transport_type = geonet::TransportType::SHB;
request.communication_profile = geonet::CommunicationProfile::ITS_G5;

Expand Down
5 changes: 5 additions & 0 deletions vanetza/btp/data_request.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#define DATA_REQUEST_HPP_BSJC1VFV

#include <vanetza/btp/header.hpp>
#include <vanetza/common/byte_buffer.hpp>
#include <vanetza/common/its_aid.hpp>
#include <vanetza/geonet/data_request.hpp>
#include <vanetza/geonet/destination_variant.hpp>
Expand All @@ -19,7 +20,11 @@ struct DataRequestGeoNetParams
geonet::TransportType transport_type;
geonet::DestinationVariant destination;
geonet::CommunicationProfile communication_profile;
decltype(geonet::DataRequest::security_profile) security_profile;
ItsAid its_aid;
boost::optional<ByteBuffer> permissions;
// TODO: Security context information (optional), Security target ID list (optional):
// Encryption is currently not supported
boost::optional<geonet::Lifetime> maximum_lifetime;
boost::optional<unsigned> maximum_hop_limit;
boost::optional<geonet::DataRequest::Repetition> repetition;
Expand Down
2 changes: 2 additions & 0 deletions vanetza/geonet/data_request.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,9 @@ void copy_request_parameters(const btp::DataRequestB& btp, DataRequest& gn)
{
gn.upper_protocol = geonet::UpperProtocol::BTP_B;
gn.communication_profile = btp.gn.communication_profile;
gn.security_profile = btp.gn.security_profile;
gn.its_aid = btp.gn.its_aid;
gn.permissions = btp.gn.permissions;
if (btp.gn.maximum_lifetime) {
gn.maximum_lifetime = *btp.gn.maximum_lifetime;
}
Expand Down
6 changes: 6 additions & 0 deletions vanetza/geonet/data_request.hpp
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
#ifndef DATA_REQUEST_HPP_3JYISVXB
#define DATA_REQUEST_HPP_3JYISVXB

#include <vanetza/common/byte_buffer.hpp>
#include <vanetza/common/its_aid.hpp>
#include <vanetza/geonet/address.hpp>
#include <vanetza/geonet/areas.hpp>
#include <vanetza/geonet/interface.hpp>
#include <vanetza/geonet/lifetime.hpp>
#include <vanetza/geonet/mib.hpp>
#include <vanetza/geonet/traffic_class.hpp>
#include <vanetza/security/encap_request.hpp>
#include <vanetza/units/time.hpp>
#include <boost/optional.hpp>
#include <boost/variant.hpp>
Expand Down Expand Up @@ -40,7 +42,11 @@ struct DataRequest

UpperProtocol upper_protocol;
CommunicationProfile communication_profile;
decltype(security::EncapRequest::sec_services) security_profile;
ItsAid its_aid;
boost::optional<ByteBuffer> permissions;
// TODO: Security context information (optional), Security target ID list (optional):
// Encryption is currently not supported
Lifetime maximum_lifetime;
boost::optional<Repetition> repetition;
unsigned max_hop_limit;
Expand Down
51 changes: 42 additions & 9 deletions vanetza/geonet/router.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include <vanetza/btp/data_indication.hpp>
#include <vanetza/btp/data_request.hpp>
#include <vanetza/common/byte_buffer.hpp>
#include <vanetza/common/its_aid.hpp>
#include <vanetza/common/position_fix.hpp>
#include <vanetza/common/runtime.hpp>
Expand All @@ -23,6 +24,7 @@
#include <vanetza/geonet/transport_interface.hpp>
#include <vanetza/geonet/extended_pdu.hpp>
#include <vanetza/geonet/secured_pdu.hpp>
#include <boost/optional.hpp>
#include <boost/units/cmath.hpp>
#include <functional>
#include <stdexcept>
Expand All @@ -40,10 +42,14 @@ struct ControlInfo
{
ControlInfo(const DataRequest request) :
communication_profile(request.communication_profile),
its_aid(request.its_aid) {}
security_profile(request.security_profile),
its_aid(request.its_aid),
permissions(request.permissions) {}

const CommunicationProfile communication_profile;
const decltype(security::EncapRequest::sec_services) security_profile;
const ItsAid its_aid;
const boost::optional<ByteBuffer> permissions;
};

template<typename PDU>
Expand Down Expand Up @@ -229,8 +235,14 @@ DataConfirm Router::request(const ShbDataRequest& request, DownPacketPtr payload
pdu->extended().source_position = m_local_position_vector;

// step 2: encapsulate packet by security
if (m_mib.itsGnSecurity) {
payload = encap_packet(ctrl.its_aid, *pdu, std::move(payload));
if (m_mib.itsGnSecurity && ctrl.security_profile) {
auto encap_result = encap_packet(ctrl.security_profile, ctrl.its_aid, *ctrl.permissions, *pdu, std::move(payload));
if (encap_result) {
payload = std::move(encap_result.get());
} else {
// TODO: How to throw an error here?
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As far as I know, no error reporting is foreseen at this point by specifications.
We may invoke a hook here so custom error logging can be realised without hassle.

return;
}
}

// step 5: execute media-dependent procedures
Expand Down Expand Up @@ -293,9 +305,15 @@ DataConfirm Router::request(const GbcDataRequest& request, DownPacketPtr payload
pdu->extended().source_position = m_local_position_vector;

// step 5: apply security
if (m_mib.itsGnSecurity) {
if (m_mib.itsGnSecurity && ctrl.security_profile) {
assert(pdu->basic().next_header == NextHeaderBasic::Secured);
payload = encap_packet(ctrl.its_aid, *pdu, std::move(payload));
auto encap_result = encap_packet(ctrl.security_profile, ctrl.its_aid, *ctrl.permissions, *pdu, std::move(payload));
if (encap_result) {
payload = std::move(encap_result.get());
} else {
// TODO: How to throw an error here?
return;
}
}

// step 6: repetition is already set-up before
Expand Down Expand Up @@ -707,10 +725,19 @@ void Router::on_beacon_timer_expired()
// Beacons originate in GeoNet layer, therefore no upper layer payload
DownPacketPtr payload { new DownPacket() };
auto pdu = create_beacon_pdu();
// GN-MGMT has no SSP defined
auto permissions = ByteBuffer {};

if (m_mib.itsGnSecurity) {
pdu->basic().next_header = NextHeaderBasic::Secured;
payload = encap_packet(aid::GN_MGMT, *pdu, std::move(payload));
// Use default security profile for beacons, see ETSI EN 302 636-4-1 v1.2.1, table 22
auto encap_result = encap_packet(security::SecurityProfile::Default, aid::GN_MGMT, permissions, *pdu, std::move(payload));
if (!encap_result) {
// TODO: Throw an error here? If so, how?
return;
} else {
payload = std::move(encap_result.get());
}
} else {
pdu->basic().next_header = NextHeaderBasic::Common;
}
Expand Down Expand Up @@ -1209,26 +1236,32 @@ std::unique_ptr<GbcPdu> Router::create_gbc_pdu(const GbcDataRequest& request)
return pdu;
}

Router::DownPacketPtr Router::encap_packet(ItsAid its_aid, Pdu& pdu, DownPacketPtr packet)
boost::optional<Router::DownPacketPtr> Router::encap_packet(boost::optional<security::SecurityProfile> security_profile, ItsAid its_aid, ByteBuffer permissions, Pdu& pdu, DownPacketPtr packet)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

return an empty pointer instead of a boost::optional?

{
security::EncapRequest encap_request;

DownPacket sec_payload;
sec_payload[OsiLayer::Network] = SecuredPdu(pdu);
sec_payload.merge(*packet, OsiLayer::Transport, max_osi_layer());
encap_request.plaintext_payload = std::move(sec_payload);
encap_request.sec_services = security_profile;
encap_request.its_aid = its_aid;
encap_request.permissions = permissions;

if (m_security_entity) {
security::EncapConfirm confirm = m_security_entity->encapsulate_packet(std::move(encap_request));
pdu.secured(std::move(confirm.sec_packet));
if (confirm.sec_packet) {
pdu.secured(std::move(*confirm.sec_packet));
} else {
return boost::none;
}
} else {
throw std::runtime_error("security entity unavailable");
}

assert(size(*packet, OsiLayer::Transport, max_osi_layer()) == 0);
assert(pdu.basic().next_header == NextHeaderBasic::Secured);
return packet;
return std::move(packet);
}

std::string stringify(Router::PacketDropReason pdr)
Expand Down
5 changes: 4 additions & 1 deletion vanetza/geonet/router.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include <vanetza/geonet/timestamp.hpp>
#include <vanetza/units/length.hpp>
#include <vanetza/units/time.hpp>
#include <vanetza/security/encap_request.hpp>
#include <vanetza/security/security_entity.hpp>
#include <boost/variant.hpp>
#include <cstdint>
Expand Down Expand Up @@ -492,11 +493,13 @@ class Router
/**
* \brief Encaspulate a packet according to security profile
*
* \param security_profile security service(s) to invoke
* \param aid ITS-AID
* \param permissions SSP required to sign the packet
* \param pdu PDU
* \param packet Packet with payload
*/
DownPacketPtr encap_packet(ItsAid aid, Pdu& pdu, DownPacketPtr packet);
boost::optional<DownPacketPtr> encap_packet(boost::optional<security::SecurityProfile> security_profile, ItsAid aid, ByteBuffer permissions, Pdu& pdu, DownPacketPtr packet);

/**
* \brief Create an initialized Single-Hop-Broadcast PDU
Expand Down
2 changes: 2 additions & 0 deletions vanetza/geonet/tests/router_indicate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ class RouterIndicate : public ::testing::Test

// create ShbDataRequest
geonet::ShbDataRequest request(mib, aid::CA);
request.permissions = ByteBuffer {1, 0, 0};
request.security_profile = security::SecurityProfile::Sign;
request.upper_protocol = geonet::UpperProtocol::IPv6;

// Router handles request
Expand Down
12 changes: 12 additions & 0 deletions vanetza/geonet/tests/router_request.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ TEST_F(RouterRequest, router_request)
{
// create ShbDataRequest
ShbDataRequest request(mib, aid::CA);
request.permissions = ByteBuffer {1, 0, 0};
request.security_profile = security::SecurityProfile::Sign;
request.upper_protocol = UpperProtocol::IPv6;

// Router handles request
Expand Down Expand Up @@ -105,6 +107,8 @@ TEST_F(RouterRequest, modified_request_maximum_lifetime)
{
// create ShbDataRequest
ShbDataRequest request(mib, aid::CA);
request.permissions = ByteBuffer {1, 0, 0};
request.security_profile = security::SecurityProfile::Sign;

// create new Lifetime that is larger than the itsGnMaxPacketLifetime of mib
Lifetime large_lifetime(Lifetime::Base::Hundred_Seconds, 9);
Expand All @@ -121,6 +125,8 @@ TEST_F(RouterRequest, modified_request_repetition)
{
// create ShbDataRequest
ShbDataRequest request(mib, aid::CA);
request.permissions = ByteBuffer {1, 0, 0};
request.security_profile = security::SecurityProfile::Sign;

// create durations that will fail in data_confirm
auto rep_faulty_int = 0.0 * units::si::seconds; // this has to be lower than mib.itsGnMinPacketRepetitionInterval
Expand All @@ -143,6 +149,8 @@ TEST_F(RouterRequest, modified_request_payload_null)
{
// create ShbDataRequest
ShbDataRequest request(mib, aid::CA);
request.permissions = ByteBuffer {1, 0, 0};
request.security_profile = security::SecurityProfile::Sign;
request.upper_protocol = UpperProtocol::IPv6;

// Router handles request
Expand All @@ -166,6 +174,8 @@ TEST_F(RouterRequest, modified_request_large_payload)

// create ShbDataRequest
ShbDataRequest request(mib, aid::CA);
request.permissions = ByteBuffer {1, 0, 0};
request.security_profile = security::SecurityProfile::Sign;
request.upper_protocol = UpperProtocol::IPv6;

// Router handles request
Expand All @@ -176,6 +186,8 @@ TEST_F(RouterRequest, modified_request_large_payload)
TEST_F(RouterRequest, shb_repetition)
{
ShbDataRequest request(mib, aid::CA);
request.permissions = ByteBuffer {1, 0, 0};
request.security_profile = security::SecurityProfile::Sign;
request.repetition = DataRequest::Repetition {
0.1 * units::si::seconds, 10.0 * units::si::seconds
};
Expand Down
Loading