示例#1
0
        private GPResponse SendCommand(GPCommand apduCommand)
        {
            if (wrapper == null)
            {
                ApduResponse response = cardInterface.SendCommand(apduCommand);
                if (response is GPResponse)
                {
                    return((GPResponse)response);
                }
            }
            else
            {
                GPCommand wrapped = Activator.CreateInstance(apduCommand.GetType()) as GPCommand;
                wrapped.ApduResponseType = apduCommand.ApduResponseType;
                wrapped.Deserialize(wrapper.Wrap(apduCommand));
                ApduResponse response = cardInterface.SendCommand(wrapped);
                if (response is GPResponse)
                {
                    return((GPResponse)response);
                }
            }

            throw new PersoException("Error returned from card");
        }
示例#2
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);
            }
        }
示例#3
0
 public abstract byte[] Wrap(GPCommand command);
示例#4
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);
            }
        }