def _parse(self, contents): self._rawdata = contents self._tlvdata = TLV_utils.unpack(contents) tmp = TLV_utils.tlv_find_tag(self._tlvdata, 0xEA, num_results=1) if len(tmp) == 0: raise ValueError, "Can't parse information file, tag 0xEA not found" tmp = TLV_utils.tlv_find_tag(tmp, 0x85, num_results=1) if len(tmp) == 0: raise ValueError, "Can't parse information file, tag 0x85 not found" self._mainblob = tmp[0][2] tmp = self._mainblob some_id, tmp = tmp[:4], tmp[4:] ascii_field_len = ord(tmp[0]) tmp = tmp[1:] ascii_field, tmp = tmp[:ascii_field_len], tmp[ascii_field_len:] self._maindata = ascii_field.split(" ") if len(tmp) > 0: if tmp[0] == "\x01": tmp = tmp[1:] birthdate_bin, tmp = tmp[:4], tmp[4:] birthdate = binascii.b2a_hex(birthdate_bin) self._birthdate = datetime.date(int(birthdate[0:4]), int(birthdate[4:6]), int(birthdate[6:8])) if len(tmp) > 0: print "Warning: unparsed data trailing: %r" % tmp
def _parse(self, contents): self._rawdata = contents self._tlvdata = TLV_utils.unpack(contents) tmp = TLV_utils.tlv_find_tag(self._tlvdata, 0xEA, num_results = 1) if len(tmp) == 0: raise ValueError, "Can't parse information file, tag 0xEA not found" tmp = TLV_utils.tlv_find_tag(tmp, 0x85, num_results = 1) if len(tmp) == 0: raise ValueError, "Can't parse information file, tag 0x85 not found" self._mainblob = tmp[0][2] tmp = self._mainblob some_id, tmp = tmp[:4], tmp[4:] ascii_field_len = ord(tmp[0]) tmp = tmp[1:] ascii_field, tmp = tmp[:ascii_field_len], tmp[ascii_field_len:] self._maindata = ascii_field.split(" ") if len(tmp) > 0: if tmp[0] == "\x01": tmp = tmp[1:] birthdate_bin, tmp = tmp[:4], tmp[4:] birthdate = binascii.b2a_hex(birthdate_bin) self._birthdate = datetime.date( int(birthdate[0:4]), int(birthdate[4:6]), int(birthdate[6:8]) ) if len(tmp) > 0: print "Warning: unparsed data trailing: %r" % tmp
def _format_management_information(self, indent): result = [] if self._management_information is None: return result try: if self._card_object is not None: c = TLV_utils.decode(self._management_information, tags=self._card_object.TLV_OBJECTS, context=self._card_object.DEFAULT_CONTEXT) else: c = TLV_utils.decode(self._management_information) result.append( self.get_indent(indent + 1) + "Management information:") result.extend( map(lambda a: self.get_indent(indent + 2) + a, c.splitlines(False))) except (SystemExit, KeyboardInterrupt): raise except: result.append( self.get_indent(indent + 1) + "Raw dump of unparseable management information following:") result.extend( self._dump_internal(self._management_information, indent=indent + 2, do_tlv=False)) return result
def deformat_response(self, tlv_data, sw): WHITELIST = (0x84, 0x86, 0x98) result = [] is_ok = True for data in tlv_data: t = data[0] & ~0x01 if t not in WHITELIST and t in range(0x80, 0xBF+1): is_ok = False # Unrecognized SM field present if is_ok: for data in tlv_data: t = data[0] & ~0x01 value = data[2] if t in WHITELIST: if t == 0x86: result.append( value[1:] ) elif t == 0x98: if sw != value: print "Warning: SW from SM not equal SW from RAPDU" sw = value else: result.append( value ) else: result.append( TLV_utils.pack( (data,), recalculate_length = True) ) else: result.append( TLV_utils.pack( tlv_data, recalculate_length = True) ) return "".join(result), sw
def cmd_open(self, file): "Open a file" fid = binascii.a2b_hex("".join(file.split())) result = self.open_file(fid) if len(result.data) > 0: print utils.hexdump(result.data) print TLV_utils.decode(result.data,tags=self.TLV_OBJECTS)
def cmd_open(self, file): "Open a file" fid = binascii.a2b_hex("".join(file.split())) result = self.open_file(fid) if len(result.data) > 0: print utils.hexdump(result.data) print TLV_utils.decode(result.data, tags=self.TLV_OBJECTS)
def cmd_selectapplication(self, application): """Select an application on the card. application can be given either as hexadecimal aid or by symbolic name (if known).""" aid = self.resolve_symbolic_aid(application) result = self.select_application(aid) if len(result.data) > 0: print utils.hexdump(result.data) print TLV_utils.decode(result.data, tags=self.TLV_OBJECTS)
def parse_DG1(self, contents): structure = TLV_utils.unpack(contents) try: mrz = TLV_utils.tlv_find_tag(structure, 0x5F1F, 1)[0][2] except IndexError: raise PassportParseError, "Could not find MRZ information in DG1" # Length of an MRZ line is either 30+5 or 31+5 or 39+5, depending on document type. (LDS technical report 2004, section 16.1) mrz_data = (mrz[:len(mrz) / 2], mrz[len(mrz) / 2:]) self.dg1_mrz = mrz_data self._parse_mrz(mrz_data)
def cmd_selectapplication(self, application): """Select an application on the card. application can be given either as hexadecimal aid or by symbolic name (if known).""" aid = self.resolve_symbolic_aid(application) result = self.select_application(aid) if len(result.data) > 0: print utils.hexdump(result.data) print TLV_utils.decode(result.data,tags=self.TLV_OBJECTS)
def parse_DG1(self, contents): structure = TLV_utils.unpack(contents) try: mrz = TLV_utils.tlv_find_tag(structure, 0x5F1F, 1)[0][2] except IndexError: raise PassportParseError, "Could not find MRZ information in DG1" # Length of an MRZ line is either 30+5 or 31+5 or 39+5, depending on document type. (LDS technical report 2004, section 16.1) mrz_data = (mrz[:len(mrz)/2], mrz[len(mrz)/2:]) self.dg1_mrz = mrz_data self._parse_mrz(mrz_data)
def cmd_selectfile(self, p1, p2, fid): """Select a file on the card.""" p1 = binascii.a2b_hex("".join(p1.split())) p2 = binascii.a2b_hex("".join(p2.split())) fid = binascii.a2b_hex("".join(fid.split())) result = self.select_file(p1, p2, fid) if len(result.data) > 0: print utils.hexdump(result.data) print TLV_utils.decode(result.data,tags=self.TLV_OBJECTS)
def cmd_selectfile(self, p1, p2, fid): """Select a file on the card.""" p1 = binascii.a2b_hex("".join(p1.split())) p2 = binascii.a2b_hex("".join(p2.split())) fid = binascii.a2b_hex("".join(fid.split())) result = self.select_file(p1, p2, fid) if len(result.data) > 0: print utils.hexdump(result.data) print TLV_utils.decode(result.data, tags=self.TLV_OBJECTS)
def dump(data): print "Dump following (%i bytes)" % (len(data)) print utils.hexdump(data) try: print "Trying TLV parse:" print TLV_utils.decode(data, tags=card.TLV_OBJECTS, context = card.DEFAULT_CONTEXT) print "TLV parsed successfully" except (SystemExit, KeyboardInterrupt): raise except: print "TLV error" pass
def cmd_cd(self, dir=None): "Change into a DF, or into the MF if no dir is given" if dir is None: result = self.change_dir() else: fid = binascii.a2b_hex("".join(dir.split())) result = self.change_dir(fid) if len(result.data) > 0: print utils.hexdump(result.data) print TLV_utils.decode(result.data, tags=self.TLV_OBJECTS)
def cmd_cd(self, dir = None): "Change into a DF, or into the MF if no dir is given" if dir is None: result = self.change_dir() else: fid = binascii.a2b_hex("".join(dir.split())) result = self.change_dir(fid) if len(result.data) > 0: print utils.hexdump(result.data) print TLV_utils.decode(result.data,tags=self.TLV_OBJECTS)
def cmd_parsetlv(self, start = None, end = None): "Decode the TLV data in the last response, start and end are optional" lastlen = len(self.last_result.data) if start is not None: start = (lastlen + (int(start,0) % lastlen) ) % lastlen else: start = 0 if end is not None: end = (lastlen + (int(end,0) % lastlen) ) % lastlen else: end = lastlen print TLV_utils.decode(self.last_result.data[start:end], tags=self.TLV_OBJECTS, context = self.DEFAULT_CONTEXT)
def process_apdu(self, apdu): if apdu.cla & 0x0c in (0x0c, 0x08): tlv_data = TLV_utils.unpack(apdu.data, with_marks = apdu.marks, include_filler=True) tlv_data = self.encrypt_command(tlv_data) tlv_data = self.authenticate_command(apdu, tlv_data) data = TLV_utils.pack(tlv_data, recalculate_length = True) new_apdu = C_APDU(apdu, data = data) return new_apdu else: return apdu
def cmd_parsetlv(self, start=None, end=None): "Decode the TLV data in the last response, start and end are optional" lastlen = len(self.last_result.data) if start is not None: start = (lastlen + (int(start, 0) % lastlen)) % lastlen else: start = 0 if end is not None: end = (lastlen + (int(end, 0) % lastlen)) % lastlen else: end = lastlen print TLV_utils.decode(self.last_result.data[start:end], tags=self.TLV_OBJECTS, context=self.DEFAULT_CONTEXT)
def cmd_passive_auth(self, verbose=1): "Perform passive authentication" hashes = {} result = "" i = 0 for name in ("DG1", "DG2", "SOD"): fid = None for n, f in self.INTERESTING_FILES: if n == name: fid = f break if fid is None: return i += 1 result = self.open_file(fid, 0x0c) if self.check_sw(result.sw): contents, sw = self.read_binary_file() #self.last_result = R_APDU(contents + self.last_sw) if name != "SOD": hashes[i] = crypto_utils.hash("SHA", contents) else: result = self.verify_cms(contents[4:]) #print hexdump(result) #print "DG1: %s" % hexdump(hashes[i]) #print "DG2: %s" % hexdump(hashes[2]) res = TLV_utils.tlv_find_tag(TLV_utils.unpack(result), 0x04) if len(res) == 0: print "failed to verify EF.SOD" return else: print "verified EF.SOD" i = 0 for tag, length, hash in res: i += 1 if hexdump(hashes[i]) == hexdump(hash): print "DG%d hash verified: %s" % (i, binascii.b2a_hex(hash)) else: print "DG%d hash failed:" % i print "was: %s" % binascii.b2a_hex(hashes[i]) print "expected: %s" % binascii.b2a_hex(hash) return
def _dump_internal(self, data, indent, do_tlv=True): c = utils.hexdump(data) r = map(lambda a: self.get_indent(indent)+a, c.splitlines(False)) if do_tlv: try: if self._card_object is not None: c = TLV_utils.decode(data, tags=self._card_object.TLV_OBJECTS, context = self._card_object.DEFAULT_CONTEXT) else: c = TLV_utils.decode(data) r.append( self.get_indent(indent) + "Trying TLV parse:" ) r.extend( map(lambda a: self.get_indent(indent)+a, c.splitlines(False)) ) except (SystemExit, KeyboardInterrupt): raise except: pass return r
def set_passport(self, passport): self.passport = passport for sources, transform, destinations in self.PROPERTY_TRANSFORMATIONS: values = [getattr(passport, src) for src in sources] transformed = transform(passport, values) for index, dst in enumerate(destinations): widget = self.main_window_xml.get_widget(dst) if not self.format_strings.has_key(dst): self.format_strings[dst] = widget.get_label() widget.set_label( self.format_strings[dst] % transformed[index] ) data = [] if hasattr(passport, "dg2_cbeff") and passport.dg2_cbeff is not None: for biometric in passport.dg2_cbeff.biometrics: data = data + [(a,b,"Encoded Face") for (a,b) in biometric.get_images()] for dg, tag, type in ( ("dg5", 0x5F40, "Displayed Portrait"), ("dg7", 0x5F43, "Displayed Signature or Usual Mark") ): if hasattr(passport, "%s_tlv" % dg): structure = getattr(passport, "%s_tlv" % dg) if structure is not None: hits = TLV_utils.tlv_find_tag(structure, tag) for t,l,v in hits: data.append( ("jpg",v,type) ) self._set_images(data)
def _format_management_information(self, indent): result = [] if self._management_information is None: return result try: if self._card_object is not None: c = TLV_utils.decode(self._management_information, tags=self._card_object.TLV_OBJECTS, context = self._card_object.DEFAULT_CONTEXT) else: c = TLV_utils.decode(self._management_information) result.append(self.get_indent(indent+1) + "Management information:") result.extend( map(lambda a: self.get_indent(indent+2)+a, c.splitlines(False)) ) except (SystemExit, KeyboardInterrupt): raise except: result.append(self.get_indent(indent+1) + "Raw dump of unparseable management information following:") result.extend(self._dump_internal(self._management_information, indent=indent+2, do_tlv=False)) return result
def __init__(self, structure, top_tag=0x7F60): "Create a new CBEFF instance from a nested TLV structure (as returned by TLV_utils.unpack)." self.biometrics = [] self.unknown_biometrics = [] blocks = TLV_utils.tlv_find_tag(structure, top_tag) for block in blocks: self.addbiometric(block[2])
def __init__(self, structure, top_tag = 0x7F60): "Create a new CBEFF instance from a nested TLV structure (as returned by TLV_utils.unpack)." self.biometrics = [] self.unknown_biometrics = [] blocks = TLV_utils.tlv_find_tag(structure, top_tag) for block in blocks: self.addbiometric(block[2])
def _dump_internal(self, data, indent, do_tlv=True): c = utils.hexdump(data) r = map(lambda a: self.get_indent(indent) + a, c.splitlines(False)) if do_tlv: try: if self._card_object is not None: c = TLV_utils.decode( data, tags=self._card_object.TLV_OBJECTS, context=self._card_object.DEFAULT_CONTEXT) else: c = TLV_utils.decode(data) r.append(self.get_indent(indent) + "Trying TLV parse:") r.extend( map(lambda a: self.get_indent(indent) + a, c.splitlines(False))) except (SystemExit, KeyboardInterrupt): raise except: pass return r
def _find_recursive(search_tag, data): while len(data) > 0: if ord(data[0]) in (0x00, 0xFF): data = data[1:] continue ber_class, constructed, tag, length, value, data = TLV_utils.tlv_unpack(data) if not constructed: if tag == search_tag: return value else: ret = Card_with_ls._find_recursive(search_tag, value) if ret is not None: return ret return None
def process_rapdu(self, rapdu): result = rapdu if self.last_c_apdu.cla & 0x0c in (0x0c, 0x08): tlv_c_data = TLV_utils.unpack(self.last_c_apdu.data) must_authenticate = False must_decrypt = False for data in tlv_c_data: if data[0] & ~0x01 == 0xBA: for response_template in data[2]: if response_template[0] == 0x8E: must_authenticate = True if response_template[0] & ~0x01 in (0x84, 0x86): must_decrypt = True if must_authenticate or must_decrypt: tlv_data = TLV_utils.unpack(rapdu.data, include_filler=True) try: if must_authenticate: tlv_data = self.authenticate_response(tlv_data) if must_decrypt: tlv_data = self.decrypt_response(tlv_data) #data = TLV_utils.pack(tlv_data, recalculate_length = True) data, sw = self.deformat_response(tlv_data, rapdu.sw) new_apdu = R_APDU(rapdu, data = data, sw = sw) result = new_apdu except ValueError: print "Warning: Can't authenticate/decrypt response due to exception being raised" traceback.print_exc(limit=2) return result
def _find_recursive(search_tag, data): while len(data) > 0: if ord(data[0]) in (0x00, 0xFF): data = data[1:] continue ber_class, constructed, tag, length, value, data = TLV_utils.tlv_unpack( data) if not constructed: if tag == search_tag: return value else: ret = Card_with_ls._find_recursive(search_tag, value) if ret is not None: return ret return None
def list_x(self, x): "Get a list of x objects, where x is one of 0 (DFs) or 1 (EFs) or 2 (DFs and EFs)" ## FIXME I just guessed this information result = self.send_apdu(C_APDU(self.APDU_LIST_X, p1=x)) files = [] unpacked = TLV_utils.unpack(result.data) for tag, length, value in unpacked: if isinstance(value, list): for tag, length, value in value: if tag == 0x86: files.append(value) else: if tag == 0x86: files.append(value) return files
def parse(self, config): structure = TLV_utils.unpack(config) for data in structure: tag, length, value = data if tag == 0x80: self.mode = ord(value[0]) & 1 algorithm = (ord(value[0]) >> 2) & 0x7 self.algorithm = algorithm elif tag in (0x83, 0x84): self.keyref = ord(value) self.keytype = tag elif tag == 0x85: self.iv = "\x00" * 8 elif tag == 0x87: self.iv = value elif tag == 0x88: self.iv = None ## FIXME else: print "Warning: Unknown MSE parameters: tag 0x%02x, length 0x%02x, value: %s" % (tag, length, utils.hexdump(value, short=True))
def calculate_cct(self, config, tlv_data, startblock = "", print_buffer=True): """Calculate the Cryptographic Checksum for some TLV data. tlv_data MUST be of the format generated by the include_filler=True parameter to unpack.""" if print_buffer: print "| Calculating cryptographic checksum:" def do_block(buffer, block): block_ = self.pad("".join(block), pi = PI_ISO) offset = sum( [len(b) for b in buffer] ) buffer.append(block_) del block[:] if print_buffer: print "|| " + "\n|| ".join( utils.hexdump( block_, offset = offset ).splitlines() ) buffer = [] if startblock != "": do_block(buffer, [startblock]) block = [] for data in tlv_data: tag, length, value = data[:3] if (tag & 0x01 == 0x01 or tag not in range(0x80, 0xbf+1)) and tag not in (0xff, 0x00): value_ = TLV_utils.pack( (data, ), recalculate_length=True ) block.append( value_ ) elif tag in (0xff, 0x00) and len(block) > 0: block.append( chr(tag) ) else: if len(block) > 0: do_block(buffer, block) if len(block) > 0: do_block(buffer, block) cct = self._mac(config, "".join(buffer)) if print_buffer: print "| Result (Tag 0x8e, length: 0x%02x):" % len(cct) print "|| " + "\n|| ".join( utils.hexdump( cct ).splitlines() ) return cct
def verify_cms(self, data): """Verify a pkcs7 SMIME message""" from M2Crypto import SMIME, X509, BIO import base64, TLV_utils, os data3 = "-----BEGIN PKCS7-----\n" data3 += base64.encodestring(data) data3 += "-----END PKCS7-----" #print data3 p7_bio = BIO.MemoryBuffer(data3) # Instantiate an SMIME object. s = SMIME.SMIME() # TODO: ugly hack for M2Crypto body = TLV_utils.tlv_find_tag(TLV_utils.unpack(data), 0xA0, 1)[0][2] thecert = TLV_utils.tlv_find_tag(body, 0xA0, 2)[1][2] cert_bio = BIO.MemoryBuffer(TLV_utils.pack(thecert)) # Load the signer's cert. x509 = X509.load_cert_bio(cert_bio, format=0) sk = X509.X509_Stack() sk.push(x509) s.set_x509_stack(sk) country = str(x509.get_issuer()).split('/')[1][2:] #print country cacert = country + "-cacert.der" #print cacert msgErr = "couldn't parse certificate to determine URL for CACert, search the intertubes," msg = "download CACert (convert to DER if necessary) and save it as \n\"%s\"" % cacert if not os.path.isfile(cacert): try: v = x509.get_ext("certificatePolicies").get_value() start = v.find("CPS: ") if start != -1: url = v[start + 5:-1] print "visit %s" % url, msg else: print msgErr, msg except Exception: print msgErr, msg return "" # Load the signer's CA cert. st = X509.X509_Store() #st.load_info('main') x509CA = X509.load_cert(cacert, format=0) st.add_x509(x509CA) s.set_x509_store(st) # Load the data, verify it. #p7, data = SMIME.smime_load_pkcs7_bio(p7_bio) p7 = SMIME.load_pkcs7_bio(p7_bio) v = s.verify(p7) return v
def parse_DG7(self, contents): self.dg7_tlv = TLV_utils.unpack(contents)
traceback.print_exc() print >>sys.stderr print "="*80 print "Results:" for fid, result in sorted(results_dir.items()): if results_file.has_key(fid): continue print "-"*80 print "Dir\t%04X" % fid if len(result.data) > 0: print utils.hexdump(result.data) try: print TLV_utils.decode(result.data,tags=card.TLV_OBJECTS) except: print "Exception during TLV parse" for fid, result in sorted(results_file.items()): print "-"*80 print "File\t%04X" % fid if len(result.data) > 0: print utils.hexdump(result.data) try: print TLV_utils.decode(result.data,tags=card.TLV_OBJECTS) except: print "Exception during TLV parse" if contents_file.has_key( fid ): contents_result = contents_file[fid] if contents_result[0] == '\x69\x81': print "Record-oriented file" elif contents_result[0] == '\x69\x82':
0x86: (decode_security_attributes, "Security attributes"), 0x85: (decode_file_descriptor_extension_HACK, "File descriptor extension"), }, } TLV_OBJECTS[TLV_utils.context_FCI] = TLV_OBJECTS[TLV_utils.context_FCP] COMMANDS = { "list_dirs": building_blocks.Card_with_80_aa.cmd_listdirs, "list_files": building_blocks.Card_with_80_aa.cmd_listfiles, "ls": building_blocks.Card_with_80_aa.cmd_list, "delete": cmd_delete, "clear_se": cmd_clear_se, "set_key": cmd_set_key, } TLV_utils.identifier("context_ardo") TLV_utils.identifier("context_art") def decode_access_rule(mask, value): result = [] for i in range(3, -1, -1): if mask & (1<<i): result.append(binascii.b2a_hex(value[0])) value = value[1:] else: result.append("__"); return " " + " ".join(result) compact_access_descriptions = ( (0xc0, 0xc0, None, "proprietary"), (0xa0, 0xa0, None, "proprietary"),
def from_data(cls, data, offset=0, length=None, **kwargs): if length is None: length = len(data) - offset structure = TLV_utils.unpack(data[offset:offset + length]) return cls(structure=structure, **kwargs)
def from_data(cls, data, offset = 0, length = None, **kwargs): if length is None: length = len(data) - offset structure = TLV_utils.unpack(data[offset:offset+length]) return cls(structure=structure, **kwargs)