def LoadHMACKeys(): req_unsolicited = conn.connect() if req_unsolicited: status, buf, uns = conn.receive() check_status_error(status) log.log("Loading the HMAC keys: host_id 6 and 7 - ver 2") hmackey06 = b'\xFE\xDC\xBA\x98\x76\x54\x32\x10\x01\x23\x45\x67\x89\xAB\xCD\xEF' hmackey06 += b'\xFE\xDC\xBA\x98\x76\x54\x32\x10\x01\x23\x45\x67\x89\xAB\xCD\xEF' hmackey06 += b'\xFE\xDC\xBA\x98\x76\x54\x32\x10\x01\x23\x45\x67\x89\xAB\xCD\xEF' hmackey06 += b'\xFE\xDC\xBA\x98\x76\x54\x32\x10\x01\x23\x45\x67\x89\xAB\xCD\xEF' log.log("HMAC key 06:", hexlify(hmackey06).decode('utf-8')) hmackey07 = b'\x01\x23\x45\x67\x89\xAB\xCD\xEF\xFE\xDC\xBA\x98\x76\x54\x32\x10' hmackey07 += b'\x01\x23\x45\x67\x89\xAB\xCD\xEF\xFE\xDC\xBA\x98\x76\x54\x32\x10' hmackey07 += b'\x01\x23\x45\x67\x89\xAB\xCD\xEF\xFE\xDC\xBA\x98\x76\x54\x32\x10' hmackey07 += b'\x01\x23\x45\x67\x89\xAB\xCD\xEF\xFE\xDC\xBA\x98\x76\x54\x32\x10' log.log("HMAC key 07:", hexlify(hmackey07).decode('utf-8')) c_tag = tagStorage() c_tag.store((0xDF, 0xEC, 0x46), 0x03) c_tag.store((0xDF, 0xEC, 0x2E), hmackey06) conn.send([0xC4, 0x0A, 0x06, 0x01], c_tag.getTemplate(0xE0)) status, buf, uns = conn.receive() log.log("Received key 06 update status") check_status_error(status) c_tag = tagStorage() c_tag.store((0xDF, 0xEC, 0x46), 0x03) c_tag.store((0xDF, 0xEC, 0x2E), hmackey07) conn.send([0xC4, 0x0A, 0x07, 0x01], c_tag.getTemplate(0xE0)) status, buf, uns = conn.receive() log.log("Received key 07 update status") check_status_error(status)
def demo_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(3) check_status_error( status ) ''' Store the tags for numeric entry ''' c_tag = tagStorage() c_tag.store( (0xDF, 0xA2, 0x06), [0x00, 0x0D, 0x00, 0x57, 0x00, 0x00] ) c_tag.store( (0xDF, 0xA2, 0x07), [0x30, 0x00] ) c_tag.store( (0xDF, 0xA2, 0x08), b'123' ) ''' Send the message ''' conn.send( [0xD2, 0x04, 0x00, 0x01], c_tag.getTemplate( 0xE0 ) ) ''' Receive and check ''' status, buf, uns = conn.receive(30) check_status_error( status ) '''print the buffer example ''' '''print(buf) ''' tlv = TLVParser(buf) user_input = tlv.getTag((0xDF, 0xA2, 0x08)) log.log('User enter [', str(user_input[0], 'iso8859-1'), ']')
def request_choice_on_pinpad_demo(): ''' 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.setnad(2) conn.send([0xD2, 0x01, 0x01, 0x00]) status, buf, uns = conn.receive() check_status_error(status) ''' Send data ''' c_tag = tagStorage() c_tag.store((0xDF, 0xA2, 0x12), LIST_STYLE_SCROLL) #BUG: Unable to push the direct string not bytearray c_tag.store((0xDF, 0xA2, 0x11), 'Optional title') for i in range(1, 6): c_tag.store((0xDF, 0xA2, 0x02), i) c_tag.store((0xDF, 0xA2, 0x03), 'Item %d' % i) conn.send([0xD2, 0x03, 0x00, 0x01], c_tag.get()) is_unsolicited = True while is_unsolicited: # unsolicited responses come when echo mode is on status, buf, is_unsolicited = conn.receive() check_status_error(status) sleep(3)
def execute_script(filename): global __SCRIPT_ROOT __SCRIPT_ROOT = os.path.dirname(os.path.abspath(filename)) th_ast_parser = __create_ast_th_language_syntax() ast = th_ast_parser.parseFile(filename, True) log = getSyslog() conn = connection.Connection() req_unsolicited = conn.connect() abort_sw1sw2 = True pool = tagStorage() localtempl = {} if req_unsolicited: #Receive unsolicited status, buf, uns = conn.receive() if status != 0x9000: raise exc.invResponseException('Unsolicited message fail', status) log.log('Unsolicited', TLVParser(buf)) for toks in ast: if toks[0] == 'setnad': conn.setnad(toks[1]) log.loginfo('Set NAD to', toks[1]) elif toks[0] == '#': log.loginfo("Comment:", str(toks[1]).strip()) elif toks[0] == 'setdevice': log.loginfo('Set device to', toks[1]) elif toks[0] == 'flush': log.loginfo('Flush comms') elif toks[0] == 'clearlocalpool': pool.clear() localtempl.clear() log.loginfo('Clear local pool') elif toks[0] == 'pause': log.loginfo('Pause for', toks[1], 'sec') time.sleep(toks[1]) elif toks[0] == 'send': __send_command(toks, conn, pool, localtempl, log) elif toks[0] == 'abortsw1sw2': abort_sw1sw2 = toks[1] log.loginfo('Abort SW1SW2 =', abort_sw1sw2) elif toks[0] == 'wait': __wait_command(toks, conn, log, abort_sw1sw2) elif toks[0] == 'prompt': log.loginfo('Prompt message:', str(" ").join(toks[1].asList())) __wait_command(toks, conn, log, abort_sw1sw2) elif toks[0] == 'storelocaltag': pool = __storetag_command(toks, pool) elif toks[0] == 'appendlocal': tpl, data = __appendlocal_command(toks, pool) localtempl[tpl] = data elif toks[0] == 'senddirect': __senddirect_command(toks, conn, log) elif toks[0] == 'putfile': __putfile_command(toks, conn, log) elif toks[0] == 'updatefile': __updatefile_command(toks, conn, log) elif toks[0] == 'getfile': __getfile_command(toks, conn, log) else: log.logerr('Unknown tokens', str(toks)) raise exc.logicalException('Unknown tokens in script')
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 OnlinePIN(): ''' First create connection ''' req_unsolicited = conn.connect() ''' If unsolicited read it''' #status, buf, uns = conn.receive() #check_status_error( status ) ''' Send data ''' pan = b'\x54\x13\x33\x00\x89\x00\x00\x39' c_tag = tagStorage() #BUG: Unable to push the direct string not bytearray c_tag.store( (0xDF, 0xEC, 0x05), 0x00 ) c_tag.store( (0xDF, 0xED, 0x05), 0x08 ) c_tag.store( (0xDF, 0x17), '\x00\x00\x00\x00\x01\x51' ) c_tag.store( (0xDF, 0x24), '\x08\x26' ) c_tag.store( (0xDF, 0x1C,), 0x02 ) c_tag.store( (0x5A), pan ) conn.send([0xDE, 0xD6, 0x03, 0x00] , c_tag.getTemplate(0xE0)) sleep(3) conn.send([0xD0, 0x00, 0x00, 0x32]) status, buf, uns = conn.receive() check_status_error( status ) # Wait for last package status, buf, uns = conn.receive() slog = getSyslog() if status == 0x9F41: slog.loginfo('Status is "Cancelled amount" as expected:', hex(status)) else: slog.logerr('Status is not "Cancelled amount"', hex(status), buf) sys.exit(-1)
def processCtlsMiFare(): # Set LEDs leds_tag = [ [(0xDF, 0xDF, 0x0C), [0x01]], # Success - single beep (0x02 = Error - Double beep) [(0xDF, 0xC0, 0x18), [0xff] ] # All LEDs on (0A would enable 2nd and 4th LED, it's 1010 binary) ] leds_template = (0xE0, leds_tag) conn.send([0xC0, 0x10, 0x00, 0x00], leds_template) status, buf, uns = getAnswer() if (status != 0x9000): log.logerr('UI function failed!') # Todo: What should we do? Let's just ignore the error and continue # Read some stuff c_read_oper = tagStorage() c_read_oper.store((0xDF, 0xA5, 0x01), [ 0x02 ]) # DFA501 - Operation type (0x02 - Read, 0x03 - Write, ,0x04 - EPurse) c_read_oper.store( (0xDF, 0xA5, 0x02), 'READ1') # DFA502 - ID so that the output can be identified c_read_oper.store((0xDF, 0xC0, 0x5A), [0x00]) # DFC05A - Sector number c_read_oper.store( (0xDF, 0xC0, 0x5B), [0x01]), # DFC05B - Key type (0x01 - Type A, 0x02 - Type B) c_read_oper.store( (0xDF, 0xC0, 0x5C), b'\xFF\xFF\xFF\xFF\xFF\xFF') # DFC05C - Valid key (6 bytes) c_read_oper.store((0xDF, 0xC0, 0x5D), [0x01]) # DFC05D - Starting block number c_read_oper.store((0xDF, 0xC0, 0x5E), [0x02]) # DFC05E - Number of blocks to read read_oper_1 = c_read_oper.getAsBytearray() c_read_oper.clear() c_read_oper.store((0xDF, 0xA5, 0x01), [ 0x02 ]) # DFA501 - Operation type (0x02 - Read, 0x03 - Write, ,0x04 - EPurse) c_read_oper.store( (0xDF, 0xA5, 0x02), 'READ2') # DFA502 - ID so that the output can be identified c_read_oper.store((0xDF, 0xC0, 0x5A), [0x03]) # DFC05A - Sector number c_read_oper.store( (0xDF, 0xC0, 0x5B), [0x01]) # DFC05B - Key type (0x00 - Type A, 0x01 - Type B) c_read_oper.store( (0xDF, 0xC0, 0x5C), b'\xFF\xFF\xFF\xFF\xFF\xFF') # DFC05C - Valid key (6 bytes) c_read_oper.store((0xDF, 0xC0, 0x5D), [0x02]) # DFC05D - Starting block number c_read_oper.store((0xDF, 0xC0, 0x5E), [0x02]) # DFC05E - Number of blocks to read read_oper_2 = c_read_oper.getAsBytearray() c_read_oper.clear() c_read_oper.store((0xDF, 0xC0, 0x30), read_oper_1) #c_read_oper.store((0xDF, 0xC0, 0x30), read_oper_2) conn.send([0xC0, 0xA1, 0x00, 0x00], c_read_oper.getTemplate(0xE0)) status, buf, uns = getAnswer()
def store_certificate(filename, level): put_file(filename) c_tag = tagStorage() c_tag.store( (0xDF, 0x83, 0x12), os.path.basename(filename).lower() ) c_tag.store( (0xDF, 0x83, 0x10), level ) conn.send([0xC5, 0x07, 0x00, 0x00], c_tag.getTemplate(0xE0)) status, buf, uns = conn.receive() return status == 0x9000
def __appendlocal_command(toks, pool): newpool = tagStorage() newpool.clear() tplvalue = toks[1][0] for t in toks[2]: fdata = pool.getTagData(tuple(t)) newpool.store(t, fdata) return tplvalue, newpool.getTemplate(tplvalue)
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 update_key_command(conn, host_id, pvk_enc): log.log("Updating the PVK using Master session key, host_id is", host_id) #pvk_enc=b'\x65\xF3\x8A\xFD\x1B\x85\xDB\xB6\xCB\xFC\xD9\xCD\xD1\x46\xAC' c_tag = tagStorage() c_tag.store((0xDF, 0xEC, 0x46), 0x01) c_tag.store((0xDF, 0xEC, 0x2E), pvk_enc) conn.send([0xC4, 0x0A, host_id, 0x01], c_tag.getTemplate(0xE0)) status, buf, uns = conn.receive() log.log("Received key update status") check_status_error(status)
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 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 put_data_sample(): ''' 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) ''' Send data ''' c_tag = tagStorage() #BUG: Unable to push the direct string not bytearray c_tag.store((0xE0), [0xDF, 0xA2, 0x0F]) conn.send([0x00, 0xDA, 0xFF, 0xFF], c_tag.get()) status, buf, uns = conn.receive() check_status_error(status)
def demo_function(): ''' First create connection ''' req_unsolicited = conn.connect() ''' If unsolicited read it''' if req_unsolicited: status, buf, uns = conn.receive() check_status_error(status) ''' Store the tags for numeric entry ''' c_tag = tagStorage() #index or text, one mandatory # index #c_tag.store( (0xDF, 0xA2, 0x06), [0x00, 0x0D] ) # enter card pan #c_tag.store( (0xDF, 0xA2, 0x06), [0x00, 0x57] ) # press enter # text c_tag.store((0xDF, 0xA2, 0x13), [0x41, 0x42, 0x43, 0x44]) #c_tag.store( (0xDF, 0xA2, 0x13), [0x41, 0x42, 0x43, 0x44, 0x46, 0x47, 0x48, 0x49] ) #c_tag.store( (0xDF, 0xA2, 0x13), [0x41, 0x42, 0x43, 0x44, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x41] ) # max len c_tag.store((0xDF, 0x83, 0x05), [0x0A]) ''' Send the message ''' NAD_PINPAD = 2 conn.setnad(NAD_PINPAD) conn.send([0xD2, 0xF1, 0x00, 0x00], c_tag.getTemplate(0xE0)) #''' abort ''' #time.sleep(7) #conn.send([0xD0, 0xFF, 0x00, 0x00]) #time.sleep(5) #status, buf, uns = conn.receive(3) #check_status_error( status ) #return ''' Receive and check ''' status, buf, uns = conn.receive(30) check_status_error(status) '''print the buffer example ''' '''print(buf) ''' tlv = TLVParser(buf) user_input = tlv.getTag((0xDF, 0x83, 0x01)) log.log('User enter [', str(user_input[0], 'iso8859-1'), ']')
def transmit_password(set_new_key, password_no): # Get ARS password and encrypt them ars = get_ars_password() if len(ars) == 0: log.logerr("ARS password not entered!") return -2 c_tag = tagStorage() if (password_no == 1): c_tag.store( (0xDF, 0xEC, 0x2E), ars ) else: c_tag.store( (0xDF, 0xEC, 0x2F), ars ) INS = 0x01 if set_new_key: INS = 0x02 conn.send([0xC5, INS, 0x00, 0x00], c_tag.getTemplate(0xE0)) status, buf, uns = conn.receive() if status != 0x9000: log.logerr("Cannot verify ARS password(s)!") return -3 if set_new_key: log.log("ARS password set correctly") else: log.log("ARS password verified correctly") return 1
def updatefile(conn, log, fn, remote_fn=None, signature=False, progress=None): if not os.path.isfile(fn): raise exc.logicalException('File ' + fn + ' doesnt exist!') from struct import pack if remote_fn == None: remote_fn = os.path.basename(fn) log.log('Uploading file ', fn, ' as ', remote_fn) fileSize = os.path.getsize(fn) size = hex(fileSize)[2:] while len(size) < 8: size = '0' + size log.log('size ', size) c_tag = tagStorage() c_tag.store((0x84), remote_fn.lower()) c_tag.store((0x80), bytearray.fromhex(size)) conn.send([0x00, 0xA5, 0x05, 0x81], c_tag.getTemplate(0x6F)) status, buf, uns = conn.receive() if status != 0x9000: raise exc.invResponseException('Cannot upload file ' + fn, status) dataCnt = 0 prevPercent = -1 with open(fn, 'rb') as f: while True: readData = f.read(1024) readSize = len(readData) if (readSize == 0): break dataCnt += readSize sendData = bytearray(readData) conn.send_raw(sendData) if hasattr(progress, '__call__'): percent = round(dataCnt / fileSize, 2) if percent != prevPercent: progress(percent) prevPercent = percent log.log('Done, waiting for confirmation') # We're done, wait for response status, buf, uns = conn.receive()
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 AuthVerify(): posDevCertDecodedFile = os.path.join(CERT_DIR, "pos_device_cert.dec") posDevCertFile = os.path.join(CERT_DIR, "pos_device_cert.enc") posSEKFormattedDecodedFile = os.path.join(CERT_DIR, "pos_sek_formatted.dec") posSEKDecodedFile = os.path.join(CERT_DIR, "pos_sek.dec") termSEKDecodedFile = os.path.join(CERT_DIR, "term_sek.dec") posSEKFile = os.path.join(CERT_DIR, "pos_sek.enc") posRandomFile = os.path.join(CERT_DIR, "pos.rnd") termRandomFile = os.path.join(CERT_DIR, "term.rnd") posDIDFile = os.path.join(CERT_DIR, "pos.did") termDIDFile = os.path.join(CERT_DIR, "term.did") POSKey = os.path.join(CERT_DIR, "pos.key") terminalPub = os.path.join(CERT_DIR, "ped.pub") mutualSEKFile = os.path.join(CERT_DIR, "mutual_sek.dec") fposRND = open(posRandomFile, 'rb') posRandom = fposRND.read() fposRND.close() ftermRND = open(termRandomFile, 'rb') termRandom = ftermRND.read() ftermRND.close() fposDID = open(posDIDFile, 'rb') posDID = fposDID.read() fposDID.close() ftermDID = open(termDIDFile, 'rb') termDID = ftermDID.read() ftermDID.close() posDevCert = bytearray(b'\x00\x01') for x in range(256 - 39): posDevCert.append(255) posDevCert.append(0) posDevCert = b"".join([posDevCert, posRandom]) posDevCert = b"".join([posDevCert, termRandom]) posDevCert = b"".join([posDevCert, termDID]) posDevCert = b"".join([posDevCert, posDID]) with open(posDevCertDecodedFile, "wb") as f: f.write(posDevCert) f.close() formattedPosSEK = bytearray(b'\x00\x01') for x in range(256 - 19): formattedPosSEK.append(255) formattedPosSEK.append(0) posSEK = ''.join([random.choice('0123456789ABCDEF') for x in range(32)]) bposSEK = binascii.unhexlify(posSEK) formattedPosSEK = b"".join([formattedPosSEK, bposSEK]) with open(posSEKDecodedFile, "wb") as f: f.write(bposSEK) f.close() with open(posSEKFormattedDecodedFile, "wb") as f: f.write(formattedPosSEK) f.close() log.log("Signing POS device certificate") opensslcmd = "openssl rsautl -sign -raw -inkey " + POSKey + " -in " + posDevCertDecodedFile + " -out " + posDevCertFile os.system(opensslcmd) if os.path.isfile(posDevCertFile): log.log("POS device certificate is signed") f = open(posDevCertFile, 'rb') posDevCertEnc = f.read() f.close() log.log("Encrypting POS stream encrytion key") opensslcmd = "openssl rsautl -verify -raw -inkey " + terminalPub + " -pubin -in " + posSEKFormattedDecodedFile + " -out " + posSEKFile os.system(opensslcmd) if os.path.isfile(posSEKFile): log.log("POS stream encrytion key is encrypted") f = open(posSEKFile, 'rb') formattedPosSEKEnc = f.read() f.close() f = open(posSEKDecodedFile, 'rb') poskey = bytearray(f.read()) f.close() f = open(termSEKDecodedFile, 'rb') termkey = bytearray(f.read()) f.close() for i in range(len(poskey)): termkey[i] ^= poskey[i] f = open(mutualSEKFile, 'wb') f.write(termkey) f.close() log.log("Mutual stream encryption key is saved: ", mutualSEKFile) ''' First create connection ''' req_unsolicited = conn.connect() ''' If unsolicited read it''' if req_unsolicited: status, buf, uns = conn.receive() ''' Send data ''' c_tag = tagStorage() c_tag.store((0xDF, 0x83, 0x14), posDevCertEnc) c_tag.store((0xDF, 0x83, 0x15), formattedPosSEKEnc) conn.send([0xDD, 0x22, 0x01, 0x00], c_tag.getTemplate(0xE0)) status, buf, uns = conn.receive() check_status_error(status)
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 AuthVerify(): posDevCertDecodedFile = os.path.join(CERT_DIR, "pos_device_cert.dec") posDevCertFile = os.path.join(CERT_DIR, "pos_device_cert.enc") posSEKFormattedDecodedFile = os.path.join(CERT_DIR, "pos_sek_formatted.dec") posSEKDecodedFile = os.path.join(CERT_DIR, "pos_sek.dec") termSEKDecodedFile = os.path.join(CERT_DIR, "term_sek.dec") posSEKFile = os.path.join(CERT_DIR, "pos_sek.enc") posRandomFile = os.path.join(CERT_DIR, "pos.rnd") termRandomFile = os.path.join(CERT_DIR, "term.rnd") posDIDFile = os.path.join(CERT_DIR, "pos.did") termDIDFile = os.path.join(CERT_DIR, "term.did") mutualSEKFile = os.path.join(CERT_DIR, "mutual_sek.dec") fposRND = open(posRandomFile, 'rb') posRandom = fposRND.read() fposRND.close() ftermRND = open(termRandomFile, 'rb') termRandom = ftermRND.read() ftermRND.close() fposDID = open(posDIDFile, 'rb') posDID = fposDID.read() fposDID.close() ftermDID = open(termDIDFile, 'rb') termDID = ftermDID.read() ftermDID.close() posDevCert = bytearray(b'\x00\x01') for x in range(256 - 39): posDevCert.append(255) posDevCert.append(0) posDevCert = b"".join([posDevCert, posRandom]) posDevCert = b"".join([posDevCert, termRandom]) posDevCert = b"".join([posDevCert, termDID]) posDevCert = b"".join([posDevCert, posDID]) with open(posDevCertDecodedFile, "wb") as f: f.write(posDevCert) f.close() formattedPosSEK = bytearray(b'\x00\x01') for x in range(256 - 19): formattedPosSEK.append(255) formattedPosSEK.append(0) posSEK = ''.join([random.choice('0123456789ABCDEF') for x in range(32)]) bposSEK = unhexlify(posSEK) formattedPosSEK = b"".join([formattedPosSEK, bposSEK]) with open(posSEKDecodedFile, "wb") as f: f.write(bposSEK) f.close() with open(posSEKFormattedDecodedFile, "wb") as f: f.write(formattedPosSEK) f.close() log.log("Signing POS device certificate") opensslcmd = "openssl rsautl -sign -raw -inkey " + POSKey + " -in " + posDevCertDecodedFile + " -out " + posDevCertFile os.system(opensslcmd) if os.path.isfile(posDevCertFile): log.log("POS device certificate is signed") f = open(posDevCertFile, 'rb') posDevCertEnc = f.read() f.close() log.log("Encrypting POS stream encrytion key") log.loginfo("openssl rsautl -verify -raw -inkey " + TermPub + " -pubin -in " + posSEKFormattedDecodedFile + " -out " + posSEKFile) os.system("openssl rsautl -verify -raw -inkey " + TermPub + " -pubin -in " + posSEKFormattedDecodedFile + " -out " + posSEKFile) if os.path.isfile(posSEKFile): log.log("POS stream encrytion key is encrypted") f = open(posSEKFile, 'rb') formattedPosSEKEnc = f.read() if not len(formattedPosSEKEnc) > 0: raise (Except( "Restored random value messed up - there is nothing, check ssl command in log above for hand verification" )) f.close() f = open(posSEKDecodedFile, 'rb') poskey = bytearray(f.read()) f.close() f = open(termSEKDecodedFile, 'rb') termkey = bytearray(f.read()) f.close() for i in range(len(poskey)): termkey[i] ^= poskey[i] f = open(mutualSEKFile, 'wb') f.write(termkey) f.close() log.log("Mutual stream encryption key is saved: ", mutualSEKFile) ''' Send data ''' c_tag = tagStorage() c_tag.store((0xDF, 0x83, 0x14), posDevCertEnc) c_tag.store((0xDF, 0x83, 0x15), formattedPosSEKEnc) log.log(str(c_tag.getTemplate(0xE0))) conn.send([0xDD, 0x22, 0x01, 0x00], c_tag.getTemplate(0xE0)) status, buf, uns = conn.receive() util.check_status_error(status) log.loginfo("Success stream encryption keys auth done")
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 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 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 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!")