Skip to content

Commit

Permalink
Resolved/removed fixme-s in code
Browse files Browse the repository at this point in the history
Signed-off-by: Lauris Kaplinski <[email protected]>
  • Loading branch information
Lauris Kaplinski committed Jul 30, 2024
1 parent 7e462b4 commit 2a62ccd
Show file tree
Hide file tree
Showing 8 changed files with 61 additions and 33 deletions.
13 changes: 7 additions & 6 deletions src/controller/command-handlers/authenticate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
#include <QJsonDocument>
#include <QCryptographicHash>
#include <QDir>
#include <QScopeGuard>

#include <map>

Expand Down Expand Up @@ -122,17 +123,17 @@ QVariantMap Authenticate::onConfirm(WebEidUI* window,
const auto signatureAlgorithm =
QString::fromStdString(cardCertAndPin.cardInfo->eid().authSignatureAlgorithm());

auto pin = getPin(cardCertAndPin.cardInfo->eid(), window);
pcsc_cpp::byte_vector pin;
getPin(pin, cardCertAndPin.cardInfo->eid().smartcard(), window);
auto pin_cleanup = qScopeGuard([&pin] {
// Erase PIN memory.
std::fill(pin.begin(), pin.end(), '\0');
});

try {
const auto signature =
createSignature(origin.url(), challengeNonce, cardCertAndPin.cardInfo->eid(), pin);

// Erase the PIN memory.
// TODO: Use a scope guard. Verify that the buffers are actually zeroed and no copies
// remain.
std::fill(pin.begin(), pin.end(), '\0');

return createAuthenticationToken(signatureAlgorithm, cardCertAndPin.certificateBytesInDer,
signature);

Expand Down
14 changes: 8 additions & 6 deletions src/controller/command-handlers/sign.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
#include "signauthutils.hpp"
#include "utils/utils.hpp"

#include <QScopeGuard>

using namespace electronic_id;

namespace
Expand Down Expand Up @@ -95,16 +97,16 @@ void Sign::emitCertificatesReady(const std::vector<CardCertificateAndPinInfo>& c

QVariantMap Sign::onConfirm(WebEidUI* window, const CardCertificateAndPinInfo& cardCertAndPin)
{
auto pin = getPin(cardCertAndPin.cardInfo->eid(), window);
pcsc_cpp::byte_vector pin;
getPin(pin, cardCertAndPin.cardInfo->eid().smartcard(), window);
auto pin_cleanup = qScopeGuard([&pin] {
// Erase PIN memory.
std::fill(pin.begin(), pin.end(), '\0');
});

try {
const auto signature = signHash(cardCertAndPin.cardInfo->eid(), pin, docHash, hashAlgo);

// Erase PIN memory.
// TODO: Use a scope guard. Verify that the buffers are actually zeroed
// and no copies remain.
std::fill(pin.begin(), pin.end(), '\0');

return {{QStringLiteral("signature"), signature.first},
{QStringLiteral("signatureAlgorithm"), signature.second}};

Expand Down
26 changes: 12 additions & 14 deletions src/controller/command-handlers/signauthutils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@

#include "ui.hpp"
#include "commandhandler.hpp"
#include "utils/utils.hpp"

using namespace electronic_id;

Expand Down Expand Up @@ -78,29 +77,28 @@ inline void eraseData(T& data)
}
}

pcsc_cpp::byte_vector getPin(const ElectronicID& card, WebEidUI* window)
int getPin(pcsc_cpp::byte_vector& pin, const pcsc_cpp::SmartCard& card, WebEidUI* window)
{
// Doesn't apply to PIN pads.
if (card.smartcard().readerHasPinPad() || card.providesExternalPinDialog()) {
return {};
if (card.readerHasPinPad()) {
return 0;
}

REQUIRE_NON_NULL(window)

auto pin = window->getPin();
if (pin.isEmpty()) {
QString pinqs = window->getPin();
if (pinqs.isEmpty()) {
THROW(ProgrammingError, "Empty PIN");
}
int len = (int)pinqs.length();

// TODO: Avoid making copies of the PIN in memory.
auto pinQByteArray = pin.toUtf8();
pcsc_cpp::byte_vector pinBytes {pinQByteArray.begin(), pinQByteArray.end()};

// TODO: Verify that the buffers are actually zeroed and no copies remain.
eraseData<QString, QChar>(pin);
eraseData<QByteArray, char>(pinQByteArray);
pin.resize(len);
for (int i = 0; i < len; i++) {
pin[i] = pinqs[i].cell();
}
eraseData<QString, QChar>(pinqs);

return pinBytes;
return len;
}

QVariantMap signatureAlgoToVariantMap(const SignatureAlgorithm signatureAlgo)
Expand Down
2 changes: 1 addition & 1 deletion src/controller/command-handlers/signauthutils.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,6 @@ extern template QString validateAndGetArgument<QString>(const QString& argName,
extern template QByteArray
validateAndGetArgument<QByteArray>(const QString& argName, const QVariantMap& args, bool allowNull);

pcsc_cpp::byte_vector getPin(const electronic_id::ElectronicID& card, WebEidUI* window);
int getPin(pcsc_cpp::byte_vector& pin, const pcsc_cpp::SmartCard& card, WebEidUI* window);

QVariantMap signatureAlgoToVariantMap(const electronic_id::SignatureAlgorithm signatureAlgo);
9 changes: 9 additions & 0 deletions src/controller/controller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,15 @@ void Controller::run()

startCommandExecution();

} catch (const std::invalid_argument& exc) {
if (isInStdinMode) {
// Pass invalid argument message to the caller just in case it may be interested
// The result will be {"invalid-argument" : message}
// Command parameter is only used if exception will be raised during json creation
writeResponseToStdOut(isInStdinMode, {{QStringLiteral("invalid-argument"), exc.what()}},
"invalid-argument");
}
onCriticalFailure(exc.what());
} catch (const std::exception& error) {
onCriticalFailure(error.what());
}
Expand Down
3 changes: 0 additions & 3 deletions src/controller/inputoutputmode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,6 @@ CommandWithArgumentsPtr readCommandFromStdin()
const auto messageLength = readMessageLength(std::cin);

if (messageLength < 5) {
// FIXME: Pass errors back up to caller in stdin mode.
throw std::invalid_argument("readCommandFromStdin: Message length is "
+ std::to_string(messageLength) + ", at least 5 required");
}
Expand All @@ -88,7 +87,6 @@ CommandWithArgumentsPtr readCommandFromStdin()
const auto json = QJsonDocument::fromJson(message);

if (!json.isObject()) {
// FIXME: Pass errors back up to caller in stdin mode.
throw std::invalid_argument("readCommandFromStdin: Invalid JSON, not an object");
}

Expand All @@ -97,7 +95,6 @@ CommandWithArgumentsPtr readCommandFromStdin()
const auto arguments = jsonObject["arguments"];

if (!command.isString() || !arguments.isObject()) {
// FIXME: Pass errors back up to caller in stdin mode.
throw std::invalid_argument("readCommandFromStdin: Invalid JSON, the main object does not "
"contain a 'command' string and 'arguments' object");
}
Expand Down
26 changes: 23 additions & 3 deletions src/ui/webeiddialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,10 @@ QString WebEidDialog::getPin()
{
// getPin() is called from background threads and must be thread-safe.
// QString uses QAtomicPointer internally and is thread-safe.
return pin;
// There should be only single reference and this is transferred to the caller for safety
QString ret = pin;
pin.clear();
return ret;
}

void WebEidDialog::onSmartCardStatusUpdate(const RetriableError status)
Expand Down Expand Up @@ -332,7 +335,8 @@ void WebEidDialog::onMultipleCertificatesReady(
ui->selectAnotherCertificate->setVisible(certificateAndPinInfos.size() > 1);
connect(ui->selectAnotherCertificate, &QPushButton::clicked, this,
[this, origin, certificateAndPinInfos] {
ui->pinInput->clear();
// We set pinInput to empty text instead of clear() to also reset undo buffer
ui->pinInput->setText({});
onMultipleCertificatesReady(origin, certificateAndPinInfos);
});
setupOK([this, origin] {
Expand Down Expand Up @@ -443,7 +447,6 @@ void WebEidDialog::onVerifyPinFailed(const VerifyPinFailed::Status status, const

std::function<QString()> message;

// FIXME: don't allow retry in case of UNKNOWN_ERROR
switch (status) {
case Status::RETRY_ALLOWED:
message = [retriesLeft]() -> QString {
Expand All @@ -465,8 +468,11 @@ void WebEidDialog::onVerifyPinFailed(const VerifyPinFailed::Status status, const
message = [] { return tr("PIN entry cancelled."); };
break;
case Status::PIN_ENTRY_DISABLED:
message = [] { return tr("PIN entry disabled"); };
break;
case Status::UNKNOWN_ERROR:
message = [] { return tr("Technical error"); };
displayFatalError(message);
break;
}

Expand Down Expand Up @@ -678,6 +684,20 @@ void WebEidDialog::displayPinBlockedError()
ui->helpButton->show();
}

void WebEidDialog::displayFatalError(std::function<QString()> message)
{
ui->pinTitleLabel->hide();
ui->pinInput->hide();
ui->pinTimeoutTimer->stop();
ui->pinTimeRemaining->hide();
ui->pinEntryTimeoutProgressBar->hide();
setTrText(ui->pinErrorLabel, message);
ui->pinErrorLabel->show();
ui->okButton->hide();
ui->cancelButton->setEnabled(true);
ui->cancelButton->show();
}

void WebEidDialog::showPinInputWarning(bool show)
{
style()->unpolish(ui->pinInput);
Expand Down
1 change: 1 addition & 0 deletions src/ui/webeiddialog.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ class WebEidDialog final : public WebEidUI
template <typename Func>
void setupOK(Func func, const char* text = {}, bool enabled = false);
void displayPinBlockedError();
void displayFatalError(std::function<QString()> message);

void showPinInputWarning(bool show);

Expand Down

0 comments on commit 2a62ccd

Please sign in to comment.