public static KernelBase ActivateKernel(
     TransactionRequest tt,
     CardQProcessor cardInterface,
     PublicKeyCertificateManager publicKeyCertificateManager,
     EMVSelectApplicationResponse response,
     TerminalSupportedKernelAidTransactionTypeCombination terminalCombinationForSelected,
     CardKernelAidCombination cardCombinationForSelected,
     EntryPointPreProcessingIndicators processingIndicatorsForSelected,
     CardExceptionManager cardExceptionManager,
     IConfigurationProvider configProvider
     ) //the response from the selected aid command
 {
     return(new Kernel(tt.GetTransactionType_9C(), cardInterface, publicKeyCertificateManager, processingIndicatorsForSelected, cardExceptionManager, configProvider, response));
 }
        public EMVTerminalApplicationBase(CardQProcessor cardQProcessor, IConfigurationProvider configProvider)
        {
            this.configProvider = configProvider;

            cancellationTokenForTerminalApplication = new CancellationTokenSource();

            TLVMetaDataSourceSingleton.Instance.DataSource = new EMVTLVMetaDataSource();

            terminalConfigurationData   = new TerminalConfigurationData();
            publicKeyCertificateManager = new PublicKeyCertificateManager(configProvider);
            cardExceptionManager        = new CardExceptionManager(configProvider);

            this.cardQProcessor = cardQProcessor;
            this.cardQProcessor.ExceptionOccured += CardInterface_ExceptionOccured;
            this.cardQProcessor.CardInterfaceManger.CardPutInField       += CardReader_CardPutInField;
            this.cardQProcessor.CardInterfaceManger.CardRemovedFromField += CardReader_CardRemovedFromField;
            cardQProcessor.StartServiceQProcess();
        }
        public static KernelBase ActivateKernel(
            TransactionRequest tt,
            CardQProcessor cardInterface,
            TornTransactionLogManager tornTransactionLogManager,
            PublicKeyCertificateManager publicKeyCertificateManager,
            EMVSelectApplicationResponse response,
            TerminalSupportedKernelAidTransactionTypeCombination terminalCombinationForSelected,
            CardKernelAidCombination cardCombinationForSelected,
            EntryPointPreProcessingIndicators processingIndicatorsForSelected,
            CardExceptionManager cardExceptionManager,
            IConfigurationProvider configProvider
            ) //the response from the selected aid command
        {
            switch (((TerminalSupportedContactlessKernelAidTransactionTypeCombination)terminalCombinationForSelected).KernelEnum)
            {
            case KernelEnum.Kernel1:
                EMVTagsEnum.DataKernelID = DataKernelID.K1;
                return(new Kernel1(tt.GetTransactionType_9C(), cardInterface, publicKeyCertificateManager, processingIndicatorsForSelected, cardExceptionManager, configProvider));

            case KernelEnum.Kernel2:
                EMVTagsEnum.DataKernelID = DataKernelID.K2;
                return(new Kernel2(tt.GetTransactionType_9C(), tornTransactionLogManager, cardInterface, publicKeyCertificateManager, processingIndicatorsForSelected, cardExceptionManager, configProvider));

            case KernelEnum.Kernel3:
                EMVTagsEnum.DataKernelID = DataKernelID.K3;
                return(new Kernel3(tt.GetTransactionType_9C(), cardInterface, publicKeyCertificateManager, processingIndicatorsForSelected, cardExceptionManager, configProvider));

            case KernelEnum.Kernel4:
                break;

            case KernelEnum.Kernel5:
                break;

            case KernelEnum.Kernel6:
                break;

            case KernelEnum.Kernel7:
                break;

            default:
                throw new EMVProtocolException("Unsupported kernel: " + ((TerminalSupportedContactlessKernelAidTransactionTypeCombination)terminalCombinationForSelected).KernelEnum);
            }
            throw new EMVProtocolException("Unsupported kernel: " + ((TerminalSupportedContactlessKernelAidTransactionTypeCombination)terminalCombinationForSelected).KernelEnum);
        }
