Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Show improved AddressItem widget #1306

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 0 additions & 40 deletions client/Application.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -148,15 +148,6 @@ class DigidocConf final: public digidoc::XmlConfCurrent
#ifdef Q_OS_MAC
std::string TSLCache() const final
{ return QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation).toStdString(); }

void setProxyHost( const std::string &host ) final
{ Settings::PROXY_HOST = host; }
void setProxyPort( const std::string &port ) final
{ Settings::PROXY_PORT = port; }
void setProxyUser( const std::string &user ) final
{ Settings::PROXY_USER = user; }
void setProxyPass( const std::string &pass ) final
{ Settings::PROXY_PASS = pass; }
#endif

std::vector<digidoc::X509Cert> TSCerts() const final
Expand Down Expand Up @@ -609,10 +600,6 @@ QVariant Application::confValue( ConfParameter parameter, const QVariant &value
switch( parameter )
{
case SiVaUrl: r = i->verifyServiceUri().c_str(); break;
case ProxyHost: r = i->proxyHost().c_str(); break;
case ProxyPort: r = i->proxyPort().c_str(); break;
case ProxyUser: r = i->proxyUser().c_str(); break;
case ProxyPass: r = i->proxyPass().c_str(); break;
case TSAUrl: r = i->TSUrl().c_str(); break;
case TSLUrl: r = i->TSLUrl().c_str(); break;
case TSLCache: r = i->TSLCache().c_str(); break;
Expand Down Expand Up @@ -884,33 +871,6 @@ int Application::run()
return exec();
}

void Application::setConfValue( ConfParameter parameter, const QVariant &value )
{
try
{
auto *i = dynamic_cast<digidoc::XmlConfCurrent*>(digidoc::Conf::instance());
if(!i)
return;
QByteArray v = value.toString().toUtf8();
switch( parameter )
{
case ProxyHost: i->setProxyHost( v.isEmpty()? std::string() : v.constData() ); break;
case ProxyPort: i->setProxyPort( v.isEmpty()? std::string() : v.constData() ); break;
case ProxyUser: i->setProxyUser( v.isEmpty()? std::string() : v.constData() ); break;
case ProxyPass: i->setProxyPass( v.isEmpty()? std::string() : v.constData() ); break;
case TSAUrl:
case SiVaUrl:
case TSLCerts:
case TSLUrl:
case TSLCache: break;
}
}
catch( const digidoc::Exception &e )
{
showWarning(tr("Caught exception!"), e);
}
}

void Application::showClient(const QStringList &params, bool crypto, bool sign, bool newWindow)
{
if(sign)
Expand Down
5 changes: 0 additions & 5 deletions client/Application.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,6 @@ class Application final: public BaseApplication
enum ConfParameter : quint8
{
SiVaUrl,
ProxyHost,
ProxyPort,
ProxyUser,
ProxyPass,
TSAUrl,
TSLUrl,
TSLCerts,
Expand Down Expand Up @@ -77,7 +73,6 @@ class Application final: public BaseApplication
static QWidget* mainWindow();
static void openHelp();
static uint readTSLVersion(const QString &path);
static void setConfValue( ConfParameter parameter, const QVariant &value );
static void showClient(const QStringList &params = {}, bool crypto = false, bool sign = false, bool newWindow = false);
static void updateTSLCache(const QDateTime &tslTime);

Expand Down
41 changes: 14 additions & 27 deletions client/CDoc1.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,6 @@ const QString CDoc1::AES128GCM_MTH = QStringLiteral("http://www.w3.org/2009/xmle
const QString CDoc1::AES192GCM_MTH = QStringLiteral("http://www.w3.org/2009/xmlenc11#aes192-gcm");
const QString CDoc1::AES256GCM_MTH = QStringLiteral("http://www.w3.org/2009/xmlenc11#aes256-gcm");
const QString CDoc1::RSA_MTH = QStringLiteral("http://www.w3.org/2001/04/xmlenc#rsa-1_5");
const QString CDoc1::KWAES128_MTH = QStringLiteral("http://www.w3.org/2001/04/xmlenc#kw-aes128");
const QString CDoc1::KWAES192_MTH = QStringLiteral("http://www.w3.org/2001/04/xmlenc#kw-aes192");
const QString CDoc1::KWAES256_MTH = QStringLiteral("http://www.w3.org/2001/04/xmlenc#kw-aes256");
const QString CDoc1::CONCATKDF_MTH = QStringLiteral("http://www.w3.org/2009/xmlenc11#ConcatKDF");
const QString CDoc1::AGREEMENT_MTH = QStringLiteral("http://www.w3.org/2009/xmlenc11#ECDH-ES");
Expand All @@ -66,7 +64,6 @@ const QHash<QString, const EVP_CIPHER*> CDoc1::ENC_MTH{
const QHash<QString, QCryptographicHash::Algorithm> CDoc1::SHA_MTH{
{SHA256_MTH, QCryptographicHash::Sha256}, {SHA384_MTH, QCryptographicHash::Sha384}, {SHA512_MTH, QCryptographicHash::Sha512}
};
const QHash<QString, quint32> CDoc1::KWAES_SIZE{{KWAES128_MTH, 16}, {KWAES192_MTH, 24}, {KWAES256_MTH, 32}};

CDoc1::CDoc1(const QString &path)
: QFile(path)
Expand Down Expand Up @@ -108,7 +105,6 @@ CDoc1::CDoc1(const QString &path)
return;

CKey key;
key.id = xml.attributes().value(QLatin1String("Id")).toString();
key.recipient = xml.attributes().value(QLatin1String("Recipient")).toString();
while(!xml.atEnd())
{
Expand All @@ -117,18 +113,17 @@ CDoc1::CDoc1(const QString &path)
break;
if(!xml.isStartElement())
continue;
// EncryptedData/KeyInfo/KeyName
if(xml.name() == QLatin1String("KeyName"))
key.name = xml.readElementText();
// EncryptedData/KeyInfo/EncryptedKey/EncryptionMethod
else if(xml.name() == QLatin1String("EncryptionMethod"))
key.method = xml.attributes().value(QLatin1String("Algorithm")).toString();
if(xml.name() == QLatin1String("EncryptionMethod"))
{
auto method = xml.attributes().value(QLatin1String("Algorithm"));
key.unsupported = std::max(key.unsupported, method != KWAES256_MTH && method != RSA_MTH);
}
// EncryptedData/KeyInfo/EncryptedKey/KeyInfo/AgreementMethod
else if(xml.name() == QLatin1String("AgreementMethod"))
key.agreement = xml.attributes().value(QLatin1String("Algorithm")).toString();
key.unsupported = std::max(key.unsupported, xml.attributes().value(QLatin1String("Algorithm")) != AGREEMENT_MTH);
// EncryptedData/KeyInfo/EncryptedKey/KeyInfo/AgreementMethod/KeyDerivationMethod
else if(xml.name() == QLatin1String("KeyDerivationMethod"))
key.derive = xml.attributes().value(QLatin1String("Algorithm")).toString();
key.unsupported = std::max(key.unsupported, xml.attributes().value(QLatin1String("Algorithm")) != CONCATKDF_MTH);
// EncryptedData/KeyInfo/EncryptedKey/KeyInfo/AgreementMethod/KeyDerivationMethod/ConcatKDFParams
else if(xml.name() == QLatin1String("ConcatKDFParams"))
{
Expand Down Expand Up @@ -273,16 +268,13 @@ CKey CDoc1::canDecrypt(const QSslCertificate &cert) const
{
if(!ENC_MTH.contains(method) ||
k.cert != cert ||
k.cipher.isEmpty())
k.cipher.isEmpty() ||
k.unsupported)
continue;
if(cert.publicKey().algorithm() == QSsl::Rsa &&
k.method == RSA_MTH)
if(cert.publicKey().algorithm() == QSsl::Rsa)
return k;
if(cert.publicKey().algorithm() == QSsl::Ec &&
!k.publicKey.isEmpty() &&
KWAES_SIZE.contains(k.method) &&
k.derive == CONCATKDF_MTH &&
k.agreement == AGREEMENT_MTH)
!k.publicKey.isEmpty())
return k;
}
return {};
Expand Down Expand Up @@ -432,8 +424,6 @@ bool CDoc1::save(const QString &path)
for(const CKey &k: qAsConst(keys))
{
writeElement(w, DENC, QStringLiteral("EncryptedKey"), [&]{
if(!k.id.isEmpty())
w.writeAttribute(QStringLiteral("Id"), k.id);
if(!k.recipient.isEmpty())
w.writeAttribute(QStringLiteral("Recipient"), k.recipient);
QByteArray cipher;
Expand All @@ -446,8 +436,6 @@ bool CDoc1::save(const QString &path)
{QStringLiteral("Algorithm"), RSA_MTH},
});
writeElement(w, DS, QStringLiteral("KeyInfo"), [&]{
if(!k.name.isEmpty())
w.writeTextElement(DS, QStringLiteral("KeyName"), k.name);
writeElement(w, DS, QStringLiteral("X509Data"), [&]{
writeBase64Element(w, DS, QStringLiteral("X509Certificate"), k.cert.toDer());
});
Expand All @@ -464,14 +452,13 @@ bool CDoc1::save(const QString &path)
QByteArray oid = Crypto::curve_oid(peerPKey);
QByteArray SsDer = Crypto::toPublicKeyDer(priv.get());

const QString encryptionMethod = KWAES256_MTH;
QString concatDigest = SHA384_MTH;
switch((SsDer.size() - 1) / 2) {
case 32: concatDigest = SHA256_MTH; break;
case 48: concatDigest = SHA384_MTH; break;
default: concatDigest = SHA512_MTH; break;
}
QByteArray encryptionKey = Crypto::concatKDF(SHA_MTH[concatDigest], KWAES_SIZE[encryptionMethod],
QByteArray encryptionKey = Crypto::concatKDF(SHA_MTH[concatDigest],
sharedSecret, props.value(QStringLiteral("DocumentFormat")).toUtf8() + SsDer + k.cert.toDer());
#ifndef NDEBUG
qDebug() << "ENC Ss" << SsDer.toHex();
Expand All @@ -484,7 +471,7 @@ bool CDoc1::save(const QString &path)
return;

writeElement(w, DENC, QStringLiteral("EncryptionMethod"), {
{QStringLiteral("Algorithm"), encryptionMethod},
{QStringLiteral("Algorithm"), KWAES256_MTH},
});
writeElement(w, DS, QStringLiteral("KeyInfo"), [&]{
writeElement(w, DENC, QStringLiteral("AgreementMethod"), {
Expand Down Expand Up @@ -553,7 +540,7 @@ QByteArray CDoc1::transportKey(const CKey &key)
if(key.isRSA)
return backend->decrypt(key.cipher, false);
return backend->deriveConcatKDF(key.publicKey, SHA_MTH[key.concatDigest],
int(KWAES_SIZE[key.method]), key.AlgorithmID, key.PartyUInfo, key.PartyVInfo);
key.AlgorithmID, key.PartyUInfo, key.PartyVInfo);
});
if(decryptedKey.isEmpty())
{
Expand Down
4 changes: 1 addition & 3 deletions client/CDoc1.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,12 +57,10 @@ class CDoc1 final: public CDoc, private QFile
static const QString
AES128CBC_MTH, AES192CBC_MTH, AES256CBC_MTH,
AES128GCM_MTH, AES192GCM_MTH, AES256GCM_MTH,
KWAES128_MTH, KWAES192_MTH, KWAES256_MTH,
SHA256_MTH, SHA384_MTH, SHA512_MTH,
RSA_MTH, CONCATKDF_MTH, AGREEMENT_MTH;
RSA_MTH, CONCATKDF_MTH, AGREEMENT_MTH, KWAES256_MTH;
static const QString DS, DENC, DSIG11, XENC11;
static const QString MIME_ZLIB, MIME_DDOC, MIME_DDOC_OLD;
static const QHash<QString, const EVP_CIPHER*> ENC_MTH;
static const QHash<QString, QCryptographicHash::Algorithm> SHA_MTH;
static const QHash<QString, quint32> KWAES_SIZE;
};
31 changes: 14 additions & 17 deletions client/CDoc2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -432,26 +432,23 @@ CDoc2::CDoc2(const QString &path)
for(const auto *recipient: *recipients){
if(recipient->fmk_encryption_method() != FMKEncryptionMethod::XOR)
{
keys.append(CKey::Unsupported);
qWarning() << "Unsupported FMK encryption method: skipping";
continue;
}
auto fillRecipient = [&] (auto key, bool isRSA) {
auto fillRecipient = [&] (auto key, bool isRSA, bool unsupported = false) {
CKey k(toByteArray(key->recipient_public_key()), isRSA);
k.recipient = toString(recipient->key_label());
k.cipher = toByteArray(recipient->encrypted_fmk());
k.unsupported = unsupported;
return k;
};
switch(recipient->capsule_type())
{
case Capsule::ECCPublicKeyCapsule:
if(const auto *key = recipient->capsule_as_ECCPublicKeyCapsule())
{
if(key->curve() != EllipticCurve::secp384r1)
{
qWarning() << "Unsupported ECC curve: skipping";
continue;
}
CKey k = fillRecipient(key, false);
CKey k = fillRecipient(key, false, key->curve() != EllipticCurve::secp384r1);
k.publicKey = toByteArray(key->sender_public_key());
keys.append(std::move(k));
}
Expand All @@ -467,8 +464,8 @@ CDoc2::CDoc2(const QString &path)
case Capsule::KeyServerCapsule:
if(const auto *server = recipient->capsule_as_KeyServerCapsule())
{
auto fillKeyServer = [&] (auto key, bool isRSA) {
CKey k = fillRecipient(key, isRSA);
auto fillKeyServer = [&] (auto key, bool isRSA, bool unsupported = false) {
CKey k = fillRecipient(key, isRSA, unsupported);
k.keyserver_id = toString(server->keyserver_id());
k.transaction_id = toString(server->transaction_id());
return k;
Expand All @@ -477,21 +474,20 @@ CDoc2::CDoc2(const QString &path)
{
case ServerDetailsUnion::ServerEccDetails:
if(const auto *eccDetails = server->recipient_key_details_as_ServerEccDetails())
{
if(eccDetails->curve() == EllipticCurve::secp384r1)
keys.append(fillKeyServer(eccDetails, false));
}
keys.append(fillKeyServer(eccDetails, false, eccDetails->curve() != EllipticCurve::secp384r1));
break;
case ServerDetailsUnion::ServerRsaDetails:
if(const auto *rsaDetails = server->recipient_key_details_as_ServerRsaDetails())
keys.append(fillKeyServer(rsaDetails, true));
break;
default:
keys.append(CKey::Unsupported);
qWarning() << "Unsupported Key Server Details: skipping";
}
}
break;
default:
keys.append(CKey::Unsupported);
qWarning() << "Unsupported Key Details: skipping";
}
}
Expand Down Expand Up @@ -562,6 +558,7 @@ bool CDoc2::save(const QString &path)
if(!cdoc20::checkConnection())
return false;
QScopedPointer<QNetworkAccessManager,QScopedPointerDeleteLater> nam(CheckConnection::setupNAM(req, Settings::CDOC2_POST_CERT));
req.setRawHeader("x-expiry-time", QDateTime::currentDateTimeUtc().addMonths(6).toString(Qt::ISODate).toLatin1());
QEventLoop e;
QNetworkReply *reply = nam->post(req, QJsonDocument({
{QLatin1String("recipient_id"), QLatin1String(recipient_id.toBase64())},
Expand Down Expand Up @@ -602,7 +599,7 @@ bool CDoc2::save(const QString &path)
toVector(key.key), toVector(encrytpedKek));
recipients.push_back(cdoc20::Header::CreateRecipientRecord(builder,
cdoc20::Recipients::Capsule::RSAPublicKeyCapsule, rsaPublicKey.Union(),
toString(key.recipient), toVector(xor_key), cdoc20::Header::FMKEncryptionMethod::XOR));
toString(key.keyLabel()), toVector(xor_key), cdoc20::Header::FMKEncryptionMethod::XOR));
continue;
}

Expand All @@ -614,7 +611,7 @@ bool CDoc2::save(const QString &path)
rsaKeyServer.Union(), toString(key.keyserver_id), toString(key.transaction_id));
recipients.push_back(cdoc20::Header::CreateRecipientRecord(builder,
cdoc20::Recipients::Capsule::KeyServerCapsule, keyServer.Union(),
toString(key.recipient), toVector(xor_key), cdoc20::Header::FMKEncryptionMethod::XOR));
toString(key.keyLabel()), toVector(xor_key), cdoc20::Header::FMKEncryptionMethod::XOR));
continue;
}

Expand Down Expand Up @@ -642,7 +639,7 @@ bool CDoc2::save(const QString &path)
cdoc20::Recipients::EllipticCurve::secp384r1, toVector(key.key), toVector(ephPublicKeyDer));
recipients.push_back(cdoc20::Header::CreateRecipientRecord(builder,
cdoc20::Recipients::Capsule::ECCPublicKeyCapsule, eccPublicKey.Union(),
toString(key.recipient), toVector(xor_key), cdoc20::Header::FMKEncryptionMethod::XOR));
toString(key.keyLabel()), toVector(xor_key), cdoc20::Header::FMKEncryptionMethod::XOR));
continue;
}

Expand All @@ -655,7 +652,7 @@ bool CDoc2::save(const QString &path)
eccKeyServer.Union(), toString(key.keyserver_id), toString(key.transaction_id));
recipients.push_back(cdoc20::Header::CreateRecipientRecord(builder,
cdoc20::Recipients::Capsule::KeyServerCapsule, keyServer.Union(),
toString(key.recipient), toVector(xor_key), cdoc20::Header::FMKEncryptionMethod::XOR));
toString(key.keyLabel()), toVector(xor_key), cdoc20::Header::FMKEncryptionMethod::XOR));
}

