Android Question How to send byte array to Smart Card

Culjko

Member
After reading your posts I realized that I cannot call a class as static if it is public. The problem I have now is how to forward the byte array to the methods, I read the posts but I didn't find anything similar.
 

Culjko

Member
Public Sub ScardApplet
Dim buffer(22) As Byte
buffer(0) = 0x00
buffer(1) = 0xa4
buffer(2) = 0x04
buffer(3) = 0x00
buffer(4) = 0x10
buffer(5) = 0xa0
buffer(6) = 0x00
buffer(7) = 0x00
buffer(8) = 0x07
buffer(9) = 0x48
buffer(10) = 0x46
buffer(11) = 0x4a
buffer(12) = 0x49
buffer(13) = 0x2d
buffer(14) = 0x54
buffer(15) = 0x61
buffer(16) = 0x78
buffer(17) = 0x43
buffer(18) = 0x6f
buffer(19) = 0x72
buffer(20) = 0x65
buffer(21) = 0x00
Dim rcvbuff() As Byte
Dim rcvlenght As Int = 0

Dim response() As Byte
commandSmartCard( buffer )

Log(resposeBuffer.Length)


Return
End Sub


Public Sub commandSmartCard(apduSend() As Byte) As Byte

Log(apduSend.Length)
Private iccSmartCard As JavaObject
iccSmartCard.InitializeContext
Private slot1(1) As Byte
Private apduResp() As Byte
slot1(0) = slotNumber
Dim endBuffer As Int = apduSend.Length-1
Dim conv As Byte = ReconvertToByte(apduSend)

iccSmartCard.InitializeNewInstance( "vpos.apipackage.PosApiHelper", Null)
Log("command " & iccSmartCard.RunMethod("IccCommand", Array As Object(slot1(0),conv ,resposeBuffer)))
Log("buffer = " & resposeBuffer.Length)
For i = 0 To 50
Log(resposeBuffer(i))
Next
Return
End Sub


Public Sub ReconvertToByte(data() As Byte) As Byte
Private converter As String = BytesToString(data,0,data.Length,"UTF-8")
Log(converter)
Return converter.GetBytes("UTF8")
End Sub
 
Upvote 0

Culjko

Member
Error:

** Service (starter) Start **
** Activity (main) Create (first time) **
bluetoothadapter
CS10
Call B4XPages.GetManager.LogEvents = True to enable logging B4XPages events.
** Activity (main) Resume **
/storage/emulated/0/Android/data/com.ciontek.ePos/files
(Class) class vpos.apipackage.PosApiHelper
(PosApiHelper) vpos.apipackage.PosApiHelper@cec8720
-2405
0
0
0
Open slot PDAM1
-2102
0
slot num 1
22
����������HFJI-TaxCore��
art/runtime/java_vm_ext.cc:496] JNI DETECTED ERROR IN APPLICATION: use of invalid jobject 0xffc707e0
art/runtime/java_vm_ext.cc:496] "main" prio=5 tid=1 Runnable
art/runtime/java_vm_ext.cc:496] | group="main" sCount=0 dsCount=0 obj=0x74135268 self=0xf1e84400
art/runtime/java_vm_ext.cc:496] | sysTid=2651 nice=0 cgrp=default sched=0/0 handle=0xf5336534
art/runtime/java_vm_ext.cc:496] | state=R schedstat=( 1023990229 117395771 1351 ) utm=74 stm=28 core=0 HZ=100
art/runtime/java_vm_ext.cc:496] | stack=0xff478000-0xff47a000 stackSize=8MB
art/runtime/java_vm_ext.cc:496] | held mutexes= "mutator lock"(shared held)
art/runtime/java_vm_ext.cc:496] (no managed stack frames)
art/runtime/java_vm_ext.cc:496]
 
Upvote 0

Culjko

Member
Log("command " & iccSmartCard.RunMethod("IccCommand", Array As Object(slot1(0),conv ,resposeBuffer)))
The error is from this line when I want to forward the byte array to Smart Chard.
Manufacturer reference:
public int IccCommand(byte slot, byte[] apduSend, byte[] apduResp)
Parameter description
Slotcassette No.:
0x00-IC Card Channel;
0x01-PSAM1 Card Channel;
0x02-PSAM2 Card Channel;
ApduSend:
sent to the card’s apdu
ApduResp:
Receive the card's apdu of returned

