Java Card OwnerPin - APDU Command - javacard

I'm starting to learn java card and I'm reading a sample code of a wallet and there an OwnerPin in it.
Here's the part of the code, related to the pin and its verification:
OwnerPIN pin;
private myApplet(byte[] bArray, short bOffset, byte bLength) {
// It is good programming practice to allocate
// all the memory that an applet needs during
// its lifetime inside the constructor
pin = new OwnerPIN(PIN_TRY_LIMIT, MAX_PIN_SIZE);
byte iLen = bArray[bOffset]; // aid length
bOffset = (short) (bOffset + iLen + 1);
byte cLen = bArray[bOffset]; // info length
bOffset = (short) (bOffset + cLen + 1);
byte aLen = bArray[bOffset]; // applet data length
// The installation parameters contain the PIN
// initialization value
pin.update(bArray, (short) (bOffset + 1), aLen);
register();
}
I'm having a little trouble understanding this code. I know that this is the part when the pin is set according to the installation script:
0x80 0xB8 0x00 0x00 0xd 0xb 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x00 0x00 0x00 0x7F;
I can't understand what is the value of pin will be after installing the applet.

The shown code is not enough to actually say anything about the given APDU.
This code sample though:
byte iLen = bArray[bOffset]; // aid length
bOffset = (short) (bOffset + iLen + 1);
byte cLen = bArray[bOffset]; // info length
bOffset = (short) (bOffset + cLen + 1);
byte aLen = bArray[bOffset]; // applet data length
is the default code for the Applet's installation method, therefore could be triggered by a Global Platform INSTALL command. However, the given APDU is not a valid Global Platform at all.
From your code we cannot see the entrypoint of the APDU in the process method, but probably it works like this: the given data is a LV-encoded list (Length/Value), therefore you parse the length byte for aid first, save the length iLen and increment bOffset to the next LV-pair. in the end the value and length of the applet data is taken and feeded into the pin.update.
In the given APDU, the PIN is acutally missing, try to parse the contents and length for aid and info and you will see that the applet data bytes are missing.

Related

why does i2cset send extra bytes?

I've been working on PIC18F55K42 chip for a while. The PIC is setup as a slave and it's receiving bytes correctly. But I encountered a few problems.
For example, when I do:
i2cset -y 1 0x54 0x80 0x01
It looks correct on the controller side and I can see the address 0x80(data address) and byte value 0x01.
When I send in block mode like:
i2cset -y 1 0x54 0x80 0x01 0x02 0x03 0x04 i
I see spurious bytes appearing on the controller. More precisely, it looks like this:
ADDRESS 80 6c 00 2f 01 02 03 04 STOP
At first I thought this is something to do with my controller and even tried digging into it's clock settings. Used Salae logic analyser too. There's nothing wrong with the controller or it's set up. The only place I can think of is the complex onion driver layering done by Linux.
I'd like to know why Linux is sending the 3 extra bytes (6c 00 2f). Why does i2c_smbus_write_block_data send extra bytes and how can it be avoided?
It's a bug in the i2cset implementation in Busybox. See miscutils/i2c_tools.c:
/* Prepare the value(s) to be written according to current mode. */
switch (mode) {
case I2C_SMBUS_BYTE_DATA:
val = xstrtou_range(argv[3], 0, 0, 0xff);
break;
case I2C_SMBUS_WORD_DATA:
val = xstrtou_range(argv[3], 0, 0, 0xffff);
break;
case I2C_SMBUS_BLOCK_DATA:
case I2C_SMBUS_I2C_BLOCK_DATA:
for (blen = 3; blen < (argc - 1); blen++)
block[blen] = xstrtou_range(argv[blen], 0, 0, 0xff);
val = -1;
break;
default:
val = -1;
break;
}
Should be block[blen - 3] = xstrtou_range(argv[blen], 0, 0, 0xff);. The bug results in 3 extra garbage bytes from stack being sent.
Use i2c_smbus_write_i2c_block_data for raw i2c transfers
i2c_smbus_write_block_data makes data transfer using SMBUS protocol

Sending a byte [] over javacard apdu

