/// <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)); }
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)); }
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)); } }
/// <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))); } }