Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 34 additions & 29 deletions client/QPCSC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,22 +63,25 @@ static auto SCCall(const char *file, int line, const char *function, Args&& ...a
}
#define SC(API, ...) SCCall<SCard##API>(__FILE__, __LINE__, "SCard"#API, __VA_ARGS__)

QHash<DRIVER_FEATURES,quint32> QPCSCReader::Private::features()
quint32 QPCSCReader::Private::feature(DRIVER_FEATURES key)
{
if(!featuresList.isEmpty())
return featuresList;
DWORD size = 0;
std::array<PCSC_TLV_STRUCTURE,FEATURE_CCID_ESC_COMMAND> feature{};
if(SC(Control, card, DWORD(CM_IOCTL_GET_FEATURE_REQUEST), nullptr, 0U, feature.data(), DWORD(feature.size() * sizeof(PCSC_TLV_STRUCTURE)), &size))
return featuresList;
if(size % sizeof(PCSC_TLV_STRUCTURE))
return featuresList;
for(const auto &f: feature)
if(features[0].tag == 0)
{
if(DWORD size = 0, capacity = DWORD(features.size() * sizeof(PCSC_TLV_STRUCTURE));
SC(Control, card, DWORD(CM_IOCTL_GET_FEATURE_REQUEST), nullptr, 0U, features.data(), capacity, &size) ||
size > capacity ||
size % sizeof(PCSC_TLV_STRUCTURE) != 0)
{
features.fill(PCSC_TLV_STRUCTURE{});
return 0;
}
}
for(const auto &f: features)
{
if(f.tag)
featuresList[f.tag] = qFromBigEndian<quint32>(f.value);
if(f.tag == key)
return qFromBigEndian<quint32>(f.value);
}
return featuresList;
return 0;
}


Expand Down Expand Up @@ -177,7 +180,6 @@ void QPCSC::run()
Q_EMIT cardChanged();
i->dwCurrentState = i->dwEventState;
qCDebug(SCard) << "New state: " << QString::fromLocal8Bit(i->szReader) << stateToString(i->dwCurrentState);
Q_EMIT statusChanged(QString::fromLocal8Bit(i->szReader), stateToString(i->dwCurrentState));
if((i->dwCurrentState & (SCARD_STATE_UNKNOWN|SCARD_STATE_IGNORE)) > 0)
{
free((void*)i->szReader);
Expand Down Expand Up @@ -245,8 +247,7 @@ bool QPCSCReader::isPinPad() const
return false;
if(qEnvironmentVariableIsSet("SMARTCARDPP_NOPINPAD"))
return false;
QHash<DRIVER_FEATURES,quint32> features = d->features();
return features.contains(FEATURE_VERIFY_PIN_DIRECT) || features.contains(FEATURE_VERIFY_PIN_START);
return d->feature(FEATURE_VERIFY_PIN_DIRECT) || d->feature(FEATURE_VERIFY_PIN_START);
}

bool QPCSCReader::isPresent() const
Expand All @@ -262,18 +263,23 @@ QString QPCSCReader::name() const
QHash<QPCSCReader::Properties, int> QPCSCReader::properties() const
{
QHash<Properties,int> properties;
if( DWORD ioctl = d->features().value(FEATURE_GET_TLV_PROPERTIES) )
if(DWORD ioctl = d->feature(FEATURE_GET_TLV_PROPERTIES))
{
DWORD size = 0;
std::array<BYTE,256> recv{};
if(SC(Control, d->card, ioctl, nullptr, 0U, recv.data(), DWORD(recv.size()), &size))
if(SC(Control, d->card, ioctl, nullptr, 0U, recv.data(), DWORD(recv.size()), &size) || size > recv.size())
return properties;
for(auto p = recv.cbegin(); std::distance(recv.cbegin(), p) < size; )
auto end = std::next(recv.cbegin(), size);
for(auto p = recv.cbegin(); std::distance(p, end) >= 2; )
{
int tag = *p++, len = *p++, value = 0;
for(int i = 0; i < len; ++i)
value |= *p++ << 8 * i;
properties.emplace(Properties(tag), value);
auto tag = Properties(*p++);
size_t len = *p++;
if(len > size_t(std::distance(p, end)) || len > sizeof(quint32))
return properties;
quint32 value = 0;
for(size_t i = 0; i < len; ++i)
value |= quint32(*p++) << (8 * i);
properties.emplace(tag, int(value));
}
}
return properties;
Expand Down Expand Up @@ -323,8 +329,7 @@ QPCSCReader::Result QPCSCReader::transferCTL(const QByteArray &apdu, bool verify
quint16 lang, quint8 minlen, quint8 newPINOffset, bool requestCurrentPIN) const
{
bool display = false;
QHash<DRIVER_FEATURES,quint32> features = d->features();
if( DWORD ioctl = features.value(FEATURE_IFD_PIN_PROPERTIES) )
if(DWORD ioctl = d->feature(FEATURE_IFD_PIN_PROPERTIES))
{
PIN_PROPERTIES_STRUCTURE caps{};
DWORD size = sizeof(caps);
Expand Down Expand Up @@ -377,17 +382,17 @@ QPCSCReader::Result QPCSCReader::transferCTL(const QByteArray &apdu, bool verify
cmd = toByteArray(data);
}

DWORD ioctl = features.value( verify ? FEATURE_VERIFY_PIN_START : FEATURE_MODIFY_PIN_START );
if( !ioctl )
ioctl = features.value( verify ? FEATURE_VERIFY_PIN_DIRECT : FEATURE_MODIFY_PIN_DIRECT );
DWORD ioctl = d->feature(verify ? FEATURE_VERIFY_PIN_START : FEATURE_MODIFY_PIN_START);
if(!ioctl)
ioctl = d->feature(verify ? FEATURE_VERIFY_PIN_DIRECT : FEATURE_MODIFY_PIN_DIRECT);

qCDebug(APDU).nospace().noquote() << 'T' << d->io.dwProtocol - 1 << "> " << apdu.toHex();
qCDebug(APDU).nospace().noquote() << "CTL" << "> " << cmd.toHex();
QByteArray data( 255 + 3, 0 );
auto size = DWORD(data.size());
LONG err = SC(Control, d->card, ioctl, cmd.constData(), DWORD(cmd.size()), LPVOID(data.data()), DWORD(data.size()), &size);

if( DWORD finish = features.value( verify ? FEATURE_VERIFY_PIN_FINISH : FEATURE_MODIFY_PIN_FINISH ) )
if(DWORD finish = d->feature(verify ? FEATURE_VERIFY_PIN_FINISH : FEATURE_MODIFY_PIN_FINISH))
{
size = DWORD(data.size());
err = SC(Control, d->card, finish, nullptr, 0U, LPVOID(data.data()), DWORD(data.size()), &size);
Expand Down
1 change: 0 additions & 1 deletion client/QPCSC.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ class QPCSC final: public QThread
bool serviceRunning() const;

Q_SIGNALS:
void statusChanged(const QString &reader, const QStringList &state);
void cardChanged();

private:
Expand Down
4 changes: 2 additions & 2 deletions client/QPCSC_p.h
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ struct QPCSC::Private

struct QPCSCReader::Private
{
QHash<DRIVER_FEATURES,quint32> features();
quint32 feature(DRIVER_FEATURES key);

QPCSC::Private *d {};
SCARDHANDLE card {};
Expand All @@ -198,5 +198,5 @@ struct QPCSCReader::Private
QByteArray reader;
bool isTransacted {};

QHash<DRIVER_FEATURES,quint32> featuresList;
std::array<PCSC_TLV_STRUCTURE,FEATURE_CCID_ESC_COMMAND> features{};
};
12 changes: 6 additions & 6 deletions client/QSmartCard.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -122,9 +122,11 @@ QPCSCReader::Result Card::transfer(bool verify, QByteArray &&apdu,

QByteArrayView Card::parseFCI(QByteArrayView data, quint8 expectedTag)
{
for(auto i = data.begin(); i != data.end();)
for(auto i = data.begin(); std::distance(i, data.end()) >= 2;)
{
quint8 tag(*i++), size(*i++);
if(size > std::distance(i, data.end()))
return {};
if(tag == expectedTag)
return {i, size};
if((tag & 0x20) == 0)
Expand Down Expand Up @@ -491,7 +493,7 @@ bool THALESCard::updateCounters(QSmartCardDataPrivate *d) const

QSmartCard::QSmartCard(QObject *parent)
: QObject(parent)
, d(new Private)
, d(std::make_unique<Private>())
{}

QSmartCard::~QSmartCard() noexcept = default;
Expand Down Expand Up @@ -658,7 +660,7 @@ void QSmartCard::reloadCard(const TokenData &token, bool reloadCounters)

QString reader = d->token.reader();
if(d->token.reader().endsWith(QLatin1String("..."))) {
for(auto truncated = QStringView(d->token.reader()).left(d->token.reader().size() - 3);
for(auto truncated = QStringView(reader).left(reader.size() - 3);
const QString &test: QPCSC::instance().readers()) {
if(test.startsWith(truncated))
reader = test;
Expand All @@ -667,9 +669,7 @@ void QSmartCard::reloadCard(const TokenData &token, bool reloadCounters)

qCDebug(CLog) << "Read" << reader;
auto card = Card::card(reader);
if(!card)
return;
if(!card->reader.connect())
if(!card || !card->reader.connect())
return;
qCDebug(CLog) << "Read card" << d->token.card() << "info";
QSharedDataPointer<QSmartCardDataPrivate> t = d->t.d;
Expand Down
Loading