Commit 2bacf523 authored by Volker Krause's avatar Volker Krause
Browse files

Replace the adhoc VDV length encoding code by a proper BER length encoder

parent 30170704
......@@ -11,6 +11,7 @@ ecm_add_test(airportdbtest.cpp LINK_LIBRARIES Qt5::Test KPim::Itinerary)
ecm_add_test(extractorinputtest.cpp LINK_LIBRARIES Qt5::Test KPim::Itinerary)
ecm_add_test(extractorrepositorytest.cpp LINK_LIBRARIES Qt5::Test KPim::Itinerary)
ecm_add_test(berdecodertest.cpp LINK_LIBRARIES Qt5::Test KPim::Itinerary)
ecm_add_test(berencodertest.cpp LINK_LIBRARIES Qt5::Test KPim::Itinerary)
ecm_add_test(bcbpparsertest.cpp LINK_LIBRARIES Qt5::Test KPim::Itinerary)
ecm_add_test(uic9183parsertest.cpp LINK_LIBRARIES Qt5::Test KPim::Itinerary)
ecm_add_test(vdvtickettest.cpp LINK_LIBRARIES Qt5::Test KPim::Itinerary)
......
/*
Copyright (C) 2020 Volker Krause <vkrause@kde.org>
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU Library General Public License as published by
the Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <tlv/berelement.cpp>
#include <QBuffer>
#include <QDebug>
#include <QObject>
#include <QTest>
using namespace KItinerary;
class BerEncoderTest : public QObject
{
Q_OBJECT
private Q_SLOTS:
void testWriteSize_data()
{
QTest::addColumn<int>("size");
QTest::addColumn<QByteArray>("expected");
QTest::newRow("zero") << 0 << QByteArray::fromHex("00");
QTest::newRow("1") << 1 << QByteArray::fromHex("01");
QTest::newRow("127") << 127 << QByteArray::fromHex("7F");
QTest::newRow("128") << 128 << QByteArray::fromHex("8180");
QTest::newRow("255") << 255 << QByteArray::fromHex("81FF");
QTest::newRow("256") << 256 << QByteArray::fromHex("820100");
QTest::newRow("65535") << 65535 << QByteArray::fromHex("82FFFF");
}
void testWriteSize()
{
QFETCH(int, size);
QFETCH(QByteArray, expected);
QByteArray out;
QBuffer buffer(&out);
QVERIFY(buffer.open(QIODevice::WriteOnly));
BER::Element::writeSize(&buffer, size);
buffer.close();
QCOMPARE(out, expected);
}
};
QTEST_APPLESS_MAIN(BerEncoderTest)
#include "berencodertest.moc"
......@@ -18,6 +18,8 @@
#include "berelement_p.h"
#include <QDebug>
#include <QIODevice>
#include <QtEndian>
using namespace KItinerary;
......@@ -189,3 +191,27 @@ BER::Element BER::Element::find(uint32_t type) const
}
return {};
}
void BER::Element::writeSize(QIODevice *out, int size)
{
const uint32_t beSize = qToBigEndian((uint32_t)(size));
constexpr auto maxBytes = sizeof(size);
static_assert(maxBytes == sizeof(beSize), "wrong size datatypes");
if (size <= 127) {
out->write(((const char*)&beSize) + maxBytes - 1, 1);
return;
}
uint32_t mask = 0xff000000;
static_assert(maxBytes == sizeof(mask), "wrong size datatypes");
for (int i = maxBytes; i > 0; --i) {
if (size & mask) {
uint8_t sizeTag = BerExtendedLenghtMask | i;
out->write((const char*)&sizeTag, 1);
out->write(((const char*)&beSize) + maxBytes - i, i);
return;
}
mask >>= 8;
}
}
......@@ -22,6 +22,8 @@
#include <cstdint>
class QIODevice;
namespace KItinerary {
/** BER/DER/X.690 encoding classes and functions. */
......@@ -76,6 +78,9 @@ public:
/** Returns the first child element of the given @p type. */
Element find(uint32_t type) const;
/** Writes the given size in BER encoding to @p out. */
static void writeSize(QIODevice *out, int size);
private:
int typeSize() const;
int lengthSize() const;
......
......@@ -143,30 +143,17 @@ void VdvCertificate::setCaCertificate(const VdvCertificate &caCert)
}
}
static void writeTaggedSize(QIODevice *out, int size)
{
if (size <= 255) {
out->write("\x81");
char size1 = (uint8_t)(size);
out->write(&size1, 1);
} else {
out->write("\x82");
uint16_t size2 = qToBigEndian((uint16_t)(size));
out->write((const char*)&size2, 2);
}
}
void VdvCertificate::writeKey(QIODevice *out) const
{
out->write("\x7F\x21");
if (m_type == Signed) {
writeTaggedSize(out, m_recoveredData.size() + 3);
BER::Element::writeSize(out, m_recoveredData.size() + 3);
out->write("\x5F\x4E");
writeTaggedSize(out, m_recoveredData.size());
BER::Element::writeSize(out, m_recoveredData.size());
out->write(m_recoveredData);
} else if (m_type == Raw) {
const auto keyBlock = header().find(TagCertificateContent);
writeTaggedSize(out, keyBlock.size());
BER::Element::writeSize(out, keyBlock.size());
out->write(keyBlock.rawData(), keyBlock.size());
}
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment