Disabling Smartcard Plug and Play on Windows 7



I have implemented the core portions of the procedure for creating a NULL CSP
for unsupported smart cards in Windows 7 found here:
http://support.microsoft.com/kb/976832

I dispensed with much of the "look for a card" and the UUID as part of the
card name, as it really shouldn't be necessary (nothing in the MSDN
description indicated it was).

I can check the registry, and it looks like the appropriate entries are
being produced, but even after following this procedure, when I insert the
card, Windows still looks for a driver.

The cards are as follows:

GemAlto GemClub Memo: ATR = 3B025301
Atmel AT88SC0104C : ATR = 3BB211000800001
Atmel AT88SC0204C : ATR = 3BB2110010800002
Atmel AT88SC0404C : ATR = 3BB2110010800004
Atmel AT88SC0808C : ATR = 3BB2110010800008
Atmel AT88SC1616C : ATR = 3BB2110010800016
Atmel AT88SC3216C : ATR = 3BB3110000000032
Atmel AT88SC6416C : ATR = 3BB3110000000064
Atmel AT88SC12816C : ATR = 3BB3110000000128
Atmel AT88SC25616C : ATR = 3BB3110000000256

None of these cards are true smart cards. They use T=0 protocol, have an
ATR, and use normal PC/SC APDUs to communicate, but they don't have file
structures, crypto, etc. like a true smart card. Also, neither GemAlto nor
Atmel has submitted a null driver to Microsoft, nor do they plan to, from
what I have been able to gather.

So far, I've been instructing our clients to disable the smart card plug and
play function with the policy editor, but this is not really a viable
solution.

Here is my code (I program with Delphi, but it should be easily readable):

const MemoATR : TATR = (Count: 4; Data : ($3B, $02, $53, $01, $00,
$00, $00, $00, $00); Name: 'GemClub Memo');
Atmel0104ATR : TATR = (Count: 8; Data : ($3B, $B2, $11, $00, $10,
$80, $00, $01, $00); Name: 'Atmel 0104');
Atmel0204ATR : TATR = (Count: 8; Data : ($3B, $B2, $11, $00, $10,
$80, $00, $02, $00); Name: 'Atmel 0204');
Atmel0404ATR : TATR = (Count: 8; Data : ($3B, $B2, $11, $00, $10,
$80, $00, $04, $00); Name: 'Atmel 0404');
Atmel0808ATR : TATR = (Count: 8; Data : ($3B, $B2, $11, $00, $10,
$80, $00, $08, $00); Name: 'Atmel 0808');
Atmel1616ATR : TATR = (Count: 8; Data : ($3B, $B2, $11, $00, $10,
$80, $00, $16, $00); Name: 'Atmel 1616');
Atmel3216ATR : TATR = (Count: 8; Data : ($3B, $B3, $11, $00, $00,
$00, $00, $32, $00); Name: 'Atmel 3216');
Atmel6416ATR : TATR = (Count: 8; Data : ($3B, $B3, $11, $00, $00,
$00, $00, $64, $00); Name: 'Atmel 6416');
Atmel12816ATR : TATR = (Count: 8; Data : ($3B, $B3, $11, $00, $00,
$00, $01, $28, $00); Name: 'Atmel 12816');
Atmel25616ATR : TATR = (Count: 8; Data : ($3B, $B3, $11, $00, $00,
$00, $02, $56, $00); Name: 'Atmel 25616');

// This is the name that will be provided as the CSP for
// the card when introduced to the system. This is provided
// in order to disable Smart Card Plug and Play for this
// card.
const CARD_CSP = '$DisableSCPnP$';

Function RegisterCardNullCSP(ATR: TATR): LongInt;
Var SC: SCARDCONTEXT;
Return : LongInt;
Cards : PChar;
CardsSize : LongWord;
CardFound : Boolean;
ContextOk : Boolean;
Begin
CardFound := False;
Return := SCardEstablishContext(SCARD_SCOPE_SYSTEM, nil, nil,
LPSCARDCONTEXT(@SC));
ContextOk := (Return = SCARD_S_SUCCESS);
if ContextOk then
Begin
// Determine if the ATR is already in the Smart Card Database
CardsSize := 0;
Return := SCardListCards(SC, LPCBYTE(@ATR.Data[0]), nil, 0, nil,
CardsSize);
if Return = SCARD_S_SUCCESS then
Begin
if CardsSize > 1 then // Empty list still returns size 1 for the NULL
termination
Begin
Cards := StrAlloc(CardsSize);
Return := SCardListCards(SC, LPCBYTE(@ATR.Data[0]), nil, 0, Cards,
CardsSize);
if Return = SCARD_S_SUCCESS then
Begin
if StrPas(Cards) = ATR.Name then
CardFound := True;
End;
StrDispose(Cards);
End;
End;
End;

