示例#1
0
 def second_gac(self):
     tag8D = self.get_tag(PROCESS_STEP.READ_RECORD, '8D')
     data = tools.assemble_dol(tag8D)
     resp = super().gac(Crypto_Type.TC, data)
     if resp.sw != 0x9000:
         Log.info('send gac1 failed.')
         return
     tlvs = utils.parse_tlv(resp.response)
     tools.output_apdu_info(resp)
     self.store_tag_group(PROCESS_STEP.SECOND_GAC,
                          utils.parse_tlv(resp.response))
     return resp
示例#2
0
 def first_gac(self):
     tag8C = self.get_tag(PROCESS_STEP.READ_RECORD, '8C')
     data = tools.assemble_dol(tag8C)
     resp = super().gac(Crypto_Type.ARQC, data)
     if resp.sw != 0x9000:
         Log.info('send gac1 failed.')
         return
     tlvs = utils.parse_tlv(resp.response)
     tools.output_apdu_info(resp)
     self.store_tag_group(PROCESS_STEP.FIRST_GAC,
                          utils.parse_tlv(resp.response))
     self.run_case('case_first_gac', 'run_mc', resp)
     return resp
示例#3
0
 def _get_pse_tag_list(self):
     '''
     获取PSE节点中包含的tag标签列表
     '''
     tlv_list = []
     dgi = self.cps.get_dgi('PSE')
     dgi_0101_tags = utils.parse_tlv(dgi.get_value('0101'))
     dgi_9102_tags = utils.parse_tlv(dgi.get_value('9102'))
     for tag in dgi_0101_tags:
         if tag.is_template is False and tag.len > 0:
             tlv_list.append(tag)
     for tag in dgi_9102_tags:
         if tag.is_template is False and tag.len > 0:
             tlv_list.append(tag)
     return tlv_list
示例#4
0
 def application_selection(self, aid):
     resp = super().application_selection(aid)
     tools.output_apdu_info(resp)
     self.store_tag_group(PROCESS_STEP.SELECT,
                          utils.parse_tlv(resp.response))
     # self.run_case('case_application_selection','run_visa',resp)
     return resp
def check_fci_9102(buffer):
    tlvs = utils.parse_tlv(buffer)
    sub_tlvs = []
    sub_fci_9102 = []
    for tlv in tlvs:
        for fci_item in fci_9102:
            if tlv.tag == fci_item[0]:
                sub_fci_9102.append(fci_item)
                sub_tlvs.append(tlv)
    # 判断集合中的顺序是否一致
    has_ordered = True
    for index in range(len(sub_fci_9102)):
        if sub_fci_9102[index][0] != sub_tlvs[index].tag or sub_fci_9102[index][1] != sub_tlvs[index].level:
            Log.warn('tag%s is not ordered.',sub_tlvs[index].tag)
            has_ordered = False
    if not has_ordered:
        order_tags = [item[0] for item in sub_fci_9102]
        Log.warn('the minium order list should be %s',str(order_tags))
    # 判断是否缺少必须的tag
    for item in fci_9102:
        if item not in sub_fci_9102:
            if item[2] == TagCondition.M:
                Log.error('FCI 9102 should contains tag%s',item[0])
            elif item[2] == TagCondition.C:
                Log.warn('FCI 9102 recommand that tag%s should be existed.',item[0])
    # 判断是否包含多余的tag
    for item in tlvs:
        if item not in sub_tlvs:
            Log.warn('FCI 9102 should not contains tag%s',item.tag)
示例#6
0
 def gen_9F4B(self,ddol):
     '''
     发送内部认证命令,卡片生成tag9F4B动态签名数据
     '''
     resp = apdu.internal_auth(ddol)
     if resp.sw != 0x9000:
         Log.error('SW: %0X',resp.sw)
         Log.error('send internal authentication apdu command failed whereby dda/cda failed')
         return ''
     tlvs = utils.parse_tlv(resp.response)
     if not tlvs:
         Log.error('response: %s',resp.response)
         Log.error('internal authentication response data can not be breaked up to tlv format')
         return ''
     # 返回的APDU可能是模板77或者80
     if resp.response.startswith('77'):
         if len(tlvs) != 2:
             Log.error('response: %s',resp.response)
             Log.error('internal authentication response data is not correct')
             return ''
         return tlvs[1].value
     elif resp.response.startswith('80'):
         return tlvs[0].value
     else:
         Log.error('response: %s',resp.response)
         Log.error('internal authentication response data is not startwith 70/80')
     return ''
