Date | Description | Author |
06/06/2006 | Initial release | Johann Dantant |
Desfire version 6
JayCOS Appli 1.2
In real-world applications, cards typically have three life phases :
The init state is when the card come out of factory. A specific sofware has been loaded into card's ROM to implement the expected features
(ticketing, purse, passport, credit card...) ; card already has its data structure, but all records are blank.
Then the card issuer insert holder's data into card's records (personalisation process) and delivers the card to its holder. The card is now
in use until it can't be used anymore (blocked state, typically card will expire after a limited period of validity).
In our sample applications, we use general purpose cards that basically provide only a data storage application. On one hand, Desfire and JayCos are micro-controller based cards that offer advanced security features and organise their memory with directory and files (more or less as specified by ISO/IEC 7816-4), on the other hand Mifare and Mifare UltraLight provide only an flat memory structure (with a weak security scheme or no security at all), but both families are versatile enough for us to implement all our applications without embedding any specific software into the card itself.
Therefore, our cards will have four life phases :
The blank state is when the card come out of factory. There's no data structure.
First of all, we have to create our data structure into card's persistent memory, and load our security keys. This phase is known as
pre-personalisation or formatting. Once the card is formated, the issuer can personalize the card, give it to the holder, and so on...
Since we are not building real-world application, it is interesting to re-use the card after a few demonstrations. Therefore, the blocked state will always be «virtual», it will always be possible to erase the whole card and have it back in blank state (note that disposable single trip ticket applications on a Mifare UltraLite card shoul'd make use of a One Time Programming block that can't be erased after use. Our sample applications will use a reguler block instead).
Field | Description | Size | Note |
---|---|---|---|
LastName | Last name of the user | 32 | If shorter than 32, padded with 00 |
FirstName | First name of the user | 32 | If shorter than 32, padded with 00 |
Company | Company or service | 24 | If shorter than 24, padded with 00 |
Title | Job title or any interesting information | 24 | If shorter than 24, padded with 00 |
BirthDate | Date of birth | 3 | Format : yymmdd |
RFU | 13 | This field is currrently not used |
Total size : 128 bytes.
To be written
Total size : 170 bytes.
The picture file is only a BLOB (binary object) where an image file can be copied to. Actual image type and size is documented in the options and signature structure.
Total size : this file takes the maximum number of bytes still available on the card after having implemented all other items.
We target cards with 4kB of EEPROM or less, so size of the picture will be limited to 2 to 2,5kB. This is enough to store a small JPEG picture, but at lowest quality only. Using JPEG-2000 gives a better quality in the same size, but to ease development for PocketPC or Windows devices that don't include native JPEG-2000 support yet, we work with classic JPEG pictures only.
To be written
Total size : 48 bytes.
Field | Description | Size | Note |
---|---|---|---|
UserId | Unique ID of holder | 4 | Can be the link to a database or enterprise directory |
StartDate | First day of validity | 3 | Format : yymmdd |
EndDate | Last day of validity | 3 | Format : yymmdd |
FingerprintsType | Type of fingerprints minutiae | 1 | 1 = SAGEM. 0 if no fingerprint |
PictureType | Type of picture | 1 | 1 = JPEG, 2 = JPEG-2000. 0 if no picture |
PictureSize | Size of picture, in bytes | 2 | 16-bit unsigned integer, MSB first. 0 if no picture |
RFU | 2 | This field is currrently not used | |
FastSignature | Signature used for physical access control application | 8 | See "security scheme" below |
FullSignature | Signature of the whole Corporate ID data | 8 | See "security scheme" below |
Total size : 32 bytes.
To be written
To be written
To be written
Key | Value | Diversified by card SNR | SAM key # & version |
---|---|---|---|
Corporate ID Master Key 0 | 00 00 0B 00 00 50 41 01 00 00 1B 00 00 50 41 01 | Yes | 2 - 23 |
Corporate ID Master Key 1 | 00 00 0A 00 00 50 41 01 00 00 1A 00 00 50 41 01 | Yes | 3 - 03 |
Corporate ID Signature Key | 00 00 0F 00 00 50 41 01 00 00 1F 00 00 50 41 01 | No | 4 - 23 |
This application is a basic electronic purse, such as the ones used in private payment applications (cofee or vending machines, company restaurant, sport clubs...).
Customer loads his purse at issuer desk (either with his credit-card, check, or cash). The balance is increased by the loaded value. An event is added to the re-load history.
When customer buys something, the purse is charged by the vendor device : balance is decreased by the charged value, and an event is added to the purchase history.
Desfire and JayCos cards offer counter-type files and cyclic record files to implement the whole scheme easily.
Mifare 1k (or 4k) cards also provide value-type blocks (but with a lower security level) ; history features must be implemented «manually».
Mifare UltraLight cards haven't any security features, and are not suitable for this application.
Balance is a value file or counter file. We use 32 bits signed integer, but only positive integers are allowed. Value is limited to 50000 to prevent forgery by a malicious re-loading device.
The re-load structure stores data collected when holder buy new credits.
Field | Description | Size | Note |
---|---|---|---|
Timestamp | Event date and time | 5 | Format : yymmddhhnn |
Issuer | Unique identifier of credit issuer | 4 | |
Payment | How did holder bought his credits ? | 1 | (Informative only) |
Credit | Added amount | 2 | 16-bit unsigned integer, MSB first |
NewBalance | New balance after re-load event | 4 | 32-bit unsigned integer, MSB first |
Total size : 16 bytes
The card must provide a rotating file to log the re-load events.
The purchase structure stores data related to a purchase event.
Field | Description | Size | Note |
---|---|---|---|
Timestamp | Event date and time | 5 | Format : yymmddhhnn |
Merchant | Unique identifier of merchant or store | 4 | |
Vendor | Identification of cashier or vendor in store | 1 | |
Debit | Charged amount | 2 | 16-bit unsigned integer, MSB first |
VendorData | Vendor specific data | 4 | (Informative only) |
Total size : 16 bytes
The card must provide a rotating file to log the purchase events.
To be written
Key | Value | Diversified by card SNR | SAM key # & version |
---|---|---|---|
Purse Master Key 0 | 00 00 0B 00 00 50 41 02 00 00 1B 00 00 50 41 02 | Yes | 5 - 22 |
Purse Master Key 1 | 00 00 0A 00 00 50 41 02 00 00 1A 00 00 50 41 02 | Yes | 6 - 02 |
This application aims to provide a versatile ticketing scheme for metropolitan transport networks (bus, subway, railway ...). It has been designed in order to be really easy to understand, yet with EN-1445 in background.
Customer buy a contract to a transport provider. The contract is valid on a specific network, during a certain validity period.
If the contract is a «pass», then customer can use the ticket for an unlimited number of trips during the validity period. Overwhise, usage of the ticket is limited by a counter.
The counter-based contract can either offer a limited number of «tickets» or «coupons». In tickets mode, counter is decreased when customer enters the network ; this means that he pays a fixed price whatever the distance. In coupons mode, counter is decreased only when customer leaves the network, and the price paid depends on the actual trip done.
Using Desfire and JayCos cards we can implement the whole scheme up to 3 contracts. There is no need for static authentication : card and reader mutual authentication is done on a per-transaction basis. Sample applications will use the Desfire SAM to store the keys in a secure manner.
With Mifare 1k (or 4k) cards we limit us to 1 contract. A static authentication block must be added to check that card is genuine.
On Mifare UltraLight we implement only an inexpensive disposable single-trip ticket with 1 contract. A static authentication block must be added to check that card is genuine.
The contract structure defines either a transport ticket (single trip or usage based) or a transport pass.
Field | Description | Size | Note |
---|---|---|---|
Priority | Priority of the contract | 1 | When more than one contracts are valid simultaneously on the same network, the one with higher priority is choosen |
Network | Unique identifier of transport network | 3 | |
ProviderId | Identifier of service provider in the network | 1 | |
CustomerId | Unique identifier of customer | 4 | |
Passengers | Number of passengers covered by the ticket | 1 | |
Mode | Mode of operation | 1 |
Possible values are :
|
Areas | Allowed areas | 1 | Bitmap of allowed areas in the network |
Class | Passenger class | 1 | Allowed vehicle classes |
Counter | Counter to be used with this contract | 1 | Allowed values are 1 to 3, 0 means no counter. Many contracts may share the same counter if needed, overwhise the issuing application must ensure that the new contract will be related to an usused counter. |
ValidWeekDays | Valid days in week | 1 | Bitmap of valid days (0x01 = monday, ... 0x40 = sunday) |
ValidTotalDays | Max number of days after first trip | 1 | 0 means no limit |
StartDate | First day of validity | 3 | Format : yymmdd |
StartHour | First hour of validity | 1 | From 0 to 23 (seen as 0h00 to 23h00) |
EndDate | Last day of validity | 3 | Format : yymmdd |
EndHour | Last hour of validity | 1 | From 0 to 23 (seen as 0h59'59" to 23h59'59") |
Certificate | Signature of contract data | 8 | See "static authentication" in the "security scheme" part below |
Total size : 32 bytes.
The card can support more than one contract. All contracts share the same log.
The event structure defines either an event related to the usage of a transport contract.
Field | Description | Size | Note |
---|---|---|---|
Timestamp | Event date and time | 5 | Format : yymmddhhnn |
Network | Unique identifier of transport network | 3 | |
Contract | Reference of the selected contract | 1 | Allowed values are : 1, 2 or 3 |
Action | Number of days remaining | 1 | See below for the list of actions |
Location | Unique identifier of the place where the event occured | 3 | This is typically the ID of the station where passenger enters or leaves the network |
RemainingDays | Number of days remaining | 1 | The validator decreases the days starting from ValidTotalDays 0 means no limit |
Counter | Counter used with this contract | 1 | |
Charged | Value charged in counter | 1 |
Total size : 16 bytes
The card must provide a rotating file to log the events. All contracts share the same log file.
Each contract can use its own in tickets or coupons mode. We use 32 bits signed integer, but only positive integers are valid.
Mifare cards provide only weak symetric cryptography, and key forgery, if it is really difficult, is not impossible. If a defrauder is able to find the Mifare authentication key used by the application, he becomes able to write cards that will look as if they were issued by the genuine authority. To overcome this, we add a static MAC (message authentication code) on the card, computed over card's data and card's unique identifier (its serial number).
Mifare UltraLite cards provide no security at all (they all freely readable in all circunstance), so in this case static authentication is the only counter-measure against card cloning.
Micro-controller cards (Desfire, Jaycos...) use strong symetric cryptography to perform mutual authentication between reader and card. Therefore, card can be trusted as soon as it share the same secret key as the reader. Anyway, we choose to keep the static authentication block, in order to have the same code running with no difference on micro-controller or memory cards.
Key | Value | Diversified by card SNR | SAM key # & version |
---|---|---|---|
Transport Master Key 0 | 00 00 0B 00 00 50 41 03 00 00 1B 00 00 50 41 03 | Yes | 7 - 23 |
Transport Master Key 1 | 00 00 0A 00 00 50 41 03 00 00 1A 00 00 50 41 03 | Yes | 8 - 03 |
Transport Signature Key | 00 00 0F 00 00 50 41 03 00 00 1F 00 00 50 41 03 | No | 9 - 23 |
The card we used provide (at various level) a so-called «mutual authentication» scheme. This means that both host application and card (or the application embedded in each) can easily assert whether the other part may be trusted or not. All mutual authentication algorithms used here are based on symetric ciphers (DES or 3-DES for Desfire and Jaycos, CRYPTO1 for Mifare classic).
Symetric ciphers use «shared» secrets keys : both parts must know the secret. But if you consider a real-world application with 1 000 000 or more cards, this means that the «secret» is shared along 1 000 000 parts or more. Suppose a hacker manages to find the key of one (one only) card, in fact he knows the key used by the 999 999 others. To overcome this issue, it is a good idea to put a different key in each card. Good idea, But now every reader needs a giant database of 1 000 000 different keys...
The practical solution is to use key diversification here. The idea is to compute the key for each card from a single «master key». The reader needs to know only one key (the master key). If the hacker manages to find the key of one card, he will be unable to come back to the master key, so the other 999 999 cards are not impacted.
Our diversification algorithm :
Step 1 :
Step 2 :
Step 3 :
C0 || C1 (16 bytes) is the diversified key, valid for this serial number only.
This is the same algorithm as provided by Desfire SAM smartcard (function specification 1, chapter 4.2.5), thus allowing to use the Desfire SAM instead of host-based cryptography.
Mifare standard cards uses 6-byte keys. We compute the diversified keys as exposed above, and drop the last 10 bytes. This method is not compliant with the Mifare diversification algorithm implemented in Philips RC171 and in Desfire SAM (function specification 1, chapter 4.3.6).
In real-world application, people often use secure-proven methods for static authentication, for instance RSA signature (issuer keeps the private key secret, and readers only know the public key), HMAC-SHA1 or CMAC-3DES (where the secret key must be shared between issuer and readers).
To ease a little our software implementations, we will only use a weak MAC algorithm, based on MD5 and two 3-DES operations. Keep in mind that this choice is for demonstration only !
Our MAC algorithm :
Step 1 :
Step 2 :
Step 3 :
C is the MAC of the data (8 bytes), valid for this serial number only.
None of the card we use is able to perform dynamic authentication (for example, in-card RSA signature).
This implementation has been defined for a Philips Desfire 4k card.
Each application has its own directory (named an «application» in Desfire documentation), and its own key-set.
We use transparent files for data storage, linear-record files for structured data, cyclic-record files for logs, and value files for
counters.
Card master key remains to default value 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00, thus allowing use to erase the whole card at any time.
File name | File ID | File type | File size | Access read | Access write | Access mode | Note |
---|---|---|---|---|---|---|---|
User identity | 1 | Standard | 128 | Keys 0 & 1 | Key 0 | Ciphered | |
Fingerprints | 2 | Standard | 170 | Keys 0 & 1 | Key 0 | Ciphered | |
Picture | 3 | Standard | 2464 | Keys 0 & 1 | Key 0 | Ciphered | |
Access control credentials | 4 | Standard | 48 | Always | Key 0 | MACed | |
Options and signature | 5 | Standard | 32 | Always | Key 0 | Plain |
Size used by the application : 2842 bytes + overhead
File name | File ID | File type | File size | Access read | Access write | Access mode | Note |
---|---|---|---|---|---|---|---|
Balance | 1 | Value, with backup | 32 ? | Keys 0 & 1 | Key 0 | Plain | |
Re-load history | 2 | Cyclic, with backup | 5 x 16 = 80 | Keys 0 & 1 | Key 0 | Plain | Backup feature consumes one record |
Purchase history | 3 | Cyclic, with backup | 7 x 16 = 112 | Keys 0 & 1 | Keys 0 & 1 | Plain | Backup feature consumes one record |
Size used by the application : 224 bytes + overhead
File name | File ID | File type | File size | Access read | Access write | Access mode | Note |
---|---|---|---|---|---|---|---|
Contracts | 1 | Linear, with backup | 3 x 32 = 96 | Keys 0 & 1 | Key 0 | MACed | |
Event log | 2 | Cyclic, with backup | 7 x 16 = 112 | Keys 0 & 1 | Keys 0 & 1 | MACed | Backup feature consumes one record |
Counter 1 | 3 | Value, with backup | 32 ? | Keys 0 & 1 | Key 0 | MACed | |
Counter 2 | 4 | Value, with backup | 32 ? | Keys 0 & 1 | Key 0 | MACed | |
Counter 3 | 5 | Value, with backup | 32 ? | Keys 0 & 1 | Key 0 | MACed |
Size used by the application : 304 bytes + overhead
This sample uses Desfire in ISO mode (Desfire commands are wrapped into ISO/IEC 7816-4 APDUs). This feature is available only on Desfire version 6 and later.
Select Desfire application | 00 A4 04 00 07 D2 76 00 00 85 01 00 |
Select transport application (DF) | 00 A4 04 00 03 03 41 50 |
Authenticate with Key 1 | 90 0A 00 00 01 01 |
90 0F 00 00 10 xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx | |
Read 3 contracts | 90 BD 00 00 07 01 00 00 00 00 00 03 |
Read 6 last events | 90 BD 00 00 07 02 00 00 00 00 00 06 |
Get value of counter 2 | 90 6C 00 00 01 03 |
Debit counter 2 by 12 units | 90 DC 00 00 09 04 0C 00 00 00 00 mm mm mm mm (4-bytes MAC) |
Write event in log | 3B 02 00 00 00 10 00 00 dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd mm mm mm mm (16 bytes of data followed by a 4-bytes MAC) |
Commit transaction | 90 C7 00 00 00 |
This implementation has been defined for a 2k card with JayCOS Appli 1.2.
Each application has its own directory (a DF as specificied in 7816-4).
We use transparent files for data storage, linear-record files for structured data, cyclic-record files for logs, and counter files for
counters.
A common key file (with reserved ID 0xAAAA) has to be created at the root of the card, and stores the 6+1 needed keys (2 keys for each application,
plus a master key).
File name | File ID | File type | File size | Access read | Access write | Access mode | Note |
---|---|---|---|---|---|---|---|
User identity | 1 | Standard | 128 | Keys 0 & 1 | Key 0 | Plain | |
Fingerprints | 2 | Standard | 170 | Keys 0 & 1 | Key 0 | Plain | |
Access control credentials | 4 | Standard | 48 | Always | Key 0 | Plain | |
Options and signature | 5 | Standard | 32 | Always | Key 0 | Plain |
Size used by the application : 378 bytes + overhead
File name | File ID | File type | File size | Access read | Access write | Access mode | Note |
---|---|---|---|---|---|---|---|
Balance | 1 | Transp. EF + Counter | 9 | Keys 0 & 1 | Key 0 | Plain | |
Re-load history | 2 | Cyclic EF | 5 x 16 = 80 | Keys 0 & 1 | Key 0 | Plain | Backup feature consumes one record |
Purchase history | 3 | Cyclic EF | 7 x 16 = 112 | Keys 0 & 1 | Keys 0 & 1 | Plain | Backup feature consumes one record |
Size used by the application : 224 bytes + overhead
File name | File ID | File type | File size | Access read | Access write | Access mode | Note |
---|---|---|---|---|---|---|---|
Contracts | 1 | Linear, with backup | 3 x 32 = 96 | Keys 0 & 1 | Key 0 | Plain | |
Event log | 2 | Cyclic, with backup | 7 x 16 = 112 | Keys 0 & 1 | Keys 0 & 1 | Plain | Backup feature consumes one record |
Counter 1 | 3 | Value, with backup | 32 ? | Keys 0 & 1 | Key 0 | Plain | |
Counter 2 | 4 | Value, with backup | 32 ? | Keys 0 & 1 | Key 0 | Plain | |
Counter 3 | 5 | Value, with backup | 32 ? | Keys 0 & 1 | Key 0 | Plain |
Size used by the application : 304 bytes + overhead
Mifare 1k has only 720 bytes of usable data (plus 32 bytes for MAD in sector 0). This is enough to implement all three applications, but with limitations :
We use the MAD feature to recognize our cards, but choose a static mapping to ease the development of the reader software.
Address | Sector | Block | Content | Access read | Access write | Note |
---|---|---|---|---|---|---|
32 | 8 | 0 | Options and signature (32 bytes) | Keys A & B | Key B | |
33 | 1 | Keys A & B | Key B | |||
34 | 2 | Identity data (128 bytes) | Keys A & B | Key B | ||
36 | 9 | 0 | Keys A & B | Key B | ||
37 | 1 | Keys A & B | Key B | |||
38 | 2 | Keys A & B | Key B | |||
40 | 10 | 0 | Keys A & B | Key B | ||
41 | 1 | Keys A & B | Key B | |||
42 | 2 | Keys A & B | Key B | |||
44 | 11 | 0 | Keys A & B | Key B | ||
45 | 1 | Fingerprints (176 bytes) | Keys A & B | Key B | ||
46 | 2 | Keys A & B | Key B | |||
48 | 12 | 0 | Keys A & B | Key B | ||
49 | 1 | Keys A & B | Key B | |||
50 | 2 | Keys A & B | Key B | |||
52 | 13 | 0 | Keys A & B | Key B | ||
53 | 1 | Keys A & B | Key B | |||
54 | 2 | Keys A & B | Key B | |||
56 | 14 | 0 | Keys A & B | Key B | ||
57 | 1 | Keys A & B | Key B | |||
58 | 2 | Keys A & B | Key B | |||
60 | 15 | 0 | Access control credentials (48 bytes) | Keys A & B | Key B | |
61 | 1 | Keys A & B | Key B | |||
62 | 2 | Keys A & B | Key B |
Size used by the application : 8 sectors = 384 bytes
Address | Sector | Block | Content | Access read | Access write | Note |
---|---|---|---|---|---|---|
4 | 1 | 0 | Balance | Keys A & B | Key B | Value-type block |
5 | 1 | Purchase history, record 1 | Keys A & B | Keys A & B | ||
6 | 2 | Purchase history, record 2 | Keys A & B | Keys A & B | ||
8 | 2 | 0 | Purchase history, record 3 | Keys A & B | Keys A & B | |
9 | 1 | Purchase history, record 4 | Keys A & B | Keys A & B | ||
10 | 2 | Purchase history, record 5 | Keys A & B | Keys A & B | ||
12 | 3 | 0 | Purchase history, record 6 | Keys A & B | Keys A & B | |
13 | 1 | Re-load history, record 0 | Keys A & B | Key B | ||
14 | 2 | Re-load history, record 1 | Keys A & B | Key B | ||
16 | 4 | 0 | Re-load history, record 2 | Keys A & B | Key B | |
17 | 1 | Re-load history, record 3 | Keys A & B | Key B | ||
18 | 2 | Re-load history, record 4 | Keys A & B | Key B |
Size used by the application : 4 sectors = 192 bytes
Address | Sector | Block | Content | Access read | Access write | Note |
---|---|---|---|---|---|---|
20 | 5 | 0 | Counter | Keys A & B | Key B | Value-type block |
21 | 1 | Contract | Keys A & B | Key B | ||
22 | 2 | Keys A & B | Key B | |||
24 | 6 | 0 | Event log, record 1 | Keys A & B | Keys A & B | |
25 | 1 | Event log, record 2 | Keys A & B | Keys A & B | ||
26 | 2 | Event log, record 3 | Keys A & B | Keys A & B | ||
28 | 7 | 0 | Event log, record 4 | Keys A & B | Keys A & B | |
29 | 1 | Event log, record 5 | Keys A & B | Keys A & B | ||
30 | 2 | Event log, record 6 | Keys A & B | Keys A & B |
Size used by the application : 3 sectors = 144 bytes
To be compliant with Mifare 1k implementations, sectors 0 to 15 provide exactly the same mapping as the Mifare 1k mapping above.
Sectors 16 to 63 store the picture for the Corporate ID application (16 48-byte sectors numbered 16 to 31 plus 8 240-byte sectors numbered 32 to 39 allow us a size 2688 bytes of for the picture).