diff --git a/src/vdv/vdvcertificate.cpp b/src/vdv/vdvcertificate.cpp index be0bca0..a63c126 100644 --- a/src/vdv/vdvcertificate.cpp +++ b/src/vdv/vdvcertificate.cpp @@ -1,113 +1,113 @@ /* Copyright (C) 2019 Volker Krause 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 . */ #include "vdvcertificate_p.h" #include "vdvdata_p.h" #include #include using namespace KItinerary; VdvCertificate::VdvCertificate() = default; VdvCertificate::VdvCertificate(const QByteArray &data, int offset) : m_offset(offset) { if ((unsigned)data.size() <= m_offset + sizeof(VdvCertificateHeader)) { qWarning() << "Certificate data too small:" << data.size() << offset; return; } m_data = data; const auto hdr = header(); if (!hdr->isValid() || data.size() < hdr->size() + offset) { qWarning() << "Invalid certificate header:" << hdr->isValid() << hdr->size() << data.size() << offset; m_data.clear(); return; } const auto certKeyBlock = hdr->contentAt(0); if (!certKeyBlock->isValid()) { qWarning() << "Invalid certificate key block."; m_data.clear(); return; } qDebug() << "car:" << QByteArray(certKey()->car.region, 2) << QByteArray(certKey()->car.name, 3); - qDebug() << "chr:" << QByteArray(certKey()->chr.name, 5); + qDebug() << "chr:" << QByteArray(certKey()->chr.name, 5) << certKey()->chr.algorithmReference << certKey()->chr.year; qDebug() << "cha:" << QByteArray(certKey()->cha.name, 6); qDebug() << "modulus:" << modulusSize() << *modulus() << *(modulus() + modulusSize() - 1); qDebug() << "exponent:" << exponentSize() << *exponent() << *(exponent() + exponentSize() - 1); } VdvCertificate::~VdvCertificate() = default; bool VdvCertificate::isValid() const { return !m_data.isEmpty(); } uint16_t VdvCertificate::modulusSize() const { switch (certKey()->certificateProfileIdentifier) { case 3: return 1536 / 8; case 4: return 1024 / 8; } qWarning() << "Unknown certificate profile identifier: " << certKey()->certificateProfileIdentifier; return 0; } const uint8_t* VdvCertificate::modulus() const { return &(certKey()->modulusBegin); } uint16_t VdvCertificate::exponentSize() const { return 4; } const uint8_t* VdvCertificate::exponent() const { return &(certKey()->modulusBegin) + modulusSize(); } const VdvCertificateHeader* VdvCertificate::header() const { return reinterpret_cast(m_data.constData() + m_offset); } const VdvCertificateKey* VdvCertificate::certKey() const { // TODO check if m_data is large enough return header()->contentAt(0)->contentAt(0); } VdvCertificate VdvPkiRepository::caCertificate(uint8_t serNum) { QFile f(QLatin1String(":/org.kde.pim/kitinerary/vdv/certs/") + QString::number(serNum) + QLatin1String(".vdv-cert")); if (!f.open(QFile::ReadOnly)) { qWarning() << "Failed to open CA cert file" << serNum << f.errorString(); return VdvCertificate(); } qDebug() << f.size(); return VdvCertificate(f.readAll()); } diff --git a/src/vdv/vdvdata_p.h b/src/vdv/vdvdata_p.h index a9471aa..4dc6266 100644 --- a/src/vdv/vdvdata_p.h +++ b/src/vdv/vdvdata_p.h @@ -1,192 +1,195 @@ /* Copyright (C) 2019 Volker Krause 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 . */ #ifndef KITINERARY_VDVDATA_P_H #define KITINERARY_VDVDATA_P_H #include #include namespace KItinerary { enum : uint8_t { TagSignature = 0x9E, TagSignatureRemainder = 0x9A, TagCaReference = 0x42, TagOneByteSize = 0x81, TagTwoByteSize = 0x82, }; enum : uint16_t { TagCertificate = 0x7F21, TagCertificateSignature = 0x5F37, TagCertificateSignatureRemainder = 0x5F38, TagCertificateContent = 0x5F4E, }; #pragma pack(push) #pragma pack(1) /** Generic structure for the header of data blocks in VDV binary data. * This consits of: * - a one or two byte tag (@tparam TagType) with a fixed value (@tparam TagValue) * - a one byte field indicating the size of the size field (optional) * - one or two bytes for the size * - followed by size bytes of content */ template struct VdvAbstractDataBlock { TagType tag; inline bool isValid() const { return qFromBigEndian(tag) == TagValue; } }; template struct VdvSimpleDataBlock : public VdvAbstractDataBlock { uint8_t size0; inline uint16_t contentSize() const { return size0; } inline uint16_t contentOffset() const { return sizeof(VdvSimpleDataBlock); } inline const uint8_t* contentData() const { return reinterpret_cast(this) + contentOffset(); } inline uint16_t size() const { return contentSize() + contentOffset(); } template inline const T* contentAt(int offset) const { return reinterpret_cast(contentData() + offset); } }; template struct VdvTaggedSizeDataBlock : public VdvAbstractDataBlock { uint8_t sizeTag; uint8_t size0; uint8_t size1; inline bool isValid() const { return VdvAbstractDataBlock::isValid() && (sizeTag == TagOneByteSize || sizeTag == TagTwoByteSize); } inline uint16_t contentSize() const { return sizeTag == TagOneByteSize ? size0 : ((size0 << 8) + size1); } inline uint16_t contentOffset() const { return sizeof(VdvTaggedSizeDataBlock) - ((sizeTag == TagOneByteSize) ? 1 : 0); } inline const uint8_t* contentData() const { return reinterpret_cast(this) + contentOffset(); } inline uint16_t size() const { return contentSize() + contentOffset(); } template inline const T* contentAt(int offset) const { return reinterpret_cast(contentData() + offset); } }; /** Signature container for the signed part of the payload data. */ struct VdvSignature : public VdvTaggedSizeDataBlock {}; /** Signature Remainder header. */ struct VdvSignatureRemainder : public VdvSimpleDataBlock { enum { Offset = 131 }; }; /** CV certificate. */ struct VdvCertificateHeader : public VdvTaggedSizeDataBlock { }; /** Certificate Authority Reference (CAR) content. */ struct VdvCaReference { char region[2]; char name[3]; uint8_t serviceIndicator: 4; uint8_t discretionaryData: 4; uint8_t algorithmReference; uint8_t year; }; struct VdvCaReferenceBlock : public VdvSimpleDataBlock {}; /** Certificate Holder Reference (CHR) */ struct VdvCertificateHolderReference { uint8_t filler[4]; // always null char name[5]; - uint8_t extension[3]; + uint8_t serviceIndicator: 4; + uint8_t discretionaryData: 4; + uint8_t algorithmReference; + uint8_t year; }; /** Certificate Holder Authorization (CHA) */ struct VdvCertificateHolderAuthorization { char name[6]; uint8_t stuff; }; /** Certificate key, contained in a certificate object. */ struct VdvCertificateKey { uint8_t certificateProfileIdentifier; VdvCaReference car; VdvCertificateHolderReference chr; VdvCertificateHolderAuthorization cha; uint8_t date[4]; uint8_t oid[9]; uint8_t modulusBegin; }; struct VdvCertificateKeyBlock : public VdvTaggedSizeDataBlock {}; /** Certificate signature. */ struct VdvCertificateSignature : public VdvTaggedSizeDataBlock {}; /** Certificate signature remainder. */ struct VdvCertificateSignatureRemainder : public VdvSimpleDataBlock {}; #pragma pack(pop) } #endif // KITINERARY_VDVDATA_P_H