Return
int
0 Execute successfully
(-2503) Communication timeout
(-2405) The cards are put out in the transaction
(-2401) Parity error
(-2403) Select Channel error
(-2400) Sending data too long(LC)
(-2404) The Protocol error(is Not T = 0 or T = 1)
(-2406) No reset card
 
Upvote 0

Culjko

Member
This is TakCore's tutorial on how to send bytes, and it works in a Windows environment :
Select Applet

As previously mentioned, the Smart Card has two applets installed. This command selects the Secure Element
Applet and routes subsequent APDU commands to it.
IsoCase: Case4Short
Class: 0x00
Instruction: 0xa4
P1-P2: 0x0400
Command Length (Lc): 0x10
Command Data: 0xA000000748464A492D546178436F7265
Expected Length (Le): 0x00
Example:
Request: 00A4040010A000000748464A492D546178436F726500

If i look user manual for IccCommand:
public int IccCommand(byte slot, byte[] apduSend, byte[] apduResp)

Parameter description
Slotcassette No.:
0x00-IC Card Channel;
0x01-PSAM1 Card Channel;
0x02-PSAM2 Card Channel;

ApduSend:
sent to the card’s apdu
ApduResp:
Receive the card's apdu of returned
Return
int

Function description
Read and Write IC Card
If both LC and LE exist, you should set "LC = X; LE = 0x01"
Example
byte cmd[] = new byte[4];
cmd[0] = 0x00; //0-3 cmd
cmd[1] = (byte) 0x84;
cmd[2] = 0x00;
cmd[3] = 0x00;
short lc = 0x00;
short le = 0x04;
String sendmsg = "";
byte [] dataIn = sendmsg.getBytes();
APDU_SEND ApduSend = new APDU_SEND(cmd, lc, dataIn, le);
APDU_RESP ApduResp = null;
byte[] resp = new byte[516];
ret = posApiHelper.IccCommand(slot, ApduSend.getBytes(), resp);

I see to Lc and Le must change place.
After that i get this message:

Open slot PDAM2
error = successfully
ATR = 133BF99600008031FE454A546178436F7265560F000000000000000000000000000000000000000000
00
APDU 00A40400A000000748464A492D546178436F72651000
Fatal signal 11 (SIGSEGV), code 1, fault addr 0xffa79000 in tid 6017 (om.ciontek.ePos)
 

Attachments

  • CiontekSmartCard.bas
    12.3 KB · Views: 124
Upvote 0

drgottjr

Expert
Licensed User
Longtime User
what and where is this: vpos.apipackage.PosApiHelper?

are you using bluetooth to connect to something? what?

you can't send this: "����������HFJI-TaxCore��" to the card unless you are connected first. are you connected? when and how? i don't see this shown.

your sub: Public Sub commandSmartCard(apduSend() As Byte) As Byte returns a byte array. but you do not use the sub this way.

please use the
B4X:
code here...
tags. your posts are very difficult to read. do you understand what "
B4X:
code here...
" means?. all of your posts for this thread (and for others that you have started) are missing "
B4X:
code here...
". please use these tags or ask how to if you do not know. thank you.
 
Upvote 0

Culjko

Member
This is code how i try this class
Dim smartcard As CiontekSmartCard
smartcard.Initialize


Dim Slotnum As Int = smartcard.GetSmartCardSlot
smartcard.openSmartCard(Slotnum)
smartcard.ScardApplet ' Should be return 9000 in buffer
smartcard.VerifyPin("3226")
smartcard.closeSmartCard
 
Upvote 0

Culjko

Member
It's been two years since I installed B4A, but I didn't do anything in it at all, since October 17, 2023 I started actively writing programs, I think I'm making fast progress, I just wrote an application that signs invoices with certificates (takcore), I used the chilkat library for that because I already bought a license for that library for Windows. I apologize for bothering you with my writing here, but I'm very bad at navigating here.
 
