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

Allow users to change the administration key of a PIV card

GnuPG-bug-id: 4794
parent 662d68fa
Pipeline #32025 passed with stage
in 12 minutes and 36 seconds
......@@ -231,6 +231,7 @@ set(_kleopatra_SRCS
commands/pivgeneratecardkeycommand.cpp
commands/changepincommand.cpp
commands/authenticatepivcardapplicationcommand.cpp
commands/setpivcardapplicationadministrationkeycommand.cpp
${_kleopatra_uiserver_files}
......
......@@ -51,6 +51,7 @@ private:
void ensureDialogCreated();
private:
QString prompt;
QPointer<PIVCardApplicationAdministrationKeyInputDialog> dialog;
};
......@@ -92,6 +93,11 @@ AuthenticatePIVCardApplicationCommand::~AuthenticatePIVCardApplicationCommand()
qCDebug(KLEOPATRA_LOG) << "AuthenticatePIVCardApplicationCommand::~AuthenticatePIVCardApplicationCommand()";
}
void AuthenticatePIVCardApplicationCommand::setPrompt(const QString& prompt)
{
d->prompt = prompt;
}
void AuthenticatePIVCardApplicationCommand::doStart()
{
qCDebug(KLEOPATRA_LOG) << "AuthenticatePIVCardApplicationCommand::doStart()";
......@@ -143,7 +149,9 @@ void AuthenticatePIVCardApplicationCommand::Private::ensureDialogCreated()
dialog = new PIVCardApplicationAdministrationKeyInputDialog(parentWidget());
dialog->setAttribute(Qt::WA_DeleteOnClose);
dialog->setLabelText(i18n("Please enter the PIV Card Application Administration Key in hex-encoded form."));
dialog->setLabelText(prompt.isEmpty() ?
i18n("Please enter the PIV Card Application Administration Key in hex-encoded form.") :
prompt);
connect(dialog, SIGNAL(accepted()), q, SLOT(slotDialogAccepted()));
connect(dialog, SIGNAL(rejected()), q, SLOT(slotDialogRejected()));
......
......@@ -28,6 +28,8 @@ public:
explicit AuthenticatePIVCardApplicationCommand(const std::string &serialNumber, QWidget *parent);
~AuthenticatePIVCardApplicationCommand() override;
void setPrompt(const QString& prompt);
private:
void doStart() override;
......
/* commands/setpivcardapplicationadministrationkeycommand.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 "setpivcardapplicationadministrationkeycommand.h"
#include "cardcommand_p.h"
#include "smartcard/readerstatus.h"
#include "commands/authenticatepivcardapplicationcommand.h"
#include "dialogs/pivcardapplicationadministrationkeyinputdialog.h"
#include <KLocalizedString>
#include <gpgme++/error.h>
#include "kleopatra_debug.h"
using namespace Kleo;
using namespace Kleo::Commands;
using namespace Kleo::Dialogs;
using namespace Kleo::SmartCard;
using namespace GpgME;
class SetPIVCardApplicationAdministrationKeyCommand::Private : public CardCommand::Private
{
friend class ::Kleo::Commands::SetPIVCardApplicationAdministrationKeyCommand;
SetPIVCardApplicationAdministrationKeyCommand *q_func() const
{
return static_cast<SetPIVCardApplicationAdministrationKeyCommand *>(q);
}
public:
explicit Private(SetPIVCardApplicationAdministrationKeyCommand *qq, const std::string &serialNumber, QWidget *p);
~Private();
void init();
private:
void slotDialogAccepted();
void slotDialogRejected();
void slotResult(const Error &err);
private:
void authenticate();
void authenticationFinished();
void authenticationCanceled();
void setAdminKey();
void ensureDialogCreated();
private:
QByteArray newAdminKey;
QPointer<PIVCardApplicationAdministrationKeyInputDialog> dialog;
bool hasBeenCanceled = false;
};
SetPIVCardApplicationAdministrationKeyCommand::Private *SetPIVCardApplicationAdministrationKeyCommand::d_func()
{
return static_cast<Private *>(d.get());
}
const SetPIVCardApplicationAdministrationKeyCommand::Private *SetPIVCardApplicationAdministrationKeyCommand::d_func() const
{
return static_cast<const Private *>(d.get());
}
#define d d_func()
#define q q_func()
SetPIVCardApplicationAdministrationKeyCommand::Private::Private(SetPIVCardApplicationAdministrationKeyCommand *qq, const std::string &serialNumber, QWidget *p)
: CardCommand::Private(qq, serialNumber, p)
, dialog()
{
}
SetPIVCardApplicationAdministrationKeyCommand::Private::~Private()
{
qCDebug(KLEOPATRA_LOG) << "SetPIVCardApplicationAdministrationKeyCommand::Private::~Private()";
}
SetPIVCardApplicationAdministrationKeyCommand::SetPIVCardApplicationAdministrationKeyCommand(const std::string &serialNumber, QWidget *p)
: CardCommand(new Private(this, serialNumber, p))
{
d->init();
}
void SetPIVCardApplicationAdministrationKeyCommand::Private::init()
{
}
SetPIVCardApplicationAdministrationKeyCommand::~SetPIVCardApplicationAdministrationKeyCommand()
{
qCDebug(KLEOPATRA_LOG) << "SetPIVCardApplicationAdministrationKeyCommand::~SetPIVCardApplicationAdministrationKeyCommand()";
}
void SetPIVCardApplicationAdministrationKeyCommand::doStart()
{
qCDebug(KLEOPATRA_LOG) << "SetPIVCardApplicationAdministrationKeyCommand::doStart()";
d->authenticate();
}
void SetPIVCardApplicationAdministrationKeyCommand::Private::authenticate()
{
qCDebug(KLEOPATRA_LOG) << "SetPIVCardApplicationAdministrationKeyCommand::authenticate()";
auto cmd = new AuthenticatePIVCardApplicationCommand(serialNumber(), parentWidget());
cmd->setPrompt(i18n("Please enter the old PIV Card Application Administration Key in hex-encoded form."));
connect(cmd, &AuthenticatePIVCardApplicationCommand::finished,
q, [this]() { authenticationFinished(); });
connect(cmd, &AuthenticatePIVCardApplicationCommand::canceled,
q, [this]() { authenticationCanceled(); });
cmd->start();
}
void SetPIVCardApplicationAdministrationKeyCommand::Private::authenticationFinished()
{
qCDebug(KLEOPATRA_LOG) << "SetPIVCardApplicationAdministrationKeyCommand::authenticationFinished()";
if (!hasBeenCanceled) {
setAdminKey();
}
}
void SetPIVCardApplicationAdministrationKeyCommand::Private::authenticationCanceled()
{
qCDebug(KLEOPATRA_LOG) << "SetPIVCardApplicationAdministrationKeyCommand::authenticationCanceled()";
hasBeenCanceled = true;
canceled();
}
void SetPIVCardApplicationAdministrationKeyCommand::Private::setAdminKey()
{
qCDebug(KLEOPATRA_LOG) << "SetPIVCardApplicationAdministrationKeyCommand::setAdminKey()";
ensureDialogCreated();
Q_ASSERT(dialog);
dialog->show();
}
void SetPIVCardApplicationAdministrationKeyCommand::Private::ensureDialogCreated()
{
if (dialog) {
return;
}
dialog = new PIVCardApplicationAdministrationKeyInputDialog(parentWidget());
dialog->setAttribute(Qt::WA_DeleteOnClose);
dialog->setLabelText(newAdminKey.isEmpty() ?
i18n("Please enter the new PIV Card Application Administration Key in hex-encoded form. "
"The key needs to consist of 24 bytes, i.e. 48 hex-characters.") :
i18n("Please enter the new PIV Card Application Administration Key again."));
connect(dialog, SIGNAL(accepted()), q, SLOT(slotDialogAccepted()));
connect(dialog, SIGNAL(rejected()), q, SLOT(slotDialogRejected()));
}
void SetPIVCardApplicationAdministrationKeyCommand::Private::slotDialogAccepted()
{
if (newAdminKey.isEmpty()) {
newAdminKey = dialog->adminKey();
dialog = nullptr;
setAdminKey();
return;
}
const QByteArray newAdminKey2 = dialog->adminKey();
if (newAdminKey != newAdminKey2) {
error(i18nc("@info", "The two keys you have entered do not match. Please retry."),
i18nc("@title", "Error"));
newAdminKey.clear();
dialog = nullptr;
setAdminKey();
return;
}
const QByteArray plusPercentEncodedAdminKey = newAdminKey.toPercentEncoding().replace(' ', '+');
const QByteArray command = QByteArray("SCD SETATTR SET-ADM-KEY ") + plusPercentEncodedAdminKey;
ReaderStatus::mutableInstance()->startSimpleTransaction(command, q, "slotResult");
}
void SetPIVCardApplicationAdministrationKeyCommand::Private::slotDialogRejected()
{
finished();
}
void SetPIVCardApplicationAdministrationKeyCommand::Private::slotResult(const GpgME::Error& err)
{
qCDebug(KLEOPATRA_LOG) << "SetPIVCardApplicationAdministrationKeyCommand::slotResult():"
<< err.asString() << "(" << err.code() << ")";
if (err) {
error(i18nc("@info", "Setting the PIV Card Application Administration Key failed: %1", QString::fromLatin1(err.asString())),
i18nc("@title", "Error"));
} else if (!err.isCanceled()) {
information(i18nc("@info", "PIV Card Application Administration Key set successfully."), i18nc("@title", "Success"));
ReaderStatus::mutableInstance()->updateStatus();
}
finished();
}
#undef d
#undef q
#include "moc_setpivcardapplicationadministrationkeycommand.cpp"
/* commands/setpivcardapplicationadministrationkeycommand.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_COMMMANDS_SETPIVCARDAPPLICATIONADMINISTRATIONKEYCOMMAND_H__
#define __KLEOPATRA_COMMMANDS_SETPIVCARDAPPLICATIONADMINISTRATIONKEYCOMMAND_H__
#include "cardcommand.h"
namespace GpgME
{
class Error;
}
namespace Kleo
{
namespace Commands
{
class SetPIVCardApplicationAdministrationKeyCommand : public CardCommand
{
Q_OBJECT
public:
explicit SetPIVCardApplicationAdministrationKeyCommand(const std::string &serialNumber, QWidget *parent);
~SetPIVCardApplicationAdministrationKeyCommand() override;
private:
void doStart() override;
private:
class Private;
inline Private *d_func();
inline const Private *d_func() const;
Q_PRIVATE_SLOT(d_func(), void slotDialogAccepted())
Q_PRIVATE_SLOT(d_func(), void slotDialogRejected())
Q_PRIVATE_SLOT(d_func(), void slotResult(GpgME::Error))
};
} // namespace Commands
} // namespace Kleo
#endif // __KLEOPATRA_COMMMANDS_SETPIVCARDAPPLICATIONADMINISTRATIONKEYCOMMAND_H__
......@@ -11,6 +11,7 @@
#include "commands/changepincommand.h"
#include "commands/pivgeneratecardkeycommand.h"
#include "commands/setpivcardapplicationadministrationkeycommand.h"
#include "smartcard/pivcard.h"
#include "smartcard/readerstatus.h"
......@@ -147,15 +148,26 @@ PIVCardWidget::PIVCardWidget(QWidget *parent):
auto actionLayout = new QHBoxLayout;
auto pinButton = new QPushButton(i18n("Change PIN"));
pinButton->setToolTip(i18n("Change the PIV Card Application PIN that activates the PIV Card and enables private key operations using the stored keys."));
actionLayout->addWidget(pinButton);
connect(pinButton, &QPushButton::clicked, this, [this] () { changePin(PIVCard::pinKeyRef()); });
auto pukButton = new QPushButton(i18n("Change PUK"));
pukButton->setToolTip(i18n("Change the PIN Unblocking Key that enables a reset of the PIN."));
actionLayout->addWidget(pukButton);
connect(pukButton, &QPushButton::clicked, this, [this] () { changePin(PIVCard::pukKeyRef()); });
{
auto button = new QPushButton(i18n("Change PIN"));
button->setToolTip(i18n("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(i18n("Change PUK"));
button->setToolTip(i18n("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(i18n("Change Admin Key"));
button->setToolTip(i18n("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);
grid->addLayout(actionLayout, row++, 0, 1, 4);
......@@ -239,3 +251,14 @@ void PIVCardWidget::changePin(const std::string &keyRef)
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();
}
......@@ -37,6 +37,7 @@ private:
void updateKey(const std::string &keyRef, const SmartCard::PIVCard *card, QLabel *label, QPushButton *button);
void generateKey(const std::string &keyref);
void changePin(const std::string &keyRef);
void setAdminKey();
private Q_SLOTS:
void generatePIVAuthenticationKey();
......
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