From e116744d1afb929e40001ed8c1e706a13f3bfdad Mon Sep 17 00:00:00 2001 From: Raul Metsma Date: Mon, 13 Jul 2026 14:43:51 +0300 Subject: [PATCH] Harden PIN usage WE2-1249 Signed-off-by: Raul Metsma --- .../command-handlers/signauthutils.cpp | 21 +++++++++++++++++++ src/ui/webeiddialog.cpp | 6 ++++++ 2 files changed, 27 insertions(+) diff --git a/src/controller/command-handlers/signauthutils.cpp b/src/controller/command-handlers/signauthutils.cpp index d1574316..f9bd2416 100644 --- a/src/controller/command-handlers/signauthutils.cpp +++ b/src/controller/command-handlers/signauthutils.cpp @@ -28,6 +28,12 @@ #include "pcsc-cpp/pcsc-cpp-utils.hpp" +#ifdef Q_OS_WIN +#include +#elif defined(Q_OS_UNIX) +#include +#endif + using namespace electronic_id; // Take argument names by copy/move as they will be modified. @@ -84,6 +90,21 @@ pcsc_cpp::byte_vector getPin(const ElectronicID& eid, WebEidUI* window) REQUIRE_NON_NULL(window) + // Lock the reserved buffer's pages in physical memory so the PIN is never written to the + // swap/page file under normal memory pressure. This does NOT protect against suspend-to-disk + // hibernation, which snapshots all of RAM -- including locked pages -- to disk regardless; + // that can only be mitigated at the OS level (e.g. encrypted hibernation image). + // The buffer never grows past the capacity reserved above (enforced by CommandApdu::verify(), + // which throws rather than let the vector holding the PIN reallocate), so the locked address + // range stays valid for the buffer's whole lifetime, including after it is moved into the + // smart card call chain. The process exits shortly after each command, which releases the + // lock, so no matching unlock call is needed. +#ifdef Q_OS_WIN + VirtualLock(pin.data(), pin.capacity()); +#elif defined(Q_OS_UNIX) + mlock(pin.data(), pin.capacity()); +#endif + QString pinQStr = window->getPin(); if (pinQStr.isEmpty()) { THROW(ProgrammingError, "Empty PIN"); diff --git a/src/ui/webeiddialog.cpp b/src/ui/webeiddialog.cpp index 8798eb03..830a0860 100644 --- a/src/ui/webeiddialog.cpp +++ b/src/ui/webeiddialog.cpp @@ -23,6 +23,7 @@ #include "webeiddialog.hpp" #include "application.hpp" #include "languageselect.hpp" +#include "utils/erasedata.hpp" #include "utils/qt_comp.hpp" #include "ui_dialog.h" @@ -178,6 +179,11 @@ WebEidDialog::WebEidDialog(QWidget* parent) : WebEidUI(parent), ui(new Private) WebEidDialog::~WebEidDialog() { + // Zero any PIN left in the cache in case the dialog is destroyed (e.g. cancelled) before + // getPin() was called to consume it. + if (!pin.isEmpty()) { + eraseData(pin); + } delete ui; }