示例#7
0
 def application_selection(self):
     resp = super().application_selection('315041592E5359532E4444463031')
     tools.output_apdu_info(resp)
     self.store_tag_group(PROCESS_STEP.SELECT,
                          utils.parse_tlv(resp.response))
     # self.run_case('case_application_selection',resp)
     return resp
示例#8
0
 def _get_aid(self):
     '''
     根据PSE中的DGI0101分组获取tag4F
     '''
     dgi = self.cps.get_dgi('PSE')
     dgi_0101_tags = utils.parse_tlv(dgi.get_value('0101'))
     for tag in dgi_0101_tags:
         if tag.tag == '4F':
             return tag.value
示例#9
0
def process_dp(dp_file, rule_file):
    fh = FileHandle(dp_file, 'rb+')
    fh.read(fh.current_offset, 8596)  #reserved
    dgi_list = get_dgi_list(fh)
    file_size = fh.file_size
    cps_list = []
    while fh.current_offset < file_size:
        card_seq = fh.read_int64_reverse(fh.current_offset)
        card_data_total_len = fh.read_int_reverse(fh.current_offset)
        cps = Cps()  #存储单个卡片数据
        cps.dp_file_path = dp_file
        pse_and_ppse_dgi = [
            'Store_PSE_1', 'Store_PSE_2', 'Store_PPSE', 'DGIF001'
        ]
        for dgi_name in dgi_list:
            dgi = Dgi()  #存储单个DGI数据
            if dgi_name in pse_and_ppse_dgi:
                if dgi_name == 'Store_PSE_1':
                    dgi = process_pse_and_ppse(fh, dgi_name, True)
                else:
                    dgi = process_pse_and_ppse(fh, dgi_name, False)
                cps.add_dgi(dgi)
                continue
            dgi_mark = fh.read_binary(fh.current_offset, 1)  #DGI标识
            if dgi_mark != '86':
                return
            next_len = get_next_len(fh)
            dgi_seq = fh.read_binary(fh.current_offset, 2)  #读取DGI序号
            dgi.name = dgi_seq
            next_len = get_next_len(fh)
            n_dgi_seq = utils.hex_str_to_int(dgi_seq)
            if n_dgi_seq <= 0x0B00:  #认为是记录
                template70 = fh.read_binary(fh.current_offset, 1)
                if template70 != '70':
                    return
                next_len = get_next_len(fh)
            dgi_data = fh.read_binary(fh.current_offset, next_len)
            if n_dgi_seq <= 0x0B00 or (dgi_seq not in do_not_parse_tlv_list
                                       and utils.is_tlv(dgi_data)):
                tlvs = utils.parse_tlv(dgi_data)
                if len(tlvs) > 0 and tlvs[0].is_template is True:
                    value = utils.assemble_tlv(tlvs[0].tag, tlvs[0].value)
                    dgi.add_tag_value(dgi_seq, value)
                else:
                    for tlv in tlvs:
                        value = utils.assemble_tlv(tlv.tag, tlv.value)
                        dgi.add_tag_value(tlv.tag, value)
            else:
                dgi.add_tag_value(dgi_seq, dgi_data)
            cps.add_dgi(dgi)
        if rule_file is not None:
            process_rule(rule_file, cps)
            process_rule_A001(rule_file, cps)
            process_rule_eps(rule_file, cps)
        cps_list.append(cps)
    return cps_list
示例#10
0
 def read_record(self):
     resps = None
     tag94 = self.get_tag(PROCESS_STEP.GPO, '94')
     if tag94:
         resps = super().read_record(tag94)
         for resp in resps:
             self.store_tag_group(PROCESS_STEP.READ_RECORD,
                                  utils.parse_tlv(resp.response))
         # self.run_case('case_read_record','run_visa',resps)
     return resps
