aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorhploetz <hploetz@f711b948-2313-0410-aaa9-d29f33439f0b>2007-06-08 00:55:16 +0000
committerhploetz <hploetz@f711b948-2313-0410-aaa9-d29f33439f0b>2007-06-08 00:55:16 +0000
commit3fa2f884191bcbac2994fcba964bbceb1087bc10 (patch)
tree4971bb7169f9cce57c0a557d3d35a562d9d7d0a2
parent918eaf3f40436925730c32096fe9f78801ae588f (diff)
Tool to read full passport information. Call without arguments to try without bac, or with mrz1 mrz2 or mrz2 to try with bac
git-svn-id: svn+ssh://localhost/home/henryk/svn/cyberflex-shell/trunk@224 f711b948-2313-0410-aaa9-d29f33439f0b
-rw-r--r--cards/passport_application.py107
-rw-r--r--cyberflex-shell.e3p5
-rwxr-xr-xfingerpass.py2
-rwxr-xr-xreadpass.py24
4 files changed, 86 insertions, 52 deletions
diff --git a/cards/passport_application.py b/cards/passport_application.py
index 8da6971..7f8600d 100644
--- a/cards/passport_application.py
+++ b/cards/passport_application.py
@@ -133,10 +133,11 @@ class Passport_Application(Application):
if verbose:
print "Kenc = %s" % hexdump(Kenc)
print "Kmac = %s" % hexdump(Kmac)
-
- print
+
+ print
result = self.send_apdu(self.APDU_GET_RANDOM)
- assert self.check_sw(result.sw)
+ if not self.check_sw(result.sw):
+ raise BACError, "SW after GET RANDOM was %02x%02x. Card refused to send rcd_icc. Should NEVER happen." % (result.sw1, result.sw2)
rnd_icc = result.data
if verbose:
@@ -155,11 +156,12 @@ class Passport_Application(Application):
if verbose:
print "Eifd = %s" % hexdump(Eifd, indent=10)
print "Mifd = %s" % hexdump(Mifd)
-
- print
+
+ print
auth_apdu = C_APDU(self.APDU_MUTUAL_AUTHENTICATE, data = Eifd + Mifd)
result = self.send_apdu(auth_apdu)
- assert self.check_sw(result.sw)
+ if not self.check_sw(result.sw):
+ raise BACError, "SW after MUTUAL AUTHENTICATE was %02x%02x. Card did not accept our BAC attempt" % (result.sw1, result.sw2)
resp_data = result.data
Eicc = resp_data[:-8]
@@ -176,9 +178,9 @@ class Passport_Application(Application):
if verbose:
print "R = %s" % hexdump(R, indent=10)
if not R[:8] == rnd_icc:
- raise ValueError, "Passport authentication failed: Wrong RND.icc on incoming data during Mutual Authenticate"
+ raise BACError, "Passport authentication failed: Wrong RND.icc on incoming data during Mutual Authenticate"
if not R[8:16] == rnd_ifd:
- raise ValueError, "Passport authentication failed: Wrong RND.ifd on incoming data during Mutual Authenticate"
+ raise BACError, "Passport authentication failed: Wrong RND.ifd on incoming data during Mutual Authenticate"
Kicc = R[16:]
if verbose:
@@ -513,6 +515,8 @@ class CBEFF:
class PassportParseError(Exception):
pass
+class BACError(Exception):
+ pass
_default_empty_mrz_data = ("","")
class Passport(object):
@@ -796,9 +800,9 @@ class Passport(object):
if not isinstance(card, ISO_7816_4_Card):
raise ValueError, "card must be a Passport_Application object or a ISO_7816_4_Card object, not %s" % type(card)
else:
- result = card.select_application("mrtd")
+ result = card.select_application(card.resolve_symbolic_aid("mrtd"))
if not card.check_sw(result.sw):
- raise EnvironmentError, "card did not accept SELECT APPLICATION, sw was %s" % result.sw
+ raise EnvironmentError, "card did not accept SELECT APPLICATION, sw was %02x %02x" % (result.sw1, result.sw2)
assert isinstance(card, Passport_Application)
p = cls(mrz_data, ignore_mrz_parse_error=True)
@@ -807,8 +811,6 @@ class Passport(object):
p.result_map_select = {}
p.result_map_read = {}
- generic_card.DEBUG = False
-
for name, fid in card.INTERESTING_FILES:
result = card.open_file(fid, 0x0C)
if not card.check_sw(result.sw) and not tried_bac and not mrz_data is _default_empty_mrz_data:
@@ -880,46 +882,53 @@ class Passport(object):
self.document_no, self.nationality, self.date_of_birth, self.sex, self.expiration_date, self.optional = "", "", "", "", "", ""
if mrz_data[0].strip() != "":
- mrz1 = mrz_data[0].replace("<", " ")
- self.type = mrz1[0:2].strip()
- self.issuer = mrz1[2:5].strip()
- n = mrz1[5:].strip().split(" ", 1)
- self.name = [n[0]]
- self.name = self.name + n[1].split(" ")
- if mrz_data[1].strip() != "":
- mrz2 = mrz_data[1]
- self.document_no = mrz2[:9].strip("<")
- if mrz2[9] == "<": # document number check digit, or filler character to indicate document number longer than 9 characters
- expanded_document_no = True
- else:
- expanded_document_no = False
- self.calculate_check_digit(mrz2[:9], mrz2[9], "Document number")
- self.nationality = mrz2[10:13].strip("<")
-
- self.date_of_birth = mrz2[13:19]
- self.calculate_check_digit(mrz2[13:19], mrz2[19], "Date of birth")
-
- self.sex = mrz2[20]
-
- self.expiration_date = mrz2[21:27]
- self.calculate_check_digit(mrz2[21:27], mrz2[27], "Date of expiration")
+ try:
+ mrz1 = mrz_data[0].replace("<", " ")
+ self.type = mrz1[0:2].strip()
+ self.issuer = mrz1[2:5].strip()
+ n = mrz1[5:].strip().split(" ", 1)
+ self.name = [n[0]]
+ self.name = self.name + n[1].split(" ")
+ except IndexError:
+ raise PassportParseError, "Some index error while parsing mrz1"
- opt_field = mrz2[28:-2]
- if not expanded_document_no:
- self.optional = opt_field.strip("<")
- if mrz2[-2] != "<":
- self.calculate_check_digit(opt_field, mrz2[-2], "Optional data")
- else:
- splitted_opt_field = opt_field.split("<", 1)
- self.document_no = self.document_no + splitted_opt_field[0][:-1]
- self.calculate_check_digit(self.document_no, splitted_opt_field[0][-1], "Expanded document number")
+ if mrz_data[1].strip() != "":
+ try:
+ mrz2 = mrz_data[1]
+ self.document_no = mrz2[:9].strip("<")
+ if mrz2[9] == "<": # document number check digit, or filler character to indicate document number longer than 9 characters
+ expanded_document_no = True
+ else:
+ expanded_document_no = False
+ self.calculate_check_digit(mrz2[:9], mrz2[9], "Document number")
+ self.nationality = mrz2[10:13].strip("<")
- if len(splitted_opt_field) > 1:
- self.optional = splitted_opt_field[1].strip("<")
+ self.date_of_birth = mrz2[13:19]
+ self.calculate_check_digit(mrz2[13:19], mrz2[19], "Date of birth")
+
+ self.sex = mrz2[20]
+
+ self.expiration_date = mrz2[21:27]
+ self.calculate_check_digit(mrz2[21:27], mrz2[27], "Date of expiration")
+
+ opt_field = mrz2[28:-2]
+ if not expanded_document_no:
+ self.optional = opt_field.strip("<")
if mrz2[-2] != "<":
- self.calculate_check_digit(splitted_opt_field[1], mrz2[-2], "Optional data")
-
- self.calculate_check_digit(mrz2[0:10]+mrz2[13:20]+mrz2[21:43], mrz2[-1], "Second line of machine readable zone")
+ self.calculate_check_digit(opt_field, mrz2[-2], "Optional data")
+ else:
+ splitted_opt_field = opt_field.split("<", 1)
+ self.document_no = self.document_no + splitted_opt_field[0][:-1]
+ self.calculate_check_digit(self.document_no, splitted_opt_field[0][-1], "Expanded document number")
+
+ if len(splitted_opt_field) > 1:
+ self.optional = splitted_opt_field[1].strip("<")
+ if mrz2[-2] != "<":
+ self.calculate_check_digit(splitted_opt_field[1], mrz2[-2], "Optional data")
+
+ self.calculate_check_digit(mrz2[0:10]+mrz2[13:20]+mrz2[21:43], mrz2[-1], "Second line of machine readable zone")
+ except:
+ raise PassportParseError, "Some index error while parsing mrz2"
if __name__ == "__main__":
diff --git a/cyberflex-shell.e3p b/cyberflex-shell.e3p
index 3657ed5..8d10629 100644
--- a/cyberflex-shell.e3p
+++ b/cyberflex-shell.e3p
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE Project SYSTEM "Project-3.7.dtd">
<!-- Project file for project cyberflex-shell -->
-<!-- Saved: 2007-06-01, 02:47:04 -->
+<!-- Saved: 2007-06-08, 02:40:24 -->
<!-- Copyright (C) 2007 Henryk Plötz, henryk@ploetzli.ch -->
<Project version="3.7">
<ProgLanguage mixed="0">Python</ProgLanguage>
@@ -102,6 +102,9 @@
<Dir>cards</Dir>
<Name>rfid_card.py</Name>
</Source>
+ <Source>
+ <Name>readpass.py</Name>
+ </Source>
</Sources>
<Forms>
</Forms>
diff --git a/fingerpass.py b/fingerpass.py
index e034b07..6f689c8 100755
--- a/fingerpass.py
+++ b/fingerpass.py
@@ -4,8 +4,6 @@
from utils import pycsc
import utils, cards, TLV_utils, sys, binascii, time, traceback, re
-STATUS_INTERVAL = 10
-
def fingerprint_rfid(card):
# Need RFID
if not isinstance(card, cards.rfid_card.RFID_Card):
diff --git a/readpass.py b/readpass.py
new file mode 100755
index 0000000..c6c50f5
--- /dev/null
+++ b/readpass.py
@@ -0,0 +1,24 @@
+#!/usr/bin/env python
+# -*- coding: iso-8859-1 -*-
+
+from utils import pycsc
+import utils, cards, TLV_utils, sys, binascii, time, traceback
+
+if __name__ == "__main__":
+ c = utils.CommandLineArgumentHelper()
+
+ (options, arguments) = c.getopt(sys.argv[1:])
+
+ pycsc_card = c.connect()
+ card = cards.new_card_object(pycsc_card)
+ cards.generic_card.DEBUG = False
+
+ print >>sys.stderr, "Using %s" % card.DRIVER_NAME
+
+ if len(arguments) > 1:
+ p = cards.passport_application.Passport.from_card(card, arguments[:2])
+ elif len(arguments) == 1:
+ p = cards.passport_application.Passport.from_card(card, ["",arguments[0]])
+ else:
+ p = cards.passport_application.Passport.from_card(card)
+