A Low-Level Vicomp Mobile Reader Communication Interface for Windows

Total Page:16

File Type:pdf, Size:1020Kb

A Low-Level Vicomp Mobile Reader Communication Interface for Windows

Copyright © 2014 Vicomp Ltd All rights reserved

VicompNativeAPI

also known as VicompLowAPI

A low-level Vicomp mobile reader communication interface for Windows

When thinking about programming any of our mobile OCR-ONLY reader (e.g. VPR460, VPR470) communication seems quite easy. You don't need any special API from Vicomp. After bounding the reader in Windows you get a Bluetooth virtual COM port. Simply, open it and listen for incoming OCR MRZ (Machine Readable Zone) ASCII strings (single byte characters) generated after each document swipe (StartOfText = 0x02 ... EndOfText = 0x03). That’s all. Don’t waste time reading this guide; just start writing your code.

However, when it comes to programming any of our OCR+RFID mobile reader things become a little bit more complicated. OCR and RFID modules are not independent from each other. There is only one Bluetooth virtual COM port they share for communication. Moreover, because of some special energy saving and OCR/RFID switching procedures, there is no standard PC/SC driver available for RFID module. Instead, we supply a low-level communication interface with PC/SC-like SCardTransmit routine. Remember this: As you don't know details of the reader low-level communication protocol, you will not be able to perform OCR+RFID activity without at least VicompNativeAPI. Read this short guide carefully before you start writing your code. Introduction

All of our mobile Bluetooth readers are powered from their own batteries. To make their working time as long as possible there are some special, sophisticated energy saving techniques implemented in the firmware. The reader goes to sleep when possible and is not visible to the host machine. Thanks to this, our reader is able to handle several thousands eDocuments without the need of charging its batteries. As this is one of the most important parameters of mobile devices we’re going to preserve this solution while developing our mobile readers. On the other hand, you must be aware there is no conventional PC/SC driver available for RFID module of the reader. To implement the reader in your application you have to take advantage of, at least, one of our special SDKs – VicompNativeAPI (for historical reasons also known as VicompLowAPI). It’s a low-level communication interface you have to get, learn and use.

You will find following functions in the API:

Open (opens reader Bluetooth virtual COM port) StartMonitor (starts OCR/RFID activity monitoring thread) ScardTransmit (PC/SC-like communication routine sending and receiving chip data) StopMonitor (stops OCR/RFID activity monitoring thread) Close (closes reader Bluetooth virtual COM port)

VicompNativeAPI covers both, OCR and RFID modules. You have only one virtual COM port to handle optical (OCR) and electronic (RFID) data. Remember, VicompNativeAPI allows you to transfer data to/from the reader but it’s you, who must know the „language and rules” of talking to eDocument chip application. You have to know, and implement, difficult cryptographic procedures related to Secure Messaging keys computations, BAC, PACE aka SAC and EAC sessions, AA, PA, CA, TA, etc. You have to realize JPEG, JPEG2000 and FBI-WSQ image handling yourself as well.

2 To get rid of all these complicated stuff you can use our VicompHighAPI, performing complete BAC/PACE/EAC/AA/PA/CA/TA/JPEG/JPEG2000/WSQ operations for you by means of just one function call: StartRfidSession. But, this is quite different story. Ask if interested. And now let’s get back to VicompNativeAPI details.

Installation Notes

Download VicompSoftEngine installation utility from our web site: http://www.vicomp.com.pl/downloads/instVicompSoftEngine.exe or http://www.vicomp.com.pl/downloads/instVicompSoftEngine.zip

Run the installation utility as an administrator. All necessary stuff is copied to different places in the system. One of those locations may be important for you. It is :\Program Files (x86)\Vicomp\SoftEngine\API

Selected items in the screenshot above are related to the VicompNativeAPI. Not all of them may be important for you. It depends on the programming environment you use. For example: libVicompNativeAPI.a – import library for Microsoft Visual Studio C++ projects VicompNativeAPI.lib – import library for Borland/Embarcadero C++ projects

If you develop application using C#/.NET then above mentioned import libraries are not important for you as you will declare and use VicompNativeAPI.dll directly from your C# code. However, VicompApiBase.h C++ header file is of

3 great importance, even if you don’t use C++ IDE. This file contains constants and functions definitions/declarations that you have to know. See the part of VicompApiBase.h that is related to VicompNativeAPI at the end of this guide. Finally, look at the VicompNativeApiSampleC++Builder source code to get general impression of how things should be implemented.

Quick Start