示例#11
0
def process_dp(dp_file, rule_file):
    cps_list = []
    fh = FileHandle(dp_file, 'rb+')
    dp_flag = fh.read_binary(fh.current_offset, 7)
    data_len = utils.hex_str_to_int(fh.read_binary(fh.current_offset, 8))
    dgi_count = fh.read_int64(fh.current_offset)
    dgi_list = []
    for i in range(dgi_count):
        dgi_name_len = fh.read_int(fh.current_offset)
        dgi_name = fh.read_str(fh.current_offset, dgi_name_len)
        dgi_list.append(dgi_name)
    card_seq = fh.read_binary(fh.current_offset, 4)
    card_data_len = fh.read_int(fh.current_offset)
    while data_len > fh.current_offset:
        cps = Cps()
        cps.dp_file_path = dp_file
        for item in dgi_list:
            dgi = Dgi()
            start_flag = fh.read_binary(fh.current_offset, 1)
            if start_flag != '86':
                return cps_list
            dgi_len = get_len(fh)
            dgi_name = fh.read_binary(fh.current_offset, 2)
            dgi.name = dgi_name
            dgi_data_len = utils.hex_str_to_int(
                fh.read_binary(fh.current_offset, 1))
            n_dgi_seq = utils.hex_str_to_int(dgi_name)
            if n_dgi_seq <= 0x0B00:  #认为是记录
                template70 = fh.read_binary(fh.current_offset, 1)
                if template70 != '70':
                    return cps_list
                dgi_data_len = get_len(fh)
            dgi_data = fh.read_binary(fh.current_offset, dgi_data_len)
            if item[0:3] == 'PSE':
                dgi = process_pse_and_ppse(dgi_name, dgi_data, 'PSE')
            elif item[0:4] == 'PPSE':
                dgi = process_pse_and_ppse(dgi_name, dgi_data, 'PPSE')
            else:
                if n_dgi_seq <= 0x0B00 or (utils.is_rsa(dgi_name) is False
                                           and utils.is_tlv(dgi_data)):
                    tlvs = utils.parse_tlv(dgi_data)
                    if len(tlvs) > 0 and tlvs[0].is_template is True:
                        value = utils.assemble_tlv(tlvs[0].tag, tlvs[0].value)
                        dgi.add_tag_value(dgi_name, value)
                    else:
                        for tlv in tlvs:
                            value = utils.assemble_tlv(tlv.tag, tlv.value)
                            dgi.add_tag_value(tlv.tag, value)
                else:
                    dgi.add_tag_value(dgi_name, dgi_data)
            cps.add_dgi(dgi)
        if rule_file is not None:
            process_rule(rule_file, cps)
        cps_list.append(cps)
    return cps_list
示例#12
0
 def gpo(self):
     tag9F38 = self.get_tag(PROCESS_STEP.SELECT, '9F38')
     data = ''
     if tag9F38:
         data = tools.assemble_dol(tag9F38)
     resp = super().gpo(data)
     if resp.sw == 0x9000:
         tools.output_apdu_info(resp)
         self.store_tag_group(PROCESS_STEP.GPO,
                              utils.parse_tlv(resp.response))
         # self.run_case('case_gpo','run_visa',resp)
     return resp
示例#13
0
 def gpo(self):
     tag9F38 = self.get_tag(PROCESS_STEP.SELECT, '9F38')
     pdol = ''
     if tag9F38:
         pdol = tools.assemble_dol(tag9F38)
     resp = super().gpo(pdol)
     if resp.sw == 0x9000:
         tools.output_apdu_info(resp)
         tlvs = utils.parse_tlv(resp.response)
         self.store_tag_group(PROCESS_STEP.GPO, tlvs)
         self.run_case('case_gpo', resp)
     return resp
示例#14
0
 def _get_dgi_list(self, tag94):
     '''
     根据tag94获取对应的DGI分组
     '''
     dgi_list = []
     dgi = self.cps.get_dgi(tag94)
     tag94 = utils.parse_tlv(dgi.get_value('94'))
     afls = utils.parse_afl(tag94[0].value)
     for afl in afls:
         sfi = utils.int_to_hex_str(afl.sfi)
         record = utils.int_to_hex_str(afl.record_no)
         dgi_list.append(sfi + record)
     return dgi_list
示例#15
0
 def read_record(self):
     aids = []
     sfi = 1
     for record_no in range(1, 5):
         resp = apdu.read_record(sfi, record_no, (0x9000, 0x6A83))
         tools.output_apdu_info(resp)
         if resp.sw == 0x6A83:
             break
         tlvs = utils.parse_tlv(resp.response)
         for tlv in tlvs:
             if tlv.tag == '4F':
                 aids.append(tlv.value)
     return aids
示例#16
0
 def application_selection(self):
     aids = []
     resp = super().application_selection('325041592E5359532E4444463031')
     if resp.sw != 0x9000:
         Log.error('select ppse failed, sw=%0X', resp.sw)
         return aids
     tools.output_apdu_info(resp)
     tlvs = utils.parse_tlv(resp.response)
     for tlv in tlvs:
         if tlv.tag == '4F':
             aids.append(tlv.value)
     self.store_tag_group(PROCESS_STEP.SELECT, tlvs)
     # self.run_case('case_application_selection',resp)
     return aids
示例#17
0
 def _get_dgi_tags(self, dgi):
     '''
     获取指定DGI节点下的tag标签列表
     '''
     tlv_list = []
     dgi_tags = self.cps.get_dgi(dgi)
     if dgi_tags is None:
         return tlv_list
     for _, value in dgi_tags.tag_value_dict.items():
         tags = utils.parse_tlv(value)
         for tag in tags:
             if tag.tag not in no_contain_list and tag.is_template is False:
                 tlv_list.append(tag)
     return tlv_list
示例#18
0
def process_card_data(fh, rule_file):
    cps = Cps()
    flag = fh.read_str(fh.current_offset, 6)
    if flag != '000EMV':
        return False, cps
    card_data_len = fh.read_int64(fh.current_offset)
    app_count = utils.hex_str_to_int(fh.read_binary(fh.current_offset, 1))
    for app in range(app_count):
        aid_len = utils.hex_str_to_int(fh.read_binary(fh.current_offset, 1))
        aid = fh.read_binary(fh.current_offset, aid_len)
        app_data_len = fh.read_int64(fh.current_offset)
        dgi_list, encrypt_dgi_list = get_dgi_list(fh)
        Log.info('encrypt dgi list :', encrypt_dgi_list)
        for item in dgi_list:
            card_dgi = Dgi()
            dgi = fh.read_binary(fh.current_offset, 2)
            dgi_len = utils.hex_str_to_int(fh.read_binary(
                fh.current_offset, 1))
            dgi_data = fh.read_binary(fh.current_offset, dgi_len)
            n_dgi = utils.hex_str_to_int(dgi)
            card_dgi.dgi = dgi
            if dgi == '0098' or dgi == '0099':
                dgi = process_pse(dgi, dgi_data)
            elif dgi == '0100':
                dgi = process_ppse(dgi, dgi_data)
            else:
                if n_dgi < 0x0B01:
                    if dgi_data[0:2] != '70':
                        return False, cps
                    if dgi_data[2:4] == '81':
                        dgi_data = dgi_data[6:]
                    else:
                        dgi_data = dgi_data[4:]
                if utils.is_rsa(dgi) is False and utils.is_tlv(dgi_data):
                    tlvs = utils.parse_tlv(dgi_data)
                    if len(tlvs) > 0 and tlvs[0].is_template is True:
                        value = utils.assemble_tlv(tlvs[0].tag, tlvs[0].value)
                        card_dgi.add_tag_value(dgi, value)
                    else:
                        for tlv in tlvs:
                            value = process_tag_decrypt(
                                rule_file, tlv.tag, tlv.value)
                            value = utils.assemble_tlv(tlv.tag, value)
                            card_dgi.add_tag_value(tlv.tag, value)
                else:
                    card_dgi.add_tag_value(dgi, dgi_data)
            cps.add_dgi(card_dgi)
    return True, cps
