private static SignalsEnum EntryPointRA(KernelDatabase database, CardResponse cardResponse, KernelQ qManager, CardQ cardQManager, Stopwatch sw) { CARDHOLDER_VERIFICATION_METHOD_CVM_RESULTS_9F34_KRN cvr = new CARDHOLDER_VERIFICATION_METHOD_CVM_RESULTS_9F34_KRN(database); EMVGetDataResponse response = (EMVGetDataResponse)cardResponse.ApduResponse; if (!response.Succeeded) { cvr.Value.CVMResult = 0x01;//failed cvr.UpdateDB(); return(SignalsEnum.WAITING_FOR_CVM_PROCESSING); } //store the pin try counter value database.AddToList(response.GetResponseTag()); int pinTryCounter = Formatting.ConvertToInt16(database.Get(EMVTagsEnum.PERSONAL_IDENTIFICATION_NUMBER_PIN_TRY_COUNTER_9F17_KRN).Value); TERMINAL_VERIFICATION_RESULTS_95_KRN tvr = new TERMINAL_VERIFICATION_RESULTS_95_KRN(database); if (cvr.Value.GetCVMPerformed() == CVMCode.EncipheredPINVerificationPerformedByICC || cvr.Value.GetCVMPerformed() == CVMCode.EncipheredPINVerificationPerformedByICCAndSignature_Paper) { string pin = Formatting.ByteArrayToASCIIString(database.Get(EMVTagsEnum.TRANSACTION_PERSONAL_IDENTIFICATION_NUMBER_PIN_DATA_99_KRN.Tag).Value); if (!PinProcessing.VerifyOfflinePin(pin, pinTryCounter, tvr, cvr)) { return(SignalsEnum.WAITING_FOR_CVM_PROCESSING); } //fire off get challenge command EMVGetChallengeRequest request = new EMVGetChallengeRequest(); cardQManager.EnqueueToInput(new CardRequest(request, CardinterfaceServiceRequestEnum.ADPU)); return(SignalsEnum.WAITING_FOR_GET_CHALLENGE); } if (cvr.Value.GetCVMPerformed() == CVMCode.PlaintextPINVerificationPerformedByICC || cvr.Value.GetCVMPerformed() == CVMCode.PlaintextPINVerificationPerformedByICCAndSignature_Paper) { string pin = Formatting.ByteArrayToASCIIString(database.Get(EMVTagsEnum.TRANSACTION_PERSONAL_IDENTIFICATION_NUMBER_PIN_DATA_99_KRN.Tag).Value); if (!PinProcessing.VerifyOfflinePin(pin, pinTryCounter, tvr, cvr)) { return(SignalsEnum.WAITING_FOR_CVM_PROCESSING); } byte[] pinData = PinProcessing.BuildPlainTextPinBlock(pin); //fire off verify for plain text pin EMVVerifyRequest request = new EMVVerifyRequest(VerifyCommandDataQualifier.Plaintext_PIN, pinData); cardQManager.EnqueueToInput(new CardRequest(request, CardinterfaceServiceRequestEnum.ADPU)); return(SignalsEnum.WAITING_FOR_VERIFY); } throw new EMVProtocolException("Invalid cvr in State_5b_WaitingForGetPinTryCounter"); }
private static void Transmit(TCPClientStream stream, byte[] txBytes) { short length = (short)(txBytes.Length); byte[] lengthBytes = new byte[] { (byte)(length / 256), (byte)(length % 256) }; byte[] txBytesTCP = Formatting.ConcatArrays(lengthBytes, txBytes); Logger.Log("Sending: [" + Formatting.ConvertToInt16(lengthBytes) + "]" + "[" + Formatting.ByteArrayToHexString(txBytes) + "]"); stream.Write(txBytesTCP); }
private static byte[] Receive(TCPClientStream stream) { byte chrSTX = 0x02; // Start of Text byte chrETX = 0x03; // End of Text byte[] rxBuffer = new Byte[4096]; int countBytesRead = stream.Read(rxBuffer); byte[] lengthBytesReceived = new byte[2]; Array.Copy(rxBuffer, 0, lengthBytesReceived, 0, lengthBytesReceived.Length); int bytesInRxPacket = Formatting.ConvertToInt16(lengthBytesReceived); if (bytesInRxPacket + 2 != countBytesRead) { throw new TCPIPManagerException("Did not receive all expected bytes"); } byte[] result = new byte[bytesInRxPacket]; Array.Copy(rxBuffer, 2, result, 0, result.Length); bool hasSTX = false; bool hasETX = false; if (result.First() == chrSTX) { byte[] strippedSTX = new byte[result.Length - 1]; Array.Copy(result, 1, strippedSTX, 0, strippedSTX.Length); result = strippedSTX; hasSTX = true; } int lastPos = Array.FindIndex(result, 0, (x) => x == chrETX); if (lastPos != -1) { int lengthToCopy = result.Length - (result.Length - lastPos); byte[] strippedETX = new byte[lengthToCopy]; Array.Copy(result, 0, strippedETX, 0, strippedETX.Length); result = strippedETX; hasETX = true; } Logger.Log("Received:[" + countBytesRead + "]" + (hasSTX == true? "[" + Formatting.ByteArrayToHexString(new byte[] { chrSTX }) + "]": "[No STX]") + "[" + Formatting.ByteArrayToASCIIString(result) + "]" + (hasETX == true ? "[" + Formatting.ByteArrayToHexString(new byte[] { chrETX }) + "]": "[No ETX]")); return(result); }
private static void Transmit(TCPClientStream stream, byte[] txBytes) { byte chrSTX = 0x02; // Start of Text byte chrETX = 0x03; // End of Text //byte[] LRC; short length = (short)(txBytes.Length + 2); byte[] lengthBytes = new byte[] { (byte)(length / 256), (byte)(length % 256) }; byte[] txBytesTCP = Formatting.ConcatArrays(lengthBytes, new byte[] { chrSTX }, txBytes, new byte[] { chrETX }); Logger.Log("Sending: [" + Formatting.ConvertToInt16(lengthBytes) + "]" + "[" + Formatting.ByteArrayToHexString(new byte[] { chrSTX }) + "]" + "[" + Formatting.ByteArrayToASCIIString(txBytes) + "]" + "[" + Formatting.ByteArrayToHexString(new byte[] { chrETX }) + "]"); stream.Write(txBytesTCP); }
private static byte[] Receive(TCPClientStream stream) { byte[] rxBuffer = new Byte[4096]; int countBytesRead = stream.Read(rxBuffer); byte[] lengthBytesReceived = new byte[2]; Array.Copy(rxBuffer, 0, lengthBytesReceived, 0, lengthBytesReceived.Length); int bytesInRxPacket = Formatting.ConvertToInt16(lengthBytesReceived); if (bytesInRxPacket + 2 != countBytesRead) { throw new TCPIPManagerException("Did not receive all expected bytes"); } byte[] result = new byte[bytesInRxPacket]; Array.Copy(rxBuffer, 2, result, 0, result.Length); Logger.Log("Received:[" + bytesInRxPacket + "]" + "[" + Formatting.ByteArrayToHexString(result) + "]"); return(result); }
/* * 14.6 */ private static SignalsEnum EntryPointRA(Kernel2Database database, CardResponse cardResponse, KernelQ qManager, CardQ cardQManager, TornTransactionLogManager tornTransactionLogManager, Stopwatch sw, PublicKeyCertificateManager publicKeyCertificateManager) { #region 14.9 if (!cardResponse.ApduResponse.Succeeded) #endregion { #region 14.10 CommonRoutines.UpdateErrorIndication(database, cardResponse, L1Enum.NOT_SET, L2Enum.STATUS_BYTES, L3Enum.NOT_SET); return(DoInvalidResponse(database, qManager)); #endregion } #region 14.11 bool parsingResult = false; if (cardResponse.ApduResponse.ResponseData.Length > 0 && cardResponse.ApduResponse.ResponseData[0] == 0x77) { EMVComputeCryptographicChecksumResponse response = cardResponse.ApduResponse as EMVComputeCryptographicChecksumResponse; parsingResult = database.ParseAndStoreCardResponse(response.ResponseData); } else { parsingResult = false; } #endregion #region 14.12 if (!parsingResult) #endregion { #region 14.13 CommonRoutines.UpdateErrorIndication(database, cardResponse, L1Enum.NOT_SET, L2Enum.PARSING_ERROR, L3Enum.NOT_SET); return(DoInvalidResponse(database, qManager)); #endregion } #region 14.12.1 CommonRoutines.PostUIOnly(database, qManager, KernelMessageidentifierEnum.CLEAR_DISPLAY, KernelStatusEnum.CARD_READ_SUCCESSFULLY, true); #endregion #region 14.14 if (database.IsEmpty(EMVTagsEnum.APPLICATION_TRANSACTION_COUNTER_ATC_9F36_KRN.Tag) || database.IsEmpty(EMVTagsEnum.POS_CARDHOLDER_INTERACTION_INFORMATION_DF4B_KRN2.Tag)) #endregion { #region 14.17 CommonRoutines.UpdateErrorIndication(database, cardResponse, L1Enum.NOT_SET, L2Enum.CARD_DATA_MISSING, L3Enum.NOT_SET); return(DoInvalidResponse(database, qManager)); #endregion } long nUN = 0; #region 14.15 if (database.IsNotEmpty(EMVTagsEnum.CVC3_TRACK2_9F61_KRN2.Tag)) #endregion { #region 14.16 if (database.IsNotEmpty(EMVTagsEnum.TRACK_1_DATA_56_KRN2.Tag) && (database.IsNotPresent(EMVTagsEnum.CVC3_TRACK1_9F60_KRN2.Tag) || database.IsEmpty(EMVTagsEnum.CVC3_TRACK1_9F60_KRN2.Tag))) #endregion { #region 14.17 CommonRoutines.UpdateErrorIndication(database, cardResponse, L1Enum.NOT_SET, L2Enum.CARD_DATA_MISSING, L3Enum.NOT_SET); return(DoInvalidResponse(database, qManager)); #endregion } #region 14.20 byte pcii = database.Get(EMVTagsEnum.POS_CARDHOLDER_INTERACTION_INFORMATION_DF4B_KRN2).Value[1]; #endregion if ((pcii & 0x10) == 0x10) //OD-CVM verification successful { #region 14.24 nUN = (nUN + 5) % 10; #endregion } else { #region 14.21 long aa = Formatting.BcdToLong(database.Get(EMVTagsEnum.AMOUNT_AUTHORISED_NUMERIC_9F02_KRN).Value); long rctl = database.ReaderContactlessTransactionLismit; if (aa > rctl) #endregion { #region 14.21.1 CommonRoutines.UpdateErrorIndication(database, cardResponse, L1Enum.NOT_SET, L2Enum.CARD_DATA_ERROR, L3Enum.NOT_SET); return(DoInvalidResponse(database, qManager)); #endregion } else { #region 14.25 nUN = (int)Formatting.ConvertToInt32(database.Get(EMVTagsEnum.UNPREDICTABLE_NUMBER_9F37_KRN).Value); #endregion } } #region 14.25.1 database.FailedMSCntr = 0; #endregion #region 14.26 TRACK_2_DATA_9F6B_KRN2 t2d = new TRACK_2_DATA_9F6B_KRN2(database); ushort t2 = Formatting.ConvertToInt16(database.Get(EMVTagsEnum.NATC_TRACK2_9F67_KRN2).Value); TLV PCVC3_TRACK2_9F65_KRN2 = database.Get(EMVTagsEnum.PCVC3_TRACK2_9F65_KRN2); MagBitmap bitmapPCVC3_TRACK2_9F65_KRN2 = new MagBitmap(PCVC3_TRACK2_9F65_KRN2.Value); TLV CVC3_TRACK2_9F61_KRN2 = database.Get(EMVTagsEnum.CVC3_TRACK2_9F61_KRN2); ushort cvc3T2AsShort = Formatting.ConvertToInt16(CVC3_TRACK2_9F61_KRN2.Value.Reverse().ToArray()); string q2LeastSigDigits = Convert.ToString(cvc3T2AsShort); q2LeastSigDigits = q2LeastSigDigits.Substring(q2LeastSigDigits.Length - bitmapPCVC3_TRACK2_9F65_KRN2.NonZeroCount); t2d.Value.DiscretionaryData = Formatting.StringToBcd(bitmapPCVC3_TRACK2_9F65_KRN2.ReplaceValues(Formatting.BcdToString(t2d.Value.DiscretionaryData), q2LeastSigDigits, bitmapPCVC3_TRACK2_9F65_KRN2.NonZeroCount, true), false); TLV PUNATC_TRACK2_9F66_KRN2 = database.Get(EMVTagsEnum.PUNATC_TRACK2_9F66_KRN2); MagBitmap bitmapPUNATC_TRACK2_9F66_KRN2 = new MagBitmap(PUNATC_TRACK2_9F66_KRN2.Value); uint unpredInt = Formatting.ConvertToInt32(database.Get(EMVTagsEnum.UNPREDICTABLE_NUMBER_NUMERIC_9F6A_KRN2).Value.Reverse().ToArray()); string unpredString = Convert.ToString(unpredInt); unpredString = unpredString.Substring(unpredString.Length - database.NUN); t2d.Value.DiscretionaryData = Formatting.StringToBcd(bitmapPUNATC_TRACK2_9F66_KRN2.ReplaceValues(Formatting.BcdToString(t2d.Value.DiscretionaryData), unpredString, database.NUN, true), false); if (t2 != 0) { TLV APPLICATION_TRANSACTION_COUNTER_ATC_9F36_KRN = database.Get(EMVTagsEnum.APPLICATION_TRANSACTION_COUNTER_ATC_9F36_KRN); uint atcAsShort = Formatting.ConvertToInt32(APPLICATION_TRANSACTION_COUNTER_ATC_9F36_KRN.Value.Reverse().ToArray()); string atcAsShortLeastSigDigits = Convert.ToString(atcAsShort); atcAsShortLeastSigDigits = atcAsShortLeastSigDigits.PadLeft(t2, '0').Substring(atcAsShortLeastSigDigits.Length - t2); t2d.Value.DiscretionaryData = Formatting.StringToBcd(bitmapPUNATC_TRACK2_9F66_KRN2.ReplaceValues(Formatting.BcdToString(t2d.Value.DiscretionaryData), atcAsShortLeastSigDigits, t2, false), false); } #endregion #region 14.27 StringBuilder dd = new StringBuilder(Formatting.BcdToString(t2d.Value.DiscretionaryData)); dd[dd.Length - 1] = Convert.ToString(nUN)[0]; t2d.Value.DiscretionaryData = Formatting.StringToBcd(dd.ToString(), false); #endregion t2d.Serialize(); //reserialize in case the length of discretionary data changed t2d.UpdateDB(); #region 14.28 if (database.IsNotEmpty(EMVTagsEnum.TRACK_1_DATA_56_KRN2.Tag)) #endregion { #region 14.29 TRACK_1_DATA_56_KRN2 t1d = new TRACK_1_DATA_56_KRN2(database); ushort t1 = Formatting.ConvertToInt16(database.Get(EMVTagsEnum.NATC_TRACK1_9F64_KRN2).Value); TLV PCVC3_TRACK1_9F62_KRN2 = database.Get(EMVTagsEnum.PCVC3_TRACK1_9F62_KRN2); MagBitmap bitmapPCVC3_TRACK1_9F62_KRN2 = new MagBitmap(PCVC3_TRACK1_9F62_KRN2.Value); TLV CVC3_TRACK1_9F60_KRN2 = database.Get(EMVTagsEnum.CVC3_TRACK1_9F60_KRN2); ushort cvc3T1AsShort = Formatting.ConvertToInt16(CVC3_TRACK1_9F60_KRN2.Value.Reverse().ToArray()); string q1LeastSigDigits = Convert.ToString(cvc3T1AsShort); q1LeastSigDigits = q1LeastSigDigits.Substring(q1LeastSigDigits.Length - bitmapPCVC3_TRACK1_9F62_KRN2.NonZeroCount); t1d.Value.DiscretionaryData = Formatting.ASCIIStringToByteArray(bitmapPCVC3_TRACK1_9F62_KRN2.ReplaceValues(Formatting.ByteArrayToASCIIString(t1d.Value.DiscretionaryData), q1LeastSigDigits, bitmapPCVC3_TRACK1_9F62_KRN2.NonZeroCount, true)); TLV PUNATC_TRACK1_9F63_KRN2 = database.Get(EMVTagsEnum.PUNATC_TRACK1_9F63_KRN2); MagBitmap bitmapPUNATC_TRACK1_9F63_KRN2 = new MagBitmap(PUNATC_TRACK1_9F63_KRN2.Value); t1d.Value.DiscretionaryData = Formatting.ASCIIStringToByteArray(bitmapPUNATC_TRACK1_9F63_KRN2.ReplaceValues(Formatting.ByteArrayToASCIIString(t1d.Value.DiscretionaryData), unpredString, database.NUN, true)); if (t2 != 0) { TLV APPLICATION_TRANSACTION_COUNTER_ATC_9F36_KRN = database.Get(EMVTagsEnum.APPLICATION_TRANSACTION_COUNTER_ATC_9F36_KRN); uint atcAsShort = Formatting.ConvertToInt32(APPLICATION_TRANSACTION_COUNTER_ATC_9F36_KRN.Value.Reverse().ToArray()); string atcAsShortLeastSigDigits = Convert.ToString(atcAsShort); atcAsShortLeastSigDigits = atcAsShortLeastSigDigits.PadLeft(t2, '0').Substring(atcAsShortLeastSigDigits.Length - t1); t2d.Value.DiscretionaryData = Formatting.ASCIIStringToByteArray(bitmapPUNATC_TRACK1_9F63_KRN2.ReplaceValues(Formatting.ByteArrayToASCIIString(t1d.Value.DiscretionaryData), atcAsShortLeastSigDigits, t1, false)); } #endregion #region 14.30 StringBuilder dd1 = new StringBuilder(Formatting.ByteArrayToASCIIString(t1d.Value.DiscretionaryData)); dd1[dd1.Length - 1] = Convert.ToString(nUN)[0]; t1d.Value.DiscretionaryData = Formatting.ASCIIStringToByteArray(dd1.ToString()); #endregion t1d.Serialize(); //reserialize in case the length of discretionary data changed t1d.UpdateDB(); } #region 14.32 Kernel2OutcomeStatusEnum k2OutcomeStatus = Kernel2OutcomeStatusEnum.ONLINE_REQUEST; KernelCVMEnum cvmEnum = KernelCVMEnum.N_A; bool receipt = false; pcii = database.Get(EMVTagsEnum.POS_CARDHOLDER_INTERACTION_INFORMATION_DF4B_KRN2).Value[1]; if ((pcii & 0x10) == 0x10) //OD-CVM verification successful #endregion { #region 14.34 cvmEnum = KernelCVMEnum.CONFIRMATION_CODE_VERIFIED; long aa = Formatting.BcdToLong(database.Get(EMVTagsEnum.AMOUNT_AUTHORISED_NUMERIC_9F02_KRN).Value); long rctl = database.ReaderContactlessTransactionLismit; if (aa > rctl) { receipt = true; } #endregion } else { #region 14.33 cvmEnum = KernelCVMEnum.NO_CVM; #endregion } CommonRoutines.CreateMSDiscretionaryDataRecord(database); CommonRoutines.CreateMSDataRecord(database); return(CommonRoutines.PostOutcomeOnly(database, qManager, k2OutcomeStatus, cvmEnum, receipt)); } else { #region 14.19.1 if (((int)Formatting.ConvertToInt32(database.Get(EMVTagsEnum.POS_CARDHOLDER_INTERACTION_INFORMATION_DF4B_KRN2).Value) & 0x00030F) != 0x000000) #endregion { KernelMessageidentifierEnum k2MessageIdentifier = KernelMessageidentifierEnum.DECLINED; KernelStatusEnum k2Status = KernelStatusEnum.READY_TO_READ; byte[] holdTime = new byte[] { 0x00, 0x00, 0x00 }; #region 14.22 PHONE_MESSAGE_TABLE_DF8131_KRN2 pmt = (PHONE_MESSAGE_TABLE_DF8131_KRN2)database.GetDefault(EMVTagsEnum.PHONE_MESSAGE_TABLE_DF8131_KRN2); foreach (PhoneMessageTableEntry_DF8131 entry in pmt.Value.Entries) { int pcii = (int)Formatting.ConvertToInt32(database.Get(EMVTagsEnum.POS_CARDHOLDER_INTERACTION_INFORMATION_DF4B_KRN2).Value); int pciMask = (int)Formatting.ConvertToInt32(entry.PCIIMask); int pciValue = (int)Formatting.ConvertToInt32(entry.PCIIValue); if ((pciMask & pcii) == pciValue) { k2MessageIdentifier = entry.MessageIdentifier; k2Status = entry.Status; holdTime = database.GetDefault(EMVTagsEnum.MESSAGE_HOLD_TIME_DF812D_KRN2).Value; break; } } #endregion #region 14.21.1 int waitTime = ((2 ^ database.FailedMSCntr) * 300); Task.Delay(TimeSpan.FromMilliseconds(waitTime)).Wait(); #endregion #region 14.21.2 database.FailedMSCntr = Math.Min(database.FailedMSCntr + 1, 5); #endregion #region 14.23 CommonRoutines.CreateMSDiscretionaryDataRecord(database); CommonRoutines.CreateMSDataRecord(database); return(CommonRoutines.PostOutcome(database, qManager, k2MessageIdentifier, k2Status, holdTime, Kernel2OutcomeStatusEnum.END_APPLICATION, Kernel2StartEnum.B, false, KernelMessageidentifierEnum.N_A, L1Enum.NOT_SET, null, L2Enum.NOT_SET, L3Enum.NOT_SET)); #endregion } else { #region 14.19.2.1 int waitTime = ((2 ^ database.FailedMSCntr) * 300); Task.Delay(TimeSpan.FromMilliseconds(waitTime)).Wait(); #endregion #region 14.19.2.2 database.FailedMSCntr = Math.Min(database.FailedMSCntr + 1, 5); #endregion #region 14.19.3 CommonRoutines.CreateMSDiscretionaryDataRecord(database); CommonRoutines.CreateMSDataRecord(database); return(CommonRoutines.PostOutcome(database, qManager, KernelMessageidentifierEnum.DECLINED, KernelStatusEnum.NOT_READY, database.GetDefault(EMVTagsEnum.MESSAGE_HOLD_TIME_DF812D_KRN2).Value, Kernel2OutcomeStatusEnum.END_APPLICATION, Kernel2StartEnum.N_A, true, KernelMessageidentifierEnum.N_A, L1Enum.NOT_SET, null, L2Enum.NOT_SET, L3Enum.NOT_SET)); #endregion } } }
private static SignalsEnum DoPart_E(Kernel2Database database, KernelQ qManager, CardQ cardQManager) { #region 9_10.70 CommonRoutines.CreateEMVDataRecord(database); Kernel2OutcomeStatusEnum k2OutcomeStatus = Kernel2OutcomeStatusEnum.N_A; Kernel2StartEnum k2StartStatus = Kernel2StartEnum.N_A; KernelStatusEnum k2Status = KernelStatusEnum.N_A; KernelMessageidentifierEnum k2MessageIdentifier = KernelMessageidentifierEnum.N_A; byte[] holdTime = new byte[] { 0x00, 0x00, 0x00 }; ValueQualifierEnum valueQualifierEnum = ValueQualifierEnum.NONE; KernelCVMEnum cvmEnum = new OUTCOME_PARAMETER_SET_DF8129_KRN2(database).Value.CVM; byte[] currencyCode = new byte[2]; byte[] valueQualifier = new byte[6]; bool uiRequestOnOutcomePresent; #endregion #region 9_10.71 if (database.IsNotEmpty(EMVTagsEnum.POS_CARDHOLDER_INTERACTION_INFORMATION_DF4B_KRN2.Tag) && ((int)Formatting.ConvertToInt32(database.Get(EMVTagsEnum.POS_CARDHOLDER_INTERACTION_INFORMATION_DF4B_KRN2).Value) & 0x0000030F) != 0x00000000) #endregion { #region 9_10.72 k2OutcomeStatus = Kernel2OutcomeStatusEnum.END_APPLICATION; k2StartStatus = Kernel2StartEnum.B; #endregion #region 9_10.73 PHONE_MESSAGE_TABLE_DF8131_KRN2 pmt = new PHONE_MESSAGE_TABLE_DF8131_KRN2(database.GetDefault(EMVTagsEnum.PHONE_MESSAGE_TABLE_DF8131_KRN2)); foreach (PhoneMessageTableEntry_DF8131 entry in pmt.Value.Entries) { int pcii = (int)Formatting.ConvertToInt32(database.Get(EMVTagsEnum.POS_CARDHOLDER_INTERACTION_INFORMATION_DF4B_KRN2).Value); int pciMask = (int)Formatting.ConvertToInt32(entry.PCIIMask); int pciValue = (int)Formatting.ConvertToInt32(entry.PCIIValue); if ((pciMask & pcii) == pciValue) { k2MessageIdentifier = entry.MessageIdentifier; k2Status = entry.Status; holdTime = database.GetDefault(EMVTagsEnum.MESSAGE_HOLD_TIME_DF812D_KRN2).Value; break; } } #endregion } else { string tt = Formatting.ByteArrayToHexString(database.Get(EMVTagsEnum.TRANSACTION_TYPE_9C_KRN).Value); #region 9_10.74 if ((database.Get(EMVTagsEnum.CRYPTOGRAM_INFORMATION_DATA_9F27_KRN).Value[0] & 0xC0) == 0x40) #endregion { k2OutcomeStatus = Kernel2OutcomeStatusEnum.APPROVED; } else { if ((database.Get(EMVTagsEnum.CRYPTOGRAM_INFORMATION_DATA_9F27_KRN).Value[0] & 0xC0) == 0x80) { k2OutcomeStatus = Kernel2OutcomeStatusEnum.ONLINE_REQUEST; } else { /* * Check if Transaction Type indicates a cash transaction (cash * withdrawal or cash disbursement) or a purchase transaction (purchase * or purchase with cashback). */ if (tt == "01" || tt == "17" || tt == "00" || tt == "09") { if (database.IsNotEmpty(EMVTagsEnum.THIRD_PARTY_DATA_9F6E_KRN2.Tag)) { THIRD_PARTY_DATA_9F6E_KRN tpd = new THIRD_PARTY_DATA_9F6E_KRN(database); TERMINAL_CAPABILITIES_9F33_KRN tc = new TERMINAL_CAPABILITIES_9F33_KRN(database); ushort uid = Formatting.ConvertToInt16(tpd.Value.UniqueIdentifier); ushort dt = Formatting.ConvertToInt16(tpd.Value.DeviceType); if ((uid & 0x8000) == 0x0000 && dt != 0x3030 || tc.Value.ICWithContactsCapable) { k2OutcomeStatus = Kernel2OutcomeStatusEnum.DECLINED; } else { k2OutcomeStatus = Kernel2OutcomeStatusEnum.TRY_ANOTHER_INTERFACE; } } else { k2OutcomeStatus = Kernel2OutcomeStatusEnum.TRY_ANOTHER_INTERFACE; } } else { k2OutcomeStatus = Kernel2OutcomeStatusEnum.END_APPLICATION; } } } #region 9_10.75 k2Status = KernelStatusEnum.NOT_READY; if ((database.Get(EMVTagsEnum.CRYPTOGRAM_INFORMATION_DATA_9F27_KRN).Value[0] & 0xC0) == 0x40) { holdTime = database.GetDefault(EMVTagsEnum.MESSAGE_HOLD_TIME_DF812D_KRN2).Value; if (database.IsNotEmpty(EMVTagsEnum.BALANCE_READ_AFTER_GEN_AC_DF8105_KRN2.Tag)) { valueQualifierEnum = ValueQualifierEnum.BALANCE; valueQualifier = database.Get(EMVTagsEnum.BALANCE_READ_AFTER_GEN_AC_DF8105_KRN2).Value; if (database.IsNotEmpty(EMVTagsEnum.APPLICATION_CURRENCY_CODE_9F42_KRN.Tag)) { currencyCode = database.Get(EMVTagsEnum.APPLICATION_CURRENCY_CODE_9F42_KRN).Value; } } if (cvmEnum == KernelCVMEnum.OBTAIN_SIGNATURE) { k2MessageIdentifier = KernelMessageidentifierEnum.APPROVED_SIGN; } else { k2MessageIdentifier = KernelMessageidentifierEnum.APPROVED; } } else { if ((database.Get(EMVTagsEnum.CRYPTOGRAM_INFORMATION_DATA_9F27_KRN).Value[0] & 0xC0) == 0x80) { holdTime = new byte[] { 0x00, 0x00, 0x00 }; k2MessageIdentifier = KernelMessageidentifierEnum.AUTHORISING_PLEASE_WAIT; } else { if (tt == "01" || tt == "17" || tt == "00" || tt == "09") { holdTime = database.GetDefault(EMVTagsEnum.MESSAGE_HOLD_TIME_DF812D_KRN2).Value; if (database.IsNotEmpty(EMVTagsEnum.THIRD_PARTY_DATA_9F6E_KRN2.Tag)) { THIRD_PARTY_DATA_9F6E_KRN tpd = new THIRD_PARTY_DATA_9F6E_KRN(database); TERMINAL_CAPABILITIES_9F33_KRN tc = new TERMINAL_CAPABILITIES_9F33_KRN(database); ushort uid = Formatting.ConvertToInt16(tpd.Value.UniqueIdentifier); ushort dt = Formatting.ConvertToInt16(tpd.Value.DeviceType); if ((uid & 0x8000) == 0x0000 && dt != 0x3030 || tc.Value.ICWithContactsCapable) { k2MessageIdentifier = KernelMessageidentifierEnum.DECLINED; } else { k2MessageIdentifier = KernelMessageidentifierEnum.INSERT_CARD; } } else { k2MessageIdentifier = KernelMessageidentifierEnum.INSERT_CARD; } } else { holdTime = new byte[] { 0x00, 0x00, 0x00 }; k2MessageIdentifier = KernelMessageidentifierEnum.CLEAR_DISPLAY; } } } #endregion } #region 9_10.76 if (database.IsNotEmpty(EMVTagsEnum.TAGS_TO_WRITE_AFTER_GEN_AC_FF8103_KRN2.Tag)) #endregion { #region 9_10.77 TLV tagToPut = database.TagsToWriteAfterGenACYet.GetFirstAndRemoveFromList(); EMVPutDataRequest request = new EMVPutDataRequest(tagToPut); #endregion #region 9_10.78 cardQManager.EnqueueToInput(new CardRequest(request, CardinterfaceServiceRequestEnum.ADPU)); return(SignalsEnum.WAITING_FOR_PUT_DATA_RESPONSE_AFTER_GEN_AC); #endregion } CommonRoutines.CreateEMVDiscretionaryData(database); #region 9_10.78.1 if (database.IsNotEmpty(EMVTagsEnum.POS_CARDHOLDER_INTERACTION_INFORMATION_DF4B_KRN2.Tag) && ((int)Formatting.ConvertToInt32(database.Get(EMVTagsEnum.POS_CARDHOLDER_INTERACTION_INFORMATION_DF4B_KRN2).Value) & 0x0000030F) != 0x00000000) #endregion { #region 9_10.79 CommonRoutines.PostUIOnly(database, qManager, k2MessageIdentifier, k2Status, true, holdTime); #endregion #region 9_10.80 uiRequestOnOutcomePresent = false; k2Status = KernelStatusEnum.READY_TO_READ; holdTime = new byte[] { 0x00, 0x00, 0x00 }; #endregion } else { #region 9_10.81 uiRequestOnOutcomePresent = true; #endregion } return(CommonRoutines.PostOutcome(database, qManager, k2MessageIdentifier, k2Status, holdTime, k2OutcomeStatus, k2StartStatus, uiRequestOnOutcomePresent, KernelMessageidentifierEnum.N_A, L1Enum.NOT_SET, null, L2Enum.NOT_SET, L3Enum.NOT_SET, valueQualifierEnum, valueQualifier, currencyCode, false, cvmEnum)); }
private static void Do9_10__39(Kernel2Database database) { if (database.IsNotEmpty(EMVTagsEnum.TRACK_2_EQUIVALENT_DATA_57_KRN.Tag)) { TRACK_2_EQUIVALENT_DATA_57_KRN t2ed = new TRACK_2_EQUIVALENT_DATA_57_KRN(database); if (database.Get(EMVTagsEnum.APPLICATION_PRIMARY_ACCOUNT_NUMBER_PAN_5A_KRN).Value.Length <= 8) { t2ed.Value.DiscretionaryData = "0000000000000"; } else { t2ed.Value.DiscretionaryData = "0000000000"; } t2ed.UpdateDB(); if (database.IsNotEmpty(EMVTagsEnum.CERTIFICATION_AUTHORITY_PUBLIC_KEY_INDEX_8F_KRN.Tag) && database.Get(EMVTagsEnum.CERTIFICATION_AUTHORITY_PUBLIC_KEY_INDEX_8F_KRN).Value[0] < 0x0A) { byte capki = database.Get(EMVTagsEnum.CERTIFICATION_AUTHORITY_PUBLIC_KEY_INDEX_8F_KRN).Value[0]; t2ed.Value.DiscretionaryData = capki + t2ed.Value.DiscretionaryData.Substring(1); } byte rrpc = database.Get(EMVTagsEnum.RRP_COUNTER_DF8307_KRN2).Value[0]; t2ed.Value.DiscretionaryData = t2ed.Value.DiscretionaryData[0] + rrpc + t2ed.Value.DiscretionaryData.Substring(2); byte[] drre = new byte[2]; Array.Copy(database.Get(EMVTagsEnum.DEVICE_RELAY_RESISTANCE_ENTROPY_DF8302_KRN2).Value, 0, drre, 0, drre.Length); ushort ddreC = Formatting.ConvertToInt16(drre); string ddreS = Convert.ToString(ddreC); ddreS = ddreS.PadLeft(5, '0'); t2ed.Value.DiscretionaryData = t2ed.Value.DiscretionaryData.Substring(0, 2) + ddreS + t2ed.Value.DiscretionaryData.Substring(7); if (database.Get(EMVTagsEnum.APPLICATION_PRIMARY_ACCOUNT_NUMBER_PAN_5A_KRN).Value.Length <= 8) { byte drre3 = (database.Get(EMVTagsEnum.DEVICE_RELAY_RESISTANCE_ENTROPY_DF8302_KRN2).Value[2]); ushort ddre3C = Formatting.ConvertToInt16(new byte[] { drre3 }); string ddre3S = Convert.ToString(ddre3C); ddre3S = ddre3S.PadLeft(3, '0'); t2ed.Value.DiscretionaryData = t2ed.Value.DiscretionaryData.Substring(0, 7) + ddre3S + t2ed.Value.DiscretionaryData.Substring(10); } ushort mrrpt = Formatting.ConvertToInt16(database.Get(EMVTagsEnum.MEASURED_RELAY_RESISTANCE_PROCESSING_TIME_DF8306_KRN2).Value); mrrpt = (ushort)(mrrpt / 10); if (mrrpt > 999) { mrrpt = 999; } string mrrptS = Convert.ToString(mrrpt); mrrptS = mrrptS.PadLeft(3, '0'); t2ed.Value.DiscretionaryData = t2ed.Value.DiscretionaryData.Substring(0, t2ed.Value.DiscretionaryData.Length - 3) + mrrptS; t2ed.UpdateDB(); } }
/* * 7.3 */ private static SignalsEnum EntryPointRA(Kernel2Database database, CardResponse cardResponse, KernelQ qManager, CardQ cardQManager, TornTransactionLogManager tornTransactionLogManager, Stopwatch sw) { #region 7.9 if (!cardResponse.ApduResponse.Succeeded) #endregion { #region 7.10.1 - 7.10.2 CommonRoutines.CreateMSDiscretionaryDataRecord(database); return(CommonRoutines.PostOutcome(database, qManager, KernelMessageidentifierEnum.ERROR_OTHER_CARD, KernelStatusEnum.NOT_READY, null, Kernel2OutcomeStatusEnum.END_APPLICATION, Kernel2StartEnum.N_A, true, KernelMessageidentifierEnum.ERROR_OTHER_CARD, L1Enum.NOT_SET, cardResponse.ApduResponse.SW12, L2Enum.STATUS_BYTES, L3Enum.NOT_SET)); #endregion } #region 7.11 bool parsingResult = false; if (cardResponse.ApduResponse.ResponseData.Length > 0 && cardResponse.ApduResponse.ResponseData[0] == 0x70) { parsingResult = database.ParseAndStoreCardResponse(cardResponse.ApduResponse.ResponseData); } else { parsingResult = false; } #endregion if (!parsingResult) { #region 7.13.1 CommonRoutines.CreateMSDiscretionaryDataRecord(database); return(CommonRoutines.PostOutcome(database, qManager, KernelMessageidentifierEnum.ERROR_OTHER_CARD, KernelStatusEnum.NOT_READY, null, Kernel2OutcomeStatusEnum.END_APPLICATION, Kernel2StartEnum.N_A, true, KernelMessageidentifierEnum.ERROR_OTHER_CARD, L1Enum.NOT_SET, null, L2Enum.PARSING_ERROR, L3Enum.NOT_SET)); #endregion } #region 7.14 if ((cardResponse.ApduResponse as EMVReadRecordResponse).GetResponseTags().IsPresent(EMVTagsEnum.UDOL_9F69_KRN2.Tag)) #endregion { #region 7.15 TLV udol = (cardResponse.ApduResponse as EMVReadRecordResponse).GetResponseTags().Get(EMVTagsEnum.UDOL_9F69_KRN2.Tag); foreach (TLV tlv in udol.Children) { if (database.IsEmpty(tlv.Tag.TagLable)) { database.Get(EMVTagsEnum.DATA_NEEDED_DF8106_KRN2).Children.AddToList(tlv); } } #endregion } #region 7.16 database.ActiveAFL.Value.Entries.RemoveAt(0); #endregion #region 7.17 if (database.ActiveAFL.Value.Entries.Count != 0) #endregion { #region 7.18 - 7.19 EMVReadRecordRequest request = new EMVReadRecordRequest(database.ActiveAFL.Value.Entries[0].SFI, database.ActiveAFL.Value.Entries[0].FirstRecordNumber); cardQManager.EnqueueToInput(new CardRequest(request, CardinterfaceServiceRequestEnum.ADPU)); return(SignalsEnum.WAITING_FOR_MAG_STRIPE_READ_RECORD_RESPONSE); #endregion } #region 7.20 if (database.IsEmpty(EMVTagsEnum.TRACK_2_DATA_9F6B_KRN2.Tag) || database.IsEmpty(EMVTagsEnum.PUNATC_TRACK2_9F66_KRN2.Tag) || database.IsEmpty(EMVTagsEnum.PCVC3_TRACK2_9F65_KRN2.Tag) || database.IsEmpty(EMVTagsEnum.NATC_TRACK2_9F67_KRN2.Tag)) #endregion { #region 7.21.1 CommonRoutines.CreateMSDiscretionaryDataRecord(database); return(CommonRoutines.PostOutcome(database, qManager, KernelMessageidentifierEnum.ERROR_OTHER_CARD, KernelStatusEnum.NOT_READY, null, Kernel2OutcomeStatusEnum.END_APPLICATION, Kernel2StartEnum.N_A, true, KernelMessageidentifierEnum.ERROR_OTHER_CARD, L1Enum.NOT_SET, null, L2Enum.CARD_DATA_MISSING, L3Enum.NOT_SET)); #endregion } #region 7.22 TLV punatc2 = database.Get(EMVTagsEnum.PUNATC_TRACK2_9F66_KRN2); int natc2 = Formatting.ConvertToInt16(database.Get(EMVTagsEnum.NATC_TRACK2_9F67_KRN2).Value); int nonZeroBits = 0; for (int i = 0; i < 8; i++) { if (((punatc2.Value[0] >> i) & 0x01) == 0x01) { nonZeroBits++; } if (((punatc2.Value[1] >> i) & 0x01) == 0x01) { nonZeroBits++; } } int check2 = nonZeroBits - natc2; database.NUN = check2; if (check2 < 0 && check2 > 8) { #region 7.24.1 return(DoInvalidResponse(database, qManager)); #endregion } if (database.IsNotEmpty(EMVTagsEnum.TRACK_1_DATA_56_KRN2.Tag)) { int check1 = 0; if (database.IsNotEmpty(EMVTagsEnum.NATC_TRACK1_9F64_KRN2.Tag) && database.IsNotEmpty(EMVTagsEnum.PUNATC_TRACK1_9F63_KRN2.Tag)) { TLV punatc1 = database.Get(EMVTagsEnum.PUNATC_TRACK1_9F63_KRN2); int natc1 = Formatting.ConvertToInt16(database.Get(EMVTagsEnum.NATC_TRACK1_9F64_KRN2).Value); int nonZeroBits1 = 0; for (int i = 0; i < 8; i++) { if (((punatc1.Value[0] >> i) & 0x01) == 0x01) { nonZeroBits1++; } if (((punatc1.Value[1] >> i) & 0x01) == 0x01) { nonZeroBits1++; } if (((punatc1.Value[2] >> i) & 0x01) == 0x01) { nonZeroBits1++; } if (((punatc1.Value[3] >> i) & 0x01) == 0x01) { nonZeroBits1++; } if (((punatc1.Value[4] >> i) & 0x01) == 0x01) { nonZeroBits1++; } if (((punatc1.Value[5] >> i) & 0x01) == 0x01) { nonZeroBits1++; } } check1 = nonZeroBits1 - natc1; } else { #region 7.24.1 return(DoInvalidResponse(database, qManager)); #endregion } if ((database.IsNotPresent(EMVTagsEnum.NATC_TRACK1_9F64_KRN2.Tag) || database.IsEmpty(EMVTagsEnum.NATC_TRACK1_9F64_KRN2.Tag)) || (database.IsNotPresent(EMVTagsEnum.PCVC3_TRACK1_9F62_KRN2.Tag) || database.IsEmpty(EMVTagsEnum.PCVC3_TRACK1_9F62_KRN2.Tag)) || (database.IsNotPresent(EMVTagsEnum.PUNATC_TRACK1_9F63_KRN2.Tag) || database.IsEmpty(EMVTagsEnum.PUNATC_TRACK1_9F63_KRN2.Tag)) || check1 != check2 ) { #region 7.24.1 return(DoInvalidResponse(database, qManager)); #endregion } } #region 7.23 TRACK_2_DATA_9F6B_KRN2 t2d = new TRACK_2_DATA_9F6B_KRN2(database); TLV ddCardT2 = database.Get(EMVTagsEnum.DD_CARD_TRACK2_DF812B_KRN2); if (ddCardT2 == null) { ddCardT2 = TLV.Create(EMVTagsEnum.DD_CARD_TRACK2_DF812B_KRN2.Tag); } ddCardT2.Value = t2d.Value.DiscretionaryData; if (database.IsNotEmpty(EMVTagsEnum.TRACK_1_DATA_56_KRN2.Tag)) { TRACK_1_DATA_56_KRN2 t1d = new TRACK_1_DATA_56_KRN2(database); TLV ddCardT1 = database.Get(EMVTagsEnum.DD_CARD_TRACK1_DF812A_KRN2); if (ddCardT1 == null) { ddCardT1 = TLV.Create(EMVTagsEnum.DD_CARD_TRACK1_DF812A_KRN2.Tag); } ddCardT1.Value = t1d.Value.DiscretionaryData; } return(State_7_8_CommonProcessing.DoCommonProcessing("State_7_WaitingForMagStripeReadRecordResponse", database, qManager, cardQManager, sw)); #endregion #endregion }
/* * SR1.9 - SR1.32 */ private static SignalsEnum EntryPointRA(Kernel2Database database, CardResponse cardResponse, KernelQ qManager, CardQ cardQManager, Stopwatch sw) { #region SR1.10 sw.Stop(); #endregion #region SR1.11 if (!cardResponse.ApduResponse.Succeeded) #endregion { #region SR1.12 - SR1.13 CommonRoutines.CreateEMVDiscretionaryData(database); return(CommonRoutines.PostOutcome(database, qManager, KernelMessageidentifierEnum.ERROR_OTHER_CARD, KernelStatusEnum.NOT_READY, null, Kernel2OutcomeStatusEnum.END_APPLICATION, Kernel2StartEnum.N_A, true, KernelMessageidentifierEnum.ERROR_OTHER_CARD, L1Enum.NOT_SET, cardResponse.ApduResponse.SW12, L2Enum.STATUS_BYTES, L3Enum.NOT_SET)); #endregion } #region SR1.14 bool parsingResult = false; EMVExchangeRelayResistanceDataResponse emverrdr = (EMVExchangeRelayResistanceDataResponse)cardResponse.ApduResponse; if ((cardResponse.ApduResponse.ResponseData.Length > 11 && cardResponse.ApduResponse.ResponseData[0] == 0x80))// && cardResponse.ApduResponse.ResponseData.Length == 10) { database.AddListToList(emverrdr.GetResponseTags()); parsingResult = true; } #region SR1.15 if (!parsingResult) #endregion { #region SR1.16, SR1.17 CommonRoutines.CreateEMVDiscretionaryData(database); return(CommonRoutines.PostOutcome(database, qManager, KernelMessageidentifierEnum.ERROR_OTHER_CARD, KernelStatusEnum.NOT_READY, null, Kernel2OutcomeStatusEnum.END_APPLICATION, Kernel2StartEnum.N_A, true, KernelMessageidentifierEnum.ERROR_OTHER_CARD, L1Enum.NOT_SET, null, L2Enum.PARSING_ERROR, L3Enum.NOT_SET)); #endregion } #region SR1.18 int a = Formatting.ConvertToInt16(database.Get(EMVTagsEnum.TERMINAL_EXPECTED_TRANSMISSION_TIME_FOR_RELAY_RESISTANCE_CAPDU_DF8134_KRN2).Value); int b = Formatting.ConvertToInt16(database.Get(EMVTagsEnum.TERMINAL_EXPECTED_TRANSMISSION_TIME_FOR_RELAY_RESISTANCE_RAPDU_DF8135_KRN2).Value); int c = Formatting.ConvertToInt16(database.Get(EMVTagsEnum.DEVICE_ESTIMATED_TRANSMISSION_TIME_FOR_RELAY_RESISTANCE_RAPDU_DF8305_KRN2).Value); int measuredRelayResistanceProcessingTime = ((int)sw.ElapsedMilliseconds / 100) - a - Math.Min(c, b); #endregion int d = Formatting.ConvertToInt16(database.Get(EMVTagsEnum.MINIMUM_RELAY_RESISTANCE_GRACE_PERIOD_DF8132_KRN2).Value); int e = Formatting.ConvertToInt16(database.Get(EMVTagsEnum.MIN_TIME_FOR_PROCESSING_RELAY_RESISTANCE_APDU_DF8303_KRN2).Value); #region SR1.19 if (measuredRelayResistanceProcessingTime < (e - d)) #endregion { #region SR1.20, SR1.21 CommonRoutines.CreateEMVDiscretionaryData(database); return(CommonRoutines.PostOutcome(database, qManager, KernelMessageidentifierEnum.ERROR_OTHER_CARD, KernelStatusEnum.NOT_READY, null, Kernel2OutcomeStatusEnum.END_APPLICATION, Kernel2StartEnum.N_A, true, KernelMessageidentifierEnum.ERROR_OTHER_CARD, L1Enum.NOT_SET, null, L2Enum.CARD_DATA_ERROR, L3Enum.NOT_SET)); #endregion } int g = Formatting.ConvertToInt16(database.Get(EMVTagsEnum.MAX_TIME_FOR_PROCESSING_RELAY_RESISTANCE_APDU_DF8304_KRN2).Value); int f = Formatting.ConvertToInt16(database.Get(EMVTagsEnum.RRP_COUNTER_DF8307_KRN2).Value); #region SR1.22 if ((f < 2) && (measuredRelayResistanceProcessingTime > (g + d))) #endregion { #region SR1.23 - SR1.27 database.Get(EMVTagsEnum.UNPREDICTABLE_NUMBER_9F37_KRN).Value = Formatting.GetRandomNumber(); database.Get(EMVTagsEnum.TERMINAL_RELAY_RESISTANCE_ENTROPY_DF8301_KRN2).Value = database.Get(EMVTagsEnum.UNPREDICTABLE_NUMBER_9F37_KRN).Value; f++; database.Get(EMVTagsEnum.RRP_COUNTER_DF8307_KRN2).Value = BitConverter.GetBytes(f); EMVExchangeRelayResistanceDataRequest request = new EMVExchangeRelayResistanceDataRequest(database.Get(EMVTagsEnum.TERMINAL_RELAY_RESISTANCE_ENTROPY_DF8301_KRN2).Value); sw.Start(); cardQManager.EnqueueToInput(new CardRequest(request, CardinterfaceServiceRequestEnum.ADPU)); return(SignalsEnum.WAITING_FOR_EXCHANGE_RELAY_RESISTANCE_DATA_RESPONSE); #endregion } TERMINAL_VERIFICATION_RESULTS_95_KRN tvr = new TERMINAL_VERIFICATION_RESULTS_95_KRN(database); #region SR1.28 if (measuredRelayResistanceProcessingTime > (g + d)) #endregion { #region SR1.29 tvr.Value.RelayResistanceTimeLimitsExceeded = true; #endregion } int h = Formatting.ConvertToInt16(database.Get(EMVTagsEnum.RELAY_RESISTANCE_TRANSMISSION_TIME_MISMATCH_THRESHOLD_DF8137_KRN2).Value); int i = Formatting.ConvertToInt16(database.Get(EMVTagsEnum.RELAY_RESISTANCE_ACCURACY_THRESHOLD_DF8136_KRN2).Value); #region SR1.30 if (((c / b) * 100 < h) || ((b / c) * 100 < h) || ((measuredRelayResistanceProcessingTime - e) > i)) { tvr.Value.RelayResistanceThresholdExceeded = true; } else { tvr.Value.RelayResistancePerformedEnum = RelayResistancePerformedEnum.RRP_PERFORMED; } tvr.UpdateDB(); #endregion #endregion return(State_3_R1_CommonProcessing.DoCommonProcessing("State_R1_ExchangeRelayResistanceData", database, qManager, cardQManager, cardResponse)); }
private static SignalsEnum ProcessNextCVM(KernelDatabase database, KernelQ qManager, CardQ cardQManager, Stopwatch sw) { CARDHOLDER_VERIFICATION_METHOD_CVM_LIST_8E_KRN cvl = new CARDHOLDER_VERIFICATION_METHOD_CVM_LIST_8E_KRN(database); CARDHOLDER_VERIFICATION_METHOD_CVM_RESULTS_9F34_KRN cvr = new CARDHOLDER_VERIFICATION_METHOD_CVM_RESULTS_9F34_KRN(database); bool goToNextCVM = false; if (cvr.Value.GetCVMPerformed() == CVMCode.EncipheredPINVerifiedOnline) { if (cvr.Value.GetCVMResult() == CVMResult.Failed) { goToNextCVM = true; } } else { //if a previously run CVM failed then state returns here and we try the next CVM if (cvr.Value.GetCVMResult() != CVMResult.Success) { goToNextCVM = true; } } if (goToNextCVM && database.CVMCurrentlySelectedCounter < cvl.Value.CardHolderVerificationRules.Count) { //if previous cvm was offline pin, check pin try counter if (cvr.Value.GetCVMPerformed() == CVMCode.EncipheredPINVerificationPerformedByICC || cvr.Value.GetCVMPerformed() == CVMCode.EncipheredPINVerificationPerformedByICCAndSignature_Paper || cvr.Value.GetCVMPerformed() == CVMCode.PlaintextPINVerificationPerformedByICC || cvr.Value.GetCVMPerformed() == CVMCode.PlaintextPINVerificationPerformedByICCAndSignature_Paper) { TLV pinTryCounterTLV = database.Get(EMVTagsEnum.PERSONAL_IDENTIFICATION_NUMBER_PIN_TRY_COUNTER_9F17_KRN); if (pinTryCounterTLV != null) { ushort pinTryCounter = Formatting.ConvertToInt16(pinTryCounterTLV.Value); if (pinTryCounter > 1) //at this point the pin try counter on the card is 0, we are always 1 behind { qManager.EnqueueToOutput(new KernelPinResponse()); return(SignalsEnum.WAITING_FOR_PIN_RESPONSE); } } } #region Book 3 Section 10.5 CVMSelection_7_5.CVMSelection(database, new Func <bool>(() => { return(true); })); cvr = new CARDHOLDER_VERIFICATION_METHOD_CVM_RESULTS_9F34_KRN(database);//update after calling cvm selection #endregion if (cvr.Value.GetCVMPerformed() == CVMCode.EncipheredPINVerificationPerformedByICC || cvr.Value.GetCVMPerformed() == CVMCode.EncipheredPINVerificationPerformedByICCAndSignature_Paper || cvr.Value.GetCVMPerformed() == CVMCode.PlaintextPINVerificationPerformedByICC || cvr.Value.GetCVMPerformed() == CVMCode.PlaintextPINVerificationPerformedByICCAndSignature_Paper || cvr.Value.GetCVMPerformed() == CVMCode.EncipheredPINVerifiedOnline) { qManager.EnqueueToOutput(new KernelPinResponse()); return(SignalsEnum.WAITING_FOR_PIN_RESPONSE); } if (cvr.Value.GetCVMResult() == CVMResult.Failed) { return(SignalsEnum.WAITING_FOR_CVM_PROCESSING); } } if (cvr.Value.GetCVMPerformed() != CVMCode.NoCVMDone) { TRANSACTION_STATUS_INFORMATION_9B_KRN tsi = new TRANSACTION_STATUS_INFORMATION_9B_KRN(database); tsi.Value.CardholderVerificationWasPerformed = true; tsi.UpdateDB(); } #region Book 3 Section 10.6 //Terminal Risk Management TLV lcol = database.Get(EMVTagsEnum.LOWER_CONSECUTIVE_OFFLINE_LIMIT_9F14_KRN); TLV ucol = database.Get(EMVTagsEnum.UPPER_CONSECUTIVE_OFFLINE_LIMIT_9F23_KRN); if (lcol != null && ucol != null) { EMVGetDataRequest requestATC = new EMVGetDataRequest(Formatting.HexStringToByteArray(EMVTagsEnum.APPLICATION_TRANSACTION_COUNTER_ATC_9F36_KRN.Tag)); EMVGetDataRequest requestLastOnlineATC = new EMVGetDataRequest(Formatting.HexStringToByteArray(EMVTagsEnum.LAST_ONLINE_APPLICATION_TRANSACTION_COUNTER_ATC_REGISTER_9F13_KRN.Tag)); cardQManager.EnqueueToInput(new CardRequest(requestATC, CardinterfaceServiceRequestEnum.ADPU)); cardQManager.EnqueueToInput(new CardRequest(requestLastOnlineATC, CardinterfaceServiceRequestEnum.ADPU)); } //Get Floor Limit Data if (database.IsEmpty(EMVTagsEnum.TERMINAL_FLOOR_LIMIT_9F1B_KRN.Tag)) { DATA_NEEDED_DF8106_KRN2 dataNeeded = new DATA_NEEDED_DF8106_KRN2(database); dataNeeded.Value.Tags.Add(EMVTagsEnum.TERMINAL_FLOOR_LIMIT_9F1B_KRN.Tag); dataNeeded.UpdateDB(); CommonRoutines.PostDEK(database, qManager); database.Get(EMVTagsEnum.DATA_TO_SEND_FF8104_KRN2).Initialize(); database.Get(EMVTagsEnum.DATA_NEEDED_DF8106_KRN2).Initialize(); } qManager.EnqueueToOutput(new KernelTRMResponse()); return(SignalsEnum.WAITING_FOR_TERMINAL_RISK_MANAGEMENT); #endregion }