Example #1
0
        private static SignalsEnum DoEMVMode(Kernel3Database database, KernelQ qManager, CardQ cardQManager, CardResponse cardResponse, Stopwatch sw, PublicKeyCertificateManager publicKeyCertificateManager, CardExceptionManager cardExceptionManager)
        {
            TLV aflRaw = database.Get(EMVTagsEnum.APPLICATION_FILE_LOCATOR_AFL_94_KRN);

            if (aflRaw != null)
            {
                List <byte[]> bytes = new List <byte[]>
                {
                    new byte[] { (byte)aflRaw.Value.Length },
                    aflRaw.Value
                };
                database.ActiveAFL.Value.Deserialize(bytes.SelectMany(a => a).ToArray(), 0);
                return(K1K3.State_3_R1_CommonProcessing.DoCommonProcessing("State_3_WaitingForGPOResponse", database, qManager, cardQManager, cardResponse));
            }
            else
            {
                database.NextCommandEnum = NextCommandEnum.NONE;
                return(State_3_4_CommonProcessing.DoCommonProcessing("State_3_WaitingForGPOResponse", database, qManager, cardQManager, sw, publicKeyCertificateManager, cardExceptionManager));
            }
        }
Example #2
0
        public static SignalsEnum Execute(
            Kernel3Database database,
            KernelQ qManager,
            CardQ cardQManager,
            Stopwatch sw,
            PublicKeyCertificateManager publicKeyCertificateManager,
            CardExceptionManager cardExceptionManager)
        {
            if (qManager.GetOutputQCount() > 0) //there is a pending request to the terminal
            {
                KernelRequest kernel1Request = qManager.DequeueFromInput(false);
                switch (kernel1Request.KernelTerminalReaderServiceRequestEnum)
                {
                case KernelTerminalReaderServiceRequestEnum.STOP:
                    return(EntryPointSTOP(database, qManager));

                case KernelTerminalReaderServiceRequestEnum.DET:
                    return(EntryPointDET(database, kernel1Request));

                default:
                    throw new EMVProtocolException("Invalid Kernel1TerminalReaderServiceRequestEnum in State_3_WaitingForGPOResponse:" + Enum.GetName(typeof(CardInterfaceServiceResponseEnum), kernel1Request.KernelTerminalReaderServiceRequestEnum));
                }
            }
            else
            {
                CardResponse cardResponse = cardQManager.DequeueFromOutput(false);
                switch (cardResponse.CardInterfaceServiceResponseEnum)
                {
                case CardInterfaceServiceResponseEnum.RA:
                    return(EntryPointRA(database, cardResponse, qManager, cardQManager, sw, publicKeyCertificateManager, cardExceptionManager));

                case CardInterfaceServiceResponseEnum.L1RSP:
                    return(EntryPointL1RSP(database, cardResponse, qManager));

                default:
                    throw new EMVProtocolException("Invalid Kernel1CardinterfaceServiceResponseEnum in State_3_WaitingForGPOResponse:" + Enum.GetName(typeof(CardInterfaceServiceResponseEnum), cardResponse.CardInterfaceServiceResponseEnum));
                }
            }
        }
Example #3
0
 public Kernel3(TransactionTypeEnum tt, CardQProcessor cardQProcessor, PublicKeyCertificateManager publicKeyCertificateManager, EntryPointPreProcessingIndicators processingIndicatorsForSelected, CardExceptionManager cardExceptionManager, IConfigurationProvider configProvider)
     : base(cardQProcessor, publicKeyCertificateManager, processingIndicatorsForSelected, cardExceptionManager, configProvider)
 {
     database = new Kernel3Database(processingIndicatorsForSelected, publicKeyCertificateManager);
     database.InitializeDefaultDataObjects(tt, configProvider);
 }
