Как реализовать команду VERIFY на картах NIST PIV?

Должно быть, я делаю что-то не так, но я не вижу, что.

Я пытаюсь получить команду VERIFY, чтобы показать количество оставшихся попыток. (Я тоже пытался ввести PIN-код, но сократил его, когда ничего не заработало.) Вот фрагмент кода, который я пробовал:

for (unsigned int basebyte = 0x00; basebyte != 0x100; basebyte += 0x80) {
    for (unsigned char add = 0x01; add != 0x20; ++add) {
        smartcard::bytevector_t b;
        b.push_back(0x00); // CLA
        b.push_back(0x20); // INS
        b.push_back(0x00); // P1
        b.push_back(basebyte + add); // P2 ("the sensible ranges are 0x01..0x1F and 0x81..0x9F")
        //b.push_back(0x00); // Lc field -- length of the following data field
        b = card.rawTransmit(b);
        if (!card.status()) {
            cout << "Received error '" << card.status() << "'" << endl;
        } else {
            if (b[0] == 0x6a && b[1] == 0x88) {
                // "Referenced data not found"
                continue;
            }

            cout << "    Attempts remaining (" << std::hex << (basebyte + add) << std::dec << "): ";
            cout << std::hex;
            for (smartcard::bytevector_t::const_iterator i = b.begin(), ie = b.end();
                i != ie; ++i) cout << std::setfill('0') << std::setw(2) << int(*i) << ' ';
            cout << std::dec << endl;
        }
    }
}

Функция rawTransmit...

bytevector_t rawTransmit(bytevector_t sendbuffer) {
    SCARD_IO_REQUEST pioSendPci, pioRecvPci;
    if (mProtocol.value() == SCARD_PROTOCOL_T0) {
        pioSendPci = pioRecvPci = *SCARD_PCI_T0;
    } else if (mProtocol.value() == SCARD_PROTOCOL_T1) {
        pioSendPci = pioRecvPci = *SCARD_PCI_T1;
    } else {
        std::ostringstream out;
        out << "unrecognized protocol '" << mProtocol.str() << "'";
        throw std::runtime_error(out.str());
    }

    DWORD rlen = 256;
    bytevector_t recvbuffer(rlen);
    mResult = SCardTransmit(mHandle, &pioSendPci, &sendbuffer[0],
        DWORD(sendbuffer.size()), &pioRecvPci, &recvbuffer[0], &rlen);
    recvbuffer.resize(rlen);
    return recvbuffer;
}

(bytevector_t определяется как std::vector<unsigned char>.)

Все карты, использующие протокол T0, возвращают 0x6a 0x88 («Ссылочные данные не найдены») для всех значений P2. Все карты, использующие T1, делают то же самое, за исключением случаев, когда P2 равен 0x81 — тогда они говорят 0x69 0x84 («Команда не разрешена, данные ссылки недействительны»).

Рассматриваемые карты определенно имеют PIN-коды, и я могу проверить PIN-код в программе «Конфигуратор токенов безопасности», предоставленной поставщиком промежуточного программного обеспечения, поэтому я знаю, что карта, считыватель и промежуточное программное обеспечение работают.

Наверное, это очевидно, но я новичок в программировании смарт-карт. Может ли кто-нибудь дать мне понять, где я ошибаюсь?


person Head Geek    schedule 02.11.2015    source источник
comment
Если я правильно прочитал спецификации карты PIV, вы должны попробовать глобальный PIN-код (0x00) или PIN-код приложения карты PIV (0x80), поэтому вы тестируете за пределами ожидаемых значений.   -  person Maarten Bodewes    schedule 03.11.2015
comment
Да, я обнаружил, что нужно значение 0x80, и как раз возвращался к вопросу, чтобы отметить это, когда увидел ваш комментарий. Я не знал, что 0x00 также проверит глобальный PIN-код - спасибо. Если вы превратите это в ответ, я с радостью приму его.   -  person Head Geek    schedule 03.11.2015


Ответы (1)


Глобальный PIN-код имеет идентификатор 00, а PIN-код приложения карты PIV имеет 80 (шестнадцатеричный), поэтому ваши тесты не включают известные идентификаторы PIN-кода карты PIV.

person Maarten Bodewes    schedule 03.11.2015