Beispiel #1
0
        private static byte[] Mac_des_3des(GPKey key, byte[] text, int offset, int length, byte[] iv)
        {
            if (length == -1)
            {
                length = text.Length - offset;
            }

            try
            {
                //Cipher cipher1 = Cipher.getInstance(DES_CBC_CIPHER);
                //cipher1.init(Cipher.ENCRYPT_MODE, key.getKey(Type.DES), new IvParameterSpec(iv));
                //Cipher cipher2 = Cipher.getInstance(DES3_CBC_CIPHER);
                //cipher2.init(Cipher.ENCRYPT_MODE, key.getKey(Type.DES3), new IvParameterSpec(iv));

                byte[] result = Arrays.Clone(iv);
                byte[] temp;
                if (length > 8)
                {
                    temp = GPCrypto.DoEncrypt_DES_CBC(key.GetKey(KeyType.DES).GetEncoded(), text, offset, length - 8, iv);
                    Array.Copy(temp, temp.Length - 8, result, 0, 8);
                }
                temp = GPCrypto.DoEncrypt_DES3_CBC(key.GetKey(KeyType.DES3).GetEncoded(), text, (offset + length) - 8, 8, result);
                Array.Copy(temp, temp.Length - 8, result, 0, 8);
                return(result);
            }
            catch (Exception e)
            {
                //e.printStackTrace();
                throw new Exception("MAC computation failed.", e);
            }
        }
        public static GPKeySet Diversify(GPKeySet keys, byte[] diversification_data, Diversification mode, int scp)
        {
            try
            {
                GPKeySet result = new GPKeySet();
                //Cipher cipher = Cipher.getInstance("DESede/ECB/NoPadding");
                foreach (KeySessionType v in KeyTypeList.Values)
                {
                    if (v == KeySessionType.RMAC)
                    {
                        continue;
                    }
                    byte[] kv = null;
                    // shift around and fill initialize update data as required.
                    if (mode == Diversification.VISA2)
                    {
                        kv = FillVisa(diversification_data, v);
                    }
                    else if (mode == Diversification.EMV)
                    {
                        kv = FillEmv(diversification_data, v);
                    }

                    // Encrypt with current master key
                    //cipher.init(Cipher.ENCRYPT_MODE, keys.getKey(v).getKey(Type.DES3));
                    //byte[] keybytes = cipher.doFinal(kv);
                    byte[] keybytes = GPCrypto.DoEncrypt_DES3_ECB(keys.GetKey(v).GetKey(KeyType.DES3).GetEncoded(), kv);

                    // Replace the key, possibly changing type. G&D SCE 6.0 uses EMV 3DES and resulting keys
                    // must be interpreted as AES-128
                    GPKey nk = new GPKey(keybytes, scp == 3 ? KeyType.AES : KeyType.DES3);
                    result.SetKey(v, nk);
                }
                return(result);
            }
            //catch (BadPaddingException e)
            //{
            //    throw new Exception("Diversification failed.", e);
            //}
            //catch (InvalidKeyException e)
            //{
            //    throw new Exception("Diversification failed.", e);
            //}
            //catch (IllegalBlockSizeException e)
            //{
            //    throw new Exception("Diversification failed.", e);
            //}
            //catch (NoSuchAlgorithmException e)
            //{
            //    throw new Exception("Diversification failed.", e);
            //}
            //catch (NoSuchPaddingException e)
            //{
            //    throw new Exception("Diversification failed.", e);
            //}
            catch (Exception e)
            {
                throw new Exception("Diversification failed.", e);
            }
        }
        private GPKeySet DeriveSessionKeysSCP01(GPKeySet staticKeys, byte[] host_challenge, byte[] card_challenge)
        {
            GPKeySet sessionKeys = new GPKeySet();

            byte[] derivationData = new byte[16];
            Array.Copy(card_challenge, 4, derivationData, 0, 4);
            Array.Copy(host_challenge, 0, derivationData, 4, 4);
            Array.Copy(card_challenge, 0, derivationData, 8, 4);
            Array.Copy(host_challenge, 4, derivationData, 12, 4);

            try
            {
                //Cipher cipher = Cipher.getInstance("DESede/ECB/NoPadding");
                foreach (KeySessionType v in KeyTypeList.Values)
                {
                    if (v == KeySessionType.RMAC) // skip RMAC key
                    {
                        continue;
                    }
                    //cipher.init(Cipher.ENCRYPT_MODE, staticKeys.getKeyFor(v));
                    //GPKey nk = new GPKey(cipher.doFinal(derivationData), Type.DES3);
                    byte[] result = GPCrypto.DoEncrypt_DES3_ECB(staticKeys.GetKeyFor(v).GetEncoded(), derivationData);
                    GPKey  nk     = new GPKey(result, KeyType.DES3);

                    sessionKeys.SetKey(v, nk);
                }
                // KEK is the same
                sessionKeys.SetKey(KeySessionType.KEK, staticKeys.GetKey(KeySessionType.KEK));
                return(sessionKeys);
            }
            //catch (NoSuchAlgorithmException e)
            //{
            //    throw new IllegalStateException("Session keys calculation failed.", e);
            //}
            //catch (NoSuchPaddingException e)
            //{
            //    throw new IllegalStateException("Session keys calculation failed.", e);
            //}
            //catch (InvalidKeyException e)
            //{
            //    throw new RuntimeException("Session keys calculation failed.", e);
            //}
            //catch (IllegalBlockSizeException e)
            //{
            //    throw new RuntimeException("Session keys calculation failed.", e);
            //}
            //catch (BadPaddingException e)
            //{
            //    throw new RuntimeException("Session keys calculation failed.", e);
            //}
            catch (Exception e)
            {
                throw new Exception("Session keys calculation failed.", e);
            }
        }
Beispiel #4
0
 private static byte[] Scp03_key_check_value(GPKey key)
 {
     try
     {
         byte[] cv = GPCrypto.DoEncrypt_AES_CBC(key.GetKey().GetEncoded(), GPCrypto.one_bytes_16);
         //Cipher c = Cipher.getInstance(AES_CBC_CIPHER);
         //c.init(Cipher.ENCRYPT_MODE, key.getKey(), iv_null_aes);
         //byte[] cv = c.doFinal(one_bytes_16);
         return(Arrays.CopyOfRange(cv, 0, 3));
     }
     catch (Exception e)
     {
         throw new Exception("Could not calculate key check value: ", e);
     }
 }
Beispiel #5
0
 private static byte[] Scp03_encrypt_key(GPKey kek, GPKey key)
 {
     try
     {
         // Pad with random
         int          n         = key.GetLength() % 16 + 1;
         byte[]       plaintext = new byte[n * 16];
         SecureRandom sr        = new SecureRandom();
         sr.NextBytes(plaintext);
         Array.Copy(key.GetValue(), 0, plaintext, 0, key.GetValue().Length);
         // encrypt
         byte[] cgram = GPCrypto.DoEncrypt_AES_CBC(kek.GetValue(), plaintext);
         //Cipher c = Cipher.getInstance(AES_CBC_CIPHER);
         //c.init(Cipher.ENCRYPT_MODE, kek.GetEncoded(), null_bytes_16);
         //byte[] cgram = c.doFinal(plaintext);
         return(cgram);
     }
     catch (Exception e)
     {
         throw new Exception("Could not calculate key check value: ", e);
     }
 }