Upvote 0

Culjko

Member
This is a big step for me, I used to work in old type databases before this,this kind of programming is totally unknown to me.
 
Upvote 0

drgottjr

Expert
Licensed User
Longtime User
This is TakCore's tutorial on how to send bytes, and it works in a Windows environment :
Select Applet

As previously mentioned, the Smart Card has two applets installed. This command selects the Secure Element
Applet and routes subsequent APDU commands to it.
IsoCase: Case4Short
Class: 0x00
Instruction: 0xa4
P1-P2: 0x0400
Command Length (Lc): 0x10
Command Data: 0xA000000748464A492D546178436F7265
Expected Length (Le): 0x00
Example:
Request: 00A4040010A000000748464A492D546178436F726500

If i look user manual for IccCommand:
public int IccCommand(byte slot, byte[] apduSend, byte[] apduResp)

Parameter description
Slotcassette No.:
0x00-IC Card Channel;
0x01-PSAM1 Card Channel;
0x02-PSAM2 Card Channel;

ApduSend:
sent to the card’s apdu
ApduResp:
Receive the card's apdu of returned
Return
int

Function description
Read and Write IC Card
If both LC and LE exist, you should set "LC = X; LE = 0x01"
Example
byte cmd[] = new byte[4];
cmd[0] = 0x00; //0-3 cmd
cmd[1] = (byte) 0x84;
cmd[2] = 0x00;
cmd[3] = 0x00;
short lc = 0x00;
short le = 0x04;
String sendmsg = "";
byte [] dataIn = sendmsg.getBytes();
APDU_SEND ApduSend = new APDU_SEND(cmd, lc, dataIn, le);
APDU_RESP ApduResp = null;
byte[] resp = new byte[516];
ret = posApiHelper.IccCommand(slot, ApduSend.getBytes(), resp);

I see to Lc and Le must change place.
After that i get this message:

Open slot PDAM2
error = successfully
ATR = 133BF99600008031FE454A546178436F7265560F000000000000000000000000000000000000000000
00
APDU 00A40400A000000748464A492D546178436F72651000
Fatal signal 11 (SIGSEGV), code 1, fault addr 0xffa79000 in tid 6017 (om.ciontek.ePos)

this is wrong:
APDU 00A40400A000000748464A492D546178436F72651000
Fatal signal 11 (SIGSEGV), code 1, fault addr 0xffa79000 in tid 6017 (om.ciontek.ePos)

you seem to be struggling with apdu format. that byte needs to be 10. you had it right the first time.
and you must wrap all your i/o in try/catch blocks. you cannot have these types of crashes. jvm errors are not always trappable, but smartcard i/o must always be wrapped. see if you can modify your .bas class
 
Last edited:
Upvote 0

Culjko

Member
You are right, in Windows that work like that and user manual of TaxCore is same
IsoCase: Case4Short
Class: 0x00
Instruction: 0xa4
P1-P2: 0x0400
Command Length (Lc): 0x10
Command Data: 0xA000000748464A492D546178436F7265
Expected Length (Le): 0x00
Example:
Request: 00A4040010A000000748464A492D546178436F726500

Error:

Open slot PDAM2
error = successfully
ATR = 133BF99600008031FE454A546178436F7265560F000000000000000000000000000000000000000000
00
APDU 00A4040010A000000748464A492D546178436F726500
art/runtime/java_vm_ext.cc:496] JNI DETECTED ERROR IN APPLICATION: use of invalid jobject 0xfff1b320
art/runtime/java_vm_ext.cc:496] "main" prio=5 tid=1 Runnable
art/runtime/java_vm_ext.cc:496] | group="main" sCount=0 dsCount=0 obj=0x74135610 self=0xe9304400
art/runtime/java_vm_ext.cc:496] | sysTid=8000 nice=0 cgrp=default sched=0/0 handle=0xec75f534
art/runtime/java_vm_ext.cc:496] | state=R schedstat=( 3286820685 244411083 1747 ) utm=209 stm=119 core=0 HZ=100
art/runtime/java_vm_ext.cc:496] | stack=0xff722000-0xff724000 stackSize=8MB
art/runtime/java_vm_ext.cc:496] | held mutexes= "mutator lock"(shared held)
art/runtime/java_vm_ext.cc:496] (no managed stack frames)
art/runtime/java_vm_ext.cc:496]
 