auto offset = cdoc20::Header::CreateHeader(builder, builder.CreateVector(recipients),
Expand Down
3 changes: 2 additions & 1 deletion client/Crypto.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -144,10 +144,11 @@ QByteArray Crypto::cipher(const EVP_CIPHER *cipher, const QByteArray &key, QByte
return data;
}

QByteArray Crypto::concatKDF(QCryptographicHash::Algorithm hashAlg, quint32 keyDataLen, const QByteArray &z, const QByteArray &otherInfo)
QByteArray Crypto::concatKDF(QCryptographicHash::Algorithm hashAlg, const QByteArray &z, const QByteArray &otherInfo)
{
if(z.isEmpty())
return z;
quint32 keyDataLen = 32;
auto hashLen = quint32(QCryptographicHash::hashLength(hashAlg));
auto reps = quint32(std::ceil(double(keyDataLen) / double(hashLen)));
QCryptographicHash md(hashAlg);
Expand Down
3 changes: 1 addition & 2 deletions client/Crypto.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,7 @@ class Crypto
static QByteArray aes_wrap(const QByteArray &key, const QByteArray &data, bool encrypt);
static QByteArray cipher(const EVP_CIPHER *cipher, const QByteArray &key, QByteArray &data, bool encrypt);
static QByteArray curve_oid(EVP_PKEY *key);
static QByteArray concatKDF(QCryptographicHash::Algorithm digestMethod,
quint32 keyDataLen, const QByteArray &z, const QByteArray &otherInfo);
static QByteArray concatKDF(QCryptographicHash::Algorithm digestMethod, const QByteArray &z, const QByteArray &otherInfo);
static QByteArray derive(EVP_PKEY *priv, EVP_PKEY *pub);
static QByteArray encrypt(EVP_PKEY *pub, int padding, const QByteArray &data);
static QByteArray expand(const QByteArray &key, const QByteArray &info, int len = 32);
Expand Down
25 changes: 25 additions & 0 deletions client/CryptoDoc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
#include <QtCore/QRegularExpression>
#include <QtCore/QThread>
#include <QtCore/QUrl>
#include <QtCore/QUrlQuery>
#include <QtGui/QDesktopServices>
#include <QtNetwork/QSslKey>
#include <QtWidgets/QMessageBox>
Expand Down Expand Up @@ -217,6 +218,10 @@ QString CDocumentModel::save(int row, const QString &path) const
return fileName;
}

CKey::CKey(Tag)
: unsupported(true)
{}

CKey::CKey(const QSslCertificate &c)
{
setCert(c);
Expand Down Expand Up @@ -246,6 +251,26 @@ void CKey::setCert(const QSslCertificate &c)
isRSA = k.algorithm() == QSsl::Rsa;
}

QString CKey::keyLabel() const
{
if(cert.isNull())
return recipient;
QDateTime exp = cert.expiryDate();
if(Settings::CDOC2_USE_KEYSERVER)
exp = std::min(exp, QDateTime::currentDateTimeUtc().addMonths(6));
auto escape = [](QString data) { return data.replace(',', QLatin1String("%2C")); };
QUrlQuery q;
q.setQueryItems({
{QStringLiteral("v"), QString::number(1)},
{QStringLiteral("type"), QStringLiteral("ID-card")},
{QStringLiteral("serial_number"), escape(cert.subjectInfo("serialNumber").join(','))},
{QStringLiteral("cn"), escape(cert.subjectInfo("CN").join(','))},
{QStringLiteral("server_exp"), QString::number(exp.toSecsSinceEpoch())},
});
return "data:" + q.query(QUrl::FullyEncoded);
}



CryptoDoc::CryptoDoc( QObject *parent )
: QObject(parent)
Expand Down
Loading
Loading