Beispiel #6
0
        private static byte[] Mac_3des(ISecretKey key, byte[] text, int offset, int length, byte[] iv)
        {
            if (length == -1)
            {
                length = text.Length - offset;
            }

            try
            {
                //Cipher cipher = Cipher.getInstance(DES3_CBC_CIPHER);
                //cipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(iv));
                //byte[] res = cipher.doFinal(text, offset, length);
                byte[] res = GPCrypto.DoEncrypt_DES3_CBC(key.GetEncoded(), text, offset, length, iv);

                byte[] result = new byte[8];
                Array.Copy(res, res.Length - 8, result, 0, 8);
                return(result);
            }
            catch (Exception e)
            {
                throw new Exception("MAC computation failed.", e);
            }
        }
        private GPKeySet DeriveSessionKeysSCP02(GPKeySet staticKeys, byte[] sequence, bool implicitChannel)
        {
            GPKeySet sessionKeys = new GPKeySet();

            try
            {
                //Cipher cipher = Cipher.getInstance("DESede/CBC/NoPadding");

                byte[] derivationData = new byte[16];
                Array.Copy(sequence, 0, derivationData, 2, 2);

                byte[] constantMAC = new byte[] { (byte)0x01, (byte)0x01 };
                Array.Copy(constantMAC, 0, derivationData, 0, 2);
                //cipher.init(Cipher.ENCRYPT_MODE, staticKeys.getKeyFor(KeySessionType.MAC), GPCrypto.iv_null_des);
                //GPKey nk = new GPKey(cipher.doFinal(derivationData), Type.DES3);
                byte[] result = GPCrypto.DoEncrypt_DES3_CBC(staticKeys.GetKeyFor(KeySessionType.MAC).GetEncoded(), derivationData);
                GPKey  nk     = new GPKey(result, KeyType.DES3);

                sessionKeys.SetKey(KeySessionType.MAC, nk);

                // TODO: is this correct? - increment by one for all other than C-MAC
                if (implicitChannel)
                {
                    Buffer_increment(derivationData, 2, 2);
                }

                byte[] constantRMAC = new byte[] { (byte)0x01, (byte)0x02 };
                Array.Copy(constantRMAC, 0, derivationData, 0, 2);
                //cipher.init(Cipher.ENCRYPT_MODE, staticKeys.getKeyFor(KeySessionType.MAC), GPCrypto.iv_null_des);
                //nk = new GPKey(cipher.doFinal(derivationData), Type.DES3);
                byte[] result2 = GPCrypto.DoEncrypt_DES3_CBC(staticKeys.GetKeyFor(KeySessionType.MAC).GetEncoded(), derivationData);
                nk = new GPKey(result2, KeyType.DES3);

                sessionKeys.SetKey(KeySessionType.RMAC, nk);

                byte[] constantENC = new byte[] { (byte)0x01, (byte)0x82 };
                Array.Copy(constantENC, 0, derivationData, 0, 2);
                //cipher.init(Cipher.ENCRYPT_MODE, staticKeys.getKeyFor(KeySessionType.ENC), GPCrypto.iv_null_des);
                //nk = new GPKey(cipher.doFinal(derivationData), Type.DES3);
                byte[] result3 = GPCrypto.DoEncrypt_DES3_CBC(staticKeys.GetKeyFor(KeySessionType.ENC).GetEncoded(), derivationData);
                nk = new GPKey(result3, KeyType.DES3);

                sessionKeys.SetKey(KeySessionType.ENC, nk);

                byte[] constantDEK = new byte[] { (byte)0x01, (byte)0x81 };
                Array.Copy(constantDEK, 0, derivationData, 0, 2);
                //cipher.init(Cipher.ENCRYPT_MODE, staticKeys.getKeyFor(KeySessionType.KEK), GPCrypto.iv_null_des);
                //nk = new GPKey(cipher.doFinal(derivationData), Type.DES3);
                byte[] result4 = GPCrypto.DoEncrypt_DES3_CBC(staticKeys.GetKeyFor(KeySessionType.KEK).GetEncoded(), derivationData);
                nk = new GPKey(result4, KeyType.DES3);

                sessionKeys.SetKey(KeySessionType.KEK, nk);
                return(sessionKeys);
            }
            //catch (NoSuchAlgorithmException e)
            //{
            //    throw new IllegalStateException("Session keys calculation failed.", e);
            //}
            //catch (NoSuchPaddingException e)
            //{
            //    throw new IllegalStateException("Session keys calculation failed.", e);
            //}
            //catch (InvalidKeyException e)
            //{
            //    throw new RuntimeException("Session keys calculation failed.", e);
            //}
            //catch (IllegalBlockSizeException e)
            //{
            //    throw new RuntimeException("Session keys calculation failed.", e);
            //}
            //catch (BadPaddingException e)
            //{
            //    throw new RuntimeException("Session keys calculation failed.", e);
            //}
            //catch (InvalidAlgorithmParameterException e)
            //{
            //    throw new RuntimeException("Session keys calculation failed.", e);
            //}
            catch (Exception e)
            {
                throw new Exception("Session keys calculation failed.", e);
            }
        }
