Exemplo n.º 1
0
        /// <summary>
        /// Process DELETE FILE instruction (E4)
        /// <para>
        /// C-APDU: <code>00 E4 00 00 02 {fid}</code>
        /// </para>
        /// </summary>
        /// <param name="apdu"></param>
        /// <returns></returns>
        private IFakeCardFeedback ProcessDeleteFile(CommandAPDU apdu)
        {
            byte[] buffer = apdu.GetBuffer();
            _ = apdu.SetIncomingAndReceive();

            short udcOffset = APDUHelpers.getOffsetCdata(apdu);
            short lc        = APDUHelpers.getIncomingLength(apdu);

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

            short fid = Util.getShort(buffer, udcOffset);

            if (_currentDF.DeleteFile(fid) == false)
            {
                ISOException.throwIt(JavaCard.ISO7816.SW_FILE_NOT_FOUND);
            }

            if (_currentEF != null && fid == _currentEF.GetFileId())
            {
                _currentEF = null;
            }

            return(apdu.SetOutgoingAndSend(0, 0));
        }
Exemplo n.º 2
0
        /// <summary>
        /// Process SELECT instruction (CC4).
        /// <para>
        /// C-APDU: <code>00 A4 00 00 02 {FID} {Le}</code>
        /// </para>
        /// <para>
        /// R-APDU: <code>{offset} {size} {header}</code>
        /// </para>
        /// <list type="table">
        ///     <item>
        ///         <term>offset</term>
        ///         <description>offset of first word of the file, 2 bytes (WORDS).</description>
        ///     </item>
        ///     <item>
        ///         <term>size</term>
        ///         <description>size of the body of the file (WORDS).</description>
        ///     </item>
        /// </list>
        /// </summary>
        /// <param name="apdu"></param>
        /// <returns></returns>
        private IFakeCardFeedback ProcessSelect(CommandAPDU apdu)
        {
            byte[] buffer = apdu.GetBuffer();
            apdu.SetIncomingAndReceive();

            short udcOffset = APDUHelpers.getOffsetCdata(apdu);
            short lc        = (short)apdu.Lc;

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

            short fid = Util.getShort(buffer, udcOffset);

            File file;

            if (fid == 0x3F00)
            {
                file = _masterFile;
            }
            else
            {
                file = _currentDF.FindFileByFileId(fid);
            }

            if (file == null)
            {
                ISOException.throwIt(JavaCard.ISO7816.SW_FILE_NOT_FOUND);
            }

            // Update current DF / EF
            if (file.IsDF())
            {
                _currentDF = (DedicatedFile)file;
                _currentEF = null;
            }
            else
            {
                _currentEF = (ElementaryFile)file;
            }

            // Build and send R-APDU
            short headerSize = file.GetHeaderSize();

            Util.setShort(buffer, 0, (short)(file._inParentBodyOffset >> 2));
            Util.setShort(buffer, 2, (short)(file.GetLength() - headerSize));
            file.GetHeader(buffer, 4);

            // TODO Automagically adds 9000

            return(apdu.SetOutgoingAndSend(0, (short)(4 + (headerSize << 2))));
        }
Exemplo n.º 3
0
        /// <summary>
        /// Process FSEARCH instruction (CC2).
        /// <para>
        /// C-APDU: <code>00 B0 {P1-P2: offset} 04</code>
        /// </para>
        /// <para>
        /// R-APDU when an EF is selected: <code>{offset} {number of word in current EF} {looked-up word}</code>
        /// </para>
        /// <para>
        /// R-APDU when no EF is selected: <code>{offset} {number of word in current DF} {looked-up word}</code>
        /// </para>
        /// </summary>
        /// <param name="apdu"></param>
        /// <returns></returns>
        private IFakeCardFeedback ProcessFSearch(CommandAPDU apdu)
        {
            // get offset
            byte[] buffer = apdu.GetBuffer();
            short  offset = Util.getShort(buffer, JavaCard.ISO7816.OFFSET_P1); // in WORDS

            // get le
            short le = apdu.SetOutgoing(); // in BYTES

            if (le != 0)
            {
                ISOException.throwIt(JavaCard.ISO7816.SW_WRONG_LENGTH);
            }

            short wordCount;
            short offsetFound = offset;

            // check that there is a current EF
            if (_currentEF != null)
            {
                wordCount = (short)(_currentEF.GetLength() - _currentEF.GetHeaderSize());
                while (!(_currentEF.IsAvailable(offsetFound, 1) || offsetFound == wordCount))
                {
                    offsetFound++;
                }
            }
            else
            {
                wordCount = (short)(_currentDF.GetLength() - _currentDF.GetHeaderSize());
                while (!(_currentDF.IsAvailable(offsetFound, 1) || offsetFound == wordCount))
                {
                    offsetFound++;
                }
            }

            // check that there is still some empty space
            if (offsetFound == wordCount)
            {
                ISOException.throwIt(Constants.SW_DATA_NOT_FOUND);
            }
            // copy answer in buffer
            Util.setShort(buffer, 0, offsetFound);
            Util.setShort(buffer, 2, wordCount);
            Util.arrayFillNonAtomic(buffer, 4, 4, (byte)MemoryState.Free);

            // and send it!
            return(apdu.SetOutgoingAndSend(0, 8));
        }
Exemplo n.º 4
0
        /// <summary>
        /// Process CREATE FILE instruction (E0)
        /// <para>
        /// C-APDU: <code>00 E0 {offset} {Lc} {header}</code>
        /// </para>
        /// <list type="table">
        ///     <item>
        ///         <term>offset</term>
        ///         <description>offset of first word of the file coded by P1 P2 (WORDS).</description>
        ///     </item>
        ///     <item>
        ///         <term>header</term>
        ///         <description>header of the new file, must be word aligned.</description>
        ///     </item>
        /// </list>
        /// </summary>
        /// <param name="apdu"></param>
        /// <returns></returns>
        private IFakeCardFeedback ProcessCreateFile(CommandAPDU apdu)
        {
            byte[] buffer = apdu.GetBuffer();
            apdu.SetIncomingAndReceive();

            short headerOffset = APDUHelpers.getOffsetCdata(apdu);
            short headerLength = APDUHelpers.getIncomingLength(apdu);

            if (headerLength < 4)
            {
                ISOException.throwIt(JavaCard.ISO7816.SW_DATA_INVALID);
            }

            short offset = Util.getShort(buffer, JavaCard.ISO7816.OFFSET_P1);

            if (!_headerParser.Parse(buffer, headerOffset, (short)(headerOffset + headerLength)))
            {
                ISOException.throwIt(JavaCard.ISO7816.SW_DATA_INVALID);
            }
            short size = (short)(_headerParser.bodyLength + (short)(_headerParser.headerLength >> 2));

            File file = null;

            switch (_headerParser.fileType)
            {
            case HeaderParser.FILETYPE_DF:
                file = _currentDF.CreateDedicatedFile(offset, size, buffer, headerOffset, headerLength);
                break;

            case HeaderParser.FILETYPE_EFSZ:
            case HeaderParser.FILETYPE_EFWZ:
                file = _currentDF.CreateElementaryFile(offset, size, buffer, headerOffset, headerLength);
                break;

            default:
                ISOException.throwIt(JavaCard.ISO7816.SW_CONDITIONS_NOT_SATISFIED);
                break;
            }

            if (file == null)
            {
                ISOException.throwIt(JavaCard.ISO7816.SW_DATA_INVALID);
            }

            return(apdu.SetOutgoingAndSend(0, 0));
        }
Exemplo n.º 5
0
        /// <summary>
        /// Process GENERATE RANDOM instruction (CC2)
        /// <para>
        /// C-APDU: <code>00 C4 00 00 08</code>
        /// </para>
        /// </summary>
        /// <param name="apdu"></param>
        /// <returns></returns>
        private IFakeCardFeedback ProcessGenerateRandom(CommandAPDU apdu)
        {
            byte[] apduBuffer = apdu.GetBuffer();
            short  le         = apdu.SetOutgoing();

            // verify that Le='08'
            if (le != 8)
            {
                // if not => error
                ISOException.throwIt(JavaCard.ISO7816.SW_WRONG_LENGTH);
            }

            // generate 8 random bytes
            var rndGen = new RNGCryptoServiceProvider();

            rndGen.GetBytes(apduBuffer, 0, 8);
            // and send it!
            return(apdu.SetOutgoingAndSend(0, 8));
        }