Commit b0821ce5 authored by Ingo Klöcker's avatar Ingo Klöcker
Browse files

Support import of certificates stored on PIV cards

GnuPG-bug-id: 4794
parent 4f33c819
Pipeline #35209 passed with stage
in 13 minutes and 2 seconds
......@@ -234,6 +234,7 @@ set(_kleopatra_SRCS
commands/authenticatepivcardapplicationcommand.cpp
commands/setpivcardapplicationadministrationkeycommand.cpp
commands/certificatetopivcardcommand.cpp
commands/importcertificatefrompivcardcommand.cpp
${_kleopatra_uiserver_files}
......
/* commands/importcertificatefrompivcardcommand.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 "importcertificatefrompivcardcommand.h"
#include "importcertificatescommand_p.h"
#include "smartcard/pivcard.h"
#include "smartcard/readerstatus.h"
#include <KLocalizedString>
#include "kleopatra_debug.h"
using namespace Kleo;
using namespace Kleo::Commands;
using namespace Kleo::SmartCard;
class ImportCertificateFromPIVCardCommand::Private : public ImportCertificatesCommand::Private
{
friend class ::Kleo::Commands::ImportCertificateFromPIVCardCommand;
ImportCertificateFromPIVCardCommand *q_func() const
{
return static_cast<ImportCertificateFromPIVCardCommand *>(q);
}
public:
explicit Private(ImportCertificateFromPIVCardCommand *qq,
const std::string &slot, const std::string &serialno);
~Private();
private:
void start();
private:
std::string serialNumber;
std::string cardSlot;
};
ImportCertificateFromPIVCardCommand::Private *ImportCertificateFromPIVCardCommand::d_func()
{
return static_cast<Private *>(d.get());
}
const ImportCertificateFromPIVCardCommand::Private *ImportCertificateFromPIVCardCommand::d_func() const
{
return static_cast<const Private *>(d.get());
}
#define q q_func()
#define d d_func()
ImportCertificateFromPIVCardCommand::Private::Private(ImportCertificateFromPIVCardCommand *qq,
const std::string &slot, const std::string &serialno)
: ImportCertificatesCommand::Private(qq, nullptr)
, serialNumber(serialno)
, cardSlot(slot)
{
}
ImportCertificateFromPIVCardCommand::Private::~Private()
{
}
void ImportCertificateFromPIVCardCommand::Private::start()
{
qCDebug(KLEOPATRA_LOG) << "ImportCertificateFromPIVCardCommand::Private::start()";
const auto pivCard = ReaderStatus::instance()->getCard<PIVCard>(serialNumber);
if (!pivCard) {
error(i18n("Failed to find the PIV card with the serial number: %1", QString::fromStdString(serialNumber)));
finished();
return;
}
const std::string certificateData = pivCard->certificateData(cardSlot);
if (certificateData.empty()) {
error(i18n("Sorry! No certificate to import from this card slot was found."));
finished();
return;
}
startImport(GpgME::CMS, QByteArray::fromStdString(certificateData), i18n("Card Certificate"));
}
ImportCertificateFromPIVCardCommand::ImportCertificateFromPIVCardCommand(const std::string& cardSlot, const std::string &serialno)
: ImportCertificatesCommand(new Private(this, cardSlot, serialno))
{
}
ImportCertificateFromPIVCardCommand::~ImportCertificateFromPIVCardCommand()
{
qCDebug(KLEOPATRA_LOG) << "ImportCertificateFromPIVCardCommand::~ImportCertificateFromPIVCardCommand()";
}
void ImportCertificateFromPIVCardCommand::doStart()
{
qCDebug(KLEOPATRA_LOG) << "ImportCertificateFromPIVCardCommand::doStart()";
d->start();
}
#undef q_func
#undef d_func
/* commands/importcertificatefrompivcardcommand.h
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
*/
#ifndef KLEOPATRA_COMMANDS_IMPORTCERTIFICATEFROMPIVCARDCOMMAND_H
#define KLEOPATRA_COMMANDS_IMPORTCERTIFICATEFROMPIVCARDCOMMAND_H
#include "importcertificatescommand.h"
namespace Kleo
{
namespace Commands
{
class ImportCertificateFromPIVCardCommand : public ImportCertificatesCommand
{
Q_OBJECT
public:
ImportCertificateFromPIVCardCommand(const std::string& cardSlot, const std::string &serialno);
~ImportCertificateFromPIVCardCommand() override;
private:
void doStart() override;
private:
class Private;
inline Private *d_func();
inline const Private *d_func() const;
};
}
}
#endif /* KLEOPATRA_COMMANDS_IMPORTCERTIFICATEFROMPIVCARDCOMMAND_H */
......@@ -11,6 +11,7 @@
#include "commands/certificatetopivcardcommand.h"
#include "commands/changepincommand.h"
#include "commands/importcertificatefrompivcardcommand.h"
#include "commands/keytocardcommand.h"
#include "commands/pivgeneratecardkeycommand.h"
#include "commands/setpivcardapplicationadministrationkeycommand.h"
......@@ -85,7 +86,7 @@ PIVCardWidget::PIVCardWidget(QWidget *parent):
// The keys
auto line1 = new QFrame();
line1->setFrameShape(QFrame::HLine);
grid->addWidget(line1, row++, 0, 1, 6);
grid->addWidget(line1, row++, 0, 1, 7);
grid->addWidget(new QLabel(QStringLiteral("<b>%1</b>").arg(i18n("Keys:"))), row++, 0);
mPIVAuthenticationKey = createKeyWidgets(PIVCard::pivAuthenticationKeyRef());
......@@ -94,6 +95,7 @@ PIVCardWidget::PIVCardWidget(QWidget *parent):
grid->addWidget(mPIVAuthenticationKey.keyAlgorithm, row, 2);
grid->addWidget(mPIVAuthenticationKey.generateButton, row, 3);
grid->addWidget(mPIVAuthenticationKey.writeCertificateButton, row, 4);
grid->addWidget(mPIVAuthenticationKey.importCertificateButton, row, 5);
row++;
mCardAuthenticationKey = createKeyWidgets(PIVCard::cardAuthenticationKeyRef());
......@@ -102,6 +104,7 @@ PIVCardWidget::PIVCardWidget(QWidget *parent):
grid->addWidget(mCardAuthenticationKey.keyAlgorithm, row, 2);
grid->addWidget(mCardAuthenticationKey.generateButton, row, 3);
grid->addWidget(mCardAuthenticationKey.writeCertificateButton, row, 4);
grid->addWidget(mCardAuthenticationKey.importCertificateButton, row, 5);
row++;
mDigitalSignatureKey = createKeyWidgets(PIVCard::digitalSignatureKeyRef());
......@@ -110,6 +113,7 @@ PIVCardWidget::PIVCardWidget(QWidget *parent):
grid->addWidget(mDigitalSignatureKey.keyAlgorithm, row, 2);
grid->addWidget(mDigitalSignatureKey.generateButton, row, 3);
grid->addWidget(mDigitalSignatureKey.writeCertificateButton, row, 4);
grid->addWidget(mDigitalSignatureKey.importCertificateButton, row, 5);
row++;
mKeyManagementKey = createKeyWidgets(PIVCard::keyManagementKeyRef());
......@@ -118,12 +122,13 @@ PIVCardWidget::PIVCardWidget(QWidget *parent):
grid->addWidget(mKeyManagementKey.keyAlgorithm, row, 2);
grid->addWidget(mKeyManagementKey.generateButton, row, 3);
grid->addWidget(mKeyManagementKey.writeCertificateButton, row, 4);
grid->addWidget(mKeyManagementKey.writeKeyButton, row, 5);
grid->addWidget(mKeyManagementKey.importCertificateButton, row, 5);
grid->addWidget(mKeyManagementKey.writeKeyButton, row, 6);
row++;
auto line2 = new QFrame();
line2->setFrameShape(QFrame::HLine);
grid->addWidget(line2, row++, 0, 1, 6);
grid->addWidget(line2, row++, 0, 1, 7);
auto actionLayout = new QHBoxLayout;
......@@ -150,7 +155,7 @@ PIVCardWidget::PIVCardWidget(QWidget *parent):
}
actionLayout->addStretch(-1);
grid->addLayout(actionLayout, row++, 0, 1, 6);
grid->addLayout(actionLayout, row++, 0, 1, 7);
grid->setColumnStretch(4, -1);
}
......@@ -163,16 +168,24 @@ PIVCardWidget::KeyWidgets PIVCardWidget::createKeyWidgets(const std::string &key
keyWidgets.keyAlgorithm = new QLabel(this);
keyWidgets.generateButton = new QPushButton(i18nc("@action:button", "Generate"), this);
keyWidgets.generateButton->setEnabled(false);
connect(keyWidgets.generateButton, &QPushButton::clicked, this, [this, keyRef] () { generateKey(keyRef); });
connect(keyWidgets.generateButton, &QPushButton::clicked,
this, [this, keyRef] () { generateKey(keyRef); });
keyWidgets.writeCertificateButton = new QPushButton(i18nc("@action:button", "Write Certificate"));
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); });
connect(keyWidgets.writeCertificateButton, &QPushButton::clicked,
this, [this, keyRef] () { writeCertificateToCard(keyRef); });
keyWidgets.importCertificateButton = new QPushButton(i18nc("@action:button", "Import Certificate"));
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::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); });
connect(keyWidgets.writeKeyButton, &QPushButton::clicked,
this, [this, keyRef] () { writeKeyToCard(keyRef); });
}
return keyWidgets;
}
......@@ -217,6 +230,7 @@ void PIVCardWidget::updateKey(const std::string &keyRef, const PIVCard *card, co
i18nc("@info:tooltip %1 display name of a key", "Replace %1 with new key", PIVCard::keyDisplayName(keyRef)));
}
widgets.generateButton->setEnabled(true);
widgets.importCertificateButton->setEnabled(!grip.empty() && !card->certificateData(keyRef).empty());
if (widgets.writeCertificateButton) {
widgets.writeCertificateButton->setEnabled(!grip.empty());
}
......@@ -246,6 +260,19 @@ void PIVCardWidget::writeCertificateToCard(const std::string &keyref)
cmd->start();
}
void PIVCardWidget::importCertificateFromCard(const std::string &keyref)
{
auto cmd = new ImportCertificateFromPIVCardCommand(keyref, mCardSerialNumber);
this->setEnabled(false);
connect(cmd, &ImportCertificateFromPIVCardCommand::finished,
this, [this]() {
ReaderStatus::mutableInstance()->updateStatus();
this->setEnabled(true);
});
cmd->setParentWidget(this);
cmd->start();
}
void PIVCardWidget::writeKeyToCard(const std::string &keyref)
{
auto cmd = new KeyToCardCommand(keyref, mCardSerialNumber);
......
......@@ -39,6 +39,7 @@ private:
QLabel *keyAlgorithm = nullptr;
QPushButton *generateButton = nullptr;
QPushButton *writeCertificateButton = nullptr;
QPushButton *importCertificateButton = nullptr;
QPushButton *writeKeyButton = nullptr;
};
......@@ -46,6 +47,7 @@ private:
void updateKey(const std::string &keyRef, const SmartCard::PIVCard *card, const KeyWidgets &widgets);
void generateKey(const std::string &keyref);
void writeCertificateToCard(const std::string &keyref);
void importCertificateFromCard(const std::string &keyref);
void writeKeyToCard(const std::string &keyref);
void changePin(const std::string &keyRef);
void setAdminKey();
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment