Exemplo n.º 1
0
        public static void PackRelatedDataTag(KernelDatabaseBase database, EMVTagMeta tagToPack, TLVList tagListForPack)
        {
            TLV           tlvRelatedData      = database.Get(tagToPack);
            List <byte[]> tlvRelatedDataBytes = new List <byte[]>();

            Logger.Log("Packing tag: " + tagListForPack.ToString());
            foreach (TLV tlv in tagListForPack)
            {
                TLV valForPackDb = database.Get(tlv.Tag.TagLable);
                TLV valForPack;
                if (valForPackDb == null)
                {
                    valForPack = TLV.Create(tlv.Tag.TagLable);
                }
                else
                {
                    byte[] copyVal = new byte[valForPackDb.Value.Length];
                    Array.Copy(valForPackDb.Value, copyVal, valForPackDb.Value.Length);
                    valForPack = TLV.Create(tlv.Tag.TagLable, copyVal);
                }
                valForPack.Val.PackValue(tlv.Val.GetLength());
                Logger.Log("Adding tag: " + valForPack.ToString());
                tlvRelatedDataBytes.Add(valForPack.Value);
            }
            tlvRelatedData.Value = tlvRelatedDataBytes.SelectMany(a => a).ToArray();
        }
Exemplo n.º 2
0
        public static byte[] PackUdolRelatedDataTag(KernelDatabaseBase database)
        {
            TLV udol = database.Get(EMVTagsEnum.UDOL_9F69_KRN2);

            byte[] udolRelatedData;
            if (udol == null)
            {
                udol = database.Get(EMVTagsEnum.DEFAULT_UDOL_DF811A_KRN2);
            }

            udolRelatedData = PackRelatedDataTag(database, udol);
            return(udolRelatedData);
        }
Exemplo n.º 3
0
        public static byte[] PackRelatedDataTag(KernelDatabaseBase database, TLV tagListForPack)
        {
            List <byte[]> tlvRelatedDataBytes = new List <byte[]>();
            TLVList       tags = TLV.DeserializeChildrenWithNoV(tagListForPack.Value, 0);

            Logger.Log("Packing tag: " + tagListForPack.ToString());
            foreach (TLV tlv in tags)
            {
                TLV valForPackDb = database.Get(tlv.Tag.TagLable);
                TLV valForPack;
                if (valForPackDb == null)
                {
                    valForPack = TLV.Create(tlv.Tag.TagLable);
                }
                else
                {
                    byte[] copyVal = new byte[valForPackDb.Value.Length];
                    Array.Copy(valForPackDb.Value, copyVal, valForPackDb.Value.Length);
                    valForPack = TLV.Create(tlv.Tag.TagLable, copyVal);
                }
                valForPack.Val.PackValue(tlv.Val.GetLength());
                Logger.Log("Adding tag: " + valForPack.ToString());
                tlvRelatedDataBytes.Add(valForPack.Value);
            }
            return(tlvRelatedDataBytes.SelectMany(a => a).ToArray());
        }
Exemplo n.º 4
0
 private static void AddDDEntry(EMVTagMeta tag, KernelDatabaseBase database)
 {
     if (database.IsPresent(tag.Tag))
     {
         database.Get(EMVTagsEnum.DISCRETIONARY_DATA_FF8106_KRN2).Children.AddToList(TLV.Create(tag.Tag, database.Get(tag).Value));
     }
 }
Exemplo n.º 5
0
        public static TLV InitializeDiscretionaryData(KernelDatabaseBase database)
        {
            TLV disc = database.Get(EMVTagsEnum.DISCRETIONARY_DATA_FF8106_KRN2);

            if (disc == null)
            {
                disc = TLV.Create(EMVTagsEnum.DISCRETIONARY_DATA_FF8106_KRN2.Tag);
                database.AddToList(disc);
            }
            return(disc);
        }
Exemplo n.º 6
0
        public static void AddSDADDataToDatabase(KernelDatabaseBase database, ICCDynamicData iccdd)
        {
            if (iccdd.ApplicationCryptogram != null)
            {
                TLV ac = database.Get(EMVTagsEnum.APPLICATION_CRYPTOGRAM_9F26_KRN);
                if (ac == null)
                {
                    ac = TLV.Create(EMVTagsEnum.APPLICATION_CRYPTOGRAM_9F26_KRN.Tag);
                }
                ac.Value = iccdd.ApplicationCryptogram;
                database.AddToList(ac);
            }

            TLV iccdn = database.Get(EMVTagsEnum.ICC_DYNAMIC_NUMBER_9F4C_KRN);

            if (iccdn == null)
            {
                iccdn = TLV.Create(EMVTagsEnum.ICC_DYNAMIC_NUMBER_9F4C_KRN.Tag);
            }
            iccdn.Value = iccdd.ICCDynamicNumber;
            database.AddToList(iccdn);
        }
Exemplo n.º 7
0
        public static void CreateMSDiscretionaryDataRecord(KernelDatabaseBase database)
        {
            //Table 4.8
            if (database.Get(EMVTagsEnum.DISCRETIONARY_DATA_FF8106_KRN2) == null)
            {
                database.AddToList(TLV.Create(EMVTagsEnum.DISCRETIONARY_DATA_FF8106_KRN2.Tag));
            }

            AddDDEntry(EMVTagsEnum.APPLICATION_CAPABILITIES_INFORMATION_9F5D_KRN2, database);
            AddDDEntry(EMVTagsEnum.DD_CARD_TRACK1_DF812A_KRN2, database);
            AddDDEntry(EMVTagsEnum.DD_CARD_TRACK2_DF812B_KRN2, database);
            AddDDEntry(EMVTagsEnum.ERROR_INDICATION_DF8115_KRN2, database);
            AddDDEntry(EMVTagsEnum.THIRD_PARTY_DATA_9F6E_KRN2, database);
        }
Exemplo n.º 8
0
        public static void PackDSDOLRelatedDataTag(KernelDatabaseBase database)
        {
            TLV tlvRelatedData = database.Get(EMVTagsEnum.DRDOL_RELATED_DATA_DF8113_KRN2);

            if (tlvRelatedData == null)
            {
                database.AddToList(TLV.Create(EMVTagsEnum.DRDOL_RELATED_DATA_DF8113_KRN2.Tag));
                tlvRelatedData = database.Get(EMVTagsEnum.DRDOL_RELATED_DATA_DF8113_KRN2);
            }
            List <byte[]> tlvRelatedDataBytes = new List <byte[]>();
            TLVList       tags = TLV.DeserializeChildrenWithNoV(database.Get(EMVTagsEnum.DSDOL_9F5B_KRN2).Value, 0);

            int count = 1;

            foreach (TLV tlv in tags)
            {
                TLV valForPack = database.Get(tlv.Tag.TagLable);
                if (valForPack == null)
                {
                    valForPack = TLV.Create(tlv.Tag.TagLable);
                }

                if (count == tags.Count && tlv.Val.GetLength() > valForPack.Value.Length)
                {
                    tlvRelatedDataBytes.Add(valForPack.Value);
                }
                else
                {
                    valForPack.Val.PackValue(tlv.Val.GetLength());
                    tlvRelatedDataBytes.Add(valForPack.Value);
                    count++;
                }
                Logger.Log("Packing DSDOL, Adding tag: " + valForPack.ToString());
            }

            tlvRelatedData.Value = tlvRelatedDataBytes.SelectMany(a => a).ToArray();
        }
Exemplo n.º 9
0
        public SmartTag(KernelDatabaseBase database, EMVTagMeta emvTagMeta, V value)
            : base()
        {
            this.database = database;
            EMVTagMeta    = emvTagMeta;

            Tag = new T(EMVTagMeta.Tag);
            Val = value;

            TLV tlv = database.Get(EMVTagMeta);

            if (tlv != null && tlv.Val.Value.Length > 0)
            {
                Val.Deserialize(tlv.Val.Serialize(), 0);
            }
        }
Exemplo n.º 10
0
        public virtual void UpdateDB()
        {
            if (database == null)
            {
                throw new EMVProtocolException("cannot call UpdateDB with database = null");
            }

            TLV tlv = database.Get(EMVTagMeta);

            if (tlv != null)
            {
                tlv.Val.Deserialize(Val.Serialize(), 0);
            }
            else
            {
                Val.Serialize();
                database.AddToList(TLV.Create(this.Tag.TagLable, Val.Value));
            }
        }
Exemplo n.º 11
0
        public static void CreateMSDataRecord(KernelDatabaseBase database)
        {
            //Table 4.10
            if (database.Get(EMVTagsEnum.DATA_RECORD_FF8105_KRN2) == null)
            {
                database.AddToList(TLV.Create(EMVTagsEnum.DATA_RECORD_FF8105_KRN2.Tag));
            }

            AddDREntry(EMVTagsEnum.POINTOFSERVICE_POS_ENTRY_MODE_9F39_KRN, database);
            AddDREntry(EMVTagsEnum.AMOUNT_AUTHORISED_NUMERIC_9F02_KRN, database);

            AddDREntry(EMVTagsEnum.APPLICATION_LABEL_50_KRN, database);
            AddDREntry(EMVTagsEnum.APPLICATION_PREFERRED_NAME_9F12_KRN, database);
            AddDREntry(EMVTagsEnum.DEDICATED_FILE_DF_NAME_84_KRN, database);
            AddDREntry(EMVTagsEnum.ISSUER_CODE_TABLE_INDEX_9F11_KRN, database);
            AddDREntry(EMVTagsEnum.MAGSTRIPE_APPLICATION_VERSION_NUMBER_READER_9F6D_KRN2, database);
            AddDREntry(EMVTagsEnum.TRACK_1_DATA_56_KRN2, database);
            AddDREntry(EMVTagsEnum.TRACK_2_DATA_9F6B_KRN2, database);
        }
Exemplo n.º 12
0
        public static void CreateEMVDiscretionaryData(KernelDatabaseBase database)
        {
            //Table 4.9
            if (database.Get(EMVTagsEnum.DISCRETIONARY_DATA_FF8106_KRN2) == null)
            {
                database.AddToList(TLV.Create(EMVTagsEnum.DISCRETIONARY_DATA_FF8106_KRN2.Tag));
            }

            AddDDEntry(EMVTagsEnum.APPLICATION_CAPABILITIES_INFORMATION_9F5D_KRN2, database);
            AddDDEntry(EMVTagsEnum.APPLICATION_CURRENCY_CODE_9F42_KRN, database);
            AddDDEntry(EMVTagsEnum.BALANCE_READ_AFTER_GEN_AC_DF8105_KRN2, database);
            AddDDEntry(EMVTagsEnum.BALANCE_READ_BEFORE_GEN_AC_DF8104_KRN2, database);
            AddDDEntry(EMVTagsEnum.DS_SUMMARY_3_DF8102_KRN2, database);
            AddDDEntry(EMVTagsEnum.DS_SUMMARY_STATUS_DF810B_KRN2, database);
            AddDDEntry(EMVTagsEnum.ERROR_INDICATION_DF8115_KRN2, database);
            AddDDEntry(EMVTagsEnum.POSTGEN_AC_PUT_DATA_STATUS_DF810E_KRN2, database);
            AddDDEntry(EMVTagsEnum.PREGEN_AC_PUT_DATA_STATUS_DF810F_KRN2, database);
            AddDDEntry(EMVTagsEnum.THIRD_PARTY_DATA_9F6E_KRN2, database);
            AddDDEntry(EMVTagsEnum.TORN_RECORD_FF8101_KRN2, database);
        }
Exemplo n.º 13
0
        public byte[] BuildStaticDataToBeAuthenticated()
        {
            TLV aip = database.Get(EMVTagsEnum.APPLICATION_INTERCHANGE_PROFILE_82_KRN.Tag);

            if (aip != null)
            {
                TLVList newList = new TLVList();
                foreach (TLV tlv in listToManage)
                {
                    if (tlv.Tag.TagLable != aip.Tag.TagLable)
                    {
                        newList.AddToList(tlv, true);
                    }
                }
                if (database.IsNotEmpty(EMVTagsEnum.STATIC_DATA_AUTHENTICATION_TAG_LIST_9F4A_KRN.Tag))
                {
                    StringBuilder sb    = new StringBuilder();
                    int           depth = 0;
                    sb.Append("Final StaticDataToBeAuthenticatedList (AIP and STATIC_DATA_AUTHENTICATION_TAG_LIST_9F4A_KRN in DB): \n");
                    sb.AppendLine(newList.ToPrintString(ref depth));
                    depth = 1;
                    sb.AppendLine(aip.ToPrintString(ref depth));
                    Logger.Log(sb.ToString());
                    return(Formatting.ConcatArrays(newList.Serialize(), aip.Value));
                }
                else
                {
                    int depth = 0;
                    Logger.Log("Final StaticDataToBeAuthenticatedList: (AIP in DB but No STATIC_DATA_AUTHENTICATION_TAG_LIST_9F4A_KRN in DB)\n" + ToPrintString(ref depth));
                    return(newList.Serialize());
                }
            }
            else
            {
                int depth = 0;
                Logger.Log("Final StaticDataToBeAuthenticatedList (No AIP in DB): \n" + ToPrintString(ref depth));
                return(Serialize());
            }
        }
        internal bool ConditionsSatisfied(KernelDatabaseBase database, long amountX, long amountY)
        {
            byte tt = database.Get(EMVTagsEnum.TRANSACTION_TYPE_9C_KRN).Value[0];

            TERMINAL_TYPE_9F35_KRN.TerminalType terminalType = new TERMINAL_TYPE_9F35_KRN(database).Value.TerminalType;
            bool isManual     = false;
            byte posEntryMode = database.Get(EMVTagsEnum.POINTOFSERVICE_POS_ENTRY_MODE_9F39_KRN).Value[0];

            if (posEntryMode == 0x01)
            {
                isManual = true;
            }

            long aa = Formatting.BcdToLong(database.Get(EMVTagsEnum.AMOUNT_AUTHORISED_NUMERIC_9F02_KRN).Value);

            bool tccEqualsacc = false;

            if (database.IsNotEmpty(EMVTagsEnum.TRANSACTION_CURRENCY_CODE_5F2A_KRN.Tag) && database.IsNotEmpty(EMVTagsEnum.APPLICATION_CURRENCY_CODE_9F42_KRN.Tag))
            {
                string tcc = Formatting.ByteArrayToHexString(database.Get(EMVTagsEnum.TRANSACTION_CURRENCY_CODE_5F2A_KRN).Value);
                string acc = Formatting.ByteArrayToHexString(database.Get(EMVTagsEnum.APPLICATION_CURRENCY_CODE_9F42_KRN).Value);
                if (tcc == acc)
                {
                    tccEqualsacc = true;
                }
            }

            switch (CVMConditionCode)
            {
            case CVMConditionCode.Always:
                return(true);

            case CVMConditionCode.IfUnattendedCash:
                if (terminalType.AttendedUnattended == TERMINAL_TYPE_9F35_KRN.AttendedUnattended.Unattended &&
                    tt == (byte)TransactionTypeEnum.CashWithdrawal)
                {
                    return(true);
                }
                else
                {
                    return(false);
                }

            case CVMConditionCode.IfManualCash:

                if (isManual && tt == (byte)TransactionTypeEnum.CashWithdrawal)
                {
                    return(true);
                }
                else
                {
                    return(false);
                }

            case CVMConditionCode.IfNotUnattendedCashAndNotManualCashAndNotPurchaseWithCashBack:
                if (!(terminalType.AttendedUnattended == TERMINAL_TYPE_9F35_KRN.AttendedUnattended.Unattended &&
                      tt == (byte)TransactionTypeEnum.CashWithdrawal) &&
                    (!(isManual && tt == (byte)TransactionTypeEnum.CashWithdrawal)) &&
                    (!(tt == (byte)TransactionTypeEnum.PurchaseWithCashback))
                    )
                {
                    return(true);
                }
                else
                {
                    return(false);
                }

            case CVMConditionCode.IfTerminalSupportstheCVM:
                return(IsSupported(database));

            case CVMConditionCode.IfPurchaseWithCashBack:
                if ((tt == (byte)TransactionTypeEnum.PurchaseWithCashback))
                {
                    return(true);
                }
                else
                {
                    return(false);
                }

            case CVMConditionCode.IfTransactionIsInTheApplicationCurrencyAndIsUnderX:

                if (tccEqualsacc && aa <= amountX)
                {
                    return(true);
                }
                else
                {
                    return(false);
                }

            case CVMConditionCode.IfTransactionIsInTheApplicationCurrencyAndIsOverX:
                if (tccEqualsacc && aa > amountX)
                {
                    return(true);
                }
                else
                {
                    return(false);
                }

            case CVMConditionCode.IfTransactionIsInTheApplicationCurrencyAndIsUnderY:
                if (tccEqualsacc && aa <= amountY)
                {
                    return(true);
                }
                else
                {
                    return(false);
                }

            case CVMConditionCode.IfTransactionIsInTheApplicationCurrencyAndIsOverY:
                if (tccEqualsacc && aa > amountY)
                {
                    return(true);
                }
                else
                {
                    return(false);
                }

            default:
                throw new EMVProtocolException("invalid CVM ConditionCode in Rule");
            }
        }
Exemplo n.º 15
0
        internal static IssuerPublicKeyCertificate BuildAndValidatePublicKey(KernelDatabaseBase database, byte[] caPublicKeyModulus, byte[] caPublicKeyExponent)
        {
            //section 6.3 EMV 4.3 Book 2

            TLV issuerPublicKeyCertificate = database.Get(EMVTagsEnum.ISSUER_PUBLIC_KEY_CERTIFICATE_90_KRN);
            TLV issuerPublicKeyExponent    = database.Get(EMVTagsEnum.ISSUER_PUBLIC_KEY_EXPONENT_9F32_KRN);
            TLV issuerPublicKeyRemainder   = database.Get(EMVTagsEnum.ISSUER_PUBLIC_KEY_REMAINDER_92_KRN);

            if (issuerPublicKeyCertificate.Value.Length != caPublicKeyModulus.Length)
            {
                return(null);
            }

            byte[] decrypt = DecryptRSA(issuerPublicKeyCertificate.Value, caPublicKeyModulus, caPublicKeyExponent);

            IssuerPublicKeyCertificate issuerCertData = new IssuerPublicKeyCertificate(decrypt, caPublicKeyModulus.Length,
                                                                                       issuerPublicKeyRemainder == null ? new byte[0] : issuerPublicKeyRemainder.Value, issuerPublicKeyExponent.Value);

            if (issuerCertData.RecoveredDataTrailer != 0xBC)
            {
                return(null);
            }

            if (issuerCertData.RecoveredDataHeader != 0x6A)
            {
                return(null);
            }

            if (issuerCertData.CertificateFormat != 0x02)
            {
                return(null);
            }

            if (!issuerCertData.ValidateHash())
            {
                return(null);
            }

            string pan = Formatting.ByteArrayToHexString(database.Get(EMVTagsEnum.APPLICATION_PRIMARY_ACCOUNT_NUMBER_PAN_5A_KRN).Value);
            string issuerIdentifier = Formatting.ByteArrayToHexString(issuerCertData.IssuerIdentifier).Replace("FF", "");

            if (!pan.StartsWith(issuerIdentifier))
            {
                return(null);
            }

            DateTime expiry = DateTime.ParseExact(Formatting.BcdToString(issuerCertData.ExpiryDate), "MMyy", System.Globalization.CultureInfo.InvariantCulture);

            //TODO: if you have a test tool trying to use an expired cert then comment this test out or update your test tool
            //if (expiry <= DateTime.Now)
            //{
            //    Logger.Log("Error: Trying to use an expired issuer public key");
            //    return null;
            //}

            //step 10 optional

            if (issuerCertData.PublicKeyAlgorithmIndicator != 0x01)
            {
                return(null);
            }

            if (issuerPublicKeyRemainder != null)
            {
                issuerCertData.Modulus = Formatting.ConcatArrays(issuerCertData.UnpaddedIssuerPublicKeyorLeftmostDigitsofIssuerPublicKey, issuerPublicKeyRemainder.Value);
            }
            else
            {
                issuerCertData.Modulus = issuerCertData.UnpaddedIssuerPublicKeyorLeftmostDigitsofIssuerPublicKey;
            }

            return(issuerCertData);
        }
Exemplo n.º 16
0
        internal static IccPublicKeyCertificate BuildAndValidatePublicKey(KernelDatabaseBase database, StaticDataToBeAuthenticatedList staticDataToBeAuthenticated, byte[] issuerPublicKeyModulus, byte[] issuerPublicKeyExponent)
        {
            //section 6.4 EMV 4.3 Book 2

            TLV iccPublicKeyCertificate = database.Get(EMVTagsEnum.INTEGRATED_CIRCUIT_CARD_ICC_PUBLIC_KEY_CERTIFICATE_9F46_KRN);
            TLV iccPublicKeyExponent    = database.Get(EMVTagsEnum.INTEGRATED_CIRCUIT_CARD_ICC_PUBLIC_KEY_EXPONENT_9F47_KRN);
            TLV iccPublicKeyRemainder   = database.Get(EMVTagsEnum.INTEGRATED_CIRCUIT_CARD_ICC_PUBLIC_KEY_REMAINDER_9F48_KRN);

            if (iccPublicKeyCertificate.Value.Length != issuerPublicKeyModulus.Length)
            {
                return(null);
            }

            byte[] decrypt = DecryptRSA(iccPublicKeyCertificate.Value, issuerPublicKeyModulus, issuerPublicKeyExponent);

            IccPublicKeyCertificate iccCertData = new IccPublicKeyCertificate(decrypt, issuerPublicKeyModulus.Length,
                                                                              iccPublicKeyRemainder == null ? new byte[0] : iccPublicKeyRemainder.Value, iccPublicKeyExponent.Value, database.StaticDataToBeAuthenticated.BuildStaticDataToBeAuthenticated());

            if (iccCertData.RecoveredDataTrailer != 0xBC)
            {
                return(null);
            }

            if (iccCertData.RecoveredDataHeader != 0x6A)
            {
                return(null);
            }

            if (iccCertData.CertificateFormat != 0x04)
            {
                return(null);
            }

            if (!iccCertData.ValidateHash())
            {
                return(null);
            }

            string pan          = Formatting.ByteArrayToHexString(database.Get(EMVTagsEnum.APPLICATION_PRIMARY_ACCOUNT_NUMBER_PAN_5A_KRN).Value);
            string panToCompare = Formatting.ByteArrayToHexString(iccCertData.ApplicationPAN).Replace("FF", "");

            if (!pan.StartsWith(panToCompare))
            {
                return(null);
            }

            DateTime expiry = DateTime.ParseExact(Formatting.BcdToString(iccCertData.ExpiryDate), "MMyy", System.Globalization.CultureInfo.InvariantCulture);

            //TODO: if you have a test tool trying to use an expired cert then comment this test out or update your test tool
            //if (expiry <= DateTime.Now)
            //{
            //    Logger.Log("Error: Trying to use an expired issuer public key");
            //    return null;
            //}

            if (iccCertData.PublicKeyAlgorithmIndicator != 0x01)
            {
                return(null);
            }

            if (iccPublicKeyRemainder != null)
            {
                iccCertData.Modulus = Formatting.ConcatArrays(iccCertData.UnpaddedICCPublicKeyorLeftmostDigitsofIssuerPublicKey, iccPublicKeyRemainder.Value);
            }
            else
            {
                iccCertData.Modulus = iccCertData.UnpaddedICCPublicKeyorLeftmostDigitsofIssuerPublicKey;
            }

            return(iccCertData);
        }
Exemplo n.º 17
0
        internal static IccPinKeyCertificate BuildAndValidatePublicKey(KernelDatabaseBase database, byte[] issuerPublicKeyModulus, byte[] issuerPublicKeyExponent)
        {
            TLV iccPinKeyCertificate = database.Get(EMVTagsEnum.INTEGRATED_CIRCUIT_CARD_ICC_PIN_ENCIPHERMENT_PUBLIC_KEY_CERTIFICATE_9F2D_KRN);

            if (iccPinKeyCertificate == null)
            {
                return(null);
            }
            TLV iccPinKeyExponent = database.Get(EMVTagsEnum.INTEGRATED_CIRCUIT_CARD_ICC_PIN_ENCIPHERMENT_PUBLIC_KEY_EXPONENT_9F2E_KRN);

            if (iccPinKeyExponent == null)
            {
                return(null);
            }
            TLV iccPinKeyRemainder = database.Get(EMVTagsEnum.INTEGRATED_CIRCUIT_CARD_ICC_PIN_ENCIPHERMENT_PUBLIC_KEY_REMAINDER_9F2F_KRN);

            if (iccPinKeyRemainder == null)
            {
                return(null);
            }

            if (iccPinKeyCertificate.Value.Length != issuerPublicKeyModulus.Length)
            {
                return(null);
            }

            byte[] decrypt = DecryptRSA(iccPinKeyCertificate.Value, issuerPublicKeyModulus, issuerPublicKeyExponent);

            IccPinKeyCertificate iccCertData = new IccPinKeyCertificate(decrypt, issuerPublicKeyModulus.Length,
                                                                        iccPinKeyRemainder == null ? new byte[0] : iccPinKeyRemainder.Value, iccPinKeyExponent.Value);

            if (iccCertData.RecoveredDataTrailer != 0xBC)
            {
                return(null);
            }

            if (iccCertData.RecoveredDataHeader != 0x6A)
            {
                return(null);
            }

            if (iccCertData.CertificateFormat != 0x04)
            {
                return(null);
            }

            if (!iccCertData.ValidateHash())
            {
                return(null);
            }

            string pan          = Formatting.ByteArrayToHexString(database.Get(EMVTagsEnum.APPLICATION_PRIMARY_ACCOUNT_NUMBER_PAN_5A_KRN).Value);
            string panToCompare = Formatting.ByteArrayToHexString(iccCertData.ApplicationPAN).Replace("FF", "");

            if (!pan.StartsWith(panToCompare))
            {
                return(null);
            }

            DateTime expiry = DateTime.ParseExact(Formatting.BcdToString(iccCertData.ExpiryDate), "MMyy", System.Globalization.CultureInfo.InvariantCulture);

            if (expiry <= DateTime.Now)
            {
                return(null);
            }

            if (iccCertData.PublicKeyAlgorithmIndicator != 0x01)
            {
                return(null);
            }

            if (iccPinKeyRemainder != null)
            {
                iccCertData.Modulus = Formatting.ConcatArrays(iccCertData.UnpaddedICCPinKeyorLeftmostDigitsofIssuerPublicKey, iccPinKeyRemainder.Value);
            }
            else
            {
                iccCertData.Modulus = iccCertData.UnpaddedICCPinKeyorLeftmostDigitsofIssuerPublicKey;
            }

            return(iccCertData);
        }
Exemplo n.º 18
0
        public static void CreateEMVDataRecord(KernelDatabaseBase database)
        {
            //Table 4.7
            if (database.Get(EMVTagsEnum.DATA_RECORD_FF8105_KRN2) == null)
            {
                database.AddToList(TLV.Create(EMVTagsEnum.DATA_RECORD_FF8105_KRN2.Tag));
            }

            CARDHOLDER_VERIFICATION_METHOD_CVM_RESULTS_9F34_KRN cvr = new CARDHOLDER_VERIFICATION_METHOD_CVM_RESULTS_9F34_KRN(database);

            if (cvr.Value.GetCVMPerformed() == CVMCode.EncipheredPINVerifiedOnline && cvr.Value.GetCVMResult() != CVMResult.Failed)
            {
                AddDREntry(EMVTagsEnum.TRANSACTION_PERSONAL_IDENTIFICATION_NUMBER_PIN_DATA_99_KRN, database);
            }

            AddDREntry(EMVTagsEnum.POINTOFSERVICE_POS_ENTRY_MODE_9F39_KRN, database);
            AddDREntry(EMVTagsEnum.AMOUNT_AUTHORISED_NUMERIC_9F02_KRN, database);
            AddDREntry(EMVTagsEnum.AMOUNT_OTHER_NUMERIC_9F03_KRN, database);
            AddDREntry(EMVTagsEnum.APPLICATION_CRYPTOGRAM_9F26_KRN, database);
            AddDREntry(EMVTagsEnum.APPLICATION_EXPIRATION_DATE_5F24_KRN, database);
            AddDREntry(EMVTagsEnum.APPLICATION_INTERCHANGE_PROFILE_82_KRN, database);
            AddDREntry(EMVTagsEnum.APPLICATION_LABEL_50_KRN, database);
            AddDREntry(EMVTagsEnum.APPLICATION_PRIMARY_ACCOUNT_NUMBER_PAN_5A_KRN, database);
            AddDREntry(EMVTagsEnum.APPLICATION_PRIMARY_ACCOUNT_NUMBER_PAN_SEQUENCE_NUMBER_5F34_KRN, database);
            AddDREntry(EMVTagsEnum.APPLICATION_PREFERRED_NAME_9F12_KRN, database);
            AddDREntry(EMVTagsEnum.APPLICATION_TRANSACTION_COUNTER_ATC_9F36_KRN, database);
            AddDREntry(EMVTagsEnum.APPLICATION_USAGE_CONTROL_9F07_KRN, database);
            AddDREntry(EMVTagsEnum.APPLICATION_VERSION_NUMBER_TERMINAL_9F09_KRN, database);
            AddDREntry(EMVTagsEnum.CRYPTOGRAM_INFORMATION_DATA_9F27_KRN, database);
            AddDREntry(EMVTagsEnum.CARDHOLDER_VERIFICATION_METHOD_CVM_RESULTS_9F34_KRN, database);
            AddDREntry(EMVTagsEnum.DEDICATED_FILE_DF_NAME_84_KRN, database);
            AddDREntry(EMVTagsEnum.INTERFACE_DEVICE_IFD_SERIAL_NUMBER_9F1E_KRN, database);
            AddDREntry(EMVTagsEnum.ISSUER_APPLICATION_DATA_9F10_KRN, database);
            AddDREntry(EMVTagsEnum.ISSUER_CODE_TABLE_INDEX_9F11_KRN, database);
            AddDREntry(EMVTagsEnum.TERMINAL_CAPABILITIES_9F33_KRN, database);
            AddDREntry(EMVTagsEnum.TERMINAL_COUNTRY_CODE_9F1A_KRN, database);
            AddDREntry(EMVTagsEnum.TERMINAL_TYPE_9F35_KRN, database);
            AddDREntry(EMVTagsEnum.TERMINAL_VERIFICATION_RESULTS_95_KRN, database);
            AddDREntry(EMVTagsEnum.TRACK_2_EQUIVALENT_DATA_57_KRN, database);
            AddDREntry(EMVTagsEnum.TRANSACTION_CURRENCY_CODE_5F2A_KRN, database);
            AddDREntry(EMVTagsEnum.TRANSACTION_DATE_9A_KRN, database);
            AddDREntry(EMVTagsEnum.TRANSACTION_TYPE_9C_KRN, database);
            AddDREntry(EMVTagsEnum.UNPREDICTABLE_NUMBER_9F37_KRN, database);
            AddDREntry(EMVTagsEnum.TRANSACTION_STATUS_INFORMATION_9B_KRN, database);

            #region c-3 kernel 3 req 3.2.1.3
            AddDREntry(EMVTagsEnum.PAYMENT_ACCOUNT_REFERENCE_9F24_KRN, database);
            #endregion

            //Kernel 2
            AddDREntry(EMVTagsEnum.TRANSACTION_CATEGORY_CODE_9F53_KRN2, database);

            //Kernel 3
            #region c-3 kernel 3 req 3.2.1.2
            AddDREntry(EMVTagsEnum.FORM_FACTOR_INDICATOR_FFI_9F6E_KRN3, database);
            AddDREntry(EMVTagsEnum.CUSTOMER_EXCLUSIVE_DATA_CED_9F7C_KRN3, database);
            #endregion

            #region c-3 kernel 3 req 4.1.1.1
            TLV ffi = database.Get(EMVTagsEnum.FORM_FACTOR_INDICATOR_FFI_9F6E_KRN3);
            if (ffi != null)
            {
                ffi.Value[3] = (byte)(ffi.Value[3] & 0xF0);//indicating that the transaction was conducted using [ISO 14443]
            }
            #endregion
        }
Exemplo n.º 19
0
        public static ICCDynamicData VerifySDAD_K3(ICCDynamicDataType iccDDType, KernelDatabaseBase database, CAPublicKeyCertificate caPublicKey, byte[] sdadRaw)
        {
            //section 6.5.2 of EMV book 2 - DDA

            //1.If the Signed Dynamic Application Data has a length different from the
            //length of the ICC Public Key Modulus, CDA has failed
            IssuerPublicKeyCertificate ipk = IssuerPublicKeyCertificate.BuildAndValidatePublicKey(database, caPublicKey.Modulus, caPublicKey.Exponent);

            if (ipk == null)
            {
                return(null);
            }
            IccPublicKeyCertificate iccpk = IccPublicKeyCertificate.BuildAndValidatePublicKey(database, database.StaticDataToBeAuthenticated, ipk.Modulus, ipk.Exponent);

            if (iccpk == null)
            {
                return(null);
            }

            if (sdadRaw.Length != iccpk.Modulus.Length)
            {
                return(null);
            }

            //2.To obtain the recovered data specified in Table 22, apply the recovery
            //function as specified in Annex A2.1 on the Signed Dynamic Application
            //Data using the ICC Public Key in conjunction with the corresponding
            //algorithm.If the Recovered Data Trailer is not equal to 'BC', CDA has
            //failed
            byte[] decrypted = PublicKeyCertificate.DecryptRSA(sdadRaw, iccpk.Modulus, iccpk.Exponent);
            SDAD   sdad      = new SDAD(decrypted);

            //3.Check the Recovered Data Header. If it is not '6A', CDA has failed.
            if (sdad.DataHeader != 0x6A)
            {
                return(null);
            }
            //4.Check the Signed Data Format. If it is not '05', CDA has failed.
            //For Visa specialpurpose readers it may return 0x95 iff offline data authentication is supported for online transactions (in the TTQ)
            if (sdad.SignedDataFormat != 0x05 && sdad.SignedDataFormat != 0x95)
            {
                return(null);
            }

            ICCDynamicData iccDD = new ICCDynamicData(database, sdad.ICCDynamicData, iccDDType);

            //5.Concatenate from left to right the second to the sixth data elements in
            //Table 17(that is, Signed Data Format through Pad Pattern), followed by
            //the data elements specified by the DDOL.

            //C.1 K3 Kernel wants it done this way rather than they way sepecified in step 5
            //The Terminal Dynamic Data elements input to the hash algorithm shall be as
            //specified in Table C-1 instead of being specified in the DDOL(as the DDOL is
            //not a recognized data element for Kernel 3).The kernel may treat the tags
            //specified in Table C-1 as default DDOLs for fDDA version '01'
            List <byte[]> hashList = new List <byte[]>
            {
                database.Get(EMVTagsEnum.UNPREDICTABLE_NUMBER_9F37_KRN).Value,
                database.Get(EMVTagsEnum.AMOUNT_AUTHORISED_NUMERIC_9F02_KRN).Value,
                database.Get(EMVTagsEnum.TRANSACTION_CURRENCY_CODE_5F2A_KRN).Value,
                database.Get(EMVTagsEnum.CARD_AUTHENTICATION_RELATED_DATA_9F69_KRN3).Value
            };

            //6.Apply the indicated hash algorithm(derived from the Hash Algorithm
            //Indicator) to the result of the concatenation of the previous step to
            //produce the hash result.
            byte[] dataForHash = sdad.Concat(hashList.SelectMany(x => x).ToArray());
            byte[] hash        = SHA1.Create().ComputeHash(dataForHash);


            //7.Compare the calculated hash result from the previous step with the
            //recovered Hash Result.If they are not the same, DDA has failed.
            if (Formatting.ByteArrayToHexString(sdad.HashResult) != Formatting.ByteArrayToHexString(hash))
            {
                return(null);
            }

            return(iccDD);
        }
