Click here to Skip to main content
15,880,392 members
Articles / Programming Languages / C#

Smartcard Framework for .NET Compact Framework

Rate me:
Please Sign up or sign in to vote.
4.38/5 (3 votes)
30 Jan 2007CPOL5 min read 70.7K   1.2K   36   15
This article describes a framework to use the PCSC smartcard API with .NET on a PocketPC

Introduction

In a couple of previous articles I presented a .NET API and a simple XML framework to write smart card application for the .NET environment. When I first developed this framework I also made a version for the Compact Framework and specially for the PocketPC. As I had some request from readers regarding the CE version I have decided to write this short article about it. I recommend that you first read my to other articles, A .NET API for PC/SC and An XML framework for Smart card application, because I describe only the main differences of the CF version compared to a full .NET 2.0 version.

A simple Smart card Framework

The CF version of the smart card classes is very similar to the one I intorduced previously. You can find below the interface and the base classes that are used to manage the card communication and the command format.

C#
public interface ICard
{
    string[] ListReaders();
    void Connect(string Reader, SHARE ShareMode, 
                 PROTOCOL PreferredProtocols);
    void Disconnect(DISCONNECT Disposition);
    APDUResponse Transmit(APDUCommand ApduCmd);
} 

The classes APDUCommand and APDUResponse are used to send the command and get the response from the card. SHARE, <code>PROTOCOL and DISCONNECT are enumerations of constants used by PC/SC.

C#
public class APDUCommand
{
    public APDUCommand(byte bCla, byte bIns, byte bP1, byte bP2, 
                       byte[] baData, byte bLe);
    public void Update(APDUParam apduParam);
    public override string ToString();
    public byte    Class;
    public byte    Ins;
    public byte    P1;
    public byte    P2;
    public byte[]  Data;
    public byte    Le;
}
    
public class APDUResponse
{
    public APDUResponse(byte[] baData);
    public byte[]    Data;
    public byte    SW1;
    public byte    SW2;
    public ushort    Status;
    public override string ToString();
}

The PocketPC version doesn't provide any event management and unlike the PC version there is no implementation using the a COM version of PC/SC, because it doesn't exist on CE and also because there is no COM interop support with the Compact Framework.

So the only implementation of the ICard interface is a NativeCard class that use the native interop of .NET.

CardNative: A native interoperability implementation class using P/Invoke

The Platform Invoke mechanism (P/Invoke) is a very powerful mechanism that gives a total access to the Win32 platform API. The .NET framework provides a complete set of classes that you can use to achieve every marshaling operation necessary to call Win32 functions from .NET. Those classes are defined in the System.Runtime.InteropServices assembly that you just need to import in your program. The P/Invoke mechanism even if it is a bit complex is far more convenient than the JNI mechanism of Java. All the atomic types like int, byte, long, etc... are automatically marshaled by the compiler itself. The byte[] is also automatically marshaled as input or output parameter. When you have to deal with more complex parameters like strings, structure or pointers to structure, .NET provides a set of marshaling classes that can be used as attributes or object in you program when marshaling parameters. To develop the CardNative class I didn't have to develop any extra code to use the PC/SC API, all the code is in the source CardNative.cs. When you want to use a Win32 API C function you need to declare the function in your class using the interoperabilty attributes provided by the System.Runtime.InteropServices assembly. Once you have declared the function you can just use it as any C# method in your class. The following code sample illustrates this mechanism.

The main differences between the PC version and the PocketPC version is that the PC/SC functions are not located in the same DLL and that parameters passed using a pointer, except for the byte array are not automatically marshaled. There are also some memory allocation functions that are not provided by the Compact Framework and you need to use the C native functions.

Memory functions that you need to import.

C#
[DllImport("coredll.dll", SetLastError=true)]
internal static extern IntPtr    LocalAlloc(UInt32 uFlags, UInt32 uBytes);

[DllImport("coredll.dll", SetLastError=true)]
internal static extern IntPtr LocalFree(IntPtr hMem);

Declaration of the PC/SC native functions

C#
[DllImport("scardce.dll", SetLastError=true, CharSet=CharSet.Auto )]
internal static extern int SGCardListReaders(UInt32 hContext, 
                          IntPtr mszReaders, out UInt32 pcchReaders);

[DllImport("scardce.dll", SetLastError=true)]
 internal static extern int SGCardEstablishContext(UInt32 dwScope, 
                                                   IntPtr phContext);

[DllImport("scardce.dll", SetLastError=true)]
internal static extern int SGCardReleaseContext(UInt32 hContext);

[DllImport("scardce.dll", SetLastError=true, CharSet=CharSet.Auto)]
internal static extern int SGCardConnect(UInt32 hContext, 
    byte[] szReader, 
    UInt32 dwShareMode, 
    UInt32 dwPreferredProtocols,
    IntPtr phCard, 
    IntPtr pdwActiveProtocol);

[DllImport("scardce.dll", SetLastError=true)]
internal static extern int SGCardDisconnect(UInt32 hCard, 
                                            UInt32 dwDisposition);

[DllImport("scardce.dll", SetLastError=true)]
internal static extern int SGCardTransmit(UInt32 hCard, 
    [In] ref SCard_IO_Request pioSendPci, 
    byte[] pbSendBuffer,
    UInt32 cbSendLength,
    IntPtr pioRecvPci,
    [Out] byte[] pbRecvBuffer,
    out UInt32 pcbRecvLength);

If you have a look to the declaration of the PC/SC functions you will notice some differences with the PC declaration. For example there is no automatic marshalling of the strings and you need to handle them as an array of bytes. For the rest the declaration is the same.