You will use functions from the VicompNativeAPI.dll located in the system folder. Do not change location of this file by copying it to your application working folder. As mentioned earlier, learn interface details from VicompApiBase.h (function declarations, return codes, messages, defines etc.)

First, declare a callback routine that will receive and handle messages from the API. See the VicompNativeApiSampleC++Builder project source code to learn how to implement this function for message handling. int __stdcall VicompCallback( unsigned int msg, unsigned int wparam, int lparam );

After you start your application open the reader virtual COM port. In case of Bluetooth reader it must be outgoing one. int irc; // integer return code irc = vicomp_nativeapi_Open( comName, VicompCallback, VICOMP_HIGH_BAUD ); // every time perform error checks before continuing execution if ( irc != VICOMP_SUCCESS ) { // error, show message and don’t continue }

After successfully opened port, start monitoring thread. int wait_for_chip = 5; // wait 5 seconds after swipe irc = vicomp_StartMonitor(wait_for_chip);

4 If you don’t want RFID module to be activated (OCR-ONLY mode) set wait_for_chip = 0.

If monitor started successfully get ready for handling messages sent to your callback routine (message / wParam / lParam). First, you are supposed to receive following message msg = VICOMP_MSG_OCR_MONITOR wParam = VICOMP_START lParam = 0

Now, you’re in a stable state. The reader is waiting for a swipe operation to read and recognize optical MRZ data. After correct swipe you get msg = VICOMP_MSG_OCR_MRZ wParam = data length lParam = pointer to data buffer

Now, the reader automatically activates RFID module (if chip_wait_time > 0). You know exactly this moment as you receive following sequence VICOMP_MSG_OCR_MONITOR / VICOMP_FINISH / 0 VICOMP_MSG_RFID_MONITOR / VICOMP_START / 0

RFID module remains active for specified time interval waiting for an electronic chip in range. This waiting condition is signaled by the following notification message VICOMP_MSG_RFID_MONITOR / VICOMP_NOTIFY / time left

If electronic chip will not be detected during this time RFID is turned off and OCR activated. VICOMP_MSG_RFID_MONITOR / VICOMP_FINISH / 0 VICOMP_MSG_OCR_MONITOR / VICOMP_START / 0

However, if electronic document is detected by the reader you get Msg = VICOMP_MSG_RFID_CHIP wParam = VICOMP_ENTER lParam = pointer to chip information

Note here that monitoring thread was aborted. This is because you take full control over communication with a chip at this moment. If monitor was active it would disturb your transmissions. And the most difficult part of the work begins. You have to know ICAO ePassport application details, APDU commands and RAPDU responses. Use vicomp_nativeapi_ScardTransmit

5 function to send and receive data. See the VicompNativeApiSampleC++Builder project source code for details. However, the sample is limited to reading only plain, not protected chips.

After you read all necessary electronic data from a chip you have to restart reader monitoring thread using vicomp_nativeapi_StartMonitor function and you are again at the beginning of the reading loop.

While terminating your application do not forget to make all necessary cleaning. vicomp_StopMonitor(); // terminate monitor thread vicomp_Close(); // close Bluetooth virtual COM port

It‘s strongly recommended to start your RFID reading trials with plain (not protected) chips. After you get an idea of VicompNativeAPI structure and usage it will be easier for you to study and implement difficult procedures required to handle BAC, PACE and EAC protected documents. Otherwise, they are likely to obscure relatively simple VicompNativeAPI concept.

When you get tired with errors and failures do not give up. We know the task is not simple. We have some experience in the field. Maybe we will be able to help you find the right way out. For the fastest possible response write directly to our software staff: [email protected]

6 VicompNativeAPI defines and declarations (from VicompApiBase.h C++ header file)

// Common for all Vicomp APIs ------

#define VICOMP_SUCCESS ( 0 ) #define VICOMP_ERROR ( -1 ) #define VICOMP_SKIP ( -2 )

// The basic concept of all Vicomp APIs is user-defined callback function. // The APIs call this function to signal different events and/or exchange // information and data with the application. // See programming samples source code to learn how to implement the callback. typedef INT ( __stdcall *VICOMP_CALLBACK )( UINT message, UINT param1, INT param2 );

#ifdef BUILD_DLL #define DLL_EXPORT __declspec(dllexport) //used by Vicomp when building the api #else #define DLL_EXPORT __declspec(dllimport) //used by the user when building an app #endif

// ------Common for all Vicomp APIs

// VicompNativeAPI ------

#define VICOMP_LOW_BAUD 9600 #define VICOMP_MID_BAUD 115200 #define VICOMP_HIGH_BAUD 460800

#define VICOMP_CHIP_WAIT_TIME_NATIVE_DEFAULT 5 // seconds #define VICOMP_CHIP_WAIT_TIME_PCSC_DEFAULT 0 // seconds

// VicompNativeAPI messages

#define VICOMP_MSG_NATIVE_API_BASE WM_APP //native messages up to WM_APP+4999

#define VICOMP_MSG_OCR_MONITOR ( VICOMP_MSG_NATIVE_API_BASE + 100 )

7 // majorParam = VICOMP_START, minorParam = VICOMP_SUCCESS or VICOMP_ERROR // VICOMP_FINISH, minorParam = VICOMP_SUCCESS or VICOMP_ERROR

#define VICOMP_MSG_OCR_MRZ ( VICOMP_MSG_NATIVE_API_BASE + 200 ) // majorParam = number of characters (bytes) // minorParam = pointer to the raw MRZ contents (incl. STX/ETX & CR/LF)

#define VICOMP_MSG_RFID_MONITOR ( VICOMP_MSG_NATIVE_API_BASE + 300 ) // majorParam = VICOMP_START, minorParam = VICOMP_SUCCESS or VICOMP_ERROR // VICOMP_NOTIFY, minorParam = seconds left for RFID being active // VICOMP_FINISH, minorParam = VICOMP_SUCCESS or VICOMP_ERROR

#define VICOMP_MSG_RFID_CHIP ( VICOMP_MSG_NATIVE_API_BASE + 400 ) // majorParam = VICOMP_CHIP_ENTER, minorParam = ptr to VICOMP_CHIP_NATIVE_INFO // structure // VICOMP_CHIP_EXIT, minorParam=0 (not used for native BT reader)

#define VICOMP_MSG_RFID_PROGRESS ( VICOMP_MSG_NATIVE_API_BASE + 500 ) // the message is sent continuously while reading large elementary files (more // than 2KB=2048bytes) by means of vicomp_native_ReadFileFast() API function // majorParam = data group identifier (2,3,4), minorParam=% of reading completion

// Address of the following structure is returned // in minorParam of the VICOMP_MSG_RFID_CHIP callback message struct VICOMP_CHIP_NATIVE_INFO { BYTE SerialNumber[64]; INT SerialNumberLen; INT MaxHardFrameSize; // 256 bytes is expected for modern rfid chips INT MaxPlainDataSize; // 245 bytes ... INT MaxCryptDataSize; // 223 bytes ... INT MaxAirBaudRate; // 424 or 848 Kbps ... }; // majorParam for VICOMP_MSG_..._MONITOR messages #define VICOMP_FINISH 0 #define VICOMP_START 1 #define VICOMP_NOTIFY 2 #define VICOMP_NOTIFY_EXT 3

// majorParam for VICOMP_MSG_RFID_CHIP message #define VICOMP_CHIP_ENTER 1 #define VICOMP_CHIP_EXIT 0 // not used for native BT reader

8 // The first API function to be called at startup of the user app extern "C" int DLL_EXPORT __stdcall vicomp_nativeapi_Open( CHAR *com_port_name, VICOMP_CALLBACK api_callback, DWORD com_port_baud_rate = VICOMP_HIGH_BAUD ); // com_port_name: Bluetooth virtual COM port name (e.g. "COM7", "com23"): // INCOMING for VPR451e and its ancestors, // OUTGOING for VPR460e and its successors // or // USB virtual COM port name for USB readers // com_port_baud_rate: VICOMP_HIGH_BAUD for all Bluetooth and USB >= VPR620e // VICOMP_LOW_BAUD for USB < VPR620e // api_callback: A routine implemented by the user that will be called by the API. // return: VICOMP_SUCCESS or VICOMP_ERROR. If specified port is already opened // VICOMP_ERROR will be returned (could not open already opened port). // ------

// ------// This is very important function that should be called at startup and then, // immediately, after completion of every RFID session performed by the user. extern "C" int DLL_EXPORT __stdcall vicomp_nativeapi_StartMonitor( INT chip_wait_time = VICOMP_CHIP_WAIT_TIME_NATIVE_DEFAULT ); // chip_wait_time: Time to wait for a chip after each swipe (reading MRZ data). // After starting the monitor, OCR module is activated first, // waiting for a swipe. After MRZ arrival, OCR module is turned // off and RFID one started for chip_wait_time seconds. // After the chip is detected RFID module is turned off and you // get exclusive control over the communication. // After you complete the work do not forget to use this function // to restart monitoring process. // If a chip is not detected during this time RFID module is // turned off and OCR module activated automatically. // If set to 0, only OCR input will be monitored and RFID module will // not be activated after MRZ arrival. OCR monitor will be active // all time and you don't have to restart it yourself. // return: VICOMP_SUCCESS or VICOMP_ERROR. // ------

