I'm going to develop SIM toolkit applet using eclipse.
I create new java card project and add sim and toolkit packages provided by 3GPP 43.019 specification
And my codes are here.
package com.example.TestPackage;
import javacard.framework.*;
import javacardx.annotations.*;
import static com.example.TestPackage.TestStkAppletStrings.*;
import sim.toolkit.*;
import sim.access.*;
/**
* Applet class
*
* #author <user>
*/
#StringPool(value = {
#StringDef(name = "Package", value = "com.example.TestPackage"),
#StringDef(name = "AppletName", value = "TestStkApplet")},
// Insert your strings here
name = "TestStkAppletStrings")
public class TestStkApplet extends Applet implements ToolkitInterface, ToolkitConstants
{
public static final byte CMD_QUALIFIER = (byte)0x80;
public static final byte MY_INSTRUCTION = (byte)0x46;
private byte[] menuEntry = {(byte)'0',(byte)'3',(byte)'.',(byte)'1',(byte)'9',(byte)' ',(byte)'A',(byte)'p',(byte)'p',(byte)'l',(byte)'e',(byte)'t'};
private byte[] menuTitle= {(byte)'M',(byte)'y',(byte)'M',(byte)'e',(byte)'n' ,(byte)'u'};
private byte[] item1 = {(byte)'I',(byte)'T',(byte)'E',(byte)'M',(byte)'1' };
private byte[] item2 = {(byte)'I',(byte)'T',(byte)'E',(byte)'M',(byte)'2' };
private byte[] item3 = {(byte)'I',(byte)'T',(byte)'E',(byte)'M',(byte)'3' };
private byte[] item4 = {(byte)'I',(byte)'T',(byte)'E',(byte)'M',(byte)'4' };
private Object[] ItemList = { item1, item2, item3, item4 };
private byte[] textDText = {(byte)'H',(byte)'e',(byte)'l',(byte)'l',(byte)'o',(byte)' ',
(byte)'w',(byte)'o',(byte)'r',(byte)'l',(byte)'d',(byte)'2'};
private byte[] baGSMAID = {(byte)0xA0, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x09, (byte)0x00, (byte)0x01};
private ToolkitRegistry reg;
private SIMView gsmFile;
private byte buffer[] = new byte[10];
private byte itemId;
private byte result;
public TestStkApplet() {
// get the GSM application reference
gsmFile = SIMSystem.getTheSIMView();
// register to the SIM Toolkit Framework
reg = ToolkitRegistry.getEntry();
// Define the applet Menu Entry and register to the EVENT_MENU_SELECTION
itemId = reg.initMenuEntry(menuEntry, (short)0x0000, (short)menuEntry.length,
PRO_CMD_DISPLAY_TEXT, false, (byte) 0x00, (short) 0x0000);
}
public static void install(byte[] bArray, short bOffset, byte bLength) {
TestStkApplet MyStkApplet = new TestStkApplet();
MyStkApplet.register();
}
#Override
public void process(APDU apdu) {
//Insert your code here
if(selectingApplet())
return;
switch(apdu.getBuffer()[1]) {
// specific APDU for this applet to configure the MenuTitle from SelectItem
case (byte)MY_INSTRUCTION:
if(apdu.setIncomingAndReceive() > (short)0) {
Util.arrayCopy(apdu.getBuffer(),(short)0x0005,menuTitle,(short)0x0000,(short)0x0006);
}
break;
default:
ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
}
}
#Override
public void processToolkit(byte event) throws ToolkitException {
EnvelopeHandler envHdlr = EnvelopeHandler.getTheHandler();
ProactiveHandler proHdlr = ProactiveHandler.getTheHandler();
ProactiveResponseHandler rspHdlr ;
boolean repeat;
switch(event) {
case EVENT_MENU_SELECTION:
// Prepare the Select Item proactive command
proHdlr.init(PRO_CMD_SELECT_ITEM,(byte)0x00,DEV_ID_ME);
// Append the Menu Title
proHdlr.appendTLV((byte) (TAG_ALPHA_IDENTIFIER | TAG_SET_CR),
menuTitle,(short)0x0000,(short)menuTitle.length);
// ask the SIM Toolkit Framework to send the proactive command and check the result
if((result = proHdlr.send()) == RES_CMD_PERF) {
rspHdlr = ProactiveResponseHandler.getTheHandler();
switch (rspHdlr.getItemIdentifier()) {
case 1:
// DisplayText High Priority
proHdlr.init(PRO_CMD_DISPLAY_TEXT, CMD_QUALIFIER,DEV_ID_DISPLAY);
proHdlr.appendTLV((byte)(TAG_TEXT_STRING| TAG_SET_CR), DCS_8_BIT_DATA,
textDText,(short)0x0000, (short)textDText.length);
proHdlr.send();
break;
}
}
break;
}
}
}
As I run it and start simulator, it returns error in creating and selecting applet.
The errors in eclipse here.
CMD>// Copyright (c) 1998, 2019, Oracle and/or its affiliates. All rights reserved.
// Applet Instantiation APDU Script
//
// Package: TestProject
// Package AID: //aid/1111111111/
// Applet: com.example.TestPackage.TestStkApplet
// Applet AID: //aid/1111111111/11
//
// Select the installer applet
0x00 0xA4 0x04 0x00 0x09 0xA0 0x00 0x00 0x00 0x62 0x03 0x01 0x08 0x01 0x7F;
APDU|CLA: 00, INS: a4, P1: 04, P2: 00, Lc: 09, a0, 00, 00, 00, 62, 03, 01, 08, 01, Le: 00, SW1: 90, SW2: 00
// Create com.example.TestPackage.TestStkApplet applet
0x80 0xB8 0x00 0x00 0x08 0x06 0x11 0x11 0x11 0x11 0x11 0x11 0x00 0x7F;
CREF|
CREF|throw_error(NULL_POINTER_EXCEPTION)
APDU|CLA: 80, INS: b8, P1: 00, P2: 00, Lc: 08, 06, 11, 11, 11, 11, 11, 11, 00, Le: 00, SW1: 64, SW2: 44
CMD>// Copyright (c) 1998, 2019, Oracle and/or its affiliates. All rights reserved.
// Applet Selection APDU Script
//
// Package: TestProject
// Package AID: //aid/1111111111/
// Applet: com.example.TestPackage.TestStkApplet
// Applet AID: //aid/1111111111/11
//
// Select com.example.TestPackage.TestStkApplet applet
0x00 0xA4 0x04 0x00 0x06 0x11 0x11 0x11 0x11 0x11 0x11 0x7F;
APDU|CLA: 00, INS: a4, P1: 04, P2: 00, Lc: 06, 11, 11, 11, 11, 11, 11, Le: 00, SW1: 6d, SW2: 00
I don't know how I fix it.
In addition, I want to ask more questions.
Simulator does not support SIM toolkit ?
What is the INS b8 means? is there any specification I can refer?
I don't know exactly how I import sim.toolkit.* and sim.access.*. please explain it in details.
Could someone explain to me?
Please let me know about it.
Related
I am using rs485 to communicate between two Arduino nano. I have connected a 4 bit I2C display to one of the Arduino nano. When the nano receives data via Rs485 from the master nano, the data is displayed on the I2C display. But the issue is that I am only able to use one of those things i.e. if I am receiving data I am not able to display it on the I2C display and if I am displaying, then I am not able to receive the data.
Has someone tried doing it together?
Code for master nano
// rs485 master
void setup() {
Serial.begin(115200);
pinMode(2,OUTPUT); //DE/RE pin
}
int i;
String s = "s1b01n01";
void loop() {
digitalWrite(2,HIGH); // high for transmiting
for(i=0;i<=8;i++) {
Serial.print(s[i]);
}
digitalWrite(2,LOW);
}
Code for Slave nano
#include <TM1637Display.h>
#define CLK 4
#define DIO 16
#define ExtEnable 2 //DE/RE pin
TM1637Display display = TM1637Display(CLK, DIO); // Create display object of type TM1637Display:
const uint8_t data[] = {0xff, 0xff, 0xff, 0xff};// Create array that turns all segments on:
const uint8_t blank[] = {0x00, 0x00, 0x00, 0x00}; // Create array that turns all segments off:
int i = 0;
char add[8], c;
char address[] = {'s', '1', 'b', '0', '1', 'n', '0', '1'};
void setup() {
Serial.begin(115200);
pinMode(ExtEnable, OUTPUT); //DE/RE pin
display.clear();
delay(1000);
display.setBrightness(7); // Set the brightness:
}
void loop() {
digitalWrite(ExtEnable, LOW); // low for receiving
if (Serial.available()) {
c = Serial.read();
Serial.print(c);
add[i] = c;
i++;
digitalWrite(ExtEnable, HIGH);
//display.showNumberDec(3); //print on display
}
Serial.print("add");
Serial.println(add);
if(add == address) { // to check
display.showNumberDec(3); //print on display
}
}
I want a button's callback method to instantiate a window (with editor) each time the button is clicked, possibly resulting in multiple windows with editors visible simultaneously. For now I would be happy if just one would appear -- it doesn't.
Comments regarding FLTK and C++ programming practice in general are also welcome.
#include <FL/Fl.H>
#include <FL/Fl_Window.H>
#include <FL/Fl_Button.H>
#include <FL/Fl_Text_Editor.H>
#include <FL/Fl_Text_Buffer.H>
class MainWin : public Fl_Window {
public:
MainWin(int w, int h, const char *title);
~MainWin();
Fl_Button* gobtn;
Fl_Text_Editor* ed; // first editor included with main window
Fl_Text_Buffer* buf;
private:
static void gomthd(Fl_Widget *, void *); // "go" method
};
class AdditionalWin : public Fl_Window { // more editors if necessary
public:
AdditionalWin(int w, int h, const char *title);
~AdditionalWin();
Fl_Text_Editor *ed;
Fl_Text_Buffer *buf;
};
int main () {
MainWin win(105, 405, "main");
return Fl::run();
}
MainWin::MainWin(int w, int h, const char* title):Fl_Window(w,h,title) {
gobtn = new Fl_Button(8, 38, 35, 20, "go");
gobtn->callback(gomthd, this);
ed = new Fl_Text_Editor(6, 67, 93, 331);
buf = new Fl_Text_Buffer();
ed->buffer(buf);
end();
resizable(this);
show();
}
AdditionalWin::AdditionalWin(int w, int h, const char *title):Fl_Window(w, h, title) {
ed = new Fl_Text_Editor(6, 67, 93, 331);
buf = new Fl_Text_Buffer();
ed->buffer(buf);
end();
resizable(this);
show();
}
void MainWin::gomthd(Fl_Widget* o, void* v) {
AdditionalWin awin(105, 405, "more");
awin.position(1, 1);
awin.show(); // ??? nothing appears
}
MainWin::~MainWin(){}
AdditionalWin::~AdditionalWin(){}
Very late to the party but still: I think the new window never shows, because awin, being a local variable, gets destroyed as soon as the MainWin::gomthd() function returns.
CMD>// Applet Instantiation APDU Script
//
// Package: cryptoPack
// Package AID: //aid/A000000062/03010C01
// Applet: CryptoDES
// Applet AID: //aid/A000000062/03010C0101
//
// Select the installer applet
0x00 0xA4 0x04 0x00 0x09 0xA0 0x00 0x00 0x00 0x62 0x03 0x01 0x08 0x01 0x7F;
APDU|CLA: 00, INS: a4, P1: 04, P2: 00, Lc: 09, a0, 00, 00, 00, 62, 03, 01, 08, 01, Le: 00, SW1: 90, SW2: 00
// Create CryptoDES applet
0x80 0xB8 0x00 0x00 0x0C 0x0A 0xA0 0x00 0x00 0x00 0x62 0x03 0x01 0x0C 0x01 0x01 0x00 0x7F;
APDU|CLA: 80, INS: b8, P1: 00, P2: 00, Lc: 0c, 0a, a0, 00, 00, 00, 62, 03, 01, 0c, 01, 01, 00, Le: 00, SW1: 64, SW2: 44
I tested this code from Java Card DES generator applet output is different from online-tools output. And my test environment is eclipse and java card platform.
I compiled CryptoDES.java as Java Card Project. And first, I operated cap-cryptoPack script. Next, create-cryptoPack.CryptoDES script.
But, as above console, Sample_Device returned 0x6444. I don't know problem. Please help me.
package cryptoPack;
import javacard.framework.APDU;
import javacard.framework.Applet;
import javacard.framework.ISO7816;
import javacard.framework.ISOException;
import javacard.framework.JCSystem;
import javacard.framework.Util;
import javacard.security.CryptoException;
import javacard.security.DESKey;
import javacard.security.KeyBuilder;
import javacardx.crypto.Cipher;
public class CryptoDES extends Applet {
// Array for the encryption/decryption key
private byte[] TheDES_Key = { (byte) 0x00, (byte) 0x00, (byte) 0x00,
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
(byte) 0x00 };
// Defining required Keys
DESKey MyDES1Key = (DESKey) KeyBuilder.buildKey(KeyBuilder.TYPE_DES,
KeyBuilder.LENGTH_DES, false);
DESKey MyDES2Key = (DESKey) KeyBuilder.buildKey(KeyBuilder.TYPE_DES,
KeyBuilder.LENGTH_DES3_2KEY, false);
DESKey MyDES3Key = (DESKey) KeyBuilder.buildKey(KeyBuilder.TYPE_DES,
KeyBuilder.LENGTH_DES3_3KEY, false);
byte ConfiguredKeyLength;
// Defining required cipher
Cipher MyCipher;
// Defining switch case variables for supported instructions = INS in APDU command
final byte SetKey = (byte) 0xC0;
final byte OneKeyDES = (byte) 0xC1;
final byte TwoKeyDES = (byte) 0xC2;
final byte ThreeKeyDES = (byte) 0xC3;
// Defining switch case variables for cipher algorithms = P1 in APDU command
final byte DES_CBC_ISO9797_M1 = (byte) 0x00;
final byte DES_CBC_ISO9797_M2 = (byte) 0x01;
final byte DES_CBC_NOPAD = (byte) 0x02;
final byte DES_CBC_PKCS5 = (byte) 0x03;
final byte DES_ECB_ISO9797_M1 = (byte) 0x04;
final byte DES_ECB_ISO9797_M2 = (byte) 0x05;
final byte DES_ECB_NOPAD = (byte) 0x06;
final byte DES_ECB_PKCS5 = (byte) 0x07;
// Defining Proprietary Status Words
final short KeyInNotSetGood = 0x6440;
// A flag to be sure that the configured key has the same length that the
// algorithm needs.
private CryptoDES() {
}
public static void install(byte bArray[], short bOffset, byte bLength)
throws ISOException {
new CryptoDES().register();
}
public void process(APDU apdu) throws ISOException {
// Assigning 0 to "ConfiguredKeyLength" to force the user to use ...
// ... "SetKey" command, after applet selection.
if (selectingApplet()) {
ConfiguredKeyLength = 0;
return;
}
byte[] buffer = apdu.getBuffer();
// Checking the CLA field in the APDU command.
if (buffer[ISO7816.OFFSET_CLA] != 0) {
ISOException.throwIt(ISO7816.SW_CLA_NOT_SUPPORTED);
}
// Checking the P1 and P2 fields in the APDU command.
if (buffer[ISO7816.OFFSET_P1] > 7 || buffer[ISO7816.OFFSET_P2] > 1) {
ISOException.throwIt(ISO7816.SW_INCORRECT_P1P2);
}
// Analyzing the command.
try {
switch (buffer[ISO7816.OFFSET_INS]) {
case SetKey:
SetCryptoKeyAndInitCipher(apdu);
break;
case OneKeyDES:
OneKeyDESCrypto(apdu);
DoEncryptDecrypt(apdu);
break;
case TwoKeyDES:
TwoKeyDESCrypto(apdu);
DoEncryptDecrypt(apdu);
break;
case (byte) ThreeKeyDES:
ThreeKeyDESCrypto(apdu);
DoEncryptDecrypt(apdu);
break;
default:
ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
}
} catch (CryptoException e) {
ISOException.throwIt(((CryptoException) e).getReason());
}
}
public void SetCryptoKeyAndInitCipher(APDU apdu)
throws ISOException {
byte[] buffer = apdu.getBuffer();
// Key must has a length of 8, 16 or 24 bytes
if (buffer[ISO7816.OFFSET_LC] == 8 || buffer[ISO7816.OFFSET_LC] == 16
|| buffer[ISO7816.OFFSET_LC] == 24) {
Util.arrayCopyNonAtomic(buffer, ISO7816.OFFSET_CDATA, TheDES_Key,
(short) 0, buffer[ISO7816.OFFSET_LC]);
ConfiguredKeyLength = buffer[ISO7816.OFFSET_LC];
} else {
ISOException.throwIt(ISO7816.SW_DATA_INVALID);
}
switch (buffer[ISO7816.OFFSET_P1]) {
case DES_CBC_ISO9797_M1:
MyCipher = Cipher.getInstance(Cipher.ALG_DES_CBC_ISO9797_M1, false);
break;
case DES_CBC_ISO9797_M2:
MyCipher = Cipher.getInstance(Cipher.ALG_DES_CBC_ISO9797_M2, false);
break;
case DES_CBC_NOPAD:
MyCipher = Cipher.getInstance(Cipher.ALG_DES_CBC_NOPAD, false);
break;
case DES_CBC_PKCS5:
MyCipher = Cipher.getInstance(Cipher.ALG_DES_CBC_PKCS5, false);
break;
case DES_ECB_ISO9797_M1:
MyCipher = Cipher.getInstance(Cipher.ALG_DES_ECB_ISO9797_M1, false);
break;
case DES_ECB_ISO9797_M2:
MyCipher = Cipher.getInstance(Cipher.ALG_DES_ECB_ISO9797_M2, false);
break;
case DES_ECB_NOPAD:
MyCipher = Cipher.getInstance(Cipher.ALG_DES_ECB_NOPAD, false);
break;
case DES_ECB_PKCS5:
MyCipher = Cipher.getInstance(Cipher.ALG_DES_ECB_PKCS5, false);
break;
}
}
public void OneKeyDESCrypto(APDU apdu)
throws ISOException {
byte[] buffer = apdu.getBuffer();
// Check to see if the configured key is the required key for this ...
// ... algorithm or not
if (ConfiguredKeyLength != 8) {
ISOException.throwIt(KeyInNotSetGood);
}
MyDES1Key.setKey(TheDES_Key, (short) 0);
if (buffer[ISO7816.OFFSET_P2] == 1) {
MyCipher.init(MyDES1Key, Cipher.MODE_ENCRYPT);
} else {
MyCipher.init(MyDES1Key, Cipher.MODE_DECRYPT);
}
}
public void TwoKeyDESCrypto(APDU apdu)
throws ISOException {
byte[] buffer = apdu.getBuffer();
// Check to see if the configured key is the required key for this ...
// ... algorithm or not
if (ConfiguredKeyLength != 16) {
ISOException.throwIt(KeyInNotSetGood);
}
MyDES2Key.setKey(TheDES_Key, (short) 0);
if (buffer[ISO7816.OFFSET_P2] == 1) {
MyCipher.init(MyDES2Key, Cipher.MODE_ENCRYPT);
} else {
MyCipher.init(MyDES2Key, Cipher.MODE_DECRYPT);
}
}
public void ThreeKeyDESCrypto(APDU apdu)
throws ISOException {
byte[] buffer = apdu.getBuffer();
// Check to see if the configured key is the required key for this ...
// ... algorithm or not
if (ConfiguredKeyLength != 24) {
ISOException.throwIt(KeyInNotSetGood);
}
MyDES3Key.setKey(TheDES_Key, (short) 0);
if (buffer[ISO7816.OFFSET_P2] == 1) {
MyCipher.init(MyDES3Key, Cipher.MODE_ENCRYPT);
} else {
MyCipher.init(MyDES3Key, Cipher.MODE_DECRYPT);
}
}
public void DoEncryptDecrypt(APDU apdu) {
byte[] buffer = apdu.getBuffer();
byte[] CipheredData = JCSystem.makeTransientByteArray((short) 32,
JCSystem.CLEAR_ON_DESELECT);
short datalen = apdu.setIncomingAndReceive();
if ((datalen % 8) != 0) {
ISOException.throwIt(ISO7816.SW_DATA_INVALID);
}
MyCipher.doFinal(buffer, (short) 0, datalen, CipheredData, (short) 0);
Util.arrayCopyNonAtomic(CipheredData, (short) 0, buffer, (short) 0,
datalen);
apdu.setOutgoingAndSend((short) 0, datalen);
}
}
Below, you see an applet that generate hash value of input data based on MD5, RIPEMD160, SHA, SHA224, SHA256, SHA384 and SHA512 :
package hashPack;
import javacard.framework.*;
import javacard.security.CryptoException;
import javacard.security.MessageDigest;
public class HashMachine extends Applet {
//outputArray
byte[] hashedValue = new byte[64];
//output Length
short OLength = 0x0000;
//Defining switch case variables for Hash algorithm commands
final byte MD5 = (byte) 0x00;
final byte RIPEMD160 = (byte) 0X01;
final byte SHA = (byte) 0X02;
final byte SHA224 = (byte) 0X03;
final byte SHA256 = (byte) 0X04;
final byte SHA384 = (byte) 0X05;
final byte SHA512 = (byte) 0X06;
public static void install(byte[] bArray, short bOffset, byte bLength) {
new HashMachine();
}
protected HashMachine() {
register();
}
public void process(APDU apdu) {
if (selectingApplet()) {
return;
}
byte[] buffer = apdu.getBuffer();
try {
switch (buffer[ISO7816.OFFSET_INS]) {
case MD5: {
MessageDigest HashObj = MessageDigest.getInstance(MessageDigest.ALG_MD5, false);
HashObj.reset();
OLength = 16;
if (buffer[ISO7816.OFFSET_LC] > 0) {
doHash(apdu, HashObj, OLength);
} else {
ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
}
}
break;
case RIPEMD160: {
MessageDigest HashObj = MessageDigest.getInstance(MessageDigest.ALG_RIPEMD160, false);
HashObj.reset();
OLength = 20;
if (buffer[ISO7816.OFFSET_LC] > 0) {
doHash(apdu, HashObj, OLength);
} else {
ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
}
}
break;
case SHA: {
MessageDigest HashObj = MessageDigest.getInstance(MessageDigest.ALG_SHA, false);
HashObj.reset();
OLength = 20;
if (buffer[ISO7816.OFFSET_LC] > 0) {
doHash(apdu, HashObj, OLength);
} else {
ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
}
}
break;
case SHA224: {
MessageDigest HashObj = MessageDigest.getInstance(MessageDigest.ALG_SHA_224, false);
HashObj.reset();
OLength = 32;
if (buffer[ISO7816.OFFSET_LC] > 0) {
doHash(apdu, HashObj, OLength);
} else {
ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
}
}
break;
case SHA256: {
MessageDigest HashObj = MessageDigest.getInstance(MessageDigest.ALG_SHA_256, false);
HashObj.reset();
OLength = 32;
if (buffer[ISO7816.OFFSET_LC] > 0) {
doHash(apdu, HashObj, OLength);
} else {
ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
}
}
break;
case SHA384: {
MessageDigest HashObj = MessageDigest.getInstance(MessageDigest.ALG_SHA_384, false);
HashObj.reset();
OLength = 64;
if (buffer[ISO7816.OFFSET_LC] > 0) {
doHash(apdu, HashObj, OLength);
} else {
ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
}
}
break;
case SHA512: {
MessageDigest HashObj = MessageDigest.getInstance(MessageDigest.ALG_SHA_512, false);
HashObj.reset();
OLength = 64;
if (buffer[ISO7816.OFFSET_LC] > 0) {
doHash(apdu, HashObj, OLength);
} else {
ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
}
}
break;
default:
ISOException.throwIt(ISO7816.SW_INS_NOT_SUPPORTED);
}
} catch (CryptoException e) {
ISOException.throwIt(((CryptoException) e).getReason());
}
}
public void doHash(APDU apdu, MessageDigest HashObj, short OLength) {
byte[] buffer = apdu.getBuffer();
HashObj.update(buffer, ISO7816.OFFSET_CDATA, buffer[ISO7816.OFFSET_LC]);
HashObj.doFinal(buffer, ISO7816.OFFSET_CDATA, buffer[ISO7816.OFFSET_LC], hashedValue, (short) 0);
Util.arrayCopyNonAtomic(hashedValue, (short) 0, buffer, (short) 0, OLength);
apdu.setOutgoingAndSend((short) 0, OLength);
}
}
The problem is that the values that this applet returns me, are different from the values that online tools return.
For example I want to have hash value of 012345(in ascii). So I convert it to its hex value (i.e 303132333435) and I sent it to my applet:
OSC: opensc-tool.exe -s 00a4040006C761819104D7 -s 0000000005303132333435
Using reader with a card: ACS CCID USB Reader 0
Sending: 00 A4 04 00 06 C7 61 81 91 04 D7
Received (SW1=0x90, SW2=0x00)
Sending: 00 00 00 00 05 30 31 32 33 34 35
Received (SW1=0x90, SW2=0x00):
40 6B 29 64 5D 4D 8A 75 97 89 84 B5 00 25 67 D2 #k)d]M.u.....%g.
As you see the applet returns 40 6B 29 64 5D 4D 8A 75 97 89 84 B5 00 25 67 D2, while online toolsreturn d6 a9 a9 33 c8 aa fc 51 e5 5a c0 66 2b 6e 4d 4a. What's wrong?
There is a bug in your code. Your doHash method does the hashing as from a twice as long input (it computes the hash from "XX" instead of "X"):
HashObj.update(buffer, ISO7816.OFFSET_CDATA, buffer[ISO7816.OFFSET_LC]);
HashObj.doFinal(buffer, ISO7816.OFFSET_CDATA, buffer[ISO7816.OFFSET_LC], hashedValue, (short) 0);
The update method is for long inputs only - it does all the computation of the first N data blocks and produces no output. The doFinal method does the same for the last block of data and it copies the output to the output buffer.
Use the second line only:
HashObj.doFinal(buffer, ISO7816.OFFSET_CDATA, buffer[ISO7816.OFFSET_LC], hashedValue, (short) 0);
Below is DES encryption code. I am getting error 0x6999: "Applet selection failed".
package JCardDES;
import javacard.framework.*;
import javacard.security.*;
import javacardx.crypto.*;
public class JCard_DES extends Applet
{
// globals
DESKey deskey;
Cipher cipherCBC;
final short dataOffset = (short) ISO7816.OFFSET_CDATA;
static byte[] TrippleDESKey = {(byte) 0x38, (byte) 0x12, (byte) 0xA4,
(byte) 0x19, (byte) 0xC6, (byte) 0x3B, (byte) 0xE7, (byte) 0x71, (byte) 0x00, (byte) 0x12, (byte) 0x00,
(byte) 0x19, (byte) 0x80, (byte) 0x3B, (byte) 0xE7, (byte) 0x71, (byte) 0x01, (byte) 0x12, (byte) 0x01,
(byte) 0x01, (byte) 0x01, (byte) 0x03, (byte) 0xE7, (byte) 0x71};
// constructor,
// initialization
private JCard_DES(byte bArray[], short bOffset, byte bLength)
{
try {
deskey = (DESKey) KeyBuilder.buildKey(KeyBuilder.TYPE_DES, KeyBuilder.LENGTH_DES3_3KEY, false);
cipherCBC = Cipher.getInstance(Cipher.ALG_DES_CBC_NOPAD, false);
}
catch (CryptoException e) {
ISOException.throwIt((short) ((short) 0x9000 + e.getReason()));
}
if (bArray[bOffset] == 0)
{
register();
}
else
{
register(bArray, (short)(bOffset+1), bArray[bOffset]);
}
}
// install
public static void install(byte bArray[], short bOffset, byte bLength)
{
new JCard_DES(bArray, bOffset, bLength);
}
public void process(APDU apdu)
{
byte[] buf = apdu.getBuffer();
if (selectingApplet())
{
return;
}
doTrippeDES(apdu);
}
// DES encryption
private void doTrippeDES(APDU apdu)
{
byte a[] = apdu.getBuffer();
short incomingLength = (short) (apdu.setIncomingAndReceive());
if (incomingLength != 24) ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
deskey.setKey(TrippleDESKey, (short)0);
cipherCBC.init(deskey, Cipher.MODE_ENCRYPT,new byte[]{0,0,0,0,0,0,0,0},(short)0,(short)8);
cipherCBC.doFinal(a, (short) dataOffset, incomingLength, a, (short) (dataOffset + 24));
cipherCBC.init(deskey, Cipher.MODE_DECRYPT,new byte[]{0,0,0,0,0,0,0,0},(short)0,(short)8);
cipherCBC.doFinal(a, (short) (dataOffset + 24), incomingLength, a, (short) (dataOffset + 48));
// send results
apdu.setOutgoing();
apdu.setOutgoingLength((short) 72);
apdu.sendBytesLong(a, (short) dataOffset, (short) 72);
}
}
That's strange, because without the initialization codes in try/catch block, there is no problem to select the applet.
My script file (APDU script) is
powerup;
// Select JCard_DES
0x00 0xA4 0x04 0x00 0X06 0XFC 0X74 0X41 0XA1 0X9B 0X63 0x7F;
Please guide me where i'm going wrong since i'm new to Java Card Programming
Thanks
Your command length (Lc) is incorrect. It should be 0x07 instead of 0x06.
0x00 0xA4 0x04 0x00 0X07 0XFC 0X74 0X41 0XA1 0X9B 0X63 0x7F
error code 0x6999 means applet selection failed.To determine the correctness of your aid and uniqueness.Pay attention to rules inside sometimes choose aid will appear automatically when the concept of completion.