SecurityToken: fix T=1 TPDU chaining handling
This commit is contained in:
@@ -20,6 +20,9 @@ package org.sufficientlysecure.keychain.securitytoken.usb.tpdu;
|
|||||||
import org.sufficientlysecure.keychain.securitytoken.usb.UsbTransportException;
|
import org.sufficientlysecure.keychain.securitytoken.usb.UsbTransportException;
|
||||||
|
|
||||||
public class IBlock extends Block {
|
public class IBlock extends Block {
|
||||||
|
public static final byte MASK_RBLOCK = (byte) 0b10000000;
|
||||||
|
public static final byte MASK_VALUE_RBLOCK = (byte) 0b00000000;
|
||||||
|
|
||||||
private static final byte BIT_SEQUENCE = 6;
|
private static final byte BIT_SEQUENCE = 6;
|
||||||
private static final byte BIT_CHAINING = 5;
|
private static final byte BIT_CHAINING = 5;
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,10 @@ import android.support.annotation.NonNull;
|
|||||||
import org.sufficientlysecure.keychain.securitytoken.usb.UsbTransportException;
|
import org.sufficientlysecure.keychain.securitytoken.usb.UsbTransportException;
|
||||||
|
|
||||||
public class RBlock extends Block {
|
public class RBlock extends Block {
|
||||||
private static final byte BIT_SEQUENCE = 5;
|
public static final byte MASK_RBLOCK = (byte) 0b11000000;
|
||||||
|
public static final byte MASK_VALUE_RBLOCK = (byte) 0b10000000;
|
||||||
|
|
||||||
|
private static final byte BIT_SEQUENCE = 4;
|
||||||
|
|
||||||
public RBlock(Block baseBlock) throws UsbTransportException {
|
public RBlock(Block baseBlock) throws UsbTransportException {
|
||||||
super(baseBlock);
|
super(baseBlock);
|
||||||
@@ -33,7 +36,7 @@ public class RBlock extends Block {
|
|||||||
|
|
||||||
public RBlock(BlockChecksumType checksumType, byte nad, byte sequence)
|
public RBlock(BlockChecksumType checksumType, byte nad, byte sequence)
|
||||||
throws UsbTransportException {
|
throws UsbTransportException {
|
||||||
super(checksumType, nad, (byte) (0b10000000 | ((sequence & 1) << BIT_SEQUENCE)), new byte[0]);
|
super(checksumType, nad, (byte) (MASK_VALUE_RBLOCK | ((sequence & 1) << BIT_SEQUENCE)), new byte[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public RError getError() throws UsbTransportException {
|
public RError getError() throws UsbTransportException {
|
||||||
|
|||||||
@@ -18,6 +18,9 @@
|
|||||||
package org.sufficientlysecure.keychain.securitytoken.usb.tpdu;
|
package org.sufficientlysecure.keychain.securitytoken.usb.tpdu;
|
||||||
|
|
||||||
public class SBlock extends Block {
|
public class SBlock extends Block {
|
||||||
|
public static final byte MASK_SBLOCK = (byte) 0b11000000;
|
||||||
|
public static final byte MASK_VALUE_SBLOCK = (byte) 0b11000000;
|
||||||
|
|
||||||
public SBlock(Block baseBlock) {
|
public SBlock(Block baseBlock) {
|
||||||
super(baseBlock);
|
super(baseBlock);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -103,10 +103,10 @@ public class T1TpduProtocol implements CcidTransportProtocol {
|
|||||||
byte[] responseApdu = responseBlock.getApdu();
|
byte[] responseApdu = responseBlock.getApdu();
|
||||||
|
|
||||||
while (((IBlock) responseBlock).getChaining()) {
|
while (((IBlock) responseBlock).getChaining()) {
|
||||||
Block ackBlock = newRBlock((byte) (1 - ((IBlock) responseBlock).getSequence()));
|
Block ackBlock = newRBlock((byte) (((IBlock) responseBlock).getSequence() + 1));
|
||||||
mTransceiver.sendXfrBlock(ackBlock.getRawData());
|
mTransceiver.sendXfrBlock(ackBlock.getRawData());
|
||||||
|
|
||||||
responseBlock = getBlockFromResponse(mTransceiver.receive());
|
responseBlock = getBlockFromResponse(mTransceiver.receiveRaw());
|
||||||
|
|
||||||
if (responseBlock instanceof IBlock) {
|
if (responseBlock instanceof IBlock) {
|
||||||
responseApdu = Arrays.concatenate(responseApdu, responseBlock.getApdu());
|
responseApdu = Arrays.concatenate(responseApdu, responseBlock.getApdu());
|
||||||
@@ -123,11 +123,11 @@ public class T1TpduProtocol implements CcidTransportProtocol {
|
|||||||
public Block getBlockFromResponse(byte[] data) throws UsbTransportException {
|
public Block getBlockFromResponse(byte[] data) throws UsbTransportException {
|
||||||
final Block baseBlock = new Block(mChecksumType, data);
|
final Block baseBlock = new Block(mChecksumType, data);
|
||||||
|
|
||||||
if ((baseBlock.getPcb() & 0b10000000) == 0b00000000) {
|
if ((baseBlock.getPcb() & IBlock.MASK_RBLOCK) == IBlock.MASK_VALUE_RBLOCK) {
|
||||||
return new IBlock(baseBlock);
|
return new IBlock(baseBlock);
|
||||||
} else if ((baseBlock.getPcb() & 0b11000000) == 0b11000000) {
|
} else if ((baseBlock.getPcb() & SBlock.MASK_SBLOCK) == SBlock.MASK_VALUE_SBLOCK) {
|
||||||
return new SBlock(baseBlock);
|
return new SBlock(baseBlock);
|
||||||
} else if ((baseBlock.getPcb() & 0b11000000) == 0b10000000) {
|
} else if ((baseBlock.getPcb() & RBlock.MASK_RBLOCK) == RBlock.MASK_VALUE_RBLOCK) {
|
||||||
return new RBlock(baseBlock);
|
return new RBlock(baseBlock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user