def test_5_read_imsi(self): enabled = self.simCtrl.pin1Enabled() attemptsLeft = self.simCtrl.pin1Status() self.assertTrue(enabled) self.assertTrue(attemptsLeft, "PUK needed") #SELECT_FILE DF_GSM sw1, sw2, data = self.sendApdu("A0A40000027F20") types.assertSw(sw1, sw2, checkSw1='RESPONSE_DATA_AVAILABLE_2G', raiseException=True) length = sw2 #GET_RESPONSE sw1, sw2, data = self.sendApdu("A0C00000%02X" %length) types.assertSw(sw1, sw2, checkSw='NO_ERROR', raiseException=True) #SELECT_FILE IMSI sw1, sw2, data = self.sendApdu("A0A40000026F07") types.assertSw(sw1, sw2, checkSw1='RESPONSE_DATA_AVAILABLE_2G', raiseException=True) length = sw2 #GET_RESPONSE sw1, sw2, data = self.sendApdu("A0C00000%02X" %length) types.assertSw(sw1, sw2, checkSw='NO_ERROR', raiseException=True) #READ BINARY length = data[3] sw1, sw2, data = self.sendApdu("A0B00000%02X" %length) if types_g.sw[(sw1<<8) + sw2] == 'GSM_ACCESS_CONDITION_NOT_FULFILLED': #VERIFY sw1, sw2, data = self.sendApdu("A020000108%sFFFFFFFF" %PIN_1.encode("hex")) types.assertSw(sw1, sw2, checkSw='NO_ERROR', raiseException=True) #repeat READ BINARY sw1, sw2, data = self.sendApdu("A0B00000%02X" %length) types.assertSw(sw1, sw2, checkSw='NO_ERROR', raiseException=True) imsi = hextools.decode_BCD(data)[3:] logging.info("IMSI: %s" %imsi)
def test_5_read_imsi(self): enabled = self.simCtrl.pin1Enabled() attemptsLeft = self.simCtrl.pin1Status() self.assertTrue(enabled) self.assertTrue(attemptsLeft, "PUK needed") self.simCtrl.selectAid() #SELECT_FILE IMSI sw1, sw2, data = self.sendApdu("00A40004026F07") types.assertSw(sw1, sw2, checkSw1='RESPONSE_DATA_AVAILABLE_3G', raiseException=True) length = sw2 #GET_RESPONSE sw1, sw2, data = self.sendApdu("00C00000%02X" % length) types.assertSw(sw1, sw2, checkSw='NO_ERROR', raiseException=True) #READ BINARY tagData = types.parseFcpTlv(data, types.FILE_LENGTH_EXCLUDING_SI_TAG) if tagData == None: raise Exception("BINARY_LENGTH_TAG not found in FCI") imsiLength = tagData[1] sw1, sw2, data = self.sendApdu("00B00000%02X" % imsiLength) if types_g.sw[(sw1 << 8) + sw2] == 'SECURITY_STATUS_NOT_SATISFIED': #VERIFY sw1, sw2, data = self.sendApdu("0020000108%sFFFFFFFF" % PIN_1.encode("hex")) types.assertSw(sw1, sw2, checkSw='NO_ERROR', raiseException=True) #repeat READ BINARY sw1, sw2, data = self.sendApdu("00B00000%02X" % imsiLength) types.assertSw(sw1, sw2, checkSw='NO_ERROR', raiseException=True) imsi = hextools.decode_BCD(data)[3:] logging.info("IMSI: %s" % imsi)
def test_5_read_imsi(self): enabled = self.simCtrl.pin1Enabled() attemptsLeft = self.simCtrl.pin1Status() self.assertTrue(enabled) self.assertTrue(attemptsLeft, "PUK needed") self.simCtrl.selectAid() #SELECT_FILE IMSI sw1, sw2, data = self.sendApdu("00A40004026F07") types.assertSw(sw1, sw2, checkSw1='RESPONSE_DATA_AVAILABLE_3G', raiseException=True) length = sw2 #GET_RESPONSE sw1, sw2, data = self.sendApdu("00C00000%02X" %length) types.assertSw(sw1, sw2, checkSw='NO_ERROR', raiseException=True) #READ BINARY tagData = types.parseFcpTlv(data, types.FILE_LENGTH_EXCLUDING_SI_TAG) if tagData == None: raise Exception("BINARY_LENGTH_TAG not found in FCI") imsiLength = tagData[1] sw1, sw2, data = self.sendApdu("00B00000%02X" %imsiLength) if types_g.sw[(sw1<<8) + sw2] == 'SECURITY_STATUS_NOT_SATISFIED': #VERIFY sw1, sw2, data = self.sendApdu("0020000108%sFFFFFFFF" %PIN_1.encode("hex")) types.assertSw(sw1, sw2, checkSw='NO_ERROR', raiseException=True) #repeat READ BINARY sw1, sw2, data = self.sendApdu("00B00000%02X" %imsiLength) types.assertSw(sw1, sw2, checkSw='NO_ERROR', raiseException=True) imsi = hextools.decode_BCD(data)[3:] logging.info("IMSI: %s" %imsi)
def parseLocalInformation(self, tag, data): respData = None if tag == comprehension_tag.LOCATION_INFORMATION: pass elif tag == comprehension_tag.IMEI: respData = hextools.decode_BCD(data)[2:] # and many more return respData
def getEfOpl(self, data): data = data.split(';') dataNew = '' for record in data: if not record: continue binRecord = hextools.hex2bytes(record) if binRecord.count(0xFF) == len(binRecord): continue lai = hextools.bytes2hex(binRecord[0:7]) mccMnc = hextools.decode_BCD(hextools.hex2bytes(lai)[0:3]) lacStart = lai[6:10] lacEnd = lai[10:14] lacRange = "%s-%s" %(lacStart, lacEnd) pnnId = binRecord[7] dataNew += "mcc_mnc=%s,lac=%s,pnnId=%d;" %(mccMnc, lacRange, pnnId) return dataNew
def getEfEcc(self, data): eccStr = '' data = data.split(';') for record in data: recordRaw = hextools.hex2bytes(record) number = hextools.decode_BCD(recordRaw[0:3]) number = number.replace('F','') if not number: continue #number = type.removeTrailingBytes(hextools.hex2bytes(number), 0xFF) aplha = None category = recordRaw[-1] eccStr += "number=%s,alpha=%s,cat=%d;" %(number, aplha, category) eccStr = eccStr.rstrip(";") if not eccStr: eccStr = "EMPTY" return eccStr
def getEfEcc(self, data): eccStr = '' data = data.split(';') for record in data: recordRaw = hextools.hex2bytes(record) number = hextools.decode_BCD(recordRaw[0:3]) number = number.replace('F', '') if not number: continue #number = type.removeTrailingBytes(hextools.hex2bytes(number), 0xFF) aplha = None category = recordRaw[-1] eccStr += "number=%s,alpha=%s,cat=%d;" % (number, aplha, category) eccStr = eccStr.rstrip(";") if not eccStr: eccStr = "EMPTY" return eccStr
def getEfOpl(self, data): data = data.split(';') dataNew = '' for record in data: if not record: continue binRecord = hextools.hex2bytes(record) if binRecord.count(0xFF) == len(binRecord): continue lai = hextools.bytes2hex(binRecord[0:7]) mccMnc = hextools.decode_BCD(hextools.hex2bytes(lai)[0:3]) lacStart = lai[6:10] lacEnd = lai[10:14] lacRange = "%s-%s" % (lacStart, lacEnd) pnnId = binRecord[7] dataNew += "mcc_mnc=%s,lac=%s,pnnId=%d;" % (mccMnc, lacRange, pnnId) return dataNew
def test_5_read_imsi(self): enabled = self.simCtrl.pin1Enabled() attemptsLeft = self.simCtrl.pin1Status() self.assertTrue(enabled) self.assertTrue(attemptsLeft, "PUK needed") #SELECT_FILE DF_GSM sw1, sw2, data = self.sendApdu("A0A40000027F20") types.assertSw(sw1, sw2, checkSw1='RESPONSE_DATA_AVAILABLE_2G', raiseException=True) length = sw2 #GET_RESPONSE sw1, sw2, data = self.sendApdu("A0C00000%02X" % length) types.assertSw(sw1, sw2, checkSw='NO_ERROR', raiseException=True) #SELECT_FILE IMSI sw1, sw2, data = self.sendApdu("A0A40000026F07") types.assertSw(sw1, sw2, checkSw1='RESPONSE_DATA_AVAILABLE_2G', raiseException=True) length = sw2 #GET_RESPONSE sw1, sw2, data = self.sendApdu("A0C00000%02X" % length) types.assertSw(sw1, sw2, checkSw='NO_ERROR', raiseException=True) #READ BINARY length = data[3] sw1, sw2, data = self.sendApdu("A0B00000%02X" % length) if types_g.sw[(sw1 << 8) + sw2] == 'GSM_ACCESS_CONDITION_NOT_FULFILLED': #VERIFY sw1, sw2, data = self.sendApdu("A020000108%sFFFFFFFF" % PIN_1.encode("hex")) types.assertSw(sw1, sw2, checkSw='NO_ERROR', raiseException=True) #repeat READ BINARY sw1, sw2, data = self.sendApdu("A0B00000%02X" % length) types.assertSw(sw1, sw2, checkSw='NO_ERROR', raiseException=True) imsi = hextools.decode_BCD(data)[3:] logging.info("IMSI: %s" % imsi)
def getEfLoci(self, data): valueRaw = hextools.hex2bytes(data) tmsi = hextools.bytes2hex(valueRaw[0:4]) lai = hextools.bytes2hex(valueRaw[4:9]) #TODO: check for mnc containing 3digits mcc_mnc = hextools.decode_BCD(hextools.hex2bytes(lai)[0:3]) lac = lai[6:10] rfu = hextools.bytes2hex([valueRaw[9]]) loction_status = hextools.bytes2hex([valueRaw[10]]) ''' loction_status Bits: b3 b2 b1 0 0 0 : updated. 0 0 1 : not updated. 0 1 0 : PLMN not allowed. 0 1 1 : Location Area not allowed. 1 1 1 : reserved ''' return "tmsi=%s,mcc_mnc=%s,lac=%s,loc_status=%s"\ %(tmsi, mcc_mnc, lac, loction_status)
def test_6_manage_channel(self): originChannel = 0 """ Open first free channel """ # MANAGE CHANNEL: OPEN (first free) sw1, sw2, data = self.sendApdu("0%01X7000%02X01" % (originChannel, 0)) types.assertSw(sw1, sw2, checkSw='NO_ERROR', raiseException=True) targetChannel = data[0] # 2 # MANAGE CHANNEL: CLOSE sw1, sw2, data = self.sendApdu("0%01X7080%02X00" % (originChannel, targetChannel)) types.assertSw(sw1, sw2, checkSw='NO_ERROR', raiseException=True) """ Select on not open channel (when targetChannel = 0) """ #SELECT_FILE MF sw1, sw2, data = self.sendApdu("0%01XA40004023F00" % targetChannel) # Two possible responses if types.assertSw(sw1, sw2, checkSw1='WRONG_INSTRUCTION_CLASS', raiseException=False): types.assertSw(sw1, sw2, checkSw='LOGICAL_CHANNEL_NOT_SUPPORTED', raiseException=True) """ Open, Select and Close channel """ # MANAGE CHANNEL: OPEN (chosen) sw1, sw2, data = self.sendApdu("0%01X7000%02X00" % (originChannel, targetChannel)) types.assertSw(sw1, sw2, checkSw='NO_ERROR', raiseException=True) #SELECT_AID (ADF_USIM) # Select some AID (applet) on a specific channel. aid = self.simCtrl.getAid() apdu = "0%01XA40404%02X%s" % (targetChannel, len(aid) / 2, aid) sw1, sw2, data = self.sendApdu(apdu) types.assertSw(sw1, sw2, checkSw1='RESPONSE_DATA_AVAILABLE_3G', raiseException=True) #SELECT_FILE MF sw1, sw2, data = self.sendApdu("0%01XA40004023F00" % targetChannel) types.assertSw(sw1, sw2, checkSw1='RESPONSE_DATA_AVAILABLE_3G', raiseException=True) self.assertGreater(sw2, 2) # MANAGE CHANNEL: CLOSE sw1, sw2, data = self.sendApdu("0%01X7080%02X00" % (originChannel, targetChannel)) types.assertSw(sw1, sw2, checkSw='NO_ERROR', raiseException=True) """ Open first free channel (when targetChannel = 0) """ # MANAGE CHANNEL: OPEN (first free) sw1, sw2, data = self.sendApdu("0%01X7000%02X01" % (originChannel, 0)) types.assertSw(sw1, sw2, checkSw='NO_ERROR', raiseException=True) self.assertEqual(data[0], targetChannel) originChannel = data[0] # 1 # MANAGE CHANNEL: OPEN (non-basic origin channel) sw1, sw2, data = self.sendApdu("0%01X7000%02X01" % (originChannel, 0)) types.assertSw(sw1, sw2, checkSw='NO_ERROR', raiseException=True) self.assertEqual(data[0], originChannel + 1) targetChannel = data[0] # 2 """ Select MF on Non-Basic channel """ #SELECT_AID (ADF_USIM) apdu = "0%01XA40404%02X%s" % (targetChannel, len(aid) / 2, aid) sw1, sw2, data = self.sendApdu(apdu) #SELECT_FILE MF sw1, sw2, data = self.sendApdu("0%01XA40004023F00" % targetChannel) types.assertSw(sw1, sw2, checkSw1='RESPONSE_DATA_AVAILABLE_3G', raiseException=True) self.assertGreater(sw2, 2) """ Close Non-Basic channel """ # MANAGE CHANNEL: CLOSE sw1, sw2, data = self.sendApdu("0%01X7080%02X00" % (originChannel, targetChannel)) types.assertSw(sw1, sw2, checkSw='NO_ERROR', raiseException=True) """ Select IMSI file on Basic channel """ #SELECT_AID (ADF_USIM) #self.simCtrl.selectAid() apdu = "00A40404%02X%s" % (len(aid) / 2, aid) sw1, sw2, data = self.sendApdu(apdu) types.assertSw(sw1, sw2, checkSw1='RESPONSE_DATA_AVAILABLE_3G', raiseException=True) #SELECT_FILE IMSI sw1, sw2, data = self.sendApdu("00A40004026F07") types.assertSw(sw1, sw2, checkSw1='RESPONSE_DATA_AVAILABLE_3G', raiseException=True) length = sw2 #GET_RESPONSE sw1, sw2, data = self.sendApdu("00C00000%02X" % length) types.assertSw(sw1, sw2, checkSw='NO_ERROR', raiseException=True) tagData = types.parseFcpTlv(data, types.FILE_LENGTH_EXCLUDING_SI_TAG) if tagData == None: raise Exception("BINARY_LENGTH_TAG not found in FCI") imsiLength = tagData[1] """ Read IMSI file on Basic channel """ #READ BINARY sw1, sw2, data = self.sendApdu("00B00000%02X" % imsiLength) if types_g.sw[(sw1 << 8) + sw2] == 'SECURITY_STATUS_NOT_SATISFIED': #VERIFY sw1, sw2, data = self.sendApdu("0020000108%sFFFFFFFF" % PIN_1.encode("hex")) types.assertSw(sw1, sw2, checkSw='NO_ERROR', raiseException=True) #repeat READ BINARY sw1, sw2, data = self.sendApdu("00B00000%02X" % imsiLength) types.assertSw(sw1, sw2, checkSw='NO_ERROR', raiseException=True) imsi = hextools.decode_BCD(data)[3:] logging.info("IMSI: %s" % imsi)
def test_6_manage_channel(self): originChannel = 0 """ Open first free channel """ # MANAGE CHANNEL: OPEN (first free) sw1, sw2, data = self.sendApdu("0%01X7000%02X01" %(originChannel, 0)) types.assertSw(sw1, sw2, checkSw='NO_ERROR', raiseException=True) targetChannel = data[0] # 2 # MANAGE CHANNEL: CLOSE sw1, sw2, data = self.sendApdu("0%01X7080%02X00" %(originChannel, targetChannel)) types.assertSw(sw1, sw2, checkSw='NO_ERROR', raiseException=True) """ Select on not open channel (when targetChannel = 0) """ #SELECT_FILE MF sw1, sw2, data = self.sendApdu("0%01XA40004023F00" %targetChannel) # Two possible responses if types.assertSw(sw1, sw2, checkSw1='WRONG_INSTRUCTION_CLASS', raiseException=False): types.assertSw(sw1, sw2, checkSw='LOGICAL_CHANNEL_NOT_SUPPORTED', raiseException=True) """ Open, Select and Close channel """ # MANAGE CHANNEL: OPEN (chosen) sw1, sw2, data = self.sendApdu("0%01X7000%02X00" %(originChannel, targetChannel)) types.assertSw(sw1, sw2, checkSw='NO_ERROR', raiseException=True) #SELECT_AID (ADF_USIM) # Select some AID (applet) on a specific channel. aid = self.simCtrl.getAid() apdu = "0%01XA40404%02X%s" %(targetChannel, len(aid)/2, aid) sw1, sw2, data = self.sendApdu(apdu) types.assertSw(sw1, sw2, checkSw1='RESPONSE_DATA_AVAILABLE_3G', raiseException=True) #SELECT_FILE MF sw1, sw2, data = self.sendApdu("0%01XA40004023F00" %targetChannel) types.assertSw(sw1, sw2, checkSw1='RESPONSE_DATA_AVAILABLE_3G', raiseException=True) self.assertGreater(sw2, 2) # MANAGE CHANNEL: CLOSE sw1, sw2, data = self.sendApdu("0%01X7080%02X00" %(originChannel, targetChannel)) types.assertSw(sw1, sw2, checkSw='NO_ERROR', raiseException=True) """ Open first free channel (when targetChannel = 0) """ # MANAGE CHANNEL: OPEN (first free) sw1, sw2, data = self.sendApdu("0%01X7000%02X01" %(originChannel, 0)) types.assertSw(sw1, sw2, checkSw='NO_ERROR', raiseException=True) self.assertEqual(data[0], targetChannel) originChannel = data[0] # 1 # MANAGE CHANNEL: OPEN (non-basic origin channel) sw1, sw2, data = self.sendApdu("0%01X7000%02X01" %(originChannel, 0)) types.assertSw(sw1, sw2, checkSw='NO_ERROR', raiseException=True) self.assertEqual(data[0], originChannel + 1) targetChannel = data[0] # 2 """ Select MF on Non-Basic channel """ #SELECT_AID (ADF_USIM) apdu = "0%01XA40404%02X%s" %(targetChannel, len(aid)/2, aid) sw1, sw2, data = self.sendApdu(apdu) #SELECT_FILE MF sw1, sw2, data = self.sendApdu("0%01XA40004023F00" %targetChannel) types.assertSw(sw1, sw2, checkSw1='RESPONSE_DATA_AVAILABLE_3G', raiseException=True) self.assertGreater(sw2, 2) """ Close Non-Basic channel """ # MANAGE CHANNEL: CLOSE sw1, sw2, data = self.sendApdu("0%01X7080%02X00" %(originChannel, targetChannel)) types.assertSw(sw1, sw2, checkSw='NO_ERROR', raiseException=True) """ Select IMSI file on Basic channel """ #SELECT_AID (ADF_USIM) #self.simCtrl.selectAid() apdu = "00A40404%02X%s" %(len(aid)/2, aid) sw1, sw2, data = self.sendApdu(apdu) types.assertSw(sw1, sw2, checkSw1='RESPONSE_DATA_AVAILABLE_3G', raiseException=True) #SELECT_FILE IMSI sw1, sw2, data = self.sendApdu("00A40004026F07") types.assertSw(sw1, sw2, checkSw1='RESPONSE_DATA_AVAILABLE_3G', raiseException=True) length = sw2 #GET_RESPONSE sw1, sw2, data = self.sendApdu("00C00000%02X" %length) types.assertSw(sw1, sw2, checkSw='NO_ERROR', raiseException=True) tagData = types.parseFcpTlv(data, types.FILE_LENGTH_EXCLUDING_SI_TAG) if tagData == None: raise Exception("BINARY_LENGTH_TAG not found in FCI") imsiLength = tagData[1] """ Read IMSI file on Basic channel """ #READ BINARY sw1, sw2, data = self.sendApdu("00B00000%02X" %imsiLength) if types_g.sw[(sw1<<8) + sw2] == 'SECURITY_STATUS_NOT_SATISFIED': #VERIFY sw1, sw2, data = self.sendApdu("0020000108%sFFFFFFFF" %PIN_1.encode("hex")) types.assertSw(sw1, sw2, checkSw='NO_ERROR', raiseException=True) #repeat READ BINARY sw1, sw2, data = self.sendApdu("00B00000%02X" %imsiLength) types.assertSw(sw1, sw2, checkSw='NO_ERROR', raiseException=True) imsi = hextools.decode_BCD(data)[3:] logging.info("IMSI: %s" %imsi)
def handleApdu(self, cardData, apdu): card = cardData[0] sendData = cardData[1] if card == None: raise Exception("card not initialized") ins = types.insName(apdu) if card != self.getMainCard(0): origApdu = apdu if (self.aidCommon(card) and card.routingAttr.aidToSelect and self.getMainCard(0).routingAttr.aidToSelect == hextools.bytes2hex(apdu) and #origin apdu is AID int(card.routingAttr.aidToSelect[0:2], 16) == apdu[0]): #check the same class apdu = hextools.hex2bytes(card.routingAttr.aidToSelect) card.routingAttr.aidToSelect = None elif (self.aidCommon(card) and card.routingAttr.getFileSelected(apdu[0]) == 'EF_DIR' and ins == 'READ_RECORD' and card.routingAttr.recordEfDirLength): apdu[4] = card.routingAttr.recordEfDirLength if origApdu != apdu: self.loggingApdu.info("") self.loggingApdu.info( "*C-APDU%d: %s" % (self.getSimId(card), hextools.bytes2hex(apdu))) if self.simType == types.TYPE_SIM and (apdu[0] & 0xF0) != 0xA0: #force 2G on USIM cards sw = types_g.sw.CLASS_NOT_SUPPORTED sw1 = sw >> 8 sw2 = sw & 0x00FF responseApdu = [sw1, sw2] elif ins == 'GET_RESPONSE' and card.routingAttr.getResponse: responseApdu = card.routingAttr.getResponse card.routingAttr.getResponse = None else: responseApdu = card.apdu(apdu) if card != self.getMainCard(0): if (self.aidCommon(card) and card.routingAttr.getFileSelected(apdu[0]) == 'EF_DIR' and ins == 'GET_RESPONSE' and types.swNoError(responseApdu) and len(responseApdu) > 7): card.routingAttr.recordEfDirLength = responseApdu[7] if (TRY_ANOTHER_CARD_ON_AUTH_FAILURE and self.getNbrOfCards() > 1 and card.routingAttr.getFileSelected(apdu[0]) == 'AUTH' and types.sw(responseApdu) == types_g.sw.AUTHENTICATION_ERROR_APPLICATION_SPECIFIC): sw1Name, swName = types.swName( types.sw(responseApdu) >> 8, types.sw(responseApdu) & 0x00FF) self.logging.warning("Response not expected. SW1: %s, SW: %s" % (sw1Name, swName)) self.logging.warning("Change card to process AUTHENTICATION") if card == self.getMainCard(0): cardTmp = self.getMainCard(1) else: cardTmp = self.getMainCard(0) responseApdu = cardTmp.apdu(apdu) cardTmp.routingAttr.setFileSelected('AUTH', apdu[0]) card.routingAttr.setFileSelected(None, apdu[0]) # TODO: check if exist cardTmp.routingAttr.insReplaced.append('INTERNAL_AUTHENTICATE') if types.sw1(responseApdu) in [ types_g.sw1.RESPONSE_DATA_AVAILABLE_2G, types_g.sw1.RESPONSE_DATA_AVAILABLE_3G ]: # cache 'GET_RESPONSE' getResponseLength = types.sw2(responseApdu) cla = apdu[0] apduTmp = "%02XC00000%02X" % (cla, getResponseLength) self.loggingApdu.info("**C-APDU%d: %s" % (self.getSimId(cardTmp), apduTmp)) cardTmp.routingAttr.getResponse = cardTmp.apdu(apduTmp) if card.routingAttr.getFileSelected( apdu[0]) == 'EF_IMSI' and types.swNoError(responseApdu): #cache imsi responseData = types.responseData(responseApdu) if ins == 'READ_BINARY' and types.p1(apdu) == 0 and types.p2( apdu) == 0: #When P1=8X then SFI is used to select the file. #Remove the check when SFI checking is implemented imsi = hextools.decode_BCD(responseData)[3:] #TODO: remove length check when name for the file comes from #the whole path and not fid. 6f07 is also in ADF_ISIM if len(imsi) > 10: card.imsi = imsi #update associated interface if self.isCardCtrl(card): self.getRelatedMainCard(card).imsi = imsi else: self.getRelatedCtrlCard(card).imsi = imsi elif ins == 'UPDATE_BINARY': card.imsi = None responseApduHex = hextools.bytes2hex(responseApdu) #example of APDU modification if responseApduHex == "02542D4D6F62696C652E706CFFFFFFFFFF9000": #change SPN name 'T-mobile.pl' for 'Tmobile-SPN' responseApdu = hextools.hex2bytes( "02546D6F62696C652D53504EFFFFFFFFFF9000") if sendData: if ((types.sw(responseApdu) == types_g.sw.NO_ERROR or types.sw1(responseApdu) == types_g.sw1.NO_ERROR_PROACTIVE_DATA) and self.getNbrOfCards() > 1): # Check for pending SAT command for cardDict in self.cardsDict: cardTmp = cardDict[MAIN_INTERFACE] if card == cardTmp: continue if set(sim_card.SAT_INS) <= set( cardTmp.routingAttr.insReplaced): swNoError = cardTmp.swNoError if types.unpackSw(swNoError)[ 0] == types_g.sw1.NO_ERROR_PROACTIVE_DATA: #update r-apdu with proactive data information responseApdu[-2] = swNoError >> 8 responseApdu[-1] = swNoError & 0x00FF break self.sendResponseApdu(responseApdu) if card == self.getMainCard(0) or sendData: self.pretty_apdu(apdu) responseApduHex = hextools.bytes2hex(responseApdu) self.loggingApdu.info("R-APDU%d: %s" % (self.getSimId(card), responseApduHex)) # gsmtap.log(apdu,responseApdu) # Uncomment for wireshark return responseApdu
def test_6_manage_channel(self): originChannel = 0 targetChannel = 2 """ Select on not open channel """ #SELECT_FILE MF sw1, sw2, data = self.sendApdu("A%01XA40000023F00" %targetChannel) types.assertSw(sw1, sw2, checkSw='LOGICAL_CHANNEL_NOT_SUPPORTED', raiseException=True) """ Open, Select and Close channel """ # MANAGE CHANNEL: OPEN (chosen) sw1, sw2, data = self.sendApdu("A%01X7000%02X00" %(originChannel, targetChannel)) types.assertSw(sw1, sw2, checkSw='NO_ERROR', raiseException=True) #SELECT_FILE MF sw1, sw2, data = self.sendApdu("A%01XA40000023F00" %targetChannel) types.assertSw(sw1, sw2, checkSw1='RESPONSE_DATA_AVAILABLE_2G', raiseException=True) self.assertGreater(sw2, 2) # MANAGE CHANNEL: CLOSE sw1, sw2, data = self.sendApdu("A%01X7080%02X00" %(originChannel, targetChannel)) types.assertSw(sw1, sw2, checkSw='NO_ERROR', raiseException=True) """ Open first free channel (when targetChannel = 0) """ # MANAGE CHANNEL: OPEN (first free) sw1, sw2, data = self.sendApdu("A%01X7000%02X01" %(originChannel, 0)) types.assertSw(sw1, sw2, checkSw='NO_ERROR', raiseException=True) self.assertEqual(data[0], 1) originChannel = data[0] # 1 # MANAGE CHANNEL: OPEN (non-basic origin channel) sw1, sw2, data = self.sendApdu("A%01X7000%02X01" %(originChannel, 0)) types.assertSw(sw1, sw2, checkSw='NO_ERROR', raiseException=True) self.assertEqual(data[0], originChannel + 1) targetChannel = data[0] # 2 """ Select IMSI file on Basic channel """ #SELECT_FILE DF_GSM sw1, sw2, data = self.sendApdu("A0A40000027F20") types.assertSw(sw1, sw2, checkSw1='RESPONSE_DATA_AVAILABLE_2G', raiseException=True) #SELECT_FILE IMSI sw1, sw2, data = self.sendApdu("A0A40000026F07") types.assertSw(sw1, sw2, checkSw1='RESPONSE_DATA_AVAILABLE_2G', raiseException=True) length = sw2 #GET_RESPONSE sw1, sw2, data = self.sendApdu("A0C00000%02X" %length) types.assertSw(sw1, sw2, checkSw='NO_ERROR', raiseException=True) imsiLen = data[3] """ Select MF on Non-Basic channel """ #SELECT_FILE MF sw1, sw2, data = self.sendApdu("A%01XA40000023F00" %targetChannel) types.assertSw(sw1, sw2, checkSw1='RESPONSE_DATA_AVAILABLE_2G', raiseException=True) self.assertGreater(sw2, 2) """ Read IMSI file on Basic channel """ #READ BINARY sw1, sw2, data = self.sendApdu("A0B00000%02X" %imsiLen) if types_g.sw[(sw1<<8) + sw2] == 'GSM_ACCESS_CONDITION_NOT_FULFILLED': #VERIFY sw1, sw2, data = self.sendApdu("A020000108%sFFFFFFFF" %PIN_1.encode("hex")) types.assertSw(sw1, sw2, checkSw='NO_ERROR', raiseException=True) #repeat READ BINARY sw1, sw2, data = self.sendApdu("A0B00000%02X" %length) types.assertSw(sw1, sw2, checkSw='NO_ERROR', raiseException=True) imsi = hextools.decode_BCD(data)[3:] logging.info("IMSI: %s" %imsi) """ Close Non-Basic channel """ # MANAGE CHANNEL: CLOSE sw1, sw2, data = self.sendApdu("A%01X7080%02X00" %(originChannel, targetChannel)) types.assertSw(sw1, sw2, checkSw='NO_ERROR', raiseException=True)
def test_6_manage_channel(self): originChannel = 0 targetChannel = 2 """ Select on not open channel """ #SELECT_FILE MF sw1, sw2, data = self.sendApdu("A%01XA40000023F00" % targetChannel) types.assertSw(sw1, sw2, checkSw='LOGICAL_CHANNEL_NOT_SUPPORTED', raiseException=True) """ Open, Select and Close channel """ # MANAGE CHANNEL: OPEN (chosen) sw1, sw2, data = self.sendApdu("A%01X7000%02X00" % (originChannel, targetChannel)) types.assertSw(sw1, sw2, checkSw='NO_ERROR', raiseException=True) #SELECT_FILE MF sw1, sw2, data = self.sendApdu("A%01XA40000023F00" % targetChannel) types.assertSw(sw1, sw2, checkSw1='RESPONSE_DATA_AVAILABLE_2G', raiseException=True) self.assertGreater(sw2, 2) # MANAGE CHANNEL: CLOSE sw1, sw2, data = self.sendApdu("A%01X7080%02X00" % (originChannel, targetChannel)) types.assertSw(sw1, sw2, checkSw='NO_ERROR', raiseException=True) """ Open first free channel (when targetChannel = 0) """ # MANAGE CHANNEL: OPEN (first free) sw1, sw2, data = self.sendApdu("A%01X7000%02X01" % (originChannel, 0)) types.assertSw(sw1, sw2, checkSw='NO_ERROR', raiseException=True) self.assertEqual(data[0], 1) originChannel = data[0] # 1 # MANAGE CHANNEL: OPEN (non-basic origin channel) sw1, sw2, data = self.sendApdu("A%01X7000%02X01" % (originChannel, 0)) types.assertSw(sw1, sw2, checkSw='NO_ERROR', raiseException=True) self.assertEqual(data[0], originChannel + 1) targetChannel = data[0] # 2 """ Select IMSI file on Basic channel """ #SELECT_FILE DF_GSM sw1, sw2, data = self.sendApdu("A0A40000027F20") types.assertSw(sw1, sw2, checkSw1='RESPONSE_DATA_AVAILABLE_2G', raiseException=True) #SELECT_FILE IMSI sw1, sw2, data = self.sendApdu("A0A40000026F07") types.assertSw(sw1, sw2, checkSw1='RESPONSE_DATA_AVAILABLE_2G', raiseException=True) length = sw2 #GET_RESPONSE sw1, sw2, data = self.sendApdu("A0C00000%02X" % length) types.assertSw(sw1, sw2, checkSw='NO_ERROR', raiseException=True) imsiLen = data[3] """ Select MF on Non-Basic channel """ #SELECT_FILE MF sw1, sw2, data = self.sendApdu("A%01XA40000023F00" % targetChannel) types.assertSw(sw1, sw2, checkSw1='RESPONSE_DATA_AVAILABLE_2G', raiseException=True) self.assertGreater(sw2, 2) """ Read IMSI file on Basic channel """ #READ BINARY sw1, sw2, data = self.sendApdu("A0B00000%02X" % imsiLen) if types_g.sw[(sw1 << 8) + sw2] == 'GSM_ACCESS_CONDITION_NOT_FULFILLED': #VERIFY sw1, sw2, data = self.sendApdu("A020000108%sFFFFFFFF" % PIN_1.encode("hex")) types.assertSw(sw1, sw2, checkSw='NO_ERROR', raiseException=True) #repeat READ BINARY sw1, sw2, data = self.sendApdu("A0B00000%02X" % length) types.assertSw(sw1, sw2, checkSw='NO_ERROR', raiseException=True) imsi = hextools.decode_BCD(data)[3:] logging.info("IMSI: %s" % imsi) """ Close Non-Basic channel """ # MANAGE CHANNEL: CLOSE sw1, sw2, data = self.sendApdu("A%01X7080%02X00" % (originChannel, targetChannel)) types.assertSw(sw1, sw2, checkSw='NO_ERROR', raiseException=True)
def getEfImsi(self, data): data = hextools.hex2bytes(data) imsi = hextools.decode_BCD(data)[3:] return imsi
def handleApdu(self, cardData, apdu): card = cardData[0] sendData = cardData[1] if card == None: raise Exception("card not initialized") ins = types.insName(apdu) if card != self.getMainCard(0): origApdu = apdu if ( self.aidCommon(card) and card.routingAttr.aidToSelect and self.getMainCard(0).routingAttr.aidToSelect == hextools.bytes2hex(apdu) and #origin apdu is AID int(card.routingAttr.aidToSelect[0:2], 16) == apdu[0]): #check the same class apdu = hextools.hex2bytes(card.routingAttr.aidToSelect) card.routingAttr.aidToSelect = None elif ( self.aidCommon(card) and card.routingAttr.getFileSelected(apdu[0]) == 'EF_DIR' and ins == 'READ_RECORD' and card.routingAttr.recordEfDirLength): apdu[4] = card.routingAttr.recordEfDirLength if origApdu != apdu: self.loggingApdu.info("") self.loggingApdu.info("*C-APDU%d: %s" %(self.getSimId(card), hextools.bytes2hex(apdu))) if self.simType == types.TYPE_SIM and (apdu[0] & 0xF0) != 0xA0: #force 2G on USIM cards sw = types_g.sw.CLASS_NOT_SUPPORTED sw1 = sw>>8 sw2 = sw & 0x00FF responseApdu = [sw1, sw2] elif ins == 'GET_RESPONSE' and card.routingAttr.getResponse: responseApdu = card.routingAttr.getResponse card.routingAttr.getResponse = None else: responseApdu = card.apdu(apdu) if card != self.getMainCard(0): if (self.aidCommon(card) and card.routingAttr.getFileSelected(apdu[0]) == 'EF_DIR' and ins == 'GET_RESPONSE' and types.swNoError(responseApdu) and len(responseApdu) > 7): card.routingAttr.recordEfDirLength = responseApdu[7] if (TRY_ANOTHER_CARD_ON_AUTH_FAILURE and self.getNbrOfCards() > 1 and card.routingAttr.getFileSelected(apdu[0]) == 'AUTH' and types.sw(responseApdu) == types_g.sw.AUTHENTICATION_ERROR_APPLICATION_SPECIFIC): sw1Name, swName = types.swName(types.sw(responseApdu) >> 8, types.sw(responseApdu) & 0x00FF) self.logging.warning("Response not expected. SW1: %s, SW: %s" %(sw1Name, swName)) self.logging.warning("Change card to process AUTHENTICATION") if card == self.getMainCard(0): cardTmp = self.getMainCard(1) else: cardTmp = self.getMainCard(0) responseApdu = cardTmp.apdu(apdu) cardTmp.routingAttr.setFileSelected('AUTH', apdu[0]) card.routingAttr.setFileSelected(None, apdu[0]) # TODO: check if exist cardTmp.routingAttr.insReplaced.append('INTERNAL_AUTHENTICATE') if types.sw1(responseApdu) in [types_g.sw1.RESPONSE_DATA_AVAILABLE_2G, types_g.sw1.RESPONSE_DATA_AVAILABLE_3G]: # cache 'GET_RESPONSE' getResponseLength = types.sw2(responseApdu) cla = apdu[0] apduTmp = "%02XC00000%02X" %(cla, getResponseLength) self.loggingApdu.info("**C-APDU%d: %s" %(self.getSimId(cardTmp), apduTmp)) cardTmp.routingAttr.getResponse = cardTmp.apdu(apduTmp) if card.routingAttr.getFileSelected(apdu[0]) == 'EF_IMSI' and types.swNoError(responseApdu): #cache imsi responseData = types.responseData(responseApdu) if ins == 'READ_BINARY' and types.p1(apdu) == 0 and types.p2(apdu) == 0: #When P1=8X then SFI is used to select the file. #Remove the check when SFI checking is implemented imsi = hextools.decode_BCD(responseData)[3:] #TODO: remove length check when name for the file comes from #the whole path and not fid. 6f07 is also in ADF_ISIM if len(imsi) > 10: card.imsi = imsi #update associated interface if self.isCardCtrl(card): self.getRelatedMainCard(card).imsi = imsi else: self.getRelatedCtrlCard(card).imsi = imsi elif ins == 'UPDATE_BINARY': card.imsi = None responseApduHex = hextools.bytes2hex(responseApdu) #example of APDU modification if responseApduHex == "02542D4D6F62696C652E706CFFFFFFFFFF9000": #change SPN name 'T-mobile.pl' for 'Tmobile-SPN' responseApdu = hextools.hex2bytes("02546D6F62696C652D53504EFFFFFFFFFF9000") if sendData: if ((types.sw(responseApdu) == types_g.sw.NO_ERROR or types.sw1(responseApdu) == types_g.sw1.NO_ERROR_PROACTIVE_DATA) and self.getNbrOfCards() > 1): # Check for pending SAT command for cardDict in self.cardsDict: cardTmp = cardDict[MAIN_INTERFACE] if card == cardTmp: continue if set(sim_card.SAT_INS) <= set(cardTmp.routingAttr.insReplaced): swNoError = cardTmp.swNoError if types.unpackSw(swNoError)[0] == types_g.sw1.NO_ERROR_PROACTIVE_DATA: #update r-apdu with proactive data information responseApdu[-2] = swNoError >> 8 responseApdu[-1] = swNoError & 0x00FF break self.sendResponseApdu(responseApdu) if card == self.getMainCard(0) or sendData: self.pretty_apdu(apdu) responseApduHex = hextools.bytes2hex(responseApdu) self.loggingApdu.info("R-APDU%d: %s" %(self.getSimId(card), responseApduHex)) # gsmtap.log(apdu,responseApdu) # Uncomment for wireshark return responseApdu