From 7f0fa947f7a06dcc8c6b939b059566a38c97d113 Mon Sep 17 00:00:00 2001 From: Siebren Weertman Date: Wed, 14 Feb 2024 09:08:12 +0100 Subject: [PATCH 1/3] Add unit tests to test generated code. SAP and SessionSetupReq Signed-off-by: Siebren Weertman Cleanup --- .gitignore | 1 + tests/CMakeLists.txt | 45 +++++ tests/cbv2g/CMakeLists.txt | 32 ++++ tests/unit/iso20/common/test_sessionSetup.cpp | 70 +++++++ tests/unit/iso20/test_header_utils.hpp | 68 +++++++ tests/unit/sap/test_supportedAppProtocol.cpp | 174 ++++++++++++++++++ 6 files changed, 390 insertions(+) create mode 100644 tests/CMakeLists.txt create mode 100644 tests/cbv2g/CMakeLists.txt create mode 100644 tests/unit/iso20/common/test_sessionSetup.cpp create mode 100644 tests/unit/iso20/test_header_utils.hpp create mode 100644 tests/unit/sap/test_supportedAppProtocol.cpp diff --git a/.gitignore b/.gitignore index 0d9522c..5338e72 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,4 @@ schemas venv *~ test/* +tests/build/ diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt new file mode 100644 index 0000000..bca6706 --- /dev/null +++ b/tests/CMakeLists.txt @@ -0,0 +1,45 @@ +cmake_minimum_required(VERSION 3.14) + +project(cbexigen VERSION 1) + +set(CMAKE_CXX_STANDARD 20) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_EXPORT_COMPILE_COMMANDS ON) + +find_package(GTest) + +add_subdirectory(cbv2g) + +file(GLOB_RECURSE CBV2G_TEST_SOURCES + ./unit/sap/*.cpp + ./unit/iso20/common/*.cpp + ./unit/iso2/*.cpp +) + +add_executable(test-${PROJECT_NAME} + ${CBV2G_TEST_SOURCES} +) + +target_compile_options(test-${PROJECT_NAME} PRIVATE -Wall -Werror -Wshadow) + +target_include_directories(test-${PROJECT_NAME} + PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR} +) + +target_link_libraries(test-${PROJECT_NAME} +PRIVATE + gtest + gtest_main + gmock + pthread + cbv2g +) + +include(GoogleTest) +gtest_discover_tests(test-${PROJECT_NAME} + TEST_PREFIX ${PROJECT_NAME} + TEST_LIST ${PROJECT_NAME}Tests +) + +set_tests_properties(${${PROJECT_NAME}Tests} PROPERTIES TIMEOUT 10) diff --git a/tests/cbv2g/CMakeLists.txt b/tests/cbv2g/CMakeLists.txt new file mode 100644 index 0000000..e0bee5d --- /dev/null +++ b/tests/cbv2g/CMakeLists.txt @@ -0,0 +1,32 @@ +cmake_minimum_required(VERSION 3.18) + +set(CMAKE_C_STANDARD 11) +set(CMAKE_C_STANDARD_REQUIRED ON) + +set(CBV2G_SOURCE_PATH "../../src/output/c") + +file(GLOB_RECURSE CBV2G_SOURCES + ${CBV2G_SOURCE_PATH}/common/*.c + ${CBV2G_SOURCE_PATH}/appHandshake/*.c + ${CBV2G_SOURCE_PATH}/din/*.c + ${CBV2G_SOURCE_PATH}/iso-2/*.c + ${CBV2G_SOURCE_PATH}/iso-20/*.c + ${CBV2G_SOURCE_PATH}/v2gtp/*.c +) + +add_library(cbv2g STATIC + ${CBV2G_SOURCES} +) + +target_compile_options(cbv2g PRIVATE -Werror -Wall -Wextra) + +target_include_directories(cbv2g + PUBLIC + ${CBV2G_SOURCE_PATH}/ + ${CBV2G_SOURCE_PATH}/appHandshake + ${CBV2G_SOURCE_PATH}/common + ${CBV2G_SOURCE_PATH}/din + ${CBV2G_SOURCE_PATH}/iso-2 + ${CBV2G_SOURCE_PATH}/iso-20 + ${CBV2G_SOURCE_PATH}/v2gtp +) diff --git a/tests/unit/iso20/common/test_sessionSetup.cpp b/tests/unit/iso20/common/test_sessionSetup.cpp new file mode 100644 index 0000000..d61bea2 --- /dev/null +++ b/tests/unit/iso20/common/test_sessionSetup.cpp @@ -0,0 +1,70 @@ +#include +#include + +#include +#include +#include + +#include "../test_header_utils.hpp" + +class Test_SessionSetup : public testing::Test { +protected: + uint8_t m_data[256] = {0}; + exi_bitstream_t m_stream; +}; + +/** \param xml_input (that was used to generate the EXI binary using EXIficient) + * + * + * + * 3030303030303030 + * 1707896956850052 + * + * PIXV12345678901231 + * + */ +TEST_F(Test_SessionSetup, WhenEncodingKnownSessionSetupRequest_ThenResultMatchesExpected) { + static constexpr uint8_t expected[] = + "\x01\xFE\x80\x02\x00\x00\x00\x28" //<- header + "\x80\x8c\x04\x18\x18\x18\x18\x18\x18\x18\x18\x08\x49\xfb\x4f\xba\xba\xa8\x40\x32\x0a\x28\x24\xac\x2b\x18\x99" + "\x19\x9a\x1a\x9b\x1b\x9c\x1c\x98\x18\x99\x19\x98\x80"; + static constexpr size_t streamLen = 0x28; + exi_bitstream_init(&m_stream, m_data, sizeof(m_data), 8, NULL); + iso20_exiDocument exiDoc = {}; + exiDoc.SessionSetupReq_isUsed = 1; + uint8_t sessionID[] = "\x30\x30\x30\x30\x30\x30\x30\x30"; + setHeader(exiDoc.SessionSetupReq.Header, sessionID, 1707896956850052); + setString(exiDoc.SessionSetupReq.EVCCID, "PIXV12345678901231"); + + int res = encode_iso20_exiDocument(&m_stream, &exiDoc); + size_t len = exi_bitstream_get_length(&m_stream); + V2GTP20_WriteHeader(&m_data[0], len, V2GTP20_MAINSTREAM_PAYLOAD_ID); + + ASSERT_EQ(res, 0); + ASSERT_EQ(len, streamLen); + ASSERT_EQ(memcmp(m_data, expected, sizeof(expected) - 1), 0) + << std::string("\\x") << toHexStr(m_data, m_data + sizeof(expected) - 1, "\\x") << '\n' + << std::string("\\x") << toHexStr(&expected[0], &expected[0] + sizeof(expected) - 1, "\\x"); +} + +TEST_F(Test_SessionSetup, WhenDecodingKnownSessionSetupRequest_ThenResultMatchesExpected) { + uint8_t input[] = + "\x01\xFE\x80\x02\x00\x00\x00\x28" //<- header + "\x80\x8c\x04\x18\x18\x18\x18\x18\x18\x18\x18\x08\x49\xfb\x4f\xba\xba\xa8\x40\x32\x0a\x28\x24\xac\x2b\x18\x99" + "\x19\x9a\x1a\x9b\x1b\x9c\x1c\x98\x18\x99\x19\x98\x80"; + iso20_exiDocument exiDoc = {}; + exi_bitstream_init(&m_stream, &input[0], sizeof(input), 8, NULL); + uint32_t len = 0; + + int res = V2GTP20_ReadHeader(&input[0], &len, V2GTP20_MAINSTREAM_PAYLOAD_ID); + ASSERT_EQ(res, 0); + res = decode_iso20_exiDocument(&m_stream, &exiDoc); + ASSERT_EQ(res, 0); + + static constexpr size_t streamLen = 0x28; + ASSERT_EQ(len, streamLen); + ASSERT_EQ((int)exiDoc.SessionSetupReq_isUsed, 1); + static const uint8_t sessionID[] = "\x30\x30\x30\x30\x30\x30\x30\x30"; + ASSERT_ISO20_HEADER_EQ(exiDoc.SessionSetupReq.Header, sessionID, 1707896956850052); + ASSERT_ISO20_STREQ(exiDoc.SessionSetupReq.EVCCID, "PIXV12345678901231"); +} diff --git a/tests/unit/iso20/test_header_utils.hpp b/tests/unit/iso20/test_header_utils.hpp new file mode 100644 index 0000000..cca4c9b --- /dev/null +++ b/tests/unit/iso20/test_header_utils.hpp @@ -0,0 +1,68 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +template +inline void setHeader(HeaderT& header, const uint8_t (&sessionID)[Len], uint64_t timeStamp, + const std::optional& signature = std::nullopt) { + static_assert(Len >= 8, "SessionID must be size 8. Larger is allowed for string literal \\0 term"); + header.SessionID.bytesLen = 8; + std::copy(&sessionID[0], &sessionID[0] + 8, header.SessionID.bytes); + header.TimeStamp = timeStamp; + header.Signature_isUsed = false; + if (signature) { + throw std::runtime_error("not supported yet"); + } +} +template +inline bool assertHeader(const HeaderT& header, const uint8_t* sessionID, uint64_t timeStamp) { + bool success = false; + [&]() { + ASSERT_EQ(header.SessionID.bytesLen, 8); + ASSERT_EQ(memcmp(header.SessionID.bytes, sessionID, 8), 0); + ASSERT_EQ((int)header.Signature_isUsed, 0); + ASSERT_EQ(header.TimeStamp, timeStamp); + success = true; + }(); + return success; +} +#define ASSERT_ISO20_HEADER_EQ(...) \ + do { /* NOLINT */ \ + if (!assertHeader(__VA_ARGS__)) { \ + return; \ + } \ + } while (0) /* NOLINT */ +#define ASSERT_ISO20_STREQ(str, sv) \ + do { /* NOLINT */ \ + std::string_view svv = sv; \ + ASSERT_EQ((str).charactersLen, svv.size()); \ + ASSERT_EQ((str).characters, svv); \ + } while (0) /* NOLINT */ + +template +inline void setString(StrT& out, std::string_view in) { + out.charactersLen = in.size(); + std::copy(in.begin(), in.end(), out.characters); +} + +template +inline void setBytes(StrT& out, std::span in) { + out.bytesLen = in.size(); + std::copy(in.begin(), in.end(), out.bytes); +} + +template +std::string toHexStr(It begin, It end, std::string_view delimit = "\\x") { + std::stringstream ss; + auto it = begin; + for (; it != end; ++it) { + ss << delimit << std::setfill('0') << std::setw(2) << std::hex << (uint16_t)*it; + } + return std::move(ss).str(); +} diff --git a/tests/unit/sap/test_supportedAppProtocol.cpp b/tests/unit/sap/test_supportedAppProtocol.cpp new file mode 100644 index 0000000..3402a8b --- /dev/null +++ b/tests/unit/sap/test_supportedAppProtocol.cpp @@ -0,0 +1,174 @@ +#include +#include + +#include +#include +#include + +class Test_SupportedAppProtocol : public testing::Test { +protected: + uint8_t m_data[256] = {0}; + exi_bitstream_t m_stream; +}; + +static void setProtocol(appHand_AppProtocolType& protoc, std::string_view ns, uint32_t vMaj, uint32_t vMin, + uint8_t schemaID, uint8_t priority) { + protoc.ProtocolNamespace.charactersLen = ns.size(); + std::copy(ns.begin(), ns.end(), protoc.ProtocolNamespace.characters); + protoc.VersionNumberMajor = vMaj; + protoc.VersionNumberMinor = vMin; + protoc.SchemaID = schemaID; + protoc.Priority = priority; +} + +/** \param xml input: + * + * + * urn:iso:15118:2:2010:MsgDef + * 1 + * 0 + * 1 + * 1 + * + * + * urn:din:70121:2012:MsgDef + * 1 + * 0 + * 2 + * 2 + * + * + * urn:iso:std:iso:15118:-20:DC + * 1 + * 0 + * 3 + * 3 + * + * + */ +TEST_F(Test_SupportedAppProtocol, WhenEncodingKnownSupportedAppProtocolRequest_ThenResultMatchesExpected) { + static constexpr uint8_t expected[] = + "\x01\xFE\x80\x01\x00\x00\x00\x66" //<-header + "\x80\x00\xeb\xab\x93\x71\xd3\x4b\x9b\x79\xd1\x89\xa9\x89\x89\xc1\xd1\x91\xd1\x91\x81\x89\x81\xd2\x6b\x9b\x3a" + "\x23\x2b\x30\x01\x00\x00\x04\x00\x01\xb7\x57\x26\xe3\xa6\x46\x96\xe3\xa3\x73\x03\x13\x23\x13\xa3\x23\x03\x13" + "\x23\xa4\xd7\x36\x74\x46\x56\x60\x02\x00\x00\x10\x08\x03\xce\xae\x4d\xc7\x4d\x2e\x6d\xe7\x4e\x6e\x8c\x87\x4d" + "\x2e\x6d\xe7\x46\x26\xa6\x26\x27\x07\x45\xa6\x46\x07\x48\x88\x60\x04\x00\x00\x30\x21"; + static constexpr size_t streamLen = 0x66; + static constexpr std::string_view namespaceISO15118_2 = "urn:iso:15118:2:2010:MsgDef"; + static constexpr std::string_view namespaceDin70121 = "urn:din:70121:2012:MsgDef"; + static constexpr std::string_view namespaceISO15118_20 = "urn:iso:std:iso:15118:-20:DC"; + exi_bitstream_init(&m_stream, m_data, sizeof(m_data), 8, NULL); + appHand_exiDocument exiDoc = {}; + exiDoc.supportedAppProtocolReq_isUsed = 1; + exiDoc.supportedAppProtocolReq.AppProtocol.arrayLen = 3; + setProtocol(exiDoc.supportedAppProtocolReq.AppProtocol.array[0], namespaceISO15118_2, 1, 0, 1, 1); + setProtocol(exiDoc.supportedAppProtocolReq.AppProtocol.array[1], namespaceDin70121, 1, 0, 2, 2); + setProtocol(exiDoc.supportedAppProtocolReq.AppProtocol.array[2], namespaceISO15118_20, 1, 0, 3, 3); + + int res = encode_appHand_exiDocument(&m_stream, &exiDoc); + int len = exi_bitstream_get_length(&m_stream); + V2GTP_WriteHeader(m_data, len); + + ASSERT_EQ(res, 0); + ASSERT_EQ(len, streamLen); + ASSERT_EQ(memcmp(m_data, expected, sizeof(expected) - 1), 0); +} + +TEST_F(Test_SupportedAppProtocol, WhenDecodingKnownSupportedAppProtocolRequestStream_ThenResultMatchesExpected) { + uint8_t input[] = + "\x01\xFE\x80\x01\x00\x00\x00\x66" //<-header + "\x80\x00\xeb\xab\x93\x71\xd3\x4b\x9b\x79\xd1\x89\xa9\x89\x89\xc1\xd1\x91\xd1\x91\x81\x89\x81\xd2\x6b\x9b\x3a" + "\x23\x2b\x30\x01\x00\x00\x04\x00\x01\xb7\x57\x26\xe3\xa6\x46\x96\xe3\xa3\x73\x03\x13\x23\x13\xa3\x23\x03\x13" + "\x23\xa4\xd7\x36\x74\x46\x56\x60\x02\x00\x00\x10\x08\x03\xce\xae\x4d\xc7\x4d\x2e\x6d\xe7\x4e\x6e\x8c\x87\x4d" + "\x2e\x6d\xe7\x46\x26\xa6\x26\x27\x07\x45\xa6\x46\x07\x48\x88\x60\x04\x00\x00\x30\x21"; + exi_bitstream_init(&m_stream, input, sizeof(input), 8, NULL); + appHand_exiDocument exiDoc = {}; + uint32_t len = 0; + + int res = V2GTP_ReadHeader(input, &len); + ASSERT_EQ(res, 0); + res = decode_appHand_exiDocument(&m_stream, &exiDoc); + ASSERT_EQ(res, 0); + + static constexpr size_t streamLen = 0x66; + static constexpr std::string_view namespaceISO15118_2 = "urn:iso:15118:2:2010:MsgDef"; + static constexpr std::string_view namespaceDin70121 = "urn:din:70121:2012:MsgDef"; + static constexpr std::string_view namespaceISO15118_20 = "urn:iso:std:iso:15118:-20:DC"; + ASSERT_EQ(len, streamLen); + ASSERT_EQ((int)exiDoc.supportedAppProtocolReq_isUsed, 1); + ASSERT_EQ(exiDoc.supportedAppProtocolReq.AppProtocol.arrayLen, 3); + + auto& protoc0 = exiDoc.supportedAppProtocolReq.AppProtocol.array[0]; + ASSERT_EQ(protoc0.ProtocolNamespace.charactersLen, namespaceISO15118_2.size()); + ASSERT_EQ(memcmp(protoc0.ProtocolNamespace.characters, namespaceISO15118_2.data(), namespaceISO15118_2.size()), 0); + ASSERT_EQ(protoc0.VersionNumberMajor, 1); + ASSERT_EQ(protoc0.VersionNumberMinor, 0); + ASSERT_EQ(protoc0.SchemaID, 1); + ASSERT_EQ(protoc0.Priority, 1); + + auto& protoc1 = exiDoc.supportedAppProtocolReq.AppProtocol.array[1]; + ASSERT_EQ(protoc1.ProtocolNamespace.charactersLen, namespaceDin70121.size()); + ASSERT_EQ(memcmp(protoc1.ProtocolNamespace.characters, namespaceDin70121.data(), namespaceDin70121.size()), 0); + ASSERT_EQ(protoc1.VersionNumberMajor, 1); + ASSERT_EQ(protoc1.VersionNumberMinor, 0); + ASSERT_EQ(protoc1.SchemaID, 2); + ASSERT_EQ(protoc1.Priority, 2); + + auto& protoc2 = exiDoc.supportedAppProtocolReq.AppProtocol.array[2]; + ASSERT_EQ(protoc2.ProtocolNamespace.charactersLen, namespaceISO15118_20.size()); + ASSERT_EQ(memcmp(protoc2.ProtocolNamespace.characters, namespaceISO15118_20.data(), namespaceISO15118_20.size()), + 0); + ASSERT_EQ(protoc2.VersionNumberMajor, 1); + ASSERT_EQ(protoc2.VersionNumberMinor, 0); + ASSERT_EQ(protoc2.SchemaID, 3); + ASSERT_EQ(protoc2.Priority, 3); +} + +/** \param xml input: + * + * + * OK_SuccessfulNegotiation + * 1 + * + */ +TEST_F(Test_SupportedAppProtocol, WhenEncodingKnownSupportedAppProtocolResponse_ThenResultMatchesExpected) { + static constexpr uint8_t expected[] = "\x01\xfe\x80\x01\x00\x00\x00\x04" //<-header + "\x80\x40\x00\x40"; + + static constexpr size_t streamLen = 0x04; + exi_bitstream_init(&m_stream, m_data, sizeof(m_data), 8, NULL); + appHand_exiDocument exiDoc = {}; + exiDoc.supportedAppProtocolRes_isUsed = 1; + exiDoc.supportedAppProtocolRes.SchemaID_isUsed = 1; + exiDoc.supportedAppProtocolRes.SchemaID = 1; + exiDoc.supportedAppProtocolRes.ResponseCode = appHand_responseCodeType_OK_SuccessfulNegotiation; + + int res = encode_appHand_exiDocument(&m_stream, &exiDoc); + ASSERT_EQ(res, 0); + int len = exi_bitstream_get_length(&m_stream); + V2GTP_WriteHeader(m_data, len); + + ASSERT_EQ(len, streamLen); + ASSERT_EQ(memcmp(m_data, expected, sizeof(expected) - 1), 0); +} +TEST_F(Test_SupportedAppProtocol, WhenDecodingKnownSupportedAppProtocolResponseStream_ThenResultMatchesExpected) { + uint8_t input[] = "\x01\xfe\x80\x01\x00\x00\x00\x04" //<-header + "\x80\x40\x00\x40"; + exi_bitstream_init(&m_stream, input, sizeof(input), 8, NULL); + appHand_exiDocument exiDoc = {}; + uint32_t len = 0; + + V2GTP_ReadHeader(input, &len); + decode_appHand_exiDocument(&m_stream, &exiDoc); + + static constexpr size_t streamLen = 0x04; + ASSERT_EQ(len, streamLen); + ASSERT_EQ((int)exiDoc.supportedAppProtocolRes_isUsed, 1); + ASSERT_EQ(exiDoc.supportedAppProtocolRes.ResponseCode, appHand_responseCodeType_OK_SuccessfulNegotiation); + ASSERT_EQ((int)exiDoc.supportedAppProtocolRes.SchemaID_isUsed, 1); + ASSERT_EQ(exiDoc.supportedAppProtocolRes.SchemaID, 1); +} From 70cb43f77c6849b08253dc9a2983ed354a376092 Mon Sep 17 00:00:00 2001 From: Siebren Weertman Date: Mon, 26 Feb 2024 13:10:01 +0000 Subject: [PATCH 2/3] Add test for xmldsig signedInfo Signed-off-by: Siebren Weertman --- tests/CMakeLists.txt | 1 + .../unit/xmldsig/test_SignedInfo_Fragment.cpp | 118 ++++++++++++++++++ 2 files changed, 119 insertions(+) create mode 100644 tests/unit/xmldsig/test_SignedInfo_Fragment.cpp diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index bca6706..f4defc1 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -14,6 +14,7 @@ file(GLOB_RECURSE CBV2G_TEST_SOURCES ./unit/sap/*.cpp ./unit/iso20/common/*.cpp ./unit/iso2/*.cpp + ./unit/xmldsig/*.cpp ) add_executable(test-${PROJECT_NAME} diff --git a/tests/unit/xmldsig/test_SignedInfo_Fragment.cpp b/tests/unit/xmldsig/test_SignedInfo_Fragment.cpp new file mode 100644 index 0000000..a68862b --- /dev/null +++ b/tests/unit/xmldsig/test_SignedInfo_Fragment.cpp @@ -0,0 +1,118 @@ +#include +#include + +#include +#include +#include + +#include + +template +class Test_SignedInfo_Fragment : public testing::Test { +protected: + using Document_t = XmlFragmentDocT; + uint8_t m_data[512] = {0}; + exi_bitstream_t m_stream; + int encode_xmldsigFragment(exi_bitstream_t* stream, Document_t*); + template + static void setExiStr(StrT& out, std::string_view setStr) + { + out.charactersLen = setStr.length(); + memcpy(out.characters, setStr.data(), setStr.length()); + } + template + static void setExiArr(StrT& out, const uint8_t (&setStr)[Len]) + { + out.bytesLen = Len - 1; + memcpy(out.bytes, setStr, Len - 1); + } +}; +class Test_SignedInfo_Fragment_ISO2: public Test_SignedInfo_Fragment { +protected: + int encode_xmldsigFragment(exi_bitstream_t* stream, Document_t* document) + { + return encode_iso2_xmldsigFragment(stream, document); + } +}; + + + +/** \brief Fragment encode + * \param xml_input + * + * + * + * + * + * + * + * + * + * AQIDBAUGBw== + * + * + * + * + * + * + * AQIDBAUGBw== + * + * + */ +TEST_F(Test_SignedInfo_Fragment_ISO2, WhenEncodingKnownSupportedAppProtocolRequest_ThenResultMatchesExpected) { + static constexpr uint8_t expected[] = + "\x80\x81\x12\xb4\x3a\x3a\x38\x1d\x17\x97\xbb\xbb\xbb\x97\x3b\x99\x97\x37\xb9\x33\x97\xaa\x29\x17\xb1\xb0\xb7" + "\x37\xb7\x34\xb1\xb0\xb6\x16\xb2\xbc\x34\x97\xa1\xab\x43\xa3\xa3\x81\xd1\x79\x7b\xbb\xbb\xb9\x73\xb9\x99\x73" + "\x7b\x93\x39\x79\x91\x81\x81\x89\x79\x81\xa1\x7b\xc3\x6b\x63\x23\x9b\x4b\x39\x6b\x6b\x7b\x93\x29\x1b\x2b\x1b" + "\x23\x9b\x09\x6b\x9b\x43\x09\xa9\x89\x92\x20\x56\x96\x43\x10\x25\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e" + "\x77\x33\x2e\x6f\x72\x67\x2f\x54\x52\x2f\x63\x61\x6e\x6f\x6e\x69\x63\x61\x6c\x2d\x65\x78\x69\x2f\x48\x6a\xd0" + "\xe8\xe8\xe0\x74\x5e\x5e\xee\xee\xee\x5c\xee\x66\x5c\xde\xe4\xce\x5e\x64\x60\x60\x62\x5e\x60\x68\x5e\xf0\xda" + "\xd8\xc8\xe6\xd2\xce\x5a\xda\xde\xe4\xca\x46\xca\xc6\xc8\xe6\xc2\x5a\xe6\xd0\xc2\x6a\x62\x64\x80\xe0\x20\x40" + "\x60\x80\xa0\xc0\xe0\x81\x5a\x59\x0c\x80\x95\xa1\xd1\xd1\xc0\xe8\xbc\xbd\xdd\xdd\xdc\xb9\xdc\xcc\xb9\xbd\xc9" + "\x9c\xbd\x51\x48\xbd\x8d\x85\xb9\xbd\xb9\xa5\x8d\x85\xb0\xb5\x95\xe1\xa4\xbd\x21\xab\x43\xa3\xa3\x81\xd1\x79" + "\x7b\xbb\xbb\xb9\x73\xb9\x99\x73\x7b\x93\x39\x79\x91\x81\x81\x89\x79\x81\xa1\x7b\xc3\x6b\x63\x23\x9b\x4b\x39" + "\x6b\x6b\x7b\x93\x29\x1b\x2b\x1b\x23\x9b\x09\x6b\x9b\x43\x09\xa9\x89\x92\x03\x80\x81\x01\x82\x02\x83\x03\x8d" + "\xc0"; + static constexpr std::string_view c_canonMethodAlgorithm = "http://www.w3.org/TR/canonical-exi/"; + static constexpr std::string_view c_transformAlgorithm = "http://www.w3.org/TR/canonical-exi/"; + static constexpr std::string_view c_digestAlgorithm = "http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha512"; + static constexpr std::string_view c_signatureMethodAlgorithm = "http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha512"; + static constexpr const uint8_t c_digestValue[] = "\x01\x02\x03\x04\x05\x06\x07"; + static constexpr std::string_view c_refURI1 = "id1"; + static constexpr std::string_view c_refURI2 = "id2"; + static constexpr size_t streamLen = sizeof(expected) - 1; + + exi_bitstream_init(&m_stream, m_data, sizeof(m_data), 0, NULL); + Document_t exiDoc = {}; + memset(&exiDoc, 0, sizeof(exiDoc)); + exiDoc.SignedInfo_isUsed = 1; + auto& signInfo = exiDoc.SignedInfo; + signInfo.Id_isUsed = 0; + setExiStr(signInfo.CanonicalizationMethod.Algorithm, c_canonMethodAlgorithm); + setExiStr(signInfo.SignatureMethod.Algorithm, c_signatureMethodAlgorithm); + signInfo.Reference.arrayLen = 2; + + auto& ref1 = signInfo.Reference.array[0]; + ref1.URI_isUsed = 1; + setExiStr(ref1.URI, c_refURI1); + ref1.Transforms_isUsed = 1; + setExiStr(ref1.Transforms.Transform.Algorithm, c_transformAlgorithm); + setExiStr(ref1.DigestMethod.Algorithm, c_digestAlgorithm); + setExiArr(ref1.DigestValue, c_digestValue); + + auto& ref2 = signInfo.Reference.array[1]; + ref2.URI_isUsed = 1; + setExiStr(ref2.URI, c_refURI2); + ref2.Transforms_isUsed = 1; + setExiStr(ref2.Transforms.Transform.Algorithm, c_transformAlgorithm); + setExiStr(ref2.DigestMethod.Algorithm, c_digestAlgorithm); + setExiArr(ref2.DigestValue, c_digestValue); + + int res = encode_xmldsigFragment(&m_stream, &exiDoc); + int len = exi_bitstream_get_length(&m_stream); + + ASSERT_EQ(res, 0); + ASSERT_EQ(len, streamLen); + const auto memcpyRes = memcmp(m_data, expected, sizeof(expected) - 1); + ASSERT_EQ(memcpyRes, 0); +} From 5ebc93b7a1e2744049961a823ba92117bfaa329e Mon Sep 17 00:00:00 2001 From: Siebren Weertman Date: Mon, 26 Feb 2024 13:36:11 +0000 Subject: [PATCH 3/3] Also test sig in other libs Signed-off-by: Siebren Weertman --- .../unit/xmldsig/test_SignedInfo_Fragment.cpp | 49 ++++++++++++++----- 1 file changed, 38 insertions(+), 11 deletions(-) diff --git a/tests/unit/xmldsig/test_SignedInfo_Fragment.cpp b/tests/unit/xmldsig/test_SignedInfo_Fragment.cpp index a68862b..9101fb3 100644 --- a/tests/unit/xmldsig/test_SignedInfo_Fragment.cpp +++ b/tests/unit/xmldsig/test_SignedInfo_Fragment.cpp @@ -13,7 +13,7 @@ class Test_SignedInfo_Fragment : public testing::Test { using Document_t = XmlFragmentDocT; uint8_t m_data[512] = {0}; exi_bitstream_t m_stream; - int encode_xmldsigFragment(exi_bitstream_t* stream, Document_t*); + virtual int encode_xmldsigFragment(exi_bitstream_t* stream, void* document) = 0; template static void setExiStr(StrT& out, std::string_view setStr) { @@ -26,16 +26,8 @@ class Test_SignedInfo_Fragment : public testing::Test { out.bytesLen = Len - 1; memcpy(out.bytes, setStr, Len - 1); } + void WhenEncodingKnownSupportedAppProtocolRequest_ThenResultMatchesExpected(); }; -class Test_SignedInfo_Fragment_ISO2: public Test_SignedInfo_Fragment { -protected: - int encode_xmldsigFragment(exi_bitstream_t* stream, Document_t* document) - { - return encode_iso2_xmldsigFragment(stream, document); - } -}; - - /** \brief Fragment encode * \param xml_input @@ -59,7 +51,8 @@ class Test_SignedInfo_Fragment_ISO2: public Test_SignedInfo_Fragment * */ -TEST_F(Test_SignedInfo_Fragment_ISO2, WhenEncodingKnownSupportedAppProtocolRequest_ThenResultMatchesExpected) { +template +void Test_SignedInfo_Fragment::WhenEncodingKnownSupportedAppProtocolRequest_ThenResultMatchesExpected() { static constexpr uint8_t expected[] = "\x80\x81\x12\xb4\x3a\x3a\x38\x1d\x17\x97\xbb\xbb\xbb\x97\x3b\x99\x97\x37\xb9\x33\x97\xaa\x29\x17\xb1\xb0\xb7" "\x37\xb7\x34\xb1\xb0\xb6\x16\xb2\xbc\x34\x97\xa1\xab\x43\xa3\xa3\x81\xd1\x79\x7b\xbb\xbb\xb9\x73\xb9\x99\x73" @@ -116,3 +109,37 @@ TEST_F(Test_SignedInfo_Fragment_ISO2, WhenEncodingKnownSupportedAppProtocolReque const auto memcpyRes = memcmp(m_data, expected, sizeof(expected) - 1); ASSERT_EQ(memcpyRes, 0); } + +class Test_SignedInfo_Fragment_ISO2: public Test_SignedInfo_Fragment { +protected: + int encode_xmldsigFragment(exi_bitstream_t* stream, void* document) final + { + return encode_iso2_xmldsigFragment(stream, (Document_t*)document); + } +}; +class Test_SignedInfo_Fragment_ISO20DC: public Test_SignedInfo_Fragment { +protected: + int encode_xmldsigFragment(exi_bitstream_t* stream, void* document) final + { + return encode_iso20_dc_xmldsigFragment(stream, (Document_t*)document); + } +}; +class Test_SignedInfo_Fragment_ISO20AC: public Test_SignedInfo_Fragment { +protected: + int encode_xmldsigFragment(exi_bitstream_t* stream, void* document) final + { + return encode_iso20_ac_xmldsigFragment(stream, (Document_t*)document); + } +}; + +TEST_F(Test_SignedInfo_Fragment_ISO2, WhenEncodingKnownSupportedAppProtocolRequest_ThenResultMatchesExpected) { + WhenEncodingKnownSupportedAppProtocolRequest_ThenResultMatchesExpected(); +} + +TEST_F(Test_SignedInfo_Fragment_ISO20AC, WhenEncodingKnownSupportedAppProtocolRequest_ThenResultMatchesExpected) { + WhenEncodingKnownSupportedAppProtocolRequest_ThenResultMatchesExpected(); +} + +TEST_F(Test_SignedInfo_Fragment_ISO20DC, WhenEncodingKnownSupportedAppProtocolRequest_ThenResultMatchesExpected) { + WhenEncodingKnownSupportedAppProtocolRequest_ThenResultMatchesExpected(); +}