diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/securitytoken/NfcTransport.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/securitytoken/NfcTransport.java index 808b92410..222228938 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/securitytoken/NfcTransport.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/securitytoken/NfcTransport.java @@ -22,6 +22,8 @@ import android.util.Log; import org.bouncycastle.util.encoders.Hex; import org.sufficientlysecure.keychain.Constants; +import org.sufficientlysecure.keychain.securitytoken.SecurityTokenInfo.TokenType; +import org.sufficientlysecure.keychain.securitytoken.SecurityTokenInfo.TransportType; import org.sufficientlysecure.keychain.ui.base.BaseSecurityTokenActivity; import java.io.IOException; @@ -103,6 +105,16 @@ public class NfcTransport implements Transport { mIsoCard.connect(); } + @Override + public TransportType getTransportType() { + return TransportType.NFC; + } + + @Override + public TokenType getTokenType() { + return null; + } + @Override public boolean equals(final Object o) { if (this == o) return true; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/securitytoken/SecurityTokenConnection.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/securitytoken/SecurityTokenConnection.java index 2a52f7586..c14b016c3 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/securitytoken/SecurityTokenConnection.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/securitytoken/SecurityTokenConnection.java @@ -48,6 +48,8 @@ import javax.crypto.Cipher; import javax.crypto.NoSuchPaddingException; import javax.crypto.spec.SecretKeySpec; +import org.sufficientlysecure.keychain.securitytoken.SecurityTokenInfo.TokenType; +import org.sufficientlysecure.keychain.securitytoken.SecurityTokenInfo.TransportType; import org.sufficientlysecure.keychain.securitytoken.usb.UsbTransportException; import org.sufficientlysecure.keychain.util.Log; import org.sufficientlysecure.keychain.util.Passphrase; @@ -948,7 +950,15 @@ public class SecurityTokenConnection { String url = getUrl(); byte[] pwInfo = getPwStatusBytes(); - return SecurityTokenInfo.create(fingerprints, aid, userId, url, pwInfo[4], pwInfo[6]); + TransportType transportType = mTransport.getTransportType(); + TokenType tokenType; + if (transportType == TransportType.USB) { + tokenType = mTransport.getTokenType(); + } else { + tokenType = isFidesmoToken() ? TokenType.FIDESMO : TokenType.UNKNOWN; + } + + return SecurityTokenInfo.create(transportType, tokenType, fingerprints, aid, userId, url, pwInfo[4], pwInfo[6]); } public static double parseOpenPgpVersion(final byte[] aid) { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/securitytoken/SecurityTokenInfo.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/securitytoken/SecurityTokenInfo.java index 9a2cb6b37..a1ceef774 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/securitytoken/SecurityTokenInfo.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/securitytoken/SecurityTokenInfo.java @@ -18,6 +18,9 @@ import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils; public abstract class SecurityTokenInfo implements Parcelable { private static final byte[] EMPTY_ARRAY = new byte[20]; + public abstract TransportType getTransportType(); + public abstract TokenType getTokenType(); + public abstract List getFingerprints(); @Nullable public abstract byte[] getAid(); @@ -32,7 +35,8 @@ public abstract class SecurityTokenInfo implements Parcelable { return getFingerprints().isEmpty(); } - public static SecurityTokenInfo create(byte[][] fingerprints, byte[] aid, String userId, String url, + public static SecurityTokenInfo create(TransportType transportType, TokenType tokenType, byte[][] fingerprints, + byte[] aid, String userId, String url, int verifyRetries, int verifyAdminRetries) { ArrayList fingerprintList = new ArrayList<>(fingerprints.length); for (byte[] fingerprint : fingerprints) { @@ -40,14 +44,15 @@ public abstract class SecurityTokenInfo implements Parcelable { fingerprintList.add(fingerprint); } } - return new AutoValue_SecurityTokenInfo(fingerprintList, aid, userId, url, verifyRetries, verifyAdminRetries); + return new AutoValue_SecurityTokenInfo( + transportType, tokenType, fingerprintList, aid, userId, url, verifyRetries, verifyAdminRetries); } public static SecurityTokenInfo newInstanceDebugKeyserver() { if (!BuildConfig.DEBUG) { throw new UnsupportedOperationException("This operation is only available in debug builds!"); } - return SecurityTokenInfo.create( + return SecurityTokenInfo.create(TransportType.NFC, TokenType.UNKNOWN, new byte[][] { KeyFormattingUtils.convertFingerprintHexFingerprint("1efdb4845ca242ca6977fddb1f788094fd3b430a") }, Hex.decode("010203040506"), "yubinu2@mugenguild.com", null, 3, 3); } @@ -56,7 +61,7 @@ public abstract class SecurityTokenInfo implements Parcelable { if (!BuildConfig.DEBUG) { throw new UnsupportedOperationException("This operation is only available in debug builds!"); } - return SecurityTokenInfo.create( + 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); } @@ -65,7 +70,7 @@ public abstract class SecurityTokenInfo implements Parcelable { if (!BuildConfig.DEBUG) { throw new UnsupportedOperationException("This operation is only available in debug builds!"); } - return SecurityTokenInfo.create( + 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); } @@ -74,9 +79,17 @@ public abstract class SecurityTokenInfo implements Parcelable { if (!BuildConfig.DEBUG) { throw new UnsupportedOperationException("This operation is only available in debug builds!"); } - return SecurityTokenInfo.create( + 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); } + public enum TransportType { + NFC, USB + } + + public enum TokenType { + YUBIKEY_NEO, YUBIKEY_4, FIDESMO, NITROKEY_PRO, NITROKEY_STORAGE, NITROKEY_START, GNUK, LEDGER_NANO_S, UNKNOWN + } + } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/securitytoken/Transport.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/securitytoken/Transport.java index 2d82842dc..033ac1dc4 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/securitytoken/Transport.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/securitytoken/Transport.java @@ -17,6 +17,9 @@ package org.sufficientlysecure.keychain.securitytoken; +import org.sufficientlysecure.keychain.securitytoken.SecurityTokenInfo.TokenType; +import org.sufficientlysecure.keychain.securitytoken.SecurityTokenInfo.TransportType; + import java.io.IOException; /** @@ -55,4 +58,8 @@ public interface Transport { * @throws IOException */ void connect() throws IOException; + + TransportType getTransportType(); + + TokenType getTokenType(); } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/securitytoken/usb/UsbTransport.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/securitytoken/usb/UsbTransport.java index bf814b6d6..a92612ef0 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/securitytoken/usb/UsbTransport.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/securitytoken/usb/UsbTransport.java @@ -28,6 +28,8 @@ import android.support.annotation.Nullable; import android.util.Pair; import org.sufficientlysecure.keychain.Constants; +import org.sufficientlysecure.keychain.securitytoken.SecurityTokenInfo.TokenType; +import org.sufficientlysecure.keychain.securitytoken.SecurityTokenInfo.TransportType; import org.sufficientlysecure.keychain.securitytoken.Transport; import org.sufficientlysecure.keychain.securitytoken.CommandApdu; import org.sufficientlysecure.keychain.securitytoken.ResponseApdu; @@ -201,6 +203,49 @@ public class UsbTransport implements Transport { return usbDevice != null ? usbDevice.hashCode() : 0; } + @Override + public TransportType getTransportType() { + return TransportType.USB; + } + + @Override + public TokenType getTokenType() { + switch (usbDevice.getVendorId()) { + case 4176: { + switch (usbDevice.getProductId()) { + case 273: + case 274: + case 277: + case 278: + return TokenType.YUBIKEY_NEO; + case 1028: + case 1029: + case 1030: + case 1031: + return TokenType.YUBIKEY_4; + } + break; + } + case 8352: { + switch (usbDevice.getProductId()) { + case 16648: + return TokenType.NITROKEY_PRO; + case 16913: + return TokenType.NITROKEY_START; + case 16649: + return TokenType.NITROKEY_STORAGE; + } + break; + } + case 9035: { + return TokenType.GNUK; + } + case 11415: { + return TokenType.LEDGER_NANO_S; + } + } + throw new IllegalStateException("Unhandled usb token type!"); + } /** * Get first class 11 (Chip/Smartcard) interface of the device diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/BaseSecurityTokenActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/BaseSecurityTokenActivity.java index 4e8ba2e10..f39d6bcd2 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/BaseSecurityTokenActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/BaseSecurityTokenActivity.java @@ -45,6 +45,7 @@ import org.sufficientlysecure.keychain.securitytoken.CardException; import org.sufficientlysecure.keychain.securitytoken.NfcTransport; import org.sufficientlysecure.keychain.securitytoken.SecurityTokenConnection; import org.sufficientlysecure.keychain.securitytoken.SecurityTokenInfo; +import org.sufficientlysecure.keychain.securitytoken.SecurityTokenInfo.TokenType; import org.sufficientlysecure.keychain.securitytoken.Transport; import org.sufficientlysecure.keychain.securitytoken.UsbConnectionDispatcher; import org.sufficientlysecure.keychain.securitytoken.usb.UsbTransport;