The following code shows how to pass a string to the PC/SC function SCardConnect.

public void Connect(string Reader, SHARE ShareMode, 
                    PROTOCOL PreferredProtocols)
{
    IntPtr    hCard = IntPtr.Zero;
    IntPtr    pProtocol = IntPtr.Zero;

    try
    {
        if (m_hContext == 0)
            EstablishContext(SCOPE.User);

        // Allocate the memory to receive the pointer's data
        hCard = LocalAlloc(0, (UInt32) Marshal.SizeOf(m_hCard));
        pProtocol = LocalAlloc(0, (UInt32) Marshal.SizeOf(m_nProtocol));

        // Get a byte array version of the string 
        byte[] baReader = Encoding.Unicode.GetBytes(Reader);
        m_nLastError = SGCardConnect(m_hContext, 
            baReader, 
            (uint) ShareMode, 
            (uint) PreferredProtocols, 
            hCard,
            pProtocol);

        if (m_nLastError != 0)
        {
            string msg = "SCardConnect error: " + m_nLastError;

            throw new Exception(msg);
        }

        m_hCard = (uint) Marshal.ReadInt32(hCard);
        m_nProtocol = (uint) Marshal.ReadInt32(pProtocol);
    }
    catch
    {
        throw;
    }
    finally
    {
        LocalFree(hCard);
        LocalFree(pProtocol);
    }
}

This code is very interesting because it shows all the differences that there are between the PC and the PocketPC version. In addition to the string management you can see that to get the card handle (m_hCard) and the protocol (pProtocol) you first need to allocate the memory to get them using the native allocation functions. On the exit of the function, if it worked you then need to get the data from the memory the same way you would do with the PC version.

Demo application: An Exchange APDU application for the PocketPC

When it comes to use the ICard interface in an application there is strictly no difference with the PC except with the limitation that exist with the .NET Compact Framework.

I designed a simple exchange APDU application that uses an older version of my APDUList.xml (there are few differences in the declaration of the APDU). The only problem that you may have is that there are not a lot of smart card readers available in the market. I developed this application using a smart card embedded in a SD card and a small smart card reader that you plug on a SD card slot. I know that there is also an extension for iPaq where you can plug a PCI smart card reader.

This is a screen shot done with the Visual Studio emulator which unfortunately cannot connect the smart card reader of the PC.

Points of Interest

This short article demonstrates the differences that there can be when you develop the same kind of application on a PC or a PocketPC. Even if the differences are less than when using a language like C++, as the CF is a subset of the .NET framework and that support for interoperability is not totally implemented it can be quite difficult to achieve the same level of functionalities.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Architect Connect In Private
Singapore Singapore
Software Architect, COM, .NET and Smartcard based security specialist.

I've been working in the software industry since I graduated in Electrical and Electronics Engineering. I chose software because I preferred digital to analog.

I started to program with 6802 machine code and evolved to the current .NET technologies... that was a long way.

For more than 20 years I have always worked in technical positions as I simply like to get my hands dirty and crack my brain when things don't go right!

After 12 years in the smart card industry I can claim a strong knowledge in security solutions based on those really small computers!
I've been back into business to design the licensing system for the enterprise solution for Consistel using a .NET smart card (yes they can run .NET CLR!)

I'm currently designing a micro-payment solution using the NXP DESFire EV1 with the ACSO6 SAM of ACS. I can then add a full proficient expertise on those systems and NFC payments.
This technology being under strict NDA by NXP I cannot publish any related article about it, however I can provide professional consulting for it.

You can contact me for professional matter by using the forum or via my LinkedIn profile.

Comments and Discussions

 
GeneralUsable SIM card reader ? [modified] Pin
CodeMonkey~8525-Jan-11 2:41
CodeMonkey~8525-Jan-11 2:41 
Generalscardce.dll Pin
Hassan H. Monfared6-Nov-10 23:45
Hassan H. Monfared6-Nov-10 23:45 
AnswerRe: scardce.dll Pin
orouit9-Nov-10 3:01
professionalorouit9-Nov-10 3:01 
Generalprogram i2c cards Pin
fresh2g615-Apr-09 0:18
fresh2g615-Apr-09 0:18 
GeneralRe: program i2c cards Pin
orouit20-Apr-09 2:53
professionalorouit20-Apr-09 2:53 
GeneralQuestion on using Smart Card API Pin
bkseo24-Feb-08 20:35
bkseo24-Feb-08 20:35 
GeneralRe: Question on using Smart Card API Pin
andlic24-Jun-09 23:29
andlic24-Jun-09 23:29 
GeneralCellular Emulator Pin
neil young12-May-07 21:37
neil young12-May-07 21:37 
AnswerRe: Cellular Emulator Pin
orouit13-May-07 7:42
professionalorouit13-May-07 7:42 
Generalhelp for Windows CE Pin
sanalp_sp19-Apr-07 20:31
sanalp_sp19-Apr-07 20:31 
AnswerRe: help for Windows CE Pin
orouit19-Apr-07 21:26
professionalorouit19-Apr-07 21:26 
QuestionSCARDCE.DLL Pin
tiredoldcoder2-Apr-07 17:26
tiredoldcoder2-Apr-07 17:26 
Where does scardce.dll file come from? I can't find a reference to it anywhere.

TOC
AnswerRe: SCARDCE.DLL Pin
orouit4-Apr-07 8:53
professionalorouit4-Apr-07 8:53 
QuestionSmartCard Device Pin
Strange9931-Jan-07 7:49
Strange9931-Jan-07 7:49 
AnswerRe: SmartCard Device Pin
orouit31-Jan-07 22:27
professionalorouit31-Jan-07 22:27 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.