def configureFileVersions(): log.log('configureFileVersions') conn.send([0xD0, 0x01, 0x00, 0x00]) status, buf, uns = getAnswer() tlv = TLVParser(buf) if status == 0x9000 and not (tlv.tagCount( (0xDF, 0xDE, 0x7E)) and tlv.tagCount((0xDF, 0xDE, 0x7F))): log.logerr( 'message had a missing expected tag or tags (DFDE7E and DFDE7F)', buf) return -1, status, buf, uns return 0, status, buf, uns
def freeSpace(): log.log('freeSpace') conn.send([0x00, 0xD0, 0x00, 0x00]) status, buf, uns = getAnswer() tlv = TLVParser(buf) if status == 0x9000 and not (tlv.tagCount( (0xDF, 0xDE, 0x7E)) == 2 and tlv.tagCount((0xDF, 0xDE, 0x7F)) == 2): log.logerr( 'message had a missing expected tag or tags (DFDE7E and DFDE7F)', buf) return -1, status, buf, uns return 0, status, buf, uns
def powerOnNotification(): log.log('powerOnNotification') displayCommandString( '\x0D\x09Perform power or wifi\x0D\x0D\x09off and on\x07') #await unsolicited power on message status, buf, uns = getAnswer(ignoreUnsolicited=False) if not uns: log.logerr('unsolicited response expected only') tlv = TLVParser(buf) if status == 0x9000 and not (tlv.tagCount((0xC3)) == 1 and tlv.tagCount( (0xC4)) == 1 and tlv.tagCount((0x9F, 0x1C)) == 1): log.logerr('message had a missing expected tags (C3, C4 and 9F1C)', buf) return -1, status, buf, uns return 0, status, buf, uns
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 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 startTransaction(start_trans_tag=START_TRANS_TAG): log.log('startTransaction') start_templ = (0xE0, start_trans_tag) conn.send([0xDE, 0xD1, 0x00, 0x00], start_templ) while True: status, buf, uns = getAnswer(False) #Don't ignore unsolicited #unexpected unsolicited received if uns: log.log('Unsolicited packet detected: ignoring') if status == 0x9000: tlv = TLVParser(buf) if tlv.tagCount(0xE6) != 0: log.log('Multi application card!') continue else: log.log('unexpected unsolicited message received ', buf) continue #expected solicited received if status != 0x9000: if status == 0x9F28: return MAGSWIPE_FALLBACK, status, buf, uns else: log.logerr('Transaction terminated with status ', hex(status)) return -1, status, buf, uns return 0, status, buf, uns
def get_vfi_certificate(): certNo = 0x00000001 global ux_certificates ux_certificates.clear() while True: c_tag = tagStorage() #BUG: Unable to push the direct string not bytearray c_tag.store( (0xDF, 0x83, 0x10), int(certNo) ) conn.send([0xC5, 0x06, 0x00, 0x00] , c_tag.getTemplate(0xE0)) status, buf, uns = conn.receive() if status == 0x9000: tlv = TLVParser(buf) if tlv.tagCount( (0xDF, 0x83, 0x11) ) == 1: log.log("Success") key = tlv.getTag( (0xDF, 0x83, 0x11) )[0] log.log("Key: ", hexlify(key)) ux_certificates.append(key) certNo += 1 else: log.logerr("Failure") else: break sleep(1) #check_status_error( status ) log.log("We have ", len(ux_certificates), " UX certificates") #log.log("UX certs: ", ux_certificates) return len(ux_certificates)
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 manageDisplayContract(P1=READ_CONTRAST): log.log('manageDisplayContract') conn.send([0xD0, 0x70, P1, 0x00]) status, buf, uns = getAnswer() if P1 == READ_CONTRAST: tlv = TLVParser(buf) if status == 0x9000 and not tlv.tagCount((0xDF, 0xA2, 0x0B)) == 1: log.logerr('message had a missing expected tag (DFA20B)', buf) return -1, status, buf, uns return 0, 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 = 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 get_cert_file(): c_tag = tagStorage() c_tag.store( (0xDF, 0x83, 0x10), 0x00000000 ) conn.send([0xC5, 0x06, 0x01, 0x00], c_tag.getTemplate(0xE0)) status, buf, uns = conn.receive() if status == 0x9000: tlv = TLVParser(buf) if tlv.tagCount( (0xDF, 0x83, 0x12 ) ) == 1: fname = tlv.getTag( (0xDF, 0x83, 0x12) )[0] log.log("Cert file ", fname) else: log.logerr("Error, no cert name!") else: log.logerr("Bad response ", status)
def GenerateRSAKey(): if not os.path.exists(CERT_DIR): os.makedirs(CERT_DIR) if query_yes_no("Gen new certs?", default="no"): CreateCACertificate(conn, log) CreatePOSCertificate(log) log.loginfo( "Mutual auth cert handshake, DD 23 can take a while ( ~10sec) ") ''' 0x08 1024 in ~ 10 sec ''' ''' 0x08 2048 in ~ 1 min ''' ''' 0x10 4096 in~ 10 min ''' conn.send([0xDD, 0x23, 0x00, 0x00], (0xE0, [[(0xDF, 0x83, 0x1C), b'\x08\x00']])) status, buf, uns = conn.receive() util.check_status_error(status) tlv = TLVParser(buf) if (tlv.tagCount((0xDF, 0x83, 0x1B)) == 1): certSignReq = tlv.getTag((0xDF, 0x83, 0x1B))[0] strCSR = toascii(certSignReq) csrFile = os.path.join(CERT_DIR, "ped.csr") terminalCert = os.path.join(CERT_DIR, "ped.pem") log.log("Saving CSR") file = open(csrFile, 'w') file.write(strCSR) file.close() log.log("Signing terminal CSR + save in: ", terminalCert) os.system("openssl x509 -req -days 360 -in " + csrFile + " -CA " + CACert + " -CAkey " + CAKey + " -CAcreateserial -out " + terminalCert) ''' Retrieve public key from ped''' log.log("Extracting terminal public key from terminal certificate") os.system("openssl x509 -pubkey -noout -in " + terminalCert + " > " + TermPub) log.log("Terminal public key is extracted: " + TermPub + " sending signed terminal certificate to terminal") PutFile(conn, log, terminalCert, "ped.pem") else: log.logerror("Terminal response fialure") exit(1) log.loginfo("Key generation and upload success!")
def init_ns(): # Initialize NS crypto1 = gvrsim.initiate_ns( ux_certificates ) if len(crypto1) == 0: log.logerr("Init NS failed!") return -1 log.log("crypto1: ", hexlify(crypto1)) # Verify NS c_tag = tagStorage() c_tag.store( (0xDF, 0xEC, 0x0F), crypto1 ) conn.send([0xC5, 0x0A, 0x00, 0x00], c_tag.getTemplate(0xE0)) status, buf, uns = conn.receive() if status != 0x9000: log.logerr("Resolve NS failed!") return -2 # Check crypto2 tlv = TLVParser(buf) if tlv.tagCount( (0xDF, 0xEC, 0x7B) ) != 1: log.logerr("Crypto2 missing!") return -3 log.log("Verify NS success") crypto2 = tlv.getTag( (0xDF, 0xEC, 0x7B) )[0] log.log("Crypto2: ", hexlify(crypto2)) # Read UPM Key exp, mod = gvrsim.read_upm_pubkey() if len(mod) == 0: log.logerr("Read UPM public key failed") return -4 # Finalize NS global crypto3 crypto3 = gvrsim.finalize_ns(mod, bytes(crypto2)) if len(crypto3) == 0: log.logerr("Finalize NS failed") return -5 log.log("Crypto3: ", hexlify(crypto3)) # Verify NS c_tag.clear() c_tag.store( (0xDF, 0xEC, 0x0F), crypto3 ) conn.send([0xC5, 0x0B, 0x00, 0x00], c_tag.getTemplate(0xE0)) status, buf, uns = conn.receive() if status != 0x9000: log.logerr("Verify NS failed!") return -2 # We are done! return 1
def findFirstFile(filemask, IgnoreNoFile=False): #filename format is '*.INI' log.log('findFirstFile') conn.send([0x00, 0xC3, 0x00, 0x00], filemask) if IgnoreNoFile == True: status, buf, uns = getAnswer(True, False, True) else: status, buf, uns = getAnswer() #Stop & ErrLog if status == 0x9000: tlv = TLVParser(buf) if not (tlv.tagCount(0x84)): log.logerr('message had a missing expected tag (84)', buf) return -1, status, buf, uns elif status == 0x9F13: log.log( 'No file match found to supplied mask, not necessarily an error') else: log.logerr('Pinpad reported error ', hex(status)) performCleanup() log.logerr('*** TEST BEING HALTED ABNORMALLY ***') exit(-1) return 0, status, buf, uns
def selectLanguage(languageCode='', P1=AUTOMATIC_LANGUAGE, P2=GET_LANGUAGE_LIST): log.log('selectLanguage') if len(languageCode) == 3 and (P1 == MANUAL_LANGUAGE and P2 == USE_LANGUAGE_SUPPLIED): languageTag = [] languageTag.append([(0xDF, 0xA2, 0x22), languageCode]) conn.send([0xD2, 0xD0, P1, P2], languageTag) else: conn.send([0xD2, 0xD0, P1, P2]) status, buf, uns = getAnswer() if (P1 == MANUAL_LANGUAGE and P2 == GET_LANGUAGE_LIST ) or P1 == AUTOMATIC_LANGUAGE or P1 == GET_LANGUAGE: tlv = TLVParser(buf) if not tlv.tagCount((0xDF, 0xA2, 0x20)): log.logerr('message had a missing expected tag or tags (DFA222)', buf) return -1, status, buf, uns elif len(buf) != 0: log.logerr('message had unexpected Data content', buf) return 0, status, buf, uns
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 __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 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) 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 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
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 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 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 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 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