Skip to content

Commit

Permalink
security: refactor decapsulation service
Browse files Browse the repository at this point in the history
Among others, this change avoids misalignments between VerificationReport
and DecapReport as pointed out by #228
  • Loading branch information
riebl committed Oct 14, 2024
1 parent 07c70c1 commit 259f0bb
Show file tree
Hide file tree
Showing 12 changed files with 212 additions and 141 deletions.
6 changes: 5 additions & 1 deletion vanetza/geonet/data_indication.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,18 @@
#include <vanetza/geonet/destination_variant.hpp>
#include <vanetza/geonet/interface.hpp>
#include <vanetza/geonet/position_vector.hpp>
#include <vanetza/security/decap_confirm.hpp>
#include <vanetza/security/decap_service.hpp>
#include <boost/optional.hpp>

namespace vanetza
{
namespace geonet
{

/**
* \brief GN-DATA.indication
* \see EN 302 636-4-1 V1.4.1, section J.4
*/
struct DataIndication
{
UpperProtocol upper_protocol;
Expand Down
34 changes: 9 additions & 25 deletions vanetza/geonet/router.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -409,11 +409,10 @@ void Router::indicate_basic(IndicationContextBasic& ctx)
indication.remaining_hop_limit = basic->hop_limit;

if (basic->next_header == NextHeaderBasic::Secured) {
indication.security_report = security::DecapReport::Incompatible_Protocol;
indicate_secured(ctx, *basic);
} else if (basic->next_header == NextHeaderBasic::Common) {
if (!m_mib.itsGnSecurity || SecurityDecapHandling::Non_Strict == m_mib.itsGnSnDecapResultHandling) {
indication.security_report = security::DecapReport::Unsigned_Message,
indication.security_report = boost::blank {}; /*< not secured at all*/
indicate_common(ctx, *basic);
} else {
packet_dropped(PacketDropReason::Decap_Unsuccessful_Strict);
Expand Down Expand Up @@ -504,31 +503,16 @@ void Router::indicate_secured(IndicationContextBasic& ctx, const BasicHeader& ba
secured_payload_visitor visitor(*this, ctx, basic);

// check whether the received packet is valid
if (DecapReport::Success == decap_confirm.report) {
if (is_successful(decap_confirm.report)) {
boost::apply_visitor(visitor, decap_confirm.plaintext_payload);
} else if (SecurityDecapHandling::Non_Strict == m_mib.itsGnSnDecapResultHandling) {
// according to ETSI EN 302 636-4-1 v1.2.1 section 9.3.3 Note 2
// handle the packet anyway, when itsGnDecapResultHandling is set to NON-Strict (1)
switch (decap_confirm.report) {
case DecapReport::False_Signature:
case DecapReport::Invalid_Certificate:
case DecapReport::Revoked_Certificate:
case DecapReport::Inconsistant_Chain:
case DecapReport::Invalid_Timestamp:
case DecapReport::Invalid_Mobility_Data:
case DecapReport::Unsigned_Message:
case DecapReport::Signer_Certificate_Not_Found:
case DecapReport::Unsupported_Signer_Identifier_Type:
case DecapReport::Unencrypted_Message:
// ok, continue
boost::apply_visitor(visitor, decap_confirm.plaintext_payload);
break;
case DecapReport::Duplicate_Message:
case DecapReport::Incompatible_Protocol:
case DecapReport::Decryption_Error:
default:
packet_dropped(PacketDropReason::Decap_Unsuccessful_Non_Strict);
break;
// Any packet is passed up with NON-STRICT decapsulation handling
// -> see ETSI EN 302 636-4-1 v1.4.1 Section 10.3.3 Note 3
if (!decap_confirm.plaintext_payload.empty()) {
boost::apply_visitor(visitor, decap_confirm.plaintext_payload);
} else {
// no payload extracted from secured message to pass up
packet_dropped(PacketDropReason::Decap_Unsuccessful_Non_Strict);
}
} else {
// discard packet
Expand Down
3 changes: 2 additions & 1 deletion vanetza/geonet/tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ add_gtest(PositionUpdater position_updater.cpp)
add_gtest(PositionVector position_vector.cpp)
add_gtest(Repeater repeater.cpp)
add_gtest(Router router.cpp)
add_gtest(RouterIndicate router_indicate.cpp)
add_gtest(RouterIndicate router_indicate.cpp
INCLUDE_DIRECTORIES ${PROJECT_SOURCE_DIR}/vanetza/security/tests)
add_gtest(SequenceNumber sequence_number.cpp)
add_gtest(Timestamp timestamp.cpp)
add_gtest(TrafficClass traffic_class.cpp)
Expand Down
6 changes: 4 additions & 2 deletions vanetza/geonet/tests/router_indicate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
#include <vanetza/geonet/tests/fake_interfaces.hpp>
#include <vanetza/geonet/tests/security_context.hpp>

#include "decap_report_printer.hpp"

using namespace vanetza;

class RouterIndicate : public ::testing::Test
Expand Down Expand Up @@ -443,7 +445,7 @@ TEST_F(RouterIndicate, shb_secured_v3_message_digest)
// assure that packet has been passed to transport layer
ASSERT_TRUE(ind_ifc.m_last_indication);
EXPECT_EQ(ind_ifc.m_last_indication->upper_protocol, geonet::UpperProtocol::BTP_B);
EXPECT_EQ(ind_ifc.m_last_indication->security_report, security::DecapReport::Success);
EXPECT_EQ(ind_ifc.m_last_indication->security_report, security::VerificationReport::Success);
EXPECT_EQ(ind_ifc.m_last_indication->its_aid, aid::CA);

ASSERT_TRUE(ind_ifc.m_last_packet);
Expand Down Expand Up @@ -508,7 +510,7 @@ TEST_F(RouterIndicate, shb_secured_v3_message_certificate)
// assure that packet has been passed to transport layer
ASSERT_TRUE(ind_ifc.m_last_indication);
EXPECT_EQ(ind_ifc.m_last_indication->upper_protocol, geonet::UpperProtocol::BTP_B);
EXPECT_EQ(ind_ifc.m_last_indication->security_report, security::DecapReport::Success);
EXPECT_EQ(ind_ifc.m_last_indication->security_report, security::VerificationReport::Success);
EXPECT_EQ(ind_ifc.m_last_indication->its_aid, aid::CA);

ASSERT_TRUE(ind_ifc.m_last_packet);
Expand Down
1 change: 1 addition & 0 deletions vanetza/security/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ add_vanetza_component(security
backend.cpp
backend_null.cpp
cam_ssp.cpp
decap_service.cpp
delegating_security_entity.cpp
ecc_point.cpp
ecdsa256.cpp
Expand Down
57 changes: 0 additions & 57 deletions vanetza/security/decap_confirm.hpp

This file was deleted.

25 changes: 0 additions & 25 deletions vanetza/security/decap_request.hpp

This file was deleted.

42 changes: 42 additions & 0 deletions vanetza/security/decap_service.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
#include <vanetza/security/decap_service.hpp>
#include <boost/variant/static_visitor.hpp>

namespace vanetza
{
namespace security
{

bool is_successful(const DecapReport& report)
{
return report == VerificationReport::Success;
}

bool operator==(const DecapReport& decap, VerificationReport verification)
{
struct Visitor : public boost::static_visitor<bool>
{
Visitor(VerificationReport report) : expected(report) {}

bool operator()(VerificationReport report) const
{
return report == expected;
}

bool operator()(boost::blank) const
{
return false;
}

VerificationReport expected;
};

return boost::apply_visitor(Visitor(verification), decap);
}

bool operator==(VerificationReport verification, const DecapReport& decap)
{
return (decap == verification);
}

} // namespace security
} // namespace vanetza
82 changes: 82 additions & 0 deletions vanetza/security/decap_service.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
#ifndef F815BB22_3075_4A9D_9385_07876D800765
#define F815BB22_3075_4A9D_9385_07876D800765

#include <vanetza/common/its_aid.hpp>
#include <vanetza/net/packet_variant.hpp>
#include <vanetza/security/certificate_validity.hpp>
#include <vanetza/security/hashed_id.hpp>
#include <vanetza/security/secured_message.hpp>
#include <vanetza/security/verify_service.hpp>
#include <boost/optional/optional.hpp>
#include <boost/variant/variant.hpp>

namespace vanetza
{
namespace security
{

/**
* \brief Input data for decapsulating a secured message.
*
* The structure is equivalent to VerifyRequest, however, decapsulation may
* also deal with decryption in future versions.
*
* \see TS 102 723-8 v1.1.1 SN-DECAP.request
*/
struct DecapRequest
{
DecapRequest(SecuredMessageView sec_msg_view) : sec_packet(sec_msg_view) {}
SecuredMessageView sec_packet;
};

/**
* \brief SN-DECAP.confirm report codes
* \see TS 102 723-8 v1.1.1 table 27 (report field)
*
* Instead of duplicating VerificationReport values and the linked burden keeping
* these values consistent, DecapReport is a variant incorporating VerificationReport.
* When decryption is implemented, a DecryptionReport may be added to the variant.
*
* The boost::blank entry indicates that the SecuredMessage was neither signed nor encrypted.
*/
using DecapReport = boost::variant<boost::blank, VerificationReport>;

/**
* \brief Check if report indicates a successful decapsulation.
*
* Either verification or decryption needs to be successful.
* An unsecured message cannot lead to a succesful decapsulation result.
*
* \param report to check
* \return true if either verification or decryption was successful
*/
bool is_successful(const DecapReport& report);

/**
* \brief Check if decapsulation report matches a particular verification report.
*
* \param decap decapsulation report
* \param verification verification report
* \return true if decapsulation matches verification
*/
bool operator==(const DecapReport& decap, VerificationReport verification);
bool operator==(VerificationReport verification, const DecapReport& decap);

/**
* \brief SN-DECAP.confirm
* \see TS 102 723-8 v1.1.1 table 27
*/
struct DecapConfirm
{
PacketVariant plaintext_payload; // mandatory (plaintext_packet_length also covered by data type)
DecapReport report; // mandatory
CertificateValidity certificate_validity; // non-standard extension
boost::optional<HashedId8> certificate_id; // optional
ItsAid its_aid; // mandatory (its_ait_lenth also covered by data type)
ByteBuffer permissions; // mandatory
};

} // namespace security
} // namespace vanetza

#endif /* F815BB22_3075_4A9D_9385_07876D800765 */
3 changes: 1 addition & 2 deletions vanetza/security/security_entity.hpp
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
#ifndef SECURITY_ENTITY_HPP
#define SECURITY_ENTITY_HPP

#include <vanetza/security/decap_confirm.hpp>
#include <vanetza/security/decap_request.hpp>
#include <vanetza/security/decap_service.hpp>
#include <vanetza/security/encap_service.hpp>

namespace vanetza
Expand Down
36 changes: 36 additions & 0 deletions vanetza/security/tests/decap_report_printer.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#ifndef DEA0116A_C521_407B_B2E3_B4C272C53C4C
#define DEA0116A_C521_407B_B2E3_B4C272C53C4C

#include <vanetza/security/decap_service.hpp>
#include <iostream>

namespace vanetza
{
namespace security
{

void PrintTo(const DecapReport& report, std::ostream* out)
{
struct Printer : boost::static_visitor<>
{
Printer(std::ostream* out) : out(out) {}

void operator()(const VerificationReport& report) const
{
*out << "DecapReport(VerificationReport(" << static_cast<int>(report) << "))";
}

void operator()(const boost::blank&) const
{
*out << "DecapReport(None)";
}

std::ostream* out;
};
boost::apply_visitor(Printer(out), report);
}

} // namespace security
} // namespace vanetza

#endif /* DEA0116A_C521_407B_B2E3_B4C272C53C4C */
Loading

0 comments on commit 259f0bb

Please sign in to comment.