public static SignalsEnum EndOnTCorAAC(KernelDatabase database, KernelQ qManager, CardQ cardQManager) { 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; string tt = Formatting.ByteArrayToHexString(database.Get(EMVTagsEnum.TRANSACTION_TYPE_9C_KRN).Value); if ((database.Get(EMVTagsEnum.CRYPTOGRAM_INFORMATION_DATA_9F27_KRN).Value[0] & 0xC0) == 0x40) { k2OutcomeStatus = Kernel2OutcomeStatusEnum.APPROVED; } else { if ((database.Get(EMVTagsEnum.CRYPTOGRAM_INFORMATION_DATA_9F27_KRN).Value[0] & 0xC0) == 0x80) { throw new EMVProtocolException("Invalid state in EndOnTCorAAC"); } else { k2OutcomeStatus = Kernel2OutcomeStatusEnum.DECLINED; } } 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 (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) { throw new EMVProtocolException("Invalid state in EndOnTCorAAC"); } else { k2MessageIdentifier = KernelMessageidentifierEnum.DECLINED; } } CommonRoutines.CreateEMVDiscretionaryData(database); uiRequestOnOutcomePresent = true; 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 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 SignalsEnum EntryPointRA(Kernel1Database database, CardResponse cardResponse, KernelQ qManager, CardQ cardQManager, Stopwatch sw, PublicKeyCertificateManager publicKeyCertificateManager) { if (!cardResponse.ApduResponse.Succeeded) { return(CommonRoutines.PostOutcome(database, qManager, KernelMessageidentifierEnum.N_A, KernelStatusEnum.N_A, null, Kernel2OutcomeStatusEnum.END_APPLICATION, Kernel2StartEnum.N_A, true, KernelMessageidentifierEnum.ERROR_OTHER_CARD, L1Enum.NOT_SET, cardResponse.ApduResponse.SW12, L2Enum.STATUS_BYTES, L3Enum.NOT_SET)); } bool parsingResult = false; EMVGenerateACResponse response = cardResponse.ApduResponse as EMVGenerateACResponse; if (cardResponse.ApduResponse.ResponseData.Length > 0 && cardResponse.ApduResponse.ResponseData[0] == 0x77) { parsingResult = database.ParseAndStoreCardResponse(response.ResponseData); } else { if (cardResponse.ApduResponse.ResponseData.Length < 11 || cardResponse.ApduResponse.ResponseData.Length > 43 || database.IsNotEmpty(EMVTagsEnum.CRYPTOGRAM_INFORMATION_DATA_9F27_KRN.Tag) || database.IsNotEmpty(EMVTagsEnum.APPLICATION_TRANSACTION_COUNTER_ATC_9F36_KRN.Tag) || database.IsNotEmpty(EMVTagsEnum.APPLICATION_CRYPTOGRAM_9F26_KRN.Tag) || (cardResponse.ApduResponse.ResponseData.Length > 11 && database.IsNotEmpty(EMVTagsEnum.ISSUER_APPLICATION_DATA_9F10_KRN.Tag)) ) { parsingResult = false; } else { database.AddToList(TLV.Create(EMVTagsEnum.CRYPTOGRAM_INFORMATION_DATA_9F27_KRN.Tag, response.CryptogramInformationData.Value)); database.AddToList(TLV.Create(EMVTagsEnum.APPLICATION_TRANSACTION_COUNTER_ATC_9F36_KRN.Tag, response.ApplicationTransactionCounter.Value)); database.AddToList(TLV.Create(EMVTagsEnum.APPLICATION_CRYPTOGRAM_9F26_KRN.Tag, response.ApplicationCryptogram.Value)); database.AddToList(TLV.Create(EMVTagsEnum.ISSUER_APPLICATION_DATA_9F10_KRN.Tag, response.IssuerApplicationData.Value)); parsingResult = true; } } if (!parsingResult) { return(CommonRoutines.PostOutcome(database, qManager, KernelMessageidentifierEnum.N_A, KernelStatusEnum.N_A, null, Kernel2OutcomeStatusEnum.END_APPLICATION, Kernel2StartEnum.N_A, true, KernelMessageidentifierEnum.ERROR_OTHER_CARD, L1Enum.NOT_SET, null, L2Enum.PARSING_ERROR, L3Enum.NOT_SET)); } if (!(database.IsNotEmpty(EMVTagsEnum.APPLICATION_TRANSACTION_COUNTER_ATC_9F36_KRN.Tag) && database.IsNotEmpty(EMVTagsEnum.CRYPTOGRAM_INFORMATION_DATA_9F27_KRN.Tag))) { return(CommonRoutines.PostOutcome(database, qManager, KernelMessageidentifierEnum.N_A, KernelStatusEnum.N_A, null, Kernel2OutcomeStatusEnum.END_APPLICATION, Kernel2StartEnum.N_A, true, KernelMessageidentifierEnum.ERROR_OTHER_CARD, L1Enum.NOT_SET, null, L2Enum.CARD_DATA_MISSING, L3Enum.NOT_SET)); } #region 3.5.2.2 TLV cidTLV = database.Get(EMVTagsEnum.CRYPTOGRAM_INFORMATION_DATA_9F27_KRN); byte cid = cidTLV.Value[0]; cid = (byte)(cid >> 6); if (cid != (byte)ACTypeEnum.ARQC) { #region 3.10.3.1 return(CommonRoutines.PostOutcome(database, qManager, KernelMessageidentifierEnum.ERROR_OTHER_CARD, KernelStatusEnum.PROCESSING_ERROR, null, Kernel2OutcomeStatusEnum.END_APPLICATION, Kernel2StartEnum.N_A, true, KernelMessageidentifierEnum.ERROR_OTHER_CARD, L1Enum.NOT_SET, null, L2Enum.CARD_DATA_ERROR, L3Enum.NOT_SET)); #endregion } #endregion #region 3.6.1.1 CommonRoutines.PostUIOnly(database, qManager, KernelMessageidentifierEnum.CLEAR_DISPLAY, KernelStatusEnum.CARD_READ_SUCCESSFULLY, true); #endregion SignalsEnum result = DoProcessingRestrictions(database, qManager); if (result != SignalsEnum.NONE) { return(result); } #region 3.9 KernelCVMEnum cvm = KernelCVMEnum.N_A; if (database.ProcessingIndicatorsForSelected.ReaderCVMRequiredLimitExceeded) { DoCVMProcessing(database, (ACTypeEnum)GetEnum(typeof(ACTypeEnum), cid)); OUTCOME_PARAMETER_SET_DF8129_KRN2 ops = new OUTCOME_PARAMETER_SET_DF8129_KRN2(database); if (ops.Value.CVM == KernelCVMEnum.NO_CVM) { #region 3.10.3.1 return(CommonRoutines.PostOutcome(database, qManager, KernelMessageidentifierEnum.ERROR_OTHER_CARD, KernelStatusEnum.PROCESSING_ERROR, null, Kernel2OutcomeStatusEnum.END_APPLICATION, Kernel2StartEnum.N_A, true, KernelMessageidentifierEnum.ERROR_OTHER_CARD, L1Enum.NOT_SET, null, L2Enum.CARD_DATA_ERROR, L3Enum.NOT_SET)); #endregion } cvm = ops.Value.CVM; } #endregion #region 3.9.2 CommonRoutines.CreateEMVDataRecord(database); CommonRoutines.CreateEMVDiscretionaryData(database); return(CommonRoutines.PostOutcome(database, qManager, KernelMessageidentifierEnum.AUTHORISING_PLEASE_WAIT, KernelStatusEnum.NOT_READY, null, Kernel2OutcomeStatusEnum.ONLINE_REQUEST, Kernel2StartEnum.N_A, true, KernelMessageidentifierEnum.N_A, L1Enum.NOT_SET, null, L2Enum.NOT_SET, L3Enum.NOT_SET, ValueQualifierEnum.NONE, null, null, false, cvm)); #endregion }