if Not CardFound then
Begin
// Introduce the card to the system
Result := SCardIntroduceCardType(SC, PChar(ATR.Name), nil, nil, 0,
LPCBYTE(@ATR.Data[0]), nil, ATR.Count);
// Set the provider name
if Result = SCARD_S_SUCCESS then
Result := SCardSetCardTypeProviderName(SC, PChar(ATR.Name),
SCARD_PROVIDER_CSP, CARD_CSP);
End;

// Cleanup resources
if ContextOk then
SCardReleaseContext(SC);

Result := Return;
End;

RegisterCardNullCSP(MemoATR);
RegisterCardNullCSP(Atmel0104ATR);
RegisterCardNullCSP(Atmel0204ATR);
RegisterCardNullCSP(Atmel0404ATR);
RegisterCardNullCSP(Atmel0808ATR);
RegisterCardNullCSP(Atmel1616ATR);
RegisterCardNullCSP(Atmel3216ATR);
RegisterCardNullCSP(Atmel6416ATR);
RegisterCardNullCSP(Atmel12816ATR);
RegisterCardNullCSP(Atmel25616ATR);

After running this code, my registry looks like this:
Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Cryptography\Calais\SmartCards]

[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Cryptography\Calais\SmartCards\Atmel 0104]
"ATR"=hex:3b,b2,11,00,10,80,00,01
"Crypto Provider"="$DisableSCPnP$"

[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Cryptography\Calais\SmartCards\Atmel 0204]
"ATR"=hex:3b,b2,11,00,10,80,00,02
"Crypto Provider"="$DisableSCPnP$"

[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Cryptography\Calais\SmartCards\Atmel 0404]
"ATR"=hex:3b,b2,11,00,10,80,00,04
"Crypto Provider"="$DisableSCPnP$"

[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Cryptography\Calais\SmartCards\Atmel 0808]
"ATR"=hex:3b,b2,11,00,10,80,00,08
"Crypto Provider"="$DisableSCPnP$"

[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Cryptography\Calais\SmartCards\Atmel 12816]
"ATR"=hex:3b,b3,11,00,00,00,01,28
"Crypto Provider"="$DisableSCPnP$"

[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Cryptography\Calais\SmartCards\Atmel 1616]
"ATR"=hex:3b,b2,11,00,10,80,00,16
"Crypto Provider"="$DisableSCPnP$"

[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Cryptography\Calais\SmartCards\Atmel 25616]
"ATR"=hex:3b,b3,11,00,00,00,02,56
"Crypto Provider"="$DisableSCPnP$"

[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Cryptography\Calais\SmartCards\Atmel 3216]
"ATR"=hex:3b,b3,11,00,00,00,00,32
"Crypto Provider"="$DisableSCPnP$"

[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Cryptography\Calais\SmartCards\Atmel 6416]
"ATR"=hex:3b,b3,11,00,00,00,00,64
"Crypto Provider"="$DisableSCPnP$"

[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Cryptography\Calais\SmartCards\GemClub Memo]
"ATR"=hex:3b,02,53,01
"Crypto Provider"="$DisableSCPnP$"

[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Cryptography\Calais\SmartCards\Identity Device (Microsoft Generic Profile)]
"Crypto Provider"="Microsoft Base Smart Card Crypto Provider"
"Smart Card Key Storage Provider"="Microsoft Smart Card Key Storage Provider"
"80000001"="msclmd.dll"

[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Cryptography\Calais\SmartCards\Identity Device (NIST SP 800-73 [PIV])]
"Crypto Provider"="Microsoft Base Smart Card Crypto Provider"
"Smart Card Key Storage Provider"="Microsoft Smart Card Key Storage Provider"
"80000001"="msclmd.dll"

Interestingly, the 64 bit section does not have these entries, it looks like
this:
Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography\Calais\SmartCards]

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography\Calais\SmartCards\Identity Device (Microsoft Generic Profile)]
"Crypto Provider"="Microsoft Base Smart Card Crypto Provider"
"Smart Card Key Storage Provider"="Microsoft Smart Card Key Storage Provider"
"80000001"="msclmd.dll"

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography\Calais\SmartCards\Identity Device (NIST SP 800-73 [PIV])]
"Crypto Provider"="Microsoft Base Smart Card Crypto Provider"
"Smart Card Key Storage Provider"="Microsoft Smart Card Key Storage Provider"
"80000001"="msclmd.dll"

Manually creating the registry keys in the normal 64 bit area works as
expected, the cards are no longer prompt for drivers. But I don't believe my
app will have permissions to do this in code.

Any suggestions?
.