def parse_apdu_response_fcp(apdu_resp_str):
"""
解析APDU响应字符串,打印状态码和数据等信息
ETSI TS 102 221
11.1.1.3 Response Data
11.1.1.4 File control parameters
"""
tag_d = {
"62": "FCP template tag = '62'",
"82": "File Descriptor",
"83": "File Identifier",
"84": "DF name (AID)",
"A5": "Proprietary information",
"8A": "Life Cycle Status Integer",
"8B": "Security attributes",
"8C": "Security attributes",
"AB": "Security attributes",
"C6": "PIN Status Template DO",
"81": "Total file size",
"80": "File size",
"88": "Short File Identifier (SFI)"
}
"""
3GPP TS 31.102
H.1 List of SFI Values at the USIM ADF Level
"""
sfi_d = {
"01": "'6FB7', Emergency call codes",
"02": "'6F05', Language indication",
"03": "'6FAD', Administrative data",
"04": "'6F38', USIM service table",
"05": "'6F56', Enabled services table",
"06": "'6F78', Access control class",
"07": "'6F07', IMSI",
"08": "'6F08', Ciphering and integrity keys",
"09": "'6F09', Ciphering and integrity keys for packet switched domain",
"0A": "'6F60', User PLMN selector",
"0B": "'6F7E', Location information",
"0C": "'6F73', Packet switched location information",
"0D": "'6F7B', Forbidden PLMNs",
"0E": "'6F48', CBMID",
"0F": "'6F5B', Hyperframe number",
"10": "'6F5C', Maximum value of hyperframe number",
"11": "'6F61', Operator PLMN selector",
"12": "'6F31', Higher Priority PLMN search period",
"13": "'6F62', Preferred HPLMN access technology",
"14": "'6F80', Incoming call information",
"15": "'6F81', Outgoing call information",
"16": "'6F4F', Capability configuration parameters 2",
"17": "'6F06', Access Rule Reference",
"18": "'6FE4', EPS NAS Security Context",
"19": "'6FC5', PLMN Network Name",
"1A": "'6FC6', Operator Network List",
"1B": "'6FCD', Service Provider Display Information",
"1C": "'6F39', Accumulated Call Meter (see note)",
"1D": "'6FD9', Equivalent HPLMN",
"1E": "'6FE3', EPS location information"
}
print(apdu_resp_str)
if len(apdu_resp_str) == 4 + int(apdu_resp_str[2:4], 16) * 2 + 4:
sw1 = apdu_resp_str[-4:-2]
sw2 = apdu_resp_str[-2:]
print(f"{sw1}{sw2}:sw1 sw2")
index = 0
while index < 4 + int(apdu_resp_str[2:4], 16) * 2:
tag = apdu_resp_str[index:index+2]
print(f"{tag}:tag, {tag_d.get(tag)}")
index = index + 2
length = int(apdu_resp_str[index:index+2], 16)
print(f"{apdu_resp_str[index:index+2]}:length")
index = index + 2
value = apdu_resp_str[index:index + length * 2]
print(f"{value}:value")
if tag == "88" and length == 1:
sfi = str(hex(int(value, 16) >> 3)[2:])
print(f"{value}'s SFI is {sfi}, {sfi_d.get(sfi)}")
if tag == "A5":
parse_apdu_response_tag_A5(value)
if tag != "62":
index = index + length * 2
def parse_apdu_response_tag_A5(apdu_resp_str):
"""
ETSI TS 102 221
11.1.1.4.6 Proprietary information
"""
tag_d = {
"A5": "Proprietary information",
"80": "UICC characteristics",
"81": "Application power consumption",
"82": "Minimum application clock frequency",
"83": "Amount of available memory",
"84": "File details",
"85": "Reserved file size",
"86": "Maximum file size",
"87": "Supported system commands",
"88": "Specific UICC environmental conditions",
"89": "Platform to Platform CAT Secured APDU"
}
print(apdu_resp_str)
index = 0
while index < 4 + int(apdu_resp_str[2:4], 16) * 2:
tag = apdu_resp_str[index:index + 2]
print(f"{tag}:tag, {tag_d.get(tag)}")
index = index + 2
length = int(apdu_resp_str[index:index + 2], 16)
print(f"{apdu_resp_str[index:index + 2]}:length")
index = index + 2
value = apdu_resp_str[index:index + length * 2]
print(f"{value}:value")
if tag != "A5":
index = index + length * 2
if __name__ == '__main__':
# apdu_resp_str = "62178202412183026F7E8A01058B036F06058002000B8801589000"
# apdu_resp_str = "621B8202412183026FD9A5038001718A01058B036F06028002000C88009000"
# apdu_resp_str = "622282054221002C0E83026F06A506D00130D201038A01058B036F060A800202688801B89000"
# parse_apdu_response_fcp(apdu_resp_str)
# apdu_resp_str = "A503800171"
# parse_apdu_response_tag_A5(apdu_resp_str)