Example #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));
        }
Example #2
0
        /// <summary>
        /// Process the GET CHALLENGE of an EMV transaction.
        /// </summary>
        /// <returns>Last status word.</returns>
        public UInt16 GetChallenge()
        {
            BeforeGetChallengeEvent.Raise(this, new EmvEventArgs());

            // Clear previous challenge
            _iccChallenge = null;

            // Execute GET CHALLENGE
            var cAPDU = new CommandAPDU(0x00, 0x84, 0x00, 0x00, 0);
            var crp   = new CommandResponsePair(cAPDU);

            crp.Transmit(_cardChannel);
            _lastStatusWord = crp.RApdu.StatusWord;

            // If GET RESPONSE needed, do it
            if (crp.RApdu.Sw1 == 0x61)
            {
                crp             = new CommandResponsePair(new GetResponseCommand(crp.RApdu.Sw2));
                _lastStatusWord = crp.RApdu.StatusWord;
            }

            // Finally, store result
            if (crp.RApdu.StatusWord == 0x9000)
            {
                _iccChallenge = crp.RApdu.Udr;
            }

            AfterGetChallengeEvent.Raise(this, new EmvEventArgs());

            return(_lastStatusWord);
        }
Example #3
0
        /// <summary>
        /// Process the VERIFY PIN phase of an EMV transaction.
        /// </summary>
        /// <param name="pinBlock">PIN Block.</param>
        /// <returns>Last status word.</returns>
        public UInt16 VerifyPin(PINBlock pinBlock)
        {
            BeforeVerifyPinEvent.Raise(this, new EmvEventArgs());

            byte p2 = 0x00;

            if (pinBlock is PlaintextPINBlock)
            {
                p2 = 0x80;
            }

            // Execute the VERIFY instruction
            var cAPDU = new CommandAPDU(0x00, 0x20, 0x00, p2, (UInt32)pinBlock.PinBlock.Length, pinBlock.PinBlock);
            var crp   = new CommandResponsePair(cAPDU);

            crp.Transmit(_cardChannel);
            _lastStatusWord      = crp.RApdu.StatusWord;
            _verifyPinStatusWord = _lastStatusWord;

            if (_lastStatusWord != 0x9000)
            {
                Tvr.CardholderVerificationFailed = true;
            }

            AfterVerifyPinEvent.Raise(this, new EmvEventArgs());

            return(_lastStatusWord);
        }
        /// <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));
        }
Example #5
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)));
        }
Example #6
0
        private void TransmitToCard(CommandAPDU command)
        {
            try
            {
                var crp       = new CommandResponsePair(command);
                var errorCode = crp.Transmit(SharedData.CardChannel);

                if (errorCode != ErrorCode.Success)
                {
                    LogFailure($"ErrorCode={errorCode}");
                }
                else if (crp.RApdu.StatusWord != 0x9000)
                {
                    LogFailure($"SW={crp.RApdu.StatusWord:X4}");
                }
                else
                {
                    LogSuccess();
                }
            }
            catch (Exception exception)
            {
                LogException(exception);
            }
        }
Example #7
0
        private static void ExecuteCrpFSearch(short offset)
        {
            PrintHeader($"FSEARCH @{offset:X4}");

            var cApdu = new CommandAPDU($"00A0{offset:X4}00");

            ExecuteCrp(cApdu);
        }
Example #8
0
        private static void ExecuteCrpErase(short offset, short length)
        {
            PrintHeader($"ERASE {length:X4} word(s) @{offset:X4}");

            var cApdu = new CommandAPDU($"000E{offset:X4}02{length:X4}");

            ExecuteCrp(cApdu);
        }
Example #9
0
        private static void ExecuteCrpGenerateRandom()
        {
            PrintHeader("GENERATE RANDOM");

            var cApdu = new CommandAPDU(0x00, 0xC4, 0x00, 0x00, 0x08);

            ExecuteCrp(cApdu);
        }
Example #10
0
        private static void ExecuteCrpGetResponse(byte le)
        {
            PrintHeader($"GET RESPONSE {le:X4} bytes");

            var cApdu = new CommandAPDU($"00C00000{le:X2}");

            ExecuteCrp(cApdu);
        }
Example #11
0
        private static void ExecuteCrpRead(short offset, byte le)
        {
            PrintHeader($"READ {le:X2} word(s) @{offset:X4}");

            var cApdu = new CommandAPDU($"00B0{offset:X4}{le:X2}");

            ExecuteCrp(cApdu);
        }
Example #12
0
        /// <summary>
        /// MasterCard cAPDU.
        /// Process the COMPUTE CRYPTOGRAPHIC CHECKSUM phase of a MasterCard transaction.
        /// </summary>
        /// <returns>Last status word.</returns>
        public UInt16 ComputeCryptographicChecksum()
        {
            BeforeComputeCryptographicChecksumEvent.Raise(this, new EmvEventArgs());

            // If UDOL 9F69 is not supplied in records, then use default UDOL = 9F6A04
            byte[] udolDataValue = null;
            var    tlvAll        = new List <TlvData>();

            foreach (var record in _tlvRecords)
            {
                tlvAll.Add(record);
                if (record.HasTag(0x9F69))
                {
                    var udol = new DataObjectList(record.GetTag(0x9F69).Value);
                    tlvAll.AddRange(TlvTerminalData);
                    udolDataValue = udol.BuildData(tlvAll);
                }
            }

            if (udolDataValue == null)
            {
                var tmp        = "";
                var seed       = new Random(10000).Next();
                var rndNumbers = new Random(seed);
                for (var i = 0; i < 8; i++)
                {
                    var rndNumber = rndNumbers.Next(10);
                    tmp += rndNumber.ToString(CultureInfo.InvariantCulture);
                }
                udolDataValue = tmp.FromHexa();
            }

            // Execute COMPUTE CRYPTOGRAPHIC CHECKSUM
            var cAPDU = new CommandAPDU(0x80, 0x2A, 0x8E, 0x80, (uint)udolDataValue.Length, udolDataValue, 0);
            var crp   = new CommandResponsePair(cAPDU);

            crp.Transmit(_cardChannel);
            _lastStatusWord = crp.RApdu.StatusWord;

            // If GET RESPONSE needed, do it
            if (crp.RApdu.Sw1 == 0x61)
            {
                _tlvCryptographicChecksum = new TlvData();
                crp = new CommandResponsePair(new GetResponseCommand(crp.RApdu.Sw2));
                crp.Transmit(_cardChannel);
                _lastStatusWord = crp.RApdu.StatusWord;
            }

            // Finally, store result
            if (crp.RApdu.StatusWord == 0x9000)
            {
                _tlvCryptographicChecksum = new TlvData(crp.RApdu.Udr);
            }

            AfterComputeCryptographicChecksumEvent.Raise(this, new EmvEventArgs());

            return(_lastStatusWord);
        }
Example #13
0
        private static void ExecuteCrpCreateFile(string fileIdentifier, string fileControlInformation)
        {
            PrintHeader($"CREATE FILE {fileIdentifier}");

            var lc    = $"{(fileIdentifier.Length + fileControlInformation.Length) / 2:X2}";
            var cApdu = new CommandAPDU($"00E00040{lc}{fileIdentifier}{fileControlInformation}");

            ExecuteCrp(cApdu);
        }
Example #14
0
        private static void ExecuteCrpDeleteFile(string fileIdentifier)
        {
            PrintHeader($"DELETE FILE {fileIdentifier}");

            var lc    = $"{fileIdentifier.Length / 2:X2}";
            var cApdu = new CommandAPDU($"00E40040{lc}{fileIdentifier}");

            ExecuteCrp(cApdu);
        }
Example #15
0
        private void selectApplet()
        {
            myReader = new Reader();
            myReader.Connect(read);

            apdu    = new CommandAPDU(0x00, 0xA4, 0x04, 0x00, AID, (byte)AID.Length);
            resApdu = myReader.Transmit(apdu);
            reponse_texBox.AppendText(resApdu.SW1.ToString("X2") + resApdu.SW2.ToString("X2"));
        }
Example #16
0
        private static void ExecuteCrpWrite(short offset, string udc)
        {
            var lc = udc.Length / 2;

            PrintHeader($"WRITE {lc:X2} word(s) @{offset:X4}");

            var cApdu = new CommandAPDU($"00D0{offset:X4}{lc:X2}{udc}");

            ExecuteCrp(cApdu);
        }
Example #17
0
        public void GenerateRandomWithWrongLeShouldFail(int le)
        {
            var fakeCard = CreateFakeCard();

            var generateRandomApdu       = new CommandAPDU($"00 C4 00 00 {le:X2}");
            var feedbackToGenerateRandom = fakeCard.ExecuteCommand(generateRandomApdu);

            Assert.AreEqual(ErrorCode.Success, feedbackToGenerateRandom.ErrorCode);
            Assert.AreEqual(0x6700, feedbackToGenerateRandom.RApdu.StatusWord);
            Assert.AreEqual(0, feedbackToGenerateRandom.RApdu.Udr.Length);
        }
Example #18
0
        private ResponseAPDU Transmit(CommandAPDU commandAdpu, int bufferSize)
        {
            if (commandAdpu == null)
            {
                throw new ArgumentNullException(nameof(commandAdpu));
            }

            var result = _connection.Transmit(commandAdpu.Adpu, bufferSize);

            return(new ResponseAPDU(result));
        }
Example #19
0
        private ResponseAPDU SendCommand(BeIDCommandAPDU command, int p1, int p2, int le)
        {
            if (command == null)
            {
                throw new ArgumentNullException(nameof(command));
            }

            var commandAdpu = new CommandAPDU(command.Cla, command.Ins, p1, p2, le);

            return(Transmit(commandAdpu, BUFFER_SIZE));
        }
Example #20
0
        public void GenerateRandomWithRightLeShouldSucceed()
        {
            var fakeCard = CreateFakeCard();

            var generateRandomApdu       = new CommandAPDU($"00 C4 00 00 08");
            var feedbackToGenerateRandom = fakeCard.ExecuteCommand(generateRandomApdu);

            Assert.AreEqual(ErrorCode.Success, feedbackToGenerateRandom.ErrorCode);
            Assert.AreEqual(0x9000, feedbackToGenerateRandom.RApdu.StatusWord);
            Assert.AreEqual(8, feedbackToGenerateRandom.RApdu.Udr.Length);
        }
Example #21
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))));
        }
Example #22
0
        /// <summary>
        /// Process the INTERNAL AUTHENTICATION of an EMV transaction.
        /// </summary>
        /// <param name="unpredictableNumber">Unpredictable number.</param>
        /// <returns>Last status word.</returns>
        public UInt16 InternalAuthenticate(byte[] unpredictableNumber)
        {
            BeforeInternalAuthenticateEvent.Raise(this, new EmvEventArgs());

            _tlvInternalAuthenticateUnpredictableNumber = new TlvData(0x9F37, 0x04, unpredictableNumber);

            // Build DDOL data
            byte[] ddolDataValue;
            if (Ddol != null)
            {
                // Use DDOL to build data
                var tlvAll = new List <TlvData>
                {
                    TlvFci,
                    TlvProcessingOptions,
                    _tlvInternalAuthenticateUnpredictableNumber
                };
                tlvAll.AddRange(TlvRecords);
                tlvAll.AddRange(TlvTerminalData);
                ddolDataValue = Ddol.BuildData(tlvAll);
            }
            else
            {
                ddolDataValue = new byte[0];
            }

            // Execute GET PROCESSING OPTIONS
            var cAPDU = new CommandAPDU(0x00, 0x88, 0x00, 0x00, (uint)ddolDataValue.Length, ddolDataValue, 0);
            var crp   = new CommandResponsePair(cAPDU);

            crp.Transmit(_cardChannel);
            _lastStatusWord = crp.RApdu.StatusWord;

            // If GET RESPONSE needed, do it
            if (crp.RApdu.Sw1 == 0x61)
            {
                _tlvSignedDynamicApplicationResponse = new TlvData();
                crp = new CommandResponsePair(new GetResponseCommand(crp.RApdu.Sw2));
                crp.Transmit(_cardChannel);
                _lastStatusWord = crp.RApdu.StatusWord;
            }

            // Finally, store result
            if (crp.RApdu.StatusWord == 0x9000)
            {
                _tlvSignedDynamicApplicationResponse = new TlvData(crp.RApdu.Udr);
            }

            AfterInternalAuthenticateEvent.Raise(this, new EmvEventArgs());

            return(_lastStatusWord);
        }
        /// <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 #24
0
        /// <summary>
        /// Process the GET PROCESSING OPTIONS phase of an EMV transaction.
        /// </summary>
        /// <returns>Last status word.</returns>
        public UInt16 GetProcessingOptions()
        {
            BeforeGetProcessingOptionsEvent.Raise(this, new EmvEventArgs());

            // If PDOL 9F38 is not supplied in FCI, then used 8300 as UDC; if supplied: build the PDOL in tag 83 L V
            byte[] pdolDataValue;
            if (TlvFci.HasTag(0x9F38))
            {
                // Use PDOL to build tag 83 value
                var pdol   = new DataObjectList(TlvFci.GetTag(0x9F38).Value);
                var tlvAll = new List <TlvData> {
                    TlvFci
                };
                tlvAll.AddRange(TlvTerminalData);
                pdolDataValue = pdol.BuildData(tlvAll);
            }
            else
            {
                pdolDataValue = new byte[0];
            }
            // Build tag 83 with computed value
            var tlvPdolData = new TlvData(0x83, (uint)pdolDataValue.Length, pdolDataValue);

            // Execute GET PROCESSING OPTIONS
            var cAPDU = new CommandAPDU(0x80, 0xA8, 0x00, 0x00, tlvPdolData.Length + 2, tlvPdolData.ToByteArray(), 0);
            var crp   = new CommandResponsePair(cAPDU);

            crp.Transmit(_cardChannel);

            _lastStatusWord = crp.RApdu.StatusWord;

            // If GET RESPONSE needed, do it
            if (crp.RApdu.Sw1 == 0x61)
            {
                _tlvProcessingOptions = new TlvData();

                crp = new CommandResponsePair(new GetResponseCommand(crp.RApdu.Sw2));
                crp.Transmit(_cardChannel);
                _lastStatusWord = crp.RApdu.StatusWord;
            }

            // Finally, store result
            if (crp.RApdu.StatusWord == 0x9000)
            {
                _tlvProcessingOptions = new TlvData(crp.RApdu.Udr);
            }

            AfterGetProcessingOptionsEvent.Raise(this, new EmvEventArgs());

            return(_lastStatusWord);
        }
Example #25
0
        public void ReadMFShouldSucceed()
        {
            var fakeCard = CreateFakeCard();

            var readApdu       = new CommandAPDU("00 B0 00 00 40");
            var feedbackToRead = fakeCard.ExecuteCommand(readApdu);

            Assert.AreEqual(ErrorCode.Success, feedbackToRead.ErrorCode);
            Assert.AreEqual(0x9000, feedbackToRead.RApdu.StatusWord);
            var filler = new byte[0x40 - 24];

            Array.Fill(filler, (byte)0xFF);
            Assert.AreEqual($"17 FF 06 E4 1F 6C 05 70 0E 2F F5 CE 0E 10 03 DF 7F 00 00 22 FF FF FE 62 {filler.ToHexa()}", feedbackToRead.RApdu.Udr.ToHexa());
        }
Example #26
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));
        }
Example #27
0
        private ResponseAPDU SendCommand(BeIDCommandAPDU command, byte[] data)
        {
            if (command == null)
            {
                throw new ArgumentNullException(nameof(command));
            }

            if (data == null)
            {
                throw new ArgumentNullException(nameof(data));
            }

            var commandAdpu = new CommandAPDU(command.Cla, command.Ins, command.P1, command.P2, data);

            return(Transmit(commandAdpu, BUFFER_SIZE));
        }
Example #28
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));
        }
Example #29
0
        public void FSearchInMasterFileShouldFindFreeWordAt0035(int searchOffset, string expectedFoundOffset)
        {
            var fakeCard = CreateFakeCard();

            var fSearchApdu       = new CommandAPDU($"00 A0 {searchOffset:X4} 00");
            var feedbackToFSearch = fakeCard.ExecuteCommand(fSearchApdu);

            Assert.AreEqual(ErrorCode.Success, feedbackToFSearch.ErrorCode);
            Assert.AreEqual(0x9000, feedbackToFSearch.RApdu.StatusWord);
            Assert.AreEqual(0, feedbackToFSearch.RApdu.Udr.Length);

            var getResponseApdu       = new CommandAPDU("00 C0 00 00 08");
            var feedbackToGetResponse = fakeCard.ExecuteCommand(getResponseApdu);

            Assert.AreEqual(ErrorCode.Success, feedbackToGetResponse.ErrorCode);
            Assert.AreEqual(0x9000, feedbackToGetResponse.RApdu.StatusWord);
            Assert.AreEqual($"{expectedFoundOffset} 02 9F FF FF FF FF", feedbackToGetResponse.RApdu.Udr.ToHexa());
        }
Example #30
0
        public void SelectMFWithWrongLeShouldFailOnGetResponse(int le)
        {
            var fakeCard = CreateFakeCard();

            var selectApdu       = new CommandAPDU("00 A4 00 00 02 3F 00");
            var feedbackToSelect = fakeCard.ExecuteCommand(selectApdu);

            Assert.AreEqual(ErrorCode.Success, feedbackToSelect.ErrorCode);
            Assert.AreEqual(0x9000, feedbackToSelect.RApdu.StatusWord);
            Assert.AreEqual(0, feedbackToSelect.RApdu.Udr.Length);

            var getResponseApdu       = new CommandAPDU($"00 C0 00 00 {le:X2}");
            var feedbackToGetResponse = fakeCard.ExecuteCommand(getResponseApdu);

            Assert.AreEqual(ErrorCode.Success, feedbackToGetResponse.ErrorCode);
            Assert.AreEqual(0x6700, feedbackToGetResponse.RApdu.StatusWord);
            Assert.AreEqual(0, feedbackToGetResponse.RApdu.Udr.Length);
        }