Page Menu
Home
GnuPG
Search
Configure Global Search
Log In
Files
F34135305
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Size
18 KB
Subscribers
None
View Options
diff --git a/src/view/pivcardwidget.cpp b/src/view/pivcardwidget.cpp
index 5d8a62b4e..3ce233134 100644
--- a/src/view/pivcardwidget.cpp
+++ b/src/view/pivcardwidget.cpp
@@ -1,396 +1,397 @@
/* view/pivcardwiget.cpp
This file is part of Kleopatra, the KDE keymanager
SPDX-FileCopyrightText: 2020 g10 Code GmbH
SPDX-FileContributor: Ingo Klöcker <dev@ingo-kloecker.de>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "pivcardwidget.h"
#include "tooltippreferences.h"
#include "commands/certificatetopivcardcommand.h"
#include "commands/changepincommand.h"
#include "commands/createcsrforcardkeycommand.h"
#include "commands/createopenpgpkeyfromcardkeyscommand.h"
#include "commands/importcertificatefrompivcardcommand.h"
#include "commands/keytocardcommand.h"
#include "commands/pivgeneratecardkeycommand.h"
#include "commands/setpivcardapplicationadministrationkeycommand.h"
#include "smartcard/pivcard.h"
#include "smartcard/readerstatus.h"
#include <Libkleo/Compliance>
#include <Libkleo/Dn>
#include <Libkleo/Formatting>
#include <Libkleo/KeyCache>
#include <KLocalizedString>
#include <KSeparator>
#include <QFrame>
#include <QGridLayout>
#include <QLabel>
#include <QPushButton>
#include <QScrollArea>
#include <QVBoxLayout>
using namespace GpgME;
using namespace Kleo;
using namespace Kleo::Commands;
using namespace Kleo::SmartCard;
namespace
{
static void layoutKeyWidgets(QGridLayout *grid, const QString &keyName, const PIVCardWidget::KeyWidgets &keyWidgets)
{
int row = grid->rowCount();
grid->addWidget(new QLabel(keyName), row, 0);
grid->addWidget(keyWidgets.keyGrip, row, 1);
grid->addWidget(keyWidgets.keyAlgorithm, row, 2);
grid->addWidget(keyWidgets.generateButton, row, 3);
if (keyWidgets.writeKeyButton) {
grid->addWidget(keyWidgets.writeKeyButton, row, 4);
}
row++;
grid->addWidget(keyWidgets.certificateInfo, row, 1, 1, 2);
grid->addWidget(keyWidgets.writeCertificateButton, row, 3);
grid->addWidget(keyWidgets.importCertificateButton, row, 4);
if (keyWidgets.createCSRButton) {
grid->addWidget(keyWidgets.createCSRButton, row, 5);
}
}
static int toolTipOptions()
{
using namespace Kleo::Formatting;
static const int validityFlags = Validity | Issuer | ExpiryDates | CertificateUsage;
static const int ownerFlags = Subject | UserIDs | OwnerTrust;
static const int detailsFlags = StorageLocation | CertificateType | SerialNumber | Fingerprint;
const TooltipPreferences prefs;
int flags = KeyID;
flags |= prefs.showValidity() ? validityFlags : 0;
flags |= prefs.showOwnerInformation() ? ownerFlags : 0;
flags |= prefs.showCertificateDetails() ? detailsFlags : 0;
return flags;
}
}
PIVCardWidget::PIVCardWidget(QWidget *parent)
: QWidget(parent)
- , mSerialNumber(new QLabel(this))
- , mVersionLabel(new QLabel(this))
{
// Set up the scroll area
auto myLayout = new QVBoxLayout(this);
myLayout->setContentsMargins(0, 0, 0, 0);
auto area = new QScrollArea;
+ area->setFocusPolicy(Qt::NoFocus);
area->setFrameShape(QFrame::NoFrame);
area->setWidgetResizable(true);
myLayout->addWidget(area);
auto areaWidget = new QWidget;
area->setWidget(areaWidget);
auto areaVLay = new QVBoxLayout(areaWidget);
auto cardInfoGrid = new QGridLayout;
{
int row = 0;
// Version and Serialnumber
- cardInfoGrid->addWidget(mVersionLabel, row++, 0, 1, 2);
+ mVersionLabel = new QLabel{this};
mVersionLabel->setTextInteractionFlags(Qt::TextBrowserInteraction);
+ cardInfoGrid->addWidget(mVersionLabel, row++, 0, 1, 2);
cardInfoGrid->addWidget(new QLabel(i18nc("@label:textbox", "Serial number:")), row, 0);
- cardInfoGrid->addWidget(mSerialNumber, row++, 1);
+ mSerialNumber = new QLabel{this};
mSerialNumber->setTextInteractionFlags(Qt::TextBrowserInteraction);
+ cardInfoGrid->addWidget(mSerialNumber, row++, 1);
cardInfoGrid->setColumnStretch(cardInfoGrid->columnCount(), 1);
}
areaVLay->addLayout(cardInfoGrid);
areaVLay->addWidget(new KSeparator(Qt::Horizontal));
- areaVLay->addWidget(new QLabel(QStringLiteral("<b>%1</b>").arg(i18n("Keys:"))));
+ areaVLay->addWidget(new QLabel(QStringLiteral("<b>%1</b>").arg(i18n("Keys:")), this));
auto keysGrid = new QGridLayout;
for (const auto &keyInfo : PIVCard::supportedKeys()) {
KeyWidgets keyWidgets = createKeyWidgets(keyInfo);
layoutKeyWidgets(keysGrid, PIVCard::keyDisplayName(keyInfo.keyRef), keyWidgets);
}
areaVLay->addLayout(keysGrid);
areaVLay->addWidget(new KSeparator(Qt::Horizontal));
auto actionLayout = new QHBoxLayout;
if (CreateOpenPGPKeyFromCardKeysCommand::isSupported()) {
mKeyForCardKeysButton = new QPushButton(this);
mKeyForCardKeysButton->setText(i18nc("@action:button", "Create OpenPGP Key"));
mKeyForCardKeysButton->setToolTip(i18nc("@info:tooltip", "Create an OpenPGP key for the keys stored on the card."));
actionLayout->addWidget(mKeyForCardKeysButton);
connect(mKeyForCardKeysButton, &QPushButton::clicked, this, &PIVCardWidget::createKeyFromCardKeys);
}
{
- auto button = new QPushButton(i18nc("@action:button", "Change PIN"));
+ auto button = new QPushButton(i18nc("@action:button", "Change PIN"), this);
button->setToolTip(i18nc("@info:tooltip",
"Change the PIV Card Application PIN that activates the PIV Card "
"and enables private key operations using the stored keys."));
actionLayout->addWidget(button);
connect(button, &QPushButton::clicked, this, [this]() {
changePin(PIVCard::pinKeyRef());
});
}
{
- auto button = new QPushButton(i18nc("@action:button", "Change PUK"));
+ auto button = new QPushButton(i18nc("@action:button", "Change PUK"), this);
button->setToolTip(i18nc("@info:tooltip", "Change the PIN Unblocking Key that enables a reset of the PIN."));
actionLayout->addWidget(button);
connect(button, &QPushButton::clicked, this, [this]() {
changePin(PIVCard::pukKeyRef());
});
}
{
- auto button = new QPushButton(i18nc("@action:button", "Change Admin Key"));
+ auto button = new QPushButton(i18nc("@action:button", "Change Admin Key"), this);
button->setToolTip(i18nc("@info:tooltip",
"Change the PIV Card Application Administration Key that is used by the "
"PIV Card Application to authenticate the PIV Card Application Administrator and by the "
"administrator (resp. Kleopatra) to authenticate the PIV Card Application."));
actionLayout->addWidget(button);
connect(button, &QPushButton::clicked, this, [this]() {
setAdminKey();
});
}
actionLayout->addStretch(-1);
areaVLay->addLayout(actionLayout);
areaVLay->addStretch(1);
}
PIVCardWidget::KeyWidgets PIVCardWidget::createKeyWidgets(const KeyPairInfo &keyInfo)
{
const std::string keyRef = keyInfo.keyRef;
KeyWidgets keyWidgets;
keyWidgets.keyGrip = new QLabel(this);
keyWidgets.keyGrip->setTextInteractionFlags(Qt::TextBrowserInteraction);
keyWidgets.keyAlgorithm = new QLabel(this);
keyWidgets.keyAlgorithm->setTextInteractionFlags(Qt::TextSelectableByMouse);
- keyWidgets.certificateInfo = new QLabel(this);
- keyWidgets.certificateInfo->setTextInteractionFlags(Qt::TextBrowserInteraction);
keyWidgets.generateButton = new QPushButton(i18nc("@action:button", "Generate"), this);
keyWidgets.generateButton->setEnabled(false);
connect(keyWidgets.generateButton, &QPushButton::clicked, this, [this, keyRef]() {
generateKey(keyRef);
});
- if (keyInfo.canSign() || keyInfo.canEncrypt()) {
- keyWidgets.createCSRButton = new QPushButton(i18nc("@action:button", "Create CSR"), this);
- keyWidgets.createCSRButton->setToolTip(i18nc("@info:tooltip", "Create a certificate signing request for this key"));
- keyWidgets.createCSRButton->setEnabled(false);
- connect(keyWidgets.createCSRButton, &QPushButton::clicked, this, [this, keyRef]() {
- createCSR(keyRef);
+ if (keyRef == PIVCard::cardAuthenticationKeyRef() || keyRef == PIVCard::keyManagementKeyRef()) {
+ keyWidgets.writeKeyButton = new QPushButton(i18nc("@action:button", "Write Key"), this);
+ keyWidgets.writeKeyButton->setToolTip(i18nc("@info:tooltip", "Write the key pair of a certificate to the card"));
+ keyWidgets.writeKeyButton->setEnabled(true);
+ connect(keyWidgets.writeKeyButton, &QPushButton::clicked, this, [this, keyRef]() {
+ writeKeyToCard(keyRef);
});
}
- keyWidgets.writeCertificateButton = new QPushButton(i18nc("@action:button", "Write Certificate"));
+ keyWidgets.certificateInfo = new QLabel(this);
+ keyWidgets.certificateInfo->setTextInteractionFlags(Qt::TextBrowserInteraction);
+ keyWidgets.writeCertificateButton = new QPushButton(i18nc("@action:button", "Write Certificate"), this);
keyWidgets.writeCertificateButton->setToolTip(i18nc("@info:tooltip", "Write the certificate corresponding to this key to the card"));
keyWidgets.writeCertificateButton->setEnabled(false);
connect(keyWidgets.writeCertificateButton, &QPushButton::clicked, this, [this, keyRef]() {
writeCertificateToCard(keyRef);
});
- keyWidgets.importCertificateButton = new QPushButton(i18nc("@action:button", "Import Certificate"));
+ keyWidgets.importCertificateButton = new QPushButton(i18nc("@action:button", "Import Certificate"), this);
keyWidgets.importCertificateButton->setToolTip(i18nc("@info:tooltip", "Import the certificate stored on the card"));
keyWidgets.importCertificateButton->setEnabled(false);
connect(keyWidgets.importCertificateButton, &QPushButton::clicked, this, [this, keyRef]() {
importCertificateFromCard(keyRef);
});
- if (keyRef == PIVCard::cardAuthenticationKeyRef() || keyRef == PIVCard::keyManagementKeyRef()) {
- keyWidgets.writeKeyButton = new QPushButton(i18nc("@action:button", "Write Key"));
- keyWidgets.writeKeyButton->setToolTip(i18nc("@info:tooltip", "Write the key pair of a certificate to the card"));
- keyWidgets.writeKeyButton->setEnabled(true);
- connect(keyWidgets.writeKeyButton, &QPushButton::clicked, this, [this, keyRef]() {
- writeKeyToCard(keyRef);
+ if (keyInfo.canSign() || keyInfo.canEncrypt()) {
+ keyWidgets.createCSRButton = new QPushButton(i18nc("@action:button", "Create CSR"), this);
+ keyWidgets.createCSRButton->setToolTip(i18nc("@info:tooltip", "Create a certificate signing request for this key"));
+ keyWidgets.createCSRButton->setEnabled(false);
+ connect(keyWidgets.createCSRButton, &QPushButton::clicked, this, [this, keyRef]() {
+ createCSR(keyRef);
});
}
mKeyWidgets.insert({keyRef, keyWidgets});
return keyWidgets;
}
PIVCardWidget::~PIVCardWidget()
{
}
void PIVCardWidget::setCard(const PIVCard *card)
{
mCardSerialNumber = card->serialNumber();
mVersionLabel->setText(i18nc("%1 version number", "PIV v%1 card", card->displayAppVersion()));
mSerialNumber->setText(card->displaySerialNumber());
mSerialNumber->setToolTip(QString::fromStdString(card->serialNumber()));
if (card) {
updateCachedValues(PIVCard::pivAuthenticationKeyRef(), card);
updateCachedValues(PIVCard::cardAuthenticationKeyRef(), card);
updateCachedValues(PIVCard::digitalSignatureKeyRef(), card);
updateCachedValues(PIVCard::keyManagementKeyRef(), card);
}
updateKeyWidgets(PIVCard::pivAuthenticationKeyRef());
updateKeyWidgets(PIVCard::cardAuthenticationKeyRef());
updateKeyWidgets(PIVCard::digitalSignatureKeyRef());
updateKeyWidgets(PIVCard::keyManagementKeyRef());
if (mKeyForCardKeysButton) {
mKeyForCardKeysButton->setEnabled(card->hasSigningKey() //
&& card->hasEncryptionKey() //
&& DeVSCompliance::algorithmIsCompliant(card->keyInfo(card->signingKeyRef()).algorithm)
&& DeVSCompliance::algorithmIsCompliant(card->keyInfo(card->encryptionKeyRef()).algorithm));
}
}
void PIVCardWidget::updateCachedValues(const std::string &keyRef, const SmartCard::PIVCard *card)
{
KeyWidgets &widgets = mKeyWidgets.at(keyRef);
widgets.keyInfo = card->keyInfo(keyRef);
widgets.certificateData = card->certificateData(keyRef);
}
void PIVCardWidget::updateKeyWidgets(const std::string &keyRef)
{
const KeyWidgets &widgets = mKeyWidgets.at(keyRef);
const std::string grip = widgets.keyInfo.grip;
if (grip.empty()) {
widgets.certificateInfo->setText(i18nc("@info", "<em>slot empty</em>"));
widgets.certificateInfo->setToolTip(QString());
widgets.keyGrip->setText(QString());
widgets.keyAlgorithm->setText(QString());
widgets.generateButton->setText(i18nc("@action:button", "Generate"));
widgets.generateButton->setToolTip(i18nc("@info:tooltip %1 display name of a key", "Generate %1", PIVCard::keyDisplayName(keyRef)));
if (widgets.createCSRButton) {
widgets.createCSRButton->setEnabled(false);
}
widgets.writeCertificateButton->setEnabled(false);
widgets.importCertificateButton->setEnabled(false);
} else {
const Key certificate = KeyCache::instance()->findSubkeyByKeyGrip(grip, GpgME::CMS).parent();
if (!certificate.isNull()) {
widgets.certificateInfo->setText(i18nc("X.509 certificate DN (validity, created: date)",
"%1 (%2, created: %3)",
DN(certificate.userID(0).id()).prettyDN(),
Formatting::complianceStringShort(certificate),
Formatting::creationDateString(certificate)));
widgets.certificateInfo->setToolTip(Formatting::toolTip(certificate, toolTipOptions()));
widgets.writeCertificateButton->setEnabled(true);
} else {
widgets.certificateInfo->setText(i18nc("@info", "<em>no matching certificate</em>"));
widgets.certificateInfo->setToolTip(QString());
widgets.writeCertificateButton->setEnabled(false);
}
widgets.keyGrip->setText(QString::fromStdString(grip));
const std::string algo = widgets.keyInfo.algorithm;
widgets.keyAlgorithm->setText(algo.empty() ? i18nc("@info unknown key algorithm", "unknown") : QString::fromStdString(algo));
widgets.importCertificateButton->setEnabled(!widgets.certificateData.empty());
widgets.generateButton->setText(i18nc("@action:button", "Replace"));
widgets.generateButton->setToolTip(i18nc("@info:tooltip %1 display name of a key", "Replace %1 with new key", PIVCard::keyDisplayName(keyRef)));
if (widgets.createCSRButton) {
widgets.createCSRButton->setEnabled(DeVSCompliance::algorithmIsCompliant(algo));
}
}
widgets.generateButton->setEnabled(true);
}
void PIVCardWidget::generateKey(const std::string &keyref)
{
auto cmd = new PIVGenerateCardKeyCommand(mCardSerialNumber, this);
this->setEnabled(false);
connect(cmd, &PIVGenerateCardKeyCommand::finished, this, [this]() {
this->setEnabled(true);
});
cmd->setKeyRef(keyref);
cmd->start();
}
void PIVCardWidget::createCSR(const std::string &keyref)
{
auto cmd = new CreateCSRForCardKeyCommand(keyref, mCardSerialNumber, PIVCard::AppName, this);
this->setEnabled(false);
connect(cmd, &CreateCSRForCardKeyCommand::finished, this, [this]() {
this->setEnabled(true);
});
cmd->start();
}
void PIVCardWidget::writeCertificateToCard(const std::string &keyref)
{
auto cmd = new CertificateToPIVCardCommand(keyref, mCardSerialNumber);
this->setEnabled(false);
connect(cmd, &CertificateToPIVCardCommand::finished, this, [this]() {
this->setEnabled(true);
});
cmd->setParentWidget(this);
cmd->start();
}
void PIVCardWidget::importCertificateFromCard(const std::string &keyref)
{
auto cmd = new ImportCertificateFromPIVCardCommand(keyref, mCardSerialNumber);
this->setEnabled(false);
connect(cmd, &ImportCertificateFromPIVCardCommand::finished, this, [this, keyref]() {
this->updateKeyWidgets(keyref);
this->setEnabled(true);
});
cmd->setParentWidget(this);
cmd->start();
}
void PIVCardWidget::writeKeyToCard(const std::string &keyref)
{
auto cmd = new KeyToCardCommand(keyref, mCardSerialNumber, PIVCard::AppName);
this->setEnabled(false);
connect(cmd, &KeyToCardCommand::finished, this, [this]() {
this->setEnabled(true);
});
cmd->setParentWidget(this);
cmd->start();
}
void PIVCardWidget::createKeyFromCardKeys()
{
auto cmd = new CreateOpenPGPKeyFromCardKeysCommand(mCardSerialNumber, PIVCard::AppName, this);
this->setEnabled(false);
connect(cmd, &CreateOpenPGPKeyFromCardKeysCommand::finished, this, [this]() {
this->setEnabled(true);
});
cmd->start();
}
void PIVCardWidget::changePin(const std::string &keyRef)
{
auto cmd = new ChangePinCommand(mCardSerialNumber, PIVCard::AppName, this);
this->setEnabled(false);
connect(cmd, &ChangePinCommand::finished, this, [this]() {
this->setEnabled(true);
});
cmd->setKeyRef(keyRef);
cmd->start();
}
void PIVCardWidget::setAdminKey()
{
auto cmd = new SetPIVCardApplicationAdministrationKeyCommand(mCardSerialNumber, this);
this->setEnabled(false);
connect(cmd, &SetPIVCardApplicationAdministrationKeyCommand::finished, this, [this]() {
this->setEnabled(true);
});
cmd->start();
}
#include "moc_pivcardwidget.cpp"
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Mon, Dec 8, 11:42 AM (1 d, 12 h)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
d5/54/e0c08ae1f91d56d413a4f407de5e
Attached To
rKLEOPATRA Kleopatra
Event Timeline
Log In to Comment