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,$pos+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 my $v = unpack('v',(substr($card, 0x10 + ( $i * 2 ), 2)));
86 my $cluster_id = unpack('HH', (( $v & 0xff00 ) >> 8) );
87 my $full_id = sprintf "%04x",$v;
88 printf "MAD sector %-2d %04x [%s]\n%s\n", $i, $v
89 , $function_clusters->{ $cluster_id }
90 , $mad_id->{$full_id} || "FIXME: add $full_id from MAD_overview.pdf to __DATA__ at end of $0"
94 # RLE encoded card holder information
95 my $data = substr( $card, $pos, 0x30);
103 while ( substr($data,$o,1) ne "\x00" ) {
104 my $len = ord(substr($data,$o,1));
105 my $type = ( $len & 0b11000000 ) >> 6;
106 $len = $len & 0b00111111;
107 my $dump = substr($data,$o+1,$len-1);
108 $dump = '0x' . unpack('H*', $dump) if $type == 0b11; # any
109 printf "%-10s %2d %s\n", $types->{$type}, $len, $dump;
112 } elsif ( $v == 0x0015 ) {
113 printf "Card number: %s\n", unpack('h*',substr($card,$pos + 0x04,6));
118 my $c1 = ( ord(substr($card,$pos+0x37,1)) & 0xf0 ) >> 4;
119 my $c2 = ( ord(substr($card,$pos+0x38,1)) & 0x0f );
120 my $c3 = ( ord(substr($card,$pos+0x38,1)) & 0xf0 ) >> 4;
122 foreach my $j ( 0 .. 3 ) {
123 my $offset = $pos + $j * 0x10;
124 my $block = substr($card, $offset, 0x10);
127 = ( ( $c1 & $mask ) * 4 )
128 + ( ( $c2 & $mask ) * 2 )
129 + ( ( $c3 & $mask ) * 1 )
133 printf "%04x %s %03b %s\n", $offset, unpack('H*',$block)
135 , $j < 3 ? $access_condition_data->{$cond} : $access_condition_trailer->{$cond}
140 printf "KEY A:%s | %s GDP: %s | B:%s\n"
141 ,unpack('H*',substr($card,$pos+0x30 ,6))
142 ,unpack('H*',substr($card,$pos+0x30+6 ,3))
143 ,unpack('H*',substr($card,$pos+0x30+9 ,1))
144 ,unpack('H*',substr($card,$pos+0x30+10,6))
152 00 card administration
153 01-07 miscellaneous applications
161 21 multi modal transit
165 40 city card services
166 47-48 access control & security
168 4A Ministry of Defence, Netherlands
169 4B Bosch Telecom, Germany
170 4A Ministry of Defence, Netherlands
171 4C European Union Institutions
173 51-54 access control & security
181 80 administration services
192 C0 entertainment & sports
201 F8-FF miscellaneous applications
204 0001 sector is defect, e.g. access keys are destroyed or unknown
205 0002 sector is reserved
206 0003 sector contains additional directory info (useful only for future cards)
207 0004 sector contains card holder information in ASCII format.
208 0005 sector not applicable (above memory size)
210 0015 - card administration MIKROELEKTRONIKA spol.s.v.MIKROELEKTRONIKA spol.s.v.o. worldwide 1 01.02.2007 Card publisher info
211 0016 - card administration Mikroelektronika spol.s.r.o., Kpt.Mikroelektronika spol.s.r.o., Kpt. PoEurope 1 10.10.2007 Issuer information
213 071C - miscellaneous applications MIKROELEKTRONIKA spol.s.r. MIKROELEKTRONIKA spol.s.r.o., Europe 1 01.12.2008 Customer profile
214 071D - miscellaneous applications ZAGREBACKI Holding d.o.o. MIKROELEKTRONIKA spol.s.r.o. EUROPE,Croatia 1 01.04.2009 Customer profile
215 071E - miscellaneous applications ZAGREBACKI Holding d.o.o. MIKROELEKTRONIKA spol.s.r.o. EUROPE,Croatia 1 01.04.2009 Bonus counter
217 1835 - city traffic KORID LK, spol.s.r.o. KORID LK, spol.s.r.o. Europe 2 08.09.2008 Eticket
218 1836 - city traffic MIKROELEKTRONIKA spol.s.r. MIKROELEKTRONIKA spol.s.r.o., Europe 1 01.12.2008 Prepaid coupon 1S
219 1837 - city traffic ZAGREBACKI Holding d.o.o. MIKROELEKTRONIKA spol.s.r.o. EUROPE,Croatia 1 01.04.2009 Prepaid coupon
220 1838 - city traffic MIKROELEKTRONIKA spol.s.r. MIKROELEKTRONIKA spol.s.r.o. Europe 1 01.05.2009 Prepaid coupon
221 1839 - city traffic Mikroelektronika spol.s r.o Mikroelektronika spol.s r.o EUROPE,Czech R 1 01.08.2009 Prepaid coupon
222 183B - city traffic UNICARD S.A. UNICARD S.A. Poland 15 01.01.2010 city traffic services
224 2061 - bus services Mikroelektronika spol.s r.o. Mikroelektronika spol.s r.o. Europe 1 01.08.2008 Electronic ticket
225 2062 - bus services ZAGREBACKI Holding d.o.o. MIKROELEKTRONIKA spol.s.r.o EUROPE,Croatia 1 01.04.2009 Electronic tiicket
226 2063 - bus services MIKROELEKTRONIKA spol.s.r. MIKROELEKTRONIKA spol.s.r.o. Europe 3 01.05.2009 electronic ticket
228 887B - electronic purse ZAGREBACKI Holding d.o.o. MIKROELEKTRONIKA spol.s.r.o. EUROPE,Croatia 4 01.04.2009 Electronic purse
229 887C - electronic purse MIKROELEKTRONIKA spol.s.r. MIKROELEKTRONIKA spol.s.r.o. Europe 4 01.05.2009 electronic purse
230 887D - electronic purse Mikroelektronika spol.s r.o Mikroelektronika spol.s r.o EUROPE,Czech R 4 01.08.2009 Electronic purse