How to read a SLE4442/32 SmartCard using PCSC

Recently, I had to read bytes from a SLE4442 SmartCard in a Linux server(Ubuntu, as usual).

There are some alternatives to read/write these SmartCards, the most widespread is PC/SC-lite. In the PC/SC tools there is a valuable program called “scriptor”, which will allow you to send commands from STDIN to the card reader and get direct feedback from your card. This is useful when you are debugging, but in production I needed a small executable(Scriptor is a perl script) to run in the ramdisk(initrd) and print the card’s content to STDOUT.

Here is a small C program I created that will connect to the card reader, send two commands(Detailed below) and print the card’s content to STDOUT.
Commands(Hex notation):

  • Select Card Type, in this case SLE4432 or SLE4442 or SLE5532 or SLE5542.
    • Command: “FF A4 00 00 01 06”, this command powers down and powers up the selected card and performs a card reset.
  • Read card content
    • Command: “FF B0 00 XX YY”, this command reads the card memory at address XX, YY bytes long.

You can provide 2 parameters to the program, the first address to be read, and how many bytes. eg:

# Will read 128 bytes starting at the 32th byte.
$ ./smartCardRead 20 80
# Will read 16 bytes starting at the first byte.
$ ./smartCardRead 00 10

By default, it will read from the first address, 256 bytes.

Before trying to compile the program below, you need to install some packages:

apt-get install build-essential pcscd pcsc-tools libpcsclite1 libpcsclite-dev
  • build-essential – Basic packages needed to compile a program
  • pcscd – Daemon that will allow libpcsclite connect to card readers
  • pcsc-tools – Tools, like scriptor, pcsc_scan, etc.
  • libpcsclite1 – Library PC/SC-lite
  • libpcsclite-dev – Library headers files

After installing these packages, just create the two files below and run make.


CFLAGS=-pthread -I/usr/include/PCSC -c

all: main.o main

main: main.o
	$(CC) main.o $(LDFLAGS) -o readSmartCard

main.o: main.c
	$(CC) $(CFLAGS) main.c

	rm -rf *.o readSmartCard


#include <stdio.h>
#include <stdlib.h>
#include <winscard.h>