Exemplo n.º 20
0
        public static ICCDynamicData VerifySDAD(ICCDynamicDataType iccDDType, bool isFirstGenAC, KernelDatabaseBase database, StaticDataToBeAuthenticatedList staticDataToBeAuthenticated, CAPublicKeyCertificate caPublicKey, CardResponse genACCardResponse)
        {
            EMVGenerateACResponse genAcResponse = (genACCardResponse.ApduResponse as EMVGenerateACResponse);

            //section 6.6.2 of EMV book 2 - CDA

            //1.If the Signed Dynamic Application Data has a length different from the
            //length of the ICC Public Key Modulus, CDA has failed
            byte[] sdadRaw = genAcResponse.SignedDynamicApplicationData.Value;
            IssuerPublicKeyCertificate ipk = IssuerPublicKeyCertificate.BuildAndValidatePublicKey(database, caPublicKey.Modulus, caPublicKey.Exponent);

            if (ipk == null)
            {
                return(null);
            }
            IccPublicKeyCertificate iccpk = IccPublicKeyCertificate.BuildAndValidatePublicKey(database, staticDataToBeAuthenticated, ipk.Modulus, ipk.Exponent);

            if (iccpk == null)
            {
                return(null);
            }

            if (sdadRaw.Length != iccpk.Modulus.Length)
            {
                return(null);
            }

            //2.To obtain the recovered data specified in Table 22, apply the recovery
            //function as specified in Annex A2.1 on the Signed Dynamic Application
            //Data using the ICC Public Key in conjunction with the corresponding
            //algorithm.If the Recovered Data Trailer is not equal to 'BC', CDA has
            //failed
            byte[] decrypted = PublicKeyCertificate.DecryptRSA(sdadRaw, iccpk.Modulus, iccpk.Exponent);
            SDAD   sdad      = new SDAD(decrypted);

            //3.Check the Recovered Data Header. If it is not '6A', CDA has failed.
            if (sdad.DataHeader != 0x6A)
            {
                return(null);
            }
            //4.Check the Signed Data Format. If it is not '05', CDA has failed.
            if (sdad.SignedDataFormat != 0x05)
            {
                return(null);
            }

            //5. Retrieve from the ICC Dynamic Data the data specified in Table 19
            ICCDynamicData iccDD = new ICCDynamicData(database, sdad.ICCDynamicData, iccDDType);

            //6.Check that the Cryptogram Information Data retrieved from the ICC
            //Dynamic Data is equal to the Cryptogram Information Data obtained from
            //the response to the GENERATE AC command. If this is not the case, CDA
            //has failed.
            if (genAcResponse.CryptogramInformationData.Value[0] != iccDD.CryptogramInformationData)
            {
                return(null);
            }

            //7.Concatenate from left to right the second to the sixth data elements in
            //Table 22(that is, Signed Data Format through Pad Pattern), followed by
            //the Unpredictable Number.
            byte[] unpredicatbleNumber = database.Get(EMVTagsEnum.UNPREDICTABLE_NUMBER_9F37_KRN).Value;
            byte[] dataForHash         = sdad.Concat(unpredicatbleNumber);

            //8.Apply the indicated hash algorithm (derived from the Hash Algorithm
            //Indicator) to the result of the concatenation of the previous step to
            //produce the hash result.
            byte[] hash = SHA1.Create().ComputeHash(dataForHash);

            //9.Compare the calculated hash result from the previous step with the
            //recovered Hash Result.If they are not the same, CDA has failed.
            if (Formatting.ByteArrayToHexString(sdad.HashResult) != Formatting.ByteArrayToHexString(hash))
            {
                return(null);
            }

            //10. Concatenate from left to right the values of the following data elements:
            List <byte[]> result = new List <byte[]>();

            if (isFirstGenAC)
            {
                //-The values of the data elements specified by, and in the order they
                //appear in the PDOL, and sent by the terminal in the GET
                //PROCESSING OPTIONS command.
                result.Add(database.Get(EMVTagsEnum.PDOL_RELATED_DATA_DF8111_KRN2).Value);
                //-The values of the data elements specified by, and in the order they
                //appear in the CDOL1, and sent by the terminal in the first
                //GENERATE AC command.
                result.Add(database.Get(EMVTagsEnum.CDOL1_RELATED_DATA_DF8107_KRN2).Value);
                //-The tags, lengths, and values of the data elements returned by the ICC
                //in the response to the GENERATE AC command in the order they are
                //returned, with the exception of the Signed Dynamic Application Data.
                foreach (TLV tlv in genAcResponse.GetResponseTags())
                {
                    if (tlv.Tag.TagLable != EMVTagsEnum.SIGNED_DYNAMIC_APPLICATION_DATA_9F4B_KRN.Tag)
                    {
                        result.Add(tlv.Serialize());
                    }
                }
            }
            else
            {
                //-The values of the data elements specified by, and in the order they
                //appear in the PDOL, and sent by the terminal in the GET
                //PROCESSING OPTIONS command.
                result.Add(database.Get(EMVTagsEnum.PDOL_RELATED_DATA_DF8111_KRN2).Value);
                //-The values of the data elements specified by, and in the order they
                //appear in the CDOL1, and sent by the terminal in the first
                //GENERATE AC command.
                result.Add(database.Get(EMVTagsEnum.CDOL1_RELATED_DATA_DF8107_KRN2).Value);
                //-The values of the data elements specified by, and in the order they
                //appear in the CDOL2, and sent by the terminal in the second
                //GENERATE AC command.
                TLV cdol2 = database.Get(EMVTagsEnum.CARD_RISK_MANAGEMENT_DATA_OBJECT_LIST_2_CDOL2_8D_KRN);
                if (cdol2 != null)
                {
                    result.Add(CommonRoutines.PackRelatedDataTag(database, cdol2));
                }
                //-The tags, lengths, and values of the data elements returned by the ICC
                //in the response to the GENERATE AC command in the order they are
                //returned, with the exception of the Signed Dynamic Application Data.
                foreach (TLV tlv in genAcResponse.GetResponseTags())
                {
                    if (tlv.Tag.TagLable != EMVTagsEnum.SIGNED_DYNAMIC_APPLICATION_DATA_9F4B_KRN.Tag)
                    {
                        result.Add(tlv.Serialize());
                    }
                }
            }
            byte[] transactionHashData = result.SelectMany(a => a).ToArray();

            //11.Apply the indicated hash algorithm (derived from the Hash Algorithm
            //Indicator) to the result of the concatenation of the previous step to
            //produce the Transaction Data Hash Code.
            byte[] transactionHash = SHA1.Create().ComputeHash(transactionHashData);

            //12.Compare the calculated Transaction Data Hash Code from the previous
            //step with the Transaction Data Hash Code retrieved from the ICC
            //Dynamic Data in Step 5.If they are not the same, CDA has failed.
            if (Formatting.ByteArrayToHexString(iccDD.TransactionDataHashCode) != Formatting.ByteArrayToHexString(transactionHash))
            {
                return(null);
            }

            return(iccDD);
        }
