Skip to content
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
32 changes: 32 additions & 0 deletions client/CryptoDoc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,38 @@ CKey::CKey(QSslCertificate _rcpt_cert) : lock(libcdoc::Lock::PUBLIC_KEY), rcpt_c
lock.setBytes(libcdoc::Lock::CERT, std::vector<uint8_t>(der.cbegin(), der.cend()));
}

bool
CKey::canDecrypt(const QSslCertificate &cert) const
{
if(!lock.isPKI() || !isSupported())
return false;
const std::vector<uint8_t> &key = lock.getBytes(libcdoc::Lock::RCPT_KEY);
// RCPT_KEY is i2d_PublicKey, not the SubjectPublicKeyInfo QSslKey::toDer() gives
return SslCertificate(cert).publicKeyDer() ==
QByteArray::fromRawData((const char*)key.data(), qsizetype(key.size()));
}

bool
CKey::isSupported() const
{
if(!lock.isCDoc1())
return lock.isValid();
if(lock.encrypted_fmk.empty())
return false;
const std::string method = lock.getString(libcdoc::Lock::METHOD);
switch(lock.pk_type)
{
case libcdoc::Algorithm::RSA:
return method == libcdoc::Crypto::RSA_MTH;
case libcdoc::Algorithm::ECC:
return !lock.getBytes(libcdoc::Lock::KEY_MATERIAL).empty() &&
(method == libcdoc::Crypto::KWAES128_MTH || method == libcdoc::Crypto::KWAES192_MTH ||
method == libcdoc::Crypto::KWAES256_MTH);
default:
return false;
}
}

bool
CKey::operator==(const CKey& rhs) const
{
Expand Down
2 changes: 2 additions & 0 deletions client/CryptoDoc.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ struct CKey {
libcdoc::Lock lock;
QSslCertificate rcpt_cert;

bool canDecrypt(const QSslCertificate &cert) const;
bool isSupported() const;
bool operator== (const CKey& rhs) const;
};

Expand Down
6 changes: 5 additions & 1 deletion client/MainWindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,11 @@ MainWindow::MainWindow( QWidget *parent )
selectPage(Pages(page));
});
connect(ui->help, &QToolButton::clicked, qApp, &Application::openHelp);
connect(ui->settings, &QToolButton::clicked, this, [this] { showSettings(SettingsDialog::GeneralSettings); });
connect(ui->settings, &QToolButton::clicked, this, [this] {
auto page = ui->startScreen->currentIndex();
bool isEncryption = page == CryptoIntro || page == CryptoDetails;
showSettings(isEncryption ? SettingsDialog::EncryptionSettings : SettingsDialog::GeneralSettings);
});

// Refresh card info on "My EID" page
connect(ui->eidPage, &MyEidInfo::dataChanged, this, &MainWindow::updateMyEid);
Expand Down
24 changes: 11 additions & 13 deletions client/QCryptoBackend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -74,16 +74,7 @@ QCryptoBackend::getBackend(const TokenData& token, const QString &pin) {
if(backend->cert().isNull())
return backend.release();

Status status;
if(pin.isEmpty())
{
do {
status = backend->login(token, {});
} while (status == PinIncorrect);
}
else
status = backend->login(token, pin);
if (status != PinOK)
if(Status status = backend->login(token, pin); status != PinOK)
return std::unexpected(status);

return backend.release();
Expand All @@ -94,14 +85,18 @@ QSslCertificate QCryptoBackend::cert() const
return token.cert();
}