示例#19
0
    def parse_store_data(self,
                         app_type,
                         dgi_name,
                         data,
                         session_key=None,
                         is_encrypted=False,
                         delete80_list=[]):
        int_dgi_name = int(dgi_name, 16)
        if is_encrypted and session_key:
            data = des3_ecb_decrypt(session_key, data)
            if dgi_name in delete80_list:
                index = data.rfind('80')
                if index != -1:
                    data = data[0:index]

        #对于PSE和PPSE,不解析TLV格式
        if app_type in ('PSE', 'PPSE'):
            dgi = Dgi()
            dgi.name = app_type
            if data.startswith('70'):
                data = data[4:]  #去掉70模板
            dgi.add_tag_value(dgi_name, data)
            return dgi
        else:
            #规则如下:
            #1. 小于0x0B00的记录数据需要解析TLV结构
            #2. 如果DGI大于0B00,并且该数据可以解析成TLV,则分如下情况
            #   a. 如果是8000,9000,9102,9103等不需要分析TLV结构的,则不分析
            #   b. 如果DGI以A,B字母开头(万事达应用),不用做TLV分析
            if int_dgi_name <= 0x0B00 \
                or (dgi_name not in self.do_not_parse_tlv_list \
                    and utils.is_tlv(data)\
                    and not (dgi_name.startswith('A') or dgi_name.startswith('B')) ):
                if utils.is_tlv(data):
                    tlvs = utils.parse_tlv(data)
                    return self._assemble_dgi(dgi_name, tlvs)
                else:
                    dgi = Dgi()
                    dgi.name = dgi_name
                    dgi.add_tag_value(dgi_name, data)
                    return dgi
            else:
                dgi = Dgi()
                dgi.name = dgi_name
                if dgi_name.endswith('_2'):
                    dgi_name = dgi_name[:-2]
                dgi.add_tag_value(dgi_name, data)
                return dgi
示例#20
0
 def first_gac(self):
     tag8C = self.get_tag(PROCESS_STEP.READ_RECORD, '8C')
     data = tools.assemble_dol(tag8C)
     resp = super().gac(Crypto_Type.ARQC, data)
     if resp.sw != 0x9000:
         Log.info('send gac1 failed.')
         return
     tlvs = utils.parse_tlv(resp.response)
     if len(tlvs) != 1 and tlvs[0].tag != '80':
         Log.info('gac1 response data error')
     data = tlvs[0].value
     self.store_tag(PROCESS_STEP.FIRST_GAC, '9F27', data[0:2])
     self.store_tag(PROCESS_STEP.FIRST_GAC, '9F36', data[2:6])
     self.store_tag(PROCESS_STEP.FIRST_GAC, '9F26', data[6:22])
     self.store_tag(PROCESS_STEP.FIRST_GAC, '9F10', data[22:])
     return resp
示例#21
0
def parse_sddf_data(xml, sddf_tag, goldpac_dgi_list=[]):
    sddf_data = ''
    for item in goldpac_dgi_list:
        if item.goldpac_dgi == sddf_tag:
            sddf_data = item.data
    dgi = Dgi()
    node_dgi, value_format = get_tag_link_attribute(xml, sddf_tag)
    if node_dgi == '' or value_format == '':
        return None
    need_remove_template = is_need_delete_template(node_dgi)
    global _aid_list_info
    is_second_app = False
    for _, aid_info in _aid_list_info.items():
        if sddf_tag[4] == aid_info[0]:
            is_second_app = aid_info[1]
            break
    if is_second_app:  #说明包含双应用
        dgi.name = node_dgi + '_2'
    else:
        dgi.name = node_dgi
    if value_format == 'TLV':
        data = utils.remove_dgi(sddf_data, node_dgi)
        if need_remove_template:
            data = utils.remove_template70(data)
        if utils.str_to_int(node_dgi) > 0xA000 or not utils.is_tlv(data):
            dgi.add_tag_value(dgi.name, data)
        else:
            tlvs = utils.parse_tlv(data)
            if len(tlvs) > 0 and tlvs[0].is_template is True:
                value = utils.assemble_tlv(tlvs[0].tag, tlvs[0].value)
                dgi.add_tag_value(dgi.name, value)
            else:
                for tlv in tlvs:
                    if tlv.len > 0x7F:
                        value = tlv.tag + '81' + utils.int_to_hex_str(
                            tlv.len) + tlv.value
                    else:
                        value = tlv.tag + utils.int_to_hex_str(
                            tlv.len) + tlv.value
                    dgi.add_tag_value(tlv.tag, value)
    elif value_format == 'V':
        dgi.add_tag_value(dgi.name, sddf_data)
    return dgi
示例#22
0
 def first_gac_cda(self):
     tag8C = self.get_tag(PROCESS_STEP.READ_RECORD, '8C')
     if not tag8C:
         Log.error('first gac cda faild since tag8C is tempty')
         return False
     tls = utils.parse_tl(tag8C)
     data = ''
     self.unpredicatble_number = ''
     for tl in tls:
         data += terminal.get_terminal(tl.tag, tl.len)
         if tl.tag == '9F37':
             self.unpredicatble_number = terminal.get_terminal(
                 tl.tag, tl.len)
     resp = super().gac(Crypto_Type.TC_CDA, data)
     if resp.sw != 0x9000:
         Log.error('send first gac command failed. SW:%04X', resp.sw)
         return
     tlvs = utils.parse_tlv(resp.response)
     tools.output_apdu_info(resp)
     self.store_tag_group(PROCESS_STEP.FIRST_GAC, tlvs)
示例#23
0
def _parse_tlv(dgi_name, data):
    dgi = Dgi()
    data = utils.remove_dgi(data, dgi_name)
    int_dgi = utils.str_to_int(dgi_name)
    if int_dgi < 0x0B01:
        if data[0:2] != '70':
            Log.error('数据有误,小于0B01的DGI应包含70模板')
            return None
        data = utils.remove_template70(data)
    if not utils.is_rsa(dgi_name) and utils.is_tlv(data):
        tlvs = utils.parse_tlv(data)
        if len(tlvs) > 0 and tlvs[0].is_template is True:
            value = utils.assemble_tlv(tlvs[0].tag, tlvs[0].value)
            dgi.add_tag_value(dgi_name, value)
        else:
            for tlv in tlvs:
                value = utils.assemble_tlv(tlv.tag, tlv.value)
                dgi.add_tag_value(tlv.tag, value)
    else:
        dgi.add_tag_value(dgi_name, data)
    return dgi
示例#24
0
 def process_assemble_dgi(self, src_dgi, src_tag, format_str):
     data = ""
     tag_list = format_str.split(',')
     for tag in tag_list[::-1]:
         if '.' not in tag:  #说明是模板
             data = tag + utils.get_strlen(data) + data
         else:
             dst_dgi = tag.split('.')[0]
             dst_tag = tag.split('.')[1]
             if dst_dgi == '':
                 data = dst_tag + data
             elif dst_dgi[len(dst_dgi) - 1] == 'v':
                 dst_dgi = dst_dgi[0:len(dst_dgi) - 1]
                 value = self.cps.get_tag_value(dst_dgi, dst_tag)
                 if not value:
                     print('dgi %s tag %s 不存在' % (dst_dgi, dst_tag))
                 data = value + data
             else:
                 value = ''
                 if dst_dgi in ('9102', '9103'):  #对于9103,9102需要特殊处理
                     tlvs = utils.parse_tlv(
                         self.cps.get_tag_value(dst_dgi, dst_dgi))
                     for tlv in tlvs:
                         if tlv.tag == dst_tag:
                             value = tlv.value
                             break
                 else:
                     value = self.cps.get_tag_value(dst_dgi, dst_tag)
                 if not value:
                     print('dgi %s tag %s 不存在' % (dst_dgi, dst_tag))
                 tag_len = utils.get_strlen(value)
                 data = dst_tag + tag_len + value + data
     dgi = Dgi()
     dgi.name = src_dgi
     dgi.add_tag_value(src_tag, data)
     self.cps.add_dgi(dgi)
     return self.cps
示例#25
0
 def get_data(self,tags):
     for tag in tags:
         resp = apdu.get_data(tag)
         if resp.sw == 0x9000:
             tlvs = utils.parse_tlv(resp.response)
             self.store_tag_group(PROCESS_STEP.GET_DATA,tlvs)