Skip to content

Instantly share code, notes, and snippets.

@zetoken
Last active July 13, 2018 07:52
Show Gist options
  • Save zetoken/bdd06ded7cd8e1f58e06c34d72041036 to your computer and use it in GitHub Desktop.
Save zetoken/bdd06ded7cd8e1f58e06c34d72041036 to your computer and use it in GitHub Desktop.
Script used with https://github.com/zetoken/command-case-applet Java Card applet
static byte[] appletAid = "F00102030405".FromHexa();
static byte[] defaultUdc = "B1B2B3B4B5".FromHexa();
const byte Cla = 0x80;
const byte InsGetBuffer = 0xCB;
const byte InsGetLc = 0xCC;
const byte InsGetLe = 0xCE;
static CommandAPDU selectCommand = new SelectCommand(
SelectCommand.SelectionMode.SelectDFName,
SelectCommand.FileOccurrence.FirstOrOnly,
SelectCommand.FileControlInformation.ReturnFci,
appletAid
);
void Main()
{
var context = new CardContext();
context.Establish().Dump("establish");
context.ListReaders("").Dump("listReaders");
context.Readers.Dump();
try
{
ProcessCommandCase("CC1", 0xC1, context);
ProcessCommandCase("CC2", 0xC2, context);
ProcessCommandCase("CC3", 0xC3, context);
ProcessCommandCase("CC4", 0xC4, context);
}
finally
{
context.Release().Dump("release");
}
}
void ProcessCommandCase(string label, byte ins, ICardContext context)
{
var cc1 = new CommandAPDU(Cla, ins, 0x00, 0x00);
ProcessSafely(context, channel => ProcessCommand("When a CC1 is sent", cc1, channel).Dump($"CC1 sent to a {label} applet command"));
var cc2 = new CommandAPDU(Cla, ins, 0x00, 0x00, 0x40);
ProcessSafely(context, channel => ProcessCommand("When a CC2 is sent", cc2, channel).Dump($"CC2 (outgoing length: le) sent to a {label} applet command"));
if (label == "CC2" || label == "CC4")
{
var cc2WithFixedOutgoingLength = new CommandAPDU(Cla, ins, 0x01, 0x03, 0x40);
ProcessSafely(context, channel => ProcessCommand("When a CC2 is sent", cc2WithFixedOutgoingLength, channel).Dump($"CC2 (outgoing length: P2) sent to a {label} applet command"));
var cc2WithMinOutgoingLength = new CommandAPDU(Cla, ins, 0x02, 0x03, 0x40);
ProcessSafely(context, channel => ProcessCommand("When a CC2 is sent", cc2WithMinOutgoingLength, channel).Dump($"CC2 (outgoing length: min(le, P2)) sent to a {label} applet command"));
}
var cc3 = new CommandAPDU(Cla, ins, 0x00, 0x00, 0x05, defaultUdc);
ProcessSafely(context, channel => ProcessCommand("When a CC3 is sent", cc3, channel).Dump($"CC3 sent to a {label} applet command"));
var cc4 = new CommandAPDU(Cla, ins, 0x00, 0x00, (byte)defaultUdc.Length, defaultUdc, 0x40);
ProcessSafely(context, channel => ProcessCommand("When a CC4 is sent", cc4, channel).Dump($"CC4 (outgoing length: le) sent to a {label} applet command"));
if (label == "CC2" || label == "CC4")
{
var cc4WithFixedOutgoingLength = new CommandAPDU(Cla, ins, 0x01, 0x03, (byte)defaultUdc.Length, defaultUdc, 0x40);
ProcessSafely(context, channel => ProcessCommand("When a CC2 is sent", cc4WithFixedOutgoingLength, channel).Dump($"CC4 (outgoing length: P2) sent to a {label} applet command"));
var cc4WithMinOutgoingLength = new CommandAPDU(Cla, ins, 0x02, 0x03, (byte)defaultUdc.Length, defaultUdc, 0x40);
ProcessSafely(context, channel => ProcessCommand("When a CC2 is sent", cc4WithMinOutgoingLength, channel).Dump($"CC4 (outgoing length: min(le, P2)) sent to a {label} applet command"));
}
}
void ProcessSafely(ICardContext context, Action<ICardChannel> action)
{
var rawChannel = new CardChannel(context, context.Readers.First());
var channel = new CardChannelIso7816(rawChannel);
try
{
channel.Connect(ShareMode.Exclusive, Protocol.Any);
var crpSelect = new CommandResponsePair(selectCommand);
crpSelect.Transmit(channel);
action(channel);
}
catch (Exception exception)
{
exception.Dump("Something went wrong");
throw;
}
finally
{
channel.Disconnect(Disposition.UnpowerCard);
}
}
LastCommand ProcessCommand(string label, CommandAPDU capdu, ICardChannel channel)
{
var crp = new CommandResponsePair(capdu);
var status = crp.Transmit(channel);
if (status == ErrorCode.Success)
{
return new LastCommand(
channel.Protocol,
capdu,
crp.RApdu,
status,
GetLastX(InsGetBuffer, 0x40, channel),
GetLastX(InsGetLc, 0x02, channel),
GetLastX(InsGetLe, 0x02, channel)
);
}
else
{
return new LastCommand(
channel.Protocol,
capdu,
crp.RApdu,
status,
new byte[] { },
new byte[] { },
new byte[] { }
);
}
}
byte[] GetLastX(byte ins, byte le, ICardChannel channel)
{
var capdu = new CommandAPDU(Cla, ins, 0x00, 0x00, le);
var crp = new CommandResponsePair(capdu);
crp.Transmit(channel);
return crp.RApdu.Udr;
}
struct LastCommand
{
byte[] RawBuffer;
byte[] RawLc;
byte[] RawLe;
CommandAPDU rawCommand;
ResponseAPDU rawResponse;
public Protocol Protocol { get; }
public string Command => rawCommand.ToString();
public string Response => rawResponse.ToString();
public ErrorCode Status { get; }
public string Buffer => RawBuffer.ToHexa();
public string Lc => RawLc.ToHexa();
public string Le => RawLe.ToHexa();
public LastCommand(Protocol protocol, CommandAPDU command, ResponseAPDU response, ErrorCode status, byte[] buffer, byte[] lc, byte[] le)
{
Protocol = protocol;
rawCommand = command;
rawResponse = response;
Status = status;
RawBuffer = buffer;
RawLc = lc;
RawLe = le;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment