views:

590

answers:

1

I have Gemalto.NET Smart Card.
I imported 2 certificates into it using Gemalto tools, which use sconnect (which as I suspect use Crypto API to do it when used in IE).

When I run

certutil -key -csp "Microsoft Base Smart Card Crypto Provider"

I have following result

Microsoft Base Smart Card Crypto Provider:
7c168bc3-dc1d-a627-c218-cd45729b42cb [Default Container] AT_KEYEXCHANGE

badd537a-a377-431b-cbc9-8699dbe15e0e AT_KEYEXCHANGE

LoadKeys returned Key does not exist. 0x8009000d (-2146893811) CertUtil: -key command completed successfully.

Now I want to find those keys in my C# program. To do it I wrote following method that should return all keys on specific smart card.

static List<string> EnumerateContainers(string card)
{
    var list = new List<string>();
    var provider = IntPtr.Zero;
    if (!CryptAcquireContext(ref provider, @"\\.\" + card + @"\", "Microsoft Base Smart Card Crypto Provider", 1, CspProviderFlags.UseMachineKeyStore))
        Debug.WriteLine("no context for " + card);

    uint bufferSize = 4096;
    var container = new StringBuilder((int)bufferSize);
    uint flags = CRYPT_FIRST;
    while(CryptGetProvParam(provider, PP_ENUMCONTAINERS, container, ref bufferSize, flags))
    {
        list.Add(container.ToString());
        flags = 0;
    }
    return list;
}

But my method find only the key 7c168bc3-dc1d-a627-c218-cd45729b42cb which is the default one. What should I do to find all keys/containers stored on the smart card ??

And Later

How can I delete those keys and import new one using C#?

A: 

I've come across the same problem and have seen similiar posts on the web but finally I've found the answer... by checking the error code!

The reason is that pcbData's value is changed by the implementation being called (to reflect length of the returned data) and must be set to buffer's size before each call.

Checking GetLastError after the failure shows error 234 which is exactly that!

Actually it seems to be a propagation of a bug in code sample from "Extending .NET Cryptography with CAPICOM and P/Invoke" (http://msdn.microsoft.com/en-us/library/ms867087.aspx)

dwFlags=CRYPT_FIRST; //required initalization StringBuilder sb = new StringBuilder(BUFFSIZE); while (Win32.CryptGetProvParam(hProv, enumflags, sb, ref pcbData, dwFlags)) { dwFlags=0; //required to continue entire enumeration containernames.Add(sb.ToString()); }

where there is pcbData = BUFFSIZE; missing inside the loop.

Regards

woj