Once the reader monitor has reported the ATR for the card in a reader, it can be used to access the card.
Windows has a model that gives card manufacturers three options for providing access to a smart card through the crypto apis.
- KSP/CSP - the manufacturer can supply a full KSP(Key Storage Provider) and CSP (Cryptographic Service Provider) and associate it with an ATR.
- Smart Card Minidriver - the manufacturer can supply a minidriver dll that the built-in Smart Card KSP and CSP will load to provide access and associate it with an ATR.
- PICS/GIDS - the manufacturer can provide a card that implements the GIDS or PICS card standard. Windows has built-in minidrivers for these.
Because of the first option, once an ATR is in hand, SCardGetCardTypeProviderName
must be called to retrieve the KSP or CSP provider name that should be used for the card.
SCardListCards
will retrieve the card name from an ATR, which is then passed to SCardGetCardTypeProviderName
. Windows only supports one KSP/CSP for an ATR, so even though SCardListCards
returns a list of card names any one of them can be used to retrieve the provider names.
Here is the code to get a card name and the KSP provider name.
struct CardWithProvider { std::wstring cardname; std::wstring kspname; }; inline std::pair<unique_winerror, CardWithProvider> smartcard_name_and_provider( lib::rng::range<const BYTE*> atr ) { unique_winerror winerror; unique_close_scardcontext context; CardWithProvider output; winerror.reset( SCardEstablishContext( SCARD_SCOPE_USER, NULL, NULL, context.replace() ) ); if (!winerror) { return std::make_pair(winerror, std::move(output)); } LPWSTR kspstring = nullptr; ON_UNWIND( unwind_kspstring, [&] { if (kspstring) { SCardFreeMemory(context.get(), kspstring); } } ); DWORD ksplength = SCARD_AUTOALLOCATE; LPWSTR cardsstring = nullptr; ON_UNWIND_AUTO( [&] { if (cardsstring) { SCardFreeMemory(context.get(), cardsstring); } } ); DWORD cardslength = SCARD_AUTOALLOCATE; winerror.reset( SCardListCards( context.get(), atr.begin(), NULL, NULL, reinterpret_cast<LPWSTR>(&cardsstring), &cardslength ) ); if (winerror == winerror_cast(SCARD_E_READER_UNAVAILABLE)) { winerror.suppress(); // don't free the static string we are // about to assign unwind_kspstring.dismiss(); kspstring = MS_SMART_CARD_KEY_STORAGE_PROVIDER; ksplength = wcslen(kspstring); } else if (!winerror) { return std::make_pair(winerror, std::move(output)); } else { winerror.reset( SCardGetCardTypeProviderName( context.get(), cardsstring, SCARD_PROVIDER_KSP, reinterpret_cast<LPWSTR>(&kspstring), &ksplength ) ); if (!winerror) { return std::make_pair(winerror, std::move(output)); } } if (cardsstring) { output.cardname = cardsstring; } output.kspname = kspstring; return std::make_pair(winerror, std::move(output)); }
No comments:
Post a Comment