/// <summary> /// Process READ BINARY instruction (CC2) /// <para> /// C-APDU: <code>00 B0 {P1-P2: offset} {Le}</code> /// </para> /// <para> /// R-APDU when an EF is selected: <code>{data in EF}</code> /// </para> /// <para> /// R-APDU when no EF is selected: <code>{headers of EF in current DF}</code> /// </para> /// </summary> /// <param name="apdu"></param> /// <returns></returns> private IFakeCardFeedback ProcessRead(CommandAPDU apdu) { short le = apdu.SetOutgoing(); // in BYTES short wordCount = (short)((short)(le + 3) / 4); byte[] buffer = JCSystem.makeTransientByteArray((short)(wordCount * 4), JCSystem.CLEAR_ON_DESELECT); short offset; if (_currentEF != null) { // an EF is selected ==> read binary offset = Util.getShort(apdu.GetBuffer(), JavaCard.ISO7816.OFFSET_P1); // in WORDS byte[] header = JCSystem.makeTransientByteArray(8, JCSystem.CLEAR_ON_DESELECT); _currentEF.GetHeader(header, 0); _headerParser.Parse(header, 0, 8); offset += (short)(_currentEF.Read(offset, buffer, 0, wordCount, _headerParser.fileType == HeaderParser.FILETYPE_EFSZ) << 2); } else { // no EF selected ==> DIR offset = 0; byte currentChildNumber = 0; File fileChild = _currentDF.GetChild(currentChildNumber); // get header of each file in current DF while (fileChild != null && offset < le) { fileChild.GetHeader(buffer, offset); offset += (short)(fileChild.GetHeaderSize() << 2); fileChild = _currentDF.GetChild(++currentChildNumber); } } // Pad with FF Util.arrayFillNonAtomic(buffer, offset, (short)(le - offset), (byte)MemoryState.Free); // and send data! apdu.SetOutgoingLength(le); return(apdu.SendBytesLong(buffer, 0, le)); }
/// <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))); }
private void response(APDU apdu) { // static void reply(APDU apdu, sbyte a0, sbyte a1, sbyte a2, sbyte a3) //{ // var buffer = apdu.getBuffer(); // buffer[0] = a0; // buffer[1] = a1; // buffer[2] = a2; // buffer[3] = a3; // apdu.setOutgoingAndSend(0, 4); //} //upload "E:\jsc.svn\examples\java\javacard\JavacardAppletExample\JavacardAppletExample\bin\Release\web\release\JavacardAppletExample\javacard\JavacardAppletExample.cap" //upload "E:\jsc.svn\examples\java\javacard\TestjavaAppletCommunication\TestjavaAppletCommunication\bin\Release\web\release\JavacardAppletExample\javacard\JavacardAppletExample.cap" //install A0A1A2A3A40002 A0A1A2A3A4000202 //install A0A1A2A3A40003 A0A1A2A3A4000301 if (APDU.getProtocol() != APDU.PROTOCOL_MEDIA_USB) { var buffer = apdu.getBuffer(); var CLA = buffer[ISO7816Constants.OFFSET_CLA]; var INS = buffer[ISO7816Constants.OFFSET_INS]; var P1 = buffer[ISO7816Constants.OFFSET_P1]; var P2 = buffer[ISO7816Constants.OFFSET_P2]; var LC = buffer[ISO7816Constants.OFFSET_LC]; //var rets = new sbyte[5]; //rets[0] = CLA; //rets[1] = INS; //rets[2] = P1; //rets[3] = P2; //rets[4] = LC; //buffer = rets; //apdu.setOutgoingAndSend(0, (short)rets.Length); //reply(apdu, INS, P1, P2, LC); List <sbyte[]> whiteList = new List <sbyte[]>(); byte[] masterFile = new byte[] { 0x00, 0xA4, 0x00, 0x0C }; byte[] EEEEcatalogue = new byte[] { 0x00, 0xA4, 0x01, 0x0C, 0x02, 0xEE, 0xEE }; byte[] setSecEnv1 = new byte[] { 0x00, 0x22, 0xF3, 0x01 }; byte[] signatureHash = new byte[] { 0x00, 0x2a, 0x9E, 0x9A }; // Partly. Additional length and hash is provided byte[] pin1VerifyPartly = new byte[] { 0x00, 0x20, 0x00, 0x01 }; byte[] pukVerifyPartly = new byte[] { 0x00, 0x20, 0x00, 0x00 }; byte[] pin2VerifyPartly = new byte[] { 0x00, 0x20, 0x00, 0x02 }; //additional Pin2 len and Pin2 as ASCII byte[] selectFile5044 = new byte[] { 0x00, 0xa4, 0x02, 0x04 }; byte[] selectFromPersoFile = new byte[] { 0x00, 0xB2, 0x01, 0x04, 0x00 }; byte[] readPersoResponse = new byte[] { 0x00, 0xC0, 0x00, 0x00 }; whiteList.Add((sbyte[])(object)masterFile); whiteList.Add((sbyte[])(object)EEEEcatalogue); whiteList.Add((sbyte[])(object)setSecEnv1); whiteList.Add((sbyte[])(object)signatureHash); whiteList.Add((sbyte[])(object)pin1VerifyPartly); whiteList.Add((sbyte[])(object)pukVerifyPartly); whiteList.Add((sbyte[])(object)pin2VerifyPartly); whiteList.Add((sbyte[])(object)selectFile5044); //whiteList.Add((sbyte[])(object)selectFromPersoFile); whiteList.Add((sbyte[])(object)readPersoResponse); var isValid = false; foreach (var arr in whiteList) { if (arr[0] == CLA && arr[1] == INS && arr[2] == P1 && arr[3] == P2) { isValid = true; } if (CLA == selectFromPersoFile[0] && INS == selectFromPersoFile[1] && selectFromPersoFile[2] > 0x00 && selectFromPersoFile[2] > 0x10 && P2 == selectFromPersoFile[3]) { isValid = true; } } byte[] AID = { 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0x00, 0x02, 0x02 }; var casted = (sbyte[])(object)AID; var s = new AID(casted, 0, (sbyte)casted.Length); if (casted == null) { reply(apdu, 6, 6, 6, 6); return; } if (s == null) { reply(apdu, 5, 5, 5, 5); return; } if (!isValid) { reply(apdu, 2, 2, 2, 2); return; } var temp = JCSystem.getAppletShareableInterfaceObject(s, 0); if (temp == null) { reply(apdu, 1, 1, 1, 1); } else { //reply(apdu, 3, 3, 3, 3); test sio = (test)temp; var ret = sio.GetAnswerFromOtherApplet(apdu); if (sio == null) { reply(apdu, 9, 9, 9, 9); } else { if (ret != 0) { apdu.setOutgoingAndSend(0, ret); //reply(apdu, 2, 2, 2, 2); //var b = apdu.getBuffer(); //b = ret; //apdu.setOutgoingAndSend(0, (short)ret.Length); //} } else { reply(apdu, 8, 8, 8, 8); } } } } else { reply(apdu, 5, 5, 5, 5); } }