예제 #4
0
        public static SignalsEnum Execute(
            KernelDatabaseBase database,
            KernelQ qManager,
            CardQ cardQManager,
            Stopwatch sw,
            PublicKeyCertificateManager publicKeyCertificateManager,
            CardExceptionManager cardExceptionManager,
            Func <string, KernelDatabaseBase, KernelQ, CardQ, Stopwatch, PublicKeyCertificateManager, CardExceptionManager, SignalsEnum> ReadRecordCompleteCallback)
        {
            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, ReadRecordCompleteCallback));

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

                default:
                    throw new EMVProtocolException("Invalid Kernel1CardinterfaceServiceResponseEnum in State_3_WaitingForGPOResponse:" + Enum.GetName(typeof(CardInterfaceServiceResponseEnum), cardResponse.CardInterfaceServiceResponseEnum));
                }
            }
        }
예제 #5
0
        public Kernel2(TransactionTypeEnum tt, TornTransactionLogManager tornTransactionLogManager, CardQProcessor cardQProcessor, PublicKeyCertificateManager publicKeyCertificateManager, EntryPointPreProcessingIndicators processingIndicatorsForSelected, CardExceptionManager cardExceptionManager, IConfigurationProvider configProvider)
            : base(cardQProcessor, publicKeyCertificateManager, processingIndicatorsForSelected, cardExceptionManager, configProvider)
        {
            this.tornTransactionLogManager = tornTransactionLogManager;

            database = new Kernel2Database(publicKeyCertificateManager);
            database.InitializeDefaultDataObjects(tt, configProvider);
        }
예제 #6
0
        private static SignalsEnum EntryPointRA(KernelDatabaseBase database, CardResponse cardResponse, KernelQ qManager, CardQ cardQManager,
                                                Stopwatch sw, PublicKeyCertificateManager publicKeyCertificateManager, CardExceptionManager cardExceptionManager,
                                                Func <string, KernelDatabaseBase, KernelQ, CardQ, Stopwatch, PublicKeyCertificateManager, CardExceptionManager, SignalsEnum> ReadRecordCompleteCallback)
        {
            byte sfi;
            bool signedFlag;

            if (!cardResponse.ApduResponse.Succeeded)
            {
                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));
            }

            if (database.ActiveAFL.Value.Entries[0].OfflineDataAuthenticationRecordLength > 0)
            {
                signedFlag = true;
            }
            else
            {
                signedFlag = false;
            }

            sfi = database.ActiveAFL.Value.Entries[0].SFI;
            database.ActiveAFL.Value.Entries.RemoveAt(0);

            if (database.ActiveAFL.Value.Entries.Count == 0)
            {
                database.NextCommandEnum = NextCommandEnum.NONE;
            }
            else
            {
                EMVReadRecordRequest request = new EMVReadRecordRequest(database.ActiveAFL.Value.Entries[0].SFI, database.ActiveAFL.Value.Entries[0].FirstRecordNumber);
                cardQManager.EnqueueToInput(new CardRequest(request, CardinterfaceServiceRequestEnum.ADPU));
                database.NextCommandEnum = NextCommandEnum.READ_RECORD;
            }

            bool parsingResult;

            if (sfi <= 10)
            {
                if (cardResponse.ApduResponse.ResponseData.Length > 0 && cardResponse.ApduResponse.ResponseData[0] == 0x70)
                {
                    parsingResult = database.ParseAndStoreCardResponse(cardResponse.ApduResponse.ResponseData);
                }
                else
                {
                    parsingResult = false;
                }
            }
            else //Processing of records in proprietary files is beyond the scope of thisspecification
            {
                parsingResult = false;
            }

            if (!parsingResult)
            {
                if (database.NextCommandEnum == NextCommandEnum.NONE)
                {
                    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));
                }
                else
                {
                    return(SignalsEnum.TEMINATE_ON_NEXT_RA);
                }
            }

            TLVList responseTags;

            if (cardResponse.ApduResponse is EMVReadRecordResponse)
            {
                responseTags = (cardResponse.ApduResponse as EMVReadRecordResponse).GetResponseTags();
            }
            else if (cardResponse.ApduResponse is EMVGetDataResponse)
            {
                responseTags = (cardResponse.ApduResponse as EMVGetDataResponse).GetResponseTags();
            }
            else
            {
                throw new EMVProtocolException("Invalid card response in State4");
            }

            TLVList cdols = responseTags.FindAll(EMVTagsEnum.CARD_RISK_MANAGEMENT_DATA_OBJECT_LIST_1_CDOL1_8C_KRN.Tag);

            if (cdols.Count > 0)
            {
                TLVList cdolList = TLV.DeserializeChildrenWithNoV(cdols.GetFirst().Value, 0);
                DATA_NEEDED_DF8106_KRN2 dataNeeded = new DATA_NEEDED_DF8106_KRN2(database);
                foreach (TLV tlv in cdolList)
                {
                    if (database.IsEmpty(tlv.Tag.TagLable))
                    {
                        dataNeeded.Value.Tags.Add(tlv.Tag.TagLable);
                    }
                }
                dataNeeded.UpdateDB();
            }

            Do434(database, signedFlag, sfi, cardResponse, responseTags);

            return(ReadRecordCompleteCallback("State_4_WaitingForEMVReadRecord", database, qManager, cardQManager, sw, publicKeyCertificateManager, cardExceptionManager));
            //return State_4_5_6_CommonProcessing.DoCommonProcessing("State_4_WaitingForEMVReadRecord", database, qManager, cardQManager, sw, publicKeyCertificateManager);
        }