Beispiel #8
0
        public override byte[] Wrap(GPCommand command)
        {
            byte[] cmd_mac = null;

            try
            {
                if (!mac && !enc)
                {
                    return(command.Serialize());
                }

                int    cla  = command.CLA;
                int    lc   = command.CommandData.Length;
                byte[] data = command.CommandData;

                // Encrypt if needed
                if (enc)
                {
                    cla = 0x84;
                    // Counter shall always be incremented
                    Buffer_increment(encryption_counter);
                    if (command.CommandData.Length > 0)
                    {
                        byte[] d = Pad80(command.CommandData, 16);
                        // Encrypt with S-ENC, after increasing the counter
                        byte[] iv = GPCrypto.DoEncrypt_AES_CBC(sessionKeys.GetKeyFor(KeySessionType.ENC).GetEncoded(), encryption_counter);
                        data = GPCrypto.DoEncrypt_AES_CBC(sessionKeys.GetKeyFor(KeySessionType.ENC).GetEncoded(), d, iv);

                        //Cipher c = Cipher.getInstance(GPCrypto.AES_CBC_CIPHER);
                        //c.init(Cipher.ENCRYPT_MODE, sessionKeys.getKeyFor(KeySessionType.ENC), GPCrypto.null_bytes_16);
                        //byte[] iv = c.doFinal(encryption_counter);

                        // Now encrypt the data with S-ENC.
                        //c.init(Cipher.ENCRYPT_MODE, sessionKeys.getKeyFor(KeySessionType.ENC), new IvParameterSpec(iv));
                        //data = c.doFinal(d);
                        lc = data.Length;
                    }
                }
                // Calculate C-MAC
                if (mac)
                {
                    cla = 0x84;
                    lc  = lc + 8;

                    ByteArrayOutputStream bo = new ByteArrayOutputStream();
                    bo.Write(chaining_value);
                    bo.Write(cla);
                    bo.Write(command.INS);
                    bo.Write(command.P1);
                    bo.Write(command.P2);
                    bo.Write(lc);
                    bo.Write(data);
                    byte[] cmac_input = bo.ToByteArray();
                    byte[] cmac       = Scp03_mac(sessionKeys.GetKey(KeySessionType.MAC), cmac_input, 128);
                    // Set new chaining value
                    Array.Copy(cmac, 0, chaining_value, 0, chaining_value.Length);
                    // 8 bytes for actual mac
                    cmd_mac = Arrays.CopyOf(cmac, 8);
                }
                // Construct new command
                ByteArrayOutputStream na = new ByteArrayOutputStream();
                na.Write(cla); // possibly fiddled
                na.Write(command.INS);
                na.Write(command.P1);
                na.Write(command.P2);
                na.Write(lc);
                na.Write(data);
                if (mac)
                {
                    na.Write(cmd_mac);
                }
                return(na.ToByteArray());
            }
            catch (Exception e)
            {
                throw new Exception("APDU wrapping failed", e);
            }
        }
