Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package yubikey-manager for openSUSE:Factory checked in at 2025-03-24 13:32:38 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/yubikey-manager (Old) and /work/SRC/openSUSE:Factory/.yubikey-manager.new.2696 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "yubikey-manager" Mon Mar 24 13:32:38 2025 rev:27 rq:1255525 version:5.6.1 Changes: -------- --- /work/SRC/openSUSE:Factory/yubikey-manager/yubikey-manager.changes 2025-03-17 22:22:53.123746616 +0100 +++ /work/SRC/openSUSE:Factory/.yubikey-manager.new.2696/yubikey-manager.changes 2025-03-24 13:32:46.325125628 +0100 @@ -1,0 +2,12 @@ +Mon Mar 24 08:20:18 UTC 2025 - Wolfgang Frisch <wolfgang.fri...@suse.com> + +- Update to 5.6.1 + * Fix: Version 5.6.0 uses Exclusive smart card connections, which caused + connections to fail if another application was accessing the YubiKey. This + version adds a fallback to use non-exclusive connections in case of such a + failure. + * Bugfix: APDU encoding was slightly incorrect for commands which specify Le, + but no data body. This caused issued on some platforms. + * CLI: The "fido info" command now shows the YubiKey AAGUID, when available. + +------------------------------------------------------------------- Old: ---- yubikey_manager-5.6.0.tar.gz yubikey_manager-5.6.0.tar.gz.sig New: ---- yubikey_manager-5.6.1.tar.gz yubikey_manager-5.6.1.tar.gz.sig ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ yubikey-manager.spec ++++++ --- /var/tmp/diff_new_pack.qpTGnT/_old 2025-03-24 13:32:47.573177625 +0100 +++ /var/tmp/diff_new_pack.qpTGnT/_new 2025-03-24 13:32:47.573177625 +0100 @@ -17,7 +17,7 @@ Name: yubikey-manager -Version: 5.6.0 +Version: 5.6.1 Release: 0 Summary: Python 3 library and command line tool for configuring a YubiKey License: BSD-2-Clause ++++++ yubikey_manager-5.6.0.tar.gz -> yubikey_manager-5.6.1.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yubikey_manager-5.6.0/NEWS new/yubikey_manager-5.6.1/NEWS --- old/yubikey_manager-5.6.0/NEWS 1970-01-01 01:00:00.000000000 +0100 +++ new/yubikey_manager-5.6.1/NEWS 1970-01-01 01:00:00.000000000 +0100 @@ -1,3 +1,11 @@ +* Version 5.6.1 (released 2025-03-18) + * Fix: Version 5.6.0 uses Exclusive smart card connections, which caused connections + to fail if another application was accessing the YubiKey. This version adds a + fallback to use non-exclusive connections in case of such a failure. + * Bugfix: APDU encoding was slightly incorrect for commands which specify Le, but no + data body. This caused issued on some platforms. + * CLI: The "fido info" command now shows the YubiKey AAGUID, when available. + * Version 5.6.0 (released 2025-03-12) * SCP: Add support for specifying Le (needed in OpenPGP get_challenge). * PIV: When writing a new CHUID, prefer to keep data from the old one if possible. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yubikey_manager-5.6.0/PKG-INFO new/yubikey_manager-5.6.1/PKG-INFO --- old/yubikey_manager-5.6.0/PKG-INFO 1970-01-01 01:00:00.000000000 +0100 +++ new/yubikey_manager-5.6.1/PKG-INFO 1970-01-01 01:00:00.000000000 +0100 @@ -1,6 +1,6 @@ Metadata-Version: 2.3 Name: yubikey-manager -Version: 5.6.0 +Version: 5.6.1 Summary: Library and CLI for managing your YubiKey configuration. Home-page: https://github.com/Yubico/yubikey-manager License: Copyright (c) 2015 Yubico AB @@ -38,7 +38,7 @@ Classifier: Topic :: Security :: Cryptography Classifier: Topic :: Utilities Requires-Dist: click (>=8.0,<9) -Requires-Dist: cryptography (>=3.0,<45) +Requires-Dist: cryptography (>=3.0,<47) Requires-Dist: fido2 (>=1.0,<=2.0.0b1) Requires-Dist: keyring (>=23.4,<26) Requires-Dist: pyscard (>=2.0,<3) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yubikey_manager-5.6.0/man/ykman.1 new/yubikey_manager-5.6.1/man/ykman.1 --- old/yubikey_manager-5.6.0/man/ykman.1 1970-01-01 01:00:00.000000000 +0100 +++ new/yubikey_manager-5.6.1/man/ykman.1 1970-01-01 01:00:00.000000000 +0100 @@ -1,4 +1,4 @@ -.TH YKMAN "1" "March 2025" "ykman 5.6.0" "User Commands" +.TH YKMAN "1" "March 2025" "ykman 5.6.1" "User Commands" .SH NAME ykman \- YubiKey Manager (ykman) .SH SYNOPSIS diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yubikey_manager-5.6.0/pyproject.toml new/yubikey_manager-5.6.1/pyproject.toml --- old/yubikey_manager-5.6.0/pyproject.toml 1970-01-01 01:00:00.000000000 +0100 +++ new/yubikey_manager-5.6.1/pyproject.toml 1970-01-01 01:00:00.000000000 +0100 @@ -1,6 +1,6 @@ [project] name = "yubikey-manager" -version = "5.6.0" +version = "5.6.1" description = "Library and CLI for managing your YubiKey configuration." authors = [ { name = "Dain Nilsson", email = "<d...@yubico.com>" } @@ -16,7 +16,7 @@ "Topic :: Utilities" ] dependencies = [ - "cryptography (>=3.0, <45)", + "cryptography (>=3.0, <47)", "pyscard (>=2.0, <3)", "fido2 (>=1.0, <=2.0.0b1)", "click (>=8.0, <9)", diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yubikey_manager-5.6.0/tests/device/test_oath.py new/yubikey_manager-5.6.1/tests/device/test_oath.py --- old/yubikey_manager-5.6.0/tests/device/test_oath.py 1970-01-01 01:00:00.000000000 +0100 +++ new/yubikey_manager-5.6.1/tests/device/test_oath.py 1970-01-01 01:00:00.000000000 +0100 @@ -91,7 +91,7 @@ HMAC_VECTORS = { - b"\x0B" + b"\x0b" * 20: { b"Hi There": { HASH_ALGORITHM.SHA256: bytes.fromhex( @@ -114,9 +114,9 @@ ), } }, - b"\xAA" + b"\xaa" * 20: { - b"\xDD" + b"\xdd" * 50: { HASH_ALGORITHM.SHA256: bytes.fromhex( "773ea91e36800e46854db8ebd09181a72959098b3ef8c122d9635514ced565fe" @@ -128,7 +128,7 @@ } }, bytes.fromhex("0102030405060708090a0b0c0d0e0f10111213141516171819"): { - b"\xCD" + b"\xcd" * 50: { HASH_ALGORITHM.SHA256: bytes.fromhex( "82558a389a443c0ea4cc819899f2083a85f0faa3e578f8077a2e3ff46729665b" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yubikey_manager-5.6.0/ykman/__init__.py new/yubikey_manager-5.6.1/ykman/__init__.py --- old/yubikey_manager-5.6.0/ykman/__init__.py 1970-01-01 01:00:00.000000000 +0100 +++ new/yubikey_manager-5.6.1/ykman/__init__.py 1970-01-01 01:00:00.000000000 +0100 @@ -25,4 +25,4 @@ # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. -__version__ = "5.6.0" +__version__ = "5.6.1" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yubikey_manager-5.6.0/ykman/_cli/fido.py new/yubikey_manager-5.6.1/ykman/_cli/fido.py --- old/yubikey_manager-5.6.0/ykman/_cli/fido.py 1970-01-01 01:00:00.000000000 +0100 +++ new/yubikey_manager-5.6.1/ykman/_cli/fido.py 1970-01-01 01:00:00.000000000 +0100 @@ -111,6 +111,8 @@ data["FIPS approved"] = is_in_fips_mode(ctx.obj["conn"]) if ctap2: + if ctap2.info.aaguid: + data["AAGUID"] = str(ctap2.info.aaguid) client_pin = ClientPin(ctap2) # N.B. All YubiKeys with CTAP2 support PIN. if ctap2.info.options["clientPin"]: if ctap2.info.force_pin_change: @@ -186,7 +188,6 @@ if not readers or readers[0].reader.name != conn._name: raise CliFail("Unable to isolate NFC reader.") dev = readers[0] - logger.debug(f"use: {dev}") is_fips = False def prompt_re_insert(): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yubikey_manager-5.6.0/ykman/diagnostics.py new/yubikey_manager-5.6.1/ykman/diagnostics.py --- old/yubikey_manager-5.6.0/ykman/diagnostics.py 1970-01-01 01:00:00.000000000 +0100 +++ new/yubikey_manager-5.6.1/ykman/diagnostics.py 1970-01-01 01:00:00.000000000 +0100 @@ -201,9 +201,9 @@ bio_enroll = ctap2.info.options.get("bioEnroll") if bio_enroll: - ctap_data[ - "Fingerprint retries" - ] = client_pin.get_uv_retries() + ctap_data["Fingerprint retries"] = ( + client_pin.get_uv_retries() + ) elif bio_enroll is False: ctap_data["Fingerprints"] = "Not configured" else: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yubikey_manager-5.6.0/ykman/pcsc/__init__.py new/yubikey_manager-5.6.1/ykman/pcsc/__init__.py --- old/yubikey_manager-5.6.0/ykman/pcsc/__init__.py 1970-01-01 01:00:00.000000000 +0100 +++ new/yubikey_manager-5.6.1/ykman/pcsc/__init__.py 1970-01-01 01:00:00.000000000 +0100 @@ -40,12 +40,14 @@ from fido2.pcsc import CtapPcscDevice from time import sleep import subprocess # nosec +import os import logging logger = logging.getLogger(__name__) YK_READER_NAME = "yubico yubikey" +_YKMAN_NO_EXCLUSIVE = "YKMAN_NO_EXLUSIVE" # Figure out what the PID should be based on the reader name @@ -89,10 +91,16 @@ return self._open_smartcard_connection() elif issubclass(CtapPcscDevice, connection_type): if self.transport == TRANSPORT.NFC: - return CtapPcscDevice( - ExclusiveConnectCardConnection(self.reader.createConnection()), - self.reader.name, - ) + connection = self.reader.createConnection() + if os.environ.get(_YKMAN_NO_EXCLUSIVE) is None: + excl_connection = ExclusiveConnectCardConnection(connection) + try: + dev = CtapPcscDevice(excl_connection, self.reader.name) + logger.debug("Using exclusive CCID connection") + return dev + except CardConnectionException: + logger.info("Failed to get exclusive CCID access") + return CtapPcscDevice(connection, self.reader.name) return super(ScardYubiKeyDevice, self).open_connection(connection_type) def _open_smartcard_connection(self) -> SmartCardConnection: @@ -106,8 +114,20 @@ class ScardSmartCardConnection(SmartCardConnection): def __init__(self, connection): - self.connection = ExclusiveConnectCardConnection(connection) - self.connection.connect() + if os.environ.get(_YKMAN_NO_EXCLUSIVE) is None: + excl_connection = ExclusiveConnectCardConnection(connection) + try: + excl_connection.connect() + self.connection = excl_connection + logger.debug("Using exclusive CCID connection") + except CardConnectionException: + logger.info("Failed to get exclusive CCID access") + connection.connect() + self.connection = connection + else: + connection.connect() + self.connection = connection + atr = self.connection.getATR() self._transport = ( TRANSPORT.USB if atr and atr[1] & 0xF0 == 0xF0 else TRANSPORT.NFC diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yubikey_manager-5.6.0/ykman/piv.py new/yubikey_manager-5.6.1/ykman/piv.py --- old/yubikey_manager-5.6.0/ykman/piv.py 1970-01-01 01:00:00.000000000 +0100 +++ new/yubikey_manager-5.6.1/ykman/piv.py 1970-01-01 01:00:00.000000000 +0100 @@ -528,9 +528,9 @@ try: # Bio metadata bio = session.get_bio_metadata() if bio.configured: - info[ - "Biometrics" - ] = f"Configured, {bio.attempts_remaining} attempts remaining" + info["Biometrics"] = ( + f"Configured, {bio.attempts_remaining} attempts remaining" + ) else: info["Biometrics"] = "Not configured" except NotSupportedError: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yubikey_manager-5.6.0/ykman/scancodes/modhex.py new/yubikey_manager-5.6.1/ykman/scancodes/modhex.py --- old/yubikey_manager-5.6.0/ykman/scancodes/modhex.py 1970-01-01 01:00:00.000000000 +0100 +++ new/yubikey_manager-5.6.1/ykman/scancodes/modhex.py 1970-01-01 01:00:00.000000000 +0100 @@ -28,7 +28,7 @@ # POSSIBILITY OF SUCH DAMAGE. """Scancode map for keyboard layout based on Modhex. Note that this - layouts allows both upper and lowercase characters.""" +layouts allows both upper and lowercase characters.""" SHIFT = 0x80 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yubikey_manager-5.6.0/yubikit/core/smartcard/__init__.py new/yubikey_manager-5.6.1/yubikit/core/smartcard/__init__.py --- old/yubikey_manager-5.6.0/yubikit/core/smartcard/__init__.py 1970-01-01 01:00:00.000000000 +0100 +++ new/yubikey_manager-5.6.1/yubikit/core/smartcard/__init__.py 1970-01-01 01:00:00.000000000 +0100 @@ -147,8 +147,7 @@ p2: int, data: bytes, le: int, - ) -> Tuple[bytes, int]: - ... + ) -> Tuple[bytes, int]: ... class ApduFormatProcessor(ApduProcessor): @@ -162,8 +161,7 @@ @abc.abstractmethod def format_apdu( self, cla: int, ins: int, p1: int, p2: int, data: bytes, le: int - ) -> bytes: - ... + ) -> bytes: ... SHORT_APDU_MAX_CHUNK = 0xFF @@ -171,9 +169,15 @@ class ShortApduProcessor(ApduFormatProcessor): def format_apdu(self, cla, ins, p1, p2, data, le): - buf = struct.pack(">BBBBB", cla, ins, p1, p2, len(data)) + data + buf = struct.pack(">BBBB", cla, ins, p1, p2) + if data: + buf += struct.pack(">B", len(data)) + data if le: buf += struct.pack(">B", le) + elif not data: + # No data nor Le, need explicit Lc + buf += b"\0" + return buf def send_apdu(self, cla, ins, p1, p2, data, le): @@ -195,9 +199,15 @@ self._max_apdu_size = max_apdu_size def format_apdu(self, cla, ins, p1, p2, data, le): - buf = struct.pack(">BBBBBH", cla, ins, p1, p2, 0, len(data)) + data + buf = struct.pack(">BBBB", cla, ins, p1, p2) + if data: + buf += struct.pack(">BH", 0, len(data)) + data if le: + if not data: + # Use 3-byte Le + buf += b"\0" buf += struct.pack(">H", le) + if len(buf) > self._max_apdu_size: raise NotSupportedError("APDU length exceeds YubiKey capability") return buf diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yubikey_manager-5.6.0/yubikit/management.py new/yubikey_manager-5.6.1/yubikit/management.py --- old/yubikey_manager-5.6.0/yubikit/management.py 1970-01-01 01:00:00.000000000 +0100 +++ new/yubikey_manager-5.6.1/yubikit/management.py 1970-01-01 01:00:00.000000000 +0100 @@ -405,20 +405,16 @@ version: Version @abc.abstractmethod - def close(self) -> None: - ... + def close(self) -> None: ... @abc.abstractmethod - def set_mode(self, data: bytes) -> None: - ... + def set_mode(self, data: bytes) -> None: ... @abc.abstractmethod - def read_config(self, page: int = 0) -> bytes: - ... + def read_config(self, page: int = 0) -> bytes: ... @abc.abstractmethod - def write_config(self, config: bytes) -> None: - ... + def write_config(self, config: bytes) -> None: ... class _ManagementOtpBackend(_Backend): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yubikey_manager-5.6.0/yubikit/piv.py new/yubikey_manager-5.6.1/yubikit/piv.py --- old/yubikey_manager-5.6.0/yubikit/piv.py 1970-01-01 01:00:00.000000000 +0100 +++ new/yubikey_manager-5.6.1/yubikit/piv.py 1970-01-01 01:00:00.000000000 +0100 @@ -742,14 +742,12 @@ logger.info("PIV application data reset performed") @overload - def authenticate(self, management_key: bytes) -> None: - ... + def authenticate(self, management_key: bytes) -> None: ... @overload def authenticate( self, key_type: MANAGEMENT_KEY_TYPE, management_key: bytes - ) -> None: - ... + ) -> None: ... def authenticate(self, *args, **kwargs) -> None: """Authenticate to PIV with management key. @@ -955,8 +953,13 @@ :param new_puk: The new PUK. """ logger.debug("Changing PUK") - self._change_reference(INS_CHANGE_REFERENCE, PUK_P2, old_puk, new_puk) - logger.info("New PUK set") + try: + self._change_reference(INS_CHANGE_REFERENCE, PUK_P2, old_puk, new_puk) + logger.info("New PUK set") + except ApduError as e: + if e.sw == SW.INVALID_INSTRUCTION: + raise NotSupportedError("Setting PUK is not supported on this YubiKey") + raise def unblock_pin(self, puk: str, new_pin: str) -> None: """Reset PIN with PUK. @@ -965,8 +968,15 @@ :param new_pin: The new PIN. """ logger.debug("Using PUK to set new PIN") - self._change_reference(INS_RESET_RETRY, PIN_P2, puk, new_pin) - logger.info("New PIN set") + try: + self._change_reference(INS_RESET_RETRY, PIN_P2, puk, new_pin) + logger.info("New PIN set") + except ApduError as e: + if e.sw == SW.INVALID_INSTRUCTION: + raise NotSupportedError( + "Unblocking PIN is not supported on this YubiKey" + ) + raise def set_pin_attempts(self, pin_attempts: int, puk_attempts: int) -> None: """Set PIN retries for PIN and PUK. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/yubikey_manager-5.6.0/yubikit/yubiotp.py new/yubikey_manager-5.6.1/yubikit/yubiotp.py --- old/yubikey_manager-5.6.0/yubikit/yubiotp.py 1970-01-01 01:00:00.000000000 +0100 +++ new/yubikey_manager-5.6.1/yubikit/yubiotp.py 1970-01-01 01:00:00.000000000 +0100 @@ -635,12 +635,10 @@ class _Backend(abc.ABC): @abc.abstractmethod - def close(self) -> None: - ... + def close(self) -> None: ... @abc.abstractmethod - def write_update(self, slot: CONFIG_SLOT, data: bytes) -> bytes: - ... + def write_update(self, slot: CONFIG_SLOT, data: bytes) -> bytes: ... @abc.abstractmethod def send_and_receive( @@ -650,8 +648,7 @@ expected_len: int, event: Optional[Event] = None, on_keepalive: Optional[Callable[[int], None]] = None, - ) -> bytes: - ... + ) -> bytes: ... class _YubiOtpOtpBackend(_Backend):