Keep the colleague's microbu-esp32c5 tree in this repository
obu-firmware builds against vanetza-idf from microbu-esp32c5/external, but that tree was gitignored, so a clone of this repository could not build the firmware it ships. It is now committed here as ordinary files in its own folder, microbu-esp32c5/: the colleague's commit cf4b99f plus the V2X2MAP bridge's signature verification (--trust) used on the bench. Nothing is fetched from or pushed to the colleague's repository; this repository and its remotes carry everything. The folder's own .gitignore keeps build output, downloaded components and private key material out, as it did there; the committed file set is identical to that repository's tracked files. The ESP32-C5 is still flashed from obu-firmware/, which only takes vanetza-idf from microbu-esp32c5/, so the two stay separate folders. FLASHING.md says how to take a newer version of the colleague's tree (copy it over the folder, rebuild, test, commit).
This commit is contained in:
+44
@@ -0,0 +1,44 @@
|
||||
include(UseGTest)
|
||||
add_library(security_test_v2 STATIC
|
||||
check_basic_elements.cpp
|
||||
check_certificate.cpp
|
||||
check_encryption_parameter.cpp
|
||||
check_header_field.cpp
|
||||
check_public_key.cpp
|
||||
check_recipient_info.cpp
|
||||
check_region.cpp
|
||||
check_secured_message.cpp
|
||||
check_signature.cpp
|
||||
check_signer_info.cpp
|
||||
check_subject_attribute.cpp
|
||||
check_trailer_field.cpp
|
||||
check_validity_restriction.cpp
|
||||
)
|
||||
target_include_directories(security_test_v2 PUBLIC $<TARGET_PROPERTY:security,INTERFACE_INCLUDE_DIRECTORIES>)
|
||||
target_link_libraries(security_test_v2 PUBLIC ${GTest_LIBRARY})
|
||||
configure_gtest_directory(LINK_LIBRARIES Boost::boost security security_test security_test_v2
|
||||
COMPILE_DEFINITIONS ASSET_DIR="${SECURITY_TEST_ASSET_DIR}")
|
||||
|
||||
add_gtest(Certificate certificate.cpp)
|
||||
add_gtest(CertificateCache certificate_cache.cpp)
|
||||
add_gtest(DefaultCertificateValidator default_certificate_validator.cpp)
|
||||
add_gtest(EccPoint ecc_point.cpp)
|
||||
add_gtest(EncryptionParameter encryption_parameter.cpp)
|
||||
add_gtest(HeaderField header_field.cpp)
|
||||
add_gtest(IntX int_x.cpp)
|
||||
add_gtest(LengthEncoding length_encoding.cpp)
|
||||
add_gtest(NaiveCertificateProvider naive_certificate_provider.cpp)
|
||||
add_gtest(Payload payload.cpp)
|
||||
add_gtest(PersistenceV2 persistence.cpp COMPILE_DEFINITIONS WORK_DIR="${CMAKE_CURRENT_BINARY_DIR}")
|
||||
add_gtest(PublicKeyV2 public_key.cpp)
|
||||
add_gtest(RecipientInfo recipient_info.cpp)
|
||||
add_gtest(Region region.cpp)
|
||||
add_gtest(SecuredMessage secured_message.cpp)
|
||||
add_gtest(SecurityEntity security_entity.cpp)
|
||||
add_gtest(Signature signature.cpp)
|
||||
add_gtest(SignerInfo signer_info.cpp)
|
||||
add_gtest(SubjectAttribute subject_attribute.cpp)
|
||||
add_gtest(SubjectInfo subject_info.cpp)
|
||||
add_gtest(TrailerField trailer_field.cpp)
|
||||
add_gtest(TrustStore trust_store.cpp)
|
||||
add_gtest(ValidityRestriction validity_restriction.cpp)
|
||||
+66
@@ -0,0 +1,66 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include <vanetza/security/v2/certificate.hpp>
|
||||
#include <vanetza/security/v2/tests/check_certificate.hpp>
|
||||
#include <vanetza/security/tests/serialization.hpp>
|
||||
|
||||
using namespace vanetza::security::v2;
|
||||
using vanetza::security::deserialize_from_hexstring;
|
||||
|
||||
TEST(Certificate, WebValidator_RootCA_v2)
|
||||
{
|
||||
const char str[] =
|
||||
"0200040C547275737465645F526F6F74808D000004F1817DD05116B855A853F80DB171A3A470D431"
|
||||
"70EA7EEFD8EF392D66ECEFBE501CEBA19963C9B6447574424FFF1BB89485743F4D09A72B715FC73C"
|
||||
"87E5F70A110101000441279A383B80C812B72B1A5F5C3C590E5041C634A1ADCC4CE58393CA046D3C"
|
||||
"619717AEF634F7D80D5F6A29FA7F86EBF823ACE0097A71EE0DF0793034B0D3797C02E0200224250B"
|
||||
"0114B12B03154E0D83030000007D12BADF99D7070BCB237ED1FA7A5D86FD47E6ABA8E616B35E95A2"
|
||||
"856FC6E26A493E1215BCEE8BEA18B8ED52FB240716C4D4EC7D7C0167F0F032CBB87DF611D9";
|
||||
|
||||
Certificate c;
|
||||
deserialize_from_hexstring(str, c);
|
||||
check(c, serialize_roundtrip(c));
|
||||
}
|
||||
|
||||
TEST(Certificate, WebValidator_AuthorizationAuthority1_v2)
|
||||
{
|
||||
const char str[] =
|
||||
"0201F5425279310C0379020A547275737465645F4141808D00000432B9C37AC51D25863A7872EF40"
|
||||
"5DB43DF37FA73411B2C0539FD39DF38828F86C946CB09039C0A9694A650D9104BA62C5A7588AEF8F"
|
||||
"68935F0D170373968131CD01010004E6C956FBEDCC969935BE832E4DE599CBFD687D81495C58B3C1"
|
||||
"2028F92489D4AF76B64D340BE2ACE8D7E2A789FE09A5F3B84F5E65BF54A07FAF74696131E762E302"
|
||||
"E0200224250B0114B12B03154E0D8303000000CC6255F38BC8844FAC2A31DE3420E65F23DBC97DC8"
|
||||
"66C840516328F27850B3520FC2A812A49DD989BFB0ECE408E53B375006974D1DA4EFD6FC5465B3F8"
|
||||
"946183";
|
||||
Certificate c;
|
||||
deserialize_from_hexstring(str, c);
|
||||
check(c, serialize_roundtrip(c));
|
||||
}
|
||||
|
||||
TEST(Certificate, WebValidator_AuthorizationAuthority2_v2)
|
||||
{
|
||||
const char str[] =
|
||||
"0201F5425279310C0379020A547275737465645F4141808D00000401418E994657434A71E034E530"
|
||||
"B1E77A8AFAC37561132C83D45C442499228CA78573F14BE034A4958108A654CAC60F15BB35907E33"
|
||||
"D0E97F8D7EAF64A1F43547010100047C5C8D8B86CF8A00A53F3CD23FCCF13D078555CC8EF27DC439"
|
||||
"780EB8EF376237FF668055DA476CC82956F6FEBFA051A6D927E70D826DB0338E42819F026AEBAA02"
|
||||
"E0200224250B0114B12B03154E0D83030000005145571104D52DD7094C577719C7CA430D59608D5F"
|
||||
"EFD10DB3E61B7C5FD3E4716224F96ED5AB4EB7F860C15347B66E23EA12E0A186A1A80B96C6E5DE05"
|
||||
"416A87";
|
||||
Certificate c;
|
||||
deserialize_from_hexstring(str, c);
|
||||
check(c, serialize_roundtrip(c));
|
||||
}
|
||||
|
||||
TEST(Certificate, WebValidator_AuthorizationTicket1_v2)
|
||||
{
|
||||
const char str[] =
|
||||
"02015388DEC640C6E19E010052000004B27D4D442F58E065F8D500478929BC843940F3C34D46C547"
|
||||
"5803C03594E35BD7E0132FD01634E86D4F50F7F2366988E12525232D00D03E98FC21CA8E5D0AF370"
|
||||
"02E0210B24030100002504010000000B0114E9DB83154CBC0203000000553C8D2B8A4E53F3D84A88"
|
||||
"37BEEBE83D5C7F68484AC5EFCEEFCC7B0BC5E9531754AAF58BF90790A10F2FD11796A85E13DFFAAC"
|
||||
"6073D2068465DA733994CD0C71";
|
||||
Certificate c;
|
||||
deserialize_from_hexstring(str, c);
|
||||
check(c, serialize_roundtrip(c));
|
||||
}
|
||||
|
||||
+135
@@ -0,0 +1,135 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include <vanetza/common/manual_runtime.hpp>
|
||||
#include <vanetza/security/v2/certificate.hpp>
|
||||
#include <vanetza/security/v2/certificate_cache.hpp>
|
||||
#include <vanetza/security/tests/serialization.hpp>
|
||||
|
||||
using namespace vanetza;
|
||||
using namespace vanetza::security;
|
||||
using namespace vanetza::security::v2;
|
||||
|
||||
class CertificateCacheTest : public ::testing::Test
|
||||
{
|
||||
public:
|
||||
CertificateCacheTest() :
|
||||
runtime(Clock::at("2018-01-03 17:15")),
|
||||
cache(runtime)
|
||||
{
|
||||
}
|
||||
|
||||
Certificate build_certificate(SubjectType subject_type, uint8_t id = 0)
|
||||
{
|
||||
Certificate cert;
|
||||
cert.subject_info.subject_type = subject_type;
|
||||
cert.signer_info = HashedId8 {{ id, id, id, id, id, id, id, id }};
|
||||
EcdsaSignature signature;
|
||||
X_Coordinate_Only x_only;;
|
||||
x_only.x.insert(x_only.x.end(), 32, 0x22);
|
||||
signature.R = std::move(x_only);
|
||||
signature.s.insert(signature.s.end(), 32, 0x11);
|
||||
cert.signature = std::move(signature);
|
||||
return cert;
|
||||
}
|
||||
|
||||
protected:
|
||||
ManualRuntime runtime;
|
||||
CertificateCache cache;
|
||||
};
|
||||
|
||||
static const HashedId8 zero_id = {{ 0, 0, 0, 0, 0, 0, 0, 0 }};
|
||||
|
||||
TEST_F(CertificateCacheTest, lookup)
|
||||
{
|
||||
const Certificate cert = build_certificate(SubjectType::Authorization_Ticket);
|
||||
const HashedId8 cert_id = calculate_hash(cert);
|
||||
|
||||
// empty cache
|
||||
EXPECT_EQ(0, cache.lookup(cert_id, SubjectType::Authorization_Ticket).size());
|
||||
|
||||
cache.insert(cert);
|
||||
|
||||
// cache only contains 'cert' and must be able to find it
|
||||
EXPECT_EQ(1, cache.lookup(cert_id, SubjectType::Authorization_Ticket).size());
|
||||
|
||||
// cache only contains 'cert' and must not return it for other types
|
||||
EXPECT_EQ(0, cache.lookup(cert_id, SubjectType::Authorization_Authority).size());
|
||||
|
||||
// but nothing else
|
||||
HashedId8 other_id = cert_id;
|
||||
other_id[3] = cert_id[3] + 1;
|
||||
EXPECT_EQ(0, cache.lookup(other_id, SubjectType::Authorization_Ticket).size());
|
||||
}
|
||||
|
||||
TEST_F(CertificateCacheTest, insert_only_some_subject_type)
|
||||
{
|
||||
cache.insert(build_certificate(SubjectType::Enrollment_Credential));
|
||||
EXPECT_EQ(0, cache.size());
|
||||
cache.insert(build_certificate(SubjectType::Authorization_Ticket));
|
||||
EXPECT_EQ(1, cache.size());
|
||||
cache.insert(build_certificate(SubjectType::Authorization_Authority));
|
||||
EXPECT_EQ(2, cache.size());
|
||||
cache.insert(build_certificate(SubjectType::Enrollment_Authority));
|
||||
EXPECT_EQ(2, cache.size());
|
||||
cache.insert(build_certificate(SubjectType::Root_CA));
|
||||
EXPECT_EQ(2, cache.size());
|
||||
cache.insert(build_certificate(SubjectType::CRL_Signer));
|
||||
EXPECT_EQ(2, cache.size());
|
||||
}
|
||||
|
||||
TEST_F(CertificateCacheTest, drop_expired)
|
||||
{
|
||||
const Certificate cert1 = build_certificate(SubjectType::Authorization_Ticket); // 2 seconds
|
||||
const Certificate cert2 = build_certificate(SubjectType::Authorization_Authority); // 1 hour
|
||||
ASSERT_NE(calculate_hash(cert1), calculate_hash(cert2));
|
||||
cache.insert(cert1);
|
||||
cache.insert(cert2);
|
||||
ASSERT_EQ(2, cache.size());
|
||||
|
||||
runtime.trigger(std::chrono::seconds(3));
|
||||
EXPECT_EQ(2, cache.size());
|
||||
cache.lookup(zero_id, SubjectType::Authorization_Ticket); // any lookup drops expired cache entries
|
||||
EXPECT_EQ(1, cache.size());
|
||||
|
||||
runtime.trigger(std::chrono::minutes(60));
|
||||
cache.lookup(zero_id, SubjectType::Authorization_Ticket);
|
||||
EXPECT_EQ(0, cache.size());
|
||||
}
|
||||
|
||||
TEST_F(CertificateCacheTest, lookup_match_extends_lifetime)
|
||||
{
|
||||
const Certificate cert1 = build_certificate(SubjectType::Authorization_Ticket);
|
||||
const Certificate cert2 = build_certificate(SubjectType::Authorization_Authority);
|
||||
const HashedId8 id_cert2 = calculate_hash(cert2);
|
||||
|
||||
cache.insert(cert1);
|
||||
cache.insert(cert2);
|
||||
EXPECT_EQ(2, cache.size());
|
||||
|
||||
for (unsigned i = 0; i < 3601; ++i) {
|
||||
runtime.trigger(std::chrono::seconds(1));
|
||||
cache.lookup(id_cert2, SubjectType::Authorization_Authority);
|
||||
}
|
||||
EXPECT_EQ(1, cache.size());
|
||||
EXPECT_EQ(1, cache.lookup(id_cert2, SubjectType::Authorization_Authority).size());
|
||||
}
|
||||
|
||||
TEST_F(CertificateCacheTest, insert_extends_lifetime)
|
||||
{
|
||||
const Certificate cert = build_certificate(SubjectType::Authorization_Ticket);
|
||||
const HashedId8 id = calculate_hash(cert);
|
||||
EXPECT_NE(zero_id, id);
|
||||
|
||||
cache.insert(cert);
|
||||
EXPECT_EQ(1, cache.size());
|
||||
|
||||
runtime.trigger(std::chrono::seconds(1));
|
||||
cache.insert(cert);
|
||||
EXPECT_EQ(1, cache.size());
|
||||
|
||||
cache.lookup(zero_id, SubjectType::Authorization_Ticket);
|
||||
EXPECT_EQ(1, cache.size());
|
||||
|
||||
runtime.trigger(std::chrono::seconds(2));
|
||||
cache.lookup(id, SubjectType::Authorization_Ticket);
|
||||
EXPECT_EQ(1, cache.size());
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
#include <vanetza/security/v2/tests/check_basic_elements.hpp>
|
||||
|
||||
namespace vanetza
|
||||
{
|
||||
namespace security
|
||||
{
|
||||
namespace v2
|
||||
{
|
||||
|
||||
void check(const Time64WithStandardDeviation& expected, const Time64WithStandardDeviation& actual)
|
||||
{
|
||||
EXPECT_EQ(expected.time64, actual.time64);
|
||||
EXPECT_EQ(expected.log_std_dev, actual.log_std_dev);
|
||||
}
|
||||
|
||||
void check(const IntX& expected, const IntX& actual)
|
||||
{
|
||||
EXPECT_EQ(expected, actual);
|
||||
}
|
||||
|
||||
} // namespace v2
|
||||
} // namespace security
|
||||
} // namespace vanetza
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
#ifndef CHECK_BASIC_ELEMENTS_HPP_XLHVYJ0S
|
||||
#define CHECK_BASIC_ELEMENTS_HPP_XLHVYJ0S
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <vanetza/security/v2/basic_elements.hpp>
|
||||
#include <vanetza/security/v2/int_x.hpp>
|
||||
#include <boost/format.hpp>
|
||||
#include <type_traits>
|
||||
|
||||
namespace vanetza
|
||||
{
|
||||
namespace security
|
||||
{
|
||||
namespace v2
|
||||
{
|
||||
|
||||
template<typename T, typename std::enable_if<std::is_arithmetic<T>::value>::type* = nullptr>
|
||||
void check(const T& expected, const T& actual)
|
||||
{
|
||||
EXPECT_EQ(expected, actual);
|
||||
}
|
||||
|
||||
template<typename T, size_t N>
|
||||
void check(const std::array<T, N>& expected, const std::array<T, N>& actual)
|
||||
{
|
||||
SCOPED_TRACE("array<T, N>");
|
||||
for (unsigned i = 0; i < N; ++i) {
|
||||
SCOPED_TRACE(boost::format("element index #%1%") % i);
|
||||
check(expected[i], actual[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void check(const Time64WithStandardDeviation&, const Time64WithStandardDeviation&);
|
||||
void check(const IntX&, const IntX&);
|
||||
|
||||
// explicit template instantiations
|
||||
template void check<uint8_t, 3>(const HashedId3&, const HashedId3&);
|
||||
template void check<uint8_t, 8>(const HashedId8&, const HashedId8&);
|
||||
template void check<Time64>(const Time64&, const Time64&);
|
||||
template void check<Time32>(const Time32&, const Time32&);
|
||||
|
||||
} // namespace v2
|
||||
} // namespace security
|
||||
} // namespace vanetza
|
||||
|
||||
#endif /* CHECK_BASIC_ELEMENTS_HPP_XLHVYJ0S */
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include <vanetza/security/v2/tests/check_certificate.hpp>
|
||||
#include <vanetza/security/v2/tests/check_list.hpp>
|
||||
#include <vanetza/security/v2/tests/check_signature.hpp>
|
||||
#include <vanetza/security/v2/tests/check_signer_info.hpp>
|
||||
#include <vanetza/security/v2/tests/check_subject_attribute.hpp>
|
||||
#include <vanetza/security/v2/tests/check_subject_info.hpp>
|
||||
#include <vanetza/security/v2/tests/check_validity_restriction.hpp>
|
||||
|
||||
namespace vanetza
|
||||
{
|
||||
namespace security
|
||||
{
|
||||
namespace v2
|
||||
{
|
||||
|
||||
void check(const Certificate& expected, const Certificate& actual)
|
||||
{
|
||||
// certificate version is static, no check required
|
||||
check(expected.signer_info, actual.signer_info);
|
||||
check(expected.subject_info, actual.subject_info);
|
||||
check(expected.subject_attributes, actual.subject_attributes, "SubjectAttribute");
|
||||
check(expected.validity_restriction, actual.validity_restriction, "ValidityRestriction");
|
||||
check(expected.signature, actual.signature);
|
||||
}
|
||||
|
||||
} // namespace v2
|
||||
} // namespace security
|
||||
} // namespace vanetza
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
#ifndef CHECK_CERTIFICATE_HPP_ICIHS76C
|
||||
#define CHECK_CERTIFICATE_HPP_ICIHS76C
|
||||
|
||||
#include <vanetza/security/v2/certificate.hpp>
|
||||
|
||||
namespace vanetza
|
||||
{
|
||||
namespace security
|
||||
{
|
||||
namespace v2
|
||||
{
|
||||
|
||||
void check(const Certificate&, const Certificate&);
|
||||
|
||||
} // namespace v2
|
||||
} // namespace security
|
||||
} // namespace vanetza
|
||||
|
||||
#endif /* CHECK_CERTIFICATE_HPP_ICIHS76C */
|
||||
|
||||
+69
@@ -0,0 +1,69 @@
|
||||
#ifndef CHECK_ECC_POINT_HPP_UQH2R8WK
|
||||
#define CHECK_ECC_POINT_HPP_UQH2R8WK
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <vanetza/security/v2/ecc_point.hpp>
|
||||
#include <vanetza/security/v2/tests/check_visitor.hpp>
|
||||
#include <boost/variant/apply_visitor.hpp>
|
||||
|
||||
namespace vanetza
|
||||
{
|
||||
namespace security
|
||||
{
|
||||
|
||||
/**
|
||||
* \brief check two X_Coordinate_Only
|
||||
* \param expected the expected value
|
||||
* \param actual the actual value
|
||||
*/
|
||||
inline void check(const X_Coordinate_Only& expected, const X_Coordinate_Only& actual)
|
||||
{
|
||||
EXPECT_EQ(expected.x, actual.x);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief check two Compressed_Lsb_Y_0
|
||||
* \param expected the expected value
|
||||
* \param actual the actual value
|
||||
*/
|
||||
inline void check(const Compressed_Lsb_Y_0& expected, const Compressed_Lsb_Y_0& actual)
|
||||
{
|
||||
EXPECT_EQ(expected.x, actual.x);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief check two Compressed_Lsb_Y_1
|
||||
* \param expected the expected value
|
||||
* \param actual the actual value
|
||||
*/
|
||||
inline void check(const Compressed_Lsb_Y_1& expected, const Compressed_Lsb_Y_1& actual)
|
||||
{
|
||||
EXPECT_EQ(expected.x, actual.x);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief check two Uncompressed
|
||||
* \param expected the expected value
|
||||
* \param actual the actual value
|
||||
*/
|
||||
inline void check(const Uncompressed& expected, const Uncompressed& actual)
|
||||
{
|
||||
EXPECT_EQ(expected.x, actual.x);
|
||||
EXPECT_EQ(expected.y, actual.y);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief check two EccPoints
|
||||
* \param expected the expected value
|
||||
* \param actual the actual value
|
||||
*/
|
||||
inline void check(const EccPoint& expected, const EccPoint& actual)
|
||||
{
|
||||
ASSERT_EQ(v2::get_type(expected), v2::get_type(actual));
|
||||
boost::apply_visitor(check_visitor<EccPoint>(), expected, actual);
|
||||
}
|
||||
|
||||
} // namespace security
|
||||
} // namespace vanetza
|
||||
|
||||
#endif /* CHECK_ECC_POINT_HPP_UQH2R8WK */
|
||||
Vendored
+21
@@ -0,0 +1,21 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include <vanetza/security/v2/tests/check_encryption_parameter.hpp>
|
||||
#include <vanetza/security/v2/tests/check_visitor.hpp>
|
||||
|
||||
namespace vanetza
|
||||
{
|
||||
namespace security
|
||||
{
|
||||
namespace v2
|
||||
{
|
||||
|
||||
void check(const EncryptionParameter& expected, const EncryptionParameter& actual)
|
||||
{
|
||||
ASSERT_EQ(get_type(expected), get_type(actual));
|
||||
EXPECT_EQ(get_size(expected), get_size(actual));
|
||||
boost::apply_visitor(check_visitor<EncryptionParameter>(), expected, actual);
|
||||
}
|
||||
|
||||
} // namespace v2
|
||||
} // namespace security
|
||||
} // namespace vanetza
|
||||
Vendored
+25
@@ -0,0 +1,25 @@
|
||||
#ifndef CHECK_ENCRYPTION_PARAMETER_HPP_5UDSKSNK
|
||||
#define CHECK_ENCRYPTION_PARAMETER_HPP_5UDSKSNK
|
||||
|
||||
#include <vanetza/security/v2/encryption_parameter.hpp>
|
||||
#include <vanetza/security/v2/tests/check_basic_elements.hpp>
|
||||
|
||||
namespace vanetza
|
||||
{
|
||||
namespace security
|
||||
{
|
||||
namespace v2
|
||||
{
|
||||
|
||||
/**
|
||||
* \brief check if the two EncryptionParameter are equal
|
||||
* \param expected the expected value
|
||||
* \param actual the actual value
|
||||
*/
|
||||
void check(const EncryptionParameter& expected, const EncryptionParameter& actual);
|
||||
|
||||
} // namespace v2
|
||||
} // namespace security
|
||||
} // namespace vanetza
|
||||
|
||||
#endif /* CHECK_ENCRYPTION_PARAMETER_HPP_5UDSKSNK */
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include <vanetza/security/v2/tests/check_basic_elements.hpp>
|
||||
#include <vanetza/security/v2/tests/check_header_field.hpp>
|
||||
#include <vanetza/security/v2/tests/check_visitor.hpp>
|
||||
|
||||
namespace vanetza
|
||||
{
|
||||
namespace security
|
||||
{
|
||||
namespace v2
|
||||
{
|
||||
|
||||
void check(const HeaderField& expected, const HeaderField& actual)
|
||||
{
|
||||
ASSERT_EQ(get_type(expected), get_type(actual));
|
||||
boost::apply_visitor(check_visitor<HeaderField>(), expected, actual);
|
||||
}
|
||||
|
||||
} // namespace v2
|
||||
} // namespace security
|
||||
} // namespace vanetza
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
#ifndef CHECK_HEADER_FIELD_HPP_DNSZT9E2
|
||||
#define CHECK_HEADER_FIELD_HPP_DNSZT9E2
|
||||
|
||||
#include <vanetza/security/v2/header_field.hpp>
|
||||
#include <vanetza/security/v2/tests/check_basic_elements.hpp>
|
||||
#include <vanetza/security/v2/tests/check_encryption_parameter.hpp>
|
||||
#include <vanetza/security/v2/tests/check_list.hpp>
|
||||
#include <vanetza/security/v2/tests/check_recipient_info.hpp>
|
||||
#include <vanetza/security/v2/tests/check_region.hpp>
|
||||
#include <vanetza/security/v2/tests/check_signer_info.hpp>
|
||||
|
||||
namespace vanetza
|
||||
{
|
||||
namespace security
|
||||
{
|
||||
namespace v2
|
||||
{
|
||||
|
||||
void check(const HeaderField&, const HeaderField&);
|
||||
|
||||
} // namespace v2
|
||||
} // namespace security
|
||||
} // namespace vanetza
|
||||
|
||||
#endif /* CHECK_HEADER_FIELD_HPP_DNSZT9E2 */
|
||||
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
#ifndef CHECK_LIST_HPP_1ONCXSED
|
||||
#define CHECK_LIST_HPP_1ONCXSED
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <boost/format.hpp>
|
||||
#include <list>
|
||||
#include <typeinfo>
|
||||
|
||||
namespace vanetza
|
||||
{
|
||||
namespace security
|
||||
{
|
||||
namespace v2
|
||||
{
|
||||
|
||||
template<typename T>
|
||||
void check(std::list<T> expected, std::list<T> actual, const char* type = typeid(T).name())
|
||||
{
|
||||
SCOPED_TRACE(boost::format("list<%1%>") % type);
|
||||
ASSERT_EQ(expected.size(), actual.size());
|
||||
std::size_t i = 0;
|
||||
while (!expected.empty() && !actual.empty()) {
|
||||
SCOPED_TRACE(boost::format("%1% #%2%") % type % i);
|
||||
check(expected.front(), actual.front());
|
||||
expected.pop_front();
|
||||
actual.pop_front();
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace v2
|
||||
} // namespace security
|
||||
} // namespace vanetza
|
||||
|
||||
#endif /* CHECK_LIST_HPP_1ONCXSED */
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
#ifndef CHECK_PAYLOAD_HPP_YNRGOKGC
|
||||
#define CHECK_PAYLOAD_HPP_YNRGOKGC
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <vanetza/common/byte_buffer.hpp>
|
||||
#include <vanetza/common/serialization_buffer.hpp>
|
||||
#include <vanetza/security/v2/payload.hpp>
|
||||
|
||||
namespace vanetza
|
||||
{
|
||||
namespace security
|
||||
{
|
||||
namespace v2
|
||||
{
|
||||
|
||||
inline void check(const PacketVariant& expected, const PacketVariant& actual)
|
||||
{
|
||||
ByteBuffer expected_buf, actual_buf;
|
||||
serialize_into_buffer(expected, expected_buf);
|
||||
serialize_into_buffer(actual, actual_buf);
|
||||
EXPECT_EQ(expected_buf, actual_buf);
|
||||
}
|
||||
|
||||
inline void check(const Payload& expected, const Payload& actual)
|
||||
{
|
||||
EXPECT_EQ(expected.type, actual.type);
|
||||
check(expected.data, actual.data);
|
||||
}
|
||||
|
||||
} // namespace v2
|
||||
} // namespace security
|
||||
} // namespace vanetza
|
||||
|
||||
#endif /* CHECK_PAYLOAD_HPP_YNRGOKGC */
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include <vanetza/common/byte_sequence.hpp>
|
||||
#include <vanetza/security/v2/tests/check_ecc_point.hpp>
|
||||
#include <vanetza/security/v2/tests/check_public_key.hpp>
|
||||
#include <vanetza/security/v2/tests/check_visitor.hpp>
|
||||
|
||||
namespace vanetza
|
||||
{
|
||||
namespace security
|
||||
{
|
||||
namespace v2
|
||||
{
|
||||
|
||||
void check(const ecdsa_nistp256_with_sha256& expected, const ecdsa_nistp256_with_sha256& actual)
|
||||
{
|
||||
check(expected.public_key, actual.public_key);
|
||||
}
|
||||
|
||||
void check(const ecies_nistp256& expected, const ecies_nistp256& actual)
|
||||
{
|
||||
EXPECT_EQ(expected.supported_symm_alg, actual.supported_symm_alg);
|
||||
check(expected.public_key, actual.public_key);
|
||||
}
|
||||
|
||||
void check(const PublicKey& expected, const PublicKey& actual)
|
||||
{
|
||||
ASSERT_EQ(get_type(expected), get_type(actual));
|
||||
boost::apply_visitor(check_visitor<PublicKey>(), expected, actual);
|
||||
}
|
||||
|
||||
PublicKey create_random_public_key(int seed)
|
||||
{
|
||||
const std::size_t size = field_size(PublicKeyAlgorithm::ECIES_NISTP256);
|
||||
EccPoint point = Uncompressed { random_byte_sequence(size, seed),
|
||||
random_byte_sequence(size, seed + 1) };
|
||||
ecies_nistp256 ecies;
|
||||
ecies.public_key = point;
|
||||
ecies.supported_symm_alg = SymmetricAlgorithm::AES128_CCM;
|
||||
|
||||
return ecies;
|
||||
}
|
||||
|
||||
} // namespace v2
|
||||
} // namespace security
|
||||
} // namespace vanetza
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
#ifndef CHECK_PUBLIC_KEY_HPP_3HUSMPTE
|
||||
#define CHECK_PUBLIC_KEY_HPP_3HUSMPTE
|
||||
|
||||
#include <vanetza/security/v2/public_key.hpp>
|
||||
|
||||
namespace vanetza
|
||||
{
|
||||
namespace security
|
||||
{
|
||||
namespace v2
|
||||
{
|
||||
|
||||
void check(const ecdsa_nistp256_with_sha256&, const ecdsa_nistp256_with_sha256&);
|
||||
void check(const ecies_nistp256&, const ecies_nistp256&);
|
||||
void check(const PublicKey&, const PublicKey&);
|
||||
|
||||
PublicKey create_random_public_key(int seed = 0);
|
||||
|
||||
} // namespace v2
|
||||
} // namespace security
|
||||
} // namespace vanetza
|
||||
|
||||
#endif /* CHECK_PUBLIC_KEY_HPP_3HUSMPTE */
|
||||
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include <vanetza/security/v2/tests/check_ecc_point.hpp>
|
||||
#include <vanetza/security/v2/tests/check_recipient_info.hpp>
|
||||
#include <vanetza/security/v2/tests/check_visitor.hpp>
|
||||
|
||||
namespace vanetza
|
||||
{
|
||||
namespace security
|
||||
{
|
||||
namespace v2
|
||||
{
|
||||
|
||||
void check(const RecipientInfo& expected, const RecipientInfo& actual)
|
||||
{
|
||||
EXPECT_EQ(expected.cert_id, actual.cert_id);
|
||||
check(expected.enc_key, actual.enc_key);
|
||||
}
|
||||
|
||||
void check(const EciesEncryptedKey& expected, const EciesEncryptedKey& actual)
|
||||
{
|
||||
check(expected.v, actual.v);
|
||||
EXPECT_EQ(expected.c, actual.c);
|
||||
EXPECT_EQ(expected.t, actual.t);
|
||||
}
|
||||
|
||||
void check(const OpaqueKey& expected, const OpaqueKey& actual)
|
||||
{
|
||||
EXPECT_EQ(expected.data, actual.data);
|
||||
}
|
||||
|
||||
void check(const Key& expected, const Key& actual)
|
||||
{
|
||||
ASSERT_EQ(get_type(expected), get_type(actual));
|
||||
boost::apply_visitor(check_visitor<Key>(), expected, actual);
|
||||
}
|
||||
|
||||
} // namespace v2
|
||||
} // namespace security
|
||||
} // namespace vanetza
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
#ifndef CHECK_RECIPIENT_INFO_HPP_NMX7BFYV
|
||||
#define CHECK_RECIPIENT_INFO_HPP_NMX7BFYV
|
||||
|
||||
#include <vanetza/security/v2/recipient_info.hpp>
|
||||
|
||||
namespace vanetza
|
||||
{
|
||||
namespace security
|
||||
{
|
||||
namespace v2
|
||||
{
|
||||
|
||||
void check(const EciesEncryptedKey&, const EciesEncryptedKey&);
|
||||
void check(const OpaqueKey&, const OpaqueKey&);
|
||||
void check(const Key&, const Key&);
|
||||
void check(const RecipientInfo&, const RecipientInfo&);
|
||||
|
||||
} // namespace v2
|
||||
} // namespace security
|
||||
} // namespace vanetza
|
||||
|
||||
#endif /* CHECK_RECIPIENT_INFO_HPP_NMX7BFYV */
|
||||
+87
@@ -0,0 +1,87 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include <vanetza/common/annotation.hpp>
|
||||
#include <vanetza/security/v2/tests/check_region.hpp>
|
||||
#include <vanetza/security/v2/tests/check_visitor.hpp>
|
||||
#include <boost/format.hpp>
|
||||
|
||||
namespace vanetza
|
||||
{
|
||||
namespace security
|
||||
{
|
||||
namespace v2
|
||||
{
|
||||
|
||||
void check(const ThreeDLocation& expected, const ThreeDLocation& actual)
|
||||
{
|
||||
EXPECT_EQ(expected.latitude, actual.latitude);
|
||||
EXPECT_EQ(expected.longitude, actual.longitude);
|
||||
EXPECT_EQ(expected.elevation, actual.elevation);
|
||||
}
|
||||
|
||||
void check(const TwoDLocation& expected, const TwoDLocation& actual)
|
||||
{
|
||||
EXPECT_EQ(expected.longitude, actual.longitude);
|
||||
EXPECT_EQ(expected.latitude, actual.latitude);
|
||||
}
|
||||
|
||||
void check(const NoneRegion& expected, const NoneRegion& actual)
|
||||
{
|
||||
mark_unused(expected);
|
||||
mark_unused(actual);
|
||||
SCOPED_TRACE("None");
|
||||
}
|
||||
|
||||
void check(const CircularRegion& expected, const CircularRegion& actual)
|
||||
{
|
||||
SCOPED_TRACE("CiruclarRegion");
|
||||
check(expected.center, actual.center);
|
||||
EXPECT_EQ(expected.radius, actual.radius);
|
||||
}
|
||||
|
||||
void check(const RectangularRegion& expected, const RectangularRegion& actual)
|
||||
{
|
||||
SCOPED_TRACE("RectangularRegion");
|
||||
check(expected.northwest, actual.northwest);
|
||||
check(expected.southeast, actual.southeast);
|
||||
}
|
||||
|
||||
void check(std::list<RectangularRegion> expected, std::list<RectangularRegion> actual)
|
||||
{
|
||||
SCOPED_TRACE("list<RectangularRegion>");
|
||||
ASSERT_EQ(expected.size(), actual.size());
|
||||
for (std::size_t i = 0, j = expected.size(); i < j; ++i) {
|
||||
SCOPED_TRACE(boost::format("Rectangle #%1%") % i);
|
||||
check(expected.front(), actual.front());
|
||||
expected.pop_front();
|
||||
actual.pop_front();
|
||||
}
|
||||
}
|
||||
|
||||
void check(PolygonalRegion expected, PolygonalRegion actual)
|
||||
{
|
||||
SCOPED_TRACE("PolygonalRegion");
|
||||
ASSERT_EQ(expected.size(), actual.size());
|
||||
for (std::size_t i = 0, j = expected.size(); i < j; ++i) {
|
||||
SCOPED_TRACE(boost::format("Coordinate #%1%") % i);
|
||||
check(expected.front(), actual.front());
|
||||
expected.pop_front();
|
||||
actual.pop_front();
|
||||
}
|
||||
}
|
||||
|
||||
void check(const IdentifiedRegion& expected, const IdentifiedRegion& actual)
|
||||
{
|
||||
EXPECT_EQ(expected.region_dictionary, actual.region_dictionary);
|
||||
EXPECT_EQ(expected.region_identifier, actual.region_identifier);
|
||||
EXPECT_EQ(expected.local_region, actual.local_region);
|
||||
}
|
||||
|
||||
void check(const GeographicRegion& expected, const GeographicRegion& actual)
|
||||
{
|
||||
ASSERT_EQ(get_type(expected), get_type(actual));
|
||||
boost::apply_visitor(check_visitor<GeographicRegion>(), expected, actual);
|
||||
}
|
||||
|
||||
} // namespace v2
|
||||
} // namespace security
|
||||
} // namespace vanetza
|
||||
+65
@@ -0,0 +1,65 @@
|
||||
#ifndef CHECK_REGION_HPP_UFSV2RZ5
|
||||
#define CHECK_REGION_HPP_UFSV2RZ5
|
||||
|
||||
#include <vanetza/security/v2/region.hpp>
|
||||
|
||||
namespace vanetza
|
||||
{
|
||||
namespace security
|
||||
{
|
||||
namespace v2
|
||||
{
|
||||
|
||||
/** \brief check two TwoDLocations
|
||||
* \param expected the expected value
|
||||
* \param actual the actual value
|
||||
*/
|
||||
void check(const TwoDLocation& expected, const TwoDLocation& actual);
|
||||
|
||||
/** \brief check two ThreeDLocations
|
||||
* \param expected the expected value
|
||||
* \param actual the actual value
|
||||
*/
|
||||
void check(const ThreeDLocation&, const ThreeDLocation&);
|
||||
|
||||
/** \brief check two CircularRegions
|
||||
* \param expected the expected value
|
||||
* \param actual the actual value
|
||||
*/
|
||||
void check(const CircularRegion& expected, const CircularRegion& actual);
|
||||
|
||||
/** \brief check two RectangularRegions
|
||||
* \param expected the expected value
|
||||
* \param actual the actual value
|
||||
*/
|
||||
void check(const RectangularRegion& expected, const RectangularRegion& actual);
|
||||
|
||||
/** \brief check two std::list<RectangularRegion>
|
||||
* \param expected the expected list
|
||||
* \param actual the actual value
|
||||
*/
|
||||
void check(std::list<RectangularRegion> expected, std::list<RectangularRegion> actual);
|
||||
|
||||
/** \brief check two PolygonalRegions
|
||||
* \param expected the expected value
|
||||
* \param actual the actual value
|
||||
*/
|
||||
void check(PolygonalRegion expected, PolygonalRegion actual);
|
||||
|
||||
/** \brief check two IdentifiedRegions
|
||||
* \param expected the expected value
|
||||
* \param actual the actual value
|
||||
*/
|
||||
void check(const IdentifiedRegion& expected, const IdentifiedRegion& actual);
|
||||
|
||||
/** \brief check two GeographicRegion
|
||||
* \param expected the expected value
|
||||
* \param actual the actual value
|
||||
*/
|
||||
void check(const GeographicRegion& expected, const GeographicRegion& actual);
|
||||
|
||||
} // namespace v2
|
||||
} // namespace security
|
||||
} // namespace vanetza
|
||||
|
||||
#endif /* CHECK_REGION_HPP_UFSV2RZ5 */
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include <vanetza/security/v2/tests/check_header_field.hpp>
|
||||
#include <vanetza/security/v2/tests/check_list.hpp>
|
||||
#include <vanetza/security/v2/tests/check_payload.hpp>
|
||||
#include <vanetza/security/v2/tests/check_secured_message.hpp>
|
||||
#include <vanetza/security/v2/tests/check_trailer_field.hpp>
|
||||
|
||||
namespace vanetza
|
||||
{
|
||||
namespace security
|
||||
{
|
||||
namespace v2
|
||||
{
|
||||
|
||||
void check(const SecuredMessage& expected, const SecuredMessage& actual)
|
||||
{
|
||||
SCOPED_TRACE("v2::SecuredMessage");
|
||||
check(expected.header_fields, actual.header_fields);
|
||||
check(expected.trailer_fields, actual.trailer_fields);
|
||||
check(expected.payload, actual.payload);
|
||||
}
|
||||
|
||||
} // namespace v2
|
||||
} // namespace security
|
||||
} // namespace vanetza
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
#ifndef CHECK_SECURED_MESSAGE_HPP_1YPFNXQA
|
||||
#define CHECK_SECURED_MESSAGE_HPP_1YPFNXQA
|
||||
|
||||
#include <vanetza/security/v2/secured_message.hpp>
|
||||
|
||||
namespace vanetza
|
||||
{
|
||||
namespace security
|
||||
{
|
||||
namespace v2
|
||||
{
|
||||
|
||||
void check(const SecuredMessage&, const SecuredMessage&);
|
||||
|
||||
} // namespace v2
|
||||
} // namespace security
|
||||
} // namespace vanetza
|
||||
|
||||
#endif /* CHECK_SECURED_MESSAGE_HPP_1YPFNXQA */
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include <vanetza/common/byte_sequence.hpp>
|
||||
#include <vanetza/security/signature.hpp>
|
||||
#include <vanetza/security/v2/tests/check_ecc_point.hpp>
|
||||
#include <vanetza/security/v2/tests/check_signature.hpp>
|
||||
#include <vanetza/security/v2/tests/check_visitor.hpp>
|
||||
#include <boost/variant/apply_visitor.hpp>
|
||||
|
||||
namespace vanetza
|
||||
{
|
||||
namespace security
|
||||
{
|
||||
|
||||
void check(const EcdsaSignature& expected, const EcdsaSignature& actual)
|
||||
{
|
||||
check(expected.R, actual.R);
|
||||
EXPECT_EQ(expected.s, actual.s);
|
||||
}
|
||||
|
||||
void check(const EcdsaSignatureFuture& expected, const EcdsaSignatureFuture& actual)
|
||||
{
|
||||
check(expected.get(), actual.get());
|
||||
}
|
||||
|
||||
EcdsaSignature create_random_ecdsa_signature(int seed)
|
||||
{
|
||||
const std::size_t field = v2::field_size(v2::PublicKeyAlgorithm::ECDSA_NISTP256_With_SHA256);
|
||||
EcdsaSignature signature;
|
||||
signature.s = random_byte_sequence(field, seed);
|
||||
signature.R = X_Coordinate_Only { random_byte_sequence(field, ~seed) };
|
||||
return signature;
|
||||
}
|
||||
|
||||
namespace v2
|
||||
{
|
||||
|
||||
void check(const Signature& expected, const Signature& actual)
|
||||
{
|
||||
ASSERT_EQ(get_type(expected), get_type(actual));
|
||||
// TODO boost::apply_visitor(check_visitor<Signature>(), expected, actual);
|
||||
}
|
||||
|
||||
} // namespace v2
|
||||
} // namespace security
|
||||
} // namespace vanetza
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
#ifndef CHECK_SIGNATURE_HPP_7RESWTUO
|
||||
#define CHECK_SIGNATURE_HPP_7RESWTUO
|
||||
|
||||
#include <vanetza/security/v2/signature.hpp>
|
||||
|
||||
namespace vanetza
|
||||
{
|
||||
namespace security
|
||||
{
|
||||
|
||||
void check(const EcdsaSignature&, const EcdsaSignature&);
|
||||
void check(const EcdsaSignatureFuture&, const EcdsaSignatureFuture&);
|
||||
|
||||
/**
|
||||
* \brief create a random EcdsaSignature
|
||||
* \param seed the optional seed for the RNG
|
||||
* \return created signature
|
||||
*/
|
||||
EcdsaSignature create_random_ecdsa_signature(int seed = 0);
|
||||
|
||||
namespace v2
|
||||
{
|
||||
|
||||
void check(const Signature&, const Signature&);
|
||||
|
||||
} // namespace v2
|
||||
} // namespace security
|
||||
} // namespace vanetza
|
||||
|
||||
#endif /* CHECK_SIGNATURE_HPP_7RESWTUO */
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include <vanetza/security/v2/tests/check_basic_elements.hpp>
|
||||
#include <vanetza/security/v2/tests/check_certificate.hpp>
|
||||
#include <vanetza/security/v2/tests/check_list.hpp>
|
||||
#include <vanetza/security/v2/tests/check_signer_info.hpp>
|
||||
#include <vanetza/security/v2/tests/check_visitor.hpp>
|
||||
|
||||
namespace vanetza
|
||||
{
|
||||
namespace security
|
||||
{
|
||||
namespace v2
|
||||
{
|
||||
|
||||
void check(const std::nullptr_t&, const std::nullptr_t&)
|
||||
{
|
||||
}
|
||||
|
||||
void check(const CertificateDigestWithOtherAlgorithm& expected, const CertificateDigestWithOtherAlgorithm& actual)
|
||||
{
|
||||
EXPECT_EQ(expected.algorithm, actual.algorithm);
|
||||
EXPECT_EQ(expected.digest, actual.digest);
|
||||
}
|
||||
|
||||
void check(const boost::recursive_wrapper<Certificate>& expected, const boost::recursive_wrapper<Certificate>& actual)
|
||||
{
|
||||
check(expected.get(), actual.get());
|
||||
}
|
||||
|
||||
void check(const SignerInfo& expected, const SignerInfo& actual)
|
||||
{
|
||||
ASSERT_EQ(get_type(expected), get_type(actual));
|
||||
boost::apply_visitor(check_visitor<SignerInfo>(), expected, actual);
|
||||
}
|
||||
|
||||
} // namespace v2
|
||||
} // namespace security
|
||||
} // namespace vanetza
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
#ifndef CHECK_SIGNER_INFO_HPP_S2AYJSYC
|
||||
#define CHECK_SIGNER_INFO_HPP_S2AYJSYC
|
||||
|
||||
#include <vanetza/security/v2/signer_info.hpp>
|
||||
|
||||
namespace vanetza
|
||||
{
|
||||
namespace security
|
||||
{
|
||||
namespace v2
|
||||
{
|
||||
|
||||
void check(const std::nullptr_t&, const std::nullptr_t&);
|
||||
void check(const CertificateDigestWithOtherAlgorithm&, const CertificateDigestWithOtherAlgorithm&);
|
||||
void check(const boost::recursive_wrapper<Certificate>&, const boost::recursive_wrapper<Certificate>&);
|
||||
void check(const SignerInfo&, const SignerInfo&);
|
||||
|
||||
} // namespace v2
|
||||
} // namespace security
|
||||
} // namespace vanetza
|
||||
|
||||
#endif /* CHECK_SIGNER_INFO_HPP_S2AYJSYC */
|
||||
+76
@@ -0,0 +1,76 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include <vanetza/common/byte_sequence.hpp>
|
||||
#include <vanetza/security/v2/tests/check_list.hpp>
|
||||
#include <vanetza/security/v2/tests/check_public_key.hpp>
|
||||
#include <vanetza/security/v2/tests/check_subject_attribute.hpp>
|
||||
#include <vanetza/security/v2/tests/check_visitor.hpp>
|
||||
|
||||
namespace vanetza
|
||||
{
|
||||
namespace security
|
||||
{
|
||||
namespace v2
|
||||
{
|
||||
|
||||
void check(const VerificationKey& expected, const VerificationKey& actual)
|
||||
{
|
||||
SCOPED_TRACE("VerificationKey");
|
||||
check(expected.key, actual.key);
|
||||
}
|
||||
|
||||
void check(const EncryptionKey& expected, const EncryptionKey& actual)
|
||||
{
|
||||
SCOPED_TRACE("EncryptionKey");
|
||||
check(expected.key, actual.key);
|
||||
}
|
||||
|
||||
void check(const SubjectAssurance& expected, const SubjectAssurance& actual)
|
||||
{
|
||||
EXPECT_EQ(expected.raw, actual.raw);
|
||||
}
|
||||
|
||||
void check(const ItsAidSsp& expected, const ItsAidSsp& actual)
|
||||
{
|
||||
SCOPED_TRACE("ItsAidSsp");
|
||||
EXPECT_EQ(expected.its_aid, actual.its_aid);
|
||||
EXPECT_EQ(expected.service_specific_permissions, actual.service_specific_permissions);
|
||||
}
|
||||
|
||||
void check(const SubjectAttribute& expected, const SubjectAttribute& actual)
|
||||
{
|
||||
ASSERT_EQ(get_type(expected), get_type(actual));
|
||||
boost::apply_visitor(check_visitor<SubjectAttribute>(), expected, actual);
|
||||
}
|
||||
|
||||
VerificationKey create_random_verification_key(int seed)
|
||||
{
|
||||
VerificationKey key;
|
||||
key.key = create_random_public_key(seed);
|
||||
return key;
|
||||
}
|
||||
|
||||
EncryptionKey create_random_encryption_key(int seed)
|
||||
{
|
||||
EncryptionKey key;
|
||||
key.key = create_random_public_key(seed);
|
||||
return key;
|
||||
}
|
||||
|
||||
IntX create_random_its_aid(int seed)
|
||||
{
|
||||
IntX result;
|
||||
result.set((seed ^ (seed >> 23)) & 0xffffff);
|
||||
return result;
|
||||
}
|
||||
|
||||
ItsAidSsp create_random_its_aid_ssp(int seed)
|
||||
{
|
||||
ItsAidSsp result;
|
||||
result.its_aid.set(~seed & 0xffffff);
|
||||
result.service_specific_permissions = random_byte_sequence(10, seed);
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace v2
|
||||
} // namespace security
|
||||
} // namespace vanetza
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
#ifndef CHECK_SUBJECT_ATTRIBUTE_HPP_40Z9HDV2
|
||||
#define CHECK_SUBJECT_ATTRIBUTE_HPP_40Z9HDV2
|
||||
|
||||
#include <vanetza/security/v2/subject_attribute.hpp>
|
||||
#include <vanetza/security/v2/tests/check_basic_elements.hpp>
|
||||
#include <vanetza/security/v2/tests/check_ecc_point.hpp>
|
||||
#include <vanetza/security/v2/tests/check_list.hpp>
|
||||
|
||||
namespace vanetza
|
||||
{
|
||||
namespace security
|
||||
{
|
||||
namespace v2
|
||||
{
|
||||
|
||||
void check(const VerificationKey&, const VerificationKey&);
|
||||
void check(const EncryptionKey&, const EncryptionKey&);
|
||||
void check(const SubjectAssurance&, const SubjectAssurance&);
|
||||
void check(const ItsAidSsp&, const ItsAidSsp&);
|
||||
void check(const SubjectAttribute&, const SubjectAttribute&);
|
||||
|
||||
VerificationKey create_random_verification_key(int seed = 0);
|
||||
EncryptionKey create_random_encryption_key(int seed = 0);
|
||||
IntX create_random_its_aid(int seed = 0);
|
||||
ItsAidSsp create_random_its_aid_ssp(int seed = 0);
|
||||
|
||||
} // namespace v2
|
||||
} // namespace security
|
||||
} // namespace vanetza
|
||||
|
||||
#endif /* CHECK_SUBJECT_ATTRIBUTE_HPP_40Z9HDV2 */
|
||||
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
#ifndef CHECK_SUBJECT_INFO_HPP_LCHGB2G3
|
||||
#define CHECK_SUBJECT_INFO_HPP_LCHGB2G3
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <vanetza/security/v2/subject_info.hpp>
|
||||
|
||||
namespace vanetza
|
||||
{
|
||||
namespace security
|
||||
{
|
||||
namespace v2
|
||||
{
|
||||
|
||||
inline void check(const SubjectInfo& expected, const SubjectInfo& actual)
|
||||
{
|
||||
EXPECT_EQ(expected.subject_type, actual.subject_type);
|
||||
EXPECT_EQ(expected.subject_name, actual.subject_name);
|
||||
}
|
||||
|
||||
} // namespace v2
|
||||
} // namespace security
|
||||
} // namespace vanetza
|
||||
|
||||
#endif /* CHECK_SUBJECT_INFO_HPP_LCHGB2G3 */
|
||||
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include <vanetza/security/v2/tests/check_signature.hpp>
|
||||
#include <vanetza/security/v2/tests/check_trailer_field.hpp>
|
||||
#include <vanetza/security/v2/tests/check_visitor.hpp>
|
||||
#include <boost/mpl/size.hpp>
|
||||
#include <boost/variant/get.hpp>
|
||||
|
||||
namespace vanetza
|
||||
{
|
||||
namespace security
|
||||
{
|
||||
namespace v2
|
||||
{
|
||||
|
||||
void check(const TrailerField& expected, const TrailerField& actual)
|
||||
{
|
||||
static_assert(boost::mpl::size<typename TrailerField::types>::value == 1,
|
||||
"Simple check works only for TrailerField variant with one possible type");
|
||||
check(boost::get<Signature>(expected), boost::get<Signature>(actual));
|
||||
}
|
||||
|
||||
} // namespace v2
|
||||
} // namespace security
|
||||
} // namespace vanetza
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
#ifndef CHECK_TRAILER_FIELD_HPP_5LY4T0VT
|
||||
#define CHECK_TRAILER_FIELD_HPP_5LY4T0VT
|
||||
|
||||
#include <vanetza/security/v2/trailer_field.hpp>
|
||||
|
||||
namespace vanetza
|
||||
{
|
||||
namespace security
|
||||
{
|
||||
namespace v2
|
||||
{
|
||||
|
||||
void check(const TrailerField&, const TrailerField&);
|
||||
|
||||
} // namespace v2
|
||||
} // namespace security
|
||||
} // namespace vanetza
|
||||
|
||||
#endif /* CHECK_TRAILER_FIELD_HPP_5LY4T0VT */
|
||||
Vendored
+42
@@ -0,0 +1,42 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include <vanetza/security/v2/tests/check_region.hpp>
|
||||
#include <vanetza/security/v2/tests/check_validity_restriction.hpp>
|
||||
#include <vanetza/security/v2/tests/check_visitor.hpp>
|
||||
#include <boost/format.hpp>
|
||||
|
||||
namespace vanetza
|
||||
{
|
||||
namespace security
|
||||
{
|
||||
namespace v2
|
||||
{
|
||||
|
||||
void check(EndValidity expected, EndValidity actual)
|
||||
{
|
||||
SCOPED_TRACE("EndValidity");
|
||||
EXPECT_EQ(expected, actual);
|
||||
}
|
||||
|
||||
void check(const StartAndEndValidity& expected, const StartAndEndValidity& actual)
|
||||
{
|
||||
SCOPED_TRACE("StartAndEndValidity");
|
||||
EXPECT_EQ(expected.start_validity, actual.start_validity);
|
||||
EXPECT_EQ(expected.end_validity, actual.end_validity);
|
||||
}
|
||||
|
||||
void check(const StartAndDurationValidity& expected, const StartAndDurationValidity& actual)
|
||||
{
|
||||
SCOPED_TRACE("StartAndDurationValidity");
|
||||
EXPECT_EQ(expected.start_validity, actual.start_validity);
|
||||
EXPECT_EQ(expected.duration.raw(), actual.duration.raw());
|
||||
}
|
||||
|
||||
void check(const ValidityRestriction& expected, const ValidityRestriction& actual)
|
||||
{
|
||||
ASSERT_EQ(get_type(expected), get_type(actual));
|
||||
boost::apply_visitor(check_visitor<ValidityRestriction>(), expected, actual);
|
||||
}
|
||||
|
||||
} // namespace v2
|
||||
} // namespace security
|
||||
} // namespace vanetza
|
||||
Vendored
+23
@@ -0,0 +1,23 @@
|
||||
#ifndef CHECK_VALIDITY_RESTRICTION_HPP_W8OY9526
|
||||
#define CHECK_VALIDITY_RESTRICTION_HPP_W8OY9526
|
||||
|
||||
#include <vanetza/security/v2/validity_restriction.hpp>
|
||||
#include <vanetza/security/v2/tests/check_list.hpp>
|
||||
|
||||
namespace vanetza
|
||||
{
|
||||
namespace security
|
||||
{
|
||||
namespace v2
|
||||
{
|
||||
|
||||
void check(EndValidity, EndValidity);
|
||||
void check(const StartAndEndValidity&, const StartAndEndValidity&);
|
||||
void check(const StartAndDurationValidity&, const StartAndDurationValidity&);
|
||||
void check(const ValidityRestriction&, const ValidityRestriction&);
|
||||
|
||||
} // namespace v2
|
||||
} // namespace security
|
||||
} // namespace vanetza
|
||||
|
||||
#endif /* CHECK_VALIDITY_RESTRICTION_HPP_W8OY9526 */
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
#ifndef CHECK_VISITOR_HPP_YJ7UPXCB
|
||||
#define CHECK_VISITOR_HPP_YJ7UPXCB
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <boost/variant/static_visitor.hpp>
|
||||
#include <typeinfo>
|
||||
|
||||
namespace vanetza
|
||||
{
|
||||
namespace security
|
||||
{
|
||||
|
||||
template<class VARIANT>
|
||||
struct check_visitor : public boost::static_visitor<>
|
||||
{
|
||||
template<typename R, typename S>
|
||||
void operator()(const R&, const S&) const
|
||||
{
|
||||
FAIL() << typeid(R).name() << " differs from " << typeid(S).name();
|
||||
}
|
||||
|
||||
template<typename R>
|
||||
void operator()(const R& lhs, const R& rhs) const
|
||||
{
|
||||
using namespace vanetza::security::v2;
|
||||
check(lhs, rhs);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace security
|
||||
} // namespace vanetza
|
||||
|
||||
#endif /* CHECK_VISITOR_HPP_YJ7UPXCB */
|
||||
Vendored
+244
@@ -0,0 +1,244 @@
|
||||
#include <vanetza/common/manual_runtime.hpp>
|
||||
#include <vanetza/security/v2/certificate_cache.hpp>
|
||||
#include <vanetza/security/v2/default_certificate_validator.hpp>
|
||||
#include <vanetza/security/v2/naive_certificate_provider.hpp>
|
||||
#include <vanetza/security/v2/trust_store.hpp>
|
||||
#include <vanetza/units/angle.hpp>
|
||||
#include <boost/variant/get.hpp>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
using namespace vanetza;
|
||||
using namespace vanetza::security;
|
||||
using namespace vanetza::security::v2;
|
||||
|
||||
class DefaultCertificateValidatorTest : public ::testing::Test
|
||||
{
|
||||
public:
|
||||
DefaultCertificateValidatorTest() :
|
||||
runtime(Clock::at("2016-08-01 00:00")),
|
||||
backend(create_backend("default")),
|
||||
cert_provider(runtime),
|
||||
cert_cache(runtime),
|
||||
cert_validator(*backend, cert_cache, trust_store)
|
||||
{
|
||||
trust_store.insert(cert_provider.root_certificate());
|
||||
cert_cache.insert(cert_provider.aa_certificate());
|
||||
}
|
||||
|
||||
protected:
|
||||
ManualRuntime runtime;
|
||||
std::unique_ptr<Backend> backend;
|
||||
NaiveCertificateProvider cert_provider;
|
||||
std::vector<Certificate> roots;
|
||||
TrustStore trust_store;
|
||||
CertificateCache cert_cache;
|
||||
DefaultCertificateValidator cert_validator;
|
||||
};
|
||||
|
||||
TEST_F(DefaultCertificateValidatorTest, invalid_signer_info)
|
||||
{
|
||||
Certificate cert = cert_provider.generate_authorization_ticket();
|
||||
cert.signer_info = cert_provider.own_chain().front();
|
||||
cert_provider.sign_authorization_ticket(cert);
|
||||
|
||||
CertificateValidity validity = cert_validator.check_certificate(cert);
|
||||
ASSERT_FALSE(validity);
|
||||
EXPECT_EQ(CertificateInvalidReason::Invalid_Signer, validity.reason());
|
||||
}
|
||||
|
||||
TEST_F(DefaultCertificateValidatorTest, missing_subject_assurance)
|
||||
{
|
||||
Certificate cert = cert_provider.generate_authorization_ticket();
|
||||
cert.remove_attribute(SubjectAttributeType::Assurance_Level);
|
||||
cert_provider.sign_authorization_ticket(cert);
|
||||
|
||||
CertificateValidity validity = cert_validator.check_certificate(cert);
|
||||
ASSERT_FALSE(validity);
|
||||
EXPECT_EQ(CertificateInvalidReason::Missing_Subject_Assurance, validity.reason());
|
||||
}
|
||||
|
||||
TEST_F(DefaultCertificateValidatorTest, inconsistent_subject_assurance)
|
||||
{
|
||||
Certificate cert = cert_provider.generate_authorization_ticket();
|
||||
cert.remove_attribute(SubjectAttributeType::Assurance_Level);
|
||||
cert.subject_attributes.push_back(SubjectAssurance(0xE0)); // higher level
|
||||
cert_provider.sign_authorization_ticket(cert);
|
||||
|
||||
CertificateValidity validity = cert_validator.check_certificate(cert);
|
||||
ASSERT_FALSE(validity);
|
||||
EXPECT_EQ(CertificateInvalidReason::Inconsistent_With_Signer, validity.reason());
|
||||
|
||||
cert.remove_attribute(SubjectAttributeType::Assurance_Level);
|
||||
cert.subject_attributes.push_back(SubjectAssurance(0x03)); // same level, higher confidence
|
||||
cert_provider.sign_authorization_ticket(cert);
|
||||
|
||||
validity = cert_validator.check_certificate(cert);
|
||||
ASSERT_FALSE(validity);
|
||||
EXPECT_EQ(CertificateInvalidReason::Inconsistent_With_Signer, validity.reason());
|
||||
}
|
||||
|
||||
TEST_F(DefaultCertificateValidatorTest, validity_time_no_constraint)
|
||||
{
|
||||
Certificate cert = cert_provider.generate_authorization_ticket();
|
||||
cert.remove_restriction(ValidityRestrictionType::Time_Start_And_End);
|
||||
cert_provider.sign_authorization_ticket(cert);
|
||||
|
||||
CertificateValidity validity = cert_validator.check_certificate(cert);
|
||||
ASSERT_FALSE(validity);
|
||||
EXPECT_EQ(CertificateInvalidReason::Broken_Time_Period, validity.reason());
|
||||
}
|
||||
|
||||
TEST_F(DefaultCertificateValidatorTest, validity_time_start_and_end)
|
||||
{
|
||||
Certificate cert = cert_provider.generate_authorization_ticket();
|
||||
cert.remove_restriction(ValidityRestrictionType::Time_Start_And_End);
|
||||
|
||||
StartAndEndValidity restriction;
|
||||
restriction.start_validity = convert_time32(runtime.now() - std::chrono::hours(1));
|
||||
restriction.end_validity = convert_time32(runtime.now() + std::chrono::hours(23));
|
||||
cert.validity_restriction.push_back(restriction);
|
||||
|
||||
cert_provider.sign_authorization_ticket(cert);
|
||||
|
||||
CertificateValidity validity = cert_validator.check_certificate(cert);
|
||||
ASSERT_TRUE(validity);
|
||||
}
|
||||
|
||||
TEST_F(DefaultCertificateValidatorTest, validity_time_start_and_duration)
|
||||
{
|
||||
Certificate cert = cert_provider.generate_authorization_ticket();
|
||||
cert.remove_restriction(ValidityRestrictionType::Time_Start_And_End);
|
||||
|
||||
StartAndDurationValidity restriction;
|
||||
restriction.start_validity = convert_time32(runtime.now() - std::chrono::hours(1));
|
||||
restriction.duration = Duration(23, Duration::Units::Hours);
|
||||
cert.validity_restriction.push_back(restriction);
|
||||
|
||||
cert_provider.sign_authorization_ticket(cert);
|
||||
|
||||
// all certificates must use time_start_and_end as restriction
|
||||
CertificateValidity validity = cert_validator.check_certificate(cert);
|
||||
ASSERT_FALSE(validity);
|
||||
ASSERT_EQ(CertificateInvalidReason::Broken_Time_Period, validity.reason());
|
||||
}
|
||||
|
||||
TEST_F(DefaultCertificateValidatorTest, validity_time_end)
|
||||
{
|
||||
Certificate cert = cert_provider.generate_authorization_ticket();
|
||||
cert.remove_restriction(ValidityRestrictionType::Time_Start_And_End);
|
||||
|
||||
EndValidity restriction = convert_time32(runtime.now() + std::chrono::hours(23));
|
||||
cert.validity_restriction.push_back(restriction);
|
||||
|
||||
cert_provider.sign_authorization_ticket(cert);
|
||||
|
||||
// all certificates must use time_start_and_end as restriction
|
||||
CertificateValidity validity = cert_validator.check_certificate(cert);
|
||||
ASSERT_FALSE(validity);
|
||||
ASSERT_EQ(CertificateInvalidReason::Broken_Time_Period, validity.reason());
|
||||
}
|
||||
|
||||
TEST_F(DefaultCertificateValidatorTest, validity_time_two_constraints)
|
||||
{
|
||||
Certificate cert = cert_provider.generate_authorization_ticket();
|
||||
cert.remove_restriction(ValidityRestrictionType::Time_Start_And_End);
|
||||
// add first constraint
|
||||
StartAndEndValidity start_and_end_validity;
|
||||
start_and_end_validity.start_validity = convert_time32(runtime.now() - std::chrono::hours(1));
|
||||
start_and_end_validity.end_validity = convert_time32(runtime.now() + std::chrono::hours(23));
|
||||
cert.validity_restriction.push_back(start_and_end_validity);
|
||||
// add second constraint
|
||||
StartAndDurationValidity start_and_duration_validity;
|
||||
start_and_duration_validity.start_validity = convert_time32(runtime.now() - std::chrono::hours(1));
|
||||
start_and_duration_validity.duration = Duration(23, Duration::Units::Hours);
|
||||
cert.validity_restriction.push_back(start_and_duration_validity);
|
||||
// re-sign certificate
|
||||
cert_provider.sign_authorization_ticket(cert);
|
||||
|
||||
CertificateValidity validity = cert_validator.check_certificate(cert);
|
||||
ASSERT_FALSE(validity);
|
||||
EXPECT_EQ(CertificateInvalidReason::Broken_Time_Period, validity.reason());
|
||||
}
|
||||
|
||||
TEST_F(DefaultCertificateValidatorTest, validity_time_consistency_with_parent)
|
||||
{
|
||||
// The generated authorization ticket's start time is prior to the AA certificate's start time
|
||||
Certificate cert = cert_provider.generate_authorization_ticket();
|
||||
cert.remove_restriction(ValidityRestrictionType::Time_Start_And_End);
|
||||
|
||||
StartAndEndValidity restriction;
|
||||
restriction.start_validity = convert_time32(runtime.now() - std::chrono::hours(3));
|
||||
restriction.end_validity = convert_time32(runtime.now() + std::chrono::hours(23));
|
||||
cert.validity_restriction.push_back(restriction);
|
||||
|
||||
cert_provider.sign_authorization_ticket(cert);
|
||||
|
||||
CertificateValidity validity = cert_validator.check_certificate(cert);
|
||||
ASSERT_FALSE(validity);
|
||||
EXPECT_EQ(CertificateInvalidReason::Inconsistent_With_Signer, validity.reason());
|
||||
}
|
||||
|
||||
TEST_F(DefaultCertificateValidatorTest, validity_time_consistency_start_and_end)
|
||||
{
|
||||
// The generated authorization ticket's start time is prior to the AA certificate's start time
|
||||
Certificate cert = cert_provider.generate_authorization_ticket();
|
||||
cert.remove_restriction(ValidityRestrictionType::Time_Start_And_End);
|
||||
|
||||
StartAndEndValidity restriction;
|
||||
restriction.start_validity = convert_time32(runtime.now() + std::chrono::hours(3));
|
||||
restriction.end_validity = convert_time32(runtime.now() - std::chrono::hours(23));
|
||||
cert.validity_restriction.push_back(restriction);
|
||||
|
||||
cert_provider.sign_authorization_ticket(cert);
|
||||
|
||||
CertificateValidity validity = cert_validator.check_certificate(cert);
|
||||
ASSERT_FALSE(validity);
|
||||
EXPECT_EQ(CertificateInvalidReason::Broken_Time_Period, validity.reason());
|
||||
}
|
||||
|
||||
TEST_F(DefaultCertificateValidatorTest, reject_additional_permissions)
|
||||
{
|
||||
Certificate cert = cert_provider.generate_authorization_ticket();
|
||||
|
||||
CertificateValidity validity = cert_validator.check_certificate(cert);
|
||||
ASSERT_TRUE(validity);
|
||||
|
||||
cert.add_permission(16513 /* deprecated, so won't be used */, ByteBuffer({}));
|
||||
cert_provider.sign_authorization_ticket(cert);
|
||||
|
||||
validity = cert_validator.check_certificate(cert);
|
||||
ASSERT_FALSE(validity);
|
||||
EXPECT_EQ(CertificateInvalidReason::Inconsistent_With_Signer, validity.reason());
|
||||
}
|
||||
|
||||
TEST_F(DefaultCertificateValidatorTest, accept_permission_subset_permutation)
|
||||
{
|
||||
// We test both orders here, so we're not dependent on changes to the certificate provider order.
|
||||
Certificate cert = cert_provider.generate_authorization_ticket();
|
||||
|
||||
// Order 1
|
||||
cert.remove_attribute(SubjectAttributeType::ITS_AID_SSP_List);
|
||||
cert.add_permission(aid::GN_MGMT, ByteBuffer({}));
|
||||
cert.add_permission(aid::CA, ByteBuffer({ 1, 0, 0 }));
|
||||
cert_provider.sign_authorization_ticket(cert);
|
||||
|
||||
CertificateValidity validity = cert_validator.check_certificate(cert);
|
||||
ASSERT_TRUE(validity);
|
||||
|
||||
// Order 2
|
||||
cert.remove_attribute(SubjectAttributeType::ITS_AID_SSP_List);
|
||||
cert.add_permission(aid::CA, ByteBuffer({ 1, 0, 0 }));
|
||||
cert.add_permission(aid::GN_MGMT, ByteBuffer({}));
|
||||
cert_provider.sign_authorization_ticket(cert);
|
||||
|
||||
validity = cert_validator.check_certificate(cert);
|
||||
ASSERT_TRUE(validity);
|
||||
|
||||
// Definite subset
|
||||
cert.remove_attribute(SubjectAttributeType::ITS_AID_SSP_List);
|
||||
cert.add_permission(aid::CA, ByteBuffer({ 1, 0, 0 }));
|
||||
cert_provider.sign_authorization_ticket(cert);
|
||||
|
||||
validity = cert_validator.check_certificate(cert);
|
||||
ASSERT_TRUE(validity);
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include <vanetza/common/byte_sequence.hpp>
|
||||
#include <vanetza/security/v2/ecc_point.hpp>
|
||||
#include <vanetza/security/v2/public_key.hpp>
|
||||
#include <vanetza/security/v2/tests/check_ecc_point.hpp>
|
||||
|
||||
using vanetza::ByteBuffer;
|
||||
using namespace vanetza::security;
|
||||
using namespace vanetza::security::v2;
|
||||
using namespace vanetza;
|
||||
using namespace std;
|
||||
|
||||
static const std::size_t length = field_size(PublicKeyAlgorithm::ECDSA_NISTP256_With_SHA256);
|
||||
|
||||
EccPoint serialize_roundtrip(const EccPoint& point)
|
||||
{
|
||||
EccPoint outPoint;
|
||||
std::stringstream stream;
|
||||
OutputArchive oa(stream);
|
||||
serialize(oa, point, PublicKeyAlgorithm::ECDSA_NISTP256_With_SHA256);
|
||||
InputArchive ia(stream);
|
||||
deserialize(ia, outPoint, PublicKeyAlgorithm::ECDSA_NISTP256_With_SHA256);
|
||||
return outPoint;
|
||||
}
|
||||
|
||||
TEST(EccPoint, uncompressed)
|
||||
{
|
||||
EccPoint point = Uncompressed { random_byte_sequence(length, 1), random_byte_sequence(length, 2) };
|
||||
EccPoint outPoint = serialize_roundtrip(point);
|
||||
check(point, outPoint);
|
||||
EXPECT_EQ(EccPointType::Uncompressed, get_type(outPoint));
|
||||
}
|
||||
|
||||
TEST(EccPoint, Compressed_Lsb_Y_0)
|
||||
{
|
||||
EccPoint point = Compressed_Lsb_Y_0 { random_byte_sequence(length, 3) };
|
||||
EccPoint outPoint = serialize_roundtrip(point);
|
||||
check(point, outPoint);
|
||||
EXPECT_EQ(EccPointType::Compressed_Lsb_Y_0, get_type(outPoint));
|
||||
}
|
||||
|
||||
TEST(EccPoint, X_Coordinate_Only)
|
||||
{
|
||||
EccPoint point = X_Coordinate_Only { random_byte_sequence(length, 4) };
|
||||
EccPoint outPoint = serialize_roundtrip(point);
|
||||
check(point, outPoint);
|
||||
EXPECT_EQ(EccPointType::X_Coordinate_Only, get_type(outPoint));
|
||||
}
|
||||
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include <vanetza/common/byte_sequence.hpp>
|
||||
#include <vanetza/security/v2/encryption_parameter.hpp>
|
||||
#include <vanetza/security/v2/tests/check_encryption_parameter.hpp>
|
||||
#include <vanetza/security/tests/serialization.hpp>
|
||||
#include <algorithm>
|
||||
|
||||
using namespace vanetza::security::v2;
|
||||
|
||||
TEST(EncryptionParameter, Nonce)
|
||||
{
|
||||
Nonce nonce;
|
||||
auto random = vanetza::random_byte_sequence(nonce.size());
|
||||
std::copy_n(random.begin(), nonce.size(), nonce.begin());
|
||||
EncryptionParameter param = nonce;
|
||||
check(param, serialize_roundtrip(param));
|
||||
}
|
||||
+94
@@ -0,0 +1,94 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include <vanetza/common/byte_sequence.hpp>
|
||||
#include <vanetza/security/v2/header_field.hpp>
|
||||
#include <vanetza/security/v2/tests/check_header_field.hpp>
|
||||
#include <vanetza/security/v2/tests/check_signature.hpp>
|
||||
#include <vanetza/security/tests/serialization.hpp>
|
||||
#include <algorithm>
|
||||
|
||||
using namespace vanetza;
|
||||
using namespace vanetza::security;
|
||||
using namespace vanetza::security::v2;
|
||||
|
||||
TEST(HeaderField, Serialize)
|
||||
{
|
||||
std::list<HeaderField> list;
|
||||
|
||||
std::list<Certificate> certificates;
|
||||
for (unsigned i = 0; i < 2; ++i) {
|
||||
auto rand_gen = random_byte_generator(i + 8 * 3);
|
||||
Certificate cert;
|
||||
HashedId8 cert_digest;
|
||||
std::generate(cert_digest.begin(), cert_digest.end(), rand_gen);
|
||||
cert.signer_info = cert_digest;
|
||||
cert.subject_info = { SubjectType::Enrollment_Credential, random_byte_sequence(28, i) };
|
||||
cert.signature = create_random_ecdsa_signature(i + 8);
|
||||
certificates.push_back(cert);
|
||||
}
|
||||
list.push_back(SignerInfo { certificates });
|
||||
|
||||
list.push_back(Time64 { 983 });
|
||||
|
||||
Time64WithStandardDeviation time_dev;
|
||||
time_dev.log_std_dev = 1;
|
||||
time_dev.time64 = 2000;
|
||||
list.push_back(time_dev);
|
||||
|
||||
list.push_back(Time32 { 434 });
|
||||
|
||||
ThreeDLocation loc;
|
||||
loc.latitude.from_value(838);
|
||||
loc.longitude.from_value(37);
|
||||
loc.elevation = {{ 83, 17 }};
|
||||
list.push_back(loc);
|
||||
|
||||
std::list<HashedId3> hashed;
|
||||
for (unsigned i = 0; i < 3; ++i) {
|
||||
HashedId3 id;
|
||||
std::generate(id.begin(), id.end(), random_byte_generator(i + 8943));
|
||||
hashed.push_back(id);
|
||||
}
|
||||
list.push_back(hashed);
|
||||
|
||||
list.push_back(IntX { 43 });
|
||||
|
||||
Nonce nonce;
|
||||
std::generate(nonce.begin(), nonce.end(), random_byte_generator(22));
|
||||
list.push_back(EncryptionParameter { nonce });
|
||||
|
||||
std::list<RecipientInfo> recipients;
|
||||
for (unsigned i = 0; i < 2; ++i) {
|
||||
const std::size_t length = field_size(PublicKeyAlgorithm::ECIES_NISTP256);
|
||||
auto rand_gen = random_byte_generator(i + 93);
|
||||
RecipientInfo info;
|
||||
EciesEncryptedKey key;
|
||||
std::generate(info.cert_id.begin(), info.cert_id.end(), rand_gen);
|
||||
key.c = random_byte_sequence(field_size(SymmetricAlgorithm::AES128_CCM), rand_gen());
|
||||
std::generate(key.t.begin(), key.t.end(), rand_gen);
|
||||
key.v = Uncompressed {
|
||||
random_byte_sequence(length, rand_gen()),
|
||||
random_byte_sequence(length, rand_gen()) };
|
||||
info.enc_key = key;
|
||||
recipients.push_back(info);
|
||||
}
|
||||
list.push_back(recipients);
|
||||
|
||||
check(list, serialize_roundtrip(list));
|
||||
}
|
||||
|
||||
TEST(HeaderField, WebValidator_SecuredMessage3_adapted)
|
||||
{
|
||||
const char str[] =
|
||||
"810180020201A8ED6DF65B0E6D6A010080940000040209B0434163CCBAFDD34A45333E418FB96C"
|
||||
"05BBE0E7E1D755D40D0B4BBE8DA508EC2F2723B7ADF0F27C39F3AECFF0783C196F9961F8821E6294"
|
||||
"375D9294CD6A01000452113CE698DB081491675DF8FFE81C23EA5D0071B2D2BF0E0DA4ADA0CDA582"
|
||||
"59CA5D999200B6565E194EDAB8BD3DCA863F2DDF39C13E7A0375ECE2566C5EB8C60200210AC04080"
|
||||
"0101C0408101010F01099EB20109B1270003040100960000008DA1F3F9F35E04C3DE77D7438988A8"
|
||||
"D57EBE44DAA021A4269E297C177C9CFE458E128EC290785D6631961625020943B6D87DAA54919A98"
|
||||
"F7865709929A7C6E480000009373CF482D400502";
|
||||
std::list<HeaderField> list;
|
||||
const size_t deserialize_length = deserialize_from_hexstring(str, list);
|
||||
EXPECT_EQ(257, deserialize_length);
|
||||
EXPECT_EQ(257, get_size(list));
|
||||
EXPECT_EQ(3, list.size());
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
#include <vanetza/security/v2/int_x.hpp>
|
||||
#include <vanetza/security/v2/length_coding.hpp>
|
||||
#include <vanetza/security/tests/serialization.hpp>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
using vanetza::ByteBuffer;
|
||||
using vanetza::security::v2::IntX;
|
||||
|
||||
TEST(IntX, set_and_get)
|
||||
{
|
||||
IntX a;
|
||||
EXPECT_EQ(0, a.get());
|
||||
|
||||
a.set(static_cast<int8_t>(89));
|
||||
EXPECT_EQ(89, a.get());
|
||||
|
||||
a.set(static_cast<uint32_t>(0x12345678));
|
||||
EXPECT_EQ(0x12345678, a.get());
|
||||
}
|
||||
|
||||
TEST(IntX, get_size)
|
||||
{
|
||||
IntX a;
|
||||
EXPECT_EQ(1, get_size(a));
|
||||
|
||||
a.set(static_cast<int8_t>(89));
|
||||
EXPECT_EQ(1, get_size(a));
|
||||
|
||||
a.set(127);
|
||||
EXPECT_EQ(1, get_size(a));
|
||||
|
||||
a.set(128);
|
||||
EXPECT_EQ(2, get_size(a));
|
||||
|
||||
a.set(0x23);
|
||||
EXPECT_EQ(1, get_size(a));
|
||||
|
||||
a.set(static_cast<uint32_t>(0x00130033));
|
||||
EXPECT_EQ(3, get_size(a));
|
||||
|
||||
a.set(static_cast<uint32_t>(0x00230033));
|
||||
EXPECT_EQ(4, get_size(a));
|
||||
|
||||
a.set(static_cast<uint32_t>(0x33003300));
|
||||
EXPECT_EQ(5, get_size(a));
|
||||
}
|
||||
|
||||
TEST(IntX, encode)
|
||||
{
|
||||
IntX a;
|
||||
EXPECT_EQ((ByteBuffer { 0x00 }), a.encode());
|
||||
|
||||
a.set(127);
|
||||
EXPECT_EQ((ByteBuffer { 127 }), a.encode());
|
||||
|
||||
a.set(128);
|
||||
EXPECT_EQ((ByteBuffer { 0x80, 128 }), a.encode());
|
||||
|
||||
a.set(0x00120034);
|
||||
EXPECT_EQ((ByteBuffer { 0xd2, 0x00, 0x34 }), a.encode());
|
||||
|
||||
a.set(0x00320034);
|
||||
EXPECT_EQ((ByteBuffer { 0xe0, 0x32, 0x00, 0x34 }), a.encode());
|
||||
}
|
||||
|
||||
TEST(IntX, decode)
|
||||
{
|
||||
ByteBuffer buf { 0xe0, 0x32, 0x00, 0x34 };
|
||||
auto decoded = IntX::decode(buf);
|
||||
ASSERT_TRUE(!!decoded);
|
||||
EXPECT_EQ(0x320034, decoded->get());
|
||||
}
|
||||
|
||||
TEST(IntX, decode_one_null_byte)
|
||||
{
|
||||
ByteBuffer buf { 0x00 };
|
||||
auto decoded = IntX::decode(buf);
|
||||
ASSERT_TRUE(!!decoded);
|
||||
EXPECT_EQ(0, decoded->get());
|
||||
}
|
||||
|
||||
TEST(IntX, decode_empty)
|
||||
{
|
||||
ByteBuffer buf;
|
||||
auto decoded = IntX::decode(buf);
|
||||
EXPECT_FALSE(!!decoded);
|
||||
}
|
||||
|
||||
TEST(IntX, decode_broken)
|
||||
{
|
||||
ByteBuffer buf { 0xff, 0xff };
|
||||
auto decoded = IntX::decode(buf);
|
||||
EXPECT_FALSE(!!decoded);
|
||||
}
|
||||
|
||||
TEST(IntX, serialization)
|
||||
{
|
||||
IntX x;
|
||||
x.set(0);
|
||||
EXPECT_EQ(x, serialize_roundtrip(x));
|
||||
|
||||
x.set(255);
|
||||
EXPECT_EQ(x, serialize_roundtrip(x));
|
||||
|
||||
x.set(0x123456);
|
||||
EXPECT_EQ(x, serialize_roundtrip(x));
|
||||
}
|
||||
+128
@@ -0,0 +1,128 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include <vanetza/common/byte_buffer_sink.hpp>
|
||||
#include <vanetza/common/byte_buffer_source.hpp>
|
||||
#include <vanetza/security/v2/length_coding.hpp>
|
||||
#include <vanetza/security/v2/serialization.hpp>
|
||||
#include <boost/iostreams/stream_buffer.hpp>
|
||||
|
||||
using vanetza::ByteBuffer;
|
||||
using vanetza::InputArchive;
|
||||
using vanetza::OutputArchive;
|
||||
using namespace vanetza::security::v2;
|
||||
|
||||
TEST(LengthEncoding, count_leading_ones)
|
||||
{
|
||||
EXPECT_EQ(0, count_leading_ones(0x00));
|
||||
EXPECT_EQ(1, count_leading_ones(0x80));
|
||||
EXPECT_EQ(1, count_leading_ones(0x81));
|
||||
EXPECT_EQ(1, count_leading_ones(0xa0));
|
||||
EXPECT_EQ(1, count_leading_ones(0xa1));
|
||||
EXPECT_EQ(2, count_leading_ones(0xd3));
|
||||
EXPECT_EQ(3, count_leading_ones(0xe8));
|
||||
EXPECT_EQ(7, count_leading_ones(0xfe));
|
||||
EXPECT_EQ(8, count_leading_ones(0xff));
|
||||
}
|
||||
|
||||
TEST(LengthEncoding, encode_length)
|
||||
{
|
||||
EXPECT_EQ(ByteBuffer { 0x00 }, encode_length(0));
|
||||
EXPECT_EQ(ByteBuffer { 5 }, encode_length(5));
|
||||
EXPECT_EQ(ByteBuffer { 123 }, encode_length(123));
|
||||
EXPECT_EQ(ByteBuffer { 127 }, encode_length(127));
|
||||
EXPECT_EQ((ByteBuffer { 0x80, 128 }), encode_length(128));
|
||||
EXPECT_EQ((ByteBuffer { 0xbf, 0xff }), encode_length(0x3fff));
|
||||
EXPECT_EQ((ByteBuffer { 0x81, 0xff }), encode_length(0x01ff));
|
||||
EXPECT_EQ((ByteBuffer { 0xdf, 0xff, 0xff }), encode_length(0x1fffff));
|
||||
EXPECT_EQ((ByteBuffer { 0xe0, 0x20, 0x00, 0x00 }), encode_length(0x200000));
|
||||
|
||||
EXPECT_EQ(ByteBuffer { 0x0a }, encode_length(10));
|
||||
EXPECT_EQ((ByteBuffer { 0x88, 0x88 }), encode_length(2184));
|
||||
}
|
||||
|
||||
TEST(LengthEncoding, decode_length_empty_buffer)
|
||||
{
|
||||
ByteBuffer buffer;
|
||||
auto decoded = decode_length(buffer);
|
||||
EXPECT_EQ(buffer.end(), std::get<0>(decoded));
|
||||
EXPECT_EQ(0, std::get<1>(decoded));
|
||||
}
|
||||
|
||||
TEST(LengthEncoding, decode_length_zero_size)
|
||||
{
|
||||
ByteBuffer buffer { 0x00, 0xC0, 0xFF, 0xEE };
|
||||
auto decoded = decode_length(buffer);
|
||||
EXPECT_EQ(std::next(buffer.begin()), std::get<0>(decoded));
|
||||
EXPECT_EQ(0, std::get<1>(decoded));
|
||||
}
|
||||
|
||||
TEST(LengthEncoding, decode_length_prefix_too_long)
|
||||
{
|
||||
ByteBuffer buffer { 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xba, 0xbe };
|
||||
auto decoded = decode_length(buffer);
|
||||
EXPECT_EQ(buffer.begin(), std::get<0>(decoded));
|
||||
EXPECT_EQ(0, std::get<1>(decoded));
|
||||
}
|
||||
|
||||
TEST(LengthEncoding, decode_length_buffer_too_short)
|
||||
{
|
||||
ByteBuffer buffer { 0x02, 0xde };
|
||||
auto decoded_tuple = decode_length(buffer);
|
||||
EXPECT_EQ(std::next(buffer.begin()), std::get<0>(decoded_tuple));
|
||||
EXPECT_EQ(2, std::get<1>(decoded_tuple));
|
||||
}
|
||||
|
||||
TEST(LengthEncoding, decode_length_good)
|
||||
{
|
||||
ByteBuffer buffer { 0xe0, 0x00, 0x00, 0x04, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde };
|
||||
auto decoded_tuple = decode_length(buffer);
|
||||
EXPECT_EQ(std::next(buffer.begin(), 4), std::get<0>(decoded_tuple));
|
||||
EXPECT_EQ(4, std::get<1>(decoded_tuple));
|
||||
}
|
||||
|
||||
TEST(LengthEncoding, serialize_length)
|
||||
{
|
||||
ByteBuffer buf;
|
||||
auto serialize_length_into_buffer = [&buf](std::size_t length) {
|
||||
vanetza::byte_buffer_sink sink(buf);
|
||||
boost::iostreams::stream_buffer<vanetza::byte_buffer_sink> stream(sink);
|
||||
OutputArchive oa(stream);
|
||||
serialize_length(oa, length);
|
||||
};
|
||||
|
||||
serialize_length_into_buffer(0x200000);
|
||||
ASSERT_EQ(4, buf.size());
|
||||
EXPECT_EQ(0xE0, buf[0]);
|
||||
EXPECT_EQ(0x20, buf[1]);
|
||||
EXPECT_EQ(0x00, buf[2]);
|
||||
EXPECT_EQ(0x00, buf[3]);
|
||||
buf.clear();
|
||||
|
||||
serialize_length_into_buffer(128);
|
||||
ASSERT_EQ(2, buf.size());
|
||||
EXPECT_EQ(0x80, buf[0]);
|
||||
EXPECT_EQ(0x80, buf[1]);
|
||||
}
|
||||
|
||||
TEST(LengthEncoding, length_coding_size)
|
||||
{
|
||||
EXPECT_EQ(1, length_coding_size(0x3f));
|
||||
EXPECT_EQ(1, length_coding_size(0x20));
|
||||
EXPECT_EQ(1, length_coding_size(0x7f));
|
||||
EXPECT_EQ(1, length_coding_size(0x40));
|
||||
EXPECT_EQ(2, length_coding_size(0x3fff));
|
||||
EXPECT_EQ(2, length_coding_size(0x2000));
|
||||
EXPECT_EQ(3, length_coding_size(0x7fff));
|
||||
EXPECT_EQ(3, length_coding_size(0x4000));
|
||||
EXPECT_EQ(3, length_coding_size(0x1fffff));
|
||||
EXPECT_EQ(4, length_coding_size(0x3fffff));
|
||||
}
|
||||
|
||||
TEST(LengthEncoding, WebValidator_length)
|
||||
{
|
||||
ByteBuffer buf {{ 0x81, 0x03 }};
|
||||
vanetza::byte_buffer_source source(buf);
|
||||
boost::iostreams::stream_buffer<vanetza::byte_buffer_source> stream(source);
|
||||
InputArchive ia(stream);
|
||||
size_t length = deserialize_length(ia);
|
||||
EXPECT_EQ(259, length);
|
||||
}
|
||||
Vendored
+91
@@ -0,0 +1,91 @@
|
||||
#include <vanetza/common/clock.hpp>
|
||||
#include <vanetza/common/manual_runtime.hpp>
|
||||
#include <vanetza/security/v2/default_certificate_validator.hpp>
|
||||
#include <vanetza/security/v2/naive_certificate_provider.hpp>
|
||||
#include <boost/variant/get.hpp>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
using namespace vanetza;
|
||||
using namespace vanetza::security;
|
||||
using namespace vanetza::security::v2;
|
||||
using boost::get;
|
||||
|
||||
class NaiveCertificateProviderTest : public ::testing::Test
|
||||
{
|
||||
public:
|
||||
NaiveCertificateProviderTest() : runtime(Clock::at("2016-08-01 00:00")), cert_provider(runtime)
|
||||
{
|
||||
}
|
||||
|
||||
protected:
|
||||
ManualRuntime runtime;
|
||||
NaiveCertificateProvider cert_provider;
|
||||
};
|
||||
|
||||
TEST_F(NaiveCertificateProviderTest, own_certificate)
|
||||
{
|
||||
Certificate signed_certificate = cert_provider.own_certificate();
|
||||
|
||||
// Check signature
|
||||
EXPECT_EQ(2 * field_size(PublicKeyAlgorithm::ECDSA_NISTP256_With_SHA256),
|
||||
extract_signature_buffer(signed_certificate.signature.some_ecdsa).size());
|
||||
EXPECT_EQ(PublicKeyAlgorithm::ECDSA_NISTP256_With_SHA256, get_type(signed_certificate.signature));
|
||||
|
||||
// Check signer_info and subject_info
|
||||
EXPECT_EQ(2, signed_certificate.version());
|
||||
EXPECT_EQ(SignerInfoType::Certificate_Digest_With_SHA256, get_type(signed_certificate.signer_info));
|
||||
EXPECT_EQ(SubjectType::Authorization_Ticket, signed_certificate.subject_info.subject_type);
|
||||
EXPECT_TRUE(signed_certificate.subject_info.subject_name.empty());
|
||||
|
||||
// Check subject attributes
|
||||
int verification_key_counter = 0;
|
||||
SubjectAssurance test_assurance_level;
|
||||
int assurance_level_counter = 0;
|
||||
|
||||
using subject_type_int = std::underlying_type<SubjectAttributeType>::type;
|
||||
subject_type_int last_subject_type = 0;
|
||||
|
||||
for (auto& subject_attribute : signed_certificate.subject_attributes) {
|
||||
// Verify that fields are in ascending order
|
||||
subject_type_int subject_type = static_cast<subject_type_int>(get_type(subject_attribute));
|
||||
EXPECT_LE(last_subject_type, subject_type);
|
||||
last_subject_type = subject_type;
|
||||
|
||||
if (SubjectAttributeType::Verification_Key == get_type(subject_attribute)) {
|
||||
verification_key_counter++;
|
||||
} else if (SubjectAttributeType::Assurance_Level == get_type(subject_attribute)) {
|
||||
test_assurance_level = get<SubjectAssurance>(subject_attribute);
|
||||
assurance_level_counter++;
|
||||
} else if (SubjectAttributeType::ITS_AID_SSP_List == get_type(subject_attribute)) {
|
||||
// TODO: check aid permissions
|
||||
}
|
||||
}
|
||||
|
||||
EXPECT_EQ(1, verification_key_counter);
|
||||
ASSERT_EQ(1, assurance_level_counter);
|
||||
EXPECT_EQ(0, test_assurance_level.raw);
|
||||
|
||||
// Check validity restrictions
|
||||
Time32 start_time;
|
||||
Time32 end_time;
|
||||
|
||||
using restriction_type_int = std::underlying_type<ValidityRestrictionType>::type;
|
||||
restriction_type_int last_restriction_type = 0;
|
||||
|
||||
for (ValidityRestriction restriction : signed_certificate.validity_restriction) {
|
||||
// Verify that fields are in ascending order
|
||||
restriction_type_int restriction_type = static_cast<restriction_type_int>(get_type(restriction));
|
||||
EXPECT_LE(last_restriction_type, restriction_type);
|
||||
last_restriction_type = restriction_type;
|
||||
|
||||
if (ValidityRestrictionType::Time_Start_And_End == get_type(restriction)) {
|
||||
StartAndEndValidity& time_validation = get<StartAndEndValidity>(restriction);
|
||||
start_time = time_validation.start_validity;
|
||||
end_time = time_validation.end_validity;
|
||||
} else if (ValidityRestrictionType::Region == get_type(restriction)) {
|
||||
// TODO: Region not specified yet
|
||||
}
|
||||
}
|
||||
|
||||
EXPECT_LT(start_time, end_time);
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include <vanetza/security/v2/payload.hpp>
|
||||
#include <vanetza/security/v2/tests/check_payload.hpp>
|
||||
#include <vanetza/security/tests/serialization.hpp>
|
||||
|
||||
using namespace vanetza;
|
||||
using namespace vanetza::security::v2;
|
||||
|
||||
TEST(Payload, serialize_cohesive)
|
||||
{
|
||||
Payload p;
|
||||
p.type = PayloadType::Unsecured;
|
||||
p.data = CohesivePacket({ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 }, OsiLayer::Application);
|
||||
|
||||
check(p, serialize_roundtrip(p));
|
||||
}
|
||||
|
||||
TEST(Payload, serialize_chunk)
|
||||
{
|
||||
Payload p;
|
||||
p.type = PayloadType::Encrypted;
|
||||
ChunkPacket packet;
|
||||
packet[OsiLayer::Network] = ByteBuffer { 1, 2, 3, 4 };
|
||||
packet[OsiLayer::Transport] = ByteBuffer { 5, 6, 7, 8 };
|
||||
packet[OsiLayer::Application] = ByteBuffer { 9, 10, 11, 12 };
|
||||
p.data = packet;
|
||||
|
||||
check(p, serialize_roundtrip(p));
|
||||
}
|
||||
|
||||
TEST(Payload, size)
|
||||
{
|
||||
Payload p;
|
||||
p.type = PayloadType::Signed;
|
||||
p.data = CohesivePacket({ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9}, OsiLayer::Session);
|
||||
EXPECT_EQ(1 /* type */ + 1 /* length coding */ + 10 /* bytes */, get_size(p));
|
||||
}
|
||||
|
||||
+90
@@ -0,0 +1,90 @@
|
||||
#include <vanetza/security/v2/persistence.hpp>
|
||||
#include <gtest/gtest.h>
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
#include <fstream>
|
||||
#include <iterator>
|
||||
#include <sstream>
|
||||
|
||||
using namespace vanetza::security;
|
||||
|
||||
#define WRITEABLE(path) WORK_DIR "/" path
|
||||
#define ASSET(path) ASSET_DIR "/" path
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
const std::array<uint8_t, 32> expected_private_key = {
|
||||
0x53, 0xb7, 0x7e, 0xb8, 0x48, 0x2e, 0x3c, 0x1a,
|
||||
0xd3, 0x36, 0x70, 0xc0, 0xc6, 0xc4, 0x6b, 0xc0,
|
||||
0x36, 0x90, 0xd4, 0x00, 0x59, 0xd3, 0xcb, 0xb5,
|
||||
0x81, 0xb3, 0x36, 0xaf, 0x8a, 0x98, 0x93, 0xf4
|
||||
};
|
||||
|
||||
const std::array<uint8_t, 32> expected_public_x = {
|
||||
0x1c, 0x85, 0x0d, 0xc7, 0x45, 0x63, 0x29, 0x3c,
|
||||
0xb0, 0xf3, 0xe5, 0x5e, 0xda, 0x7b, 0x10, 0xec,
|
||||
0xb4, 0xe9, 0x74, 0x6f, 0x83, 0x6f, 0x84, 0x76,
|
||||
0x96, 0xc3, 0x1e, 0xe8, 0x68, 0x4e, 0x37, 0x76
|
||||
};
|
||||
|
||||
const std::array<uint8_t, 32> expected_public_y = {
|
||||
0x28, 0xf1, 0x67, 0xfb, 0x64, 0xce, 0x7b, 0x79,
|
||||
0xa6, 0x02, 0x06, 0x2a, 0xac, 0x11, 0x7f, 0x59,
|
||||
0x6b, 0xac, 0x77, 0xc7, 0x1c, 0xd6, 0xf4, 0xca,
|
||||
0xa7, 0x08, 0x7a, 0xcc, 0xcd, 0xab, 0x91, 0xab
|
||||
};
|
||||
|
||||
void check_key_pair(const ecdsa256::KeyPair& kp)
|
||||
{
|
||||
EXPECT_EQ(kp.private_key.key, expected_private_key);
|
||||
EXPECT_EQ(kp.public_key.x, expected_public_x);
|
||||
EXPECT_EQ(kp.public_key.y, expected_public_y);
|
||||
}
|
||||
|
||||
ecdsa256::KeyPair make_test_key_pair()
|
||||
{
|
||||
ecdsa256::KeyPair kp;
|
||||
kp.private_key.key = expected_private_key;
|
||||
kp.public_key.x = expected_public_x;
|
||||
kp.public_key.y = expected_public_y;
|
||||
return kp;
|
||||
}
|
||||
|
||||
std::string read_file_bytes(const std::string& path)
|
||||
{
|
||||
std::ifstream file(path, std::ios::binary);
|
||||
return {std::istreambuf_iterator<char>(file), std::istreambuf_iterator<char>()};
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
#if defined VANETZA_WITH_OPENSSL || defined VANETZA_WITH_CRYPTOPP
|
||||
|
||||
TEST(Persistence, load_private_key_from_file)
|
||||
{
|
||||
check_key_pair(v2::load_private_key_from_file(ASSET("test_key.der")));
|
||||
}
|
||||
|
||||
TEST(Persistence, save_and_load_pkcs8_der)
|
||||
{
|
||||
auto kp = make_test_key_pair();
|
||||
const std::string path = WRITEABLE("test_save.der");
|
||||
std::ofstream ofs(path, std::ios::binary);
|
||||
EXPECT_TRUE(v2::save_private_key_pkcs8_der(ofs, kp));
|
||||
ofs.flush();
|
||||
check_key_pair(v2::load_private_key_from_file(path));
|
||||
std::remove(path.c_str());
|
||||
}
|
||||
|
||||
TEST(Persistence, save_der_matches_reference_file)
|
||||
{
|
||||
auto kp = make_test_key_pair();
|
||||
std::ostringstream oss(std::ios::binary);
|
||||
EXPECT_TRUE(v2::save_private_key_pkcs8_der(oss, kp));
|
||||
auto reference = read_file_bytes(ASSET("test_key.der"));
|
||||
EXPECT_EQ(oss.str(), reference);
|
||||
}
|
||||
|
||||
#endif /* VANETZA_WITH_OPENSSL || VANETZA_WITH_CRYPTOPP */
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include <vanetza/common/byte_sequence.hpp>
|
||||
#include <vanetza/security/public_key.hpp>
|
||||
#include <vanetza/security/v2/public_key.hpp>
|
||||
#include <vanetza/security/v2/tests/check_public_key.hpp>
|
||||
|
||||
using namespace vanetza;
|
||||
using namespace vanetza::security;
|
||||
using namespace std;
|
||||
|
||||
v2::PublicKey serialize(v2::PublicKey key)
|
||||
{
|
||||
std::stringstream stream;
|
||||
OutputArchive oa(stream);
|
||||
serialize(oa, key);
|
||||
|
||||
v2::PublicKey deKey;
|
||||
InputArchive ia(stream);
|
||||
deserialize(ia, deKey);
|
||||
return deKey;
|
||||
}
|
||||
|
||||
TEST(PublicKey, Field_Size)
|
||||
{
|
||||
EXPECT_EQ(32, field_size(v2::PublicKeyAlgorithm::ECDSA_NISTP256_With_SHA256));
|
||||
EXPECT_EQ(32, field_size(v2::PublicKeyAlgorithm::ECIES_NISTP256));
|
||||
}
|
||||
|
||||
TEST(PublicKey, ECIES_NISTP256)
|
||||
{
|
||||
v2::ecies_nistp256 ecies;
|
||||
ecies.public_key = Uncompressed { random_byte_sequence(32, 1), random_byte_sequence(32, 2) };
|
||||
ecies.supported_symm_alg = v2::SymmetricAlgorithm::AES128_CCM;
|
||||
v2::PublicKey key = ecies;
|
||||
|
||||
v2::PublicKey deKey = serialize(key);
|
||||
check(key, deKey);
|
||||
EXPECT_EQ(v2::PublicKeyAlgorithm::ECIES_NISTP256, get_type(deKey));
|
||||
EXPECT_EQ(67, get_size(deKey));
|
||||
}
|
||||
|
||||
TEST(PublicKey, ECDSA_NISTP256_With_SHA256)
|
||||
{
|
||||
v2::ecdsa_nistp256_with_sha256 ecdsa;
|
||||
ecdsa.public_key = X_Coordinate_Only { random_byte_sequence(32, 1) };
|
||||
v2::PublicKey key = ecdsa;
|
||||
|
||||
v2::PublicKey deKey = serialize(key);
|
||||
check(key, deKey);
|
||||
EXPECT_EQ(v2::PublicKeyAlgorithm::ECDSA_NISTP256_With_SHA256, get_type(deKey));
|
||||
EXPECT_EQ(34, get_size(deKey));
|
||||
}
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include <vanetza/common/byte_sequence.hpp>
|
||||
#include <vanetza/security/v2/recipient_info.hpp>
|
||||
#include <vanetza/security/v2/tests/check_recipient_info.hpp>
|
||||
#include <vanetza/security/tests/serialization.hpp>
|
||||
|
||||
using namespace vanetza;
|
||||
using namespace vanetza::security;
|
||||
using namespace vanetza::security::v2;
|
||||
|
||||
TEST(RecipientInfo, Serialize)
|
||||
{
|
||||
EciesEncryptedKey ecies;
|
||||
ecies.v = Compressed_Lsb_Y_0 { random_byte_sequence(field_size(PublicKeyAlgorithm::ECIES_NISTP256), 1337) };
|
||||
auto cbuf = random_byte_sequence(field_size(SymmetricAlgorithm::AES128_CCM), 7331);
|
||||
ecies.c = { cbuf.begin(), cbuf.end() };
|
||||
auto tbuf = random_byte_sequence(ecies.t.size(), 1234);
|
||||
std::copy_n(tbuf.begin(), ecies.t.size(), ecies.t.data());
|
||||
RecipientInfo info;
|
||||
info.enc_key = ecies;
|
||||
auto certbuf = random_byte_sequence(info.cert_id.size(), 4321);
|
||||
std::copy_n(certbuf.begin(), info.cert_id.size(), info.cert_id.data());
|
||||
|
||||
check(info, serialize_roundtrip(info, SymmetricAlgorithm::AES128_CCM));
|
||||
}
|
||||
@@ -0,0 +1,261 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include <vanetza/security/v2/region.hpp>
|
||||
#include <vanetza/security/v2/tests/check_region.hpp>
|
||||
#include <vanetza/security/tests/serialization.hpp>
|
||||
#include <vanetza/units/angle.hpp>
|
||||
#include <vanetza/units/length.hpp>
|
||||
#include <limits>
|
||||
|
||||
using namespace vanetza::security::v2;
|
||||
using vanetza::geonet::distance_u16t;
|
||||
using vanetza::geonet::geo_angle_i32t;
|
||||
using vanetza::units::degrees;
|
||||
using vanetza::units::si::meter;
|
||||
|
||||
TEST(Region, Serialize_CircularRegion)
|
||||
{
|
||||
CircularRegion reg;
|
||||
reg.center.latitude = static_cast<geo_angle_i32t>(12564 * degrees);
|
||||
reg.center.longitude = static_cast<geo_angle_i32t>(654321 * degrees);
|
||||
reg.radius = static_cast<distance_u16t>(1337 * meter);
|
||||
check(reg, serialize_roundtrip(reg));
|
||||
}
|
||||
|
||||
TEST(Region, Serialize_IdentifiedRegion)
|
||||
{
|
||||
IdentifiedRegion reg;
|
||||
reg.region_dictionary = RegionDictionary::ISO_3166_1;
|
||||
reg.region_identifier = 12345;
|
||||
reg.local_region.set(546);
|
||||
check(reg, serialize_roundtrip(reg));
|
||||
}
|
||||
|
||||
TEST(Region, Serialize_PolygonalRegion)
|
||||
{
|
||||
PolygonalRegion reg;
|
||||
for (std::size_t i = 0; i < 3; ++i) {
|
||||
reg.push_back(TwoDLocation {
|
||||
geo_angle_i32t::from_value(25 + i),
|
||||
geo_angle_i32t::from_value(26 + i)
|
||||
});
|
||||
}
|
||||
check(reg, serialize_roundtrip(reg));
|
||||
}
|
||||
|
||||
TEST(Region, Serialize_RectangularRegion_list)
|
||||
{
|
||||
std::list<RectangularRegion> reg;
|
||||
for (std::size_t i = 0; i < 5; ++i) {
|
||||
reg.push_back(RectangularRegion {
|
||||
TwoDLocation {
|
||||
geo_angle_i32t::from_value(1000000 + i),
|
||||
geo_angle_i32t::from_value(1010000 + i)
|
||||
},
|
||||
TwoDLocation {
|
||||
geo_angle_i32t::from_value(1020000 + i),
|
||||
geo_angle_i32t::from_value(1030000 + i)
|
||||
}
|
||||
});
|
||||
}
|
||||
check(reg, serialize_roundtrip(reg));
|
||||
}
|
||||
|
||||
TEST(Region, TwoDLocation_Within_Circle)
|
||||
{
|
||||
CircularRegion region;
|
||||
region.radius = static_cast<distance_u16t>(400 * meter);
|
||||
region.center = TwoDLocation {
|
||||
geo_angle_i32t::from_value(490139190),
|
||||
geo_angle_i32t::from_value(84044460)
|
||||
};
|
||||
|
||||
EXPECT_TRUE(is_within(region.center, region));
|
||||
|
||||
EXPECT_TRUE(is_within(TwoDLocation {
|
||||
geo_angle_i32t::from_value(490143170),
|
||||
geo_angle_i32t::from_value(83995470)
|
||||
}, region));
|
||||
|
||||
EXPECT_FALSE(is_within(TwoDLocation {
|
||||
geo_angle_i32t::from_value(490145910),
|
||||
geo_angle_i32t::from_value(83984740)
|
||||
}, region));
|
||||
|
||||
EXPECT_FALSE(is_within(TwoDLocation {
|
||||
geo_angle_i32t::from_value(490137060),
|
||||
geo_angle_i32t::from_value(84120020)
|
||||
}, region));
|
||||
}
|
||||
|
||||
TEST(Region, Circle_Within_Circle)
|
||||
{
|
||||
CircularRegion outer;
|
||||
outer.radius = static_cast<distance_u16t>(400 * meter);
|
||||
outer.center = TwoDLocation {
|
||||
geo_angle_i32t::from_value(490139190),
|
||||
geo_angle_i32t::from_value(84044460)
|
||||
};
|
||||
|
||||
CircularRegion inner;
|
||||
inner.center = outer.center;
|
||||
|
||||
for (int i = 0; i <= 400; i += 10) {
|
||||
inner.radius = static_cast<distance_u16t>(i * meter);
|
||||
EXPECT_TRUE(is_within(inner, outer));
|
||||
}
|
||||
|
||||
inner.radius = static_cast<distance_u16t>(401 * meter);
|
||||
EXPECT_FALSE(is_within(inner, outer));
|
||||
|
||||
inner.center = TwoDLocation {
|
||||
geo_angle_i32t::from_value(490143170),
|
||||
geo_angle_i32t::from_value(83995470)
|
||||
};
|
||||
|
||||
inner.radius = static_cast<distance_u16t>(38 * meter);
|
||||
EXPECT_TRUE(is_within(inner, outer));
|
||||
|
||||
inner.radius = static_cast<distance_u16t>(40 * meter);
|
||||
EXPECT_FALSE(is_within(inner, outer));
|
||||
}
|
||||
|
||||
TEST(Region, TwoDLocation_Within_None)
|
||||
{
|
||||
NoneRegion region;
|
||||
|
||||
EXPECT_TRUE(is_within(TwoDLocation {
|
||||
geo_angle_i32t::from_value(490143170),
|
||||
geo_angle_i32t::from_value(83995470)
|
||||
}, region));
|
||||
}
|
||||
|
||||
TEST(Region, Circle_Within_None)
|
||||
{
|
||||
NoneRegion outer;
|
||||
|
||||
CircularRegion inner;
|
||||
inner.radius = static_cast<distance_u16t>(400 * meter);
|
||||
inner.center = TwoDLocation {
|
||||
geo_angle_i32t::from_value(490139190),
|
||||
geo_angle_i32t::from_value(84044460)
|
||||
};
|
||||
|
||||
EXPECT_TRUE(is_within(inner, outer));
|
||||
EXPECT_FALSE(is_within(outer, inner));
|
||||
}
|
||||
|
||||
TEST(Region, TwoDLocation_Within_Rectangles)
|
||||
{
|
||||
TwoDLocation northwest {
|
||||
static_cast<geo_angle_i32t>(20 * degrees),
|
||||
static_cast<geo_angle_i32t>(10 * degrees)
|
||||
};
|
||||
TwoDLocation southeast {
|
||||
static_cast<geo_angle_i32t>(10 * degrees),
|
||||
static_cast<geo_angle_i32t>(20 * degrees)
|
||||
};
|
||||
RectangularRegion region { northwest, southeast };
|
||||
std::list<RectangularRegion> regions({ region });
|
||||
|
||||
// inside
|
||||
EXPECT_TRUE(is_within(TwoDLocation {
|
||||
static_cast<geo_angle_i32t>(15 * degrees),
|
||||
static_cast<geo_angle_i32t>(15 * degrees)
|
||||
}, regions));
|
||||
|
||||
// outside - left
|
||||
EXPECT_FALSE(is_within(TwoDLocation {
|
||||
static_cast<geo_angle_i32t>(15 * degrees),
|
||||
static_cast<geo_angle_i32t>(9 * degrees)
|
||||
}, regions));
|
||||
|
||||
// outside - right
|
||||
EXPECT_FALSE(is_within(TwoDLocation {
|
||||
static_cast<geo_angle_i32t>(15 * degrees),
|
||||
static_cast<geo_angle_i32t>(21 * degrees)
|
||||
}, regions));
|
||||
|
||||
// outside - top
|
||||
EXPECT_FALSE(is_within(TwoDLocation {
|
||||
static_cast<geo_angle_i32t>(21 * degrees),
|
||||
static_cast<geo_angle_i32t>(15 * degrees)
|
||||
}, regions));
|
||||
|
||||
// outside - down
|
||||
EXPECT_FALSE(is_within(TwoDLocation {
|
||||
static_cast<geo_angle_i32t>(9 * degrees),
|
||||
static_cast<geo_angle_i32t>(15 * degrees)
|
||||
}, regions));
|
||||
}
|
||||
|
||||
TEST(Region, Rectangles_Within_None)
|
||||
{
|
||||
TwoDLocation northwest {
|
||||
static_cast<geo_angle_i32t>(20 * degrees),
|
||||
static_cast<geo_angle_i32t>(10 * degrees)
|
||||
};
|
||||
TwoDLocation southeast {
|
||||
static_cast<geo_angle_i32t>(10 * degrees),
|
||||
static_cast<geo_angle_i32t>(20 * degrees)
|
||||
};
|
||||
RectangularRegion region { northwest, southeast };
|
||||
std::list<RectangularRegion> regions({ region });
|
||||
|
||||
EXPECT_TRUE(is_within(regions, NoneRegion()));
|
||||
EXPECT_FALSE(is_within(NoneRegion(), regions));
|
||||
}
|
||||
|
||||
TEST(Region, Rectangle_Within_Rectangle_Exact)
|
||||
{
|
||||
TwoDLocation northwest_a {
|
||||
static_cast<geo_angle_i32t>(10 * degrees),
|
||||
static_cast<geo_angle_i32t>(10 * degrees)
|
||||
};
|
||||
TwoDLocation southeast_a {
|
||||
static_cast<geo_angle_i32t>(20 * degrees),
|
||||
static_cast<geo_angle_i32t>(20 * degrees)
|
||||
};
|
||||
|
||||
TwoDLocation northwest_b {
|
||||
static_cast<geo_angle_i32t>(10 * degrees),
|
||||
static_cast<geo_angle_i32t>(10 * degrees)
|
||||
};
|
||||
TwoDLocation southeast_b {
|
||||
static_cast<geo_angle_i32t>(20 * degrees),
|
||||
static_cast<geo_angle_i32t>(20 * degrees)
|
||||
};
|
||||
|
||||
RectangularRegion a { northwest_a, southeast_a };
|
||||
RectangularRegion b { northwest_b, southeast_b };
|
||||
|
||||
std::list<RectangularRegion> region_a({ a });
|
||||
std::list<RectangularRegion> region_b({ b });
|
||||
|
||||
EXPECT_TRUE(is_within(region_a, region_b));
|
||||
EXPECT_TRUE(is_within(region_b, region_a));
|
||||
}
|
||||
|
||||
TEST(Region, Altitude_To_Elevation)
|
||||
{
|
||||
using Elevation = ThreeDLocation::Elevation;
|
||||
|
||||
auto altitude_empty = std::numeric_limits<double>::quiet_NaN() * meter;
|
||||
EXPECT_EQ(to_elevation(altitude_empty), ThreeDLocation::unknown_elevation);
|
||||
|
||||
auto altitude_positive = 2843.6 * meter;
|
||||
EXPECT_EQ(to_elevation(altitude_positive), (Elevation { 0x6F, 0x14 }));
|
||||
|
||||
auto altitude_negative = -170.2 * meter;
|
||||
EXPECT_EQ(to_elevation(altitude_negative), (Elevation { 0xF9, 0x5A }));
|
||||
|
||||
auto altitude_below_min = -420.0 * meter;
|
||||
EXPECT_EQ(to_elevation(altitude_below_min), ThreeDLocation::min_elevation);
|
||||
|
||||
auto altitude_above_max = 6150.0 * meter;
|
||||
EXPECT_EQ(to_elevation(altitude_above_max), ThreeDLocation::max_elevation);
|
||||
|
||||
// examples given in TS 103 097 V1.2.1 (section 4.2.19)
|
||||
EXPECT_EQ(to_elevation(0.0 * meter), (Elevation { 0x00, 0x00 }));
|
||||
EXPECT_EQ(to_elevation(100.0 * meter), (Elevation { 0x03, 0xe8 }));
|
||||
EXPECT_EQ(to_elevation(-209.5 * meter), (Elevation { 0xf7, 0xd1 }));
|
||||
}
|
||||
+134
@@ -0,0 +1,134 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include <vanetza/security/v2/secured_message.hpp>
|
||||
#include <vanetza/security/v2/tests/check_secured_message.hpp>
|
||||
#include <vanetza/security/v2/tests/check_signature.hpp>
|
||||
#include <vanetza/security/tests/serialization.hpp>
|
||||
|
||||
using namespace vanetza;
|
||||
using namespace vanetza::security;
|
||||
|
||||
// Note: WebValidator refers to https://werkzeug.dcaiti.tu-berlin.de/etsi/ts103097/
|
||||
|
||||
TEST(SecuredMessage, Serialization)
|
||||
{
|
||||
v2::SecuredMessage m;
|
||||
|
||||
m.header_fields.push_back(v2::Time64 { 0x4711 });
|
||||
m.payload = { v2::PayloadType::Unsecured, CohesivePacket({ 5, 10, 15, 25, 40 }, OsiLayer::Application) };
|
||||
std::list<v2::TrailerField> list;
|
||||
list.push_back(v2::Signature { create_random_ecdsa_signature(44) });
|
||||
list.push_back(v2::Signature { create_random_ecdsa_signature(45) });
|
||||
m.trailer_fields = list;
|
||||
|
||||
check(m, serialize_roundtrip(m));
|
||||
}
|
||||
|
||||
TEST(SecuredMessage, header_field_extractor)
|
||||
{
|
||||
v2::SecuredMessage m;
|
||||
auto empty = m.header_field(v2::HeaderFieldType::Generation_Time);
|
||||
EXPECT_FALSE(empty);
|
||||
|
||||
m.header_fields.push_back(v2::Time64 { 25 });
|
||||
m.header_fields.push_back(v2::IntX { 23 });
|
||||
|
||||
auto time = m.header_field(v2::HeaderFieldType::Generation_Time);
|
||||
ASSERT_TRUE(time);
|
||||
EXPECT_EQ(25, boost::get<v2::Time64>(*time));
|
||||
|
||||
auto msg = m.header_field(v2::HeaderFieldType::Its_Aid);
|
||||
ASSERT_TRUE(msg);
|
||||
EXPECT_EQ(23, boost::get<v2::IntX>(*msg).get());
|
||||
|
||||
// field modifications should pass through
|
||||
boost::get<v2::Time64>(*time) = 26;
|
||||
auto time2 = m.header_field(v2::HeaderFieldType::Generation_Time);
|
||||
ASSERT_TRUE(time2);
|
||||
EXPECT_EQ(v2::Time64 { 26 }, boost::get<v2::Time64>(*time2));
|
||||
}
|
||||
|
||||
TEST(SecuredMessage, trailer_field_extractor)
|
||||
{
|
||||
v2::SecuredMessage m;
|
||||
auto empty = m.trailer_field(v2::TrailerFieldType::Signature);
|
||||
EXPECT_FALSE(!!empty);
|
||||
|
||||
m.trailer_fields.push_back(v2::Signature {});
|
||||
m.trailer_fields.push_back(v2::Signature {});
|
||||
auto first = m.trailer_field(v2::TrailerFieldType::Signature);
|
||||
ASSERT_TRUE(!!first);
|
||||
EXPECT_EQ(&m.trailer_fields.front(), first);
|
||||
}
|
||||
|
||||
TEST(SecuredMessage, WebValidator_Serialize_SecuredMessageV2_1)
|
||||
{
|
||||
// SecuredMessage/v1 from FOKUS WebValidator adapted for v2
|
||||
const char str[] =
|
||||
"02810180020201A8ED6DF65B0E6D6A0100809400000418929DB6A9E452223062C52028E956BF98"
|
||||
"74E0A40D21D5F9F56564F39C5DD187C922F2E5F0630373879A43393373B9F6205BF01FBD9C1F1131"
|
||||
"65C291C376F535010004EABA91A915D81807E910FD292D99DF8B401EED88CF7F031412D5ED9905F9"
|
||||
"996469798C412FC8F7237A3AB3469795E2DEF5E1B783EA4F6B6A2359D21772B2EA9D0200210AC040"
|
||||
"800101C0408101010F01099EB20109B1270003040100960000004B2E6D0D0EE9BC4AD9CD087B601E"
|
||||
"9AF06031995443D652763455FBB794B33982889260740EF64CFA8C6808A58F98E06CE42A1E9C22A0"
|
||||
"785D7242647F7895ABFC0000009373931CD7580502011C983E690E5F6D755BD4871578A9427E7B"
|
||||
"C383903DC7DA3B560384013643010000FE8566BEA87B39E6411F80226E792D6E01E77B598F2BB1FC"
|
||||
"E7F2DD441185C07CEF0573FBFB9876B99FE811486F6F5D499E6114FC0724A67F8D71D2A897A7EB34";
|
||||
v2::SecuredMessage m;
|
||||
deserialize_from_hexstring(str, m);
|
||||
|
||||
EXPECT_EQ(358, get_size(m));
|
||||
EXPECT_EQ(2, m.protocol_version());
|
||||
|
||||
EXPECT_EQ(3, m.header_fields.size());
|
||||
auto signer_info = m.header_field(v2::HeaderFieldType::Signer_Info);
|
||||
ASSERT_TRUE(!!signer_info);
|
||||
auto generation_time = m.header_field(v2::HeaderFieldType::Generation_Time);
|
||||
ASSERT_TRUE(!!generation_time);
|
||||
auto its_aid = m.header_field(v2::HeaderFieldType::Its_Aid);
|
||||
ASSERT_TRUE(!!its_aid);
|
||||
EXPECT_EQ(v2::IntX {2}, boost::get<v2::IntX>(*its_aid));
|
||||
|
||||
EXPECT_EQ(v2::PayloadType::Signed, m.payload.type);
|
||||
EXPECT_EQ(28, size(m.payload.data, min_osi_layer(), max_osi_layer()));
|
||||
|
||||
EXPECT_EQ(1, m.trailer_fields.size());
|
||||
EXPECT_TRUE(!!m.trailer_field(v2::TrailerFieldType::Signature));
|
||||
}
|
||||
|
||||
TEST(SecuredMessage, WebValidator_Serialize_SecuredMessageV2_2)
|
||||
{
|
||||
// SecuredMessage/v1 from FOKUS WebValidator adapted for v2
|
||||
const char str[] =
|
||||
"02810180020201A8ED6DF65B0E6D6A01008094000004C4EC137145DD4F450145DE530CCA36E73A"
|
||||
"B3D87FC8275847CDAD8248C1CD20879BD6A8CB54EA9E05D3B41376CE2F24789AEF82836CA818D568"
|
||||
"ADF4A140E96E48010004D6C268EE68B5B8B387B2312B7E1D21CE0C366D251A32431508B96EB6A347"
|
||||
"9CCF96A8738F30ED451F00DA8DDE84367C7EB16727D14FF14F5DD8F9791FE0A12A640200210AC040"
|
||||
"800101C0408101010F01099EB20109B1270003040100960000001EB035FE8E51DCDD8558DE0BE9B8"
|
||||
"7895B36B420583A5C6B2B8B2EAB7F3D3C99163638FA025A0033D4BD80BBA02B8E3DE1B55766459D4"
|
||||
"94677AF24917E51B80AC0000009373CC5F22C805020120F29384759027349075829034707ABABA"
|
||||
"BABABAABAB98437985739845783974954301000081E7CDB6D2C741C1700822305C39E8E809622AF9"
|
||||
"FCA1C0786F762D08E80580C42F1FCC1D5499577210834C390BB4613E102DECB14F575A2820743DC9"
|
||||
"A66BBD7A";
|
||||
v2::SecuredMessage m;
|
||||
deserialize_from_hexstring(str, m);
|
||||
check(m, serialize_roundtrip(m));
|
||||
}
|
||||
|
||||
TEST(SecuredMessage, WebValidator_Serialize_SecuredMessageV2_3)
|
||||
{
|
||||
// SecuredMessage/v1 from FOKUS WebValidator adapted for v2
|
||||
const char str[] =
|
||||
"02810180020201A8ED6DF65B0E6D6A010080940000040209B0434163CCBAFDD34A45333E418FB9"
|
||||
"6C05BBE0E7E1D755D40D0B4BBE8DA508EC2F2723B7ADF0F27C39F3AECFF0783C196F9961F8821E62"
|
||||
"94375D9294CD6A01000452113CE698DB081491675DF8FFE81C23EA5D0071B2D2BF0E0DA4ADA0CDA5"
|
||||
"8259CA5D999200B6565E194EDAB8BD3DCA863F2DDF39C13E7A0375ECE2566C5EB8C60200210AC040"
|
||||
"800101C0408101010F01099EB20109B1270003040100960000008DA1F3F9F35E04C3DE77D7438988"
|
||||
"A8D57EBE44DAA021A4269E297C177C9CFE458E128EC290785D6631961625020943B6D87DAA54919A"
|
||||
"98F7865709929A7C6E480000009373CF482D40050201080123456789ABCDEF43010000371423BB"
|
||||
"A0902D8AF2FB2226D73A7781D4D6B6772650A8BEE5A1AF198CEDABA2C9BF57540C629E6A1E629B88"
|
||||
"12AEBDDDBCAF472F6586F16C14B3DEFBE9B6ADB2";
|
||||
v2::SecuredMessage m;
|
||||
deserialize_from_hexstring(str, m);
|
||||
check(m, serialize_roundtrip(m));
|
||||
}
|
||||
|
||||
+1076
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,27 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include <vanetza/common/byte_sequence.hpp>
|
||||
#include <vanetza/security/public_key.hpp>
|
||||
#include <vanetza/security/v2/signature.hpp>
|
||||
#include <vanetza/security/v2/tests/check_signature.hpp>
|
||||
#include <vanetza/security/tests/serialization.hpp>
|
||||
|
||||
using namespace vanetza::security;
|
||||
|
||||
TEST(Signature, serialize)
|
||||
{
|
||||
v2::Signature signature = create_random_ecdsa_signature(42);
|
||||
check(signature, v2::serialize_roundtrip(signature));
|
||||
}
|
||||
|
||||
TEST(Signature, WebValidator_Size)
|
||||
{
|
||||
v2::Signature sig;
|
||||
EcdsaSignature eSig;
|
||||
X_Coordinate_Only x;
|
||||
x.x = buffer_from_hexstring("8DA1F3F9F35E04C3DE77D7438988A8D57EBE44DAA021A4269E297C177C9CFE45");
|
||||
eSig.R = x;
|
||||
eSig.s = buffer_from_hexstring("8E128EC290785D6631961625020943B6D87DAA54919A98F7865709929A7C6E48");
|
||||
sig = eSig;
|
||||
|
||||
EXPECT_EQ(66, get_size(sig));
|
||||
}
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include <vanetza/common/byte_sequence.hpp>
|
||||
#include <vanetza/security/v2/certificate.hpp>
|
||||
#include <vanetza/security/v2/signer_info.hpp>
|
||||
#include <vanetza/security/v2/tests/check_signature.hpp>
|
||||
#include <vanetza/security/v2/tests/check_signer_info.hpp>
|
||||
#include <vanetza/security/tests/serialization.hpp>
|
||||
|
||||
using vanetza::random_byte_sequence;
|
||||
using vanetza::security::create_random_ecdsa_signature;
|
||||
using vanetza::security::HashedId8;
|
||||
using namespace vanetza::security::v2;
|
||||
|
||||
TEST(SignerInfo, Serialization)
|
||||
{
|
||||
std::list<Certificate> certificates;
|
||||
Certificate a;
|
||||
a.signature = create_random_ecdsa_signature(28);
|
||||
Certificate b;
|
||||
b.signature = create_random_ecdsa_signature(29);
|
||||
certificates.push_back(a);
|
||||
certificates.push_back(b);
|
||||
SignerInfo info { certificates };
|
||||
|
||||
check(info, serialize_roundtrip(info));
|
||||
}
|
||||
|
||||
TEST(SignerInfo, WebValidator_Size)
|
||||
{
|
||||
SignerInfo info;
|
||||
HashedId8 id {{ 0xA8, 0xED, 0x6D, 0xF6, 0x5B, 0x0E, 0x6D, 0x6A }};
|
||||
info = id;
|
||||
|
||||
EXPECT_EQ(9, get_size(info));
|
||||
}
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include <vanetza/security/v2/subject_attribute.hpp>
|
||||
#include <vanetza/security/v2/tests/check_list.hpp>
|
||||
#include <vanetza/security/v2/tests/check_subject_attribute.hpp>
|
||||
#include <vanetza/security/tests/serialization.hpp>
|
||||
|
||||
using namespace vanetza::security::v2;
|
||||
using vanetza::security::deserialize_from_hexstring;
|
||||
|
||||
TEST(SubjectAttribute, serialize)
|
||||
{
|
||||
std::list<SubjectAttribute> list;
|
||||
list.push_back(create_random_verification_key(33));
|
||||
list.push_back(create_random_encryption_key(34));
|
||||
list.push_back(SubjectAssurance { 124 });
|
||||
std::list<IntX> its_aid;
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
its_aid.push_back(create_random_its_aid(i + 66));
|
||||
}
|
||||
list.push_back(its_aid);
|
||||
std::list<ItsAidSsp> its_aid_ssp;
|
||||
for (int i = 0; i < 1; ++i) {
|
||||
its_aid_ssp.push_back(create_random_its_aid_ssp(i + 67));
|
||||
}
|
||||
list.push_back(its_aid_ssp);
|
||||
|
||||
check(list, serialize_roundtrip(list));
|
||||
}
|
||||
|
||||
TEST(SubjectAttribute, WebValidator_ItsAidSsp)
|
||||
{
|
||||
std::list<ItsAidSsp> list;
|
||||
ItsAidSsp its1;
|
||||
its1.its_aid.set(16512);
|
||||
its1.service_specific_permissions = {0x01};
|
||||
list.push_back(its1);
|
||||
|
||||
ItsAidSsp its2;
|
||||
its2.its_aid.set(16513);
|
||||
its2.service_specific_permissions = {0x01};
|
||||
list.push_back(its2);
|
||||
|
||||
EXPECT_EQ(10, get_size(list));
|
||||
std::list<ItsAidSsp> other_list;
|
||||
deserialize_from_hexstring("0AC040800101C040810101", other_list);
|
||||
check(list, other_list);
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include <vanetza/common/byte_sequence.hpp>
|
||||
#include <vanetza/security/v2/subject_info.hpp>
|
||||
#include <vanetza/security/v2/tests/check_subject_info.hpp>
|
||||
#include <vanetza/security/tests/serialization.hpp>
|
||||
|
||||
using namespace vanetza::security::v2;
|
||||
|
||||
TEST(SubjectInfo, Serialization)
|
||||
{
|
||||
SubjectInfo sub;
|
||||
sub.subject_type = SubjectType::Root_CA;
|
||||
sub.subject_name = vanetza::random_byte_sequence(40);
|
||||
check(sub, serialize_roundtrip(sub));
|
||||
}
|
||||
|
||||
TEST(SubjectInfo, WebValidator_Size)
|
||||
{
|
||||
SubjectInfo info;
|
||||
info.subject_type = SubjectType::Authorization_Ticket;
|
||||
|
||||
EXPECT_EQ(2, get_size(info));
|
||||
}
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include <vanetza/common/byte_sequence.hpp>
|
||||
#include <vanetza/security/v2/trailer_field.hpp>
|
||||
#include <vanetza/security/v2/tests/check_list.hpp>
|
||||
#include <vanetza/security/v2/tests/check_signature.hpp>
|
||||
#include <vanetza/security/v2/tests/check_trailer_field.hpp>
|
||||
#include <vanetza/security/tests/serialization.hpp>
|
||||
|
||||
using namespace vanetza;
|
||||
using namespace vanetza::security::v2;
|
||||
using vanetza::security::buffer_from_hexstring;
|
||||
using vanetza::security::create_random_ecdsa_signature;
|
||||
using vanetza::security::EccPoint;
|
||||
using vanetza::security::EcdsaSignature;
|
||||
using vanetza::security::X_Coordinate_Only;
|
||||
|
||||
TEST(TrailerField, Serialization)
|
||||
{
|
||||
std::list<TrailerField> list;
|
||||
EcdsaSignature a = create_random_ecdsa_signature(8);
|
||||
EcdsaSignature b = create_random_ecdsa_signature(9);
|
||||
list.push_back(TrailerField { a });
|
||||
list.push_back(TrailerField { b });
|
||||
|
||||
check(list, serialize_roundtrip(list));
|
||||
}
|
||||
|
||||
TEST(TrailerField, WebValidator_Size)
|
||||
{
|
||||
TrailerField field;
|
||||
Signature sig;
|
||||
EcdsaSignature ecdsa;
|
||||
EccPoint point;
|
||||
X_Coordinate_Only x;
|
||||
x.x = buffer_from_hexstring("371423BBA0902D8AF2FB2226D73A7781D4D6B6772650A8BEE5A1AF198CEDABA2");
|
||||
point = x;
|
||||
ecdsa.R = point;
|
||||
ecdsa.s = buffer_from_hexstring("C9BF57540C629E6A1E629B8812AEBDDDBCAF472F6586F16C14B3DEFBE9B6ADB2");
|
||||
sig = ecdsa;
|
||||
field = sig;
|
||||
|
||||
std::list<TrailerField> list;
|
||||
list.push_back(field);
|
||||
|
||||
EXPECT_EQ(67, get_size(list));
|
||||
EXPECT_EQ(67, get_size(field));
|
||||
}
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include <vanetza/security/v2/certificate.hpp>
|
||||
#include <vanetza/security/v2/trust_store.hpp>
|
||||
#include <vanetza/security/tests/serialization.hpp>
|
||||
|
||||
using namespace vanetza::security::v2;
|
||||
using vanetza::security::HashedId8;
|
||||
using vanetza::security::deserialize_from_hexstring;
|
||||
|
||||
TEST(TrustStoreTest, lookup)
|
||||
{
|
||||
const char cert_hex[] =
|
||||
"0200040C547275737465645F526F6F74808D000004F1817DD05116B855A853F80DB171A3A470D431"
|
||||
"70EA7EEFD8EF392D66ECEFBE501CEBA19963C9B6447574424FFF1BB89485743F4D09A72B715FC73C"
|
||||
"87E5F70A110101000441279A383B80C812B72B1A5F5C3C590E5041C634A1ADCC4CE58393CA046D3C"
|
||||
"619717AEF634F7D80D5F6A29FA7F86EBF823ACE0097A71EE0DF0793034B0D3797C02E0200224250B"
|
||||
"0114B12B03154E0D83030000007D12BADF99D7070BCB237ED1FA7A5D86FD47E6ABA8E616B35E95A2"
|
||||
"856FC6E26A493E1215BCEE8BEA18B8ED52FB240716C4D4EC7D7C0167F0F032CBB87DF611D9";
|
||||
Certificate c;
|
||||
deserialize_from_hexstring(cert_hex, c);
|
||||
const HashedId8 cert_id = calculate_hash(c);
|
||||
const HashedId8 zero_id {{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }};
|
||||
|
||||
TrustStore trust_store;
|
||||
EXPECT_EQ(0, trust_store.lookup(cert_id).size());
|
||||
trust_store.insert(c);
|
||||
EXPECT_EQ(0, trust_store.lookup(zero_id).size());
|
||||
EXPECT_EQ(1, trust_store.lookup(cert_id).size());
|
||||
}
|
||||
+130
@@ -0,0 +1,130 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include <vanetza/common/bit_number.hpp>
|
||||
#include <vanetza/security/v2/validity_restriction.hpp>
|
||||
#include <vanetza/security/v2/tests/check_validity_restriction.hpp>
|
||||
#include <vanetza/security/tests/serialization.hpp>
|
||||
|
||||
using namespace vanetza::security::v2;
|
||||
|
||||
TEST(Duration, Raw)
|
||||
{
|
||||
uint16_t a = 0x8007;
|
||||
uint16_t b = 7;
|
||||
|
||||
Duration dur1(b, Duration::Units::Years);
|
||||
Duration dur2(a);
|
||||
|
||||
EXPECT_EQ(dur1.raw(), a);
|
||||
EXPECT_EQ(dur2.raw(), a);
|
||||
}
|
||||
|
||||
TEST(Duration, Unit)
|
||||
{
|
||||
const uint16_t raw = 0x8007;
|
||||
Duration duration(raw);
|
||||
|
||||
EXPECT_EQ(duration.raw(), raw);
|
||||
EXPECT_EQ(duration.unit(), Duration::Units::Years);
|
||||
}
|
||||
|
||||
TEST(Duration, Value)
|
||||
{
|
||||
const uint16_t raw = 0x8007;
|
||||
Duration duration(raw);
|
||||
|
||||
EXPECT_EQ(duration.raw(), raw);
|
||||
EXPECT_EQ(duration.value(), 7);
|
||||
}
|
||||
|
||||
TEST(Duration, ToSeconds_Seconds)
|
||||
{
|
||||
const uint16_t raw = 0x0007;
|
||||
Duration duration(raw);
|
||||
|
||||
EXPECT_EQ(duration.raw(), raw);
|
||||
EXPECT_EQ(duration.value(), 7);
|
||||
EXPECT_EQ(duration.to_seconds(), std::chrono::seconds(7));
|
||||
}
|
||||
|
||||
TEST(Duration, ToSeconds_Minutes)
|
||||
{
|
||||
const uint16_t raw = 0x2007;
|
||||
Duration duration(raw);
|
||||
|
||||
EXPECT_EQ(duration.raw(), raw);
|
||||
EXPECT_EQ(duration.value(), 7);
|
||||
EXPECT_EQ(duration.to_seconds(), std::chrono::minutes(7));
|
||||
}
|
||||
|
||||
TEST(Duration, ToSeconds_Hours)
|
||||
{
|
||||
const uint16_t raw = 0x4007;
|
||||
Duration duration(raw);
|
||||
|
||||
EXPECT_EQ(duration.raw(), raw);
|
||||
EXPECT_EQ(duration.value(), 7);
|
||||
EXPECT_EQ(duration.to_seconds(), std::chrono::hours(7));
|
||||
}
|
||||
|
||||
TEST(Duration, ToSeconds_Sixty_Hour_Blocks)
|
||||
{
|
||||
const uint16_t raw = 0x6007;
|
||||
Duration duration(raw);
|
||||
|
||||
EXPECT_EQ(duration.raw(), raw);
|
||||
EXPECT_EQ(duration.value(), 7);
|
||||
EXPECT_EQ(duration.to_seconds(), std::chrono::hours(7 * 60));
|
||||
}
|
||||
|
||||
TEST(Duration, ToSeconds_Years)
|
||||
{
|
||||
const uint16_t raw = 0x8002;
|
||||
Duration duration(raw);
|
||||
|
||||
EXPECT_EQ(duration.raw(), raw);
|
||||
EXPECT_EQ(duration.value(), 2);
|
||||
EXPECT_EQ(duration.to_seconds(), std::chrono::seconds(2 * 31556925));
|
||||
}
|
||||
|
||||
TEST(Duration, ToSecondsMax)
|
||||
{
|
||||
Duration duration(0xffff, Duration::Units::Years);
|
||||
EXPECT_EQ(duration.value(), 0x1fff);
|
||||
EXPECT_EQ(duration.unit(), Duration::Units::Years);
|
||||
EXPECT_EQ(duration.to_seconds(), std::chrono::seconds(static_cast<int64_t>(31556925) * 0x1fff));
|
||||
}
|
||||
|
||||
TEST(Duration, ToSecondsInvalidUnit)
|
||||
{
|
||||
Duration duration(0xffff);
|
||||
EXPECT_EQ(duration.to_seconds(), std::chrono::seconds::min());
|
||||
}
|
||||
|
||||
TEST(ValidityRestriction, Serialization)
|
||||
{
|
||||
std::list<ValidityRestriction> list;
|
||||
list.push_back(EndValidity { 0x548736 });
|
||||
list.push_back(StartAndEndValidity { 0x54, 0x5712});
|
||||
list.push_back(StartAndDurationValidity { 0x5712, Duration(13, Duration::Units::Hours)});
|
||||
list.push_back(GeographicRegion { CircularRegion {} });
|
||||
|
||||
check(list, serialize_roundtrip(list));
|
||||
}
|
||||
|
||||
TEST(ValidityRestriction, WebValidator_Size)
|
||||
{
|
||||
std::list<ValidityRestriction> list;
|
||||
StartAndEndValidity start;
|
||||
start.start_validity = 12345;
|
||||
start.end_validity = 4786283;
|
||||
list.push_back(start);
|
||||
|
||||
IdentifiedRegion id;
|
||||
id.region_dictionary = RegionDictionary::UN_Stats;
|
||||
id.region_identifier = 150;
|
||||
id.local_region.set(0);
|
||||
list.push_back(GeographicRegion { id });
|
||||
|
||||
EXPECT_EQ(15, get_size(list));
|
||||
// TODO: compare raw bytes
|
||||
}
|
||||
Reference in New Issue
Block a user