WinSCard SCARD_E_PROTO_MISMATCH при подключении к эстонской идентификационной карте

Я пытаюсь прочитать личный файл эстонской идентификационной карты.

Мне нужно отправить следующие данные на карту (из
Вот) для чтения записей из личного файла (т.е. идентификационный номер, имя и т. д.):

00 A4 00 0C          # We choose root folder
00 A4 01 0C 02 EE EE # We choose folder EEEE
00 A4 02 04 02 50 44 # We choose file 5044, which contains personal data
00 B2 XX 04          # We read record XX (see table) from the personal data file
# The card responds 61 YY, where YY denotes the number of bytes waiting to be read
00 C0 00 00 YY       # We read YY bytes from the card
# Card responds ... 90 00, where ... is the requested data and 90 00 means status OK

Однако необработанные байты находятся в протоколе T = 0, и карта застревает в T = 1 на неоправданно долгое время, прежде чем принять T = 0. Последовательность событий следующая:

  1. Карта прикреплена к читателю
  2. Программа возвращается из SCardStatusChange и начинает обрабатывать карту
  3. При попытке подключиться к карте (SCardConnect или же SCardReconnect) Ошибка SCARD_E_SHARING_VIOLATION принимается снова и снова, в течение 5 с
  4. Затем при попытке подключиться ошибка SCARD_E_PROTO_MISMATCH принимается от 3 до 30 секунд, может быть, больше.
  5. После этого карта успешно подключается и считывает данные.

Можно ли как-то быстрее подключиться к нему по протоколу T = 0?

Упрощенная версия моего исходного кода выглядит следующим образом:

// NOTE: this is approximately what I do.
// I haven't tested this code yet - it's almost 1 AM here.
#include <winscard.h>
void readSmartCard() {
LONG sCardErrorCode;
SCARDCONTEXT sCardContext;
DWORD sCardReaderStrLen = 1024;
wchar_t sCardReaderStr[1024];
SCARDHANDLE sCardHandle;
DWORD sCardActiveProtocol;
SCARD_READERSTATE readerState;

sCardErrorCode = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &sCardContext);

// error handling macro

ZeroMemory(&sCardReaderState, sizeof(sCardReaderState));
sCardReaderState.szReader = L"\\\\?PnP?\\Notification";
sCardReaderState.pvUserData = nullptr;
sCardReaderState.dwEventState = SCARD_STATE_PRESENT;

sCardErrorCode = SCardGetStatusChange(sCardContext, INFINITE, &readerState, 1);

// e.h.m

if (readerState.dwCurrentState == 65538) {
sCardErrorCode = SCardListReaders(sCardContext, NULL, sCardReaderStr, &sCardReaderStrLen);
// e.h.m
readerState.szReader = sCardReaderStr;
}

sCardErrorCode = SCardGetStatusChange(sCardContext, INFINITE, &readerState, 1);
// e.h.m

if (sCardReaderState.dwEventState & SCARD_STATE_PRESENT) {

while (true) {
sCardErrorCode = SCardConnect(sCardContext, readerState.szReader, SCARD_SHARE_EXCLUSIVE,
SCARD_PROTOCOL_T0, &sCardHandle, &sCardActiveProtocol);

// e.h.m
printf("%x", sCardErrorCode);
// this will print:
// 8010000b (for around 5s)
// 8010000f (for around 20s)
if (sCardErrorCode == SCARD_S_SUCCESS) {
break;
}
Sleep(1000);
}

// open personal file and read data, yay!
}
}

0

Решение

Вы спрашиваете SCardConnect() для эксклюзивного доступа к T0 только протокол, поэтому, если карта используется, то SCARD_E_SHARING_VIOLATION возвращается, и если карта не используется, но T1 тогда активен SCARD_E_PROTO_MISMATCH возвращается вместо.

когда SCardGetStatusChange() сообщает об уведомлении, вы проверяете только SCARD_STATE_PRESENT флаг, но могут присутствовать и другие флаги, которые вы игнорируете, такие как SCARD_STATE_INUSE,

Если вам нужен эксклюзивный доступ к читателю, вам придется подождать, пока SCARD_STATE_INUSE очищается и / или SCARD_E_SHARING_VIOLATION больше не начало сообщаться. С этим ничего не поделаешь, если только вы не измените свою логику, чтобы разрешить подключение в режиме совместного использования вместо эксклюзивного режима.

Если вы хотите подключиться к считывателю независимо от его текущего протокола (и, следовательно, получить эксклюзивный доступ раньше), вы можете спросить SCardConnect() принять и то и другое T0 а также T1 протоколы в то же время, или объединяя их в dwPreferredProtocol параметр (см. пример в документация). Тогда, если pdwActiveProtocol выходы параметров, которые T1 является активным протоколом, вы можете ждать изменения статуса на T0 протокол перед чтением карты.

0

Другие решения

После долгих поисков в интернете я обнаружил, что никаких изменений в командах не требуется.

Мне просто нужно было добавить дополнительный нулевой байт в конец переданных команд чтения / открытия и получить данные в ответ на команду чтения, а также не использовать отдельную команду для получения байтов. (T = 0 использует модель «запрос данных / чтение данных», в то время как T = 1, кажется, просто отвечает данными)

Мне также нужно было изменить все упоминания SCARD_PCI_T0 условно использовать SCARD_PCI_T1 и сделать SCardConnect() Функция принимает T1 тоже.

Я опубликую достойный пример кода здесь позже.

0

По вопросам рекламы [email protected]