Exemplo n.º 21
0
        public static void CVMSelection(KernelDatabaseBase database, Func <bool> kernelSupportedCallback)
        {
            CARDHOLDER_VERIFICATION_METHOD_CVM_RESULTS_9F34_KRN cvmResults = new CARDHOLDER_VERIFICATION_METHOD_CVM_RESULTS_9F34_KRN(database);

            //#region support for Refunds pg 177
            //byte transactionType = database.Get(EMVTagsEnum.TRANSACTION_TYPE_9C_KRN).Value[0];
            //if (transactionType == (byte)TransactionTypeEnum.Refund)
            //{
            //    Do_CVM_14(database, cvmResults);
            //    return;
            //}
            //#endregion

            APPLICATION_INTERCHANGE_PROFILE_82_KRN aip = new APPLICATION_INTERCHANGE_PROFILE_82_KRN(database);

            TERMINAL_VERIFICATION_RESULTS_95_KRN tvr = new TERMINAL_VERIFICATION_RESULTS_95_KRN(database);

            KernelCVMEnum cvmEnum = KernelCVMEnum.N_A;

            CardHolderVerificationRule cvrCurrentlySelected;

            if (aip.Value.OnDeviceCardholderVerificationIsSupported && kernelSupportedCallback.Invoke())
            {
                #region cvm.2
                long aa    = Formatting.BcdToLong(database.Get(EMVTagsEnum.AMOUNT_AUTHORISED_NUMERIC_9F02_KRN).Value);
                long rcvml = Formatting.BcdToLong(database.Get(EMVTagsEnum.READER_CVM_REQUIRED_LIMIT_DF8126_KRN2).Value);
                if (aa > rcvml)
                #endregion
                {
                    #region cvm.4
                    cvmEnum = KernelCVMEnum.CONFIRMATION_CODE_VERIFIED;
                    cvmResults.Value.CVMPerformed = 0x01; //on-device cardholder verification performed
                    cvmResults.Value.CVMCondition = 0x00;
                    cvmResults.Value.CVMResult    = 0x02; //successful
                    CommonRoutines.UpdateOutcomeParameterSet(database, cvmEnum);
                    cvmResults.UpdateDB();
                    return;

                    #endregion
                }
                else
                {
                    #region cvm.3
                    cvmEnum = KernelCVMEnum.NO_CVM;
                    cvmResults.Value.CVMPerformed = 0x3F; //No CVM performed
                    cvmResults.Value.CVMCondition = 0x00;
                    cvmResults.Value.CVMResult    = 0x02; //successful
                    CommonRoutines.UpdateOutcomeParameterSet(database, cvmEnum);
                    cvmResults.UpdateDB();
                    return;

                    #endregion
                }
            }

            #region cvm.5
            if (!aip.Value.CardholderVerificationIsSupported)
            #endregion
            {
                #region cvm.6
                cvmEnum = KernelCVMEnum.NO_CVM;
                cvmResults.Value.CVMPerformed = 0x3F; //No CVM performed
                cvmResults.Value.CVMCondition = 0x00;
                cvmResults.Value.CVMResult    = 0x00; //unknown
                CommonRoutines.UpdateOutcomeParameterSet(database, cvmEnum);
                cvmResults.UpdateDB();
                return;

                #endregion
            }

            #region cvm.7
            if (database.IsNotPresent(EMVTagsEnum.CARDHOLDER_VERIFICATION_METHOD_CVM_LIST_8E_KRN.Tag) ||
                database.IsEmpty(EMVTagsEnum.CARDHOLDER_VERIFICATION_METHOD_CVM_LIST_8E_KRN.Tag))
            #endregion
            {
                #region cvm.8
                cvmEnum = KernelCVMEnum.NO_CVM;
                cvmResults.Value.CVMPerformed = 0x3F; //No CVM performed
                cvmResults.Value.CVMCondition = 0x00;
                cvmResults.Value.CVMResult    = 0x00; //unknown
                CommonRoutines.UpdateOutcomeParameterSet(database, cvmEnum);
                cvmResults.UpdateDB();
                tvr.Value.ICCDataMissing = true;
                tvr.UpdateDB();
                return;

                #endregion
            }

            #region cvm.9
            CARDHOLDER_VERIFICATION_METHOD_CVM_LIST_8E_KRN cvl = new CARDHOLDER_VERIFICATION_METHOD_CVM_LIST_8E_KRN(database);
            #endregion

BackToIterate:
            CVMListIterationReturn result;
            do
            {
                cvrCurrentlySelected = cvl.Value.CardHolderVerificationRules[database.CVMCurrentlySelectedCounter];
                #region cvm.10 cvm.11
                result = IterateCVM(database, cvrCurrentlySelected, cvl.Value.AmountX, cvl.Value.AmountY);
                #endregion
                database.CVMCurrentlySelectedCounter++;
                #region cvm.12 cvm.13
            } while (database.CVMCurrentlySelectedCounter < cvl.Value.CardHolderVerificationRules.Count &&
                     result != CVMListIterationReturn.ConditionsMet);
            #endregion

            if (result != CVMListIterationReturn.ConditionsMet)
            {
                Do_CVM_14(database, cvmResults);
                return;
            }

            #region cvm.15
            if (!cvrCurrentlySelected.IsCVMRecognised())
            #endregion
            {
                #region cvm.16
                tvr = new TERMINAL_VERIFICATION_RESULTS_95_KRN(database);
                tvr.Value.UnrecognisedCVM = true;
                tvr.UpdateDB();
                #endregion
            }
            else
            {
                #region cvm.17
                if (cvrCurrentlySelected.IsSupported(database) && cvrCurrentlySelected.GetCVMCode() != (byte)CVMCode.FailCVMProcessing)
                #endregion
                {
                    #region cvm.18 and from EMV Book 3 Section 10.5
                    switch ((byte)(cvrCurrentlySelected.CVMRule & 0x3F))
                    {
                    //Pin processing (U,X,Z) continues in PinProcessing Procedure after CVM Selection
                    case (byte)CVMCode.EncipheredPINVerifiedOnline:
                        cvmEnum = KernelCVMEnum.ONLINE_PIN;
                        cvmResults.Value.CVMResult = 0x00;     //unknown
                        tvr.Value.OnlinePINEntered = true;
                        break;

                    case (byte)CVMCode.EncipheredPINVerificationPerformedByICC:
                    case (byte)CVMCode.PlaintextPINVerificationPerformedByICC:
                        cvmEnum = KernelCVMEnum.OFFLINE_PIN;
                        cvmResults.Value.CVMResult = 0x00;     //unknown
                        break;

                    case (byte)CVMCode.EncipheredPINVerificationPerformedByICCAndSignature_Paper:
                    case (byte)CVMCode.PlaintextPINVerificationPerformedByICCAndSignature_Paper:
                        cvmEnum = KernelCVMEnum.COMBO;
                        cvmResults.Value.CVMResult = 0x00;     //unknown
                        break;

                    //V in diagram
                    case (byte)CVMCode.Signature_Paper:
                        cvmEnum = KernelCVMEnum.OBTAIN_SIGNATURE;
                        cvmResults.Value.CVMResult = 0x00;     //unknown
                        CommonRoutines.UpdateOutcomeParameterSet(database, true);
                        break;

                    //W in diagram
                    case (byte)CVMCode.NoCVMRequired:
                        cvmEnum = KernelCVMEnum.NO_CVM;
                        cvmResults.Value.CVMResult = 0x02;     //successful
                        break;

                    case (byte)CVMCode.RFU:
                        cvmEnum = KernelCVMEnum.N_A;
                        tvr.Value.UnrecognisedCVM  = true;
                        cvmResults.Value.CVMResult = 0x01;     //failed
                        break;

                    default:
                        goto BackToIterate;
                    }
                    #endregion
                    cvmResults.Value.CVMPerformed = cvrCurrentlySelected.CVMRule;
                    cvmResults.Value.CVMCondition = (byte)cvrCurrentlySelected.CVMConditionCode;
                    cvmResults.UpdateDB();
                    int depth = 0;
                    Logger.Log(cvmResults.ToPrintString(ref depth));
                    CommonRoutines.UpdateOutcomeParameterSet(database, cvmEnum);
                    tvr.UpdateDB();
                    return;
                }
            }

            #region cvm.19
            if (((byte)cvrCurrentlySelected.CVMConditionCode & 0x40) == (byte)CVMFailureCondition.ApplySucceedingCVRuleIfThisCVMIsUnsuccessful)
            #endregion
            {
                #region cvm.20
                if (database.CVMCurrentlySelectedCounter < cvl.Value.CardHolderVerificationRules.Count)
                #endregion
                {
                    #region cvm.10
                    goto BackToIterate;
                    #endregion
                }
                else
                {
                    Do22_25(database, cvrCurrentlySelected);
                    return;
                }
            }
            else
            {
                Do22_25(database, cvrCurrentlySelected);
                return;
            }
        }
