Click here to Skip to main content
Licence CPOL
First Posted 30 Jan 2007
Views 41,538
Downloads 334
Bookmarked 32 times

Smartcard Framework for .NET Compact Framework

By | 30 Jan 2007 | Article
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.

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.

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.

[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

[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)

About the Author

orouit

Architect
Consistel - Singapore
Singapore Singapore

Member

Software Architect, COM, .NET and Smartcard based security specialist.
 
I've been working in the software industry since I finished my study of Electrical Engineering. I chose software because I prefered digital to analog.
 
I started to program with 6802 machine code and evolved to the current .NET technologies... that's a long way.
 
In almost 20 years I have always worked in technical position, management would be a regression for me 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 specialisation in security solutions based on those really small computers! I'm currently back in the business to design the licensing system for the enterprise solution I'm currenly working on, using a .NET smart card (yes they can run CLR!)
 
You can contact me for professional consulting by using the forum.

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board. (secure sign-in)
 
Search this forum  
 FAQ
    Noise  Layout  Per page   
  Refresh
GeneralUsable SIM card reader ? [modified] PinmemberCodeMonkey~852:41 25 Jan '11  
Generalscardce.dll PinmemberMember 160451223:45 6 Nov '10  
AnswerRe: scardce.dll Pinmemberorouit3:01 9 Nov '10  
Generalprogram i2c cards Pinmemberfresh2g60:18 15 Apr '09  
GeneralRe: program i2c cards Pinmemberorouit2:53 20 Apr '09  
GeneralQuestion on using Smart Card API Pinmemberbkseo20:35 24 Feb '08  
GeneralRe: Question on using Smart Card API Pinmemberandlic23:29 24 Jun '09  
GeneralCellular Emulator Pinmemberneil young21:37 12 May '07  
AnswerRe: Cellular Emulator Pinmemberorouit7:42 13 May '07  
Generalhelp for Windows CE Pinmembersanalp_sp20:31 19 Apr '07  
AnswerRe: help for Windows CE Pinmemberorouit21:26 19 Apr '07  
QuestionSCARDCE.DLL Pinmembertiredoldcoder17:26 2 Apr '07  
AnswerRe: SCARDCE.DLL Pinmemberorouit8:53 4 Apr '07  
QuestionSmartCard Device PinmemberStrange997:49 31 Jan '07  
AnswerRe: SmartCard Device Pinmemberorouit22:27 31 Jan '07  

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

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

Permalink | Advertise | Privacy | Mobile
Web04 | 2.5.120528.1 | Last Updated 30 Jan 2007
Article Copyright 2007 by orouit
Everything else Copyright © CodeProject, 1999-2012
Terms of Use
Layout: fixed | fluid