Advertisement
Kikku80

PIN Change (EE2021)

Nov 20th, 2019
271
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 7.70 KB | None | 0 0
  1. public async Task<(bool ApplicationCrytogramVerificationResult, byte[] ArpcResponse)> CardUnblockAsync(string PAN, string sequenceNumber, byte smiKeyIndex, byte smcKeyIndex, byte acKeyIndex,
  2.             byte[] applicationCryptogram, byte[] ATC)
  3.         {
  4.             HsmTcpConnection connection = null;
  5.             try
  6.             {
  7.                 if (string.IsNullOrEmpty(PAN) || string.IsNullOrEmpty(sequenceNumber))
  8.                     throw new HsmApplicationCryptogramVerifyException("PAN Data is not valid");
  9.  
  10.                 if (applicationCryptogram == null)
  11.                     throw new HsmApplicationCryptogramVerifyException("Application Cryptogram is not valid");
  12.  
  13.                 if (applicationCryptogram == null || applicationCryptogram.Length != 8)
  14.                     throw new HsmApplicationCryptogramVerifyException("Application Cryptogram is not valid");
  15.  
  16.                 if (ATC == null)
  17.                     throw new HsmApplicationCryptogramVerifyException("ATC is not valid");
  18.  
  19.                 int msgLength = 6 + //header
  20.                                 3 + //function code
  21.                                 1 + //function modifier
  22.                                 1 + //function flag
  23.                                 3 + //IMK SMI
  24.                                 3 + //IMK SMC
  25.                                 1 + //MK method
  26.                                 1 + 8 // PAN + Sequence number
  27.                                 + 1 //SM Key Method
  28.                                
  29.                                 + 1 + 8 // SM Key Length + data
  30.                                 + 2 // PF method + length
  31.                                 + 8 // encrypted pin block
  32.                                 + 3 // PPK
  33.                                 + 1 // PIN Block Format
  34.                                 + 6 // ANB
  35.                                 + 4 // PC and PI Data
  36.                                 + 2 + 7 + 8 + ATC.Length + applicationCryptogram.Length;
  37.           //    int msgLength = 6 + 3 + 1 + 1 + 1 + 3 + 3 + 1 + 1 + (((PAN.Length + sequenceNumber.Length) /2) + ((PAN.Length+sequenceNumber.Length) %2)) + 1 + applicationCryptogram.Length + 8 + 8 + 3 + 1 + 6 + 2 + 7 + ATC.Length + applicationCryptogram.Length;
  38.    
  39.                 //header + function name + function modifier + function flag + scheme + SMI + SMC + IMKAC + (Len +PAN + SequenceNos) + (Len + AC) + (OLD & New PIN) + PPK
  40.                 //+ PinBlockFormat + ANB + ScriptDataPosition + Script Data
  41.  
  42.                 byte[] req = new byte[msgLength];
  43.                 req[0] = 0x01; // SOH Character
  44.                 req[1] = 0x01; // Version Number
  45.  
  46.                 var seqNum = GetNextSequenceNumber();
  47.                 req[2] = (byte)(seqNum >> 8); // Sequence Number
  48.                 req[3] = (byte)seqNum; // Sequence Number
  49.  
  50.                 req[4] = (byte)((msgLength - 6) >> 8); // length of message (header is not included that is why -6)
  51.                 req[5] = (byte)(msgLength - 6); // length of message
  52.  
  53.                 req[6] = 0xEE; // Function name
  54.                 req[7] = 0x20;
  55.                 req[8] = 0x21;
  56.  
  57.                 req[9] = 0x00; // Function modifier
  58.                 req[10] = 0x03; //Function flag - 00= Pin Unblock only, 03= Pin Change
  59.  
  60.                 req[11] = 0x02; // Var Len
  61.                 req[12] = 0x00;
  62.                 req[13] = smiKeyIndex; // Key specifier for IMK SMI
  63.  
  64.                 req[14] = 0x02; // Var Len
  65.                 req[15] = 0x00;
  66.                 req[16] = smcKeyIndex; // Key specifier for IMK SMC
  67.  
  68.                 req[17] = 0x00; // MK Method
  69.  
  70.                 req[18] = (byte) Convertor.StringToBCD(PAN + sequenceNumber,2, PAN.Length,req,19);
  71.              
  72.                 var pos = 19 + req[18];
  73.                
  74.                 //SM Key method
  75.                 req[pos++] = 0x05;
  76.                
  77.                 //SM key data includes ATC plus empty data
  78.                 req[pos++] = 0x08; //length
  79.                 req[pos++] = 0x00;
  80.                 req[pos++] = 0x19;
  81.                 req[pos++] = 0x00;
  82.                 req[pos++] = 0x00;
  83.                 req[pos++] = 0x00;
  84.                 req[pos++] = 0x00;
  85.                 req[pos++] = 0x00;
  86.                 req[pos++] = 0x00;
  87.                
  88.                 req[pos++] = 0x02; //PF method
  89.                 req[pos++] = 0x12; //Length of PF Method
  90.                
  91.                 req[pos++] = 0x32; //encrypted pin block
  92.                 req[pos++] = 0x13;
  93.                 req[pos++] = 0x17;
  94.                 req[pos++] = 0x5A;
  95.                 req[pos++] = 0xBC;
  96.                 req[pos++] = 0x32;
  97.                 req[pos++] = 0xB9;
  98.                 req[pos++] = 0x49;
  99.  
  100.                 req[pos++] = 0x02;
  101.                 req[pos++] = 0x00;
  102.                 req[pos++] = 0x07; //PPK. we should not be using this for this function - index 7 is staging , 2 is live
  103.  
  104.                 req[pos++] = 0x10; //PIN Block Format
  105.  
  106.                 //Account Number Block
  107.                 pos += Convertor.StringToBCD(PAN, PAN.Length - 13, 12, req, pos);//ANB
  108.  
  109.                 req[pos++] = 0x00; // PC method
  110.                 req[pos++] = 0x00; // length of PC method
  111.                 req[pos++] = 0x00; // PI method
  112.  
  113.                 req[pos++] = 0x1B; // Length of PI Data
  114.                
  115.                 req[pos++] = 0x00; //Script Data Position
  116.                 req[pos++] = 0x0F;
  117.  
  118.                 req[pos++] = 0x18; //Script data len
  119.                 req[pos++] = 0x84; //Class
  120.                 req[pos++] = 0x24; //Ins
  121.                 req[pos++] = 0x00; //P1
  122.                 req[pos++] = 0x00;// P2
  123.                 req[pos++] = 0x08; //Lc
  124.  
  125.                 Buffer.BlockCopy(ATC, 0, req, pos, ATC.Length);
  126.                 pos += ATC.Length;
  127.  
  128.                 Buffer.BlockCopy(applicationCryptogram, 0, req, pos, applicationCryptogram.Length);
  129.                 pos += applicationCryptogram.Length;
  130.                
  131.                 req[pos++] = 0x00; //8 bytes used for Pin change only
  132.                 req[pos++] = 0x00;
  133.                 req[pos++] = 0x00;
  134.                 req[pos++] = 0x00;
  135.                 req[pos++] = 0x00;
  136.                 req[pos++] = 0x00;
  137.                 req[pos++] = 0x00;
  138.                 req[pos++] = 0x00;
  139.                
  140.                 req[pos++] = 0x80;
  141.                 Console.WriteLine($"Request Buffer: {ByteArrayToString(req)}");    
  142.                
  143.                 connection = GetConnection();
  144.                 var response = await connection.SendRequestAsync(req);
  145.                
  146.                 Console.WriteLine($"Response Buffer: {ByteArrayToString(response)}");    
  147.  
  148.  
  149.                 if (response == null || response.Length < 4)
  150.                     throw new HsmApplicationCryptogramVerifyException("EMV-PIN-CHANGE-UNBLOCK (EE2016) function returned invalid response");
  151.  
  152.  
  153.                 //check response code
  154.                 if (response[3] != 0x00 && response[3] != 0x08) //function failed
  155.                     throw new HsmApplicationCryptogramVerifyException(string.Format("EMV-PIN-CHANGE-UNBLOCK (EE2016) response is {0:X2}", response[3]));
  156.                 else if (response[3] == 0x08)
  157.                 {
  158.                     return (false, null);
  159.                 }
  160.                 else //0x00
  161.                 {
  162.                     _log.Debug("EMV-PIN-CHANGE-UNBLOCK (EE2016) succeeded");
  163.                     byte[] ARPC = new byte[response[4]];
  164.                     Buffer.BlockCopy(response, 5, ARPC, 0, response[4]);
  165.                     return (true, ARPC);
  166.                 }
  167.             }
  168.             finally
  169.             {
  170.                 //return connection to stack
  171.                 if (hsmConnections != null)
  172.                     hsmConnections.Push(connection);
  173.             }
  174.         }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement