Use check for life cycle management to determine if token supports reset

This commit is contained in:
Dominik Schürmann 2017-11-02 19:13:44 +01:00
parent 90310b7036
commit 8acf62a0e8
4 changed files with 21 additions and 14 deletions

View file

@ -17,7 +17,10 @@
package org.sufficientlysecure.keychain.securitytoken;
import org.bouncycastle.util.encoders.Hex;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.securitytoken.usb.UsbTransportException;
import org.sufficientlysecure.keychain.util.Log;
import java.nio.ByteBuffer;
import java.util.Arrays;
@ -72,7 +75,7 @@ class CardCapabilities {
return capabilityBytes != null && (capabilityBytes[2] & MASK_EXTENDED) != 0;
}
public boolean hasResetSupport() throws UsbTransportException {
public boolean hasLifeCycleManagement() throws UsbTransportException {
byte[] lastBytes = Arrays.copyOfRange(historicalBytes, historicalBytes.length - 2, historicalBytes.length);
boolean hasExpectedLastBytes = Arrays.equals(lastBytes, EXPECTED_PROCESSING_STATUS_BYTES);

View file

@ -990,11 +990,12 @@ public class SecurityTokenConnection {
String userId = getUserId();
String url = getUrl();
byte[] pwInfo = getPwStatusBytes();
boolean hasLifeCycleManagement = mCardCapabilities.hasLifeCycleManagement();
TransportType transportType = mTransport.getTransportType();
SecurityTokenInfo info = SecurityTokenInfo
.create(transportType, tokenType, fingerprints, aid, userId, url, pwInfo[4], pwInfo[6]);
.create(transportType, tokenType, fingerprints, aid, userId, url, pwInfo[4], pwInfo[6], hasLifeCycleManagement);
if (! info.isSecurityTokenSupported()) {
throw new UnsupportedSecurityTokenException();

View file

@ -35,6 +35,7 @@ public abstract class SecurityTokenInfo implements Parcelable {
public abstract String getUrl();
public abstract int getVerifyRetries();
public abstract int getVerifyAdminRetries();
public abstract boolean hasLifeCycleManagement();
public boolean isEmpty() {
return getFingerprints().isEmpty();
@ -42,7 +43,8 @@ public abstract class SecurityTokenInfo implements Parcelable {
public static SecurityTokenInfo create(TransportType transportType, TokenType tokenType, byte[][] fingerprints,
byte[] aid, String userId, String url,
int verifyRetries, int verifyAdminRetries) {
int verifyRetries, int verifyAdminRetries,
boolean hasLifeCycleSupport) {
ArrayList<byte[]> fingerprintList = new ArrayList<>(fingerprints.length);
for (byte[] fingerprint : fingerprints) {
if (!Arrays.equals(EMPTY_ARRAY, fingerprint)) {
@ -50,7 +52,7 @@ public abstract class SecurityTokenInfo implements Parcelable {
}
}
return new AutoValue_SecurityTokenInfo(
transportType, tokenType, fingerprintList, aid, userId, url, verifyRetries, verifyAdminRetries);
transportType, tokenType, fingerprintList, aid, userId, url, verifyRetries, verifyAdminRetries, hasLifeCycleSupport);
}
public static SecurityTokenInfo newInstanceDebugKeyserver() {
@ -59,7 +61,7 @@ public abstract class SecurityTokenInfo implements Parcelable {
}
return SecurityTokenInfo.create(TransportType.NFC, TokenType.UNKNOWN,
new byte[][] { KeyFormattingUtils.convertFingerprintHexFingerprint("1efdb4845ca242ca6977fddb1f788094fd3b430a") },
Hex.decode("010203040506"), "yubinu2@mugenguild.com", null, 3, 3);
Hex.decode("010203040506"), "yubinu2@mugenguild.com", null, 3, 3, true);
}
public static SecurityTokenInfo newInstanceDebugUri() {
@ -68,7 +70,7 @@ public abstract class SecurityTokenInfo implements Parcelable {
}
return SecurityTokenInfo.create(TransportType.NFC, TokenType.UNKNOWN,
new byte[][] { KeyFormattingUtils.convertFingerprintHexFingerprint("4700BA1AC417ABEF3CC7765AD686905837779C3E") },
Hex.decode("010203040506"), "yubinu2@mugenguild.com", "http://valodim.stratum0.net/mryubinu2.asc", 3, 3);
Hex.decode("010203040506"), "yubinu2@mugenguild.com", "http://valodim.stratum0.net/mryubinu2.asc", 3, 3, true);
}
public static SecurityTokenInfo newInstanceDebugLocked() {
@ -77,7 +79,7 @@ public abstract class SecurityTokenInfo implements Parcelable {
}
return SecurityTokenInfo.create(TransportType.NFC, TokenType.UNKNOWN,
new byte[][] { KeyFormattingUtils.convertFingerprintHexFingerprint("4700BA1AC417ABEF3CC7765AD686905837779C3E") },
Hex.decode("010203040506"), "yubinu2@mugenguild.com", "http://valodim.stratum0.net/mryubinu2.asc", 0, 3);
Hex.decode("010203040506"), "yubinu2@mugenguild.com", "http://valodim.stratum0.net/mryubinu2.asc", 0, 3, true);
}
public static SecurityTokenInfo newInstanceDebugLockedHard() {
@ -86,7 +88,7 @@ public abstract class SecurityTokenInfo implements Parcelable {
}
return SecurityTokenInfo.create(TransportType.NFC, TokenType.UNKNOWN,
new byte[][] { KeyFormattingUtils.convertFingerprintHexFingerprint("4700BA1AC417ABEF3CC7765AD686905837779C3E") },
Hex.decode("010203040506"), "yubinu2@mugenguild.com", "http://valodim.stratum0.net/mryubinu2.asc", 0, 0);
Hex.decode("010203040506"), "yubinu2@mugenguild.com", "http://valodim.stratum0.net/mryubinu2.asc", 0, 0, true);
}
public enum TransportType {
@ -138,8 +140,9 @@ public abstract class SecurityTokenInfo implements Parcelable {
public boolean isResetSupported() {
boolean isKnownSupported = SUPPORTED_USB_RESET.contains(getTokenType());
boolean isNfcTransport = getTransportType() == TransportType.NFC;
boolean hasLifeCycleManagement = hasLifeCycleManagement();
return isKnownSupported || isNfcTransport;
return (isKnownSupported || isNfcTransport) && hasLifeCycleManagement;
}
public static Version parseGnukVersionString(String serialNo) {

View file

@ -167,31 +167,31 @@ public class SecurityTokenUtilsTest extends Mockito {
capabilities = new CardCapabilities(Hex.decode("007300008000000000000000000000"));
Assert.assertEquals(capabilities.hasChaining(), true);
Assert.assertEquals(capabilities.hasExtended(), false);
Assert.assertEquals(capabilities.hasResetSupport(), true);
Assert.assertEquals(capabilities.hasLifeCycleManagement(), true);
// Yk 4
capabilities = new CardCapabilities(Hex.decode("0073000080059000"));
Assert.assertEquals(capabilities.hasChaining(), true);
Assert.assertEquals(capabilities.hasExtended(), false);
Assert.assertEquals(capabilities.hasResetSupport(), true);
Assert.assertEquals(capabilities.hasLifeCycleManagement(), true);
// Nitrokey pro
capabilities = new CardCapabilities(Hex.decode("0031c573c00140059000"));
Assert.assertEquals(capabilities.hasChaining(), false);
Assert.assertEquals(capabilities.hasExtended(), true);
Assert.assertEquals(capabilities.hasResetSupport(), true);
Assert.assertEquals(capabilities.hasLifeCycleManagement(), true);
// GNUK without Life Cycle Management
capabilities = new CardCapabilities(Hex.decode("00318473800180009000"));
Assert.assertEquals(capabilities.hasChaining(), true);
Assert.assertEquals(capabilities.hasExtended(), false);
Assert.assertEquals(capabilities.hasResetSupport(), false);
Assert.assertEquals(capabilities.hasLifeCycleManagement(), false);
// GNUK with Life Cycle Management: ./configure --enable-factory-reset
capabilities = new CardCapabilities(Hex.decode("00318473800180059000"));
Assert.assertEquals(capabilities.hasChaining(), true);
Assert.assertEquals(capabilities.hasExtended(), false);
Assert.assertEquals(capabilities.hasResetSupport(), true);
Assert.assertEquals(capabilities.hasLifeCycleManagement(), true);
}
@Test