From 9f57a1312e8e81f7e0e42fc813e49342bfd7291c Mon Sep 17 00:00:00 2001 From: Nikita Mikhailov Date: Mon, 9 May 2016 15:25:06 +0600 Subject: [PATCH] SecurityToken: fix T=1 TPDU chaining handling --- .../keychain/securitytoken/usb/tpdu/IBlock.java | 3 +++ .../keychain/securitytoken/usb/tpdu/RBlock.java | 7 +++++-- .../keychain/securitytoken/usb/tpdu/SBlock.java | 3 +++ .../securitytoken/usb/tpdu/T1TpduProtocol.java | 10 +++++----- 4 files changed, 16 insertions(+), 7 deletions(-) diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/securitytoken/usb/tpdu/IBlock.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/securitytoken/usb/tpdu/IBlock.java index 8caa54ae8..3df4d9cdf 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/securitytoken/usb/tpdu/IBlock.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/securitytoken/usb/tpdu/IBlock.java @@ -20,6 +20,9 @@ package org.sufficientlysecure.keychain.securitytoken.usb.tpdu; import org.sufficientlysecure.keychain.securitytoken.usb.UsbTransportException; 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_CHAINING = 5; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/securitytoken/usb/tpdu/RBlock.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/securitytoken/usb/tpdu/RBlock.java index 678b5e01e..153758fb2 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/securitytoken/usb/tpdu/RBlock.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/securitytoken/usb/tpdu/RBlock.java @@ -22,7 +22,10 @@ import android.support.annotation.NonNull; import org.sufficientlysecure.keychain.securitytoken.usb.UsbTransportException; 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 { super(baseBlock); @@ -33,7 +36,7 @@ public class RBlock extends Block { public RBlock(BlockChecksumType checksumType, byte nad, byte sequence) 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 { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/securitytoken/usb/tpdu/SBlock.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/securitytoken/usb/tpdu/SBlock.java index 9bf3fdc9d..72302fc4b 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/securitytoken/usb/tpdu/SBlock.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/securitytoken/usb/tpdu/SBlock.java @@ -18,6 +18,9 @@ package org.sufficientlysecure.keychain.securitytoken.usb.tpdu; 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) { super(baseBlock); } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/securitytoken/usb/tpdu/T1TpduProtocol.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/securitytoken/usb/tpdu/T1TpduProtocol.java index fb86c8020..2d0b4c383 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/securitytoken/usb/tpdu/T1TpduProtocol.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/securitytoken/usb/tpdu/T1TpduProtocol.java @@ -103,10 +103,10 @@ public class T1TpduProtocol implements CcidTransportProtocol { byte[] responseApdu = responseBlock.getApdu(); while (((IBlock) responseBlock).getChaining()) { - Block ackBlock = newRBlock((byte) (1 - ((IBlock) responseBlock).getSequence())); + Block ackBlock = newRBlock((byte) (((IBlock) responseBlock).getSequence() + 1)); mTransceiver.sendXfrBlock(ackBlock.getRawData()); - responseBlock = getBlockFromResponse(mTransceiver.receive()); + responseBlock = getBlockFromResponse(mTransceiver.receiveRaw()); if (responseBlock instanceof IBlock) { responseApdu = Arrays.concatenate(responseApdu, responseBlock.getApdu()); @@ -123,11 +123,11 @@ public class T1TpduProtocol implements CcidTransportProtocol { public Block getBlockFromResponse(byte[] data) throws UsbTransportException { 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); - } else if ((baseBlock.getPcb() & 0b11000000) == 0b11000000) { + } else if ((baseBlock.getPcb() & SBlock.MASK_SBLOCK) == SBlock.MASK_VALUE_SBLOCK) { 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); }