I send a byte [] from the host application to the javacard applet. But when I try to retrieve it as byte [] via the command buffer[ISO7816.OFFSET_CDATA], I am told that I cannot convert byte to byte[]. How can I send a byte [] via command APDU from the host application and retrieve it as byte[] on the other end (javacard applet). It appears buffer[ISO7816.OFFSET_CDATA] returns byte. See my comments on where the error occurs.
My idea is as follows:
The host application sends challenge as a byte [] to be signed by the javacard applet. Note that the signature requires the challenge to be a byte []. The javacard signs as follows:
private void sign(APDU apdu) {
if(!pin.isValidated()) ISOException.throwIt(SW_PIN_VERIFICATION_REQUIRED);
else{
byte [] buffer = apdu.getBuffer();
byte numBytes = buffer[ISO7816.OFFSET_LC];
byte byteRead =(byte)(apdu.setIncomingAndReceive());
if ( ( numBytes != 20 ) || (byteRead != 20) )
ISOException.throwIt(ISO7816.SW_WRONG_LENGTH);
byte [] challenge = buffer[ISO7816.OFFSET_CDATA];// error point cannot convert from byte to byte []
byte [] output = new byte [64];
short length = 64;
short x =0;
Signature signature =Signature.getInstance(Signature.ALG_RSA_SHA_PKCS1, false);
signature.init(privKey, Signature.MODE_SIGN);
short sigLength = signature.sign(challenge, offset,length, output, x); // challenge must be a byte []
//This sequence of three methods sends the data contained in
//'serial' with offset '0' and length 'serial.length'
//to the host application.
apdu.setOutgoing();
apdu.setOutgoingLength((short)output.length);
apdu.sendBytesLong(output,(short)0,(short)output.length);
}
}
The challenge is sent by the host application as shown below:
byte [] card_signature=null;
SecureRandom random = SecureRandom . getInstance( "SHA1PRNG" ) ;
byte [] bytes = new byte [ 20 ] ;
random . nextBytes ( bytes) ;
CommandAPDU challenge;
ResponseAPDU resp3;
challenge = new CommandAPDU(IDENTITY_CARD_CLA,SIGN_CHALLENGE, 0x00, 0x20,bytes);
resp3= c.transmit(challenge);
if(resp3.getSW()==0x9000) {
card_signature = resp3.getData();
String s= DatatypeConverter.printHexBinary(card_signature);
System.out.println("signature: " + s);
} else System.out.println("Challenge signature error " + resp3.getSW());
Generally, you send bytes over through the APDU interface. A Java or Java Card byte[] is a construct that can hold those bytes. This is where the APDU buffer comes in: it is the byte array that holds the bytes sent over the APDU interface - or at least a portion of them after calling setIncomingAndReceive().
The challenge therefore is within the APDU buffer; instead of calling:
short sigLength = signature.sign(challenge, offset,length, output, x);
you can therefore simply call:
short sigLength = signature.sign(buffer, apdu.getOffsetCdata(), CHALLENGE_SIZE, buffer, START);
where CHALLENGE_SIZE is 20 and START is simply zero.
Then you can use:
apdu.getOutgoingAndSend(START, sigLength);
to send back the signed challenge.
If you require to keep the challenge for a later stage then you should create a byte array in RAM using JCSystem.makeTransientByteArray() during construction of the Applet and then use Util.arrayCopy() to move the byte values into the challenge buffer. However, since the challenge is generated by the offcard system, there doesn't seem to be any need for this. The offcard system should keep the challenge, not the card.
You should not use ISO7816.OFFSET_CDATA anymore; it will not return the correct result if you would use larger key sizes that generate larger signatures and therefore require the use of extended length APDUs.

2x beaglebone black microcontrolers and nrf24l01 connection doesn't work

