Example #1
0
        /// <summary>
        /// Process ERASE instruction (CC3)
        /// <para>
        /// C-APDU: <code>00 0E {offset} {Lc} {length} </code>
        /// </para>
        /// <list type="table">
        ///     <item>
        ///         <term>offset</term>
        ///         <description>offset of first word of the file coded by P1 P2 (WORDS) to be erased.</description>
        ///     </item>
        ///     <item>
        ///         <term>length</term>
        ///         <description>number of words to be erased.</description>
        ///     </item>
        /// </list>
        /// </summary>
        /// <param name="apdu"></param>
        /// <returns></returns>
        private IFakeCardFeedback ProcessErase(CommandAPDU apdu)
        {
            // TODO: check ==> security of current EF

            byte[] apduBuffer = apdu.GetBuffer();
            apdu.SetIncomingAndReceive();

            // Check if Lc ==2
            short lc = APDUHelpers.getIncomingLength(apdu);

            if (lc != 2)
            {
                ISOException.throwIt(JavaCard.ISO7816.SW_WRONG_LENGTH);
            }

            short offset    = Util.getShort(apduBuffer, JavaCard.ISO7816.OFFSET_P1); // in WORDS
            short udcOffset = APDUHelpers.getOffsetCdata(apdu);
            short length    = Util.getShort(apduBuffer, udcOffset);                  // in WORDS

            VerifyOutOfFile(offset, length);

            _currentEF.Erase(offset, length);

            return(FakeCardFeedback.FromSuccess(unchecked ((short)0x9000)));
        }
        /// <inheritdoc />
        public IFakeCardFeedback ExecuteCommand(CommandAPDU cApdu)
        {
            if (cApdu.BinaryCommand.Length < 5)
            {
                return(FakeCardFeedback.FromError(ErrorCode.CommDataLost));
            }

            if (cApdu.IsCc2 && cApdu.Cla == 0x00 && cApdu.Ins == 0xC0)
            {
                return(ProcessGetResponse(cApdu));
            }

            ClearUdrToBeRetrieved();

            IFakeCardFeedback response;

            try
            {
                response = _fakeCard.ExecuteCommand(cApdu);
            }
            catch (ISOException isoException)
            {
                return(FakeCardFeedback.FromSuccess(isoException.getReason()));
            }

            if (response.RApdu.Udr.Length == 0 || cApdu.IsCc2)
            {
                return(response);
            }

            StoreUdrToBeRetrieved(response.RApdu.Udr, cApdu.Ins);

            return(FakeCardFeedback.FromSuccess((short)response.RApdu.StatusWord));
        }
        /// <summary>
        /// process a GET RESPONSE command after a successful FSEARCH.
        /// </summary>
        /// <param name="cApdu"></param>
        /// <returns></returns>
        private IFakeCardFeedback ProcessGetResponseAfterFSearch(CommandAPDU cApdu)
        {
            if (cApdu.Le != 0x08)
            {
                return(FakeCardFeedback.FromSuccess(JavaCard.ISO7816.SW_WRONG_LENGTH));
            }

            var rApduBytes = GetRApduBytesWithRetrievedUdr((short)cApdu.Le);

            ClearUdrToBeRetrieved();

            return(FakeCardFeedback.FromSuccess(rApduBytes));
        }
Example #4
0
        public IFakeCardFeedback setOutgoingAndSend(short offset, short length)
        {
            _offset = offset;
            _length = length;

            Util.setShort(_buffer, (short)(_offset + _length), unchecked ((short)0x9000));
            _length += 2;

            var responseBytes = new byte[_length];

            Array.Copy(_buffer, _offset, responseBytes, 0, _length);

            return(FakeCardFeedback.FromSuccess(responseBytes));
        }
        /// <summary>
        /// Sends len more bytes from outData byte array starting at specified offset bOff.
        /// </summary>
        /// <param name="_"></param>
        /// <param name="buffer">Source data byte array.</param>
        /// <param name="offset">Offset into OutData array.</param>
        /// <param name="length">Byte length of the data to send.</param>
        /// <returns></returns>
        public static IFakeCardFeedback SendBytesLong(this ICardCommand _, byte[] buffer, short offset, short length)
        {
            _offset = offset;
            _length = length;

            Array.Copy(buffer, offset, _buffer, 0, _length);

            Util.setShort(_buffer, bOff: (short)(_offset + _length), unchecked ((short)0x9000));
            _length += 2;

            var responseBytes = new byte[_length];

            Array.Copy(_buffer, _offset, responseBytes, 0, _length);

            return(FakeCardFeedback.FromSuccess(responseBytes));
        }