Example #4
0
        private static SignalsEnum EntryPointRA(Kernel3Database database, CardResponse cardResponse, KernelQ qManager, CardQ cardQManager, Stopwatch sw, PublicKeyCertificateManager publicKeyCertificateManager, CardExceptionManager cardExceptionManager)
        {
            #region 5.2.2.2
            if (!cardResponse.ApduResponse.Succeeded)
            {
                TERMINAL_TRANSACTION_QUALIFIERS_9F66_KRN ttq = new TERMINAL_TRANSACTION_QUALIFIERS_9F66_KRN(database);
                if (cardResponse.ApduResponse.SW1 == 0x69 && cardResponse.ApduResponse.SW2 == 0x84 && ttq.Value.EMVModeSupported)
                {
                    return(CommonRoutines.PostOutcome(database, qManager,
                                                      KernelMessageidentifierEnum.INSERT_CARD,
                                                      KernelStatusEnum.PROCESSING_ERROR,
                                                      null,
                                                      Kernel2OutcomeStatusEnum.TRY_ANOTHER_INTERFACE,
                                                      Kernel2StartEnum.N_A,
                                                      true,
                                                      KernelMessageidentifierEnum.INSERT_CARD,
                                                      L1Enum.NOT_SET,
                                                      cardResponse.ApduResponse.SW12,
                                                      L2Enum.STATUS_BYTES,
                                                      L3Enum.NOT_SET));
                }
                if (cardResponse.ApduResponse.SW1 == 0x69 && cardResponse.ApduResponse.SW2 == 0x85)
                {
                    return(CommonRoutines.PostOutcome(database, qManager,
                                                      KernelMessageidentifierEnum.N_A,
                                                      KernelStatusEnum.N_A,
                                                      null,
                                                      Kernel2OutcomeStatusEnum.SELECT_NEXT,
                                                      Kernel2StartEnum.C,
                                                      null,
                                                      KernelMessageidentifierEnum.N_A,
                                                      L1Enum.NOT_SET,
                                                      null,
                                                      L2Enum.NOT_SET,
                                                      L3Enum.NOT_SET));
                }
                if (cardResponse.ApduResponse.SW1 == 0x69 && cardResponse.ApduResponse.SW2 == 0x86 && ttq.Value.EMVModeSupported)
                {
                    return(CommonRoutines.PostOutcome(database, qManager,
                                                      KernelMessageidentifierEnum.SEE_PHONE,
                                                      KernelStatusEnum.READY_TO_READ,
                                                      new byte[] { 0x00, 0x00, 0x0D },
                                                      Kernel2OutcomeStatusEnum.END_APPLICATION,
                                                      Kernel2StartEnum.B,
                                                      true,
                                                      KernelMessageidentifierEnum.SEE_PHONE,
                                                      L1Enum.NOT_SET,
                                                      cardResponse.ApduResponse.SW12,
                                                      L2Enum.STATUS_BYTES,
                                                      L3Enum.NOT_SET));
                }

                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,
                                                  cardResponse.ApduResponse.SW12,
                                                  L2Enum.STATUS_BYTES,
                                                  L3Enum.NOT_SET));
            }
            #endregion

            bool parsingResult = false;
            if (cardResponse.ApduResponse.ResponseData.Length > 0 && cardResponse.ApduResponse.ResponseData[0] == 0x77)
            {
                EMVGetProcessingOptionsResponse response = cardResponse.ApduResponse as EMVGetProcessingOptionsResponse;
                parsingResult = database.ParseAndStoreCardResponse(response.ResponseData);
            }
            else
            {
                if (cardResponse.ApduResponse.ResponseData.Length > 0 && cardResponse.ApduResponse.ResponseData[0] == 0x80)
                {
                    EMVGetProcessingOptionsResponse response = cardResponse.ApduResponse as EMVGetProcessingOptionsResponse;
                    if (cardResponse.ApduResponse.ResponseData.Length < 6 ||
                        ((cardResponse.ApduResponse.ResponseData.Length - 2) % 4 != 0) ||
                        database.IsNotEmpty(EMVTagsEnum.APPLICATION_INTERCHANGE_PROFILE_82_KRN.Tag) ||
                        database.IsNotEmpty(EMVTagsEnum.APPLICATION_FILE_LOCATOR_AFL_94_KRN.Tag))
                    {
                        parsingResult = false;
                    }
                    else
                    {
                        database.AddToList(TLV.Create(EMVTagsEnum.APPLICATION_INTERCHANGE_PROFILE_82_KRN.Tag, response.GetResponseTags().Get(EMVTagsEnum.APPLICATION_INTERCHANGE_PROFILE_82_KRN.Tag).Value));
                        database.AddToList(TLV.Create(EMVTagsEnum.APPLICATION_FILE_LOCATOR_AFL_94_KRN.Tag, response.GetResponseTags().Get(EMVTagsEnum.APPLICATION_FILE_LOCATOR_AFL_94_KRN.Tag).Value));
                        parsingResult = true;
                    }
                }
            }

            if (!parsingResult)
            {
                return(K1K3.State_3_R1_CommonProcessing.DoInvalidReponse(database, qManager, L1Enum.NOT_SET, L2Enum.PARSING_ERROR, L3Enum.NOT_SET));
            }
            else
            {
                #region 5.4.1.1
                CommonRoutines.PostUIOnly(database, qManager, KernelMessageidentifierEnum.CLEAR_DISPLAY, KernelStatusEnum.CARD_READ_SUCCESSFULLY, true);
                #endregion

                if (!(database.IsNotEmpty(EMVTagsEnum.APPLICATION_INTERCHANGE_PROFILE_82_KRN.Tag)) &&
                    database.IsNotEmpty(EMVTagsEnum.APPLICATION_FILE_LOCATOR_AFL_94_KRN.Tag))
                {
                    return(K1K3.State_3_R1_CommonProcessing.DoInvalidReponse(database, qManager, L1Enum.NOT_SET, L2Enum.CARD_DATA_MISSING, L3Enum.NOT_SET));
                }
                else
                {
                    TERMINAL_TRANSACTION_QUALIFIERS_9F66_KRN ttq = new TERMINAL_TRANSACTION_QUALIFIERS_9F66_KRN(database);
                    if (ttq.Value.MagStripeModeSupported && !ttq.Value.EMVModeSupported)
                    {
                        return(K1K3.State_3_R1_CommonProcessing.DoInvalidReponse(database, qManager, L1Enum.NOT_SET, L2Enum.MAGSTRIPE_NOT_SUPPORTED, L3Enum.NOT_SET));
                    }
                    else
                    {
                        if (!ttq.Value.MagStripeModeSupported && ttq.Value.EMVModeSupported)
                        {
                            return(DoEMVMode(database, qManager, cardQManager, cardResponse, sw, publicKeyCertificateManager, cardExceptionManager));
                        }
                        else
                        {
                            return(K1K3.State_3_R1_CommonProcessing.DoInvalidReponse(database, qManager, L1Enum.NOT_SET, L2Enum.MAGSTRIPE_NOT_SUPPORTED, L3Enum.NOT_SET));
                        }
                    }
                }
            }
        }
Example #5
0
 private static SignalsEnum EntryPointSTOP(Kernel3Database database, KernelQ qManager)
 {
     return(CommonRoutines.PostOutcomeWithError(database, qManager, Kernel2OutcomeStatusEnum.END_APPLICATION, Kernel2StartEnum.N_A, L1Enum.NOT_SET, L2Enum.NOT_SET, L3Enum.STOP));
 }