9 // ------// A general-purpose, PC/SC-like data transfer function. By means of this only // function you can implement all the required communication. However, take a // look at the next two routines that may be easier to use for simple, basic // tasks. extern "C" int DLL_EXPORT __stdcall vicomp_nativeapi_SCardTransmit( BYTE *capdu, DWORD capdu_len, BYTE *rapdu, DWORD *rapdu_len ); // capdu: Command APDU, a byte array to be send to the card as it is, without // any additional formatting by the API. It is user responsibility to // create appropriate CAPDUs for different purposes. Particularly, in // case of protected documents (Secure Messaging protocol) you have to // encrypt the command using some external cryptographic tools. // capdu_len: Actual, total length (in bytes) of CAPDU // rapdu: Response APDU, a byte array sent back by the card as a response for // CAPDU. It is user responsibility to interprete this response properly. // Particularly, in case of handling protected documents and performing // Secure Messaging protocol you have to dencrypt and verify encrypted // response using some external cryptographic tools. // rapdu_len: Actual, total length (in bytes) of RAPDU. RAPDU should not be // shorter than two bytes (Status Word SW = [SW1][SW2], usually // SW1=0x90 SW2=0x00 in case of successfull processing). // return: VICOMP_SUCCESS or VICOMP_ERROR. The API does not analyse SW1/SW2 // status word, it is your task. In other words, for example, you will // get VICOMP_SUCCESS function return code while SW1=0x69 SW=0x82 that // means OPERATION FAILED, SECURITY CONDITIONS NOT SATISFIED. // // IMPORTANT NOTE: It is allowed for the length of capdu data block to be of any // size (larger than single transfer data size). In this case the API internally // performs so called command chaining, according to ISO. // ------

// ------// This is the first function to call after the chip is detected. You may not // be able to select and read elementary files (data groups) without previous // selection of the ICAO MRTD (ePassport) application. extern "C" int DLL_EXPORT __stdcall vicomp_nativeapi_SelectIcaoMrtdApp( VOID ); // return: VICOMP_SUCCESS or VICOMP_ERROR. // ------

10 // ------// Obviously, any file from the chip may be successfully read by using universal // vicomp_native_SCardTransmit function (see above). However it is strongly // suggested to use our special method that performs reading several times // faster (some special Vicomp native boosting secrets). Note, there is no // offset and/or byte count arguments, entire file is read by this routine. extern "C" int DLL_EXPORT __stdcall vicomp_nativeapi_ReadFileFast( BYTE *file_id, BYTE *buf = NULL, BYTE *ssc = NULL, BYTE *k_enc = NULL, BYTE *k_mac = NULL ); // file_id: Elementary file identifier (0x011F for EF.COM, 0x0101 for EF.DG1 etc.) // buf: Memory buffer to receive data, if you supply NULL pointer you will get // size in bytes of currently selected file on return. This may be useful // to know the size of memory to allocate for data buffer. // ssc, k_enc, k_mac: 8, 16, 16 bytes length memory buffers respectively. // Cryptographic parameters to be used when executing // Secure Messaging protocol (SM) for protected chips. // You will get them after performing BAC/PACE/CA protocols. // It is your responsibility to use appropriate external // cryptographic tools for this purpose. // Set them all to NULL to execute plain (not protected) // transfers. // return: VICOMP_SUCCESS or VICOMP_ERROR. However, there is a special case when // you set buf to NULL. In this case the function returns total number // of bytes contained in selected file (file size) or VICOMP_ERROR // in case of failure. // // IMPORTANT NOTE: On return cryptographic parameters contain updated (current) // values that you can use for successive calls. // ------

// ------// You CAN call this function anytime you want to stop monitor manually (rare // cases in normal operation) but you HAVE to call it before calling // vicomp_native_Close (next routine) on application shutdown if monitor is active. extern "C" int DLL_EXPORT __stdcall vicomp_nativeapi_StopMonitor( VOID ); // return: VICOMP_SUCCESS or VICOMP_ERROR // ------

11 // ------// The last API function to be called before shutdown of the user app. extern "C" int DLL_EXPORT __stdcall vicomp_nativeapi_Close( VOID ); // return: VICOMP_SUCCESS or VICOMP_ERROR. If the port is already closed // VICOMP_ERROR will be returned (could not close already closed port). // ------

// ------VicompNativeAPI

12

Recommended publications