예제 #7
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));
                        }
                    }
                }
            }
        }
예제 #8
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));
            }
        }
        private static SignalsEnum EntryPointRA(Kernel1Database database, CardResponse cardResponse, KernelQ qManager, CardQ cardQManager, Stopwatch sw, PublicKeyCertificateManager publicKeyCertificateManager, CardExceptionManager cardExceptionManager)
        {
            if (!cardResponse.ApduResponse.Succeeded)
            {
                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));
            }

            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
            {
                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
                {
                    TLV aflRaw = database.Get(EMVTagsEnum.APPLICATION_FILE_LOCATOR_AFL_94_KRN);
                    if (aflRaw != null)
                    {
                        List <byte[]> bytes = new List <byte[]>();
                        bytes.Add(new byte[] { (byte)aflRaw.Value.Length });
                        bytes.Add(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
                    {
                        //GPO and ReadRecords Complete
                        database.NextCommandEnum = NextCommandEnum.NONE;
                        return(State_3_4_CommonProcessing.DoCommonProcessing("State_3_WaitingForGPOResponse", database, qManager, cardQManager, sw, publicKeyCertificateManager, cardExceptionManager));
                    }
                }
            }
        }
        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 SignalsEnum DoCommonProcessing(string source, KernelDatabaseBase databaseIn, KernelQ qManager, CardQ cardQManager, Stopwatch sw, PublicKeyCertificateManager pkcm, CardExceptionManager cardExceptionManager)
        {
            Kernel1Database database = (Kernel1Database)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));
            }

            bool goOnline = false;

            #region 3.2.1.1
            if (database.IsPresent(EMVTagsEnum.VLP_ISSUER_AUTHORISATION_CODE_9F74_KRN1.Tag))
            {
                if (database.ProcessingIndicatorsForSelected.ReaderContactlessFloorLimitExceeded)
                {
                    goOnline = true;
                }
                if (database.ProcessingIndicatorsForSelected.ReaderCVMRequiredLimitExceeded)
                {
                    goOnline = true;
                }
            }
            else
            {
                goOnline = true;
            }
            #endregion

            if (goOnline)
            {
                return(DoOnlineProcess(database, cardQManager));
            }
            else
            {
                return(DoOfflineProcess(database, cardQManager));
            }
        }
예제 #13
0
 public Kernel(TransactionTypeEnum tt, CardQProcessor cardQProcessor, PublicKeyCertificateManager publicKeyCertificateManager, EntryPointPreProcessingIndicators processingIndicatorsForSelected, CardExceptionManager cardExceptionManager, IConfigurationProvider configProvider, EMVSelectApplicationResponse emvSelectApplicationResponse)
     : base(cardQProcessor, publicKeyCertificateManager, processingIndicatorsForSelected, cardExceptionManager, configProvider)
 {
     database = new KernelDatabase(publicKeyCertificateManager);
     database.InitializeDefaultDataObjects(tt, configProvider);
     this.emvSelectApplicationResponse = emvSelectApplicationResponse;
 }