Head Geek
Head Geek

Reputation: 39878

How to implement VERIFY command on NIST PIV cards?

I must be doing something wrong, but I can't see what.

I'm trying to get the VERIFY command to show the number of attempts remaining. (I was trying to enter the PIN as well, but cut back to this when I couldn't get anything to work.) Here's the code fragment that I've been trying:

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;
        }
    }
}

The rawTransmit function...

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 is defined as std::vector<unsigned char>.)

All the cards using protocol T0 return 0x6a 0x88 ("Referenced data not found") for all P2 values. All the cards using T1 do the same, except when P2 is 0x81 -- then they say 0x69 0x84 ("Command not allowed, referenced data invalidated").

The cards in question definitely DO have PINs, and I can verify the PIN in the "Security Token Configurator" program provided by the middleware vendor, so I know that the card, reader, and middleware stuff are all working.

It's probably obvious, but I'm new to smartcard programming. Can anyone give me a clue where I'm going wrong?

Upvotes: 1

Views: 344

Answers (1)

Maarten Bodewes
Maarten Bodewes

Reputation: 94038

The Global PIN has ID 00 and the PIV Card Application PIN has 80 (hex) so your tests do not include the known PIV card PIN ID's.

Upvotes: 2

Related Questions