diff options
author | hploetz <hploetz@f711b948-2313-0410-aaa9-d29f33439f0b> | 2007-06-08 00:55:16 +0000 |
---|---|---|
committer | hploetz <hploetz@f711b948-2313-0410-aaa9-d29f33439f0b> | 2007-06-08 00:55:16 +0000 |
commit | 3fa2f884191bcbac2994fcba964bbceb1087bc10 (patch) | |
tree | 4971bb7169f9cce57c0a557d3d35a562d9d7d0a2 | |
parent | 918eaf3f40436925730c32096fe9f78801ae588f (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.py | 107 | ||||
-rw-r--r-- | cyberflex-shell.e3p | 5 | ||||
-rwxr-xr-x | fingerpass.py | 2 | ||||
-rwxr-xr-x | readpass.py | 24 |
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) + |