Use check for life cycle management to determine if token supports reset
This commit is contained in:
@@ -17,7 +17,10 @@
|
|||||||
|
|
||||||
package org.sufficientlysecure.keychain.securitytoken;
|
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.securitytoken.usb.UsbTransportException;
|
||||||
|
import org.sufficientlysecure.keychain.util.Log;
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
@@ -72,7 +75,7 @@ class CardCapabilities {
|
|||||||
return capabilityBytes != null && (capabilityBytes[2] & MASK_EXTENDED) != 0;
|
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);
|
byte[] lastBytes = Arrays.copyOfRange(historicalBytes, historicalBytes.length - 2, historicalBytes.length);
|
||||||
boolean hasExpectedLastBytes = Arrays.equals(lastBytes, EXPECTED_PROCESSING_STATUS_BYTES);
|
boolean hasExpectedLastBytes = Arrays.equals(lastBytes, EXPECTED_PROCESSING_STATUS_BYTES);
|
||||||
|
|
||||||
|
|||||||
@@ -990,11 +990,12 @@ public class SecurityTokenConnection {
|
|||||||
String userId = getUserId();
|
String userId = getUserId();
|
||||||
String url = getUrl();
|
String url = getUrl();
|
||||||
byte[] pwInfo = getPwStatusBytes();
|
byte[] pwInfo = getPwStatusBytes();
|
||||||
|
boolean hasLifeCycleManagement = mCardCapabilities.hasLifeCycleManagement();
|
||||||
|
|
||||||
TransportType transportType = mTransport.getTransportType();
|
TransportType transportType = mTransport.getTransportType();
|
||||||
|
|
||||||
SecurityTokenInfo info = SecurityTokenInfo
|
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()) {
|
if (! info.isSecurityTokenSupported()) {
|
||||||
throw new UnsupportedSecurityTokenException();
|
throw new UnsupportedSecurityTokenException();
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ public abstract class SecurityTokenInfo implements Parcelable {
|
|||||||
public abstract String getUrl();
|
public abstract String getUrl();
|
||||||
public abstract int getVerifyRetries();
|
public abstract int getVerifyRetries();
|
||||||
public abstract int getVerifyAdminRetries();
|
public abstract int getVerifyAdminRetries();
|
||||||
|
public abstract boolean hasLifeCycleManagement();
|
||||||
|
|
||||||
public boolean isEmpty() {
|
public boolean isEmpty() {
|
||||||
return getFingerprints().isEmpty();
|
return getFingerprints().isEmpty();
|
||||||
@@ -42,7 +43,8 @@ public abstract class SecurityTokenInfo implements Parcelable {
|
|||||||
|
|
||||||
public static SecurityTokenInfo create(TransportType transportType, TokenType tokenType, byte[][] fingerprints,
|
public static SecurityTokenInfo create(TransportType transportType, TokenType tokenType, byte[][] fingerprints,
|
||||||
byte[] aid, String userId, String url,
|
byte[] aid, String userId, String url,
|
||||||
int verifyRetries, int verifyAdminRetries) {
|
int verifyRetries, int verifyAdminRetries,
|
||||||
|
boolean hasLifeCycleSupport) {
|
||||||
ArrayList<byte[]> fingerprintList = new ArrayList<>(fingerprints.length);
|
ArrayList<byte[]> fingerprintList = new ArrayList<>(fingerprints.length);
|
||||||
for (byte[] fingerprint : fingerprints) {
|
for (byte[] fingerprint : fingerprints) {
|
||||||
if (!Arrays.equals(EMPTY_ARRAY, fingerprint)) {
|
if (!Arrays.equals(EMPTY_ARRAY, fingerprint)) {
|
||||||
@@ -50,7 +52,7 @@ public abstract class SecurityTokenInfo implements Parcelable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return new AutoValue_SecurityTokenInfo(
|
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() {
|
public static SecurityTokenInfo newInstanceDebugKeyserver() {
|
||||||
@@ -59,7 +61,7 @@ public abstract class SecurityTokenInfo implements Parcelable {
|
|||||||
}
|
}
|
||||||
return SecurityTokenInfo.create(TransportType.NFC, TokenType.UNKNOWN,
|
return SecurityTokenInfo.create(TransportType.NFC, TokenType.UNKNOWN,
|
||||||
new byte[][] { KeyFormattingUtils.convertFingerprintHexFingerprint("1efdb4845ca242ca6977fddb1f788094fd3b430a") },
|
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() {
|
public static SecurityTokenInfo newInstanceDebugUri() {
|
||||||
@@ -68,7 +70,7 @@ public abstract class SecurityTokenInfo implements Parcelable {
|
|||||||
}
|
}
|
||||||
return SecurityTokenInfo.create(TransportType.NFC, TokenType.UNKNOWN,
|
return SecurityTokenInfo.create(TransportType.NFC, TokenType.UNKNOWN,
|
||||||
new byte[][] { KeyFormattingUtils.convertFingerprintHexFingerprint("4700BA1AC417ABEF3CC7765AD686905837779C3E") },
|
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() {
|
public static SecurityTokenInfo newInstanceDebugLocked() {
|
||||||
@@ -77,7 +79,7 @@ public abstract class SecurityTokenInfo implements Parcelable {
|
|||||||
}
|
}
|
||||||
return SecurityTokenInfo.create(TransportType.NFC, TokenType.UNKNOWN,
|
return SecurityTokenInfo.create(TransportType.NFC, TokenType.UNKNOWN,
|
||||||
new byte[][] { KeyFormattingUtils.convertFingerprintHexFingerprint("4700BA1AC417ABEF3CC7765AD686905837779C3E") },
|
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() {
|
public static SecurityTokenInfo newInstanceDebugLockedHard() {
|
||||||
@@ -86,7 +88,7 @@ public abstract class SecurityTokenInfo implements Parcelable {
|
|||||||
}
|
}
|
||||||
return SecurityTokenInfo.create(TransportType.NFC, TokenType.UNKNOWN,
|
return SecurityTokenInfo.create(TransportType.NFC, TokenType.UNKNOWN,
|
||||||
new byte[][] { KeyFormattingUtils.convertFingerprintHexFingerprint("4700BA1AC417ABEF3CC7765AD686905837779C3E") },
|
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 {
|
public enum TransportType {
|
||||||
@@ -138,8 +140,9 @@ public abstract class SecurityTokenInfo implements Parcelable {
|
|||||||
public boolean isResetSupported() {
|
public boolean isResetSupported() {
|
||||||
boolean isKnownSupported = SUPPORTED_USB_RESET.contains(getTokenType());
|
boolean isKnownSupported = SUPPORTED_USB_RESET.contains(getTokenType());
|
||||||
boolean isNfcTransport = getTransportType() == TransportType.NFC;
|
boolean isNfcTransport = getTransportType() == TransportType.NFC;
|
||||||
|
boolean hasLifeCycleManagement = hasLifeCycleManagement();
|
||||||
|
|
||||||
return isKnownSupported || isNfcTransport;
|
return (isKnownSupported || isNfcTransport) && hasLifeCycleManagement;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Version parseGnukVersionString(String serialNo) {
|
public static Version parseGnukVersionString(String serialNo) {
|
||||||
|
|||||||
@@ -167,31 +167,31 @@ public class SecurityTokenUtilsTest extends Mockito {
|
|||||||
capabilities = new CardCapabilities(Hex.decode("007300008000000000000000000000"));
|
capabilities = new CardCapabilities(Hex.decode("007300008000000000000000000000"));
|
||||||
Assert.assertEquals(capabilities.hasChaining(), true);
|
Assert.assertEquals(capabilities.hasChaining(), true);
|
||||||
Assert.assertEquals(capabilities.hasExtended(), false);
|
Assert.assertEquals(capabilities.hasExtended(), false);
|
||||||
Assert.assertEquals(capabilities.hasResetSupport(), true);
|
Assert.assertEquals(capabilities.hasLifeCycleManagement(), true);
|
||||||
|
|
||||||
// Yk 4
|
// Yk 4
|
||||||
capabilities = new CardCapabilities(Hex.decode("0073000080059000"));
|
capabilities = new CardCapabilities(Hex.decode("0073000080059000"));
|
||||||
Assert.assertEquals(capabilities.hasChaining(), true);
|
Assert.assertEquals(capabilities.hasChaining(), true);
|
||||||
Assert.assertEquals(capabilities.hasExtended(), false);
|
Assert.assertEquals(capabilities.hasExtended(), false);
|
||||||
Assert.assertEquals(capabilities.hasResetSupport(), true);
|
Assert.assertEquals(capabilities.hasLifeCycleManagement(), true);
|
||||||
|
|
||||||
// Nitrokey pro
|
// Nitrokey pro
|
||||||
capabilities = new CardCapabilities(Hex.decode("0031c573c00140059000"));
|
capabilities = new CardCapabilities(Hex.decode("0031c573c00140059000"));
|
||||||
Assert.assertEquals(capabilities.hasChaining(), false);
|
Assert.assertEquals(capabilities.hasChaining(), false);
|
||||||
Assert.assertEquals(capabilities.hasExtended(), true);
|
Assert.assertEquals(capabilities.hasExtended(), true);
|
||||||
Assert.assertEquals(capabilities.hasResetSupport(), true);
|
Assert.assertEquals(capabilities.hasLifeCycleManagement(), true);
|
||||||
|
|
||||||
// GNUK without Life Cycle Management
|
// GNUK without Life Cycle Management
|
||||||
capabilities = new CardCapabilities(Hex.decode("00318473800180009000"));
|
capabilities = new CardCapabilities(Hex.decode("00318473800180009000"));
|
||||||
Assert.assertEquals(capabilities.hasChaining(), true);
|
Assert.assertEquals(capabilities.hasChaining(), true);
|
||||||
Assert.assertEquals(capabilities.hasExtended(), false);
|
Assert.assertEquals(capabilities.hasExtended(), false);
|
||||||
Assert.assertEquals(capabilities.hasResetSupport(), false);
|
Assert.assertEquals(capabilities.hasLifeCycleManagement(), false);
|
||||||
|
|
||||||
// GNUK with Life Cycle Management: ./configure --enable-factory-reset
|
// GNUK with Life Cycle Management: ./configure --enable-factory-reset
|
||||||
capabilities = new CardCapabilities(Hex.decode("00318473800180059000"));
|
capabilities = new CardCapabilities(Hex.decode("00318473800180059000"));
|
||||||
Assert.assertEquals(capabilities.hasChaining(), true);
|
Assert.assertEquals(capabilities.hasChaining(), true);
|
||||||
Assert.assertEquals(capabilities.hasExtended(), false);
|
Assert.assertEquals(capabilities.hasExtended(), false);
|
||||||
Assert.assertEquals(capabilities.hasResetSupport(), true);
|
Assert.assertEquals(capabilities.hasLifeCycleManagement(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
Reference in New Issue
Block a user