Commit 49af5da5 authored by Ingo Klöcker's avatar Ingo Klöcker

Allow users to change PIN and PUK of a PIV card

GnuPG-bug-id: 4794
parent 48b58502
......@@ -228,6 +228,7 @@ set(_kleopatra_SRCS
commands/keytocardcommand.cpp
commands/cardcommand.cpp
commands/pivgeneratecardkeycommand.cpp
commands/changepincommand.cpp
${_kleopatra_uiserver_files}
......
/* commands/changepincommand.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 "changepincommand.h"
#include "cardcommand_p.h"
#include "smartcard/pivcard.h"
#include "smartcard/readerstatus.h"
#include <KLocalizedString>
#include <gpgme++/error.h>
#include "kleopatra_debug.h"
using namespace Kleo;
using namespace Kleo::Commands;
using namespace Kleo::SmartCard;
using namespace GpgME;
class ChangePinCommand::Private : public CardCommand::Private
{
friend class ::Kleo::Commands::ChangePinCommand;
ChangePinCommand *q_func() const
{
return static_cast<ChangePinCommand *>(q);
}
public:
explicit Private(ChangePinCommand *qq, const std::string &serialNumber, QWidget *p);
~Private();
void init();
private:
void slotResult(const Error &err);
private:
void changePin();
private:
std::string keyRef;
};
ChangePinCommand::Private *ChangePinCommand::d_func()
{
return static_cast<Private *>(d.get());
}
const ChangePinCommand::Private *ChangePinCommand::d_func() const
{
return static_cast<const Private *>(d.get());
}
#define d d_func()
#define q q_func()
ChangePinCommand::Private::Private(ChangePinCommand *qq, const std::string &serialNumber, QWidget *p)
: CardCommand::Private(qq, serialNumber, p)
{
}
ChangePinCommand::Private::~Private()
{
qCDebug(KLEOPATRA_LOG) << "ChangePinCommand::Private::~Private()";
}
ChangePinCommand::ChangePinCommand(const std::string &serialNumber, QWidget *p)
: CardCommand(new Private(this, serialNumber, p))
{
d->init();
}
void ChangePinCommand::Private::init()
{
}
ChangePinCommand::~ChangePinCommand()
{
qCDebug(KLEOPATRA_LOG) << "ChangePinCommand::~ChangePinCommand()";
}
void ChangePinCommand::setKeyRef(const std::string &keyRef)
{
d->keyRef = keyRef;
}
void ChangePinCommand::doStart()
{
qCDebug(KLEOPATRA_LOG) << "ChangePinCommand::doStart()";
d->changePin();
}
void ChangePinCommand::Private::changePin()
{
qCDebug(KLEOPATRA_LOG) << "ChangePinCommand::changePin()";
QByteArrayList command;
command << "SCD PASSWD";
command << QByteArray::fromStdString(keyRef);
ReaderStatus::mutableInstance()->startSimpleTransaction(command.join(' '), q, "slotResult");
}
namespace {
static QString errorMessage(const std::string &keyRef, const QString &errorText)
{
// see cmd_passwd() in gpg-card.c
if (keyRef == PIVCard::pukKeyRef()) {
return i18nc("@info", "Changing the PUK failed: %1", errorText);
}
return i18nc("@info", "Changing the PIN failed: %1", errorText);
}
static QString successMessage(const std::string &keyRef)
{
// see cmd_passwd() in gpg-card.c
if (keyRef == PIVCard::pukKeyRef()) {
return i18nc("@info", "PUK successfully changed.");
}
return i18nc("@info", "PIN changed successfully.");
}
}
void ChangePinCommand::Private::slotResult(const GpgME::Error& err)
{
qCDebug(KLEOPATRA_LOG) << "ChangePinCommand::slotResult():"
<< err.asString() << "(" << err.code() << ")";
if (err) {
error(errorMessage(keyRef, QString::fromLatin1(err.asString())),
i18nc("@title", "Error"));
} else if (!err.isCanceled()) {
information(successMessage(keyRef), i18nc("@title", "Success"));
ReaderStatus::mutableInstance()->updateStatus();
}
finished();
}
#undef d
#undef q
#include "moc_changepincommand.cpp"
/* commands/changepincommand.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_CHANGEPINCOMMAND_H__
#define __KLEOPATRA_COMMMANDS_CHANGEPINCOMMAND_H__
#include "cardcommand.h"
namespace GpgME
{
class Error;
}
namespace Kleo
{
namespace Commands
{
class ChangePinCommand : public CardCommand
{
Q_OBJECT
public:
explicit ChangePinCommand(const std::string &serialNumber, QWidget *parent);
~ChangePinCommand() override;
void setKeyRef(const std::string &keyRef);
private:
void doStart() override;
private:
class Private;
inline Private *d_func();
inline const Private *d_func() const;
Q_PRIVATE_SLOT(d_func(), void slotResult(GpgME::Error))
};
} // namespace Commands
} // namespace Kleo
#endif // __KLEOPATRA_COMMMANDS_CHANGEPINCOMMAND_H__
......@@ -50,6 +50,18 @@ std::string PIVCard::keyManagementKeyRef()
return std::string("PIV.9D");
}
// static
std::string PIVCard::pinKeyRef()
{
return std::string("PIV.80");
}
// static
std::string PIVCard::pukKeyRef()
{
return std::string("PIV.81");
}
// static
std::vector< std::pair<std::string, QString> > PIVCard::supportedAlgorithms(const std::string &keyRef)
{
......
......@@ -29,6 +29,9 @@ public:
static std::string digitalSignatureKeyRef();
static std::string keyManagementKeyRef();
static std::string pinKeyRef();
static std::string pukKeyRef();
static std::vector< std::pair<std::string, QString> > supportedAlgorithms(const std::string &keyRef);
std::string keyGrip(const std::string &keyRef) const;
......
......@@ -9,6 +9,7 @@
#include "pivcardwidget.h"
#include "commands/changepincommand.h"
#include "commands/pivgeneratecardkeycommand.h"
#include "smartcard/pivcard.h"
......@@ -144,6 +145,21 @@ PIVCardWidget::PIVCardWidget(QWidget *parent):
line2->setFrameShape(QFrame::HLine);
grid->addWidget(line2, row++, 0, 1, 4);
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()); });
actionLayout->addStretch(-1);
grid->addLayout(actionLayout, row++, 0, 1, 4);
grid->setColumnStretch(4, -1);
}
......@@ -211,3 +227,15 @@ void PIVCardWidget::generateKeyManagementKey()
{
generateKey(PIVCard::keyManagementKeyRef());
}
void PIVCardWidget::changePin(const std::string &keyRef)
{
auto cmd = new ChangePinCommand(mCardSerialNumber, this);
this->setEnabled(false);
connect(cmd, &ChangePinCommand::finished,
this, [this]() {
this->setEnabled(true);
});
cmd->setKeyRef(keyRef);
cmd->start();
}
......@@ -36,6 +36,7 @@ public:
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);
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