Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- --
- -- This file is part of Cardpeek, the smartcard reader utility.
- --
- -- Copyright 2009-2013 by 'L1L1'
- --
- -- Cardpeek is free software: you can redistribute it and/or modify
- -- it under the terms of the GNU General Public License as published by
- -- the Free Software Foundation, either version 3 of the License, or
- -- (at your option) any later version.
- --
- -- Cardpeek is distributed in the hope that it will be useful,
- -- but WITHOUT ANY WARRANTY; without even the implied warranty of
- -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- -- GNU General Public License for more details.
- --
- -- You should have received a copy of the GNU General Public License
- -- along with Cardpeek. If not, see <http://www.gnu.org/licenses/>.
- --
- -- @name EMV-AMEX
- -- @description Bank cards 'PIN and chip'
- -- @targets 0.8
- --
- -- History:
- -- Aug 07 2010: Corrected bug in GPO command.
- -- Aug 08 2010: Corrected bug in AFL data processing
- -- Mar 27 2011: Added CVM patch from Adam Laurie.
- -- Jan 23 2012: Added UK Post Office Card Account in AID list from Tyson Key.
- -- Mar 25 2012: Added a few AIDs
- -- @update: Feb 21 2014: Better NFC compatibility by using current date in GPO.
- require('lib.tlv')
- require('lib.strict')
- --------------------------------------------------------------------------
- -- GLOBAL EMV CARD COMMANDS extending general lib.apdu
- --------------------------------------------------------------------------
- function build_empty_pdol_data_block(pdol)
- local data = bytes.new(8);
- local o_tag
- local o_len
- while pdol do
- o_tag, pdol = asn1.split_tag(pdol)
- o_len, pdol = asn1.split_tag(pdol)
- if o_tag==0x9F66 and o_len==4 then
- -- Terminal Transaction Qualifiers (VISA)
- data = data .. "30 00 00 00"
- elseif o_tag==0x9F1A and o_len==2 then
- -- Terminal country code
- data = data .. "0250"
- elseif o_tag==0x5F2A and o_len==2 then
- -- Transaction currency code
- data = data .. "0978"
- elseif o_tag==0x9A and o_len==3 then
- -- Transaction date
- data = data .. os.date("%y %m %d")
- elseif o_tag==0x9F37 and o_len==4 then
- -- Unpredictable number
- data = data .. "DEADBEEF"
- else
- -- When in doubt Zeroize
- while o_len > 0 do
- data = data .. 0x00
- o_len = o_len-1
- end
- end
- end
- return data
- end
- function card.get_processing_options(pdol)
- local command
- local pdol_data
- if pdol and #pdol>0 then
- pdol_data = build_empty_pdol_data_block(pdol)
- command = bytes.new(8,"80 A8 00 00",#pdol_data+2,0x83,#pdol_data,pdol_data,"00")
- else
- command = bytes.new(8,"80 A8 00 00 02 83 00 00")
- end
- return card.send(command)
- end
- -- override card.get_data() for EMV
- function card.get_data(data)
- local command = bytes.new(8,"80 CA",bit.AND(bit.SHR(data,8),0xFF),bit.AND(data,0xFF),0)
- return card.send(command)
- end
- -- ------------------------------------------------------------------------
- -- EMV
- -- ------------------------------------------------------------------------
- TRANSACTION_TYPE = {
- [0]="Purchase",
- [1]="Cash"
- }
- function ui_parse_transaction_type(node,cc)
- local tt = TRANSACTION_TYPE[cc[0]]
- if tt == nil then
- return tostring(cc)
- end
- nodes.set_attribute(node,"val",cc)
- nodes.set_attribute(node,"alt",tt)
- return true
- end
- function ui_parse_CVM(node,data)
- local i
- local left
- local right
- local leftstring
- local rightstring
- local subnode
- local out
- local data_start
- local data_end
- nodes.append(node,{ classname="item",
- label="X",
- size=4,
- val=bytes.sub(data,0,3)})
- nodes.append(node,{ classname="item",
- label="Y",
- size=4,
- val=bytes.sub(data,4,7)})
- -- Calculate data ending boundary to accommodate Amex which includes trailing zeroes
- -- that cause bogus CVM entries to appear
- data_start = 0
- data_end = 0
- for i=0, #data do
- if ( data_start == 0 and data:get(i) ~= 0 ) then
- data_start = i
- elseif ( data_end == 0 and data_start ~= 0 and data:get(i) == 0 ) then
- data_end = i
- break
- end
- end
- for i= 4,(data_end/2)-1 do
- subnode = nodes.append(node, { classname="item",
- label="CVM",
- id=i-3,
- size=2,
- val=bytes.sub(data,i*2,i*2+1)})
- left = data:get(i*2)
- right = data:get(i*2+1)
- if bit.AND(left,0x40) == 0x40 then
- out = "Apply succeeding CV rule if this rule is unsuccessful: "
- else
- out = "Fail cardholder verification if this CVM is unsuccessful: "
- end
- if CVM_REFERENCE_BYTE1[bit.AND(left,0xBF)] == nil then
- leftstring = string.format("Unknown (%02X)",left)
- else
- leftstring = CVM_REFERENCE_BYTE1[bit.AND(left,0xBF)]
- end
- if CVM_REFERENCE_BYTE2[right] == nil then
- rightstring = string.format("Unknown (%02X)",right)
- else
- rightstring = CVM_REFERENCE_BYTE2[right]
- end
- out = out .. leftstring .. " - " .. rightstring
- nodes.set_attribute(subnode,"alt",out)
- end
- nodes.set_attribute(node,"val",data)
- return true
- end
- CVM_REFERENCE_BYTE1 = {
- [0x00] = "Fail CVM processing",
- [0x01] = "Plaintext PIN verification performed by ICC",
- [0x02] = "Enciphered PIN verified online",
- [0x03] = "Plaintext PIN verification performed by ICC and signature (paper)",
- [0x04] = "Enciphered PIN verification performed by ICC",
- [0x05] = "Enciphered PIN verification performed by ICC and signature (paper)",
- [0x1E] = "Signature (paper)",
- [0x1F] = "No CVM Required",
- }
- CVM_REFERENCE_BYTE2 = {
- [0x00] = "Always",
- [0x01] = "If unattended cash",
- [0x02] = "If not attended cash and not manual cash and not purchase with cashback",
- [0x03] = "If terminal supports the CVM",
- [0x04] = "If manual cash",
- [0x05] = "If purchase with cashback",
- [0x06] = "If transaction is in the application currency and is under X value",
- [0x07] = "If transaction is in the application currency and is over X value",
- [0x08] = "If transaction is in the application currency and is under Y value",
- [0x09] = "If transaction is in the application currency and is over Y value"
- }
- EMV_REFERENCE = {
- ['5D'] = {"Directory Definition File (DDF) Name" },
- ['70'] = {"Application Data File (ADF)" },
- ['80'] = {"Response Message Template Format 1" },
- ['82'] = {"Application Interchange Profile (AIP)" },
- ['87'] = {"Application Priority Indicator" },
- ['88'] = {"Short File Identifier (SFI)" },
- ['8C'] = {"Card Risk Management Data Object List 1 (CDOL1)" },
- ['8D'] = {"Card Risk Management Data Object List 2 (CDOL2)" },
- ['8E'] = {"Cardholder Verification Method (CVM) List", ui_parse_CVM },
- ['8F'] = {"Certificate Authority Public Key Index (PKI)" },
- ['90'] = {"Issuer PK Certificate" },
- ['91'] = {"Issuer Authentication Data" },
- ['92'] = {"Issuer PK Remainder" },
- ['93'] = {"Signed Static Application Data" },
- ['94'] = {"Application File Locator (AFL)" },
- ['95'] = {"Terminal Verification Results (TVR)" },
- ['97'] = {"Transaction Certificate Data Object List (TDOL)" },
- ['9A'] = {"Transaction Date", ui_parse_YYMMDD },
- ['9C'] = {"Transaction Type", ui_parse_transaction_type },
- ['A5'] = {"FCI Proprietary Template" },
- ['9F02'] = {"Amount, Authorized" },
- ['9F03'] = {"Amount, Other" },
- ['9F05'] = {"Application Discretionary Data" },
- ['9F07'] = {"Application Usage Control" },
- ['9F08'] = {"Application Version Number" },
- ['9F0B'] = {"Cardholder Name - Extended" },
- ['9F0D'] = {"Issuer Action Code - Default" },
- ['9F0E'] = {"Issuer Action Code - Denial" },
- ['9F0F'] = {"Issuer Action Code - Online" },
- ['9F10'] = {"Issuer Application Data" },
- ['9F11'] = {"Issuer Code Table Index" },
- ['9F12'] = {"Application Preferred Name" },
- ['9F13'] = {"Last Online ATC Register" },
- ['9F14'] = {"Lower Consecutive Offline Limit (Terminal Check)" },
- ['9F17'] = {"PIN Try Counter", ui_parse_number },
- ['9F19'] = {"Dynamic Data Authentication Data Object List (DDOL)" },
- ['9F1A'] = {"Terminal Country Code", ui_parse_country_code },
- ['9F1F'] = {"Track 1 Discretionary Data", ui_parse_printable },
- ['9F23'] = {"Upper Consecutive Offline Limit (Terminal Check)" },
- ['9F26'] = {"Application Cryptogram (AC)" },
- ['9F27'] = {"Cryptogram Information Data" },
- ['9F2D'] = {"ICC PIN Encipherment Public Key Certificate" },
- ['9F2E'] = {"ICC PIN Encipherment Public Key Exponent" },
- ['9F2F'] = {"ICC PIN Encipherment Public Key Remainder" },
- ['9F32'] = {"Issuer PK Exponent" },
- ['9F36'] = {"Application Transaction Counter (ATC)" },
- ['9F37'] = {"Unpredictable number" },
- ['9F38'] = {"Processing Options Data Object List (PDOL)" },
- ['9F42'] = {"Application Currency Code" },
- ['9F44'] = {"Application Currency Exponent" },
- ['9F45'] = {"Data Authentication Code" },
- ['9F46'] = {"ICC Public Key Certificate" },
- ['9F47'] = {"ICC Public Key Exponent" },
- ['9F48'] = {"ICC Public Key Remainder" },
- ['9F4A'] = {"Static Data Authentication Tag List" },
- ['9F4B'] = {"Signed Dynamic Application Data" },
- ['9F4C'] = {"Integrated Circuit Card (ICC) Dynamic Number" },
- ['9F4D'] = {"Log Entry" },
- ['9F4F'] = {"Log Fromat" },
- ['9F51'] = {"Application Currency Code" },
- ['9F52'] = {"Card Verification Results (CVR)" },
- ['9F53'] = {"Consecutive Transaction Limit (International)" },
- ['9F54'] = {"Cumulative Total Transaction Amount Limit" },
- ['9F55'] = {"Geographic Indicator" },
- ['9F56'] = {"Issuer Authentication Indicator" },
- ['9F57'] = {"Issuer Country Code" },
- ['9F58'] = {"Lower Consecutive Offline Limit (Card Check)" },
- ['9F59'] = {"Upper Consecutive Offline Limit (Card Check)" },
- ['9F5A'] = {"Issuer URL2" },
- ['9F5C'] = {"Cumulative Total Transaction Amount Upper Limit" },
- ['9F72'] = {"Consecutive Transaction Limit (International - Country)" },
- ['9F73'] = {"Currency Conversion Factor" },
- ['9F74'] = {"VLP Issuer Authorization Code" },
- ['9F75'] = {"Cumulative Total Transaction Amount Limit - Dual Currency" },
- ['9F76'] = {"Secondary Application Currency Code" },
- ['9F77'] = {"VLP Funds Limit" },
- ['9F78'] = {"VLP Single Transaction Limit" },
- ['9F79'] = {"VLP Available Funds" },
- ['9F7F'] = {"Card Production Life Cycle (CPLC) History File Identifiers" },
- ['BF0C'] = {"FCI Issuer Discretionary Data" }
- }
- function emv_parse(cardenv,tlv)
- return tlv_parse(cardenv,tlv,EMV_REFERENCE)
- end
- PPSE = "#325041592E5359532E4444463031"
- PSE = "#315041592E5359532E4444463031"
- -- AID_LIST enhanced with information from Wikipedia
- -- http://en.wikipedia.org/wiki/EMV
- AID_LIST = {
- "#A0000000421010", -- French CB
- "#A0000000422010", -- French CB
- "#A0000000031010", -- Visa credit or debit
- "#A0000000032010", -- Visa electron
- "#A0000000032020", -- V pay
- "#A0000000032010", -- Visa electron
- "#A0000000038010", -- Visa Plus
- "#A0000000041010", -- Mastercard credit or debit
- "#A0000000042010", --
- "#A0000000043060", -- Mastercard Maestro
- "#A0000000046000", -- Mastercard Cirrus
- "#A00000006900", -- FR Moneo
- "#A00000002501", -- American Express
- "#A0000001850002", -- UK Post Office Card Account card
- "#A0000001523010", -- Diners club/Discover
- "#A0000002771010", -- Interac
- "#A0000003241010", -- Discover
- "#A0000000651010", -- JCB
- }
- EXTRA_DATA = { 0x9F36, 0x9F13, 0x9F17, 0x9F4D, 0x9F4F }
- function emv_process_ppse(cardenv)
- local sw, resp
- local APP
- local dirent
- sw, resp = card.select(PPSE)
- if sw ~= 0x9000 then
- log.print(log.INFO,"No PPSE")
- return false
- end
- -- Construct tree
- APP = nodes.append(cardenv, {classname="application", label="application", id=PPSE})
- emv_parse(APP,resp)
- AID_LIST = {}
- for dirent in nodes.find(APP,{ id="4F" }) do
- aid = tostring(nodes.get_attribute(dirent,"val"))
- log.print(log.INFO,"PPSE contains application #" .. aid)
- table.insert(AID_LIST,"#"..aid)
- end
- return true
- end
- function emv_process_pse(cardenv)
- local sw, resp
- local APP
- local ref
- local sfi
- local FILE
- local rec
- local REC
- local RECORD
- local aid
- local warm_atr
- local tag4F
- sw, resp = card.select(PSE)
- -- Could it be a french card?
- if sw == 0x6E00 then
- card.warm_reset()
- warm_atr = card.last_atr()
- nodes.append(cardenv, {classname="atr", label="ATR", id="warm", size=#warm_atr, val=warm_atr})
- sw, resp = card.select(PSE)
- end
- -- could it be a contactless smartcard?
- if sw == 0x6A82 then
- return emv_process_ppse(cardenv)
- end
- if sw ~= 0x9000 then
- log.print(log.INFO,"No PSE")
- return false
- end
- -- Construct tree
- APP = nodes.append(cardenv, {classname="application", label="application", id=PSE})
- emv_parse(APP,resp)
- ref = nodes.find_first(APP,{id="88"})
- if (ref) then
- sfi = nodes.get_attribute(ref,"val")
- FILE = nodes.append(APP,{classname="file", label="file", id=sfi[0]})
- rec = 1
- AID_LIST = {}
- repeat
- sw,resp = card.read_record(sfi:get(0),rec)
- if sw == 0x9000 then
- RECORD = nodes.append(FILE, {classname="record", label="record", id=tostring(rec)})
- emv_parse(RECORD,resp)
- for tag4F in nodes.find(RECORD,{id="4F"}) do
- aid = tostring(nodes.get_attribute(tag4F,"val"))
- log.print(log.INFO,"PSE contains application #" .. aid)
- table.insert(AID_LIST,"#"..aid)
- end
- rec = rec + 1
- end
- until sw ~= 0x9000
- else
- log.print(log.WARNING,"SFI indicator (tag 88) not found in PSE")
- end
- return true
- end
- function visa_process_application_logs(application, log_sfi, log_max)
- local sw, resp
- local LOG_FILE
- local LOG_DATA
- local LOG_FORMAT
- local log_recno
- LOG_FILE = nodes.append(application,{ classname="file",
- label="file",
- id=tostring(log_sfi)})
- LOG_DATA = nodes.append(LOG_FILE, { classname="item",
- label = "log data"})
- log.print(log.INFO,string.format("Reading LOG SFI %i",log_sfi))
- for log_recno =1,log_max do
- sw,resp = card.read_record(log_sfi, log_recno)
- if sw ~= 0x9000 then
- log.print(log.WARNING,"Read log record failed")
- break
- else
- nodes.append(LOG_DATA,{ classname = "record",
- label="record",
- id=log_recno,
- size=#resp,
- val=resp})
- end
- end
- end
- function emv_process_application_logs(application, log_sfi, log_max)
- local log_format
- local log_tag
- local log_items = { }
- local sw, resp
- local tag
- local tag_name
- local tag_func
- local len
- local i
- local item
- local item_pos
- local LOG_FILE
- local LOG_DATA
- local LOG_FORMAT
- local REC
- local ITEM
- local ITEM_AMOUNT
- local log_recno
- local data
- local currency_code, currency_name, currency_digits
- LOG_FILE = nodes.append(application, { classname="file", label="log file", id=log_sfi})
- LOG_FORMAT = nodes.append(LOG_FILE, { classname="block", label="log format"})
- log_format = application:find_first({id = "9F4F"}):get_attribute("val")
- i = 1
- item = ""
- nodes.set_attribute(LOG_FORMAT,"val",log_format);
- while log_format
- do
- tag, log_format = asn1.split_tag(log_format)
- len, log_format = asn1.split_length(log_format)
- tag_name, tag_func = tlv_tag_info(tag,EMV_REFERENCE,0);
- log_items[i]= { tag, len, tag_name, tag_func }
- i = i+1
- item = item .. string.format("%X[%d] ", tag, len);
- end
- nodes.set_attribute(LOG_FORMAT,"alt",item);
- log.print(log.INFO,string.format("Reading LOG SFI %i",log_sfi))
- for log_recno =1,log_max do
- sw,resp = card.read_record(log_sfi,log_recno)
- if sw ~= 0x9000 then
- log.print(log.WARNING,"Read log record failed")
- break
- else
- REC = nodes.append(LOG_FILE,{classname="record", label="record", id=log_recno, size=#resp})
- item_pos = 0
- ITEM_AMOUNT = nil
- currency_digits = 0
- for i=1,#log_items do
- if log_items[i][3] then
- ITEM = nodes.append(REC,{ classname="item",
- label=log_items[i][3],
- size=log_items[i][2] })
- else
- ITEM = nodes.append(REC,{ classname="item",
- label=string.format("tag %X",log_items[i][1]),
- size=log_items[i][2] })
- end
- data = bytes.sub(resp,item_pos,item_pos+log_items[i][2]-1)
- nodes.set_attribute(ITEM,"val",data)
- if log_items[i][1]==0x9F02 then
- ITEM_AMOUNT=ITEM
- elseif log_items[i][1]==0x5F2A then
- currency_code = tonumber(tostring(data))
- currency_name = iso_currency_code_name(currency_code)
- currency_digits = iso_currency_code_digits(currency_code)
- nodes.set_attribute(ITEM,"alt",currency_name)
- elseif log_items[i][4] then
- log_items[i][4](ITEM,data)
- end
- item_pos = item_pos + log_items[i][2]
- end
- if ITEM_AMOUNT then
- local amount = tostring(nodes.get_attribute(ITEM_AMOUNT,"val"))
- nodes.set_attribute(ITEM_AMOUNT,"alt",string.format("%.2f",amount/(10^currency_digits)))
- end
- end
- end
- end
- function emv_process_application(cardenv,aid)
- local sw, resp
- local ref
- local pdol
- local AFL
- local extra
- local j -- counter
- log.print(log.INFO,"Processing application "..aid)
- -- Select AID
- sw,resp = card.select(aid)
- if sw ~=0x9000 then
- return false
- end
- -- Process 'File Control Infomation' and get PDOL
- local APP
- local FCI
- APP = nodes.append(cardenv, { classname = "application", label = "application", id=aid })
- FCI = nodes.append(APP, { classname = "header", label = "answer to select", size=#resp, val=resp })
- emv_parse(FCI,resp)
- ref = nodes.find_first(FCI,{id="9F38"})
- if (ref) then
- pdol = nodes.get_attribute(ref,"val")
- else
- pdol = nil;
- end
- -- INITIATE get processing options, now that we have pdol
- local GPO
- if ui.question("Issue a GET PROCESSING OPTIONS command?",{"Yes","No"})==1 then
- -- Get processing options
- log.print(log.INFO,"Attempting GPO")
- sw,resp = card.get_processing_options(pdol)
- if sw ~=0x9000 then
- if pdol then
- -- try empty GPO just in case the card is blocking some stuff
- log.print(log.WARNING,
- string.format("GPO with data failed with code %X, retrying GPO without data",sw))
- sw,resp = card.get_processing_options(nil)
- end
- end
- if sw ~=0x9000 then
- log.print(log.ERROR,"GPO Failed")
- ui.question("GET PROCESSING OPTIONS failed, the script will continue to read the card",{"OK"})
- else
- GPO = nodes.append(APP,{classname="block",label="processing_options", size=#resp, val=resp})
- emv_parse(GPO,resp)
- end
- end
- -- Read extra data
- --extra = nodes.append(APP,{classname="block",label="extra emv data"})
- for j=1,#EXTRA_DATA do
- sw,resp = card.get_data(EXTRA_DATA[j])
- if sw == 0x9000 then
- emv_parse(APP,resp):set_attribute("classname","block")
- end
- end
- -- find LOG INFO
- local LOG
- local logformat
- logformat=nil
- ref = nodes.find_first(APP,{id="9F4D"})
- -- I've seen this on some cards :
- if ref==nil then
- -- proprietary style ?
- ref = nodes.find_first(APP,{id="DF60"})
- logformat = "VISA"
- else
- logformat = "EMV"
- end
- if ref then
- LOG = nodes.get_attribute(ref,"val")
- else
- sw, resp = card.get_data(0x9F4D)
- if sw==0x9000 then
- LOG = tostring(resp)
- logformat = "EMV"
- else
- sw, resp = card.get_data(0xDF60)
- if sw==0x9000 then
- LOG = tostring(resp)
- logformat = "VISA"
- else
- logformat = nil
- LOG = nil
- end
- end
- end
- if logformat then
- log.print(log.INFO,"Found "..logformat.." transaction log indicator")
- else
- log.print(log.INFO,"No transaction log indicator")
- end
- local sfi_index
- local rec_index
- local SFI
- local REC
- for sfi_index=1,31 do
- SFI = nil
- if (logformat==nil or LOG:get(0)~=sfi_index) then
- for rec_index=1,255 do
- log.print(log.INFO,string.format("Reading SFI %i, record %i",sfi_index, rec_index))
- sw,resp = card.read_record(sfi_index,rec_index)
- if sw ~= 0x9000 then
- log.print(log.WARNING,string.format("Read record failed for SFI %i, record %i",sfi_index,rec_index))
- -- Hack to accommodate Amex, which has files where the first few records are missing
- if ( rec_index > 5 ) then
- break
- end
- else
- if (SFI==nil) then
- SFI = nodes.append(APP,{classname="file", label="file", id=sfi_index})
- end
- REC = nodes.append(SFI,{classname="record", label="record", id=rec_index})
- if (emv_parse(REC,resp)==false) then
- nodes.set_attribute(REC,"val",resp)
- nodes.set_attribute(REC,"size",#resp)
- end
- end
- end -- for rec_index
- end -- if log exists
- end -- for sfi_index
- -- Read logs if they exist
- if logformat=="EMV" then
- emv_process_application_logs(APP,LOG:get(0),LOG:get(1))
- elseif logformat=="VISA" then
- visa_process_application_logs(APP,LOG:get(0),LOG:get(1))
- end
- return true
- end
- CPLC_DATA =
- {
- { "IC Fabricator", 2, 0 } ,
- { "IC Type", 2, 0 },
- { "Operating System Provider Identifier", 2 },
- { "Operating System Release Date", 2 },
- { "Operating System Release Level", 2 },
- { "IC Fabrication Date", 2 },
- { "IC Serial Number", 4 },
- { "IC Batch Identifier", 2 },
- { "IC ModuleFabricator", 2 },
- { "IC ModulePackaging Date", 2 },
- { "ICC Manufacturer", 2 },
- { "IC Embedding Date", 2 },
- { "Prepersonalizer Identifier", 2 },
- { "Prepersonalization Date", 2 },
- { "Prepersonalization Equipment", 4 },
- { "Personalizer Identifier", 2 },
- { "Personalization Date", 2 },
- { "Personalization Equipment", 4 },
- }
- function emv_process_cplc(cardenv)
- local sw, resp
- local CPLC
- local cplc_data
- local cplc_tag
- local i
- local pos
- local ref2
- log.print(log.INFO,"Processing CPLC data")
- sw,resp = card.get_data(0x9F7F)
- if sw == 0x9000 then
- cplc_tag, cplc_data = asn1.split(resp)
- CPLC = nodes.append(cardenv,{classname="block", label="cpcl data", id="9F7F", size=#cplc_data})
- nodes.set_attribute(CPLC,"val",cplc_data)
- pos = 0
- for i=1,#CPLC_DATA do
- ref2 = nodes.append(CPLC,{classname="item", label=CPLC_DATA[i][1], id=pos});
- nodes.set_attribute(ref2,"val",bytes.sub(cplc_data,pos,pos+CPLC_DATA[i][2]-1))
- pos = pos + CPLC_DATA[i][2]
- end
- end
- end
- -- PROCESSING
- if card.connect() then
- local mycard = card.tree_startup("EMV")
- emv_process_pse(mycard)
- card.warm_reset()
- for i=1,#AID_LIST
- do
- -- print(AID_LIST[i])
- emv_process_application(mycard,AID_LIST[i])
- card.warm_reset()
- end
- emv_process_cplc(mycard)
- card.disconnect()
- else
- ui.question("No card detected in reader",{"OK"})
- end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement