
MULTOS smart cards overview
Introducing the MULTOS cardSmart cards contain an embedded integrated circuit chip. The chip itself is not directly visible or accessible on the card but is built into a “micro-module” consisting of a metal contact plate with thin bonding-wires connecting the contact pads to the chip. The chip, contact plate and bonding wires are mounted on a miniature circuit board giving a robust package that is subsequently glued into a milled recess within the plastic card. The chip is a complete microprocessor computer in its own right. It has ROM containing the operating system and also applications. It also has non-volatile memory for both application and data storage. The non-volatile memory is 68k EEPROM memory. There is also dynamic RAM for data storage whilst the chip is powered on. The chip is supplied with low-voltage power via the contact plate, which also provides the physical link to the serial communications between the chip and the smart card reader. For more information see ISO7816-2 and ISO7816-3. MULTOS for programmersMULTOS SmartDeck has all required native tools (compiler/linker/simulator) to develop smartcard applications (applets). You are free to chose Java or C compiler for Your projects. Multi-application cards are supported, witch means a single smatrcard can hold many applets onboard and this is perfect solution for scalable projetcs. MULTOS has native bignumbers and RSA libraries, witch allows to build highly-secure cryptography application easy and fast. Check out the eLoyalty applet sources (comes with SmartDeck) coded in C and Java. You will see it's easy to create own applications C source
/* eLoyalty application for SmartWorks C. */
// Note that if these pragma's are ommited then the SmartWorks loader
// will generate equivalents
#pragma attribute("aid", "f0 00 00 01")
#pragma attribute("dir", "61 10 4f 4 f0 00 00 01 50 8 65 6c 6f 79 61 6c 74 79")
#include <multoscomms.h>
#define ERR_OK 0x9000
#define ERR_WRONGCLASS 0x6402
#define ERR_BAD_INS 0x6404
#define ERR_UNDERFLOW 0x6406
#define CMD_ADDPTS 0x10 /* Add points to the card */
#define CMD_SUBPTS 0x20 /* Deduct some points from the card */
#define CMD_QRYPTS 0x30 /* Return the number of points currently on the card */
#define CMD_APPINFO 0x40 /* Returns info about the application */
#define CMD_QRYID 0x44 /* Returns the ID info */
#define CMD_SETID 0x42 /* Sets the ID info */
#define MYAPP_CLA 0x70
/* APDU structure for QRYID and SETID commands. */
typedef struct
{
char surname[20];
char otherNames[40];
} APDU_ID;
/* APDU structure for ADDPTS, SUBPTRS, and QRYPTS commands. */
typedef struct
{
int points;
} APDU_PTS;
/* APDU structure for APPINFO */
typedef struct
{
char info[17];
} APDU_APPINFO;
static APDU_APPINFO app_info = { "Loyalty " };
/* Data from APDU; this is placed at PB[0] */
#pragma melpublic
union
{
APDU_ID id;
APDU_PTS pts;
APDU_APPINFO info;
} apdu_data;
#pragma melstatic
/* Static data for application. */
static APDU_ID id = { "Curtis", "Paul Lyndon" };
int points = 100;
void
main(void)
{
int newPoints;
/* Check class in APDU. */
if (CLA != MYAPP_CLA)
ExitSW(ERR_WRONGCLASS);
/* Decode instruction. */
switch (INS)
{
case CMD_ADDPTS:
/* Ensure case 3 command. */
if (!CheckCase(3))
ExitSW(ERR_WRONGCLASS);
/* Award points. */
newPoints = points + apdu_data.pts.points;
break;
case CMD_SUBPTS:
/* Ensure case 3 command. */
if (!CheckCase(3))
ExitSW(ERR_WRONGCLASS);
/* Deduct points. */
newPoints = points - apdu_data.pts.points;
break;
case CMD_QRYPTS:
/* Ensure case 2 command. */
if (!CheckCase(2))
ExitSW(ERR_WRONGCLASS);
/* Report points. */
apdu_data.pts.points = points;
ExitLa(sizeof(APDU_PTS));
case CMD_QRYID:
/* Ensure case 2 command. */
if (!CheckCase(2))
ExitSW(ERR_WRONGCLASS);
/* Report ID. */
apdu_data.id = id;
/* Exit */
ExitLa(sizeof(APDU_ID));
case CMD_SETID:
/* Ensure case 3 command. */
if (!CheckCase(3))
ExitSW(ERR_WRONGCLASS);
id = apdu_data.id;
/* Exit */
Exit();
case CMD_APPINFO:
/* Ensure case 2 command. */
if (!CheckCase(2))
ExitSW(ERR_WRONGCLASS);
apdu_data.info = app_info;
/* Exit */
ExitLa(sizeof(APDU_APPINFO));
default:
ExitSW(ERR_BAD_INS);
}
/* Common processing for point change. */
if (newPoints < 0)
ExitSW(ERR_UNDERFLOW);
points = newPoints;
}
Java sourceimport com.multos.ifd.*;
import com.multos.framework.*;
public final class eloyalty
{
static final int ERR_UNDERFLOW = 0x6906;
// Commands understood by this application.
static final int CMD_ADDPTS = 0x10;
static final int CMD_SUBPTS = 0x20;
static final int CMD_QRYPTS = 0x30;
static final int CMD_APPINFO = 0x40;
static final int CMD_QRYID = 0x44;
static final int CMD_SETID = 0x42;
// APDU class this application responds to.
static final int MYAPP_CLA = 0x70;
// Personalisation data: surname.
static byte surname[] = {(byte)'C',(byte)'u',(byte)'r',(byte)'t',(byte)'i',(byte)'s',0,0,0,0,0,0,0,0,0,0,0,0,0,0};
// Personalisation data: fornames.
static byte forenames[] = {(byte)'P',(byte)'a',(byte)'u',(byte)'l',(byte)' ',(byte)'L',(byte)'y',(byte)'n',(byte)'d',(byte)'o',(byte)'n',0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
// Initialisation: 100 points already credited.
static int points = 100;
// Application information.
static byte info[] = {(byte)'L', (byte)'o', (byte)'y', (byte)'a', (byte)'l', (byte)'t', (byte)'y', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
public static void main()
{
int newPoints = 0;
// Check CLA.
if (APDU.getCLA() != MYAPP_CLA)
MULTOS.exitSW(ISO7816.ERR_CLASS_NOT_SUPPORTED);
// Get and decode INS.
int ins = APDU.getINS();
switch(ins)
{
case CMD_ADDPTS:
// Ensure ISO case 3 command
if (!APDU.checkCase(3))
MULTOS.exitSW(ISO7816.ERR_WRONG_LENGTH);
// Compute new points
newPoints = points + Util.getInt(APDU.data, 0);
// If we overflowed the number of points we can accumulate, error
if (newPoints < 0)
MULTOS.exitSW(ERR_UNDERFLOW);
// Credit points.
points = newPoints;
break;
case CMD_SUBPTS:
// Ensure ISO case 3 command
if (!APDU.checkCase(3))
MULTOS.exitSW(ISO7816.ERR_WRONG_LENGTH);
// Compute new points
newPoints = points - Util.getInt(APDU.data, 0);
// Error if not enough points on card
if (newPoints < 0)
MULTOS.exitSW(ERR_UNDERFLOW);
// Debit points.
points = newPoints;
break;
case CMD_QRYPTS:
// Ensure ISO case 2 command.
if (!APDU.checkCase(2))
MULTOS.exitSW(ISO7816.ERR_WRONG_LENGTH);
// Report points in R-APDU.
Util.setInt(APDU.data, 0, points);
// Exit setting La.
APDU.setLa(2);
break;
case CMD_QRYID:
// Ensure ISO case 2 command
if (!APDU.checkCase(2))
MULTOS.exitSW(ISO7816.ERR_WRONG_LENGTH);
// Copy from local surname and forename arrays to R-APDU data.
Util.arrayCopy(surname, 0, APDU.data, 0, surname.length);
Util.arrayCopy(forenames, 0, APDU.data, surname.length, forenames.length);
// Set La to reflect data length.
APDU.setLa(surname.length + forenames.length);
break;
case CMD_SETID:
// Ensure ISO case 3 command
if (!APDU.checkCase(3))
MULTOS.exitSW(ISO7816.ERR_WRONG_LENGTH);
// Copy surname and forename fields into permanent storage
Util.arrayCopy(APDU.data, 0, surname, 0, surname.length);
Util.arrayCopy(APDU.data, surname.length, forenames, 0, forenames.length);
break;
case CMD_APPINFO:
// Ensure ISO case 2 command
if (!APDU.checkCase(2))
MULTOS.exitSW(ISO7816.ERR_WRONG_LENGTH);
// Copy application information to R-APDU
Util.arrayCopy(info, 0, APDU.data, 0, info.length);
APDU.setLa(info.length);
break;
}
}
}
Fell free to contact us for any additional information.
MULTOS for customers- Shopping points
- Identification
- Applications security
- Licensing
- High-secure storage for sensative data
- Digital signature
- Access private web hosts using SSL
- Cryptography
Contact us, and we will help You to implement Your project on MULTOS in limited terms.
|