예제 #1
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;
 }
 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 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);
        }
        public static SignalsEnum Execute(
            KernelDatabase database,
            KernelQ qManager,
            CardQ cardQManager,
            EMVSelectApplicationResponse emvSelectApplicationResponse,
            Stopwatch sw)
        {
            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));

                case KernelTerminalReaderServiceRequestEnum.ONLINE:
                    return(EntryPointOnline(database, kernel1Request, qManager, cardQManager, emvSelectApplicationResponse));

                default:
                    throw new EMVProtocolException("Invalid Kernel1TerminalReaderServiceRequestEnum in State_8_WaitingForOnlineAuth:" + 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));

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

                default:
                    throw new EMVProtocolException("Invalid Kernel1CardinterfaceServiceResponseEnum in State_8_WaitingForOnlineAuth:" + Enum.GetName(typeof(CardInterfaceServiceResponseEnum), cardResponse.CardInterfaceServiceResponseEnum));
                }
            }
        }
예제 #5
0
        public static bool DoCDA(KernelDatabase database, KernelQ qManager, CAPublicKeyCertificate capk, CardQ cardQManager, CardResponse cardResponse, EMVSelectApplicationResponse emvSelectApplicationResponse, bool isFirstGenAC)
        {
            //#region 9_10.2
            TERMINAL_VERIFICATION_RESULTS_95_KRN  tvr = new TERMINAL_VERIFICATION_RESULTS_95_KRN(database);
            TRANSACTION_STATUS_INFORMATION_9B_KRN tsi = new TRANSACTION_STATUS_INFORMATION_9B_KRN(database);

            tsi.Value.OfflineDataAuthenticationWasPerformed = true;
            tsi.UpdateDB();

            bool cdaSucceeded = VerifySDAD_CDA(database, capk, cardResponse, isFirstGenAC);

            if (!cdaSucceeded)
            {
                tvr.Value.CDAFailed = true;
                tvr.UpdateDB();
                return(false);
            }
            else
            {
                return(true);
            }
        }
        private static SignalsEnum EntryPointOnline(KernelDatabase database, KernelRequest kernel1Request, KernelQ qManager, CardQ cardQManager, EMVSelectApplicationResponse emvSelectApplicationResponse)
        {
            KernelOnlineRequest response = (KernelOnlineRequest)kernel1Request;

            //check if approved or not or unable to go online
            if (response.OnlineApprovalStatus == KernelOnlineResponseType.UnableToGoOnline)
            {
                //if unable to go online, check what action to take using TAC/IAC default,
                TERMINAL_VERIFICATION_RESULTS_95_KRN tvr = new TERMINAL_VERIFICATION_RESULTS_95_KRN(database);
                ulong tvrAsNumber = Formatting.ConvertToInt64(tvr.Value.Value);
                ulong tacAsNumber = Formatting.ConvertToInt64(database.Get(EMVTagsEnum.TERMINAL_ACTION_CODE_DEFAULT_DF8120_KRN2).Value);
                if (database.IsNotEmpty(EMVTagsEnum.ISSUER_ACTION_CODE_DEFAULT_9F0D_KRN.Tag))
                {
                    ulong iacAsNumber = Formatting.ConvertToInt64(database.Get(EMVTagsEnum.ISSUER_ACTION_CODE_DEFAULT_9F0D_KRN).Value);
                    if (!(
                            ((tacAsNumber | iacAsNumber) & tvrAsNumber) == 0)
                        )
                    {
                        database.ACType.Value.DSACTypeEnum = ACTypeEnum.AAC;
                    }
                    else
                    {
                        database.ACType.Value.DSACTypeEnum = ACTypeEnum.TC;
                    }
                }
                else
                {
                    if (!((tacAsNumber & tvrAsNumber) == 0))
                    {
                        database.ACType.Value.DSACTypeEnum = ACTypeEnum.AAC;
                    }
                    else
                    {
                        database.ACType.Value.DSACTypeEnum = ACTypeEnum.TC;
                    }
                }
                //what should these be set to in this case?
                database.AddToList(TLV.Create(EMVTagsEnum.ISSUER_AUTHENTICATION_DATA_91_KRN.Tag));
                database.AddToList(TLV.Create(EMVTagsEnum.AUTHORISATION_RESPONSE_CODE_8A_KRN.Tag));
            }
            else
            {
                if (response.OnlineApprovalStatus == KernelOnlineResponseType.Approve)
                {
                    database.ACType.Value.DSACTypeEnum = ACTypeEnum.TC;
                }
                else
                {
                    database.ACType.Value.DSACTypeEnum = ACTypeEnum.AAC;
                }
                database.AddToList(response.InputData.Get(EMVTagsEnum.ISSUER_AUTHENTICATION_DATA_91_KRN.Tag));
                database.AddToList(response.InputData.Get(EMVTagsEnum.AUTHORISATION_RESPONSE_CODE_8A_KRN.Tag));
                if (response.InputData.Get(EMVTagsEnum.ISSUER_SCRIPT_TEMPLATE_1_71_KRN.Tag) != null)
                {
                    database.AddToList(response.InputData.Get(EMVTagsEnum.ISSUER_SCRIPT_TEMPLATE_1_71_KRN.Tag));
                }
                if (response.InputData.Get(EMVTagsEnum.ISSUER_SCRIPT_TEMPLATE_2_72_KRN.Tag) != null)
                {
                    database.AddToList(response.InputData.Get(EMVTagsEnum.ISSUER_SCRIPT_TEMPLATE_2_72_KRN.Tag));
                }
            }

            APPLICATION_INTERCHANGE_PROFILE_82_KRN aip = new APPLICATION_INTERCHANGE_PROFILE_82_KRN(database);

            if (aip.Value.IssuerAuthenticationIsSupported && response.OnlineApprovalStatus != KernelOnlineResponseType.UnableToGoOnline)
            {
                TLV _91 = response.InputData.Get(EMVTagsEnum.ISSUER_AUTHENTICATION_DATA_91_KRN.Tag);
                EMVExternalAuthenticateRequest request = new EMVExternalAuthenticateRequest(_91.Value);
                cardQManager.EnqueueToInput(new CardRequest(request, CardinterfaceServiceRequestEnum.ADPU));
                return(SignalsEnum.WAITING_FOR_EXTERNAL_AUTHENTICATE);
            }
            else
            {
                //if scripts need to be run before gen ac, do now
                return(CardActionAnalysis.Initiate2ndCardActionAnalysis(database, qManager, cardQManager, emvSelectApplicationResponse));
            }
        }
        private static SignalsEnum EntryPointTRM(KernelDatabase database, KernelRequest kernel1Request, CardQ cardQManager, KernelQ qManager, EMVSelectApplicationResponse emvSelectApplicationResponse)
        {
            TERMINAL_VERIFICATION_RESULTS_95_KRN  tvr = new TERMINAL_VERIFICATION_RESULTS_95_KRN(database);
            TRANSACTION_STATUS_INFORMATION_9B_KRN tsi = new TRANSACTION_STATUS_INFORMATION_9B_KRN(database);

            tsi.Value.TerminalRiskmanagementWasPerformed = true;
            tsi.UpdateDB();

            //The state works as follows:
            //State_5_WaitingForCVMProcessing ends by possibly adding 2 messages to the card q
            //and 1 or 2 messages in the terminal q (get floor limit (optional) and do trm)
            //the card messages are processed by this state first, then the get floor limit by DEK if it
            //was in the q and then this method

            //Random Transaction Selection determined by terminal, not kernel
            //Terminal can also force transaction online
            //EMVTagsEnum.MAXIMUM_TARGET_PERCENTAGE_TO_BE_USED_FOR_BIASED_RANDOM_SELECTION_INTERNAL_KRN
            //EMVTagsEnum.THRESHOLD_VALUE_FOR_BIASED_RANDOM_SELECTION_INTERNAL_KRN
            //EMVTagsEnum.MAXIMUM_TARGET_PERCENTAGE_TO_BE_USED_FOR_BIASED_RANDOM_SELECTION_INTERNAL_KRN

            switch (((KernelTRMRequest)kernel1Request).KernelTRMRequestType)
            {
            case KernelTRMRequestType.GoOnlineForRandomSelection:
                tvr.Value.TransactionSelectedRandomlyForOnlineProcessing = true;
                tvr.UpdateDB();
                break;

            case KernelTRMRequestType.GoOnline:
                tvr.Value.MerchantForcedTransactionOnline = true;
                tvr.UpdateDB();
                break;
            }

            //Floor limit check done by kernel, no need for it to be done by terminal
            if (database.IsNotEmpty(EMVTagsEnum.TERMINAL_FLOOR_LIMIT_9F1B_KRN.Tag))
            {
                long aa = Formatting.BcdToLong(database.Get(EMVTagsEnum.AMOUNT_AUTHORISED_NUMERIC_9F02_KRN).Value);
                long fl = Formatting.BcdToLong(database.Get(EMVTagsEnum.TERMINAL_FLOOR_LIMIT_9F1B_KRN).Value);
                if (aa > fl)
                {
                    tvr.Value.TransactionExceedsFloorLimit = true;
                    tvr.UpdateDB();
                }
            }

            //Velocity Check
            TLV lcol   = database.Get(EMVTagsEnum.LOWER_CONSECUTIVE_OFFLINE_LIMIT_9F14_KRN);
            TLV ucol   = database.Get(EMVTagsEnum.UPPER_CONSECUTIVE_OFFLINE_LIMIT_9F23_KRN);
            TLV atcTLV = database.Get(EMVTagsEnum.APPLICATION_TRANSACTION_COUNTER_ATC_9F36_KRN.Tag);
            TLV lastOnlineATCRegisterTLV = database.Get(EMVTagsEnum.LAST_ONLINE_APPLICATION_TRANSACTION_COUNTER_ATC_REGISTER_9F13_KRN.Tag);

            bool doVelocity = false;

            if (lcol != null && ucol != null)
            {
                if (database.Get(EMVTagsEnum.APPLICATION_TRANSACTION_COUNTER_ATC_9F36_KRN.Tag) != null &&
                    database.Get(EMVTagsEnum.LAST_ONLINE_APPLICATION_TRANSACTION_COUNTER_ATC_REGISTER_9F13_KRN.Tag) != null)
                {
                    if (Formatting.ConvertToInt32(atcTLV.Value) >
                        Formatting.ConvertToInt32(lastOnlineATCRegisterTLV.Value))
                    {
                        doVelocity = true;
                    }
                    else
                    {
                        // Set both the ‘Lower consecutive offline limit exceeded’ and the ‘Upper consecutive offline limit exceeded’ bits in the TVR to 1.
                        // Not set the ‘New card’ indicator in the TVR unless the Last Online ATC Register is returned and equals zero.
                        // End velocity checking for this transaction
                        tvr.Value.LowerConsecutiveOfflineLimitExceeded = true;
                        tvr.Value.UpperConsecutiveOfflineLimitExceeded = true;

                        if (lastOnlineATCRegisterTLV != null)
                        {
                            if (Formatting.ConvertToInt32(lastOnlineATCRegisterTLV.Value) == 0)
                            {
                                tvr.Value.NewCard = true;
                            }
                        }
                        tvr.UpdateDB();
                    }
                }
            }
            if (doVelocity == true)
            {
                uint atc     = Formatting.ConvertToInt32(atcTLV.Value);
                uint lastATC = Formatting.ConvertToInt32(lastOnlineATCRegisterTLV.Value);

                uint atcDiff = atc - lastATC;
                uint lcolInt = Formatting.ConvertToInt32(lcol.Value);
                uint ucolInt = Formatting.ConvertToInt32(ucol.Value);
                if (atcDiff > lcolInt)
                {
                    //set ‘Lower consecutive offline limit exceeded’ bit in the TVR to 1
                    tvr.Value.LowerConsecutiveOfflineLimitExceeded = true;
                    if (atcDiff > ucolInt)
                    {
                        //set the ‘Upper consecutive offline limit exceeded’ bit in the TVR to 1.
                        tvr.Value.UpperConsecutiveOfflineLimitExceeded = true;
                    }
                }
                if (lastATC == 0)
                {
                    //set ‘New card’ bit in the TVR to 1.
                    tvr.Value.NewCard = true;
                }
                tvr.UpdateDB();
            }

            #region Book 3 Section 10.7
            //Terminal Action Analysis of kernel 2 being used
            database.ACType.Value.DSACTypeEnum = TerminalActionAnalysis_7_8.TerminalActionAnalysis(database);
            #endregion

            #region Book 3 Section 10.8
            //Card Action Analysis
            return(CardActionAnalysis.InitiateCardActionAnalysis(database, qManager, cardQManager, emvSelectApplicationResponse));

            #endregion
        }
예제 #8
0
        private static SignalsEnum ProcessGenACCommand(KernelDatabase database, CardResponse cardResponse, KernelQ qManager, CardQ cardQManager, Stopwatch sw, PublicKeyCertificateManager publicKeyCertificateManager, EMVSelectApplicationResponse emvSelectApplicationResponse)
        {
            //remove values stored during 1st gen ac
            database.RemoveFromList(database.Get(EMVTagsEnum.CRYPTOGRAM_INFORMATION_DATA_9F27_KRN.Tag));
            database.RemoveFromList(database.Get(EMVTagsEnum.APPLICATION_TRANSACTION_COUNTER_ATC_9F36_KRN.Tag));
            database.RemoveFromList(database.Get(EMVTagsEnum.APPLICATION_CRYPTOGRAM_9F26_KRN.Tag));
            database.RemoveFromList(database.Get(EMVTagsEnum.ISSUER_APPLICATION_DATA_9F10_KRN.Tag));
            //will only exist if CDA was perfomred after 1st gen ac
            database.RemoveFromList(database.Get(EMVTagsEnum.SIGNED_DYNAMIC_APPLICATION_DATA_9F4B_KRN.Tag));

            bool parsingResult = false;

            if (cardResponse.ApduResponse.ResponseData.Length > 0 && cardResponse.ApduResponse.ResponseData[0] == 0x77)
            {
                EMVGenerateACResponse response = cardResponse.ApduResponse as EMVGenerateACResponse;
                parsingResult = database.ParseAndStoreCardResponse(response.ResponseData);
            }
            else
            {
                if (cardResponse.ApduResponse.ResponseData.Length > 0 && cardResponse.ApduResponse.ResponseData[0] == 0x80)
                {
                    if (cardResponse.ApduResponse.ResponseData.Length < 11 ||
                        cardResponse.ApduResponse.ResponseData.Length > 43 ||
                        database.IsNotEmpty(EMVTagsEnum.CRYPTOGRAM_INFORMATION_DATA_9F27_KRN.Tag) ||
                        database.IsNotEmpty(EMVTagsEnum.APPLICATION_TRANSACTION_COUNTER_ATC_9F36_KRN.Tag) ||
                        database.IsNotEmpty(EMVTagsEnum.APPLICATION_CRYPTOGRAM_9F26_KRN.Tag) ||
                        (cardResponse.ApduResponse.ResponseData.Length > 11 &&
                         database.IsNotEmpty(EMVTagsEnum.ISSUER_APPLICATION_DATA_9F10_KRN.Tag))
                        )
                    {
                        parsingResult = false;
                    }
                    else
                    {
                        byte[] responseBuffer = new byte[cardResponse.ApduResponse.ResponseData.Length - 2];
                        Array.Copy(cardResponse.ApduResponse.ResponseData, 2, responseBuffer, 0, responseBuffer.Length);
                        database.AddToList(TLV.Create(EMVTagsEnum.CRYPTOGRAM_INFORMATION_DATA_9F27_KRN.Tag, new byte[] { responseBuffer[0] }));
                        database.AddToList(TLV.Create(EMVTagsEnum.APPLICATION_TRANSACTION_COUNTER_ATC_9F36_KRN.Tag, new byte[] { responseBuffer[1], responseBuffer[2] }));

                        byte[] ac = new byte[8];
                        Array.Copy(responseBuffer, 3, ac, 0, 8);
                        database.AddToList(TLV.Create(EMVTagsEnum.APPLICATION_CRYPTOGRAM_9F26_KRN.Tag, ac));
                        if (responseBuffer.Length > 11)
                        {
                            byte[] iad = new byte[responseBuffer.Length - 11];
                            Array.Copy(responseBuffer, 11, iad, 0, iad.Length);
                            database.AddToList(TLV.Create(EMVTagsEnum.ISSUER_APPLICATION_DATA_9F10_KRN.Tag, iad));
                        }
                        parsingResult = true;
                    }
                }
            }

            if (!parsingResult)
            {
                return(State_7_10_CommonProcessing.DoInvalidResponsePart_C(database, qManager, L1Enum.NOT_SET, L2Enum.PARSING_ERROR, L3Enum.NOT_SET));
            }

            if (!(database.IsNotEmpty(EMVTagsEnum.APPLICATION_TRANSACTION_COUNTER_ATC_9F36_KRN.Tag) &&
                  database.IsNotEmpty(EMVTagsEnum.CRYPTOGRAM_INFORMATION_DATA_9F27_KRN.Tag)))
            {
                return(State_7_10_CommonProcessing.DoInvalidResponsePart_C(database, qManager, L1Enum.NOT_SET, L2Enum.CARD_DATA_MISSING, L3Enum.NOT_SET));
            }

            APPLICATION_INTERCHANGE_PROFILE_82_KRN aip = new APPLICATION_INTERCHANGE_PROFILE_82_KRN(database);
            TERMINAL_CAPABILITIES_9F33_KRN         tc  = new TERMINAL_CAPABILITIES_9F33_KRN(database);
            TERMINAL_VERIFICATION_RESULTS_95_KRN   tvr = new TERMINAL_VERIFICATION_RESULTS_95_KRN(database);

            REFERENCE_CONTROL_PARAMETER_DF8114_KRN2 rcp = new REFERENCE_CONTROL_PARAMETER_DF8114_KRN2(database);

            if (!
                (((database.Get(EMVTagsEnum.CRYPTOGRAM_INFORMATION_DATA_9F27_KRN).Value[0] & 0xC0) == 0x40 && rcp.Value.ACTypeEnum == ACTypeEnum.TC) ||
                 ((database.Get(EMVTagsEnum.CRYPTOGRAM_INFORMATION_DATA_9F27_KRN).Value[0] & 0xC0) == 0x80 && (rcp.Value.ACTypeEnum == ACTypeEnum.TC || rcp.Value.ACTypeEnum == ACTypeEnum.ARQC)) ||
                 ((database.Get(EMVTagsEnum.CRYPTOGRAM_INFORMATION_DATA_9F27_KRN).Value[0] & 0xC0) == 0x00))
                )
            {
                return(State_7_10_CommonProcessing.DoInvalidResponsePart_C(database, qManager, L1Enum.NOT_SET, L2Enum.CARD_DATA_MISSING, L3Enum.NOT_SET));
            }

            if (aip.Value.CDASupported && tc.Value.CDACapable)
            {
                string  aid                 = emvSelectApplicationResponse.GetDFName();
                string  rid                 = aid.Substring(0, 10);
                RIDEnum ridEnum             = (RIDEnum)Enum.Parse(typeof(RIDEnum), rid);
                CAPublicKeyCertificate capk = database.PublicKeyCertificateManager.GetCAPK(ridEnum, database.Get(EMVTagsEnum.CERTIFICATION_AUTHORITY_PUBLIC_KEY_INDEX_8F_KRN).Value[0]);

                if (capk == null)
                {
                    tvr.Value.CDAFailed = true;
                    tvr.UpdateDB();
                }

                if (database.IsNotEmpty(EMVTagsEnum.SIGNED_DYNAMIC_APPLICATION_DATA_9F4B_KRN.Tag))
                {
                    State_7_10_CommonProcessing.DoCDA(database, qManager, capk, cardQManager, cardResponse, emvSelectApplicationResponse, false);
                }
                else
                {
                    tvr.Value.CDAFailed = true;
                    tvr.UpdateDB();
                }
            }
            return(State_7_10_CommonProcessing.EndOnTCorAAC(database, qManager, cardQManager));
        }
        private static SignalsEnum EntryPointRA(KernelDatabase database, CardResponse cardResponse, KernelQ qManager, CardQ cardQManager, EMVSelectApplicationResponse emvSelectApplicationResponse, Stopwatch sw)
        {
            bool signedFlag;
            byte sfi;

            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);

            TLV nextTLV = database.TagsToReadYet.GetNextGetDataTagFromList();

            if (nextTLV != null)
            {
                database.ActiveTag = nextTLV.Tag.TagLable;
            }
            else
            {
                database.ActiveTag = null;
            }

            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)
            {
                //added for cards returning misformtted data, read records instruction returns no data
                if (cardResponse.ApduResponse.ResponseData.Length == 0)
                {
                    parsingResult = true;
                }
                else
                {
                    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 this specification
            {
                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();
            }

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

            return(DoCommonProcessing("State_4_WaitingForEMVReadRecord", database, qManager, cardQManager, sw, emvSelectApplicationResponse));
        }
        public static SignalsEnum DoCommonProcessing(string source, KernelDatabase database, KernelQ qManager, CardQ cardQManager, Stopwatch sw, EMVSelectApplicationResponse emvSelectApplicationResponse)
        {
            if (database.NextCommandEnum == NextCommandEnum.READ_RECORD)
            {
                DoDEKIfNeeded(database, qManager);
                return(SignalsEnum.WAITING_FOR_EMV_READ_RECORD_RESPONSE);
            }

            DoDEKIfNeeded(database, qManager);

            if (database.IsEmpty(EMVTagsEnum.AMOUNT_AUTHORISED_NUMERIC_9F02_KRN.Tag))
            {
                CommonRoutines.CreateEMVDiscretionaryData(database);
                return(CommonRoutines.PostOutcomeWithError(database, qManager, Kernel2OutcomeStatusEnum.END_APPLICATION, Kernel2StartEnum.N_A, L1Enum.NOT_SET, L2Enum.NOT_SET, L3Enum.AMOUNT_NOT_PRESENT));
            }

            if (!(database.IsNotEmpty(EMVTagsEnum.APPLICATION_EXPIRATION_DATE_5F24_KRN.Tag) &&
                  database.IsNotEmpty(EMVTagsEnum.APPLICATION_PRIMARY_ACCOUNT_NUMBER_PAN_5A_KRN.Tag) &&
                  database.IsNotEmpty(EMVTagsEnum.CARD_RISK_MANAGEMENT_DATA_OBJECT_LIST_1_CDOL1_8C_KRN.Tag)))
            {
                CommonRoutines.CreateEMVDiscretionaryData(database);
                return(CommonRoutines.PostOutcome(database, qManager,
                                                  KernelMessageidentifierEnum.ERROR_OTHER_CARD,
                                                  KernelStatusEnum.NOT_READY,
                                                  null,
                                                  Kernel2OutcomeStatusEnum.END_APPLICATION,
                                                  Kernel2StartEnum.N_A,
                                                  true,
                                                  KernelMessageidentifierEnum.N_A,
                                                  L1Enum.NOT_SET,
                                                  null,
                                                  L2Enum.CARD_DATA_MISSING,
                                                  L3Enum.NOT_SET));
            }

            #region Book 3 Section 10.3
            APPLICATION_INTERCHANGE_PROFILE_82_KRN aipCheck = new APPLICATION_INTERCHANGE_PROFILE_82_KRN(database);
            TERMINAL_CAPABILITIES_9F33_KRN         tc       = new TERMINAL_CAPABILITIES_9F33_KRN(database);
            TERMINAL_VERIFICATION_RESULTS_95_KRN   tvr      = new TERMINAL_VERIFICATION_RESULTS_95_KRN(database);
            if ((aipCheck.Value.CDASupported && tc.Value.CDACapable) ||
                aipCheck.Value.DDAsupported && tc.Value.DDACapable ||
                aipCheck.Value.SDASupported && tc.Value.SDACapable)
            {
                if (aipCheck.Value.CDASupported && tc.Value.CDACapable)
                {
                    //some checking in preperation for ODA is done here, ODA is done after 1st gen ac
                    if (!(
                            database.IsNotEmpty(EMVTagsEnum.CERTIFICATION_AUTHORITY_PUBLIC_KEY_INDEX_8F_KRN.Tag) &&
                            database.IsNotEmpty(EMVTagsEnum.ISSUER_PUBLIC_KEY_CERTIFICATE_90_KRN.Tag) &&
                            database.IsNotEmpty(EMVTagsEnum.ISSUER_PUBLIC_KEY_EXPONENT_9F32_KRN.Tag) &&
                            database.IsNotEmpty(EMVTagsEnum.INTEGRATED_CIRCUIT_CARD_ICC_PUBLIC_KEY_CERTIFICATE_9F46_KRN.Tag) &&
                            database.IsNotEmpty(EMVTagsEnum.INTEGRATED_CIRCUIT_CARD_ICC_PUBLIC_KEY_EXPONENT_9F47_KRN.Tag) //&&
                            //database.IsNotEmpty(EMVTagsEnum.STATIC_DATA_AUTHENTICATION_TAG_LIST_9F4A_KRN.Tag)
                            ))
                    {
                        tvr.Value.ICCDataMissing = true;
                        tvr.Value.CDAFailed      = true;
                    }
                }

                string  aid     = emvSelectApplicationResponse.GetDFName();
                string  rid     = aid.Substring(0, 10);
                RIDEnum ridEnum = (RIDEnum)Enum.Parse(typeof(RIDEnum), rid);
                if (database.PublicKeyCertificateManager.GetCAPK(ridEnum, database.Get(EMVTagsEnum.CERTIFICATION_AUTHORITY_PUBLIC_KEY_INDEX_8F_KRN).Value[0]) == null)
                {
                    if (aipCheck.Value.CDASupported && tc.Value.CDACapable)
                    {
                        tvr.Value.CDAFailed = true;
                    }
                    if (aipCheck.Value.DDAsupported && tc.Value.DDACapable)
                    {
                        tvr.Value.DDAFailed = true;
                    }
                    if (aipCheck.Value.SDASupported && tc.Value.SDACapable)
                    {
                        tvr.Value.SDAFailed = true;
                    }
                }

                //bool aipFound = false;
                //TLV aip = null;
                //if (database.IsNotEmpty(EMVTagsEnum.STATIC_DATA_AUTHENTICATION_TAG_LIST_9F4A_KRN.Tag))
                //{
                //    TLV sdal = database.Get(EMVTagsEnum.STATIC_DATA_AUTHENTICATION_TAG_LIST_9F4A_KRN);
                //    TLVList list = TLV.DeserializeChildrenWithNoLV(sdal.Value, 0);
                //    //if (list.Count == 1)
                //    //{
                //    aip = list.Get(EMVTagsEnum.APPLICATION_INTERCHANGE_PROFILE_82_KRN.Tag);
                //    if (aip != null)
                //    {
                //        aipFound = true;
                //    }
                //    //}
                //}
                //else
                //{
                //    if (database.IsNotEmpty(EMVTagsEnum.APPLICATION_INTERCHANGE_PROFILE_82_KRN.Tag))
                //    {
                //        aip = database.Get(EMVTagsEnum.APPLICATION_INTERCHANGE_PROFILE_82_KRN.Tag);
                //        aipFound = true;
                //    }
                //}
                //if (database.IsNotEmpty(EMVTagsEnum.APPLICATION_INTERCHANGE_PROFILE_82_KRN.Tag))
                //{
                //    aip = database.Get(EMVTagsEnum.APPLICATION_INTERCHANGE_PROFILE_82_KRN.Tag);
                //    aipFound = true;
                //}

                TLV aip = database.Get(EMVTagsEnum.APPLICATION_INTERCHANGE_PROFILE_82_KRN);
                if (database.IsEmpty(EMVTagsEnum.APPLICATION_INTERCHANGE_PROFILE_82_KRN.Tag))
                {
                    CommonRoutines.CreateEMVDiscretionaryData(database);
                    return(CommonRoutines.PostOutcome(database, qManager,
                                                      KernelMessageidentifierEnum.ERROR_OTHER_CARD,
                                                      KernelStatusEnum.NOT_READY,
                                                      null,
                                                      Kernel2OutcomeStatusEnum.END_APPLICATION,
                                                      Kernel2StartEnum.N_A,
                                                      true,
                                                      KernelMessageidentifierEnum.ERROR_OTHER_CARD,
                                                      L1Enum.NOT_SET,
                                                      null,
                                                      L2Enum.CARD_DATA_ERROR,
                                                      L3Enum.NOT_SET));
                }

                int length = database.StaticDataToBeAuthenticated.Serialize().Length;
                if (2048 - length >= aip.Value.Length)
                {
                    //will be removed later when the SDA is done
                    database.StaticDataToBeAuthenticated.AddToList(aip);
                }
                //else
                //{
                //    if (aipCheck.Value.CDASupported && tc.Value.CDACapable)
                //    {
                //        tvr.Value.CDAFailed = true;
                //    }
                //    if (aipCheck.Value.DDAsupported && tc.Value.DDACapable)
                //    {
                //        tvr.Value.DDAFailed = true;
                //    }
                //    if (aipCheck.Value.SDASupported && tc.Value.SDACapable)
                //    {
                //        tvr.Value.SDAFailed = true;
                //    }
                //}
                tvr.UpdateDB();
            }
            #endregion

            #region Book 3 Section 10.4
            //using kernel 2 processing restrictions
            ProcessingRestrictions_7_7.ProcessingRestrictions(database);
            #endregion

            return(SignalsEnum.WAITING_FOR_CVM_PROCESSING);
        }
예제 #11
0
        private static SignalsEnum EntryPointRA(KernelDatabase database, CardResponse cardResponse, KernelQ qManager, CardQ cardQManager, PublicKeyCertificateManager pkcm, EMVSelectApplicationResponse emvSelectApplicationResponse, Stopwatch sw)
        {
            CARDHOLDER_VERIFICATION_METHOD_CVM_RESULTS_9F34_KRN cvr = new CARDHOLDER_VERIFICATION_METHOD_CVM_RESULTS_9F34_KRN(database);

            EMVGetChallengeResponse response = (EMVGetChallengeResponse)cardResponse.ApduResponse;

            if (!response.Succeeded)
            {
                cvr.Value.CVMResult = 0x01;//failed
                cvr.UpdateDB();
                return(SignalsEnum.WAITING_FOR_CVM_PROCESSING);
            }

            //store the challenge
            byte[] pinChallenge = response.ResponseData;

            if (cvr.Value.GetCVMPerformed() == CVMCode.EncipheredPINVerificationPerformedByICC ||
                cvr.Value.GetCVMPerformed() == CVMCode.EncipheredPINVerificationPerformedByICCAndSignature_Paper)
            {
                string  aid                 = emvSelectApplicationResponse.GetDFName();
                string  rid                 = aid.Substring(0, 10);
                RIDEnum ridEnum             = (RIDEnum)Enum.Parse(typeof(RIDEnum), rid);
                CAPublicKeyCertificate capk = pkcm.GetCAPK(ridEnum, database.Get(EMVTagsEnum.CERTIFICATION_AUTHORITY_PUBLIC_KEY_INDEX_8F_KRN).Value[0]);
                if (capk == null)
                {
                    cvr.Value.CVMResult = 0x01;//failed
                    cvr.UpdateDB();
                    return(SignalsEnum.WAITING_FOR_CVM_PROCESSING);
                }

                string pin      = Formatting.ByteArrayToASCIIString(database.Get(EMVTagsEnum.TRANSACTION_PERSONAL_IDENTIFICATION_NUMBER_PIN_DATA_99_KRN.Tag).Value);
                byte[] pinBlock = PinProcessing.BuildPlainTextPinBlock(pin);

                //encrypt the pin
                byte[] encipheredPin = PinProcessing.BuildPinVerifyData(database, capk, pinBlock, pinChallenge);
                if (encipheredPin == null)
                {
                    cvr.Value.CVMResult = 0x01;//failed
                    cvr.UpdateDB();
                    return(SignalsEnum.WAITING_FOR_CVM_PROCESSING);
                }

                //fire off verify for enciphered pin
                EMVVerifyRequest request = new EMVVerifyRequest(VerifyCommandDataQualifier.Enciphered_PIN, encipheredPin);
                cardQManager.EnqueueToInput(new CardRequest(request, CardinterfaceServiceRequestEnum.ADPU));
            }


            //verify message for plain text pin fired in waiting for pin response
            return(SignalsEnum.WAITING_FOR_VERIFY);
        }
예제 #12
0
        public static SignalsEnum InitiateCardActionAnalysis(KernelDatabaseBase database, KernelQ qManager, CardQ cardQManager, EMVSelectApplicationResponse emvSelectApplicationResponse)
        {
            APPLICATION_INTERCHANGE_PROFILE_82_KRN aip = new APPLICATION_INTERCHANGE_PROFILE_82_KRN(database);
            TERMINAL_CAPABILITIES_9F33_KRN         tc  = new TERMINAL_CAPABILITIES_9F33_KRN(database);
            TERMINAL_VERIFICATION_RESULTS_95_KRN   tvr = new TERMINAL_VERIFICATION_RESULTS_95_KRN(database);

            //time to get signature data for dda cards, in order to do oda after 1st gen ac
            EMVGenerateACRequest request = null;

            if (aip.Value.CDASupported && tc.Value.CDACapable)
            {
                //cda done after gen ac 1, call gen ac1 now with signature requested
                request = CreateGenAC(database, true);
                cardQManager.EnqueueToInput(new CardRequest(request, CardinterfaceServiceRequestEnum.ADPU));
                return(SignalsEnum.WAITING_FOR_GEN_AC_1);
            }
            if (aip.Value.DDAsupported && tc.Value.DDACapable)
            {
                #region Book 3 Section 10.3
                //do dda signature request, internal authenticate will do oda once it has the signature
                TLV    ddol = database.Get(EMVTagsEnum.DYNAMIC_DATA_AUTHENTICATION_DATA_OBJECT_LIST_DDOL_9F49_KRN);
                byte[] ddolRelatedData;
                if (ddol == null)
                {
                    TLV unpred = database.Get(EMVTagsEnum.UNPREDICTABLE_NUMBER_9F37_KRN);
                    unpred.Val.PackValue(unpred.Val.GetLength());
                    ddolRelatedData = unpred.Value;
                }
                else
                {
                    ddolRelatedData = CommonRoutines.PackRelatedDataTag(database, ddol);
                }
                EMVInternalAuthenticateRequest requestDDA = new EMVInternalAuthenticateRequest(ddolRelatedData);
                cardQManager.EnqueueToInput(new CardRequest(requestDDA, CardinterfaceServiceRequestEnum.ADPU));
                return(SignalsEnum.WAITING_FOR_INTERNAL_AUTHENTICATE);

                #endregion
            }
            if (aip.Value.SDASupported && tc.Value.SDACapable)
            {
                string  aid                 = emvSelectApplicationResponse.GetDFName();
                string  rid                 = aid.Substring(0, 10);
                RIDEnum ridEnum             = (RIDEnum)Enum.Parse(typeof(RIDEnum), rid);
                CAPublicKeyCertificate capk = database.PublicKeyCertificateManager.GetCAPK(ridEnum, database.Get(EMVTagsEnum.CERTIFICATION_AUTHORITY_PUBLIC_KEY_INDEX_8F_KRN).Value[0]);

                TLV ssadTLV = database.Get(EMVTagsEnum.SIGNED_STATIC_APPLICATION_DATA_93_KRN);
                if (capk == null || ssadTLV == null)
                {
                    tvr.Value.SDAFailed = true;
                    tvr.UpdateDB();
                }
                else
                {
                    TRANSACTION_STATUS_INFORMATION_9B_KRN tsi = new TRANSACTION_STATUS_INFORMATION_9B_KRN(database);
                    tsi.Value.OfflineDataAuthenticationWasPerformed = true;
                    tsi.UpdateDB();

                    byte[] sdadRaw  = database.Get(EMVTagsEnum.SIGNED_STATIC_APPLICATION_DATA_93_KRN).Value;
                    byte[] authCode = VerifySAD.VerifySSAD(ICCDynamicDataType.DYNAMIC_NUMBER_ONLY, database, capk, sdadRaw);
                    if (authCode == null)
                    {
                        tvr.Value.SDAFailed = true;
                        tvr.UpdateDB();
                    }
                    else
                    {
                        TLV dataAuthenticationCode = database.Get(EMVTagsEnum.DATA_AUTHENTICATION_CODE_9F45_KRN);
                        if (dataAuthenticationCode == null)
                        {
                            dataAuthenticationCode = TLV.Create(EMVTagsEnum.DATA_AUTHENTICATION_CODE_9F45_KRN.Tag, authCode);
                        }
                        else
                        {
                            dataAuthenticationCode.Value = authCode;
                        }
                    }
                }

                //sda done after gen ac 1, call gen ac 1 now with no signature requested
                request = CreateGenAC(database, false);
                cardQManager.EnqueueToInput(new CardRequest(request, CardinterfaceServiceRequestEnum.ADPU));
                return(SignalsEnum.WAITING_FOR_GEN_AC_1);
            }

            tvr.Value.OfflineDataAuthenticationWasNotPerformed = true;
            tvr.UpdateDB();
            //to do: ceck this, is this correct for a card where no oda is supported
            request = CreateGenAC(database, false);
            cardQManager.EnqueueToInput(new CardRequest(request, CardinterfaceServiceRequestEnum.ADPU));
            return(SignalsEnum.WAITING_FOR_GEN_AC_1);
        }
예제 #13
0
        public static SignalsEnum Initiate2ndCardActionAnalysis(KernelDatabaseBase database, KernelQ qManager, CardQ cardQManager, EMVSelectApplicationResponse emvSelectApplicationResponse, bool entryFromScriptProcessingCompleted = false)
        {
            if (!entryFromScriptProcessingCompleted)
            {
                //check if scripts need to be run
                TLV _71 = database.Get(EMVTagsEnum.ISSUER_SCRIPT_TEMPLATE_1_71_KRN);
                if (_71 != null)
                {
                    ((KernelDatabase)database).ScriptsToRunBeforeGenAC = BuildScriptList(_71);
                    if (((KernelDatabase)database).ScriptsToRunBeforeGenAC.Count > 0)
                    {
                        ((KernelDatabase)database).IsScriptProcessingBeforeGenACInProgress = true;
                        //post first script
                        TLV firstScript = ((KernelDatabase)database).ScriptsToRunBeforeGenAC.GetFirstAndRemoveFromList();
                        EMVScriptCommandRequest scriptRequest = new EMVScriptCommandRequest();
                        scriptRequest.Deserialize(firstScript.Value);
                        cardQManager.EnqueueToInput(new CardRequest(scriptRequest, CardinterfaceServiceRequestEnum.ADPU));
                        return(SignalsEnum.WAITING_FOR_SCRIPT_PROCESSING);
                    }
                }
            }

            APPLICATION_INTERCHANGE_PROFILE_82_KRN aip = new APPLICATION_INTERCHANGE_PROFILE_82_KRN(database);
            TERMINAL_CAPABILITIES_9F33_KRN         tc  = new TERMINAL_CAPABILITIES_9F33_KRN(database);

            //section 6.5.5 in Book 3
            TLV cdol2 = database.Get(EMVTagsEnum.CARD_RISK_MANAGEMENT_DATA_OBJECT_LIST_2_CDOL2_8D_KRN);

            byte[] cdol2Data = CommonRoutines.PackRelatedDataTag(database, cdol2);

            REFERENCE_CONTROL_PARAMETER_DF8114_KRN2 rcpST = new REFERENCE_CONTROL_PARAMETER_DF8114_KRN2(database);

            rcpST.Value.ACTypeEnum = GetDSACType(database);
            if (aip.Value.CDASupported && tc.Value.CDACapable)
            {
                rcpST.Value.CDASignatureRequested = true;
            }
            else
            {
                rcpST.Value.CDASignatureRequested = false;
            }
            rcpST.UpdateDB();

            EMVGenerateACRequest request = new EMVGenerateACRequest(cdol2Data, null, rcpST);

            cardQManager.EnqueueToInput(new CardRequest(request, CardinterfaceServiceRequestEnum.ADPU));

            return(SignalsEnum.WAITING_FOR_GEN_AC_2);
        }
        private static SignalsEnum EntryPointRA(KernelDatabase database, CardResponse cardResponse, KernelQ qManager, CardQ cardQManager, Stopwatch sw, PublicKeyCertificateManager publicKeyCertificateManager, EMVSelectApplicationResponse emvSelectApplicationResponse)
        {
            if (database.IsScriptProcessingBeforeGenACInProgress)
            {
                if (cardResponse.ApduResponse.SW1 != 0x90 && cardResponse.ApduResponse.SW1 != 0x62 && cardResponse.ApduResponse.SW1 != 0x63)
                {
                    TERMINAL_VERIFICATION_RESULTS_95_KRN tvr = new TERMINAL_VERIFICATION_RESULTS_95_KRN(database);
                    tvr.Value.ScriptProcessingFailedBeforeFinalGENERATEAC = true;
                    tvr.UpdateDB();
                    database.IsScriptProcessingBeforeGenACInProgress = false;
                    return(CardActionAnalysis.Initiate2ndCardActionAnalysis(database, qManager, cardQManager, emvSelectApplicationResponse));
                }

                if (database.ScriptsToRunBeforeGenAC.Count == 0)
                {
                    database.IsScriptProcessingBeforeGenACInProgress = false;
                    return(CardActionAnalysis.Initiate2ndCardActionAnalysis(database, qManager, cardQManager, emvSelectApplicationResponse, true));
                }

                TLV firstScript = database.ScriptsToRunBeforeGenAC.GetFirstAndRemoveFromList();
                EMVScriptCommandRequest scriptRequest = new EMVScriptCommandRequest();
                scriptRequest.Deserialize(firstScript.Value);
                cardQManager.EnqueueToInput(new CardRequest(scriptRequest, CardinterfaceServiceRequestEnum.ADPU));
                return(SignalsEnum.WAITING_FOR_SCRIPT_PROCESSING);
            }
            else
            {
                if (cardResponse.ApduResponse.SW1 != 0x90 && cardResponse.ApduResponse.SW1 != 0x62 && cardResponse.ApduResponse.SW1 != 0x63)
                {
                    TERMINAL_VERIFICATION_RESULTS_95_KRN tvr = new TERMINAL_VERIFICATION_RESULTS_95_KRN(database);
                    tvr.Value.ScriptProcessingFailedAfterFinalGENERATEAC = true;
                    tvr.UpdateDB();
                    //update emv data to return with this updated value
                    if (database.Get(EMVTagsEnum.DATA_RECORD_FF8105_KRN2) != null)
                    {
                        database.Get(EMVTagsEnum.DATA_RECORD_FF8105_KRN2).Children.RemoveFromList(database.Get(EMVTagsEnum.TERMINAL_VERIFICATION_RESULTS_95_KRN.Tag));
                        database.Get(EMVTagsEnum.DATA_RECORD_FF8105_KRN2).Children.AddToList(TLV.Create(EMVTagsEnum.TERMINAL_VERIFICATION_RESULTS_95_KRN.Tag, database.Get(EMVTagsEnum.TERMINAL_VERIFICATION_RESULTS_95_KRN).Value));
                    }
                    return(SignalsEnum.STOP);
                }
                if (database.ScriptsToRunAfterGenAC.Count == 0)
                {
                    return(SignalsEnum.STOP);
                }

                TLV firstScript = database.ScriptsToRunAfterGenAC.GetFirstAndRemoveFromList();
                EMVScriptCommandRequest scriptRequest = new EMVScriptCommandRequest();
                scriptRequest.Deserialize(firstScript.Value);
                cardQManager.EnqueueToInput(new CardRequest(scriptRequest, CardinterfaceServiceRequestEnum.ADPU));
                return(SignalsEnum.WAITING_FOR_SCRIPT_PROCESSING);
            }
        }
        private static SignalsEnum EntryPointRA(KernelDatabase database, CardResponse cardResponse, KernelQ qManager, CardQ cardQManager, Stopwatch sw, PublicKeyCertificateManager publicKeyCertificateManager, EMVSelectApplicationResponse emvSelectApplicationResponse)
        {
            if (!cardResponse.ApduResponse.Succeeded)
            {
                return(State_7_10_CommonProcessing.DoInvalidResponsePart_C(database, qManager, L1Enum.NOT_SET, L2Enum.STATUS_BYTES, L3Enum.NOT_SET));
            }

            bool parsingResult = false;

            if (cardResponse.ApduResponse.ResponseData.Length > 0 && cardResponse.ApduResponse.ResponseData[0] == 0x77)
            {
                EMVGenerateACResponse response = cardResponse.ApduResponse as EMVGenerateACResponse;
                parsingResult = database.ParseAndStoreCardResponse(response.ResponseData);
            }
            else
            {
                if (cardResponse.ApduResponse.ResponseData.Length > 0 && cardResponse.ApduResponse.ResponseData[0] == 0x80)
                {
                    if (cardResponse.ApduResponse.ResponseData.Length < 11 ||
                        cardResponse.ApduResponse.ResponseData.Length > 43 ||
                        database.IsNotEmpty(EMVTagsEnum.CRYPTOGRAM_INFORMATION_DATA_9F27_KRN.Tag) ||
                        database.IsNotEmpty(EMVTagsEnum.APPLICATION_TRANSACTION_COUNTER_ATC_9F36_KRN.Tag) ||
                        database.IsNotEmpty(EMVTagsEnum.APPLICATION_CRYPTOGRAM_9F26_KRN.Tag) ||
                        (cardResponse.ApduResponse.ResponseData.Length > 11 &&
                         database.IsNotEmpty(EMVTagsEnum.ISSUER_APPLICATION_DATA_9F10_KRN.Tag))
                        )
                    {
                        parsingResult = false;
                    }
                    else
                    {
                        byte[] responseBuffer = new byte[cardResponse.ApduResponse.ResponseData.Length - 2];
                        Array.Copy(cardResponse.ApduResponse.ResponseData, 2, responseBuffer, 0, responseBuffer.Length);
                        database.AddToList(TLV.Create(EMVTagsEnum.CRYPTOGRAM_INFORMATION_DATA_9F27_KRN.Tag, new byte[] { responseBuffer[0] }));
                        database.AddToList(TLV.Create(EMVTagsEnum.APPLICATION_TRANSACTION_COUNTER_ATC_9F36_KRN.Tag, new byte[] { responseBuffer[1], responseBuffer[2] }));

                        byte[] ac = new byte[8];
                        Array.Copy(responseBuffer, 3, ac, 0, 8);
                        database.AddToList(TLV.Create(EMVTagsEnum.APPLICATION_CRYPTOGRAM_9F26_KRN.Tag, ac));
                        if (responseBuffer.Length > 11)
                        {
                            byte[] iad = new byte[responseBuffer.Length - 11];
                            Array.Copy(responseBuffer, 11, iad, 0, iad.Length);
                            database.AddToList(TLV.Create(EMVTagsEnum.ISSUER_APPLICATION_DATA_9F10_KRN.Tag, iad));
                        }
                        parsingResult = true;
                    }
                }
            }

            if (!parsingResult)
            {
                return(State_7_10_CommonProcessing.DoInvalidResponsePart_C(database, qManager, L1Enum.NOT_SET, L2Enum.PARSING_ERROR, L3Enum.NOT_SET));
            }

            if (!(database.IsNotEmpty(EMVTagsEnum.APPLICATION_TRANSACTION_COUNTER_ATC_9F36_KRN.Tag) &&
                  database.IsNotEmpty(EMVTagsEnum.CRYPTOGRAM_INFORMATION_DATA_9F27_KRN.Tag)))
            {
                return(State_7_10_CommonProcessing.DoInvalidResponsePart_C(database, qManager, L1Enum.NOT_SET, L2Enum.CARD_DATA_MISSING, L3Enum.NOT_SET));
            }

            REFERENCE_CONTROL_PARAMETER_DF8114_KRN2 rcp = new REFERENCE_CONTROL_PARAMETER_DF8114_KRN2(database);

            if (!
                (((database.Get(EMVTagsEnum.CRYPTOGRAM_INFORMATION_DATA_9F27_KRN).Value[0] & 0xC0) == 0x40 && rcp.Value.ACTypeEnum == ACTypeEnum.TC) ||
                 ((database.Get(EMVTagsEnum.CRYPTOGRAM_INFORMATION_DATA_9F27_KRN).Value[0] & 0xC0) == 0x80 && (rcp.Value.ACTypeEnum == ACTypeEnum.TC || rcp.Value.ACTypeEnum == ACTypeEnum.ARQC)) ||
                 ((database.Get(EMVTagsEnum.CRYPTOGRAM_INFORMATION_DATA_9F27_KRN).Value[0] & 0xC0) == 0x00))
                )
            {
                return(State_7_10_CommonProcessing.DoInvalidResponsePart_C(database, qManager, L1Enum.NOT_SET, L2Enum.CARD_DATA_MISSING, L3Enum.NOT_SET));
            }

            APPLICATION_INTERCHANGE_PROFILE_82_KRN aip = new APPLICATION_INTERCHANGE_PROFILE_82_KRN(database);
            TERMINAL_CAPABILITIES_9F33_KRN         tc  = new TERMINAL_CAPABILITIES_9F33_KRN(database);
            TERMINAL_VERIFICATION_RESULTS_95_KRN   tvr = new TERMINAL_VERIFICATION_RESULTS_95_KRN(database);

            if (aip.Value.CDASupported && tc.Value.CDACapable)
            {
                string  aid                 = emvSelectApplicationResponse.GetDFName();
                string  rid                 = aid.Substring(0, 10);
                RIDEnum ridEnum             = (RIDEnum)Enum.Parse(typeof(RIDEnum), rid);
                CAPublicKeyCertificate capk = database.PublicKeyCertificateManager.GetCAPK(ridEnum, database.Get(EMVTagsEnum.CERTIFICATION_AUTHORITY_PUBLIC_KEY_INDEX_8F_KRN).Value[0]);

                if (capk == null)
                {
                    tvr.Value.CDAFailed = true;
                    tvr.UpdateDB();
                }

                if (database.IsNotEmpty(EMVTagsEnum.SIGNED_DYNAMIC_APPLICATION_DATA_9F4B_KRN.Tag))
                {
                    State_7_10_CommonProcessing.DoCDA(database, qManager, capk, cardQManager, cardResponse, emvSelectApplicationResponse, true);
                }
                else
                {
                    tvr.Value.CDAFailed = true;
                    tvr.UpdateDB();
                }
            }
            else
            {
                if (aip.Value.DDAsupported && tc.Value.DDACapable)
                {
                    //oda was done already in waiting for internal authenticate
                }
                else
                {
                    if (aip.Value.SDASupported && tc.Value.SDACapable)
                    {
                        //sda was done already in card action analysis
                    }
                }
            }

            //check for offline approved or declined, if so end transaction
            if ((database.Get(EMVTagsEnum.CRYPTOGRAM_INFORMATION_DATA_9F27_KRN).Value[0] & 0xC0) == 0x40 ||
                (database.Get(EMVTagsEnum.CRYPTOGRAM_INFORMATION_DATA_9F27_KRN).Value[0] & 0xC0) == 0x00)
            {
                return(State_7_10_CommonProcessing.EndOnTCorAAC(database, qManager, cardQManager));
            }
            else
            {
                CommonRoutines.CreateEMVDataRecord(database);
                CommonRoutines.CreateEMVDiscretionaryData(database);
                qManager.EnqueueToOutput(new KernelOnlineResponse(database.Get(EMVTagsEnum.DATA_RECORD_FF8105_KRN2), database.Get(EMVTagsEnum.DISCRETIONARY_DATA_FF8106_KRN2)));
                return(SignalsEnum.WAITING_FOR_ONLINE_RESPONSE);
            }
        }
예제 #16
0
        private static SignalsEnum EntryPointRA(KernelDatabase database, CardResponse cardResponse, KernelQ qManager, CardQ cardQManager, Stopwatch sw, PublicKeyCertificateManager publicKeyCertificateManager, EMVSelectApplicationResponse emvSelectApplicationResponse)
        {
            if (!cardResponse.ApduResponse.Succeeded)
            {
                return(State_7_10_CommonProcessing.DoInvalidResponsePart_C(database, qManager, L1Enum.NOT_SET, L2Enum.STATUS_BYTES, L3Enum.NOT_SET));
            }

            SignalsEnum result = ProcessGenACCommand(database, cardResponse, qManager, cardQManager, sw, publicKeyCertificateManager, emvSelectApplicationResponse);

            TLV _72 = database.Get(EMVTagsEnum.ISSUER_SCRIPT_TEMPLATE_2_72_KRN);

            if (_72 != null)
            {
                database.ScriptsToRunAfterGenAC = CardActionAnalysis.BuildScriptList(_72);
                if (database.ScriptsToRunAfterGenAC.Count > 0)
                {
                    //post first script
                    TLV firstScript = database.ScriptsToRunAfterGenAC.GetFirstAndRemoveFromList();
                    EMVScriptCommandRequest scriptRequest = new EMVScriptCommandRequest();
                    scriptRequest.Deserialize(firstScript.Value);
                    cardQManager.EnqueueToInput(new CardRequest(scriptRequest, CardinterfaceServiceRequestEnum.ADPU));
                    return(SignalsEnum.WAITING_FOR_SCRIPT_PROCESSING);
                }
            }

            return(result);
        }
예제 #17
0
        private static SignalsEnum EntryPointRA(KernelDatabase database, CardResponse cardResponse, KernelQ qManager, CardQ cardQManager, Stopwatch sw, PublicKeyCertificateManager publicKeyCertificateManager, EMVSelectApplicationResponse emvSelectApplicationResponse)
        {
            if (!cardResponse.ApduResponse.Succeeded)
            {
                return(CommonRoutines.PostOutcome(database, qManager,
                                                  KernelMessageidentifierEnum.N_A,
                                                  KernelStatusEnum.N_A,
                                                  null,
                                                  Kernel2OutcomeStatusEnum.END_APPLICATION,
                                                  Kernel2StartEnum.N_A,
                                                  true,
                                                  KernelMessageidentifierEnum.ERROR_OTHER_CARD,
                                                  L1Enum.NOT_SET,
                                                  cardResponse.ApduResponse.SW12,
                                                  L2Enum.STATUS_BYTES,
                                                  L3Enum.NOT_SET));
            }

            EMVInternalAuthenticateResponse response = cardResponse.ApduResponse as EMVInternalAuthenticateResponse;

            string  aid                 = emvSelectApplicationResponse.GetDFName();
            string  rid                 = aid.Substring(0, 10);
            RIDEnum ridEnum             = (RIDEnum)Enum.Parse(typeof(RIDEnum), rid);
            CAPublicKeyCertificate capk = database.PublicKeyCertificateManager.GetCAPK(ridEnum, database.Get(EMVTagsEnum.CERTIFICATION_AUTHORITY_PUBLIC_KEY_INDEX_8F_KRN).Value[0]);

            #region 3.8.1.1
            bool ddaPassed = DoDDA(database, qManager, capk, response.GetTLVSignedApplicationData());
            #endregion
            if (!ddaPassed)
            {
                TERMINAL_VERIFICATION_RESULTS_95_KRN tvr = new TERMINAL_VERIFICATION_RESULTS_95_KRN(database);
                tvr.Value.DDAFailed = true;
                tvr.UpdateDB();
            }

            TLV cdol1 = database.Get(EMVTagsEnum.CARD_RISK_MANAGEMENT_DATA_OBJECT_LIST_1_CDOL1_8C_KRN);
            CommonRoutines.PackRelatedDataTag(database, EMVTagsEnum.CDOL1_RELATED_DATA_DF8107_KRN2, cdol1);

            REFERENCE_CONTROL_PARAMETER_DF8114_KRN2 rcpST = new REFERENCE_CONTROL_PARAMETER_DF8114_KRN2(database);
            rcpST.Value.ACTypeEnum            = database.ACType.Value.DSACTypeEnum;
            rcpST.Value.CDASignatureRequested = false;
            rcpST.UpdateDB();

            EMVGenerateACRequest request = new EMVGenerateACRequest(database.Get(EMVTagsEnum.CDOL1_RELATED_DATA_DF8107_KRN2), null, rcpST);
            cardQManager.EnqueueToInput(new CardRequest(request, CardinterfaceServiceRequestEnum.ADPU));

            return(SignalsEnum.WAITING_FOR_GEN_AC_1);
        }
예제 #18
0
        private static SignalsEnum EntryPointRA(KernelDatabase database, CardResponse cardResponse, KernelQ qManager, CardQ cardQManager, Stopwatch sw, PublicKeyCertificateManager publicKeyCertificateManager, EMVSelectApplicationResponse emvSelectApplicationResponse)
        {
            if (!cardResponse.ApduResponse.Succeeded)
            {
                TERMINAL_VERIFICATION_RESULTS_95_KRN tvr = new TERMINAL_VERIFICATION_RESULTS_95_KRN(database);
                tvr.Value.IssuerAuthenticationFailed = true;
                tvr.UpdateDB();
            }
            else
            {
                TRANSACTION_STATUS_INFORMATION_9B_KRN tsi = new TRANSACTION_STATUS_INFORMATION_9B_KRN(database);
                tsi.Value.IssuerAuthenticationWasPerformed = true;
                tsi.UpdateDB();
            }

            //EMVExternalAuthenticateResponse response = cardResponse.ApduResponse as EMVExternalAuthenticateResponse;

            //if scripts need to be run before gen ac, do now
            return(CardActionAnalysis.Initiate2ndCardActionAnalysis(database, qManager, cardQManager, emvSelectApplicationResponse));
        }
        CreateCandidateListByDirMethod(CardQProcessor cardInterfaceManager)
        {
            List <Tuple <TerminalSupportedKernelAidTransactionTypeCombination, CardKernelAidCombination> > candidateList = new List <Tuple <TerminalSupportedKernelAidTransactionTypeCombination, CardKernelAidCombination> >();

            foreach (TerminalSupportedKernelAidTransactionTypeCombination kc in TerminalSupportedKernelAidTransactionTypeCombinations.SupportedContactCombinations)
            {
                string finalAdfName = Enum.GetName(typeof(AIDEnum), ((TerminalSupportedContactKernelAidTransactionTypeCombination)kc).AIDEnum);
                #region 12.3.3 Step 1
                ApduResponse cardResponse = cardInterfaceManager.SendCommand(new EMVSelectApplicationRequest(finalAdfName)) as EMVSelectApplicationResponse;
                #endregion
                if (!(cardResponse is EMVSelectApplicationResponse))
                {
                    throw new EMVProtocolException("Pre-processing transmit error: try again");
                }

                EMVSelectApplicationResponse response = (EMVSelectApplicationResponse)cardResponse;

NextAID:
                #region 12.3.3 Step 2
                if (response.SW1 == 0x6A && response.SW2 == 0x81) //card blocked
                {
                    throw new Exception("Card blocked");
                }
                if (response.SW1 == 0x6A && response.SW2 == 0x81) //command not supported
                {
                    throw new Exception("Select command not supported");
                }
                if (response.SW1 == 0x6A && response.SW2 == 0x82) //file not found
                {
                    continue;
                }
                #endregion

                if (!response.Succeeded && !(response.SW1 == 0x62 && response.SW2 == 0x83))
                {
                    throw new Exception("Select command failed");
                }

                if (response.GetDFName() == finalAdfName)
                {
                    //full match
                    if (response.Succeeded) //i.e. app not blocked 0x6283
                    {
                        TLV            adfNameTag = response.GetDFNameTag();
                        TLV            applicationPriorityIndicatorTag = response.GetApplicationPriorityindicatorTag();
                        TLV            preferedName         = response.GetPreferredNameTag();
                        TLV            appLabel             = response.GetApplicationLabelTag();
                        Optional <TLV> extendedSelectionTag = Optional <TLV> .CreateEmpty();

                        candidateList.Add(Tuple.Create(kc, new CardKernelAidCombination()
                        {
                            AdfNameTag = adfNameTag,
                            ApplicationPriorityIndicatorTag = applicationPriorityIndicatorTag,
                            ApplicationPreferredName        = preferedName,
                            ApplicationLabel     = appLabel,
                            ExtendedSelectionTag = extendedSelectionTag,
                        }));
                        continue;
                    }
                }
                if (response.GetDFName().StartsWith(finalAdfName))
                {
                    //partial match
                    if (((TerminalSupportedContactKernelAidTransactionTypeCombination)kc).ApplicationSelectionIndicator)
                    {
                        if (response.Succeeded) //i.e. app not blocked 0x6283
                        {
                            TLV            adfNameTag = response.GetDFNameTag();
                            TLV            applicationPriorityIndicatorTag = response.GetApplicationPriorityindicatorTag();
                            TLV            preferedName         = response.GetPreferredNameTag();
                            TLV            appLabel             = response.GetApplicationLabelTag();
                            Optional <TLV> extendedSelectionTag = Optional <TLV> .CreateEmpty();

                            candidateList.Add(Tuple.Create(kc, new CardKernelAidCombination()
                            {
                                AdfNameTag = adfNameTag,
                                ApplicationPriorityIndicatorTag = applicationPriorityIndicatorTag,
                                ExtendedSelectionTag            = extendedSelectionTag,
                                ApplicationPreferredName        = preferedName,
                                ApplicationLabel = appLabel,
                            }));
                            continue;
                        }
                        else
                        {
                            ApduResponse cardResponseNext = cardInterfaceManager.SendCommand(new EMVSelectApplicationRequest(finalAdfName, true)) as EMVSelectApplicationResponse;
                            if (!(cardResponse is EMVSelectApplicationResponse))
                            {
                                throw new EMVProtocolException("Pre-processing transmit error: try again");
                            }

                            response = (EMVSelectApplicationResponse)cardResponse;
                            if (response.Succeeded || response.SW1 == 0x62 || response.SW1 == 0x63)
                            {
                                goto NextAID;
                            }
                        }
                    }
                }
            }
            return(candidateList);
        }