Example #6
0
        public IFakeCardFeedback ExecuteCommand(CommandAPDU cApdu)
        {
            if (cApdu.Cla != 0x00)
            {
                return(FakeCardFeedback.FromSuccess(StatusWord.ClaNotSupported));
            }

            switch (cApdu.Ins)
            {
            case Constants.INS_CREATE_FILE:
                return(ProcessCreateFile(cApdu));

            case Constants.INS_DELETE_FILE:
                return(ProcessDeleteFile(cApdu));

            case Constants.INS_ERASE:
                return(ProcessErase(cApdu));

            case Constants.INS_FSEARCH:
                return(ProcessFSearch(cApdu));

            case Constants.INS_GENERATE_RANDOM:
                return(ProcessGenerateRandom(cApdu));

            case Constants.INS_READ_BINARY:
                return(ProcessRead(cApdu));

            case Constants.INS_SELECT:
                return(ProcessSelect(cApdu));

            case Constants.INS_WRITE_BINARY:
                return(ProcessWrite(cApdu));

            default:
                return(FakeCardFeedback.FromSuccess(StatusWord.InsNotSupported));
            }
        }
Example #7
0
        /// <summary>
        /// Process WRITE BINARY instruction (CC3)
        /// <para>
        /// C-APDU: <code>00 B0 {offset} {Lc} {data} </code>
        /// </para>
        /// <list type="table">
        ///     <item>
        ///         <term>offset</term>
        ///         <description>offset of first word of the file coded by P1 P2 (WORDS) to be written.</description>
        ///     </item>
        ///     <item>
        ///         <term>data</term>
        ///         <description>data to be written in file.</description>
        ///     </item>
        /// </list>
        /// </summary>
        /// <param name="apdu"></param>
        /// <returns></returns>
        private IFakeCardFeedback ProcessWrite(CommandAPDU apdu)
        {
            // TODO: check ==> security of current EF

            byte[] apduBuffer = apdu.GetBuffer();
            apdu.SetIncomingAndReceive();

            short offset    = Util.getShort(apduBuffer, JavaCard.ISO7816.OFFSET_P1); // in WORDS
            short length    = APDUHelpers.getIncomingLength(apdu);                   // in BYTES
            short wordCount = (short)((short)(length + 3) / 4);                      // length in WORDS

            // availability check
            VerifyOutOfFile(offset, wordCount);
            if (!_currentEF.IsAvailable(offset, wordCount))
            {
                ISOException.throwIt(JavaCard.ISO7816.SW_WRONG_LENGTH);
            }

            // copy data in a buffer
            byte[] buffer    = JCSystem.makeTransientByteArray((short)(wordCount * 4), JCSystem.CLEAR_ON_DESELECT);
            short  udcOffset = APDUHelpers.getOffsetCdata(apdu);

            Util.arrayCopyNonAtomic(apduBuffer, udcOffset, buffer, 0, length);

            // complete words with FF in buffer
            short iMax = (short)(wordCount * 4);

            for (short i = length; i < iMax; i++)
            {
                buffer[i] = 0xFF;
            }

            // and write data to file
            _currentEF.Write(buffer, 0, offset, wordCount);

            return(FakeCardFeedback.FromSuccess(unchecked ((short)0x9000)));
        }
        /// <summary>
        /// Process a GET RESPONSE command.
        /// </summary>
        /// <param name="cApdu"></param>
        /// <returns></returns>
        private IFakeCardFeedback ProcessGetResponse(CommandAPDU cApdu)
        {
            if (cApdu.P1 != 0x00 || cApdu.P2 != 0x00)
            {
                return(FakeCardFeedback.FromSuccess(JavaCard.ISO7816.SW_WRONG_P1P2));
            }

            if (_udrWaitingToBeRetrieved == null)
            {
                return(FakeCardFeedback.FromSuccess(unchecked ((short)0x9010)));
            }

            switch (_lastInsProcessed)
            {
            case JavaCard.ISO7816.INS_SELECT:
                return(ProcessGetResponseAfterSelect(cApdu));

            case Constants.INS_FSEARCH:
                return(ProcessGetResponseAfterFSearch(cApdu));

            default:
                return(FakeCardFeedback.FromSuccess(unchecked ((short)0x9010)));
            }
        }