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

Allow creating an OpenPGP key for the keys on a PIV card

GnuPG-bug-id: 5126
parent 152ff283
Pipeline #41324 failed with stage
in 10 minutes and 38 seconds
......@@ -15,7 +15,7 @@ option(DISABLE_KWATCHGNUPG "Don't build the kwatchgnupg tool [default=OFF]" OFF)
# Standalone build. Find / include everything necessary.
set(KF5_MIN_VERSION "5.76.0")
set(KMIME_VERSION "5.15.80")
set(LIBKLEO_VERSION "5.15.82")
set(LIBKLEO_VERSION "5.16.41")
set(QT_REQUIRED_VERSION "5.13.0")
set(GPGME_REQUIRED_VERSION "1.11.1")
......
......@@ -17,6 +17,7 @@
#include "dialogs/adduseriddialog.h"
#include "smartcard/openpgpcard.h"
#include "smartcard/pivcard.h"
#include "smartcard/readerstatus.h"
#include <Libkleo/Formatting>
......@@ -90,14 +91,26 @@ CreateOpenPGPKeyFromCardKeysCommand::Private::~Private()
void CreateOpenPGPKeyFromCardKeysCommand::Private::start()
{
const auto pgpCard = ReaderStatus::instance()->getCard<OpenPGPCard>(serialNumber());
if (!pgpCard) {
error(i18n("Failed to find the OpenPGP card with the serial number: %1", QString::fromStdString(serialNumber())));
const auto card = ReaderStatus::instance()->getCard(serialNumber(), appName);
if (!card) {
error(i18n("Failed to find the smartcard with the serial number: %1", QString::fromStdString(serialNumber())));
finished();
return;
}
Key signingKey;
if (card->appName() == OpenPGPCard::AppName) {
const auto pgpCard = std::dynamic_pointer_cast<OpenPGPCard>(card);
signingKey = KeyCache::instance()->findByKeyIDOrFingerprint(pgpCard->sigFpr());
} else if (appName == PIVCard::AppName) {
const auto pivCard = std::dynamic_pointer_cast<PIVCard>(card);
signingKey = KeyCache::instance()->findSubkeyByKeyGrip(pivCard->keyGrip(PIVCard::digitalSignatureKeyRef()), OpenPGP).parent();
} else {
qCWarning(KLEOPATRA_LOG) << "CreateOpenPGPKeyFromCardKeysCommand does not support card application" << QString::fromStdString(appName);
finished();
return;
}
const auto signingKey = KeyCache::instance()->findByKeyIDOrFingerprint(pgpCard->sigFpr());
if (!signingKey.isNull()) {
const QString message = i18nc("@info",
"<p>There is already an OpenPGP key corresponding to the signing key on this card:</p><p>%1</p>"
......@@ -115,7 +128,7 @@ void CreateOpenPGPKeyFromCardKeysCommand::Private::start()
ensureDialogCreated();
dialog->setWindowTitle(i18n("Enter User ID"));
dialog->setName(pgpCard->cardHolder());
dialog->setName(card->cardHolder());
dialog->show();
}
......
......@@ -203,7 +203,7 @@ PGPCardWidget::PGPCardWidget(QWidget *parent):
actionLayout->addWidget(resetCodeButton);
connect(resetCodeButton, &QPushButton::clicked, this, [this] () { doChangePin(OpenPGPCard::resetCodeKeyRef()); });
mKeyForCardKeysButton->setText(i18n("Create Key for Card Keys"));
mKeyForCardKeysButton->setText(i18n("Create OpenPGP Key"));
mKeyForCardKeysButton->setToolTip(i18n("Create an OpenPGP key for the keys stored on the card."));
actionLayout->addWidget(mKeyForCardKeysButton);
connect(mKeyForCardKeysButton, &QPushButton::clicked, this, &PGPCardWidget::createKeyFromCardKeys);
......
......@@ -13,6 +13,7 @@
#include "commands/certificatetopivcardcommand.h"
#include "commands/changepincommand.h"
#include "commands/createopenpgpkeyfromcardkeyscommand.h"
#include "commands/importcertificatefrompivcardcommand.h"
#include "commands/keytocardcommand.h"
#include "commands/pivgeneratecardkeycommand.h"
......@@ -74,10 +75,11 @@ static int toolTipOptions()
}
}
PIVCardWidget::PIVCardWidget(QWidget *parent):
QWidget(parent),
mSerialNumber(new QLabel(this)),
mVersionLabel(new QLabel(this))
PIVCardWidget::PIVCardWidget(QWidget *parent)
: QWidget(parent)
, mSerialNumber(new QLabel(this))
, mVersionLabel(new QLabel(this))
, mKeyForCardKeysButton(new QPushButton(this))
{
// Set up the scroll area
auto myLayout = new QVBoxLayout(this);
......@@ -143,6 +145,11 @@ PIVCardWidget::PIVCardWidget(QWidget *parent):
auto actionLayout = new QHBoxLayout;
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"));
button->setToolTip(i18nc("@info:tooltip", "Change the PIV Card Application PIN that activates the PIV Card "
......@@ -221,6 +228,10 @@ void PIVCardWidget::setCard(const PIVCard *card)
updateKeyWidgets(PIVCard::cardAuthenticationKeyRef(), card);
updateKeyWidgets(PIVCard::digitalSignatureKeyRef(), card);
updateKeyWidgets(PIVCard::keyManagementKeyRef(), card);
const bool signingKeyAvailable = !card->keyGrip(PIVCard::digitalSignatureKeyRef()).empty();
const bool encryptionKeyAvailable = !card->keyGrip(PIVCard::keyManagementKeyRef()).empty();
mKeyForCardKeysButton->setEnabled(signingKeyAvailable && encryptionKeyAvailable);
}
void PIVCardWidget::updateKeyWidgets(const std::string &keyRef, const PIVCard *card)
......@@ -238,8 +249,8 @@ void PIVCardWidget::updateKeyWidgets(const std::string &keyRef, const PIVCard *c
widgets.writeCertificateButton->setEnabled(false);
widgets.importCertificateButton->setEnabled(false);
} else {
const Key certificate = KeyCache::instance()->findSubkeyByKeyGrip(grip).parent();
if (!certificate.isNull() && certificate.protocol() == GpgME::CMS) {
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(),
......@@ -316,6 +327,17 @@ void PIVCardWidget::writeKeyToCard(const std::string &keyref)
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);
......
......@@ -52,6 +52,7 @@ private:
void writeCertificateToCard(const std::string &keyref);
void importCertificateFromCard(const std::string &keyref);
void writeKeyToCard(const std::string &keyref);
void createKeyFromCardKeys();
void changePin(const std::string &keyRef);
void setAdminKey();
......@@ -59,6 +60,7 @@ private:
std::string mCardSerialNumber;
QLabel *mSerialNumber = nullptr;
QLabel *mVersionLabel = nullptr;
QPushButton *mKeyForCardKeysButton = nullptr;
QMap<std::string, KeyWidgets> mKeyWidgets;
};
} // namespace Kleo
......
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