Beispiel #1
0
        public byte[] SelectFile(byte[] id, SelectMode mode, SelectOccurrence occurrence, SelectFileControlInfo info)
        {
            if (id == null)
            {
                throw new ArgumentException("id");
            }

            // Setup the command
            CApdu command = new CApdu();

            command.Cla  = 0x00;
            command.Ins  = (byte)Part4Instruction.Select;
            command.P1   = (byte)mode;
            command.P2   = (byte)((byte)occurrence | (byte)info);
            command.Data = id;
            command.LE   = 0x00;

            // Transceive
            RApdu response = Transcieve(command);

            // Parse and test response
            if (response.IsError)
            {
                throw response.ThrowBySW("SelectFile");
            }

            return(response.Data);
        }
Beispiel #2
0
        public byte[] GetData(byte[] id)
        {
            // Argument validation
            if (id == null)
            {
                throw new ArgumentException("id");
            }

            // Setup the command and transcieve
            CApdu command = new CApdu();

            command.Cla = 0x00;
            command.Ins = (byte)Part4Instruction.GetDataA;
            command.P1  = id[0];
            command.P2  = id[1];

            RApdu response = Transcieve(command);

            // Validate the response
            if (response.IsError)
            {
                throw response.ThrowBySW("GetData");
            }

            return(response.Data);
        }
Beispiel #3
0
        public void SwitchProtocol(SwitchProtocolStandard standard, SwitchProtocolLayer layer)
        {
            const byte DataLength = 4;

            // Construct the data object
            byte[] data = new byte[DataLength];
            data[0] = TagSwitchProtocol;
            data[1] = 0x02; // Static length for data object
            data[2] = (byte)standard;
            data[3] = (byte)layer;

            CApdu command = new CApdu();

            command.Cla  = CApdu.ClaProprietary;
            command.Ins  = InsSupplementalCommand;
            command.P1   = 0x00; // Always null
            command.P2   = P2SwitchProtocol;
            command.Data = data;

            Iso7816Protocol protocol = GetProtocol <Iso7816Protocol>();
            RApdu           response = protocol.Transceive(command);

            // Validate the response,
            if (response.IsError)
            {
                throw response.ThrowBySW("SwitchProtocol");
            }
        }
Beispiel #4
0
        /*
         * PLAID Commands
         */

        public byte[] PlaidInitialAuthenticate(short keyIndex, byte[] estr1, short opMode)
        {
            // Setup the command
            CApdu command = new CApdu();

            command.Cla = CLA;
            command.Ins = (byte)PACSAMCommand.PlaidInitialAuth;
            command.P1  = (byte)((keyIndex >> 8) & 0xFF); // Key index MSB
            command.P2  = (byte)(keyIndex & 0xFF);        // Key index LSB

            // Generate the full APDU data
            MemoryStream data = new MemoryStream();

            data.WriteByte((byte)((opMode >> 8) & 0xFF)); // Key index MSB
            data.WriteByte((byte)(opMode & 0xFF));        // Key index LSB
            data.Write(estr1, 0, estr1.Length);
            command.Data = data.ToArray();
            //command.LE = 0x00;

            // Transceive
            RApdu response = Transcieve(command);

            // Parse and test DESFire status code
            if (response.IsError)
            {
                throw new Iso7816Exception(response.SW12, "PlaidInitialAuthenticate");
            }

            return(response.Data);
        }
Beispiel #5
0
        public bool EV1VerifyMAC(byte[] data)
        {
            // Setup the command
            CApdu command = new CApdu();

            command.Cla  = CLA;
            command.Ins  = (byte)PACSAMCommand.EV1verifyMac;
            command.P1   = 0;
            command.P2   = 0;
            command.Data = data;
            command.LE   = 0x00;

            // Transceive
            RApdu response = Transcieve(command);

            // Parse and test DESFire status code
            if (response.IsError)
            {
                //throw new Iso7816Exception(response.SW12, "EV1VerifyMAC");
                return(false);
            }

            // Done
            return(true);
        }
Beispiel #6
0
        /*
         * DESFireEV1 Commands
         */


        public byte[] EV1Authenticate0(short keyIndex, byte[] ekRndB)
        {
            // This command will reset our authentication status
            //ResetAuthentication();

            // Setup the command
            CApdu command = new CApdu();

            command.Cla = CLA;
            command.Ins = (byte)PACSAMCommand.EV1Auth0;
            command.P1  = (byte)((keyIndex >> 8) & 0xFF); // Key index MSB
            command.P2  = (byte)(keyIndex & 0xFF);        // Key index LSB

            MemoryStream data = new MemoryStream();

            // ekRndB (from PICC)
            data.Write(ekRndB, 0, ekRndB.Length);

            command.Data = data.ToArray();
            command.LE   = 0x00;

            // Transceive
            RApdu response = Transcieve(command);

            // Parse and test DESFire status code
            if (response.IsError)
            {
                throw new Iso7816Exception(response.SW12, "EV1Authenticate0");
            }

            return(response.Data);
        }
Beispiel #7
0
        public void EV1Authenticate1(byte[] ekRndA)
        {
            // Setup the command
            CApdu command = new CApdu();

            command.Cla  = CLA;
            command.Ins  = (byte)PACSAMCommand.EV1Auth1;
            command.P1   = 0;
            command.P2   = 0;
            command.Data = ekRndA;
            command.LE   = 0x00;

            // Transceive
            RApdu response = Transcieve(command);

            // Parse and test DESFire status code
            if (response.IsError)
            {
                throw new Iso7816Exception(response.SW12, "EV1Authenticate1");
            }

            // If we get a valid response then everything went OK and the PACSAM instance now has a session key established.
            // Confirm this by interrogating the PACSAM
            var status = GetStatus();

            if ((status.DESFireStatus != DESFireAuthStatus.AUTH_STATE_OK_DES) &&
                (status.DESFireStatus != DESFireAuthStatus.AUTH_STATE_OK_ISO) &&
                (status.DESFireStatus != DESFireAuthStatus.AUTH_STATE_OK_AES))
            {
                throw new InvalidOperationException(@"PACSAM authentication state not changed. Authentication failed.");
            }
        }
Beispiel #8
0
        public void GeneralAuthenticate(ushort address, GeneralAuthenticateKeyType keyType, byte keyIndex)
        {
            const int AuthenticateDataLen = 5;

            CApdu command = new CApdu();

            command.Cla = CLA;
            command.Ins = INSGeneralAuthenticate;
            command.P1  = 0x00; // Always null
            command.P2  = 0x00; // Always null

            byte[] data = new byte[AuthenticateDataLen];
            data[0] = 0x01; // Static version
            data[1] = (byte)(address >> 8);
            data[2] = (byte)(address & 0xFF);
            data[3] = (byte)keyType;
            data[4] = 0;

            command.Data = data;

            RApdu response = myProtocol.Transceive(command);

            // Validate the response,
            if (response.IsError)
            {
                throw response.ThrowBySW("GeneralAuthenticate");
            }
        }
Beispiel #9
0
        public void LoadKey(PACSAMKeyType keyType, byte element, byte[] record)
        {
            // Setup the command
            CApdu command = new CApdu();

            command.Cla  = CLA;
            command.Ins  = (byte)PACSAMCommand.LoadKey;
            command.P1   = (byte)keyType;
            command.P2   = element;
            command.Data = record;

            // NOTE: For some reason I get poor handling of Extended APDU's when supplying the LE byte. This may only be relevant to the Javacos virtual reader
            // but for now we just omit it.
            if (record.Length <= 255)
            {
                command.LE = 0x00;
            }

            // Transceive
            RApdu response = Transcieve(command);

            // Parse and test DESFire status code
            if (response.IsError)
            {
                throw new Iso7816Exception(response.SW12, "LoadKey");
            }
        }
Beispiel #10
0
        public byte[] GetDataExtended(byte[] id, byte p1, byte p2)
        {
            // Argument validation
            if (id == null)
            {
                throw new ArgumentException("id");
            }

            // Setup the command and transcieve
            CApdu command = new CApdu();

            command.Cla  = 0x00;
            command.Ins  = (byte)Part4Instruction.GetDataB;
            command.P1   = p1;
            command.P2   = p2;
            command.Data = id;
            command.LE   = 0x00;

            RApdu response = Transcieve(command);

            // Validate the response,
            if (response.IsError)
            {
                throw response.ThrowBySW("GetDataExtended");
            }

            return(response.Data);
        }
