diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/securitytoken/usb/CcidDescription.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/securitytoken/usb/CcidDescription.java index 82ef9861e..7c9db08b5 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/securitytoken/usb/CcidDescription.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/securitytoken/usb/CcidDescription.java @@ -36,6 +36,8 @@ abstract class CcidDescription { // dwFeatures Masks private static final int FEATURE_AUTOMATIC_VOLTAGE = 0x00008; + private static final int FEATURE_AUTOMATIC_PPS = 0x00080; + private static final int FEATURE_EXCHANGE_LEVEL_TPDU = 0x10000; private static final int FEATURE_EXCHAGE_LEVEL_SHORT_APDU = 0x20000; private static final int FEATURE_EXCHAGE_LEVEL_EXTENDED_APDU = 0x40000; @@ -130,6 +132,10 @@ abstract class CcidDescription { } } + boolean hasAutomaticPps() { + return hasFeature(FEATURE_AUTOMATIC_PPS); + } + private boolean hasFeature(int feature) { return (getFeatures() & feature) != 0; } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/securitytoken/usb/CcidTransceiver.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/securitytoken/usb/CcidTransceiver.java index 2d5cf2afc..75ff2b358 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/securitytoken/usb/CcidTransceiver.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/securitytoken/usb/CcidTransceiver.java @@ -258,6 +258,10 @@ public class CcidTransceiver { } } + public boolean hasAutomaticPps() { + return usbCcidDescription.hasAutomaticPps(); + } + /** Corresponds to 6.2.1 RDR_to_PC_DataBlock. */ @AutoValue public abstract static class CcidDataBlock { 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 4fa786715..5cfe38e36 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 @@ -54,7 +54,10 @@ public class T1TpduProtocol implements CcidTransportProtocol { // TODO: set checksum from atr blockFactory = new T1TpduBlockFactory(BlockChecksumAlgorithm.LRC); - performPpsExchange(); + boolean skipPpsExchange = ccidTransceiver.hasAutomaticPps(); + if (!skipPpsExchange) { + performPpsExchange(); + } } private void performPpsExchange() throws UsbTransportException { diff --git a/OpenKeychain/src/test/java/org/sufficientlysecure/keychain/securitytoken/usb/CcidTransceiverTest.java b/OpenKeychain/src/test/java/org/sufficientlysecure/keychain/securitytoken/usb/CcidTransceiverTest.java index 626c680ae..1cf41ea82 100644 --- a/OpenKeychain/src/test/java/org/sufficientlysecure/keychain/securitytoken/usb/CcidTransceiverTest.java +++ b/OpenKeychain/src/test/java/org/sufficientlysecure/keychain/securitytoken/usb/CcidTransceiverTest.java @@ -269,6 +269,14 @@ public class CcidTransceiverTest { assertArrayEquals(Hex.decode(responseData), ccidDataBlock.getData()); } + @Test + public void testReturnsCorrectAutoPpsFlag() throws Exception { + CcidDescription description = CcidDescription.fromValues((byte) 0, (byte) 7, 3, 65722); + CcidTransceiver ccidTransceiver = new CcidTransceiver(usbConnection, usbBulkIn, usbBulkOut, description); + + assertTrue(ccidTransceiver.hasAutomaticPps()); + } + private void verifyDialog() { assertTrue(expectReplies.isEmpty()); assertFalse(expectRepliesVerify.isEmpty());