Exemplo n.º 22
0
        public static ICCDynamicData VerifySDAD(ICCDynamicDataType iccDDType, KernelDatabaseBase database, CAPublicKeyCertificate caPublicKey, byte[] sdadRaw)
        {
            //section 6.5.2 of EMV book 2 - DDA

            //1.If the Signed Dynamic Application Data has a length different from the
            //length of the ICC Public Key Modulus, CDA has failed
            IssuerPublicKeyCertificate ipk = IssuerPublicKeyCertificate.BuildAndValidatePublicKey(database, caPublicKey.Modulus, caPublicKey.Exponent);

            if (ipk == null)
            {
                return(null);
            }
            IccPublicKeyCertificate iccpk = IccPublicKeyCertificate.BuildAndValidatePublicKey(database, database.StaticDataToBeAuthenticated, ipk.Modulus, ipk.Exponent);

            if (iccpk == null)
            {
                return(null);
            }

            if (sdadRaw.Length != iccpk.Modulus.Length)
            {
                return(null);
            }

            //2.To obtain the recovered data specified in Table 22, apply the recovery
            //function as specified in Annex A2.1 on the Signed Dynamic Application
            //Data using the ICC Public Key in conjunction with the corresponding
            //algorithm.If the Recovered Data Trailer is not equal to 'BC', CDA has
            //failed
            byte[] decrypted = PublicKeyCertificate.DecryptRSA(sdadRaw, iccpk.Modulus, iccpk.Exponent);
            SDAD   sdad      = new SDAD(decrypted);

            //3.Check the Recovered Data Header. If it is not '6A', CDA has failed.
            if (sdad.DataHeader != 0x6A)
            {
                return(null);
            }
            //4.Check the Signed Data Format. If it is not '05', CDA has failed.
            //For Visa specialpurpose readers it may return 0x95 iff offline data authentication is supported for online transactions (in the TTQ)
            if (sdad.SignedDataFormat != 0x05 && sdad.SignedDataFormat != 0x95)
            {
                return(null);
            }

            ICCDynamicData iccDD = new ICCDynamicData(database, sdad.ICCDynamicData, iccDDType);

            //5.Concatenate from left to right the second to the sixth data elements in
            //Table 17(that is, Signed Data Format through Pad Pattern), followed by
            //the data elements specified by the DDOL.
            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);
            }

            byte[] dataForHash = sdad.Concat(ddolRelatedData);

            //6.Apply the indicated hash algorithm(derived from the Hash Algorithm
            //Indicator) to the result of the concatenation of the previous step to
            //produce the hash result.
            byte[] hash = SHA1.Create().ComputeHash(dataForHash);


            //7.Compare the calculated hash result from the previous step with the
            //recovered Hash Result.If they are not the same, DDA has failed.
            if (Formatting.ByteArrayToHexString(sdad.HashResult) != Formatting.ByteArrayToHexString(hash))
            {
                return(null);
            }

            return(iccDD);
        }
Exemplo n.º 23
0
        internal static SignalsEnum PostOutcome(KernelDatabaseBase database, KernelQ qManager,
                                                KernelMessageidentifierEnum uiMessage,
                                                KernelStatusEnum uiStatus,
                                                byte[] holdTime,
                                                Kernel2OutcomeStatusEnum status,
                                                Kernel2StartEnum start,
                                                bool?isUIRequestOnOutcomePresent,
                                                KernelMessageidentifierEnum messageOnError,
                                                L1Enum l1Enum,
                                                byte[] SW12,
                                                L2Enum l2Enum,
                                                L3Enum l3Enum,
                                                ValueQualifierEnum valueQualifierEnum,
                                                byte[] valueQualifier,
                                                byte[] currencyCode,
                                                bool receipt,
                                                KernelCVMEnum cvmStatus)
        {
            if (messageOnError != KernelMessageidentifierEnum.N_A || l1Enum != L1Enum.NOT_SET || l2Enum != L2Enum.NOT_SET || l3Enum != L3Enum.NOT_SET)
            {
                TLV disc = InitializeDiscretionaryData(database);

                ERROR_INDICATION_DF8115_KRN2 kei = new ERROR_INDICATION_DF8115_KRN2(database);
                kei.Value.MsgOnError = messageOnError;
                kei.Value.L1Enum     = l1Enum;
                kei.Value.L2Enum     = l2Enum;
                kei.Value.L3Enum     = l3Enum;
                if (SW12 != null)
                {
                    kei.Value.SW12 = SW12;
                }
                kei.UpdateDB();

                disc.Children.AddToList(kei);
                disc.Serialize();
            }

            if (uiMessage != KernelMessageidentifierEnum.N_A || uiStatus != KernelStatusEnum.N_A)
            {
                USER_INTERFACE_REQUEST_DATA_DF8116_KRN2 uird = new USER_INTERFACE_REQUEST_DATA_DF8116_KRN2(database);
                uird.Value.KernelMessageidentifierEnum = uiMessage;
                uird.Value.KernelStatusEnum            = uiStatus;
                if (holdTime == null)
                {
                    TLV holdTimeTLV = database.GetDefault(EMVTagsEnum.MESSAGE_HOLD_TIME_DF812D_KRN2);
                    if (holdTimeTLV != null)
                    {
                        holdTime = holdTimeTLV.Value;
                    }
                    else
                    {
                        holdTime = new byte[] { 0x00, 0x00, 0x00 }
                    };
                }
                uird.Value.HoldTime = holdTime;
                if (valueQualifier != null)
                {
                    uird.Value.ValueQualifier = valueQualifier;
                }
                uird.Value.ValueQualifierEnum = valueQualifierEnum;
                if (currencyCode != null)
                {
                    uird.Value.CurrencyCode = currencyCode;
                }
                uird.UpdateDB();
            }

            OUTCOME_PARAMETER_SET_DF8129_KRN2 kops = new OUTCOME_PARAMETER_SET_DF8129_KRN2(database);

            kops.Value.Status = status;
            kops.Value.Start  = start;
            if (isUIRequestOnOutcomePresent == null)
            {
                kops.Value.UIRequestOnOutcomePresent = isUIRequestOnOutcomePresent == false;
                kops.Value.UIRequestOnRestartPresent = isUIRequestOnOutcomePresent == false;
            }
            else
            {
                kops.Value.UIRequestOnOutcomePresent = isUIRequestOnOutcomePresent == true ? true : false;
                kops.Value.UIRequestOnRestartPresent = isUIRequestOnOutcomePresent == true ? false : true;
            }
            kops.Value.DataRecordPresent        = database.Get(EMVTagsEnum.DATA_RECORD_FF8105_KRN2) != null ? true : false;
            kops.Value.DiscretionaryDataPresent = database.Get(EMVTagsEnum.DISCRETIONARY_DATA_FF8106_KRN2) != null ? true : false;
            //kops.Value.Receipt = receipt;
            kops.Value.CVM = cvmStatus;
            kops.UpdateDB();

            qManager.EnqueueToOutput(new KernelOUTResponse(
                                         database.Get(EMVTagsEnum.OUTCOME_PARAMETER_SET_DF8129_KRN2),
                                         database.Get(EMVTagsEnum.ERROR_INDICATION_DF8115_KRN2),
                                         database.Get(EMVTagsEnum.DATA_RECORD_FF8105_KRN2),
                                         database.Get(EMVTagsEnum.DISCRETIONARY_DATA_FF8106_KRN2),
                                         database.Get(EMVTagsEnum.USER_INTERFACE_REQUEST_DATA_DF8116_KRN2)));

            return(SignalsEnum.STOP);
        }