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: KEYA:-/A ACCESS:A-/- DATB:A/A ?',
48 0b010 => 'R/W: KEYA:-/- ACCESS:A-/- DATB:A/- ?'.
49 0b100 => 'R/W: KEYA:-/B ACCESS:AB/- KEYB:-/B',
50 0b110 => 'R/W: KEYA:-/- ACCESS:AB/- KEYB:-/-',
51 0b001 => 'R/W: KEYA:-/A ACCESS:A-/A DATB:A/A ?',
52 0b011 => 'R/W: KEYA:-/B ACCESS:AB/B KEYB:-/B',
53 0b101 => 'R/W: KEYA:-/- ACCESS:AB/B KEYB:-/-',
54 0b111 => 'R/W: KEYA:-/- ACCESS:AB/- KEYB:-/-',
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 my ( $ADV, $MA, $DA );
71 foreach my $i ( 0 .. 15 ) {
76 printf "manufacturer block\nSerial number: %s\nCB: %s\nmanufacturer data: %s\n"
77 , unpack('H*',substr($card,0,4))
78 , unpack('H*',substr($card,4,1))
79 , unpack('H*',substr($card,5,11))
81 # General purpose byte (GPB)
82 my $gdp = ord(substr($card,0x39,1));
83 $ADV = $gdp & 0b00000011;
84 $MA = $gdp & 0b01000000;
85 $DA = $gdp & 0b10000000;
86 printf "ADV (MAD version code): %d\n", $ADV;
87 printf "MA (multiapplication): %s\n", $MA ? 'yes' : 'monoaplication';
88 printf "DA (MAD available): %s\n", $DA ? 'yes' : 'no';
90 printf "Info byte (publisher sector): %x\n", ord(substr($card,0x11,1));
92 my $mad_offset = 0x10 + ( $i * 2 );
93 my $v = unpack('v',(substr($card, $mad_offset, 2)));
94 my $cluster_id = unpack('HH', (( $v & 0xff00 ) >> 8) );
95 my $full_id = sprintf "%04x",$v;
96 printf "MAD sector %-2d@%x %04x [%s]\n%s\n", $i, $mad_offset, $v
97 , $function_clusters->{ $cluster_id }
98 , $mad_id->{$full_id} || "FIXME: add $full_id from MAD_overview.pdf to __DATA__ at end of $0"
101 if ( $v == 0x0004 ) {
102 # RLE encoded card holder information
103 my $data = substr( $card, $pos, 0x30);
107 0b01 => 'given name',
111 while ( substr($data,$o,1) ne "\x00" ) {
112 my $len = ord(substr($data,$o,1));
113 my $type = ( $len & 0b11000000 ) >> 6;
114 $len = $len & 0b00111111;
115 my $dump = substr($data,$o+1,$len-1);
116 $dump = '0x' . unpack('H*', $dump) if $type == 0b11; # any
117 printf "%-10s %2d %s\n", $types->{$type}, $len, $dump;
120 } elsif ( $v == 0x0015 ) {
121 printf "Card number: %s\n", unpack('h*',substr($card,$pos + 0x04,6));
125 printf "# sector %-2d\n", $i;
128 my $c1 = ( ord(substr($card,$pos+0x37,1)) & 0xf0 ) >> 4;
129 my $c2 = ( ord(substr($card,$pos+0x38,1)) & 0x0f );
130 my $c3 = ( ord(substr($card,$pos+0x38,1)) & 0xf0 ) >> 4;
132 foreach my $j ( 0 .. 3 ) {
133 my $offset = $pos + $j * 0x10;
134 my $block = substr($card, $offset, 0x10);
137 = ( ( $c1 & $mask ) * 4 )
138 + ( ( $c2 & $mask ) * 2 )
139 + ( ( $c3 & $mask ) * 1 )
143 my $hex = unpack('H*',$block);
144 $hex =~ s/(....)/$1 /g;
146 if ( $ENV{SWAP} && $j < 3 ) {
147 my $hex_sw = unpack('h*',$block);
148 $hex_sw =~ s/(....)/$1 /g;
149 $hex .= " | $hex_sw";
152 printf "%04x %s %03b %s\n", $offset, $hex
154 , $j < 3 ? $access_condition_data->{$cond} : $access_condition_trailer->{$cond}
159 printf "KEY A:%s | %s GDP: %s | B:%s\n"
160 ,unpack('H*',substr($card,$pos+0x30 ,6))
161 ,unpack('H*',substr($card,$pos+0x30+6 ,3))
162 ,unpack('H*',substr($card,$pos+0x30+9 ,1))
163 ,unpack('H*',substr($card,$pos+0x30+10,6))
171 00 card administration
172 01-07 miscellaneous applications
180 21 multi modal transit
184 40 city card services
185 47-48 access control & security
187 4A Ministry of Defence, Netherlands
188 4B Bosch Telecom, Germany
189 4A Ministry of Defence, Netherlands
190 4C European Union Institutions
192 51-54 access control & security
200 80 administration services
211 C0 entertainment & sports
220 F8-FF miscellaneous applications
223 0001 sector is defect, e.g. access keys are destroyed or unknown
224 0002 sector is reserved
225 0003 sector contains additional directory info (useful only for future cards)
226 0004 sector contains card holder information in ASCII format.
227 0005 sector not applicable (above memory size)
229 0015 - card administration MIKROELEKTRONIKA spol.s.v.MIKROELEKTRONIKA spol.s.v.o. worldwide 1 01.02.2007 Card publisher info
230 0016 - card administration Mikroelektronika spol.s.r.o., Kpt.Mikroelektronika spol.s.r.o., Kpt. PoEurope 1 10.10.2007 Issuer information
232 071C - miscellaneous applications MIKROELEKTRONIKA spol.s.r. MIKROELEKTRONIKA spol.s.r.o., Europe 1 01.12.2008 Customer profile
233 071D - miscellaneous applications ZAGREBACKI Holding d.o.o. MIKROELEKTRONIKA spol.s.r.o. EUROPE,Croatia 1 01.04.2009 Customer profile
234 071E - miscellaneous applications ZAGREBACKI Holding d.o.o. MIKROELEKTRONIKA spol.s.r.o. EUROPE,Croatia 1 01.04.2009 Bonus counter
236 1835 - city traffic KORID LK, spol.s.r.o. KORID LK, spol.s.r.o. Europe 2 08.09.2008 Eticket
237 1836 - city traffic MIKROELEKTRONIKA spol.s.r. MIKROELEKTRONIKA spol.s.r.o., Europe 1 01.12.2008 Prepaid coupon 1S
238 1837 - city traffic ZAGREBACKI Holding d.o.o. MIKROELEKTRONIKA spol.s.r.o. EUROPE,Croatia 1 01.04.2009 Prepaid coupon
239 1838 - city traffic MIKROELEKTRONIKA spol.s.r. MIKROELEKTRONIKA spol.s.r.o. Europe 1 01.05.2009 Prepaid coupon
240 1839 - city traffic Mikroelektronika spol.s r.o Mikroelektronika spol.s r.o EUROPE,Czech R 1 01.08.2009 Prepaid coupon
241 183B - city traffic UNICARD S.A. UNICARD S.A. Poland 15 01.01.2010 city traffic services
243 2061 - bus services Mikroelektronika spol.s r.o. Mikroelektronika spol.s r.o. Europe 1 01.08.2008 Electronic ticket
244 2062 - bus services ZAGREBACKI Holding d.o.o. MIKROELEKTRONIKA spol.s.r.o EUROPE,Croatia 1 01.04.2009 Electronic tiicket
245 2063 - bus services MIKROELEKTRONIKA spol.s.r. MIKROELEKTRONIKA spol.s.r.o. Europe 3 01.05.2009 electronic ticket
247 887B - electronic purse ZAGREBACKI Holding d.o.o. MIKROELEKTRONIKA spol.s.r.o. EUROPE,Croatia 4 01.04.2009 Electronic purse
248 887C - electronic purse MIKROELEKTRONIKA spol.s.r. MIKROELEKTRONIKA spol.s.r.o. Europe 4 01.05.2009 electronic purse
249 887D - electronic purse Mikroelektronika spol.s r.o Mikroelektronika spol.s r.o EUROPE,Czech R 4 01.08.2009 Electronic purse