Beispiel #11
0
        public override RApdu Transceive(CApdu command)
        {
            IntPtr requestPci;

            switch (myCard.CommsProtocol)
            {
            case SCardProtocol.T0:
                requestPci = PCSCApi.SCardPciT0;
                break;

            case SCardProtocol.T1:
                requestPci = PCSCApi.SCardPciT1;
                break;

            default:
                throw PCSCException.ThrowUnsupportedProtocol();
            }

            int responseLength = 1024;

            byte[]     responseBuffer = new byte[responseLength];
            byte[]     cmdBuffer      = command.ToArray();
            PCSCResult result         = NativeMethods.SCardTransmit(myCard.Handle, requestPci, cmdBuffer, cmdBuffer.Length, IntPtr.Zero, responseBuffer, ref responseLength);

            if (PCSCResult.None == result)
            {
                byte[] response = new byte[responseLength];
                Array.Copy(responseBuffer, response, responseLength);

#if DEBUG
                RaiseOnTranscieve("CAPDU> " + Converters.ByteArrayToString(cmdBuffer));
                RaiseOnTranscieve("RAPDU> " + Converters.ByteArrayToString(response));
#endif

                return(RApdu.Parse(response));
            }
            else
            {
#if DEBUG
                RaiseOnTranscieve("CAPDU> " + Converters.ByteArrayToString(cmdBuffer));
                RaiseOnTranscieve("RAPDU> Error condition (HRESULT = " + EnumHelper.GetDescription(result) + ")");
#endif
                throw new PCSCException("Communications error.");
            }
        }
Beispiel #12
0
        public void LoadKeys(OptionalLoadKeyStructure structure, byte secureKeyIndex, byte keyIndex, byte[] key)
        {
            CApdu command = new CApdu();

            command.Cla  = CLA;
            command.Ins  = INSLoadKeys;
            command.P1   = (byte)((byte)structure | secureKeyIndex);
            command.P2   = keyIndex;
            command.Data = key;

            RApdu response = myProtocol.Transceive(command);

            // Validate the response,
            if (response.IsError)
            {
                throw response.ThrowBySW("LoadKeys");
            }
        }
Beispiel #13
0
        public void UpdateBinary(ushort address, byte[] data)
        {
            CApdu command = new CApdu();

            command.Cla  = CLA;
            command.Ins  = INSUpdateBinary;
            command.P1   = (byte)(address >> 8);
            command.P2   = (byte)(address & 0xFF);
            command.Data = data;

            RApdu response = myProtocol.Transceive(command);

            // Validate the response,
            if (response.IsError)
            {
                throw response.ThrowBySW("UpdateBinary");
            }
        }
Beispiel #14
0
        public byte[] GetATS()
        {
            CApdu command = new CApdu();

            command.Cla = CLA;
            command.Ins = INSGetATS;
            command.P1  = P1GetATS;
            command.P2  = 0x00; // Always null

            RApdu response = myProtocol.Transceive(command);

            // Validate the response,
            if (response.IsError)
            {
                throw response.ThrowBySW("GetATS");
            }

            return(response.Data);
        }
Beispiel #15
0
 internal PCSCIso14443AProtocol(byte[] atr, PCSCCard card)
     : base(atr, card)
 {
     try
     {
         // Retrieve our UID
         CApdu command  = new CApdu(0xFF, 0xCA, 0, le: 00);
         RApdu response = Transceive(command);
         if (response.IsError)
         {
             throw new InvalidOperationException("Error retrieving the Card UID");
         }
         UID = response.Data;
     }
     catch (Exception)
     {
         // Some IFD's don't support UID retrieval
     }
 }
Beispiel #16
0
        public byte[] ReadBinary(ushort address, byte length)
        {
            CApdu command = new CApdu();

            command.Cla = CLA;
            command.Ins = INSReadBinary;
            command.P1  = (byte)(address >> 8);
            command.P2  = (byte)(address & 0xFF);
            command.LE  = length; // 16 byte read

            RApdu response = myProtocol.Transceive(command);

            // Validate the response,
            if (response.IsError)
            {
                throw response.ThrowBySW("ReadBinary");
            }

            return(response.Data);
        }
Beispiel #17
0
        public void PlaidLoadFAKey(short keyIndex, byte[] cryptogram)
        {
            // Setup the command
            CApdu command = new CApdu();

            command.Cla  = CLA;
            command.Ins  = (byte)PACSAMCommand.PlaidLoadFAKey;
            command.P1   = (byte)((keyIndex >> 8) & 0xFF); // Key index MSB
            command.P2   = (byte)(keyIndex & 0xFF);        // Key index LSB
            command.Data = cryptogram;

            // Transceive
            RApdu response = Transcieve(command);

            // Parse and test status code
            if (response.IsError)
            {
                throw new Iso7816Exception(response.SW12, "PlaidLoadFAKey");
            }
        }
Beispiel #18
0
        protected void ManageSession(byte[] dataObject)
        {
            CApdu command = new CApdu();

            command.Cla  = CApdu.ClaProprietary;
            command.Ins  = InsSupplementalCommand;
            command.P1   = 0x00; // Always null
            command.P2   = P2ManageSession;
            command.Data = dataObject;
            command.LE   = 0x00;

            Iso7816Protocol protocol = GetProtocol <Iso7816Protocol>();
            RApdu           response = protocol.Transceive(command);

            // Validate the response,
            if (response.IsError)
            {
                throw response.ThrowBySW("ManageSession");
            }
        }
Beispiel #19
0
        public byte[] GetData(byte element)
        {
            Iso7816Protocol protocol = Card.GetProtocol <Iso7816Protocol>();

            // Construct the APDU
            CApdu command = new CApdu();

            command.Cla = CLA;
            command.Ins = INS_GET_DATA;
            command.P1  = element;
            command.P2  = 0x00;
            RApdu response = protocol.Transceive(command);

            // Validate the response,
            if (response.IsError)
            {
                throw response.ThrowBySW("GetData");
            }

            return(response.Data);
        }
Beispiel #20
0
        public void ResetAuthentication()
        {
            Iso7816Protocol protocol = Card.GetProtocol <Iso7816Protocol>();

            // Construct the APDU
            CApdu command = new CApdu();

            command.Cla = CLA;
            command.Ins = INS_RESET_AUTH;
            command.P1  = 0x00;
            command.P2  = 0x00;
            RApdu response = protocol.Transceive(command);

            // Validate the response,
            if (response.IsError)
            {
                throw response.ThrowBySW("SetData");
            }

            return;
        }
Beispiel #21
0
        public void EV1UpdateIV(byte[] data)
        {
            // Setup the command
            CApdu command = new CApdu();

            command.Cla  = CLA;
            command.Ins  = (byte)PACSAMCommand.EV1UpdateIV;
            command.P1   = 0;
            command.P2   = 0;
            command.Data = data;
            command.LE   = 0x00;

            // Transceive
            RApdu response = Transcieve(command);

            // Parse and test DESFire status code
            if (response.IsError)
            {
                throw new Iso7816Exception(response.SW12, "EV1UpdateIV");
            }
        }
Beispiel #22
0
        public void SetData(byte[] cryptogram)
        {
            Iso7816Protocol protocol = Card.GetProtocol <Iso7816Protocol>();

            // Construct the APDU
            CApdu command = new CApdu();

            command.Cla  = CLA;
            command.Ins  = INS_SET_DATA;
            command.P1   = 0x00;
            command.P2   = 0x00;
            command.Data = cryptogram;
            RApdu response = protocol.Transceive(command);

            // Validate the response,
            if (response.IsError)
            {
                throw response.ThrowBySW("SetData");
            }

            return;
        }
Beispiel #23
0
        public byte[] FinalAuthenticate(byte[] estr2)
        {
            Iso7816Protocol protocol = Card.GetProtocol <Iso7816Protocol>();

            CApdu command = new CApdu();

            command.Cla  = CLA;
            command.Ins  = INS_PLAID_FINAL_AUTH;
            command.P1   = 0x00;
            command.P2   = 0x00;
            command.Data = estr2;

            RApdu response = protocol.Transceive(command);

            // Validate the response,
            if (response.IsError)
            {
                throw response.ThrowBySW("FinalAuthenticate");
            }

            return(response.Data);
        }
Beispiel #24
0
        public byte[] InitialAuthenticate(KeysetList keysets)
        {
            Iso7816Protocol protocol = Card.GetProtocol <Iso7816Protocol>();

            CApdu command = new CApdu();

            command.Cla  = CLA;
            command.Ins  = INS_PLAID_INITIAL_AUTH;
            command.P1   = 0x00;
            command.P2   = 0x00;
            command.Data = keysets.Encode();

            RApdu response = protocol.Transceive(command);

            // Validate the response,
            if (response.IsError)
            {
                throw response.ThrowBySW("InitialAuthenticate");
            }

            return(response.Data);
        }
Beispiel #25
0
        protected RApdu Transcieve(CApdu command)
        {
            Iso7816Protocol protocol = Card.GetProtocol <Iso7816Protocol>();
            MemoryStream    data     = new MemoryStream();

            // Send the first (and possibly only) tranceive command
            RApdu response = protocol.Transceive(command);

            // Check for more data
            while (response.SW1 == RApdu.SW1MoreData)
            {
                // Dump what we have so far to the memory stream
                data.Write(response.Data, 0, response.Data.Length);

                // Issue a 'GET RESPONSE' request
                command.Ins  = (byte)Part4Instruction.GetResponse;
                command.P1   = 0x00;
                command.P2   = 0x00;
                command.Data = new byte[0];
                command.LE   = response.SW2;

                // Request the next block
                response = protocol.Transceive(command);
            }

            // Check for other error, just return if it is
            if (response.IsError)
            {
                return(response);
            }

            // Get the final block of response data
            data.Write(response.Data, 0, response.Data.Length);

            // Done, return the last RApdu with the full data
            response.Data = data.ToArray();
            return(response);
        }
Beispiel #26
0
        public PlaidStatus GetStatus()
        {
            Iso7816Protocol protocol = Card.GetProtocol <Iso7816Protocol>();

            // Construct the APDU
            CApdu command = new CApdu();

            command.Cla = CLA;
            command.Ins = INS_GET_STATUS;
            command.P1  = 0x00;
            command.P2  = 0x00;
            RApdu response = protocol.Transceive(command);

            // Validate the response,
            if (response.IsError)
            {
                throw response.ThrowBySW("GetStatus");
            }

            PlaidStatus status = new PlaidStatus(response.Data);

            return(status);
        }
Beispiel #27
0
        public void EV1SetDivData(byte[] divData)
        {
            // Setup the command
            CApdu command = new CApdu();

            command.Cla  = CLA;
            command.Ins  = (byte)PACSAMCommand.EV1SetDivData;
            command.P1   = 0;
            command.P2   = 0;
            command.Data = divData;
            command.LE   = 0x00;

            // Transceive
            RApdu response = Transcieve(command);

            // Parse and test DESFire status code
            if (response.IsError)
            {
                throw new Iso7816Exception(response.SW12, "EV1SetDivData");
            }

            // If we get a valid response then everything went OK and the PACSAM instance now has a session key established.
        }
Beispiel #28
0
        protected RApdu Transcieve(byte cla, byte ins, byte p1 = 0, byte p2 = 0, byte[] data = null, byte?le = 0)
        {
            // Setup the command
            CApdu command = new CApdu();

            command.Cla = cla;
            command.Ins = ins;
            command.P1  = p1;
            command.P2  = p2;
            if (data != null)
            {
                command.Data = data;
            }
            if (le != null)
            {
                command.LE = le;
            }

            // Transceive
            RApdu response = Transcieve(command);

            return(response);
        }
Beispiel #29
0
        public byte[] PlaidFinalAuthenticate(byte[] estr3)
        {
            // Setup the command
            CApdu command = new CApdu();

            command.Cla  = CLA;
            command.Ins  = (byte)PACSAMCommand.PlaidFinalAuth;
            command.P1   = 0x00;
            command.P2   = 0x00;
            command.Data = estr3;
            command.LE   = 0x00;

            // Transceive
            RApdu response = Transcieve(command);

            // Parse and test status code
            if (response.IsError)
            {
                throw new Iso7816Exception(response.SW12, "PlaidFinalAuthenticate");
            }

            return(response.Data);
        }
Beispiel #30
0
        public byte[] PlaidSetData(byte[] commandObject)
        {
            // Setup the command
            CApdu command = new CApdu();

            command.Cla  = CLA;
            command.Ins  = (byte)PACSAMCommand.PlaidSetData;
            command.P1   = 0x00;
            command.P2   = 0x00;
            command.Data = commandObject;
            //command.LE = 0x00;

            // Transceive
            RApdu response = Transcieve(command);

            // Parse and test status code
            if (response.IsError)
            {
                throw new Iso7816Exception(response.SW12, "PlaidSetData");
            }

            return(response.Data);
        }