Development

Table of Content

  1. How Can I Add Libchipcard Support to My Own Applications ?
  2. How Can I Use Libchipcard ?
  3. Data Organization On Chip Cards
  4. Sending Your Own Command to the Chipcard



1. How Can I Add Libchipcard Support to My Own Applications ?

Well, the easiest way is to use the automake/autoconf family of tools. To add libchipcard into your project your ./configure.in script should include these lines:

AC_LIBCHIPCARD(0.8.0)
if test -n "$libchipcard_dir"; then
all_libraries="$all_libraries $libchipcard_libs"
all_includes="$all_includes $libchipcard_includes"
AC_DEFINE(HAS_LIBCHIPCARD)
define_has_libchipcard="#define HAS_LIBCHIPCARD"
fi
AC_SUBST(define_has_libchipcard)
Table: Lines to be included in configure.in

You'll need to add a line saying #undef HAS_LIBCHIPCARD to your acconfig.h file, otherwise aclocal/autoconf/automake will complain about HAS_LIBCHIPCARD not being covered by config.h.

Your Makefile.am files could then look like this (taken from tutorial subdir):

noinst_PROGRAMS=tutorial1
INCLUDES=@all_includes@

tutorial1_SOURCES = tutorial1.cpp
tutorial1_LDADD = @all_libraries@
Table: Example .Makefile.am

If you want optional support for libchipcard then you can use this in your *.cpp/*.c/*.h files:

#ifdef HAVE_CONFIG_H
# include <config.h> // need this to define HAS_LIBCHIPCARD
#endif

#ifdef HAS_LIBCHIPCARD
# include <chipcard.h>
// insert code that uses libchipcard
#endif
Table: Example test.cpp

With this in your program files you can use LibChipCard if available or exclude chipcard support if LibChipCard is missing. This is the way OpenHBCI handles it.

Top


2. How Can I Use Libchipcard ?

Below is a simple graph which shows the most interesting classes.

CTCard inheritance

From the developers point of view the class CTCard (and its children) is the most important one. This in fact is the only class you have to deal with. Therfore we'll have a look at this one and will later discuss the inheriting classes.

Introduction Into Communication With Chipcards

Generally, a program sends some specific commands to the chipcard via the reader (terminal), this is the so called APDU. It contains at least:
Name Description
CLA this is the command class byte (in most cases this is 0)
INS the instruction byte, specifiying what the card is supposed to do
P1 first parameter byte, depends on the instruction the card has to perform
P2 second parameter byte, depends on the instruction, too

This APDU (plus some other control and data bytes) is all packed into a struct called CTCommand (please refer to the API documentation for it's content) and send to the card via the reader.
After the cards response Libchipcard returns the answer and the result code in the very same struct.
As you can see CTCommand is the central object in a dialog with a chip card.

CTCard

Now, to communicate with the card, you need to setup the described CTCommand struct and feed it to CTCard's method execCommand. This method actually sends the APDU from this struct to the card and retrieves its answer.

Well, before you can send anything to the card you must prepare it by calling CTCard::openCard(). This method loads the appropriate driver library (CTAPI), initializes the card reader (if it not already is) and connects the card to the reader. If this succeeds you can start sending commands.

After you have finished working with the card you may want to release it, thus allowing the user to remove the card safely from the reader. This can be achieved by calling CTCard::closeCard().

There are some other interesting methods in this class, but these are the most important ones. Please refer to the api documentation (downloadable in a separate package from the project page, see this site's download section).

CTMemoryCard

Since there are two basic types of chipcards - memory cards and processor cards - libchipcard offers one class for each of them.

This class provides some basic methods which simplify accessing memory cards (like German health insurance cards). These methods allow you to

The implementation is simple: These methods all create CTCommand objects, fill them with appropriate data for the corresponding instruction, send this command to the card via execCommand() and return the result in a CTError object. If you want to check for an error simply call the method isOk() of this CTError object.

You should look at the source of this class to see how simple it is to implement new commands.

CTProcessorCard

This is the other basic class, it works on processor cards (like EC cards and HBCI cards).
You can:

Support For Special Cards

Generally, libchipcard offers basic support for chip cards.
However, there are two kinds of special chip cards this library supports directly:

This support is indicated by the existence of the classes

Top


3. Data Organization On Chip Cards

A chip card normally has the following structure:
mf-df-ef

Master File

The master file is the root of the data on the chip card (referred to as "MF" throughout the api documentation). As with The Highlander there can only be ONE master file. This master file may have some "dedicated files"("DF") and "element files" ("EF").

Dedicated File

This is best described as a kind of directoy, which includes element files. A dedicated file itself does not contain data. You can select such a data file using the various "selectXX" methods of the card classes.

Element File

An element file now finally contains the data. You can select such an element file using the various "selectXX" methods of the card classes.

To make it more complicated some cards (mostly memory cards, like German health insureance cards) do not have data files or element files at all. They store their data directly in the master file. And these cards do NOT allow calling the "selectFile" method with other values than "0x3f00", which specifies the master file.

But that looks more complicated than it really is, because you rarely try to read cards you don't have the slightest piece of information for. In most cases the documentation for the card you want to read tells you if there are some data/element files to select.

For example the German health insureance card does NOT have those files and therefore you can read the data directly from the master file after and even without selecting it (with selectFile(0x3f00)).


Top


4. Sending Your Own Command to the Chipcard

Now that you know how data is stored on a chip card and how commands are send to the card we can play around with it. Let's create an example that selects a file on a memory card. To make this example be of use in any case we simply select the Master File which is accessable on nearly all memory cards (remember, the simplest memory card is the German medical card, so you can use it for this example). Well, of course, selecting a file can be done more easily with the already existing methods of CTProcessorCard and CTMemoryCard, but hey, it's just an example ;-)
This code assumes to be part of a class which inherits CTCard, so the method execCommand() is available. Another assumption is that the card has already been openend via openCard().
We'll see the code first and discuss later.

CTCommand cmd; // we need this to send a command to the card
CTError err; // this object will receive the error code our command returns
cmd.setCla(0x00); // class the command belongs to
cmd.setIns(0xa4); // the code of the command Select File
cmd.setP1(0x00);
cmd.setP2(0x0);
cmd.setLr(255); // expected length of the answer from card
cmd.setData((char) 0x3f); // file id (High byte first)
cmd.addData((char) 0xff); // file id (Low byte)
err=execCommand(cmd);
if (err.isOk()) return true; // return if there was no error
printf("Error was: %s\n",err.errorString().c_str()); // show the error code if there was an error

Ok, let's now discuss the code line by line. What I did not show in this example was that the command may have returned some data. If you are interested in that data you can find it in the member CTCommand::data (in our case this is cmd.data).

Well, isn't it easy to send a command to the card ? This is the way other classes implement new commands. As you already know the class CTCard only contains very basic commands which are encapsulated int some methods, like CTCard::openCard() and so on.
Inheriting classes simply define new methods which themselves send commands to the chip card by exactly the way described above.
So the command you see above is derived from a fragment of the method CTMemoryCard::selectFile().
In fact you should never call the method CTCard::execCommand() directly, better write a class which inherits CTCard and place the command execution there, thus encapsulating access to the chip card.

If you have written a class that includes commands usefull for a special card type (like cell phone cards) I would absolutely appreciate if you send them to me.
I would gladly incorporate these classes into future versions of libchipcard after testing them and name you as the author of that class.