Beispiel #1
0
        public static SignalsEnum EndOnTCorAAC(KernelDatabase database, KernelQ qManager, CardQ cardQManager)
        {
            CommonRoutines.CreateEMVDataRecord(database);

            Kernel2OutcomeStatusEnum    k2OutcomeStatus     = Kernel2OutcomeStatusEnum.N_A;
            Kernel2StartEnum            k2StartStatus       = Kernel2StartEnum.N_A;
            KernelStatusEnum            k2Status            = KernelStatusEnum.N_A;
            KernelMessageidentifierEnum k2MessageIdentifier = KernelMessageidentifierEnum.N_A;

            byte[]             holdTime           = new byte[] { 0x00, 0x00, 0x00 };
            ValueQualifierEnum valueQualifierEnum = ValueQualifierEnum.NONE;
            KernelCVMEnum      cvmEnum            = new OUTCOME_PARAMETER_SET_DF8129_KRN2(database).Value.CVM;

            byte[] currencyCode   = new byte[2];
            byte[] valueQualifier = new byte[6];
            bool   uiRequestOnOutcomePresent;

            string tt = Formatting.ByteArrayToHexString(database.Get(EMVTagsEnum.TRANSACTION_TYPE_9C_KRN).Value);

            if ((database.Get(EMVTagsEnum.CRYPTOGRAM_INFORMATION_DATA_9F27_KRN).Value[0] & 0xC0) == 0x40)
            {
                k2OutcomeStatus = Kernel2OutcomeStatusEnum.APPROVED;
            }
            else
            {
                if ((database.Get(EMVTagsEnum.CRYPTOGRAM_INFORMATION_DATA_9F27_KRN).Value[0] & 0xC0) == 0x80)
                {
                    throw new EMVProtocolException("Invalid state in EndOnTCorAAC");
                }
                else
                {
                    k2OutcomeStatus = Kernel2OutcomeStatusEnum.DECLINED;
                }
            }

            k2Status = KernelStatusEnum.NOT_READY;

            if ((database.Get(EMVTagsEnum.CRYPTOGRAM_INFORMATION_DATA_9F27_KRN).Value[0] & 0xC0) == 0x40)
            {
                holdTime = database.GetDefault(EMVTagsEnum.MESSAGE_HOLD_TIME_DF812D_KRN2).Value;

                if (cvmEnum == KernelCVMEnum.OBTAIN_SIGNATURE)
                {
                    k2MessageIdentifier = KernelMessageidentifierEnum.APPROVED_SIGN;
                }
                else
                {
                    k2MessageIdentifier = KernelMessageidentifierEnum.APPROVED;
                }
            }
            else
            {
                if ((database.Get(EMVTagsEnum.CRYPTOGRAM_INFORMATION_DATA_9F27_KRN).Value[0] & 0xC0) == 0x80)
                {
                    throw new EMVProtocolException("Invalid state in EndOnTCorAAC");
                }
                else
                {
                    k2MessageIdentifier = KernelMessageidentifierEnum.DECLINED;
                }
            }

            CommonRoutines.CreateEMVDiscretionaryData(database);

            uiRequestOnOutcomePresent = true;

            return(CommonRoutines.PostOutcome(database, qManager,
                                              k2MessageIdentifier,
                                              k2Status,
                                              holdTime,
                                              k2OutcomeStatus,
                                              k2StartStatus,
                                              uiRequestOnOutcomePresent,
                                              KernelMessageidentifierEnum.N_A,
                                              L1Enum.NOT_SET,
                                              null,
                                              L2Enum.NOT_SET,
                                              L3Enum.NOT_SET,
                                              valueQualifierEnum,
                                              valueQualifier,
                                              currencyCode,
                                              false,
                                              cvmEnum));
        }
        private static SignalsEnum DoPart_E(Kernel2Database database, KernelQ qManager, CardQ cardQManager)
        {
            #region 9_10.70
            CommonRoutines.CreateEMVDataRecord(database);

            Kernel2OutcomeStatusEnum    k2OutcomeStatus     = Kernel2OutcomeStatusEnum.N_A;
            Kernel2StartEnum            k2StartStatus       = Kernel2StartEnum.N_A;
            KernelStatusEnum            k2Status            = KernelStatusEnum.N_A;
            KernelMessageidentifierEnum k2MessageIdentifier = KernelMessageidentifierEnum.N_A;
            byte[]             holdTime           = new byte[] { 0x00, 0x00, 0x00 };
            ValueQualifierEnum valueQualifierEnum = ValueQualifierEnum.NONE;
            KernelCVMEnum      cvmEnum            = new OUTCOME_PARAMETER_SET_DF8129_KRN2(database).Value.CVM;
            byte[]             currencyCode       = new byte[2];
            byte[]             valueQualifier     = new byte[6];
            bool uiRequestOnOutcomePresent;

            #endregion

            #region 9_10.71
            if (database.IsNotEmpty(EMVTagsEnum.POS_CARDHOLDER_INTERACTION_INFORMATION_DF4B_KRN2.Tag) &&
                ((int)Formatting.ConvertToInt32(database.Get(EMVTagsEnum.POS_CARDHOLDER_INTERACTION_INFORMATION_DF4B_KRN2).Value) & 0x0000030F) != 0x00000000)
            #endregion
            {
                #region 9_10.72
                k2OutcomeStatus = Kernel2OutcomeStatusEnum.END_APPLICATION;
                k2StartStatus   = Kernel2StartEnum.B;
                #endregion

                #region 9_10.73
                PHONE_MESSAGE_TABLE_DF8131_KRN2 pmt = new PHONE_MESSAGE_TABLE_DF8131_KRN2(database.GetDefault(EMVTagsEnum.PHONE_MESSAGE_TABLE_DF8131_KRN2));
                foreach (PhoneMessageTableEntry_DF8131 entry in pmt.Value.Entries)
                {
                    int pcii     = (int)Formatting.ConvertToInt32(database.Get(EMVTagsEnum.POS_CARDHOLDER_INTERACTION_INFORMATION_DF4B_KRN2).Value);
                    int pciMask  = (int)Formatting.ConvertToInt32(entry.PCIIMask);
                    int pciValue = (int)Formatting.ConvertToInt32(entry.PCIIValue);
                    if ((pciMask & pcii) == pciValue)
                    {
                        k2MessageIdentifier = entry.MessageIdentifier;
                        k2Status            = entry.Status;
                        holdTime            = database.GetDefault(EMVTagsEnum.MESSAGE_HOLD_TIME_DF812D_KRN2).Value;
                        break;
                    }
                }
                #endregion
            }
            else
            {
                string tt = Formatting.ByteArrayToHexString(database.Get(EMVTagsEnum.TRANSACTION_TYPE_9C_KRN).Value);
                #region 9_10.74
                if ((database.Get(EMVTagsEnum.CRYPTOGRAM_INFORMATION_DATA_9F27_KRN).Value[0] & 0xC0) == 0x40)
                #endregion
                {
                    k2OutcomeStatus = Kernel2OutcomeStatusEnum.APPROVED;
                }
                else
                {
                    if ((database.Get(EMVTagsEnum.CRYPTOGRAM_INFORMATION_DATA_9F27_KRN).Value[0] & 0xC0) == 0x80)
                    {
                        k2OutcomeStatus = Kernel2OutcomeStatusEnum.ONLINE_REQUEST;
                    }
                    else
                    {
                        /*
                         * Check if Transaction Type indicates a cash transaction (cash
                         * withdrawal or cash disbursement) or a purchase transaction (purchase
                         * or purchase with cashback).
                         */
                        if (tt == "01" || tt == "17" || tt == "00" || tt == "09")
                        {
                            if (database.IsNotEmpty(EMVTagsEnum.THIRD_PARTY_DATA_9F6E_KRN2.Tag))
                            {
                                THIRD_PARTY_DATA_9F6E_KRN      tpd = new THIRD_PARTY_DATA_9F6E_KRN(database);
                                TERMINAL_CAPABILITIES_9F33_KRN tc  = new TERMINAL_CAPABILITIES_9F33_KRN(database);
                                ushort uid = Formatting.ConvertToInt16(tpd.Value.UniqueIdentifier);
                                ushort dt  = Formatting.ConvertToInt16(tpd.Value.DeviceType);
                                if ((uid & 0x8000) == 0x0000 && dt != 0x3030 || tc.Value.ICWithContactsCapable)
                                {
                                    k2OutcomeStatus = Kernel2OutcomeStatusEnum.DECLINED;
                                }
                                else
                                {
                                    k2OutcomeStatus = Kernel2OutcomeStatusEnum.TRY_ANOTHER_INTERFACE;
                                }
                            }
                            else
                            {
                                k2OutcomeStatus = Kernel2OutcomeStatusEnum.TRY_ANOTHER_INTERFACE;
                            }
                        }
                        else
                        {
                            k2OutcomeStatus = Kernel2OutcomeStatusEnum.END_APPLICATION;
                        }
                    }
                }

                #region 9_10.75
                k2Status = KernelStatusEnum.NOT_READY;

                if ((database.Get(EMVTagsEnum.CRYPTOGRAM_INFORMATION_DATA_9F27_KRN).Value[0] & 0xC0) == 0x40)
                {
                    holdTime = database.GetDefault(EMVTagsEnum.MESSAGE_HOLD_TIME_DF812D_KRN2).Value;

                    if (database.IsNotEmpty(EMVTagsEnum.BALANCE_READ_AFTER_GEN_AC_DF8105_KRN2.Tag))
                    {
                        valueQualifierEnum = ValueQualifierEnum.BALANCE;
                        valueQualifier     = database.Get(EMVTagsEnum.BALANCE_READ_AFTER_GEN_AC_DF8105_KRN2).Value;
                        if (database.IsNotEmpty(EMVTagsEnum.APPLICATION_CURRENCY_CODE_9F42_KRN.Tag))
                        {
                            currencyCode = database.Get(EMVTagsEnum.APPLICATION_CURRENCY_CODE_9F42_KRN).Value;
                        }
                    }

                    if (cvmEnum == KernelCVMEnum.OBTAIN_SIGNATURE)
                    {
                        k2MessageIdentifier = KernelMessageidentifierEnum.APPROVED_SIGN;
                    }
                    else
                    {
                        k2MessageIdentifier = KernelMessageidentifierEnum.APPROVED;
                    }
                }
                else
                {
                    if ((database.Get(EMVTagsEnum.CRYPTOGRAM_INFORMATION_DATA_9F27_KRN).Value[0] & 0xC0) == 0x80)
                    {
                        holdTime            = new byte[] { 0x00, 0x00, 0x00 };
                        k2MessageIdentifier = KernelMessageidentifierEnum.AUTHORISING_PLEASE_WAIT;
                    }
                    else
                    {
                        if (tt == "01" || tt == "17" || tt == "00" || tt == "09")
                        {
                            holdTime = database.GetDefault(EMVTagsEnum.MESSAGE_HOLD_TIME_DF812D_KRN2).Value;


                            if (database.IsNotEmpty(EMVTagsEnum.THIRD_PARTY_DATA_9F6E_KRN2.Tag))
                            {
                                THIRD_PARTY_DATA_9F6E_KRN      tpd = new THIRD_PARTY_DATA_9F6E_KRN(database);
                                TERMINAL_CAPABILITIES_9F33_KRN tc  = new TERMINAL_CAPABILITIES_9F33_KRN(database);
                                ushort uid = Formatting.ConvertToInt16(tpd.Value.UniqueIdentifier);
                                ushort dt  = Formatting.ConvertToInt16(tpd.Value.DeviceType);
                                if ((uid & 0x8000) == 0x0000 && dt != 0x3030 || tc.Value.ICWithContactsCapable)
                                {
                                    k2MessageIdentifier = KernelMessageidentifierEnum.DECLINED;
                                }
                                else
                                {
                                    k2MessageIdentifier = KernelMessageidentifierEnum.INSERT_CARD;
                                }
                            }
                            else
                            {
                                k2MessageIdentifier = KernelMessageidentifierEnum.INSERT_CARD;
                            }
                        }
                        else
                        {
                            holdTime            = new byte[] { 0x00, 0x00, 0x00 };
                            k2MessageIdentifier = KernelMessageidentifierEnum.CLEAR_DISPLAY;
                        }
                    }
                }

                #endregion
            }

            #region 9_10.76
            if (database.IsNotEmpty(EMVTagsEnum.TAGS_TO_WRITE_AFTER_GEN_AC_FF8103_KRN2.Tag))
            #endregion
            {
                #region 9_10.77
                TLV tagToPut = database.TagsToWriteAfterGenACYet.GetFirstAndRemoveFromList();
                EMVPutDataRequest request = new EMVPutDataRequest(tagToPut);
                #endregion
                #region 9_10.78
                cardQManager.EnqueueToInput(new CardRequest(request, CardinterfaceServiceRequestEnum.ADPU));
                return(SignalsEnum.WAITING_FOR_PUT_DATA_RESPONSE_AFTER_GEN_AC);

                #endregion
            }

            CommonRoutines.CreateEMVDiscretionaryData(database);

            #region 9_10.78.1
            if (database.IsNotEmpty(EMVTagsEnum.POS_CARDHOLDER_INTERACTION_INFORMATION_DF4B_KRN2.Tag) &&
                ((int)Formatting.ConvertToInt32(database.Get(EMVTagsEnum.POS_CARDHOLDER_INTERACTION_INFORMATION_DF4B_KRN2).Value) & 0x0000030F) != 0x00000000)
            #endregion
            {
                #region 9_10.79
                CommonRoutines.PostUIOnly(database, qManager, k2MessageIdentifier, k2Status, true, holdTime);
                #endregion

                #region 9_10.80
                uiRequestOnOutcomePresent = false;
                k2Status = KernelStatusEnum.READY_TO_READ;
                holdTime = new byte[] { 0x00, 0x00, 0x00 };
                #endregion
            }
            else
            {
                #region 9_10.81
                uiRequestOnOutcomePresent = true;
                #endregion
            }
            return(CommonRoutines.PostOutcome(database, qManager,
                                              k2MessageIdentifier,
                                              k2Status,
                                              holdTime,
                                              k2OutcomeStatus,
                                              k2StartStatus,
                                              uiRequestOnOutcomePresent,
                                              KernelMessageidentifierEnum.N_A,
                                              L1Enum.NOT_SET,
                                              null,
                                              L2Enum.NOT_SET,
                                              L3Enum.NOT_SET,
                                              valueQualifierEnum,
                                              valueQualifier,
                                              currencyCode,
                                              false,
                                              cvmEnum));
        }
        private static SignalsEnum EntryPointRA(Kernel1Database database, CardResponse cardResponse, KernelQ qManager, CardQ cardQManager, Stopwatch sw, PublicKeyCertificateManager publicKeyCertificateManager)
        {
            if (!cardResponse.ApduResponse.Succeeded)
            {
                return(CommonRoutines.PostOutcome(database, qManager,
                                                  KernelMessageidentifierEnum.N_A,
                                                  KernelStatusEnum.N_A,
                                                  null,
                                                  Kernel2OutcomeStatusEnum.END_APPLICATION,
                                                  Kernel2StartEnum.N_A,
                                                  true,
                                                  KernelMessageidentifierEnum.ERROR_OTHER_CARD,
                                                  L1Enum.NOT_SET,
                                                  cardResponse.ApduResponse.SW12,
                                                  L2Enum.STATUS_BYTES,
                                                  L3Enum.NOT_SET));
            }

            bool parsingResult             = false;
            EMVGenerateACResponse response = cardResponse.ApduResponse as EMVGenerateACResponse;

            if (cardResponse.ApduResponse.ResponseData.Length > 0 && cardResponse.ApduResponse.ResponseData[0] == 0x77)
            {
                parsingResult = database.ParseAndStoreCardResponse(response.ResponseData);
            }
            else
            {
                if (cardResponse.ApduResponse.ResponseData.Length < 11 ||
                    cardResponse.ApduResponse.ResponseData.Length > 43 ||
                    database.IsNotEmpty(EMVTagsEnum.CRYPTOGRAM_INFORMATION_DATA_9F27_KRN.Tag) ||
                    database.IsNotEmpty(EMVTagsEnum.APPLICATION_TRANSACTION_COUNTER_ATC_9F36_KRN.Tag) ||
                    database.IsNotEmpty(EMVTagsEnum.APPLICATION_CRYPTOGRAM_9F26_KRN.Tag) ||
                    (cardResponse.ApduResponse.ResponseData.Length > 11 &&
                     database.IsNotEmpty(EMVTagsEnum.ISSUER_APPLICATION_DATA_9F10_KRN.Tag))
                    )
                {
                    parsingResult = false;
                }
                else
                {
                    database.AddToList(TLV.Create(EMVTagsEnum.CRYPTOGRAM_INFORMATION_DATA_9F27_KRN.Tag, response.CryptogramInformationData.Value));
                    database.AddToList(TLV.Create(EMVTagsEnum.APPLICATION_TRANSACTION_COUNTER_ATC_9F36_KRN.Tag, response.ApplicationTransactionCounter.Value));
                    database.AddToList(TLV.Create(EMVTagsEnum.APPLICATION_CRYPTOGRAM_9F26_KRN.Tag, response.ApplicationCryptogram.Value));
                    database.AddToList(TLV.Create(EMVTagsEnum.ISSUER_APPLICATION_DATA_9F10_KRN.Tag, response.IssuerApplicationData.Value));
                    parsingResult = true;
                }
            }

            if (!parsingResult)
            {
                return(CommonRoutines.PostOutcome(database, qManager,
                                                  KernelMessageidentifierEnum.N_A,
                                                  KernelStatusEnum.N_A,
                                                  null,
                                                  Kernel2OutcomeStatusEnum.END_APPLICATION,
                                                  Kernel2StartEnum.N_A,
                                                  true,
                                                  KernelMessageidentifierEnum.ERROR_OTHER_CARD,
                                                  L1Enum.NOT_SET,
                                                  null,
                                                  L2Enum.PARSING_ERROR,
                                                  L3Enum.NOT_SET));
            }

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

            #region 3.5.2.2
            TLV  cidTLV = database.Get(EMVTagsEnum.CRYPTOGRAM_INFORMATION_DATA_9F27_KRN);
            byte cid    = cidTLV.Value[0];
            cid = (byte)(cid >> 6);
            if (cid != (byte)ACTypeEnum.ARQC)
            {
                #region 3.10.3.1
                return(CommonRoutines.PostOutcome(database, qManager,
                                                  KernelMessageidentifierEnum.ERROR_OTHER_CARD,
                                                  KernelStatusEnum.PROCESSING_ERROR,
                                                  null,
                                                  Kernel2OutcomeStatusEnum.END_APPLICATION,
                                                  Kernel2StartEnum.N_A,
                                                  true,
                                                  KernelMessageidentifierEnum.ERROR_OTHER_CARD,
                                                  L1Enum.NOT_SET,
                                                  null,
                                                  L2Enum.CARD_DATA_ERROR,
                                                  L3Enum.NOT_SET));

                #endregion
            }
            #endregion

            #region 3.6.1.1
            CommonRoutines.PostUIOnly(database, qManager, KernelMessageidentifierEnum.CLEAR_DISPLAY, KernelStatusEnum.CARD_READ_SUCCESSFULLY, true);
            #endregion

            SignalsEnum result = DoProcessingRestrictions(database, qManager);
            if (result != SignalsEnum.NONE)
            {
                return(result);
            }

            #region 3.9
            KernelCVMEnum cvm = KernelCVMEnum.N_A;
            if (database.ProcessingIndicatorsForSelected.ReaderCVMRequiredLimitExceeded)
            {
                DoCVMProcessing(database, (ACTypeEnum)GetEnum(typeof(ACTypeEnum), cid));
                OUTCOME_PARAMETER_SET_DF8129_KRN2 ops = new OUTCOME_PARAMETER_SET_DF8129_KRN2(database);
                if (ops.Value.CVM == KernelCVMEnum.NO_CVM)
                {
                    #region 3.10.3.1
                    return(CommonRoutines.PostOutcome(database, qManager,
                                                      KernelMessageidentifierEnum.ERROR_OTHER_CARD,
                                                      KernelStatusEnum.PROCESSING_ERROR,
                                                      null,
                                                      Kernel2OutcomeStatusEnum.END_APPLICATION,
                                                      Kernel2StartEnum.N_A,
                                                      true,
                                                      KernelMessageidentifierEnum.ERROR_OTHER_CARD,
                                                      L1Enum.NOT_SET,
                                                      null,
                                                      L2Enum.CARD_DATA_ERROR,
                                                      L3Enum.NOT_SET));

                    #endregion
                }
                cvm = ops.Value.CVM;
            }
            #endregion

            #region 3.9.2
            CommonRoutines.CreateEMVDataRecord(database);
            CommonRoutines.CreateEMVDiscretionaryData(database);
            return(CommonRoutines.PostOutcome(database, qManager,
                                              KernelMessageidentifierEnum.AUTHORISING_PLEASE_WAIT,
                                              KernelStatusEnum.NOT_READY,
                                              null,
                                              Kernel2OutcomeStatusEnum.ONLINE_REQUEST,
                                              Kernel2StartEnum.N_A,
                                              true,
                                              KernelMessageidentifierEnum.N_A,
                                              L1Enum.NOT_SET,
                                              null,
                                              L2Enum.NOT_SET,
                                              L3Enum.NOT_SET,
                                              ValueQualifierEnum.NONE,
                                              null,
                                              null,
                                              false,
                                              cvm));

            #endregion
        }