def getAnswer(ignoreUnsolicited=True, stopOnErrors=True): while True: status, buf, uns = conn.receive() if uns and ignoreUnsolicited: log.log('Unsolicited packet detected: ', TLVParser(buf)) continue if status != 0x9000: log.logerr('Pinpad reported error ', hex(status)) traceback.print_stack() if stopOnErrors: performCleanup() exit(-1) break return status, buf, uns
def delfile(file): conn = Connection() log = getSyslog() req_unsolicited = conn.connect() if req_unsolicited: #Receive unsolicited status, buf, uns = conn.receive() if status != 0x9000: log.logerr('Unsolicited fail') exit(-1) log.log('Unsolicited', TLVParser(buf) ) conn.send([0x00, 0xAB, 0x00, 0x00], file) sw12 = conn.receive()[0] if sw12 != 0x9000: exit(sw12)
def __detect_chain_size(conn, log, chain): global __DETECTED_CHAIN_SIZE global __CHAIN_FORCED_DATA_SIZE packetSize = 248 # const if chain == CHAIN_FORCED: packetSize = __CHAIN_FORCED_DATA_SIZE elif chain == CHAIN_AUTODETECT: if __DETECTED_CHAIN_SIZE == 0: # Detect chain size conn.send([0xD0, 0x00, 0x00, 0x00]) status, buf, uns = conn.receive() tlv = TLVParser(buf) if (tlv.tagCount((0xDF, 0xA2, 0x1D))): packetSize = tlv.getTag((0xDF, 0xA2, 0x1D), TLVParser.CONVERT_INT)[0] __DETECTED_CHAIN_SIZE = packetSize else: log.logerr( "No packet size (DFA21D tag), assuming chained messages are not supported!" ) __DETECTED_CHAIN_SIZE = 248 else: packetSize = __DETECTED_CHAIN_SIZE return packetSize
def awaitCardEvent(): #unsolicited response while True: status, buf, uns = getAnswer(False) #Don't ignore unsolicited if not uns: log.logerr('unexpected solicited message received ', buf) return -1, status, buf, uns tlv = TLVParser(buf) result = emvCardState(tlv) if result != ERROR_UNKNOWN_CARD: return result, status, buf, uns else: result = magstripeCardState(tlv) return result, status, buf, uns return -1, status, buf, uns
def GenerateHMAC(): req_unsolicited = conn.connect() if req_unsolicited: status, buf, uns = conn.receive() check_status_error(status) # pan = b'\x37\x96\x05\x17\x71\x11\x11\x8F' # pan = b'\x34\x30\x30\x35\x35\x36\x32\x32\x33\x31\x32\x31\x32\x31\x34\x39' c_tag = tagStorage() # c_tag.store((0xDF, 0xEC, 0x0E), pan) # message for MAC c_tag.store((0xDF, 0xEC, 0x23), 0x06) # host ID c_tag.store((0xDF, 0xEC, 0x23), 0x07) # host ID conn.send([0xC4, 0x22, 0x00, 0x00], c_tag.getTemplate(0xE0)) log.log("Generate HMAC sent") status, buf, uns = conn.receive() log.log("Generate HMAC response received") check_status_error(status) tlv = TLVParser(buf) tag_output_data = (0xDF, 0xEC, 0x7B) if (tlv.tagCount(tag_output_data) == 1): hmac = tlv.getTag(tag_output_data)[0] log.log("Generated HMAC:", hexlify(hmac).decode('utf-8'))
def get_session_key(key_type): global crypto3 global session_key if len(crypto3) == 0: log.logerr("N-S not initialized!") return -1 session_key = '' c_tag = tagStorage() c_tag.store( (0xDF, 0xEC, 0x0F), crypto3 ) conn.send([0xC5, 0x00, key_type, 0x00], c_tag.getTemplate(0xE0)) status, buf, uns = conn.receive() if status != 0x9000: log.logerr("Cannot get session key!") return -2 # Got it tlv = TLVParser(buf) if tlv.tagCount( (0xDF, 0xEC, 0x2E) ) == 1: log.log("Session key received") session_key = tlv.getTag( (0xDF, 0xEC, 0x2E) )[0] log.log("Session key: ", hexlify(session_key)) return 1 else: log.logerr("Failure") return -3
def getAnswer(ignoreUnsolicited = True, stopOnErrors = True): while True: status, buf, uns = conn.receive() tlv = TLVParser(buf) checkEncryptedPAN(tlv) if uns and ignoreUnsolicited: log.log('Unsolicited packet detected: ', tlv) continue if status != 0x9000: log.logerr('Pinpad reported error ', hex(status)) if stopOnErrors: performCleanup() exit(-1) break return status, buf, uns
def verifyPIN(verify_pin_tag, P1=0x01): log.log('verifyPIN') if len(verify_pin_tag) != 0: verify_templ = (0xE0, verify_pin_tag) conn.send([0xDE, 0xD5, P1, 0x01, verify_templ]) else: conn.send([0xDE, 0xD5, P1, 0x01]) while True: status, buf, uns = getAnswer(False) #solicited, PIN entry completed if not uns: log.log('PIN verification concluded ', buf) return 0, status, buf, uns #unsolicited, PIN attempted tlv = TLVParser(buf) log.log('PIN try attempted ', tlv)
def processCtlsContinue(): #Create localtag for transaction continue_ctls_tag = [ [(0xC2), [0x30, 0x30]], [(0xC0), [0x01]], [(0x8A), [0x5A, 0x33]] # [ (0x89), b'\x37\xDD\x29\x75\xC2\xB6' ] # Warning: DUMMY VALUE! ] continue_ctls_templ = (0xE0, continue_ctls_tag) #Start transaction conn.send([0xC0, 0xA1, 0x00, 0x00], continue_ctls_templ) status, buf, uns = getAnswer() log.log('Waiting for Contactless Continue') while True: status, buf, uns = getAnswer(False) if uns: break log.logerr('Unexpected packet detected, ', TLVParser(buf))
def getBinaryStatus(filename): #filename format is 'FILENAME.OLD' log.log('getBinaryStatus') conn.send([0x00, 0xC0, 0x00, 0x00], filename) status, buf, uns = getAnswer() tlv = TLVParser(buf) if status == 0x9000 and not (tlv.tagCount(0x80) and tlv.tagCount(0x81) and tlv.tagCount(0x82) and tlv.tagCount(0x83) and tlv.tagCount(0x87) and tlv.tagCount(0x88) and tlv.tagCount(0x89)): log.logerr( 'message had a missing expected tag or tags (80, 81, 82, 83, 87, 88 and 89)', buf) return -1, status, buf, uns return 0, status, buf, uns
def transtest_function(): log = getSyslog() conn = connection.Connection() #Create ssl server #conn.connect_serial('COM1', 57600, timeout=2 ); req_unsolicited = conn.connect() if req_unsolicited: #Receive unsolicited status, buf, uns = conn.receive() if status != 0x9000: log.logerr('Unsolicited fail') exit(-1) log.log('Unsolicited', TLVParser(buf)) #Send INIT contactless conn.send([0xc0, 0x01, 0x00, 0x00]) status, buf, uns = conn.receive() if status != 0x9000: log.logerr('ctls init fail') exit(-1) #Create localtag for transaction start_trans_tag = [[(0x9F, 0x02), b'\x00\x00\x00\x00\x04\x56'], [(0x9C), b'\x00'], [(0x5F, 0x2A), b'\x08\x26'], [(0x9F, 0x1A), b'\x08\x26']] start_templ = (0xe0, start_trans_tag) print(start_templ) #Start transaction conn.send([0xc0, 0xa0, 0x01, 0x20], start_templ) status, buf, uns = conn.receive() if status != 0x9000: log.logerr('Start transaction fail', hex(status), buf) exit(-1) # Now wait for the user to CANCEL input("ENTER to CANCEL") conn.send([0xc0, 0xc0, 0x00, 0x00]) status, buf, uns = conn.receive() if status != 0x9000: log.logerr('cancel fail!') exit(-1) status, buf, uns = conn.receive() if status != 0x9000: log.logerr('start txn fail!') exit(-1)
def removeEMVCard(): # Display Remove card conn.send([0xD2, 0x01, 0x0E, 0x01]) status, buf, uns = getAnswer(False) if status != 0x9000: log.logerr('Remove card', hex(status), buf) exit(-1) log.log('*** REMOVE CARD WAIT ***') while True: status, buf, uns = getAnswer(False) if uns: tlv = TLVParser(buf) cardState = EMVCardState(tlv) if cardState == EMV_CARD_REMOVED: break log.logerr('Bad packet ', tlv) return tlv
def continueTransaction(continue_trans_tag=CONTINUE_TRANS_TAG): log.log('continueTransaction') continue_tpl = (0xE0, continue_trans_tag) conn.send([0xDE, 0xD2, 0x00, 0x00], continue_tpl) while True: status, buf, uns = getAnswer(False) #Don't ignore unsolicited if status != 0x9000: log.logerr('Transaction terminated with status ', hex(status)) return -1, status, buf, uns tlv = TLVParser(buf) #optional E6 (Status) template, reporting why Terminal is in wait state if tlv.tagCount(0xE6) != 0: log.log('transaction in wait state ', TLVParser(buf)) log.log('PIN Entry is being performed, waiting for user input') #handling to allow user to break from PIN entry to continue test print( 'PIN entry modification, press PC key \'A\' to abort, \'B\' to bypass or \'C\' to cancel' ) while True: if kbhit(): key = getch() log.log('key press ', key) if key == 'a' or key == 'A': log.logerr('PIN entry aborting') abortDevice() break if key == 'b' or key == 'B': log.logerr('PIN entry bypassing') verifyPIN(P1=0xFF) break if key == 'c' or key == 'C': log.logerr('PIN entry cancelling') verifyPIN(P1=0x00) break if conn.is_data_avail(): break # Has user attempted PIN entry, proceed to evaluation of results continue else: #Status result if tlv.tagCount(0xE3): log.log('transaction approved') return TRANSACTION_APPROVED, status, buf, uns if tlv.tagCount(0xE4): log.log('online request, transaction must be verified online') return ONLINE_REQUESTED, status, buf, uns if tlv.tagCount(0xE5): log.log('transaction declined') return TRANSACTION_DECLINED, status, buf, uns
def GenerateHMAC(): req_unsolicited = conn.connect() if req_unsolicited: status, buf, uns = conn.receive() check_status_error(status) #pan = b'\x41\x11\x11\x11\x11\x11\x11\x11' pan = '4111111111111111' # expected HMAC for TC test secrets: d1f8827dd9276f9f80f8890d3e607ac03ca022ba91b8024356dcdf54ad434f83 # pan = b'\x34\x30\x30\x35\x35\x36\x32\x32\x33\x31\x32\x31\x32\x31\x34\x39' c_tag = tagStorage() c_tag.store((0xDF, 0xEC, 0x0E), pan) # message for MAC c_tag.store((0xDF, 0xEC, 0x23), 0x06) # host ID #c_tag.store((0xDF, 0xEC, 0x23), 0x07) # host ID conn.send([0xC4, 0x22, 0x00, 0x00], c_tag.getTemplate(0xE0)) log.log("Generate HMAC sent") status, buf, uns = conn.receive() log.log("Generate HMAC response received") check_status_error(status) tlv = TLVParser(buf) tag_output_data = (0xDF, 0xEC, 0x7B) if (tlv.tagCount(tag_output_data) == 1): hmac = tlv.getTag(tag_output_data)[0] log.log("Generated HMAC:", hexlify(hmac).decode('utf-8')) c_tag = tagStorage() c_tag.store((0xDF, 0xEC, 0x0E), hmac) # message for MAC #c_tag.store((0xDF, 0xEC, 0x23), 0x06) # host ID c_tag.store((0xDF, 0xEC, 0x23), 0x07) # host ID conn.send([0xC4, 0x22, 0x00, 0x00], c_tag.getTemplate(0xE0)) log.log("Generate HMAC sent") status, buf, uns = conn.receive() log.log("Generate HMAC response received") check_status_error(status) tlv = TLVParser(buf) tag_output_data = (0xDF, 0xEC, 0x7B) if (tlv.tagCount(tag_output_data) == 1): hmac = tlv.getTag(tag_output_data)[0] log.log("Generated HMAC:", hexlify(hmac).decode('utf-8'))
def processTransaction(): req_unsolicited = conn.connect() if req_unsolicited: #Receive unsolicited log.log('Waiting for unsolicited') #status, buf, uns = getAnswer(False) #log.log('Unsolicited', TLVParser(buf) ) #Send reset device conn.send([0xD0, 0x00, 0x00, 0x01]) status, buf, uns = getAnswer() tlv = TLVParser(buf) tid = tlv.getTag((0x9F, 0x1e)) if len(tid): tid = str(tid[0], 'iso8859-1') log.log('Terminal TID: ', tid) else: tid = '' log.logerr('Invalid TID (or cannot determine TID)!') #Send clear display conn.send([0xD2, 0x01, 0x01, 0x01]) status, buf, uns = getAnswer() #Monitor card and keyboard status conn.send([0xD0, 0x60, 0x1D, 0x03]) status, buf, uns = getAnswer(False) cardState = EMV_CARD_REMOVED if uns: # Check for insertion unsolicited message tlv = TLVParser(buf) if tlv.tagCount(0x48): cardState = EMVCardState(tlv) ctls = initContactless() if (cardState != EMV_CARD_INSERTED): if (ctls): # Start Contactless transaction start_ctls_tag = [ [(0x9F, 0x02), b'\x00\x00\x00\x00\x01\x00'], [(0x9A), b'\x12\x01\x01'], [(0x9C), b'\x00'], [(0x9F, 0x21), b'\x01\x01\x01'], # [(0x9F,0x41), b'\x00\x01' ], [(0x5F, 0x2A), b'\x08\x26'], [(0x9F, 0x1A), b'\x08\x26'] ] start_templ = (0xE0, start_ctls_tag) conn.send([0xC0, 0xA0, 0x01, 0x00], start_templ) log.log('Starting Contactless transaction') status, buf, uns = getAnswer() else: promptForCard() log.log('**** WAIT FOR CARD INSERTION / TAP / SWIPE ****') tranType = 0 result = 0 ignoreSwipe = False while True: status, buf, uns = getAnswer(False) # Get unsolicited ONLY if uns: # Check for insertion unsolicited message tlv = TLVParser(buf) if tlv.tagCount(0x48): cardState = EMVCardState(tlv) magState = MagstripeCardState(tlv) if ctls and (cardState == EMV_CARD_INSERTED or magState == MAGSTRIPE_TRACKS_AVAILABLE ): # Ignore failed swipes # Cancel Contactless first log.log('Cancelling contactless') conn.send([0xC0, 0xC0, 0x00, 0x00]) status, buf, uns = getAnswer() status, buf, uns = getAnswer( False ) # Ignore unsolicited as the answer WILL BE unsolicited... if cardState == EMV_CARD_INSERTED: log.log("Card inserted, process EMV transaction!") result = processEMV(tid) tranType = 1 break else: if cardState == ERROR_UNKNOWN_CARD: log.log('Unknown card type ') continue if not ignoreSwipe: if magState == ERROR_UNKNOWN_CARD: log.logerr( 'Swipe has failed, there are no tracks!') continue else: if magState == MAGSTRIPE_TRACKS_AVAILABLE: log.log('Card swiped!') vspDecrypt(tlv, tid) tranType = 2 break log.log("Waiting for next occurrance!") continue # Check for unsolicited keyboard status if tlv.tagCount((0xDF, 0xA2, 0x05)): kbd_tag_val = tlv.getTag((0xDF, 0xA2, 0x05), TLVParser.CONVERT_INT)[0] log.log("Keyboard status, keypress ", hex(kbd_tag_val), 'h') continue if tlv.tagCount(0xE3) or tlv.tagCount(0xE5): log.log("Approved contactless EMV transaction!") # todo: vsp decrypt! vspDecrypt(tlv, tid) tranType = 4 break if tlv.tagCount(0xE7): vspDecrypt(tlv, tid) processCtlsContinue() tranType = 3 break if tlv.tagCount(0xE4): vspDecrypt(tlv, tid) processCtlsContinue() tranType = 5 break if status != 0x9000: if status == 0x9F33: # Fallforward to ICC / Swipe promptForCard() # No need to exit the loop - swipe is not active now continue else: if status == 0x9F34: # Fallforward to ICC only promptForCard() # No need to exit the loop - ctls is not active now, but we have to disable swipes ignoreSwipe = True continue log.logerr("Invalid packet detected, ignoring it!") print('E4: ', tlv.tagCount(0xE4)) print(tlv) else: log.log("Card already inserted!") result = processEMV(tid) tranType = 1 # After loop if tranType == 1: # If card still inserted, ask for removal conn.send([0xD0, 0x60, 0x01, 0x00]) status, buf, uns = getAnswer(False) # Get unsolicited tlv = TLVParser(buf) if EMVCardState(tlv) == EMV_CARD_INSERTED: log.log("Card inserted, asking to remove it") removeEMVCard() #Reset display - regardless of tx type conn.send([0xD2, 0x01, 0x01, 0x01]) log.log('*** RESET DISPLAY ***') status, buf, uns = getAnswer()
def processEMV(tid): #Create localtag for transaction start_trans_tag = [ [(0x9F, 0x02), b'\x00\x00\x00\x00\x50\x00'], [(0x9A), b'\x04\x01\x01'], [(0x9C), b'\x00'], [(0x9F, 0x21), b'\x01\x01\x01'], [(0x9F, 0x41), b'\x00\x01'], [(0x5F, 0x2A), b'\x08\x26'], [(0xDF, 0xA2, 0x18), b'\x00'], [(0xDF, 0xA2, 0x14), b'\x01'], [(0xDF, 0xA2, 0x04), b'\x00'] # Manual app selection!! ] start_templ = (0xE0, start_trans_tag) #Start transaction conn.send([0xDE, 0xD1, 0x00, 0x00], start_templ) while True: #sleep(1) #conn.send([0xD0, 0xFF, 0x00, 0x00]) status, buf, uns = getEMVAnswer() if status != 0x9000: if status == 0x9F28: return processMagstripeFallback(tid) else: log.logerr('Transaction terminated with status ', hex(status)) return -1 if uns and status == 0x9000: tlv = TLVParser(buf) if tlv.tagCount(0xE6) != 0: log.log('Multi application card!') continue else: log.log('Ignoring unsolicited packet ', tlv) continue else: tlv = TLVParser(buf) if tlv.tagCount(0x50) > 1 and tlv.tagCount((0x9F, 0x06)) > 1: # This is app selection stuff appLabels = tlv.getTag(0x50) appAIDs = tlv.getTag((0x9F, 0x06)) log.log('We have ', len(appLabels), ' applications') if len(appLabels) != len(appAIDs): log.logerr('Invalid response: AID count ', len(appAIDs), ' differs from Labels count ', len(appLabels)) exit(-1) for i in range(len(appLabels)): log.log('App ', i + 1, ': AID ', hexlify(appAIDs[i]), ', label ', str(appLabels[i])) sel = -1 while True: #sels = input('Choose one app: ') #try: # sel = int(sels.strip()) #except: # print('invalid entry!!!') #if sel > 0 and sel <= len(appLabels): break #print(' Invalid selection, please pick valid number! ') # Note: The below will work for up to 9 apps... if kbhit(): try: sel = ord(getch()) except: print('invalid key!') #log.log('key press ', sel) if sel > 0x30 and sel <= 0x30 + len(appLabels): sel -= 0x30 # to number (0 .. x) break elif sel == 27: conn.send([0xD0, 0xFF, 0x00, 0x00]) status, buf, uns = getAnswer() log.logerr('Transaction aborted') return -1 print(' Invalid selection, please pick valid number! ') if conn.is_data_avail(): status, buf, uns = getEMVAnswer() if status != 0x9000: log.logerr('Transaction terminated with status ', hex(status)) return -1 break if sel >= 0: sel = sel - 1 log.log('Selected ', sel) app_sel_tags = [[(0x50), bytearray(appLabels[sel])], [(0x9F, 0x06), bytearray(appAIDs[sel])]] app_sel_templ = (0xE0, app_sel_tags) conn.send([0xDE, 0xD2, 0x00, 0x00], app_sel_templ) log.log('App selected, waiting for response...') continue break #Let's check VSP tlv = TLVParser(buf) vspDecrypt(tlv, tid) #print(TLVParser(buf)) #Continue transaction continue_tran_tag = [[(0x9F, 0x02), [0x00, 0x00, 0x00, 0x00, 0x54, 0x00]], [(0x5F, 0x2A), [0x09, 0x78]], [(0xC2), [0x36, 0x35]], [(0xDF, 0xA2, 0x18), [0x00]], [(0xDF, 0xA3, 0x07), [0x03, 0xE8]], [(0xC0), [0x01]], [(0x91), [ 0x37, 0xDD, 0x29, 0x75, 0xC2, 0xB6, 0x68, 0x2D, 0x00, 0x12 ]]] continue_tpl = (0xE0, continue_tran_tag) conn.send([0xDE, 0xD2, 0x00, 0x00], continue_tpl) while True: status, buf, uns = getEMVAnswer() if status != 0x9000: log.logerr('Transaction terminated with status ', hex(status)) return -1 tlv = TLVParser(buf) if uns and status == 0x9000: #print(tlv) if tlv.tagCount(0xE6) != 0: log.log('PIN Entry is being performed, waiting again') print( 'PIN Entry, press \'A\' to abort, \'B\' to bypass or \'C\' to cancel' ) while True: #sleep(1) validKey = False if kbhit(): key = getch() log.log('key press ', key) if key == 'a' or key == 'A': log.logerr('aborting') conn.send([0xD0, 0xFF, 0x00, 0x00]) validKey = True if key == 'b' or key == 'B': log.logerr('bypassing') conn.send([0xDE, 0xD5, 0xFF, 0x01]) validKey = True if key == 'c' or key == 'C': log.logerr('cancelling') conn.send([0xDE, 0xD5, 0x00, 0x00]) validKey = True if validKey: status, buf, uns = getAnswer( stopOnErrors=False ) # Wait for confirmation, then break to wait for response if status == 0x9000: break else: continue else: continue if conn.is_data_avail(): break continue else: log.log('Ignoring unsolicited packet ', tlv) continue else: if tlv.tagCount(0xE3): log.log("Transaction approved offline") return 1 else: if tlv.tagCount(0xE5): log.log("Transaction declined offline") return 2 else: break # If we get here, we received Online Request. Continue with positive response. conn.send([0xDE, 0xD2, 0x00, 0x00]) status, buf, uns = getEMVAnswer( True) # Ignore unsolicited automatically here if status != 0x9000: log.logerr('Online Request has failed', hex(status)) return -1 tlv = TLVParser(buf) if tlv.tagCount(0xE3): log.log("Transaction approved") return 1 if tlv.tagCount(0xE5): log.log("Transaction declined") return 2 return 3
def OnlinePIN(): ''' First create connection ''' req_unsolicited = conn.connect() ''' If unsolicited read it''' if req_unsolicited: status, buf, uns = conn.receive() check_status_error(status) #host_id = 5; # Alter from default of 2 to VSS Script index 2 (host_id=3) host_id = 2 # Alter from default of 2 to VSS Script index 2 (host_id=3) ''' Send data ''' pan = b'\x54\x13\x33\x00\x89\x00\x00\x39' amount = b'\x00\x00\x00\x01\x23\x00' c_tag = tagStorage() #BUG: Unable to push the direct string not bytearray c_tag.store((0xDF, 0xEC, 0x05), 0x00) # pin try flag c_tag.store((0xDF, 0xED, 0x05), 0x08) # max pin length c_tag.store((0xDF, 0xED, 0x04), 0x04) # min pin length c_tag.store((0xDF, 0xDF, 0x17), amount) # c_tag.store( (0xDF, 0xDF, 0x24), b'PLN') c_tag.store((0xDF, 0xDF, 0x24), (0x08, 0x26)) c_tag.store((0xDF, 0xDF, 0x1C), 2) c_tag.store((0x5A), pan) conn.send([0xDE, 0xD6, host_id, 0x01], c_tag.getTemplate(0xE0)) log.log("Get online PIN sent") log.log('*** PIN ENTRY WAIT ***') # possible_cancel(conn,log,host_id) status, buf, uns = conn.receive() log.log("Get online PIN received") check_status_error(status) tlv = TLVParser(buf) if (tlv.tagCount((0xDF, 0xED, 0x6C)) == 1 and tlv.tagCount( (0xDF, 0xED, 0x03)) == 1): #encryptedPIN = tlv.getTag((0xDF, 0xED, 0x6C), TLVParser.CONVERT_HEX_STR)[0].upper() encryptedPIN = tlv.getTag((0xDF, 0xED, 0x6C))[0] ksn = tlv.getTag((0xDF, 0xED, 0x03), TLVParser.CONVERT_HEX_STR)[0].upper() log.log("Encrypted PIN: ", hexlify(encryptedPIN)) log.log("KSN: ", ksn) # We have KSN, let's find key keyTable = { 'FFFF9876543210E00001': '042666B49184CF5C68DE9628D0397B36', 'FFFF9876543210E00002': 'C46551CEF9FD244FAA9AD834130D3B38', 'FFFF9876543210E00003': '0DF3D9422ACA561A47676D07AD6BAD05', 'FFFF9876543210E00004': '279C0F6AEED0BE9A2B2C733E1383AE6E', 'FFFF9876543210E00005': '5F8DC6D2C845C1DA508DDC048093B8C0', 'FFFF9876543210E00006': '5E415CB0BAF9F0C3D0C14B63FB62FFBC', 'FFFF9876543210E00007': '0C8F780B7C8B492FAE84A9EB2A6CE69F', 'FFFF9876543210E00008': '27F66D5244FF621EAA6F6120EDEB427F', 'FFFF9876543210E00009': '27E31064FDC565968900E2057F658E81', 'FFFF9876543210E0000A': '6CF2500A22507C83C776CEADC1E330EB', 'FFFF9876543210E0000B': '3E8260BA04B2D6DFC01482B3819A1848', 'FFFF9876543210E0000C': 'B716E1E11CF53D7F726CAEE75C3A62B0', 'FFFF9876543210E0000D': 'E072EDF9534053A0B6C581C58FBF25CC', 'FFFF9876543210E0000E': 'A80046087F5B8FDB5AAD95E1842908B0', 'FFFF9876543210E0000F': '93DD5B956C4878B82E453AAEFD32A555', 'FFFF9876543210E00010': '59598DCBD9BD943F94165CE453585FA8', 'FFFF9876543210E00011': '2B5F01F4F0CC0515639D523231BF1B5D', 'FFFF9876543210E00012': '9CF640F279C2AE1915F725EEEAC2CB50', 'FFFF9876543210E00013': 'C3DF489FDF11534BF03DE97C27DC4CD0', 'FFFF9876543210E00014': '658488507721B30E4737FA93F923CB2D', 'FFFF9876543210E00015': 'E161D1956A61F62DF37AFD7F9CC36965', } if not ksn in keyTable: raise exceptions.logicalException( "Cannot find key in static table - please inject Security keys again!!!" ) key = keyTable[ksn] log.log("Key: ", key) #encryptedPIN = unhexlify(encryptedPIN) open("pin.dat", "wb").write(encryptedPIN) if os.path.isfile("pindec.dat"): os.remove("pindec.dat") vscmd = "openssl" #args = ' ' + "des-ede -nosalt -nopad -d -in pin.dat -out pindec.dat -k " + key args = ' ' + "des-ede -p -nosalt -nopad -d -in pin.dat -out pindec.dat -K " + key + " -iv 0000000000000000" log.log("calling openssl ", vscmd, ", params: ", args) if os.system(vscmd + args): raise exceptions.logicalException("Openssl call failed.") dec = open("pindec.dat", "rb").read() log.log("Decrypted PIN block: ", hexlify(dec)) pinLen = dec[0] & 0x0F log.log("PIN length detected: ", pinLen) if (pinLen < 4 or pinLen > 12): raise exceptions.logicalException("Invalid PIN Block length!") if (pinLen % 2): pinLen += 1 pinLen = (int)(pinLen / 2) #pan = bytearray(pan[-6:]) # Take last 12 PAN digits pan = bytearray(unhexlify((hexlify(bytearray(pan))[-13:])[:12])) pan.reverse() encodedPIN = bytearray(dec) encodedPIN.reverse() appendCnt = len(encodedPIN) - len(pan) #print('encoded pin: ', hexlify(encodedPIN)) #print('pan: ', hexlify(pan)) clearPIN = bytearray() for idx in range(len(pan)): #print('encpin val ', encodedPIN[idx], '; pan val ', pan[idx]) val = encodedPIN[idx] val ^= pan[idx] clearPIN.append(val) encodedPIN.reverse() while (appendCnt > 0): appendCnt -= 1 clearPIN.append(encodedPIN[appendCnt]) clearPIN.reverse() log.log("PIN block: ", hexlify(clearPIN)) clearPIN = clearPIN[1:pinLen + 1] PIN = str(hexlify(clearPIN)).replace("f", "") log.loginfo('PIN entered: ', PIN) os.remove("pin.dat") os.remove("pindec.dat") else: log.logerr("Invalid data!")
def OnlinePIN_IBM3624(): """ This script tests implementation of PIN IBM3624 with offset. 1. The script establishes connection to VIPA 2. Sends the data required for PIN validation, namely the PAN and offset. 3. The customer enters the PIN on VIPA pinpad and the pinpad responds with the information wether PIN is correct or improper """ amount = b'\x00\x00\x00\x00\x00\x00' pin = b'\x12\x34' pvk = b'\x79\x73\xc0\x90\x5a\xc3\xbe\x59\xd9\xf8\x53\x80\x53\x8a\x99\x3e' master_key = b'\x54\x9B\x6E\x13\xB5\x45\xA8\x7F\xA4\x32\x13\xF8\xE5\xBC\x85\x0D' kcv = b'\x1D\x85\xE5' padding_char = b'\x0F' pvk_enc = encrypt_pvk_with_master(master_key, kcv, pvk) #pin_block = ibm3624_pin_block_generation(pin, pvk, padding_char) log.log("amount is: ", hexlify(amount)) log.log("Valid pin is: ", hexlify(pin)) log.log("Secret PVK formely injected is:", hexlify(pvk)) log.log("Encrypted PVK is:", hexlify(pvk_enc)) #log.log("pin block is: ", hexlify(pin_block)) ''' First create connection ''' req_unsolicited = conn.connect() ''' If unsolicited read it''' if req_unsolicited: status, buf, uns = conn.receive() check_status_error(status) host_id = 9 update_key_command(conn, host_id, pvk_enc) c_tag = tagStorage() #BUG: Unable to push the direct string not bytearray c_tag.store((0xDF, 0xEC, 0x05), 0x00) # pin try flag c_tag.store((0xDF, 0xED, 0x05), 0x04) # max pin length c_tag.store((0xDF, 0xED, 0x04), 0x04) # min pin length c_tag.store((0xDF, 0xDF, 0x17), amount) # c_tag.store( (0xDF, 0xDF, 0x24), b'PLN') # currency code # c_tag.store( (0xDF, 0xDF, 0x1C), 2) # currency exponent c_tag.store((0xDF, 0xED, 0x08), 6) # PIN_BLOCK_FORMAT_IBM3624 # c_tag.store( (0xDF, 0xED, 0x12), decim_table) c_tag.store((0xDF, 0xED, 0x12), b'\x0F') #Now treat it as a padding. # c_tag.store( (0xDF, 0xED, 0x11), ibm3624_pin_offset) # c_tag.store( (0x5A), pan ) conn.send([0xDE, 0xD6, host_id, 0x00], c_tag.getTemplate(0xE0)) log.log("Verify IBM3624 pin sent") status, buf, uns = conn.receive() log.log("Received verification status") check_status_error(status) tlv = TLVParser(buf) if tlv.tagCount((0xDF, 0xED, 0x6C)) == 1: pin_block = tlv.getTag((0xDF, 0xED, 0x6C))[0] log.log("Pin block is: ", bytes(pin_block)) log.log("PVK is: ", pvk.hex()) entered_pin = decrypt_key(pvk, bytes(pin_block)) log.log("Entered pin is: ", entered_pin.hex()) else: log.log("No valid response from Vipa")
def elm_init_function(): ''' First create connection ''' req_unsolicited = conn.connect() ''' If unsolicited read it''' if req_unsolicited: status, buf, uns = conn.receive() check_status_error(status) ''' Reset display ''' conn.send([0xD2, 0x01, 0x01, 0x00]) status, buf, uns = conn.receive() check_status_error(status) ''' Check VSP Status ''' conn.send([0xDD, 0x00, 0x03, 0x00]) status, buf, uns = conn.receive() check_status_error(status) tlv = TLVParser(buf) vsp_stat = tlv.getTag((0xDF, 0xA2, 0x30), TLVParser.CONVERT_INT)[0] log.log('VSP status ', vsp_stat) if vsp_stat != 0: log.log('VSP Detected') if vsp_stat == 1: log.log('VSP Not active') else: if vsp_stat == 2: log.log('VSP Active') else: log.logerr('Unknown status!') return False ''' Get VSP version ''' vsp_version = tlv.getTag((0xDF, 0xA2, 0x32), TLVParser.CONVERT_STR)[0] log.log('VSP Version ', vsp_version) if (vsp_version[:2] == '4.'): log.log('ELM Detected!') ''' First of all, we need TID ''' conn.send([0xD0, 0x00, 0x00, 0x01]) status, buf, uns = conn.receive() tlv = TLVParser(buf) tid = tlv.getTag((0x9F, 0x1e)) if len(tid): tid = str(tid[0], 'iso8859-1') log.log('Terminal TID: ', tid) else: tid = '' log.logerr('Invalid TID (or cannot determine TID)!') return False ''' Trying to enable it ''' conn.send([0xDD, 0xC1, 0x00, 0x00]) status, buf, uns = conn.receive() check_status_error(status) status, buf, uns = conn.receive() check_status_error(status) tlv = TLVParser(buf) t1 = tlv.getTag((0x5F, 0x21), TLVParser.CONVERT_STR) if len(t1): t1 = t1[0] else: t1 = '' t2 = tlv.getTag((0x5F, 0x22), TLVParser.CONVERT_STR) if len(t2): t2 = t2[0] else: t2 = '' if len(t1): log.log('T1: ', t1) if len(t2): log.log('T2: ', t2) try: enc = semtec.encryptor() enc.set_TID(tid) except exceptions.logicalException as exc: log.logerr('Cannot create decryptor object! Error ', exc) return False pan = '' expiry = '' try: pan_d, expiry_d, t1_d, t2_d = enc.decrypt(pan, expiry, t1, t2) log.log('Done ok') except exceptions.logicalException as exc: if not '909' in str(exc): log.logerr('Advance DDK error ', exc) else: log.log('VSP keys advanced on Host') return True else: log.logerr('Not ELM (Dogwood)') return False else: log.log('No VSP detected!') return False
def transtest_function(): log = getSyslog() conn = connection.Connection(); # # !!! NOTE: Now you can set connection parameters from command line! # #Create ssl server #conn.connect_serial('COM1', 57600, timeout=2 ); req_unsolicited = conn.connect() if req_unsolicited: #Receive unsolicited status, buf, uns = conn.receive() if status != 0x9000: log.logerr('Unsolicited fail') exit(-1) log.log('Unsolicited', TLVParser(buf) ) #Send INIT contactless conn.send([0xc0, 0x01, 0x00, 0x00]) status, buf, uns = conn.receive() if status != 0x9000: log.logerr('ctls init fail') exit(-1) ##################################################### # Get handle conn.send([0xc0, 0xf8, 0x01, 0x00]) status, buf, uns = conn.receive() if status != 0x9000: log.logerr('Get handle fail', hex(status), buf) exit(-1) tlv = TLVParser(buf) cicappHandle = tlv.getTag((0xdf,0xc0,0x01), TLVParser.CONVERT_INT)[0] log.log('Handle=', hex(cicappHandle)) ##################################################### # Force proxy mode conn.send([0xc0, 0xf8, 0x02, 0x01]) status, buf, uns = conn.receive() if status != 0x9000: log.logerr('Control proxy mode fail', hex(status), buf) exit(-1) ##################################################### # Send 'PassThruEnable' passThruCtlTags = [ [ (0xdf, 0xc0, 0x01), [cicappHandle] ], [ (0xdf, 0x1f), [0x30] ], # POS timeout [ (0xdf, 0xc0, 0x40), [0x01] ] ] SendPassThruPacket(conn, 220, passThruCtlTags) status, buf, uns = conn.receive() if status != 0x9000: log.logerr('Send pass-thru fail', hex(status), buf) exit(-1) ##################################################### # Send 'WaitForCard' waitForCardTags = [ [ (0xdf, 0xc0, 0x01), [cicappHandle] ], [ (0xdf, 0x1f), [0x30] ] # POS timeout ] SendPassThruPacket(conn, 221, waitForCardTags) status, buf, uns = conn.receive() if status != 0x9000: log.logerr('Send pass-thru fail', hex(status), buf) exit(-1) # Wait for unsolicited message status, buf, uns = conn.receive() if status != 0x9000: log.logerr('Wait for card fail!') exit(-1) ##################################################### # Send 'HighLevelPassThru' ('MIFARE Authenticate') innerTags = [ [ (0xdf, 0xc0, 0x5a), [0x00] ], # Sector number [ (0xdf, 0xc0, 0x5b), [0x01] ], # Key A (01) [ (0xdf, 0xc0, 0x5c), [0xff, 0xff, 0xff, 0xff, 0xff, 0xff ] ] # Key value ] hlPassThruTags = [ [ (0xdf, 0xc0, 0x01), [cicappHandle] ], [ (0xdf, 0x1f), [0x30] ], # POS timeout [ (0xdf, 0xc0, 0x58), [0x00, 0x01] ], # Subcommand: MIFARE Authenticate [ (0xdf, 0xc0, 0x59), Tags2Array(innerTags) ] # Subcommand data ] SendPassThruPacket(conn, 224, hlPassThruTags) status, buf, uns = conn.receive() if status != 0x9000: log.logerr('Send pass-thru fail', hex(status), buf) exit(-1) ##################################################### # Send 'HighLevelPassThru' ('MIFARE Read') innerTags = [ [ (0xdf, 0xc0, 0x5e), [0x01] ], # Block count [ (0xdf, 0xc0, 0x5d), [0x02] ] # Start block ] hlPassThruTags = [ [ (0xdf, 0xc0, 0x01), [cicappHandle] ], [ (0xdf, 0x1f), [0x30] ], # POS timeout [ (0xdf, 0xc0, 0x58), [0x00, 0x02] ], # Subcommand: MIFARE Read [ (0xdf, 0xc0, 0x59), Tags2Array(innerTags) ] # Subcommand data ] SendPassThruPacket(conn, 224, hlPassThruTags) status, buf, uns = conn.receive() if status != 0x9000: log.logerr('Send pass-thru fail', hex(status), buf) exit(-1) ##################################################### # Send 'HighLevelPassThru' ('MIFARE Write') innerTags = [ [ (0xdf, 0xc0, 0x5e), [0x01] ], # Block count [ (0xdf, 0xc0, 0x5d), [0x02] ], # Start block [ (0xdf, 0xc0, 0x5f), binascii.unhexlify(b'0123456789abcdef0f1e2d3c4b5a6978') ] # Data 16 bytes! ] hlPassThruTags = [ [ (0xdf, 0xc0, 0x01), [cicappHandle] ], [ (0xdf, 0x1f), [0x30] ], # POS timeout [ (0xdf, 0xc0, 0x58), [0x00, 0x03] ], # Subcommand: MIFARE Write [ (0xdf, 0xc0, 0x59), Tags2Array(innerTags) ] # Subcommand data ] SendPassThruPacket(conn, 224, hlPassThruTags) status, buf, uns = conn.receive() if status != 0x9000: log.logerr('Send pass-thru fail', hex(status), buf) exit(-1) ##################################################### # Send 'HighLevelPassThru' ('MIFARE Read') innerTags = [ [ (0xdf, 0xc0, 0x5e), [0x01] ], # Block count [ (0xdf, 0xc0, 0x5d), [0x02] ] # Start block ] hlPassThruTags = [ [ (0xdf, 0xc0, 0x01), [cicappHandle] ], [ (0xdf, 0x1f), [0x30] ], # POS timeout [ (0xdf, 0xc0, 0x58), [0x00, 0x02] ], # Subcommand: MIFARE Read [ (0xdf, 0xc0, 0x59), Tags2Array(innerTags) ] # Subcommand data ] SendPassThruPacket(conn, 224, hlPassThruTags) status, buf, uns = conn.receive() if status != 0x9000: log.logerr('Send pass-thru fail', hex(status), buf) exit(-1)
def processEMV(tid): #Create localtag for transaction start_trans_tag = [[(0x9F, 0x02), b'\x00\x00\x00\x10\x04\x00'], [(0x9A), b'\x04\x01\x01'], [(0x9C), b'\x00'], [(0x9F, 0x21), b'\x01\x01\x01'], [(0x9F, 0x41), b'\x00\x01'], [(0x5F, 0x2A), b'\x08\x26'], [(0xDF, 0xA2, 0x18), b'\x00'], [(0xDF, 0xA2, 0x14), b'\x01'], [(0xDF, 0xA2, 0x04), b'\x01']] start_templ = (0xE0, start_trans_tag) #Start transaction conn.send([0xDE, 0xD1, 0x00, 0x00], start_templ) while True: status, buf, uns = getEMVAnswer() if status != 0x9000: if status == 0x9F28: return processMagstripeFallback(tid) else: log.logerr('Transaction terminated with status ', hex(status)) return -1 if uns and status == 0x9000: tlv = TLVParser(buf) if tlv.tagCount(0xE6) != 0: log.log('Multi application card!') continue else: log.log('Ignoring unsolicited packet ', tlv) continue else: break #Let's check VSP tlv = TLVParser(buf) vspDecrypt(tlv, tid) S1DecryptData(tlv) #print(TLVParser(buf)) #Continue transaction continue_tran_tag = [[(0x9F, 0x02), [0x00, 0x00, 0x00, 0x00, 0x54, 0x00]], [(0x5F, 0x2A), [0x09, 0x78]], [(0xC2), [0x30, 0x30]], [(0xDF, 0xA2, 0x18), [0x00]], [(0xDF, 0xA3, 0x07), [0x03, 0xE8]], [(0xC0), [0x01]], [(0x8A), [0x59, 0x32]], [(0x91), [ 0x37, 0xDD, 0x29, 0x75, 0xC2, 0xB6, 0x68, 0x2D, 0x00, 0x12 ]]] continue_tpl = (0xE0, continue_tran_tag) conn.send([0xDE, 0xD2, 0x00, 0x00], continue_tpl) while True: status, buf, uns = getEMVAnswer() if status != 0x9000: log.logerr('Transaction terminated with status ', hex(status)) return -1 tlv = TLVParser(buf) if uns and status == 0x9000: #print(tlv) if tlv.tagCount(0xE6) != 0: log.log('PIN Entry is being performed, waiting again') print( 'PIN Entry, press \'A\' to abort, \'B\' to bypass or \'C\' to cancel' ) while True: #sleep(1) if kbhit(): key = getch() log.log('key press ', key) if key == 'a' or key == 'A': log.logerr('aborting') conn.send([0xD0, 0xFF, 0x00, 0x00]) break if key == 'b' or key == 'B': log.logerr('bypassing') conn.send([0xDE, 0xD5, 0xFF, 0x01]) status, buf, uns = getAnswer( ) # Wait for confirmation, then break to wait for response break if key == 'c' or key == 'C': log.logerr('cancelling') conn.send([0xDE, 0xD5, 0x00, 0x00]) status, buf, uns = getAnswer( ) # Wait for confirmation, then break to wait for response break if conn.is_data_avail(): break continue else: log.log('Ignoring unsolicited packet ', tlv) continue else: if tlv.tagCount(0xE3): log.log("Transaction approved offline") return 1 else: if tlv.tagCount(0xE5): log.log("Transaction declined offline") return 2 else: break # If we get here, we received Online Request. Continue with positive response. conn.send([0xDE, 0xD2, 0x00, 0x00]) status, buf, uns = getEMVAnswer( True) # Ignore unsolicited automatically here if status != 0x9000: log.logerr('Online Request has failed', hex(status)) return -1 tlv = TLVParser(buf) if tlv.tagCount(0xE3): log.log("Transaction approved") return 1 if tlv.tagCount(0xE5): log.log("Transaction declined") return 2 return 3
def transtest_function(): log = getSyslog() conn = connection.Connection(); #Create ssl server #conn.connect_tcp_server(timeout=30) #conn.connect_tcp_client('localhost',16107) #conn.connect_serial('COM1', 57600, timeout=2 ); req_unsolicited = conn.connect() if req_unsolicited: #Receive unsolicited status, buf, uns = conn.receive() if status != 0x9000: log.logerr('Unsolicited fail') exit(-1) log.log('Unsolicited', TLVParser(buf) ) #Send reset device conn.send([0xD2, 0x01, 0x01, 0x00]) status, buf, uns = conn.receive() if status != 0x9000: log.logerr('reset fail') exit(-1) #Monitor card status conn.send([0xD0, 0x60, 0x01, 0x00]) status, buf, uns = conn.receive() if status != 0x9000: log.logerr('Cardstatus fail') exit(-1) #print('CardStatus',TLVParser(buf)) #Prompt for card conn.send([0xD2, 0x01, 0x0D, 0x00]) status, buf, uns = conn.receive() if status != 0x9000: log.logerr('prompt card fail') exit(-1) #Short insert card notification log.log('**** WAIT FOR CARD INSERTION ****') status, buf, uns = conn.receive() if status != 0x9000 and not uns: log.logerr('Pinpad fail!!', hex(status),uns) exit(-1) tlv = TLVParser(buf) ins_tag_val = tlv.getTag(0x48, tlv.CONVERT_INT) if ins_tag_val[0]!=0x300: log.logerr('PINPAD FAILED tag 0x48 is', ins_tag_val) exit(-1) #Create localtag for transaction start_trans_tag = [ [(0x9F, 0x02), b'\x00\x00\x00\x10\x04\x00' ], [(0x9A), b'\x04\x01\x01'], [(0x9C), b'\x00'], [(0x9F,0x21), b'\x01\x01\x01'], [(0x9F,0x41), b'\x00\x01' ], [(0x5F,0x2A), b'\x08\x26' ], [(0xDF,0xA2,0x18), b'\x00'], [(0xDF,0xA2,0x14), b'\x01'], [(0xDF,0xA2,0x04), b'\x01'] ] start_templ = ( 0xE0, start_trans_tag ) print(start_templ) #Start transaction conn.send([0xDE, 0xD1, 0x00, 0x00], start_templ) status, buf, uns = conn.receive() if status != 0x9000: log.logerr('Start transaction fail', hex(status), buf) exit(-1) #print(TLVParser(buf)) #Continue transaction c_tag = tagStorage() c_tag.store( (0x9F,0x02), [0x00, 0x00, 0x00,0x00, 0x54, 0x00 ] ) c_tag.store( (0x5F,0x2A), [0x09, 0x78] ) c_tag.store( 0xC2, [0x30, 0x30] ) c_tag.store( (0xDF,0xA2,0x18), 0x00 ) c_tag.store( (0xDF,0xA3,0x07), [0x03,0xE8] ) c_tag.store( 0xC0, 0x01 ) c_tag.store( 0x8A, [0x59, 0x32 ] ) c_tag.store( 0x91, [0x37,0xDD,0x29,0x75,0xC2,0xB6,0x68,0x2D,0x00,0x12] ) #continue_tran_tag = [ # [ (0x9F,0x02), [0x00, 0x00, 0x00,0x00, 0x54, 0x00 ] ], # [ (0x5F,0x2A), [0x09, 0x78] ], # [ (0xC2), [0x30, 0x30] ], # [ (0xDF,0xA2,0x18), [0x00] ], # [ (0xDF,0xA3,0x07), [0x03,0xE8] ], # [ (0xC0), [0x01] ], # [ (0x8A), [0x59, 0x32 ] ], # [ (0x91), [0x37,0xDD,0x29,0x75,0xC2,0xB6,0x68,0x2D,0x00,0x12] ] #] #continue_tpl = (0xE0, continue_tran_tag ) #conn.send([0xDE, 0xD2, 0x00, 0x00], continue_tpl) conn.send( [0xDE, 0xD2, 0x00, 0x00], c_tag.getTemplate(0xE0) ) status, buf, uns = conn.receive() if status != 0x9000: log.logerr('Continue transaction fail', hex(status), buf) exit(-1) #print(TLVParser(buf)) log.log('*** PIN ENTRY WAIT ***') status, buf, uns = conn.receive() utility.check_status_error((status, buf, uns)) tlv = TLVParser(buf) #print(tlv) if tlv.tagCount(0xE6) != 0: log.logerr('Not complete response wait again') status, buf, uns = conn.receive() if status != 0x9000: log.logerr('Pin entry wait #2', hex(status), buf) exit(-1) # Continue with positive response conn.send([0xDE, 0xD2, 0x00, 0x00]) log.log('*** ONLINE REQUEST WAIT ***') status, buf, uns = conn.receive() if status != 0x9000: log.logerr('Online Request wait', hex(status), buf) exit(-1) #print(TLVParser(buf)) #Remove card conn.send([0xD2, 0x01, 0x0E, 0x00]) log.log('*** REMOVE CARD PROMPT***') status, buf, uns = conn.receive() if status != 0x9000: log.logerr('Remove card', hex(status), buf) exit(-1) log.log('*** REMOVE CARD WAIT ***') status, buf, uns = conn.receive() if status != 0x9000: log.logerr('Remove card wait', hex(status), buf) exit(-1) #Reset display conn.send([0xD2, 0x01, 0x01, 0x00]) log.log('*** RESET DISPLAY ***') status, buf, uns = conn.receive() if status != 0x9000: log.logerr('Reset display wait', hex(status), buf) exit(-1) #Disconnect conn.send([0xD2, 0x01, 0x01, 0x00]) log.log('*** DISCONNECT ***') status, buf, uns = conn.receive() if status != 0x9000: log.logerr('Disconnect wait', hex(status), buf) exit(-1)
def startCTLSTranAndWaitUnsolicited(selectedAID, tid): start_ctls_tag = [[(0x9F, 0x02), b'\x00\x00\x00\x00\x01\x00'], [(0x9A), b'\x18\x01\x26'], [(0x9C), b'\x00'], [(0x9F, 0x21), b'\x12\x56\x01'], [(0x5F, 0x2A), b'\x08\x26'], [(0x9F, 0x1A), b'\x08\x26']] if selectedAID == None: #get the list of AIDs log.log("Start CTLS transaction to get the list of CTLS AIDs on card") start_ctls_tag.append([(0x9F, 0x06), b'\x00\x01']) else: log.log("Start CTLS transaction with AID", selectedAID.hex()) start_ctls_tag.append([(0x9F, 0x06), selectedAID]) start_templ = (0xE0, start_ctls_tag) prev_nad = conn.setnad(2) conn.send([0xC0, 0xA0, 0x01, 0x00], start_templ) # For MiFare, change P1 to 0x03 log.log('Starting Contactless transaction') status, buf, uns = getAnswer() conn.setnad(prev_nad) log.log('**** WAIT FOR CARD INSERTION / TAP / SWIPE ****') tranType = 0 result = 0 ignoreSwipe = False prev_nad = conn.setnad(2) while True: status, buf, uns = getAnswer(False) # Get unsolicited ONLY if uns: # Check for insertion unsolicited message tlv = TLVParser(buf) if tlv.tagCount(0x48): cardState = EMVCardState(tlv) magState = MagstripeCardState(tlv) if ctls and (cardState == EMV_CARD_INSERTED or magState == MAGSTRIPE_TRACKS_AVAILABLE ): # Ignore failed swipes # Cancel Contactless first log.log('Cancelling contactless') prev_nad = conn.setnad(clts_nad) conn.send([0xC0, 0xC0, 0x00, 0x00]) status, buf, uns = getAnswer() status, buf, uns = getAnswer( False ) # Ignore unsolicited as the answer WILL BE unsolicited... conn.setnad(prev_nad) if cardState == EMV_CARD_INSERTED: log.log("Card inserted, process EMV transaction!") result = processEMV(tid) tranType = 1 break else: if cardState == ERROR_UNKNOWN_CARD: log.log('Unknown card type ') continue if not ignoreSwipe: if magState == ERROR_UNKNOWN_CARD: log.logerr('Swipe has failed, there are no tracks!') continue else: if magState == MAGSTRIPE_TRACKS_AVAILABLE: log.log('Card swiped!') vspDecrypt(tlv, tid) tranType = 2 break log.log("Waiting for next occurrance!") continue # Check for unsolicited keyboard status if tlv.tagCount((0xDF, 0xA2, 0x05)): kbd_tag_val = tlv.getTag((0xDF, 0xA2, 0x05), TLVParser.CONVERT_INT)[0] log.log("Keyboard status, keypress ", hex(kbd_tag_val), 'h') continue if tlv.tagCount(0xE3) or tlv.tagCount(0xE5): log.log("Approved contactless EMV transaction!") # todo: vsp decrypt! vspDecrypt(tlv, tid) tranType = 4 break if tlv.tagCount(0xE7): vspDecrypt(tlv, tid) processCtlsContinue() tranType = 3 break if tlv.tagCount(0xE4): vspDecrypt(tlv, tid) processCtlsContinue() tranType = 5 break if tlv.tagCount(0xE0) and tlv.tagCount((0xDF, 0xC0, 0x41)): log.log('MiFare tx detected!') processCtlsMiFare() break if tlv.tagCount(0x6F): break if status != 0x9000: if status == 0x9F33: # Fallforward to ICC / Swipe promptForCard() # No need to exit the loop - swipe is not active now continue else: if status == 0x9F34: # Fallforward to ICC only promptForCard() # No need to exit the loop - ctls is not active now, but we have to disable swipes ignoreSwipe = True continue log.logerr("Invalid packet detected, ignoring it!") print('E4: ', tlv.tagCount(0xE4)) return tlv
def transtest_function(): log = getSyslog() conn = connection.Connection() # # !!! NOTE: Now you can set connection parameters from command line! # #Create ssl server #conn.connect_serial('COM1', 57600, timeout=2 ); req_unsolicited = conn.connect() if req_unsolicited: #Receive unsolicited status, buf, uns = conn.receive() if status != 0x9000: log.logerr('Unsolicited fail') exit(-1) log.log('Unsolicited', TLVParser(buf)) #Send INIT contactless conn.send([0xc0, 0x01, 0x00, 0x00]) status, buf, uns = conn.receive() if status != 0x9000: log.logerr('ctls init fail') exit(-1) ##################################################### # Get handle conn.send([0xc0, 0xf8, 0x01, 0x00]) status, buf, uns = conn.receive() if status != 0x9000: log.logerr('Get handle fail', hex(status), buf) exit(-1) tlv = TLVParser(buf) cicappHandle = tlv.getTag((0xdf, 0xc0, 0x01), TLVParser.CONVERT_INT)[0] log.log('Handle=', hex(cicappHandle)) ##################################################### # Force proxy mode log.log('Force MAPP ctls proxy mode') conn.send([0xc0, 0xf8, 0x02, 0x01]) status, buf, uns = conn.receive() if status != 0x9000: log.logerr('Control proxy mode fail', hex(status), buf) exit(-1) ##################################################### # Send 'StartTxn' with MIFARE poll log.log('Sending StartTxn with MIFARE polling on') innerTags = [[(0x9F, 0x02), b'\x00\x00\x00\x00\x04\x56'], [(0x9C), b'\x00'], [(0x5F, 0x2A), b'\x08\x26'], [(0x9F, 0x1A), b'\x08\x26']] passThruCtlTags = [ [(0xdf, 0xc0, 0x01), [cicappHandle]], [(0xdf, 0x1f), [0x05]], # POS timeout [(0xdf, 0xc0, 0x30), Tags2Array(innerTags)], # Transaction data [(0xdf, 0xc0, 0x31), [0x01]], # Transaction result request [(0xdf, 0xc0, 0x3d), [0x01]] # TransactionSelectionMask: PollForMIFARE ] # 203 = StartTransaction SendPassThruPacket(conn, 203, passThruCtlTags) status, buf, uns = conn.receive() if status != 0x9000: log.logerr('Send pass-thru fail', hex(status), buf) exit(-1) log.log("Waiting for card tap") # Wait for unsolicited message transactionOutcome = -1 while True: status, buf, uns = conn.receive() if status != 0x9000: log.logerr('Wait for card fail!') exit(-1) # Check the buffer for transaction outcome log.log('type(buf)=', type(buf)) log.log('buf=', buf) tlv = TLVParser(buf) print('tlv=', tlv) rawCICAPPFrame = tlv.getTag((0xdf, 0xc0, 0x59)) if len(rawCICAPPFrame) == 0: log.logerr('Unexpected frame received') else: # FULL CICAPP frame received frameData = rawCICAPPFrame[0] cmdCode = frameData.pop(0) log.log('Received response for command', hex(cmdCode), "=", cmdCode) tlv = TLVParser(Array2Tags(frameData)) print('tlv=', tlv) transactionOutcome = tlv.getTag((0xdf, 0xc0, 0x36), TLVParser.CONVERT_INT) if (len(transactionOutcome) > 0): transactionOutcome = transactionOutcome[0] log.log('TransactionOutcome=', transactionOutcome) break resultCode = tlv.getTag((0xdf, 0x30), TLVParser.CONVERT_INT) print('resultCodeLen=', len(resultCode)) if (len(resultCode) > 0): resultCode = resultCode[0] log.log('resultCode=', resultCode) if resultCode != 250: break # TransactionOutcome::SwitchedToPassThru=50 if transactionOutcome == 50: # Pass thru card - display serial number and type cardType = tlv.getTag((0xdf, 0xc0, 0x41), TLVParser.CONVERT_INT) if (len(cardType)): cardType = cardType[0] cardSerial = tlv.getTag((0xdf, 0xc0, 0x42), TLVParser.CONVERT_HEX_STR) if (len(cardSerial)): cardSerial = cardSerial[0] log.log('cardType=', cardType, ' cardSerial=', cardSerial) ##################################################### # Send 'PassThruDisable' log.log('Disabling pass-thru') passThruCtlTags = [ [(0xdf, 0xc0, 0x01), [cicappHandle]], [(0xdf, 0x1f), [0x30]], # POS timeout [(0xdf, 0xc0, 0x40), [0x00]] ] SendPassThruPacket(conn, 220, passThruCtlTags) status, buf, uns = conn.receive() if status != 0x9000: log.logerr('Send pass-thru fail', hex(status), buf) exit(-1)
def Authenticate(): termDevCert = os.path.join(CERT_DIR, "terminal_device_cert.enc") termDevCertDecoded = os.path.join(CERT_DIR, "terminal_device_cert.dec") posRandomFile = os.path.join(CERT_DIR, "pos.rnd") posDIDFile = os.path.join(CERT_DIR, "pos.did") termRandomFile = os.path.join(CERT_DIR, "term.rnd") termDIDFile = os.path.join(CERT_DIR, "term.did") termSEKFile = os.path.join(CERT_DIR, "term_sek.enc") termSEKFormattedDecodedFile = os.path.join(CERT_DIR, "term_sek_formatted.dec") termSEKDecodedFile = os.path.join(CERT_DIR, "term_sek.dec") posRandom = [0x12, 0x34, 0x56, 0x78, 0x12, 0x34, 0x56, 0x78] posDID = [0x98, 0x76, 0x54, 0x32, 0x10, 0x98, 0x76, 0x54, 0x32, 0x10] posCertContent = "" if os.path.isfile(POSCert): log.loginfo("Using POSCert") with open(POSCert, 'r') as f: posCertContent = f.read() ''' Send data ''' c_tag = tagStorage() c_tag.store((0xDF, 0x83, 0x13), posRandom) c_tag.store((0xDF, 0x83, 0x1A), posDID) if posCertContent: c_tag.store((0xDF, 0x83, 0x11), posCertContent) c_tag.store((0xDF, 0x83, 0x12), os.path.basename(POSCert)) conn.send([0xDD, 0x21, 0x00, 0x00], c_tag.getTemplate(0xE0)) status, buf, uns = conn.receive() util.check_status_error(status) tlv = TLVParser(buf) if (tlv.tagCount((0xDF, 0x83, 0x14)) == 1 and tlv.tagCount( (0xDF, 0x83, 0x1D)) == 1): encryptedDevCert = tlv.getTag((0xDF, 0x83, 0x14))[0] log.log("Signed Device certificate: ", hexlify(encryptedDevCert)) clearRND = tlv.getTag((0xDF, 0x83, 0x1D))[0] log.log("Clear random number: ", hexlify(clearRND)) log.log("Saving terminal device certificate: " + termDevCert) fTermDC = open(termDevCert, 'wb') fTermDC.write(encryptedDevCert) fTermDC.close() log.log("Saving POS random") fposRND = open(posRandomFile, 'wb') fposRND.write(bytearray(i for i in posRandom)) fposRND.close() log.log("Saving POS DID") fposDID = open(posDIDFile, 'wb') fposDID.write(bytearray(i for i in posDID)) fposDID.close() log.log("Decoding terminal device certificate") os.system("openssl rsautl -verify -raw -inkey " + TermPub + " -pubin -in " + termDevCert + " -out " + termDevCertDecoded) if os.path.isfile(termDevCertDecoded): with open(termDevCertDecoded, "rb") as f: byte = f.read(2) log.log("byte start: ", hexlify(byte)) byte = f.read(1) log.log("byte 3: ", byte) while byte == b'\xff': byte = f.read(1) log.log("byte last: ", hexlify(byte)) clearRNDRemote = f.read(8) RNDOwn = f.read(8) DIDOwn = f.read(10) DIDRemote = f.read(10) log.log("Clear random number REMOTE: ", hexlify(clearRNDRemote)) if clearRND == clearRNDRemote: log.log("Random is validated") log.log("Saving term random") ftermRND = open(termRandomFile, 'wb') ftermRND.write(clearRNDRemote) ftermRND.close() log.log("Saving term DID") ftermDID = open(termDIDFile, 'wb') ftermDID.write(DIDRemote) ftermDID.close() else: log.log("Random is NOT validated") if (tlv.tagCount((0xDF, 0x83, 0x15)) == 1): encStreamEncKey = tlv.getTag((0xDF, 0x83, 0x15))[0] log.log("Saving terminal stream encryption key") fTermSEK = open(termSEKFile, 'wb') fTermSEK.write(encStreamEncKey) fTermSEK.close() log.log("Decoding terminal stream encryption key") opensslcmd = "openssl rsautl -sign -raw -inkey " + POSKey + " -in " + termSEKFile + " -out " + termSEKFormattedDecodedFile os.system(opensslcmd) if os.path.isfile(termSEKFormattedDecodedFile): log.log("Terminal SEK is decoded") with open(termSEKFormattedDecodedFile, "rb") as f: byte = f.read(2) log.log("byte start: ", hexlify(byte)) byte = f.read(1) log.log("byte 3: ", byte) while byte == b'\xff': byte = f.read(1) log.log("byte last: ", hexlify(byte)) decStreamEncKey = f.read(16) log.log("Clear terminal SEK: ", hexlify(decStreamEncKey)) log.log("Saving clear terminal stream encryption key") fTermSEK = open(termSEKDecodedFile, 'wb') fTermSEK.write(decStreamEncKey) fTermSEK.close()
def processTransaction(): req_unsolicited = conn.connect() if req_unsolicited: #Receive unsolicited log.log('Waiting for unsolicited') #status, buf, uns = getAnswer(False) #log.log('Unsolicited', TLVParser(buf) ) #Send reset device conn.send([0xD0, 0x00, 0x00, 0x01]) status, buf, uns = getAnswer() tlv = TLVParser(buf) tid = tlv.getTag((0x9F, 0x1e)) if len(tid): tid = str(tid[0], 'iso8859-1') log.log('Terminal TID: ', tid) else: tid = '' log.logerr('Invalid TID (or cannot determine TID)!') #Send clear display conn.send([0xD2, 0x01, 0x01, 0x01]) status, buf, uns = getAnswer() #Monitor card and keyboard status conn.send([0xD0, 0x60, 0x1D, 0x03]) status, buf, uns = getAnswer(False) cardState = EMV_CARD_REMOVED if uns: # Check for insertion unsolicited message tlv = TLVParser(buf) if tlv.tagCount(0x48): cardState = EMVCardState(tlv) NAD_PINPAD = 2 NAD_TERMINAL = 1 ctls_nad = NAD_PINPAD ctls = initContactless(ctls_nad) if cardState == EMV_CARD_INSERTED: log.logerr( "Card inserted, please remove since this test is a CTLS one") return if not ctls: log.logerr("No CTLS device found, stopping test") return # Start Contactless transaction selectedAID = None result = startCTLSTranAndWaitUnsolicited(selectedAID, tid) labels = None if result.tagCount(0x6F): labels = getApplLabel(result.getTag(0x6F)) if labels == None or len(labels) == 0: log.logerr("No applications to choose received") else: log.log("Labels to choose are: ", labels) selectedAID = chooseOneFromAIDList(labels) if selectedAID == None: log.logerr("None AID is selected") return result = startCTLSTranAndWaitUnsolicited(selectedAID, tid) print(result) #Reset display - regardless of tx type conn.send([0xD2, 0x01, 0x01, 0x01]) log.log('*** RESET DISPLAY ***') status, buf, uns = getAnswer()
def transtest_function(): log = getSyslog() conn = connection.Connection() # # !!! NOTE: Now you can set connection parameters from command line! # #Create ssl server #conn.connect_serial('COM1', 57600, timeout=2 ); req_unsolicited = conn.connect() if req_unsolicited: #Receive unsolicited status, buf, uns = conn.receive() if status != 0x9000: log.logerr('Unsolicited fail') exit(-1) log.log('Unsolicited', TLVParser(buf)) #Send INIT contactless conn.send([0xc0, 0x01, 0x00, 0x00]) status, buf, uns = conn.receive() if status != 0x9000: log.logerr('ctls init fail') exit(-1) ##################################################### # Get handle conn.send([0xc0, 0xf8, 0x01, 0x00]) status, buf, uns = conn.receive() if status != 0x9000: log.logerr('Get handle fail', hex(status), buf) exit(-1) tlv = TLVParser(buf) cicappHandle = tlv.getTag((0xdf, 0xc0, 0x01), TLVParser.CONVERT_INT)[0] log.log('Handle=', hex(cicappHandle)) ##################################################### # Force proxy mode conn.send([0xc0, 0xf8, 0x02, 0x01]) status, buf, uns = conn.receive() if status != 0x9000: log.logerr('Control proxy mode fail', hex(status), buf) exit(-1) ##################################################### # Send 'PassThruEnable' passThruCtlTags = [ [(0xdf, 0xc0, 0x01), [cicappHandle]], [(0xdf, 0x1f), [0x30]], # POS timeout [(0xdf, 0xc0, 0x40), [0x01]] ] SendPassThruPacket(conn, 220, passThruCtlTags) status, buf, uns = conn.receive() if status != 0x9000: log.logerr('Send pass-thru fail', hex(status), buf) exit(-1) ##################################################### # Send 'ControlUI' log.log('Enable LEDs') controlUI = [ [(0xdf, 0xc0, 0x01), [cicappHandle]], [(0xdf, 0x1f), [0x30]], # POS timeout [(0xdf, 0xc0, 0x18), [0xff]], # All LED's on [(0xdf, 0x0c), [0x01]] # Buzzer - success/single beep ] # 222=ControlUI SendPassThruPacket(conn, 222, controlUI) status, buf, uns = conn.receive() if status != 0x9000: log.logerr('Send pass-thru fail', hex(status), buf) exit(-1) time.sleep(1) ##################################################### # Send 'ControlUI' log.log('Change LEDs') controlUI = [ [(0xdf, 0xc0, 0x01), [cicappHandle]], [(0xdf, 0x1f), [0x30]], # POS timeout [(0xdf, 0xc0, 0x18), [0x04]] # 3rd LED on ] # 222=ControlUI SendPassThruPacket(conn, 222, controlUI) status, buf, uns = conn.receive() if status != 0x9000: log.logerr('Send pass-thru fail', hex(status), buf) exit(-1) time.sleep(1) ##################################################### # Send 'ControlUI' log.log('Change LEDs') controlUI = [ [(0xdf, 0xc0, 0x01), [cicappHandle]], [(0xdf, 0x1f), [0x30]], # POS timeout [(0xdf, 0xc0, 0x18), [0x0a]], # 2nd & 4th LED on [(0xdf, 0x0c), [0x02]] # Buzzer - error/double beep ] # 222=ControlUI SendPassThruPacket(conn, 222, controlUI) status, buf, uns = conn.receive() if status != 0x9000: log.logerr('Send pass-thru fail', hex(status), buf) exit(-1) time.sleep(1) ##################################################### # Send 'ControlUI' log.log('Disable LEDs') controlUI = [ [(0xdf, 0xc0, 0x01), [cicappHandle]], [(0xdf, 0x1f), [0x30]], # POS timeout [(0xdf, 0xc0, 0x18), [0x00]] # All LED's off ] # 222=ControlUI SendPassThruPacket(conn, 222, controlUI) status, buf, uns = conn.receive() if status != 0x9000: log.logerr('Send pass-thru fail', hex(status), buf) exit(-1)
def process_tx(): # This just processes Start EMV transaction and executes Verify PIN afterwards! # Check if card is inserted conn.send([0xD0, 0x60, 0x00, 0x00]) status, buf, uns = conn.receive() if status != 0x9000: log.logerr("Error checking for card presence!") return -1 tlv = TLVParser(buf) if tlv.tagCount(0x48): ins_tag_val = tlv.getTag(0x48, TLVParser.CONVERT_INT)[0] ins_tag_val &= 0xFF00 ins_tag_val >>= 8 if ins_tag_val != 3: log.logerr("EMV card is NOT inserted!") return -2 # Carry on date = strftime( "%y%m%d" ) time = strftime( "%H%M%S" ) tags = tagStorage() tags.store( (0x9F, 0x02), b'\x00\x00\x00\x00\x50\x00' ) tags.store( (0x9A), bytearray.fromhex(date) ) tags.store( (0x9F, 0x21), bytearray.fromhex(time) ) tags.store( (0x9A), b'\x00' ) tags.store( (0x9C), b'\x00' ) tags.store( (0x9F,0x41), b'\x00\x01' ) tags.store( (0x5F,0x2A), b'\x08\x26' ) tags.store( (0xDF,0xA2,0x18), b'\x01' ) tags.store( (0xDF,0xA2,0x14), b'\x01' ) tags.store( (0xDF,0xA2,0x04), b'\x01' ) #Start transaction conn.send([0xDE, 0xD1, 0x00, 0x00], tags.getTemplate(0xE0)) while True: #sleep(1) #conn.send([0xD0, 0xFF, 0x00, 0x00]) status, buf, uns = conn.receive() if status != 0x9000: if status == 0x9F28: log.logerr("Unsupported card!") else: log.logerr("Transaction terminated with status ", hex(status)) return -3 else: break # Ok, start tx processed. Get PIN, encrypt it, verify it while True: c_pin = input("Enter PIN: ") if len(c_pin) < 4 or len(c_pin) > 12: log.logerr("Invalid PIN length ", len(c_pin)) return -4 global session_key if get_session_key(0) <= 0: log.logerr("Cannot generate session key for PIN!") return -5 enc_pin = gvrsim.encrypt_pin( bytes(session_key), c_pin ) if len(enc_pin) == 0: log.logerr("Cannot encrypt PIN!") # Provide this to VIPA tags.clear() tags.store( (0xDF, 0xED, 0x6C), enc_pin ); conn.send([0xDE, 0xD8, 0x01, 0x00], tags.getTemplate(0xE0)) while True: status, buf, uns = conn.receive_raw() if uns: log.log("Unsolicited stuff, ignoring") else: break if status != 0x9000: log.logerr("This should NEVER happen!") return -6 if len(buf) == 3: from struct import unpack pres = buf[0] card_status = unpack("!H",buf[1:3])[0] log.log("Result ", hex(pres), ", card SW1SW2 ", hex(card_status)) if pres == 0x00: log.logerr("Unknown error, should never happen!") return -100 elif pres == 0x01: log.logerr("PIN failed, card might be blocked!") return -101 elif pres == 0x02: log.log("PIN okay!") break elif pres == 0x03: log.logerr("Error during Get Challenge!") # Retry here? elif pres == 0x05: log.logerr("Invalid card!") return -102 elif pres == 0x06: log.logerr("Incorrect PIN entered") # Retry for sure else: log.logerr("Invalid response length ", len(buf)) return -7 return 1
def transactionExample(): tid, status, buf, uns = resetDevice( ) #reset device and retrieve Terminal ID for VSP usage result, status, buf, uns = openAndInitialiseContactless( ) #initialise contactless reader result, status, buf, uns = cardStatus( ) #start monitoring for card movements ctlsDeviceFound, status, buf, uns = contactlessStatus( P1=0x00) #Check Contactless reader ready if not ctlsDeviceFound: displayCommand( P1=0x0D) #No contactless reader available, prompt for card else: result, status, buf, uns = startContactlessTransaction( ) #Else, enable for contactless transaction log.log('waiting for card movement Tap/Insert/Swipe') #At this point we are either getting a Contactless or an Insert/Swipe while True: status, buf, uns = getAnswer(False) #Don't ignore unsolicited if not uns: log.logerr('unexpected solicited message received ', buf) return -1, status, buf, uns tlv = TLVParser(buf) if tlv.tagCount( 0x48 ): #Card Insertion Detected, proceed with ICC or Magswipe handling emvStatus = emvCardState(tlv) magStatus = magstripeCardState(tlv) #First stop contactless if it was started if ctlsDeviceFound and (emvStatus == EMV_CARD_INSERTED or magStatus == MAGSTRIPE_TRACKS_AVAILABLE): result, status, buf, uns = cancelContactlessTransaction() #ICC Card Handling if emvStatus == EMV_CARD_INSERTED: log.log("Card inserted, process EMV transaction") result, status, buf, uns = startTransaction() #putData result, status, buf, uns = putData('\x00\x00\x00\x00\x10\x70', 0x9f, 0x02) #getData result, status, buf, uns = getData(0x9F, 0x02) #VSP handling tlvEMV = TLVParser(buf) if vspIsEncrypted(tlvEMV): vspDecrypt(tlvEMV, tid) #continue transaction if result == MAGSWIPE_FALLBACK: result, status, buf, uns = awaitCardRemoval() displayCommandString('Please Try MagStipe') continue #Card movement should generate another unsolicited message result, status, buf, uns = continueTransaction() if result == ONLINE_REQUESTED: displayCommand(0x05) result, status, buf, uns = continueTransaction( CONTINUE2_TRANS_TAG) log.log('Prompt for ICC card removal') awaitCardRemoval() return result, status, buf, uns elif emvStatus == EMV_CARD_REMOVED and magStatus != MAGSTRIPE_TRACKS_AVAILABLE: log.log('Unexpected ICC card removal') return -1, status, buf, uns else: pass # fall through #MagSwipe card handling, if ICC not found if magStatus == MAGSTRIPE_TRACKS_AVAILABLE: log.log("Card swiped, process MagStripe transaction") #VSP handling if vspIsEncrypted(tlv): vspDecrypt(tlv, tid) #continue transaction return 0, status, buf, uns elif emvStatus == ERROR_UNKNOWN_CARD or magStatus == ERROR_UNKNOWN_CARD: log.log('Unknown card type') return -1, status, buf, uns else: log.logerr('card state undefined') return -1, status, buf, uns else: # Contactless transaction if tlv.tagCount(0xE3): log.log('transaction approved') return TRANSACTION_APPROVED, status, buf, uns if tlv.tagCount(0xE4): log.log('online request, transaction must be verified online') result, status, buf, uns = continueContactlessTransaction() tlv = TLVParser(buf) if tlv.tagCount(0xE3): log.log('transaction approved') return TRANSACTION_APPROVED, status, buf, uns if tlv.tagCount(0xE5): log.log('transaction declined') return TRANSACTION_DECLINED, status, buf, uns log.log('Online requested, unexpected result not clear') return result, status, buf, uns if tlv.tagCount(0xE5): log.log('transaction declined') return TRANSACTION_DECLINED, status, buf, uns if tlv.tagCount(0xE7): log.log('Contactless MagStripe card was tapped') return CONTACTLESS_MAGSTRIPE_TAP, status, buf, uns log.logerr('no appropriate template received in response Data') return -1, status, buf, uns