From a8c192b55154a6133ddb604c5d20ec839e538b7d Mon Sep 17 00:00:00 2001 From: Dain Nilsson Date: Wed, 12 Oct 2022 09:53:16 -0700 Subject: [PATCH 01/24] Initial stab at desktop support. --- DesktopDemo/.gitignore | 1 + DesktopDemo/build.gradle | 20 ++ .../yubikit/desktop/app/DesktopApp.java | 288 ++++++++++++++++++ .../yubikit/desktop/app/package-info.java | 4 + desktop/.gitignore | 1 + desktop/build.gradle | 17 ++ .../com/yubico/yubikit/desktop/HidDevice.java | 66 ++++ .../yubikit/desktop/HidFidoConnection.java | 51 ++++ .../yubikit/desktop/HidOtpConnection.java | 44 +++ .../yubikit/desktop/HidSessionListener.java | 33 ++ .../yubikit/desktop/PcscConfiguration.java | 47 +++ .../yubico/yubikit/desktop/PcscDevice.java | 102 +++++++ .../yubikit/desktop/PcscSessionListener.java | 33 ++ .../desktop/PcscSmartCardConnection.java | 66 ++++ .../yubikit/desktop/YubiKitHidManager.java | 37 +++ .../yubikit/desktop/YubiKitManager.java | 85 ++++++ .../yubico/yubikit/desktop/package-info.java | 4 + settings.gradle | 1 + 18 files changed, 900 insertions(+) create mode 100755 DesktopDemo/.gitignore create mode 100755 DesktopDemo/build.gradle create mode 100755 DesktopDemo/src/main/java/com/yubico/yubikit/desktop/app/DesktopApp.java create mode 100755 DesktopDemo/src/main/java/com/yubico/yubikit/desktop/app/package-info.java create mode 100755 desktop/.gitignore create mode 100755 desktop/build.gradle create mode 100755 desktop/src/main/java/com/yubico/yubikit/desktop/HidDevice.java create mode 100755 desktop/src/main/java/com/yubico/yubikit/desktop/HidFidoConnection.java create mode 100755 desktop/src/main/java/com/yubico/yubikit/desktop/HidOtpConnection.java create mode 100755 desktop/src/main/java/com/yubico/yubikit/desktop/HidSessionListener.java create mode 100755 desktop/src/main/java/com/yubico/yubikit/desktop/PcscConfiguration.java create mode 100755 desktop/src/main/java/com/yubico/yubikit/desktop/PcscDevice.java create mode 100755 desktop/src/main/java/com/yubico/yubikit/desktop/PcscSessionListener.java create mode 100755 desktop/src/main/java/com/yubico/yubikit/desktop/PcscSmartCardConnection.java create mode 100755 desktop/src/main/java/com/yubico/yubikit/desktop/YubiKitHidManager.java create mode 100755 desktop/src/main/java/com/yubico/yubikit/desktop/YubiKitManager.java create mode 100755 desktop/src/main/java/com/yubico/yubikit/desktop/package-info.java diff --git a/DesktopDemo/.gitignore b/DesktopDemo/.gitignore new file mode 100755 index 00000000..42afabfd --- /dev/null +++ b/DesktopDemo/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/DesktopDemo/build.gradle b/DesktopDemo/build.gradle new file mode 100755 index 00000000..00cf9e84 --- /dev/null +++ b/DesktopDemo/build.gradle @@ -0,0 +1,20 @@ +plugins { + id 'application' +} + +dependencies { + compileOnly 'com.google.code.findbugs:jsr305:3.0.2' + + implementation project(':desktop') + implementation project(':testing') +} + +application { + mainClassName = "com.yubico.yubikit.desktop.app.DesktopApp" + applicationName = 'DesktopApp' +} + +java { + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 +} \ No newline at end of file diff --git a/DesktopDemo/src/main/java/com/yubico/yubikit/desktop/app/DesktopApp.java b/DesktopDemo/src/main/java/com/yubico/yubikit/desktop/app/DesktopApp.java new file mode 100755 index 00000000..4c8ddc46 --- /dev/null +++ b/DesktopDemo/src/main/java/com/yubico/yubikit/desktop/app/DesktopApp.java @@ -0,0 +1,288 @@ +package com.yubico.yubikit.desktop.app; + +import com.yubico.yubikit.core.Logger; +import com.yubico.yubikit.core.application.ApplicationNotAvailableException; +import com.yubico.yubikit.core.application.BadResponseException; +import com.yubico.yubikit.core.smartcard.ApduException; +import com.yubico.yubikit.desktop.HidDevice; +import com.yubico.yubikit.desktop.HidSessionListener; +import com.yubico.yubikit.desktop.PcscConfiguration; +import com.yubico.yubikit.desktop.PcscDevice; +import com.yubico.yubikit.desktop.PcscSessionListener; +import com.yubico.yubikit.desktop.YubiKitHidManager; +import com.yubico.yubikit.desktop.YubiKitManager; +import com.yubico.yubikit.piv.KeyType; +import com.yubico.yubikit.piv.ManagementKeyType; +import com.yubico.yubikit.piv.PinPolicy; +import com.yubico.yubikit.piv.PivSession; +import com.yubico.yubikit.piv.Slot; +import com.yubico.yubikit.piv.SlotMetadata; +import com.yubico.yubikit.piv.TouchPolicy; +import com.yubico.yubikit.piv.jca.PivAlgorithmParameterSpec; +import com.yubico.yubikit.piv.jca.PivKeyManager; +import com.yubico.yubikit.piv.jca.PivPrivateKey; +import com.yubico.yubikit.piv.jca.PivProvider; +import com.yubico.yubikit.testing.Codec; +import com.yubico.yubikit.testing.piv.PivTestUtils; +import com.yubico.yubikit.yubiotp.YubiOtpSession; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.URL; +import java.nio.charset.StandardCharsets; +import java.security.InvalidAlgorithmParameterException; +import java.security.InvalidKeyException; +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.KeyStore; +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; +import java.security.Provider; +import java.security.Security; +import java.security.SignatureException; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; +import java.util.concurrent.Semaphore; + +import javax.net.ssl.HttpsURLConnection; +import javax.net.ssl.KeyManager; +import javax.net.ssl.SSLContext; + +public class DesktopApp { + public static void main(String[] argv) { + System.out.println("Insert YubiKey now..."); + + Logger.setLogger(new Logger() { + @Override + protected void logDebug(String message) { + System.err.println("DEBUG: " + message); + } + + @Override + protected void logError(String message, Throwable throwable) { + System.err.println("ERROR: " + message); + throwable.printStackTrace(); + } + }); + + //testHidOtp(); + testCcid(); + + Logger.d("Application exited"); + } + + private static void testCcid() { + YubiKitManager yubikit = new YubiKitManager(); + + yubikit.run(new PcscConfiguration(), new PcscSessionListener() { + @Override + public void onSessionReceived(PcscDevice session) { + /* + if (session.getInterface() == Interface.NFC) { + try { + byte[] ndefData = session.readNdef(); + String otp = NdefUtils.getNdefPayload(ndefData); + Logger.d("Read OTP: " + otp); + } catch (IOException | ApduException | ApplicationNotAvailableException e) { + e.printStackTrace(); + } + } + + */ + + testPiv(session); + + try (PivSession piv = new PivSession(session.openIso7816Connection())) { + /* + PivJcaDeviceTests.testImportKeys(piv); + PivJcaDeviceTests.testGenerateKeys(piv); + + PivDeviceTests.testSign(piv, KeyType.ECCP256); + PivDeviceTests.testSign(piv, KeyType.RSA2048); + PivDeviceTests.testDecrypt(piv, KeyType.RSA2048); + */ + + //testHttps(piv); + + /* + for (Slot slot : Arrays.asList(Slot.AUTHENTICATION, Slot.SIGNATURE, Slot.CARD_AUTH, Slot.KEY_MANAGEMENT)) { + System.out.println("Slot: " + slot); + try { + System.out.println(piv.getCertificate(slot)); + } catch (ApduException | BadResponseException e) { + System.out.println("No certificate"); + } + }*/ + } catch (Exception e) { + e.printStackTrace(); + } + + yubikit.stop(); + } + + @Override + public void onSessionRemoved(PcscDevice session) { + Logger.d("Shutting down..."); + yubikit.stop(); + } + }); + } + + private static void testHttps(PivSession piv) throws Exception { + Security.addProvider(new PivProvider(piv)); + + URL url = new URL("https://dain.se:8443"); + + KeyStore keyStore = KeyStore.getInstance("YKPiv"); + keyStore.load(null); + PivPrivateKey privateKey = (PivPrivateKey) keyStore.getKey("9a", "123456".toCharArray()); + + X509Certificate certificate = (X509Certificate) keyStore.getCertificate("9a"); + //PivPrivateKey privateKey = PivPrivateKey.from(certificate.getPublicKey(), Slot.AUTHENTICATION, null); + + SSLContext sslContext = SSLContext.getInstance("TLS"); + sslContext.init(new KeyManager[]{new PivKeyManager(privateKey, new X509Certificate[]{certificate})}, null, null); + + HttpsURLConnection connection = (HttpsURLConnection) url.openConnection(); + connection.setSSLSocketFactory(sslContext.getSocketFactory()); + + piv.verifyPin("123456".toCharArray()); + + try(BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream(), StandardCharsets.UTF_8))) { + reader.lines().forEach(Logger::d); + } + + Security.removeProvider("YKPiv"); + } + + private static void testPiv(PcscDevice session) { + try (PivSession piv = new PivSession(session.openIso7816Connection())) { + //piv.authenticate(new byte[]{1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8}); + //Logger.d("Generate key..."); + //piv.generateKey(Slot.SIGNATURE, KeyType.ECCP256, PinPolicy.DEFAULT, TouchPolicy.DEFAULT); + try { + Logger.d("Get metadata..."); + SlotMetadata metadata = piv.getSlotMetadata(Slot.AUTHENTICATION); + Logger.d("Metadata: " + metadata.getKeyType() + ", " + metadata.isGenerated() + ", " + metadata.getPinPolicy() + ", " + metadata.getPublicKey()); + + } catch (UnsupportedOperationException e) { + Logger.e("Metadata not supported", e); + } + piv.authenticate(ManagementKeyType.TDES, Codec.fromHex("010203040506070801020304050607080102030405060708")); + + Provider provider = new PivProvider(piv); + Security.addProvider(provider); + + // Create certificate + //Provider provider = new PivProvider(piv); + KeyPairGenerator kpg = KeyPairGenerator.getInstance("EC", provider); + kpg.initialize(new PivAlgorithmParameterSpec(Slot.AUTHENTICATION, KeyType.ECCP256, PinPolicy.ALWAYS, TouchPolicy.DEFAULT, "123456".toCharArray())); + KeyPair keyPair = kpg.generateKeyPair(); + + X509Certificate cert = PivTestUtils.createCertificate(keyPair); + cert.verify(keyPair.getPublic()); + piv.putCertificate(Slot.AUTHENTICATION, cert); + + piv.getCertificate(Slot.AUTHENTICATION); + + //Logger.d("Metadata management: " + piv.getSlotMetadata(Slot.CARD_MANAGEMENT)); + + //Logger.d("Metadata authentication: " + metadata.getKeyType() + ", " + metadata.isGenerated() + ", " + metadata.getPinPolicy() + ", " + metadata.getPublicKey()); + //metadata = piv.getSlotMetadata(Slot.SIGNATURE); + + + /* + PinMetadata pinMetadata = piv.getPinMetadata(); + Logger.d("PIN: default=" + pinMetadata.isDefaultValue() + ", total="+pinMetadata.getTotalAttempts()+", remaining="+pinMetadata.getAttemptsRemaining()); + + PinMetadata pukMetadata = piv.getPukMetadata(); + Logger.d("PUK: default=" + pukMetadata.isDefaultValue() + ", total="+pukMetadata.getTotalAttempts()+", remaining="+pukMetadata.getAttemptsRemaining()); + PivDeviceTests.testDecrypt(piv, KeyType.RSA1024); + PivDeviceTests.testDecrypt(piv, KeyType.RSA2048); + PivDeviceTests.testEcdh(piv, KeyType.ECCP256); + PivDeviceTests.testEcdh(piv, KeyType.ECCP384); + + piv.authenticate(Codec.fromHex("010203040506070801020304050607080102030405060708")); + PublicKey pub = piv.generateKey(Slot.AUTHENTICATION, KeyType.ECCP256, PinPolicy.ALWAYS, TouchPolicy.DEFAULT); + piv.verify("123456".toCharArray()); + X509Certificate cert = PivTestUtils.createCertificate(piv, pub, Slot.AUTHENTICATION, KeyType.ECCP256); + cert.verify(pub); + piv.putCertificate(Slot.AUTHENTICATION, cert); + + pub = piv.generateKey(Slot.AUTHENTICATION, KeyType.RSA1024, PinPolicy.DEFAULT, TouchPolicy.DEFAULT); + piv.verify("123456".toCharArray()); + cert = PivTestUtils.createCertificate(piv, pub, Slot.AUTHENTICATION, KeyType.RSA1024); + cert.verify(pub); + piv.putCertificate(Slot.AUTHENTICATION, cert); + + /* + PivDeviceTests.testManagementKey(piv); + PivDeviceTests.testPin(piv); + PivDeviceTests.testPuk(piv); + PivDeviceTests.testGenerateKeys(piv); + PivDeviceTests.testImportKeys(piv); + */ + } catch (RuntimeException e) { + Logger.e("Error", e.getCause() != null ? e.getCause() : e); + } catch (ApplicationNotAvailableException | ApduException | IOException e) { + Logger.e("Error", e); + } catch (SignatureException e) { + e.printStackTrace(); + } catch (BadResponseException e) { + e.printStackTrace(); + } catch (NoSuchAlgorithmException e) { + e.printStackTrace(); + } catch (CertificateException e) { + e.printStackTrace(); + } catch (InvalidKeyException e) { + e.printStackTrace(); + } catch (NoSuchProviderException e) { + e.printStackTrace(); + } catch (InvalidAlgorithmParameterException e) { + e.printStackTrace(); + } + Logger.d("PIV tests done!"); + } + + private static void testHidOtp() { + YubiKitHidManager hidManager = new YubiKitHidManager(); + + Semaphore lock = new Semaphore(0); + + hidManager.setListener(new HidSessionListener() { + @Override + public void onSessionReceived(HidDevice device) { + Logger.d("HID session started"); + YubiOtpSession.create(device, result -> { + try { + YubiOtpSession app = result.getValue(); + Logger.d("HID read version: " + app.getVersion()); + + Logger.d("Slot 1: " + app.getConfigurationState().isConfigured(com.yubico.yubikit.yubiotp.Slot.ONE)); + Logger.d("Slot 2: " + app.getConfigurationState().isConfigured(com.yubico.yubikit.yubiotp.Slot.TWO)); + //app.setHmacSha1Key(com.yubico.yubikit.otp.Slot.TWO, new byte[]{1,2,3,4,5,6}, true); + //app.setStaticPassword(com.yubico.yubikit.otp.Slot.TWO, new byte[]{(byte) 0x8b, 0x0c}); + app.swapConfigurations(); + //app.deleteSlot(com.yubico.yubikit.otp.Slot.ONE, null); + Logger.d("Configuration updated"); + } catch (Exception e) { + e.printStackTrace(); + } + lock.release(); + }); + } + + @Override + public void onSessionRemoved(HidDevice session) { + lock.release(); + } + }); + + try { + lock.acquire(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } +} \ No newline at end of file diff --git a/DesktopDemo/src/main/java/com/yubico/yubikit/desktop/app/package-info.java b/DesktopDemo/src/main/java/com/yubico/yubikit/desktop/app/package-info.java new file mode 100755 index 00000000..78a440a9 --- /dev/null +++ b/DesktopDemo/src/main/java/com/yubico/yubikit/desktop/app/package-info.java @@ -0,0 +1,4 @@ +@PackageNonnullByDefault +package com.yubico.yubikit.desktop.app; + +import com.yubico.yubikit.core.PackageNonnullByDefault; \ No newline at end of file diff --git a/desktop/.gitignore b/desktop/.gitignore new file mode 100755 index 00000000..42afabfd --- /dev/null +++ b/desktop/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/desktop/build.gradle b/desktop/build.gradle new file mode 100755 index 00000000..ed050c64 --- /dev/null +++ b/desktop/build.gradle @@ -0,0 +1,17 @@ +apply plugin: 'java-library' + +dependencies { + api project(':core') + + compileOnly 'com.google.code.findbugs:jsr305:3.0.2' + + implementation 'org.hid4java:hid4java:0.6.0' +} + +sourceCompatibility = "1.8" +targetCompatibility = "1.8" + +ext.pomName = "Yubico YubiKit Desktop" +description = "This module is the core library desktop implementation and provides functionality to detect a YubiKey plugged in or tapped over NFC and to open an ISO/IEC 7816 connection, using the javax.smartcardio API." + +apply from: rootProject.file('publish.gradle') \ No newline at end of file diff --git a/desktop/src/main/java/com/yubico/yubikit/desktop/HidDevice.java b/desktop/src/main/java/com/yubico/yubikit/desktop/HidDevice.java new file mode 100755 index 00000000..540b60d9 --- /dev/null +++ b/desktop/src/main/java/com/yubico/yubikit/desktop/HidDevice.java @@ -0,0 +1,66 @@ +package com.yubico.yubikit.desktop; + +import com.yubico.yubikit.core.Transport; +import com.yubico.yubikit.core.YubiKeyConnection; +import com.yubico.yubikit.core.YubiKeyDevice; +import com.yubico.yubikit.core.util.Callback; +import com.yubico.yubikit.core.util.Result; + +import java.io.IOException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +public class HidDevice implements YubiKeyDevice { + private final ExecutorService executorService = Executors.newSingleThreadExecutor(); + private final org.hid4java.HidDevice hidDevice; + private final int usagePage; + + HidDevice(org.hid4java.HidDevice hidDevice) { + this.hidDevice = hidDevice; + usagePage = hidDevice.getUsagePage() & 0xffff; + } + + public HidOtpConnection openOtpConnection() throws IOException { + return new HidOtpConnection(hidDevice, (byte) 0); + } + + public HidFidoConnection openFidoConnection() throws IOException { + if (usagePage == 0xf1d0) { + return new HidFidoConnection(hidDevice); + } + throw new IOException("fido connection not supported"); + } + + @Override + public Transport getTransport() { + return Transport.USB; + } + + @Override + public boolean supportsConnection(Class connectionType) { + if (connectionType.isAssignableFrom(HidOtpConnection.class)) { + return usagePage == 5; + } else if (connectionType.isAssignableFrom(HidFidoConnection.class)) { + return usagePage == 0xf1d0; + } + return false; + } + + @Override + public void requestConnection(Class connectionType, Callback> callback) { + if (!supportsConnection(connectionType)) { + throw new IllegalStateException("Unsupported connection type"); + } + executorService.submit(() -> { + try { + if (connectionType.isAssignableFrom(HidOtpConnection.class)) { + callback.invoke(Result.success(connectionType.cast(new HidOtpConnection(hidDevice, (byte)0)))); + } else if (connectionType.isAssignableFrom(HidFidoConnection.class)) { + callback.invoke(Result.success(connectionType.cast(new HidFidoConnection(hidDevice)))); + } + } catch (IOException e) { + callback.invoke(Result.failure(e)); + } + }); + } +} diff --git a/desktop/src/main/java/com/yubico/yubikit/desktop/HidFidoConnection.java b/desktop/src/main/java/com/yubico/yubikit/desktop/HidFidoConnection.java new file mode 100755 index 00000000..d27ec6b7 --- /dev/null +++ b/desktop/src/main/java/com/yubico/yubikit/desktop/HidFidoConnection.java @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2020 Yubico AB - All Rights Reserved + * Unauthorized copying and/or distribution of this file, via any medium is strictly prohibited + * Proprietary and confidential + */ +package com.yubico.yubikit.desktop; + +import com.yubico.yubikit.core.fido.FidoConnection; + +import org.hid4java.HidDevice; + +import java.io.IOException; + +public class HidFidoConnection implements FidoConnection { + private static final int TIMEOUT = 1000; + + private final HidDevice hidDevice; + + public HidFidoConnection(HidDevice hidDevice) throws IOException { + if (hidDevice.isOpen()) { + throw new IOException("Device already open"); + } + hidDevice.open(); + this.hidDevice = hidDevice; + } + + @Override + public void close() { + hidDevice.close(); + } + + @Override + public void send(byte[] packet) throws IOException { + int sent = hidDevice.write(packet, packet.length, (byte) 0); + if (sent < 0) { + throw new IOException(hidDevice.getLastErrorMessage()); + } else if (sent != PACKET_SIZE) { + throw new IOException("Unexpected amount of data sent: " + sent); + } + } + + @Override + public void receive(byte[] packet) throws IOException { + int received = hidDevice.read(packet, TIMEOUT); + if (received < 0) { + throw new IOException(hidDevice.getLastErrorMessage()); + } else if (received != PACKET_SIZE) { + throw new IOException("Unexpected amount of data read: " + received); + } + } +} diff --git a/desktop/src/main/java/com/yubico/yubikit/desktop/HidOtpConnection.java b/desktop/src/main/java/com/yubico/yubikit/desktop/HidOtpConnection.java new file mode 100755 index 00000000..06e99189 --- /dev/null +++ b/desktop/src/main/java/com/yubico/yubikit/desktop/HidOtpConnection.java @@ -0,0 +1,44 @@ +package com.yubico.yubikit.desktop; + +import com.yubico.yubikit.core.Logger; +import com.yubico.yubikit.core.otp.OtpConnection; + +import org.hid4java.HidDevice; + +import java.io.IOException; + +public class HidOtpConnection implements OtpConnection { + private final HidDevice hidDevice; + private final byte interfaceId; + + HidOtpConnection(HidDevice hidDevice, byte interfaceId) throws IOException { + if (hidDevice.isOpen()) { + throw new IOException("Device already open"); + } + hidDevice.open(); + this.interfaceId = interfaceId; + this.hidDevice = hidDevice; + Logger.d("usb connection opened"); + } + + @Override + public void receive(byte[] report) throws IOException { + int received = hidDevice.getFeatureReport(report, interfaceId); + if (received != FEATURE_REPORT_SIZE) { + throw new IOException("Unexpected amount of data read: " + received); + } + } + + @Override + public void send(byte[] report) throws IOException { + int sent = hidDevice.sendFeatureReport(report, interfaceId); + if (sent != FEATURE_REPORT_SIZE) { + throw new IOException("Unexpected amount of data sent: " + sent); + } + } + + @Override + public void close() { + hidDevice.close(); + } +} diff --git a/desktop/src/main/java/com/yubico/yubikit/desktop/HidSessionListener.java b/desktop/src/main/java/com/yubico/yubikit/desktop/HidSessionListener.java new file mode 100755 index 00000000..e6b3d1cc --- /dev/null +++ b/desktop/src/main/java/com/yubico/yubikit/desktop/HidSessionListener.java @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2019 Yubico. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.yubico.yubikit.desktop; + +public interface HidSessionListener { + /** + * Invoked when detected inserted device after usb discovery started + * + * @param session usb session that associated with plugged in device + */ + void onSessionReceived(HidDevice session); + + /** + * Invoked when detected removal/ejection of usb device after usb discovery started + * + * @param session usb session that will become inactive + */ + void onSessionRemoved(HidDevice session); +} diff --git a/desktop/src/main/java/com/yubico/yubikit/desktop/PcscConfiguration.java b/desktop/src/main/java/com/yubico/yubikit/desktop/PcscConfiguration.java new file mode 100755 index 00000000..1c63e944 --- /dev/null +++ b/desktop/src/main/java/com/yubico/yubikit/desktop/PcscConfiguration.java @@ -0,0 +1,47 @@ +package com.yubico.yubikit.desktop; + +import com.yubico.yubikit.core.Transport; + +import java.util.Arrays; +import java.util.EnumSet; +import java.util.regex.Pattern; + +import javax.annotation.Nullable; + +public class PcscConfiguration { + private final EnumSet transportFilter = EnumSet.allOf(Transport.class); + private long pollingTimeout = 250; + @Nullable + private Pattern readerNameFilter = null; + + long getPollingTimeout() { + return pollingTimeout; + } + + boolean isInterfaceAllowed(Transport transport) { + return transportFilter.contains(transport); + } + + boolean filterName(String name) { + if (readerNameFilter != null) { + return readerNameFilter.matcher(name).find(); + } + return true; + } + + public PcscConfiguration pollingTimeout(long pollingTimeout) { + this.pollingTimeout = pollingTimeout; + return this; + } + + public PcscConfiguration interfaceFilter(Transport... transports) { + transportFilter.clear(); + transportFilter.addAll(Arrays.asList(transports)); + return this; + } + + public PcscConfiguration readerNameFilter(Pattern pattern) { + this.readerNameFilter = pattern; + return this; + } +} diff --git a/desktop/src/main/java/com/yubico/yubikit/desktop/PcscDevice.java b/desktop/src/main/java/com/yubico/yubikit/desktop/PcscDevice.java new file mode 100755 index 00000000..49e77fc8 --- /dev/null +++ b/desktop/src/main/java/com/yubico/yubikit/desktop/PcscDevice.java @@ -0,0 +1,102 @@ +package com.yubico.yubikit.desktop; + +import com.yubico.yubikit.core.Transport; +import com.yubico.yubikit.core.YubiKeyConnection; +import com.yubico.yubikit.core.YubiKeyDevice; +import com.yubico.yubikit.core.application.ApplicationNotAvailableException; +import com.yubico.yubikit.core.smartcard.Apdu; +import com.yubico.yubikit.core.smartcard.ApduException; +import com.yubico.yubikit.core.smartcard.SmartCardConnection; +import com.yubico.yubikit.core.smartcard.SmartCardProtocol; +import com.yubico.yubikit.core.util.Callback; +import com.yubico.yubikit.core.util.Result; + +import java.io.IOException; +import java.nio.ByteBuffer; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +import javax.smartcardio.CardException; +import javax.smartcardio.CardTerminal; + +public class PcscDevice implements YubiKeyDevice { + private static final byte[] NDEF_AID = new byte[]{(byte) 0xd2, 0x76, 0x00, 0x00, (byte) 0x85, 0x01, 0x01}; + + private final ExecutorService executorService = Executors.newSingleThreadExecutor(); + private final CardTerminal terminal; + private final Transport transport; + + public PcscDevice(CardTerminal terminal) { + this.terminal = terminal; + + // If the terminal has YubiKey in the name, it's connected via USB. Otherwise we assume it's NFC + if (terminal.getName().toLowerCase().contains("yubikey")) { + transport = Transport.USB; + } else { + transport = Transport.NFC; + } + } + + public String getReaderName() { + return terminal.getName(); + } + + @Override + public Transport getTransport() { + return transport; + } + + public SmartCardConnection openIso7816Connection() throws IOException { + try { + return new PcscSmartCardConnection(terminal.connect("T=1")); + } catch (CardException e) { + throw new IOException(e); + } + } + + /** + * Reads the NDEF record from a YubiKey over NFC. + * This is only available when connecting over NFC, and only if the YubiKey has been configured + * to output one of its OTP slots over NDEF. + * + * @return the raw NDEF record + * @throws IOException in case of connection error + * @throws ApduException in case of communication error + * @throws ApplicationNotAvailableException in case the NDEF applet isn't available + */ + public byte[] readNdef() throws IOException, ApduException, ApplicationNotAvailableException { + try (SmartCardProtocol ndef = new SmartCardProtocol(openIso7816Connection())) { + ndef.select(NDEF_AID); + + ndef.sendAndReceive(new Apdu(0x00, 0xa4, 0x00, 0x0C, new byte[]{(byte) 0xe1, 0x04})); + byte[] resp = ndef.sendAndReceive(new Apdu(0x00, 0xb0, 0, 0, null)); + int ndefLen = resp[1]; + ByteBuffer buf = ByteBuffer.allocate(ndefLen).put(resp, 2, resp.length - 2); + while (buf.position() < ndefLen) { + buf.put(ndef.sendAndReceive(new Apdu(0x00, 0xb0, 0, buf.position(), null))); + } + return buf.array(); + } + } + + @Override + public boolean supportsConnection(Class connectionType) { + return connectionType.isAssignableFrom(PcscSmartCardConnection.class); + } + + @Override + public void requestConnection(Class connectionType, Callback> callback) { + if (!supportsConnection(connectionType)) { + throw new IllegalStateException("Unsupported connection type"); + } + executorService.submit(() -> { + try { + callback.invoke(Result.success(connectionType.cast(new PcscSmartCardConnection(terminal.connect("T=1"))))); + } catch (CardException e) { + callback.invoke(Result.failure(new IOException(e))); + } catch (IOException e) { + callback.invoke(Result.failure(e)); + } + }); + } +} diff --git a/desktop/src/main/java/com/yubico/yubikit/desktop/PcscSessionListener.java b/desktop/src/main/java/com/yubico/yubikit/desktop/PcscSessionListener.java new file mode 100755 index 00000000..69f27d6f --- /dev/null +++ b/desktop/src/main/java/com/yubico/yubikit/desktop/PcscSessionListener.java @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2019 Yubico. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.yubico.yubikit.desktop; + +public interface PcscSessionListener { + /** + * Invoked when detected inserted device after usb discovery started + * + * @param session usb session that associated with plugged in device + */ + void onSessionReceived(PcscDevice session); + + /** + * Invoked when detected removal/ejection of usb device after usb discovery started + * + * @param session usb session that will become inactive + */ + void onSessionRemoved(PcscDevice session); +} diff --git a/desktop/src/main/java/com/yubico/yubikit/desktop/PcscSmartCardConnection.java b/desktop/src/main/java/com/yubico/yubikit/desktop/PcscSmartCardConnection.java new file mode 100755 index 00000000..52bfb292 --- /dev/null +++ b/desktop/src/main/java/com/yubico/yubikit/desktop/PcscSmartCardConnection.java @@ -0,0 +1,66 @@ +package com.yubico.yubikit.desktop; + +import com.yubico.yubikit.core.Logger; +import com.yubico.yubikit.core.Transport; +import com.yubico.yubikit.core.smartcard.SmartCardConnection; +import com.yubico.yubikit.core.util.StringUtils; + +import java.io.IOException; +import java.util.Arrays; + +import javax.smartcardio.Card; +import javax.smartcardio.CardChannel; +import javax.smartcardio.CardException; +import javax.smartcardio.CommandAPDU; + +public class PcscSmartCardConnection implements SmartCardConnection { + private final Card card; + private final Transport transport; + private final CardChannel cardChannel; + + public PcscSmartCardConnection(Card card) throws IOException { + this.card = card; + this.transport = (card.getATR().getBytes()[1] & 0xf0) == 0xf0 ? Transport.USB : Transport.NFC; + try { + card.beginExclusive(); + this.cardChannel = card.getBasicChannel(); + } catch (CardException e) { + throw new IOException(e); + } + } + + @Override + public Transport getTransport() { + return transport; + } + + @Override + public boolean isExtendedLengthApduSupported() { + return false; //TODO + } + + @Override + public void close() throws IOException { + try { + card.endExclusive(); + } catch (CardException e) { + throw new IOException(e); + } + } + + @Override + public byte[] sendAndReceive(byte[] apdu) throws IOException { + try { + Logger.d(apdu.length + " bytes sent over PCSC: " + StringUtils.bytesToHex(apdu)); + if (apdu.length < 5) { + // CardChannel.transmit requires at least 5 bytes. + apdu = Arrays.copyOf(apdu, 5); + } + byte[] response = cardChannel.transmit(new CommandAPDU(apdu)).getBytes(); + Logger.d(response.length + " bytes received: " + StringUtils.bytesToHex(response)); + return response; + } catch (CardException e) { + throw new IOException(e); + } + } +} \ No newline at end of file diff --git a/desktop/src/main/java/com/yubico/yubikit/desktop/YubiKitHidManager.java b/desktop/src/main/java/com/yubico/yubikit/desktop/YubiKitHidManager.java new file mode 100755 index 00000000..6f84a548 --- /dev/null +++ b/desktop/src/main/java/com/yubico/yubikit/desktop/YubiKitHidManager.java @@ -0,0 +1,37 @@ +package com.yubico.yubikit.desktop; + +import com.yubico.yubikit.core.Logger; + +import org.hid4java.HidManager; +import org.hid4java.HidServices; +import org.hid4java.HidServicesListener; +import org.hid4java.event.HidServicesEvent; + +public class YubiKitHidManager { + + private final HidServices services; + + public YubiKitHidManager() { + services = HidManager.getHidServices(); + } + + public void setListener(HidSessionListener listener) { + services.addHidServicesListener(new HidServicesListener() { + @Override + public void hidDeviceAttached(HidServicesEvent event) { + Logger.d("HID attached: " + event); + listener.onSessionReceived(new HidDevice(event.getHidDevice())); + } + + @Override + public void hidDeviceDetached(HidServicesEvent event) { + Logger.d("HID removed: " + event); + } + + @Override + public void hidFailure(HidServicesEvent event) { + Logger.d("HID failure: " + event); + } + }); + } +} diff --git a/desktop/src/main/java/com/yubico/yubikit/desktop/YubiKitManager.java b/desktop/src/main/java/com/yubico/yubikit/desktop/YubiKitManager.java new file mode 100755 index 00000000..1709fa5a --- /dev/null +++ b/desktop/src/main/java/com/yubico/yubikit/desktop/YubiKitManager.java @@ -0,0 +1,85 @@ +package com.yubico.yubikit.desktop; + +import com.yubico.yubikit.core.Logger; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.atomic.AtomicBoolean; + +import javax.smartcardio.CardException; +import javax.smartcardio.CardTerminal; +import javax.smartcardio.CardTerminals; +import javax.smartcardio.TerminalFactory; + +public class YubiKitManager { + private final CardTerminals terminals; + private final AtomicBoolean running = new AtomicBoolean(); + private final Map sessions = new HashMap<>(); + + public YubiKitManager(CardTerminals cardTerminals) { + this.terminals = cardTerminals; + } + + public YubiKitManager() { + this(TerminalFactory.getDefault().terminals()); + } + + public void stop() { + running.set(false); + } + + /** + * Starts listening for YubiKey device events. This method will continue to run until + * {@link #stop} is called. The callback will be invoked in the same (single) thread which this + * method is invoked on. + * + * @param configuration options which influence listening behavior + * @param listener the callback to invoke for sessions added/removed + */ + public void run(PcscConfiguration configuration, PcscSessionListener listener) { + if (!running.compareAndSet(false, true)) { + throw new IllegalStateException("PCSC detection already running!"); + } + + while (running.get()) { + Set removed = new HashSet<>(sessions.keySet()); + try { + for (CardTerminal terminal : terminals.list(CardTerminals.State.CARD_PRESENT)) { + String name = terminal.getName(); + if (sessions.containsKey(name)) { + removed.remove(name); + } else if (configuration.filterName(name)) { + PcscDevice session = new PcscDevice(terminal); + sessions.put(name, session); + if (configuration.isInterfaceAllowed(session.getTransport())) { + Logger.d("Session started: " + name); + listener.onSessionReceived(session); + } + } + } + for (String name : removed) { + PcscDevice session = sessions.remove(name); + if (configuration.isInterfaceAllowed(session.getTransport())) { + Logger.d("Session ended: " + name); + listener.onSessionRemoved(session); + } + } + terminals.waitForChange(configuration.getPollingTimeout()); + } catch (CardException e) { + e.printStackTrace(); + } + } + + for (Map.Entry entry : sessions.entrySet()) { + PcscDevice session = entry.getValue(); + if (configuration.isInterfaceAllowed(session.getTransport())) { + Logger.d("Session ended: " + entry.getKey()); + listener.onSessionRemoved(session); + } + } + sessions.clear(); + } +} diff --git a/desktop/src/main/java/com/yubico/yubikit/desktop/package-info.java b/desktop/src/main/java/com/yubico/yubikit/desktop/package-info.java new file mode 100755 index 00000000..9d9f0ea9 --- /dev/null +++ b/desktop/src/main/java/com/yubico/yubikit/desktop/package-info.java @@ -0,0 +1,4 @@ +@PackageNonnullByDefault +package com.yubico.yubikit.desktop; + +import com.yubico.yubikit.core.PackageNonnullByDefault; \ No newline at end of file diff --git a/settings.gradle b/settings.gradle index 5cb077a2..a0a5cfb1 100755 --- a/settings.gradle +++ b/settings.gradle @@ -1,3 +1,4 @@ include ':core', ':oath', ':yubiotp', ':management', ':piv', ':openpgp', ':support', ':fido' include ':testing' include ':android', ':AndroidDemo', ':testing-android' +include ':desktop', ':DesktopDemo' From 4c2cdb1878016304c5a0460a73f350db26f2639a Mon Sep 17 00:00:00 2001 From: Greg Domzalski Date: Wed, 12 Oct 2022 12:19:59 -0700 Subject: [PATCH 02/24] Add desktop operating system detection helpers --- .../yubikit/desktop/OperatingSystem.java | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 desktop/src/main/java/com/yubico/yubikit/desktop/OperatingSystem.java diff --git a/desktop/src/main/java/com/yubico/yubikit/desktop/OperatingSystem.java b/desktop/src/main/java/com/yubico/yubikit/desktop/OperatingSystem.java new file mode 100644 index 00000000..8b107c14 --- /dev/null +++ b/desktop/src/main/java/com/yubico/yubikit/desktop/OperatingSystem.java @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2022 Yubico. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.yubico.yubikit.desktop; + +import java.lang.*; + +class OperatingSystem { + public static String Name = System.getProperty("os.name"); + + public static boolean isWindows() + { + return Name.toLowerCase().contains("win"); + } + + public static boolean isMac() + { + return Name.toLowerCase().contains("mac"); + } + + public static boolean isLinux() + { + return Name.toLowerCase().contains("linux"); + } +} From a68df015988e34e10f6b96a830ec9048ea784d86 Mon Sep 17 00:00:00 2001 From: Greg Domzalski Date: Wed, 12 Oct 2022 12:20:22 -0700 Subject: [PATCH 03/24] Usage page for HID Keyboard should be 1 --- desktop/src/main/java/com/yubico/yubikit/desktop/HidDevice.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/desktop/src/main/java/com/yubico/yubikit/desktop/HidDevice.java b/desktop/src/main/java/com/yubico/yubikit/desktop/HidDevice.java index 540b60d9..8de62f3a 100755 --- a/desktop/src/main/java/com/yubico/yubikit/desktop/HidDevice.java +++ b/desktop/src/main/java/com/yubico/yubikit/desktop/HidDevice.java @@ -39,7 +39,7 @@ public Transport getTransport() { @Override public boolean supportsConnection(Class connectionType) { if (connectionType.isAssignableFrom(HidOtpConnection.class)) { - return usagePage == 5; + return usagePage == 1; } else if (connectionType.isAssignableFrom(HidFidoConnection.class)) { return usagePage == 0xf1d0; } From dbbccc674e558d1cdd95f322ed220b6b37fd0557 Mon Sep 17 00:00:00 2001 From: Greg Domzalski Date: Wed, 12 Oct 2022 12:25:51 -0700 Subject: [PATCH 04/24] Handle Windows' extra byte on feature reports --- .../yubikit/desktop/HidOtpConnection.java | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/desktop/src/main/java/com/yubico/yubikit/desktop/HidOtpConnection.java b/desktop/src/main/java/com/yubico/yubikit/desktop/HidOtpConnection.java index 06e99189..af57558b 100755 --- a/desktop/src/main/java/com/yubico/yubikit/desktop/HidOtpConnection.java +++ b/desktop/src/main/java/com/yubico/yubikit/desktop/HidOtpConnection.java @@ -23,16 +23,27 @@ public class HidOtpConnection implements OtpConnection { @Override public void receive(byte[] report) throws IOException { - int received = hidDevice.getFeatureReport(report, interfaceId); - if (received != FEATURE_REPORT_SIZE) { + int offset = OperatingSystem.isWindows() ? 1 : 0; + int reportSize = FEATURE_REPORT_SIZE + offset; + + byte[] temp = new byte[reportSize]; + int received = hidDevice.getFeatureReport(temp, interfaceId); + + System.arraycopy(temp, offset, report, 0, FEATURE_REPORT_SIZE); + + if (received != reportSize) { throw new IOException("Unexpected amount of data read: " + received); } } @Override public void send(byte[] report) throws IOException { + int offset = OperatingSystem.isWindows() ? 1 : 0; + int reportSize = FEATURE_REPORT_SIZE + offset; + int sent = hidDevice.sendFeatureReport(report, interfaceId); - if (sent != FEATURE_REPORT_SIZE) { + + if (sent != reportSize) { throw new IOException("Unexpected amount of data sent: " + sent); } } From 77f879db172bdb1621018089f204b661bc7faf73 Mon Sep 17 00:00:00 2001 From: Adam Velebil Date: Wed, 12 Oct 2022 14:47:01 -0700 Subject: [PATCH 05/24] add testing-desktop module --- .../yubikit/desktop/app/DesktopApp.java | 14 ++-- .../yubikit/desktop/OperatingSystem.java | 2 +- testing-desktop/README.adoc | 16 ++++ testing-desktop/build.gradle | 28 +++++++ .../yubikit/testing/DesktopTestDriver.java | 73 +++++++++++++++++++ .../framework/PivInstrumentedTests.java | 50 +++++++++++++ .../framework/YKInstrumentedTests.java | 55 ++++++++++++++ .../yubikit/testing/PivJcaProviderTests.java | 48 ++++++++++++ .../com/yubico/yubikit/testing/PivTests.java | 40 ++++++++++ 9 files changed, 317 insertions(+), 9 deletions(-) create mode 100644 testing-desktop/README.adoc create mode 100755 testing-desktop/build.gradle create mode 100644 testing-desktop/src/main/java/com/yubico/yubikit/testing/DesktopTestDriver.java create mode 100755 testing-desktop/src/main/java/com/yubico/yubikit/testing/framework/PivInstrumentedTests.java create mode 100755 testing-desktop/src/main/java/com/yubico/yubikit/testing/framework/YKInstrumentedTests.java create mode 100644 testing-desktop/src/test/java/com/yubico/yubikit/testing/PivJcaProviderTests.java create mode 100644 testing-desktop/src/test/java/com/yubico/yubikit/testing/PivTests.java diff --git a/DesktopDemo/src/main/java/com/yubico/yubikit/desktop/app/DesktopApp.java b/DesktopDemo/src/main/java/com/yubico/yubikit/desktop/app/DesktopApp.java index 4c8ddc46..83467fd7 100755 --- a/DesktopDemo/src/main/java/com/yubico/yubikit/desktop/app/DesktopApp.java +++ b/DesktopDemo/src/main/java/com/yubico/yubikit/desktop/app/DesktopApp.java @@ -4,13 +4,7 @@ import com.yubico.yubikit.core.application.ApplicationNotAvailableException; import com.yubico.yubikit.core.application.BadResponseException; import com.yubico.yubikit.core.smartcard.ApduException; -import com.yubico.yubikit.desktop.HidDevice; -import com.yubico.yubikit.desktop.HidSessionListener; -import com.yubico.yubikit.desktop.PcscConfiguration; -import com.yubico.yubikit.desktop.PcscDevice; -import com.yubico.yubikit.desktop.PcscSessionListener; -import com.yubico.yubikit.desktop.YubiKitHidManager; -import com.yubico.yubikit.desktop.YubiKitManager; +import com.yubico.yubikit.desktop.*; import com.yubico.yubikit.piv.KeyType; import com.yubico.yubikit.piv.ManagementKeyType; import com.yubico.yubikit.piv.PinPolicy; @@ -51,6 +45,10 @@ public class DesktopApp { public static void main(String[] argv) { + if (OperatingSystem.isMac()) { + System.setProperty("sun.security.smartcardio.library", "/System/Library/Frameworks/PCSC.framework/Versions/Current/PCSC"); + } + System.out.println("Insert YubiKey now..."); Logger.setLogger(new Logger() { @@ -176,7 +174,7 @@ private static void testPiv(PcscDevice session) { // Create certificate //Provider provider = new PivProvider(piv); - KeyPairGenerator kpg = KeyPairGenerator.getInstance("EC", provider); + KeyPairGenerator kpg = KeyPairGenerator.getInstance("YkPivEC", provider); kpg.initialize(new PivAlgorithmParameterSpec(Slot.AUTHENTICATION, KeyType.ECCP256, PinPolicy.ALWAYS, TouchPolicy.DEFAULT, "123456".toCharArray())); KeyPair keyPair = kpg.generateKeyPair(); diff --git a/desktop/src/main/java/com/yubico/yubikit/desktop/OperatingSystem.java b/desktop/src/main/java/com/yubico/yubikit/desktop/OperatingSystem.java index 8b107c14..424b4556 100644 --- a/desktop/src/main/java/com/yubico/yubikit/desktop/OperatingSystem.java +++ b/desktop/src/main/java/com/yubico/yubikit/desktop/OperatingSystem.java @@ -18,7 +18,7 @@ import java.lang.*; -class OperatingSystem { +public class OperatingSystem { public static String Name = System.getProperty("os.name"); public static boolean isWindows() diff --git a/testing-desktop/README.adoc b/testing-desktop/README.adoc new file mode 100644 index 00000000..bbfd873a --- /dev/null +++ b/testing-desktop/README.adoc @@ -0,0 +1,16 @@ +== Instrumented tests for YubiKit Desktop + +This module contains tests for execution on a physical device and with YubiKey connected via USB. The test runs need a presence of someone who can tap the key when needed and therefore are these tests suitable only for local execution. + +NOTE: Don't run any of the tests on a production YubiKey. The tests execute various YubiKit methods on the YubiKey, data will be changed and removed. + +=== Running the tests +1. Make sure that the YubiKey you are using is meant for testing. Don't proceed with the tests if unsure. + Running the instrumented tests will: change PIN, PUK, management key and overwrite stored certificates in the PIV application +2. Connect your device through wireless debugging and select it +3. Right-click the `testing-desktop` project and select _Run 'All tests'_ + +==== Running from commandline +It is also possible to run the tests from commandline by executing following command after the device is connected through adb: + + ./gradlew testing-desktop:test diff --git a/testing-desktop/build.gradle b/testing-desktop/build.gradle new file mode 100755 index 00000000..b390707a --- /dev/null +++ b/testing-desktop/build.gradle @@ -0,0 +1,28 @@ +plugins { + id 'java' +} + +repositories { + mavenCentral() +} + +dependencies { + implementation 'org.jetbrains:annotations:20.1.0' + testImplementation('junit:junit:4.13.2') + testRuntimeOnly('org.junit.vintage:junit-vintage-engine:5.9.0') + + implementation project(':desktop') + implementation project(':piv') + implementation project(':testing') +} + +java { + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 +} + +test { + useJUnitPlatform() +} + +description = "This module contains instrumented test framework and tests for yubikit-desktop." diff --git a/testing-desktop/src/main/java/com/yubico/yubikit/testing/DesktopTestDriver.java b/testing-desktop/src/main/java/com/yubico/yubikit/testing/DesktopTestDriver.java new file mode 100644 index 00000000..cfff21df --- /dev/null +++ b/testing-desktop/src/main/java/com/yubico/yubikit/testing/DesktopTestDriver.java @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2022 Yubico. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.yubico.yubikit.testing; + +import com.yubico.yubikit.core.YubiKeyDevice; +import com.yubico.yubikit.desktop.*; +import org.jetbrains.annotations.NotNull; + +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.BlockingQueue; + +public class DesktopTestDriver { + + private final BlockingQueue sessionQueue = new ArrayBlockingQueue<>(1); + + private final YubiKitManager yubikit; + + private Thread observerThread = null; + + public DesktopTestDriver() { + if (OperatingSystem.isMac()) { + System.setProperty("sun.security.smartcardio.library", "/System/Library/Frameworks/PCSC.framework/Versions/Current/PCSC"); + } + yubikit = new YubiKitManager(); + startObserving(); + } + + private void startObserving() { + + observerThread = new Thread(() -> yubikit.run(new PcscConfiguration(), new PcscSessionListener() { + @Override + public void onSessionReceived(@NotNull PcscDevice session) { + sessionQueue.add(session); + System.out.println("Session added"); + } + + @Override + public void onSessionRemoved(@NotNull PcscDevice session) { + System.out.println("Session removed"); + } + })); + + observerThread.start(); + } + + private void stopObserving() { + yubikit.stop(); + } + + public YubiKeyDevice awaitSession() throws InterruptedException { + YubiKeyDevice connectedDevice = sessionQueue.take(); + System.out.println("Device connected"); + return connectedDevice; + } + + public void returnSession(YubiKeyDevice device) { + System.out.println("Device returned"); + } +} diff --git a/testing-desktop/src/main/java/com/yubico/yubikit/testing/framework/PivInstrumentedTests.java b/testing-desktop/src/main/java/com/yubico/yubikit/testing/framework/PivInstrumentedTests.java new file mode 100755 index 00000000..7c483a7f --- /dev/null +++ b/testing-desktop/src/main/java/com/yubico/yubikit/testing/framework/PivInstrumentedTests.java @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2022 Yubico. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.yubico.yubikit.testing.framework; + +import com.yubico.yubikit.core.smartcard.SmartCardConnection; +import com.yubico.yubikit.piv.PivSession; + +import java.util.Optional; +import java.util.concurrent.LinkedBlockingQueue; + +public class PivInstrumentedTests extends YKInstrumentedTests { + + public interface Callback { + void invoke(PivSession value) throws Throwable; + } + + protected void withPivSession(Callback callback) throws Throwable { + LinkedBlockingQueue> result = new LinkedBlockingQueue<>(); + device.requestConnection(SmartCardConnection.class, callbackResult -> { + try { + if (callbackResult.isSuccess()) { + PivSession pivSession = new PivSession(callbackResult.getValue()); + callback.invoke(pivSession); + result.offer(Optional.empty()); + } + } catch (Throwable e) { + result.offer(Optional.of(e)); + } + }); + + Optional exception = result.take(); + if (exception.isPresent()) { + throw exception.get(); + } + } +} \ No newline at end of file diff --git a/testing-desktop/src/main/java/com/yubico/yubikit/testing/framework/YKInstrumentedTests.java b/testing-desktop/src/main/java/com/yubico/yubikit/testing/framework/YKInstrumentedTests.java new file mode 100755 index 00000000..5ae3ecd0 --- /dev/null +++ b/testing-desktop/src/main/java/com/yubico/yubikit/testing/framework/YKInstrumentedTests.java @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2022 Yubico. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.yubico.yubikit.testing.framework; + +import com.yubico.yubikit.core.YubiKeyDevice; + +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.rules.ExternalResource; +import org.junit.rules.TestName; +import org.junit.rules.TestRule; + +import com.yubico.yubikit.testing.DesktopTestDriver; + +public class YKInstrumentedTests { + + protected YubiKeyDevice device = null; + private final DesktopTestDriver testDriver = new DesktopTestDriver(); + + @Rule + public final TestName name = new TestName(); + + @Rule + public final ExternalResource externalResource = new ExternalResource() { + + @Override + protected void before() throws Throwable { + device = testDriver.awaitSession(); + System.out.println("Got session"); + } + + @Override + protected void after() { + System.out.println("Returning session"); + testDriver.returnSession(device); + device = null; + } + }; + +} diff --git a/testing-desktop/src/test/java/com/yubico/yubikit/testing/PivJcaProviderTests.java b/testing-desktop/src/test/java/com/yubico/yubikit/testing/PivJcaProviderTests.java new file mode 100644 index 00000000..5c1626c4 --- /dev/null +++ b/testing-desktop/src/test/java/com/yubico/yubikit/testing/PivJcaProviderTests.java @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2022 Yubico. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.yubico.yubikit.testing; + +import com.yubico.yubikit.testing.framework.PivInstrumentedTests; +import com.yubico.yubikit.testing.piv.PivJcaDecryptTests; +import com.yubico.yubikit.testing.piv.PivJcaDeviceTests; +import com.yubico.yubikit.testing.piv.PivJcaSigningTests; + +import org.junit.Test; +import org.junit.runner.RunWith; + +public class PivJcaProviderTests extends PivInstrumentedTests { + + @Test + public void testGenerateKeys() throws Throwable { + withPivSession(PivJcaDeviceTests::testGenerateKeys); + } + + @Test + public void testImportKeys() throws Throwable { + withPivSession(PivJcaDeviceTests::testImportKeys); + } + + @Test + public void testSigning() throws Throwable { + withPivSession(PivJcaSigningTests::testSign); + } + + @Test + public void testDecrypt() throws Throwable { + withPivSession(PivJcaDecryptTests::testDecrypt); + } +} diff --git a/testing-desktop/src/test/java/com/yubico/yubikit/testing/PivTests.java b/testing-desktop/src/test/java/com/yubico/yubikit/testing/PivTests.java new file mode 100644 index 00000000..5926b0ee --- /dev/null +++ b/testing-desktop/src/test/java/com/yubico/yubikit/testing/PivTests.java @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2022 Yubico. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.yubico.yubikit.testing; + +import com.yubico.yubikit.testing.framework.PivInstrumentedTests; +import com.yubico.yubikit.testing.piv.PivDeviceTests; + +import org.junit.Test; + +public class PivTests extends PivInstrumentedTests { + + @Test + public void testPin() throws Throwable { + withPivSession(PivDeviceTests::testPin); + } + + @Test + public void testPuk() throws Throwable { + withPivSession(PivDeviceTests::testPuk); + } + + @Test + public void testManagementKey() throws Throwable { + withPivSession(PivDeviceTests::testManagementKey); + } +} From 8920b939f1fd0b5865f16f2c90637ed9a05f3b67 Mon Sep 17 00:00:00 2001 From: Dain Nilsson Date: Wed, 12 Oct 2022 16:31:57 -0700 Subject: [PATCH 06/24] Rewrite device enumeration. --- .../yubikit/desktop/app/DesktopApp.java | 122 ++++++------ desktop/build.gradle | 2 +- .../yubikit/desktop/CompositeDevice.java | 50 +++++ .../yubico/yubikit/desktop/UsbPidGroup.java | 175 ++++++++++++++++++ .../yubikit/desktop/UsbYubiKeyDevice.java | 30 +++ .../yubikit/desktop/YubiKitHidManager.java | 37 ---- .../yubikit/desktop/YubiKitManager.java | 123 ++++++------ .../yubikit/desktop/{ => hid}/HidDevice.java | 51 ++++- .../desktop/{ => hid}/HidFidoConnection.java | 18 +- .../yubikit/desktop/hid/HidManager.java | 85 +++++++++ .../desktop/{ => hid}/HidOtpConnection.java | 19 +- .../desktop/{ => hid}/HidSessionListener.java | 4 +- .../yubikit/desktop/hid/package-info.java | 4 + .../NfcPcscDevice.java} | 70 +++---- .../desktop/{ => pcsc}/PcscConfiguration.java | 18 +- .../yubikit/desktop/pcsc/PcscDevice.java | 76 ++++++++ .../yubikit/desktop/pcsc/PcscManager.java | 47 +++++ .../{ => pcsc}/PcscSessionListener.java | 8 +- .../{ => pcsc}/PcscSmartCardConnection.java | 19 +- .../yubikit/desktop/pcsc/UsbPcscDevice.java | 79 ++++++++ .../yubikit/desktop/pcsc/package-info.java | 4 + 21 files changed, 808 insertions(+), 233 deletions(-) create mode 100755 desktop/src/main/java/com/yubico/yubikit/desktop/CompositeDevice.java create mode 100755 desktop/src/main/java/com/yubico/yubikit/desktop/UsbPidGroup.java create mode 100755 desktop/src/main/java/com/yubico/yubikit/desktop/UsbYubiKeyDevice.java delete mode 100755 desktop/src/main/java/com/yubico/yubikit/desktop/YubiKitHidManager.java rename desktop/src/main/java/com/yubico/yubikit/desktop/{ => hid}/HidDevice.java (54%) rename desktop/src/main/java/com/yubico/yubikit/desktop/{ => hid}/HidFidoConnection.java (67%) create mode 100755 desktop/src/main/java/com/yubico/yubikit/desktop/hid/HidManager.java rename desktop/src/main/java/com/yubico/yubikit/desktop/{ => hid}/HidOtpConnection.java (69%) rename desktop/src/main/java/com/yubico/yubikit/desktop/{ => hid}/HidSessionListener.java (93%) create mode 100755 desktop/src/main/java/com/yubico/yubikit/desktop/hid/package-info.java rename desktop/src/main/java/com/yubico/yubikit/desktop/{PcscDevice.java => pcsc/NfcPcscDevice.java} (53%) rename desktop/src/main/java/com/yubico/yubikit/desktop/{ => pcsc}/PcscConfiguration.java (65%) create mode 100755 desktop/src/main/java/com/yubico/yubikit/desktop/pcsc/PcscDevice.java create mode 100755 desktop/src/main/java/com/yubico/yubikit/desktop/pcsc/PcscManager.java rename desktop/src/main/java/com/yubico/yubikit/desktop/{ => pcsc}/PcscSessionListener.java (84%) rename desktop/src/main/java/com/yubico/yubikit/desktop/{ => pcsc}/PcscSmartCardConnection.java (74%) create mode 100755 desktop/src/main/java/com/yubico/yubikit/desktop/pcsc/UsbPcscDevice.java create mode 100755 desktop/src/main/java/com/yubico/yubikit/desktop/pcsc/package-info.java diff --git a/DesktopDemo/src/main/java/com/yubico/yubikit/desktop/app/DesktopApp.java b/DesktopDemo/src/main/java/com/yubico/yubikit/desktop/app/DesktopApp.java index 83467fd7..a4c6817d 100755 --- a/DesktopDemo/src/main/java/com/yubico/yubikit/desktop/app/DesktopApp.java +++ b/DesktopDemo/src/main/java/com/yubico/yubikit/desktop/app/DesktopApp.java @@ -1,10 +1,19 @@ package com.yubico.yubikit.desktop.app; import com.yubico.yubikit.core.Logger; +import com.yubico.yubikit.core.YubiKeyDevice; import com.yubico.yubikit.core.application.ApplicationNotAvailableException; import com.yubico.yubikit.core.application.BadResponseException; +import com.yubico.yubikit.core.fido.FidoConnection; +import com.yubico.yubikit.core.otp.OtpConnection; import com.yubico.yubikit.core.smartcard.ApduException; import com.yubico.yubikit.desktop.*; +import com.yubico.yubikit.core.smartcard.SmartCardConnection; +import com.yubico.yubikit.desktop.hid.HidDevice; +import com.yubico.yubikit.desktop.hid.HidSessionListener; +import com.yubico.yubikit.desktop.hid.HidManager; +import com.yubico.yubikit.desktop.pcsc.NfcPcscDevice; +import com.yubico.yubikit.management.DeviceInfo; import com.yubico.yubikit.piv.KeyType; import com.yubico.yubikit.piv.ManagementKeyType; import com.yubico.yubikit.piv.PinPolicy; @@ -37,6 +46,10 @@ import java.security.SignatureException; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Map; import java.util.concurrent.Semaphore; import javax.net.ssl.HttpsURLConnection; @@ -64,67 +77,56 @@ protected void logError(String message, Throwable throwable) { } }); - //testHidOtp(); - testCcid(); - - Logger.d("Application exited"); - } - - private static void testCcid() { - YubiKitManager yubikit = new YubiKitManager(); - - yubikit.run(new PcscConfiguration(), new PcscSessionListener() { - @Override - public void onSessionReceived(PcscDevice session) { - /* - if (session.getInterface() == Interface.NFC) { + YubiKitManager manager = new YubiKitManager(); + Map devices = manager.listAllDevices(); + Logger.d("Devices: " + devices); + for (Map.Entry entry : devices.entrySet()) { + YubiKeyDevice device = entry.getKey(); + DeviceInfo info = entry.getValue(); + Logger.d("FOUND KEY: " + device + " " + info); + if (device.supportsConnection(SmartCardConnection.class)) { + Logger.d("Request CCID connection"); + device.requestConnection(SmartCardConnection.class, value -> { try { - byte[] ndefData = session.readNdef(); - String otp = NdefUtils.getNdefPayload(ndefData); - Logger.d("Read OTP: " + otp); - } catch (IOException | ApduException | ApplicationNotAvailableException e) { - e.printStackTrace(); + Logger.d("Got CCID connection " + value.getValue()); + } catch (IOException e) { + Logger.e("Failed to get CCID", e); } - } - - */ - - testPiv(session); - - try (PivSession piv = new PivSession(session.openIso7816Connection())) { - /* - PivJcaDeviceTests.testImportKeys(piv); - PivJcaDeviceTests.testGenerateKeys(piv); - - PivDeviceTests.testSign(piv, KeyType.ECCP256); - PivDeviceTests.testSign(piv, KeyType.RSA2048); - PivDeviceTests.testDecrypt(piv, KeyType.RSA2048); - */ - - //testHttps(piv); - - /* - for (Slot slot : Arrays.asList(Slot.AUTHENTICATION, Slot.SIGNATURE, Slot.CARD_AUTH, Slot.KEY_MANAGEMENT)) { - System.out.println("Slot: " + slot); - try { - System.out.println(piv.getCertificate(slot)); - } catch (ApduException | BadResponseException e) { - System.out.println("No certificate"); - } - }*/ - } catch (Exception e) { - e.printStackTrace(); - } - - yubikit.stop(); + }); } - - @Override - public void onSessionRemoved(PcscDevice session) { - Logger.d("Shutting down..."); - yubikit.stop(); + if (device.supportsConnection(OtpConnection.class)) { + Logger.d("Request OTP connection"); + device.requestConnection(OtpConnection.class, value -> { + try { + Logger.d("Got OTP connection " + value.getValue()); + } catch (IOException e) { + Logger.e("Failed to get OTP", e); + } + }); } - }); + if (device.supportsConnection(FidoConnection.class)) { + Logger.d("Request FIDO connection"); + device.requestConnection(FidoConnection.class, value -> { + try { + Logger.d("Got FIDO connection " + value.getValue()); + } catch (IOException e) { + Logger.e("Failed to get FIDO", e); + } + }); + } + } + + //testHidOtp(); + //testCcid(); + + Logger.d("Sleeping..."); + try { + Thread.sleep(5000); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + + Logger.d("Application exited"); } private static void testHttps(PivSession piv) throws Exception { @@ -154,7 +156,7 @@ private static void testHttps(PivSession piv) throws Exception { Security.removeProvider("YKPiv"); } - private static void testPiv(PcscDevice session) { + private static void testPiv(NfcPcscDevice session) { try (PivSession piv = new PivSession(session.openIso7816Connection())) { //piv.authenticate(new byte[]{1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8}); //Logger.d("Generate key..."); @@ -174,7 +176,7 @@ private static void testPiv(PcscDevice session) { // Create certificate //Provider provider = new PivProvider(piv); - KeyPairGenerator kpg = KeyPairGenerator.getInstance("YkPivEC", provider); + KeyPairGenerator kpg = KeyPairGenerator.getInstance("YKPivEC", provider); kpg.initialize(new PivAlgorithmParameterSpec(Slot.AUTHENTICATION, KeyType.ECCP256, PinPolicy.ALWAYS, TouchPolicy.DEFAULT, "123456".toCharArray())); KeyPair keyPair = kpg.generateKeyPair(); @@ -244,7 +246,7 @@ private static void testPiv(PcscDevice session) { } private static void testHidOtp() { - YubiKitHidManager hidManager = new YubiKitHidManager(); + HidManager hidManager = new HidManager(); Semaphore lock = new Semaphore(0); diff --git a/desktop/build.gradle b/desktop/build.gradle index ed050c64..b9be7616 100755 --- a/desktop/build.gradle +++ b/desktop/build.gradle @@ -1,7 +1,7 @@ apply plugin: 'java-library' dependencies { - api project(':core') + api project(':support') compileOnly 'com.google.code.findbugs:jsr305:3.0.2' diff --git a/desktop/src/main/java/com/yubico/yubikit/desktop/CompositeDevice.java b/desktop/src/main/java/com/yubico/yubikit/desktop/CompositeDevice.java new file mode 100755 index 00000000..26c285ce --- /dev/null +++ b/desktop/src/main/java/com/yubico/yubikit/desktop/CompositeDevice.java @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2022 Yubico. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.yubico.yubikit.desktop; + +import com.yubico.yubikit.core.Transport; +import com.yubico.yubikit.core.YubiKeyConnection; +import com.yubico.yubikit.core.YubiKeyDevice; +import com.yubico.yubikit.core.util.Callback; +import com.yubico.yubikit.core.util.Result; + +import java.io.IOException; + +public class CompositeDevice implements YubiKeyDevice { + private final UsbPidGroup pidGroup; + private final String key; + + CompositeDevice(UsbPidGroup pidGroup, String key) { + this.pidGroup = pidGroup; + this.key = key; + } + + @Override + public Transport getTransport() { + return Transport.USB; + } + + @Override + public boolean supportsConnection(Class connectionType) { + return pidGroup.supportsConnection(connectionType); + } + + @Override + public void requestConnection(Class connectionType, Callback> callback) { + pidGroup.requestConnection(key, connectionType, callback); + } +} diff --git a/desktop/src/main/java/com/yubico/yubikit/desktop/UsbPidGroup.java b/desktop/src/main/java/com/yubico/yubikit/desktop/UsbPidGroup.java new file mode 100755 index 00000000..e25fcd3d --- /dev/null +++ b/desktop/src/main/java/com/yubico/yubikit/desktop/UsbPidGroup.java @@ -0,0 +1,175 @@ +/* + * Copyright (C) 2022 Yubico. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.yubico.yubikit.desktop; + +import com.yubico.yubikit.core.*; +import com.yubico.yubikit.core.fido.FidoConnection; +import com.yubico.yubikit.core.otp.OtpConnection; +import com.yubico.yubikit.core.smartcard.SmartCardConnection; +import com.yubico.yubikit.core.util.Callback; +import com.yubico.yubikit.core.util.Result; +import com.yubico.yubikit.management.DeviceInfo; +import com.yubico.yubikit.support.DeviceUtil; + +import java.io.IOException; +import java.util.*; + +public class UsbPidGroup { + final UsbPid pid; + private final Map infos = new HashMap<>(); + private final Map> resolved = new HashMap<>(); + private final Map> unresolved = new HashMap<>(); + private final Map devCount = new HashMap<>(); + private final Set fingerprints = new HashSet<>(); + private final long ctime = System.currentTimeMillis(); + + UsbPidGroup(UsbPid pid) { + this.pid = pid; + } + + private String buildKey(DeviceInfo info) { + // TODO + /* + return ( + info.serial, + info.version, + info.form_factor, + str(info.supported_capabilities), + info.config.get_bytes(False), + info.is_locked, + info.is_fips, + info.is_sky, + ) + */ + return "" + info.getSerialNumber() + info.getVersion() + info.getFormFactor(); + } + + int getUsbInterface(Class connectionType) { + if (SmartCardConnection.class.isAssignableFrom(connectionType)) { + return UsbInterface.CCID; + } + if (OtpConnection.class.isAssignableFrom(connectionType)) { + return UsbInterface.OTP; + } + if (FidoConnection.class.isAssignableFrom(connectionType)) { + return UsbInterface.FIDO; + } + throw new IllegalArgumentException(); + } + + void add(Class connectionType, UsbYubiKeyDevice device, boolean forceResolve) { + Logger.d("Add device node " + device + connectionType); + int usbInterface = getUsbInterface(connectionType); + fingerprints.add(device.getFingerprint()); + devCount.put(usbInterface, devCount.getOrDefault(usbInterface, 0) + 1); + if (forceResolve || resolved.size() < devCount.values().stream().reduce(0, Math::max)) { + try(YubiKeyConnection connection = device.openConnection(connectionType)) { + DeviceInfo info = DeviceUtil.readInfo(connection, pid); + String key = buildKey(info); + infos.put(key, info); + if (!resolved.containsKey(key)) { + resolved.put(key, new HashMap<>()); + } + resolved.get(key).put(usbInterface, device); + Logger.d("Resolved device " + info.getSerialNumber()); + return; + } catch (IOException e) { + Logger.e("Failed opening device", e); + } + } + if (!unresolved.containsKey(usbInterface)) { + unresolved.put(usbInterface, new ArrayList<>()); + } + unresolved.get(usbInterface).add(device); + } + + boolean supportsConnection(Class connectionType) { + return (getUsbInterface(connectionType) & pid.usbInterfaces) != 0; + } + + void requestConnection(String key, Class connectionType, Callback> callback) { + int usbInterface = getUsbInterface(connectionType); + UsbYubiKeyDevice device = resolved.get(key).get(usbInterface); + if (device != null) { + device.requestConnection(connectionType, callback); + } else { + Logger.d("Resolve device for " + connectionType + ", " + key); + List devices = unresolved.getOrDefault(usbInterface, new ArrayList<>()); + Logger.d("Unresolved: " + devices); + List failed = new ArrayList<>(); + try { + while (!devices.isEmpty()) { + device = devices.remove(0); + Logger.d("Candidate: " + device); + try (T connection = device.openConnection(connectionType)) { + DeviceInfo info = DeviceUtil.readInfo(connection, pid); + String deviceKey = buildKey(info); + if (infos.containsKey(deviceKey)) { + if (!resolved.containsKey(deviceKey)) { + resolved.put(deviceKey, new HashMap<>()); + } + resolved.get(deviceKey).put(usbInterface, device); + if (deviceKey.equals(key)) { + device.requestConnection(connectionType, callback); + return; + } else if (pid.type == YubiKeyType.NEO && devices.isEmpty()) { + Logger.d("Resolved last NEO device without serial"); + device.requestConnection(connectionType, callback); + return; + } + } + } catch (IOException e) { + Logger.e("Failed opening candidate device", e); + failed.add(device); + } + } + } finally { + devices.addAll(failed); + } + + //TODO + /* + if self._devcount[iface] < len(self._infos): + logger.debug(f"Checking for more devices over {iface!s}") + for dev in _CONNECTION_LIST_MAPPING[conn_type](): + if self._pid == dev.pid and dev.fingerprint not in self._fingerprints: + self.add(conn_type, dev, True) + + resolved = self._resolved[key].get(iface) + if resolved: + return resolved.open_connection(conn_type) + + # Retry if we are within a 5 second period after creation, + # as not all USB interface become usable at the exact same time. + if time() < self._ctime + 5: + logger.debug("Device not found, retry in 1s") + sleep(1.0) + return self.connect(key, conn_type) + + raise ValueError("Failed to connect to the device") + */ + } + } + + Map getDevices() { + Map devices = new LinkedHashMap<>(); + for (Map.Entry entry : infos.entrySet()) { + devices.put(new CompositeDevice(this, entry.getKey()), entry.getValue()); + } + return devices; + } +} diff --git a/desktop/src/main/java/com/yubico/yubikit/desktop/UsbYubiKeyDevice.java b/desktop/src/main/java/com/yubico/yubikit/desktop/UsbYubiKeyDevice.java new file mode 100755 index 00000000..e0234f1d --- /dev/null +++ b/desktop/src/main/java/com/yubico/yubikit/desktop/UsbYubiKeyDevice.java @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2022 Yubico. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.yubico.yubikit.desktop; + +import com.yubico.yubikit.core.UsbPid; +import com.yubico.yubikit.core.YubiKeyConnection; +import com.yubico.yubikit.core.YubiKeyDevice; + +import java.io.IOException; + +public interface UsbYubiKeyDevice extends YubiKeyDevice { + T openConnection(Class connectionType) throws IOException; + + String getFingerprint(); + UsbPid getPid(); +} diff --git a/desktop/src/main/java/com/yubico/yubikit/desktop/YubiKitHidManager.java b/desktop/src/main/java/com/yubico/yubikit/desktop/YubiKitHidManager.java deleted file mode 100755 index 6f84a548..00000000 --- a/desktop/src/main/java/com/yubico/yubikit/desktop/YubiKitHidManager.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.yubico.yubikit.desktop; - -import com.yubico.yubikit.core.Logger; - -import org.hid4java.HidManager; -import org.hid4java.HidServices; -import org.hid4java.HidServicesListener; -import org.hid4java.event.HidServicesEvent; - -public class YubiKitHidManager { - - private final HidServices services; - - public YubiKitHidManager() { - services = HidManager.getHidServices(); - } - - public void setListener(HidSessionListener listener) { - services.addHidServicesListener(new HidServicesListener() { - @Override - public void hidDeviceAttached(HidServicesEvent event) { - Logger.d("HID attached: " + event); - listener.onSessionReceived(new HidDevice(event.getHidDevice())); - } - - @Override - public void hidDeviceDetached(HidServicesEvent event) { - Logger.d("HID removed: " + event); - } - - @Override - public void hidFailure(HidServicesEvent event) { - Logger.d("HID failure: " + event); - } - }); - } -} diff --git a/desktop/src/main/java/com/yubico/yubikit/desktop/YubiKitManager.java b/desktop/src/main/java/com/yubico/yubikit/desktop/YubiKitManager.java index 1709fa5a..8b5bbdc1 100755 --- a/desktop/src/main/java/com/yubico/yubikit/desktop/YubiKitManager.java +++ b/desktop/src/main/java/com/yubico/yubikit/desktop/YubiKitManager.java @@ -1,85 +1,80 @@ +/* + * Copyright (C) 2022 Yubico. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package com.yubico.yubikit.desktop; import com.yubico.yubikit.core.Logger; +import com.yubico.yubikit.core.UsbPid; +import com.yubico.yubikit.core.YubiKeyConnection; +import com.yubico.yubikit.core.YubiKeyDevice; +import com.yubico.yubikit.core.fido.FidoConnection; +import com.yubico.yubikit.core.otp.OtpConnection; +import com.yubico.yubikit.core.smartcard.SmartCardConnection; +import com.yubico.yubikit.desktop.hid.HidManager; +import com.yubico.yubikit.desktop.pcsc.PcscManager; +import com.yubico.yubikit.management.DeviceInfo; -import java.util.HashMap; -import java.util.HashSet; -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.atomic.AtomicBoolean; - -import javax.smartcardio.CardException; -import javax.smartcardio.CardTerminal; -import javax.smartcardio.CardTerminals; -import javax.smartcardio.TerminalFactory; +import java.util.*; public class YubiKitManager { - private final CardTerminals terminals; - private final AtomicBoolean running = new AtomicBoolean(); - private final Map sessions = new HashMap<>(); + private final PcscManager pcscManager; + private final HidManager hidManager; - public YubiKitManager(CardTerminals cardTerminals) { - this.terminals = cardTerminals; + public YubiKitManager(PcscManager pcscManager, HidManager hidManager) { + this.pcscManager = pcscManager; + this.hidManager = hidManager; } public YubiKitManager() { - this(TerminalFactory.getDefault().terminals()); + this(new PcscManager(), new HidManager()); } - public void stop() { - running.set(false); - } - - /** - * Starts listening for YubiKey device events. This method will continue to run until - * {@link #stop} is called. The callback will be invoked in the same (single) thread which this - * method is invoked on. - * - * @param configuration options which influence listening behavior - * @param listener the callback to invoke for sessions added/removed - */ - public void run(PcscConfiguration configuration, PcscSessionListener listener) { - if (!running.compareAndSet(false, true)) { - throw new IllegalStateException("PCSC detection already running!"); + List listDevices(Class connectionType) { + if (SmartCardConnection.class.isAssignableFrom(connectionType)) { + return pcscManager.getDevices(); + } else if (OtpConnection.class.isAssignableFrom(connectionType)) { + return hidManager.getOtpDevices(); + } else if (FidoConnection.class.isAssignableFrom(connectionType)) { + return hidManager.getFidoDevices(); } + throw new IllegalStateException("Unsupported connection type"); + } - while (running.get()) { - Set removed = new HashSet<>(sessions.keySet()); - try { - for (CardTerminal terminal : terminals.list(CardTerminals.State.CARD_PRESENT)) { - String name = terminal.getName(); - if (sessions.containsKey(name)) { - removed.remove(name); - } else if (configuration.filterName(name)) { - PcscDevice session = new PcscDevice(terminal); - sessions.put(name, session); - if (configuration.isInterfaceAllowed(session.getTransport())) { - Logger.d("Session started: " + name); - listener.onSessionReceived(session); - } - } + public Map listAllDevices(Set> connectionTypes) { + Map groups = new HashMap<>(); + for (Class connectionType : connectionTypes) { + Logger.d("Enumerate devices for " + connectionType); + for (UsbYubiKeyDevice device : listDevices(connectionType)) { + UsbPid pid = device.getPid(); + Logger.d("Found device with PID " + pid); + if (!groups.containsKey(pid)) { + groups.put(pid, new UsbPidGroup(pid)); } - for (String name : removed) { - PcscDevice session = sessions.remove(name); - if (configuration.isInterfaceAllowed(session.getTransport())) { - Logger.d("Session ended: " + name); - listener.onSessionRemoved(session); - } - } - terminals.waitForChange(configuration.getPollingTimeout()); - } catch (CardException e) { - e.printStackTrace(); + groups.get(pid).add(connectionType, device, false); } } - for (Map.Entry entry : sessions.entrySet()) { - PcscDevice session = entry.getValue(); - if (configuration.isInterfaceAllowed(session.getTransport())) { - Logger.d("Session ended: " + entry.getKey()); - listener.onSessionRemoved(session); - } + Map devices = new LinkedHashMap<>(); + for (UsbPidGroup group: groups.values()) { + devices.putAll(group.getDevices()); } - sessions.clear(); + return devices; + } + + public Map listAllDevices() { + return listAllDevices(new HashSet<>(Arrays.asList(SmartCardConnection.class, OtpConnection.class, FidoConnection.class))); } } diff --git a/desktop/src/main/java/com/yubico/yubikit/desktop/HidDevice.java b/desktop/src/main/java/com/yubico/yubikit/desktop/hid/HidDevice.java similarity index 54% rename from desktop/src/main/java/com/yubico/yubikit/desktop/HidDevice.java rename to desktop/src/main/java/com/yubico/yubikit/desktop/hid/HidDevice.java index 8de62f3a..35bd7db1 100755 --- a/desktop/src/main/java/com/yubico/yubikit/desktop/HidDevice.java +++ b/desktop/src/main/java/com/yubico/yubikit/desktop/hid/HidDevice.java @@ -1,16 +1,33 @@ -package com.yubico.yubikit.desktop; +/* + * Copyright (C) 2022 Yubico. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.yubico.yubikit.desktop.hid; import com.yubico.yubikit.core.Transport; +import com.yubico.yubikit.core.UsbPid; import com.yubico.yubikit.core.YubiKeyConnection; -import com.yubico.yubikit.core.YubiKeyDevice; import com.yubico.yubikit.core.util.Callback; import com.yubico.yubikit.core.util.Result; +import com.yubico.yubikit.desktop.UsbYubiKeyDevice; import java.io.IOException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; -public class HidDevice implements YubiKeyDevice { +public class HidDevice implements UsbYubiKeyDevice { private final ExecutorService executorService = Executors.newSingleThreadExecutor(); private final org.hid4java.HidDevice hidDevice; private final int usagePage; @@ -52,15 +69,31 @@ public void requestConnection(Class connectionT throw new IllegalStateException("Unsupported connection type"); } executorService.submit(() -> { - try { - if (connectionType.isAssignableFrom(HidOtpConnection.class)) { - callback.invoke(Result.success(connectionType.cast(new HidOtpConnection(hidDevice, (byte)0)))); - } else if (connectionType.isAssignableFrom(HidFidoConnection.class)) { - callback.invoke(Result.success(connectionType.cast(new HidFidoConnection(hidDevice)))); - } + try(T connection = openConnection(connectionType)) { + callback.invoke(Result.success(connection)); } catch (IOException e) { callback.invoke(Result.failure(e)); } }); } + + @Override + public T openConnection(Class connectionType) throws IOException { + if (connectionType.isAssignableFrom(HidOtpConnection.class)) { + return connectionType.cast(openOtpConnection()); + } else if (connectionType.isAssignableFrom(HidFidoConnection.class)) { + return connectionType.cast(openFidoConnection()); + } + throw new IllegalStateException("Unsupported connection type"); + } + + @Override + public String getFingerprint() { + return hidDevice.getPath(); + } + + @Override + public UsbPid getPid() { + return UsbPid.fromValue(hidDevice.getProductId()); + } } diff --git a/desktop/src/main/java/com/yubico/yubikit/desktop/HidFidoConnection.java b/desktop/src/main/java/com/yubico/yubikit/desktop/hid/HidFidoConnection.java similarity index 67% rename from desktop/src/main/java/com/yubico/yubikit/desktop/HidFidoConnection.java rename to desktop/src/main/java/com/yubico/yubikit/desktop/hid/HidFidoConnection.java index d27ec6b7..bb4d440f 100755 --- a/desktop/src/main/java/com/yubico/yubikit/desktop/HidFidoConnection.java +++ b/desktop/src/main/java/com/yubico/yubikit/desktop/hid/HidFidoConnection.java @@ -1,9 +1,19 @@ /* - * Copyright (C) 2020 Yubico AB - All Rights Reserved - * Unauthorized copying and/or distribution of this file, via any medium is strictly prohibited - * Proprietary and confidential + * Copyright (C) 2020-2022 Yubico. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ -package com.yubico.yubikit.desktop; +package com.yubico.yubikit.desktop.hid; import com.yubico.yubikit.core.fido.FidoConnection; diff --git a/desktop/src/main/java/com/yubico/yubikit/desktop/hid/HidManager.java b/desktop/src/main/java/com/yubico/yubikit/desktop/hid/HidManager.java new file mode 100755 index 00000000..93d1917c --- /dev/null +++ b/desktop/src/main/java/com/yubico/yubikit/desktop/hid/HidManager.java @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2022 Yubico. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.yubico.yubikit.desktop.hid; + +import com.yubico.yubikit.core.Logger; + +import org.hid4java.HidServices; +import org.hid4java.HidServicesListener; +import org.hid4java.event.HidServicesEvent; + +import java.util.ArrayList; +import java.util.List; + +public class HidManager { + + private final HidServices services; + + public HidManager() { + services = org.hid4java.HidManager.getHidServices(); + } + + public List getDevices() { + List yubikeys = new ArrayList<>(); + for (org.hid4java.HidDevice device: services.getAttachedHidDevices()) { + if(device.getProductId() == 0x1050) { + yubikeys.add(new HidDevice(device)); + } + } + return yubikeys; + } + + public List getOtpDevices() { + List yubikeys = new ArrayList<>(); + for (org.hid4java.HidDevice device: services.getAttachedHidDevices()) { + if(device.getVendorId() == 0x1050 && (device.getUsagePage() & 0xffff) == 1) { + yubikeys.add(new HidDevice(device)); + } + } + return yubikeys; + } + + public List getFidoDevices() { + List yubikeys = new ArrayList<>(); + for (org.hid4java.HidDevice device: services.getAttachedHidDevices()) { + if(device.getVendorId() == 0x1050 && (device.getUsagePage() & 0xffff) == 0xf1d0) { + yubikeys.add(new HidDevice(device)); + } + } + return yubikeys; + } + + public void setListener(HidSessionListener listener) { + services.addHidServicesListener(new HidServicesListener() { + @Override + public void hidDeviceAttached(HidServicesEvent event) { + Logger.d("HID attached: " + event); + listener.onSessionReceived(new HidDevice(event.getHidDevice())); + } + + @Override + public void hidDeviceDetached(HidServicesEvent event) { + Logger.d("HID removed: " + event); + } + + @Override + public void hidFailure(HidServicesEvent event) { + Logger.d("HID failure: " + event); + } + }); + } +} diff --git a/desktop/src/main/java/com/yubico/yubikit/desktop/HidOtpConnection.java b/desktop/src/main/java/com/yubico/yubikit/desktop/hid/HidOtpConnection.java similarity index 69% rename from desktop/src/main/java/com/yubico/yubikit/desktop/HidOtpConnection.java rename to desktop/src/main/java/com/yubico/yubikit/desktop/hid/HidOtpConnection.java index af57558b..e59ab92c 100755 --- a/desktop/src/main/java/com/yubico/yubikit/desktop/HidOtpConnection.java +++ b/desktop/src/main/java/com/yubico/yubikit/desktop/hid/HidOtpConnection.java @@ -1,8 +1,25 @@ -package com.yubico.yubikit.desktop; +/* + * Copyright (C) 2022 Yubico. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.yubico.yubikit.desktop.hid; import com.yubico.yubikit.core.Logger; import com.yubico.yubikit.core.otp.OtpConnection; +import com.yubico.yubikit.desktop.OperatingSystem; import org.hid4java.HidDevice; import java.io.IOException; diff --git a/desktop/src/main/java/com/yubico/yubikit/desktop/HidSessionListener.java b/desktop/src/main/java/com/yubico/yubikit/desktop/hid/HidSessionListener.java similarity index 93% rename from desktop/src/main/java/com/yubico/yubikit/desktop/HidSessionListener.java rename to desktop/src/main/java/com/yubico/yubikit/desktop/hid/HidSessionListener.java index e6b3d1cc..08eefd67 100755 --- a/desktop/src/main/java/com/yubico/yubikit/desktop/HidSessionListener.java +++ b/desktop/src/main/java/com/yubico/yubikit/desktop/hid/HidSessionListener.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2019 Yubico. + * Copyright (C) 2019-2022 Yubico. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.yubico.yubikit.desktop; +package com.yubico.yubikit.desktop.hid; public interface HidSessionListener { /** diff --git a/desktop/src/main/java/com/yubico/yubikit/desktop/hid/package-info.java b/desktop/src/main/java/com/yubico/yubikit/desktop/hid/package-info.java new file mode 100755 index 00000000..cb7b2006 --- /dev/null +++ b/desktop/src/main/java/com/yubico/yubikit/desktop/hid/package-info.java @@ -0,0 +1,4 @@ +@PackageNonnullByDefault +package com.yubico.yubikit.desktop.hid; + +import com.yubico.yubikit.core.PackageNonnullByDefault; \ No newline at end of file diff --git a/desktop/src/main/java/com/yubico/yubikit/desktop/PcscDevice.java b/desktop/src/main/java/com/yubico/yubikit/desktop/pcsc/NfcPcscDevice.java similarity index 53% rename from desktop/src/main/java/com/yubico/yubikit/desktop/PcscDevice.java rename to desktop/src/main/java/com/yubico/yubikit/desktop/pcsc/NfcPcscDevice.java index 49e77fc8..390ab257 100755 --- a/desktop/src/main/java/com/yubico/yubikit/desktop/PcscDevice.java +++ b/desktop/src/main/java/com/yubico/yubikit/desktop/pcsc/NfcPcscDevice.java @@ -1,4 +1,20 @@ -package com.yubico.yubikit.desktop; +/* + * Copyright (C) 2022 Yubico. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.yubico.yubikit.desktop.pcsc; import com.yubico.yubikit.core.Transport; import com.yubico.yubikit.core.YubiKeyConnection; @@ -19,39 +35,16 @@ import javax.smartcardio.CardException; import javax.smartcardio.CardTerminal; -public class PcscDevice implements YubiKeyDevice { +public class NfcPcscDevice extends PcscDevice { private static final byte[] NDEF_AID = new byte[]{(byte) 0xd2, 0x76, 0x00, 0x00, (byte) 0x85, 0x01, 0x01}; - private final ExecutorService executorService = Executors.newSingleThreadExecutor(); - private final CardTerminal terminal; - private final Transport transport; - - public PcscDevice(CardTerminal terminal) { - this.terminal = terminal; - - // If the terminal has YubiKey in the name, it's connected via USB. Otherwise we assume it's NFC - if (terminal.getName().toLowerCase().contains("yubikey")) { - transport = Transport.USB; - } else { - transport = Transport.NFC; - } - } - - public String getReaderName() { - return terminal.getName(); + public NfcPcscDevice(CardTerminal terminal) { + super(terminal); } @Override public Transport getTransport() { - return transport; - } - - public SmartCardConnection openIso7816Connection() throws IOException { - try { - return new PcscSmartCardConnection(terminal.connect("T=1")); - } catch (CardException e) { - throw new IOException(e); - } + return Transport.NFC; } /** @@ -78,25 +71,4 @@ public byte[] readNdef() throws IOException, ApduException, ApplicationNotAvaila return buf.array(); } } - - @Override - public boolean supportsConnection(Class connectionType) { - return connectionType.isAssignableFrom(PcscSmartCardConnection.class); - } - - @Override - public void requestConnection(Class connectionType, Callback> callback) { - if (!supportsConnection(connectionType)) { - throw new IllegalStateException("Unsupported connection type"); - } - executorService.submit(() -> { - try { - callback.invoke(Result.success(connectionType.cast(new PcscSmartCardConnection(terminal.connect("T=1"))))); - } catch (CardException e) { - callback.invoke(Result.failure(new IOException(e))); - } catch (IOException e) { - callback.invoke(Result.failure(e)); - } - }); - } } diff --git a/desktop/src/main/java/com/yubico/yubikit/desktop/PcscConfiguration.java b/desktop/src/main/java/com/yubico/yubikit/desktop/pcsc/PcscConfiguration.java similarity index 65% rename from desktop/src/main/java/com/yubico/yubikit/desktop/PcscConfiguration.java rename to desktop/src/main/java/com/yubico/yubikit/desktop/pcsc/PcscConfiguration.java index 1c63e944..b87bda9d 100755 --- a/desktop/src/main/java/com/yubico/yubikit/desktop/PcscConfiguration.java +++ b/desktop/src/main/java/com/yubico/yubikit/desktop/pcsc/PcscConfiguration.java @@ -1,4 +1,20 @@ -package com.yubico.yubikit.desktop; +/* + * Copyright (C) 2022 Yubico. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.yubico.yubikit.desktop.pcsc; import com.yubico.yubikit.core.Transport; diff --git a/desktop/src/main/java/com/yubico/yubikit/desktop/pcsc/PcscDevice.java b/desktop/src/main/java/com/yubico/yubikit/desktop/pcsc/PcscDevice.java new file mode 100755 index 00000000..1fa9a6c0 --- /dev/null +++ b/desktop/src/main/java/com/yubico/yubikit/desktop/pcsc/PcscDevice.java @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2022 Yubico. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.yubico.yubikit.desktop.pcsc; + +import com.yubico.yubikit.core.YubiKeyConnection; +import com.yubico.yubikit.core.YubiKeyDevice; +import com.yubico.yubikit.core.smartcard.SmartCardConnection; +import com.yubico.yubikit.core.util.Callback; +import com.yubico.yubikit.core.util.Result; + +import javax.smartcardio.CardException; +import javax.smartcardio.CardTerminal; +import java.io.IOException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +abstract class PcscDevice implements YubiKeyDevice { + private final ExecutorService executorService = Executors.newSingleThreadExecutor(); + private final CardTerminal terminal; + + public PcscDevice(CardTerminal terminal) { + this.terminal = terminal; + } + + public String getName() { + return terminal.getName(); + } + + public SmartCardConnection openIso7816Connection() throws IOException { + try { + return new PcscSmartCardConnection(terminal.connect("T=1")); + } catch (CardException e) { + throw new IOException(e); + } + } + + @Override + public boolean supportsConnection(Class connectionType) { + return connectionType.isAssignableFrom(PcscSmartCardConnection.class); + } + + public T openConnection(Class connectionType) throws IOException { + if (!supportsConnection(connectionType)) { + throw new IllegalStateException("Unsupported connection type"); + } + return connectionType.cast(openIso7816Connection()); + } + + @Override + public void requestConnection(Class connectionType, Callback> callback) { + if (!supportsConnection(connectionType)) { + throw new IllegalStateException("Unsupported connection type"); + } + executorService.submit(() -> { + try(T connection = openConnection(connectionType)) { + callback.invoke(Result.success(connection)); + } catch (IOException e) { + callback.invoke(Result.failure(e)); + } + }); + } +} diff --git a/desktop/src/main/java/com/yubico/yubikit/desktop/pcsc/PcscManager.java b/desktop/src/main/java/com/yubico/yubikit/desktop/pcsc/PcscManager.java new file mode 100755 index 00000000..8463e8a1 --- /dev/null +++ b/desktop/src/main/java/com/yubico/yubikit/desktop/pcsc/PcscManager.java @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2022 Yubico. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.yubico.yubikit.desktop.pcsc; + +import javax.smartcardio.CardException; +import javax.smartcardio.CardTerminal; +import javax.smartcardio.CardTerminals; +import javax.smartcardio.TerminalFactory; +import java.util.*; + +public class PcscManager { + private final TerminalFactory terminalFactory; + + public PcscManager(TerminalFactory terminalFactory) { + this.terminalFactory = terminalFactory; + } + + public PcscManager() { + this(TerminalFactory.getDefault()); + } + + public List getDevices() { + List yubikeys = new ArrayList<>(); + try { + for (CardTerminal device: terminalFactory.terminals().list(CardTerminals.State.CARD_PRESENT)) { + yubikeys.add(new UsbPcscDevice(device)); + } + } catch (CardException e) { + throw new RuntimeException(e); + } + return yubikeys; + } +} diff --git a/desktop/src/main/java/com/yubico/yubikit/desktop/PcscSessionListener.java b/desktop/src/main/java/com/yubico/yubikit/desktop/pcsc/PcscSessionListener.java similarity index 84% rename from desktop/src/main/java/com/yubico/yubikit/desktop/PcscSessionListener.java rename to desktop/src/main/java/com/yubico/yubikit/desktop/pcsc/PcscSessionListener.java index 69f27d6f..57869605 100755 --- a/desktop/src/main/java/com/yubico/yubikit/desktop/PcscSessionListener.java +++ b/desktop/src/main/java/com/yubico/yubikit/desktop/pcsc/PcscSessionListener.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2019 Yubico. + * Copyright (C) 2019-2022 Yubico. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.yubico.yubikit.desktop; +package com.yubico.yubikit.desktop.pcsc; public interface PcscSessionListener { /** @@ -22,12 +22,12 @@ public interface PcscSessionListener { * * @param session usb session that associated with plugged in device */ - void onSessionReceived(PcscDevice session); + void onSessionReceived(NfcPcscDevice session); /** * Invoked when detected removal/ejection of usb device after usb discovery started * * @param session usb session that will become inactive */ - void onSessionRemoved(PcscDevice session); + void onSessionRemoved(NfcPcscDevice session); } diff --git a/desktop/src/main/java/com/yubico/yubikit/desktop/PcscSmartCardConnection.java b/desktop/src/main/java/com/yubico/yubikit/desktop/pcsc/PcscSmartCardConnection.java similarity index 74% rename from desktop/src/main/java/com/yubico/yubikit/desktop/PcscSmartCardConnection.java rename to desktop/src/main/java/com/yubico/yubikit/desktop/pcsc/PcscSmartCardConnection.java index 52bfb292..f20d9598 100755 --- a/desktop/src/main/java/com/yubico/yubikit/desktop/PcscSmartCardConnection.java +++ b/desktop/src/main/java/com/yubico/yubikit/desktop/pcsc/PcscSmartCardConnection.java @@ -1,4 +1,20 @@ -package com.yubico.yubikit.desktop; +/* + * Copyright (C) 2022 Yubico. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.yubico.yubikit.desktop.pcsc; import com.yubico.yubikit.core.Logger; import com.yubico.yubikit.core.Transport; @@ -41,6 +57,7 @@ public boolean isExtendedLengthApduSupported() { @Override public void close() throws IOException { + Logger.d("Closing CCID connection"); try { card.endExclusive(); } catch (CardException e) { diff --git a/desktop/src/main/java/com/yubico/yubikit/desktop/pcsc/UsbPcscDevice.java b/desktop/src/main/java/com/yubico/yubikit/desktop/pcsc/UsbPcscDevice.java new file mode 100755 index 00000000..bb30edd8 --- /dev/null +++ b/desktop/src/main/java/com/yubico/yubikit/desktop/pcsc/UsbPcscDevice.java @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2022 Yubico. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.yubico.yubikit.desktop.pcsc; + +import com.yubico.yubikit.core.*; +import com.yubico.yubikit.core.smartcard.SmartCardConnection; +import com.yubico.yubikit.core.util.Callback; +import com.yubico.yubikit.core.util.Result; +import com.yubico.yubikit.desktop.UsbYubiKeyDevice; + +import javax.smartcardio.CardException; +import javax.smartcardio.CardTerminal; +import java.io.IOException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +public class UsbPcscDevice extends PcscDevice implements UsbYubiKeyDevice { + private final UsbPid pid; + + public UsbPcscDevice(CardTerminal terminal) { + super(terminal); + this.pid = getPidFromName(terminal.getName()); + } + + private static UsbPid getPidFromName(String name) { + if (!name.toLowerCase().contains("yubikey")) { + throw new IllegalArgumentException("Given argument is not a USB YubiKey"); + } + + int usbInterfaces = 0; + if (name.contains("CCID")) { + usbInterfaces |= UsbInterface.CCID; + } + if (name.contains("OTP")) { + usbInterfaces |= UsbInterface.OTP; + } + if (name.contains("FIDO") || name.contains("U2F")) { + usbInterfaces |= UsbInterface.FIDO; + } + YubiKeyType keyType = name.contains("NEO") ? YubiKeyType.NEO : YubiKeyType.YK4; + + for (UsbPid pid : UsbPid.values()) { + if (pid.type == keyType && pid.usbInterfaces == usbInterfaces) { + return pid; + } + } + + throw new IllegalArgumentException("No known PID for device name"); + } + + @Override + public Transport getTransport() { + return Transport.USB; + } + + @Override + public String getFingerprint() { + return getName(); + } + + @Override + public UsbPid getPid() { + return pid; + } +} diff --git a/desktop/src/main/java/com/yubico/yubikit/desktop/pcsc/package-info.java b/desktop/src/main/java/com/yubico/yubikit/desktop/pcsc/package-info.java new file mode 100755 index 00000000..56387438 --- /dev/null +++ b/desktop/src/main/java/com/yubico/yubikit/desktop/pcsc/package-info.java @@ -0,0 +1,4 @@ +@PackageNonnullByDefault +package com.yubico.yubikit.desktop.pcsc; + +import com.yubico.yubikit.core.PackageNonnullByDefault; \ No newline at end of file From cf98ed84fbe973644fee8fd2cb04e477060e18d5 Mon Sep 17 00:00:00 2001 From: Dain Nilsson Date: Wed, 12 Oct 2022 17:00:34 -0700 Subject: [PATCH 07/24] Fix tests. --- .../yubikit/testing/DesktopTestDriver.java | 34 +------------------ 1 file changed, 1 insertion(+), 33 deletions(-) diff --git a/testing-desktop/src/main/java/com/yubico/yubikit/testing/DesktopTestDriver.java b/testing-desktop/src/main/java/com/yubico/yubikit/testing/DesktopTestDriver.java index cfff21df..35c2c06b 100644 --- a/testing-desktop/src/main/java/com/yubico/yubikit/testing/DesktopTestDriver.java +++ b/testing-desktop/src/main/java/com/yubico/yubikit/testing/DesktopTestDriver.java @@ -18,53 +18,21 @@ import com.yubico.yubikit.core.YubiKeyDevice; import com.yubico.yubikit.desktop.*; -import org.jetbrains.annotations.NotNull; - -import java.util.concurrent.ArrayBlockingQueue; -import java.util.concurrent.BlockingQueue; public class DesktopTestDriver { - private final BlockingQueue sessionQueue = new ArrayBlockingQueue<>(1); - private final YubiKitManager yubikit; - private Thread observerThread = null; - public DesktopTestDriver() { if (OperatingSystem.isMac()) { System.setProperty("sun.security.smartcardio.library", "/System/Library/Frameworks/PCSC.framework/Versions/Current/PCSC"); } yubikit = new YubiKitManager(); - startObserving(); } - private void startObserving() { - - observerThread = new Thread(() -> yubikit.run(new PcscConfiguration(), new PcscSessionListener() { - @Override - public void onSessionReceived(@NotNull PcscDevice session) { - sessionQueue.add(session); - System.out.println("Session added"); - } - - @Override - public void onSessionRemoved(@NotNull PcscDevice session) { - System.out.println("Session removed"); - } - })); - - observerThread.start(); - } - - private void stopObserving() { - yubikit.stop(); - } public YubiKeyDevice awaitSession() throws InterruptedException { - YubiKeyDevice connectedDevice = sessionQueue.take(); - System.out.println("Device connected"); - return connectedDevice; + return yubikit.listAllDevices().keySet().iterator().next(); } public void returnSession(YubiKeyDevice device) { From d1f25a4348798aa915f81b00225b1855bc983545 Mon Sep 17 00:00:00 2001 From: Greg Domzalski Date: Wed, 12 Oct 2022 19:11:31 -0700 Subject: [PATCH 08/24] hid4java already does buffer manip The hid4java API returns lengths that include both the payload and the extra byte for the report ID. This extra byte can essentially be ignored. Right now this extra byte is special cased in our code to run on Windows - we'll need to test on other OSes to see if it is necessary there as well. --- .../com/yubico/yubikit/desktop/hid/HidOtpConnection.java | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/desktop/src/main/java/com/yubico/yubikit/desktop/hid/HidOtpConnection.java b/desktop/src/main/java/com/yubico/yubikit/desktop/hid/HidOtpConnection.java index e59ab92c..19a78622 100755 --- a/desktop/src/main/java/com/yubico/yubikit/desktop/hid/HidOtpConnection.java +++ b/desktop/src/main/java/com/yubico/yubikit/desktop/hid/HidOtpConnection.java @@ -43,10 +43,7 @@ public void receive(byte[] report) throws IOException { int offset = OperatingSystem.isWindows() ? 1 : 0; int reportSize = FEATURE_REPORT_SIZE + offset; - byte[] temp = new byte[reportSize]; - int received = hidDevice.getFeatureReport(temp, interfaceId); - - System.arraycopy(temp, offset, report, 0, FEATURE_REPORT_SIZE); + int received = hidDevice.getFeatureReport(report, interfaceId); if (received != reportSize) { throw new IOException("Unexpected amount of data read: " + received); From 7365e669d139972a3502bb60399a4a80cb884243 Mon Sep 17 00:00:00 2001 From: Adam Velebil Date: Wed, 11 Dec 2024 07:47:43 +0100 Subject: [PATCH 09/24] rebased experimental desktop code on top of main --- .../groovy/project-convention-java-library.gradle | 4 ---- desktop/build.gradle | 7 +------ .../yubico/yubikit/desktop/CompositeDevice.java | 6 ++++++ .../desktop/pcsc/PcscSmartCardConnection.java | 6 ++++++ settings.gradle | 2 +- testing-desktop/build.gradle | 2 +- .../testing/framework/PivInstrumentedTests.java | 14 ++++++++------ .../testing/framework/YKInstrumentedTests.java | 14 ++++++++++---- 8 files changed, 33 insertions(+), 22 deletions(-) diff --git a/buildSrc/src/main/groovy/project-convention-java-library.gradle b/buildSrc/src/main/groovy/project-convention-java-library.gradle index 0e7a1845..cd53941f 100644 --- a/buildSrc/src/main/groovy/project-convention-java-library.gradle +++ b/buildSrc/src/main/groovy/project-convention-java-library.gradle @@ -7,7 +7,3 @@ java { targetCompatibility = JavaVersion.VERSION_1_8 sourceCompatibility = JavaVersion.VERSION_1_8 } - -compileJava { - options.compilerArgs.addAll(['--release', '8']) -} \ No newline at end of file diff --git a/desktop/build.gradle b/desktop/build.gradle index b9be7616..6b308217 100755 --- a/desktop/build.gradle +++ b/desktop/build.gradle @@ -1,16 +1,11 @@ -apply plugin: 'java-library' +apply plugin: 'yubikit-java-library' dependencies { api project(':support') - compileOnly 'com.google.code.findbugs:jsr305:3.0.2' - implementation 'org.hid4java:hid4java:0.6.0' } -sourceCompatibility = "1.8" -targetCompatibility = "1.8" - ext.pomName = "Yubico YubiKit Desktop" description = "This module is the core library desktop implementation and provides functionality to detect a YubiKey plugged in or tapped over NFC and to open an ISO/IEC 7816 connection, using the javax.smartcardio API." diff --git a/desktop/src/main/java/com/yubico/yubikit/desktop/CompositeDevice.java b/desktop/src/main/java/com/yubico/yubikit/desktop/CompositeDevice.java index 26c285ce..edc3053f 100755 --- a/desktop/src/main/java/com/yubico/yubikit/desktop/CompositeDevice.java +++ b/desktop/src/main/java/com/yubico/yubikit/desktop/CompositeDevice.java @@ -47,4 +47,10 @@ public boolean supportsConnection(Class connectionT public void requestConnection(Class connectionType, Callback> callback) { pidGroup.requestConnection(key, connectionType, callback); } + + @Override + public T openConnection(Class connectionType) throws IOException { + // TODO + return null; + } } diff --git a/desktop/src/main/java/com/yubico/yubikit/desktop/pcsc/PcscSmartCardConnection.java b/desktop/src/main/java/com/yubico/yubikit/desktop/pcsc/PcscSmartCardConnection.java index f20d9598..7ad8ea7a 100755 --- a/desktop/src/main/java/com/yubico/yubikit/desktop/pcsc/PcscSmartCardConnection.java +++ b/desktop/src/main/java/com/yubico/yubikit/desktop/pcsc/PcscSmartCardConnection.java @@ -55,6 +55,12 @@ public boolean isExtendedLengthApduSupported() { return false; //TODO } + @Override + public byte[] getAtr() { + // TODO + return new byte[0]; + } + @Override public void close() throws IOException { Logger.d("Closing CCID connection"); diff --git a/settings.gradle b/settings.gradle index a0a5cfb1..76e67d28 100755 --- a/settings.gradle +++ b/settings.gradle @@ -1,4 +1,4 @@ include ':core', ':oath', ':yubiotp', ':management', ':piv', ':openpgp', ':support', ':fido' include ':testing' include ':android', ':AndroidDemo', ':testing-android' -include ':desktop', ':DesktopDemo' +include ':desktop', ':DesktopDemo', ':testing-desktop' diff --git a/testing-desktop/build.gradle b/testing-desktop/build.gradle index b390707a..4931ea11 100755 --- a/testing-desktop/build.gradle +++ b/testing-desktop/build.gradle @@ -7,7 +7,7 @@ repositories { } dependencies { - implementation 'org.jetbrains:annotations:20.1.0' + implementation 'org.jetbrains:annotations:23.0.0' testImplementation('junit:junit:4.13.2') testRuntimeOnly('org.junit.vintage:junit-vintage-engine:5.9.0') diff --git a/testing-desktop/src/main/java/com/yubico/yubikit/testing/framework/PivInstrumentedTests.java b/testing-desktop/src/main/java/com/yubico/yubikit/testing/framework/PivInstrumentedTests.java index 7c483a7f..f3d52294 100755 --- a/testing-desktop/src/main/java/com/yubico/yubikit/testing/framework/PivInstrumentedTests.java +++ b/testing-desktop/src/main/java/com/yubico/yubikit/testing/framework/PivInstrumentedTests.java @@ -18,23 +18,25 @@ import com.yubico.yubikit.core.smartcard.SmartCardConnection; import com.yubico.yubikit.piv.PivSession; +import com.yubico.yubikit.testing.TestState; +import com.yubico.yubikit.testing.piv.PivTestState; import java.util.Optional; import java.util.concurrent.LinkedBlockingQueue; public class PivInstrumentedTests extends YKInstrumentedTests { - public interface Callback { - void invoke(PivSession value) throws Throwable; - } + protected void withPivSession(TestState.StatefulSessionCallback callback) throws Throwable { - protected void withPivSession(Callback callback) throws Throwable { LinkedBlockingQueue> result = new LinkedBlockingQueue<>(); device.requestConnection(SmartCardConnection.class, callbackResult -> { try { if (callbackResult.isSuccess()) { - PivSession pivSession = new PivSession(callbackResult.getValue()); - callback.invoke(pivSession); + + final PivTestState state = new PivTestState.Builder(device, usbPid) + .scpKid(getScpKid()) + .build(); + state.withPiv(callback); result.offer(Optional.empty()); } } catch (Throwable e) { diff --git a/testing-desktop/src/main/java/com/yubico/yubikit/testing/framework/YKInstrumentedTests.java b/testing-desktop/src/main/java/com/yubico/yubikit/testing/framework/YKInstrumentedTests.java index 5ae3ecd0..16f5a99e 100755 --- a/testing-desktop/src/main/java/com/yubico/yubikit/testing/framework/YKInstrumentedTests.java +++ b/testing-desktop/src/main/java/com/yubico/yubikit/testing/framework/YKInstrumentedTests.java @@ -16,22 +16,24 @@ package com.yubico.yubikit.testing.framework; +import com.yubico.yubikit.core.UsbPid; import com.yubico.yubikit.core.YubiKeyDevice; -import org.junit.After; -import org.junit.Before; +import org.jetbrains.annotations.Nullable; import org.junit.Rule; import org.junit.rules.ExternalResource; import org.junit.rules.TestName; -import org.junit.rules.TestRule; import com.yubico.yubikit.testing.DesktopTestDriver; public class YKInstrumentedTests { - protected YubiKeyDevice device = null; private final DesktopTestDriver testDriver = new DesktopTestDriver(); + protected YubiKeyDevice device = null; + protected UsbPid usbPid = null; + + @Rule public final TestName name = new TestName(); @@ -52,4 +54,8 @@ protected void after() { } }; + @Nullable + protected Byte getScpKid() { + return null; + } } From 9a30480b39c27d2ad68728efd31d164c1cbca4a2 Mon Sep 17 00:00:00 2001 From: Adam Velebil Date: Wed, 11 Dec 2024 14:36:19 +0100 Subject: [PATCH 10/24] fix SLF4J, add desktop version of device tests --- DesktopDemo/build.gradle | 3 +- .../yubikit/desktop/app/DesktopApp.java | 269 +++--------------- DesktopDemo/src/main/logback.xml | 31 ++ desktop/build.gradle | 2 +- .../yubikit/desktop/CompositeDevice.java | 7 +- .../yubikit/desktop/OperatingSystem.java | 15 +- .../yubico/yubikit/desktop/UsbPidGroup.java | 78 ++++- .../yubikit/desktop/YubiKitManager.java | 12 +- .../yubikit/desktop/hid/HidManager.java | 18 +- .../yubikit/desktop/hid/HidOtpConnection.java | 6 +- .../yubikit/desktop/pcsc/NfcPcscDevice.java | 8 - .../desktop/pcsc/PcscSmartCardConnection.java | 15 +- .../yubikit/desktop/pcsc/UsbPcscDevice.java | 12 +- testing-desktop/build.gradle | 7 +- .../yubikit/testing/AlwaysManualTest.java | 20 ++ .../yubikit/testing/DesktopTestDriver.java | 12 +- .../testing/PinUvAuthProtocolV1Test.java | 20 ++ .../com/yubico/yubikit/testing/SlowTest.java | 20 ++ .../com/yubico/yubikit/testing/SmokeTest.java | 20 ++ .../framework/FidoInstrumentedTests.java | 68 +++++ .../ManagementInstrumentedTests.java | 33 +++ .../framework/MpeInstrumentedTests.java | 39 +++ .../framework/OathInstrumentedTests.java | 40 +++ .../framework/OpenPgpInstrumentedTests.java | 30 ++ .../framework/PivInstrumentedTests.java | 31 +- .../SecurityDomainInstrumentedTests.java | 31 ++ .../framework/YKInstrumentedTests.java | 13 +- .../yubico/yubikit/testing/DeviceTests.java | 45 +++ .../yubikit/testing/FastDeviceTests.java | 39 +++ .../yubikit/testing/PivJcaProviderTests.java | 48 ---- .../yubikit/testing/SmokeDeviceTests.java | 32 +++ .../BasicWebAuthnClientInstrumentedTests.java | 87 ++++++ .../Ctap2BioEnrollmentInstrumentedTests.java | 29 ++ .../fido/Ctap2ClientPinInstrumentedTests.java | 54 ++++ .../fido/Ctap2ConfigInstrumentedTests.java | 82 ++++++ ...CredentialManagementInstrumentedTests.java | 62 ++++ .../fido/Ctap2SessionInstrumentedTests.java | 61 ++++ .../Ctap2SessionResetInstrumentedTests.java | 60 ++++ ...nterpriseAttestationInstrumentedTests.java | 64 +++++ .../yubikit/testing/fido/FidoTests.java | 46 +++ .../fido/UvDiscouragedInstrumentedTests.java | 51 ++++ .../testing/management/ManagementTests.java | 28 ++ .../testing/mpe/MultiProtocolResetTests.java | 57 ++++ .../yubikit/testing/oath/OathTests.java | 66 +++++ .../yubikit/testing/openpgp/OpenPgpTests.java | 153 ++++++++++ .../PivBioMultiProtocolTests.java} | 21 +- .../testing/piv/PivJcaProviderTests.java | 77 +++++ .../yubico/yubikit/testing/piv/PivTests.java | 83 ++++++ .../yubico/yubikit/testing/sd/Scp03Tests.java | 52 ++++ .../yubico/yubikit/testing/sd/Scp11Tests.java | 65 +++++ .../testing/sd/SecurityDomainTests.java | 28 ++ .../src/test/resources/logback-test.xml | 31 ++ .../yubikit/testing/piv/PivMoveKeyTests.java | 2 +- .../piv/PivPinComplexityDeviceTests.java | 2 +- 54 files changed, 1894 insertions(+), 391 deletions(-) create mode 100644 DesktopDemo/src/main/logback.xml create mode 100644 testing-desktop/src/main/java/com/yubico/yubikit/testing/AlwaysManualTest.java create mode 100644 testing-desktop/src/main/java/com/yubico/yubikit/testing/PinUvAuthProtocolV1Test.java create mode 100644 testing-desktop/src/main/java/com/yubico/yubikit/testing/SlowTest.java create mode 100644 testing-desktop/src/main/java/com/yubico/yubikit/testing/SmokeTest.java create mode 100755 testing-desktop/src/main/java/com/yubico/yubikit/testing/framework/FidoInstrumentedTests.java create mode 100644 testing-desktop/src/main/java/com/yubico/yubikit/testing/framework/ManagementInstrumentedTests.java create mode 100755 testing-desktop/src/main/java/com/yubico/yubikit/testing/framework/MpeInstrumentedTests.java create mode 100644 testing-desktop/src/main/java/com/yubico/yubikit/testing/framework/OathInstrumentedTests.java create mode 100644 testing-desktop/src/main/java/com/yubico/yubikit/testing/framework/OpenPgpInstrumentedTests.java create mode 100644 testing-desktop/src/main/java/com/yubico/yubikit/testing/framework/SecurityDomainInstrumentedTests.java create mode 100644 testing-desktop/src/test/java/com/yubico/yubikit/testing/DeviceTests.java create mode 100644 testing-desktop/src/test/java/com/yubico/yubikit/testing/FastDeviceTests.java delete mode 100644 testing-desktop/src/test/java/com/yubico/yubikit/testing/PivJcaProviderTests.java create mode 100644 testing-desktop/src/test/java/com/yubico/yubikit/testing/SmokeDeviceTests.java create mode 100644 testing-desktop/src/test/java/com/yubico/yubikit/testing/fido/BasicWebAuthnClientInstrumentedTests.java create mode 100644 testing-desktop/src/test/java/com/yubico/yubikit/testing/fido/Ctap2BioEnrollmentInstrumentedTests.java create mode 100644 testing-desktop/src/test/java/com/yubico/yubikit/testing/fido/Ctap2ClientPinInstrumentedTests.java create mode 100644 testing-desktop/src/test/java/com/yubico/yubikit/testing/fido/Ctap2ConfigInstrumentedTests.java create mode 100644 testing-desktop/src/test/java/com/yubico/yubikit/testing/fido/Ctap2CredentialManagementInstrumentedTests.java create mode 100644 testing-desktop/src/test/java/com/yubico/yubikit/testing/fido/Ctap2SessionInstrumentedTests.java create mode 100644 testing-desktop/src/test/java/com/yubico/yubikit/testing/fido/Ctap2SessionResetInstrumentedTests.java create mode 100644 testing-desktop/src/test/java/com/yubico/yubikit/testing/fido/EnterpriseAttestationInstrumentedTests.java create mode 100644 testing-desktop/src/test/java/com/yubico/yubikit/testing/fido/FidoTests.java create mode 100644 testing-desktop/src/test/java/com/yubico/yubikit/testing/fido/UvDiscouragedInstrumentedTests.java create mode 100644 testing-desktop/src/test/java/com/yubico/yubikit/testing/management/ManagementTests.java create mode 100644 testing-desktop/src/test/java/com/yubico/yubikit/testing/mpe/MultiProtocolResetTests.java create mode 100644 testing-desktop/src/test/java/com/yubico/yubikit/testing/oath/OathTests.java create mode 100644 testing-desktop/src/test/java/com/yubico/yubikit/testing/openpgp/OpenPgpTests.java rename testing-desktop/src/test/java/com/yubico/yubikit/testing/{PivTests.java => piv/PivBioMultiProtocolTests.java} (57%) create mode 100644 testing-desktop/src/test/java/com/yubico/yubikit/testing/piv/PivJcaProviderTests.java create mode 100644 testing-desktop/src/test/java/com/yubico/yubikit/testing/piv/PivTests.java create mode 100644 testing-desktop/src/test/java/com/yubico/yubikit/testing/sd/Scp03Tests.java create mode 100644 testing-desktop/src/test/java/com/yubico/yubikit/testing/sd/Scp11Tests.java create mode 100644 testing-desktop/src/test/java/com/yubico/yubikit/testing/sd/SecurityDomainTests.java create mode 100644 testing-desktop/src/test/resources/logback-test.xml diff --git a/DesktopDemo/build.gradle b/DesktopDemo/build.gradle index 00cf9e84..33d822e2 100755 --- a/DesktopDemo/build.gradle +++ b/DesktopDemo/build.gradle @@ -5,8 +5,9 @@ plugins { dependencies { compileOnly 'com.google.code.findbugs:jsr305:3.0.2' + implementation 'ch.qos.logback:logback-classic:1.5.12' + implementation project(':desktop') - implementation project(':testing') } application { diff --git a/DesktopDemo/src/main/java/com/yubico/yubikit/desktop/app/DesktopApp.java b/DesktopDemo/src/main/java/com/yubico/yubikit/desktop/app/DesktopApp.java index a4c6817d..6f8a6ae9 100755 --- a/DesktopDemo/src/main/java/com/yubico/yubikit/desktop/app/DesktopApp.java +++ b/DesktopDemo/src/main/java/com/yubico/yubikit/desktop/app/DesktopApp.java @@ -1,62 +1,38 @@ +/* + * Copyright (C) 2024 Yubico. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package com.yubico.yubikit.desktop.app; -import com.yubico.yubikit.core.Logger; import com.yubico.yubikit.core.YubiKeyDevice; -import com.yubico.yubikit.core.application.ApplicationNotAvailableException; -import com.yubico.yubikit.core.application.BadResponseException; import com.yubico.yubikit.core.fido.FidoConnection; import com.yubico.yubikit.core.otp.OtpConnection; -import com.yubico.yubikit.core.smartcard.ApduException; -import com.yubico.yubikit.desktop.*; import com.yubico.yubikit.core.smartcard.SmartCardConnection; -import com.yubico.yubikit.desktop.hid.HidDevice; -import com.yubico.yubikit.desktop.hid.HidSessionListener; -import com.yubico.yubikit.desktop.hid.HidManager; -import com.yubico.yubikit.desktop.pcsc.NfcPcscDevice; +import com.yubico.yubikit.desktop.OperatingSystem; +import com.yubico.yubikit.desktop.YubiKitManager; import com.yubico.yubikit.management.DeviceInfo; -import com.yubico.yubikit.piv.KeyType; -import com.yubico.yubikit.piv.ManagementKeyType; -import com.yubico.yubikit.piv.PinPolicy; -import com.yubico.yubikit.piv.PivSession; -import com.yubico.yubikit.piv.Slot; -import com.yubico.yubikit.piv.SlotMetadata; -import com.yubico.yubikit.piv.TouchPolicy; -import com.yubico.yubikit.piv.jca.PivAlgorithmParameterSpec; -import com.yubico.yubikit.piv.jca.PivKeyManager; -import com.yubico.yubikit.piv.jca.PivPrivateKey; -import com.yubico.yubikit.piv.jca.PivProvider; -import com.yubico.yubikit.testing.Codec; -import com.yubico.yubikit.testing.piv.PivTestUtils; -import com.yubico.yubikit.yubiotp.YubiOtpSession; -import java.io.BufferedReader; +import org.slf4j.LoggerFactory; + import java.io.IOException; -import java.io.InputStreamReader; -import java.net.URL; -import java.nio.charset.StandardCharsets; -import java.security.InvalidAlgorithmParameterException; -import java.security.InvalidKeyException; -import java.security.KeyPair; -import java.security.KeyPairGenerator; -import java.security.KeyStore; -import java.security.NoSuchAlgorithmException; -import java.security.NoSuchProviderException; -import java.security.Provider; -import java.security.Security; -import java.security.SignatureException; -import java.security.cert.CertificateException; -import java.security.cert.X509Certificate; -import java.util.Arrays; -import java.util.HashSet; -import java.util.List; import java.util.Map; -import java.util.concurrent.Semaphore; - -import javax.net.ssl.HttpsURLConnection; -import javax.net.ssl.KeyManager; -import javax.net.ssl.SSLContext; public class DesktopApp { + + private static final org.slf4j.Logger logger = LoggerFactory.getLogger(DesktopApp.class); + public static void main(String[] argv) { if (OperatingSystem.isMac()) { System.setProperty("sun.security.smartcardio.library", "/System/Library/Frameworks/PCSC.framework/Versions/Current/PCSC"); @@ -64,225 +40,52 @@ public static void main(String[] argv) { System.out.println("Insert YubiKey now..."); - Logger.setLogger(new Logger() { - @Override - protected void logDebug(String message) { - System.err.println("DEBUG: " + message); - } - - @Override - protected void logError(String message, Throwable throwable) { - System.err.println("ERROR: " + message); - throwable.printStackTrace(); - } - }); - YubiKitManager manager = new YubiKitManager(); Map devices = manager.listAllDevices(); - Logger.d("Devices: " + devices); + logger.debug("Devices: {}", devices); for (Map.Entry entry : devices.entrySet()) { YubiKeyDevice device = entry.getKey(); DeviceInfo info = entry.getValue(); - Logger.d("FOUND KEY: " + device + " " + info); + logger.debug("Found key: {} {}", device, info); if (device.supportsConnection(SmartCardConnection.class)) { - Logger.d("Request CCID connection"); + logger.debug("Request CCID connection"); device.requestConnection(SmartCardConnection.class, value -> { try { - Logger.d("Got CCID connection " + value.getValue()); + logger.debug("Got CCID connection {}", value.getValue()); } catch (IOException e) { - Logger.e("Failed to get CCID", e); + logger.error("Failed to get CCID: ", e); } }); } if (device.supportsConnection(OtpConnection.class)) { - Logger.d("Request OTP connection"); + logger.debug("Request OTP connection"); device.requestConnection(OtpConnection.class, value -> { try { - Logger.d("Got OTP connection " + value.getValue()); + logger.debug("Got OTP connection {}", value.getValue()); } catch (IOException e) { - Logger.e("Failed to get OTP", e); + logger.error("Failed to get OTP: ", e); } }); } if (device.supportsConnection(FidoConnection.class)) { - Logger.d("Request FIDO connection"); + logger.debug("Request FIDO connection"); device.requestConnection(FidoConnection.class, value -> { try { - Logger.d("Got FIDO connection " + value.getValue()); + logger.debug("Got FIDO connection {}", value.getValue()); } catch (IOException e) { - Logger.e("Failed to get FIDO", e); + logger.error("Failed to get FIDO: ", e); } }); } } - //testHidOtp(); - //testCcid(); - - Logger.d("Sleeping..."); + logger.debug("Sleeping..."); try { Thread.sleep(5000); } catch (InterruptedException e) { throw new RuntimeException(e); } - Logger.d("Application exited"); - } - - private static void testHttps(PivSession piv) throws Exception { - Security.addProvider(new PivProvider(piv)); - - URL url = new URL("https://dain.se:8443"); - - KeyStore keyStore = KeyStore.getInstance("YKPiv"); - keyStore.load(null); - PivPrivateKey privateKey = (PivPrivateKey) keyStore.getKey("9a", "123456".toCharArray()); - - X509Certificate certificate = (X509Certificate) keyStore.getCertificate("9a"); - //PivPrivateKey privateKey = PivPrivateKey.from(certificate.getPublicKey(), Slot.AUTHENTICATION, null); - - SSLContext sslContext = SSLContext.getInstance("TLS"); - sslContext.init(new KeyManager[]{new PivKeyManager(privateKey, new X509Certificate[]{certificate})}, null, null); - - HttpsURLConnection connection = (HttpsURLConnection) url.openConnection(); - connection.setSSLSocketFactory(sslContext.getSocketFactory()); - - piv.verifyPin("123456".toCharArray()); - - try(BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream(), StandardCharsets.UTF_8))) { - reader.lines().forEach(Logger::d); - } - - Security.removeProvider("YKPiv"); - } - - private static void testPiv(NfcPcscDevice session) { - try (PivSession piv = new PivSession(session.openIso7816Connection())) { - //piv.authenticate(new byte[]{1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8}); - //Logger.d("Generate key..."); - //piv.generateKey(Slot.SIGNATURE, KeyType.ECCP256, PinPolicy.DEFAULT, TouchPolicy.DEFAULT); - try { - Logger.d("Get metadata..."); - SlotMetadata metadata = piv.getSlotMetadata(Slot.AUTHENTICATION); - Logger.d("Metadata: " + metadata.getKeyType() + ", " + metadata.isGenerated() + ", " + metadata.getPinPolicy() + ", " + metadata.getPublicKey()); - - } catch (UnsupportedOperationException e) { - Logger.e("Metadata not supported", e); - } - piv.authenticate(ManagementKeyType.TDES, Codec.fromHex("010203040506070801020304050607080102030405060708")); - - Provider provider = new PivProvider(piv); - Security.addProvider(provider); - - // Create certificate - //Provider provider = new PivProvider(piv); - KeyPairGenerator kpg = KeyPairGenerator.getInstance("YKPivEC", provider); - kpg.initialize(new PivAlgorithmParameterSpec(Slot.AUTHENTICATION, KeyType.ECCP256, PinPolicy.ALWAYS, TouchPolicy.DEFAULT, "123456".toCharArray())); - KeyPair keyPair = kpg.generateKeyPair(); - - X509Certificate cert = PivTestUtils.createCertificate(keyPair); - cert.verify(keyPair.getPublic()); - piv.putCertificate(Slot.AUTHENTICATION, cert); - - piv.getCertificate(Slot.AUTHENTICATION); - - //Logger.d("Metadata management: " + piv.getSlotMetadata(Slot.CARD_MANAGEMENT)); - - //Logger.d("Metadata authentication: " + metadata.getKeyType() + ", " + metadata.isGenerated() + ", " + metadata.getPinPolicy() + ", " + metadata.getPublicKey()); - //metadata = piv.getSlotMetadata(Slot.SIGNATURE); - - - /* - PinMetadata pinMetadata = piv.getPinMetadata(); - Logger.d("PIN: default=" + pinMetadata.isDefaultValue() + ", total="+pinMetadata.getTotalAttempts()+", remaining="+pinMetadata.getAttemptsRemaining()); - - PinMetadata pukMetadata = piv.getPukMetadata(); - Logger.d("PUK: default=" + pukMetadata.isDefaultValue() + ", total="+pukMetadata.getTotalAttempts()+", remaining="+pukMetadata.getAttemptsRemaining()); - PivDeviceTests.testDecrypt(piv, KeyType.RSA1024); - PivDeviceTests.testDecrypt(piv, KeyType.RSA2048); - PivDeviceTests.testEcdh(piv, KeyType.ECCP256); - PivDeviceTests.testEcdh(piv, KeyType.ECCP384); - - piv.authenticate(Codec.fromHex("010203040506070801020304050607080102030405060708")); - PublicKey pub = piv.generateKey(Slot.AUTHENTICATION, KeyType.ECCP256, PinPolicy.ALWAYS, TouchPolicy.DEFAULT); - piv.verify("123456".toCharArray()); - X509Certificate cert = PivTestUtils.createCertificate(piv, pub, Slot.AUTHENTICATION, KeyType.ECCP256); - cert.verify(pub); - piv.putCertificate(Slot.AUTHENTICATION, cert); - - pub = piv.generateKey(Slot.AUTHENTICATION, KeyType.RSA1024, PinPolicy.DEFAULT, TouchPolicy.DEFAULT); - piv.verify("123456".toCharArray()); - cert = PivTestUtils.createCertificate(piv, pub, Slot.AUTHENTICATION, KeyType.RSA1024); - cert.verify(pub); - piv.putCertificate(Slot.AUTHENTICATION, cert); - - /* - PivDeviceTests.testManagementKey(piv); - PivDeviceTests.testPin(piv); - PivDeviceTests.testPuk(piv); - PivDeviceTests.testGenerateKeys(piv); - PivDeviceTests.testImportKeys(piv); - */ - } catch (RuntimeException e) { - Logger.e("Error", e.getCause() != null ? e.getCause() : e); - } catch (ApplicationNotAvailableException | ApduException | IOException e) { - Logger.e("Error", e); - } catch (SignatureException e) { - e.printStackTrace(); - } catch (BadResponseException e) { - e.printStackTrace(); - } catch (NoSuchAlgorithmException e) { - e.printStackTrace(); - } catch (CertificateException e) { - e.printStackTrace(); - } catch (InvalidKeyException e) { - e.printStackTrace(); - } catch (NoSuchProviderException e) { - e.printStackTrace(); - } catch (InvalidAlgorithmParameterException e) { - e.printStackTrace(); - } - Logger.d("PIV tests done!"); - } - - private static void testHidOtp() { - HidManager hidManager = new HidManager(); - - Semaphore lock = new Semaphore(0); - - hidManager.setListener(new HidSessionListener() { - @Override - public void onSessionReceived(HidDevice device) { - Logger.d("HID session started"); - YubiOtpSession.create(device, result -> { - try { - YubiOtpSession app = result.getValue(); - Logger.d("HID read version: " + app.getVersion()); - - Logger.d("Slot 1: " + app.getConfigurationState().isConfigured(com.yubico.yubikit.yubiotp.Slot.ONE)); - Logger.d("Slot 2: " + app.getConfigurationState().isConfigured(com.yubico.yubikit.yubiotp.Slot.TWO)); - //app.setHmacSha1Key(com.yubico.yubikit.otp.Slot.TWO, new byte[]{1,2,3,4,5,6}, true); - //app.setStaticPassword(com.yubico.yubikit.otp.Slot.TWO, new byte[]{(byte) 0x8b, 0x0c}); - app.swapConfigurations(); - //app.deleteSlot(com.yubico.yubikit.otp.Slot.ONE, null); - Logger.d("Configuration updated"); - } catch (Exception e) { - e.printStackTrace(); - } - lock.release(); - }); - } - - @Override - public void onSessionRemoved(HidDevice session) { - lock.release(); - } - }); - - try { - lock.acquire(); - } catch (InterruptedException e) { - e.printStackTrace(); - } + logger.debug("Application exited"); } } \ No newline at end of file diff --git a/DesktopDemo/src/main/logback.xml b/DesktopDemo/src/main/logback.xml new file mode 100644 index 00000000..62edd79f --- /dev/null +++ b/DesktopDemo/src/main/logback.xml @@ -0,0 +1,31 @@ + + + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger - %msg%n + + + + + + + + \ No newline at end of file diff --git a/desktop/build.gradle b/desktop/build.gradle index 6b308217..5587c758 100755 --- a/desktop/build.gradle +++ b/desktop/build.gradle @@ -3,7 +3,7 @@ apply plugin: 'yubikit-java-library' dependencies { api project(':support') - implementation 'org.hid4java:hid4java:0.6.0' + implementation 'org.hid4java:hid4java:0.8.0' } ext.pomName = "Yubico YubiKit Desktop" diff --git a/desktop/src/main/java/com/yubico/yubikit/desktop/CompositeDevice.java b/desktop/src/main/java/com/yubico/yubikit/desktop/CompositeDevice.java index edc3053f..d5127b74 100755 --- a/desktop/src/main/java/com/yubico/yubikit/desktop/CompositeDevice.java +++ b/desktop/src/main/java/com/yubico/yubikit/desktop/CompositeDevice.java @@ -50,7 +50,10 @@ public void requestConnection(Class connectionT @Override public T openConnection(Class connectionType) throws IOException { - // TODO - return null; + return pidGroup.openConnection(key, connectionType); + } + + public UsbPidGroup getPidGroup() { + return pidGroup; } } diff --git a/desktop/src/main/java/com/yubico/yubikit/desktop/OperatingSystem.java b/desktop/src/main/java/com/yubico/yubikit/desktop/OperatingSystem.java index 424b4556..67f25653 100644 --- a/desktop/src/main/java/com/yubico/yubikit/desktop/OperatingSystem.java +++ b/desktop/src/main/java/com/yubico/yubikit/desktop/OperatingSystem.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 Yubico. + * Copyright (C) 2022,2024 Yubico. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,23 +16,18 @@ package com.yubico.yubikit.desktop; -import java.lang.*; - public class OperatingSystem { - public static String Name = System.getProperty("os.name"); + public static final String Name = System.getProperty("os.name"); - public static boolean isWindows() - { + public static boolean isWindows() { return Name.toLowerCase().contains("win"); } - public static boolean isMac() - { + public static boolean isMac() { return Name.toLowerCase().contains("mac"); } - public static boolean isLinux() - { + public static boolean isLinux() { return Name.toLowerCase().contains("linux"); } } diff --git a/desktop/src/main/java/com/yubico/yubikit/desktop/UsbPidGroup.java b/desktop/src/main/java/com/yubico/yubikit/desktop/UsbPidGroup.java index e25fcd3d..239b1110 100755 --- a/desktop/src/main/java/com/yubico/yubikit/desktop/UsbPidGroup.java +++ b/desktop/src/main/java/com/yubico/yubikit/desktop/UsbPidGroup.java @@ -16,8 +16,13 @@ package com.yubico.yubikit.desktop; -import com.yubico.yubikit.core.*; +import com.yubico.yubikit.core.UsbInterface; +import com.yubico.yubikit.core.UsbPid; +import com.yubico.yubikit.core.YubiKeyConnection; +import com.yubico.yubikit.core.YubiKeyDevice; +import com.yubico.yubikit.core.YubiKeyType; import com.yubico.yubikit.core.fido.FidoConnection; +import com.yubico.yubikit.core.internal.Logger; import com.yubico.yubikit.core.otp.OtpConnection; import com.yubico.yubikit.core.smartcard.SmartCardConnection; import com.yubico.yubikit.core.util.Callback; @@ -25,6 +30,8 @@ import com.yubico.yubikit.management.DeviceInfo; import com.yubico.yubikit.support.DeviceUtil; +import org.slf4j.LoggerFactory; + import java.io.IOException; import java.util.*; @@ -37,6 +44,8 @@ public class UsbPidGroup { private final Set fingerprints = new HashSet<>(); private final long ctime = System.currentTimeMillis(); + private final org.slf4j.Logger logger = LoggerFactory.getLogger(UsbPidGroup.class); + UsbPidGroup(UsbPid pid) { this.pid = pid; } @@ -72,7 +81,7 @@ int getUsbInterface(Class connectionType) { } void add(Class connectionType, UsbYubiKeyDevice device, boolean forceResolve) { - Logger.d("Add device node " + device + connectionType); + Logger.trace(logger, "Add device node {}{}", device, connectionType); int usbInterface = getUsbInterface(connectionType); fingerprints.add(device.getFingerprint()); devCount.put(usbInterface, devCount.getOrDefault(usbInterface, 0) + 1); @@ -85,10 +94,13 @@ void add(Class connectionType, UsbYubiKeyDevice dev resolved.put(key, new HashMap<>()); } resolved.get(key).put(usbInterface, device); - Logger.d("Resolved device " + info.getSerialNumber()); + Integer serialNumber = info.getSerialNumber(); + Logger.trace(logger, "Resolved device {}", serialNumber != null + ? serialNumber + : "without serial number"); return; } catch (IOException e) { - Logger.e("Failed opening device", e); + Logger.error(logger, "Failed opening device. ", e); } } if (!unresolved.containsKey(usbInterface)) { @@ -101,20 +113,64 @@ boolean supportsConnection(Class connectionType) { return (getUsbInterface(connectionType) & pid.usbInterfaces) != 0; } + T openConnection(String key, Class connectionType) throws IOException { + int usbInterface = getUsbInterface(connectionType); + UsbYubiKeyDevice device = resolved.get(key).get(usbInterface); + if (device != null) { + return device.openConnection(connectionType); + } + + Logger.debug(logger, "Resolve device for {}, {}", connectionType, key); + List devices = unresolved.getOrDefault(usbInterface, new ArrayList<>()); + Logger.debug(logger, "Unresolved: {}", devices); + List failed = new ArrayList<>(); + try { + while (!devices.isEmpty()) { + device = devices.remove(0); + Logger.debug(logger, "Candidate: {}", device); + try (T connection = device.openConnection(connectionType)) { + DeviceInfo info = DeviceUtil.readInfo(connection, pid); + String deviceKey = buildKey(info); + if (infos.containsKey(deviceKey)) { + if (!resolved.containsKey(deviceKey)) { + resolved.put(deviceKey, new HashMap<>()); + } + resolved.get(deviceKey).put(usbInterface, device); + if (deviceKey.equals(key)) { + return device.openConnection(connectionType); + } else if (pid.type == YubiKeyType.NEO && devices.isEmpty()) { + Logger.debug(logger, "Resolved last NEO device without serial"); + return device.openConnection(connectionType); + } + } + + return connection; + } catch (IOException e) { + Logger.error(logger, "Failed opening candidate device: ", e); + failed.add(device); + } + } + } finally { + devices.addAll(failed); + } + + throw new IOException("Failed to open connection"); + } + void requestConnection(String key, Class connectionType, Callback> callback) { int usbInterface = getUsbInterface(connectionType); UsbYubiKeyDevice device = resolved.get(key).get(usbInterface); if (device != null) { device.requestConnection(connectionType, callback); } else { - Logger.d("Resolve device for " + connectionType + ", " + key); + Logger.debug(logger, "Resolve device for {}, {}", connectionType, key); List devices = unresolved.getOrDefault(usbInterface, new ArrayList<>()); - Logger.d("Unresolved: " + devices); + Logger.debug(logger, "Unresolved: {}", devices); List failed = new ArrayList<>(); try { while (!devices.isEmpty()) { device = devices.remove(0); - Logger.d("Candidate: " + device); + Logger.debug(logger, "Candidate: {}", device); try (T connection = device.openConnection(connectionType)) { DeviceInfo info = DeviceUtil.readInfo(connection, pid); String deviceKey = buildKey(info); @@ -127,13 +183,13 @@ void requestConnection(String key, Class connec device.requestConnection(connectionType, callback); return; } else if (pid.type == YubiKeyType.NEO && devices.isEmpty()) { - Logger.d("Resolved last NEO device without serial"); + Logger.debug(logger, "Resolved last NEO device without serial"); device.requestConnection(connectionType, callback); return; } } } catch (IOException e) { - Logger.e("Failed opening candidate device", e); + Logger.error(logger, "Failed opening candidate device: ", e); failed.add(device); } } @@ -172,4 +228,8 @@ Map getDevices() { } return devices; } + + public UsbPid getPid() { + return pid; + } } diff --git a/desktop/src/main/java/com/yubico/yubikit/desktop/YubiKitManager.java b/desktop/src/main/java/com/yubico/yubikit/desktop/YubiKitManager.java index 8b5bbdc1..a25a16ef 100755 --- a/desktop/src/main/java/com/yubico/yubikit/desktop/YubiKitManager.java +++ b/desktop/src/main/java/com/yubico/yubikit/desktop/YubiKitManager.java @@ -16,23 +16,27 @@ package com.yubico.yubikit.desktop; -import com.yubico.yubikit.core.Logger; import com.yubico.yubikit.core.UsbPid; import com.yubico.yubikit.core.YubiKeyConnection; import com.yubico.yubikit.core.YubiKeyDevice; import com.yubico.yubikit.core.fido.FidoConnection; +import com.yubico.yubikit.core.internal.Logger; import com.yubico.yubikit.core.otp.OtpConnection; import com.yubico.yubikit.core.smartcard.SmartCardConnection; import com.yubico.yubikit.desktop.hid.HidManager; import com.yubico.yubikit.desktop.pcsc.PcscManager; import com.yubico.yubikit.management.DeviceInfo; +import org.slf4j.LoggerFactory; + import java.util.*; public class YubiKitManager { private final PcscManager pcscManager; private final HidManager hidManager; + private final org.slf4j.Logger logger = LoggerFactory.getLogger(YubiKitManager.class); + public YubiKitManager(PcscManager pcscManager, HidManager hidManager) { this.pcscManager = pcscManager; this.hidManager = hidManager; @@ -56,10 +60,10 @@ List listDevices(Class public Map listAllDevices(Set> connectionTypes) { Map groups = new HashMap<>(); for (Class connectionType : connectionTypes) { - Logger.d("Enumerate devices for " + connectionType); + Logger.trace(logger, "Enumerate devices for {}", connectionType); for (UsbYubiKeyDevice device : listDevices(connectionType)) { UsbPid pid = device.getPid(); - Logger.d("Found device with PID " + pid); + Logger.trace(logger, "Found device with PID {}", pid); if (!groups.containsKey(pid)) { groups.put(pid, new UsbPidGroup(pid)); } @@ -75,6 +79,6 @@ public Map listAllDevices(Set listAllDevices() { - return listAllDevices(new HashSet<>(Arrays.asList(SmartCardConnection.class, OtpConnection.class, FidoConnection.class))); + return listAllDevices(new HashSet<>(Arrays.asList(SmartCardConnection.class, FidoConnection.class, OtpConnection.class))); } } diff --git a/desktop/src/main/java/com/yubico/yubikit/desktop/hid/HidManager.java b/desktop/src/main/java/com/yubico/yubikit/desktop/hid/HidManager.java index 93d1917c..6826daee 100755 --- a/desktop/src/main/java/com/yubico/yubikit/desktop/hid/HidManager.java +++ b/desktop/src/main/java/com/yubico/yubikit/desktop/hid/HidManager.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 Yubico. + * Copyright (C) 2022,2024 Yubico. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,11 +16,12 @@ package com.yubico.yubikit.desktop.hid; -import com.yubico.yubikit.core.Logger; +import com.yubico.yubikit.core.internal.Logger; import org.hid4java.HidServices; import org.hid4java.HidServicesListener; import org.hid4java.event.HidServicesEvent; +import org.slf4j.LoggerFactory; import java.util.ArrayList; import java.util.List; @@ -29,6 +30,8 @@ public class HidManager { private final HidServices services; + private final org.slf4j.Logger logger = LoggerFactory.getLogger(HidManager.class); + public HidManager() { services = org.hid4java.HidManager.getHidServices(); } @@ -67,18 +70,23 @@ public void setListener(HidSessionListener listener) { services.addHidServicesListener(new HidServicesListener() { @Override public void hidDeviceAttached(HidServicesEvent event) { - Logger.d("HID attached: " + event); + Logger.debug(logger, "HID attached: {}", event); listener.onSessionReceived(new HidDevice(event.getHidDevice())); } @Override public void hidDeviceDetached(HidServicesEvent event) { - Logger.d("HID removed: " + event); + Logger.debug(logger, "HID removed: {}", event); } @Override public void hidFailure(HidServicesEvent event) { - Logger.d("HID failure: " + event); + Logger.debug(logger, "HID failure: {}", event); + } + + @Override + public void hidDataReceived(HidServicesEvent event) { + Logger.debug(logger, "HID Data received: {}", event); } }); } diff --git a/desktop/src/main/java/com/yubico/yubikit/desktop/hid/HidOtpConnection.java b/desktop/src/main/java/com/yubico/yubikit/desktop/hid/HidOtpConnection.java index 19a78622..5a8945a8 100755 --- a/desktop/src/main/java/com/yubico/yubikit/desktop/hid/HidOtpConnection.java +++ b/desktop/src/main/java/com/yubico/yubikit/desktop/hid/HidOtpConnection.java @@ -16,11 +16,12 @@ package com.yubico.yubikit.desktop.hid; -import com.yubico.yubikit.core.Logger; +import com.yubico.yubikit.core.internal.Logger; import com.yubico.yubikit.core.otp.OtpConnection; import com.yubico.yubikit.desktop.OperatingSystem; import org.hid4java.HidDevice; +import org.slf4j.LoggerFactory; import java.io.IOException; @@ -29,13 +30,14 @@ public class HidOtpConnection implements OtpConnection { private final byte interfaceId; HidOtpConnection(HidDevice hidDevice, byte interfaceId) throws IOException { + org.slf4j.Logger logger = LoggerFactory.getLogger(HidOtpConnection.class); if (hidDevice.isOpen()) { throw new IOException("Device already open"); } hidDevice.open(); this.interfaceId = interfaceId; this.hidDevice = hidDevice; - Logger.d("usb connection opened"); + Logger.debug(logger, "usb connection opened"); } @Override diff --git a/desktop/src/main/java/com/yubico/yubikit/desktop/pcsc/NfcPcscDevice.java b/desktop/src/main/java/com/yubico/yubikit/desktop/pcsc/NfcPcscDevice.java index 390ab257..702c29c1 100755 --- a/desktop/src/main/java/com/yubico/yubikit/desktop/pcsc/NfcPcscDevice.java +++ b/desktop/src/main/java/com/yubico/yubikit/desktop/pcsc/NfcPcscDevice.java @@ -17,22 +17,14 @@ package com.yubico.yubikit.desktop.pcsc; import com.yubico.yubikit.core.Transport; -import com.yubico.yubikit.core.YubiKeyConnection; -import com.yubico.yubikit.core.YubiKeyDevice; import com.yubico.yubikit.core.application.ApplicationNotAvailableException; import com.yubico.yubikit.core.smartcard.Apdu; import com.yubico.yubikit.core.smartcard.ApduException; -import com.yubico.yubikit.core.smartcard.SmartCardConnection; import com.yubico.yubikit.core.smartcard.SmartCardProtocol; -import com.yubico.yubikit.core.util.Callback; -import com.yubico.yubikit.core.util.Result; import java.io.IOException; import java.nio.ByteBuffer; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import javax.smartcardio.CardException; import javax.smartcardio.CardTerminal; public class NfcPcscDevice extends PcscDevice { diff --git a/desktop/src/main/java/com/yubico/yubikit/desktop/pcsc/PcscSmartCardConnection.java b/desktop/src/main/java/com/yubico/yubikit/desktop/pcsc/PcscSmartCardConnection.java index 7ad8ea7a..489b81c4 100755 --- a/desktop/src/main/java/com/yubico/yubikit/desktop/pcsc/PcscSmartCardConnection.java +++ b/desktop/src/main/java/com/yubico/yubikit/desktop/pcsc/PcscSmartCardConnection.java @@ -16,11 +16,13 @@ package com.yubico.yubikit.desktop.pcsc; -import com.yubico.yubikit.core.Logger; import com.yubico.yubikit.core.Transport; +import com.yubico.yubikit.core.internal.Logger; import com.yubico.yubikit.core.smartcard.SmartCardConnection; import com.yubico.yubikit.core.util.StringUtils; +import org.slf4j.LoggerFactory; + import java.io.IOException; import java.util.Arrays; @@ -34,9 +36,12 @@ public class PcscSmartCardConnection implements SmartCardConnection { private final Transport transport; private final CardChannel cardChannel; + private final org.slf4j.Logger logger = LoggerFactory.getLogger(PcscSmartCardConnection.class); + public PcscSmartCardConnection(Card card) throws IOException { this.card = card; - this.transport = (card.getATR().getBytes()[1] & 0xf0) == 0xf0 ? Transport.USB : Transport.NFC; + this.transport = (card.getATR() + .getBytes()[1] & 0xf0) == 0xf0 ? Transport.USB : Transport.NFC; try { card.beginExclusive(); this.cardChannel = card.getBasicChannel(); @@ -63,7 +68,7 @@ public byte[] getAtr() { @Override public void close() throws IOException { - Logger.d("Closing CCID connection"); + Logger.debug(logger, "Closing CCID connection"); try { card.endExclusive(); } catch (CardException e) { @@ -74,13 +79,13 @@ public void close() throws IOException { @Override public byte[] sendAndReceive(byte[] apdu) throws IOException { try { - Logger.d(apdu.length + " bytes sent over PCSC: " + StringUtils.bytesToHex(apdu)); + Logger.trace(logger, "{} bytes sent over PCSC: {}", apdu.length, StringUtils.bytesToHex(apdu)); if (apdu.length < 5) { // CardChannel.transmit requires at least 5 bytes. apdu = Arrays.copyOf(apdu, 5); } byte[] response = cardChannel.transmit(new CommandAPDU(apdu)).getBytes(); - Logger.d(response.length + " bytes received: " + StringUtils.bytesToHex(response)); + Logger.trace(logger, "{} bytes received: {}", response.length, StringUtils.bytesToHex(response)); return response; } catch (CardException e) { throw new IOException(e); diff --git a/desktop/src/main/java/com/yubico/yubikit/desktop/pcsc/UsbPcscDevice.java b/desktop/src/main/java/com/yubico/yubikit/desktop/pcsc/UsbPcscDevice.java index bb30edd8..162d2603 100755 --- a/desktop/src/main/java/com/yubico/yubikit/desktop/pcsc/UsbPcscDevice.java +++ b/desktop/src/main/java/com/yubico/yubikit/desktop/pcsc/UsbPcscDevice.java @@ -16,17 +16,13 @@ package com.yubico.yubikit.desktop.pcsc; -import com.yubico.yubikit.core.*; -import com.yubico.yubikit.core.smartcard.SmartCardConnection; -import com.yubico.yubikit.core.util.Callback; -import com.yubico.yubikit.core.util.Result; +import com.yubico.yubikit.core.Transport; +import com.yubico.yubikit.core.UsbInterface; +import com.yubico.yubikit.core.UsbPid; +import com.yubico.yubikit.core.YubiKeyType; import com.yubico.yubikit.desktop.UsbYubiKeyDevice; -import javax.smartcardio.CardException; import javax.smartcardio.CardTerminal; -import java.io.IOException; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; public class UsbPcscDevice extends PcscDevice implements UsbYubiKeyDevice { private final UsbPid pid; diff --git a/testing-desktop/build.gradle b/testing-desktop/build.gradle index 4931ea11..89b5f3c0 100755 --- a/testing-desktop/build.gradle +++ b/testing-desktop/build.gradle @@ -8,12 +8,15 @@ repositories { dependencies { implementation 'org.jetbrains:annotations:23.0.0' - testImplementation('junit:junit:4.13.2') - testRuntimeOnly('org.junit.vintage:junit-vintage-engine:5.9.0') implementation project(':desktop') implementation project(':piv') implementation project(':testing') + + testImplementation 'junit:junit:4.13.2' + testImplementation 'ch.qos.logback:logback-classic:1.5.12' + + testRuntimeOnly('org.junit.vintage:junit-vintage-engine:5.9.0') } java { diff --git a/testing-desktop/src/main/java/com/yubico/yubikit/testing/AlwaysManualTest.java b/testing-desktop/src/main/java/com/yubico/yubikit/testing/AlwaysManualTest.java new file mode 100644 index 00000000..741514a2 --- /dev/null +++ b/testing-desktop/src/main/java/com/yubico/yubikit/testing/AlwaysManualTest.java @@ -0,0 +1,20 @@ +/* + * Copyright (C) 2024 Yubico. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.yubico.yubikit.testing; + +public interface AlwaysManualTest { +} diff --git a/testing-desktop/src/main/java/com/yubico/yubikit/testing/DesktopTestDriver.java b/testing-desktop/src/main/java/com/yubico/yubikit/testing/DesktopTestDriver.java index 35c2c06b..9271482d 100644 --- a/testing-desktop/src/main/java/com/yubico/yubikit/testing/DesktopTestDriver.java +++ b/testing-desktop/src/main/java/com/yubico/yubikit/testing/DesktopTestDriver.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 Yubico. + * Copyright (C) 2022-2024 Yubico. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,12 +17,18 @@ package com.yubico.yubikit.testing; import com.yubico.yubikit.core.YubiKeyDevice; -import com.yubico.yubikit.desktop.*; +import com.yubico.yubikit.core.internal.Logger; +import com.yubico.yubikit.desktop.OperatingSystem; +import com.yubico.yubikit.desktop.YubiKitManager; + +import org.slf4j.LoggerFactory; public class DesktopTestDriver { private final YubiKitManager yubikit; + private final static org.slf4j.Logger logger = LoggerFactory.getLogger(DesktopTestDriver.class); + public DesktopTestDriver() { if (OperatingSystem.isMac()) { System.setProperty("sun.security.smartcardio.library", "/System/Library/Frameworks/PCSC.framework/Versions/Current/PCSC"); @@ -36,6 +42,6 @@ public YubiKeyDevice awaitSession() throws InterruptedException { } public void returnSession(YubiKeyDevice device) { - System.out.println("Device returned"); + Logger.debug(logger, "Device returned"); } } diff --git a/testing-desktop/src/main/java/com/yubico/yubikit/testing/PinUvAuthProtocolV1Test.java b/testing-desktop/src/main/java/com/yubico/yubikit/testing/PinUvAuthProtocolV1Test.java new file mode 100644 index 00000000..ae497767 --- /dev/null +++ b/testing-desktop/src/main/java/com/yubico/yubikit/testing/PinUvAuthProtocolV1Test.java @@ -0,0 +1,20 @@ +/* + * Copyright (C) 2024 Yubico. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.yubico.yubikit.testing; + +public interface PinUvAuthProtocolV1Test { +} diff --git a/testing-desktop/src/main/java/com/yubico/yubikit/testing/SlowTest.java b/testing-desktop/src/main/java/com/yubico/yubikit/testing/SlowTest.java new file mode 100644 index 00000000..2ce9ac4d --- /dev/null +++ b/testing-desktop/src/main/java/com/yubico/yubikit/testing/SlowTest.java @@ -0,0 +1,20 @@ +/* + * Copyright (C) 2024 Yubico. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.yubico.yubikit.testing; + +public interface SlowTest { +} diff --git a/testing-desktop/src/main/java/com/yubico/yubikit/testing/SmokeTest.java b/testing-desktop/src/main/java/com/yubico/yubikit/testing/SmokeTest.java new file mode 100644 index 00000000..9cc98909 --- /dev/null +++ b/testing-desktop/src/main/java/com/yubico/yubikit/testing/SmokeTest.java @@ -0,0 +1,20 @@ +/* + * Copyright (C) 2024 Yubico. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.yubico.yubikit.testing; + +public interface SmokeTest { +} diff --git a/testing-desktop/src/main/java/com/yubico/yubikit/testing/framework/FidoInstrumentedTests.java b/testing-desktop/src/main/java/com/yubico/yubikit/testing/framework/FidoInstrumentedTests.java new file mode 100755 index 00000000..a5c665c5 --- /dev/null +++ b/testing-desktop/src/main/java/com/yubico/yubikit/testing/framework/FidoInstrumentedTests.java @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2024 Yubico. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.yubico.yubikit.testing.framework; + +import com.yubico.yubikit.core.Transport; +import com.yubico.yubikit.core.smartcard.scp.ScpKid; +import com.yubico.yubikit.fido.ctap.Ctap2Session; +import com.yubico.yubikit.fido.ctap.PinUvAuthProtocol; +import com.yubico.yubikit.fido.ctap.PinUvAuthProtocolV2; +import com.yubico.yubikit.testing.TestState; +import com.yubico.yubikit.testing.fido.FidoTestState; + +import org.jetbrains.annotations.Nullable; + +public class FidoInstrumentedTests extends YKInstrumentedTests { + + protected void withDevice(TestState.StatefulDeviceCallback callback) throws Throwable { + withDevice(true, callback); + } + + protected void withDevice(boolean setPin, TestState.StatefulDeviceCallback callback) throws Throwable { + FidoTestState state = new FidoTestState.Builder(device, usbPid, getPinUvAuthProtocol()) + .scpKid(getScpKid()) + //.reconnectDeviceCallback(this::reconnectDevice) + .setPin(setPin) + .build(); + + state.withDeviceCallback(callback); + } + + protected void withCtap2Session(TestState.StatefulSessionCallback callback) throws Throwable { + FidoTestState state = new FidoTestState.Builder(device, usbPid, getPinUvAuthProtocol()) + .scpKid(getScpKid()) + //.reconnectDeviceCallback(this::reconnectDevice) + .setPin(true) + .build(); + + state.withCtap2(callback); + } + + @Nullable + @Override + protected Byte getScpKid() { + if (device.getTransport() == Transport.NFC) { + return ScpKid.SCP11b; + } + return null; + } + + protected PinUvAuthProtocol getPinUvAuthProtocol() { + // default is protocol V2 + return new PinUvAuthProtocolV2(); + } +} \ No newline at end of file diff --git a/testing-desktop/src/main/java/com/yubico/yubikit/testing/framework/ManagementInstrumentedTests.java b/testing-desktop/src/main/java/com/yubico/yubikit/testing/framework/ManagementInstrumentedTests.java new file mode 100644 index 00000000..da3ee06e --- /dev/null +++ b/testing-desktop/src/main/java/com/yubico/yubikit/testing/framework/ManagementInstrumentedTests.java @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2024 Yubico. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.yubico.yubikit.testing.framework; + +import com.yubico.yubikit.core.smartcard.SmartCardConnection; +import com.yubico.yubikit.management.ManagementSession; + +public class ManagementInstrumentedTests extends YKInstrumentedTests { + + public interface Callback { + void invoke(ManagementSession value) throws Throwable; + } + + protected void withManagementSession(Callback callback) throws Throwable { + try (SmartCardConnection connection = device.openConnection(SmartCardConnection.class)) { + callback.invoke(new ManagementSession(connection)); + } + } +} \ No newline at end of file diff --git a/testing-desktop/src/main/java/com/yubico/yubikit/testing/framework/MpeInstrumentedTests.java b/testing-desktop/src/main/java/com/yubico/yubikit/testing/framework/MpeInstrumentedTests.java new file mode 100755 index 00000000..5a355b93 --- /dev/null +++ b/testing-desktop/src/main/java/com/yubico/yubikit/testing/framework/MpeInstrumentedTests.java @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2024 Yubico. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.yubico.yubikit.testing.framework; + +import com.yubico.yubikit.fido.ctap.Ctap2Session; +import com.yubico.yubikit.piv.PivSession; +import com.yubico.yubikit.testing.TestState; +import com.yubico.yubikit.testing.mpe.MpeTestState; + +public class MpeInstrumentedTests extends YKInstrumentedTests { + + protected void withPivSession(TestState.StatefulSessionCallback callback) throws Throwable { + final MpeTestState state = new MpeTestState.Builder(device, usbPid) + .scpKid(getScpKid()) + .build(); + state.withPiv(callback); + } + + protected void withCtap2Session(TestState.StatefulSessionCallback callback) throws Throwable { + final MpeTestState state = new MpeTestState.Builder(device, usbPid) + .scpKid(getScpKid()) + .build(); + state.withCtap2(callback); + } +} \ No newline at end of file diff --git a/testing-desktop/src/main/java/com/yubico/yubikit/testing/framework/OathInstrumentedTests.java b/testing-desktop/src/main/java/com/yubico/yubikit/testing/framework/OathInstrumentedTests.java new file mode 100644 index 00000000..07271f8c --- /dev/null +++ b/testing-desktop/src/main/java/com/yubico/yubikit/testing/framework/OathInstrumentedTests.java @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2024 Yubico. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.yubico.yubikit.testing.framework; + +import com.yubico.yubikit.oath.OathSession; +import com.yubico.yubikit.testing.TestState; +import com.yubico.yubikit.testing.oath.OathTestState; + +public class OathInstrumentedTests extends YKInstrumentedTests { + + protected void withDevice(TestState.StatefulDeviceCallback callback) throws Throwable { + final OathTestState state = new OathTestState.Builder(device, usbPid) + .scpKid(getScpKid()) + //.reconnectDeviceCallback(this::reconnectDevice) + .build(); + + state.withDeviceCallback(callback); + } + + protected void withOathSession(TestState.StatefulSessionCallback callback) throws Throwable { + final OathTestState state = new OathTestState.Builder(device, usbPid) + .scpKid(getScpKid()) + .build(); + state.withOath(callback); + } +} \ No newline at end of file diff --git a/testing-desktop/src/main/java/com/yubico/yubikit/testing/framework/OpenPgpInstrumentedTests.java b/testing-desktop/src/main/java/com/yubico/yubikit/testing/framework/OpenPgpInstrumentedTests.java new file mode 100644 index 00000000..be5834cf --- /dev/null +++ b/testing-desktop/src/main/java/com/yubico/yubikit/testing/framework/OpenPgpInstrumentedTests.java @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2024 Yubico. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.yubico.yubikit.testing.framework; + +import com.yubico.yubikit.openpgp.OpenPgpSession; +import com.yubico.yubikit.testing.TestState; +import com.yubico.yubikit.testing.openpgp.OpenPgpTestState; + +public class OpenPgpInstrumentedTests extends YKInstrumentedTests { + protected void withOpenPgpSession(TestState.StatefulSessionCallback callback) throws Throwable { + final OpenPgpTestState state = new OpenPgpTestState.Builder(device, usbPid) + .scpKid(getScpKid()) + .build(); + state.withOpenPgp(callback); + } +} \ No newline at end of file diff --git a/testing-desktop/src/main/java/com/yubico/yubikit/testing/framework/PivInstrumentedTests.java b/testing-desktop/src/main/java/com/yubico/yubikit/testing/framework/PivInstrumentedTests.java index f3d52294..e6933c3b 100755 --- a/testing-desktop/src/main/java/com/yubico/yubikit/testing/framework/PivInstrumentedTests.java +++ b/testing-desktop/src/main/java/com/yubico/yubikit/testing/framework/PivInstrumentedTests.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 Yubico. + * Copyright (C) 2022,2024 Yubico. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,37 +16,16 @@ package com.yubico.yubikit.testing.framework; -import com.yubico.yubikit.core.smartcard.SmartCardConnection; import com.yubico.yubikit.piv.PivSession; import com.yubico.yubikit.testing.TestState; import com.yubico.yubikit.testing.piv.PivTestState; -import java.util.Optional; -import java.util.concurrent.LinkedBlockingQueue; - public class PivInstrumentedTests extends YKInstrumentedTests { protected void withPivSession(TestState.StatefulSessionCallback callback) throws Throwable { - - LinkedBlockingQueue> result = new LinkedBlockingQueue<>(); - device.requestConnection(SmartCardConnection.class, callbackResult -> { - try { - if (callbackResult.isSuccess()) { - - final PivTestState state = new PivTestState.Builder(device, usbPid) - .scpKid(getScpKid()) - .build(); - state.withPiv(callback); - result.offer(Optional.empty()); - } - } catch (Throwable e) { - result.offer(Optional.of(e)); - } - }); - - Optional exception = result.take(); - if (exception.isPresent()) { - throw exception.get(); - } + final PivTestState state = new PivTestState.Builder(device, usbPid) + .scpKid(getScpKid()) + .build(); + state.withPiv(callback); } } \ No newline at end of file diff --git a/testing-desktop/src/main/java/com/yubico/yubikit/testing/framework/SecurityDomainInstrumentedTests.java b/testing-desktop/src/main/java/com/yubico/yubikit/testing/framework/SecurityDomainInstrumentedTests.java new file mode 100644 index 00000000..59e2c1bc --- /dev/null +++ b/testing-desktop/src/main/java/com/yubico/yubikit/testing/framework/SecurityDomainInstrumentedTests.java @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2024 Yubico. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.yubico.yubikit.testing.framework; + +import com.yubico.yubikit.testing.TestState; +import com.yubico.yubikit.testing.sd.SecurityDomainTestState; + +public class SecurityDomainInstrumentedTests extends YKInstrumentedTests { + + protected void withState(TestState.StatefulDeviceCallback callback) throws Throwable { + final SecurityDomainTestState state = new SecurityDomainTestState.Builder(device, usbPid) + //.reconnectDeviceCallback(this::reconnectDevice) + .build(); + + state.withDeviceCallback(callback); + } +} \ No newline at end of file diff --git a/testing-desktop/src/main/java/com/yubico/yubikit/testing/framework/YKInstrumentedTests.java b/testing-desktop/src/main/java/com/yubico/yubikit/testing/framework/YKInstrumentedTests.java index 16f5a99e..206d94cc 100755 --- a/testing-desktop/src/main/java/com/yubico/yubikit/testing/framework/YKInstrumentedTests.java +++ b/testing-desktop/src/main/java/com/yubico/yubikit/testing/framework/YKInstrumentedTests.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 Yubico. + * Copyright (C) 2022,2024 Yubico. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,14 +18,14 @@ import com.yubico.yubikit.core.UsbPid; import com.yubico.yubikit.core.YubiKeyDevice; +import com.yubico.yubikit.desktop.CompositeDevice; +import com.yubico.yubikit.testing.DesktopTestDriver; import org.jetbrains.annotations.Nullable; import org.junit.Rule; import org.junit.rules.ExternalResource; import org.junit.rules.TestName; -import com.yubico.yubikit.testing.DesktopTestDriver; - public class YKInstrumentedTests { private final DesktopTestDriver testDriver = new DesktopTestDriver(); @@ -33,7 +33,6 @@ public class YKInstrumentedTests { protected YubiKeyDevice device = null; protected UsbPid usbPid = null; - @Rule public final TestName name = new TestName(); @@ -43,12 +42,14 @@ public class YKInstrumentedTests { @Override protected void before() throws Throwable { device = testDriver.awaitSession(); - System.out.println("Got session"); + if (device instanceof CompositeDevice) { + CompositeDevice compositeDevice = (CompositeDevice) device; + usbPid = compositeDevice.getPidGroup().getPid(); + } } @Override protected void after() { - System.out.println("Returning session"); testDriver.returnSession(device); device = null; } diff --git a/testing-desktop/src/test/java/com/yubico/yubikit/testing/DeviceTests.java b/testing-desktop/src/test/java/com/yubico/yubikit/testing/DeviceTests.java new file mode 100644 index 00000000..c691e11d --- /dev/null +++ b/testing-desktop/src/test/java/com/yubico/yubikit/testing/DeviceTests.java @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2024 Yubico. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.yubico.yubikit.testing; + +import com.yubico.yubikit.testing.mpe.MultiProtocolResetTests; +import com.yubico.yubikit.testing.fido.FidoTests; +import com.yubico.yubikit.testing.oath.OathTests; +import com.yubico.yubikit.testing.openpgp.OpenPgpTests; +import com.yubico.yubikit.testing.piv.PivTests; +import com.yubico.yubikit.testing.sd.SecurityDomainTests; + +import org.junit.runner.RunWith; +import org.junit.runners.Suite; + +/** + * All integration tests for Security domain, PIV, OpenPGP, OATH, FIDO2 and MPE. + *

+ * The YubiKey applications will be reset several times. + *

+ */ +@RunWith(Suite.class) +@Suite.SuiteClasses({ + SecurityDomainTests.class, + PivTests.class, + OpenPgpTests.class, + OathTests.class, + MultiProtocolResetTests.class, + FidoTests.class +}) +public class DeviceTests { +} diff --git a/testing-desktop/src/test/java/com/yubico/yubikit/testing/FastDeviceTests.java b/testing-desktop/src/test/java/com/yubico/yubikit/testing/FastDeviceTests.java new file mode 100644 index 00000000..1c49ae70 --- /dev/null +++ b/testing-desktop/src/test/java/com/yubico/yubikit/testing/FastDeviceTests.java @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2024 Yubico. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.yubico.yubikit.testing; + +import org.junit.experimental.categories.Categories; +import org.junit.runner.RunWith; +import org.junit.runners.Suite; + +/** + * These tests are here to make testing a bit faster and exclude following: + *

    + *
  • {@link SlowTest}
  • + *
  • {@link PinUvAuthProtocolV1Test}
  • + *
  • {@link AlwaysManualTest}
  • + *
+ */ +@RunWith(Categories.class) +@Suite.SuiteClasses(DeviceTests.class) +@Categories.ExcludeCategory({ + SlowTest.class, + PinUvAuthProtocolV1Test.class, + AlwaysManualTest.class +}) +public class FastDeviceTests { +} diff --git a/testing-desktop/src/test/java/com/yubico/yubikit/testing/PivJcaProviderTests.java b/testing-desktop/src/test/java/com/yubico/yubikit/testing/PivJcaProviderTests.java deleted file mode 100644 index 5c1626c4..00000000 --- a/testing-desktop/src/test/java/com/yubico/yubikit/testing/PivJcaProviderTests.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (C) 2022 Yubico. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.yubico.yubikit.testing; - -import com.yubico.yubikit.testing.framework.PivInstrumentedTests; -import com.yubico.yubikit.testing.piv.PivJcaDecryptTests; -import com.yubico.yubikit.testing.piv.PivJcaDeviceTests; -import com.yubico.yubikit.testing.piv.PivJcaSigningTests; - -import org.junit.Test; -import org.junit.runner.RunWith; - -public class PivJcaProviderTests extends PivInstrumentedTests { - - @Test - public void testGenerateKeys() throws Throwable { - withPivSession(PivJcaDeviceTests::testGenerateKeys); - } - - @Test - public void testImportKeys() throws Throwable { - withPivSession(PivJcaDeviceTests::testImportKeys); - } - - @Test - public void testSigning() throws Throwable { - withPivSession(PivJcaSigningTests::testSign); - } - - @Test - public void testDecrypt() throws Throwable { - withPivSession(PivJcaDecryptTests::testDecrypt); - } -} diff --git a/testing-desktop/src/test/java/com/yubico/yubikit/testing/SmokeDeviceTests.java b/testing-desktop/src/test/java/com/yubico/yubikit/testing/SmokeDeviceTests.java new file mode 100644 index 00000000..f13335bc --- /dev/null +++ b/testing-desktop/src/test/java/com/yubico/yubikit/testing/SmokeDeviceTests.java @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2024 Yubico. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.yubico.yubikit.testing; + +import org.junit.experimental.categories.Categories; +import org.junit.runner.RunWith; +import org.junit.runners.Suite; + +/** + * Quick, randomly selected tests for different applications. + */ +@RunWith(Categories.class) +@Categories.IncludeCategory({ + SmokeTest.class, +}) +@Suite.SuiteClasses(DeviceTests.class) +public class SmokeDeviceTests { +} \ No newline at end of file diff --git a/testing-desktop/src/test/java/com/yubico/yubikit/testing/fido/BasicWebAuthnClientInstrumentedTests.java b/testing-desktop/src/test/java/com/yubico/yubikit/testing/fido/BasicWebAuthnClientInstrumentedTests.java new file mode 100644 index 00000000..53a113f6 --- /dev/null +++ b/testing-desktop/src/test/java/com/yubico/yubikit/testing/fido/BasicWebAuthnClientInstrumentedTests.java @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2024 Yubico. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.yubico.yubikit.testing.fido; + +import com.yubico.yubikit.fido.ctap.PinUvAuthProtocol; +import com.yubico.yubikit.fido.ctap.PinUvAuthProtocolV1; +import com.yubico.yubikit.testing.PinUvAuthProtocolV1Test; +import com.yubico.yubikit.testing.SmokeTest; +import com.yubico.yubikit.testing.framework.FidoInstrumentedTests; + +import org.junit.Test; +import org.junit.experimental.categories.Category; +import org.junit.runner.RunWith; +import org.junit.runners.Suite; + +@RunWith(Suite.class) +@Suite.SuiteClasses({ + BasicWebAuthnClientInstrumentedTests.PinUvAuthV2Test.class, + BasicWebAuthnClientInstrumentedTests.PinUvAuthV1Test.class, +}) +public class BasicWebAuthnClientInstrumentedTests { + public static class PinUvAuthV2Test extends FidoInstrumentedTests { + + @Test + @Category(SmokeTest.class) + public void testMakeCredentialGetAssertion() throws Throwable { + withDevice(BasicWebAuthnClientTests::testMakeCredentialGetAssertion); + } + + @Test + public void testMakeCredentialGetAssertionTokenUvOnly() throws Throwable { + withDevice(BasicWebAuthnClientTests::testMakeCredentialGetAssertionTokenUvOnly); + } + + @Test + public void testGetAssertionMultipleUsersRk() throws Throwable { + withDevice(BasicWebAuthnClientTests::testGetAssertionMultipleUsersRk); + } + + @Test + public void testGetAssertionWithAllowList() throws Throwable { + withDevice(BasicWebAuthnClientTests::testGetAssertionWithAllowList); + } + + @Test + public void testMakeCredentialWithExcludeList() throws Throwable { + withDevice(BasicWebAuthnClientTests::testMakeCredentialWithExcludeList); + } + + @Test + public void testMakeCredentialKeyAlgorithms() throws Throwable { + withDevice(BasicWebAuthnClientTests::testMakeCredentialKeyAlgorithms); + } + + @Test + public void testClientPinManagement() throws Throwable { + withDevice(BasicWebAuthnClientTests::testClientPinManagement); + } + + @Test + public void testClientCredentialManagement() throws Throwable { + withDevice(BasicWebAuthnClientTests::testClientCredentialManagement); + } + } + + @Category(PinUvAuthProtocolV1Test.class) + public static class PinUvAuthV1Test extends PinUvAuthV2Test { + @Override + protected PinUvAuthProtocol getPinUvAuthProtocol() { + return new PinUvAuthProtocolV1(); + } + } +} diff --git a/testing-desktop/src/test/java/com/yubico/yubikit/testing/fido/Ctap2BioEnrollmentInstrumentedTests.java b/testing-desktop/src/test/java/com/yubico/yubikit/testing/fido/Ctap2BioEnrollmentInstrumentedTests.java new file mode 100644 index 00000000..6d68a16b --- /dev/null +++ b/testing-desktop/src/test/java/com/yubico/yubikit/testing/fido/Ctap2BioEnrollmentInstrumentedTests.java @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2024 Yubico. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.yubico.yubikit.testing.fido; + + +import com.yubico.yubikit.testing.framework.FidoInstrumentedTests; + +import org.junit.Test; + +public class Ctap2BioEnrollmentInstrumentedTests extends FidoInstrumentedTests { + @Test + public void testFingerprintEnrollment() throws Throwable { + withCtap2Session(Ctap2BioEnrollmentTests::testFingerprintEnrollment); + } +} diff --git a/testing-desktop/src/test/java/com/yubico/yubikit/testing/fido/Ctap2ClientPinInstrumentedTests.java b/testing-desktop/src/test/java/com/yubico/yubikit/testing/fido/Ctap2ClientPinInstrumentedTests.java new file mode 100644 index 00000000..ab4c2dca --- /dev/null +++ b/testing-desktop/src/test/java/com/yubico/yubikit/testing/fido/Ctap2ClientPinInstrumentedTests.java @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2024 Yubico. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.yubico.yubikit.testing.fido; + +import com.yubico.yubikit.fido.ctap.PinUvAuthProtocol; +import com.yubico.yubikit.fido.ctap.PinUvAuthProtocolV1; +import com.yubico.yubikit.testing.PinUvAuthProtocolV1Test; +import com.yubico.yubikit.testing.framework.FidoInstrumentedTests; + +import org.junit.Test; +import org.junit.experimental.categories.Category; +import org.junit.runner.RunWith; +import org.junit.runners.Suite; + +@RunWith(Suite.class) +@Suite.SuiteClasses({ + Ctap2ClientPinInstrumentedTests.PinUvAuthV2Test.class, + Ctap2ClientPinInstrumentedTests.PinUvAuthV1Test.class, +}) +public class Ctap2ClientPinInstrumentedTests { + public static class PinUvAuthV2Test extends FidoInstrumentedTests { + @Test + public void testClientPin() throws Throwable { + withCtap2Session(Ctap2ClientPinTests::testClientPin); + } + + @Test + public void testPinComplexity() throws Throwable { + withDevice(Ctap2ClientPinTests::testPinComplexity); + } + } + + @Category(PinUvAuthProtocolV1Test.class) + public static class PinUvAuthV1Test extends PinUvAuthV2Test { + @Override + protected PinUvAuthProtocol getPinUvAuthProtocol() { + return new PinUvAuthProtocolV1(); + } + } +} diff --git a/testing-desktop/src/test/java/com/yubico/yubikit/testing/fido/Ctap2ConfigInstrumentedTests.java b/testing-desktop/src/test/java/com/yubico/yubikit/testing/fido/Ctap2ConfigInstrumentedTests.java new file mode 100644 index 00000000..70f23a17 --- /dev/null +++ b/testing-desktop/src/test/java/com/yubico/yubikit/testing/fido/Ctap2ConfigInstrumentedTests.java @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2024 Yubico. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.yubico.yubikit.testing.fido; + +import com.yubico.yubikit.testing.AlwaysManualTest; +import com.yubico.yubikit.testing.framework.FidoInstrumentedTests; + +import org.junit.Test; +import org.junit.experimental.categories.Categories; +import org.junit.experimental.categories.Category; +import org.junit.runner.RunWith; +import org.junit.runners.Suite; + +/** + * Config tests. + *

+ * These tests will change FIDO2 application configuration through authenticatorConfig. As these changes + * are irreversible. + *

+ * Read documentation for each test for more information. + */ +@RunWith(Categories.class) +@Suite.SuiteClasses(Ctap2ConfigInstrumentedTests.ConfigTests.class) +@Categories.ExcludeCategory(AlwaysManualTest.class) +public class Ctap2ConfigInstrumentedTests { + + public static class ConfigTests extends FidoInstrumentedTests { + @Test + public void testReadWriteEnterpriseAttestation() throws Throwable { + withCtap2Session(Ctap2ConfigTests::testReadWriteEnterpriseAttestation); + } + + /** + * Toggles the {@code alwaysUv} option to opposite value. It is not possible to set this + * option to `false` on a FIPS approved YubiKey. + * + * @throws Throwable if an error occurs + */ + @Test + @Category(AlwaysManualTest.class) + public void testToggleAlwaysUv() throws Throwable { + withCtap2Session(Ctap2ConfigTests::testToggleAlwaysUv); + } + + /** + * Sets the {@code forcePinChange} flag, verifies that and then changes the PIN twice so + * that the device uses the {@code TestUtil.PIN}. + * + * @throws Throwable if an error occurs + */ + @Test + public void testSetForcePinChange() throws Throwable { + withCtap2Session(Ctap2ConfigTests::testSetForcePinChange); + } + + /** + * Changes the {@code minPinLength} value. This change is irreversible and after running + * this test, the YubiKey should be reset. + * + * @throws Throwable if an error occurs + */ + @Test + @Category(AlwaysManualTest.class) + public void testSetMinPinLength() throws Throwable { + withCtap2Session(Ctap2ConfigTests::testSetMinPinLength); + } + } +} diff --git a/testing-desktop/src/test/java/com/yubico/yubikit/testing/fido/Ctap2CredentialManagementInstrumentedTests.java b/testing-desktop/src/test/java/com/yubico/yubikit/testing/fido/Ctap2CredentialManagementInstrumentedTests.java new file mode 100644 index 00000000..5ed3b5fb --- /dev/null +++ b/testing-desktop/src/test/java/com/yubico/yubikit/testing/fido/Ctap2CredentialManagementInstrumentedTests.java @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2024 Yubico. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.yubico.yubikit.testing.fido; + +import com.yubico.yubikit.fido.ctap.PinUvAuthProtocol; +import com.yubico.yubikit.fido.ctap.PinUvAuthProtocolV1; +import com.yubico.yubikit.testing.PinUvAuthProtocolV1Test; +import com.yubico.yubikit.testing.SmokeTest; +import com.yubico.yubikit.testing.framework.FidoInstrumentedTests; + +import org.junit.Test; +import org.junit.experimental.categories.Category; +import org.junit.runner.RunWith; +import org.junit.runners.Suite; + +@RunWith(Suite.class) +@Suite.SuiteClasses({ + Ctap2CredentialManagementInstrumentedTests.PinUvAuthV2Test.class, + Ctap2CredentialManagementInstrumentedTests.PinUvAuthV1Test.class, +}) +public class Ctap2CredentialManagementInstrumentedTests { + public static class PinUvAuthV2Test extends FidoInstrumentedTests { + @Test + public void testReadMetadata() throws Throwable { + withCtap2Session(Ctap2CredentialManagementTests::testReadMetadata); + } + + @Test + @Category(SmokeTest.class) + public void testManagement() throws Throwable { + withCtap2Session(Ctap2CredentialManagementTests::testManagement); + } + + @Test + @Category(SmokeTest.class) + public void testUpdateUserInformation() throws Throwable { + withCtap2Session(Ctap2CredentialManagementTests::testUpdateUserInformation); + } + } + + @Category(PinUvAuthProtocolV1Test.class) + public static class PinUvAuthV1Test extends PinUvAuthV2Test { + @Override + protected PinUvAuthProtocol getPinUvAuthProtocol() { + return new PinUvAuthProtocolV1(); + } + } +} diff --git a/testing-desktop/src/test/java/com/yubico/yubikit/testing/fido/Ctap2SessionInstrumentedTests.java b/testing-desktop/src/test/java/com/yubico/yubikit/testing/fido/Ctap2SessionInstrumentedTests.java new file mode 100644 index 00000000..6138002e --- /dev/null +++ b/testing-desktop/src/test/java/com/yubico/yubikit/testing/fido/Ctap2SessionInstrumentedTests.java @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2024 Yubico. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.yubico.yubikit.testing.fido; + +import com.yubico.yubikit.fido.ctap.PinUvAuthProtocol; +import com.yubico.yubikit.fido.ctap.PinUvAuthProtocolV1; +import com.yubico.yubikit.testing.PinUvAuthProtocolV1Test; +import com.yubico.yubikit.testing.SmokeTest; +import com.yubico.yubikit.testing.framework.FidoInstrumentedTests; + +import org.junit.Test; +import org.junit.experimental.categories.Category; +import org.junit.runner.RunWith; +import org.junit.runners.Suite; + +@RunWith(Suite.class) +@Suite.SuiteClasses({ + Ctap2SessionInstrumentedTests.PinUvAuthV2Test.class, + Ctap2SessionInstrumentedTests.PinUvAuthV1Test.class, +}) +public class Ctap2SessionInstrumentedTests { + public static class PinUvAuthV2Test extends FidoInstrumentedTests { + @Test + @Category(SmokeTest.class) + public void testCtap2GetInfo() throws Throwable { + withCtap2Session(Ctap2SessionTests::testCtap2GetInfo); + } + + @Test + public void testCancelCborCommandImmediate() throws Throwable { + withCtap2Session(Ctap2SessionTests::testCancelCborCommandImmediate); + } + + @Test + public void testCancelCborCommandAfterDelay() throws Throwable { + withCtap2Session(Ctap2SessionTests::testCancelCborCommandAfterDelay); + } + } + + @Category(PinUvAuthProtocolV1Test.class) + public static class PinUvAuthV1Test extends PinUvAuthV2Test { + @Override + protected PinUvAuthProtocol getPinUvAuthProtocol() { + return new PinUvAuthProtocolV1(); + } + } +} diff --git a/testing-desktop/src/test/java/com/yubico/yubikit/testing/fido/Ctap2SessionResetInstrumentedTests.java b/testing-desktop/src/test/java/com/yubico/yubikit/testing/fido/Ctap2SessionResetInstrumentedTests.java new file mode 100644 index 00000000..544527cc --- /dev/null +++ b/testing-desktop/src/test/java/com/yubico/yubikit/testing/fido/Ctap2SessionResetInstrumentedTests.java @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2024 Yubico. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.yubico.yubikit.testing.fido; + +import com.yubico.yubikit.fido.ctap.PinUvAuthProtocol; +import com.yubico.yubikit.fido.ctap.PinUvAuthProtocolV1; +import com.yubico.yubikit.testing.AlwaysManualTest; +import com.yubico.yubikit.testing.PinUvAuthProtocolV1Test; +import com.yubico.yubikit.testing.framework.FidoInstrumentedTests; + +import org.junit.Test; +import org.junit.experimental.categories.Category; +import org.junit.runner.RunWith; +import org.junit.runners.Suite; + +/** + * Tests FIDO Reset. + *

+ * This is a manual test which will reset the FIDO application. + *

    + *
  • Before running the test, disconnect the YubiKey from the Android device.
  • + *
  • YubiKey Bio devices are currently ignored.
  • + *
+ */ +@RunWith(Suite.class) +@Suite.SuiteClasses({ + Ctap2SessionResetInstrumentedTests.PinUvAuthV2Test.class, + Ctap2SessionResetInstrumentedTests.PinUvAuthV1Test.class, +}) +public class Ctap2SessionResetInstrumentedTests { + public static class PinUvAuthV2Test extends FidoInstrumentedTests { + @Test + @Category(AlwaysManualTest.class) + public void testReset() throws Throwable { + withDevice(false, Ctap2SessionTests::testReset); + } + } + + @Category(PinUvAuthProtocolV1Test.class) + public static class PinUvAuthV1Test extends PinUvAuthV2Test { + @Override + protected PinUvAuthProtocol getPinUvAuthProtocol() { + return new PinUvAuthProtocolV1(); + } + } +} diff --git a/testing-desktop/src/test/java/com/yubico/yubikit/testing/fido/EnterpriseAttestationInstrumentedTests.java b/testing-desktop/src/test/java/com/yubico/yubikit/testing/fido/EnterpriseAttestationInstrumentedTests.java new file mode 100644 index 00000000..a302fc53 --- /dev/null +++ b/testing-desktop/src/test/java/com/yubico/yubikit/testing/fido/EnterpriseAttestationInstrumentedTests.java @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2023-2024 Yubico. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.yubico.yubikit.testing.fido; + +import com.yubico.yubikit.fido.ctap.PinUvAuthProtocol; +import com.yubico.yubikit.fido.ctap.PinUvAuthProtocolV1; +import com.yubico.yubikit.testing.PinUvAuthProtocolV1Test; +import com.yubico.yubikit.testing.framework.FidoInstrumentedTests; + +import org.junit.Test; +import org.junit.experimental.categories.Category; +import org.junit.runner.RunWith; +import org.junit.runners.Suite; + +@RunWith(Suite.class) +@Suite.SuiteClasses({ + EnterpriseAttestationInstrumentedTests.PinUvAuthV2Test.class, + EnterpriseAttestationInstrumentedTests.PinUvAuthV1Test.class, +}) +public class EnterpriseAttestationInstrumentedTests { + public static class PinUvAuthV2Test extends FidoInstrumentedTests { + @Test + public void testSupportedPlatformManagedEA() throws Throwable { + withCtap2Session(EnterpriseAttestationTests::testSupportedPlatformManagedEA); + } + + @Test + public void testUnsupportedPlatformManagedEA() throws Throwable { + withCtap2Session(EnterpriseAttestationTests::testUnsupportedPlatformManagedEA); + } + + @Test + public void testCreateOptionsAttestationPreference() throws Throwable { + withDevice(EnterpriseAttestationTests::testCreateOptionsAttestationPreference); + } + + @Test + public void testVendorFacilitatedEA() throws Throwable { + withCtap2Session(EnterpriseAttestationTests::testVendorFacilitatedEA); + } + } + + @Category(PinUvAuthProtocolV1Test.class) + public static class PinUvAuthV1Test extends PinUvAuthV2Test { + @Override + protected PinUvAuthProtocol getPinUvAuthProtocol() { + return new PinUvAuthProtocolV1(); + } + } +} diff --git a/testing-desktop/src/test/java/com/yubico/yubikit/testing/fido/FidoTests.java b/testing-desktop/src/test/java/com/yubico/yubikit/testing/fido/FidoTests.java new file mode 100644 index 00000000..d246b60b --- /dev/null +++ b/testing-desktop/src/test/java/com/yubico/yubikit/testing/fido/FidoTests.java @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2024 Yubico. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.yubico.yubikit.testing.fido; + +import com.yubico.yubikit.testing.AlwaysManualTest; + +import org.junit.experimental.categories.Categories; +import org.junit.runner.RunWith; +import org.junit.runners.Suite; + +/** + * Setup YubiKey before running the integration tests: + *
    + *
  • reset the FIDO application
  • + *
  • optionally set PIN to `11234567`
  • + *
+ */ +@RunWith(Categories.class) +@Suite.SuiteClasses({ + BasicWebAuthnClientInstrumentedTests.class, + Ctap2ClientPinInstrumentedTests.class, + Ctap2CredentialManagementInstrumentedTests.class, + Ctap2SessionInstrumentedTests.class, + EnterpriseAttestationInstrumentedTests.class, + UvDiscouragedInstrumentedTests.class, + Ctap2ConfigInstrumentedTests.class, + Ctap2BioEnrollmentInstrumentedTests.class, + Ctap2SessionResetInstrumentedTests.class, +}) +@Categories.ExcludeCategory(AlwaysManualTest.class) +public class FidoTests { +} diff --git a/testing-desktop/src/test/java/com/yubico/yubikit/testing/fido/UvDiscouragedInstrumentedTests.java b/testing-desktop/src/test/java/com/yubico/yubikit/testing/fido/UvDiscouragedInstrumentedTests.java new file mode 100644 index 00000000..3dc7d58f --- /dev/null +++ b/testing-desktop/src/test/java/com/yubico/yubikit/testing/fido/UvDiscouragedInstrumentedTests.java @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2024 Yubico. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.yubico.yubikit.testing.fido; + +import com.yubico.yubikit.fido.client.PinRequiredClientError; +import com.yubico.yubikit.testing.AlwaysManualTest; +import com.yubico.yubikit.testing.framework.FidoInstrumentedTests; + +import org.junit.Test; +import org.junit.experimental.categories.Category; + +public class UvDiscouragedInstrumentedTests extends FidoInstrumentedTests { + /** + * Reset the FIDO application before running this test. + *

+ * The test will make credential/get assertion without using the PIN which is acceptable for + * {@code UserVerificationRequirement.DISCOURAGED}. + *

+ * Skipped on FIPS approved devices. + */ + @Test + @Category(AlwaysManualTest.class) + public void testMakeCredentialGetAssertion() throws Throwable { + withDevice(false, BasicWebAuthnClientTests::testUvDiscouragedMcGa_noPin); + } + + /** + * This test will make credential without passing PIN value on a device which is protected by + * PIN. + *

+ * Expected to fail with PinRequiredClientError + */ + @Test(expected = PinRequiredClientError.class) + public void testMakeCredentialGetAssertionWithPin() throws Throwable { + withDevice(BasicWebAuthnClientTests::testUvDiscouragedMcGa_withPin); + } +} diff --git a/testing-desktop/src/test/java/com/yubico/yubikit/testing/management/ManagementTests.java b/testing-desktop/src/test/java/com/yubico/yubikit/testing/management/ManagementTests.java new file mode 100644 index 00000000..725cd7fd --- /dev/null +++ b/testing-desktop/src/test/java/com/yubico/yubikit/testing/management/ManagementTests.java @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2024 Yubico. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.yubico.yubikit.testing.management; + +import com.yubico.yubikit.testing.framework.ManagementInstrumentedTests; + +import org.junit.Test; + +public class ManagementTests extends ManagementInstrumentedTests { + @Test + public void testNfcRestricted() throws Throwable { + withManagementSession(ManagementDeviceTests::testNfcRestricted); + } +} diff --git a/testing-desktop/src/test/java/com/yubico/yubikit/testing/mpe/MultiProtocolResetTests.java b/testing-desktop/src/test/java/com/yubico/yubikit/testing/mpe/MultiProtocolResetTests.java new file mode 100644 index 00000000..6c1dfd3f --- /dev/null +++ b/testing-desktop/src/test/java/com/yubico/yubikit/testing/mpe/MultiProtocolResetTests.java @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2024 Yubico. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.yubico.yubikit.testing.mpe; + +import com.yubico.yubikit.core.smartcard.scp.ScpKid; +import com.yubico.yubikit.testing.framework.MpeInstrumentedTests; + +import org.jetbrains.annotations.Nullable; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Suite; + +@RunWith(Suite.class) +@Suite.SuiteClasses({ + MultiProtocolResetTests.NoScpTests.class, + MultiProtocolResetTests.Scp11bTests.class, +}) +public class MultiProtocolResetTests { + public static class NoScpTests extends MpeInstrumentedTests { + @Test + public void testSettingPivPinBlocksFidoReset() throws Throwable { + withPivSession(MultiProtocolResetDeviceTests::testSettingPivPinBlocksFidoReset); + } + + @Test + public void testPivOperationBlocksFidoReset() throws Throwable { + withPivSession(MultiProtocolResetDeviceTests::testPivOperationBlocksFidoReset); + } + + @Test + public void testSettingFidoPinBlocksPivReset() throws Throwable { + withCtap2Session(MultiProtocolResetDeviceTests::testSettingFidoPinBlocksPivReset); + } + } + + public static class Scp11bTests extends NoScpTests { + @Nullable + @Override + protected Byte getScpKid() { + return ScpKid.SCP11b; + } + } +} diff --git a/testing-desktop/src/test/java/com/yubico/yubikit/testing/oath/OathTests.java b/testing-desktop/src/test/java/com/yubico/yubikit/testing/oath/OathTests.java new file mode 100644 index 00000000..74acc71f --- /dev/null +++ b/testing-desktop/src/test/java/com/yubico/yubikit/testing/oath/OathTests.java @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2024 Yubico. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.yubico.yubikit.testing.oath; + +import com.yubico.yubikit.core.smartcard.scp.ScpKid; +import com.yubico.yubikit.testing.SmokeTest; +import com.yubico.yubikit.testing.framework.OathInstrumentedTests; + +import org.jetbrains.annotations.Nullable; +import org.junit.Test; +import org.junit.experimental.categories.Category; +import org.junit.runner.RunWith; +import org.junit.runners.Suite; + +@RunWith(Suite.class) +@Suite.SuiteClasses({ + OathTests.NoScpTests.class, + OathTests.Scp11bTests.class, +}) +public class OathTests { + public static class NoScpTests extends OathInstrumentedTests { + @Test + @Category(SmokeTest.class) + public void testChangePassword() throws Throwable { + withDevice(OathDeviceTests::testChangePassword); + } + + @Test + public void testResetPassword() throws Throwable { + withOathSession(OathDeviceTests::testRemovePassword); + } + + @Test + @Category(SmokeTest.class) + public void testAccountManagement() throws Throwable { + withOathSession(OathDeviceTests::testAccountManagement); + } + + @Test + public void testRenameAccount() throws Throwable { + withOathSession(OathDeviceTests::testRenameAccount); + } + } + + public static class Scp11bTests extends NoScpTests { + @Nullable + @Override + protected Byte getScpKid() { + return ScpKid.SCP11b; + } + } +} diff --git a/testing-desktop/src/test/java/com/yubico/yubikit/testing/openpgp/OpenPgpTests.java b/testing-desktop/src/test/java/com/yubico/yubikit/testing/openpgp/OpenPgpTests.java new file mode 100644 index 00000000..13f5529d --- /dev/null +++ b/testing-desktop/src/test/java/com/yubico/yubikit/testing/openpgp/OpenPgpTests.java @@ -0,0 +1,153 @@ +/* + * Copyright (C) 2024 Yubico. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.yubico.yubikit.testing.openpgp; + +import com.yubico.yubikit.core.smartcard.scp.ScpKid; +import com.yubico.yubikit.testing.SlowTest; +import com.yubico.yubikit.testing.SmokeTest; +import com.yubico.yubikit.testing.framework.OpenPgpInstrumentedTests; + +import org.jetbrains.annotations.Nullable; +import org.junit.Test; +import org.junit.experimental.categories.Category; +import org.junit.runner.RunWith; +import org.junit.runners.Suite; + +@RunWith(Suite.class) +@Suite.SuiteClasses({ + OpenPgpTests.NoScpTests.class, + OpenPgpTests.Scp11bTests.class, +}) +public class OpenPgpTests { + public static class NoScpTests extends OpenPgpInstrumentedTests { + @Test + public void testImportRsaKeys() throws Throwable { + withOpenPgpSession(OpenPgpDeviceTests::testImportRsaKeys); + } + + @Test + public void testImportEcDsaKeys() throws Throwable { + withOpenPgpSession(OpenPgpDeviceTests::testImportEcDsaKeys); + } + + @Test + public void testImportEd25519Keys() throws Throwable { + withOpenPgpSession(OpenPgpDeviceTests::testImportEd25519); + } + + @Test + public void testImportX25519Keys() throws Throwable { + withOpenPgpSession(OpenPgpDeviceTests::testImportX25519); + } + + @Test + public void testGenerateRequiresAdmin() throws Throwable { + withOpenPgpSession(OpenPgpDeviceTests::testGenerateRequiresAdmin); + } + + @Test + public void testChangePin() throws Throwable { + withOpenPgpSession(OpenPgpDeviceTests::testChangePin); + } + + @Test + public void testResetPin() throws Throwable { + withOpenPgpSession(OpenPgpDeviceTests::testResetPin); + } + + @Test + public void testSetPinAttempts() throws Throwable { + withOpenPgpSession(OpenPgpDeviceTests::testSetPinAttempts); + } + + @Test + @Category(SlowTest.class) + public void testGenerateRsaKeys() throws Throwable { + withOpenPgpSession(OpenPgpDeviceTests::testGenerateRsaKeys); + } + + @Test + public void testGenerateEcKeys() throws Throwable { + withOpenPgpSession(OpenPgpDeviceTests::testGenerateEcKeys); + } + + @Test + public void testGenerateEd25519() throws Throwable { + withOpenPgpSession(OpenPgpDeviceTests::testGenerateEd25519); + } + + @Test + public void testGenerateX25519() throws Throwable { + withOpenPgpSession(OpenPgpDeviceTests::testGenerateX25519); + } + + @Test + public void testAttestation() throws Throwable { + withOpenPgpSession(OpenPgpDeviceTests::testAttestation); + } + + @Test + @Category(SmokeTest.class) + public void testSigPinPolicy() throws Throwable { + withOpenPgpSession(OpenPgpDeviceTests::testSigPinPolicy); + } + + @Test + public void testKdf() throws Throwable { + withOpenPgpSession(OpenPgpDeviceTests::testKdf); + } + + @Test + public void testUnverifyPin() throws Throwable { + withOpenPgpSession(OpenPgpDeviceTests::testUnverifyPin); + } + + @Test + public void testDeleteKey() throws Throwable { + withOpenPgpSession(OpenPgpDeviceTests::testDeleteKey); + } + + @Test + public void testCertificateManagement() throws Throwable { + withOpenPgpSession(OpenPgpDeviceTests::testCertificateManagement); + } + + @Test + @Category(SmokeTest.class) + public void testGetChallenge() throws Throwable { + withOpenPgpSession(OpenPgpDeviceTests::testGetChallenge); + } + + @Test + public void testSetUif() throws Throwable { + withOpenPgpSession(OpenPgpDeviceTests::testSetUif); + } + + @Test + public void testPinComplexity() throws Throwable { + withOpenPgpSession(OpenPgpDeviceTests::testPinComplexity); + } + } + + public static class Scp11bTests extends NoScpTests { + @Nullable + @Override + protected Byte getScpKid() { + return ScpKid.SCP11b; + } + } +} diff --git a/testing-desktop/src/test/java/com/yubico/yubikit/testing/PivTests.java b/testing-desktop/src/test/java/com/yubico/yubikit/testing/piv/PivBioMultiProtocolTests.java similarity index 57% rename from testing-desktop/src/test/java/com/yubico/yubikit/testing/PivTests.java rename to testing-desktop/src/test/java/com/yubico/yubikit/testing/piv/PivBioMultiProtocolTests.java index 5926b0ee..27ac20d2 100644 --- a/testing-desktop/src/test/java/com/yubico/yubikit/testing/PivTests.java +++ b/testing-desktop/src/test/java/com/yubico/yubikit/testing/piv/PivBioMultiProtocolTests.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 Yubico. + * Copyright (C) 2024 Yubico. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,27 +14,16 @@ * limitations under the License. */ -package com.yubico.yubikit.testing; +package com.yubico.yubikit.testing.piv; import com.yubico.yubikit.testing.framework.PivInstrumentedTests; -import com.yubico.yubikit.testing.piv.PivDeviceTests; import org.junit.Test; -public class PivTests extends PivInstrumentedTests { +public class PivBioMultiProtocolTests extends PivInstrumentedTests { @Test - public void testPin() throws Throwable { - withPivSession(PivDeviceTests::testPin); - } - - @Test - public void testPuk() throws Throwable { - withPivSession(PivDeviceTests::testPuk); - } - - @Test - public void testManagementKey() throws Throwable { - withPivSession(PivDeviceTests::testManagementKey); + public void testAuthenticate() throws Throwable { + withPivSession(PivBioMultiProtocolDeviceTests::testAuthenticate); } } diff --git a/testing-desktop/src/test/java/com/yubico/yubikit/testing/piv/PivJcaProviderTests.java b/testing-desktop/src/test/java/com/yubico/yubikit/testing/piv/PivJcaProviderTests.java new file mode 100644 index 00000000..662fdce2 --- /dev/null +++ b/testing-desktop/src/test/java/com/yubico/yubikit/testing/piv/PivJcaProviderTests.java @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2024 Yubico. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.yubico.yubikit.testing.piv; + +import com.yubico.yubikit.core.smartcard.scp.ScpKid; +import com.yubico.yubikit.testing.SlowTest; +import com.yubico.yubikit.testing.SmokeTest; +import com.yubico.yubikit.testing.framework.PivInstrumentedTests; + +import org.jetbrains.annotations.Nullable; +import org.junit.Test; +import org.junit.experimental.categories.Category; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@RunWith(JUnit4.class) +public class PivJcaProviderTests { + + public static class NoScpTests extends PivInstrumentedTests { + @Test + @Category(SlowTest.class) + public void testGenerateKeys() throws Throwable { + withPivSession(PivJcaDeviceTests::testGenerateKeys); + } + + @Test + @Category(SlowTest.class) + public void testGenerateKeysPreferBC() throws Throwable { + withPivSession(PivJcaDeviceTests::testGenerateKeysPreferBC); + } + + @Test + @Category(SmokeTest.class) + public void testImportKeys() throws Throwable { + withPivSession(PivJcaDeviceTests::testImportKeys); + } + + @Test + @Category(SlowTest.class) + public void testSigning() throws Throwable { + withPivSession(PivJcaSigningTests::testSign); + } + + @Test + @Category(SlowTest.class) + public void testDecrypt() throws Throwable { + withPivSession(PivJcaDecryptTests::testDecrypt); + } + + @Test + public void testMoveKey() throws Throwable { + withPivSession(PivMoveKeyTests::moveKey); + } + } + + public static class Scp11bTests extends NoScpTests { + @Nullable + @Override + protected Byte getScpKid() { + return ScpKid.SCP11b; + } + } +} diff --git a/testing-desktop/src/test/java/com/yubico/yubikit/testing/piv/PivTests.java b/testing-desktop/src/test/java/com/yubico/yubikit/testing/piv/PivTests.java new file mode 100644 index 00000000..5fdff96a --- /dev/null +++ b/testing-desktop/src/test/java/com/yubico/yubikit/testing/piv/PivTests.java @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2024 Yubico. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.yubico.yubikit.testing.piv; + +import com.yubico.yubikit.core.smartcard.scp.ScpKid; +import com.yubico.yubikit.testing.SmokeTest; +import com.yubico.yubikit.testing.framework.PivInstrumentedTests; + +import org.jetbrains.annotations.Nullable; +import org.junit.Test; +import org.junit.experimental.categories.Category; +import org.junit.runner.RunWith; +import org.junit.runners.Suite; + +@RunWith(Suite.class) +@Suite.SuiteClasses({ + PivTests.NoScpTests.class, + PivTests.Scp11bTests.class, + PivJcaProviderTests.NoScpTests.class, + PivJcaProviderTests.Scp11bTests.class +}) +public class PivTests { + public static class NoScpTests extends PivInstrumentedTests { + @Test + @Category(SmokeTest.class) + public void testPin() throws Throwable { + withPivSession(PivDeviceTests::testPin); + } + + @Test + public void testPuk() throws Throwable { + withPivSession(PivDeviceTests::testPuk); + } + + @Test + public void testManagementKey() throws Throwable { + withPivSession(PivDeviceTests::testManagementKey); + } + + @Test + public void testManagementKeyType() throws Throwable { + withPivSession(PivDeviceTests::testManagementKeyType); + } + + @Test + public void testPutUncompressedCertificate() throws Throwable { + withPivSession(PivCertificateTests::putUncompressedCertificate); + } + + @Test + @Category(SmokeTest.class) + public void testPutCompressedCertificate() throws Throwable { + withPivSession(PivCertificateTests::putCompressedCertificate); + } + + @Test + public void testPinComplexity() throws Throwable { + withPivSession(PivPinComplexityDeviceTests::testPinComplexity); + } + } + + public static class Scp11bTests extends NoScpTests { + @Override + @Nullable + protected Byte getScpKid() { + return ScpKid.SCP11b; + } + } +} diff --git a/testing-desktop/src/test/java/com/yubico/yubikit/testing/sd/Scp03Tests.java b/testing-desktop/src/test/java/com/yubico/yubikit/testing/sd/Scp03Tests.java new file mode 100644 index 00000000..42515ec8 --- /dev/null +++ b/testing-desktop/src/test/java/com/yubico/yubikit/testing/sd/Scp03Tests.java @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2024 Yubico. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.yubico.yubikit.testing.sd; + +import com.yubico.yubikit.testing.SmokeTest; +import com.yubico.yubikit.testing.framework.SecurityDomainInstrumentedTests; + +import org.junit.Before; +import org.junit.Test; +import org.junit.experimental.categories.Category; + +public class Scp03Tests extends SecurityDomainInstrumentedTests { + + @Before + public void before() throws Throwable { + withState(Scp03DeviceTests::before); + } + @Test + public void testImportKey() throws Throwable { + withState(Scp03DeviceTests::testImportKey); + } + + @Test + public void testDeleteKey() throws Throwable { + withState(Scp03DeviceTests::testDeleteKey); + } + + @Test + @Category(SmokeTest.class) + public void testReplaceKey() throws Throwable { + withState(Scp03DeviceTests::testReplaceKey); + } + + @Test + public void testWrongKey() throws Throwable { + withState(Scp03DeviceTests::testWrongKey); + } +} diff --git a/testing-desktop/src/test/java/com/yubico/yubikit/testing/sd/Scp11Tests.java b/testing-desktop/src/test/java/com/yubico/yubikit/testing/sd/Scp11Tests.java new file mode 100644 index 00000000..dc368681 --- /dev/null +++ b/testing-desktop/src/test/java/com/yubico/yubikit/testing/sd/Scp11Tests.java @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2024 Yubico. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.yubico.yubikit.testing.sd; + +import com.yubico.yubikit.testing.framework.SecurityDomainInstrumentedTests; + +import org.junit.Before; +import org.junit.Test; + +public class Scp11Tests extends SecurityDomainInstrumentedTests { + + @Before + public void before() throws Throwable { + withState(Scp11DeviceTests::before); + } + + @Test + public void testScp11aAuthenticate() throws Throwable { + withState(Scp11DeviceTests::testScp11aAuthenticate); + } + + @Test + public void testScp11aAllowlist() throws Throwable { + withState(Scp11DeviceTests::testScp11aAllowList); + } + + @Test + public void testScp11aAllowlistBlocked() throws Throwable { + withState(Scp11DeviceTests::testScp11aAllowListBlocked); + } + + @Test + public void testScp11bAuthenticate() throws Throwable { + withState(Scp11DeviceTests::testScp11bAuthenticate); + } + + @Test + public void testScp11bWrongPubKey() throws Throwable { + withState(Scp11DeviceTests::testScp11bWrongPubKey); + } + + @Test + public void testScp11bImport() throws Throwable { + withState(Scp11DeviceTests::testScp11bImport); + } + + @Test + public void testScp11cAuthenticate() throws Throwable { + withState(Scp11DeviceTests::testScp11cAuthenticate); + } +} diff --git a/testing-desktop/src/test/java/com/yubico/yubikit/testing/sd/SecurityDomainTests.java b/testing-desktop/src/test/java/com/yubico/yubikit/testing/sd/SecurityDomainTests.java new file mode 100644 index 00000000..4fbbc10f --- /dev/null +++ b/testing-desktop/src/test/java/com/yubico/yubikit/testing/sd/SecurityDomainTests.java @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2024 Yubico. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.yubico.yubikit.testing.sd; + +import org.junit.runner.RunWith; +import org.junit.runners.Suite; + +@RunWith(Suite.class) +@Suite.SuiteClasses({ + Scp03Tests.class, + Scp11Tests.class +}) +public class SecurityDomainTests { +} diff --git a/testing-desktop/src/test/resources/logback-test.xml b/testing-desktop/src/test/resources/logback-test.xml new file mode 100644 index 00000000..62edd79f --- /dev/null +++ b/testing-desktop/src/test/resources/logback-test.xml @@ -0,0 +1,31 @@ + + + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger - %msg%n + + + + + + + + \ No newline at end of file diff --git a/testing/src/main/java/com/yubico/yubikit/testing/piv/PivMoveKeyTests.java b/testing/src/main/java/com/yubico/yubikit/testing/piv/PivMoveKeyTests.java index 432cdca1..258885a7 100644 --- a/testing/src/main/java/com/yubico/yubikit/testing/piv/PivMoveKeyTests.java +++ b/testing/src/main/java/com/yubico/yubikit/testing/piv/PivMoveKeyTests.java @@ -52,7 +52,7 @@ public class PivMoveKeyTests { - static void moveKey(PivSession piv, PivTestState state) + static public void moveKey(PivSession piv, PivTestState state) throws IOException, ApduException, BadResponseException, NoSuchAlgorithmException { Assume.assumeTrue("Key does not support move instruction", piv.supports(FEATURE_MOVE_KEY)); setupJca(piv); diff --git a/testing/src/main/java/com/yubico/yubikit/testing/piv/PivPinComplexityDeviceTests.java b/testing/src/main/java/com/yubico/yubikit/testing/piv/PivPinComplexityDeviceTests.java index 39ed4d29..20857a0b 100755 --- a/testing/src/main/java/com/yubico/yubikit/testing/piv/PivPinComplexityDeviceTests.java +++ b/testing/src/main/java/com/yubico/yubikit/testing/piv/PivPinComplexityDeviceTests.java @@ -35,7 +35,7 @@ public class PivPinComplexityDeviceTests { * * @see DeviceInfo#getPinComplexity() */ - static void testPinComplexity(PivSession piv, PivTestState state) throws Throwable { + static public void testPinComplexity(PivSession piv, PivTestState state) throws Throwable { final DeviceInfo deviceInfo = state.getDeviceInfo(); assumeTrue("Device does not support PIN complexity", deviceInfo != null); From 6536e51106f93b0f344128817d1cd9abfda7cd32 Mon Sep 17 00:00:00 2001 From: Adam Velebil Date: Wed, 11 Dec 2024 15:29:40 +0100 Subject: [PATCH 11/24] fix getAtr() --- .../yubico/yubikit/desktop/pcsc/PcscSmartCardConnection.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/desktop/src/main/java/com/yubico/yubikit/desktop/pcsc/PcscSmartCardConnection.java b/desktop/src/main/java/com/yubico/yubikit/desktop/pcsc/PcscSmartCardConnection.java index 489b81c4..c2fb6325 100755 --- a/desktop/src/main/java/com/yubico/yubikit/desktop/pcsc/PcscSmartCardConnection.java +++ b/desktop/src/main/java/com/yubico/yubikit/desktop/pcsc/PcscSmartCardConnection.java @@ -62,8 +62,7 @@ public boolean isExtendedLengthApduSupported() { @Override public byte[] getAtr() { - // TODO - return new byte[0]; + return card.getATR().getBytes(); } @Override From 04297db867cec53cc30c102750a8448a641b0686 Mon Sep 17 00:00:00 2001 From: Adam Velebil Date: Fri, 13 Dec 2024 11:24:34 +0100 Subject: [PATCH 12/24] move tests to desktop package --- .../desktop/pcsc/PcscSmartCardConnection.java | 2 +- testing-desktop/build.gradle | 2 ++ .../testing/{ => desktop}/AlwaysManualTest.java | 2 +- .../testing/{ => desktop}/DesktopTestDriver.java | 2 +- .../{ => desktop}/PinUvAuthProtocolV1Test.java | 2 +- .../yubikit/testing/{ => desktop}/SlowTest.java | 2 +- .../yubikit/testing/{ => desktop}/SmokeTest.java | 2 +- .../framework/FidoInstrumentedTests.java | 2 +- .../framework/ManagementInstrumentedTests.java | 2 +- .../framework/MpeInstrumentedTests.java | 2 +- .../framework/OathInstrumentedTests.java | 2 +- .../framework/OpenPgpInstrumentedTests.java | 2 +- .../framework/PivInstrumentedTests.java | 12 ++++++++++-- .../framework/SecurityDomainInstrumentedTests.java | 2 +- .../framework/YKInstrumentedTests.java | 6 +++--- .../yubikit/testing/{ => desktop}/DeviceTests.java | 14 +++++++------- .../testing/{ => desktop}/FastDeviceTests.java | 2 +- .../testing/{ => desktop}/SmokeDeviceTests.java | 2 +- .../fido/BasicWebAuthnClientInstrumentedTests.java | 9 +++++---- .../fido/Ctap2BioEnrollmentInstrumentedTests.java | 5 +++-- .../fido/Ctap2ClientPinInstrumentedTests.java | 7 ++++--- .../fido/Ctap2ConfigInstrumentedTests.java | 7 ++++--- ...Ctap2CredentialManagementInstrumentedTests.java | 9 +++++---- .../fido/Ctap2SessionInstrumentedTests.java | 9 +++++---- .../fido/Ctap2SessionResetInstrumentedTests.java | 9 +++++---- .../EnterpriseAttestationInstrumentedTests.java | 7 ++++--- .../testing/{ => desktop}/fido/FidoTests.java | 4 ++-- .../fido/UvDiscouragedInstrumentedTests.java | 7 ++++--- .../{ => desktop}/management/ManagementTests.java | 5 +++-- .../{ => desktop}/mpe/MultiProtocolResetTests.java | 5 +++-- .../testing/{ => desktop}/oath/OathTests.java | 7 ++++--- .../{ => desktop}/openpgp/OpenPgpTests.java | 9 +++++---- .../piv/PivBioMultiProtocolTests.java | 5 +++-- .../{ => desktop}/piv/PivJcaProviderTests.java | 12 ++++++++---- .../testing/{ => desktop}/piv/PivTests.java | 9 ++++++--- .../testing/{ => desktop}/sd/Scp03Tests.java | 7 ++++--- .../testing/{ => desktop}/sd/Scp11Tests.java | 5 +++-- .../{ => desktop}/sd/SecurityDomainTests.java | 2 +- 38 files changed, 117 insertions(+), 84 deletions(-) rename testing-desktop/src/main/java/com/yubico/yubikit/testing/{ => desktop}/AlwaysManualTest.java (93%) rename testing-desktop/src/main/java/com/yubico/yubikit/testing/{ => desktop}/DesktopTestDriver.java (97%) rename testing-desktop/src/main/java/com/yubico/yubikit/testing/{ => desktop}/PinUvAuthProtocolV1Test.java (93%) rename testing-desktop/src/main/java/com/yubico/yubikit/testing/{ => desktop}/SlowTest.java (93%) rename testing-desktop/src/main/java/com/yubico/yubikit/testing/{ => desktop}/SmokeTest.java (93%) rename testing-desktop/src/main/java/com/yubico/yubikit/testing/{ => desktop}/framework/FidoInstrumentedTests.java (97%) rename testing-desktop/src/main/java/com/yubico/yubikit/testing/{ => desktop}/framework/ManagementInstrumentedTests.java (95%) rename testing-desktop/src/main/java/com/yubico/yubikit/testing/{ => desktop}/framework/MpeInstrumentedTests.java (96%) rename testing-desktop/src/main/java/com/yubico/yubikit/testing/{ => desktop}/framework/OathInstrumentedTests.java (96%) rename testing-desktop/src/main/java/com/yubico/yubikit/testing/{ => desktop}/framework/OpenPgpInstrumentedTests.java (95%) rename testing-desktop/src/main/java/com/yubico/yubikit/testing/{ => desktop}/framework/PivInstrumentedTests.java (78%) rename testing-desktop/src/main/java/com/yubico/yubikit/testing/{ => desktop}/framework/SecurityDomainInstrumentedTests.java (95%) rename testing-desktop/src/main/java/com/yubico/yubikit/testing/{ => desktop}/framework/YKInstrumentedTests.java (92%) rename testing-desktop/src/test/java/com/yubico/yubikit/testing/{ => desktop}/DeviceTests.java (72%) rename testing-desktop/src/test/java/com/yubico/yubikit/testing/{ => desktop}/FastDeviceTests.java (96%) rename testing-desktop/src/test/java/com/yubico/yubikit/testing/{ => desktop}/SmokeDeviceTests.java (95%) rename testing-desktop/src/test/java/com/yubico/yubikit/testing/{ => desktop}/fido/BasicWebAuthnClientInstrumentedTests.java (90%) rename testing-desktop/src/test/java/com/yubico/yubikit/testing/{ => desktop}/fido/Ctap2BioEnrollmentInstrumentedTests.java (82%) rename testing-desktop/src/test/java/com/yubico/yubikit/testing/{ => desktop}/fido/Ctap2ClientPinInstrumentedTests.java (87%) rename testing-desktop/src/test/java/com/yubico/yubikit/testing/{ => desktop}/fido/Ctap2ConfigInstrumentedTests.java (91%) rename testing-desktop/src/test/java/com/yubico/yubikit/testing/{ => desktop}/fido/Ctap2CredentialManagementInstrumentedTests.java (86%) rename testing-desktop/src/test/java/com/yubico/yubikit/testing/{ => desktop}/fido/Ctap2SessionInstrumentedTests.java (86%) rename testing-desktop/src/test/java/com/yubico/yubikit/testing/{ => desktop}/fido/Ctap2SessionResetInstrumentedTests.java (85%) rename testing-desktop/src/test/java/com/yubico/yubikit/testing/{ => desktop}/fido/EnterpriseAttestationInstrumentedTests.java (89%) rename testing-desktop/src/test/java/com/yubico/yubikit/testing/{ => desktop}/fido/FidoTests.java (93%) rename testing-desktop/src/test/java/com/yubico/yubikit/testing/{ => desktop}/fido/UvDiscouragedInstrumentedTests.java (87%) rename testing-desktop/src/test/java/com/yubico/yubikit/testing/{ => desktop}/management/ManagementTests.java (80%) rename testing-desktop/src/test/java/com/yubico/yubikit/testing/{ => desktop}/mpe/MultiProtocolResetTests.java (90%) rename testing-desktop/src/test/java/com/yubico/yubikit/testing/{ => desktop}/oath/OathTests.java (89%) rename testing-desktop/src/test/java/com/yubico/yubikit/testing/{ => desktop}/openpgp/OpenPgpTests.java (93%) rename testing-desktop/src/test/java/com/yubico/yubikit/testing/{ => desktop}/piv/PivBioMultiProtocolTests.java (81%) rename testing-desktop/src/test/java/com/yubico/yubikit/testing/{ => desktop}/piv/PivJcaProviderTests.java (82%) rename testing-desktop/src/test/java/com/yubico/yubikit/testing/{ => desktop}/piv/PivTests.java (87%) rename testing-desktop/src/test/java/com/yubico/yubikit/testing/{ => desktop}/sd/Scp03Tests.java (85%) rename testing-desktop/src/test/java/com/yubico/yubikit/testing/{ => desktop}/sd/Scp11Tests.java (90%) rename testing-desktop/src/test/java/com/yubico/yubikit/testing/{ => desktop}/sd/SecurityDomainTests.java (94%) diff --git a/desktop/src/main/java/com/yubico/yubikit/desktop/pcsc/PcscSmartCardConnection.java b/desktop/src/main/java/com/yubico/yubikit/desktop/pcsc/PcscSmartCardConnection.java index c2fb6325..a37494e6 100755 --- a/desktop/src/main/java/com/yubico/yubikit/desktop/pcsc/PcscSmartCardConnection.java +++ b/desktop/src/main/java/com/yubico/yubikit/desktop/pcsc/PcscSmartCardConnection.java @@ -57,7 +57,7 @@ public Transport getTransport() { @Override public boolean isExtendedLengthApduSupported() { - return false; //TODO + return true; } @Override diff --git a/testing-desktop/build.gradle b/testing-desktop/build.gradle index 89b5f3c0..6115822d 100755 --- a/testing-desktop/build.gradle +++ b/testing-desktop/build.gradle @@ -16,6 +16,8 @@ dependencies { testImplementation 'junit:junit:4.13.2' testImplementation 'ch.qos.logback:logback-classic:1.5.12' + implementation 'org.bouncycastle:bcpkix-jdk15to18:1.78.1' + testRuntimeOnly('org.junit.vintage:junit-vintage-engine:5.9.0') } diff --git a/testing-desktop/src/main/java/com/yubico/yubikit/testing/AlwaysManualTest.java b/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/AlwaysManualTest.java similarity index 93% rename from testing-desktop/src/main/java/com/yubico/yubikit/testing/AlwaysManualTest.java rename to testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/AlwaysManualTest.java index 741514a2..786d27ec 100644 --- a/testing-desktop/src/main/java/com/yubico/yubikit/testing/AlwaysManualTest.java +++ b/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/AlwaysManualTest.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.yubico.yubikit.testing; +package com.yubico.yubikit.testing.desktop; public interface AlwaysManualTest { } diff --git a/testing-desktop/src/main/java/com/yubico/yubikit/testing/DesktopTestDriver.java b/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/DesktopTestDriver.java similarity index 97% rename from testing-desktop/src/main/java/com/yubico/yubikit/testing/DesktopTestDriver.java rename to testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/DesktopTestDriver.java index 9271482d..8afa96e8 100644 --- a/testing-desktop/src/main/java/com/yubico/yubikit/testing/DesktopTestDriver.java +++ b/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/DesktopTestDriver.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.yubico.yubikit.testing; +package com.yubico.yubikit.testing.desktop; import com.yubico.yubikit.core.YubiKeyDevice; import com.yubico.yubikit.core.internal.Logger; diff --git a/testing-desktop/src/main/java/com/yubico/yubikit/testing/PinUvAuthProtocolV1Test.java b/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/PinUvAuthProtocolV1Test.java similarity index 93% rename from testing-desktop/src/main/java/com/yubico/yubikit/testing/PinUvAuthProtocolV1Test.java rename to testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/PinUvAuthProtocolV1Test.java index ae497767..ad704c77 100644 --- a/testing-desktop/src/main/java/com/yubico/yubikit/testing/PinUvAuthProtocolV1Test.java +++ b/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/PinUvAuthProtocolV1Test.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.yubico.yubikit.testing; +package com.yubico.yubikit.testing.desktop; public interface PinUvAuthProtocolV1Test { } diff --git a/testing-desktop/src/main/java/com/yubico/yubikit/testing/SlowTest.java b/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/SlowTest.java similarity index 93% rename from testing-desktop/src/main/java/com/yubico/yubikit/testing/SlowTest.java rename to testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/SlowTest.java index 2ce9ac4d..e2b2ec5b 100644 --- a/testing-desktop/src/main/java/com/yubico/yubikit/testing/SlowTest.java +++ b/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/SlowTest.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.yubico.yubikit.testing; +package com.yubico.yubikit.testing.desktop; public interface SlowTest { } diff --git a/testing-desktop/src/main/java/com/yubico/yubikit/testing/SmokeTest.java b/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/SmokeTest.java similarity index 93% rename from testing-desktop/src/main/java/com/yubico/yubikit/testing/SmokeTest.java rename to testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/SmokeTest.java index 9cc98909..a250a950 100644 --- a/testing-desktop/src/main/java/com/yubico/yubikit/testing/SmokeTest.java +++ b/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/SmokeTest.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.yubico.yubikit.testing; +package com.yubico.yubikit.testing.desktop; public interface SmokeTest { } diff --git a/testing-desktop/src/main/java/com/yubico/yubikit/testing/framework/FidoInstrumentedTests.java b/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/framework/FidoInstrumentedTests.java similarity index 97% rename from testing-desktop/src/main/java/com/yubico/yubikit/testing/framework/FidoInstrumentedTests.java rename to testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/framework/FidoInstrumentedTests.java index a5c665c5..573bf14e 100755 --- a/testing-desktop/src/main/java/com/yubico/yubikit/testing/framework/FidoInstrumentedTests.java +++ b/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/framework/FidoInstrumentedTests.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.yubico.yubikit.testing.framework; +package com.yubico.yubikit.testing.desktop.framework; import com.yubico.yubikit.core.Transport; import com.yubico.yubikit.core.smartcard.scp.ScpKid; diff --git a/testing-desktop/src/main/java/com/yubico/yubikit/testing/framework/ManagementInstrumentedTests.java b/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/framework/ManagementInstrumentedTests.java similarity index 95% rename from testing-desktop/src/main/java/com/yubico/yubikit/testing/framework/ManagementInstrumentedTests.java rename to testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/framework/ManagementInstrumentedTests.java index da3ee06e..6433c2b6 100644 --- a/testing-desktop/src/main/java/com/yubico/yubikit/testing/framework/ManagementInstrumentedTests.java +++ b/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/framework/ManagementInstrumentedTests.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.yubico.yubikit.testing.framework; +package com.yubico.yubikit.testing.desktop.framework; import com.yubico.yubikit.core.smartcard.SmartCardConnection; import com.yubico.yubikit.management.ManagementSession; diff --git a/testing-desktop/src/main/java/com/yubico/yubikit/testing/framework/MpeInstrumentedTests.java b/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/framework/MpeInstrumentedTests.java similarity index 96% rename from testing-desktop/src/main/java/com/yubico/yubikit/testing/framework/MpeInstrumentedTests.java rename to testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/framework/MpeInstrumentedTests.java index 5a355b93..4d5dd6a0 100755 --- a/testing-desktop/src/main/java/com/yubico/yubikit/testing/framework/MpeInstrumentedTests.java +++ b/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/framework/MpeInstrumentedTests.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.yubico.yubikit.testing.framework; +package com.yubico.yubikit.testing.desktop.framework; import com.yubico.yubikit.fido.ctap.Ctap2Session; import com.yubico.yubikit.piv.PivSession; diff --git a/testing-desktop/src/main/java/com/yubico/yubikit/testing/framework/OathInstrumentedTests.java b/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/framework/OathInstrumentedTests.java similarity index 96% rename from testing-desktop/src/main/java/com/yubico/yubikit/testing/framework/OathInstrumentedTests.java rename to testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/framework/OathInstrumentedTests.java index 07271f8c..b40edfa2 100644 --- a/testing-desktop/src/main/java/com/yubico/yubikit/testing/framework/OathInstrumentedTests.java +++ b/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/framework/OathInstrumentedTests.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.yubico.yubikit.testing.framework; +package com.yubico.yubikit.testing.desktop.framework; import com.yubico.yubikit.oath.OathSession; import com.yubico.yubikit.testing.TestState; diff --git a/testing-desktop/src/main/java/com/yubico/yubikit/testing/framework/OpenPgpInstrumentedTests.java b/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/framework/OpenPgpInstrumentedTests.java similarity index 95% rename from testing-desktop/src/main/java/com/yubico/yubikit/testing/framework/OpenPgpInstrumentedTests.java rename to testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/framework/OpenPgpInstrumentedTests.java index be5834cf..8abb0080 100644 --- a/testing-desktop/src/main/java/com/yubico/yubikit/testing/framework/OpenPgpInstrumentedTests.java +++ b/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/framework/OpenPgpInstrumentedTests.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.yubico.yubikit.testing.framework; +package com.yubico.yubikit.testing.desktop.framework; import com.yubico.yubikit.openpgp.OpenPgpSession; import com.yubico.yubikit.testing.TestState; diff --git a/testing-desktop/src/main/java/com/yubico/yubikit/testing/framework/PivInstrumentedTests.java b/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/framework/PivInstrumentedTests.java similarity index 78% rename from testing-desktop/src/main/java/com/yubico/yubikit/testing/framework/PivInstrumentedTests.java rename to testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/framework/PivInstrumentedTests.java index e6933c3b..e7410e64 100755 --- a/testing-desktop/src/main/java/com/yubico/yubikit/testing/framework/PivInstrumentedTests.java +++ b/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/framework/PivInstrumentedTests.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022,2024 Yubico. + * Copyright (C) 2022-2024 Yubico. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,15 +14,23 @@ * limitations under the License. */ -package com.yubico.yubikit.testing.framework; +package com.yubico.yubikit.testing.desktop.framework; import com.yubico.yubikit.piv.PivSession; import com.yubico.yubikit.testing.TestState; import com.yubico.yubikit.testing.piv.PivTestState; +import org.bouncycastle.jce.provider.BouncyCastleProvider; + +import java.security.Security; + public class PivInstrumentedTests extends YKInstrumentedTests { protected void withPivSession(TestState.StatefulSessionCallback callback) throws Throwable { + + Security.removeProvider("BC"); + Security.insertProviderAt(new BouncyCastleProvider(), 1); + final PivTestState state = new PivTestState.Builder(device, usbPid) .scpKid(getScpKid()) .build(); diff --git a/testing-desktop/src/main/java/com/yubico/yubikit/testing/framework/SecurityDomainInstrumentedTests.java b/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/framework/SecurityDomainInstrumentedTests.java similarity index 95% rename from testing-desktop/src/main/java/com/yubico/yubikit/testing/framework/SecurityDomainInstrumentedTests.java rename to testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/framework/SecurityDomainInstrumentedTests.java index 59e2c1bc..4e212b22 100644 --- a/testing-desktop/src/main/java/com/yubico/yubikit/testing/framework/SecurityDomainInstrumentedTests.java +++ b/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/framework/SecurityDomainInstrumentedTests.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.yubico.yubikit.testing.framework; +package com.yubico.yubikit.testing.desktop.framework; import com.yubico.yubikit.testing.TestState; import com.yubico.yubikit.testing.sd.SecurityDomainTestState; diff --git a/testing-desktop/src/main/java/com/yubico/yubikit/testing/framework/YKInstrumentedTests.java b/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/framework/YKInstrumentedTests.java similarity index 92% rename from testing-desktop/src/main/java/com/yubico/yubikit/testing/framework/YKInstrumentedTests.java rename to testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/framework/YKInstrumentedTests.java index 206d94cc..32402253 100755 --- a/testing-desktop/src/main/java/com/yubico/yubikit/testing/framework/YKInstrumentedTests.java +++ b/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/framework/YKInstrumentedTests.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022,2024 Yubico. + * Copyright (C) 2022-2024 Yubico. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,12 +14,12 @@ * limitations under the License. */ -package com.yubico.yubikit.testing.framework; +package com.yubico.yubikit.testing.desktop.framework; import com.yubico.yubikit.core.UsbPid; import com.yubico.yubikit.core.YubiKeyDevice; import com.yubico.yubikit.desktop.CompositeDevice; -import com.yubico.yubikit.testing.DesktopTestDriver; +import com.yubico.yubikit.testing.desktop.DesktopTestDriver; import org.jetbrains.annotations.Nullable; import org.junit.Rule; diff --git a/testing-desktop/src/test/java/com/yubico/yubikit/testing/DeviceTests.java b/testing-desktop/src/test/java/com/yubico/yubikit/testing/desktop/DeviceTests.java similarity index 72% rename from testing-desktop/src/test/java/com/yubico/yubikit/testing/DeviceTests.java rename to testing-desktop/src/test/java/com/yubico/yubikit/testing/desktop/DeviceTests.java index c691e11d..0ab5dca1 100644 --- a/testing-desktop/src/test/java/com/yubico/yubikit/testing/DeviceTests.java +++ b/testing-desktop/src/test/java/com/yubico/yubikit/testing/desktop/DeviceTests.java @@ -14,14 +14,14 @@ * limitations under the License. */ -package com.yubico.yubikit.testing; +package com.yubico.yubikit.testing.desktop; -import com.yubico.yubikit.testing.mpe.MultiProtocolResetTests; -import com.yubico.yubikit.testing.fido.FidoTests; -import com.yubico.yubikit.testing.oath.OathTests; -import com.yubico.yubikit.testing.openpgp.OpenPgpTests; -import com.yubico.yubikit.testing.piv.PivTests; -import com.yubico.yubikit.testing.sd.SecurityDomainTests; +import com.yubico.yubikit.testing.desktop.mpe.MultiProtocolResetTests; +import com.yubico.yubikit.testing.desktop.fido.FidoTests; +import com.yubico.yubikit.testing.desktop.oath.OathTests; +import com.yubico.yubikit.testing.desktop.openpgp.OpenPgpTests; +import com.yubico.yubikit.testing.desktop.piv.PivTests; +import com.yubico.yubikit.testing.desktop.sd.SecurityDomainTests; import org.junit.runner.RunWith; import org.junit.runners.Suite; diff --git a/testing-desktop/src/test/java/com/yubico/yubikit/testing/FastDeviceTests.java b/testing-desktop/src/test/java/com/yubico/yubikit/testing/desktop/FastDeviceTests.java similarity index 96% rename from testing-desktop/src/test/java/com/yubico/yubikit/testing/FastDeviceTests.java rename to testing-desktop/src/test/java/com/yubico/yubikit/testing/desktop/FastDeviceTests.java index 1c49ae70..905159b3 100644 --- a/testing-desktop/src/test/java/com/yubico/yubikit/testing/FastDeviceTests.java +++ b/testing-desktop/src/test/java/com/yubico/yubikit/testing/desktop/FastDeviceTests.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.yubico.yubikit.testing; +package com.yubico.yubikit.testing.desktop; import org.junit.experimental.categories.Categories; import org.junit.runner.RunWith; diff --git a/testing-desktop/src/test/java/com/yubico/yubikit/testing/SmokeDeviceTests.java b/testing-desktop/src/test/java/com/yubico/yubikit/testing/desktop/SmokeDeviceTests.java similarity index 95% rename from testing-desktop/src/test/java/com/yubico/yubikit/testing/SmokeDeviceTests.java rename to testing-desktop/src/test/java/com/yubico/yubikit/testing/desktop/SmokeDeviceTests.java index f13335bc..2f432e61 100644 --- a/testing-desktop/src/test/java/com/yubico/yubikit/testing/SmokeDeviceTests.java +++ b/testing-desktop/src/test/java/com/yubico/yubikit/testing/desktop/SmokeDeviceTests.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.yubico.yubikit.testing; +package com.yubico.yubikit.testing.desktop; import org.junit.experimental.categories.Categories; import org.junit.runner.RunWith; diff --git a/testing-desktop/src/test/java/com/yubico/yubikit/testing/fido/BasicWebAuthnClientInstrumentedTests.java b/testing-desktop/src/test/java/com/yubico/yubikit/testing/desktop/fido/BasicWebAuthnClientInstrumentedTests.java similarity index 90% rename from testing-desktop/src/test/java/com/yubico/yubikit/testing/fido/BasicWebAuthnClientInstrumentedTests.java rename to testing-desktop/src/test/java/com/yubico/yubikit/testing/desktop/fido/BasicWebAuthnClientInstrumentedTests.java index 53a113f6..9a00e9c2 100644 --- a/testing-desktop/src/test/java/com/yubico/yubikit/testing/fido/BasicWebAuthnClientInstrumentedTests.java +++ b/testing-desktop/src/test/java/com/yubico/yubikit/testing/desktop/fido/BasicWebAuthnClientInstrumentedTests.java @@ -14,13 +14,14 @@ * limitations under the License. */ -package com.yubico.yubikit.testing.fido; +package com.yubico.yubikit.testing.desktop.fido; import com.yubico.yubikit.fido.ctap.PinUvAuthProtocol; import com.yubico.yubikit.fido.ctap.PinUvAuthProtocolV1; -import com.yubico.yubikit.testing.PinUvAuthProtocolV1Test; -import com.yubico.yubikit.testing.SmokeTest; -import com.yubico.yubikit.testing.framework.FidoInstrumentedTests; +import com.yubico.yubikit.testing.desktop.PinUvAuthProtocolV1Test; +import com.yubico.yubikit.testing.desktop.SmokeTest; +import com.yubico.yubikit.testing.desktop.framework.FidoInstrumentedTests; +import com.yubico.yubikit.testing.fido.BasicWebAuthnClientTests; import org.junit.Test; import org.junit.experimental.categories.Category; diff --git a/testing-desktop/src/test/java/com/yubico/yubikit/testing/fido/Ctap2BioEnrollmentInstrumentedTests.java b/testing-desktop/src/test/java/com/yubico/yubikit/testing/desktop/fido/Ctap2BioEnrollmentInstrumentedTests.java similarity index 82% rename from testing-desktop/src/test/java/com/yubico/yubikit/testing/fido/Ctap2BioEnrollmentInstrumentedTests.java rename to testing-desktop/src/test/java/com/yubico/yubikit/testing/desktop/fido/Ctap2BioEnrollmentInstrumentedTests.java index 6d68a16b..a2bf6c15 100644 --- a/testing-desktop/src/test/java/com/yubico/yubikit/testing/fido/Ctap2BioEnrollmentInstrumentedTests.java +++ b/testing-desktop/src/test/java/com/yubico/yubikit/testing/desktop/fido/Ctap2BioEnrollmentInstrumentedTests.java @@ -14,10 +14,11 @@ * limitations under the License. */ -package com.yubico.yubikit.testing.fido; +package com.yubico.yubikit.testing.desktop.fido; -import com.yubico.yubikit.testing.framework.FidoInstrumentedTests; +import com.yubico.yubikit.testing.desktop.framework.FidoInstrumentedTests; +import com.yubico.yubikit.testing.fido.Ctap2BioEnrollmentTests; import org.junit.Test; diff --git a/testing-desktop/src/test/java/com/yubico/yubikit/testing/fido/Ctap2ClientPinInstrumentedTests.java b/testing-desktop/src/test/java/com/yubico/yubikit/testing/desktop/fido/Ctap2ClientPinInstrumentedTests.java similarity index 87% rename from testing-desktop/src/test/java/com/yubico/yubikit/testing/fido/Ctap2ClientPinInstrumentedTests.java rename to testing-desktop/src/test/java/com/yubico/yubikit/testing/desktop/fido/Ctap2ClientPinInstrumentedTests.java index ab4c2dca..7fca6884 100644 --- a/testing-desktop/src/test/java/com/yubico/yubikit/testing/fido/Ctap2ClientPinInstrumentedTests.java +++ b/testing-desktop/src/test/java/com/yubico/yubikit/testing/desktop/fido/Ctap2ClientPinInstrumentedTests.java @@ -14,12 +14,13 @@ * limitations under the License. */ -package com.yubico.yubikit.testing.fido; +package com.yubico.yubikit.testing.desktop.fido; import com.yubico.yubikit.fido.ctap.PinUvAuthProtocol; import com.yubico.yubikit.fido.ctap.PinUvAuthProtocolV1; -import com.yubico.yubikit.testing.PinUvAuthProtocolV1Test; -import com.yubico.yubikit.testing.framework.FidoInstrumentedTests; +import com.yubico.yubikit.testing.desktop.PinUvAuthProtocolV1Test; +import com.yubico.yubikit.testing.desktop.framework.FidoInstrumentedTests; +import com.yubico.yubikit.testing.fido.Ctap2ClientPinTests; import org.junit.Test; import org.junit.experimental.categories.Category; diff --git a/testing-desktop/src/test/java/com/yubico/yubikit/testing/fido/Ctap2ConfigInstrumentedTests.java b/testing-desktop/src/test/java/com/yubico/yubikit/testing/desktop/fido/Ctap2ConfigInstrumentedTests.java similarity index 91% rename from testing-desktop/src/test/java/com/yubico/yubikit/testing/fido/Ctap2ConfigInstrumentedTests.java rename to testing-desktop/src/test/java/com/yubico/yubikit/testing/desktop/fido/Ctap2ConfigInstrumentedTests.java index 70f23a17..ba7d99f2 100644 --- a/testing-desktop/src/test/java/com/yubico/yubikit/testing/fido/Ctap2ConfigInstrumentedTests.java +++ b/testing-desktop/src/test/java/com/yubico/yubikit/testing/desktop/fido/Ctap2ConfigInstrumentedTests.java @@ -14,10 +14,11 @@ * limitations under the License. */ -package com.yubico.yubikit.testing.fido; +package com.yubico.yubikit.testing.desktop.fido; -import com.yubico.yubikit.testing.AlwaysManualTest; -import com.yubico.yubikit.testing.framework.FidoInstrumentedTests; +import com.yubico.yubikit.testing.desktop.AlwaysManualTest; +import com.yubico.yubikit.testing.desktop.framework.FidoInstrumentedTests; +import com.yubico.yubikit.testing.fido.Ctap2ConfigTests; import org.junit.Test; import org.junit.experimental.categories.Categories; diff --git a/testing-desktop/src/test/java/com/yubico/yubikit/testing/fido/Ctap2CredentialManagementInstrumentedTests.java b/testing-desktop/src/test/java/com/yubico/yubikit/testing/desktop/fido/Ctap2CredentialManagementInstrumentedTests.java similarity index 86% rename from testing-desktop/src/test/java/com/yubico/yubikit/testing/fido/Ctap2CredentialManagementInstrumentedTests.java rename to testing-desktop/src/test/java/com/yubico/yubikit/testing/desktop/fido/Ctap2CredentialManagementInstrumentedTests.java index 5ed3b5fb..1c03cd77 100644 --- a/testing-desktop/src/test/java/com/yubico/yubikit/testing/fido/Ctap2CredentialManagementInstrumentedTests.java +++ b/testing-desktop/src/test/java/com/yubico/yubikit/testing/desktop/fido/Ctap2CredentialManagementInstrumentedTests.java @@ -14,13 +14,14 @@ * limitations under the License. */ -package com.yubico.yubikit.testing.fido; +package com.yubico.yubikit.testing.desktop.fido; import com.yubico.yubikit.fido.ctap.PinUvAuthProtocol; import com.yubico.yubikit.fido.ctap.PinUvAuthProtocolV1; -import com.yubico.yubikit.testing.PinUvAuthProtocolV1Test; -import com.yubico.yubikit.testing.SmokeTest; -import com.yubico.yubikit.testing.framework.FidoInstrumentedTests; +import com.yubico.yubikit.testing.desktop.PinUvAuthProtocolV1Test; +import com.yubico.yubikit.testing.desktop.SmokeTest; +import com.yubico.yubikit.testing.desktop.framework.FidoInstrumentedTests; +import com.yubico.yubikit.testing.fido.Ctap2CredentialManagementTests; import org.junit.Test; import org.junit.experimental.categories.Category; diff --git a/testing-desktop/src/test/java/com/yubico/yubikit/testing/fido/Ctap2SessionInstrumentedTests.java b/testing-desktop/src/test/java/com/yubico/yubikit/testing/desktop/fido/Ctap2SessionInstrumentedTests.java similarity index 86% rename from testing-desktop/src/test/java/com/yubico/yubikit/testing/fido/Ctap2SessionInstrumentedTests.java rename to testing-desktop/src/test/java/com/yubico/yubikit/testing/desktop/fido/Ctap2SessionInstrumentedTests.java index 6138002e..060edfbe 100644 --- a/testing-desktop/src/test/java/com/yubico/yubikit/testing/fido/Ctap2SessionInstrumentedTests.java +++ b/testing-desktop/src/test/java/com/yubico/yubikit/testing/desktop/fido/Ctap2SessionInstrumentedTests.java @@ -14,13 +14,14 @@ * limitations under the License. */ -package com.yubico.yubikit.testing.fido; +package com.yubico.yubikit.testing.desktop.fido; import com.yubico.yubikit.fido.ctap.PinUvAuthProtocol; import com.yubico.yubikit.fido.ctap.PinUvAuthProtocolV1; -import com.yubico.yubikit.testing.PinUvAuthProtocolV1Test; -import com.yubico.yubikit.testing.SmokeTest; -import com.yubico.yubikit.testing.framework.FidoInstrumentedTests; +import com.yubico.yubikit.testing.desktop.PinUvAuthProtocolV1Test; +import com.yubico.yubikit.testing.desktop.SmokeTest; +import com.yubico.yubikit.testing.desktop.framework.FidoInstrumentedTests; +import com.yubico.yubikit.testing.fido.Ctap2SessionTests; import org.junit.Test; import org.junit.experimental.categories.Category; diff --git a/testing-desktop/src/test/java/com/yubico/yubikit/testing/fido/Ctap2SessionResetInstrumentedTests.java b/testing-desktop/src/test/java/com/yubico/yubikit/testing/desktop/fido/Ctap2SessionResetInstrumentedTests.java similarity index 85% rename from testing-desktop/src/test/java/com/yubico/yubikit/testing/fido/Ctap2SessionResetInstrumentedTests.java rename to testing-desktop/src/test/java/com/yubico/yubikit/testing/desktop/fido/Ctap2SessionResetInstrumentedTests.java index 544527cc..38d27148 100644 --- a/testing-desktop/src/test/java/com/yubico/yubikit/testing/fido/Ctap2SessionResetInstrumentedTests.java +++ b/testing-desktop/src/test/java/com/yubico/yubikit/testing/desktop/fido/Ctap2SessionResetInstrumentedTests.java @@ -14,13 +14,14 @@ * limitations under the License. */ -package com.yubico.yubikit.testing.fido; +package com.yubico.yubikit.testing.desktop.fido; import com.yubico.yubikit.fido.ctap.PinUvAuthProtocol; import com.yubico.yubikit.fido.ctap.PinUvAuthProtocolV1; -import com.yubico.yubikit.testing.AlwaysManualTest; -import com.yubico.yubikit.testing.PinUvAuthProtocolV1Test; -import com.yubico.yubikit.testing.framework.FidoInstrumentedTests; +import com.yubico.yubikit.testing.desktop.AlwaysManualTest; +import com.yubico.yubikit.testing.desktop.PinUvAuthProtocolV1Test; +import com.yubico.yubikit.testing.desktop.framework.FidoInstrumentedTests; +import com.yubico.yubikit.testing.fido.Ctap2SessionTests; import org.junit.Test; import org.junit.experimental.categories.Category; diff --git a/testing-desktop/src/test/java/com/yubico/yubikit/testing/fido/EnterpriseAttestationInstrumentedTests.java b/testing-desktop/src/test/java/com/yubico/yubikit/testing/desktop/fido/EnterpriseAttestationInstrumentedTests.java similarity index 89% rename from testing-desktop/src/test/java/com/yubico/yubikit/testing/fido/EnterpriseAttestationInstrumentedTests.java rename to testing-desktop/src/test/java/com/yubico/yubikit/testing/desktop/fido/EnterpriseAttestationInstrumentedTests.java index a302fc53..4a31f746 100644 --- a/testing-desktop/src/test/java/com/yubico/yubikit/testing/fido/EnterpriseAttestationInstrumentedTests.java +++ b/testing-desktop/src/test/java/com/yubico/yubikit/testing/desktop/fido/EnterpriseAttestationInstrumentedTests.java @@ -14,12 +14,13 @@ * limitations under the License. */ -package com.yubico.yubikit.testing.fido; +package com.yubico.yubikit.testing.desktop.fido; import com.yubico.yubikit.fido.ctap.PinUvAuthProtocol; import com.yubico.yubikit.fido.ctap.PinUvAuthProtocolV1; -import com.yubico.yubikit.testing.PinUvAuthProtocolV1Test; -import com.yubico.yubikit.testing.framework.FidoInstrumentedTests; +import com.yubico.yubikit.testing.desktop.PinUvAuthProtocolV1Test; +import com.yubico.yubikit.testing.desktop.framework.FidoInstrumentedTests; +import com.yubico.yubikit.testing.fido.EnterpriseAttestationTests; import org.junit.Test; import org.junit.experimental.categories.Category; diff --git a/testing-desktop/src/test/java/com/yubico/yubikit/testing/fido/FidoTests.java b/testing-desktop/src/test/java/com/yubico/yubikit/testing/desktop/fido/FidoTests.java similarity index 93% rename from testing-desktop/src/test/java/com/yubico/yubikit/testing/fido/FidoTests.java rename to testing-desktop/src/test/java/com/yubico/yubikit/testing/desktop/fido/FidoTests.java index d246b60b..8d3126a8 100644 --- a/testing-desktop/src/test/java/com/yubico/yubikit/testing/fido/FidoTests.java +++ b/testing-desktop/src/test/java/com/yubico/yubikit/testing/desktop/fido/FidoTests.java @@ -14,9 +14,9 @@ * limitations under the License. */ -package com.yubico.yubikit.testing.fido; +package com.yubico.yubikit.testing.desktop.fido; -import com.yubico.yubikit.testing.AlwaysManualTest; +import com.yubico.yubikit.testing.desktop.AlwaysManualTest; import org.junit.experimental.categories.Categories; import org.junit.runner.RunWith; diff --git a/testing-desktop/src/test/java/com/yubico/yubikit/testing/fido/UvDiscouragedInstrumentedTests.java b/testing-desktop/src/test/java/com/yubico/yubikit/testing/desktop/fido/UvDiscouragedInstrumentedTests.java similarity index 87% rename from testing-desktop/src/test/java/com/yubico/yubikit/testing/fido/UvDiscouragedInstrumentedTests.java rename to testing-desktop/src/test/java/com/yubico/yubikit/testing/desktop/fido/UvDiscouragedInstrumentedTests.java index 3dc7d58f..bdbef4f9 100644 --- a/testing-desktop/src/test/java/com/yubico/yubikit/testing/fido/UvDiscouragedInstrumentedTests.java +++ b/testing-desktop/src/test/java/com/yubico/yubikit/testing/desktop/fido/UvDiscouragedInstrumentedTests.java @@ -14,11 +14,12 @@ * limitations under the License. */ -package com.yubico.yubikit.testing.fido; +package com.yubico.yubikit.testing.desktop.fido; import com.yubico.yubikit.fido.client.PinRequiredClientError; -import com.yubico.yubikit.testing.AlwaysManualTest; -import com.yubico.yubikit.testing.framework.FidoInstrumentedTests; +import com.yubico.yubikit.testing.desktop.AlwaysManualTest; +import com.yubico.yubikit.testing.desktop.framework.FidoInstrumentedTests; +import com.yubico.yubikit.testing.fido.BasicWebAuthnClientTests; import org.junit.Test; import org.junit.experimental.categories.Category; diff --git a/testing-desktop/src/test/java/com/yubico/yubikit/testing/management/ManagementTests.java b/testing-desktop/src/test/java/com/yubico/yubikit/testing/desktop/management/ManagementTests.java similarity index 80% rename from testing-desktop/src/test/java/com/yubico/yubikit/testing/management/ManagementTests.java rename to testing-desktop/src/test/java/com/yubico/yubikit/testing/desktop/management/ManagementTests.java index 725cd7fd..0ae91297 100644 --- a/testing-desktop/src/test/java/com/yubico/yubikit/testing/management/ManagementTests.java +++ b/testing-desktop/src/test/java/com/yubico/yubikit/testing/desktop/management/ManagementTests.java @@ -14,9 +14,10 @@ * limitations under the License. */ -package com.yubico.yubikit.testing.management; +package com.yubico.yubikit.testing.desktop.management; -import com.yubico.yubikit.testing.framework.ManagementInstrumentedTests; +import com.yubico.yubikit.testing.desktop.framework.ManagementInstrumentedTests; +import com.yubico.yubikit.testing.management.ManagementDeviceTests; import org.junit.Test; diff --git a/testing-desktop/src/test/java/com/yubico/yubikit/testing/mpe/MultiProtocolResetTests.java b/testing-desktop/src/test/java/com/yubico/yubikit/testing/desktop/mpe/MultiProtocolResetTests.java similarity index 90% rename from testing-desktop/src/test/java/com/yubico/yubikit/testing/mpe/MultiProtocolResetTests.java rename to testing-desktop/src/test/java/com/yubico/yubikit/testing/desktop/mpe/MultiProtocolResetTests.java index 6c1dfd3f..cd419ab6 100644 --- a/testing-desktop/src/test/java/com/yubico/yubikit/testing/mpe/MultiProtocolResetTests.java +++ b/testing-desktop/src/test/java/com/yubico/yubikit/testing/desktop/mpe/MultiProtocolResetTests.java @@ -14,10 +14,11 @@ * limitations under the License. */ -package com.yubico.yubikit.testing.mpe; +package com.yubico.yubikit.testing.desktop.mpe; import com.yubico.yubikit.core.smartcard.scp.ScpKid; -import com.yubico.yubikit.testing.framework.MpeInstrumentedTests; +import com.yubico.yubikit.testing.desktop.framework.MpeInstrumentedTests; +import com.yubico.yubikit.testing.mpe.MultiProtocolResetDeviceTests; import org.jetbrains.annotations.Nullable; import org.junit.Test; diff --git a/testing-desktop/src/test/java/com/yubico/yubikit/testing/oath/OathTests.java b/testing-desktop/src/test/java/com/yubico/yubikit/testing/desktop/oath/OathTests.java similarity index 89% rename from testing-desktop/src/test/java/com/yubico/yubikit/testing/oath/OathTests.java rename to testing-desktop/src/test/java/com/yubico/yubikit/testing/desktop/oath/OathTests.java index 74acc71f..975422d3 100644 --- a/testing-desktop/src/test/java/com/yubico/yubikit/testing/oath/OathTests.java +++ b/testing-desktop/src/test/java/com/yubico/yubikit/testing/desktop/oath/OathTests.java @@ -14,11 +14,12 @@ * limitations under the License. */ -package com.yubico.yubikit.testing.oath; +package com.yubico.yubikit.testing.desktop.oath; import com.yubico.yubikit.core.smartcard.scp.ScpKid; -import com.yubico.yubikit.testing.SmokeTest; -import com.yubico.yubikit.testing.framework.OathInstrumentedTests; +import com.yubico.yubikit.testing.desktop.SmokeTest; +import com.yubico.yubikit.testing.desktop.framework.OathInstrumentedTests; +import com.yubico.yubikit.testing.oath.OathDeviceTests; import org.jetbrains.annotations.Nullable; import org.junit.Test; diff --git a/testing-desktop/src/test/java/com/yubico/yubikit/testing/openpgp/OpenPgpTests.java b/testing-desktop/src/test/java/com/yubico/yubikit/testing/desktop/openpgp/OpenPgpTests.java similarity index 93% rename from testing-desktop/src/test/java/com/yubico/yubikit/testing/openpgp/OpenPgpTests.java rename to testing-desktop/src/test/java/com/yubico/yubikit/testing/desktop/openpgp/OpenPgpTests.java index 13f5529d..f188b8e7 100644 --- a/testing-desktop/src/test/java/com/yubico/yubikit/testing/openpgp/OpenPgpTests.java +++ b/testing-desktop/src/test/java/com/yubico/yubikit/testing/desktop/openpgp/OpenPgpTests.java @@ -14,12 +14,13 @@ * limitations under the License. */ -package com.yubico.yubikit.testing.openpgp; +package com.yubico.yubikit.testing.desktop.openpgp; import com.yubico.yubikit.core.smartcard.scp.ScpKid; -import com.yubico.yubikit.testing.SlowTest; -import com.yubico.yubikit.testing.SmokeTest; -import com.yubico.yubikit.testing.framework.OpenPgpInstrumentedTests; +import com.yubico.yubikit.testing.desktop.SlowTest; +import com.yubico.yubikit.testing.desktop.SmokeTest; +import com.yubico.yubikit.testing.desktop.framework.OpenPgpInstrumentedTests; +import com.yubico.yubikit.testing.openpgp.OpenPgpDeviceTests; import org.jetbrains.annotations.Nullable; import org.junit.Test; diff --git a/testing-desktop/src/test/java/com/yubico/yubikit/testing/piv/PivBioMultiProtocolTests.java b/testing-desktop/src/test/java/com/yubico/yubikit/testing/desktop/piv/PivBioMultiProtocolTests.java similarity index 81% rename from testing-desktop/src/test/java/com/yubico/yubikit/testing/piv/PivBioMultiProtocolTests.java rename to testing-desktop/src/test/java/com/yubico/yubikit/testing/desktop/piv/PivBioMultiProtocolTests.java index 27ac20d2..95226b19 100644 --- a/testing-desktop/src/test/java/com/yubico/yubikit/testing/piv/PivBioMultiProtocolTests.java +++ b/testing-desktop/src/test/java/com/yubico/yubikit/testing/desktop/piv/PivBioMultiProtocolTests.java @@ -14,9 +14,10 @@ * limitations under the License. */ -package com.yubico.yubikit.testing.piv; +package com.yubico.yubikit.testing.desktop.piv; -import com.yubico.yubikit.testing.framework.PivInstrumentedTests; +import com.yubico.yubikit.testing.desktop.framework.PivInstrumentedTests; +import com.yubico.yubikit.testing.piv.PivBioMultiProtocolDeviceTests; import org.junit.Test; diff --git a/testing-desktop/src/test/java/com/yubico/yubikit/testing/piv/PivJcaProviderTests.java b/testing-desktop/src/test/java/com/yubico/yubikit/testing/desktop/piv/PivJcaProviderTests.java similarity index 82% rename from testing-desktop/src/test/java/com/yubico/yubikit/testing/piv/PivJcaProviderTests.java rename to testing-desktop/src/test/java/com/yubico/yubikit/testing/desktop/piv/PivJcaProviderTests.java index 662fdce2..45949cf1 100644 --- a/testing-desktop/src/test/java/com/yubico/yubikit/testing/piv/PivJcaProviderTests.java +++ b/testing-desktop/src/test/java/com/yubico/yubikit/testing/desktop/piv/PivJcaProviderTests.java @@ -14,12 +14,16 @@ * limitations under the License. */ -package com.yubico.yubikit.testing.piv; +package com.yubico.yubikit.testing.desktop.piv; import com.yubico.yubikit.core.smartcard.scp.ScpKid; -import com.yubico.yubikit.testing.SlowTest; -import com.yubico.yubikit.testing.SmokeTest; -import com.yubico.yubikit.testing.framework.PivInstrumentedTests; +import com.yubico.yubikit.testing.desktop.SlowTest; +import com.yubico.yubikit.testing.desktop.SmokeTest; +import com.yubico.yubikit.testing.desktop.framework.PivInstrumentedTests; +import com.yubico.yubikit.testing.piv.PivJcaDecryptTests; +import com.yubico.yubikit.testing.piv.PivJcaDeviceTests; +import com.yubico.yubikit.testing.piv.PivJcaSigningTests; +import com.yubico.yubikit.testing.piv.PivMoveKeyTests; import org.jetbrains.annotations.Nullable; import org.junit.Test; diff --git a/testing-desktop/src/test/java/com/yubico/yubikit/testing/piv/PivTests.java b/testing-desktop/src/test/java/com/yubico/yubikit/testing/desktop/piv/PivTests.java similarity index 87% rename from testing-desktop/src/test/java/com/yubico/yubikit/testing/piv/PivTests.java rename to testing-desktop/src/test/java/com/yubico/yubikit/testing/desktop/piv/PivTests.java index 5fdff96a..cdfadc5b 100644 --- a/testing-desktop/src/test/java/com/yubico/yubikit/testing/piv/PivTests.java +++ b/testing-desktop/src/test/java/com/yubico/yubikit/testing/desktop/piv/PivTests.java @@ -14,11 +14,14 @@ * limitations under the License. */ -package com.yubico.yubikit.testing.piv; +package com.yubico.yubikit.testing.desktop.piv; import com.yubico.yubikit.core.smartcard.scp.ScpKid; -import com.yubico.yubikit.testing.SmokeTest; -import com.yubico.yubikit.testing.framework.PivInstrumentedTests; +import com.yubico.yubikit.testing.desktop.SmokeTest; +import com.yubico.yubikit.testing.desktop.framework.PivInstrumentedTests; +import com.yubico.yubikit.testing.piv.PivCertificateTests; +import com.yubico.yubikit.testing.piv.PivDeviceTests; +import com.yubico.yubikit.testing.piv.PivPinComplexityDeviceTests; import org.jetbrains.annotations.Nullable; import org.junit.Test; diff --git a/testing-desktop/src/test/java/com/yubico/yubikit/testing/sd/Scp03Tests.java b/testing-desktop/src/test/java/com/yubico/yubikit/testing/desktop/sd/Scp03Tests.java similarity index 85% rename from testing-desktop/src/test/java/com/yubico/yubikit/testing/sd/Scp03Tests.java rename to testing-desktop/src/test/java/com/yubico/yubikit/testing/desktop/sd/Scp03Tests.java index 42515ec8..8e89a8c9 100644 --- a/testing-desktop/src/test/java/com/yubico/yubikit/testing/sd/Scp03Tests.java +++ b/testing-desktop/src/test/java/com/yubico/yubikit/testing/desktop/sd/Scp03Tests.java @@ -14,10 +14,11 @@ * limitations under the License. */ -package com.yubico.yubikit.testing.sd; +package com.yubico.yubikit.testing.desktop.sd; -import com.yubico.yubikit.testing.SmokeTest; -import com.yubico.yubikit.testing.framework.SecurityDomainInstrumentedTests; +import com.yubico.yubikit.testing.desktop.SmokeTest; +import com.yubico.yubikit.testing.desktop.framework.SecurityDomainInstrumentedTests; +import com.yubico.yubikit.testing.sd.Scp03DeviceTests; import org.junit.Before; import org.junit.Test; diff --git a/testing-desktop/src/test/java/com/yubico/yubikit/testing/sd/Scp11Tests.java b/testing-desktop/src/test/java/com/yubico/yubikit/testing/desktop/sd/Scp11Tests.java similarity index 90% rename from testing-desktop/src/test/java/com/yubico/yubikit/testing/sd/Scp11Tests.java rename to testing-desktop/src/test/java/com/yubico/yubikit/testing/desktop/sd/Scp11Tests.java index dc368681..f0de181f 100644 --- a/testing-desktop/src/test/java/com/yubico/yubikit/testing/sd/Scp11Tests.java +++ b/testing-desktop/src/test/java/com/yubico/yubikit/testing/desktop/sd/Scp11Tests.java @@ -14,9 +14,10 @@ * limitations under the License. */ -package com.yubico.yubikit.testing.sd; +package com.yubico.yubikit.testing.desktop.sd; -import com.yubico.yubikit.testing.framework.SecurityDomainInstrumentedTests; +import com.yubico.yubikit.testing.desktop.framework.SecurityDomainInstrumentedTests; +import com.yubico.yubikit.testing.sd.Scp11DeviceTests; import org.junit.Before; import org.junit.Test; diff --git a/testing-desktop/src/test/java/com/yubico/yubikit/testing/sd/SecurityDomainTests.java b/testing-desktop/src/test/java/com/yubico/yubikit/testing/desktop/sd/SecurityDomainTests.java similarity index 94% rename from testing-desktop/src/test/java/com/yubico/yubikit/testing/sd/SecurityDomainTests.java rename to testing-desktop/src/test/java/com/yubico/yubikit/testing/desktop/sd/SecurityDomainTests.java index 4fbbc10f..8886583d 100644 --- a/testing-desktop/src/test/java/com/yubico/yubikit/testing/sd/SecurityDomainTests.java +++ b/testing-desktop/src/test/java/com/yubico/yubikit/testing/desktop/sd/SecurityDomainTests.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.yubico.yubikit.testing.sd; +package com.yubico.yubikit.testing.desktop.sd; import org.junit.runner.RunWith; import org.junit.runners.Suite; From 7bc2730319dd1a321f7369f25598e126480e03a5 Mon Sep 17 00:00:00 2001 From: Adam Velebil Date: Fri, 13 Dec 2024 16:17:40 +0100 Subject: [PATCH 13/24] fix openConnection --- .../yubico/yubikit/desktop/UsbPidGroup.java | 36 +++++++++---------- .../desktop/hid/HidFidoConnection.java | 18 +++++++--- .../yubikit/desktop/hid/HidManager.java | 28 +++++++-------- .../yubikit/desktop/hid/HidOtpConnection.java | 16 ++++++--- .../desktop/pcsc/PcscSmartCardConnection.java | 3 +- .../src/test/resources/logback-test.xml | 2 +- .../com/yubico/yubikit/testing/TestState.java | 5 +-- 7 files changed, 59 insertions(+), 49 deletions(-) diff --git a/desktop/src/main/java/com/yubico/yubikit/desktop/UsbPidGroup.java b/desktop/src/main/java/com/yubico/yubikit/desktop/UsbPidGroup.java index 239b1110..5d22d665 100755 --- a/desktop/src/main/java/com/yubico/yubikit/desktop/UsbPidGroup.java +++ b/desktop/src/main/java/com/yubico/yubikit/desktop/UsbPidGroup.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 Yubico. + * Copyright (C) 2022,2024 Yubico. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,6 +16,7 @@ package com.yubico.yubikit.desktop; +import com.yubico.yubikit.core.Transport; import com.yubico.yubikit.core.UsbInterface; import com.yubico.yubikit.core.UsbPid; import com.yubico.yubikit.core.YubiKeyConnection; @@ -37,6 +38,7 @@ public class UsbPidGroup { final UsbPid pid; + private final Map infos = new HashMap<>(); private final Map> resolved = new HashMap<>(); private final Map> unresolved = new HashMap<>(); @@ -51,20 +53,15 @@ public class UsbPidGroup { } private String buildKey(DeviceInfo info) { - // TODO - /* - return ( - info.serial, - info.version, - info.form_factor, - str(info.supported_capabilities), - info.config.get_bytes(False), - info.is_locked, - info.is_fips, - info.is_sky, - ) - */ - return "" + info.getSerialNumber() + info.getVersion() + info.getFormFactor(); + return "" + + info.getSerialNumber() + + info.getVersion() + + info.getFormFactor() + + info.getSupportedCapabilities(Transport.USB) + + info.getConfig() + + info.isLocked() + + info.isFips() + + info.isSky(); } int getUsbInterface(Class connectionType) { @@ -128,7 +125,8 @@ T openConnection(String key, Class connectionTy while (!devices.isEmpty()) { device = devices.remove(0); Logger.debug(logger, "Candidate: {}", device); - try (T connection = device.openConnection(connectionType)) { + try { + T connection = device.openConnection(connectionType); DeviceInfo info = DeviceUtil.readInfo(connection, pid); String deviceKey = buildKey(info); if (infos.containsKey(deviceKey)) { @@ -137,14 +135,12 @@ T openConnection(String key, Class connectionTy } resolved.get(deviceKey).put(usbInterface, device); if (deviceKey.equals(key)) { - return device.openConnection(connectionType); + return connection; } else if (pid.type == YubiKeyType.NEO && devices.isEmpty()) { Logger.debug(logger, "Resolved last NEO device without serial"); - return device.openConnection(connectionType); + return connection; } } - - return connection; } catch (IOException e) { Logger.error(logger, "Failed opening candidate device: ", e); failed.add(device); diff --git a/desktop/src/main/java/com/yubico/yubikit/desktop/hid/HidFidoConnection.java b/desktop/src/main/java/com/yubico/yubikit/desktop/hid/HidFidoConnection.java index bb4d440f..5ba258ee 100755 --- a/desktop/src/main/java/com/yubico/yubikit/desktop/hid/HidFidoConnection.java +++ b/desktop/src/main/java/com/yubico/yubikit/desktop/hid/HidFidoConnection.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2020-2022 Yubico. + * Copyright (C) 2020-2022,2024 Yubico. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,8 +16,10 @@ package com.yubico.yubikit.desktop.hid; import com.yubico.yubikit.core.fido.FidoConnection; +import com.yubico.yubikit.core.internal.Logger; import org.hid4java.HidDevice; +import org.slf4j.LoggerFactory; import java.io.IOException; @@ -26,16 +28,24 @@ public class HidFidoConnection implements FidoConnection { private final HidDevice hidDevice; + private final org.slf4j.Logger logger = LoggerFactory.getLogger(HidFidoConnection.class); + public HidFidoConnection(HidDevice hidDevice) throws IOException { - if (hidDevice.isOpen()) { + Logger.debug(logger, "Opening HID FIDO connection"); + + if (!hidDevice.isClosed()) { throw new IOException("Device already open"); } - hidDevice.open(); + + if (!hidDevice.open()) { + throw new IOException("Failure opening device"); + } this.hidDevice = hidDevice; } @Override public void close() { + Logger.debug(logger, "Closing HID FIDO connection"); hidDevice.close(); } @@ -44,7 +54,7 @@ public void send(byte[] packet) throws IOException { int sent = hidDevice.write(packet, packet.length, (byte) 0); if (sent < 0) { throw new IOException(hidDevice.getLastErrorMessage()); - } else if (sent != PACKET_SIZE) { + } else if (sent != PACKET_SIZE + 1) { throw new IOException("Unexpected amount of data sent: " + sent); } } diff --git a/desktop/src/main/java/com/yubico/yubikit/desktop/hid/HidManager.java b/desktop/src/main/java/com/yubico/yubikit/desktop/hid/HidManager.java index 6826daee..db0e6cc9 100755 --- a/desktop/src/main/java/com/yubico/yubikit/desktop/hid/HidManager.java +++ b/desktop/src/main/java/com/yubico/yubikit/desktop/hid/HidManager.java @@ -26,8 +26,15 @@ import java.util.ArrayList; import java.util.List; +import javax.annotation.Nullable; + public class HidManager { + private static final int YUBICO_VENDOR_ID = 0x1050; + private static final int HID_USAGE_PAGE_OTP = 0x0001; + private static final int HID_USAGE_PAGE_FIDO = 0xf1d0; + + private final HidServices services; private final org.slf4j.Logger logger = LoggerFactory.getLogger(HidManager.class); @@ -36,10 +43,11 @@ public HidManager() { services = org.hid4java.HidManager.getHidServices(); } - public List getDevices() { + public List getHidDevices(int vendorId, @Nullable Integer usagePage) { List yubikeys = new ArrayList<>(); for (org.hid4java.HidDevice device: services.getAttachedHidDevices()) { - if(device.getProductId() == 0x1050) { + if(device.getProductId() == vendorId && + (usagePage != null && (device.getUsagePage() & 0xffff) == usagePage)) { yubikeys.add(new HidDevice(device)); } } @@ -47,23 +55,11 @@ public List getDevices() { } public List getOtpDevices() { - List yubikeys = new ArrayList<>(); - for (org.hid4java.HidDevice device: services.getAttachedHidDevices()) { - if(device.getVendorId() == 0x1050 && (device.getUsagePage() & 0xffff) == 1) { - yubikeys.add(new HidDevice(device)); - } - } - return yubikeys; + return getHidDevices(YUBICO_VENDOR_ID, HID_USAGE_PAGE_OTP); } public List getFidoDevices() { - List yubikeys = new ArrayList<>(); - for (org.hid4java.HidDevice device: services.getAttachedHidDevices()) { - if(device.getVendorId() == 0x1050 && (device.getUsagePage() & 0xffff) == 0xf1d0) { - yubikeys.add(new HidDevice(device)); - } - } - return yubikeys; + return getHidDevices(YUBICO_VENDOR_ID, HID_USAGE_PAGE_FIDO); } public void setListener(HidSessionListener listener) { diff --git a/desktop/src/main/java/com/yubico/yubikit/desktop/hid/HidOtpConnection.java b/desktop/src/main/java/com/yubico/yubikit/desktop/hid/HidOtpConnection.java index 5a8945a8..b75bb764 100755 --- a/desktop/src/main/java/com/yubico/yubikit/desktop/hid/HidOtpConnection.java +++ b/desktop/src/main/java/com/yubico/yubikit/desktop/hid/HidOtpConnection.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 Yubico. + * Copyright (C) 2022,2024 Yubico. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -28,16 +28,21 @@ public class HidOtpConnection implements OtpConnection { private final HidDevice hidDevice; private final byte interfaceId; + private final static org.slf4j.Logger logger = LoggerFactory.getLogger(HidOtpConnection.class); HidOtpConnection(HidDevice hidDevice, byte interfaceId) throws IOException { - org.slf4j.Logger logger = LoggerFactory.getLogger(HidOtpConnection.class); - if (hidDevice.isOpen()) { + Logger.debug(logger, "Opening HID OTP connection"); + + if (!hidDevice.isClosed()) { throw new IOException("Device already open"); } - hidDevice.open(); + + if (!hidDevice.open()) { + throw new IOException("Failure opening device"); + } + this.interfaceId = interfaceId; this.hidDevice = hidDevice; - Logger.debug(logger, "usb connection opened"); } @Override @@ -66,6 +71,7 @@ public void send(byte[] report) throws IOException { @Override public void close() { + Logger.debug(logger, "Closing HID OTP connection"); hidDevice.close(); } } diff --git a/desktop/src/main/java/com/yubico/yubikit/desktop/pcsc/PcscSmartCardConnection.java b/desktop/src/main/java/com/yubico/yubikit/desktop/pcsc/PcscSmartCardConnection.java index a37494e6..b52b2228 100755 --- a/desktop/src/main/java/com/yubico/yubikit/desktop/pcsc/PcscSmartCardConnection.java +++ b/desktop/src/main/java/com/yubico/yubikit/desktop/pcsc/PcscSmartCardConnection.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 Yubico. + * Copyright (C) 2022,2024 Yubico. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -43,6 +43,7 @@ public PcscSmartCardConnection(Card card) throws IOException { this.transport = (card.getATR() .getBytes()[1] & 0xf0) == 0xf0 ? Transport.USB : Transport.NFC; try { + Logger.debug(logger, "Opening CCID connection"); card.beginExclusive(); this.cardChannel = card.getBasicChannel(); } catch (CardException e) { diff --git a/testing-desktop/src/test/resources/logback-test.xml b/testing-desktop/src/test/resources/logback-test.xml index 62edd79f..aaf7e4d7 100644 --- a/testing-desktop/src/test/resources/logback-test.xml +++ b/testing-desktop/src/test/resources/logback-test.xml @@ -25,7 +25,7 @@ - + \ No newline at end of file diff --git a/testing/src/main/java/com/yubico/yubikit/testing/TestState.java b/testing/src/main/java/com/yubico/yubikit/testing/TestState.java index 53a4843d..83a35806 100644 --- a/testing/src/main/java/com/yubico/yubikit/testing/TestState.java +++ b/testing/src/main/java/com/yubico/yubikit/testing/TestState.java @@ -162,10 +162,11 @@ protected YubiKeyConnection openConnection() throws IOException { // common utils public DeviceInfo getDeviceInfo() { - DeviceInfo deviceInfo = null; + DeviceInfo deviceInfo; try (YubiKeyConnection connection = openConnection()) { deviceInfo = DeviceUtil.readInfo(connection, usbPid); - } catch (IOException | UnsupportedOperationException ignoredException) { + } catch (IOException | UnsupportedOperationException exception) { + throw new RuntimeException("Failed to read info", exception); } return deviceInfo; From bad52f3a56f87ed16bf1318635e660726ab34aab Mon Sep 17 00:00:00 2001 From: Adam Velebil Date: Mon, 16 Dec 2024 09:36:25 +0100 Subject: [PATCH 14/24] desktop integrationTest --- testing-desktop/build.gradle | 33 ++++++++++++++++--- .../yubikit/testing/desktop/DeviceTests.java | 0 .../testing/desktop/FastDeviceTests.java | 0 .../testing/desktop/SmokeDeviceTests.java | 0 .../BasicWebAuthnClientInstrumentedTests.java | 0 .../Ctap2BioEnrollmentInstrumentedTests.java | 0 .../fido/Ctap2ClientPinInstrumentedTests.java | 0 .../fido/Ctap2ConfigInstrumentedTests.java | 0 ...CredentialManagementInstrumentedTests.java | 0 .../fido/Ctap2SessionInstrumentedTests.java | 0 .../Ctap2SessionResetInstrumentedTests.java | 0 ...nterpriseAttestationInstrumentedTests.java | 0 .../testing/desktop/fido/FidoTests.java | 0 .../fido/UvDiscouragedInstrumentedTests.java | 0 .../desktop/management/ManagementTests.java | 0 .../desktop/mpe/MultiProtocolResetTests.java | 0 .../testing/desktop/oath/OathTests.java | 0 .../testing/desktop/openpgp/OpenPgpTests.java | 0 .../desktop/piv/PivBioMultiProtocolTests.java | 0 .../desktop/piv/PivJcaProviderTests.java | 0 .../yubikit/testing/desktop/piv/PivTests.java | 0 .../testing/desktop/sd/Scp03Tests.java | 0 .../testing/desktop/sd/Scp11Tests.java | 0 .../desktop/sd/SecurityDomainTests.java | 0 .../resources/logback-test.xml | 0 25 files changed, 29 insertions(+), 4 deletions(-) rename testing-desktop/src/{test => integrationTest}/java/com/yubico/yubikit/testing/desktop/DeviceTests.java (100%) rename testing-desktop/src/{test => integrationTest}/java/com/yubico/yubikit/testing/desktop/FastDeviceTests.java (100%) rename testing-desktop/src/{test => integrationTest}/java/com/yubico/yubikit/testing/desktop/SmokeDeviceTests.java (100%) rename testing-desktop/src/{test => integrationTest}/java/com/yubico/yubikit/testing/desktop/fido/BasicWebAuthnClientInstrumentedTests.java (100%) rename testing-desktop/src/{test => integrationTest}/java/com/yubico/yubikit/testing/desktop/fido/Ctap2BioEnrollmentInstrumentedTests.java (100%) rename testing-desktop/src/{test => integrationTest}/java/com/yubico/yubikit/testing/desktop/fido/Ctap2ClientPinInstrumentedTests.java (100%) rename testing-desktop/src/{test => integrationTest}/java/com/yubico/yubikit/testing/desktop/fido/Ctap2ConfigInstrumentedTests.java (100%) rename testing-desktop/src/{test => integrationTest}/java/com/yubico/yubikit/testing/desktop/fido/Ctap2CredentialManagementInstrumentedTests.java (100%) rename testing-desktop/src/{test => integrationTest}/java/com/yubico/yubikit/testing/desktop/fido/Ctap2SessionInstrumentedTests.java (100%) rename testing-desktop/src/{test => integrationTest}/java/com/yubico/yubikit/testing/desktop/fido/Ctap2SessionResetInstrumentedTests.java (100%) rename testing-desktop/src/{test => integrationTest}/java/com/yubico/yubikit/testing/desktop/fido/EnterpriseAttestationInstrumentedTests.java (100%) rename testing-desktop/src/{test => integrationTest}/java/com/yubico/yubikit/testing/desktop/fido/FidoTests.java (100%) rename testing-desktop/src/{test => integrationTest}/java/com/yubico/yubikit/testing/desktop/fido/UvDiscouragedInstrumentedTests.java (100%) rename testing-desktop/src/{test => integrationTest}/java/com/yubico/yubikit/testing/desktop/management/ManagementTests.java (100%) rename testing-desktop/src/{test => integrationTest}/java/com/yubico/yubikit/testing/desktop/mpe/MultiProtocolResetTests.java (100%) rename testing-desktop/src/{test => integrationTest}/java/com/yubico/yubikit/testing/desktop/oath/OathTests.java (100%) rename testing-desktop/src/{test => integrationTest}/java/com/yubico/yubikit/testing/desktop/openpgp/OpenPgpTests.java (100%) rename testing-desktop/src/{test => integrationTest}/java/com/yubico/yubikit/testing/desktop/piv/PivBioMultiProtocolTests.java (100%) rename testing-desktop/src/{test => integrationTest}/java/com/yubico/yubikit/testing/desktop/piv/PivJcaProviderTests.java (100%) rename testing-desktop/src/{test => integrationTest}/java/com/yubico/yubikit/testing/desktop/piv/PivTests.java (100%) rename testing-desktop/src/{test => integrationTest}/java/com/yubico/yubikit/testing/desktop/sd/Scp03Tests.java (100%) rename testing-desktop/src/{test => integrationTest}/java/com/yubico/yubikit/testing/desktop/sd/Scp11Tests.java (100%) rename testing-desktop/src/{test => integrationTest}/java/com/yubico/yubikit/testing/desktop/sd/SecurityDomainTests.java (100%) rename testing-desktop/src/{test => integrationTest}/resources/logback-test.xml (100%) diff --git a/testing-desktop/build.gradle b/testing-desktop/build.gradle index 6115822d..8d54d19e 100755 --- a/testing-desktop/build.gradle +++ b/testing-desktop/build.gradle @@ -6,6 +6,18 @@ repositories { mavenCentral() } +sourceSets { + integrationTest { + compileClasspath += sourceSets.main.output + runtimeClasspath += sourceSets.main.output + } +} + +configurations { + integrationTestImplementation.extendsFrom implementation + integrationTestRuntimeOnly.extendsFrom runtimeOnly +} + dependencies { implementation 'org.jetbrains:annotations:23.0.0' @@ -13,12 +25,12 @@ dependencies { implementation project(':piv') implementation project(':testing') - testImplementation 'junit:junit:4.13.2' - testImplementation 'ch.qos.logback:logback-classic:1.5.12' + integrationTestImplementation 'junit:junit:4.13.2' + integrationTestImplementation 'ch.qos.logback:logback-classic:1.5.12' implementation 'org.bouncycastle:bcpkix-jdk15to18:1.78.1' - testRuntimeOnly('org.junit.vintage:junit-vintage-engine:5.9.0') + integrationTestRuntimeOnly('org.junit.vintage:junit-vintage-engine:5.9.0') } java { @@ -26,8 +38,21 @@ java { targetCompatibility = JavaVersion.VERSION_1_8 } -test { +tasks.register('integrationTest', Test) { + description = 'Runs integration tests.' + group = 'verification' + + testClassesDirs = sourceSets.integrationTest.output.classesDirs + classpath = sourceSets.integrationTest.runtimeClasspath + shouldRunAfter test + useJUnitPlatform() + +// testLogging { +// events "passed" +// } } + + description = "This module contains instrumented test framework and tests for yubikit-desktop." diff --git a/testing-desktop/src/test/java/com/yubico/yubikit/testing/desktop/DeviceTests.java b/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/DeviceTests.java similarity index 100% rename from testing-desktop/src/test/java/com/yubico/yubikit/testing/desktop/DeviceTests.java rename to testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/DeviceTests.java diff --git a/testing-desktop/src/test/java/com/yubico/yubikit/testing/desktop/FastDeviceTests.java b/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/FastDeviceTests.java similarity index 100% rename from testing-desktop/src/test/java/com/yubico/yubikit/testing/desktop/FastDeviceTests.java rename to testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/FastDeviceTests.java diff --git a/testing-desktop/src/test/java/com/yubico/yubikit/testing/desktop/SmokeDeviceTests.java b/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/SmokeDeviceTests.java similarity index 100% rename from testing-desktop/src/test/java/com/yubico/yubikit/testing/desktop/SmokeDeviceTests.java rename to testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/SmokeDeviceTests.java diff --git a/testing-desktop/src/test/java/com/yubico/yubikit/testing/desktop/fido/BasicWebAuthnClientInstrumentedTests.java b/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/fido/BasicWebAuthnClientInstrumentedTests.java similarity index 100% rename from testing-desktop/src/test/java/com/yubico/yubikit/testing/desktop/fido/BasicWebAuthnClientInstrumentedTests.java rename to testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/fido/BasicWebAuthnClientInstrumentedTests.java diff --git a/testing-desktop/src/test/java/com/yubico/yubikit/testing/desktop/fido/Ctap2BioEnrollmentInstrumentedTests.java b/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/fido/Ctap2BioEnrollmentInstrumentedTests.java similarity index 100% rename from testing-desktop/src/test/java/com/yubico/yubikit/testing/desktop/fido/Ctap2BioEnrollmentInstrumentedTests.java rename to testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/fido/Ctap2BioEnrollmentInstrumentedTests.java diff --git a/testing-desktop/src/test/java/com/yubico/yubikit/testing/desktop/fido/Ctap2ClientPinInstrumentedTests.java b/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/fido/Ctap2ClientPinInstrumentedTests.java similarity index 100% rename from testing-desktop/src/test/java/com/yubico/yubikit/testing/desktop/fido/Ctap2ClientPinInstrumentedTests.java rename to testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/fido/Ctap2ClientPinInstrumentedTests.java diff --git a/testing-desktop/src/test/java/com/yubico/yubikit/testing/desktop/fido/Ctap2ConfigInstrumentedTests.java b/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/fido/Ctap2ConfigInstrumentedTests.java similarity index 100% rename from testing-desktop/src/test/java/com/yubico/yubikit/testing/desktop/fido/Ctap2ConfigInstrumentedTests.java rename to testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/fido/Ctap2ConfigInstrumentedTests.java diff --git a/testing-desktop/src/test/java/com/yubico/yubikit/testing/desktop/fido/Ctap2CredentialManagementInstrumentedTests.java b/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/fido/Ctap2CredentialManagementInstrumentedTests.java similarity index 100% rename from testing-desktop/src/test/java/com/yubico/yubikit/testing/desktop/fido/Ctap2CredentialManagementInstrumentedTests.java rename to testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/fido/Ctap2CredentialManagementInstrumentedTests.java diff --git a/testing-desktop/src/test/java/com/yubico/yubikit/testing/desktop/fido/Ctap2SessionInstrumentedTests.java b/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/fido/Ctap2SessionInstrumentedTests.java similarity index 100% rename from testing-desktop/src/test/java/com/yubico/yubikit/testing/desktop/fido/Ctap2SessionInstrumentedTests.java rename to testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/fido/Ctap2SessionInstrumentedTests.java diff --git a/testing-desktop/src/test/java/com/yubico/yubikit/testing/desktop/fido/Ctap2SessionResetInstrumentedTests.java b/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/fido/Ctap2SessionResetInstrumentedTests.java similarity index 100% rename from testing-desktop/src/test/java/com/yubico/yubikit/testing/desktop/fido/Ctap2SessionResetInstrumentedTests.java rename to testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/fido/Ctap2SessionResetInstrumentedTests.java diff --git a/testing-desktop/src/test/java/com/yubico/yubikit/testing/desktop/fido/EnterpriseAttestationInstrumentedTests.java b/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/fido/EnterpriseAttestationInstrumentedTests.java similarity index 100% rename from testing-desktop/src/test/java/com/yubico/yubikit/testing/desktop/fido/EnterpriseAttestationInstrumentedTests.java rename to testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/fido/EnterpriseAttestationInstrumentedTests.java diff --git a/testing-desktop/src/test/java/com/yubico/yubikit/testing/desktop/fido/FidoTests.java b/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/fido/FidoTests.java similarity index 100% rename from testing-desktop/src/test/java/com/yubico/yubikit/testing/desktop/fido/FidoTests.java rename to testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/fido/FidoTests.java diff --git a/testing-desktop/src/test/java/com/yubico/yubikit/testing/desktop/fido/UvDiscouragedInstrumentedTests.java b/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/fido/UvDiscouragedInstrumentedTests.java similarity index 100% rename from testing-desktop/src/test/java/com/yubico/yubikit/testing/desktop/fido/UvDiscouragedInstrumentedTests.java rename to testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/fido/UvDiscouragedInstrumentedTests.java diff --git a/testing-desktop/src/test/java/com/yubico/yubikit/testing/desktop/management/ManagementTests.java b/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/management/ManagementTests.java similarity index 100% rename from testing-desktop/src/test/java/com/yubico/yubikit/testing/desktop/management/ManagementTests.java rename to testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/management/ManagementTests.java diff --git a/testing-desktop/src/test/java/com/yubico/yubikit/testing/desktop/mpe/MultiProtocolResetTests.java b/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/mpe/MultiProtocolResetTests.java similarity index 100% rename from testing-desktop/src/test/java/com/yubico/yubikit/testing/desktop/mpe/MultiProtocolResetTests.java rename to testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/mpe/MultiProtocolResetTests.java diff --git a/testing-desktop/src/test/java/com/yubico/yubikit/testing/desktop/oath/OathTests.java b/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/oath/OathTests.java similarity index 100% rename from testing-desktop/src/test/java/com/yubico/yubikit/testing/desktop/oath/OathTests.java rename to testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/oath/OathTests.java diff --git a/testing-desktop/src/test/java/com/yubico/yubikit/testing/desktop/openpgp/OpenPgpTests.java b/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/openpgp/OpenPgpTests.java similarity index 100% rename from testing-desktop/src/test/java/com/yubico/yubikit/testing/desktop/openpgp/OpenPgpTests.java rename to testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/openpgp/OpenPgpTests.java diff --git a/testing-desktop/src/test/java/com/yubico/yubikit/testing/desktop/piv/PivBioMultiProtocolTests.java b/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/piv/PivBioMultiProtocolTests.java similarity index 100% rename from testing-desktop/src/test/java/com/yubico/yubikit/testing/desktop/piv/PivBioMultiProtocolTests.java rename to testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/piv/PivBioMultiProtocolTests.java diff --git a/testing-desktop/src/test/java/com/yubico/yubikit/testing/desktop/piv/PivJcaProviderTests.java b/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/piv/PivJcaProviderTests.java similarity index 100% rename from testing-desktop/src/test/java/com/yubico/yubikit/testing/desktop/piv/PivJcaProviderTests.java rename to testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/piv/PivJcaProviderTests.java diff --git a/testing-desktop/src/test/java/com/yubico/yubikit/testing/desktop/piv/PivTests.java b/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/piv/PivTests.java similarity index 100% rename from testing-desktop/src/test/java/com/yubico/yubikit/testing/desktop/piv/PivTests.java rename to testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/piv/PivTests.java diff --git a/testing-desktop/src/test/java/com/yubico/yubikit/testing/desktop/sd/Scp03Tests.java b/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/sd/Scp03Tests.java similarity index 100% rename from testing-desktop/src/test/java/com/yubico/yubikit/testing/desktop/sd/Scp03Tests.java rename to testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/sd/Scp03Tests.java diff --git a/testing-desktop/src/test/java/com/yubico/yubikit/testing/desktop/sd/Scp11Tests.java b/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/sd/Scp11Tests.java similarity index 100% rename from testing-desktop/src/test/java/com/yubico/yubikit/testing/desktop/sd/Scp11Tests.java rename to testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/sd/Scp11Tests.java diff --git a/testing-desktop/src/test/java/com/yubico/yubikit/testing/desktop/sd/SecurityDomainTests.java b/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/sd/SecurityDomainTests.java similarity index 100% rename from testing-desktop/src/test/java/com/yubico/yubikit/testing/desktop/sd/SecurityDomainTests.java rename to testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/sd/SecurityDomainTests.java diff --git a/testing-desktop/src/test/resources/logback-test.xml b/testing-desktop/src/integrationTest/resources/logback-test.xml similarity index 100% rename from testing-desktop/src/test/resources/logback-test.xml rename to testing-desktop/src/integrationTest/resources/logback-test.xml From f5c19ebd945515ce5101e2132019f94a7a2ddfc2 Mon Sep 17 00:00:00 2001 From: Adam Velebil Date: Mon, 16 Dec 2024 14:50:02 +0100 Subject: [PATCH 15/24] fix HID integration tests --- .../yubikit/desktop/YubiKitManager.java | 4 +-- .../yubikit/desktop/hid/HidManager.java | 2 +- .../framework/FidoInstrumentedTests.java | 4 +-- .../framework/OathInstrumentedTests.java | 2 +- .../SecurityDomainInstrumentedTests.java | 2 +- .../framework/YKInstrumentedTests.java | 33 +++++++++++++++---- 6 files changed, 33 insertions(+), 14 deletions(-) diff --git a/desktop/src/main/java/com/yubico/yubikit/desktop/YubiKitManager.java b/desktop/src/main/java/com/yubico/yubikit/desktop/YubiKitManager.java index a25a16ef..3a21be47 100755 --- a/desktop/src/main/java/com/yubico/yubikit/desktop/YubiKitManager.java +++ b/desktop/src/main/java/com/yubico/yubikit/desktop/YubiKitManager.java @@ -60,10 +60,10 @@ List listDevices(Class public Map listAllDevices(Set> connectionTypes) { Map groups = new HashMap<>(); for (Class connectionType : connectionTypes) { - Logger.trace(logger, "Enumerate devices for {}", connectionType); + Logger.debug(logger, "Enumerate devices for {}", connectionType); for (UsbYubiKeyDevice device : listDevices(connectionType)) { UsbPid pid = device.getPid(); - Logger.trace(logger, "Found device with PID {}", pid); + Logger.debug(logger, "Found device with PID {}", pid); if (!groups.containsKey(pid)) { groups.put(pid, new UsbPidGroup(pid)); } diff --git a/desktop/src/main/java/com/yubico/yubikit/desktop/hid/HidManager.java b/desktop/src/main/java/com/yubico/yubikit/desktop/hid/HidManager.java index db0e6cc9..1ce49da6 100755 --- a/desktop/src/main/java/com/yubico/yubikit/desktop/hid/HidManager.java +++ b/desktop/src/main/java/com/yubico/yubikit/desktop/hid/HidManager.java @@ -46,7 +46,7 @@ public HidManager() { public List getHidDevices(int vendorId, @Nullable Integer usagePage) { List yubikeys = new ArrayList<>(); for (org.hid4java.HidDevice device: services.getAttachedHidDevices()) { - if(device.getProductId() == vendorId && + if(device.getVendorId() == vendorId && (usagePage != null && (device.getUsagePage() & 0xffff) == usagePage)) { yubikeys.add(new HidDevice(device)); } diff --git a/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/framework/FidoInstrumentedTests.java b/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/framework/FidoInstrumentedTests.java index 573bf14e..d37f581d 100755 --- a/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/framework/FidoInstrumentedTests.java +++ b/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/framework/FidoInstrumentedTests.java @@ -35,7 +35,7 @@ protected void withDevice(TestState.StatefulDeviceCallback callba protected void withDevice(boolean setPin, TestState.StatefulDeviceCallback callback) throws Throwable { FidoTestState state = new FidoTestState.Builder(device, usbPid, getPinUvAuthProtocol()) .scpKid(getScpKid()) - //.reconnectDeviceCallback(this::reconnectDevice) + .reconnectDeviceCallback(this::reconnectDevice) .setPin(setPin) .build(); @@ -45,7 +45,7 @@ protected void withDevice(boolean setPin, TestState.StatefulDeviceCallback callback) throws Throwable { FidoTestState state = new FidoTestState.Builder(device, usbPid, getPinUvAuthProtocol()) .scpKid(getScpKid()) - //.reconnectDeviceCallback(this::reconnectDevice) + .reconnectDeviceCallback(this::reconnectDevice) .setPin(true) .build(); diff --git a/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/framework/OathInstrumentedTests.java b/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/framework/OathInstrumentedTests.java index b40edfa2..2a9ee47a 100644 --- a/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/framework/OathInstrumentedTests.java +++ b/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/framework/OathInstrumentedTests.java @@ -25,7 +25,7 @@ public class OathInstrumentedTests extends YKInstrumentedTests { protected void withDevice(TestState.StatefulDeviceCallback callback) throws Throwable { final OathTestState state = new OathTestState.Builder(device, usbPid) .scpKid(getScpKid()) - //.reconnectDeviceCallback(this::reconnectDevice) + .reconnectDeviceCallback(this::reconnectDevice) .build(); state.withDeviceCallback(callback); diff --git a/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/framework/SecurityDomainInstrumentedTests.java b/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/framework/SecurityDomainInstrumentedTests.java index 4e212b22..b3c77238 100644 --- a/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/framework/SecurityDomainInstrumentedTests.java +++ b/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/framework/SecurityDomainInstrumentedTests.java @@ -23,7 +23,7 @@ public class SecurityDomainInstrumentedTests extends YKInstrumentedTests { protected void withState(TestState.StatefulDeviceCallback callback) throws Throwable { final SecurityDomainTestState state = new SecurityDomainTestState.Builder(device, usbPid) - //.reconnectDeviceCallback(this::reconnectDevice) + .reconnectDeviceCallback(this::reconnectDevice) .build(); state.withDeviceCallback(callback); diff --git a/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/framework/YKInstrumentedTests.java b/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/framework/YKInstrumentedTests.java index 32402253..c4e0c4de 100755 --- a/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/framework/YKInstrumentedTests.java +++ b/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/framework/YKInstrumentedTests.java @@ -41,22 +41,41 @@ public class YKInstrumentedTests { @Override protected void before() throws Throwable { - device = testDriver.awaitSession(); - if (device instanceof CompositeDevice) { - CompositeDevice compositeDevice = (CompositeDevice) device; - usbPid = compositeDevice.getPidGroup().getPid(); - } + getDevice(); } @Override protected void after() { - testDriver.returnSession(device); - device = null; + releaseDevice(); } }; + protected YubiKeyDevice reconnectDevice() { + releaseDevice(); + getDevice(); + return device; + } + @Nullable protected Byte getScpKid() { return null; } + + private void getDevice() { + try { + device = testDriver.awaitSession(); + if (device instanceof CompositeDevice) { + CompositeDevice compositeDevice = (CompositeDevice) device; + usbPid = compositeDevice.getPidGroup().getPid(); + } + } catch (InterruptedException interruptedException) { + throw new RuntimeException("awaitSession failed", interruptedException); + } + } + + private void releaseDevice() { + testDriver.returnSession(device); + device = null; + } + } From b85c476d77874f9fc3eb14740f6d43c8bdee96eb Mon Sep 17 00:00:00 2001 From: Adam Velebil Date: Tue, 14 Jan 2025 11:14:28 +0100 Subject: [PATCH 16/24] apply spotless to desktop modules --- DesktopDemo/build.gradle | 1 + .../yubikit/desktop/app/DesktopApp.java | 118 +++--- .../yubikit/desktop/app/package-info.java | 2 +- desktop/build.gradle | 4 +- .../yubikit/desktop/CompositeDevice.java | 65 ++-- .../yubikit/desktop/OperatingSystem.java | 20 +- .../yubico/yubikit/desktop/UsbPidGroup.java | 356 +++++++++--------- .../yubikit/desktop/UsbYubiKeyDevice.java | 8 +- .../yubikit/desktop/YubiKitManager.java | 85 ++--- .../yubico/yubikit/desktop/hid/HidDevice.java | 114 +++--- .../desktop/hid/HidFidoConnection.java | 70 ++-- .../yubikit/desktop/hid/HidManager.java | 109 +++--- .../yubikit/desktop/hid/HidOtpConnection.java | 76 ++-- .../desktop/hid/HidSessionListener.java | 24 +- .../yubikit/desktop/hid/package-info.java | 2 +- .../yubico/yubikit/desktop/package-info.java | 2 +- .../yubikit/desktop/pcsc/NfcPcscDevice.java | 62 ++- .../desktop/pcsc/PcscConfiguration.java | 63 ++-- .../yubikit/desktop/pcsc/PcscDevice.java | 78 ++-- .../yubikit/desktop/pcsc/PcscManager.java | 37 +- .../desktop/pcsc/PcscSessionListener.java | 24 +- .../desktop/pcsc/PcscSmartCardConnection.java | 106 +++--- .../yubikit/desktop/pcsc/UsbPcscDevice.java | 77 ++-- .../yubikit/desktop/pcsc/package-info.java | 2 +- testing-desktop/build.gradle | 1 + .../yubikit/testing/desktop/DeviceTests.java | 23 +- .../testing/desktop/FastDeviceTests.java | 16 +- .../testing/desktop/SmokeDeviceTests.java | 9 +- .../BasicWebAuthnClientInstrumentedTests.java | 85 +++-- .../Ctap2BioEnrollmentInstrumentedTests.java | 10 +- .../fido/Ctap2ClientPinInstrumentedTests.java | 35 +- .../fido/Ctap2ConfigInstrumentedTests.java | 85 +++-- ...CredentialManagementInstrumentedTests.java | 47 ++- .../fido/Ctap2SessionInstrumentedTests.java | 45 ++- .../Ctap2SessionResetInstrumentedTests.java | 38 +- ...nterpriseAttestationInstrumentedTests.java | 51 ++- .../testing/desktop/fido/FidoTests.java | 27 +- .../fido/UvDiscouragedInstrumentedTests.java | 46 ++- .../desktop/management/ManagementTests.java | 9 +- .../desktop/mpe/MultiProtocolResetTests.java | 43 ++- .../testing/desktop/oath/OathTests.java | 55 ++- .../testing/desktop/openpgp/OpenPgpTests.java | 237 ++++++------ .../desktop/piv/PivBioMultiProtocolTests.java | 9 +- .../desktop/piv/PivJcaProviderTests.java | 73 ++-- .../yubikit/testing/desktop/piv/PivTests.java | 83 ++-- .../testing/desktop/sd/Scp03Tests.java | 50 +-- .../testing/desktop/sd/Scp11Tests.java | 65 ++-- .../desktop/sd/SecurityDomainTests.java | 8 +- .../testing/desktop/AlwaysManualTest.java | 3 +- .../testing/desktop/DesktopTestDriver.java | 30 +- .../desktop/PinUvAuthProtocolV1Test.java | 3 +- .../yubikit/testing/desktop/SlowTest.java | 3 +- .../yubikit/testing/desktop/SmokeTest.java | 3 +- .../framework/FidoInstrumentedTests.java | 68 ++-- .../ManagementInstrumentedTests.java | 16 +- .../framework/MpeInstrumentedTests.java | 24 +- .../framework/OathInstrumentedTests.java | 30 +- .../framework/OpenPgpInstrumentedTests.java | 15 +- .../framework/PivInstrumentedTests.java | 21 +- .../SecurityDomainInstrumentedTests.java | 16 +- .../framework/YKInstrumentedTests.java | 68 ++-- 61 files changed, 1464 insertions(+), 1491 deletions(-) diff --git a/DesktopDemo/build.gradle b/DesktopDemo/build.gradle index 33d822e2..14a8d7a2 100755 --- a/DesktopDemo/build.gradle +++ b/DesktopDemo/build.gradle @@ -1,5 +1,6 @@ plugins { id 'application' + id 'project-convention-spotless' } dependencies { diff --git a/DesktopDemo/src/main/java/com/yubico/yubikit/desktop/app/DesktopApp.java b/DesktopDemo/src/main/java/com/yubico/yubikit/desktop/app/DesktopApp.java index 6f8a6ae9..015bec46 100755 --- a/DesktopDemo/src/main/java/com/yubico/yubikit/desktop/app/DesktopApp.java +++ b/DesktopDemo/src/main/java/com/yubico/yubikit/desktop/app/DesktopApp.java @@ -23,69 +23,75 @@ import com.yubico.yubikit.desktop.OperatingSystem; import com.yubico.yubikit.desktop.YubiKitManager; import com.yubico.yubikit.management.DeviceInfo; - -import org.slf4j.LoggerFactory; - import java.io.IOException; import java.util.Map; +import org.slf4j.LoggerFactory; public class DesktopApp { - private static final org.slf4j.Logger logger = LoggerFactory.getLogger(DesktopApp.class); + private static final org.slf4j.Logger logger = LoggerFactory.getLogger(DesktopApp.class); - public static void main(String[] argv) { - if (OperatingSystem.isMac()) { - System.setProperty("sun.security.smartcardio.library", "/System/Library/Frameworks/PCSC.framework/Versions/Current/PCSC"); - } - - System.out.println("Insert YubiKey now..."); + public static void main(String[] argv) { + if (OperatingSystem.isMac()) { + System.setProperty( + "sun.security.smartcardio.library", + "/System/Library/Frameworks/PCSC.framework/Versions/Current/PCSC"); + } - YubiKitManager manager = new YubiKitManager(); - Map devices = manager.listAllDevices(); - logger.debug("Devices: {}", devices); - for (Map.Entry entry : devices.entrySet()) { - YubiKeyDevice device = entry.getKey(); - DeviceInfo info = entry.getValue(); - logger.debug("Found key: {} {}", device, info); - if (device.supportsConnection(SmartCardConnection.class)) { - logger.debug("Request CCID connection"); - device.requestConnection(SmartCardConnection.class, value -> { - try { - logger.debug("Got CCID connection {}", value.getValue()); - } catch (IOException e) { - logger.error("Failed to get CCID: ", e); - } - }); - } - if (device.supportsConnection(OtpConnection.class)) { - logger.debug("Request OTP connection"); - device.requestConnection(OtpConnection.class, value -> { - try { - logger.debug("Got OTP connection {}", value.getValue()); - } catch (IOException e) { - logger.error("Failed to get OTP: ", e); - } - }); - } - if (device.supportsConnection(FidoConnection.class)) { - logger.debug("Request FIDO connection"); - device.requestConnection(FidoConnection.class, value -> { - try { - logger.debug("Got FIDO connection {}", value.getValue()); - } catch (IOException e) { - logger.error("Failed to get FIDO: ", e); - } - }); - } - } + System.out.println("Insert YubiKey now..."); - logger.debug("Sleeping..."); - try { - Thread.sleep(5000); - } catch (InterruptedException e) { - throw new RuntimeException(e); - } + YubiKitManager manager = new YubiKitManager(); + Map devices = manager.listAllDevices(); + logger.debug("Devices: {}", devices); + for (Map.Entry entry : devices.entrySet()) { + YubiKeyDevice device = entry.getKey(); + DeviceInfo info = entry.getValue(); + logger.debug("Found key: {} {}", device, info); + if (device.supportsConnection(SmartCardConnection.class)) { + logger.debug("Request CCID connection"); + device.requestConnection( + SmartCardConnection.class, + value -> { + try { + logger.debug("Got CCID connection {}", value.getValue()); + } catch (IOException e) { + logger.error("Failed to get CCID: ", e); + } + }); + } + if (device.supportsConnection(OtpConnection.class)) { + logger.debug("Request OTP connection"); + device.requestConnection( + OtpConnection.class, + value -> { + try { + logger.debug("Got OTP connection {}", value.getValue()); + } catch (IOException e) { + logger.error("Failed to get OTP: ", e); + } + }); + } + if (device.supportsConnection(FidoConnection.class)) { + logger.debug("Request FIDO connection"); + device.requestConnection( + FidoConnection.class, + value -> { + try { + logger.debug("Got FIDO connection {}", value.getValue()); + } catch (IOException e) { + logger.error("Failed to get FIDO: ", e); + } + }); + } + } - logger.debug("Application exited"); + logger.debug("Sleeping..."); + try { + Thread.sleep(5000); + } catch (InterruptedException e) { + throw new RuntimeException(e); } -} \ No newline at end of file + + logger.debug("Application exited"); + } +} diff --git a/DesktopDemo/src/main/java/com/yubico/yubikit/desktop/app/package-info.java b/DesktopDemo/src/main/java/com/yubico/yubikit/desktop/app/package-info.java index 78a440a9..f8058e75 100755 --- a/DesktopDemo/src/main/java/com/yubico/yubikit/desktop/app/package-info.java +++ b/DesktopDemo/src/main/java/com/yubico/yubikit/desktop/app/package-info.java @@ -1,4 +1,4 @@ @PackageNonnullByDefault package com.yubico.yubikit.desktop.app; -import com.yubico.yubikit.core.PackageNonnullByDefault; \ No newline at end of file +import com.yubico.yubikit.core.PackageNonnullByDefault; diff --git a/desktop/build.gradle b/desktop/build.gradle index 5587c758..7e9eec50 100755 --- a/desktop/build.gradle +++ b/desktop/build.gradle @@ -1,4 +1,6 @@ -apply plugin: 'yubikit-java-library' +plugins { + id 'yubikit-java-library' +} dependencies { api project(':support') diff --git a/desktop/src/main/java/com/yubico/yubikit/desktop/CompositeDevice.java b/desktop/src/main/java/com/yubico/yubikit/desktop/CompositeDevice.java index d5127b74..54c3f058 100755 --- a/desktop/src/main/java/com/yubico/yubikit/desktop/CompositeDevice.java +++ b/desktop/src/main/java/com/yubico/yubikit/desktop/CompositeDevice.java @@ -21,39 +21,40 @@ import com.yubico.yubikit.core.YubiKeyDevice; import com.yubico.yubikit.core.util.Callback; import com.yubico.yubikit.core.util.Result; - import java.io.IOException; public class CompositeDevice implements YubiKeyDevice { - private final UsbPidGroup pidGroup; - private final String key; - - CompositeDevice(UsbPidGroup pidGroup, String key) { - this.pidGroup = pidGroup; - this.key = key; - } - - @Override - public Transport getTransport() { - return Transport.USB; - } - - @Override - public boolean supportsConnection(Class connectionType) { - return pidGroup.supportsConnection(connectionType); - } - - @Override - public void requestConnection(Class connectionType, Callback> callback) { - pidGroup.requestConnection(key, connectionType, callback); - } - - @Override - public T openConnection(Class connectionType) throws IOException { - return pidGroup.openConnection(key, connectionType); - } - - public UsbPidGroup getPidGroup() { - return pidGroup; - } + private final UsbPidGroup pidGroup; + private final String key; + + CompositeDevice(UsbPidGroup pidGroup, String key) { + this.pidGroup = pidGroup; + this.key = key; + } + + @Override + public Transport getTransport() { + return Transport.USB; + } + + @Override + public boolean supportsConnection(Class connectionType) { + return pidGroup.supportsConnection(connectionType); + } + + @Override + public void requestConnection( + Class connectionType, Callback> callback) { + pidGroup.requestConnection(key, connectionType, callback); + } + + @Override + public T openConnection(Class connectionType) + throws IOException { + return pidGroup.openConnection(key, connectionType); + } + + public UsbPidGroup getPidGroup() { + return pidGroup; + } } diff --git a/desktop/src/main/java/com/yubico/yubikit/desktop/OperatingSystem.java b/desktop/src/main/java/com/yubico/yubikit/desktop/OperatingSystem.java index 67f25653..a15db6d2 100644 --- a/desktop/src/main/java/com/yubico/yubikit/desktop/OperatingSystem.java +++ b/desktop/src/main/java/com/yubico/yubikit/desktop/OperatingSystem.java @@ -17,17 +17,17 @@ package com.yubico.yubikit.desktop; public class OperatingSystem { - public static final String Name = System.getProperty("os.name"); + public static final String Name = System.getProperty("os.name"); - public static boolean isWindows() { - return Name.toLowerCase().contains("win"); - } + public static boolean isWindows() { + return Name.toLowerCase().contains("win"); + } - public static boolean isMac() { - return Name.toLowerCase().contains("mac"); - } + public static boolean isMac() { + return Name.toLowerCase().contains("mac"); + } - public static boolean isLinux() { - return Name.toLowerCase().contains("linux"); - } + public static boolean isLinux() { + return Name.toLowerCase().contains("linux"); + } } diff --git a/desktop/src/main/java/com/yubico/yubikit/desktop/UsbPidGroup.java b/desktop/src/main/java/com/yubico/yubikit/desktop/UsbPidGroup.java index 5d22d665..d679190d 100755 --- a/desktop/src/main/java/com/yubico/yubikit/desktop/UsbPidGroup.java +++ b/desktop/src/main/java/com/yubico/yubikit/desktop/UsbPidGroup.java @@ -30,202 +30,206 @@ import com.yubico.yubikit.core.util.Result; import com.yubico.yubikit.management.DeviceInfo; import com.yubico.yubikit.support.DeviceUtil; - -import org.slf4j.LoggerFactory; - import java.io.IOException; import java.util.*; +import org.slf4j.LoggerFactory; public class UsbPidGroup { - final UsbPid pid; - - private final Map infos = new HashMap<>(); - private final Map> resolved = new HashMap<>(); - private final Map> unresolved = new HashMap<>(); - private final Map devCount = new HashMap<>(); - private final Set fingerprints = new HashSet<>(); - private final long ctime = System.currentTimeMillis(); - - private final org.slf4j.Logger logger = LoggerFactory.getLogger(UsbPidGroup.class); - - UsbPidGroup(UsbPid pid) { - this.pid = pid; + final UsbPid pid; + + private final Map infos = new HashMap<>(); + private final Map> resolved = new HashMap<>(); + private final Map> unresolved = new HashMap<>(); + private final Map devCount = new HashMap<>(); + private final Set fingerprints = new HashSet<>(); + private final long ctime = System.currentTimeMillis(); + + private final org.slf4j.Logger logger = LoggerFactory.getLogger(UsbPidGroup.class); + + UsbPidGroup(UsbPid pid) { + this.pid = pid; + } + + private String buildKey(DeviceInfo info) { + return "" + + info.getSerialNumber() + + info.getVersion() + + info.getFormFactor() + + info.getSupportedCapabilities(Transport.USB) + + info.getConfig() + + info.isLocked() + + info.isFips() + + info.isSky(); + } + + int getUsbInterface(Class connectionType) { + if (SmartCardConnection.class.isAssignableFrom(connectionType)) { + return UsbInterface.CCID; } - - private String buildKey(DeviceInfo info) { - return "" + - info.getSerialNumber() + - info.getVersion() + - info.getFormFactor() + - info.getSupportedCapabilities(Transport.USB) + - info.getConfig() + - info.isLocked() + - info.isFips() + - info.isSky(); + if (OtpConnection.class.isAssignableFrom(connectionType)) { + return UsbInterface.OTP; } - - int getUsbInterface(Class connectionType) { - if (SmartCardConnection.class.isAssignableFrom(connectionType)) { - return UsbInterface.CCID; - } - if (OtpConnection.class.isAssignableFrom(connectionType)) { - return UsbInterface.OTP; - } - if (FidoConnection.class.isAssignableFrom(connectionType)) { - return UsbInterface.FIDO; - } - throw new IllegalArgumentException(); + if (FidoConnection.class.isAssignableFrom(connectionType)) { + return UsbInterface.FIDO; } - - void add(Class connectionType, UsbYubiKeyDevice device, boolean forceResolve) { - Logger.trace(logger, "Add device node {}{}", device, connectionType); - int usbInterface = getUsbInterface(connectionType); - fingerprints.add(device.getFingerprint()); - devCount.put(usbInterface, devCount.getOrDefault(usbInterface, 0) + 1); - if (forceResolve || resolved.size() < devCount.values().stream().reduce(0, Math::max)) { - try(YubiKeyConnection connection = device.openConnection(connectionType)) { - DeviceInfo info = DeviceUtil.readInfo(connection, pid); - String key = buildKey(info); - infos.put(key, info); - if (!resolved.containsKey(key)) { - resolved.put(key, new HashMap<>()); - } - resolved.get(key).put(usbInterface, device); - Integer serialNumber = info.getSerialNumber(); - Logger.trace(logger, "Resolved device {}", serialNumber != null - ? serialNumber - : "without serial number"); - return; - } catch (IOException e) { - Logger.error(logger, "Failed opening device. ", e); - } - } - if (!unresolved.containsKey(usbInterface)) { - unresolved.put(usbInterface, new ArrayList<>()); + throw new IllegalArgumentException(); + } + + void add( + Class connectionType, + UsbYubiKeyDevice device, + boolean forceResolve) { + Logger.trace(logger, "Add device node {}{}", device, connectionType); + int usbInterface = getUsbInterface(connectionType); + fingerprints.add(device.getFingerprint()); + devCount.put(usbInterface, devCount.getOrDefault(usbInterface, 0) + 1); + if (forceResolve || resolved.size() < devCount.values().stream().reduce(0, Math::max)) { + try (YubiKeyConnection connection = device.openConnection(connectionType)) { + DeviceInfo info = DeviceUtil.readInfo(connection, pid); + String key = buildKey(info); + infos.put(key, info); + if (!resolved.containsKey(key)) { + resolved.put(key, new HashMap<>()); } - unresolved.get(usbInterface).add(device); + resolved.get(key).put(usbInterface, device); + Integer serialNumber = info.getSerialNumber(); + Logger.trace( + logger, + "Resolved device {}", + serialNumber != null ? serialNumber : "without serial number"); + return; + } catch (IOException e) { + Logger.error(logger, "Failed opening device. ", e); + } } - - boolean supportsConnection(Class connectionType) { - return (getUsbInterface(connectionType) & pid.usbInterfaces) != 0; + if (!unresolved.containsKey(usbInterface)) { + unresolved.put(usbInterface, new ArrayList<>()); + } + unresolved.get(usbInterface).add(device); + } + + boolean supportsConnection(Class connectionType) { + return (getUsbInterface(connectionType) & pid.usbInterfaces) != 0; + } + + T openConnection(String key, Class connectionType) + throws IOException { + int usbInterface = getUsbInterface(connectionType); + UsbYubiKeyDevice device = resolved.get(key).get(usbInterface); + if (device != null) { + return device.openConnection(connectionType); } - T openConnection(String key, Class connectionType) throws IOException { - int usbInterface = getUsbInterface(connectionType); - UsbYubiKeyDevice device = resolved.get(key).get(usbInterface); - if (device != null) { - return device.openConnection(connectionType); - } - - Logger.debug(logger, "Resolve device for {}, {}", connectionType, key); - List devices = unresolved.getOrDefault(usbInterface, new ArrayList<>()); - Logger.debug(logger, "Unresolved: {}", devices); - List failed = new ArrayList<>(); + Logger.debug(logger, "Resolve device for {}, {}", connectionType, key); + List devices = unresolved.getOrDefault(usbInterface, new ArrayList<>()); + Logger.debug(logger, "Unresolved: {}", devices); + List failed = new ArrayList<>(); + try { + while (!devices.isEmpty()) { + device = devices.remove(0); + Logger.debug(logger, "Candidate: {}", device); try { - while (!devices.isEmpty()) { - device = devices.remove(0); - Logger.debug(logger, "Candidate: {}", device); - try { - T connection = device.openConnection(connectionType); - DeviceInfo info = DeviceUtil.readInfo(connection, pid); - String deviceKey = buildKey(info); - if (infos.containsKey(deviceKey)) { - if (!resolved.containsKey(deviceKey)) { - resolved.put(deviceKey, new HashMap<>()); - } - resolved.get(deviceKey).put(usbInterface, device); - if (deviceKey.equals(key)) { - return connection; - } else if (pid.type == YubiKeyType.NEO && devices.isEmpty()) { - Logger.debug(logger, "Resolved last NEO device without serial"); - return connection; - } - } - } catch (IOException e) { - Logger.error(logger, "Failed opening candidate device: ", e); - failed.add(device); - } + T connection = device.openConnection(connectionType); + DeviceInfo info = DeviceUtil.readInfo(connection, pid); + String deviceKey = buildKey(info); + if (infos.containsKey(deviceKey)) { + if (!resolved.containsKey(deviceKey)) { + resolved.put(deviceKey, new HashMap<>()); + } + resolved.get(deviceKey).put(usbInterface, device); + if (deviceKey.equals(key)) { + return connection; + } else if (pid.type == YubiKeyType.NEO && devices.isEmpty()) { + Logger.debug(logger, "Resolved last NEO device without serial"); + return connection; } - } finally { - devices.addAll(failed); + } + } catch (IOException e) { + Logger.error(logger, "Failed opening candidate device: ", e); + failed.add(device); } - - throw new IOException("Failed to open connection"); + } + } finally { + devices.addAll(failed); } - void requestConnection(String key, Class connectionType, Callback> callback) { - int usbInterface = getUsbInterface(connectionType); - UsbYubiKeyDevice device = resolved.get(key).get(usbInterface); - if (device != null) { - device.requestConnection(connectionType, callback); - } else { - Logger.debug(logger, "Resolve device for {}, {}", connectionType, key); - List devices = unresolved.getOrDefault(usbInterface, new ArrayList<>()); - Logger.debug(logger, "Unresolved: {}", devices); - List failed = new ArrayList<>(); - try { - while (!devices.isEmpty()) { - device = devices.remove(0); - Logger.debug(logger, "Candidate: {}", device); - try (T connection = device.openConnection(connectionType)) { - DeviceInfo info = DeviceUtil.readInfo(connection, pid); - String deviceKey = buildKey(info); - if (infos.containsKey(deviceKey)) { - if (!resolved.containsKey(deviceKey)) { - resolved.put(deviceKey, new HashMap<>()); - } - resolved.get(deviceKey).put(usbInterface, device); - if (deviceKey.equals(key)) { - device.requestConnection(connectionType, callback); - return; - } else if (pid.type == YubiKeyType.NEO && devices.isEmpty()) { - Logger.debug(logger, "Resolved last NEO device without serial"); - device.requestConnection(connectionType, callback); - return; - } - } - } catch (IOException e) { - Logger.error(logger, "Failed opening candidate device: ", e); - failed.add(device); - } - } - } finally { - devices.addAll(failed); + throw new IOException("Failed to open connection"); + } + + void requestConnection( + String key, Class connectionType, Callback> callback) { + int usbInterface = getUsbInterface(connectionType); + UsbYubiKeyDevice device = resolved.get(key).get(usbInterface); + if (device != null) { + device.requestConnection(connectionType, callback); + } else { + Logger.debug(logger, "Resolve device for {}, {}", connectionType, key); + List devices = unresolved.getOrDefault(usbInterface, new ArrayList<>()); + Logger.debug(logger, "Unresolved: {}", devices); + List failed = new ArrayList<>(); + try { + while (!devices.isEmpty()) { + device = devices.remove(0); + Logger.debug(logger, "Candidate: {}", device); + try (T connection = device.openConnection(connectionType)) { + DeviceInfo info = DeviceUtil.readInfo(connection, pid); + String deviceKey = buildKey(info); + if (infos.containsKey(deviceKey)) { + if (!resolved.containsKey(deviceKey)) { + resolved.put(deviceKey, new HashMap<>()); + } + resolved.get(deviceKey).put(usbInterface, device); + if (deviceKey.equals(key)) { + device.requestConnection(connectionType, callback); + return; + } else if (pid.type == YubiKeyType.NEO && devices.isEmpty()) { + Logger.debug(logger, "Resolved last NEO device without serial"); + device.requestConnection(connectionType, callback); + return; + } } - - //TODO - /* - if self._devcount[iface] < len(self._infos): - logger.debug(f"Checking for more devices over {iface!s}") - for dev in _CONNECTION_LIST_MAPPING[conn_type](): - if self._pid == dev.pid and dev.fingerprint not in self._fingerprints: - self.add(conn_type, dev, True) - - resolved = self._resolved[key].get(iface) - if resolved: - return resolved.open_connection(conn_type) - - # Retry if we are within a 5 second period after creation, - # as not all USB interface become usable at the exact same time. - if time() < self._ctime + 5: - logger.debug("Device not found, retry in 1s") - sleep(1.0) - return self.connect(key, conn_type) - - raise ValueError("Failed to connect to the device") - */ + } catch (IOException e) { + Logger.error(logger, "Failed opening candidate device: ", e); + failed.add(device); + } } + } finally { + devices.addAll(failed); + } + + // TODO + /* + if self._devcount[iface] < len(self._infos): + logger.debug(f"Checking for more devices over {iface!s}") + for dev in _CONNECTION_LIST_MAPPING[conn_type](): + if self._pid == dev.pid and dev.fingerprint not in self._fingerprints: + self.add(conn_type, dev, True) + + resolved = self._resolved[key].get(iface) + if resolved: + return resolved.open_connection(conn_type) + + # Retry if we are within a 5 second period after creation, + # as not all USB interface become usable at the exact same time. + if time() < self._ctime + 5: + logger.debug("Device not found, retry in 1s") + sleep(1.0) + return self.connect(key, conn_type) + + raise ValueError("Failed to connect to the device") + */ } + } - Map getDevices() { - Map devices = new LinkedHashMap<>(); - for (Map.Entry entry : infos.entrySet()) { - devices.put(new CompositeDevice(this, entry.getKey()), entry.getValue()); - } - return devices; + Map getDevices() { + Map devices = new LinkedHashMap<>(); + for (Map.Entry entry : infos.entrySet()) { + devices.put(new CompositeDevice(this, entry.getKey()), entry.getValue()); } + return devices; + } - public UsbPid getPid() { - return pid; - } + public UsbPid getPid() { + return pid; + } } diff --git a/desktop/src/main/java/com/yubico/yubikit/desktop/UsbYubiKeyDevice.java b/desktop/src/main/java/com/yubico/yubikit/desktop/UsbYubiKeyDevice.java index e0234f1d..653814a5 100755 --- a/desktop/src/main/java/com/yubico/yubikit/desktop/UsbYubiKeyDevice.java +++ b/desktop/src/main/java/com/yubico/yubikit/desktop/UsbYubiKeyDevice.java @@ -19,12 +19,12 @@ import com.yubico.yubikit.core.UsbPid; import com.yubico.yubikit.core.YubiKeyConnection; import com.yubico.yubikit.core.YubiKeyDevice; - import java.io.IOException; public interface UsbYubiKeyDevice extends YubiKeyDevice { - T openConnection(Class connectionType) throws IOException; + T openConnection(Class connectionType) throws IOException; + + String getFingerprint(); - String getFingerprint(); - UsbPid getPid(); + UsbPid getPid(); } diff --git a/desktop/src/main/java/com/yubico/yubikit/desktop/YubiKitManager.java b/desktop/src/main/java/com/yubico/yubikit/desktop/YubiKitManager.java index 3a21be47..07b15302 100755 --- a/desktop/src/main/java/com/yubico/yubikit/desktop/YubiKitManager.java +++ b/desktop/src/main/java/com/yubico/yubikit/desktop/YubiKitManager.java @@ -26,59 +26,60 @@ import com.yubico.yubikit.desktop.hid.HidManager; import com.yubico.yubikit.desktop.pcsc.PcscManager; import com.yubico.yubikit.management.DeviceInfo; - -import org.slf4j.LoggerFactory; - import java.util.*; +import org.slf4j.LoggerFactory; public class YubiKitManager { - private final PcscManager pcscManager; - private final HidManager hidManager; + private final PcscManager pcscManager; + private final HidManager hidManager; - private final org.slf4j.Logger logger = LoggerFactory.getLogger(YubiKitManager.class); + private final org.slf4j.Logger logger = LoggerFactory.getLogger(YubiKitManager.class); - public YubiKitManager(PcscManager pcscManager, HidManager hidManager) { - this.pcscManager = pcscManager; - this.hidManager = hidManager; - } + public YubiKitManager(PcscManager pcscManager, HidManager hidManager) { + this.pcscManager = pcscManager; + this.hidManager = hidManager; + } - public YubiKitManager() { - this(new PcscManager(), new HidManager()); - } + public YubiKitManager() { + this(new PcscManager(), new HidManager()); + } - List listDevices(Class connectionType) { - if (SmartCardConnection.class.isAssignableFrom(connectionType)) { - return pcscManager.getDevices(); - } else if (OtpConnection.class.isAssignableFrom(connectionType)) { - return hidManager.getOtpDevices(); - } else if (FidoConnection.class.isAssignableFrom(connectionType)) { - return hidManager.getFidoDevices(); - } - throw new IllegalStateException("Unsupported connection type"); + List listDevices(Class connectionType) { + if (SmartCardConnection.class.isAssignableFrom(connectionType)) { + return pcscManager.getDevices(); + } else if (OtpConnection.class.isAssignableFrom(connectionType)) { + return hidManager.getOtpDevices(); + } else if (FidoConnection.class.isAssignableFrom(connectionType)) { + return hidManager.getFidoDevices(); } + throw new IllegalStateException("Unsupported connection type"); + } - public Map listAllDevices(Set> connectionTypes) { - Map groups = new HashMap<>(); - for (Class connectionType : connectionTypes) { - Logger.debug(logger, "Enumerate devices for {}", connectionType); - for (UsbYubiKeyDevice device : listDevices(connectionType)) { - UsbPid pid = device.getPid(); - Logger.debug(logger, "Found device with PID {}", pid); - if (!groups.containsKey(pid)) { - groups.put(pid, new UsbPidGroup(pid)); - } - groups.get(pid).add(connectionType, device, false); - } + public Map listAllDevices( + Set> connectionTypes) { + Map groups = new HashMap<>(); + for (Class connectionType : connectionTypes) { + Logger.debug(logger, "Enumerate devices for {}", connectionType); + for (UsbYubiKeyDevice device : listDevices(connectionType)) { + UsbPid pid = device.getPid(); + Logger.debug(logger, "Found device with PID {}", pid); + if (!groups.containsKey(pid)) { + groups.put(pid, new UsbPidGroup(pid)); } - - Map devices = new LinkedHashMap<>(); - for (UsbPidGroup group: groups.values()) { - devices.putAll(group.getDevices()); - } - return devices; + groups.get(pid).add(connectionType, device, false); + } } - public Map listAllDevices() { - return listAllDevices(new HashSet<>(Arrays.asList(SmartCardConnection.class, FidoConnection.class, OtpConnection.class))); + Map devices = new LinkedHashMap<>(); + for (UsbPidGroup group : groups.values()) { + devices.putAll(group.getDevices()); } + return devices; + } + + public Map listAllDevices() { + return listAllDevices( + new HashSet<>( + Arrays.asList(SmartCardConnection.class, FidoConnection.class, OtpConnection.class))); + } } diff --git a/desktop/src/main/java/com/yubico/yubikit/desktop/hid/HidDevice.java b/desktop/src/main/java/com/yubico/yubikit/desktop/hid/HidDevice.java index 35bd7db1..5af2ba03 100755 --- a/desktop/src/main/java/com/yubico/yubikit/desktop/hid/HidDevice.java +++ b/desktop/src/main/java/com/yubico/yubikit/desktop/hid/HidDevice.java @@ -22,78 +22,80 @@ import com.yubico.yubikit.core.util.Callback; import com.yubico.yubikit.core.util.Result; import com.yubico.yubikit.desktop.UsbYubiKeyDevice; - import java.io.IOException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class HidDevice implements UsbYubiKeyDevice { - private final ExecutorService executorService = Executors.newSingleThreadExecutor(); - private final org.hid4java.HidDevice hidDevice; - private final int usagePage; + private final ExecutorService executorService = Executors.newSingleThreadExecutor(); + private final org.hid4java.HidDevice hidDevice; + private final int usagePage; - HidDevice(org.hid4java.HidDevice hidDevice) { - this.hidDevice = hidDevice; - usagePage = hidDevice.getUsagePage() & 0xffff; - } + HidDevice(org.hid4java.HidDevice hidDevice) { + this.hidDevice = hidDevice; + usagePage = hidDevice.getUsagePage() & 0xffff; + } - public HidOtpConnection openOtpConnection() throws IOException { - return new HidOtpConnection(hidDevice, (byte) 0); - } + public HidOtpConnection openOtpConnection() throws IOException { + return new HidOtpConnection(hidDevice, (byte) 0); + } - public HidFidoConnection openFidoConnection() throws IOException { - if (usagePage == 0xf1d0) { - return new HidFidoConnection(hidDevice); - } - throw new IOException("fido connection not supported"); + public HidFidoConnection openFidoConnection() throws IOException { + if (usagePage == 0xf1d0) { + return new HidFidoConnection(hidDevice); } + throw new IOException("fido connection not supported"); + } - @Override - public Transport getTransport() { - return Transport.USB; - } + @Override + public Transport getTransport() { + return Transport.USB; + } - @Override - public boolean supportsConnection(Class connectionType) { - if (connectionType.isAssignableFrom(HidOtpConnection.class)) { - return usagePage == 1; - } else if (connectionType.isAssignableFrom(HidFidoConnection.class)) { - return usagePage == 0xf1d0; - } - return false; + @Override + public boolean supportsConnection(Class connectionType) { + if (connectionType.isAssignableFrom(HidOtpConnection.class)) { + return usagePage == 1; + } else if (connectionType.isAssignableFrom(HidFidoConnection.class)) { + return usagePage == 0xf1d0; } + return false; + } - @Override - public void requestConnection(Class connectionType, Callback> callback) { - if (!supportsConnection(connectionType)) { - throw new IllegalStateException("Unsupported connection type"); - } - executorService.submit(() -> { - try(T connection = openConnection(connectionType)) { - callback.invoke(Result.success(connection)); - } catch (IOException e) { - callback.invoke(Result.failure(e)); - } - }); + @Override + public void requestConnection( + Class connectionType, Callback> callback) { + if (!supportsConnection(connectionType)) { + throw new IllegalStateException("Unsupported connection type"); } + executorService.submit( + () -> { + try (T connection = openConnection(connectionType)) { + callback.invoke(Result.success(connection)); + } catch (IOException e) { + callback.invoke(Result.failure(e)); + } + }); + } - @Override - public T openConnection(Class connectionType) throws IOException { - if (connectionType.isAssignableFrom(HidOtpConnection.class)) { - return connectionType.cast(openOtpConnection()); - } else if (connectionType.isAssignableFrom(HidFidoConnection.class)) { - return connectionType.cast(openFidoConnection()); - } - throw new IllegalStateException("Unsupported connection type"); + @Override + public T openConnection(Class connectionType) + throws IOException { + if (connectionType.isAssignableFrom(HidOtpConnection.class)) { + return connectionType.cast(openOtpConnection()); + } else if (connectionType.isAssignableFrom(HidFidoConnection.class)) { + return connectionType.cast(openFidoConnection()); } + throw new IllegalStateException("Unsupported connection type"); + } - @Override - public String getFingerprint() { - return hidDevice.getPath(); - } + @Override + public String getFingerprint() { + return hidDevice.getPath(); + } - @Override - public UsbPid getPid() { - return UsbPid.fromValue(hidDevice.getProductId()); - } + @Override + public UsbPid getPid() { + return UsbPid.fromValue(hidDevice.getProductId()); + } } diff --git a/desktop/src/main/java/com/yubico/yubikit/desktop/hid/HidFidoConnection.java b/desktop/src/main/java/com/yubico/yubikit/desktop/hid/HidFidoConnection.java index 5ba258ee..3e17ad0e 100755 --- a/desktop/src/main/java/com/yubico/yubikit/desktop/hid/HidFidoConnection.java +++ b/desktop/src/main/java/com/yubico/yubikit/desktop/hid/HidFidoConnection.java @@ -17,55 +17,53 @@ import com.yubico.yubikit.core.fido.FidoConnection; import com.yubico.yubikit.core.internal.Logger; - +import java.io.IOException; import org.hid4java.HidDevice; import org.slf4j.LoggerFactory; -import java.io.IOException; - public class HidFidoConnection implements FidoConnection { - private static final int TIMEOUT = 1000; - - private final HidDevice hidDevice; + private static final int TIMEOUT = 1000; - private final org.slf4j.Logger logger = LoggerFactory.getLogger(HidFidoConnection.class); + private final HidDevice hidDevice; - public HidFidoConnection(HidDevice hidDevice) throws IOException { - Logger.debug(logger, "Opening HID FIDO connection"); + private final org.slf4j.Logger logger = LoggerFactory.getLogger(HidFidoConnection.class); - if (!hidDevice.isClosed()) { - throw new IOException("Device already open"); - } + public HidFidoConnection(HidDevice hidDevice) throws IOException { + Logger.debug(logger, "Opening HID FIDO connection"); - if (!hidDevice.open()) { - throw new IOException("Failure opening device"); - } - this.hidDevice = hidDevice; + if (!hidDevice.isClosed()) { + throw new IOException("Device already open"); } - @Override - public void close() { - Logger.debug(logger, "Closing HID FIDO connection"); - hidDevice.close(); + if (!hidDevice.open()) { + throw new IOException("Failure opening device"); } + this.hidDevice = hidDevice; + } + + @Override + public void close() { + Logger.debug(logger, "Closing HID FIDO connection"); + hidDevice.close(); + } - @Override - public void send(byte[] packet) throws IOException { - int sent = hidDevice.write(packet, packet.length, (byte) 0); - if (sent < 0) { - throw new IOException(hidDevice.getLastErrorMessage()); - } else if (sent != PACKET_SIZE + 1) { - throw new IOException("Unexpected amount of data sent: " + sent); - } + @Override + public void send(byte[] packet) throws IOException { + int sent = hidDevice.write(packet, packet.length, (byte) 0); + if (sent < 0) { + throw new IOException(hidDevice.getLastErrorMessage()); + } else if (sent != PACKET_SIZE + 1) { + throw new IOException("Unexpected amount of data sent: " + sent); } + } - @Override - public void receive(byte[] packet) throws IOException { - int received = hidDevice.read(packet, TIMEOUT); - if (received < 0) { - throw new IOException(hidDevice.getLastErrorMessage()); - } else if (received != PACKET_SIZE) { - throw new IOException("Unexpected amount of data read: " + received); - } + @Override + public void receive(byte[] packet) throws IOException { + int received = hidDevice.read(packet, TIMEOUT); + if (received < 0) { + throw new IOException(hidDevice.getLastErrorMessage()); + } else if (received != PACKET_SIZE) { + throw new IOException("Unexpected amount of data read: " + received); } + } } diff --git a/desktop/src/main/java/com/yubico/yubikit/desktop/hid/HidManager.java b/desktop/src/main/java/com/yubico/yubikit/desktop/hid/HidManager.java index 1ce49da6..6da6ed70 100755 --- a/desktop/src/main/java/com/yubico/yubikit/desktop/hid/HidManager.java +++ b/desktop/src/main/java/com/yubico/yubikit/desktop/hid/HidManager.java @@ -17,73 +17,70 @@ package com.yubico.yubikit.desktop.hid; import com.yubico.yubikit.core.internal.Logger; - +import java.util.ArrayList; +import java.util.List; +import javax.annotation.Nullable; import org.hid4java.HidServices; import org.hid4java.HidServicesListener; import org.hid4java.event.HidServicesEvent; import org.slf4j.LoggerFactory; -import java.util.ArrayList; -import java.util.List; - -import javax.annotation.Nullable; - public class HidManager { - private static final int YUBICO_VENDOR_ID = 0x1050; - private static final int HID_USAGE_PAGE_OTP = 0x0001; - private static final int HID_USAGE_PAGE_FIDO = 0xf1d0; - + private static final int YUBICO_VENDOR_ID = 0x1050; + private static final int HID_USAGE_PAGE_OTP = 0x0001; + private static final int HID_USAGE_PAGE_FIDO = 0xf1d0; - private final HidServices services; + private final HidServices services; - private final org.slf4j.Logger logger = LoggerFactory.getLogger(HidManager.class); + private final org.slf4j.Logger logger = LoggerFactory.getLogger(HidManager.class); - public HidManager() { - services = org.hid4java.HidManager.getHidServices(); - } - - public List getHidDevices(int vendorId, @Nullable Integer usagePage) { - List yubikeys = new ArrayList<>(); - for (org.hid4java.HidDevice device: services.getAttachedHidDevices()) { - if(device.getVendorId() == vendorId && - (usagePage != null && (device.getUsagePage() & 0xffff) == usagePage)) { - yubikeys.add(new HidDevice(device)); - } - } - return yubikeys; - } - - public List getOtpDevices() { - return getHidDevices(YUBICO_VENDOR_ID, HID_USAGE_PAGE_OTP); - } + public HidManager() { + services = org.hid4java.HidManager.getHidServices(); + } - public List getFidoDevices() { - return getHidDevices(YUBICO_VENDOR_ID, HID_USAGE_PAGE_FIDO); + public List getHidDevices(int vendorId, @Nullable Integer usagePage) { + List yubikeys = new ArrayList<>(); + for (org.hid4java.HidDevice device : services.getAttachedHidDevices()) { + if (device.getVendorId() == vendorId + && (usagePage != null && (device.getUsagePage() & 0xffff) == usagePage)) { + yubikeys.add(new HidDevice(device)); + } } - - public void setListener(HidSessionListener listener) { - services.addHidServicesListener(new HidServicesListener() { - @Override - public void hidDeviceAttached(HidServicesEvent event) { - Logger.debug(logger, "HID attached: {}", event); - listener.onSessionReceived(new HidDevice(event.getHidDevice())); - } - - @Override - public void hidDeviceDetached(HidServicesEvent event) { - Logger.debug(logger, "HID removed: {}", event); - } - - @Override - public void hidFailure(HidServicesEvent event) { - Logger.debug(logger, "HID failure: {}", event); - } - - @Override - public void hidDataReceived(HidServicesEvent event) { - Logger.debug(logger, "HID Data received: {}", event); - } + return yubikeys; + } + + public List getOtpDevices() { + return getHidDevices(YUBICO_VENDOR_ID, HID_USAGE_PAGE_OTP); + } + + public List getFidoDevices() { + return getHidDevices(YUBICO_VENDOR_ID, HID_USAGE_PAGE_FIDO); + } + + public void setListener(HidSessionListener listener) { + services.addHidServicesListener( + new HidServicesListener() { + @Override + public void hidDeviceAttached(HidServicesEvent event) { + Logger.debug(logger, "HID attached: {}", event); + listener.onSessionReceived(new HidDevice(event.getHidDevice())); + } + + @Override + public void hidDeviceDetached(HidServicesEvent event) { + Logger.debug(logger, "HID removed: {}", event); + } + + @Override + public void hidFailure(HidServicesEvent event) { + Logger.debug(logger, "HID failure: {}", event); + } + + @Override + public void hidDataReceived(HidServicesEvent event) { + Logger.debug(logger, "HID Data received: {}", event); + } }); - } + } } diff --git a/desktop/src/main/java/com/yubico/yubikit/desktop/hid/HidOtpConnection.java b/desktop/src/main/java/com/yubico/yubikit/desktop/hid/HidOtpConnection.java index b75bb764..c4600504 100755 --- a/desktop/src/main/java/com/yubico/yubikit/desktop/hid/HidOtpConnection.java +++ b/desktop/src/main/java/com/yubico/yubikit/desktop/hid/HidOtpConnection.java @@ -18,60 +18,58 @@ import com.yubico.yubikit.core.internal.Logger; import com.yubico.yubikit.core.otp.OtpConnection; - import com.yubico.yubikit.desktop.OperatingSystem; +import java.io.IOException; import org.hid4java.HidDevice; import org.slf4j.LoggerFactory; -import java.io.IOException; - public class HidOtpConnection implements OtpConnection { - private final HidDevice hidDevice; - private final byte interfaceId; - private final static org.slf4j.Logger logger = LoggerFactory.getLogger(HidOtpConnection.class); - - HidOtpConnection(HidDevice hidDevice, byte interfaceId) throws IOException { - Logger.debug(logger, "Opening HID OTP connection"); + private final HidDevice hidDevice; + private final byte interfaceId; + private static final org.slf4j.Logger logger = LoggerFactory.getLogger(HidOtpConnection.class); - if (!hidDevice.isClosed()) { - throw new IOException("Device already open"); - } + HidOtpConnection(HidDevice hidDevice, byte interfaceId) throws IOException { + Logger.debug(logger, "Opening HID OTP connection"); - if (!hidDevice.open()) { - throw new IOException("Failure opening device"); - } + if (!hidDevice.isClosed()) { + throw new IOException("Device already open"); + } - this.interfaceId = interfaceId; - this.hidDevice = hidDevice; + if (!hidDevice.open()) { + throw new IOException("Failure opening device"); } - @Override - public void receive(byte[] report) throws IOException { - int offset = OperatingSystem.isWindows() ? 1 : 0; - int reportSize = FEATURE_REPORT_SIZE + offset; + this.interfaceId = interfaceId; + this.hidDevice = hidDevice; + } + + @Override + public void receive(byte[] report) throws IOException { + int offset = OperatingSystem.isWindows() ? 1 : 0; + int reportSize = FEATURE_REPORT_SIZE + offset; - int received = hidDevice.getFeatureReport(report, interfaceId); + int received = hidDevice.getFeatureReport(report, interfaceId); - if (received != reportSize) { - throw new IOException("Unexpected amount of data read: " + received); - } + if (received != reportSize) { + throw new IOException("Unexpected amount of data read: " + received); } + } - @Override - public void send(byte[] report) throws IOException { - int offset = OperatingSystem.isWindows() ? 1 : 0; - int reportSize = FEATURE_REPORT_SIZE + offset; + @Override + public void send(byte[] report) throws IOException { + int offset = OperatingSystem.isWindows() ? 1 : 0; + int reportSize = FEATURE_REPORT_SIZE + offset; - int sent = hidDevice.sendFeatureReport(report, interfaceId); - - if (sent != reportSize) { - throw new IOException("Unexpected amount of data sent: " + sent); - } - } + int sent = hidDevice.sendFeatureReport(report, interfaceId); - @Override - public void close() { - Logger.debug(logger, "Closing HID OTP connection"); - hidDevice.close(); + if (sent != reportSize) { + throw new IOException("Unexpected amount of data sent: " + sent); } + } + + @Override + public void close() { + Logger.debug(logger, "Closing HID OTP connection"); + hidDevice.close(); + } } diff --git a/desktop/src/main/java/com/yubico/yubikit/desktop/hid/HidSessionListener.java b/desktop/src/main/java/com/yubico/yubikit/desktop/hid/HidSessionListener.java index 08eefd67..9e4b5ff8 100755 --- a/desktop/src/main/java/com/yubico/yubikit/desktop/hid/HidSessionListener.java +++ b/desktop/src/main/java/com/yubico/yubikit/desktop/hid/HidSessionListener.java @@ -17,17 +17,17 @@ package com.yubico.yubikit.desktop.hid; public interface HidSessionListener { - /** - * Invoked when detected inserted device after usb discovery started - * - * @param session usb session that associated with plugged in device - */ - void onSessionReceived(HidDevice session); + /** + * Invoked when detected inserted device after usb discovery started + * + * @param session usb session that associated with plugged in device + */ + void onSessionReceived(HidDevice session); - /** - * Invoked when detected removal/ejection of usb device after usb discovery started - * - * @param session usb session that will become inactive - */ - void onSessionRemoved(HidDevice session); + /** + * Invoked when detected removal/ejection of usb device after usb discovery started + * + * @param session usb session that will become inactive + */ + void onSessionRemoved(HidDevice session); } diff --git a/desktop/src/main/java/com/yubico/yubikit/desktop/hid/package-info.java b/desktop/src/main/java/com/yubico/yubikit/desktop/hid/package-info.java index cb7b2006..bea45eb8 100755 --- a/desktop/src/main/java/com/yubico/yubikit/desktop/hid/package-info.java +++ b/desktop/src/main/java/com/yubico/yubikit/desktop/hid/package-info.java @@ -1,4 +1,4 @@ @PackageNonnullByDefault package com.yubico.yubikit.desktop.hid; -import com.yubico.yubikit.core.PackageNonnullByDefault; \ No newline at end of file +import com.yubico.yubikit.core.PackageNonnullByDefault; diff --git a/desktop/src/main/java/com/yubico/yubikit/desktop/package-info.java b/desktop/src/main/java/com/yubico/yubikit/desktop/package-info.java index 9d9f0ea9..bd0f9477 100755 --- a/desktop/src/main/java/com/yubico/yubikit/desktop/package-info.java +++ b/desktop/src/main/java/com/yubico/yubikit/desktop/package-info.java @@ -1,4 +1,4 @@ @PackageNonnullByDefault package com.yubico.yubikit.desktop; -import com.yubico.yubikit.core.PackageNonnullByDefault; \ No newline at end of file +import com.yubico.yubikit.core.PackageNonnullByDefault; diff --git a/desktop/src/main/java/com/yubico/yubikit/desktop/pcsc/NfcPcscDevice.java b/desktop/src/main/java/com/yubico/yubikit/desktop/pcsc/NfcPcscDevice.java index 702c29c1..5f446d42 100755 --- a/desktop/src/main/java/com/yubico/yubikit/desktop/pcsc/NfcPcscDevice.java +++ b/desktop/src/main/java/com/yubico/yubikit/desktop/pcsc/NfcPcscDevice.java @@ -21,46 +21,44 @@ import com.yubico.yubikit.core.smartcard.Apdu; import com.yubico.yubikit.core.smartcard.ApduException; import com.yubico.yubikit.core.smartcard.SmartCardProtocol; - import java.io.IOException; import java.nio.ByteBuffer; - import javax.smartcardio.CardTerminal; public class NfcPcscDevice extends PcscDevice { - private static final byte[] NDEF_AID = new byte[]{(byte) 0xd2, 0x76, 0x00, 0x00, (byte) 0x85, 0x01, 0x01}; + private static final byte[] NDEF_AID = + new byte[] {(byte) 0xd2, 0x76, 0x00, 0x00, (byte) 0x85, 0x01, 0x01}; - public NfcPcscDevice(CardTerminal terminal) { - super(terminal); - } + public NfcPcscDevice(CardTerminal terminal) { + super(terminal); + } - @Override - public Transport getTransport() { - return Transport.NFC; - } + @Override + public Transport getTransport() { + return Transport.NFC; + } - /** - * Reads the NDEF record from a YubiKey over NFC. - * This is only available when connecting over NFC, and only if the YubiKey has been configured - * to output one of its OTP slots over NDEF. - * - * @return the raw NDEF record - * @throws IOException in case of connection error - * @throws ApduException in case of communication error - * @throws ApplicationNotAvailableException in case the NDEF applet isn't available - */ - public byte[] readNdef() throws IOException, ApduException, ApplicationNotAvailableException { - try (SmartCardProtocol ndef = new SmartCardProtocol(openIso7816Connection())) { - ndef.select(NDEF_AID); + /** + * Reads the NDEF record from a YubiKey over NFC. This is only available when connecting over NFC, + * and only if the YubiKey has been configured to output one of its OTP slots over NDEF. + * + * @return the raw NDEF record + * @throws IOException in case of connection error + * @throws ApduException in case of communication error + * @throws ApplicationNotAvailableException in case the NDEF applet isn't available + */ + public byte[] readNdef() throws IOException, ApduException, ApplicationNotAvailableException { + try (SmartCardProtocol ndef = new SmartCardProtocol(openIso7816Connection())) { + ndef.select(NDEF_AID); - ndef.sendAndReceive(new Apdu(0x00, 0xa4, 0x00, 0x0C, new byte[]{(byte) 0xe1, 0x04})); - byte[] resp = ndef.sendAndReceive(new Apdu(0x00, 0xb0, 0, 0, null)); - int ndefLen = resp[1]; - ByteBuffer buf = ByteBuffer.allocate(ndefLen).put(resp, 2, resp.length - 2); - while (buf.position() < ndefLen) { - buf.put(ndef.sendAndReceive(new Apdu(0x00, 0xb0, 0, buf.position(), null))); - } - return buf.array(); - } + ndef.sendAndReceive(new Apdu(0x00, 0xa4, 0x00, 0x0C, new byte[] {(byte) 0xe1, 0x04})); + byte[] resp = ndef.sendAndReceive(new Apdu(0x00, 0xb0, 0, 0, null)); + int ndefLen = resp[1]; + ByteBuffer buf = ByteBuffer.allocate(ndefLen).put(resp, 2, resp.length - 2); + while (buf.position() < ndefLen) { + buf.put(ndef.sendAndReceive(new Apdu(0x00, 0xb0, 0, buf.position(), null))); + } + return buf.array(); } + } } diff --git a/desktop/src/main/java/com/yubico/yubikit/desktop/pcsc/PcscConfiguration.java b/desktop/src/main/java/com/yubico/yubikit/desktop/pcsc/PcscConfiguration.java index b87bda9d..63e2b5e9 100755 --- a/desktop/src/main/java/com/yubico/yubikit/desktop/pcsc/PcscConfiguration.java +++ b/desktop/src/main/java/com/yubico/yubikit/desktop/pcsc/PcscConfiguration.java @@ -17,47 +17,44 @@ package com.yubico.yubikit.desktop.pcsc; import com.yubico.yubikit.core.Transport; - import java.util.Arrays; import java.util.EnumSet; import java.util.regex.Pattern; - import javax.annotation.Nullable; public class PcscConfiguration { - private final EnumSet transportFilter = EnumSet.allOf(Transport.class); - private long pollingTimeout = 250; - @Nullable - private Pattern readerNameFilter = null; - - long getPollingTimeout() { - return pollingTimeout; - } - - boolean isInterfaceAllowed(Transport transport) { - return transportFilter.contains(transport); - } + private final EnumSet transportFilter = EnumSet.allOf(Transport.class); + private long pollingTimeout = 250; + @Nullable private Pattern readerNameFilter = null; - boolean filterName(String name) { - if (readerNameFilter != null) { - return readerNameFilter.matcher(name).find(); - } - return true; - } + long getPollingTimeout() { + return pollingTimeout; + } - public PcscConfiguration pollingTimeout(long pollingTimeout) { - this.pollingTimeout = pollingTimeout; - return this; - } - - public PcscConfiguration interfaceFilter(Transport... transports) { - transportFilter.clear(); - transportFilter.addAll(Arrays.asList(transports)); - return this; - } + boolean isInterfaceAllowed(Transport transport) { + return transportFilter.contains(transport); + } - public PcscConfiguration readerNameFilter(Pattern pattern) { - this.readerNameFilter = pattern; - return this; + boolean filterName(String name) { + if (readerNameFilter != null) { + return readerNameFilter.matcher(name).find(); } + return true; + } + + public PcscConfiguration pollingTimeout(long pollingTimeout) { + this.pollingTimeout = pollingTimeout; + return this; + } + + public PcscConfiguration interfaceFilter(Transport... transports) { + transportFilter.clear(); + transportFilter.addAll(Arrays.asList(transports)); + return this; + } + + public PcscConfiguration readerNameFilter(Pattern pattern) { + this.readerNameFilter = pattern; + return this; + } } diff --git a/desktop/src/main/java/com/yubico/yubikit/desktop/pcsc/PcscDevice.java b/desktop/src/main/java/com/yubico/yubikit/desktop/pcsc/PcscDevice.java index 1fa9a6c0..1b49c56b 100755 --- a/desktop/src/main/java/com/yubico/yubikit/desktop/pcsc/PcscDevice.java +++ b/desktop/src/main/java/com/yubico/yubikit/desktop/pcsc/PcscDevice.java @@ -21,56 +21,58 @@ import com.yubico.yubikit.core.smartcard.SmartCardConnection; import com.yubico.yubikit.core.util.Callback; import com.yubico.yubikit.core.util.Result; - -import javax.smartcardio.CardException; -import javax.smartcardio.CardTerminal; import java.io.IOException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; +import javax.smartcardio.CardException; +import javax.smartcardio.CardTerminal; abstract class PcscDevice implements YubiKeyDevice { - private final ExecutorService executorService = Executors.newSingleThreadExecutor(); - private final CardTerminal terminal; + private final ExecutorService executorService = Executors.newSingleThreadExecutor(); + private final CardTerminal terminal; - public PcscDevice(CardTerminal terminal) { - this.terminal = terminal; - } + public PcscDevice(CardTerminal terminal) { + this.terminal = terminal; + } - public String getName() { - return terminal.getName(); - } + public String getName() { + return terminal.getName(); + } - public SmartCardConnection openIso7816Connection() throws IOException { - try { - return new PcscSmartCardConnection(terminal.connect("T=1")); - } catch (CardException e) { - throw new IOException(e); - } + public SmartCardConnection openIso7816Connection() throws IOException { + try { + return new PcscSmartCardConnection(terminal.connect("T=1")); + } catch (CardException e) { + throw new IOException(e); } + } - @Override - public boolean supportsConnection(Class connectionType) { - return connectionType.isAssignableFrom(PcscSmartCardConnection.class); - } + @Override + public boolean supportsConnection(Class connectionType) { + return connectionType.isAssignableFrom(PcscSmartCardConnection.class); + } - public T openConnection(Class connectionType) throws IOException { - if (!supportsConnection(connectionType)) { - throw new IllegalStateException("Unsupported connection type"); - } - return connectionType.cast(openIso7816Connection()); + public T openConnection(Class connectionType) + throws IOException { + if (!supportsConnection(connectionType)) { + throw new IllegalStateException("Unsupported connection type"); } + return connectionType.cast(openIso7816Connection()); + } - @Override - public void requestConnection(Class connectionType, Callback> callback) { - if (!supportsConnection(connectionType)) { - throw new IllegalStateException("Unsupported connection type"); - } - executorService.submit(() -> { - try(T connection = openConnection(connectionType)) { - callback.invoke(Result.success(connection)); - } catch (IOException e) { - callback.invoke(Result.failure(e)); - } - }); + @Override + public void requestConnection( + Class connectionType, Callback> callback) { + if (!supportsConnection(connectionType)) { + throw new IllegalStateException("Unsupported connection type"); } + executorService.submit( + () -> { + try (T connection = openConnection(connectionType)) { + callback.invoke(Result.success(connection)); + } catch (IOException e) { + callback.invoke(Result.failure(e)); + } + }); + } } diff --git a/desktop/src/main/java/com/yubico/yubikit/desktop/pcsc/PcscManager.java b/desktop/src/main/java/com/yubico/yubikit/desktop/pcsc/PcscManager.java index 8463e8a1..bce8dedb 100755 --- a/desktop/src/main/java/com/yubico/yubikit/desktop/pcsc/PcscManager.java +++ b/desktop/src/main/java/com/yubico/yubikit/desktop/pcsc/PcscManager.java @@ -16,32 +16,33 @@ package com.yubico.yubikit.desktop.pcsc; +import java.util.*; import javax.smartcardio.CardException; import javax.smartcardio.CardTerminal; import javax.smartcardio.CardTerminals; import javax.smartcardio.TerminalFactory; -import java.util.*; public class PcscManager { - private final TerminalFactory terminalFactory; + private final TerminalFactory terminalFactory; - public PcscManager(TerminalFactory terminalFactory) { - this.terminalFactory = terminalFactory; - } + public PcscManager(TerminalFactory terminalFactory) { + this.terminalFactory = terminalFactory; + } - public PcscManager() { - this(TerminalFactory.getDefault()); - } + public PcscManager() { + this(TerminalFactory.getDefault()); + } - public List getDevices() { - List yubikeys = new ArrayList<>(); - try { - for (CardTerminal device: terminalFactory.terminals().list(CardTerminals.State.CARD_PRESENT)) { - yubikeys.add(new UsbPcscDevice(device)); - } - } catch (CardException e) { - throw new RuntimeException(e); - } - return yubikeys; + public List getDevices() { + List yubikeys = new ArrayList<>(); + try { + for (CardTerminal device : + terminalFactory.terminals().list(CardTerminals.State.CARD_PRESENT)) { + yubikeys.add(new UsbPcscDevice(device)); + } + } catch (CardException e) { + throw new RuntimeException(e); } + return yubikeys; + } } diff --git a/desktop/src/main/java/com/yubico/yubikit/desktop/pcsc/PcscSessionListener.java b/desktop/src/main/java/com/yubico/yubikit/desktop/pcsc/PcscSessionListener.java index 57869605..26446863 100755 --- a/desktop/src/main/java/com/yubico/yubikit/desktop/pcsc/PcscSessionListener.java +++ b/desktop/src/main/java/com/yubico/yubikit/desktop/pcsc/PcscSessionListener.java @@ -17,17 +17,17 @@ package com.yubico.yubikit.desktop.pcsc; public interface PcscSessionListener { - /** - * Invoked when detected inserted device after usb discovery started - * - * @param session usb session that associated with plugged in device - */ - void onSessionReceived(NfcPcscDevice session); + /** + * Invoked when detected inserted device after usb discovery started + * + * @param session usb session that associated with plugged in device + */ + void onSessionReceived(NfcPcscDevice session); - /** - * Invoked when detected removal/ejection of usb device after usb discovery started - * - * @param session usb session that will become inactive - */ - void onSessionRemoved(NfcPcscDevice session); + /** + * Invoked when detected removal/ejection of usb device after usb discovery started + * + * @param session usb session that will become inactive + */ + void onSessionRemoved(NfcPcscDevice session); } diff --git a/desktop/src/main/java/com/yubico/yubikit/desktop/pcsc/PcscSmartCardConnection.java b/desktop/src/main/java/com/yubico/yubikit/desktop/pcsc/PcscSmartCardConnection.java index b52b2228..74b2ef56 100755 --- a/desktop/src/main/java/com/yubico/yubikit/desktop/pcsc/PcscSmartCardConnection.java +++ b/desktop/src/main/java/com/yubico/yubikit/desktop/pcsc/PcscSmartCardConnection.java @@ -20,75 +20,73 @@ import com.yubico.yubikit.core.internal.Logger; import com.yubico.yubikit.core.smartcard.SmartCardConnection; import com.yubico.yubikit.core.util.StringUtils; - -import org.slf4j.LoggerFactory; - import java.io.IOException; import java.util.Arrays; - import javax.smartcardio.Card; import javax.smartcardio.CardChannel; import javax.smartcardio.CardException; import javax.smartcardio.CommandAPDU; +import org.slf4j.LoggerFactory; public class PcscSmartCardConnection implements SmartCardConnection { - private final Card card; - private final Transport transport; - private final CardChannel cardChannel; + private final Card card; + private final Transport transport; + private final CardChannel cardChannel; - private final org.slf4j.Logger logger = LoggerFactory.getLogger(PcscSmartCardConnection.class); + private final org.slf4j.Logger logger = LoggerFactory.getLogger(PcscSmartCardConnection.class); - public PcscSmartCardConnection(Card card) throws IOException { - this.card = card; - this.transport = (card.getATR() - .getBytes()[1] & 0xf0) == 0xf0 ? Transport.USB : Transport.NFC; - try { - Logger.debug(logger, "Opening CCID connection"); - card.beginExclusive(); - this.cardChannel = card.getBasicChannel(); - } catch (CardException e) { - throw new IOException(e); - } + public PcscSmartCardConnection(Card card) throws IOException { + this.card = card; + this.transport = (card.getATR().getBytes()[1] & 0xf0) == 0xf0 ? Transport.USB : Transport.NFC; + try { + Logger.debug(logger, "Opening CCID connection"); + card.beginExclusive(); + this.cardChannel = card.getBasicChannel(); + } catch (CardException e) { + throw new IOException(e); } + } - @Override - public Transport getTransport() { - return transport; - } + @Override + public Transport getTransport() { + return transport; + } - @Override - public boolean isExtendedLengthApduSupported() { - return true; - } + @Override + public boolean isExtendedLengthApduSupported() { + return true; + } - @Override - public byte[] getAtr() { - return card.getATR().getBytes(); - } + @Override + public byte[] getAtr() { + return card.getATR().getBytes(); + } - @Override - public void close() throws IOException { - Logger.debug(logger, "Closing CCID connection"); - try { - card.endExclusive(); - } catch (CardException e) { - throw new IOException(e); - } + @Override + public void close() throws IOException { + Logger.debug(logger, "Closing CCID connection"); + try { + card.endExclusive(); + } catch (CardException e) { + throw new IOException(e); } + } - @Override - public byte[] sendAndReceive(byte[] apdu) throws IOException { - try { - Logger.trace(logger, "{} bytes sent over PCSC: {}", apdu.length, StringUtils.bytesToHex(apdu)); - if (apdu.length < 5) { - // CardChannel.transmit requires at least 5 bytes. - apdu = Arrays.copyOf(apdu, 5); - } - byte[] response = cardChannel.transmit(new CommandAPDU(apdu)).getBytes(); - Logger.trace(logger, "{} bytes received: {}", response.length, StringUtils.bytesToHex(response)); - return response; - } catch (CardException e) { - throw new IOException(e); - } + @Override + public byte[] sendAndReceive(byte[] apdu) throws IOException { + try { + Logger.trace( + logger, "{} bytes sent over PCSC: {}", apdu.length, StringUtils.bytesToHex(apdu)); + if (apdu.length < 5) { + // CardChannel.transmit requires at least 5 bytes. + apdu = Arrays.copyOf(apdu, 5); + } + byte[] response = cardChannel.transmit(new CommandAPDU(apdu)).getBytes(); + Logger.trace( + logger, "{} bytes received: {}", response.length, StringUtils.bytesToHex(response)); + return response; + } catch (CardException e) { + throw new IOException(e); } -} \ No newline at end of file + } +} diff --git a/desktop/src/main/java/com/yubico/yubikit/desktop/pcsc/UsbPcscDevice.java b/desktop/src/main/java/com/yubico/yubikit/desktop/pcsc/UsbPcscDevice.java index 162d2603..23637a82 100755 --- a/desktop/src/main/java/com/yubico/yubikit/desktop/pcsc/UsbPcscDevice.java +++ b/desktop/src/main/java/com/yubico/yubikit/desktop/pcsc/UsbPcscDevice.java @@ -21,55 +21,54 @@ import com.yubico.yubikit.core.UsbPid; import com.yubico.yubikit.core.YubiKeyType; import com.yubico.yubikit.desktop.UsbYubiKeyDevice; - import javax.smartcardio.CardTerminal; public class UsbPcscDevice extends PcscDevice implements UsbYubiKeyDevice { - private final UsbPid pid; - - public UsbPcscDevice(CardTerminal terminal) { - super(terminal); - this.pid = getPidFromName(terminal.getName()); - } + private final UsbPid pid; - private static UsbPid getPidFromName(String name) { - if (!name.toLowerCase().contains("yubikey")) { - throw new IllegalArgumentException("Given argument is not a USB YubiKey"); - } + public UsbPcscDevice(CardTerminal terminal) { + super(terminal); + this.pid = getPidFromName(terminal.getName()); + } - int usbInterfaces = 0; - if (name.contains("CCID")) { - usbInterfaces |= UsbInterface.CCID; - } - if (name.contains("OTP")) { - usbInterfaces |= UsbInterface.OTP; - } - if (name.contains("FIDO") || name.contains("U2F")) { - usbInterfaces |= UsbInterface.FIDO; - } - YubiKeyType keyType = name.contains("NEO") ? YubiKeyType.NEO : YubiKeyType.YK4; - - for (UsbPid pid : UsbPid.values()) { - if (pid.type == keyType && pid.usbInterfaces == usbInterfaces) { - return pid; - } - } - - throw new IllegalArgumentException("No known PID for device name"); + private static UsbPid getPidFromName(String name) { + if (!name.toLowerCase().contains("yubikey")) { + throw new IllegalArgumentException("Given argument is not a USB YubiKey"); } - @Override - public Transport getTransport() { - return Transport.USB; + int usbInterfaces = 0; + if (name.contains("CCID")) { + usbInterfaces |= UsbInterface.CCID; } - - @Override - public String getFingerprint() { - return getName(); + if (name.contains("OTP")) { + usbInterfaces |= UsbInterface.OTP; } + if (name.contains("FIDO") || name.contains("U2F")) { + usbInterfaces |= UsbInterface.FIDO; + } + YubiKeyType keyType = name.contains("NEO") ? YubiKeyType.NEO : YubiKeyType.YK4; - @Override - public UsbPid getPid() { + for (UsbPid pid : UsbPid.values()) { + if (pid.type == keyType && pid.usbInterfaces == usbInterfaces) { return pid; + } } + + throw new IllegalArgumentException("No known PID for device name"); + } + + @Override + public Transport getTransport() { + return Transport.USB; + } + + @Override + public String getFingerprint() { + return getName(); + } + + @Override + public UsbPid getPid() { + return pid; + } } diff --git a/desktop/src/main/java/com/yubico/yubikit/desktop/pcsc/package-info.java b/desktop/src/main/java/com/yubico/yubikit/desktop/pcsc/package-info.java index 56387438..de75363a 100755 --- a/desktop/src/main/java/com/yubico/yubikit/desktop/pcsc/package-info.java +++ b/desktop/src/main/java/com/yubico/yubikit/desktop/pcsc/package-info.java @@ -1,4 +1,4 @@ @PackageNonnullByDefault package com.yubico.yubikit.desktop.pcsc; -import com.yubico.yubikit.core.PackageNonnullByDefault; \ No newline at end of file +import com.yubico.yubikit.core.PackageNonnullByDefault; diff --git a/testing-desktop/build.gradle b/testing-desktop/build.gradle index 8d54d19e..b8930e36 100755 --- a/testing-desktop/build.gradle +++ b/testing-desktop/build.gradle @@ -1,5 +1,6 @@ plugins { id 'java' + id 'project-convention-spotless' } repositories { diff --git a/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/DeviceTests.java b/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/DeviceTests.java index 0ab5dca1..e65f7650 100644 --- a/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/DeviceTests.java +++ b/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/DeviceTests.java @@ -16,30 +16,29 @@ package com.yubico.yubikit.testing.desktop; -import com.yubico.yubikit.testing.desktop.mpe.MultiProtocolResetTests; import com.yubico.yubikit.testing.desktop.fido.FidoTests; +import com.yubico.yubikit.testing.desktop.mpe.MultiProtocolResetTests; import com.yubico.yubikit.testing.desktop.oath.OathTests; import com.yubico.yubikit.testing.desktop.openpgp.OpenPgpTests; import com.yubico.yubikit.testing.desktop.piv.PivTests; import com.yubico.yubikit.testing.desktop.sd.SecurityDomainTests; - import org.junit.runner.RunWith; import org.junit.runners.Suite; /** * All integration tests for Security domain, PIV, OpenPGP, OATH, FIDO2 and MPE. - *

- * The YubiKey applications will be reset several times. + * + *

The YubiKey applications will be reset several times. + * *

*/ @RunWith(Suite.class) @Suite.SuiteClasses({ - SecurityDomainTests.class, - PivTests.class, - OpenPgpTests.class, - OathTests.class, - MultiProtocolResetTests.class, - FidoTests.class + SecurityDomainTests.class, + PivTests.class, + OpenPgpTests.class, + OathTests.class, + MultiProtocolResetTests.class, + FidoTests.class }) -public class DeviceTests { -} +public class DeviceTests {} diff --git a/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/FastDeviceTests.java b/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/FastDeviceTests.java index 905159b3..dd411970 100644 --- a/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/FastDeviceTests.java +++ b/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/FastDeviceTests.java @@ -22,18 +22,14 @@ /** * These tests are here to make testing a bit faster and exclude following: + * *

    - *
  • {@link SlowTest}
  • - *
  • {@link PinUvAuthProtocolV1Test}
  • - *
  • {@link AlwaysManualTest}
  • + *
  • {@link SlowTest} + *
  • {@link PinUvAuthProtocolV1Test} + *
  • {@link AlwaysManualTest} *
*/ @RunWith(Categories.class) @Suite.SuiteClasses(DeviceTests.class) -@Categories.ExcludeCategory({ - SlowTest.class, - PinUvAuthProtocolV1Test.class, - AlwaysManualTest.class -}) -public class FastDeviceTests { -} +@Categories.ExcludeCategory({SlowTest.class, PinUvAuthProtocolV1Test.class, AlwaysManualTest.class}) +public class FastDeviceTests {} diff --git a/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/SmokeDeviceTests.java b/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/SmokeDeviceTests.java index 2f432e61..867c5992 100644 --- a/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/SmokeDeviceTests.java +++ b/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/SmokeDeviceTests.java @@ -20,13 +20,10 @@ import org.junit.runner.RunWith; import org.junit.runners.Suite; -/** - * Quick, randomly selected tests for different applications. - */ +/** Quick, randomly selected tests for different applications. */ @RunWith(Categories.class) @Categories.IncludeCategory({ - SmokeTest.class, + SmokeTest.class, }) @Suite.SuiteClasses(DeviceTests.class) -public class SmokeDeviceTests { -} \ No newline at end of file +public class SmokeDeviceTests {} diff --git a/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/fido/BasicWebAuthnClientInstrumentedTests.java b/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/fido/BasicWebAuthnClientInstrumentedTests.java index 9a00e9c2..64f64986 100644 --- a/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/fido/BasicWebAuthnClientInstrumentedTests.java +++ b/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/fido/BasicWebAuthnClientInstrumentedTests.java @@ -22,7 +22,6 @@ import com.yubico.yubikit.testing.desktop.SmokeTest; import com.yubico.yubikit.testing.desktop.framework.FidoInstrumentedTests; import com.yubico.yubikit.testing.fido.BasicWebAuthnClientTests; - import org.junit.Test; import org.junit.experimental.categories.Category; import org.junit.runner.RunWith; @@ -30,59 +29,59 @@ @RunWith(Suite.class) @Suite.SuiteClasses({ - BasicWebAuthnClientInstrumentedTests.PinUvAuthV2Test.class, - BasicWebAuthnClientInstrumentedTests.PinUvAuthV1Test.class, + BasicWebAuthnClientInstrumentedTests.PinUvAuthV2Test.class, + BasicWebAuthnClientInstrumentedTests.PinUvAuthV1Test.class, }) public class BasicWebAuthnClientInstrumentedTests { - public static class PinUvAuthV2Test extends FidoInstrumentedTests { + public static class PinUvAuthV2Test extends FidoInstrumentedTests { - @Test - @Category(SmokeTest.class) - public void testMakeCredentialGetAssertion() throws Throwable { - withDevice(BasicWebAuthnClientTests::testMakeCredentialGetAssertion); - } + @Test + @Category(SmokeTest.class) + public void testMakeCredentialGetAssertion() throws Throwable { + withDevice(BasicWebAuthnClientTests::testMakeCredentialGetAssertion); + } - @Test - public void testMakeCredentialGetAssertionTokenUvOnly() throws Throwable { - withDevice(BasicWebAuthnClientTests::testMakeCredentialGetAssertionTokenUvOnly); - } + @Test + public void testMakeCredentialGetAssertionTokenUvOnly() throws Throwable { + withDevice(BasicWebAuthnClientTests::testMakeCredentialGetAssertionTokenUvOnly); + } - @Test - public void testGetAssertionMultipleUsersRk() throws Throwable { - withDevice(BasicWebAuthnClientTests::testGetAssertionMultipleUsersRk); - } + @Test + public void testGetAssertionMultipleUsersRk() throws Throwable { + withDevice(BasicWebAuthnClientTests::testGetAssertionMultipleUsersRk); + } - @Test - public void testGetAssertionWithAllowList() throws Throwable { - withDevice(BasicWebAuthnClientTests::testGetAssertionWithAllowList); - } + @Test + public void testGetAssertionWithAllowList() throws Throwable { + withDevice(BasicWebAuthnClientTests::testGetAssertionWithAllowList); + } - @Test - public void testMakeCredentialWithExcludeList() throws Throwable { - withDevice(BasicWebAuthnClientTests::testMakeCredentialWithExcludeList); - } + @Test + public void testMakeCredentialWithExcludeList() throws Throwable { + withDevice(BasicWebAuthnClientTests::testMakeCredentialWithExcludeList); + } - @Test - public void testMakeCredentialKeyAlgorithms() throws Throwable { - withDevice(BasicWebAuthnClientTests::testMakeCredentialKeyAlgorithms); - } + @Test + public void testMakeCredentialKeyAlgorithms() throws Throwable { + withDevice(BasicWebAuthnClientTests::testMakeCredentialKeyAlgorithms); + } - @Test - public void testClientPinManagement() throws Throwable { - withDevice(BasicWebAuthnClientTests::testClientPinManagement); - } + @Test + public void testClientPinManagement() throws Throwable { + withDevice(BasicWebAuthnClientTests::testClientPinManagement); + } - @Test - public void testClientCredentialManagement() throws Throwable { - withDevice(BasicWebAuthnClientTests::testClientCredentialManagement); - } + @Test + public void testClientCredentialManagement() throws Throwable { + withDevice(BasicWebAuthnClientTests::testClientCredentialManagement); } + } - @Category(PinUvAuthProtocolV1Test.class) - public static class PinUvAuthV1Test extends PinUvAuthV2Test { - @Override - protected PinUvAuthProtocol getPinUvAuthProtocol() { - return new PinUvAuthProtocolV1(); - } + @Category(PinUvAuthProtocolV1Test.class) + public static class PinUvAuthV1Test extends PinUvAuthV2Test { + @Override + protected PinUvAuthProtocol getPinUvAuthProtocol() { + return new PinUvAuthProtocolV1(); } + } } diff --git a/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/fido/Ctap2BioEnrollmentInstrumentedTests.java b/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/fido/Ctap2BioEnrollmentInstrumentedTests.java index a2bf6c15..64d11a25 100644 --- a/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/fido/Ctap2BioEnrollmentInstrumentedTests.java +++ b/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/fido/Ctap2BioEnrollmentInstrumentedTests.java @@ -16,15 +16,13 @@ package com.yubico.yubikit.testing.desktop.fido; - import com.yubico.yubikit.testing.desktop.framework.FidoInstrumentedTests; import com.yubico.yubikit.testing.fido.Ctap2BioEnrollmentTests; - import org.junit.Test; public class Ctap2BioEnrollmentInstrumentedTests extends FidoInstrumentedTests { - @Test - public void testFingerprintEnrollment() throws Throwable { - withCtap2Session(Ctap2BioEnrollmentTests::testFingerprintEnrollment); - } + @Test + public void testFingerprintEnrollment() throws Throwable { + withCtap2Session(Ctap2BioEnrollmentTests::testFingerprintEnrollment); + } } diff --git a/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/fido/Ctap2ClientPinInstrumentedTests.java b/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/fido/Ctap2ClientPinInstrumentedTests.java index 7fca6884..cf9f26a2 100644 --- a/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/fido/Ctap2ClientPinInstrumentedTests.java +++ b/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/fido/Ctap2ClientPinInstrumentedTests.java @@ -21,7 +21,6 @@ import com.yubico.yubikit.testing.desktop.PinUvAuthProtocolV1Test; import com.yubico.yubikit.testing.desktop.framework.FidoInstrumentedTests; import com.yubico.yubikit.testing.fido.Ctap2ClientPinTests; - import org.junit.Test; import org.junit.experimental.categories.Category; import org.junit.runner.RunWith; @@ -29,27 +28,27 @@ @RunWith(Suite.class) @Suite.SuiteClasses({ - Ctap2ClientPinInstrumentedTests.PinUvAuthV2Test.class, - Ctap2ClientPinInstrumentedTests.PinUvAuthV1Test.class, + Ctap2ClientPinInstrumentedTests.PinUvAuthV2Test.class, + Ctap2ClientPinInstrumentedTests.PinUvAuthV1Test.class, }) public class Ctap2ClientPinInstrumentedTests { - public static class PinUvAuthV2Test extends FidoInstrumentedTests { - @Test - public void testClientPin() throws Throwable { - withCtap2Session(Ctap2ClientPinTests::testClientPin); - } + public static class PinUvAuthV2Test extends FidoInstrumentedTests { + @Test + public void testClientPin() throws Throwable { + withCtap2Session(Ctap2ClientPinTests::testClientPin); + } - @Test - public void testPinComplexity() throws Throwable { - withDevice(Ctap2ClientPinTests::testPinComplexity); - } + @Test + public void testPinComplexity() throws Throwable { + withDevice(Ctap2ClientPinTests::testPinComplexity); } + } - @Category(PinUvAuthProtocolV1Test.class) - public static class PinUvAuthV1Test extends PinUvAuthV2Test { - @Override - protected PinUvAuthProtocol getPinUvAuthProtocol() { - return new PinUvAuthProtocolV1(); - } + @Category(PinUvAuthProtocolV1Test.class) + public static class PinUvAuthV1Test extends PinUvAuthV2Test { + @Override + protected PinUvAuthProtocol getPinUvAuthProtocol() { + return new PinUvAuthProtocolV1(); } + } } diff --git a/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/fido/Ctap2ConfigInstrumentedTests.java b/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/fido/Ctap2ConfigInstrumentedTests.java index ba7d99f2..c37bad8e 100644 --- a/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/fido/Ctap2ConfigInstrumentedTests.java +++ b/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/fido/Ctap2ConfigInstrumentedTests.java @@ -19,7 +19,6 @@ import com.yubico.yubikit.testing.desktop.AlwaysManualTest; import com.yubico.yubikit.testing.desktop.framework.FidoInstrumentedTests; import com.yubico.yubikit.testing.fido.Ctap2ConfigTests; - import org.junit.Test; import org.junit.experimental.categories.Categories; import org.junit.experimental.categories.Category; @@ -28,56 +27,56 @@ /** * Config tests. - *

- * These tests will change FIDO2 application configuration through authenticatorConfig. As these changes - * are irreversible. - *

- * Read documentation for each test for more information. + * + *

These tests will change FIDO2 application configuration through authenticatorConfig. As these + * changes are irreversible. + * + *

Read documentation for each test for more information. */ @RunWith(Categories.class) @Suite.SuiteClasses(Ctap2ConfigInstrumentedTests.ConfigTests.class) @Categories.ExcludeCategory(AlwaysManualTest.class) public class Ctap2ConfigInstrumentedTests { - public static class ConfigTests extends FidoInstrumentedTests { - @Test - public void testReadWriteEnterpriseAttestation() throws Throwable { - withCtap2Session(Ctap2ConfigTests::testReadWriteEnterpriseAttestation); - } + public static class ConfigTests extends FidoInstrumentedTests { + @Test + public void testReadWriteEnterpriseAttestation() throws Throwable { + withCtap2Session(Ctap2ConfigTests::testReadWriteEnterpriseAttestation); + } - /** - * Toggles the {@code alwaysUv} option to opposite value. It is not possible to set this - * option to `false` on a FIPS approved YubiKey. - * - * @throws Throwable if an error occurs - */ - @Test - @Category(AlwaysManualTest.class) - public void testToggleAlwaysUv() throws Throwable { - withCtap2Session(Ctap2ConfigTests::testToggleAlwaysUv); - } + /** + * Toggles the {@code alwaysUv} option to opposite value. It is not possible to set this option + * to `false` on a FIPS approved YubiKey. + * + * @throws Throwable if an error occurs + */ + @Test + @Category(AlwaysManualTest.class) + public void testToggleAlwaysUv() throws Throwable { + withCtap2Session(Ctap2ConfigTests::testToggleAlwaysUv); + } - /** - * Sets the {@code forcePinChange} flag, verifies that and then changes the PIN twice so - * that the device uses the {@code TestUtil.PIN}. - * - * @throws Throwable if an error occurs - */ - @Test - public void testSetForcePinChange() throws Throwable { - withCtap2Session(Ctap2ConfigTests::testSetForcePinChange); - } + /** + * Sets the {@code forcePinChange} flag, verifies that and then changes the PIN twice so that + * the device uses the {@code TestUtil.PIN}. + * + * @throws Throwable if an error occurs + */ + @Test + public void testSetForcePinChange() throws Throwable { + withCtap2Session(Ctap2ConfigTests::testSetForcePinChange); + } - /** - * Changes the {@code minPinLength} value. This change is irreversible and after running - * this test, the YubiKey should be reset. - * - * @throws Throwable if an error occurs - */ - @Test - @Category(AlwaysManualTest.class) - public void testSetMinPinLength() throws Throwable { - withCtap2Session(Ctap2ConfigTests::testSetMinPinLength); - } + /** + * Changes the {@code minPinLength} value. This change is irreversible and after running this + * test, the YubiKey should be reset. + * + * @throws Throwable if an error occurs + */ + @Test + @Category(AlwaysManualTest.class) + public void testSetMinPinLength() throws Throwable { + withCtap2Session(Ctap2ConfigTests::testSetMinPinLength); } + } } diff --git a/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/fido/Ctap2CredentialManagementInstrumentedTests.java b/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/fido/Ctap2CredentialManagementInstrumentedTests.java index 1c03cd77..2a853632 100644 --- a/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/fido/Ctap2CredentialManagementInstrumentedTests.java +++ b/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/fido/Ctap2CredentialManagementInstrumentedTests.java @@ -22,7 +22,6 @@ import com.yubico.yubikit.testing.desktop.SmokeTest; import com.yubico.yubikit.testing.desktop.framework.FidoInstrumentedTests; import com.yubico.yubikit.testing.fido.Ctap2CredentialManagementTests; - import org.junit.Test; import org.junit.experimental.categories.Category; import org.junit.runner.RunWith; @@ -30,34 +29,34 @@ @RunWith(Suite.class) @Suite.SuiteClasses({ - Ctap2CredentialManagementInstrumentedTests.PinUvAuthV2Test.class, - Ctap2CredentialManagementInstrumentedTests.PinUvAuthV1Test.class, + Ctap2CredentialManagementInstrumentedTests.PinUvAuthV2Test.class, + Ctap2CredentialManagementInstrumentedTests.PinUvAuthV1Test.class, }) public class Ctap2CredentialManagementInstrumentedTests { - public static class PinUvAuthV2Test extends FidoInstrumentedTests { - @Test - public void testReadMetadata() throws Throwable { - withCtap2Session(Ctap2CredentialManagementTests::testReadMetadata); - } + public static class PinUvAuthV2Test extends FidoInstrumentedTests { + @Test + public void testReadMetadata() throws Throwable { + withCtap2Session(Ctap2CredentialManagementTests::testReadMetadata); + } - @Test - @Category(SmokeTest.class) - public void testManagement() throws Throwable { - withCtap2Session(Ctap2CredentialManagementTests::testManagement); - } + @Test + @Category(SmokeTest.class) + public void testManagement() throws Throwable { + withCtap2Session(Ctap2CredentialManagementTests::testManagement); + } - @Test - @Category(SmokeTest.class) - public void testUpdateUserInformation() throws Throwable { - withCtap2Session(Ctap2CredentialManagementTests::testUpdateUserInformation); - } + @Test + @Category(SmokeTest.class) + public void testUpdateUserInformation() throws Throwable { + withCtap2Session(Ctap2CredentialManagementTests::testUpdateUserInformation); } + } - @Category(PinUvAuthProtocolV1Test.class) - public static class PinUvAuthV1Test extends PinUvAuthV2Test { - @Override - protected PinUvAuthProtocol getPinUvAuthProtocol() { - return new PinUvAuthProtocolV1(); - } + @Category(PinUvAuthProtocolV1Test.class) + public static class PinUvAuthV1Test extends PinUvAuthV2Test { + @Override + protected PinUvAuthProtocol getPinUvAuthProtocol() { + return new PinUvAuthProtocolV1(); } + } } diff --git a/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/fido/Ctap2SessionInstrumentedTests.java b/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/fido/Ctap2SessionInstrumentedTests.java index 060edfbe..986b1c6d 100644 --- a/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/fido/Ctap2SessionInstrumentedTests.java +++ b/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/fido/Ctap2SessionInstrumentedTests.java @@ -22,7 +22,6 @@ import com.yubico.yubikit.testing.desktop.SmokeTest; import com.yubico.yubikit.testing.desktop.framework.FidoInstrumentedTests; import com.yubico.yubikit.testing.fido.Ctap2SessionTests; - import org.junit.Test; import org.junit.experimental.categories.Category; import org.junit.runner.RunWith; @@ -30,33 +29,33 @@ @RunWith(Suite.class) @Suite.SuiteClasses({ - Ctap2SessionInstrumentedTests.PinUvAuthV2Test.class, - Ctap2SessionInstrumentedTests.PinUvAuthV1Test.class, + Ctap2SessionInstrumentedTests.PinUvAuthV2Test.class, + Ctap2SessionInstrumentedTests.PinUvAuthV1Test.class, }) public class Ctap2SessionInstrumentedTests { - public static class PinUvAuthV2Test extends FidoInstrumentedTests { - @Test - @Category(SmokeTest.class) - public void testCtap2GetInfo() throws Throwable { - withCtap2Session(Ctap2SessionTests::testCtap2GetInfo); - } + public static class PinUvAuthV2Test extends FidoInstrumentedTests { + @Test + @Category(SmokeTest.class) + public void testCtap2GetInfo() throws Throwable { + withCtap2Session(Ctap2SessionTests::testCtap2GetInfo); + } - @Test - public void testCancelCborCommandImmediate() throws Throwable { - withCtap2Session(Ctap2SessionTests::testCancelCborCommandImmediate); - } + @Test + public void testCancelCborCommandImmediate() throws Throwable { + withCtap2Session(Ctap2SessionTests::testCancelCborCommandImmediate); + } - @Test - public void testCancelCborCommandAfterDelay() throws Throwable { - withCtap2Session(Ctap2SessionTests::testCancelCborCommandAfterDelay); - } + @Test + public void testCancelCborCommandAfterDelay() throws Throwable { + withCtap2Session(Ctap2SessionTests::testCancelCborCommandAfterDelay); } + } - @Category(PinUvAuthProtocolV1Test.class) - public static class PinUvAuthV1Test extends PinUvAuthV2Test { - @Override - protected PinUvAuthProtocol getPinUvAuthProtocol() { - return new PinUvAuthProtocolV1(); - } + @Category(PinUvAuthProtocolV1Test.class) + public static class PinUvAuthV1Test extends PinUvAuthV2Test { + @Override + protected PinUvAuthProtocol getPinUvAuthProtocol() { + return new PinUvAuthProtocolV1(); } + } } diff --git a/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/fido/Ctap2SessionResetInstrumentedTests.java b/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/fido/Ctap2SessionResetInstrumentedTests.java index 38d27148..0e270d31 100644 --- a/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/fido/Ctap2SessionResetInstrumentedTests.java +++ b/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/fido/Ctap2SessionResetInstrumentedTests.java @@ -22,7 +22,6 @@ import com.yubico.yubikit.testing.desktop.PinUvAuthProtocolV1Test; import com.yubico.yubikit.testing.desktop.framework.FidoInstrumentedTests; import com.yubico.yubikit.testing.fido.Ctap2SessionTests; - import org.junit.Test; import org.junit.experimental.categories.Category; import org.junit.runner.RunWith; @@ -30,32 +29,33 @@ /** * Tests FIDO Reset. - *

- * This is a manual test which will reset the FIDO application. + * + *

This is a manual test which will reset the FIDO application. + * *

    - *
  • Before running the test, disconnect the YubiKey from the Android device.
  • - *
  • YubiKey Bio devices are currently ignored.
  • + *
  • Before running the test, disconnect the YubiKey from the Android device. + *
  • YubiKey Bio devices are currently ignored. *
*/ @RunWith(Suite.class) @Suite.SuiteClasses({ - Ctap2SessionResetInstrumentedTests.PinUvAuthV2Test.class, - Ctap2SessionResetInstrumentedTests.PinUvAuthV1Test.class, + Ctap2SessionResetInstrumentedTests.PinUvAuthV2Test.class, + Ctap2SessionResetInstrumentedTests.PinUvAuthV1Test.class, }) public class Ctap2SessionResetInstrumentedTests { - public static class PinUvAuthV2Test extends FidoInstrumentedTests { - @Test - @Category(AlwaysManualTest.class) - public void testReset() throws Throwable { - withDevice(false, Ctap2SessionTests::testReset); - } + public static class PinUvAuthV2Test extends FidoInstrumentedTests { + @Test + @Category(AlwaysManualTest.class) + public void testReset() throws Throwable { + withDevice(false, Ctap2SessionTests::testReset); } + } - @Category(PinUvAuthProtocolV1Test.class) - public static class PinUvAuthV1Test extends PinUvAuthV2Test { - @Override - protected PinUvAuthProtocol getPinUvAuthProtocol() { - return new PinUvAuthProtocolV1(); - } + @Category(PinUvAuthProtocolV1Test.class) + public static class PinUvAuthV1Test extends PinUvAuthV2Test { + @Override + protected PinUvAuthProtocol getPinUvAuthProtocol() { + return new PinUvAuthProtocolV1(); } + } } diff --git a/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/fido/EnterpriseAttestationInstrumentedTests.java b/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/fido/EnterpriseAttestationInstrumentedTests.java index 4a31f746..e865b00a 100644 --- a/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/fido/EnterpriseAttestationInstrumentedTests.java +++ b/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/fido/EnterpriseAttestationInstrumentedTests.java @@ -21,7 +21,6 @@ import com.yubico.yubikit.testing.desktop.PinUvAuthProtocolV1Test; import com.yubico.yubikit.testing.desktop.framework.FidoInstrumentedTests; import com.yubico.yubikit.testing.fido.EnterpriseAttestationTests; - import org.junit.Test; import org.junit.experimental.categories.Category; import org.junit.runner.RunWith; @@ -29,37 +28,37 @@ @RunWith(Suite.class) @Suite.SuiteClasses({ - EnterpriseAttestationInstrumentedTests.PinUvAuthV2Test.class, - EnterpriseAttestationInstrumentedTests.PinUvAuthV1Test.class, + EnterpriseAttestationInstrumentedTests.PinUvAuthV2Test.class, + EnterpriseAttestationInstrumentedTests.PinUvAuthV1Test.class, }) public class EnterpriseAttestationInstrumentedTests { - public static class PinUvAuthV2Test extends FidoInstrumentedTests { - @Test - public void testSupportedPlatformManagedEA() throws Throwable { - withCtap2Session(EnterpriseAttestationTests::testSupportedPlatformManagedEA); - } + public static class PinUvAuthV2Test extends FidoInstrumentedTests { + @Test + public void testSupportedPlatformManagedEA() throws Throwable { + withCtap2Session(EnterpriseAttestationTests::testSupportedPlatformManagedEA); + } - @Test - public void testUnsupportedPlatformManagedEA() throws Throwable { - withCtap2Session(EnterpriseAttestationTests::testUnsupportedPlatformManagedEA); - } + @Test + public void testUnsupportedPlatformManagedEA() throws Throwable { + withCtap2Session(EnterpriseAttestationTests::testUnsupportedPlatformManagedEA); + } - @Test - public void testCreateOptionsAttestationPreference() throws Throwable { - withDevice(EnterpriseAttestationTests::testCreateOptionsAttestationPreference); - } + @Test + public void testCreateOptionsAttestationPreference() throws Throwable { + withDevice(EnterpriseAttestationTests::testCreateOptionsAttestationPreference); + } - @Test - public void testVendorFacilitatedEA() throws Throwable { - withCtap2Session(EnterpriseAttestationTests::testVendorFacilitatedEA); - } + @Test + public void testVendorFacilitatedEA() throws Throwable { + withCtap2Session(EnterpriseAttestationTests::testVendorFacilitatedEA); } + } - @Category(PinUvAuthProtocolV1Test.class) - public static class PinUvAuthV1Test extends PinUvAuthV2Test { - @Override - protected PinUvAuthProtocol getPinUvAuthProtocol() { - return new PinUvAuthProtocolV1(); - } + @Category(PinUvAuthProtocolV1Test.class) + public static class PinUvAuthV1Test extends PinUvAuthV2Test { + @Override + protected PinUvAuthProtocol getPinUvAuthProtocol() { + return new PinUvAuthProtocolV1(); } + } } diff --git a/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/fido/FidoTests.java b/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/fido/FidoTests.java index 8d3126a8..a3d2ac22 100644 --- a/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/fido/FidoTests.java +++ b/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/fido/FidoTests.java @@ -17,30 +17,29 @@ package com.yubico.yubikit.testing.desktop.fido; import com.yubico.yubikit.testing.desktop.AlwaysManualTest; - import org.junit.experimental.categories.Categories; import org.junit.runner.RunWith; import org.junit.runners.Suite; /** * Setup YubiKey before running the integration tests: + * *
    - *
  • reset the FIDO application
  • - *
  • optionally set PIN to `11234567`
  • + *
  • reset the FIDO application + *
  • optionally set PIN to `11234567` *
*/ @RunWith(Categories.class) @Suite.SuiteClasses({ - BasicWebAuthnClientInstrumentedTests.class, - Ctap2ClientPinInstrumentedTests.class, - Ctap2CredentialManagementInstrumentedTests.class, - Ctap2SessionInstrumentedTests.class, - EnterpriseAttestationInstrumentedTests.class, - UvDiscouragedInstrumentedTests.class, - Ctap2ConfigInstrumentedTests.class, - Ctap2BioEnrollmentInstrumentedTests.class, - Ctap2SessionResetInstrumentedTests.class, + BasicWebAuthnClientInstrumentedTests.class, + Ctap2ClientPinInstrumentedTests.class, + Ctap2CredentialManagementInstrumentedTests.class, + Ctap2SessionInstrumentedTests.class, + EnterpriseAttestationInstrumentedTests.class, + UvDiscouragedInstrumentedTests.class, + Ctap2ConfigInstrumentedTests.class, + Ctap2BioEnrollmentInstrumentedTests.class, + Ctap2SessionResetInstrumentedTests.class, }) @Categories.ExcludeCategory(AlwaysManualTest.class) -public class FidoTests { -} +public class FidoTests {} diff --git a/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/fido/UvDiscouragedInstrumentedTests.java b/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/fido/UvDiscouragedInstrumentedTests.java index bdbef4f9..3da5b8c5 100644 --- a/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/fido/UvDiscouragedInstrumentedTests.java +++ b/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/fido/UvDiscouragedInstrumentedTests.java @@ -20,33 +20,31 @@ import com.yubico.yubikit.testing.desktop.AlwaysManualTest; import com.yubico.yubikit.testing.desktop.framework.FidoInstrumentedTests; import com.yubico.yubikit.testing.fido.BasicWebAuthnClientTests; - import org.junit.Test; import org.junit.experimental.categories.Category; public class UvDiscouragedInstrumentedTests extends FidoInstrumentedTests { - /** - * Reset the FIDO application before running this test. - *

- * The test will make credential/get assertion without using the PIN which is acceptable for - * {@code UserVerificationRequirement.DISCOURAGED}. - *

- * Skipped on FIPS approved devices. - */ - @Test - @Category(AlwaysManualTest.class) - public void testMakeCredentialGetAssertion() throws Throwable { - withDevice(false, BasicWebAuthnClientTests::testUvDiscouragedMcGa_noPin); - } + /** + * Reset the FIDO application before running this test. + * + *

The test will make credential/get assertion without using the PIN which is acceptable for + * {@code UserVerificationRequirement.DISCOURAGED}. + * + *

Skipped on FIPS approved devices. + */ + @Test + @Category(AlwaysManualTest.class) + public void testMakeCredentialGetAssertion() throws Throwable { + withDevice(false, BasicWebAuthnClientTests::testUvDiscouragedMcGa_noPin); + } - /** - * This test will make credential without passing PIN value on a device which is protected by - * PIN. - *

- * Expected to fail with PinRequiredClientError - */ - @Test(expected = PinRequiredClientError.class) - public void testMakeCredentialGetAssertionWithPin() throws Throwable { - withDevice(BasicWebAuthnClientTests::testUvDiscouragedMcGa_withPin); - } + /** + * This test will make credential without passing PIN value on a device which is protected by PIN. + * + *

Expected to fail with PinRequiredClientError + */ + @Test(expected = PinRequiredClientError.class) + public void testMakeCredentialGetAssertionWithPin() throws Throwable { + withDevice(BasicWebAuthnClientTests::testUvDiscouragedMcGa_withPin); + } } diff --git a/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/management/ManagementTests.java b/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/management/ManagementTests.java index 0ae91297..a88baf7b 100644 --- a/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/management/ManagementTests.java +++ b/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/management/ManagementTests.java @@ -18,12 +18,11 @@ import com.yubico.yubikit.testing.desktop.framework.ManagementInstrumentedTests; import com.yubico.yubikit.testing.management.ManagementDeviceTests; - import org.junit.Test; public class ManagementTests extends ManagementInstrumentedTests { - @Test - public void testNfcRestricted() throws Throwable { - withManagementSession(ManagementDeviceTests::testNfcRestricted); - } + @Test + public void testNfcRestricted() throws Throwable { + withManagementSession(ManagementDeviceTests::testNfcRestricted); + } } diff --git a/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/mpe/MultiProtocolResetTests.java b/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/mpe/MultiProtocolResetTests.java index cd419ab6..be73b78a 100644 --- a/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/mpe/MultiProtocolResetTests.java +++ b/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/mpe/MultiProtocolResetTests.java @@ -19,7 +19,6 @@ import com.yubico.yubikit.core.smartcard.scp.ScpKid; import com.yubico.yubikit.testing.desktop.framework.MpeInstrumentedTests; import com.yubico.yubikit.testing.mpe.MultiProtocolResetDeviceTests; - import org.jetbrains.annotations.Nullable; import org.junit.Test; import org.junit.runner.RunWith; @@ -27,32 +26,32 @@ @RunWith(Suite.class) @Suite.SuiteClasses({ - MultiProtocolResetTests.NoScpTests.class, - MultiProtocolResetTests.Scp11bTests.class, + MultiProtocolResetTests.NoScpTests.class, + MultiProtocolResetTests.Scp11bTests.class, }) public class MultiProtocolResetTests { - public static class NoScpTests extends MpeInstrumentedTests { - @Test - public void testSettingPivPinBlocksFidoReset() throws Throwable { - withPivSession(MultiProtocolResetDeviceTests::testSettingPivPinBlocksFidoReset); - } + public static class NoScpTests extends MpeInstrumentedTests { + @Test + public void testSettingPivPinBlocksFidoReset() throws Throwable { + withPivSession(MultiProtocolResetDeviceTests::testSettingPivPinBlocksFidoReset); + } - @Test - public void testPivOperationBlocksFidoReset() throws Throwable { - withPivSession(MultiProtocolResetDeviceTests::testPivOperationBlocksFidoReset); - } + @Test + public void testPivOperationBlocksFidoReset() throws Throwable { + withPivSession(MultiProtocolResetDeviceTests::testPivOperationBlocksFidoReset); + } - @Test - public void testSettingFidoPinBlocksPivReset() throws Throwable { - withCtap2Session(MultiProtocolResetDeviceTests::testSettingFidoPinBlocksPivReset); - } + @Test + public void testSettingFidoPinBlocksPivReset() throws Throwable { + withCtap2Session(MultiProtocolResetDeviceTests::testSettingFidoPinBlocksPivReset); } + } - public static class Scp11bTests extends NoScpTests { - @Nullable - @Override - protected Byte getScpKid() { - return ScpKid.SCP11b; - } + public static class Scp11bTests extends NoScpTests { + @Nullable + @Override + protected Byte getScpKid() { + return ScpKid.SCP11b; } + } } diff --git a/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/oath/OathTests.java b/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/oath/OathTests.java index 975422d3..46f0306b 100644 --- a/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/oath/OathTests.java +++ b/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/oath/OathTests.java @@ -20,7 +20,6 @@ import com.yubico.yubikit.testing.desktop.SmokeTest; import com.yubico.yubikit.testing.desktop.framework.OathInstrumentedTests; import com.yubico.yubikit.testing.oath.OathDeviceTests; - import org.jetbrains.annotations.Nullable; import org.junit.Test; import org.junit.experimental.categories.Category; @@ -29,39 +28,39 @@ @RunWith(Suite.class) @Suite.SuiteClasses({ - OathTests.NoScpTests.class, - OathTests.Scp11bTests.class, + OathTests.NoScpTests.class, + OathTests.Scp11bTests.class, }) public class OathTests { - public static class NoScpTests extends OathInstrumentedTests { - @Test - @Category(SmokeTest.class) - public void testChangePassword() throws Throwable { - withDevice(OathDeviceTests::testChangePassword); - } + public static class NoScpTests extends OathInstrumentedTests { + @Test + @Category(SmokeTest.class) + public void testChangePassword() throws Throwable { + withDevice(OathDeviceTests::testChangePassword); + } - @Test - public void testResetPassword() throws Throwable { - withOathSession(OathDeviceTests::testRemovePassword); - } + @Test + public void testResetPassword() throws Throwable { + withOathSession(OathDeviceTests::testRemovePassword); + } - @Test - @Category(SmokeTest.class) - public void testAccountManagement() throws Throwable { - withOathSession(OathDeviceTests::testAccountManagement); - } + @Test + @Category(SmokeTest.class) + public void testAccountManagement() throws Throwable { + withOathSession(OathDeviceTests::testAccountManagement); + } - @Test - public void testRenameAccount() throws Throwable { - withOathSession(OathDeviceTests::testRenameAccount); - } + @Test + public void testRenameAccount() throws Throwable { + withOathSession(OathDeviceTests::testRenameAccount); } + } - public static class Scp11bTests extends NoScpTests { - @Nullable - @Override - protected Byte getScpKid() { - return ScpKid.SCP11b; - } + public static class Scp11bTests extends NoScpTests { + @Nullable + @Override + protected Byte getScpKid() { + return ScpKid.SCP11b; } + } } diff --git a/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/openpgp/OpenPgpTests.java b/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/openpgp/OpenPgpTests.java index f188b8e7..51ca8713 100644 --- a/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/openpgp/OpenPgpTests.java +++ b/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/openpgp/OpenPgpTests.java @@ -21,7 +21,6 @@ import com.yubico.yubikit.testing.desktop.SmokeTest; import com.yubico.yubikit.testing.desktop.framework.OpenPgpInstrumentedTests; import com.yubico.yubikit.testing.openpgp.OpenPgpDeviceTests; - import org.jetbrains.annotations.Nullable; import org.junit.Test; import org.junit.experimental.categories.Category; @@ -30,125 +29,125 @@ @RunWith(Suite.class) @Suite.SuiteClasses({ - OpenPgpTests.NoScpTests.class, - OpenPgpTests.Scp11bTests.class, + OpenPgpTests.NoScpTests.class, + OpenPgpTests.Scp11bTests.class, }) public class OpenPgpTests { - public static class NoScpTests extends OpenPgpInstrumentedTests { - @Test - public void testImportRsaKeys() throws Throwable { - withOpenPgpSession(OpenPgpDeviceTests::testImportRsaKeys); - } - - @Test - public void testImportEcDsaKeys() throws Throwable { - withOpenPgpSession(OpenPgpDeviceTests::testImportEcDsaKeys); - } - - @Test - public void testImportEd25519Keys() throws Throwable { - withOpenPgpSession(OpenPgpDeviceTests::testImportEd25519); - } - - @Test - public void testImportX25519Keys() throws Throwable { - withOpenPgpSession(OpenPgpDeviceTests::testImportX25519); - } - - @Test - public void testGenerateRequiresAdmin() throws Throwable { - withOpenPgpSession(OpenPgpDeviceTests::testGenerateRequiresAdmin); - } - - @Test - public void testChangePin() throws Throwable { - withOpenPgpSession(OpenPgpDeviceTests::testChangePin); - } - - @Test - public void testResetPin() throws Throwable { - withOpenPgpSession(OpenPgpDeviceTests::testResetPin); - } - - @Test - public void testSetPinAttempts() throws Throwable { - withOpenPgpSession(OpenPgpDeviceTests::testSetPinAttempts); - } - - @Test - @Category(SlowTest.class) - public void testGenerateRsaKeys() throws Throwable { - withOpenPgpSession(OpenPgpDeviceTests::testGenerateRsaKeys); - } - - @Test - public void testGenerateEcKeys() throws Throwable { - withOpenPgpSession(OpenPgpDeviceTests::testGenerateEcKeys); - } - - @Test - public void testGenerateEd25519() throws Throwable { - withOpenPgpSession(OpenPgpDeviceTests::testGenerateEd25519); - } - - @Test - public void testGenerateX25519() throws Throwable { - withOpenPgpSession(OpenPgpDeviceTests::testGenerateX25519); - } - - @Test - public void testAttestation() throws Throwable { - withOpenPgpSession(OpenPgpDeviceTests::testAttestation); - } - - @Test - @Category(SmokeTest.class) - public void testSigPinPolicy() throws Throwable { - withOpenPgpSession(OpenPgpDeviceTests::testSigPinPolicy); - } - - @Test - public void testKdf() throws Throwable { - withOpenPgpSession(OpenPgpDeviceTests::testKdf); - } - - @Test - public void testUnverifyPin() throws Throwable { - withOpenPgpSession(OpenPgpDeviceTests::testUnverifyPin); - } - - @Test - public void testDeleteKey() throws Throwable { - withOpenPgpSession(OpenPgpDeviceTests::testDeleteKey); - } - - @Test - public void testCertificateManagement() throws Throwable { - withOpenPgpSession(OpenPgpDeviceTests::testCertificateManagement); - } - - @Test - @Category(SmokeTest.class) - public void testGetChallenge() throws Throwable { - withOpenPgpSession(OpenPgpDeviceTests::testGetChallenge); - } - - @Test - public void testSetUif() throws Throwable { - withOpenPgpSession(OpenPgpDeviceTests::testSetUif); - } - - @Test - public void testPinComplexity() throws Throwable { - withOpenPgpSession(OpenPgpDeviceTests::testPinComplexity); - } - } - - public static class Scp11bTests extends NoScpTests { - @Nullable - @Override - protected Byte getScpKid() { - return ScpKid.SCP11b; - } + public static class NoScpTests extends OpenPgpInstrumentedTests { + @Test + public void testImportRsaKeys() throws Throwable { + withOpenPgpSession(OpenPgpDeviceTests::testImportRsaKeys); + } + + @Test + public void testImportEcDsaKeys() throws Throwable { + withOpenPgpSession(OpenPgpDeviceTests::testImportEcDsaKeys); + } + + @Test + public void testImportEd25519Keys() throws Throwable { + withOpenPgpSession(OpenPgpDeviceTests::testImportEd25519); + } + + @Test + public void testImportX25519Keys() throws Throwable { + withOpenPgpSession(OpenPgpDeviceTests::testImportX25519); + } + + @Test + public void testGenerateRequiresAdmin() throws Throwable { + withOpenPgpSession(OpenPgpDeviceTests::testGenerateRequiresAdmin); + } + + @Test + public void testChangePin() throws Throwable { + withOpenPgpSession(OpenPgpDeviceTests::testChangePin); + } + + @Test + public void testResetPin() throws Throwable { + withOpenPgpSession(OpenPgpDeviceTests::testResetPin); + } + + @Test + public void testSetPinAttempts() throws Throwable { + withOpenPgpSession(OpenPgpDeviceTests::testSetPinAttempts); + } + + @Test + @Category(SlowTest.class) + public void testGenerateRsaKeys() throws Throwable { + withOpenPgpSession(OpenPgpDeviceTests::testGenerateRsaKeys); + } + + @Test + public void testGenerateEcKeys() throws Throwable { + withOpenPgpSession(OpenPgpDeviceTests::testGenerateEcKeys); + } + + @Test + public void testGenerateEd25519() throws Throwable { + withOpenPgpSession(OpenPgpDeviceTests::testGenerateEd25519); + } + + @Test + public void testGenerateX25519() throws Throwable { + withOpenPgpSession(OpenPgpDeviceTests::testGenerateX25519); + } + + @Test + public void testAttestation() throws Throwable { + withOpenPgpSession(OpenPgpDeviceTests::testAttestation); + } + + @Test + @Category(SmokeTest.class) + public void testSigPinPolicy() throws Throwable { + withOpenPgpSession(OpenPgpDeviceTests::testSigPinPolicy); + } + + @Test + public void testKdf() throws Throwable { + withOpenPgpSession(OpenPgpDeviceTests::testKdf); + } + + @Test + public void testUnverifyPin() throws Throwable { + withOpenPgpSession(OpenPgpDeviceTests::testUnverifyPin); + } + + @Test + public void testDeleteKey() throws Throwable { + withOpenPgpSession(OpenPgpDeviceTests::testDeleteKey); + } + + @Test + public void testCertificateManagement() throws Throwable { + withOpenPgpSession(OpenPgpDeviceTests::testCertificateManagement); + } + + @Test + @Category(SmokeTest.class) + public void testGetChallenge() throws Throwable { + withOpenPgpSession(OpenPgpDeviceTests::testGetChallenge); + } + + @Test + public void testSetUif() throws Throwable { + withOpenPgpSession(OpenPgpDeviceTests::testSetUif); + } + + @Test + public void testPinComplexity() throws Throwable { + withOpenPgpSession(OpenPgpDeviceTests::testPinComplexity); + } + } + + public static class Scp11bTests extends NoScpTests { + @Nullable + @Override + protected Byte getScpKid() { + return ScpKid.SCP11b; } + } } diff --git a/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/piv/PivBioMultiProtocolTests.java b/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/piv/PivBioMultiProtocolTests.java index 95226b19..67897bd0 100644 --- a/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/piv/PivBioMultiProtocolTests.java +++ b/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/piv/PivBioMultiProtocolTests.java @@ -18,13 +18,12 @@ import com.yubico.yubikit.testing.desktop.framework.PivInstrumentedTests; import com.yubico.yubikit.testing.piv.PivBioMultiProtocolDeviceTests; - import org.junit.Test; public class PivBioMultiProtocolTests extends PivInstrumentedTests { - @Test - public void testAuthenticate() throws Throwable { - withPivSession(PivBioMultiProtocolDeviceTests::testAuthenticate); - } + @Test + public void testAuthenticate() throws Throwable { + withPivSession(PivBioMultiProtocolDeviceTests::testAuthenticate); + } } diff --git a/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/piv/PivJcaProviderTests.java b/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/piv/PivJcaProviderTests.java index 45949cf1..ae01f8b5 100644 --- a/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/piv/PivJcaProviderTests.java +++ b/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/piv/PivJcaProviderTests.java @@ -24,7 +24,6 @@ import com.yubico.yubikit.testing.piv.PivJcaDeviceTests; import com.yubico.yubikit.testing.piv.PivJcaSigningTests; import com.yubico.yubikit.testing.piv.PivMoveKeyTests; - import org.jetbrains.annotations.Nullable; import org.junit.Test; import org.junit.experimental.categories.Category; @@ -34,48 +33,48 @@ @RunWith(JUnit4.class) public class PivJcaProviderTests { - public static class NoScpTests extends PivInstrumentedTests { - @Test - @Category(SlowTest.class) - public void testGenerateKeys() throws Throwable { - withPivSession(PivJcaDeviceTests::testGenerateKeys); - } + public static class NoScpTests extends PivInstrumentedTests { + @Test + @Category(SlowTest.class) + public void testGenerateKeys() throws Throwable { + withPivSession(PivJcaDeviceTests::testGenerateKeys); + } - @Test - @Category(SlowTest.class) - public void testGenerateKeysPreferBC() throws Throwable { - withPivSession(PivJcaDeviceTests::testGenerateKeysPreferBC); - } + @Test + @Category(SlowTest.class) + public void testGenerateKeysPreferBC() throws Throwable { + withPivSession(PivJcaDeviceTests::testGenerateKeysPreferBC); + } - @Test - @Category(SmokeTest.class) - public void testImportKeys() throws Throwable { - withPivSession(PivJcaDeviceTests::testImportKeys); - } + @Test + @Category(SmokeTest.class) + public void testImportKeys() throws Throwable { + withPivSession(PivJcaDeviceTests::testImportKeys); + } - @Test - @Category(SlowTest.class) - public void testSigning() throws Throwable { - withPivSession(PivJcaSigningTests::testSign); - } + @Test + @Category(SlowTest.class) + public void testSigning() throws Throwable { + withPivSession(PivJcaSigningTests::testSign); + } - @Test - @Category(SlowTest.class) - public void testDecrypt() throws Throwable { - withPivSession(PivJcaDecryptTests::testDecrypt); - } + @Test + @Category(SlowTest.class) + public void testDecrypt() throws Throwable { + withPivSession(PivJcaDecryptTests::testDecrypt); + } - @Test - public void testMoveKey() throws Throwable { - withPivSession(PivMoveKeyTests::moveKey); - } + @Test + public void testMoveKey() throws Throwable { + withPivSession(PivMoveKeyTests::moveKey); } + } - public static class Scp11bTests extends NoScpTests { - @Nullable - @Override - protected Byte getScpKid() { - return ScpKid.SCP11b; - } + public static class Scp11bTests extends NoScpTests { + @Nullable + @Override + protected Byte getScpKid() { + return ScpKid.SCP11b; } + } } diff --git a/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/piv/PivTests.java b/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/piv/PivTests.java index cdfadc5b..4d1ffefb 100644 --- a/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/piv/PivTests.java +++ b/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/piv/PivTests.java @@ -22,7 +22,6 @@ import com.yubico.yubikit.testing.piv.PivCertificateTests; import com.yubico.yubikit.testing.piv.PivDeviceTests; import com.yubico.yubikit.testing.piv.PivPinComplexityDeviceTests; - import org.jetbrains.annotations.Nullable; import org.junit.Test; import org.junit.experimental.categories.Category; @@ -31,56 +30,56 @@ @RunWith(Suite.class) @Suite.SuiteClasses({ - PivTests.NoScpTests.class, - PivTests.Scp11bTests.class, - PivJcaProviderTests.NoScpTests.class, - PivJcaProviderTests.Scp11bTests.class + PivTests.NoScpTests.class, + PivTests.Scp11bTests.class, + PivJcaProviderTests.NoScpTests.class, + PivJcaProviderTests.Scp11bTests.class }) public class PivTests { - public static class NoScpTests extends PivInstrumentedTests { - @Test - @Category(SmokeTest.class) - public void testPin() throws Throwable { - withPivSession(PivDeviceTests::testPin); - } + public static class NoScpTests extends PivInstrumentedTests { + @Test + @Category(SmokeTest.class) + public void testPin() throws Throwable { + withPivSession(PivDeviceTests::testPin); + } - @Test - public void testPuk() throws Throwable { - withPivSession(PivDeviceTests::testPuk); - } + @Test + public void testPuk() throws Throwable { + withPivSession(PivDeviceTests::testPuk); + } - @Test - public void testManagementKey() throws Throwable { - withPivSession(PivDeviceTests::testManagementKey); - } + @Test + public void testManagementKey() throws Throwable { + withPivSession(PivDeviceTests::testManagementKey); + } - @Test - public void testManagementKeyType() throws Throwable { - withPivSession(PivDeviceTests::testManagementKeyType); - } + @Test + public void testManagementKeyType() throws Throwable { + withPivSession(PivDeviceTests::testManagementKeyType); + } - @Test - public void testPutUncompressedCertificate() throws Throwable { - withPivSession(PivCertificateTests::putUncompressedCertificate); - } + @Test + public void testPutUncompressedCertificate() throws Throwable { + withPivSession(PivCertificateTests::putUncompressedCertificate); + } - @Test - @Category(SmokeTest.class) - public void testPutCompressedCertificate() throws Throwable { - withPivSession(PivCertificateTests::putCompressedCertificate); - } + @Test + @Category(SmokeTest.class) + public void testPutCompressedCertificate() throws Throwable { + withPivSession(PivCertificateTests::putCompressedCertificate); + } - @Test - public void testPinComplexity() throws Throwable { - withPivSession(PivPinComplexityDeviceTests::testPinComplexity); - } + @Test + public void testPinComplexity() throws Throwable { + withPivSession(PivPinComplexityDeviceTests::testPinComplexity); } + } - public static class Scp11bTests extends NoScpTests { - @Override - @Nullable - protected Byte getScpKid() { - return ScpKid.SCP11b; - } + public static class Scp11bTests extends NoScpTests { + @Override + @Nullable + protected Byte getScpKid() { + return ScpKid.SCP11b; } + } } diff --git a/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/sd/Scp03Tests.java b/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/sd/Scp03Tests.java index 8e89a8c9..4d679260 100644 --- a/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/sd/Scp03Tests.java +++ b/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/sd/Scp03Tests.java @@ -19,35 +19,35 @@ import com.yubico.yubikit.testing.desktop.SmokeTest; import com.yubico.yubikit.testing.desktop.framework.SecurityDomainInstrumentedTests; import com.yubico.yubikit.testing.sd.Scp03DeviceTests; - import org.junit.Before; import org.junit.Test; import org.junit.experimental.categories.Category; public class Scp03Tests extends SecurityDomainInstrumentedTests { - @Before - public void before() throws Throwable { - withState(Scp03DeviceTests::before); - } - @Test - public void testImportKey() throws Throwable { - withState(Scp03DeviceTests::testImportKey); - } - - @Test - public void testDeleteKey() throws Throwable { - withState(Scp03DeviceTests::testDeleteKey); - } - - @Test - @Category(SmokeTest.class) - public void testReplaceKey() throws Throwable { - withState(Scp03DeviceTests::testReplaceKey); - } - - @Test - public void testWrongKey() throws Throwable { - withState(Scp03DeviceTests::testWrongKey); - } + @Before + public void before() throws Throwable { + withState(Scp03DeviceTests::before); + } + + @Test + public void testImportKey() throws Throwable { + withState(Scp03DeviceTests::testImportKey); + } + + @Test + public void testDeleteKey() throws Throwable { + withState(Scp03DeviceTests::testDeleteKey); + } + + @Test + @Category(SmokeTest.class) + public void testReplaceKey() throws Throwable { + withState(Scp03DeviceTests::testReplaceKey); + } + + @Test + public void testWrongKey() throws Throwable { + withState(Scp03DeviceTests::testWrongKey); + } } diff --git a/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/sd/Scp11Tests.java b/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/sd/Scp11Tests.java index f0de181f..b6e296cc 100644 --- a/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/sd/Scp11Tests.java +++ b/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/sd/Scp11Tests.java @@ -18,49 +18,48 @@ import com.yubico.yubikit.testing.desktop.framework.SecurityDomainInstrumentedTests; import com.yubico.yubikit.testing.sd.Scp11DeviceTests; - import org.junit.Before; import org.junit.Test; public class Scp11Tests extends SecurityDomainInstrumentedTests { - @Before - public void before() throws Throwable { - withState(Scp11DeviceTests::before); - } + @Before + public void before() throws Throwable { + withState(Scp11DeviceTests::before); + } - @Test - public void testScp11aAuthenticate() throws Throwable { - withState(Scp11DeviceTests::testScp11aAuthenticate); - } + @Test + public void testScp11aAuthenticate() throws Throwable { + withState(Scp11DeviceTests::testScp11aAuthenticate); + } - @Test - public void testScp11aAllowlist() throws Throwable { - withState(Scp11DeviceTests::testScp11aAllowList); - } + @Test + public void testScp11aAllowlist() throws Throwable { + withState(Scp11DeviceTests::testScp11aAllowList); + } - @Test - public void testScp11aAllowlistBlocked() throws Throwable { - withState(Scp11DeviceTests::testScp11aAllowListBlocked); - } + @Test + public void testScp11aAllowlistBlocked() throws Throwable { + withState(Scp11DeviceTests::testScp11aAllowListBlocked); + } - @Test - public void testScp11bAuthenticate() throws Throwable { - withState(Scp11DeviceTests::testScp11bAuthenticate); - } + @Test + public void testScp11bAuthenticate() throws Throwable { + withState(Scp11DeviceTests::testScp11bAuthenticate); + } - @Test - public void testScp11bWrongPubKey() throws Throwable { - withState(Scp11DeviceTests::testScp11bWrongPubKey); - } + @Test + public void testScp11bWrongPubKey() throws Throwable { + withState(Scp11DeviceTests::testScp11bWrongPubKey); + } - @Test - public void testScp11bImport() throws Throwable { - withState(Scp11DeviceTests::testScp11bImport); - } + @Test + public void testScp11bImport() throws Throwable { + withState(Scp11DeviceTests::testScp11bImport); + } - @Test - public void testScp11cAuthenticate() throws Throwable { - withState(Scp11DeviceTests::testScp11cAuthenticate); - } + @Test + public void testScp11cAuthenticate() throws Throwable { + withState(Scp11DeviceTests::testScp11cAuthenticate); + } } diff --git a/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/sd/SecurityDomainTests.java b/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/sd/SecurityDomainTests.java index 8886583d..1a5f26aa 100644 --- a/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/sd/SecurityDomainTests.java +++ b/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/sd/SecurityDomainTests.java @@ -20,9 +20,5 @@ import org.junit.runners.Suite; @RunWith(Suite.class) -@Suite.SuiteClasses({ - Scp03Tests.class, - Scp11Tests.class -}) -public class SecurityDomainTests { -} +@Suite.SuiteClasses({Scp03Tests.class, Scp11Tests.class}) +public class SecurityDomainTests {} diff --git a/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/AlwaysManualTest.java b/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/AlwaysManualTest.java index 786d27ec..3161efe6 100644 --- a/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/AlwaysManualTest.java +++ b/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/AlwaysManualTest.java @@ -16,5 +16,4 @@ package com.yubico.yubikit.testing.desktop; -public interface AlwaysManualTest { -} +public interface AlwaysManualTest {} diff --git a/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/DesktopTestDriver.java b/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/DesktopTestDriver.java index 8afa96e8..3e82af28 100644 --- a/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/DesktopTestDriver.java +++ b/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/DesktopTestDriver.java @@ -20,28 +20,28 @@ import com.yubico.yubikit.core.internal.Logger; import com.yubico.yubikit.desktop.OperatingSystem; import com.yubico.yubikit.desktop.YubiKitManager; - import org.slf4j.LoggerFactory; public class DesktopTestDriver { - private final YubiKitManager yubikit; + private final YubiKitManager yubikit; - private final static org.slf4j.Logger logger = LoggerFactory.getLogger(DesktopTestDriver.class); + private static final org.slf4j.Logger logger = LoggerFactory.getLogger(DesktopTestDriver.class); - public DesktopTestDriver() { - if (OperatingSystem.isMac()) { - System.setProperty("sun.security.smartcardio.library", "/System/Library/Frameworks/PCSC.framework/Versions/Current/PCSC"); - } - yubikit = new YubiKitManager(); + public DesktopTestDriver() { + if (OperatingSystem.isMac()) { + System.setProperty( + "sun.security.smartcardio.library", + "/System/Library/Frameworks/PCSC.framework/Versions/Current/PCSC"); } + yubikit = new YubiKitManager(); + } + public YubiKeyDevice awaitSession() throws InterruptedException { + return yubikit.listAllDevices().keySet().iterator().next(); + } - public YubiKeyDevice awaitSession() throws InterruptedException { - return yubikit.listAllDevices().keySet().iterator().next(); - } - - public void returnSession(YubiKeyDevice device) { - Logger.debug(logger, "Device returned"); - } + public void returnSession(YubiKeyDevice device) { + Logger.debug(logger, "Device returned"); + } } diff --git a/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/PinUvAuthProtocolV1Test.java b/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/PinUvAuthProtocolV1Test.java index ad704c77..3cb19d76 100644 --- a/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/PinUvAuthProtocolV1Test.java +++ b/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/PinUvAuthProtocolV1Test.java @@ -16,5 +16,4 @@ package com.yubico.yubikit.testing.desktop; -public interface PinUvAuthProtocolV1Test { -} +public interface PinUvAuthProtocolV1Test {} diff --git a/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/SlowTest.java b/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/SlowTest.java index e2b2ec5b..d28c5b30 100644 --- a/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/SlowTest.java +++ b/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/SlowTest.java @@ -16,5 +16,4 @@ package com.yubico.yubikit.testing.desktop; -public interface SlowTest { -} +public interface SlowTest {} diff --git a/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/SmokeTest.java b/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/SmokeTest.java index a250a950..dbc2e012 100644 --- a/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/SmokeTest.java +++ b/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/SmokeTest.java @@ -16,5 +16,4 @@ package com.yubico.yubikit.testing.desktop; -public interface SmokeTest { -} +public interface SmokeTest {} diff --git a/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/framework/FidoInstrumentedTests.java b/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/framework/FidoInstrumentedTests.java index d37f581d..cf6b25b6 100755 --- a/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/framework/FidoInstrumentedTests.java +++ b/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/framework/FidoInstrumentedTests.java @@ -23,46 +23,50 @@ import com.yubico.yubikit.fido.ctap.PinUvAuthProtocolV2; import com.yubico.yubikit.testing.TestState; import com.yubico.yubikit.testing.fido.FidoTestState; - import org.jetbrains.annotations.Nullable; public class FidoInstrumentedTests extends YKInstrumentedTests { - protected void withDevice(TestState.StatefulDeviceCallback callback) throws Throwable { - withDevice(true, callback); - } + protected void withDevice(TestState.StatefulDeviceCallback callback) + throws Throwable { + withDevice(true, callback); + } - protected void withDevice(boolean setPin, TestState.StatefulDeviceCallback callback) throws Throwable { - FidoTestState state = new FidoTestState.Builder(device, usbPid, getPinUvAuthProtocol()) - .scpKid(getScpKid()) - .reconnectDeviceCallback(this::reconnectDevice) - .setPin(setPin) - .build(); + protected void withDevice( + boolean setPin, TestState.StatefulDeviceCallback callback) throws Throwable { + FidoTestState state = + new FidoTestState.Builder(device, usbPid, getPinUvAuthProtocol()) + .scpKid(getScpKid()) + .reconnectDeviceCallback(this::reconnectDevice) + .setPin(setPin) + .build(); - state.withDeviceCallback(callback); - } + state.withDeviceCallback(callback); + } - protected void withCtap2Session(TestState.StatefulSessionCallback callback) throws Throwable { - FidoTestState state = new FidoTestState.Builder(device, usbPid, getPinUvAuthProtocol()) - .scpKid(getScpKid()) - .reconnectDeviceCallback(this::reconnectDevice) - .setPin(true) - .build(); + protected void withCtap2Session( + TestState.StatefulSessionCallback callback) throws Throwable { + FidoTestState state = + new FidoTestState.Builder(device, usbPid, getPinUvAuthProtocol()) + .scpKid(getScpKid()) + .reconnectDeviceCallback(this::reconnectDevice) + .setPin(true) + .build(); - state.withCtap2(callback); - } + state.withCtap2(callback); + } - @Nullable - @Override - protected Byte getScpKid() { - if (device.getTransport() == Transport.NFC) { - return ScpKid.SCP11b; - } - return null; + @Nullable + @Override + protected Byte getScpKid() { + if (device.getTransport() == Transport.NFC) { + return ScpKid.SCP11b; } + return null; + } - protected PinUvAuthProtocol getPinUvAuthProtocol() { - // default is protocol V2 - return new PinUvAuthProtocolV2(); - } -} \ No newline at end of file + protected PinUvAuthProtocol getPinUvAuthProtocol() { + // default is protocol V2 + return new PinUvAuthProtocolV2(); + } +} diff --git a/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/framework/ManagementInstrumentedTests.java b/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/framework/ManagementInstrumentedTests.java index 6433c2b6..2b3c4f36 100644 --- a/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/framework/ManagementInstrumentedTests.java +++ b/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/framework/ManagementInstrumentedTests.java @@ -21,13 +21,13 @@ public class ManagementInstrumentedTests extends YKInstrumentedTests { - public interface Callback { - void invoke(ManagementSession value) throws Throwable; - } + public interface Callback { + void invoke(ManagementSession value) throws Throwable; + } - protected void withManagementSession(Callback callback) throws Throwable { - try (SmartCardConnection connection = device.openConnection(SmartCardConnection.class)) { - callback.invoke(new ManagementSession(connection)); - } + protected void withManagementSession(Callback callback) throws Throwable { + try (SmartCardConnection connection = device.openConnection(SmartCardConnection.class)) { + callback.invoke(new ManagementSession(connection)); } -} \ No newline at end of file + } +} diff --git a/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/framework/MpeInstrumentedTests.java b/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/framework/MpeInstrumentedTests.java index 4d5dd6a0..72794ec0 100755 --- a/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/framework/MpeInstrumentedTests.java +++ b/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/framework/MpeInstrumentedTests.java @@ -23,17 +23,15 @@ public class MpeInstrumentedTests extends YKInstrumentedTests { - protected void withPivSession(TestState.StatefulSessionCallback callback) throws Throwable { - final MpeTestState state = new MpeTestState.Builder(device, usbPid) - .scpKid(getScpKid()) - .build(); - state.withPiv(callback); - } + protected void withPivSession( + TestState.StatefulSessionCallback callback) throws Throwable { + final MpeTestState state = new MpeTestState.Builder(device, usbPid).scpKid(getScpKid()).build(); + state.withPiv(callback); + } - protected void withCtap2Session(TestState.StatefulSessionCallback callback) throws Throwable { - final MpeTestState state = new MpeTestState.Builder(device, usbPid) - .scpKid(getScpKid()) - .build(); - state.withCtap2(callback); - } -} \ No newline at end of file + protected void withCtap2Session( + TestState.StatefulSessionCallback callback) throws Throwable { + final MpeTestState state = new MpeTestState.Builder(device, usbPid).scpKid(getScpKid()).build(); + state.withCtap2(callback); + } +} diff --git a/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/framework/OathInstrumentedTests.java b/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/framework/OathInstrumentedTests.java index 2a9ee47a..7375aa21 100644 --- a/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/framework/OathInstrumentedTests.java +++ b/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/framework/OathInstrumentedTests.java @@ -22,19 +22,21 @@ public class OathInstrumentedTests extends YKInstrumentedTests { - protected void withDevice(TestState.StatefulDeviceCallback callback) throws Throwable { - final OathTestState state = new OathTestState.Builder(device, usbPid) - .scpKid(getScpKid()) - .reconnectDeviceCallback(this::reconnectDevice) - .build(); + protected void withDevice(TestState.StatefulDeviceCallback callback) + throws Throwable { + final OathTestState state = + new OathTestState.Builder(device, usbPid) + .scpKid(getScpKid()) + .reconnectDeviceCallback(this::reconnectDevice) + .build(); - state.withDeviceCallback(callback); - } + state.withDeviceCallback(callback); + } - protected void withOathSession(TestState.StatefulSessionCallback callback) throws Throwable { - final OathTestState state = new OathTestState.Builder(device, usbPid) - .scpKid(getScpKid()) - .build(); - state.withOath(callback); - } -} \ No newline at end of file + protected void withOathSession( + TestState.StatefulSessionCallback callback) throws Throwable { + final OathTestState state = + new OathTestState.Builder(device, usbPid).scpKid(getScpKid()).build(); + state.withOath(callback); + } +} diff --git a/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/framework/OpenPgpInstrumentedTests.java b/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/framework/OpenPgpInstrumentedTests.java index 8abb0080..7226d028 100644 --- a/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/framework/OpenPgpInstrumentedTests.java +++ b/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/framework/OpenPgpInstrumentedTests.java @@ -21,10 +21,11 @@ import com.yubico.yubikit.testing.openpgp.OpenPgpTestState; public class OpenPgpInstrumentedTests extends YKInstrumentedTests { - protected void withOpenPgpSession(TestState.StatefulSessionCallback callback) throws Throwable { - final OpenPgpTestState state = new OpenPgpTestState.Builder(device, usbPid) - .scpKid(getScpKid()) - .build(); - state.withOpenPgp(callback); - } -} \ No newline at end of file + protected void withOpenPgpSession( + TestState.StatefulSessionCallback callback) + throws Throwable { + final OpenPgpTestState state = + new OpenPgpTestState.Builder(device, usbPid).scpKid(getScpKid()).build(); + state.withOpenPgp(callback); + } +} diff --git a/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/framework/PivInstrumentedTests.java b/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/framework/PivInstrumentedTests.java index e7410e64..a21bfdb9 100755 --- a/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/framework/PivInstrumentedTests.java +++ b/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/framework/PivInstrumentedTests.java @@ -19,21 +19,18 @@ import com.yubico.yubikit.piv.PivSession; import com.yubico.yubikit.testing.TestState; import com.yubico.yubikit.testing.piv.PivTestState; - -import org.bouncycastle.jce.provider.BouncyCastleProvider; - import java.security.Security; +import org.bouncycastle.jce.provider.BouncyCastleProvider; public class PivInstrumentedTests extends YKInstrumentedTests { - protected void withPivSession(TestState.StatefulSessionCallback callback) throws Throwable { + protected void withPivSession( + TestState.StatefulSessionCallback callback) throws Throwable { - Security.removeProvider("BC"); - Security.insertProviderAt(new BouncyCastleProvider(), 1); + Security.removeProvider("BC"); + Security.insertProviderAt(new BouncyCastleProvider(), 1); - final PivTestState state = new PivTestState.Builder(device, usbPid) - .scpKid(getScpKid()) - .build(); - state.withPiv(callback); - } -} \ No newline at end of file + final PivTestState state = new PivTestState.Builder(device, usbPid).scpKid(getScpKid()).build(); + state.withPiv(callback); + } +} diff --git a/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/framework/SecurityDomainInstrumentedTests.java b/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/framework/SecurityDomainInstrumentedTests.java index b3c77238..b3f8210a 100644 --- a/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/framework/SecurityDomainInstrumentedTests.java +++ b/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/framework/SecurityDomainInstrumentedTests.java @@ -21,11 +21,13 @@ public class SecurityDomainInstrumentedTests extends YKInstrumentedTests { - protected void withState(TestState.StatefulDeviceCallback callback) throws Throwable { - final SecurityDomainTestState state = new SecurityDomainTestState.Builder(device, usbPid) - .reconnectDeviceCallback(this::reconnectDevice) - .build(); + protected void withState(TestState.StatefulDeviceCallback callback) + throws Throwable { + final SecurityDomainTestState state = + new SecurityDomainTestState.Builder(device, usbPid) + .reconnectDeviceCallback(this::reconnectDevice) + .build(); - state.withDeviceCallback(callback); - } -} \ No newline at end of file + state.withDeviceCallback(callback); + } +} diff --git a/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/framework/YKInstrumentedTests.java b/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/framework/YKInstrumentedTests.java index c4e0c4de..312b1a63 100755 --- a/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/framework/YKInstrumentedTests.java +++ b/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/framework/YKInstrumentedTests.java @@ -20,7 +20,6 @@ import com.yubico.yubikit.core.YubiKeyDevice; import com.yubico.yubikit.desktop.CompositeDevice; import com.yubico.yubikit.testing.desktop.DesktopTestDriver; - import org.jetbrains.annotations.Nullable; import org.junit.Rule; import org.junit.rules.ExternalResource; @@ -28,54 +27,53 @@ public class YKInstrumentedTests { - private final DesktopTestDriver testDriver = new DesktopTestDriver(); + private final DesktopTestDriver testDriver = new DesktopTestDriver(); - protected YubiKeyDevice device = null; - protected UsbPid usbPid = null; + protected YubiKeyDevice device = null; + protected UsbPid usbPid = null; - @Rule - public final TestName name = new TestName(); + @Rule public final TestName name = new TestName(); - @Rule - public final ExternalResource externalResource = new ExternalResource() { + @Rule + public final ExternalResource externalResource = + new ExternalResource() { @Override protected void before() throws Throwable { - getDevice(); + getDevice(); } @Override protected void after() { - releaseDevice(); + releaseDevice(); } - }; - - protected YubiKeyDevice reconnectDevice() { - releaseDevice(); - getDevice(); - return device; - } + }; - @Nullable - protected Byte getScpKid() { - return null; - } + protected YubiKeyDevice reconnectDevice() { + releaseDevice(); + getDevice(); + return device; + } - private void getDevice() { - try { - device = testDriver.awaitSession(); - if (device instanceof CompositeDevice) { - CompositeDevice compositeDevice = (CompositeDevice) device; - usbPid = compositeDevice.getPidGroup().getPid(); - } - } catch (InterruptedException interruptedException) { - throw new RuntimeException("awaitSession failed", interruptedException); - } - } + @Nullable + protected Byte getScpKid() { + return null; + } - private void releaseDevice() { - testDriver.returnSession(device); - device = null; + private void getDevice() { + try { + device = testDriver.awaitSession(); + if (device instanceof CompositeDevice) { + CompositeDevice compositeDevice = (CompositeDevice) device; + usbPid = compositeDevice.getPidGroup().getPid(); + } + } catch (InterruptedException interruptedException) { + throw new RuntimeException("awaitSession failed", interruptedException); } + } + private void releaseDevice() { + testDriver.returnSession(device); + device = null; + } } From 7ef693c7a9b26fe87a2bee8c352dfd4a72d54923 Mon Sep 17 00:00:00 2001 From: Adam Velebil Date: Tue, 14 Jan 2025 17:08:39 +0100 Subject: [PATCH 17/24] demo app fixes --- DesktopDemo/build.gradle | 4 +-- .../yubikit/desktop/app/DesktopApp.java | 14 ++++----- DesktopDemo/src/main/logback.xml | 31 ------------------- DesktopDemo/src/main/resources/logback.xml | 13 ++++++++ 4 files changed, 22 insertions(+), 40 deletions(-) delete mode 100644 DesktopDemo/src/main/logback.xml create mode 100644 DesktopDemo/src/main/resources/logback.xml diff --git a/DesktopDemo/build.gradle b/DesktopDemo/build.gradle index 14a8d7a2..201a9aec 100755 --- a/DesktopDemo/build.gradle +++ b/DesktopDemo/build.gradle @@ -6,13 +6,13 @@ plugins { dependencies { compileOnly 'com.google.code.findbugs:jsr305:3.0.2' - implementation 'ch.qos.logback:logback-classic:1.5.12' + implementation 'ch.qos.logback:logback-classic:1.5.16' implementation project(':desktop') } application { - mainClassName = "com.yubico.yubikit.desktop.app.DesktopApp" + mainClass = "com.yubico.yubikit.desktop.app.DesktopApp" applicationName = 'DesktopApp' } diff --git a/DesktopDemo/src/main/java/com/yubico/yubikit/desktop/app/DesktopApp.java b/DesktopDemo/src/main/java/com/yubico/yubikit/desktop/app/DesktopApp.java index 015bec46..417270d8 100755 --- a/DesktopDemo/src/main/java/com/yubico/yubikit/desktop/app/DesktopApp.java +++ b/DesktopDemo/src/main/java/com/yubico/yubikit/desktop/app/DesktopApp.java @@ -38,23 +38,23 @@ public static void main(String[] argv) { "/System/Library/Frameworks/PCSC.framework/Versions/Current/PCSC"); } - System.out.println("Insert YubiKey now..."); + logger.info("Insert YubiKey now..."); YubiKitManager manager = new YubiKitManager(); Map devices = manager.listAllDevices(); - logger.debug("Devices: {}", devices); + logger.info("Devices: {}", devices); for (Map.Entry entry : devices.entrySet()) { YubiKeyDevice device = entry.getKey(); DeviceInfo info = entry.getValue(); - logger.debug("Found key: {} {}", device, info); + logger.info("Found key: {} {}", device, info); if (device.supportsConnection(SmartCardConnection.class)) { logger.debug("Request CCID connection"); device.requestConnection( SmartCardConnection.class, value -> { try { - logger.debug("Got CCID connection {}", value.getValue()); - } catch (IOException e) { + logger.info("Got CCID connection {}", value.getValue()); + } catch (Exception e) { logger.error("Failed to get CCID: ", e); } }); @@ -85,9 +85,9 @@ public static void main(String[] argv) { } } - logger.debug("Sleeping..."); + logger.info("Sleeping..."); try { - Thread.sleep(5000); + Thread.sleep(500); } catch (InterruptedException e) { throw new RuntimeException(e); } diff --git a/DesktopDemo/src/main/logback.xml b/DesktopDemo/src/main/logback.xml deleted file mode 100644 index 62edd79f..00000000 --- a/DesktopDemo/src/main/logback.xml +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - %d{HH:mm:ss.SSS} [%thread] %-5level %logger - %msg%n - - - - - - - - \ No newline at end of file diff --git a/DesktopDemo/src/main/resources/logback.xml b/DesktopDemo/src/main/resources/logback.xml new file mode 100644 index 00000000..903561fc --- /dev/null +++ b/DesktopDemo/src/main/resources/logback.xml @@ -0,0 +1,13 @@ + + + + + %d{HH:mm:ss.SSS} [%-20thread][%-5level] %msg%n + + + + + + + + \ No newline at end of file From 5f6ffb139c245564d02ef22eeb0e8a1142ab151c Mon Sep 17 00:00:00 2001 From: Adam Velebil Date: Fri, 17 Jan 2025 12:02:34 +0100 Subject: [PATCH 18/24] DesktopDemo updates --- DesktopDemo/build.gradle | 3 + .../yubikit/desktop/app/DesktopApp.java | 102 +++++++++++++----- DesktopDemo/src/main/resources/logback.xml | 2 +- .../yubico/yubikit/desktop/UsbPidGroup.java | 50 ++++----- .../yubikit/desktop/UsbYubiKeyDevice.java | 28 ++++- .../yubico/yubikit/desktop/hid/HidDevice.java | 15 +-- .../yubikit/desktop/hid/HidOtpConnection.java | 7 +- .../yubikit/desktop/pcsc/PcscDevice.java | 5 +- 8 files changed, 146 insertions(+), 66 deletions(-) diff --git a/DesktopDemo/build.gradle b/DesktopDemo/build.gradle index 201a9aec..baea1451 100755 --- a/DesktopDemo/build.gradle +++ b/DesktopDemo/build.gradle @@ -9,6 +9,9 @@ dependencies { implementation 'ch.qos.logback:logback-classic:1.5.16' implementation project(':desktop') + implementation project(':oath') + implementation project(':fido') + implementation project(':yubiotp') } application { diff --git a/DesktopDemo/src/main/java/com/yubico/yubikit/desktop/app/DesktopApp.java b/DesktopDemo/src/main/java/com/yubico/yubikit/desktop/app/DesktopApp.java index 417270d8..75133fc1 100755 --- a/DesktopDemo/src/main/java/com/yubico/yubikit/desktop/app/DesktopApp.java +++ b/DesktopDemo/src/main/java/com/yubico/yubikit/desktop/app/DesktopApp.java @@ -20,10 +20,16 @@ import com.yubico.yubikit.core.fido.FidoConnection; import com.yubico.yubikit.core.otp.OtpConnection; import com.yubico.yubikit.core.smartcard.SmartCardConnection; +import com.yubico.yubikit.desktop.CompositeDevice; import com.yubico.yubikit.desktop.OperatingSystem; import com.yubico.yubikit.desktop.YubiKitManager; +import com.yubico.yubikit.fido.ctap.Ctap2Session; import com.yubico.yubikit.management.DeviceInfo; -import java.io.IOException; +import com.yubico.yubikit.oath.OathSession; +import com.yubico.yubikit.yubiotp.ConfigurationState; +import com.yubico.yubikit.yubiotp.Slot; +import com.yubico.yubikit.yubiotp.YubiOtpSession; +import java.util.List; import java.util.Map; import org.slf4j.LoggerFactory; @@ -31,67 +37,115 @@ public class DesktopApp { private static final org.slf4j.Logger logger = LoggerFactory.getLogger(DesktopApp.class); - public static void main(String[] argv) { + public static void main(String[] argv) throws Exception { if (OperatingSystem.isMac()) { + System.setProperty( "sun.security.smartcardio.library", "/System/Library/Frameworks/PCSC.framework/Versions/Current/PCSC"); } - logger.info("Insert YubiKey now..."); - YubiKitManager manager = new YubiKitManager(); Map devices = manager.listAllDevices(); - logger.info("Devices: {}", devices); + if (devices.isEmpty()) { + logger.info("No devices are connected."); + } else { + logger.info("Found {} devices", devices.size()); + } + for (Map.Entry entry : devices.entrySet()) { YubiKeyDevice device = entry.getKey(); DeviceInfo info = entry.getValue(); - logger.info("Found key: {} {}", device, info); + + String deviceType = device.getClass().getSimpleName(); + + if (device instanceof CompositeDevice) { + CompositeDevice compositeDevice = (CompositeDevice) device; + deviceType += " (" + compositeDevice.getPidGroup().getPid() + ")"; + } + + logger.info( + "- {}:{}/{}/{}", + deviceType, + info.getFormFactor(), + info.getVersion(), + info.getSerialNumber()); + if (device.supportsConnection(SmartCardConnection.class)) { - logger.debug("Request CCID connection"); device.requestConnection( SmartCardConnection.class, value -> { try { - logger.info("Got CCID connection {}", value.getValue()); + SmartCardConnection connection = value.getValue(); + OathSession oath = new OathSession(connection); + logger.info( + " Device supports SmartCardConnection. OATH applet version is: {}", + oath.getVersion()); } catch (Exception e) { - logger.error("Failed to get CCID: ", e); + logger.error(" SmartCard connection failed with error: {}", e.getMessage()); } }); + + sleep(); + } else { + logger.info(" Device does not support SmartCardConnection"); } - if (device.supportsConnection(OtpConnection.class)) { - logger.debug("Request OTP connection"); + + if (device.supportsConnection(FidoConnection.class)) { device.requestConnection( - OtpConnection.class, + FidoConnection.class, value -> { try { - logger.debug("Got OTP connection {}", value.getValue()); - } catch (IOException e) { - logger.error("Failed to get OTP: ", e); + FidoConnection fidoConnection = value.getValue(); + Ctap2Session ctap2Session = new Ctap2Session(fidoConnection); + final List versions = ctap2Session.getCachedInfo().getVersions(); + logger.info( + " Device supports FidoConnection. Supported versions: {}", + String.join(", ", versions)); + } catch (Exception e) { + logger.error(" FIDO connection failed with error: {}", e.getMessage()); } }); + sleep(); + } else { + logger.info(" Device does not support FidoConnection"); } - if (device.supportsConnection(FidoConnection.class)) { - logger.debug("Request FIDO connection"); + + if (device.supportsConnection(OtpConnection.class)) { device.requestConnection( - FidoConnection.class, + OtpConnection.class, value -> { try { - logger.debug("Got FIDO connection {}", value.getValue()); - } catch (IOException e) { - logger.error("Failed to get FIDO: ", e); + OtpConnection otpConnection = value.getValue(); + YubiOtpSession yubiOtpSession = new YubiOtpSession(otpConnection); + ConfigurationState state = yubiOtpSession.getConfigurationState(); + String configuredSlots = " "; + if (state.isConfigured(Slot.ONE)) { + configuredSlots += "SLOT1 "; + } + if (state.isConfigured(Slot.TWO)) { + configuredSlots += "SLOT2"; + } + logger.info( + " Device supports OtpConnection. Configured slots:{}", configuredSlots); + } catch (Exception e) { + logger.error(" OTP connection failed with error: {}", e.getMessage()); } }); + sleep(); + } else { + logger.info(" Device does not support OtpConnection"); } } + logger.info("Application exited"); + } - logger.info("Sleeping..."); + private static void sleep() { try { Thread.sleep(500); } catch (InterruptedException e) { + Thread.currentThread().interrupt(); throw new RuntimeException(e); } - - logger.debug("Application exited"); } } diff --git a/DesktopDemo/src/main/resources/logback.xml b/DesktopDemo/src/main/resources/logback.xml index 903561fc..0dd53dcc 100644 --- a/DesktopDemo/src/main/resources/logback.xml +++ b/DesktopDemo/src/main/resources/logback.xml @@ -7,7 +7,7 @@ - + \ No newline at end of file diff --git a/desktop/src/main/java/com/yubico/yubikit/desktop/UsbPidGroup.java b/desktop/src/main/java/com/yubico/yubikit/desktop/UsbPidGroup.java index d679190d..a80381da 100755 --- a/desktop/src/main/java/com/yubico/yubikit/desktop/UsbPidGroup.java +++ b/desktop/src/main/java/com/yubico/yubikit/desktop/UsbPidGroup.java @@ -98,8 +98,8 @@ void add( "Resolved device {}", serialNumber != null ? serialNumber : "without serial number"); return; - } catch (IOException e) { - Logger.error(logger, "Failed opening device. ", e); + } catch (UnsupportedOperationException | IOException e) { + Logger.error(logger, "Failed opening device: {}", e.getMessage()); } } if (!unresolved.containsKey(usbInterface)) { @@ -128,8 +128,9 @@ T openConnection(String key, Class connectionTy while (!devices.isEmpty()) { device = devices.remove(0); Logger.debug(logger, "Candidate: {}", device); + T connection = null; try { - T connection = device.openConnection(connectionType); + connection = device.openConnection(connectionType); DeviceInfo info = DeviceUtil.readInfo(connection, pid); String deviceKey = buildKey(info); if (infos.containsKey(deviceKey)) { @@ -144,24 +145,35 @@ T openConnection(String key, Class connectionTy return connection; } } + connection.close(); } catch (IOException e) { + if (connection != null) { + connection.close(); + } Logger.error(logger, "Failed opening candidate device: ", e); failed.add(device); + } catch (Exception e) { + if (connection != null) { + connection.close(); + } + throw e; } } } finally { devices.addAll(failed); } - throw new IOException("Failed to open connection"); + throw new IOException("Could not open " + connectionType.getSimpleName()); } void requestConnection( String key, Class connectionType, Callback> callback) { int usbInterface = getUsbInterface(connectionType); UsbYubiKeyDevice device = resolved.get(key).get(usbInterface); + Exception lastException = null; if (device != null) { device.requestConnection(connectionType, callback); + return; } else { Logger.debug(logger, "Resolve device for {}, {}", connectionType, key); List devices = unresolved.getOrDefault(usbInterface, new ArrayList<>()); @@ -188,37 +200,19 @@ void requestConnection( return; } } - } catch (IOException e) { - Logger.error(logger, "Failed opening candidate device: ", e); + } catch (UnsupportedOperationException | IOException e) { + Logger.error(logger, "Failed opening candidate device: {}", e.getMessage()); + lastException = e; failed.add(device); } } } finally { devices.addAll(failed); } - - // TODO - /* - if self._devcount[iface] < len(self._infos): - logger.debug(f"Checking for more devices over {iface!s}") - for dev in _CONNECTION_LIST_MAPPING[conn_type](): - if self._pid == dev.pid and dev.fingerprint not in self._fingerprints: - self.add(conn_type, dev, True) - - resolved = self._resolved[key].get(iface) - if resolved: - return resolved.open_connection(conn_type) - - # Retry if we are within a 5 second period after creation, - # as not all USB interface become usable at the exact same time. - if time() < self._ctime + 5: - logger.debug("Device not found, retry in 1s") - sleep(1.0) - return self.connect(key, conn_type) - - raise ValueError("Failed to connect to the device") - */ } + + // was not able to request connection from any the devices + callback.invoke(Result.failure(new IOException("Request connection failed", lastException))); } Map getDevices() { diff --git a/desktop/src/main/java/com/yubico/yubikit/desktop/UsbYubiKeyDevice.java b/desktop/src/main/java/com/yubico/yubikit/desktop/UsbYubiKeyDevice.java index 653814a5..ea02c62b 100755 --- a/desktop/src/main/java/com/yubico/yubikit/desktop/UsbYubiKeyDevice.java +++ b/desktop/src/main/java/com/yubico/yubikit/desktop/UsbYubiKeyDevice.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 Yubico. + * Copyright (C) 2022-2025 Yubico. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -27,4 +27,30 @@ public interface UsbYubiKeyDevice extends YubiKeyDevice { String getFingerprint(); UsbPid getPid(); + + interface TryOpenUsbCallback { + T open() throws IOException; + } + + static T tryOpen(TryOpenUsbCallback callback) + throws IOException { + Exception lastException = null; + long USB_RECLAIM_TIMEOUT = 3000; + long startTime = System.currentTimeMillis(); + while (System.currentTimeMillis() - startTime < USB_RECLAIM_TIMEOUT) { + try { + return callback.open(); + } catch (Exception exception) { + lastException = exception; + try { + //noinspection BusyWait + Thread.sleep(100); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new IOException("Interrupted while trying to open connection"); + } + } + } + throw new IOException("Failed to open connection", lastException); + } } diff --git a/desktop/src/main/java/com/yubico/yubikit/desktop/hid/HidDevice.java b/desktop/src/main/java/com/yubico/yubikit/desktop/hid/HidDevice.java index 5af2ba03..c0da6302 100755 --- a/desktop/src/main/java/com/yubico/yubikit/desktop/hid/HidDevice.java +++ b/desktop/src/main/java/com/yubico/yubikit/desktop/hid/HidDevice.java @@ -81,12 +81,15 @@ public void requestConnection( @Override public T openConnection(Class connectionType) throws IOException { - if (connectionType.isAssignableFrom(HidOtpConnection.class)) { - return connectionType.cast(openOtpConnection()); - } else if (connectionType.isAssignableFrom(HidFidoConnection.class)) { - return connectionType.cast(openFidoConnection()); - } - throw new IllegalStateException("Unsupported connection type"); + return UsbYubiKeyDevice.tryOpen( + () -> { + if (connectionType.isAssignableFrom(HidOtpConnection.class)) { + return connectionType.cast(openOtpConnection()); + } else if (connectionType.isAssignableFrom(HidFidoConnection.class)) { + return connectionType.cast(openFidoConnection()); + } + throw new IllegalStateException("Unsupported connection type"); + }); } @Override diff --git a/desktop/src/main/java/com/yubico/yubikit/desktop/hid/HidOtpConnection.java b/desktop/src/main/java/com/yubico/yubikit/desktop/hid/HidOtpConnection.java index c4600504..4afc25af 100755 --- a/desktop/src/main/java/com/yubico/yubikit/desktop/hid/HidOtpConnection.java +++ b/desktop/src/main/java/com/yubico/yubikit/desktop/hid/HidOtpConnection.java @@ -18,7 +18,6 @@ import com.yubico.yubikit.core.internal.Logger; import com.yubico.yubikit.core.otp.OtpConnection; -import com.yubico.yubikit.desktop.OperatingSystem; import java.io.IOException; import org.hid4java.HidDevice; import org.slf4j.LoggerFactory; @@ -45,8 +44,7 @@ public class HidOtpConnection implements OtpConnection { @Override public void receive(byte[] report) throws IOException { - int offset = OperatingSystem.isWindows() ? 1 : 0; - int reportSize = FEATURE_REPORT_SIZE + offset; + int reportSize = FEATURE_REPORT_SIZE + 1; int received = hidDevice.getFeatureReport(report, interfaceId); @@ -57,8 +55,7 @@ public void receive(byte[] report) throws IOException { @Override public void send(byte[] report) throws IOException { - int offset = OperatingSystem.isWindows() ? 1 : 0; - int reportSize = FEATURE_REPORT_SIZE + offset; + int reportSize = FEATURE_REPORT_SIZE + 1; int sent = hidDevice.sendFeatureReport(report, interfaceId); diff --git a/desktop/src/main/java/com/yubico/yubikit/desktop/pcsc/PcscDevice.java b/desktop/src/main/java/com/yubico/yubikit/desktop/pcsc/PcscDevice.java index 1b49c56b..aab07b4e 100755 --- a/desktop/src/main/java/com/yubico/yubikit/desktop/pcsc/PcscDevice.java +++ b/desktop/src/main/java/com/yubico/yubikit/desktop/pcsc/PcscDevice.java @@ -21,6 +21,7 @@ import com.yubico.yubikit.core.smartcard.SmartCardConnection; import com.yubico.yubikit.core.util.Callback; import com.yubico.yubikit.core.util.Result; +import com.yubico.yubikit.desktop.UsbYubiKeyDevice; import java.io.IOException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; @@ -54,10 +55,12 @@ public boolean supportsConnection(Class connectionT public T openConnection(Class connectionType) throws IOException { + if (!supportsConnection(connectionType)) { throw new IllegalStateException("Unsupported connection type"); } - return connectionType.cast(openIso7816Connection()); + + return UsbYubiKeyDevice.tryOpen(() -> connectionType.cast(openIso7816Connection())); } @Override From d6fe2105da7d83df3dc1cd01a7a38db7c684ea26 Mon Sep 17 00:00:00 2001 From: Adam Velebil Date: Fri, 17 Jan 2025 15:09:50 +0100 Subject: [PATCH 19/24] shutdown executors; remove tryOpen --- .../yubikit/desktop/app/DesktopApp.java | 9 +++++- DesktopDemo/src/main/resources/logback.xml | 2 -- .../yubikit/desktop/CompositeDevice.java | 8 ++++- .../yubico/yubikit/desktop/UsbPidGroup.java | 22 +++++++++++++- .../yubikit/desktop/UsbYubiKeyDevice.java | 29 ++----------------- .../yubico/yubikit/desktop/hid/HidDevice.java | 23 ++++++++------- .../yubikit/desktop/pcsc/PcscDevice.java | 11 +++++-- 7 files changed, 59 insertions(+), 45 deletions(-) diff --git a/DesktopDemo/src/main/java/com/yubico/yubikit/desktop/app/DesktopApp.java b/DesktopDemo/src/main/java/com/yubico/yubikit/desktop/app/DesktopApp.java index 75133fc1..31c5301b 100755 --- a/DesktopDemo/src/main/java/com/yubico/yubikit/desktop/app/DesktopApp.java +++ b/DesktopDemo/src/main/java/com/yubico/yubikit/desktop/app/DesktopApp.java @@ -137,12 +137,19 @@ public static void main(String[] argv) throws Exception { logger.info(" Device does not support OtpConnection"); } } + + for (YubiKeyDevice yubiKeyDevice : devices.keySet()) { + if (yubiKeyDevice instanceof CompositeDevice) { + CompositeDevice usbYubiKeyDevice = (CompositeDevice) yubiKeyDevice; + usbYubiKeyDevice.close(); + } + } logger.info("Application exited"); } private static void sleep() { try { - Thread.sleep(500); + Thread.sleep(200); } catch (InterruptedException e) { Thread.currentThread().interrupt(); throw new RuntimeException(e); diff --git a/DesktopDemo/src/main/resources/logback.xml b/DesktopDemo/src/main/resources/logback.xml index 0dd53dcc..194e487c 100644 --- a/DesktopDemo/src/main/resources/logback.xml +++ b/DesktopDemo/src/main/resources/logback.xml @@ -5,8 +5,6 @@ %d{HH:mm:ss.SSS} [%-20thread][%-5level] %msg%n - - diff --git a/desktop/src/main/java/com/yubico/yubikit/desktop/CompositeDevice.java b/desktop/src/main/java/com/yubico/yubikit/desktop/CompositeDevice.java index 54c3f058..89080822 100755 --- a/desktop/src/main/java/com/yubico/yubikit/desktop/CompositeDevice.java +++ b/desktop/src/main/java/com/yubico/yubikit/desktop/CompositeDevice.java @@ -21,9 +21,10 @@ import com.yubico.yubikit.core.YubiKeyDevice; import com.yubico.yubikit.core.util.Callback; import com.yubico.yubikit.core.util.Result; +import java.io.Closeable; import java.io.IOException; -public class CompositeDevice implements YubiKeyDevice { +public class CompositeDevice implements YubiKeyDevice, Closeable { private final UsbPidGroup pidGroup; private final String key; @@ -57,4 +58,9 @@ public T openConnection(Class connectionType) public UsbPidGroup getPidGroup() { return pidGroup; } + + @Override + public void close() throws IOException { + pidGroup.close(); + } } diff --git a/desktop/src/main/java/com/yubico/yubikit/desktop/UsbPidGroup.java b/desktop/src/main/java/com/yubico/yubikit/desktop/UsbPidGroup.java index a80381da..643ff6dc 100755 --- a/desktop/src/main/java/com/yubico/yubikit/desktop/UsbPidGroup.java +++ b/desktop/src/main/java/com/yubico/yubikit/desktop/UsbPidGroup.java @@ -30,11 +30,12 @@ import com.yubico.yubikit.core.util.Result; import com.yubico.yubikit.management.DeviceInfo; import com.yubico.yubikit.support.DeviceUtil; +import java.io.Closeable; import java.io.IOException; import java.util.*; import org.slf4j.LoggerFactory; -public class UsbPidGroup { +public class UsbPidGroup implements Closeable { final UsbPid pid; private final Map infos = new HashMap<>(); @@ -226,4 +227,23 @@ Map getDevices() { public UsbPid getPid() { return pid; } + + @Override + public void close() throws IOException { + for (String resolvedEntry : resolved.keySet()) { + Map ifaceDevice = resolved.get(resolvedEntry); + for (UsbYubiKeyDevice device : ifaceDevice.values()) { + Logger.debug(logger, "Closing resolved device {}", device.getFingerprint()); + device.close(); + } + } + + for (Integer unresolvedIface : unresolved.keySet()) { + List unresolvedDevices = unresolved.get(unresolvedIface); + for (UsbYubiKeyDevice device : unresolvedDevices) { + Logger.debug(logger, "Closing unresolved device {}", device.getFingerprint()); + device.close(); + } + } + } } diff --git a/desktop/src/main/java/com/yubico/yubikit/desktop/UsbYubiKeyDevice.java b/desktop/src/main/java/com/yubico/yubikit/desktop/UsbYubiKeyDevice.java index ea02c62b..2a800b62 100755 --- a/desktop/src/main/java/com/yubico/yubikit/desktop/UsbYubiKeyDevice.java +++ b/desktop/src/main/java/com/yubico/yubikit/desktop/UsbYubiKeyDevice.java @@ -19,38 +19,13 @@ import com.yubico.yubikit.core.UsbPid; import com.yubico.yubikit.core.YubiKeyConnection; import com.yubico.yubikit.core.YubiKeyDevice; +import java.io.Closeable; import java.io.IOException; -public interface UsbYubiKeyDevice extends YubiKeyDevice { +public interface UsbYubiKeyDevice extends YubiKeyDevice, Closeable { T openConnection(Class connectionType) throws IOException; String getFingerprint(); UsbPid getPid(); - - interface TryOpenUsbCallback { - T open() throws IOException; - } - - static T tryOpen(TryOpenUsbCallback callback) - throws IOException { - Exception lastException = null; - long USB_RECLAIM_TIMEOUT = 3000; - long startTime = System.currentTimeMillis(); - while (System.currentTimeMillis() - startTime < USB_RECLAIM_TIMEOUT) { - try { - return callback.open(); - } catch (Exception exception) { - lastException = exception; - try { - //noinspection BusyWait - Thread.sleep(100); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - throw new IOException("Interrupted while trying to open connection"); - } - } - } - throw new IOException("Failed to open connection", lastException); - } } diff --git a/desktop/src/main/java/com/yubico/yubikit/desktop/hid/HidDevice.java b/desktop/src/main/java/com/yubico/yubikit/desktop/hid/HidDevice.java index c0da6302..2d09a44b 100755 --- a/desktop/src/main/java/com/yubico/yubikit/desktop/hid/HidDevice.java +++ b/desktop/src/main/java/com/yubico/yubikit/desktop/hid/HidDevice.java @@ -22,11 +22,12 @@ import com.yubico.yubikit.core.util.Callback; import com.yubico.yubikit.core.util.Result; import com.yubico.yubikit.desktop.UsbYubiKeyDevice; +import java.io.Closeable; import java.io.IOException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; -public class HidDevice implements UsbYubiKeyDevice { +public class HidDevice implements UsbYubiKeyDevice, Closeable { private final ExecutorService executorService = Executors.newSingleThreadExecutor(); private final org.hid4java.HidDevice hidDevice; private final int usagePage; @@ -81,15 +82,12 @@ public void requestConnection( @Override public T openConnection(Class connectionType) throws IOException { - return UsbYubiKeyDevice.tryOpen( - () -> { - if (connectionType.isAssignableFrom(HidOtpConnection.class)) { - return connectionType.cast(openOtpConnection()); - } else if (connectionType.isAssignableFrom(HidFidoConnection.class)) { - return connectionType.cast(openFidoConnection()); - } - throw new IllegalStateException("Unsupported connection type"); - }); + if (connectionType.isAssignableFrom(HidOtpConnection.class)) { + return connectionType.cast(openOtpConnection()); + } else if (connectionType.isAssignableFrom(HidFidoConnection.class)) { + return connectionType.cast(openFidoConnection()); + } + throw new IllegalStateException("Unsupported connection type"); } @Override @@ -101,4 +99,9 @@ public String getFingerprint() { public UsbPid getPid() { return UsbPid.fromValue(hidDevice.getProductId()); } + + @Override + public void close() throws IOException { + executorService.shutdown(); + } } diff --git a/desktop/src/main/java/com/yubico/yubikit/desktop/pcsc/PcscDevice.java b/desktop/src/main/java/com/yubico/yubikit/desktop/pcsc/PcscDevice.java index aab07b4e..e27c2395 100755 --- a/desktop/src/main/java/com/yubico/yubikit/desktop/pcsc/PcscDevice.java +++ b/desktop/src/main/java/com/yubico/yubikit/desktop/pcsc/PcscDevice.java @@ -21,14 +21,14 @@ import com.yubico.yubikit.core.smartcard.SmartCardConnection; import com.yubico.yubikit.core.util.Callback; import com.yubico.yubikit.core.util.Result; -import com.yubico.yubikit.desktop.UsbYubiKeyDevice; +import java.io.Closeable; import java.io.IOException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import javax.smartcardio.CardException; import javax.smartcardio.CardTerminal; -abstract class PcscDevice implements YubiKeyDevice { +abstract class PcscDevice implements YubiKeyDevice, Closeable { private final ExecutorService executorService = Executors.newSingleThreadExecutor(); private final CardTerminal terminal; @@ -60,7 +60,7 @@ public T openConnection(Class connectionType) throw new IllegalStateException("Unsupported connection type"); } - return UsbYubiKeyDevice.tryOpen(() -> connectionType.cast(openIso7816Connection())); + return connectionType.cast(openIso7816Connection()); } @Override @@ -78,4 +78,9 @@ public void requestConnection( } }); } + + @Override + public void close() throws IOException { + executorService.shutdown(); + } } From 599b653a7a38a24283db5b26748b39fb21f9defd Mon Sep 17 00:00:00 2001 From: Adam Velebil Date: Fri, 17 Jan 2025 16:09:53 +0100 Subject: [PATCH 20/24] cleanup of unused code --- .../yubico/yubikit/desktop/UsbPidGroup.java | 3 - .../yubikit/desktop/hid/HidManager.java | 32 ---------- .../desktop/hid/HidSessionListener.java | 33 ---------- .../yubico/yubikit/desktop/package-info.java | 16 +++++ .../yubikit/desktop/pcsc/NfcPcscDevice.java | 64 ------------------- .../desktop/pcsc/PcscConfiguration.java | 60 ----------------- .../desktop/pcsc/PcscSessionListener.java | 33 ---------- testing-desktop/build.gradle | 2 +- .../testing/desktop/DesktopTestDriver.java | 2 +- 9 files changed, 18 insertions(+), 227 deletions(-) delete mode 100755 desktop/src/main/java/com/yubico/yubikit/desktop/hid/HidSessionListener.java delete mode 100755 desktop/src/main/java/com/yubico/yubikit/desktop/pcsc/NfcPcscDevice.java delete mode 100755 desktop/src/main/java/com/yubico/yubikit/desktop/pcsc/PcscConfiguration.java delete mode 100755 desktop/src/main/java/com/yubico/yubikit/desktop/pcsc/PcscSessionListener.java diff --git a/desktop/src/main/java/com/yubico/yubikit/desktop/UsbPidGroup.java b/desktop/src/main/java/com/yubico/yubikit/desktop/UsbPidGroup.java index 643ff6dc..5f0b7133 100755 --- a/desktop/src/main/java/com/yubico/yubikit/desktop/UsbPidGroup.java +++ b/desktop/src/main/java/com/yubico/yubikit/desktop/UsbPidGroup.java @@ -42,8 +42,6 @@ public class UsbPidGroup implements Closeable { private final Map> resolved = new HashMap<>(); private final Map> unresolved = new HashMap<>(); private final Map devCount = new HashMap<>(); - private final Set fingerprints = new HashSet<>(); - private final long ctime = System.currentTimeMillis(); private final org.slf4j.Logger logger = LoggerFactory.getLogger(UsbPidGroup.class); @@ -82,7 +80,6 @@ void add( boolean forceResolve) { Logger.trace(logger, "Add device node {}{}", device, connectionType); int usbInterface = getUsbInterface(connectionType); - fingerprints.add(device.getFingerprint()); devCount.put(usbInterface, devCount.getOrDefault(usbInterface, 0) + 1); if (forceResolve || resolved.size() < devCount.values().stream().reduce(0, Math::max)) { try (YubiKeyConnection connection = device.openConnection(connectionType)) { diff --git a/desktop/src/main/java/com/yubico/yubikit/desktop/hid/HidManager.java b/desktop/src/main/java/com/yubico/yubikit/desktop/hid/HidManager.java index 6da6ed70..dcf359f3 100755 --- a/desktop/src/main/java/com/yubico/yubikit/desktop/hid/HidManager.java +++ b/desktop/src/main/java/com/yubico/yubikit/desktop/hid/HidManager.java @@ -16,14 +16,10 @@ package com.yubico.yubikit.desktop.hid; -import com.yubico.yubikit.core.internal.Logger; import java.util.ArrayList; import java.util.List; import javax.annotation.Nullable; import org.hid4java.HidServices; -import org.hid4java.HidServicesListener; -import org.hid4java.event.HidServicesEvent; -import org.slf4j.LoggerFactory; public class HidManager { @@ -33,8 +29,6 @@ public class HidManager { private final HidServices services; - private final org.slf4j.Logger logger = LoggerFactory.getLogger(HidManager.class); - public HidManager() { services = org.hid4java.HidManager.getHidServices(); } @@ -57,30 +51,4 @@ public List getOtpDevices() { public List getFidoDevices() { return getHidDevices(YUBICO_VENDOR_ID, HID_USAGE_PAGE_FIDO); } - - public void setListener(HidSessionListener listener) { - services.addHidServicesListener( - new HidServicesListener() { - @Override - public void hidDeviceAttached(HidServicesEvent event) { - Logger.debug(logger, "HID attached: {}", event); - listener.onSessionReceived(new HidDevice(event.getHidDevice())); - } - - @Override - public void hidDeviceDetached(HidServicesEvent event) { - Logger.debug(logger, "HID removed: {}", event); - } - - @Override - public void hidFailure(HidServicesEvent event) { - Logger.debug(logger, "HID failure: {}", event); - } - - @Override - public void hidDataReceived(HidServicesEvent event) { - Logger.debug(logger, "HID Data received: {}", event); - } - }); - } } diff --git a/desktop/src/main/java/com/yubico/yubikit/desktop/hid/HidSessionListener.java b/desktop/src/main/java/com/yubico/yubikit/desktop/hid/HidSessionListener.java deleted file mode 100755 index 9e4b5ff8..00000000 --- a/desktop/src/main/java/com/yubico/yubikit/desktop/hid/HidSessionListener.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (C) 2019-2022 Yubico. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.yubico.yubikit.desktop.hid; - -public interface HidSessionListener { - /** - * Invoked when detected inserted device after usb discovery started - * - * @param session usb session that associated with plugged in device - */ - void onSessionReceived(HidDevice session); - - /** - * Invoked when detected removal/ejection of usb device after usb discovery started - * - * @param session usb session that will become inactive - */ - void onSessionRemoved(HidDevice session); -} diff --git a/desktop/src/main/java/com/yubico/yubikit/desktop/package-info.java b/desktop/src/main/java/com/yubico/yubikit/desktop/package-info.java index bd0f9477..0dd14c92 100755 --- a/desktop/src/main/java/com/yubico/yubikit/desktop/package-info.java +++ b/desktop/src/main/java/com/yubico/yubikit/desktop/package-info.java @@ -1,3 +1,19 @@ +/* + * Copyright (C) 2022,2024 Yubico. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + @PackageNonnullByDefault package com.yubico.yubikit.desktop; diff --git a/desktop/src/main/java/com/yubico/yubikit/desktop/pcsc/NfcPcscDevice.java b/desktop/src/main/java/com/yubico/yubikit/desktop/pcsc/NfcPcscDevice.java deleted file mode 100755 index 5f446d42..00000000 --- a/desktop/src/main/java/com/yubico/yubikit/desktop/pcsc/NfcPcscDevice.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (C) 2022 Yubico. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.yubico.yubikit.desktop.pcsc; - -import com.yubico.yubikit.core.Transport; -import com.yubico.yubikit.core.application.ApplicationNotAvailableException; -import com.yubico.yubikit.core.smartcard.Apdu; -import com.yubico.yubikit.core.smartcard.ApduException; -import com.yubico.yubikit.core.smartcard.SmartCardProtocol; -import java.io.IOException; -import java.nio.ByteBuffer; -import javax.smartcardio.CardTerminal; - -public class NfcPcscDevice extends PcscDevice { - private static final byte[] NDEF_AID = - new byte[] {(byte) 0xd2, 0x76, 0x00, 0x00, (byte) 0x85, 0x01, 0x01}; - - public NfcPcscDevice(CardTerminal terminal) { - super(terminal); - } - - @Override - public Transport getTransport() { - return Transport.NFC; - } - - /** - * Reads the NDEF record from a YubiKey over NFC. This is only available when connecting over NFC, - * and only if the YubiKey has been configured to output one of its OTP slots over NDEF. - * - * @return the raw NDEF record - * @throws IOException in case of connection error - * @throws ApduException in case of communication error - * @throws ApplicationNotAvailableException in case the NDEF applet isn't available - */ - public byte[] readNdef() throws IOException, ApduException, ApplicationNotAvailableException { - try (SmartCardProtocol ndef = new SmartCardProtocol(openIso7816Connection())) { - ndef.select(NDEF_AID); - - ndef.sendAndReceive(new Apdu(0x00, 0xa4, 0x00, 0x0C, new byte[] {(byte) 0xe1, 0x04})); - byte[] resp = ndef.sendAndReceive(new Apdu(0x00, 0xb0, 0, 0, null)); - int ndefLen = resp[1]; - ByteBuffer buf = ByteBuffer.allocate(ndefLen).put(resp, 2, resp.length - 2); - while (buf.position() < ndefLen) { - buf.put(ndef.sendAndReceive(new Apdu(0x00, 0xb0, 0, buf.position(), null))); - } - return buf.array(); - } - } -} diff --git a/desktop/src/main/java/com/yubico/yubikit/desktop/pcsc/PcscConfiguration.java b/desktop/src/main/java/com/yubico/yubikit/desktop/pcsc/PcscConfiguration.java deleted file mode 100755 index 63e2b5e9..00000000 --- a/desktop/src/main/java/com/yubico/yubikit/desktop/pcsc/PcscConfiguration.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (C) 2022 Yubico. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.yubico.yubikit.desktop.pcsc; - -import com.yubico.yubikit.core.Transport; -import java.util.Arrays; -import java.util.EnumSet; -import java.util.regex.Pattern; -import javax.annotation.Nullable; - -public class PcscConfiguration { - private final EnumSet transportFilter = EnumSet.allOf(Transport.class); - private long pollingTimeout = 250; - @Nullable private Pattern readerNameFilter = null; - - long getPollingTimeout() { - return pollingTimeout; - } - - boolean isInterfaceAllowed(Transport transport) { - return transportFilter.contains(transport); - } - - boolean filterName(String name) { - if (readerNameFilter != null) { - return readerNameFilter.matcher(name).find(); - } - return true; - } - - public PcscConfiguration pollingTimeout(long pollingTimeout) { - this.pollingTimeout = pollingTimeout; - return this; - } - - public PcscConfiguration interfaceFilter(Transport... transports) { - transportFilter.clear(); - transportFilter.addAll(Arrays.asList(transports)); - return this; - } - - public PcscConfiguration readerNameFilter(Pattern pattern) { - this.readerNameFilter = pattern; - return this; - } -} diff --git a/desktop/src/main/java/com/yubico/yubikit/desktop/pcsc/PcscSessionListener.java b/desktop/src/main/java/com/yubico/yubikit/desktop/pcsc/PcscSessionListener.java deleted file mode 100755 index 26446863..00000000 --- a/desktop/src/main/java/com/yubico/yubikit/desktop/pcsc/PcscSessionListener.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (C) 2019-2022 Yubico. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.yubico.yubikit.desktop.pcsc; - -public interface PcscSessionListener { - /** - * Invoked when detected inserted device after usb discovery started - * - * @param session usb session that associated with plugged in device - */ - void onSessionReceived(NfcPcscDevice session); - - /** - * Invoked when detected removal/ejection of usb device after usb discovery started - * - * @param session usb session that will become inactive - */ - void onSessionRemoved(NfcPcscDevice session); -} diff --git a/testing-desktop/build.gradle b/testing-desktop/build.gradle index b8930e36..40f0c548 100755 --- a/testing-desktop/build.gradle +++ b/testing-desktop/build.gradle @@ -27,7 +27,7 @@ dependencies { implementation project(':testing') integrationTestImplementation 'junit:junit:4.13.2' - integrationTestImplementation 'ch.qos.logback:logback-classic:1.5.12' + integrationTestImplementation 'ch.qos.logback:logback-classic:1.5.16' implementation 'org.bouncycastle:bcpkix-jdk15to18:1.78.1' diff --git a/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/DesktopTestDriver.java b/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/DesktopTestDriver.java index 3e82af28..69e2717c 100644 --- a/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/DesktopTestDriver.java +++ b/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/DesktopTestDriver.java @@ -41,7 +41,7 @@ public YubiKeyDevice awaitSession() throws InterruptedException { return yubikit.listAllDevices().keySet().iterator().next(); } - public void returnSession(YubiKeyDevice device) { + public void returnSession(YubiKeyDevice ignoredDevice) { Logger.debug(logger, "Device returned"); } } From 2c707cbb7aaa7441debb628140a6de8ab9fa30b0 Mon Sep 17 00:00:00 2001 From: Adam Velebil Date: Fri, 17 Jan 2025 16:23:26 +0100 Subject: [PATCH 21/24] update license headers --- .../main/java/com/yubico/yubikit/desktop/app/DesktopApp.java | 3 +-- .../main/java/com/yubico/yubikit/desktop/CompositeDevice.java | 3 +-- .../main/java/com/yubico/yubikit/desktop/OperatingSystem.java | 3 +-- .../src/main/java/com/yubico/yubikit/desktop/UsbPidGroup.java | 3 +-- .../main/java/com/yubico/yubikit/desktop/UsbYubiKeyDevice.java | 1 - .../main/java/com/yubico/yubikit/desktop/YubiKitManager.java | 3 +-- .../main/java/com/yubico/yubikit/desktop/hid/HidDevice.java | 3 +-- .../java/com/yubico/yubikit/desktop/hid/HidFidoConnection.java | 2 +- .../main/java/com/yubico/yubikit/desktop/hid/HidManager.java | 3 +-- .../java/com/yubico/yubikit/desktop/hid/HidOtpConnection.java | 3 +-- .../main/java/com/yubico/yubikit/desktop/pcsc/PcscDevice.java | 3 +-- .../main/java/com/yubico/yubikit/desktop/pcsc/PcscManager.java | 3 +-- .../yubico/yubikit/desktop/pcsc/PcscSmartCardConnection.java | 3 +-- .../java/com/yubico/yubikit/desktop/pcsc/UsbPcscDevice.java | 3 +-- .../java/com/yubico/yubikit/testing/desktop/DeviceTests.java | 3 +-- .../com/yubico/yubikit/testing/desktop/FastDeviceTests.java | 3 +-- .../com/yubico/yubikit/testing/desktop/SmokeDeviceTests.java | 3 +-- .../desktop/fido/BasicWebAuthnClientInstrumentedTests.java | 3 +-- .../desktop/fido/Ctap2BioEnrollmentInstrumentedTests.java | 3 +-- .../testing/desktop/fido/Ctap2ClientPinInstrumentedTests.java | 3 +-- .../testing/desktop/fido/Ctap2ConfigInstrumentedTests.java | 3 +-- .../fido/Ctap2CredentialManagementInstrumentedTests.java | 3 +-- .../testing/desktop/fido/Ctap2SessionInstrumentedTests.java | 3 +-- .../desktop/fido/Ctap2SessionResetInstrumentedTests.java | 3 +-- .../desktop/fido/EnterpriseAttestationInstrumentedTests.java | 3 +-- .../com/yubico/yubikit/testing/desktop/fido/FidoTests.java | 3 +-- .../testing/desktop/fido/UvDiscouragedInstrumentedTests.java | 3 +-- .../yubikit/testing/desktop/management/ManagementTests.java | 3 +-- .../yubikit/testing/desktop/mpe/MultiProtocolResetTests.java | 3 +-- .../com/yubico/yubikit/testing/desktop/oath/OathTests.java | 3 +-- .../yubico/yubikit/testing/desktop/openpgp/OpenPgpTests.java | 3 +-- .../yubikit/testing/desktop/piv/PivBioMultiProtocolTests.java | 3 +-- .../yubikit/testing/desktop/piv/PivJcaProviderTests.java | 3 +-- .../java/com/yubico/yubikit/testing/desktop/piv/PivTests.java | 3 +-- .../java/com/yubico/yubikit/testing/desktop/sd/Scp03Tests.java | 3 +-- .../java/com/yubico/yubikit/testing/desktop/sd/Scp11Tests.java | 3 +-- .../yubico/yubikit/testing/desktop/sd/SecurityDomainTests.java | 3 +-- .../com/yubico/yubikit/testing/desktop/AlwaysManualTest.java | 3 +-- .../com/yubico/yubikit/testing/desktop/DesktopTestDriver.java | 3 +-- .../yubikit/testing/desktop/PinUvAuthProtocolV1Test.java | 3 +-- .../main/java/com/yubico/yubikit/testing/desktop/SlowTest.java | 3 +-- .../java/com/yubico/yubikit/testing/desktop/SmokeTest.java | 3 +-- .../testing/desktop/framework/FidoInstrumentedTests.java | 3 +-- .../testing/desktop/framework/ManagementInstrumentedTests.java | 3 +-- .../testing/desktop/framework/MpeInstrumentedTests.java | 3 +-- .../testing/desktop/framework/OathInstrumentedTests.java | 3 +-- .../testing/desktop/framework/OpenPgpInstrumentedTests.java | 3 +-- .../testing/desktop/framework/PivInstrumentedTests.java | 3 +-- .../desktop/framework/SecurityDomainInstrumentedTests.java | 3 +-- .../yubikit/testing/desktop/framework/YKInstrumentedTests.java | 3 +-- 50 files changed, 49 insertions(+), 98 deletions(-) diff --git a/DesktopDemo/src/main/java/com/yubico/yubikit/desktop/app/DesktopApp.java b/DesktopDemo/src/main/java/com/yubico/yubikit/desktop/app/DesktopApp.java index 31c5301b..951d30d8 100755 --- a/DesktopDemo/src/main/java/com/yubico/yubikit/desktop/app/DesktopApp.java +++ b/DesktopDemo/src/main/java/com/yubico/yubikit/desktop/app/DesktopApp.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2024 Yubico. + * Copyright (C) 2024-2025 Yubico. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.yubico.yubikit.desktop.app; import com.yubico.yubikit.core.YubiKeyDevice; diff --git a/desktop/src/main/java/com/yubico/yubikit/desktop/CompositeDevice.java b/desktop/src/main/java/com/yubico/yubikit/desktop/CompositeDevice.java index 89080822..6c9cacae 100755 --- a/desktop/src/main/java/com/yubico/yubikit/desktop/CompositeDevice.java +++ b/desktop/src/main/java/com/yubico/yubikit/desktop/CompositeDevice.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 Yubico. + * Copyright (C) 2022-2025 Yubico. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.yubico.yubikit.desktop; import com.yubico.yubikit.core.Transport; diff --git a/desktop/src/main/java/com/yubico/yubikit/desktop/OperatingSystem.java b/desktop/src/main/java/com/yubico/yubikit/desktop/OperatingSystem.java index a15db6d2..f528385c 100644 --- a/desktop/src/main/java/com/yubico/yubikit/desktop/OperatingSystem.java +++ b/desktop/src/main/java/com/yubico/yubikit/desktop/OperatingSystem.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022,2024 Yubico. + * Copyright (C) 2022-2025 Yubico. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.yubico.yubikit.desktop; public class OperatingSystem { diff --git a/desktop/src/main/java/com/yubico/yubikit/desktop/UsbPidGroup.java b/desktop/src/main/java/com/yubico/yubikit/desktop/UsbPidGroup.java index 5f0b7133..182fb41c 100755 --- a/desktop/src/main/java/com/yubico/yubikit/desktop/UsbPidGroup.java +++ b/desktop/src/main/java/com/yubico/yubikit/desktop/UsbPidGroup.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022,2024 Yubico. + * Copyright (C) 2022-2025 Yubico. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.yubico.yubikit.desktop; import com.yubico.yubikit.core.Transport; diff --git a/desktop/src/main/java/com/yubico/yubikit/desktop/UsbYubiKeyDevice.java b/desktop/src/main/java/com/yubico/yubikit/desktop/UsbYubiKeyDevice.java index 2a800b62..7994f0ba 100755 --- a/desktop/src/main/java/com/yubico/yubikit/desktop/UsbYubiKeyDevice.java +++ b/desktop/src/main/java/com/yubico/yubikit/desktop/UsbYubiKeyDevice.java @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.yubico.yubikit.desktop; import com.yubico.yubikit.core.UsbPid; diff --git a/desktop/src/main/java/com/yubico/yubikit/desktop/YubiKitManager.java b/desktop/src/main/java/com/yubico/yubikit/desktop/YubiKitManager.java index 07b15302..59fd96df 100755 --- a/desktop/src/main/java/com/yubico/yubikit/desktop/YubiKitManager.java +++ b/desktop/src/main/java/com/yubico/yubikit/desktop/YubiKitManager.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 Yubico. + * Copyright (C) 2022-2025 Yubico. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.yubico.yubikit.desktop; import com.yubico.yubikit.core.UsbPid; diff --git a/desktop/src/main/java/com/yubico/yubikit/desktop/hid/HidDevice.java b/desktop/src/main/java/com/yubico/yubikit/desktop/hid/HidDevice.java index 2d09a44b..fa6bc84e 100755 --- a/desktop/src/main/java/com/yubico/yubikit/desktop/hid/HidDevice.java +++ b/desktop/src/main/java/com/yubico/yubikit/desktop/hid/HidDevice.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 Yubico. + * Copyright (C) 2022-2025 Yubico. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.yubico.yubikit.desktop.hid; import com.yubico.yubikit.core.Transport; diff --git a/desktop/src/main/java/com/yubico/yubikit/desktop/hid/HidFidoConnection.java b/desktop/src/main/java/com/yubico/yubikit/desktop/hid/HidFidoConnection.java index 3e17ad0e..c8b92e43 100755 --- a/desktop/src/main/java/com/yubico/yubikit/desktop/hid/HidFidoConnection.java +++ b/desktop/src/main/java/com/yubico/yubikit/desktop/hid/HidFidoConnection.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2020-2022,2024 Yubico. + * Copyright (C) 2020-2025 Yubico. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/desktop/src/main/java/com/yubico/yubikit/desktop/hid/HidManager.java b/desktop/src/main/java/com/yubico/yubikit/desktop/hid/HidManager.java index dcf359f3..cb1271ea 100755 --- a/desktop/src/main/java/com/yubico/yubikit/desktop/hid/HidManager.java +++ b/desktop/src/main/java/com/yubico/yubikit/desktop/hid/HidManager.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022,2024 Yubico. + * Copyright (C) 2022-2025 Yubico. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.yubico.yubikit.desktop.hid; import java.util.ArrayList; diff --git a/desktop/src/main/java/com/yubico/yubikit/desktop/hid/HidOtpConnection.java b/desktop/src/main/java/com/yubico/yubikit/desktop/hid/HidOtpConnection.java index 4afc25af..ba141e3e 100755 --- a/desktop/src/main/java/com/yubico/yubikit/desktop/hid/HidOtpConnection.java +++ b/desktop/src/main/java/com/yubico/yubikit/desktop/hid/HidOtpConnection.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022,2024 Yubico. + * Copyright (C) 2022-2025 Yubico. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.yubico.yubikit.desktop.hid; import com.yubico.yubikit.core.internal.Logger; diff --git a/desktop/src/main/java/com/yubico/yubikit/desktop/pcsc/PcscDevice.java b/desktop/src/main/java/com/yubico/yubikit/desktop/pcsc/PcscDevice.java index e27c2395..e242f4c9 100755 --- a/desktop/src/main/java/com/yubico/yubikit/desktop/pcsc/PcscDevice.java +++ b/desktop/src/main/java/com/yubico/yubikit/desktop/pcsc/PcscDevice.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 Yubico. + * Copyright (C) 2022-2025 Yubico. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.yubico.yubikit.desktop.pcsc; import com.yubico.yubikit.core.YubiKeyConnection; diff --git a/desktop/src/main/java/com/yubico/yubikit/desktop/pcsc/PcscManager.java b/desktop/src/main/java/com/yubico/yubikit/desktop/pcsc/PcscManager.java index bce8dedb..2902664d 100755 --- a/desktop/src/main/java/com/yubico/yubikit/desktop/pcsc/PcscManager.java +++ b/desktop/src/main/java/com/yubico/yubikit/desktop/pcsc/PcscManager.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 Yubico. + * Copyright (C) 2022-2025 Yubico. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.yubico.yubikit.desktop.pcsc; import java.util.*; diff --git a/desktop/src/main/java/com/yubico/yubikit/desktop/pcsc/PcscSmartCardConnection.java b/desktop/src/main/java/com/yubico/yubikit/desktop/pcsc/PcscSmartCardConnection.java index 74b2ef56..0d7a937a 100755 --- a/desktop/src/main/java/com/yubico/yubikit/desktop/pcsc/PcscSmartCardConnection.java +++ b/desktop/src/main/java/com/yubico/yubikit/desktop/pcsc/PcscSmartCardConnection.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022,2024 Yubico. + * Copyright (C) 2022-2025 Yubico. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.yubico.yubikit.desktop.pcsc; import com.yubico.yubikit.core.Transport; diff --git a/desktop/src/main/java/com/yubico/yubikit/desktop/pcsc/UsbPcscDevice.java b/desktop/src/main/java/com/yubico/yubikit/desktop/pcsc/UsbPcscDevice.java index 23637a82..e0a2df28 100755 --- a/desktop/src/main/java/com/yubico/yubikit/desktop/pcsc/UsbPcscDevice.java +++ b/desktop/src/main/java/com/yubico/yubikit/desktop/pcsc/UsbPcscDevice.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 Yubico. + * Copyright (C) 2022-2025 Yubico. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.yubico.yubikit.desktop.pcsc; import com.yubico.yubikit.core.Transport; diff --git a/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/DeviceTests.java b/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/DeviceTests.java index e65f7650..aa4060ad 100644 --- a/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/DeviceTests.java +++ b/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/DeviceTests.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2024 Yubico. + * Copyright (C) 2024-2025 Yubico. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.yubico.yubikit.testing.desktop; import com.yubico.yubikit.testing.desktop.fido.FidoTests; diff --git a/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/FastDeviceTests.java b/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/FastDeviceTests.java index dd411970..df6fbde5 100644 --- a/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/FastDeviceTests.java +++ b/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/FastDeviceTests.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2024 Yubico. + * Copyright (C) 2024-2025 Yubico. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.yubico.yubikit.testing.desktop; import org.junit.experimental.categories.Categories; diff --git a/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/SmokeDeviceTests.java b/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/SmokeDeviceTests.java index 867c5992..d0d1b91a 100644 --- a/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/SmokeDeviceTests.java +++ b/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/SmokeDeviceTests.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2024 Yubico. + * Copyright (C) 2024-2025 Yubico. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.yubico.yubikit.testing.desktop; import org.junit.experimental.categories.Categories; diff --git a/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/fido/BasicWebAuthnClientInstrumentedTests.java b/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/fido/BasicWebAuthnClientInstrumentedTests.java index 64f64986..5b4022b6 100644 --- a/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/fido/BasicWebAuthnClientInstrumentedTests.java +++ b/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/fido/BasicWebAuthnClientInstrumentedTests.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2024 Yubico. + * Copyright (C) 2024-2025 Yubico. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.yubico.yubikit.testing.desktop.fido; import com.yubico.yubikit.fido.ctap.PinUvAuthProtocol; diff --git a/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/fido/Ctap2BioEnrollmentInstrumentedTests.java b/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/fido/Ctap2BioEnrollmentInstrumentedTests.java index 64d11a25..7b7a966b 100644 --- a/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/fido/Ctap2BioEnrollmentInstrumentedTests.java +++ b/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/fido/Ctap2BioEnrollmentInstrumentedTests.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2024 Yubico. + * Copyright (C) 2024-2025 Yubico. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.yubico.yubikit.testing.desktop.fido; import com.yubico.yubikit.testing.desktop.framework.FidoInstrumentedTests; diff --git a/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/fido/Ctap2ClientPinInstrumentedTests.java b/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/fido/Ctap2ClientPinInstrumentedTests.java index cf9f26a2..8235f649 100644 --- a/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/fido/Ctap2ClientPinInstrumentedTests.java +++ b/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/fido/Ctap2ClientPinInstrumentedTests.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2024 Yubico. + * Copyright (C) 2024-2025 Yubico. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.yubico.yubikit.testing.desktop.fido; import com.yubico.yubikit.fido.ctap.PinUvAuthProtocol; diff --git a/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/fido/Ctap2ConfigInstrumentedTests.java b/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/fido/Ctap2ConfigInstrumentedTests.java index c37bad8e..99e9fe58 100644 --- a/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/fido/Ctap2ConfigInstrumentedTests.java +++ b/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/fido/Ctap2ConfigInstrumentedTests.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2024 Yubico. + * Copyright (C) 2024-2025 Yubico. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.yubico.yubikit.testing.desktop.fido; import com.yubico.yubikit.testing.desktop.AlwaysManualTest; diff --git a/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/fido/Ctap2CredentialManagementInstrumentedTests.java b/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/fido/Ctap2CredentialManagementInstrumentedTests.java index 2a853632..2657c77e 100644 --- a/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/fido/Ctap2CredentialManagementInstrumentedTests.java +++ b/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/fido/Ctap2CredentialManagementInstrumentedTests.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2024 Yubico. + * Copyright (C) 2024-2025 Yubico. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.yubico.yubikit.testing.desktop.fido; import com.yubico.yubikit.fido.ctap.PinUvAuthProtocol; diff --git a/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/fido/Ctap2SessionInstrumentedTests.java b/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/fido/Ctap2SessionInstrumentedTests.java index 986b1c6d..d07a990f 100644 --- a/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/fido/Ctap2SessionInstrumentedTests.java +++ b/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/fido/Ctap2SessionInstrumentedTests.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2024 Yubico. + * Copyright (C) 2024-2025 Yubico. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.yubico.yubikit.testing.desktop.fido; import com.yubico.yubikit.fido.ctap.PinUvAuthProtocol; diff --git a/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/fido/Ctap2SessionResetInstrumentedTests.java b/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/fido/Ctap2SessionResetInstrumentedTests.java index 0e270d31..8f382d81 100644 --- a/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/fido/Ctap2SessionResetInstrumentedTests.java +++ b/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/fido/Ctap2SessionResetInstrumentedTests.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2024 Yubico. + * Copyright (C) 2024-2025 Yubico. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.yubico.yubikit.testing.desktop.fido; import com.yubico.yubikit.fido.ctap.PinUvAuthProtocol; diff --git a/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/fido/EnterpriseAttestationInstrumentedTests.java b/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/fido/EnterpriseAttestationInstrumentedTests.java index e865b00a..77ec943f 100644 --- a/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/fido/EnterpriseAttestationInstrumentedTests.java +++ b/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/fido/EnterpriseAttestationInstrumentedTests.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2023-2024 Yubico. + * Copyright (C) 2023-2025 Yubico. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.yubico.yubikit.testing.desktop.fido; import com.yubico.yubikit.fido.ctap.PinUvAuthProtocol; diff --git a/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/fido/FidoTests.java b/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/fido/FidoTests.java index a3d2ac22..8dc693c8 100644 --- a/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/fido/FidoTests.java +++ b/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/fido/FidoTests.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2024 Yubico. + * Copyright (C) 2024-2025 Yubico. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.yubico.yubikit.testing.desktop.fido; import com.yubico.yubikit.testing.desktop.AlwaysManualTest; diff --git a/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/fido/UvDiscouragedInstrumentedTests.java b/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/fido/UvDiscouragedInstrumentedTests.java index 3da5b8c5..4cc0abb2 100644 --- a/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/fido/UvDiscouragedInstrumentedTests.java +++ b/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/fido/UvDiscouragedInstrumentedTests.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2024 Yubico. + * Copyright (C) 2024-2025 Yubico. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.yubico.yubikit.testing.desktop.fido; import com.yubico.yubikit.fido.client.PinRequiredClientError; diff --git a/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/management/ManagementTests.java b/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/management/ManagementTests.java index a88baf7b..064e4717 100644 --- a/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/management/ManagementTests.java +++ b/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/management/ManagementTests.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2024 Yubico. + * Copyright (C) 2024-2025 Yubico. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.yubico.yubikit.testing.desktop.management; import com.yubico.yubikit.testing.desktop.framework.ManagementInstrumentedTests; diff --git a/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/mpe/MultiProtocolResetTests.java b/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/mpe/MultiProtocolResetTests.java index be73b78a..d8879657 100644 --- a/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/mpe/MultiProtocolResetTests.java +++ b/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/mpe/MultiProtocolResetTests.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2024 Yubico. + * Copyright (C) 2024-2025 Yubico. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.yubico.yubikit.testing.desktop.mpe; import com.yubico.yubikit.core.smartcard.scp.ScpKid; diff --git a/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/oath/OathTests.java b/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/oath/OathTests.java index 46f0306b..89aacf4b 100644 --- a/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/oath/OathTests.java +++ b/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/oath/OathTests.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2024 Yubico. + * Copyright (C) 2024-2025 Yubico. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.yubico.yubikit.testing.desktop.oath; import com.yubico.yubikit.core.smartcard.scp.ScpKid; diff --git a/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/openpgp/OpenPgpTests.java b/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/openpgp/OpenPgpTests.java index 51ca8713..e675154a 100644 --- a/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/openpgp/OpenPgpTests.java +++ b/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/openpgp/OpenPgpTests.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2024 Yubico. + * Copyright (C) 2024-2025 Yubico. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.yubico.yubikit.testing.desktop.openpgp; import com.yubico.yubikit.core.smartcard.scp.ScpKid; diff --git a/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/piv/PivBioMultiProtocolTests.java b/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/piv/PivBioMultiProtocolTests.java index 67897bd0..762752ef 100644 --- a/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/piv/PivBioMultiProtocolTests.java +++ b/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/piv/PivBioMultiProtocolTests.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2024 Yubico. + * Copyright (C) 2024-2025 Yubico. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.yubico.yubikit.testing.desktop.piv; import com.yubico.yubikit.testing.desktop.framework.PivInstrumentedTests; diff --git a/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/piv/PivJcaProviderTests.java b/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/piv/PivJcaProviderTests.java index ae01f8b5..b47a9e6a 100644 --- a/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/piv/PivJcaProviderTests.java +++ b/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/piv/PivJcaProviderTests.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2024 Yubico. + * Copyright (C) 2024-2025 Yubico. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.yubico.yubikit.testing.desktop.piv; import com.yubico.yubikit.core.smartcard.scp.ScpKid; diff --git a/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/piv/PivTests.java b/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/piv/PivTests.java index 4d1ffefb..a8dfe216 100644 --- a/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/piv/PivTests.java +++ b/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/piv/PivTests.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2024 Yubico. + * Copyright (C) 2024-2025 Yubico. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.yubico.yubikit.testing.desktop.piv; import com.yubico.yubikit.core.smartcard.scp.ScpKid; diff --git a/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/sd/Scp03Tests.java b/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/sd/Scp03Tests.java index 4d679260..ee19d3dc 100644 --- a/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/sd/Scp03Tests.java +++ b/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/sd/Scp03Tests.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2024 Yubico. + * Copyright (C) 2024-2025 Yubico. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.yubico.yubikit.testing.desktop.sd; import com.yubico.yubikit.testing.desktop.SmokeTest; diff --git a/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/sd/Scp11Tests.java b/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/sd/Scp11Tests.java index b6e296cc..fcbbb16f 100644 --- a/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/sd/Scp11Tests.java +++ b/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/sd/Scp11Tests.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2024 Yubico. + * Copyright (C) 2024-2025 Yubico. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.yubico.yubikit.testing.desktop.sd; import com.yubico.yubikit.testing.desktop.framework.SecurityDomainInstrumentedTests; diff --git a/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/sd/SecurityDomainTests.java b/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/sd/SecurityDomainTests.java index 1a5f26aa..b604203c 100644 --- a/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/sd/SecurityDomainTests.java +++ b/testing-desktop/src/integrationTest/java/com/yubico/yubikit/testing/desktop/sd/SecurityDomainTests.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2024 Yubico. + * Copyright (C) 2024-2025 Yubico. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.yubico.yubikit.testing.desktop.sd; import org.junit.runner.RunWith; diff --git a/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/AlwaysManualTest.java b/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/AlwaysManualTest.java index 3161efe6..14921738 100644 --- a/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/AlwaysManualTest.java +++ b/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/AlwaysManualTest.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2024 Yubico. + * Copyright (C) 2024-2025 Yubico. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.yubico.yubikit.testing.desktop; public interface AlwaysManualTest {} diff --git a/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/DesktopTestDriver.java b/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/DesktopTestDriver.java index 69e2717c..c9175ac3 100644 --- a/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/DesktopTestDriver.java +++ b/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/DesktopTestDriver.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022-2024 Yubico. + * Copyright (C) 2022-2025 Yubico. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.yubico.yubikit.testing.desktop; import com.yubico.yubikit.core.YubiKeyDevice; diff --git a/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/PinUvAuthProtocolV1Test.java b/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/PinUvAuthProtocolV1Test.java index 3cb19d76..cd727a1a 100644 --- a/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/PinUvAuthProtocolV1Test.java +++ b/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/PinUvAuthProtocolV1Test.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2024 Yubico. + * Copyright (C) 2024-2025 Yubico. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.yubico.yubikit.testing.desktop; public interface PinUvAuthProtocolV1Test {} diff --git a/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/SlowTest.java b/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/SlowTest.java index d28c5b30..325c7311 100644 --- a/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/SlowTest.java +++ b/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/SlowTest.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2024 Yubico. + * Copyright (C) 2024-2025 Yubico. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.yubico.yubikit.testing.desktop; public interface SlowTest {} diff --git a/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/SmokeTest.java b/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/SmokeTest.java index dbc2e012..db08536a 100644 --- a/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/SmokeTest.java +++ b/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/SmokeTest.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2024 Yubico. + * Copyright (C) 2024-2025 Yubico. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.yubico.yubikit.testing.desktop; public interface SmokeTest {} diff --git a/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/framework/FidoInstrumentedTests.java b/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/framework/FidoInstrumentedTests.java index cf6b25b6..a75d823b 100755 --- a/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/framework/FidoInstrumentedTests.java +++ b/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/framework/FidoInstrumentedTests.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2024 Yubico. + * Copyright (C) 2024-2025 Yubico. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.yubico.yubikit.testing.desktop.framework; import com.yubico.yubikit.core.Transport; diff --git a/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/framework/ManagementInstrumentedTests.java b/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/framework/ManagementInstrumentedTests.java index 2b3c4f36..aedad306 100644 --- a/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/framework/ManagementInstrumentedTests.java +++ b/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/framework/ManagementInstrumentedTests.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2024 Yubico. + * Copyright (C) 2024-2025 Yubico. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.yubico.yubikit.testing.desktop.framework; import com.yubico.yubikit.core.smartcard.SmartCardConnection; diff --git a/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/framework/MpeInstrumentedTests.java b/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/framework/MpeInstrumentedTests.java index 72794ec0..b405a3e4 100755 --- a/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/framework/MpeInstrumentedTests.java +++ b/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/framework/MpeInstrumentedTests.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2024 Yubico. + * Copyright (C) 2024-2025 Yubico. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.yubico.yubikit.testing.desktop.framework; import com.yubico.yubikit.fido.ctap.Ctap2Session; diff --git a/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/framework/OathInstrumentedTests.java b/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/framework/OathInstrumentedTests.java index 7375aa21..fbb0a293 100644 --- a/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/framework/OathInstrumentedTests.java +++ b/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/framework/OathInstrumentedTests.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2024 Yubico. + * Copyright (C) 2024-2025 Yubico. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.yubico.yubikit.testing.desktop.framework; import com.yubico.yubikit.oath.OathSession; diff --git a/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/framework/OpenPgpInstrumentedTests.java b/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/framework/OpenPgpInstrumentedTests.java index 7226d028..422c0f57 100644 --- a/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/framework/OpenPgpInstrumentedTests.java +++ b/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/framework/OpenPgpInstrumentedTests.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2024 Yubico. + * Copyright (C) 2024-2025 Yubico. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.yubico.yubikit.testing.desktop.framework; import com.yubico.yubikit.openpgp.OpenPgpSession; diff --git a/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/framework/PivInstrumentedTests.java b/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/framework/PivInstrumentedTests.java index a21bfdb9..dab0a78e 100755 --- a/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/framework/PivInstrumentedTests.java +++ b/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/framework/PivInstrumentedTests.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022-2024 Yubico. + * Copyright (C) 2022-2025 Yubico. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.yubico.yubikit.testing.desktop.framework; import com.yubico.yubikit.piv.PivSession; diff --git a/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/framework/SecurityDomainInstrumentedTests.java b/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/framework/SecurityDomainInstrumentedTests.java index b3f8210a..a854d523 100644 --- a/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/framework/SecurityDomainInstrumentedTests.java +++ b/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/framework/SecurityDomainInstrumentedTests.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2024 Yubico. + * Copyright (C) 2024-2025 Yubico. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.yubico.yubikit.testing.desktop.framework; import com.yubico.yubikit.testing.TestState; diff --git a/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/framework/YKInstrumentedTests.java b/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/framework/YKInstrumentedTests.java index 312b1a63..610899f8 100755 --- a/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/framework/YKInstrumentedTests.java +++ b/testing-desktop/src/main/java/com/yubico/yubikit/testing/desktop/framework/YKInstrumentedTests.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022-2024 Yubico. + * Copyright (C) 2022-2025 Yubico. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.yubico.yubikit.testing.desktop.framework; import com.yubico.yubikit.core.UsbPid; From 47b24200764d4078a4a9c126c551cf140383234a Mon Sep 17 00:00:00 2001 From: Adam Velebil Date: Mon, 20 Jan 2025 17:03:07 +0100 Subject: [PATCH 22/24] update readmes --- README.adoc | 10 ++++++++++ desktop/build.gradle | 4 +++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/README.adoc b/README.adoc index 5a3e71b3..a243bbb2 100644 --- a/README.adoc +++ b/README.adoc @@ -76,6 +76,16 @@ If you run into any issues during the development process, please fill out a developer https://support.yubico.com/support/tickets/new[support ticket] and our team will be happy to assist you. +=== Support for desktop apps +WARNING: This is an introductory version and is not intended for production use. + +Since version 2.8.0, the SDK contains the desktop module, which provides concrete implementations +of the core interfaces (USB and NFC connectivity) for building desktop Java applications. + +There are two related modules: + +* testing-desktop: SDK device test suite for desktop platforms +* DesktopDemo: A sample application demonstrating basic usage === FAQ diff --git a/desktop/build.gradle b/desktop/build.gradle index 7e9eec50..1599408a 100755 --- a/desktop/build.gradle +++ b/desktop/build.gradle @@ -9,6 +9,8 @@ dependencies { } ext.pomName = "Yubico YubiKit Desktop" -description = "This module is the core library desktop implementation and provides functionality to detect a YubiKey plugged in or tapped over NFC and to open an ISO/IEC 7816 connection, using the javax.smartcardio API." +description = "This module is the core library desktop implementation and provides " + + "functionality to detect a YubiKey plugged in or tapped over NFC and to open " + + "an ISO/IEC 7816 connection, using the javax.smartcardio API." apply from: rootProject.file('publish.gradle') \ No newline at end of file From 123fc18c750420ed57090560db453f4168694aa1 Mon Sep 17 00:00:00 2001 From: Adam Velebil Date: Tue, 21 Jan 2025 11:55:46 +0100 Subject: [PATCH 23/24] update README files --- DesktopDemo/README.adoc | 27 +++++++++++++++++++++++++++ README.adoc | 4 +++- desktop/README.adoc | 16 ++++++++++++++++ 3 files changed, 46 insertions(+), 1 deletion(-) create mode 100644 DesktopDemo/README.adoc create mode 100644 desktop/README.adoc diff --git a/DesktopDemo/README.adoc b/DesktopDemo/README.adoc new file mode 100644 index 00000000..74ef45af --- /dev/null +++ b/DesktopDemo/README.adoc @@ -0,0 +1,27 @@ += Desktop Demo Application +:icons: font + +WARNING: This demo uses experimental APIs from the desktop module. The underlying APIs are not stable and may change in future versions without notice. + +This is a demonstration application showing how to use the desktop module of our SDK. +It provides examples of basic usage and common implementation patterns. + +== Overview + +The DesktopDemo is a simple application that demonstrates: + +* Basic setup of a desktop application +* Implementation of core functionality +* Common usage patterns + +== Running the Demo + +[source,bash] +---- +./gradlew :DesktopDemo:run +---- + +== Note + +This demo is built using the experimental desktop module. As the underlying APIs may change, +please ensure you're using compatible versions of all modules. \ No newline at end of file diff --git a/README.adoc b/README.adoc index a243bbb2..aa3d1790 100644 --- a/README.adoc +++ b/README.adoc @@ -77,7 +77,9 @@ developer https://support.yubico.com/support/tickets/new[support ticket] and our team will be happy to assist you. === Support for desktop apps -WARNING: This is an introductory version and is not intended for production use. +:icons: font + +WARNING: This is an experimental version and is not intended for production use. Since version 2.8.0, the SDK contains the desktop module, which provides concrete implementations of the core interfaces (USB and NFC connectivity) for building desktop Java applications. diff --git a/desktop/README.adoc b/desktop/README.adoc new file mode 100644 index 00000000..f4da345e --- /dev/null +++ b/desktop/README.adoc @@ -0,0 +1,16 @@ += Desktop Module +:icons: font + +WARNING: This module is experimental. The API is not stable and may change in future versions without notice. + +This module provides concrete implementations of the core interfaces for desktop Java applications. +It enables building desktop applications using our SDK. + +== Overview + +The desktop module is part of our SDK's desktop support, introduced in version 2.8.0. +It implements the core interfaces necessary for desktop application development. + +== Usage + +See the DesktopDemo module for examples of how to use this implementation. \ No newline at end of file From d5762ca3bd6e16b9c8e6bf7bd36461b114d86c65 Mon Sep 17 00:00:00 2001 From: Adam Velebil Date: Tue, 21 Jan 2025 12:05:20 +0100 Subject: [PATCH 24/24] remove unused :icons: --- DesktopDemo/README.adoc | 1 - README.adoc | 1 - desktop/README.adoc | 1 - 3 files changed, 3 deletions(-) diff --git a/DesktopDemo/README.adoc b/DesktopDemo/README.adoc index 74ef45af..cd49a772 100644 --- a/DesktopDemo/README.adoc +++ b/DesktopDemo/README.adoc @@ -1,5 +1,4 @@ = Desktop Demo Application -:icons: font WARNING: This demo uses experimental APIs from the desktop module. The underlying APIs are not stable and may change in future versions without notice. diff --git a/README.adoc b/README.adoc index aa3d1790..f512a023 100644 --- a/README.adoc +++ b/README.adoc @@ -77,7 +77,6 @@ developer https://support.yubico.com/support/tickets/new[support ticket] and our team will be happy to assist you. === Support for desktop apps -:icons: font WARNING: This is an experimental version and is not intended for production use. diff --git a/desktop/README.adoc b/desktop/README.adoc index f4da345e..48bc09c4 100644 --- a/desktop/README.adoc +++ b/desktop/README.adoc @@ -1,5 +1,4 @@ = Desktop Module -:icons: font WARNING: This module is experimental. The API is not stable and may change in future versions without notice.