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
Example #5
0
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'))
Example #6
0
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
Example #11
0
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
Example #14
0
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
Example #17
0
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!")
Example #18
0
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")
Example #19
0
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
Example #20
0
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)
Example #21
0
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)
Example #23
0
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()
Example #26
0
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)
Example #28
0
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