#define CHECK(f, rv) \
	if (SCARD_S_SUCCESS != rv) \
	{ \
		fprintf(stderr, f ": %s\n", pcsc_stringify_error(rv)); \
		return -1; \
#define CHECK_RESPONSE(buffer, bufferLength) \
	if(buffer[bufferLength-2] != 0x90 || buffer[bufferLength-1] != 0x00) { \
		fprintf(stderr, "Invalid response!\n"); \
		return -2; \

int main(int argc, char *argv[]) {
	LONG rv;
	DWORD dwReaders, dwActiveProtocol, dwRecvLength;
	LPTSTR mszReaders;
	BYTE pbRecvBuffer[266];
	unsigned int i;

	fprintf(stderr, "Smart Card reader - terciofilho -\n");

	BYTE cmdDefineCardType[] = { 0xFF, 0xA4, 0x00, 0x00, 0x01, 0x06 };
	BYTE cmdReadCard[] = { 0xFF, 0xB0, 0x00, 0x20, 0xC0 };

	if(argc != 3)
		fprintf(stderr, "Usage: %s FIRST_ADDRESS READ_LENGTH\nNo parameters provided, default values:\nFIRST_ADDRESS = 0x%X\nREAD_LENGTH = 0x%X\n", argv[0], cmdReadCard[3], cmdReadCard[4]);
		if(strtol(argv[2], NULL, 16) > 256)
			fprintf(stderr, "Invalid READ_LENGTH. Must be < 256.\n");
			return -3;
		cmdReadCard[3] = strtol(argv[1], NULL, 16);
		cmdReadCard[4] = strtol(argv[2], NULL, 16);
		fprintf(stderr, "FIRST_ADDRESS = 0x%02x\nREAD_LENGTH = 0x%02x\n", cmdReadCard[3], cmdReadCard[4]);

	rv = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext);
	CHECK("SCardEstablishContext", rv);

	rv = SCardListReaders(hContext, NULL, (LPTSTR)&mszReaders, &dwReaders);
	CHECK("SCardListReaders", rv)
	fprintf(stderr, "Reader name: %s\n", mszReaders);

	rv = SCardConnect(hContext, mszReaders, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, &hCard, &dwActiveProtocol);
	CHECK("SCardConnect", rv)

			pioSendPci = *SCARD_PCI_T0;

			pioSendPci = *SCARD_PCI_T1;
	dwRecvLength = sizeof(pbRecvBuffer);

	rv = SCardTransmit(hCard, &pioSendPci, cmdDefineCardType, sizeof(cmdDefineCardType), NULL, pbRecvBuffer, &dwRecvLength);
	CHECK("SCardTransmit", rv)
	CHECK_RESPONSE(pbRecvBuffer, dwRecvLength);

	dwRecvLength = sizeof(pbRecvBuffer);
	rv = SCardTransmit(hCard, &pioSendPci, cmdReadCard, sizeof(cmdReadCard), NULL, pbRecvBuffer, &dwRecvLength);
	CHECK("SCardTransmit", rv)
	CHECK_RESPONSE(pbRecvBuffer, dwRecvLength);

	for(i=0; i<dwRecvLength-2; i++)
		printf("%c", pbRecvBuffer[i]);

	rv = SCardDisconnect(hCard, SCARD_LEAVE_CARD);
	CHECK("SCardDisconnect", rv);

	rv = SCardFreeMemory(hContext, mszReaders);
	CHECK("SCardFreeMemory", rv);

	rv = SCardReleaseContext(hContext);
	CHECK("SCardReleaseContext", rv);

There is a manual out there, that is VERY helpful when sending commands to these cards, PMA-ACR38x(CCID)-6.02.

DISCLAIMER: I cannot guarantee that this code is bug free or will work in your setup. I’m not a C guru, I didn’t check all possible failure points.


How to cross compile libvpx for Windows in a Mac OS X


Here I’m again.

I’m working a secret project that needs to link agains libvpx in a Windows environment.

There is almost no information on how to compile libvpx, imagine cross compile in a Mac, well, none.

I successfully compiled it for Windows in a very simple fashion.


  • Xcode
  • MacPorts
  • git
  • mingw32 port installed
  • yasm assembler
  • Git clone of libvpx repository
  • 5 minutes of your time

I’ll not cover how to install XCode neither MacPorts, as it’s straightforward. Xcode can be installed via Mac AppStore, and MacPorts you just need to follow the instructions here. All commands above are intended to be copied and pasted in the Terminal window.

After MacPorts installed, run this command, just in case you already have MacPorts installed(It’ll update your port catalog and upgrade all installed ports):

$ sudo port selfupdate && sudo port upgradeoutdated

Then, we need to install the ports we need:

$ sudo port install i386-mingw32-binutils i386-mingw32-gcc i386-mingw32-runtime i386-mingw32-w32api yasm git-core

This will take some time, just rest and relax.

The next step you must run in a folder that you know, for example, ~/Code/, it’s up to you. Now, let’s clone the libvpx repository:

$ git clone
cd libvpx

This will create a folder called libvpx in the current folder.

In the configure script of libvpx there is a check that is broken in mingw, apply this patch to allow it to run smoothly:

$ patch -p1 << 'EOF'
diff --git a/configure b/configure
index 297cec4..196583a 100755
--- a/configure
+++ b/configure
@@ -555,9 +555,6 @@ process_detect() {
     check_header stdio.h || die "Unable to invoke compiler: ${CC} ${CFLAGS}"
-    check_ld <<EOF || die "Toolchain is unable to link executables"
-int main(void) {return 0;}
     # check system headers
     check_header stdint.h
     check_header pthread.h

It must print a line saying: “patching file configure”.

For the sake of simplicity, I created a script that will configure the toolchain to mingw, here it is:

$ cat > << 'EOF'
export CC=i386-mingw32-gcc
export CXX=i386-mingw32-g++
export CPP=i386-mingw32-cpp
export AR=i386-mingw32-ar
export RANLIB=i386-mingw32-ranlib
export ADD2LINE=i386-mingw32-addr2line
export AS=yasm
export LD=i386-mingw32-ld
export NM=i386-mingw32-nm
export STRIP=i386-mingw32-strip
exec "$@"

Make this script executable:

$ chmod +x

Well, all setup! Let’s configure:

$ ./ ./configure --disable-examples --disable-ssse3 --disable-multithread --enable-vp8 --target=x86-win32-gcc

You must see something like this:

Configuring selected codecs
  enabling vp8_encoder
  enabling vp8_decoder
  enabling vp9_encoder
  enabling vp9_decoder
Configuring for target 'x86-win32-gcc'
  enabling x86
  enabling runtime_cpu_detect
  enabling mmx
  enabling sse
  enabling sse2
  enabling sse3
  using yasm
  checking here for x86inc "x86" "" 
  enabling use_x86inc
  enabling postproc
  enabling unit_tests
Creating makefiles for x86-win32-gcc libs
Creating makefiles for x86-win32-gcc docs

Then, make the lib:

$ ./ make

Well, you will see some warnings, but if there is no errors, you are done!

Search for a libvpx.a file, use it to link against your application!

See ya!

Ps.: I couldn’t build it using multithreading. My project doesn’t need it, but I’m working on it…

– Update October, 25 2013 –

Added missing chmod in