Example #6
0
 private static SignalsEnum EntryPointL1RSP(Kernel3Database database, CardResponse cardResponse, KernelQ qManager)
 {
     return(CommonRoutines.PostOutcomeWithError(database, qManager, Kernel2OutcomeStatusEnum.TRY_AGAIN, Kernel2StartEnum.B, cardResponse.L1Enum, L2Enum.NOT_SET, L3Enum.NOT_SET));
 }
Example #7
0
 private static SignalsEnum EntryPointDET(Kernel3Database database, KernelRequest kernel1Request)
 {
     database.UpdateWithDETData(kernel1Request.InputData);
     return(SignalsEnum.WAITING_FOR_GPO_REPONSE);
 }
        private static bool CheckMandatoryFields(Kernel3Database database, PublicKeyCertificateManager pkcm)
        {
            TLV ttqCheck = database.Get(EMVTagsEnum.TERMINAL_TRANSACTION_QUALIFIERS_TTQ_9F66_KRN);

            if (ttqCheck == null)
            {
                return(false);
            }

            TERMINAL_TRANSACTION_QUALIFIERS_9F66_KRN ttq = new TERMINAL_TRANSACTION_QUALIFIERS_9F66_KRN(database);

            //Reader
            if (database.IsNotPresent(EMVTagsEnum.AMOUNT_AUTHORISED_NUMERIC_9F02_KRN.Tag))
            {
                return(false);
            }
            if (database.IsNotPresent(EMVTagsEnum.AMOUNT_OTHER_NUMERIC_9F03_KRN.Tag))
            {
                return(false);
            }
            //if (database.IsNotPresent(EMVTagsEnum.APPLICATION_IDENTIFIER_AID_TERMINAL_9F06_KRN.Tag)) return false;
            //if (database.IsNotPresent(EMVTagsEnum.MERCHANT_NAME_AND_LOCATION_9F4E_KRN.Tag)) return false;
            if (database.IsNotPresent(EMVTagsEnum.TRANSACTION_CURRENCY_CODE_5F2A_KRN.Tag))
            {
                return(false);
            }
            if (database.IsNotPresent(EMVTagsEnum.TRANSACTION_DATE_9A_KRN.Tag))
            {
                return(false);
            }
            if (database.IsNotPresent(EMVTagsEnum.TRANSACTION_TYPE_9C_KRN.Tag))
            {
                return(false);
            }
            if (database.IsNotPresent(EMVTagsEnum.TERMINAL_COUNTRY_CODE_9F1A_KRN.Tag))
            {
                return(false);
            }
            if (database.IsNotPresent(EMVTagsEnum.UNPREDICTABLE_NUMBER_9F37_KRN.Tag))
            {
                return(false);
            }

            //Card
            //if (database.IsNotPresent(EMVTagsEnum.CARD_TRANSACTION_QUALIFIERS_CTQ_9F6C_KRN3.Tag)) return false;
            //CARD_TRANSACTION_QUALIFIERS_CTQ_9F6C_KRN3 ctq = new CARD_TRANSACTION_QUALIFIERS_CTQ_9F6C_KRN3(database);

            //if (database.IsNotPresent(EMVTagsEnum.APPLICATION_FILE_LOCATOR_AFL_94_KRN.Tag)) return false;
            //if (database.IsNotPresent(EMVTagsEnum.APPLICATION_DEDICATED_FILE_ADF_NAME_4F_KRN.Tag)) return false;
            if (database.IsNotPresent(EMVTagsEnum.APPLICATION_INTERCHANGE_PROFILE_82_KRN.Tag))
            {
                return(false);
            }
            if (database.IsNotPresent(EMVTagsEnum.APPLICATION_TRANSACTION_COUNTER_ATC_9F36_KRN.Tag))
            {
                return(false);
            }

            if (database.IsNotPresent(EMVTagsEnum.DEDICATED_FILE_DF_NAME_84_KRN.Tag))
            {
                return(false);
            }
            //if (database.IsNotPresent(EMVTagsEnum.FILE_CONTROL_INFORMATION_FCI_PROPRIETARY_TEMPLATE_A5_KRN.Tag)) return false;
            //if (database.IsNotPresent(EMVTagsEnum.FILE_CONTROL_INFORMATION_FCI_TEMPLATE_6F_KRN.Tag)) return false;
            //if (database.IsNotPresent(EMVTagsEnum.FORM_FACTOR_INDICATOR_FFI_9F6E_KRN3.Tag)) return false;
            if (database.IsNotPresent(EMVTagsEnum.ISSUER_APPLICATION_DATA_9F10_KRN.Tag))
            {
                return(false);
            }
            if (database.IsNotPresent(EMVTagsEnum.PROCESSING_OPTIONS_DATA_OBJECT_LIST_PDOL_9F38_KRN.Tag))
            {
                return(false);
            }
            if (database.IsNotPresent(EMVTagsEnum.TRACK_2_EQUIVALENT_DATA_57_KRN.Tag))
            {
                return(false);
            }

            bool odaCardSupported = true;

            if (database.IsPresent(EMVTagsEnum.APPLICATION_INTERCHANGE_PROFILE_82_KRN.Tag))
            {
                APPLICATION_INTERCHANGE_PROFILE_82_KRN aip = new APPLICATION_INTERCHANGE_PROFILE_82_KRN(database);
                APPLICATION_INTERCHANGE_PROFILE_82_KRN.APPLICATION_INTERCHANGE_PROFILE_82_KRN_VALUE aipST = aip.Value;
                if (!aipST.DDAsupported)
                {
                    odaCardSupported = false;
                }
                else
                {
                    odaCardSupported = true;
                }

                if (database.IsPresent(EMVTagsEnum.CARD_ADDITIONAL_PROCESSES_9F68_KRN.Tag))
                {
                    if (Formatting.IsBitSet(database.Get(EMVTagsEnum.CARD_ADDITIONAL_PROCESSES_9F68_KRN).Value[1], 5))
                    {
                        odaCardSupported = true;
                    }
                    else
                    {
                        odaCardSupported = false;
                    }
                }
            }

            //Card fdda
            if (odaCardSupported && ttq.Value.OfflineDataAuthenticationForOnlineAuthorizationsSupported && database.Kernel3Configuration.FDDAForOnlineSupported)
            {
                if (database.IsNotPresent(EMVTagsEnum.SIGNED_DYNAMIC_APPLICATION_DATA_9F4B_KRN.Tag) &&
                    database.IsNotPresent(EMVTagsEnum.SIGNED_STATIC_APPLICATION_DATA_93_KRN.Tag) &&
                    database.IsNotPresent(EMVTagsEnum.APPLICATION_CRYPTOGRAM_9F26_KRN.Tag))
                {
                    return(false);
                }

                if (database.IsPresent(EMVTagsEnum.SIGNED_DYNAMIC_APPLICATION_DATA_9F4B_KRN.Tag))
                {
                    if (database.IsNotPresent(EMVTagsEnum.CERTIFICATION_AUTHORITY_PUBLIC_KEY_INDEX_8F_KRN.Tag))
                    {
                        return(false);
                    }
                    if (pkcm.GetCAPK(RIDEnum.A000000003, database.Get(EMVTagsEnum.CERTIFICATION_AUTHORITY_PUBLIC_KEY_INDEX_8F_KRN).Value[0]) == null)
                    {
                        return(false);
                    }

                    if (database.IsNotPresent(EMVTagsEnum.ISSUER_PUBLIC_KEY_CERTIFICATE_90_KRN.Tag))
                    {
                        return(false);
                    }
                    if (database.IsNotPresent(EMVTagsEnum.ISSUER_PUBLIC_KEY_EXPONENT_9F32_KRN.Tag))
                    {
                        return(false);
                    }
                    if (database.IsNotPresent(EMVTagsEnum.ISSUER_PUBLIC_KEY_REMAINDER_92_KRN.Tag))
                    {
                        return(false);
                    }

                    if (database.IsNotPresent(EMVTagsEnum.INTEGRATED_CIRCUIT_CARD_ICC_PUBLIC_KEY_CERTIFICATE_9F46_KRN.Tag))
                    {
                        return(false);
                    }
                    if (database.IsNotPresent(EMVTagsEnum.INTEGRATED_CIRCUIT_CARD_ICC_PUBLIC_KEY_EXPONENT_9F47_KRN.Tag))
                    {
                        return(false);
                    }
                    //if (database.IsNotPresent(EMVTagsEnum.INTEGRATED_CIRCUIT_CARD_ICC_PUBLIC_KEY_REMAINDER_9F48_KRN.Tag)) return false;

                    if (database.IsNotPresent(EMVTagsEnum.CARD_AUTHENTICATION_RELATED_DATA_9F69_KRN3.Tag))
                    {
                        return(false);
                    }

                    //if (database.IsNotPresent(EMVTagsEnum.APPLICATION_EXPIRATION_DATE_5F24_KRN.Tag)) return false;
                    if (database.IsNotPresent(EMVTagsEnum.APPLICATION_PRIMARY_ACCOUNT_NUMBER_PAN_5A_KRN.Tag))
                    {
                        return(false);
                    }
                }

                if (database.IsPresent(EMVTagsEnum.SIGNED_STATIC_APPLICATION_DATA_93_KRN.Tag))
                {
                    if (database.IsNotPresent(EMVTagsEnum.CERTIFICATION_AUTHORITY_PUBLIC_KEY_INDEX_8F_KRN.Tag))
                    {
                        return(false);
                    }
                    if (pkcm.GetCAPK(RIDEnum.A000000003, database.Get(EMVTagsEnum.CERTIFICATION_AUTHORITY_PUBLIC_KEY_INDEX_8F_KRN).Value[0]) == null)
                    {
                        return(false);
                    }

                    if (database.IsNotPresent(EMVTagsEnum.ISSUER_PUBLIC_KEY_CERTIFICATE_90_KRN.Tag))
                    {
                        return(false);
                    }
                    if (database.IsNotPresent(EMVTagsEnum.ISSUER_PUBLIC_KEY_EXPONENT_9F32_KRN.Tag))
                    {
                        return(false);
                    }
                    if (database.IsNotPresent(EMVTagsEnum.ISSUER_PUBLIC_KEY_REMAINDER_92_KRN.Tag))
                    {
                        return(false);
                    }

                    //if (database.IsNotPresent(EMVTagsEnum.APPLICATION_EXPIRATION_DATE_5F24_KRN.Tag)) return false;
                    if (database.IsNotPresent(EMVTagsEnum.APPLICATION_PRIMARY_ACCOUNT_NUMBER_PAN_5A_KRN.Tag))
                    {
                        return(false);
                    }
                }
            }

            //Application Usage Control
            //if (database.IsNotPresent(EMVTagsEnum.ISSUER_COUNTRY_CODE_5F28_KRN.Tag)) return false;

            return(true);
        }
        private static SignalsEnum DoProcessingRestrictions(Kernel3Database database, KernelQ qManager, CardExceptionManager cardExceptionManager)
        {
            #region 5.5.1.1
            DateTime transactionDate = EMVTagsEnum.TRANSACTION_DATE_9A_KRN.FormatAsDateTime(database.Get(EMVTagsEnum.TRANSACTION_DATE_9A_KRN).Value);
            DateTime appExpiryDate   = DateTime.Now;
            TLV      appExiryDateTLV = database.Get(EMVTagsEnum.APPLICATION_EXPIRATION_DATE_5F24_KRN);
            if (appExiryDateTLV != null)
            {
                appExpiryDate = EMVTagsEnum.APPLICATION_EXPIRATION_DATE_5F24_KRN.FormatAsDateTime(appExiryDateTLV.Value);
            }
            if (appExiryDateTLV == null || (transactionDate > appExpiryDate))
            {
                CARD_TRANSACTION_QUALIFIERS_CTQ_9F6C_KRN3 ctq = new CARD_TRANSACTION_QUALIFIERS_CTQ_9F6C_KRN3(database);
                if (ctq.Value.GoOnlineIfApplicationExpired)
                {
                    database.OnlineRequiredByReaderIndicator = true;
                }
                else
                {
                    database.DeclineRequiredByReaderIndicator = true;
                    return(SignalsEnum.NONE);
                }
            }
            #endregion

            #region 5.5.1.2
            string pan = Formatting.ByteArrayToHexString(database.Get(EMVTagsEnum.APPLICATION_PRIMARY_ACCOUNT_NUMBER_PAN_5A_KRN).Value);
            if (database.Kernel3Configuration.ExceptionFileEnabled && cardExceptionManager.CheckForCardException(pan))
            {
                database.DeclineRequiredByReaderIndicator = true;
                return(SignalsEnum.NONE);
            }
            #endregion

            TransactionTypeEnum tt = (TransactionTypeEnum)Formatting.GetEnum(typeof(TransactionTypeEnum), database.Get(EMVTagsEnum.TRANSACTION_TYPE_9C_KRN).Value[0]);

            #region 5.5.1.3
            if (tt == TransactionTypeEnum.CashWithdrawal || tt == TransactionTypeEnum.CashDisbursement && database.Kernel3Configuration.AUCManualCheckSupported)
            {
                TLV icc = database.Get(EMVTagsEnum.ISSUER_COUNTRY_CODE_5F28_KRN);
                if (icc == null)
                {
                    database.DeclineRequiredByReaderIndicator = true;
                    return(SignalsEnum.NONE);
                }
                TLV tcc = database.Get(EMVTagsEnum.TERMINAL_COUNTRY_CODE_9F1A_KRN);
                APPLICATION_USAGE_CONTROL_9F07_KRN auc = new APPLICATION_USAGE_CONTROL_9F07_KRN(database);

                if (!((Formatting.ByteArrayToHexString(icc.Value) == Formatting.ByteArrayToHexString(tcc.Value) && auc.Value.IsValidForDomesticCashTransactions) ||
                      (Formatting.ByteArrayToHexString(icc.Value) != Formatting.ByteArrayToHexString(tcc.Value) && auc.Value.IsValidForInternationalCashTransactions)))
                {
                    CARD_TRANSACTION_QUALIFIERS_CTQ_9F6C_KRN3 ctq = new CARD_TRANSACTION_QUALIFIERS_CTQ_9F6C_KRN3(database);
                    if (database.IsEmpty(EMVTagsEnum.CARD_TRANSACTION_QUALIFIERS_CTQ_9F6C_KRN3.Tag) || ctq.Value.SwitchInterfaceForCashTransactions)
                    {
                        return(CommonRoutines.PostOutcome(database, qManager,
                                                          KernelMessageidentifierEnum.N_A,
                                                          KernelStatusEnum.PROCESSING_ERROR,
                                                          null,
                                                          Kernel2OutcomeStatusEnum.TRY_ANOTHER_INTERFACE,
                                                          Kernel2StartEnum.N_A,
                                                          true,
                                                          KernelMessageidentifierEnum.N_A,
                                                          L1Enum.NOT_SET,
                                                          null,
                                                          L2Enum.STATUS_BYTES,
                                                          L3Enum.NOT_SET));
                    }
                    else
                    {
                        database.DeclineRequiredByReaderIndicator = true;
                        return(SignalsEnum.NONE);
                    }
                }
            }
            #endregion

            #region 5.5.1.4
            if (tt == TransactionTypeEnum.PurchaseWithCashback && database.Kernel3Configuration.AUCCashbackCheckSupported)
            {
                TLV icc = database.Get(EMVTagsEnum.ISSUER_COUNTRY_CODE_5F28_KRN);
                if (icc == null)
                {
                    database.DeclineRequiredByReaderIndicator = true;
                    return(SignalsEnum.NONE);
                }
                TLV tcc = database.Get(EMVTagsEnum.TERMINAL_COUNTRY_CODE_9F1A_KRN);

                APPLICATION_USAGE_CONTROL_9F07_KRN auc = new APPLICATION_USAGE_CONTROL_9F07_KRN(database);

                if (!((Formatting.ByteArrayToHexString(icc.Value) == Formatting.ByteArrayToHexString(tcc.Value) && auc.Value.IsValidForDomesticCashTransactions) ||
                      (Formatting.ByteArrayToHexString(icc.Value) != Formatting.ByteArrayToHexString(tcc.Value) && auc.Value.IsValidForInternationalCashTransactions)))
                {
                    CARD_TRANSACTION_QUALIFIERS_CTQ_9F6C_KRN3 ctq = new CARD_TRANSACTION_QUALIFIERS_CTQ_9F6C_KRN3(database);
                    if (database.IsEmpty(EMVTagsEnum.CARD_TRANSACTION_QUALIFIERS_CTQ_9F6C_KRN3.Tag) || ctq.Value.SwitchInterfaceForCashBackTransactions)
                    {
                        return(CommonRoutines.PostOutcome(database, qManager,
                                                          KernelMessageidentifierEnum.N_A,
                                                          KernelStatusEnum.PROCESSING_ERROR,
                                                          null,
                                                          Kernel2OutcomeStatusEnum.TRY_ANOTHER_INTERFACE,
                                                          Kernel2StartEnum.N_A,
                                                          true,
                                                          KernelMessageidentifierEnum.N_A,
                                                          L1Enum.NOT_SET,
                                                          null,
                                                          L2Enum.STATUS_BYTES,
                                                          L3Enum.NOT_SET));
                    }
                    else
                    {
                        database.DeclineRequiredByReaderIndicator = true;
                        return(SignalsEnum.NONE);
                    }
                }
            }
            #endregion

            #region 5.5.1.5
            if (database.Kernel3Configuration.ATMOfflineCheck)
            {
                TERMINAL_TYPE_9F35_KRN termType = new TERMINAL_TYPE_9F35_KRN(database);
                if (termType.Value.TerminalType.Code == 0x14 || termType.Value.TerminalType.Code == 0x15 || termType.Value.TerminalType.Code == 0x16)
                {
                    if (database.IsEmpty(EMVTagsEnum.CARD_TRANSACTION_QUALIFIERS_CTQ_9F6C_KRN3.Tag))
                    {
                        database.DeclineRequiredByReaderIndicator = true;
                        return(SignalsEnum.NONE);
                    }
                    else
                    {
                        CARD_TRANSACTION_QUALIFIERS_CTQ_9F6C_KRN3 ctq = new CARD_TRANSACTION_QUALIFIERS_CTQ_9F6C_KRN3(database);
                        if (!ctq.Value.ValidForContactlessATMTransactions)
                        {
                            database.OnlineRequiredByReaderIndicator = true;
                        }
                        else
                        {
                            APPLICATION_USAGE_CONTROL_9F07_KRN auc = new APPLICATION_USAGE_CONTROL_9F07_KRN(database);
                            if (auc == null)
                            {
                                database.OnlineRequiredByReaderIndicator = true;
                            }
                            else if (!auc.Value.IsValidAtATMs)
                            {
                                database.DeclineRequiredByReaderIndicator = true;
                                return(SignalsEnum.NONE);
                            }
                            else
                            {
                                return(CommonRoutines.PostOutcome(database, qManager,
                                                                  KernelMessageidentifierEnum.N_A,
                                                                  KernelStatusEnum.PROCESSING_ERROR,
                                                                  null,
                                                                  Kernel2OutcomeStatusEnum.TRY_ANOTHER_INTERFACE,
                                                                  Kernel2StartEnum.N_A,
                                                                  true,
                                                                  KernelMessageidentifierEnum.N_A,
                                                                  L1Enum.NOT_SET,
                                                                  null,
                                                                  L2Enum.STATUS_BYTES,
                                                                  L3Enum.NOT_SET));
                            }
                        }
                    }
                }
            }
            #endregion

            return(SignalsEnum.NONE);
        }
        public static SignalsEnum DoCommonProcessing(string source, KernelDatabaseBase databaseIn, KernelQ qManager, CardQ cardQManager, Stopwatch sw, PublicKeyCertificateManager pkcm, CardExceptionManager cardExceptionManager)
        {
            Kernel3Database database = (Kernel3Database)databaseIn;

            if (database.NextCommandEnum == NextCommandEnum.READ_RECORD)
            {
                DoDEKIfNeeded(database, qManager);
                return(SignalsEnum.WAITING_FOR_EMV_READ_RECORD_RESPONSE);
            }

            DoDEKIfNeeded(database, qManager);

            //ReaderContactlessTransactionLimit exceeded
            if (database.ProcessingIndicatorsForSelected.ContactlessApplicationNotAllowed)
            {
                CommonRoutines.CreateEMVDiscretionaryData(database);
                return(CommonRoutines.PostOutcomeWithError(database, qManager, Kernel2OutcomeStatusEnum.SELECT_NEXT, Kernel2StartEnum.C, L1Enum.NOT_SET, L2Enum.MAX_LIMIT_EXCEEDED, L3Enum.NOT_SET));
            }

            #region 5.4.3.1
            TLV cidTLV = database.Get(EMVTagsEnum.CRYPTOGRAM_INFORMATION_DATA_9F27_KRN);
            if (cidTLV == null)
            {
                cidTLV = TLV.Create(EMVTagsEnum.CRYPTOGRAM_INFORMATION_DATA_9F27_KRN.Tag);
                cidTLV.Val.PackValue(cidTLV.Val.DataFormatter.GetMaxLength());
                byte iad = database.Get(EMVTagsEnum.ISSUER_APPLICATION_DATA_9F10_KRN).Value[4];
                Formatting.SetBitPosition(ref cidTLV.Value[0], Formatting.GetBitPosition(iad, 6), 8);
                Formatting.SetBitPosition(ref cidTLV.Value[0], Formatting.GetBitPosition(iad, 5), 7);
                database.AddToList(cidTLV);
            }
            #endregion

            #region 5.4.3.2
            byte cid = cidTLV.Value[0];
            cid = (byte)(cid >> 6);
            TERMINAL_TRANSACTION_QUALIFIERS_9F66_KRN ttq = new TERMINAL_TRANSACTION_QUALIFIERS_9F66_KRN(database);
            if (cid == (byte)ACTypeEnum.AAC)
            {
                database.DeclineRequiredByReaderIndicator = true;
            }
            if (cid == (byte)ACTypeEnum.ARQC || ttq.Value.OnlineCryptogramRequired)
            {
                database.OnlineRequiredByReaderIndicator = true;
            }
            if (cid != (byte)ACTypeEnum.AAC && cid != (byte)ACTypeEnum.ARQC && cid != (byte)ACTypeEnum.TC)
            {
                database.DeclineRequiredByReaderIndicator = true;
            }
            #endregion

            #region 5.4.2.1
            if (!database.DeclineRequiredByReaderIndicator)
            {
                if (!CheckMandatoryFields(database, pkcm))
                {
                    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

            if (!database.DeclineRequiredByReaderIndicator && !database.OnlineRequiredByReaderIndicator)
            {
                #region 5.5.1.1 to 5.5.1.5
                SignalsEnum result = DoProcessingRestrictions(database, qManager, cardExceptionManager);
                if (result != SignalsEnum.NONE)
                {
                    return(result);
                }
                #endregion

                #region  5.6.1.1, 5.6.1.2 and 5.6.2.1, 5.6.2.1
                if (!DoOfflineAuth(database, qManager, pkcm))
                #endregion
                {
                    CARD_TRANSACTION_QUALIFIERS_CTQ_9F6C_KRN3 ctq = new CARD_TRANSACTION_QUALIFIERS_CTQ_9F6C_KRN3(database);
                    if (ctq.Value.GoOnlineIfOfflineDataAuthenticationFailsAndReaderIsOnlineCapable && !database.ProcessingIndicatorsForSelected.TTQ.Value.OfflineOnlyReader)
                    {
                        database.OnlineRequiredByReaderIndicator = true;
                    }
                    else if (ctq.Value.SwitchInterfaceIfOfflineDataAuthenticationFailsAndReaderSupportsVIS && database.ProcessingIndicatorsForSelected.TTQ.Value.EMVContactChipSupported)
                    {
                        return(CommonRoutines.PostOutcome(database, qManager,
                                                          KernelMessageidentifierEnum.INSERT_CARD,
                                                          KernelStatusEnum.PROCESSING_ERROR,
                                                          null,
                                                          Kernel2OutcomeStatusEnum.TRY_ANOTHER_INTERFACE,
                                                          Kernel2StartEnum.N_A,
                                                          true,
                                                          KernelMessageidentifierEnum.INSERT_CARD,
                                                          L1Enum.NOT_SET,
                                                          null,
                                                          L2Enum.TERMINAL_DATA_ERROR,
                                                          L3Enum.NOT_SET));
                    }
                    else
                    {
                        database.DeclineRequiredByReaderIndicator = true;
                    }
                }
            }


            #region 5.7.1.1, 5.7.1.2, 5.7.1.3
            KernelCVMEnum cvm = KernelCVMEnum.N_A;
            if (!database.DeclineRequiredByReaderIndicator)
            {
                cvm = DoCVMProcessing(database, (ACTypeEnum)Formatting.GetEnum(typeof(ACTypeEnum), cid));
                if (cvm == KernelCVMEnum.NO_CVM && ttq.Value.CVMRequired)
                {
                    database.DeclineRequiredByReaderIndicator = true;
                }
            }
            #endregion

            #region 4.3.1.1
            byte[]             currencyCode = null;
            byte[]             balance      = null;
            ValueQualifierEnum vq           = ValueQualifierEnum.NONE;
            if (database.Kernel3Configuration.DisplayAvailableSpendingAmount)
            {
                TLV balanceTLV = database.Get(EMVTagsEnum.AVAILABLE_OFFLINE_SPENDING_AMOUNT_AOSA_9F5D_KRN3);
                if (balanceTLV != null)
                {
                    vq           = ValueQualifierEnum.BALANCE;
                    balance      = balanceTLV.Value;
                    currencyCode = database.Get(EMVTagsEnum.TRANSACTION_CURRENCY_CODE_5F2A_KRN).Value;
                }
            }
            #endregion

            //#region support for Refunds
            //byte transactionType = database.Get(EMVTagsEnum.TRANSACTION_TYPE_9C_KRN).Value[0];
            //if (transactionType == (byte)TransactionTypeEnum.Refund)
            //    database.DeclineRequiredByReaderIndicator = true;
            //#endregion

            #region 5.8.1.1
            if (database.OnlineRequiredByReaderIndicator && !database.DeclineRequiredByReaderIndicator)
            {
                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,
                                                  vq,
                                                  balance,
                                                  currencyCode,
                                                  false,
                                                  cvm));
            }
            #endregion

            #region 5.9.1.1
            if (!database.OnlineRequiredByReaderIndicator && !database.DeclineRequiredByReaderIndicator)
            {
                CommonRoutines.CreateEMVDataRecord(database);
                CommonRoutines.CreateEMVDiscretionaryData(database);
                return(CommonRoutines.PostOutcome(database, qManager,
                                                  cvm == KernelCVMEnum.OBTAIN_SIGNATURE ? KernelMessageidentifierEnum.APPROVED_SIGN : KernelMessageidentifierEnum.APPROVED,
                                                  KernelStatusEnum.READY_TO_READ,
                                                  null,
                                                  Kernel2OutcomeStatusEnum.APPROVED,
                                                  Kernel2StartEnum.N_A,
                                                  true,
                                                  KernelMessageidentifierEnum.N_A,
                                                  L1Enum.NOT_SET,
                                                  null,
                                                  L2Enum.NOT_SET,
                                                  L3Enum.NOT_SET,
                                                  vq,
                                                  balance,
                                                  currencyCode,
                                                  false,
                                                  cvm));
            }
            #endregion

            CommonRoutines.CreateEMVDiscretionaryData(database);
            //#region support for Refunds
            //if (transactionType == (byte)TransactionTypeEnum.Refund)
            //#endregion
            //{
            //    //CommonRoutines.PostUIOnly(database, qManager, Kernel1MessageidentifierEnum.CLEAR_DISPLAY, Kernel1StatusEnum.N_A, true, new byte[] { 0x00, 0x00, 0x00 });

            //    CommonRoutines.CreateEMVDataRecord(database);
            //    return CommonRoutines.PostOutcome(database, qManager,
            //        KernelMessageidentifierEnum.N_A,
            //        KernelStatusEnum.N_A,
            //        null,
            //        Kernel2OutcomeStatusEnum.END_APPLICATION,
            //        Kernel2StartEnum.N_A,
            //        true,
            //        KernelMessageidentifierEnum.N_A,
            //        L1Enum.NOT_SET,
            //        null,
            //        L2Enum.NOT_SET,
            //        L3Enum.NOT_SET,
            //        ValueQualifierEnum.NONE,
            //        null,
            //        null,
            //        false,
            //        cvm);
            //}
            //else
            //{
            #region 5.9.1.2
            return(CommonRoutines.PostOutcome(database, qManager,
                                              KernelMessageidentifierEnum.DECLINED,
                                              KernelStatusEnum.READY_TO_READ,
                                              null,
                                              Kernel2OutcomeStatusEnum.DECLINED,
                                              Kernel2StartEnum.N_A,
                                              true,
                                              KernelMessageidentifierEnum.N_A,
                                              L1Enum.NOT_SET,
                                              null,
                                              L2Enum.NOT_SET,
                                              L3Enum.NOT_SET,
                                              vq,
                                              balance,
                                              currencyCode,
                                              false,
                                              cvm));

            #endregion
            //}
        }
        public static KernelCVMEnum DoCVMProcessing(Kernel3Database database, ACTypeEnum acType)
        {
            KernelCVMEnum cvm = KernelCVMEnum.N_A;
            TERMINAL_TRANSACTION_QUALIFIERS_9F66_KRN ttq = new TERMINAL_TRANSACTION_QUALIFIERS_9F66_KRN(database);

            if (!database.DeclineRequiredByReaderIndicator)
            {
                #region 5.7.1.1
                if (database.IsEmpty(EMVTagsEnum.CARD_TRANSACTION_QUALIFIERS_CTQ_9F6C_KRN3.Tag) && ttq.Value.CVMRequired)
                #endregion
                {
                    if (ttq.Value.SignatureSupported)
                    {
                        cvm = KernelCVMEnum.OBTAIN_SIGNATURE;
                    }
                    else if (ttq.Value.ConsumerDeviceCVMSupported && ttq.Value.OnlinePINSupported)
                    {
                        cvm = KernelCVMEnum.ONLINE_PIN;
                    }
                    else// only ttq.Value.ConsumerDeviceCVMSupported
                    {
                        database.DeclineRequiredByReaderIndicator = true;
                    }
                }
                if (database.IsNotEmpty(EMVTagsEnum.CARD_TRANSACTION_QUALIFIERS_CTQ_9F6C_KRN3.Tag))
                {
                    #region 5.7.1.2
                    CARD_TRANSACTION_QUALIFIERS_CTQ_9F6C_KRN3 ctq = new CARD_TRANSACTION_QUALIFIERS_CTQ_9F6C_KRN3(database);
                    if (ctq.Value.OnlinePINRequired && ttq.Value.OnlinePINSupported)
                    {
                        cvm = KernelCVMEnum.ONLINE_PIN;
                        database.OnlineRequiredByReaderIndicator = true;
                    }
                    else
                    {
                        if (ctq.Value.ConsumerDeviceCVMPerformed)
                        {
                            TLV card = database.Get(EMVTagsEnum.CARD_AUTHENTICATION_RELATED_DATA_9F69_KRN3);
                            if (card != null)
                            {
                                byte[] card67 = new byte[2];
                                byte[] ctq12  = new byte[2];
                                Array.Copy(card.Value, 6, card67, 0, 2);
                                Array.Copy(ctq.Value.Value, 0, ctq12, 0, 2);
                                if (Formatting.ByteArrayToHexString(card67) == Formatting.ByteArrayToHexString(ctq12))
                                {
                                    cvm = KernelCVMEnum.CONFIRMATION_CODE_VERIFIED;
                                }
                                else
                                {
                                    database.DeclineRequiredByReaderIndicator = true;
                                }
                            }
                            else
                            {
                                if (acType == ACTypeEnum.ARQC)
                                {
                                    cvm = KernelCVMEnum.CONFIRMATION_CODE_VERIFIED;
                                }
                                else
                                {
                                    database.DeclineRequiredByReaderIndicator = true;
                                }
                            }
                        }
                    }

                    if (!ctq.Value.OnlinePINRequired && !ctq.Value.ConsumerDeviceCVMPerformed)
                    {
                        if (ttq.Value.SignatureSupported && ctq.Value.SignatureRequired)
                        {
                            cvm = KernelCVMEnum.OBTAIN_SIGNATURE;
                        }
                    }

                    #endregion
                }
            }
            if (cvm == KernelCVMEnum.N_A && ttq.Value.CVMRequired)
            {
                cvm = KernelCVMEnum.NO_CVM;
                database.DeclineRequiredByReaderIndicator = true;
            }
            if (cvm == KernelCVMEnum.N_A)
            {
                cvm = KernelCVMEnum.NO_CVM;
            }

            return(cvm);
        }