Advertisement
Guest User

EMV-AMEX.lua

a guest
Jun 8th, 2014
2,496
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 27.03 KB | None | 0 0
  1. --
  2. -- This file is part of Cardpeek, the smartcard reader utility.
  3. --
  4. -- Copyright 2009-2013 by 'L1L1'
  5. --
  6. -- Cardpeek is free software: you can redistribute it and/or modify
  7. -- it under the terms of the GNU General Public License as published by
  8. -- the Free Software Foundation, either version 3 of the License, or
  9. -- (at your option) any later version.
  10. --
  11. -- Cardpeek is distributed in the hope that it will be useful,
  12. -- but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. -- GNU General Public License for more details.
  15. --
  16. -- You should have received a copy of the GNU General Public License
  17. -- along with Cardpeek.  If not, see <http://www.gnu.org/licenses/>.
  18. --
  19. -- @name EMV-AMEX
  20. -- @description Bank cards 'PIN and chip'
  21. -- @targets 0.8
  22. --
  23. -- History:
  24. -- Aug 07 2010: Corrected bug in GPO command.
  25. -- Aug 08 2010: Corrected bug in AFL data processing
  26. -- Mar 27 2011: Added CVM patch from Adam Laurie.
  27. -- Jan 23 2012: Added UK Post Office Card Account in AID list from Tyson Key.
  28. -- Mar 25 2012: Added a few AIDs
  29. -- @update: Feb 21 2014: Better NFC compatibility by using current date in GPO.
  30.  
  31. require('lib.tlv')
  32. require('lib.strict')
  33.  
  34. --------------------------------------------------------------------------
  35. -- GLOBAL EMV CARD COMMANDS extending general lib.apdu
  36. --------------------------------------------------------------------------
  37.  
  38. function build_empty_pdol_data_block(pdol)
  39.     local data = bytes.new(8);
  40.     local o_tag
  41.     local o_len
  42.  
  43.     while pdol do
  44.         o_tag, pdol = asn1.split_tag(pdol)
  45.         o_len, pdol = asn1.split_tag(pdol)
  46.  
  47.         if o_tag==0x9F66 and o_len==4 then
  48.             --  Terminal Transaction Qualifiers (VISA)
  49.             data = data .. "30 00 00 00"
  50.         elseif o_tag==0x9F1A and o_len==2 then
  51.             -- Terminal country code
  52.             data = data .. "0250"
  53.         elseif o_tag==0x5F2A and o_len==2 then
  54.             -- Transaction currency code
  55.             data = data .. "0978"
  56.         elseif o_tag==0x9A and o_len==3 then
  57.             -- Transaction date
  58.             data = data .. os.date("%y %m %d")
  59.         elseif o_tag==0x9F37 and o_len==4 then
  60.             -- Unpredictable number
  61.             data = data .. "DEADBEEF"
  62.         else
  63.             -- When in doubt Zeroize
  64.             while o_len > 0 do
  65.                 data = data .. 0x00
  66.                 o_len = o_len-1
  67.             end
  68.         end
  69.     end
  70.     return data
  71. end
  72.  
  73. function card.get_processing_options(pdol)
  74.         local command
  75.     local pdol_data
  76.     if pdol and #pdol>0 then
  77.        pdol_data = build_empty_pdol_data_block(pdol)
  78.            command = bytes.new(8,"80 A8 00 00",#pdol_data+2,0x83,#pdol_data,pdol_data,"00")
  79.         else
  80.            command = bytes.new(8,"80 A8 00 00 02 83 00 00")
  81.         end
  82.         return card.send(command)
  83. end
  84.  
  85. -- override card.get_data() for EMV
  86. function card.get_data(data)
  87.         local command = bytes.new(8,"80 CA",bit.AND(bit.SHR(data,8),0xFF),bit.AND(data,0xFF),0)
  88.         return card.send(command)
  89. end
  90.  
  91.  
  92. -- ------------------------------------------------------------------------
  93. -- EMV
  94. -- ------------------------------------------------------------------------
  95.  
  96. TRANSACTION_TYPE = {
  97.   [0]="Purchase",
  98.   [1]="Cash"
  99. }
  100.  
  101. function ui_parse_transaction_type(node,cc)
  102.         local tt = TRANSACTION_TYPE[cc[0]]
  103.         if tt == nil then
  104.            return tostring(cc)
  105.         end
  106.         nodes.set_attribute(node,"val",cc)
  107.         nodes.set_attribute(node,"alt",tt)
  108.         return true
  109. end
  110.  
  111. function ui_parse_CVM(node,data)
  112.         local i
  113.         local left
  114.         local right
  115.         local leftstring
  116.         local rightstring
  117.         local subnode
  118.         local out
  119.     local data_start
  120.     local data_end
  121.  
  122.         nodes.append(node,{     classname="item",
  123.                                 label="X",
  124.                                 size=4,
  125.                                 val=bytes.sub(data,0,3)})
  126.  
  127.         nodes.append(node,{     classname="item",
  128.                                 label="Y",
  129.                                 size=4,
  130.                                 val=bytes.sub(data,4,7)})
  131.  
  132.  
  133.     -- Calculate data ending boundary to accommodate Amex which includes trailing zeroes
  134.     -- that cause bogus CVM entries to appear
  135.     data_start = 0
  136.     data_end = 0
  137.     for i=0, #data do
  138.         if ( data_start == 0 and data:get(i) ~= 0 ) then
  139.             data_start = i
  140.         elseif ( data_end == 0 and data_start ~= 0 and data:get(i) == 0 ) then
  141.             data_end = i
  142.             break
  143.         end
  144.     end
  145.  
  146.         for i= 4,(data_end/2)-1 do
  147.                 subnode = nodes.append(node, { classname="item",
  148.                                                    label="CVM",
  149.                                                    id=i-3,
  150.                                                    size=2,
  151.                                                    val=bytes.sub(data,i*2,i*2+1)})
  152.                 left = data:get(i*2)
  153.                 right = data:get(i*2+1)
  154.  
  155.                 if bit.AND(left,0x40) == 0x40 then
  156.                         out = "Apply succeeding CV rule if this rule is unsuccessful: "
  157.                 else
  158.                         out = "Fail cardholder verification if this CVM is unsuccessful: "
  159.                 end
  160.  
  161.                 if CVM_REFERENCE_BYTE1[bit.AND(left,0xBF)] == nil then
  162.                         leftstring = string.format("Unknown (%02X)",left)
  163.                 else
  164.                         leftstring = CVM_REFERENCE_BYTE1[bit.AND(left,0xBF)]
  165.                 end
  166.                 if CVM_REFERENCE_BYTE2[right] == nil then
  167.                         rightstring = string.format("Unknown (%02X)",right)
  168.                 else
  169.                         rightstring = CVM_REFERENCE_BYTE2[right]
  170.                 end
  171.                 out = out .. leftstring .. " - " .. rightstring
  172.                 nodes.set_attribute(subnode,"alt",out)
  173.         end
  174.         nodes.set_attribute(node,"val",data)
  175.         return true
  176. end
  177.  
  178. CVM_REFERENCE_BYTE1 = {
  179.    [0x00] = "Fail CVM processing",
  180.    [0x01] = "Plaintext PIN verification performed by ICC",
  181.    [0x02] = "Enciphered PIN verified online",
  182.    [0x03] = "Plaintext PIN verification performed by ICC and signature (paper)",
  183.    [0x04] = "Enciphered PIN verification performed by ICC",
  184.    [0x05] = "Enciphered PIN verification performed by ICC and signature (paper)",
  185.    [0x1E] = "Signature (paper)",
  186.    [0x1F] = "No CVM Required",
  187. }
  188.  
  189. CVM_REFERENCE_BYTE2 = {
  190.    [0x00] = "Always",
  191.    [0x01] = "If unattended cash",
  192.    [0x02] = "If not attended cash and not manual cash and not purchase with cashback",
  193.    [0x03] = "If terminal supports the CVM",
  194.    [0x04] = "If manual cash",
  195.    [0x05] = "If purchase with cashback",
  196.    [0x06] = "If transaction is in the application currency and is under X value",
  197.    [0x07] = "If transaction is in the application currency and is over X value",
  198.    [0x08] = "If transaction is in the application currency and is under Y value",
  199.    [0x09] = "If transaction is in the application currency and is over Y value"
  200. }      
  201.  
  202. EMV_REFERENCE = {
  203.    ['5D'] = {"Directory Definition File (DDF) Name" },
  204.    ['70'] = {"Application Data File (ADF)" },
  205.    ['80'] = {"Response Message Template Format 1" },
  206.    ['82'] = {"Application Interchange Profile (AIP)" },
  207.    ['87'] = {"Application Priority Indicator" },
  208.    ['88'] = {"Short File Identifier (SFI)" },
  209.    ['8C'] = {"Card Risk Management Data Object List 1 (CDOL1)" },
  210.    ['8D'] = {"Card Risk Management Data Object List 2 (CDOL2)" },
  211.    ['8E'] = {"Cardholder Verification Method (CVM) List", ui_parse_CVM },
  212.    ['8F'] = {"Certificate Authority Public Key Index (PKI)" },
  213.    ['90'] = {"Issuer PK Certificate" },
  214.    ['91'] = {"Issuer Authentication Data" },
  215.    ['92'] = {"Issuer PK Remainder" },
  216.    ['93'] = {"Signed Static Application Data" },
  217.    ['94'] = {"Application File Locator (AFL)" },
  218.    ['95'] = {"Terminal Verification Results (TVR)" },
  219.    ['97'] = {"Transaction Certificate Data Object List (TDOL)" },
  220.    ['9A'] = {"Transaction Date", ui_parse_YYMMDD },
  221.    ['9C'] = {"Transaction Type", ui_parse_transaction_type },
  222.    ['A5'] = {"FCI Proprietary Template" },
  223.    ['9F02'] = {"Amount, Authorized" },
  224.    ['9F03'] = {"Amount, Other" },
  225.    ['9F05'] = {"Application Discretionary Data" },
  226.    ['9F07'] = {"Application Usage Control" },
  227.    ['9F08'] = {"Application Version Number" },
  228.    ['9F0B'] = {"Cardholder Name - Extended" },
  229.    ['9F0D'] = {"Issuer Action Code - Default" },
  230.    ['9F0E'] = {"Issuer Action Code - Denial" },
  231.    ['9F0F'] = {"Issuer Action Code - Online" },
  232.    ['9F10'] = {"Issuer Application Data" },
  233.    ['9F11'] = {"Issuer Code Table Index" },
  234.    ['9F12'] = {"Application Preferred Name" },
  235.    ['9F13'] = {"Last Online ATC Register" },
  236.    ['9F14'] = {"Lower Consecutive Offline Limit (Terminal Check)" },
  237.    ['9F17'] = {"PIN Try Counter", ui_parse_number },
  238.    ['9F19'] = {"Dynamic Data Authentication Data Object List (DDOL)" },
  239.    ['9F1A'] = {"Terminal Country Code", ui_parse_country_code },
  240.    ['9F1F'] = {"Track 1 Discretionary Data", ui_parse_printable },
  241.    ['9F23'] = {"Upper Consecutive Offline Limit (Terminal Check)" },
  242.    ['9F26'] = {"Application Cryptogram (AC)" },
  243.    ['9F27'] = {"Cryptogram Information Data" },
  244.    ['9F2D'] = {"ICC PIN Encipherment Public Key Certificate" },
  245.    ['9F2E'] = {"ICC PIN Encipherment Public Key Exponent" },
  246.    ['9F2F'] = {"ICC PIN Encipherment Public Key Remainder" },
  247.    ['9F32'] = {"Issuer PK Exponent" },
  248.    ['9F36'] = {"Application Transaction Counter (ATC)" },
  249.    ['9F37'] = {"Unpredictable number" },
  250.    ['9F38'] = {"Processing Options Data Object List (PDOL)" },
  251.    ['9F42'] = {"Application Currency Code" },
  252.    ['9F44'] = {"Application Currency Exponent" },
  253.    ['9F45'] = {"Data Authentication Code" },
  254.    ['9F46'] = {"ICC Public Key Certificate" },
  255.    ['9F47'] = {"ICC Public Key Exponent" },
  256.    ['9F48'] = {"ICC Public Key Remainder" },
  257.    ['9F4A'] = {"Static Data Authentication Tag List" },
  258.    ['9F4B'] = {"Signed Dynamic Application Data" },
  259.    ['9F4C'] = {"Integrated Circuit Card (ICC) Dynamic Number" },
  260.    ['9F4D'] = {"Log Entry" },
  261.    ['9F4F'] = {"Log Fromat" },
  262.    ['9F51'] = {"Application Currency Code" },
  263.    ['9F52'] = {"Card Verification Results (CVR)" },
  264.    ['9F53'] = {"Consecutive Transaction Limit (International)" },
  265.    ['9F54'] = {"Cumulative Total Transaction Amount Limit" },
  266.    ['9F55'] = {"Geographic Indicator" },
  267.    ['9F56'] = {"Issuer Authentication Indicator" },
  268.    ['9F57'] = {"Issuer Country Code" },
  269.    ['9F58'] = {"Lower Consecutive Offline Limit (Card Check)" },
  270.    ['9F59'] = {"Upper Consecutive Offline Limit (Card Check)" },
  271.    ['9F5A'] = {"Issuer URL2" },
  272.    ['9F5C'] = {"Cumulative Total Transaction Amount Upper Limit" },
  273.    ['9F72'] = {"Consecutive Transaction Limit (International - Country)" },
  274.    ['9F73'] = {"Currency Conversion Factor" },
  275.    ['9F74'] = {"VLP Issuer Authorization Code" },
  276.    ['9F75'] = {"Cumulative Total Transaction Amount Limit - Dual Currency" },
  277.    ['9F76'] = {"Secondary Application Currency Code" },
  278.    ['9F77'] = {"VLP Funds Limit" },
  279.    ['9F78'] = {"VLP Single Transaction Limit" },
  280.    ['9F79'] = {"VLP Available Funds" },
  281.    ['9F7F'] = {"Card Production Life Cycle (CPLC) History File Identifiers" },
  282.    ['BF0C'] = {"FCI Issuer Discretionary Data" }
  283. }
  284.  
  285. function emv_parse(cardenv,tlv)
  286.         return tlv_parse(cardenv,tlv,EMV_REFERENCE)
  287. end
  288.  
  289. PPSE = "#325041592E5359532E4444463031"
  290. PSE  = "#315041592E5359532E4444463031"
  291.  
  292. -- AID_LIST enhanced with information from Wikipedia
  293. -- http://en.wikipedia.org/wiki/EMV
  294.  
  295. AID_LIST = {
  296.   "#A0000000421010", -- French CB
  297.   "#A0000000422010", -- French CB
  298.  
  299.   "#A0000000031010", -- Visa credit or debit
  300.   "#A0000000032010", -- Visa electron
  301.   "#A0000000032020", -- V pay
  302.   "#A0000000032010", -- Visa electron
  303.   "#A0000000038010", -- Visa Plus
  304.  
  305.   "#A0000000041010", -- Mastercard credit or debit
  306.   "#A0000000042010", --
  307.   "#A0000000043060", -- Mastercard Maestro
  308.   "#A0000000046000", -- Mastercard Cirrus
  309.  
  310.   "#A00000006900",   -- FR Moneo
  311.   "#A00000002501",   -- American Express
  312.   "#A0000001850002", -- UK Post Office Card Account card
  313.   "#A0000001523010", -- Diners club/Discover
  314.   "#A0000002771010", -- Interac
  315.   "#A0000003241010", -- Discover
  316.   "#A0000000651010", -- JCB
  317. }
  318.  
  319. EXTRA_DATA = { 0x9F36, 0x9F13, 0x9F17, 0x9F4D, 0x9F4F }
  320.  
  321.  
  322. function emv_process_ppse(cardenv)
  323.         local sw, resp
  324.         local APP
  325.         local dirent
  326.  
  327.         sw, resp = card.select(PPSE)
  328.  
  329.         if sw ~= 0x9000 then
  330.            log.print(log.INFO,"No PPSE")
  331.            return false
  332.         end
  333.  
  334.         -- Construct tree
  335.         APP = nodes.append(cardenv, {classname="application", label="application", id=PPSE})
  336.         emv_parse(APP,resp)
  337.  
  338.         AID_LIST = {}
  339.  
  340.         for dirent in nodes.find(APP,{ id="4F" }) do
  341.             aid = tostring(nodes.get_attribute(dirent,"val"))
  342.                 log.print(log.INFO,"PPSE contains application #" .. aid)
  343.             table.insert(AID_LIST,"#"..aid)
  344.         end
  345.         return true
  346.  
  347. end
  348.  
  349. function emv_process_pse(cardenv)
  350.         local sw, resp
  351.         local APP
  352.         local ref
  353.         local sfi
  354.         local FILE
  355.         local rec
  356.         local REC
  357.         local RECORD
  358.         local aid
  359.         local warm_atr
  360.         local tag4F
  361.  
  362.         sw, resp = card.select(PSE)
  363.        
  364.         -- Could it be a french card?
  365.         if sw == 0x6E00 then
  366.            card.warm_reset()
  367.            warm_atr = card.last_atr()
  368.            nodes.append(cardenv, {classname="atr", label="ATR", id="warm", size=#warm_atr, val=warm_atr})
  369.            sw, resp = card.select(PSE)
  370.         end
  371.  
  372.         -- could it be a contactless smartcard?
  373.         if sw == 0x6A82 then
  374.            return emv_process_ppse(cardenv)
  375.         end
  376.  
  377.         if sw ~= 0x9000 then
  378.         log.print(log.INFO,"No PSE")
  379.             return false
  380.         end
  381.  
  382.         -- Construct tree
  383.         APP = nodes.append(cardenv, {classname="application", label="application", id=PSE})
  384.         emv_parse(APP,resp)
  385.  
  386.         ref = nodes.find_first(APP,{id="88"})
  387.         if (ref) then
  388.             sfi = nodes.get_attribute(ref,"val")
  389.             FILE = nodes.append(APP,{classname="file", label="file", id=sfi[0]})
  390.  
  391.             rec = 1
  392.             AID_LIST = {}
  393.             repeat
  394.             sw,resp = card.read_record(sfi:get(0),rec)
  395.                 if sw == 0x9000 then
  396.                     RECORD = nodes.append(FILE, {classname="record", label="record", id=tostring(rec)})
  397.                     emv_parse(RECORD,resp)
  398.                 for tag4F in nodes.find(RECORD,{id="4F"}) do
  399.                         aid = tostring(nodes.get_attribute(tag4F,"val"))
  400.                             log.print(log.INFO,"PSE contains application #" .. aid)
  401.                         table.insert(AID_LIST,"#"..aid)
  402.                         end
  403.                 rec = rec + 1
  404.             end
  405.            until sw ~= 0x9000
  406.         else
  407.            log.print(log.WARNING,"SFI indicator (tag 88) not found in PSE")
  408.         end
  409.         return true
  410. end
  411.  
  412. function visa_process_application_logs(application, log_sfi, log_max)
  413.         local sw, resp
  414.         local LOG_FILE
  415.         local LOG_DATA
  416.         local LOG_FORMAT
  417.         local log_recno
  418.  
  419.         LOG_FILE   = nodes.append(application,{ classname="file",
  420.                                                     label="file",
  421.                                                     id=tostring(log_sfi)})
  422.  
  423.         LOG_DATA   = nodes.append(LOG_FILE, { classname="item",
  424.                                                   label = "log data"})
  425.        
  426.         log.print(log.INFO,string.format("Reading LOG SFI %i",log_sfi))
  427.         for log_recno =1,log_max do
  428.            sw,resp = card.read_record(log_sfi, log_recno)
  429.            if sw ~= 0x9000 then
  430.                   log.print(log.WARNING,"Read log record failed")
  431.                   break
  432.            else
  433.                   nodes.append(LOG_DATA,{ classname = "record",
  434.                                               label="record",
  435.                                               id=log_recno,
  436.                                               size=#resp,
  437.                                               val=resp})
  438.            end
  439.         end
  440.  
  441. end
  442.  
  443.  
  444. function emv_process_application_logs(application, log_sfi, log_max)
  445.         local log_format
  446.         local log_tag
  447.         local log_items = { }
  448.         local sw, resp
  449.         local tag
  450.         local tag_name
  451.         local tag_func
  452.         local len
  453.         local i
  454.         local item
  455.         local item_pos
  456.         local LOG_FILE
  457.         local LOG_DATA
  458.         local LOG_FORMAT
  459.         local REC
  460.         local ITEM
  461.         local ITEM_AMOUNT
  462.         local log_recno
  463.         local data
  464.         local currency_code, currency_name, currency_digits
  465.  
  466.         LOG_FILE   = nodes.append(application,     { classname="file", label="log file", id=log_sfi})
  467.         LOG_FORMAT = nodes.append(LOG_FILE,        { classname="block", label="log format"})
  468.        
  469.         log_format = application:find_first({id = "9F4F"}):get_attribute("val")
  470.  
  471.         i = 1
  472.         item = ""
  473.         nodes.set_attribute(LOG_FORMAT,"val",log_format);
  474.         while log_format
  475.         do
  476.             tag, log_format = asn1.split_tag(log_format)
  477.             len, log_format = asn1.split_length(log_format)
  478.             tag_name, tag_func = tlv_tag_info(tag,EMV_REFERENCE,0);
  479.             log_items[i]= { tag, len, tag_name, tag_func }
  480.             i = i+1
  481.             item = item .. string.format("%X[%d] ", tag, len);
  482.         end
  483.         nodes.set_attribute(LOG_FORMAT,"alt",item);
  484.  
  485.         log.print(log.INFO,string.format("Reading LOG SFI %i",log_sfi))
  486.         for log_recno =1,log_max do
  487.            sw,resp = card.read_record(log_sfi,log_recno)
  488.            if sw ~= 0x9000 then
  489.                   log.print(log.WARNING,"Read log record failed")
  490.                   break
  491.            else
  492.                   REC = nodes.append(LOG_FILE,{classname="record", label="record", id=log_recno, size=#resp})
  493.                   item_pos = 0
  494.                   ITEM_AMOUNT = nil
  495.                   currency_digits = 0
  496.                   for i=1,#log_items do
  497.                      if log_items[i][3] then
  498.                         ITEM = nodes.append(REC,{ classname="item",
  499.                                                       label=log_items[i][3],
  500.                                                       size=log_items[i][2] })
  501.                      else
  502.                         ITEM = nodes.append(REC,{ classname="item",
  503.                                                       label=string.format("tag %X",log_items[i][1]),
  504.                                                       size=log_items[i][2] })
  505.                      end
  506.  
  507.                      data = bytes.sub(resp,item_pos,item_pos+log_items[i][2]-1)
  508.                      nodes.set_attribute(ITEM,"val",data)
  509.  
  510.                      if log_items[i][1]==0x9F02 then
  511.                         ITEM_AMOUNT=ITEM
  512.                      elseif log_items[i][1]==0x5F2A then
  513.                         currency_code   = tonumber(tostring(data))
  514.                         currency_name   = iso_currency_code_name(currency_code)
  515.                         currency_digits = iso_currency_code_digits(currency_code)
  516.                         nodes.set_attribute(ITEM,"alt",currency_name)
  517.                      elseif log_items[i][4] then
  518.                         log_items[i][4](ITEM,data)
  519.                      end
  520.                      item_pos = item_pos + log_items[i][2]
  521.                   end
  522.  
  523.                   if ITEM_AMOUNT then
  524.                      local amount = tostring(nodes.get_attribute(ITEM_AMOUNT,"val"))
  525.                      nodes.set_attribute(ITEM_AMOUNT,"alt",string.format("%.2f",amount/(10^currency_digits)))
  526.                   end
  527.            end
  528.         end
  529.  
  530. end
  531.  
  532. function emv_process_application(cardenv,aid)
  533.         local sw, resp
  534.         local ref
  535.         local pdol
  536.         local AFL
  537.         local extra
  538.         local j -- counter
  539.  
  540.         log.print(log.INFO,"Processing application "..aid)
  541.  
  542.         -- Select AID
  543.         sw,resp = card.select(aid)
  544.         if sw ~=0x9000 then
  545.            return false
  546.         end
  547.  
  548.         -- Process 'File Control Infomation' and get PDOL
  549.         local APP
  550.         local FCI
  551.        
  552.         APP = nodes.append(cardenv, { classname = "application", label = "application", id=aid })
  553.         FCI = nodes.append(APP, { classname = "header", label = "answer to select", size=#resp, val=resp })
  554.         emv_parse(FCI,resp)
  555.         ref = nodes.find_first(FCI,{id="9F38"})
  556.         if (ref) then
  557.            pdol = nodes.get_attribute(ref,"val")
  558.         else
  559.            pdol = nil;
  560.         end
  561.  
  562.         -- INITIATE get processing options, now that we have pdol
  563.         local GPO
  564.  
  565.         if ui.question("Issue a GET PROCESSING OPTIONS command?",{"Yes","No"})==1 then
  566.             -- Get processing options
  567.             log.print(log.INFO,"Attempting GPO")
  568.             sw,resp = card.get_processing_options(pdol)
  569.             if sw ~=0x9000 then
  570.                 if pdol then
  571.                     -- try empty GPO just in case the card is blocking some stuff
  572.                     log.print(log.WARNING,
  573.                               string.format("GPO with data failed with code %X, retrying GPO without data",sw))
  574.                     sw,resp = card.get_processing_options(nil)  
  575.                 end
  576.            end
  577.            if sw ~=0x9000 then
  578.                 log.print(log.ERROR,"GPO Failed")
  579.                 ui.question("GET PROCESSING OPTIONS failed, the script will continue to read the card",{"OK"})
  580.            else
  581.                 GPO = nodes.append(APP,{classname="block",label="processing_options", size=#resp, val=resp})
  582.                 emv_parse(GPO,resp)
  583.            end
  584.         end
  585.  
  586.         -- Read extra data
  587.         --extra = nodes.append(APP,{classname="block",label="extra emv data"})
  588.         for j=1,#EXTRA_DATA do
  589.             sw,resp = card.get_data(EXTRA_DATA[j])
  590.             if sw == 0x9000 then
  591.                emv_parse(APP,resp):set_attribute("classname","block")
  592.             end
  593.         end
  594.        
  595.         -- find LOG INFO
  596.         local LOG
  597.         local logformat
  598.        
  599.         logformat=nil
  600.         ref = nodes.find_first(APP,{id="9F4D"})
  601.         -- I've seen this on some cards :
  602.         if ref==nil then
  603.            -- proprietary style ?
  604.            ref = nodes.find_first(APP,{id="DF60"})
  605.            logformat = "VISA"
  606.         else
  607.            logformat = "EMV"
  608.         end
  609.  
  610.         if ref then
  611.            LOG = nodes.get_attribute(ref,"val")
  612.         else
  613.            sw, resp = card.get_data(0x9F4D)
  614.            if sw==0x9000 then
  615.               LOG = tostring(resp)
  616.               logformat = "EMV"
  617.            else
  618.               sw, resp = card.get_data(0xDF60)
  619.               if sw==0x9000 then
  620.                  LOG = tostring(resp)
  621.                  logformat = "VISA"
  622.               else
  623.                  logformat = nil
  624.                  LOG = nil
  625.               end
  626.            end
  627.         end
  628.  
  629.         if logformat then
  630.            log.print(log.INFO,"Found "..logformat.." transaction log indicator")
  631.         else
  632.            log.print(log.INFO,"No transaction log indicator")
  633.         end
  634.  
  635.  
  636.         local sfi_index
  637.         local rec_index
  638.         local SFI
  639.         local REC
  640.            
  641.         for sfi_index=1,31 do
  642.                 SFI = nil
  643.  
  644.                 if (logformat==nil or LOG:get(0)~=sfi_index) then
  645.  
  646.                         for rec_index=1,255 do
  647.                                 log.print(log.INFO,string.format("Reading SFI %i, record %i",sfi_index, rec_index))
  648.                                 sw,resp = card.read_record(sfi_index,rec_index)
  649.                                 if sw ~= 0x9000 then
  650.                                     log.print(log.WARNING,string.format("Read record failed for SFI %i, record %i",sfi_index,rec_index))
  651.                     -- Hack to accommodate Amex, which has files where the first few records are missing   
  652.                                     if ( rec_index > 5 ) then
  653.                                         break
  654.                                     end
  655.                                 else
  656.                                     if (SFI==nil) then
  657.                                             SFI = nodes.append(APP,{classname="file", label="file",     id=sfi_index})
  658.                                     end
  659.                                     REC = nodes.append(SFI,{classname="record", label="record", id=rec_index})
  660.                                     if (emv_parse(REC,resp)==false) then
  661.                                             nodes.set_attribute(REC,"val",resp)
  662.                                             nodes.set_attribute(REC,"size",#resp)
  663.                                     end
  664.                                 end
  665.        
  666.                         end -- for rec_index
  667.  
  668.                 end -- if log exists
  669.  
  670.             end -- for sfi_index
  671.  
  672.         -- Read logs if they exist
  673.         if logformat=="EMV" then
  674.            emv_process_application_logs(APP,LOG:get(0),LOG:get(1))
  675.         elseif logformat=="VISA" then
  676.            visa_process_application_logs(APP,LOG:get(0),LOG:get(1))
  677.         end
  678.  
  679.  
  680.         return true
  681. end
  682.  
  683.  
  684. CPLC_DATA =
  685. {
  686.   { "IC Fabricator", 2, 0 } ,
  687.   { "IC Type", 2, 0 },
  688.   { "Operating System Provider Identifier", 2 },
  689.   { "Operating System Release Date", 2 },
  690.   { "Operating System Release Level", 2 },
  691.   { "IC Fabrication Date", 2 },
  692.   { "IC Serial Number", 4 },
  693.   { "IC Batch Identifier", 2 },
  694.   { "IC ModuleFabricator", 2 },
  695.   { "IC ModulePackaging Date", 2 },
  696.   { "ICC Manufacturer", 2 },
  697.   { "IC Embedding Date", 2 },
  698.   { "Prepersonalizer Identifier", 2 },
  699.   { "Prepersonalization Date", 2 },
  700.   { "Prepersonalization Equipment", 4 },
  701.   { "Personalizer Identifier", 2 },
  702.   { "Personalization Date", 2 },
  703.   { "Personalization Equipment", 4 },
  704. }
  705.  
  706.  
  707. function emv_process_cplc(cardenv)
  708.         local sw, resp
  709.         local CPLC
  710.         local cplc_data
  711.         local cplc_tag
  712.         local i
  713.         local pos
  714.         local ref2
  715.  
  716.         log.print(log.INFO,"Processing CPLC data")
  717.         sw,resp = card.get_data(0x9F7F)
  718.         if sw == 0x9000 then
  719.            cplc_tag, cplc_data = asn1.split(resp)
  720.            CPLC      = nodes.append(cardenv,{classname="block", label="cpcl data", id="9F7F", size=#cplc_data})
  721.            nodes.set_attribute(CPLC,"val",cplc_data)
  722.            pos = 0
  723.            for i=1,#CPLC_DATA do
  724.                ref2 = nodes.append(CPLC,{classname="item", label=CPLC_DATA[i][1], id=pos});
  725.                nodes.set_attribute(ref2,"val",bytes.sub(cplc_data,pos,pos+CPLC_DATA[i][2]-1))
  726.                pos = pos + CPLC_DATA[i][2]
  727.            end
  728.         end
  729. end
  730.  
  731.  
  732. -- PROCESSING
  733.  
  734. if card.connect() then
  735.  
  736.    local mycard = card.tree_startup("EMV")
  737.  
  738.    emv_process_pse(mycard)
  739.    card.warm_reset()
  740.  
  741.    for i=1,#AID_LIST
  742.    do
  743.         -- print(AID_LIST[i])
  744.         emv_process_application(mycard,AID_LIST[i])
  745.         card.warm_reset()
  746.    end
  747.  
  748.    emv_process_cplc(mycard)
  749.  
  750.    card.disconnect()
  751. else
  752.    ui.question("No card detected in reader",{"OK"})
  753. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement