I'm working on a C# Java Card (Smart Card) program, and I am trying to utilize the PCSC-sharp library on github.
Here's the "short / tl;dr" version of my request: The PCSC-sharp example covers Iso7816 Case2Short. Can someone either correct my examples below, or provide me an example of an Iso7816 Case3Short (Command data. No response data) and Case4Short (Command data. Expected response data)?
Here's the "long" version of my request: On the Java Card, I'm using both standard and custom APDU commands, and I can successfully invoke these commands using a python script (with the smartcard library). In other words, I have proven working Java Card commands.
My goal now is to use PCSC-sharp to perform the same commands, but I'm failing when I'm including data (i.e., APDU LC is > 0).
Here's the example on github. Note that I can use this with only changes to the reader name, the instruction (select file instead of get challenge), and Le.
var contextFactory = ContextFactory.Instance;
using (var ctx = contextFactory.Establish(SCardScope.System)) {
using (var isoReader = new IsoReader(ctx, "ACME Smartcard reader",
SCardShareMode.Shared, SCardProtocol.Any, false)) {
var apdu = new CommandApdu(IsoCase.Case2Short, isoReader.ActiveProtocol) {
CLA = 0x00, // Class
Instruction = InstructionCode.GetChallenge,
P1 = 0x00, // Parameter 1
P2 = 0x00, // Parameter 2
Le = 0x08 // Expected length of the returned data
};
var response = isoReader.Transmit(apdu);
Console.WriteLine("SW1 SW2 = {0:X2} {1:X2}", response.SW1, response.SW2);
// ..
}
}
The APDU in my version of the example translates to:
Send: 00 A4 00 00 00 00
Resp: 90 00
... which works for me and is appropriate for Case2Short (no data, no response)
What I'm trying to recreate are 2 different types of transfers:
Case3Short (Command data. No response data)
Send: 00 A4 04 00 06 01 02 03 04 05 06 00
Resp 90 00
Here's my code:
private bool SendApduCase3()
{
var success = false;
DebugWriteLine("case3 start");
using (var isoReader = new IsoReader(td.context, td.name, SCardShareMode.Shared, SCardProtocol.T1, false))
{
DebugWriteLine("case3 command");
var commandApdu = new CommandApdu(IsoCase.Case3Short, isoReader.ActiveProtocol)
{
CLA = 0x00,
INS = 0xA4,
P1 = 0x04,
P2 = 0x00,
Data = new byte[] { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06 },
Le = 0x00
};
DebugWriteLine("case3 transmit");
var response = isoReader.Transmit(commandApdu);
if ((response.SW1 == 0x90) && (response.SW2 == 0x00)) success = true;
}
DebugWriteLine("case3 " + success.ToString());
return (success);
}
... but it catches on the command and never makes it to the transmit, instead returning the following error:
System.ArgumentException:
Iso7816-4 Case3Short does not expect any data fields in its return value and therefore has no bytes for Le
at PCSC.Iso7816.CommandApdu.set_Le(Int32 value)
if = 0x00
is removed then the Command is send, but now it's getting hung up on the transmit, which is odd since there shouldn't be return data.
ReaderPresent: catch case3
PCSC.Exceptions.InsufficientBufferException: The data buffer to receive returned data is too small for the returned data."
Case4Short (Command data. Expected response data)
Send: 80 11 00 00 04
Resp: 01 02 03 04 90 00
Here's my code:
private bool SendApduCase4()
{
var success = false;
DebugWriteLine("case4 start");
using (var isoReader = new IsoReader(td.context, td.name, SCardShareMode.Shared, SCardProtocol.T1, false))
{
DebugWriteLine("case4 command");
var commandApdu = new CommandApdu(IsoCase.Case3Short, isoReader.ActiveProtocol)
{
CLA = 0x00,
INS = 0xA4,
P1 = 0x00,
P2 = 0x00,
Data = new byte[] { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06 },
Le = 0x00
};
DebugWriteLine("case4 transmit");
var response = isoReader.Transmit(commandApdu);
if (response.HasData) DebugWriteLine(response.GetData().ToString());
if ((response.SW1 == 0x90) && (response.SW2 == 0x00))
{
if (response.HasData)
{
byte[] expected = new byte[] { 0x51, 0x01, 0x02, 0x03 };
if (response.GetData() == expected) success = true;
}
}
}
DebugWriteLine("case4 " + success.ToString());
return (success);
}
... similarly, it catches on the command and never makes it to the transmit
What am I doing wrong here?
Oh and the closest answer I found in my search was here, but didn't cover what I need.