QString QCryptoBackend::errorString(Status error)
QString QCryptoBackend::errorString(Status error, const TokenData &token)
{
switch( error )
{
case PinOK: return QString();
case PinCanceled: return tr("PIN entry canceled");
case PinLocked: return tr("PIN locked");
case PinIncorrect: return tr("PIN incorrect");
case PinIncorrect:
if(QSmartCardData data = QSmartCard::readCard(token, true); !data.isNull())
return tr("PIN incorrect") + QStringLiteral(". ") +
tr("Remaining attempts: %1").arg(data.retryCount(QSmartCardData::pinType(token.cert())));
return tr("PIN incorrect");
case InProgress: return tr("Signing/decrypting is already in progress another window.");
case GeneralError: return tr("PKCS11 general error");
case DeviceError: return tr("PKCS11 device error");
Expand Down Expand Up @@ -251,7 +246,10 @@ void QCryptoManager::refresh()
{
QWriteLocker locker(&d->lock);
if(!std::ranges::equal(newCache, d->cache, [](const TokenData &a, const TokenData &b) {
return a == b && a.data(QStringLiteral("blocked")) == b.data(QStringLiteral("blocked"));
return a == b &&
a.data(QStringLiteral("blocked")) == b.data(QStringLiteral("blocked")) &&
a.data(QStringLiteral("pinCountLow")) == b.data(QStringLiteral("pinCountLow")) &&
a.data(QStringLiteral("pinFinalTry")) == b.data(QStringLiteral("pinFinalTry"));
}))
{
d->cache = newCache;
Expand Down
2 changes: 1 addition & 1 deletion client/QCryptoBackend.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ class QCryptoBackend
*/
mutable Status status = PinOK;

static QString errorString(Status error);
static QString errorString(Status error, const TokenData &token = {});

protected:
virtual Status login(const TokenData &cert, const QString &pin) = 0;
Expand Down
38 changes: 11 additions & 27 deletions client/QPKCS11.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@
#include "SslCertificate.h"
#include "TokenData.h"
#include "Utils.h"
#include "dialogs/PinPopup.h"

#include <QtCore/QDebug>
#include <QtCore/QtEndian>
Expand Down Expand Up @@ -387,33 +386,16 @@ QPKCS11::Status QPKCS11::login(const TokenData &t, const QString &pin)
if(!d->l->isFinDriver && !(token.flags & CKF_LOGIN_REQUIRED))
return PinOK;

SslCertificate cert(t.cert());
bool isSign = cert.keyUsage().keys().contains(SslCertificate::NonRepudiation);
PinPopup::TokenFlags f;
if(token.flags & CKF_USER_PIN_LOCKED) return PinLocked;
if(token.flags & CKF_USER_PIN_COUNT_LOW) f = PinPopup::PinCountLow;
if(token.flags & CKF_USER_PIN_FINAL_TRY) f = PinPopup::PinFinalTry;
CK_RV err = dispatchToMain([&]{
if(token.flags & CKF_PROTECTED_AUTHENTICATION_PATH) {
f |= PinPopup::PinpadFlag;
PinPopup p(isSign ? QSmartCardData::Pin2Type : QSmartCardData::Pin1Type, f, cert, Application::mainWindow());
p.open();
p.startTimer();
return waitFor(d->l->f->C_Login, d->session, CKU_USER, nullptr, 0);
} else {
QByteArray pinData;
if(pin.isEmpty()) {
PinPopup p(isSign ? QSmartCardData::Pin2Type : QSmartCardData::Pin1Type, f, cert, Application::mainWindow());
p.setPinLen(token.ulMinPinLen, token.ulMaxPinLen < 12 ? 12 : token.ulMaxPinLen);
if(!p.exec())
return CKR_FUNCTION_CANCELED;
pinData = p.pin().toUtf8();
} else {
pinData = pin.toUtf8();
}
return d->l->f->C_Login(d->session, CKU_USER, CK_UTF8CHAR_PTR(pinData.constData()), CK_ULONG(pinData.size()));
}
});
CK_RV err {};
if(token.flags & CKF_PROTECTED_AUTHENTICATION_PATH) {
err = waitFor(d->l->f->C_Login, d->session, CKU_USER, nullptr, 0);
} else if(pin.isEmpty()) {
return PinCanceled;
} else {
QByteArray pinData = pin.toUtf8();
err = d->l->f->C_Login(d->session, CKU_USER, CK_UTF8CHAR_PTR(pinData.constData()), CK_ULONG(pinData.size()));
}

switch(err)
{
Expand Down Expand Up @@ -477,6 +459,8 @@ QList<TokenData> QPKCS11::tokens()
t.setData(QStringLiteral("id"), id);
t.setData(QStringLiteral("blocked"), (token.flags & (CKF_USER_PIN_LOCKED|CKF_USER_PIN_TO_BE_CHANGED)) > 0);
t.setData(QStringLiteral("pinpad"), (token.flags & CKF_PROTECTED_AUTHENTICATION_PATH) > 0);
t.setData(QStringLiteral("pinCountLow"), (token.flags & CKF_USER_PIN_COUNT_LOW) > 0);
t.setData(QStringLiteral("pinFinalTry"), (token.flags & CKF_USER_PIN_FINAL_TRY) > 0);
t.setData(QStringLiteral("pinMin"), int(token.ulMinPinLen));
t.setData(QStringLiteral("pinMax"), int(token.ulMaxPinLen));

Expand Down
34 changes: 8 additions & 26 deletions client/QSmartCard.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
#include "QCryptoBackend.h"
#include "Settings.h"
#include "Utils.h"
#include "dialogs/PinPopup.h"
#include "dialogs/PinpadPopup.h"
#include "dialogs/PinUnblock.h"
#include "effects/FadeInNotification.h"

Expand Down Expand Up @@ -78,6 +78,11 @@ quint8 QSmartCardData::minPinLen(QSmartCardData::PinType type)
return 4;
}

QSmartCardData::PinType QSmartCardData::pinType(const QSslCertificate &cert)
{
return SslCertificate(cert).keyUsage().contains(SslCertificate::NonRepudiation) ? Pin2Type : Pin1Type;
}

QString QSmartCardData::typeString(QSmartCardData::PinType type)
{
switch(type)
Expand Down Expand Up @@ -499,7 +504,7 @@ bool QSmartCard::pinChange(TokenData token, QSmartCardData current, QSmartCardDa
if(current.isNull())
return false;
auto notify = qScopeGuard([token] { qApp->cryptoManager()->refreshToken(token); });
std::unique_ptr<PinPopup,QScopedPointerDeleteLater> popup;
std::unique_ptr<PinpadPopup,QScopedPointerDeleteLater> popup;
QByteArray oldPin, newPin;
QSmartCardData::PinType src = type;
if(action != QSmartCard::ChangeWithPin && action != QSmartCard::ActivateWithPin)
Expand All @@ -518,30 +523,7 @@ bool QSmartCard::pinChange(TokenData token, QSmartCardData current, QSmartCardDa

if(current.isPinpad())
{
QString bodyText;
switch(action)
{
case QSmartCard::ActivateWithPuk:
case QSmartCard::ChangeWithPuk:
bodyText = tr("To change %1 code with the PUK code on a PinPad reader the PUK code has to be entered first and then the %1 code twice.").arg(QSmartCardData::typeString(type));
break;
case QSmartCard::UnblockWithPuk:
bodyText = tr("To unblock the %1 code on a PinPad reader the PUK code has to be entered first and then the %1 code twice.").arg(QSmartCardData::typeString(type));
break;
default:
bodyText = tr("To change %1 on a PinPad reader the old %1 code has to be entered first and then the new %1 code twice.").arg(QSmartCardData::typeString(type));
break;
}

PinPopup::TokenFlags flags = PinPopup::PinpadChangeFlag;
switch(current.retryCount(src))
{
case 2: flags |= PinPopup::PinCountLow; break;
case 1: flags |= PinPopup::PinFinalTry; break;
case 0: flags |= PinPopup::PinLocked; break;
default: break;
}
popup.reset(new PinPopup(src, flags, current.authCert(), parent, bodyText));
popup.reset(new PinpadPopup(type, action, current, parent));
popup->open();
oldPin = card->pinTemplate({});
newPin = card->pinTemplate({});
Expand Down
2 changes: 2 additions & 0 deletions client/QSmartCard.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@

class SslCertificate;
class QSmartCardDataPrivate;
class QSslCertificate;
class QSslKey;
class TokenData;
class QWidget;
Expand Down Expand Up @@ -73,6 +74,7 @@ class QSmartCardData
bool pinLocked(PinType type) const;

static quint8 minPinLen(QSmartCardData::PinType type);
static PinType pinType(const QSslCertificate &cert);
static QString typeString( PinType type );

private:
Expand Down
Loading
Loading