Smart Card1
Smart Card1
Smart Card1
NET - Part I
Introduction
The .NET framework has been introduced in 2002, and the version 3.0 has just been released in
November. So far, Microsoft hasn't included Smart Card classes in .NET, and if you want to develop a
Smart Card aware application, you have to develop your own classes. Fortunately, it is much easier to
reuse existing code in .NET than with Java. In Windows, if you need to use Smart Card, you just need to
use the PC/SC API in your program. This API comes in C functions or COM objects that wrap the PC/SC
functions. The .NET Framework offers two types of interoperabilities with the legacy code: the COM
interoperbility, and the P/Invoke feature for native code interoperability.
Background
This article demonstrates how to use the interoperability features of .NET and use them to write a simple
framework to use a Smart Card in your applications. A Smart Card is a small embedded device that
receives commands through a card reader using the PC/SC Win32 API. If you want to use this API, you
will need a Smart Card reader to use a Smart Card such as a SIM card.
The SC framework I'm going to describe is composed of an interface to communicate with the Smart Card,
a few classes to wrap the different parameters of a Smart Card command, and the implementation classes
depending on the interop mode we are using.
The Smart Card interface provides a simple access to a Smart Card for .NET programs. We will see later
how to implement this interface using both the interoperability techniques.
The classes APDUCommand and APDUResponse are used to send the command and get the response from
the card. SHARE, PROTOCOL, and DISCONNECT are constants used by PC/SC.
When a card is inserted in the reader or removed, PC/SC allows you to handle those events. So I added a
card event support to this framework based on the event model of .NET. The class CardBase, which
inherits from the interface ICard, implements support for two
events, CardInserted and CardRemoved. The mechanism of detection is implemented in the derived
class that implements ICard. So far I only implemented this support in CardNative. If you want to
support the event in your application program, you just need to implement
theCardInsertedEventHandler and the CardRemovedEventHandler.
I developed two implementations of the interface ICard. One is using COM interoperability, and the other
using native interoperability with P/Invoke. Both implementations behave the same way. In addition, I
ported the P/Invoke implementation for the Compact Framework so it is possible to develop Smart Card
applications for the Pocket PC.
COM interoperability is the simplest way to reuse legacy code in .NET framework. All versions of Visual
Studio .NET provide very good support for COM. You just need to add a reference to the COM object you
need to import, and it generates a wrapper DLL and all the necessary classes to use your COM interfaces.
Basically, you don't have to write any code. However, your COM components must respect a few rules,
specially regarding the parameters used in the methods. The different interfaces of the PC/SC COM
components were written long before .NET existed, and some of the interfaces are not totally compliant
with COM interoperability. This is why I had to develop my own COM interface to get the list of readers.
For the most important interface, ISCard and the interfaces it uses the import went fine.
The COM component I developed replaces the ISCardDatabase interface, and only implements one of its
methods: ListReaders. In the Microsoft implementation, the return parameter is a SAFEARRAY of BSTR,
which unfortunately .NET is unable to import properly. The right way to do it is to use a VARIANT* that
contains the SAFEARRAY of BSTR. Then, .NET will generate a wrapper method that returns an object that
you just have to cast into a string[]. Using a COM object in .NET is as simple as adding a reference to
this object in your code. Visual Studio will then generate a wrapper class that you directly use in your
code. The following extract illustrates this.
/// <summary>
/// Default constructor
/// </summary>
public CardCOM()
{
// Create the SCard object
m_itfCard = new CSCardClass();
}
The ISCardDatabase interface is provided in a DLL that must be registered with Regsvr32.
The Platform Invoke mechanism (P/Invoke) is a very powerful mechanism that gives 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 an input or output parameter. When you have to deal with
more complex parameters like strings, structures, or a pointer to a structure, .NET provides a set of
marshaling classes that can be used as attributes or objects in your 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 file CardNative.cs. When you want to use a Win32 API C function, you
need to declare the function in your class using the interoperability 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.
[DllImport("winscard.dll", SetLastError=true)]
internal static extern int SCardTransmit(UInt32 hCard,
[In] ref SCard_IO_Request pioSendPci,
byte[] pbSendBuffer,
UInt32 cbSendLength,
IntPtr pioRecvPci,
[Out] byte[] pbRecvBuffer,
out UInt32 pcbRecvLength
);
if (ApduCmd.Data == null)
{
ApduBuffer = new byte[APDUCommand.APDU_MIN_LENGTH +
((ApduCmd.Le != 0) ? 1 : 0)];
if (ApduCmd.Le != 0)
ApduBuffer[4] = (byte) ApduCmd.Le;
}
else
{
ApduBuffer = new byte[APDUCommand.APDU_MIN_LENGTH + 1 +
ApduCmd.Data.Length];
for (int nI = 0; nI < ApduCmd.Data.Length; nI++)
ApduBuffer[APDUCommand.APDU_MIN_LENGTH + 1 + nI] =
ApduCmd.Data[nI];
ApduBuffer[APDUCommand.APDU_MIN_LENGTH] =
(byte) ApduCmd.Data.Length;
}
ApduBuffer[0] = ApduCmd.Class;
ApduBuffer[1] = ApduCmd.Ins;
ApduBuffer[2] = ApduCmd.P1;
ApduBuffer[3] = ApduCmd.P2;
m_nLastError = SCardTransmit(m_hCard,
ref ioRequest,
ApduBuffer,
(uint) ApduBuffer.Length,
IntPtr.Zero, ApduResponse, out RecvLength);
if (m_nLastError != 0)
{
string msg = "SCardTransmit error: " + m_nLastError;
throw new Exception(msg);
}
The Smart Card API is very easy to use. However, if you want to write a Smart Card application, you must
know the commands to send to the card to perform operations such as selecting files, verifying PINs, or
reading data. Those commands are called APDU commands, and are described in the specification of the
Smart Card you want to access. The purpose of this article is not to explain how to use a Smart Card, but
to give you a simple C# API to play with any Smart Card you'd want.
Most people have a GSM phone so if you have a Smart Card reader on your PC (some laptops come with
an embedded Smart Card reader), you can use the little demo program to play with your SIM card. This
simple program presents the PIN (if your PIN is activated), selects the phone number file, and reads the
10 first records of this file. Everything you will get is in binary format like it is stored in the card. If your
PIN is activated, you must uncomment the line that verifies the PIN in my code. The PIN value is entered
in binary. If your PIN is 1234, you must enter 31323334 and pad with FF bytes until the PIN length is 8.
In the second part of this article, I will present a more advanced framework to write Smart Card
applications. This framework will use the classes I described in this article, and will make it easier writing
Smart Card applications.
Points of interest
In this first part, we have seen two methods to use legacy code with .NET. This is one of the very powerful
features of .NET that makes it the ideal managed framework to develop applications on the Windows
platform. This Smart Card framework can be very useful if you want to access a Smart Card application in
your .NET code. Of course, VB.NET users can use this framework as well.
However, this set of class still requires that you write dedicated code to access the card using the APDU
command which is not the most interesting code to write. In the second part of this article, I will give you
an XML framework that allows to write Smart Card applications with minimum code, using XML
declarations.
Smart Card framework for .NET - Part II
Introduction
In the first part, I described how to develop a set of classes with C# to wrap the PC/SC API of Windows.
PC/SC is a set of APIs used to communicate with a Smart Card. Even if the classes are easier to use than
the PC/SC functions, you still need to write code that is not always easy to understand. Communication
with a Smart Card uses a protocol named APDU to send the commands to the card, they are called APDU
commands. The framework I propose is designed to simplify the development of a Smart Card application.
Most of the time, you would have to chain several commands to perform an action like reading or writing
a file. With the framework I describe here, you can easily chain commands and then describe the Smart
Card elements of your application with an XML description.
Background
This article assumes that you have read the Part 1 of this article and that you have some knowledge of
XML. Even if not necessary, a basic knowledge of Smartcard programming can help.
Most people have a mobile phone and so use a Smart Card every day. For example, when you enter your
PIN on your mobile phone or read a phone number in your SIM card directory, your mobile sends a set of
commands to the card to perform the action. An APDU command is a set of bytes that are send to the
card that will respond with a code and eventually with the data you want to read.
APDU Length in
Description
byte bytes
P1 1 Parameter 1
P2 1 Parameter 2
This parameter is either the length of the sent data or the length of the
P3 1
expected data
SW1,
2 Command status
SW2
An APDU command always returns at least two bytes that are the status bytes. When the command
returns some data, the status bytes are the last two bytes returned by the command.
There are five different configurations to send commands to a card. They are categorized in two groups,
commands that send data and commands that receive data.
lgth =
90 00
0
datalgth 90 00
On a normal execution, those commands will answer with 9000 or with an error code.
datalgth 90 00
When a command requests data from the card with an unknown number of bytes, you must first send the
command with a length of 0 to get the number of bytes that the card will return. Then, you can call
the GET RESPONSE command with a request length lower or equal to the given length.
0 9F lgth
DATA of
CLASS INS P1 P2 P3 SW1 SW2
length req_lgth <= lgth
C0 0 0 req_lgth 90 00
This case is very similar to the previous one. The difference is that you are first sending a command that
transmits data to the card. This command replies with a 9FXX code where XXindicates the length of the
maximum data you can read with the GET RESPONSE command.
datalgth 90 00
DATA of
CLASS INS P1 P2 P3 SW1 SW2
length req_lgth <= lgth
C0 0 0 req_lgth 90 00
The commands that can be sent to a SIM card are described in a specification called 3GPP TS 11.11
(a.k.a. GSM 11.11). I won't describe here the whole set of commands and the files of the SIM card. If you
are interested in it, you can find a version of the GSM1111 here.
Class byte for GSM is A0, S indicates that data is sent to the card, and R that data is received from the
card. All byte values are given in hexadecimal.
SELECT A4 00 00 02 S/R
STATUS F2 00 00 lght R
READ BINARY B0 offset_high offset_low lgth R
Now, let us see how it is possible to write an XML framework to simplify the writing of Smart Card
applications.
The basic idea is to provide a simple and flexible framework in XML to describe APDU commands and write
an application which can be a sequence of several commands or of sequences. A command is the atomic
unit of description, it can be used alone or from a sequence if parameters need to be passed to the
command itself.
APDU command
An atomic APDU command is represented with an XML element. APDU commands are assembled in
a ApduList document. The ApduList and the Apdu elements are defined by the following schema:
<xs:schema attributeFormDefault="unqualified"
elementFormDefault="qualified"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="ApduList">
<xs:complexType>
<xs:sequence>
<xs:element maxOccurs="unbounded" name="Apdu">
<xs:complexType>
<xs:attribute name="Name" type="xs:string" use="required" />
<xs:attribute name="Class" type="xs:string" use="required" />
<xs:attribute name="Ins" type="xs:string" use="required" />
<xs:attribute name="P1" type="xs:unsignedByte" use="required" />
<xs:attribute name="P2" type="xs:unsignedByte" use="required" />
<xs:attribute name="P3" type="xs:string" use="required" />
<xs:attribute name="Data" type="xs:string" use="optional" />
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
A command file contains a set of pre-defined APDU commands. A command can be played by its name
after the APDU command list has been loaded. There are different types of commands; some commands
can be played individually, and some need to use the result of a previous command.
When the P3 parameter represents the length of expected data from the command, its value can be the
result of the previous call of a command, or the command should have to be replayed to get this variable
value. Here is the syntax accepted by the parameter to handle this case:
P3 = "R,0:SW1?xx"
R indicates that the command must be replayed with a condition on the value of SW1 after a first call
with P3=0. If SW1 == xx, the command will be replayed with P3 = SW2.
P3 = "R,xx:DRyy"
R indicates that the command must be replayed, but without the condition this time. On the first
call, P3 = xx, then the command is replayed with P3 = xx + RespData[yy] (yyth data of the response,
the first data index is 1 in the norm).
P3 = "SW2"
If SW1 == 0x9F on the previous call to a command, then this command is played using P3 = SW2 of the
previous command.
P3 = "DRxx"
If there were data from the previous command, xx is used as the index in the response data to get the
value of P3. Le = RespData[xx].
Sequence of commands
A sequence of commands is used to chain atomic APDU commands or sequences. A sequence can use
parameters that are given to commands that compose it. A SequenceList describes a set
of Sequence elements that can be called in an application. The following schema describes
a SequenceList of Sequence elements:
<xs:schema attributeFormDefault="unqualified"
elementFormDefault="qualified"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="SequenceList">
<xs:complexType>
<xs:sequence>
<xs:element maxOccurs="unbounded" name="Sequence">
<xs:complexType>
<xs:sequence>
<xs:element maxOccurs="unbounded" name="Command">
<xs:complexType>
<xs:attribute name="Apdu"
type="xs:string" use="optional" />
<xs:attribute name="P2"
type="xs:unsignedByte" use="optional" />
<xs:attribute name="Data"
type="xs:string" use="optional" />
<xs:attribute
name="Sequence" type="xs:string" use="optional" />
<xs:attribute name="P1"
type="xs:string" use="optional" />
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute name="Name" type="xs:string" use="required" />
<xs:attribute name="PIN" type="xs:string" use="optional" />
<xs:attribute name="Record"
type="xs:unsignedByte" use="optional" />
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
The Sequence element allows you to pass parameters to a command or another Sequence.
The Sequence uses a subelement that is Command. A Command is used to call an APDU with or without
parameters. When a parameter is given in a Command, it overrides the default parameter of the APDU
element.
For example, if you want to verify a PIN code, you can use the following Sequence:
The class that is used to call this sequence allows you to give a value to the PIN parameter. When
the Command is executed, the parameter Data will get the value given for the parameter
PIN. A Sequence parameter can take any name. In this version, the value of the parameter is a string
that represents a set of byte values.
seqParam.Add("PIN", "31323334FFFFFFFF");
apduResp = player.ProcessSequence("Verify CHV1", seqParam);
Console.WriteLine(apduResp.ToString());
Now that we have seen how to declare the commands and chain them using the Sequence element, I'm
going to describe the code that takes advantage of this simple 'XML language'.
In order to use the XML format previously described, I have developed a simple C# class which is able to
process APDU commands or APDU sequences.
The class APDUPlayer has three constructors, and exposes a few public methods. The two most
important methods are those that are used to execute an APDU command or a sequence of APDUs.
The following method is used to execute a single APDU command. The APDUParam parameter can be used
to modify a parameter of the APDU that was read from the XML description.
/// <summary>
/// Process a simple APDU command, Parameters
/// can be provided in the APDUParam object
/// </summary>
/// <param name="command">APDU command name</param>
/// <param name="apduParam">Parameters for the command</param>
/// <returns>An APDUResponse object with the response of the card </returns>
public APDUResponse ProcessCommand(string apduName, APDUParam apduParam);
This other method is used to execute a sequence of APDUs. The SequenceParameter class is a list of
parameter/value couple that are used as input parameters for the sequence to play.
/// <summary>
/// Process an APDU sequence and execute each
/// of its commands in the sequence order
/// </summary>
/// <param name="apduSequenceName">Name of the sequence to play</param>
/// <param name="seqParam">An array of SequenceParam
/// object used as parameters for the sequence</param>
/// <returns>APDUResponse object of the last command executed</returns>
public APDUResponse ProcessSequence(string apduSequenceName,
SequenceParameter seqParam);
In my previous article, we read the phone book of a SIM card using the PC/SC wrapper I described, but
this application was just getting the raw content of the phone book file (6F3A). In this sample, we are
going to interpret the data of each record. The content of the phone record is the following:
This EF contains the Abbreviated Dialing Numbers (ADN). In addition, it contains identifiers of associated
network/bearer capabilities and identifiers of extension records. It may also contain an associated alpha
tagging.
X + 3 to X +
Phone number string M 10 bytes
12
X + 14 Extension 1 record
This specification has been taken from the GSM11.11 document that specifies the logic of the SIM card.
We are going to extract from this description the information we need to get the phone number and its
associated name.
The first bytes are the name that appears on your mobile phone with the phone number. It is a string
using a coding close to the ASCII coding by default.
The fourteenth bytes that follow contain the phone number itself and some description bytes. The first
byte is the length of the phone number in bytes, including the TON & NPI byte which indicates if the
number is national (Ax, 8x) or international (9x).
The ten last bytes of this group contain the phone number itself. The coding is BCD where the bytes are in
reverse order. If the number of digits is odd, then the last byte of number contains a F and the digit. For
example, the number 015648327 is coded the following way: 10658423F7.
The two last bytes of the record contain data that are rarely used.
The class PhoneNumber is a helper class provided to interpret the bytes of a phone number record. It is
used the following way:
The ToString method gets a string of the content of the phone record in the following format, <name> :
<number>.
The program ReadPhonebook is a console application that reads the tenth first phone numbers of the ADN
file by default. You can read another number of records giving it as a parameter to the program.
P <pincode>: PIN code to present to the card. If you don't give this parameter, no PIN code will be
presented to the card.
<nbRecord>: Number of records to read. By default, the program reads 10 records.
Examples:
ReadPhonebook P 1234 25, will present 1234 as the PIN and read 25 records.
ReadPhonebook 50, reads 50 records, doesn't present any PIN.
ReadPhonebook P 4567, presents 4567 as PIN and reads 10 records.
APDExchange application
The APDUExchange Windows Forms application is a basic C# application that can be used to send any
APDU command to a card. It is possible to type the command or use an APDUListfile to preload
commands.
The application automatically detects card insertion or removal on demand. It uses the NativeCard
implementation of the Smart Card API described in the previous article.
If you want to send a command that is not in the APDU list, you just need to add the command to the file
using the format previously described.
Points of Interest
I have been working in the Smart Card industry for quite some time, and I rarely find articles about this
topic on the internet. As Smart Cards are now largely adopted and that some computers even have an
embedded Smart Card reader, I thought it would be interesting to demonstrate how a simple XML
framework could simplify the development of a Smart Card enabled application. You can use this code and
extend the framework to your needs, and I hope that these articles have shown you that using Smart
Cards could be quite simple.