Upvote 0

Culjko

Member
But if u look At user manual of Ciontek:
public int IccCommand(byte slot, byte[] apduSend, byte[] apduResp)

Example:

B4X:
byte cmd[] = new byte[4];
cmd[0] = 0x00; //0-3 cmd
cmd[1] = (byte) 0x84;
cmd[2] = 0x00;
cmd[3] = 0x00;
short lc = 0x00;
short le = 0x04;
String sendmsg = "";
byte [] dataIn = sendmsg.getBytes();
APDU_SEND ApduSend = new APDU_SEND(cmd, lc, dataIn, le);
APDU_RESP ApduResp = null;
byte[] resp = new byte[516];
ret = posApiHelper.IccCommand(slot, ApduSend.getBytes(), resp);

According to their instructions Lc and Le is on end of line.
 
Upvote 0

Culjko

Member
I find what is problem in library have data paker or something like that name is APDU_SEND

B4X:
package vpos.apipackage;

public class APDU_SEND {
  public byte[] Command = null;
 
  public short Lc;
 
  public byte[] DataIn = null;
 
  public short Le;
 
  public APDU_SEND(byte[] Command, short Lc, byte[] DataIn, short Le) {
    this.Command = new byte[Command.length];
    this.DataIn = new byte[DataIn.length];
    this.Command = Command;
    this.Lc = Lc;
    this.DataIn = DataIn;
    this.Le = Le;
  }
 
  public byte[] getBytes() {
    byte[] buf = new byte[520];
    System.arraycopy(this.Command, 0, buf, 0, this.Command.length);
    buf[4] = (byte)(this.Lc / 256);
    buf[5] = (byte)(this.Lc % 256);
    System.arraycopy(this.DataIn, 0, buf, 6, this.DataIn.length);
    buf[518] = (byte)(this.Le / 256);
    buf[519] = (byte)(this.Le % 256);
    return buf;
  }
}


How to write code for this Class?

apduClass.InitializeNewInstance("vpos.apipackage.APDU_SEND", null) - java.lang.InstantiationException:
java.lang.Class<vpos.apipackage.APDU_SEND> has no zero argument constructor

apduClass.InitializeNewInstance("vpos.apipackage.APDU_SEND", Array(cmd, Lc,Data, Lebytes )) - java.lang.RuntimeException: Constructor not found.
 
Upvote 0

drgottjr

Expert
Licensed User
Longtime User
i do not know what Ciontek is.
i do not know what vpos.apipackage.PosApiHelper is.
i do not know how you are communicating with card.
i do not know which card you are trying to communicate with.
i do not know what "public class APDU_SEND" is. i do not know if it is correctly written, and i do not know if you are using it correctly. ("Constructor not found" - it may need to be static, but i do not know where this appears in the project.)

what i do know is apdu.

this is wrong:
Java:
short lc = 0x00;
short le = 0x04;

you have it backwards.
le is 0x00 (almost always)
lc could be 0x04 (but not usually, if at all)
also, if this code is supposed to be java, these variables are byte, not short.

According to their instructions Lc and Le is on end of line.

i do not know where you found this or if it actually says what you say it says.
"end of line" means nothing. what line? there is no "line".
lc is always byte[4] and le is always the trailer byte (and isusually 0x00.
it means you do not know how many bytes will be in response).

i still do not know if you are connected to the card and how you
connected. since the commands you are trying to build are wrong,
you will receive some kind of error (i do not know where any errors
are coming from since i do not know how any communication between
the android device, a card reader and any 3rd party libraries is
being made. regardless, you have to wrap all these attempts in
try/catch blocks)

thanks for using "code" tags. at least i can follow what you are doing now.

you seem to be using multiple libraries, but i have no idea what they do.
 
Last edited:
Upvote 0
Top