Commit ee215f05 authored by Ludovic Rousseau's avatar Ludovic Rousseau Committed by rousseau

cleanup


git-svn-id: svn://anonscm.debian.org/svn/pcsclite/trunk/pcsc-tools@4191 0ce88b0d-b2fd-0310-8134-9614164e65ea
parent 1d0e76c2
#!/usr/bin/perl
# ATR_analysis
# Copyright (C) 2000, 2002 Ludovic Rousseau, Christophe Levantis
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
# $Id: ATR_analysis,v 1.3 2002-08-26 08:15:35 rousseau Exp $
# For more information about the ATR see ISO 7816-3 1997, pages 12 and up
#
# TS initial character
# T0 format character, Y1 | K
# interfaces characters
# TA(1) global, codes FI and DI
# TB(1) global, codes II and PI
# TC(1) global, codes N
# TD(1) codes Y(2) and T
# TA(2) global, codes specific mode
# TB(2) global, codes PI2
# TC(2) specific
# TD(2) codes Y(3) and T
# TA(3) TA(i), TB(i), TC(i) (i>2)
# - specific after T!=15
# - global after T=15
# TD(i) codes Y(i+1) and T
# T1 historical bytes
# max 15 characters
# TK
# TCK check character
use strict;
use warnings;
use Getopt::Std;
# file containing the smart card models
my $SMARTCARD_LIST = "smartcard_list.txt";
# where to look for $SMARTCARD_LIST
my @LIST_PATH = qw(. /usr/local/pcsc /usr/lib/pcsc);
our ($opt_v, $opt_h);
my ($atr, %TS, @Fi, @Di, @XI, @UI, $T, $value, $counter, $line);
my ($Y1, $K, @object, $nb_bytes);
# tables
%TS = (0x3B, "Direct Convention", 0x3F, "Inverse Convention");
@Fi = (372, 372, 558, 744, 1116, 1488, 1860, "RFU", "RFU", 512, 768, 1024,
1536, 2048, "RFU", "RFU");
@Di = ("RFU", 1, 2, 4, 8, 16, 32, "RFU", 12, 20, "RFU", "RFU", "RFU",
"RFU", "RFU", "RFU");
@XI = ("not supported", "state L", "state H", "no preference");
@UI = ("A only (5V)", "B only (3V)", "A and B", "RFU");
# prorotypes
sub analyse_TA();
sub analyse_TB();
sub analyse_TC();
sub analyse_TD();
sub find_card($$@);
# globals init
$T = 0;
$value = 0;
$counter = 1;
getopts("vh");
if ($opt_v)
{
print "Version: 1.1, (c) 2002, Ludovic Rousseau <ludovic.rousseau\@free.fr>\n";
exit;
}
# 1_ 1 argument then input = ATR else smart card
if (($#ARGV != 0) or $opt_h)
{
print "Usage: $0 ATR_string\n";
print " Ex: $0 '3B A7 00 40 18 80 65 A2 08 01 01 52'\n";
exit;
}
# 1_ get the ATR
$atr = $ARGV[0];
if (substr ($atr, 2, 1) ne " ")
{
# "3BA7004018" -> "3B A7 00 40 18"
$atr =~ s/(..)/$1 /g;
}
print "ATR: $atr\n";
# 2_ Split in bytes of the lines
@object = split(/\s/, $atr);
$nb_bytes=$#object+1;
#print $nb_bytes;
# 3_ Analysis
# Analysis of TS:
$value=hex(shift(@object));
if (defined $TS{$value})
{
printf "+ TS = %02X --> %s\n", $value, $TS{$value};
}
else
{
printf "+ TS = %02X --> UNDEFINED\n", $value
}
exit if ($#object < 0);
# Analysis of T0:
$value = hex(shift(@object));
$Y1 = $value >> 4;
$K = $value % 16;
printf "+ T0 = %02X, Y(1): %04b, K: %d (historical bytes)\n", $value, $Y1, $K;
exit if ($#object < 0);
analyse_TA() if ($Y1 & 0x1);
exit if ($#object < 0);
analyse_TB() if ($Y1 & 0x2);
exit if ($#object < 0);
analyse_TC() if ($Y1 & 0x4);
exit if ($#object < 0);
analyse_TD() if ($Y1 & 0x8);
# the rest are historical byets
print "+ Historical bytes: @object\n";
# find the corresponding card type
find_card($atr, $SMARTCARD_LIST, @LIST_PATH);
######## Sub functions
# _____ _
# |_ _|/ \
# | | / _ \
# | |/ ___ \
# |_/_/ \_\
#
sub analyse_TA()
{
$value = hex(shift(@object));
printf (" TA($counter) = %02X --> ", $value);
# TA1 Analysis
if ($counter == 1)
{
my $F = $value >> 4;
my $D = $value % 16;
$value=$Fi[$F]/$Di[$D] if ($Di[$D] ne "RFU");
printf "Fi=%s, Di=%s, %.3f cycles/ETU", $Fi[$F], $Di[$D], $value;
}
# TA2 Analysis - TA2 is the specific mode byte
if ($counter==2)
{
my $F=$value >> 4;
my $D=$value % 16;
printf ("Protocol to be used in spec mode: T=%s", $D);
if ($F & 0x8)
{
print " - Unable to change";
}
else
{
print " - Capable to change";
}
if ($F & 0x1)
{
print " - implicity defined";
}
else
{
print " - defined by interface bytes";
}
}
# TA3 Analysis
if ($counter>=3)
{
if ($T==1)
{
printf ("IFSC: %s", $value);
}
else
{ #### T <> 1
my $F=$value >> 6;
my $D=$value % 64;
my $Class="(3G) ";
$Class=$Class."A 5V " if ($D & 0x1);
$Class=$Class."B 3V " if ($D & 0x2);
$Class=$Class."C 1.8V " if ($D & 0x4);
$Class=$Class."D RFU " if ($D & 0x8);
$Class=$Class."E RFU" if ($D & 0x10);
printf ("Clock stop: %s - Class accepted by the card: %s", $XI[$F],$Class);
}
}
print "\n";
} # analyse_TA()
# _____ ____
# |_ _| __ )
# | | | _ \
# | | | |_) |
# |_| |____/
#
sub analyse_TB()
{
$value=hex(shift(@object));
printf (" TB($counter) = %02X --> ", $value);
my $I = $value >> 5;
my $PI = $value % 32;
if ($counter == 1)
{
print "Programming Param P: $PI, I: $I";
}
if ($counter == 2)
{
print "Programming param PI2 (PI1 sould be ignored): ";
if (($value>49)||($value<251))
{
print "$value (dV)";
}
else
{
print "$value is RFU";
}
}
if ($counter >= 3)
{
if ($T == 1)
{
my $BWI=$value >> 4;
my $CWI=$value % 16;
printf ("Block Wainting Integer: %s - Character Waiting Integer: %s", $BWI, $CWI);
}
}
print "\n";
} # analyse_TB()
# _____ ____
# |_ _/ ___|
# | || |
# | || |___
# |_| \____|
#
sub analyse_TC()
{
$value=hex(shift(@object));
printf (" TC($counter) = %02X --> ", $value);
if ($counter == 1)
{
print "Extra guard time: $value";
}
if ($counter == 2)
{
printf ("Work waiting time: 960 x %d x (Fi/F)", $value);
}
if ($counter >= 3)
{
if ($T==1)
{
printf ("Error detection code: ");
if ($value==1)
{
print "CRC";
}
elsif ($value==0)
{
print "LRC";
}
else
{
print "RFU";
}
}
}
print "\n";
} # analyse_TC()
# _____ ____
# |_ _| _ \
# | | | | | |
# | | | |_| |
# |_| |____/
#
sub analyse_TD()
{
my $str='';
$value = hex(shift(@object));
my $Y = $value >> 4;
$T=$value % 16;
if ($T == 15)
{
$str=" - Global interface bytes following";
}
printf (" TD($counter) = %02X --> Y(i+1) = %04b, Protocol T = $T$str\n", $value, $Y);
$counter++;
print "-----\n";
exit if ($#object < 0);
analyse_TA() if ($Y & 0x1);
exit if ($#object < 0);
analyse_TB() if ($Y & 0x2);
exit if ($#object < 0);
analyse_TC() if ($Y & 0x4);
exit if ($#object < 0);
analyse_TD() if ($Y & 0x8);
} # analyse_TD()
# _____ _ _ _
#| ___(_)_ __ __| | ___ __ _ _ __ __| |
#| |_ | | '_ \ / _` | / __/ _` | '__/ _` |
#| _| | | | | | (_| | | (_| (_| | | | (_| |
#|_| |_|_| |_|\__,_| \___\__,_|_| \__,_|
#
sub find_card($$@)
{
my $atr = shift;
my $file = shift;
my @path = @_;
my ($line, $found, $p);
foreach $p (@path)
{
if (-e "$p/$file")
{
$file = "$p/$file";
last;
}
}
$found = 0;
print "\nPossibly identified card:\n";
open FILE, "< $file" or die "Can't open $file: $!\n";
while ($line = <FILE>)
{
next if ($line =~ m/^#/); # comment
next if ($line =~ m/^$/); # empty line
next if ($line =~ m/^\t/); # description
chomp $line;
if ($atr =~ m/^$line$/i)
{
# print the card ATR if a regular expression was used
print "$atr\n" if (uc $line ne uc $atr);
print "$line\n"; # print the matching ATR
$found = 1;
# print until a line do not start by a tabulation
while (($line = <FILE>) =~ m/^\t/)
{
print $line; # print the card description
}
}
}
close FILE;
if (! $found)
{
print "\tNONE\n\n";
print "Your card is not present in the database.\n";
print "Please send a mail to <ludovic.rousseau\@free.fr> containing:\n";
print "- your ATR\n";
print "- a card description\n";
}
} # find_card($$)
.TH ATR_ANALYSIS "1" "August 2002" "Version: 1.1" "User Commands"
.SH NAME
ATR_analysis \- analyse a smart card ATR
.SH SYNOPSIS
.B ATR_analysis
.BI [ ATRstring ]
.SH DESCRIPTION
.B ATR_analysis
is used to parse the ATR (answer to reset) sent by a smart card.
The command also tries to find the card model using an ATR database
stored in a text file
.IR smartcard_list.txt .
The
.I smartcard_list.txt
file is searched in
.I .
,
.I /usr/local/pcsc
and
.I /usr/lib/pcsc
directories.
Exemple:
$ ATR_analysis '3B A7 00 40 18 80 65 A2 08 01 01 52'
ATR: 3B A7 00 40 18 80 65 A2 08 01 01 52
+ TS = 3B --> Direct Convention
+ T0 = A7, Y(1): 1010, K: 7 (historical bytes)
TB(1) = 00 --> Programming Param P: 0, I: 0
TD(1) = 40 --> Y(i+1) = 0100, Protocol T = 0
-----
TC(2) = 18 --> Work waiting time: 960 x 24 x (Fi/F)
+ Historical bytes: 80 65 A2 08 01 01 52
Possibly identified card:
3B A7 00 40 18 80 65 A2 08 01 01 52
Gemplus GPK8000
.SH BUGS
Maybe many bugs since I am not a ISO 7816 expert.
.SH FILES
.I smartcard_list.txt
.SH "SEE ALSO"
.BR pcscd "(1), " pcsc_scan (1)
.SH AUTHOR
Ludovic Rousseau <ludovic.rousseau@free.fr>
This diff is collapsed.
ATR_analysis
ATR_analysis.1p
Changelog
gscriptor
gscriptor.1p
LICENCE
Makefile
MANIFEST
pcsc_scan.1
pcsc_scan.c
README
scriptor
scriptor.1p
smartcard_list.txt
test.script
TODO
# $Id: Makefile,v 1.9 2002-08-21 07:58:19 rousseau Exp $
CC=gcc
VERSION=`echo \`pwd\` | sed s/.*tools-//`
CFLAGS=-Wall -O2 -DVERSION=\"$(VERSION)\"
LDLIBS=-lpcsclite -lpthread
# by default install in /usr/local
ifeq ($(DESTDIR),)
DESTDIR=/usr/local
endif
BIN=pcsc_scan
BIN_SCRIPT=ATR_analysis gscriptor scriptor
MAN=pcsc_scan.1.gz gscriptor.1p.gz scriptor.1p.gz ATR_analysis.1p.gz
all: $(BIN) $(MAN)
pcsc_scan: pcsc_scan.o
install: all
install --directory $(DESTDIR)/bin/
install $(BIN) $(DESTDIR)/bin/
install $(BIN_SCRIPT) $(DESTDIR)/bin/
install --directory $(DESTDIR)/pcsc
install --mode 644 smartcard_list.txt $(DESTDIR)/pcsc
install --directory $(DESTDIR)/share/man/man1/
install --mode 644 $(MAN) $(DESTDIR)/share/man/man1/
clean:
rm -f pcsc_scan.o $(BIN) $(MAN)
%.1.gz: %.1
gzip --best $^ --to-stdout > $@
%.1p.gz: %.1p
gzip --best $^ --to-stdout > $@
.PHONY: clean all install
Some tools to be used with smart cards and PC/SC
================================================
This archive contains some tools usefull for a PC/SC user.
PC/SC lite [1] from MUSCLE [2].
The tools provided are: