7#include "vdvcertificate_p.h"
9#include "iso9796_2decoder_p.h"
11#include "../asn1/berelement.h"
19VdvCertificate::VdvCertificate() =
default;
21VdvCertificate::VdvCertificate(
const QByteArray &data,
int offset)
24 const auto hdr = BER::TypedElement<TagCertificate>(data, offset);
26 qDebug() <<
"Invalid certificate header:" << hdr.isValid() << data.
size() << offset;
31 const auto certKeyBlock = hdr.find(TagCertificateContent);
32 if (certKeyBlock.isValid()) {
34 qDebug() <<
"found decrypted key";
35 qDebug() <<
"CHR:" <<
QByteArray(certKey()->chr.name, 5) << certKey()->chr.algorithmReference << certKey()->chr.year;
36 qDebug() <<
"CAR:" <<
QByteArray(certKey()->car.region, 2) <<
QByteArray(certKey()->car.name, 3);
40 const auto sig = hdr.find(TagCertificateSignature);
42 qWarning() <<
"Invalid certificate content: neither a key nor a signature!";
48 qDebug() <<
"found encrypted key";
51VdvCertificate::~VdvCertificate() =
default;
53bool VdvCertificate::isValid()
const
55 if (m_type == Invalid) {
58 return m_type ==
Signed ? !m_recoveredData.isEmpty() : !m_data.isEmpty();
61bool VdvCertificate::needsCaKey()
const
63 return m_type ==
Signed && m_recoveredData.isEmpty();
66int VdvCertificate::size()
const
68 return m_type == Invalid ? 0 : header().size();
71uint16_t VdvCertificate::modulusSize()
const
73 switch (certKey()->certificateProfileIdentifier) {
81 qWarning() <<
"Unknown certificate profile identifier: " << certKey()->certificateProfileIdentifier;
85const uint8_t* VdvCertificate::modulus()
const
87 const auto k = certKey();
88 return (&k->oidBegin) + k->oidSize();
91uint16_t VdvCertificate::exponentSize()
const
96const uint8_t* VdvCertificate::exponent()
const
98 return modulus() + modulusSize();
101void VdvCertificate::setCaCertificate(
const VdvCertificate &caCert)
103 if (!caCert.isValid()) {
104 qWarning() <<
"Invalid CA certificate.";
108 Iso9796_2Decoder decoder;
109 decoder.setRsaParameters(caCert.modulus(), caCert.modulusSize(), caCert.exponent(), caCert.exponentSize());
111 const auto sig = header().find(TagCertificateSignature);
112 decoder.addWithRecoveredMessage(sig.contentData(), sig.contentSize());
114 if (header().contentSize() > sig.size()) {
115 const auto rem = header().find(TagCertificateSignatureRemainder);
117 decoder.add(rem.contentData(), rem.contentSize());
119 qWarning() <<
"Invalid signature remainder!" << rem.isValid() << rem.size() << sig.size() << header().contentSize();
123 m_recoveredData = decoder.recoveredMessage();
124 if (!m_recoveredData.isEmpty() && m_recoveredData.size() >= (certKey()->headerSize() + modulusSize() + exponentSize())) {
125 qDebug() <<
"successfully decrypted key";
126 qDebug() <<
"CAR:" <<
QByteArray(certKey()->car.region, 2) <<
QByteArray(certKey()->car.name, 3);
127 qDebug() <<
"CHR:" <<
QByteArray(certKey()->chr.name, 5) << certKey()->chr.algorithmReference << certKey()->chr.year;
129 qWarning() <<
"decrypting certificate key failed!";
130 qDebug() <<
"size is:" << m_recoveredData.size() <<
"expected:" << (certKey()->headerSize() + modulusSize() + exponentSize());
131 qDebug() <<
QByteArray((
const char*)sig.contentData(), sig.contentSize()).
toHex();
133 m_recoveredData.
clear();
137void VdvCertificate::writeKey(
QIODevice *out)
const
139 out->
write(
"\x7F\x21");
140 if (m_type == Signed) {
142 out->
write(
"\x5F\x4E");
144 out->
write(m_recoveredData);
145 }
else if (m_type == Raw) {
146 const auto keyBlock = header().find(TagCertificateContent);
148 out->
write(keyBlock.rawData(), keyBlock.size());
152bool VdvCertificate::isSelfSigned()
const
154 return memcmp(&certKey()->car, certKey()->chr.name,
sizeof(VdvCaReference)) == 0;
157QDate VdvCertificate::endOfValidity()
const
159 const auto key = certKey();
168const VdvCertificateKey* VdvCertificate::certKey()
const
170 if (m_type == Signed) {
171 return reinterpret_cast<const VdvCertificateKey*
>(m_recoveredData.constData());
172 }
else if (m_type == Raw) {
173 return header().find(TagCertificateContent).contentAt<VdvCertificateKey>();
179VdvCertificate VdvPkiRepository::caCertificate(
const VdvCaReference *car)
183 sizeof(VdvCaReference))
187 qWarning() <<
"Failed to open CA cert file" << f.fileName()
189 return VdvCertificate();
192 VdvCertificate cert(f.readAll());
193 if (cert.needsCaKey()) {
194 VdvCaReference rootCAR;
195 rootCAR.region[0] =
'E'; rootCAR.region[1] =
'U';
196 rootCAR.name[0] =
'V'; rootCAR.name[1] =
'D'; rootCAR.name[2] =
'V';
197 rootCAR.serviceIndicator = 0;
198 rootCAR.discretionaryData = 1;
199 rootCAR.algorithmReference = 1;
201 cert.setCaCertificate(caCertificate(&rootCAR));
An element in BER/DER/X.690 encoding.
static void writeSize(QIODevice *out, int size)
Writes the given size in BER encoding to out.
AKONADI_MIME_EXPORT const char Signed[]
Classes for reservation/travel data models, data extraction and data augmentation.
qsizetype size() const const
QByteArray toHex(char separator) const const
qint64 write(const QByteArray &data)
QString fromLatin1(QByteArrayView str)