7 # MIFARE Application Directory (MAD)
8 # http://www.nxp.com/acrobat_download2/other/identification/MAD_overview.pdf
10 use Data::Dump qw(dump);
12 my $debug = $ENV{DEBUG} || 0;
14 my $function_clusters;
20 my ( $code, $function ) = split(/\s+/,$_,2);
22 if ( $code =~ m/^($h{2})-($h{2})$/ ) {
23 foreach my $c ( hex($1) .. hex($2) ) {
24 $function_clusters->{ unpack('HH',$c) } = $function;
26 } elsif ( $code =~ m/^($h{2})$/ ) {
27 $function_clusters->{ lc $code } = $function;
28 } elsif ( $code =~ m/^($h{4})$/ ) {
29 $mad_id->{ lc $1 } = $function;
31 die "can't parse __DATA__ line $.\n$_\n";
35 my $access_condition_data = {
36 0b000 => 'R:AB W:AB I:AB DTR:AB',
37 0b010 => 'R:AB W:-- I:-- DTR:--',
38 0b100 => 'R:AB W:-B I:-- DTR:--',
39 0b110 => 'R:AB W:-B I:-B DTR:AB',
40 0b001 => 'R:AB W:-- I:-- DTR:AB',
41 0b011 => 'R:-B W:-B I:-- DTR:--',
42 0b101 => 'R:-B W:-- I:-- DTR:--',
43 0b111 => 'R:-- W:-- I:-- DTR:--',
46 my $access_condition_trailer = {
47 0b000 => 'R/W: KEYSECXA:-/A ACCESS COND:A-/- KEYSECXB:A/A',
48 0b010 => 'R/W: KEYSECXA:-/- ACCESS COND:A-/- KEYSECXB:A/-',
49 0b100 => 'R/W: KEYSECXA:-/B ACCESS COND:AB/- KEYSECXB:-/B',
50 0b110 => 'R/W: KEYSECXA:-/- ACCESS COND:AB/- KEYSECXB:-/-',
51 0b001 => 'R/W: KEYSECXA:-/A ACCESS COND:A-/A KEYSECXB:A/A',
52 0b011 => 'R/W: KEYSECXA:-/B ACCESS COND:AB/B KEYSECXB:-/B',
53 0b101 => 'R/W: KEYSECXA:-/- ACCESS COND:AB/B KEYSECXB:-/-',
54 0b111 => 'R/W: KEYSECXA:-/- ACCESS COND:AB/- KEYSECXB:-/-',
59 warn "# function_clusters ",dump($function_clusters);
60 warn "# mad_id ", dump($mad_id);
66 die "expected 4096 bytes, got ",length($card), " bytes\n"
67 unless length $card == 4096;
69 foreach my $i ( 0 .. 15 ) {
74 printf "manufacturer block\nSerial number: %s\nCB: %s\nmanufacturer data: %s\n"
75 , unpack('H*',substr($card,0,4))
76 , unpack('H*',substr($card,4,1))
77 , unpack('H*',substr($card,5,11))
79 # General purpose byte (GPB)
80 my $gdp = ord(substr($card,0x39,1));
81 printf "ADV (MAD version code): %d\n", $gdp & 0b00000011;
82 printf "MA (multiapplication): %s\n", $gdp & 0b01000000 ? 'yes' : 'monoaplication';
83 printf "DA (MAD available): %s\n", $gdp & 0b10000000 ? 'yes' : 'no';
85 printf "Info byte (publisher sector): %x\n", ord(substr($card,0x11,1));
87 my $mad_offset = 0x10 + ( $i * 2 );
88 my $v = unpack('v',(substr($card, $mad_offset, 2)));
89 my $cluster_id = unpack('HH', (( $v & 0xff00 ) >> 8) );
90 my $full_id = sprintf "%04x",$v;
91 printf "MAD sector %-2d@%x %04x [%s]\n%s\n", $i, $mad_offset, $v
92 , $function_clusters->{ $cluster_id }
93 , $mad_id->{$full_id} || "FIXME: add $full_id from MAD_overview.pdf to __DATA__ at end of $0"
97 # RLE encoded card holder information
98 my $data = substr( $card, $pos, 0x30);
102 0b01 => 'given name',
106 while ( substr($data,$o,1) ne "\x00" ) {
107 my $len = ord(substr($data,$o,1));
108 my $type = ( $len & 0b11000000 ) >> 6;
109 $len = $len & 0b00111111;
110 my $dump = substr($data,$o+1,$len-1);
111 $dump = '0x' . unpack('H*', $dump) if $type == 0b11; # any
112 printf "%-10s %2d %s\n", $types->{$type}, $len, $dump;
115 } elsif ( $v == 0x0015 ) {
116 printf "Card number: %s\n", unpack('h*',substr($card,$pos + 0x04,6));
121 my $c1 = ( ord(substr($card,$pos+0x37,1)) & 0xf0 ) >> 4;
122 my $c2 = ( ord(substr($card,$pos+0x38,1)) & 0x0f );
123 my $c3 = ( ord(substr($card,$pos+0x38,1)) & 0xf0 ) >> 4;
125 foreach my $j ( 0 .. 3 ) {
126 my $offset = $pos + $j * 0x10;
127 my $block = substr($card, $offset, 0x10);
130 = ( ( $c1 & $mask ) * 4 )
131 + ( ( $c2 & $mask ) * 2 )
132 + ( ( $c3 & $mask ) * 1 )
136 my $hex = unpack('H*',$block);
137 $hex =~ s/(....)/$1 /g;
139 if ( $ENV{SWAP} && $j < 3 ) {
140 my $hex_sw = unpack('h*',$block);
141 $hex_sw =~ s/(....)/$1 /g;
142 $hex .= " | $hex_sw";
145 printf "%04x %s %03b %s\n", $offset, $hex
147 , $j < 3 ? $access_condition_data->{$cond} : $access_condition_trailer->{$cond}
152 printf "KEY A:%s | %s GDP: %s | B:%s\n"
153 ,unpack('H*',substr($card,$pos+0x30 ,6))
154 ,unpack('H*',substr($card,$pos+0x30+6 ,3))
155 ,unpack('H*',substr($card,$pos+0x30+9 ,1))
156 ,unpack('H*',substr($card,$pos+0x30+10,6))
164 00 card administration
165 01-07 miscellaneous applications
173 21 multi modal transit
177 40 city card services
178 47-48 access control & security
180 4A Ministry of Defence, Netherlands
181 4B Bosch Telecom, Germany
182 4A Ministry of Defence, Netherlands
183 4C European Union Institutions
185 51-54 access control & security
193 80 administration services
204 C0 entertainment & sports
213 F8-FF miscellaneous applications
216 0001 sector is defect, e.g. access keys are destroyed or unknown
217 0002 sector is reserved
218 0003 sector contains additional directory info (useful only for future cards)
219 0004 sector contains card holder information in ASCII format.
220 0005 sector not applicable (above memory size)
222 0015 - card administration MIKROELEKTRONIKA spol.s.v.MIKROELEKTRONIKA spol.s.v.o. worldwide 1 01.02.2007 Card publisher info
223 0016 - card administration Mikroelektronika spol.s.r.o., Kpt.Mikroelektronika spol.s.r.o., Kpt. PoEurope 1 10.10.2007 Issuer information
225 071C - miscellaneous applications MIKROELEKTRONIKA spol.s.r. MIKROELEKTRONIKA spol.s.r.o., Europe 1 01.12.2008 Customer profile
226 071D - miscellaneous applications ZAGREBACKI Holding d.o.o. MIKROELEKTRONIKA spol.s.r.o. EUROPE,Croatia 1 01.04.2009 Customer profile
227 071E - miscellaneous applications ZAGREBACKI Holding d.o.o. MIKROELEKTRONIKA spol.s.r.o. EUROPE,Croatia 1 01.04.2009 Bonus counter
229 1835 - city traffic KORID LK, spol.s.r.o. KORID LK, spol.s.r.o. Europe 2 08.09.2008 Eticket
230 1836 - city traffic MIKROELEKTRONIKA spol.s.r. MIKROELEKTRONIKA spol.s.r.o., Europe 1 01.12.2008 Prepaid coupon 1S
231 1837 - city traffic ZAGREBACKI Holding d.o.o. MIKROELEKTRONIKA spol.s.r.o. EUROPE,Croatia 1 01.04.2009 Prepaid coupon
232 1838 - city traffic MIKROELEKTRONIKA spol.s.r. MIKROELEKTRONIKA spol.s.r.o. Europe 1 01.05.2009 Prepaid coupon
233 1839 - city traffic Mikroelektronika spol.s r.o Mikroelektronika spol.s r.o EUROPE,Czech R 1 01.08.2009 Prepaid coupon
234 183B - city traffic UNICARD S.A. UNICARD S.A. Poland 15 01.01.2010 city traffic services
236 2061 - bus services Mikroelektronika spol.s r.o. Mikroelektronika spol.s r.o. Europe 1 01.08.2008 Electronic ticket
237 2062 - bus services ZAGREBACKI Holding d.o.o. MIKROELEKTRONIKA spol.s.r.o EUROPE,Croatia 1 01.04.2009 Electronic tiicket
238 2063 - bus services MIKROELEKTRONIKA spol.s.r. MIKROELEKTRONIKA spol.s.r.o. Europe 3 01.05.2009 electronic ticket
240 887B - electronic purse ZAGREBACKI Holding d.o.o. MIKROELEKTRONIKA spol.s.r.o. EUROPE,Croatia 4 01.04.2009 Electronic purse
241 887C - electronic purse MIKROELEKTRONIKA spol.s.r. MIKROELEKTRONIKA spol.s.r.o. Europe 4 01.05.2009 electronic purse
242 887D - electronic purse Mikroelektronika spol.s r.o Mikroelektronika spol.s r.o EUROPE,Czech R 4 01.08.2009 Electronic purse