KItinerary

vdvticketparser.cpp
1/*
2 SPDX-FileCopyrightText: 2019 Volker Krause <vkrause@kde.org>
3
4 SPDX-License-Identifier: LGPL-2.0-or-later
5*/
6
7#include "vdvticketparser.h"
8#include "vdvdata_p.h"
9#include "vdvcertificate_p.h"
10#include "iso9796_2decoder_p.h"
11#include "logging.h"
12
13#include "../asn1/berelement.h"
14
15#include <QByteArray>
16#include <QDebug>
17
18using namespace KItinerary;
19
20VdvTicketParser::VdvTicketParser() = default;
21VdvTicketParser::~VdvTicketParser() = default;
22
24{
25 // (1) find the certificate authority reference (CAR) to identify the key to decode the CV certificate
26 const auto sig = BER::TypedElement<TagSignature>(data);
27 if (!sig.isValid()) {
28 qCDebug(Log) << "Invalid VDV ticket signature.";
29 return false;
30 }
31 const auto sigRemainder = BER::TypedElement<TagSignatureRemainder>(data, sig.size());
32 if (!sigRemainder.isValid()) {
33 qCDebug(Log) << "Invalid VDV signature remainder.";
34 return false;
35 }
36
37 const auto cvCertOffset = sig.size() + sigRemainder.size();
38 auto cvCert = VdvCertificate(data, cvCertOffset);
39 if ((!cvCert.isValid() && !cvCert.needsCaKey())) {
40 qCDebug(Log) << "Invalid CV signature:" << cvCert.isValid() << cvCertOffset << cvCert.size();
41 return false;
42 }
43
44 const auto carOffset = cvCertOffset + cvCert.size();
45 const auto carBlock = BER::TypedElement<TagCaReference>(data, carOffset);
46 if (!carBlock.isValid()) {
47 qCDebug(Log) << "Invalid CA Reference.";
48 return false;
49 }
50 const auto car = carBlock.contentAt<VdvCaReference>(0);
51 if (!car) {
52 qCDebug(Log) << "Cannot obtain CA Reference.";
53 return false;
54 }
55 qCDebug(Log) << "CV CAR:" << QByteArray(car->region, 5) << car->serviceIndicator << car->discretionaryData << car->algorithmReference << car->year;
56
57 const auto caCert = VdvPkiRepository::caCertificate(car);
58 if (!caCert.isValid()) {
59 qCWarning(Log) << "Could not find CA certificate" << QByteArray(reinterpret_cast<const char*>(car), sizeof(VdvCaReference)).toHex();
60 return false;
61 }
62
63 // (2) decode the CV certificate
64 cvCert.setCaCertificate(caCert);
65 if (!cvCert.isValid()) {
66 qCWarning(Log) << "Failed to decode CV certificate.";
67 return false;
68 }
69
70 // (3) decode the ticket data using the decoded CV certificate
71 Iso9796_2Decoder decoder;
72 decoder.setRsaParameters(cvCert.modulus(), cvCert.modulusSize(), cvCert.exponent(), cvCert.exponentSize());
73 decoder.addWithRecoveredMessage(sig.contentData(), sig.contentSize());
74 decoder.add(sigRemainder.contentData(), sigRemainder.contentSize());
75
76 // (4) profit!
77 m_ticket = VdvTicket(decoder.recoveredMessage(), data);
78 return true;
79}
80
82{
83 if (data.size() < 352) {
84 return false;
85 }
86
87 // signature header
88 const auto sig = BER::TypedElement<TagSignature>(data);
89 if (!sig.isValid()) {
90 return false;
91 }
92 const auto rem = BER::TypedElement<TagSignatureRemainder>(data, sig.size());
93 if (!rem.isValid()) {
94 return false;
95 }
96
97 // verify the "VDV" marker is there
98 return strncmp((const char*)(rem.contentData() + rem.contentSize() - 5), "VDV", 3) == 0;
99}
100
102{
103 return m_ticket;
104}
VdvTicket ticket() const
Returns the parsed ticket data.
bool parse(const QByteArray &data)
Tries to parse the ticket in data.
static bool maybeVdvTicket(const QByteArray &data)
Fast check if data might contain a VDV ticket.
Ticket information from a VDV barcode.
Definition vdvticket.h:30
Classes for reservation/travel data models, data extraction and data augmentation.
Definition berelement.h:17
qsizetype size() const const
QByteArray toHex(char separator) const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Tue Mar 26 2024 11:14:49 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.