I'm trying to setup connection between two BBB using nrf24l01.
I hope i set up everything properly( but I'm not really sure), I used this tutorial https://electron14.com/?p=404 and this code : RF24/librf24-bbb/librf24, and some self investigation.
the result of pingtest is :
./pingtest
RF24/examples/pingpair/
ROLE: Ping out
- gpio.cpp RF24::begin end fun
STATUS = 0x0e RX_DR=0 TX_DS=0 MAX_RT=0 RX_P_NO=7 TX_FULL=0
RX_ADDR_P0-1 = 0xf0f0f0f0e1 0xf0f0f0f0d2
RX_ADDR_P2-5 = 0xc3 0xc4 0xc5 0xc6
TX_ADDR = 0xf0f0f0f0e1
RX_PW_P0-6 = 0x20 0x20 0x00 0x00 0x00 0x00
EN_AA = 0x00
EN_RXADDR = 0x03
RF_CH = 0x4c
RF_SETUP = 0x27
CONFIG = 0x0f
DYNPD/FEATURE = 0x00 0x00
Data Rate = 250KBPS
Model = nRF24L01+
CRC Length = 16 bits
PA Power = PA_HIGH
Now sending 23...ok...Failed, response timed out.
Now sending 1231...ok...Failed, response timed out.
Now sending 2441...ok...Failed, response timed out.
Now sending 3649...ok...Failed, response timed out.
Now sending 4859...ok...Failed, response timed out.
Now sending 6071...ok...Failed, response timed out.
and from other BBB pongtest
./pongtest
RF24/examples/pingpair/
ROLE: Pong back
STATUS = 0x0e RX_DR=0 TX_DS=0 MAX_RT=0 RX_P_NO=7 TX_FULL=0
RX_ADDR_P0-1 = 0xf0f0f0f0d2 0xf0f0f0f0e1
RX_ADDR_P2-5 = 0xc3 0xc4 0xc5 0xc6
TX_ADDR = 0xf0f0f0f0d2
RX_PW_P0-6 = 0x20 0x20 0x00 0x00 0x00 0x00
EN_AA = 0x00
EN_RXADDR = 0x03
RF_CH = 0x4c
RF_SETUP = 0x27
CONFIG = 0x0f
DYNPD/FEATURE = 0x00 0x00
Data Rate = 250KBPS
Model = nRF24L01+
CRC Length = 16 bits
PA Power = PA_HIGH
Can someone help me ?
Based on your data, both devices have a status register value of 0x0e, which is clearing the lsb; that bit sets the direction of the device, either Tx (0) or Rx (1). Based on the status register of each board being cleared, you have both of them setup as transmitters.

Unknown Error (6c 15) with Setoutgoinglength in java card 2.2.1

I wrote a code that for java card 2.2.1 and I test it eith JCIDE.
I get error in method Setoutgoinglength()
public void getoutput(APDU apdu)
{
byte [] buffer = apdu.getBuffer();
byte hello[] = {'H','E','L','L','O',' ','W','O','R','L','D',' ', 'J','A','V','A',' ','C','A','R','D'};
short le = apdu.setOutgoing();
short totalBytes = (short) hello.length;
Util.arrayCopyNonAtomic(hello, (short)0, buffer, (short)0, (short)totalBytes);
apdu.setOutgoingLength(totalBytes);
apdu.sendBytes((short) 0, (short) hello.length);}
6CXX means that your Le is not equal to the correct length of response data (XX is equal to the length of correct response data). 6C15 specifically means that the correct Le to be used should be 0x15.
What happened is that your Le field is 0x00 (which is actually interpreted by the card as 256 in decimal form) but you used totalBytes, which has a value of 0x15, as parameter to apdu.setOutgoingLength() which is not equal to 256.
The correct APDU to send is 00 40 00 00 15

ISO 15693: read multiple security blocks

I am trying to modify an existing SCardTransmit() command (C#) that currently reads one security status/block from a ISO 15693 vicinity RFID card (TI Tag-it HF), to one that will retrieve the security status for all 64 blocks on the card. The existing code is as follows:
Byte[] sendHeader = { 0xFF, 0x30, 0x00, 0x03, 0x05, 0x01, 0x00, 0x00, 0x00, Convert.ToByte(blockNum), 0x01 };
Byte[] sendBuffer = new Byte[255]; //Send Buffer in SCardTransmit
int sendbufferlen; //Send Buffer length in SCardTransmit
SmartCardData pack = new SmartCardData();
sendHeader.CopyTo(sendBuffer, 0);
sendbufferlen = Convert.ToByte(sendHeader.Length);
SCardTransmitReceived rxBuf = SmartCardTransmit(sendBuffer, sendbufferlen);
The way I understand it, the bytes preceding Convert.ToByte(blockNum) represent the command to get a security status, followed by the block in question, and the number of blocks to read. The only reference I have seen regarding security status reads is in section 10.3.4 in the "Contactless Smart Card Reader Dev Guide"
NOTE: SmartCardTransmit takes care of calling SCardTransmit with the correct card handle and the other needed parameters. I'm more interested in the format of the send header that represents a request for security blocks 0 to 63.
Unfortunately, that is not possible. The Get Security Status command of the HID/Omnikey smartcard reader can only retrieve the security status of one block with each command. So regardless of what Le byte you try to provide, the reader will always only return the security status of the block you specify with blockNum.
So the only way to get the security status for all blocks is by iterating through all blocks and issuing the command for each of them:
bool moreBlocks = true;
int blockNum = 0;
while (moreBlocks) {
byte[] sendBuffer = {
0xFF, 0x30, 0x00, 0x03,
0x05,
0x01,
0x00, 0x00,
(byte)((blockNum>>8) & 0xFF), (byte)(blockNum & 0xFF),
0x00
};
SCardTransmitReceived rxBuf = SmartCardTransmit(sendBuffer, sendBuffer.Length);
moreBlocks = check_if_rxBuf_ends_with_sw9000(rxBuf);
++blockNum;
}
From this document:
link
it appears that your tag complies with ISO15693 standard. From the documentation you have provided it appears that the command you need is at page 59. Now, from the description of the command it appears 0x01 is Version and the following two bytes (0x00 and 0x00) means reading by block. The byte before Convert.ToByte() seams to be the MSB of the starting block (0x00). The Convert.ToByte() is the LSB of the starting block. The next is Le in command description (the number of blocks to be read).

Resources