コード例 #1
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));
            }

            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);
            }
        }
コード例 #2
0
        private static SignalsEnum ProcessNextCVM(KernelDatabase database, KernelQ qManager, CardQ cardQManager, Stopwatch sw)
        {
            CARDHOLDER_VERIFICATION_METHOD_CVM_LIST_8E_KRN      cvl = new CARDHOLDER_VERIFICATION_METHOD_CVM_LIST_8E_KRN(database);
            CARDHOLDER_VERIFICATION_METHOD_CVM_RESULTS_9F34_KRN cvr = new CARDHOLDER_VERIFICATION_METHOD_CVM_RESULTS_9F34_KRN(database);

            bool goToNextCVM = false;

            if (cvr.Value.GetCVMPerformed() == CVMCode.EncipheredPINVerifiedOnline)
            {
                if (cvr.Value.GetCVMResult() == CVMResult.Failed)
                {
                    goToNextCVM = true;
                }
            }
            else
            {
                //if a previously run CVM failed then state returns here and we try the next CVM
                if (cvr.Value.GetCVMResult() != CVMResult.Success)
                {
                    goToNextCVM = true;
                }
            }

            if (goToNextCVM && database.CVMCurrentlySelectedCounter < cvl.Value.CardHolderVerificationRules.Count)
            {
                //if previous cvm was offline pin, check pin try counter
                if (cvr.Value.GetCVMPerformed() == CVMCode.EncipheredPINVerificationPerformedByICC ||
                    cvr.Value.GetCVMPerformed() == CVMCode.EncipheredPINVerificationPerformedByICCAndSignature_Paper ||
                    cvr.Value.GetCVMPerformed() == CVMCode.PlaintextPINVerificationPerformedByICC ||
                    cvr.Value.GetCVMPerformed() == CVMCode.PlaintextPINVerificationPerformedByICCAndSignature_Paper)
                {
                    TLV pinTryCounterTLV = database.Get(EMVTagsEnum.PERSONAL_IDENTIFICATION_NUMBER_PIN_TRY_COUNTER_9F17_KRN);
                    if (pinTryCounterTLV != null)
                    {
                        ushort pinTryCounter = Formatting.ConvertToInt16(pinTryCounterTLV.Value);
                        if (pinTryCounter > 1) //at this point the pin try counter on the card is 0, we are always 1 behind
                        {
                            qManager.EnqueueToOutput(new KernelPinResponse());
                            return(SignalsEnum.WAITING_FOR_PIN_RESPONSE);
                        }
                    }
                }

                #region Book 3 Section 10.5
                CVMSelection_7_5.CVMSelection(database, new Func <bool>(() => { return(true); }));
                cvr = new CARDHOLDER_VERIFICATION_METHOD_CVM_RESULTS_9F34_KRN(database);//update after calling cvm selection
                #endregion

                if (cvr.Value.GetCVMPerformed() == CVMCode.EncipheredPINVerificationPerformedByICC ||
                    cvr.Value.GetCVMPerformed() == CVMCode.EncipheredPINVerificationPerformedByICCAndSignature_Paper ||
                    cvr.Value.GetCVMPerformed() == CVMCode.PlaintextPINVerificationPerformedByICC ||
                    cvr.Value.GetCVMPerformed() == CVMCode.PlaintextPINVerificationPerformedByICCAndSignature_Paper ||
                    cvr.Value.GetCVMPerformed() == CVMCode.EncipheredPINVerifiedOnline)
                {
                    qManager.EnqueueToOutput(new KernelPinResponse());
                    return(SignalsEnum.WAITING_FOR_PIN_RESPONSE);
                }

                if (cvr.Value.GetCVMResult() == CVMResult.Failed)
                {
                    return(SignalsEnum.WAITING_FOR_CVM_PROCESSING);
                }
            }

            if (cvr.Value.GetCVMPerformed() != CVMCode.NoCVMDone)
            {
                TRANSACTION_STATUS_INFORMATION_9B_KRN tsi = new TRANSACTION_STATUS_INFORMATION_9B_KRN(database);
                tsi.Value.CardholderVerificationWasPerformed = true;
                tsi.UpdateDB();
            }

            #region Book 3 Section 10.6
            //Terminal Risk Management
            TLV lcol = database.Get(EMVTagsEnum.LOWER_CONSECUTIVE_OFFLINE_LIMIT_9F14_KRN);
            TLV ucol = database.Get(EMVTagsEnum.UPPER_CONSECUTIVE_OFFLINE_LIMIT_9F23_KRN);
            if (lcol != null && ucol != null)
            {
                EMVGetDataRequest requestATC           = new EMVGetDataRequest(Formatting.HexStringToByteArray(EMVTagsEnum.APPLICATION_TRANSACTION_COUNTER_ATC_9F36_KRN.Tag));
                EMVGetDataRequest requestLastOnlineATC = new EMVGetDataRequest(Formatting.HexStringToByteArray(EMVTagsEnum.LAST_ONLINE_APPLICATION_TRANSACTION_COUNTER_ATC_REGISTER_9F13_KRN.Tag));
                cardQManager.EnqueueToInput(new CardRequest(requestATC, CardinterfaceServiceRequestEnum.ADPU));
                cardQManager.EnqueueToInput(new CardRequest(requestLastOnlineATC, CardinterfaceServiceRequestEnum.ADPU));
            }

            //Get Floor Limit Data
            if (database.IsEmpty(EMVTagsEnum.TERMINAL_FLOOR_LIMIT_9F1B_KRN.Tag))
            {
                DATA_NEEDED_DF8106_KRN2 dataNeeded = new DATA_NEEDED_DF8106_KRN2(database);
                dataNeeded.Value.Tags.Add(EMVTagsEnum.TERMINAL_FLOOR_LIMIT_9F1B_KRN.Tag);
                dataNeeded.UpdateDB();
                CommonRoutines.PostDEK(database, qManager);
                database.Get(EMVTagsEnum.DATA_TO_SEND_FF8104_KRN2).Initialize();
                database.Get(EMVTagsEnum.DATA_NEEDED_DF8106_KRN2).Initialize();
            }

            qManager.EnqueueToOutput(new KernelTRMResponse());
            return(SignalsEnum.WAITING_FOR_TERMINAL_RISK_MANAGEMENT);

            #endregion
        }