Beispiel #9
0
        public override byte[] Wrap(GPCommand command)
        {
            try
            {
                if (!mac && !enc)
                {
                    return(command.Serialize());
                }

                if (rmac)
                {
                    rMac.Reset();
                    rMac.Write(ClearBits((byte)command.CLA, (byte)0x07));
                    rMac.Write(command.INS);
                    rMac.Write(command.P1);
                    rMac.Write(command.P2);
                    if (command.CommandData.Length >= 0)
                    {
                        rMac.Write(command.CommandData.Length);
                        rMac.Write(command.CommandData);
                    }
                }

                byte   origCLA          = command.CLA;
                byte   newCLA           = origCLA;
                byte   origINS          = command.INS;
                byte   origP1           = command.P1;
                byte   origP2           = command.P2;
                byte[] origData         = command.CommandData;
                byte   origLc           = (byte)command.CommandData.Length;
                byte   newLc            = origLc;
                byte[] newData          = null;
                byte   le               = command.Le.Value;
                ByteArrayOutputStream t = new ByteArrayOutputStream();

                if (origLc > GetBlockSize())
                {
                    throw new Exception("APDU too long for wrapping.");
                }

                if (mac)
                {
                    if (icv == null)
                    {
                        icv = new byte[8];
                    }
                    else if (icvEnc)
                    {
                        //IBufferedCipher c = null;
                        if (scp == 1)
                        {
                            icv = GPCrypto.DoEncrypt_DES3_ECB(sessionKeys.GetKeyFor(KeySessionType.MAC).GetEncoded(), icv);
                            //c = Cipher.getInstance(GPCrypto.DES3_ECB_CIPHER);
                            //c.init(Cipher.ENCRYPT_MODE, sessionKeys.getKeyFor(KeyType.MAC));
                        }
                        else
                        {
                            icv = GPCrypto.DoEncrypt_DES_ECB(sessionKeys.GetKey(KeySessionType.MAC).GetKey(KeyType.DES).GetEncoded(), icv);
                            //c = Cipher.getInstance(GPCrypto.DES_ECB_CIPHER);
                            //c.init(Cipher.ENCRYPT_MODE, sessionKeys.getKey(KeyType.MAC).getKey(Type.DES));
                        }
                        // encrypts the future ICV ?
                        //icv = c.doFinal(icv);
                    }

                    if (preAPDU)
                    {
                        newCLA = SetBits((byte)newCLA, (byte)0x04);
                        newLc  = (byte)(newLc + 8);
                    }
                    t.Write(newCLA);
                    t.Write(origINS);
                    t.Write(origP1);
                    t.Write(origP2);
                    t.Write(newLc);
                    t.Write(origData);

                    if (scp == 1)
                    {
                        icv = Mac_3des(sessionKeys.GetKey(KeySessionType.MAC), t.ToByteArray(), icv);
                    }
                    else if (scp == 2)
                    {
                        icv = Mac_des_3des(sessionKeys.GetKey(KeySessionType.MAC), t.ToByteArray(), icv);
                    }

                    if (postAPDU)
                    {
                        newCLA = SetBits((byte)newCLA, (byte)0x04);
                        newLc  = (byte)(newLc + 8);
                    }
                    t.Reset();
                    newData = origData;
                }

                if (enc && (origLc > 0))
                {
                    if (scp == 1)
                    {
                        t.Write(origLc);
                        t.Write(origData);
                        if ((t.Size() % 8) != 0)
                        {
                            byte[] x = Pad80(t.ToByteArray(), 8);
                            t.Reset();
                            t.Write(x);
                        }
                    }
                    else
                    {
                        t.Write(Pad80(origData, 8));
                    }
                    newLc += (byte)(t.Size() - origData.Length);

                    //Cipher c = Cipher.getInstance(GPCrypto.DES3_CBC_CIPHER);
                    //c.init(Cipher.ENCRYPT_MODE, sessionKeys.getKeyFor(KeyType.ENC), GPCrypto.iv_null_des);
                    //newData = c.doFinal(t.toByteArray());
                    newData = GPCrypto.DoEncrypt_DES3_CBC(sessionKeys.GetKeyFor(KeySessionType.ENC).GetEncoded(), t.ToByteArray());

                    t.Reset();
                }
                t.Write(newCLA);
                t.Write(origINS);
                t.Write(origP1);
                t.Write(origP2);
                if (newLc > 0)
                {
                    t.Write(newLc);
                    t.Write(newData);
                }
                if (mac)
                {
                    t.Write(icv);
                }
                if (le > 0)
                {
                    t.Write(le);
                }
                return(t.ToByteArray());
            }
            catch (Exception e)
            {
                throw new Exception("APDU wrapping failed", e);
            }
        }