Hello community,

here is the log from the commit of package yubikey-manager for openSUSE:Factory 
checked in at 2020-02-04 19:56:32
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/yubikey-manager (Old)
 and      /work/SRC/openSUSE:Factory/.yubikey-manager.new.26092 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "yubikey-manager"

Tue Feb  4 19:56:32 2020 rev:14 rq:769932 version:3.1.1

Changes:
--------
--- /work/SRC/openSUSE:Factory/yubikey-manager/yubikey-manager.changes  
2019-12-18 14:48:36.585946614 +0100
+++ 
/work/SRC/openSUSE:Factory/.yubikey-manager.new.26092/yubikey-manager.changes   
    2020-02-04 19:56:38.105436447 +0100
@@ -1,0 +2,17 @@
+Tue Feb  4 09:58:35 UTC 2020 - Paolo Stivanin <[email protected]>
+
+- Update to 3.1.1
+  * Add support for YubiKey 5C NFC
+  * OpenPGP: set-touch now performs compatibility checks before prompting for 
PIN
+  * OpenPGP: Improve error messages and documentation for set-touch
+  * PIV: read-object command no longer adds a trailing newline
+  * CLI: Hint at missing permissions when opening a device fails
+  * Linux: Improve error handling when pcscd is not running
+  * Windows: Improve how .DLL files are loaded, thanks to Marius Gabriel Mihai 
for reporting this!
+  * Bugfix: set-touch now accepts the cached-fixed option
+  * Bugfix: Fix crash in OtpController.prepare_upload_key() error parsing
+  * Bugfix: Fix crash in piv info command when a certificate slot contains an 
invalid certificate
+  * Library: PivController.read_certificate(slot) now wraps certificate 
parsing exceptions in new exception type InvalidCertificate
+  * Library: PivController.list_certificates() now returns None for slots 
containing invalid certificate, instead of raising an exception
+
+-------------------------------------------------------------------

Old:
----
  yubikey-manager-3.1.0.tar.gz
  yubikey-manager-3.1.0.tar.gz.sig

New:
----
  yubikey-manager-3.1.1.tar.gz
  yubikey-manager-3.1.1.tar.gz.sig

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ yubikey-manager.spec ++++++
--- /var/tmp/diff_new_pack.NlrsB1/_old  2020-02-04 19:56:39.021436981 +0100
+++ /var/tmp/diff_new_pack.NlrsB1/_new  2020-02-04 19:56:39.021436981 +0100
@@ -1,7 +1,7 @@
 #
 # spec file for package yubikey-manager
 #
-# Copyright (c) 2019 SUSE LLC
+# Copyright (c) 2020 SUSE LLC
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -17,7 +17,7 @@
 
 
 Name:           yubikey-manager
-Version:        3.1.0
+Version:        3.1.1
 Release:        0
 Summary:        Python 3 library and command line tool for configuring a 
YubiKey
 License:        BSD-2-Clause

++++++ yubikey-manager-3.1.0.tar.gz -> yubikey-manager-3.1.1.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yubikey-manager-3.1.0/NEWS 
new/yubikey-manager-3.1.1/NEWS
--- old/yubikey-manager-3.1.0/NEWS      2019-08-20 09:54:22.000000000 +0200
+++ new/yubikey-manager-3.1.1/NEWS      2020-01-29 08:40:16.000000000 +0100
@@ -1,3 +1,17 @@
+* Version 3.1.1 (released 2020-01-29)
+ ** Add support for YubiKey 5C NFC
+ ** OpenPGP: set-touch now performs compatibility checks before prompting for 
PIN
+ ** OpenPGP: Improve error messages and documentation for set-touch
+ ** PIV: read-object command no longer adds a trailing newline
+ ** CLI: Hint at missing permissions when opening a device fails
+ ** Linux: Improve error handling when pcscd is not running
+ ** Windows: Improve how .DLL files are loaded, thanks to Marius Gabriel Mihai 
for reporting this!
+ ** Bugfix: set-touch now accepts the cached-fixed option
+ ** Bugfix: Fix crash in OtpController.prepare_upload_key() error parsing
+ ** Bugfix: Fix crash in piv info command when a certificate slot contains an 
invalid certificate
+ ** Library: PivController.read_certificate(slot) now wraps certificate 
parsing exceptions in new exception type `InvalidCertificate`
+ ** Library: PivController.list_certificates() now returns `None` for slots 
containing invalid certificate, instead of raising an exception
+
 * Version 3.1.0 (released 2019-08-20)
  ** Add support for YubiKey 5Ci
  ** OpenPGP: the info command now prints OpenPGP specification version as well
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yubikey-manager-3.1.0/PKG-INFO 
new/yubikey-manager-3.1.1/PKG-INFO
--- old/yubikey-manager-3.1.0/PKG-INFO  2019-08-20 09:59:20.000000000 +0200
+++ new/yubikey-manager-3.1.1/PKG-INFO  2020-01-29 08:40:47.000000000 +0100
@@ -1,12 +1,13 @@
-Metadata-Version: 1.1
+Metadata-Version: 1.2
 Name: yubikey-manager
-Version: 3.1.0
+Version: 3.1.1
 Summary: Tool for managing your YubiKey configuration.
 Home-page: https://github.com/Yubico/yubikey-manager
-Author: Yubico Open Source Maintainers
-Author-email: [email protected]
+Author: Dain Nilsson
+Author-email: [email protected]
+Maintainer: Yubico Open Source Maintainers
+Maintainer-email: [email protected]
 License: BSD 2 clause
-Description-Content-Type: UNKNOWN
 Description: UNKNOWN
 Platform: UNKNOWN
 Classifier: License :: OSI Approved :: BSD License
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yubikey-manager-3.1.0/README.adoc 
new/yubikey-manager-3.1.1/README.adoc
--- old/yubikey-manager-3.1.0/README.adoc       2019-08-20 09:54:22.000000000 
+0200
+++ new/yubikey-manager-3.1.1/README.adoc       2020-01-29 08:40:16.000000000 
+0100
@@ -1,6 +1,5 @@
 == YubiKey Manager CLI
-image:https://travis-ci.org/Yubico/yubikey-manager.svg?branch=master["Build 
Status", link="https://travis-ci.org/Yubico/yubikey-manager";]
-image:https://ci.appveyor.com/api/projects/status/fp7nb97m8372axq8?svg=true["Appveyor
 Status", link="https://ci.appveyor.com/project/Yubico53275/yubikey-manager";]
+image:https://github.com/Yubico/yubikey-manager/workflows/build/badge.svg["Build
 Status", link="https://github.com/Yubico/yubikey-manager/actions";]
 
 Python library and command line tool for configuring a YubiKey. If you're 
looking for the full graphical application, which also includes the command 
line tool, it's https://developers.yubico.com/yubikey-manager-qt/[here].
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yubikey-manager-3.1.0/man/ykman.1 
new/yubikey-manager-3.1.1/man/ykman.1
--- old/yubikey-manager-3.1.0/man/ykman.1       2019-08-20 09:54:22.000000000 
+0200
+++ new/yubikey-manager-3.1.1/man/ykman.1       2020-01-29 08:40:16.000000000 
+0100
@@ -1,4 +1,4 @@
-.TH YKMAN "1" "June 2019" "ykman 3.0.0" "User Commands"
+.TH YKMAN "1" "January 2020" "ykman 3.1.1" "User Commands"
 .SH NAME
 ykman \- YubiKey Manager (ykman)
 .SH SYNOPSIS
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yubikey-manager-3.1.0/setup.py 
new/yubikey-manager-3.1.1/setup.py
--- old/yubikey-manager-3.1.0/setup.py  2019-08-20 09:54:22.000000000 +0200
+++ new/yubikey-manager-3.1.1/setup.py  2020-01-29 08:40:16.000000000 +0100
@@ -30,7 +30,8 @@
 from setuptools import setup
 
 install_requires = [
-    'six', 'pyscard', 'pyusb', 'click', 'cryptography', 'pyopenssl', 'fido2 >= 
0.7'
+    'six', 'pyscard', 'pyusb', 'click',
+    'cryptography', 'pyopenssl', 'fido2 >= 0.7'
 ]
 tests_require = []
 if sys.version_info < (3, 3):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/yubikey-manager-3.1.0/test/on_yubikey/cli_piv/test_misc.py 
new/yubikey-manager-3.1.1/test/on_yubikey/cli_piv/test_misc.py
--- old/yubikey-manager-3.1.0/test/on_yubikey/cli_piv/test_misc.py      
2019-08-20 09:54:22.000000000 +0200
+++ new/yubikey-manager-3.1.1/test/on_yubikey/cli_piv/test_misc.py      
2020-01-29 08:40:16.000000000 +0100
@@ -1,7 +1,8 @@
 import unittest
 
-from ..framework import cli_test_suite
+from ykman.piv import OBJ
 from .util import DEFAULT_MANAGEMENT_KEY
+from ..framework import cli_test_suite
 
 
 @cli_test_suite
@@ -19,12 +20,19 @@
             output = ykman_cli('piv', 'reset', '-f')
             self.assertIn('Success!', output)
 
-        def test_write_read_object(self):
-            ykman_cli(
-                'piv', 'write-object',
-                '-m', DEFAULT_MANAGEMENT_KEY, '0x5f0001',
-                '-', input='test data')
-            output = ykman_cli('piv', 'read-object', '0x5f0001')
-            self.assertEquals('test data\n', output)
+        def test_export_invalid_certificate_fails(self):
+            ykman_cli('piv', 'write-object', hex(OBJ.AUTHENTICATION), '-',
+                      '-m', DEFAULT_MANAGEMENT_KEY,
+                      input='This is not a cert')
+
+            with self.assertRaises(SystemExit):
+                ykman_cli('piv', 'export-certificate',
+                          hex(OBJ.AUTHENTICATION), '-')
+
+        def test_info_with_invalid_certificate_does_not_crash(self):
+            ykman_cli('piv', 'write-object', hex(OBJ.AUTHENTICATION), '-',
+                      '-m', DEFAULT_MANAGEMENT_KEY,
+                      input='This is not a cert')
+            ykman_cli('piv', 'info')
 
     return [Misc]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/yubikey-manager-3.1.0/test/on_yubikey/cli_piv/test_read_write_object.py 
new/yubikey-manager-3.1.1/test/on_yubikey/cli_piv/test_read_write_object.py
--- old/yubikey-manager-3.1.0/test/on_yubikey/cli_piv/test_read_write_object.py 
1970-01-01 01:00:00.000000000 +0100
+++ new/yubikey-manager-3.1.1/test/on_yubikey/cli_piv/test_read_write_object.py 
2020-01-29 08:40:16.000000000 +0100
@@ -0,0 +1,86 @@
+import os
+import unittest
+
+from cryptography.hazmat.primitives import serialization
+from ..framework import cli_test_suite
+from ykman.piv import OBJ, SLOT, TAG
+from ykman.util import Tlv
+from .util import DEFAULT_MANAGEMENT_KEY
+from ...util import generate_self_signed_certificate
+
+
+@cli_test_suite
+def additional_tests(ykman_cli):
+    class ReadWriteObject(unittest.TestCase):
+
+        def setUp(cls):
+            ykman_cli('piv', 'reset', '-f')
+            pass
+
+        @classmethod
+        def tearDownClass(cls):
+            ykman_cli('piv', 'reset', '-f')
+            pass
+
+        def test_write_read_preserves_ansi_escapes(self):
+            red = b'\x00\x1b[31m'
+            blue = b'\x00\x1b[34m'
+            reset = b'\x00\x1b[0m'
+            data = (b'Hello, ' + red + b'red' + reset + b' and ' + blue
+                    + b'blue' + reset + b' world!')
+            ykman_cli(
+                'piv', 'write-object',
+                '-m', DEFAULT_MANAGEMENT_KEY, '0x5f0001',
+                '-', input=data)
+            output_data = ykman_cli.with_bytes_output(
+                'piv', 'read-object', '0x5f0001')
+            self.assertEqual(data, output_data)
+
+        def test_read_write_read_is_noop(self):
+            data = os.urandom(32)
+
+            ykman_cli('piv', 'write-object', hex(OBJ.AUTHENTICATION), '-',
+                      '-m', DEFAULT_MANAGEMENT_KEY,
+                      input=data)
+
+            output1 = ykman_cli.with_bytes_output('piv', 'read-object',
+                                                  hex(OBJ.AUTHENTICATION))
+            self.assertEqual(output1, data)
+
+            ykman_cli('piv', 'write-object', hex(OBJ.AUTHENTICATION), '-',
+                      '-m', DEFAULT_MANAGEMENT_KEY,
+                      input=output1)
+
+            output2 = ykman_cli.with_bytes_output('piv', 'read-object',
+                                                  hex(OBJ.AUTHENTICATION))
+            self.assertEqual(output2, data)
+
+        def test_read_write_certificate_as_object(self):
+            with self.assertRaises(SystemExit):
+                ykman_cli('piv', 'read-object', hex(OBJ.AUTHENTICATION))
+
+            cert = generate_self_signed_certificate()
+            cert_bytes_der = cert.public_bytes(
+                encoding=serialization.Encoding.DER)
+
+            input_tlv = (
+                Tlv(TAG.CERTIFICATE, cert_bytes_der) +
+                Tlv(TAG.CERT_INFO, b'\0') +
+                Tlv(TAG.LRC, b'')
+            )
+
+            ykman_cli('piv', 'write-object', hex(OBJ.AUTHENTICATION), '-',
+                      '-m', DEFAULT_MANAGEMENT_KEY,
+                      input=input_tlv)
+
+            output1 = ykman_cli.with_bytes_output('piv', 'read-object',
+                                                  hex(OBJ.AUTHENTICATION))
+            output_cert_bytes = Tlv.parse_dict(output1)[TAG.CERTIFICATE]
+            self.assertEqual(output_cert_bytes, cert_bytes_der)
+
+            output2 = ykman_cli.with_bytes_output('piv', 'export-certificate',
+                                                  hex(SLOT.AUTHENTICATION), 
'-',
+                                                  '--format', 'DER')
+            self.assertEqual(output2, cert_bytes_der)
+
+    return [ReadWriteObject]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/yubikey-manager-3.1.0/test/on_yubikey/framework/__init__.py 
new/yubikey-manager-3.1.1/test/on_yubikey/framework/__init__.py
--- old/yubikey-manager-3.1.0/test/on_yubikey/framework/__init__.py     
2019-08-20 09:54:22.000000000 +0200
+++ new/yubikey-manager-3.1.1/test/on_yubikey/framework/__init__.py     
2020-01-29 08:40:16.000000000 +0100
@@ -25,7 +25,7 @@
     _test_serials = set(int(s) for s in _test_serials.split(','))
 
     for dev in list_devices():
-        print('{:%.3f} {}'.format(time.time() - start_time, dev))
+        print('{:.3f} {}'.format(time.time() - start_time, dev))
         _serials_present.add(dev.serial)
         _versions[dev.serial] = dev.version
         dev.close()
@@ -66,7 +66,10 @@
     Creates a specialized version of ykman_cli preset with the serial number of
     the given device.
     '''
-    return functools.partial(test.util.ykman_cli, '--device', dev.serial)
+    f = functools.partial(test.util.ykman_cli, '--device', dev.serial)
+    f.with_bytes_output = functools.partial(test.util.ykman_cli_bytes,
+                                            '--device', dev.serial)
+    return f
 
 
 def _specialize_open_device(dev, transport):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yubikey-manager-3.1.0/test/on_yubikey/test_opgp.py 
new/yubikey-manager-3.1.1/test/on_yubikey/test_opgp.py
--- old/yubikey-manager-3.1.0/test/on_yubikey/test_opgp.py      2019-08-20 
09:54:22.000000000 +0200
+++ new/yubikey-manager-3.1.1/test/on_yubikey/test_opgp.py      2020-01-29 
08:40:16.000000000 +0100
@@ -3,7 +3,7 @@
 import unittest
 from cryptography.hazmat.backends import default_backend
 from cryptography.hazmat.primitives.serialization import Encoding, PublicFormat
-from cryptography.hazmat.primitives.asymmetric import ec, rsa, x25519
+from cryptography.hazmat.primitives.asymmetric import ec, rsa
 from ykman.driver_ccid import APDUError
 from ykman.opgp import OpgpController, KEY_SLOT
 from ykman.util import TRANSPORT
@@ -116,6 +116,9 @@
 
         @yubikey_conditions.version_min((5, 2, 0))
         def test_import_x25519(self):
+            from cryptography.hazmat.primitives.asymmetric import x25519
             priv = x25519.X25519PrivateKey.generate()
             self.controller.verify_admin(DEFAULT_ADMIN_PIN)
             self.controller.import_key(KEY_SLOT.ENC, priv)
+
+    return [OpgpTestCase, KeyManagement]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yubikey-manager-3.1.0/test/util.py 
new/yubikey-manager-3.1.1/test/util.py
--- old/yubikey-manager-3.1.0/test/util.py      2019-08-20 09:54:22.000000000 
+0200
+++ new/yubikey-manager-3.1.1/test/util.py      2020-01-29 08:40:16.000000000 
+0100
@@ -1,7 +1,20 @@
+import datetime
+import logging
+import os
+
 from click.testing import CliRunner
+from cryptography import x509
+from cryptography.hazmat.backends import default_backend
+from cryptography.hazmat.primitives import hashes
+from cryptography.hazmat.primitives.asymmetric import ec
+from cryptography.hazmat.primitives.serialization import Encoding
+from cryptography.utils import int_from_bytes
+from cryptography.x509.oid import NameOID
 from ykman.cli.__main__ import cli
-import os
+from ykman.util import Tlv
+
 
+logger = logging.getLogger(__name__)
 
 PKG_DIR = os.path.dirname(os.path.abspath(__file__))
 
@@ -17,7 +30,60 @@
     return result.output
 
 
+def ykman_cli_bytes(*argv, **kwargs):
+    result = ykman_cli_raw(*argv, **kwargs)
+    if result.exit_code != 0:
+        raise result.exception
+    return result.stdout_bytes
+
+
 def ykman_cli_raw(*argv, **kwargs):
     runner = CliRunner()
     result = runner.invoke(cli, list(argv), obj={}, **kwargs)
     return result
+
+
+def _generate_private_key():
+    return ec.generate_private_key(ec.SECP256R1(), default_backend())
+
+
+def _sign_cert(key, builder):
+    cert = builder.sign(key, hashes.SHA256(), default_backend())
+
+    sig = key.sign(cert.tbs_certificate_bytes, ec.ECDSA(hashes.SHA256()))
+
+    seq = Tlv.parse_list(Tlv.unpack(0x30, cert.public_bytes(Encoding.DER)))
+    # Replace signature, add unused bits = 0
+    seq[2] = Tlv(seq[2].tag, b'\0' + sig)
+    # Re-assemble sequence
+    der = Tlv(0x30, b''.join(seq))
+
+    return x509.load_der_x509_certificate(der, default_backend())
+
+
+def generate_self_signed_certificate(
+        common_name='Test', valid_from=None, valid_to=None):
+
+    valid_from = valid_from if valid_from else datetime.datetime.utcnow()
+    valid_to = valid_to if valid_to else valid_from + 
datetime.timedelta(days=1)
+
+    private_key = _generate_private_key()
+    public_key = private_key.public_key()
+
+    builder = x509.CertificateBuilder()
+    builder = builder.public_key(public_key)
+    builder = builder.subject_name(
+        x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, common_name), ]))
+
+    # Same as subject on self-signed certificates.
+    builder = builder.issuer_name(
+        x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, common_name), ]))
+
+    # x509.random_serial_number added in cryptography 1.6
+    serial = int_from_bytes(os.urandom(20), 'big') >> 1
+    builder = builder.serial_number(serial)
+
+    builder = builder.not_valid_before(valid_from)
+    builder = builder.not_valid_after(valid_to)
+
+    return _sign_cert(private_key, builder)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yubikey-manager-3.1.0/ykman/VERSION 
new/yubikey-manager-3.1.1/ykman/VERSION
--- old/yubikey-manager-3.1.0/ykman/VERSION     2019-08-20 09:54:22.000000000 
+0200
+++ new/yubikey-manager-3.1.1/ykman/VERSION     2020-01-29 08:40:16.000000000 
+0100
@@ -1 +1 @@
-3.1.0
+3.1.1
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yubikey-manager-3.1.0/ykman/cli/__main__.py 
new/yubikey-manager-3.1.1/ykman/cli/__main__.py
--- old/yubikey-manager-3.1.0/ykman/cli/__main__.py     2019-08-20 
09:54:22.000000000 +0200
+++ new/yubikey-manager-3.1.1/ykman/cli/__main__.py     2020-01-29 
08:40:16.000000000 +0100
@@ -28,6 +28,8 @@
 from __future__ import absolute_import, print_function
 
 import ykman.logging_setup
+import smartcard.pcsc.PCSCExceptions
+
 from ykman import __version__
 from ..util import TRANSPORT, Cve201715361VulnerableError, YUBIKEY
 from ..native.pyusb import get_usb_backend_version
@@ -96,8 +98,10 @@
                     ctx.fail("Command '{}' is not supported by this device."
                              .format(cmd))
         except FailedOpeningDeviceException:
-            ctx.fail('Failed connecting to a YubiKey with serial: {}'
-                     .format(serial))
+            ctx.fail(
+                'Failed connecting to a YubiKey with serial: {}. \
+                        Make sure the application have the required \
+                            permissions.'.format(serial))
 
 
 def _run_cmd_for_single(ctx, cmd, transports, reader=None):
@@ -127,8 +131,9 @@
         try:
             return descriptor.open_device(transports)
         except FailedOpeningDeviceException:
-            ctx.fail('Failed connecting to {} [{}]'.format(
-                descriptor.name, descriptor.mode))
+            ctx.fail('Failed connecting to {} [{}]. Make sure the application 
have \
+                    the required permissions.'.format(
+                        descriptor.name, descriptor.mode))
     else:
         _disabled_transport(ctx, transports, cmd)
 
@@ -221,29 +226,37 @@
 
     descriptors = get_descriptors()
     handled_serials = set()
-    for dev in list_devices():
-        if dev.key_type == YUBIKEY.SKY:
-            # We have nothing to match on, so just drop a SKY descriptor
-            d = next(x for x in descriptors if x.key_type == YUBIKEY.SKY)
-            descriptors.remove(d)
-            _print_device(dev, None)
-        else:
-            serial = dev.serial
-            if serial not in handled_serials:
-                # Drop a descriptor with a matching serial and mode
-                handled_serials.add(serial)
-                matches = [d for d in descriptors if (d.key_type, d.mode)
-                           == (dev.driver.key_type, dev.driver.mode)]
-                if len(matches) > 0:
-                    d = matches[0]
-                    descriptors.remove(d)
-                    _print_device(dev, serial)
-        dev.close()
-        if not descriptors:
-            break
+
+    try:
+        for dev in list_devices(transports=TRANSPORT.CCID):
+            if dev.key_type == YUBIKEY.SKY:
+                # We have nothing to match on, so just drop a SKY descriptor
+                d = next(x for x in descriptors if x.key_type == YUBIKEY.SKY)
+                descriptors.remove(d)
+                _print_device(dev, None)
+            else:
+                serial = dev.serial
+                if serial not in handled_serials:
+                    # Drop a descriptor with a matching serial and mode
+                    handled_serials.add(serial)
+                    matches = [d for d in descriptors if (d.key_type, d.mode)
+                               == (dev.driver.key_type, dev.driver.mode)]
+                    if len(matches) > 0:
+                        d = matches[0]
+                        descriptors.remove(d)
+                        _print_device(dev, serial)
+            dev.close()
+            if not descriptors:
+                break
+    except smartcard.pcsc.PCSCExceptions.EstablishContextException as e:
+        logger.error('Failed to list devices', exc_info=e)
+        ctx.fail(
+            'Failed to establish CCID context. Is the pcscd service running?')
 
     # List descriptors that failed to open.
-    logger.debug('Failed to open all devices, listing based on descriptors')
+    if len(descriptors) > 0:
+        logger.debug(
+            'Failed to open some devices, listing based on descriptors')
     for desc in descriptors:
         click.echo('{} [{}]'.format(desc.name, desc.mode))
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yubikey-manager-3.1.0/ykman/cli/oath.py 
new/yubikey-manager-3.1.1/ykman/cli/oath.py
--- old/yubikey-manager-3.1.0/ykman/cli/oath.py 2019-08-20 09:54:22.000000000 
+0200
+++ new/yubikey-manager-3.1.1/ykman/cli/oath.py 2020-01-29 08:40:16.000000000 
+0100
@@ -266,7 +266,7 @@
 
     if data.algorithm == ALGO.SHA512 and (
             controller.version < (4, 3, 1) or ctx.obj['dev'].is_fips):
-                ctx.fail('Algorithm SHA512 not supported on this YubiKey.')
+        ctx.fail('Algorithm SHA512 not supported on this YubiKey.')
 
     key = data.make_key()
     if not force and any(cred.key == key for cred in controller.list()):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yubikey-manager-3.1.0/ykman/cli/opgp.py 
new/yubikey-manager-3.1.1/ykman/cli/opgp.py
--- old/yubikey-manager-3.1.0/ykman/cli/opgp.py 2019-08-20 09:54:22.000000000 
+0200
+++ new/yubikey-manager-3.1.1/ykman/cli/opgp.py 2020-01-29 08:40:16.000000000 
+0100
@@ -163,16 +163,37 @@
     \b
     KEY     Key slot to set (sig, enc, aut or att).
     POLICY  Touch policy to set (on, off, fixed, cached or cached-fixed).
+
+    The touch policy is used to require user interaction for all
+    operations using the private key on the YubiKey. The touch policy is set
+    indivdually for each key slot. To see the current touch policy, run
+
+    \b
+        $ ykman openpgp info
+
+    Touch policies:
+
+    \b
+    Off (default)   No touch required
+    On              Touch required
+    Fixed           Touch required, can't be disabled without a full reset
+    Cached          Touch required, cached for 15s after use
+    Cached-Fixed    Touch required, cached for 15s after use, can't be disabled
+                    without a full reset
     """
     controller = ctx.obj['controller']
 
-    if admin_pin is None:
-        admin_pin = click.prompt('Enter admin PIN', hide_input=True, err=True)
-
     policy_name = policy.name.lower().replace('_', '-')
 
     if policy not in controller.supported_touch_policies:
-        ctx.fail('Touch policy {} not supported.'.format(policy_name))
+        ctx.fail('Touch policy {} not supported by this YubiKey.'
+                 .format(policy_name))
+
+    if key == KEY_SLOT.ATT and not controller.supports_attestation:
+        ctx.fail('Attestation is not supported by this YubiKey.')
+
+    if admin_pin is None:
+        admin_pin = click.prompt('Enter admin PIN', hide_input=True, err=True)
 
     if force or click.confirm(
         'Set touch policy of {} key to {}?'.format(
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yubikey-manager-3.1.0/ykman/cli/piv.py 
new/yubikey-manager-3.1.1/ykman/cli/piv.py
--- old/yubikey-manager-3.1.0/ykman/cli/piv.py  2019-08-20 09:54:22.000000000 
+0200
+++ new/yubikey-manager-3.1.1/ykman/cli/piv.py  2020-01-29 08:40:16.000000000 
+0100
@@ -155,54 +155,58 @@
     for (slot, cert) in controller.list_certificates().items():
         click.echo('Slot %02x:' % slot)
 
-        try:
-            # Try to read out full DN, fallback to only CN.
-            # Support for DN was added in crytography 2.5
-            subject_dn = cert.subject.rfc4514_string()
-            issuer_dn = cert.issuer.rfc4514_string()
-            print_dn = True
-        except AttributeError:
-            print_dn = False
-            logger.debug('Failed to read DN, falling back to only CNs')
-            subject_cn = cert.subject.get_attributes_for_oid(
-                x509.NameOID.COMMON_NAME)
-            subject_cn = subject_cn[0].value if subject_cn else 'None'
-            issuer_cn = cert.issuer.get_attributes_for_oid(
-                x509.NameOID.COMMON_NAME)
-            issuer_cn = issuer_cn[0].value if issuer_cn else 'None'
-        except ValueError as e:
-            # Malformed certificates may throw ValueError
-            logger.debug('Failed parsing certificate', exc_info=e)
-            click.echo('\tMalformed certificate: {}'.format(e))
-            continue
+        if isinstance(cert, x509.Certificate):
+            try:
+                # Try to read out full DN, fallback to only CN.
+                # Support for DN was added in crytography 2.5
+                subject_dn = cert.subject.rfc4514_string()
+                issuer_dn = cert.issuer.rfc4514_string()
+                print_dn = True
+            except AttributeError:
+                print_dn = False
+                logger.debug('Failed to read DN, falling back to only CNs')
+                subject_cn = cert.subject.get_attributes_for_oid(
+                    x509.NameOID.COMMON_NAME)
+                subject_cn = subject_cn[0].value if subject_cn else 'None'
+                issuer_cn = cert.issuer.get_attributes_for_oid(
+                    x509.NameOID.COMMON_NAME)
+                issuer_cn = issuer_cn[0].value if issuer_cn else 'None'
+            except ValueError as e:
+                # Malformed certificates may throw ValueError
+                logger.debug('Failed parsing certificate', exc_info=e)
+                click.echo('\tMalformed certificate: {}'.format(e))
+                continue
 
-        fingerprint = 
b2a_hex(cert.fingerprint(hashes.SHA256())).decode('ascii')
-        algo = ALGO.from_public_key(cert.public_key())
-        serial = cert.serial_number
-        try:
-            not_before = cert.not_valid_before
-        except ValueError as e:
-            logger.debug('Failed reading not_valid_before', exc_info=e)
-            not_before = None
-        try:
-            not_after = cert.not_valid_after
-        except ValueError as e:
-            logger.debug('Failed reading not_valid_after', exc_info=e)
-            not_after = None
-        # Print out everything
-        click.echo('\tAlgorithm:\t%s' % algo.name)
-        if print_dn:
-            click.echo('\tSubject DN:\t%s' % subject_dn)
-            click.echo('\tIssuer DN:\t%s' % issuer_dn)
+            fingerprint = b2a_hex(
+                cert.fingerprint(hashes.SHA256())).decode('ascii')
+            algo = ALGO.from_public_key(cert.public_key())
+            serial = cert.serial_number
+            try:
+                not_before = cert.not_valid_before
+            except ValueError as e:
+                logger.debug('Failed reading not_valid_before', exc_info=e)
+                not_before = None
+            try:
+                not_after = cert.not_valid_after
+            except ValueError as e:
+                logger.debug('Failed reading not_valid_after', exc_info=e)
+                not_after = None
+            # Print out everything
+            click.echo('\tAlgorithm:\t%s' % algo.name)
+            if print_dn:
+                click.echo('\tSubject DN:\t%s' % subject_dn)
+                click.echo('\tIssuer DN:\t%s' % issuer_dn)
+            else:
+                click.echo('\tSubject CN:\t%s' % subject_cn)
+                click.echo('\tIssuer CN:\t%s' % issuer_cn)
+            click.echo('\tSerial:\t\t%s' % serial)
+            click.echo('\tFingerprint:\t%s' % fingerprint)
+            if not_before:
+                click.echo('\tNot before:\t%s' % not_before)
+            if not_after:
+                click.echo('\tNot after:\t%s' % not_after)
         else:
-            click.echo('\tSubject CN:\t%s' % subject_cn)
-            click.echo('\tIssuer CN:\t%s' % issuer_cn)
-        click.echo('\tSerial:\t\t%s' % serial)
-        click.echo('\tFingerprint:\t%s' % fingerprint)
-        if not_before:
-            click.echo('\tNot before:\t%s' % not_before)
-        if not_after:
-            click.echo('\tNot after:\t%s' % not_after)
+            click.echo('\tError: Failed to parse certificate.')
 
 
 @piv.command()
@@ -842,7 +846,7 @@
 
     def do_read_object(retry=True):
         try:
-            click.echo(controller.get_data(object_id))
+            click.echo(controller.get_data(object_id), nl=False)
         except APDUError as e:
             if e.sw == SW.NOT_FOUND:
                 ctx.fail('No data found.')
@@ -949,7 +953,7 @@
         return True
     except WrongPin as e:
         ctx.fail('PIN verification failed, {} tries 
left.'.format(e.tries_left))
-    except AuthenticationBlocked as e:
+    except AuthenticationBlocked:
         ctx.fail('PIN is blocked.')
     except Exception:
         ctx.fail('PIN verification failed.')
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yubikey-manager-3.1.0/ykman/cli/util.py 
new/yubikey-manager-3.1.1/ykman/cli/util.py
--- old/yubikey-manager-3.1.0/ykman/cli/util.py 2019-08-20 09:54:22.000000000 
+0200
+++ new/yubikey-manager-3.1.1/ykman/cli/util.py 2020-01-29 08:40:16.000000000 
+0100
@@ -68,7 +68,7 @@
 
     def convert(self, value, param, ctx):
         name = super(EnumChoice, self).convert(
-            value.replace('-', '_'), param, ctx)
+            value, param, ctx).replace('-', '_')
         return self.choices_enum[name]
 
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yubikey-manager-3.1.0/ykman/descriptor.py 
new/yubikey-manager-3.1.1/ykman/descriptor.py
--- old/yubikey-manager-3.1.0/ykman/descriptor.py       2019-08-20 
09:54:22.000000000 +0200
+++ new/yubikey-manager-3.1.1/ykman/descriptor.py       2020-01-29 
08:40:16.000000000 +0100
@@ -47,7 +47,9 @@
 
 class Descriptor(object):
 
-    def __init__(self, key_type, mode, version, fingerprint, serial=None, 
backend=None):
+    def __init__(
+            self, key_type, mode, version, fingerprint,
+            serial=None, backend=None):
         self._logger = logger.getChild('Descriptor')
         self._version = version
         self._key_type = key_type
@@ -117,9 +119,15 @@
     def from_usb(cls, usb_dev, backend):
         v_int = usb_dev.bcdDevice
         version = ((v_int >> 8) % 16, (v_int >> 4) % 16, v_int % 16)
-        pid = PID(usb_dev.idProduct)
+        try:
+            pid = PID(usb_dev.idProduct)
+        except ValueError:
+            logger.debug('Ignoring unknown PID: 
{:x}'.format(usb_dev.idProduct))
+            return None
+
         fp = (pid, version, usb_dev.bus, usb_dev.address, 
usb_dev.iSerialNumber)
-        return cls(pid.get_type(), Mode.from_pid(pid), version, fp, 
backend=backend)
+        return cls(
+            pid.get_type(), Mode.from_pid(pid), version, fp, backend=backend)
 
     @classmethod
     def from_driver(cls, driver):
@@ -131,13 +139,12 @@
     found = []  # Composite devices are listed multiple times on Windows...
     backend = get_usb_backend()
     for dev in usb.core.find(True, idVendor=0x1050, backend=backend):
-        try:
-            addr = (dev.bus, dev.address)
-            if addr not in found:
-                found.append(addr)
-                yield Descriptor.from_usb(dev, backend)
-        except ValueError as e:
-            logger.debug('Invalid PID', exc_info=e)
+        addr = (dev.bus, dev.address)
+        if addr not in found:
+            found.append(addr)
+            desc = Descriptor.from_usb(dev, backend)
+            if desc:
+                yield desc
 
 
 def get_descriptors():
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yubikey-manager-3.1.0/ykman/device.py 
new/yubikey-manager-3.1.1/ykman/device.py
--- old/yubikey-manager-3.1.0/ykman/device.py   2019-08-20 09:54:22.000000000 
+0200
+++ new/yubikey-manager-3.1.1/ykman/device.py   2020-01-29 08:40:16.000000000 
+0100
@@ -264,14 +264,11 @@
             config._set(TAG.USB_ENABLED, usb_enabled)
 
         # Workaround for invalid configurations.
-        # Assume all form factors except USB_A_KEYCHAIN
-        # does not support NFC.
-        if config.form_factor in (
-                FORM_FACTOR.USB_A_NANO,
-                FORM_FACTOR.USB_C_KEYCHAIN,
-                FORM_FACTOR.USB_C_NANO,
-                FORM_FACTOR.USB_C_LIGHTNING
-                ):
+        # Assume all form factors except USB_A_KEYCHAIN and
+        # USB_C_KEYCHAIN >= 5.2.4 does not support NFC.
+        if not ((config.form_factor is FORM_FACTOR.USB_A_KEYCHAIN)
+                or (config.form_factor is FORM_FACTOR.USB_C_KEYCHAIN
+                    and config.version >= (5, 2, 4))):
             config._set(TAG.NFC_SUPPORTED, 0)
             config._set(TAG.NFC_ENABLED, 0)
 
@@ -300,6 +297,8 @@
                     self.device_name += ' Nano'
                 elif config.form_factor == FORM_FACTOR.USB_C_KEYCHAIN:
                     self.device_name += 'C'
+                    if config.nfc_supported:
+                        self.device_name += ' NFC'
                 elif config.form_factor == FORM_FACTOR.USB_C_NANO:
                     self.device_name += 'C Nano'
                 elif config.form_factor == FORM_FACTOR.USB_C_LIGHTNING:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yubikey-manager-3.1.0/ykman/native/libloader.py 
new/yubikey-manager-3.1.1/ykman/native/libloader.py
--- old/yubikey-manager-3.1.0/ykman/native/libloader.py 2019-08-20 
09:54:22.000000000 +0200
+++ new/yubikey-manager-3.1.1/ykman/native/libloader.py 2020-01-29 
08:40:16.000000000 +0100
@@ -85,7 +85,6 @@
         if os.path.isabs(libname):
             yield libname
         else:
-            # FIXME / TODO return '.' and os.path.dirname(__file__)
             for path in self.getplatformpaths(libname, extra_paths):
                 yield path
 
@@ -272,7 +271,6 @@
         try:
             if dir:
                 os.chdir(dir)
-                path = os.path.basename(path)
             self.cdll = ctypes.cdll.LoadLibrary(path)
             self.windll = ctypes.windll.LoadLibrary(path)
         finally:
@@ -290,10 +288,12 @@
 
 
 class WindowsLibraryLoader(LibraryLoader):
-    name_formats = ['%s.dll', 'lib%s*.dll', '%slib.dll']
+    name_formats = ['lib%s*.dll']
 
     def load_library(self, libname, version=None, extra_paths=[]):
+        tmp = os.environ['PATH']
         try:
+            os.environ['PATH'] = ''
             result = LibraryLoader.load_library(self, libname, version,
                                                 extra_paths)
         except ImportError:
@@ -316,6 +316,8 @@
                     result = None
             if result is None:
                 raise ImportError('%s not found.' % libname)
+        finally:
+            os.environ['PATH'] = tmp
         return result
 
     def load(self, path):
@@ -324,7 +326,7 @@
     def getplatformpaths(self, libname, extra_paths):
         if os.path.sep not in libname:
             for name in self.name_formats:
-                for dir in extra_paths + ['.']:  # Include cwd
+                for dir in extra_paths:
                     pattern = os.path.abspath(os.path.join(dir, name % 
libname))
                     for path in glob.glob(pattern):
                         yield path
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yubikey-manager-3.1.0/ykman/native/pyusb.py 
new/yubikey-manager-3.1.1/ykman/native/pyusb.py
--- old/yubikey-manager-3.1.0/ykman/native/pyusb.py     2019-08-20 
09:54:22.000000000 +0200
+++ new/yubikey-manager-3.1.1/ykman/native/pyusb.py     2020-01-29 
08:40:16.000000000 +0100
@@ -31,24 +31,10 @@
 import ctypes.util
 import os
 import sys
-import usb.core
 import usb.backend.libusb1 as libusb1
-import usb.backend.libusb0 as libusb0
-import usb.backend.openusb as openusb
 
 
 def _find_library_local(libname):
-    # Look in working directory
-    if os.path.isfile(libname):
-        return libname
-    elif sys.platform == 'win32' and os.path.isfile(libname + '.dll'):
-        return libname + '.dll'
-    # Look next to executable
-    libpath = os.path.join(os.path.dirname(sys.executable), libname)
-    if os.path.isfile(libpath):
-        return libpath
-    elif sys.platform == 'win32' and os.path.isfile(libpath + '.dll'):
-        return libpath + '.dll'
     # For .app bundles
     if sys.platform == 'darwin':
         libpath = os.path.join(
@@ -56,18 +42,29 @@
                 sys.executable), '../Frameworks', libname + '.dylib')
         if os.path.isfile(libpath):
             return libpath
+    else:
+        # Look in ykman/native/
+        libpath = os.path.join(os.path.dirname(__file__), libname)
+        if os.path.isfile(libpath):
+            return libpath
+        elif sys.platform == 'win32' and os.path.isfile(libpath + '.dll'):
+            return libpath + '.dll'
 
 
 def _load_usb_backend():
     # First try to find backend locally, if not found try the systems.
-    for lib in (libusb1, openusb, libusb0):
-        backend = lib.get_backend(find_library=_find_library_local)
-        if backend is not None:
-            return backend
-    for lib in (libusb1, openusb, libusb0):
-        backend = lib.get_backend()
+    try:
+        tmp = os.environ['PATH']
+        os.environ['PATH'] = ''
+        backend = libusb1.get_backend(find_library=_find_library_local)
         if backend is not None:
             return backend
+    finally:
+        os.environ['PATH'] = tmp
+
+    backend = libusb1.get_backend()
+    if backend is not None:
+        return backend
 
 
 def get_usb_backend():
@@ -94,9 +91,3 @@
         lib.libusb_get_version.restype = ctypes.POINTER(LibUsb1Version)
         version = lib.libusb_get_version().contents
         return 'libusb {0.major}.{0.minor}.{0.micro}'.format(version)
-    elif isinstance(backend, openusb._OpenUSB):
-        lib = openusb._lib
-        usb.core.find(True)  # OpenUSB seems to hang if not called.
-    elif isinstance(backend, libusb0._LibUSB):
-        lib = libusb0._lib
-    return lib._name
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yubikey-manager-3.1.0/ykman/otp.py 
new/yubikey-manager-3.1.1/ykman/otp.py
--- old/yubikey-manager-3.1.0/ykman/otp.py      2019-08-20 09:54:22.000000000 
+0200
+++ new/yubikey-manager-3.1.1/ykman/otp.py      2020-01-29 08:40:16.000000000 
+0100
@@ -88,9 +88,9 @@
     PUBLIC_ID_UNDEFINED = 'Public ID is required.'
     SECRET_KEY_INVALID_LENGTH = 'Secret key must be 32 character long.'
     SECRET_KEY_NOT_HEX = 'Secret key must consist only of hex characters 
(0-9A-F).'  # noqa: E501
-    SECRET_KEY_UNDEFINED = 'AES key is required.'
+    SECRET_KEY_UNDEFINED = 'Secret key is required.'
     SERIAL_NOT_INT = 'Serial number must be an integer.'
-    SERIAL_TOO_LONG = 'Serial number too long.'
+    SERIAL_TOO_LONG = 'Serial number is too long.'
 
     def message(self):
         return self.value
@@ -104,7 +104,7 @@
         self.status = status
         self.content = content
         self.errors = [
-            e if e in PrepareUploadError else PrepareUploadError[e]
+            e if isinstance(e, PrepareUploadError) else PrepareUploadError[e]
             for e in error_ids]
 
     def messages(self):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yubikey-manager-3.1.0/ykman/piv.py 
new/yubikey-manager-3.1.1/ykman/piv.py
--- old/yubikey-manager-3.1.0/ykman/piv.py      2019-08-20 09:54:22.000000000 
+0200
+++ new/yubikey-manager-3.1.1/ykman/piv.py      2020-01-29 08:40:16.000000000 
+0100
@@ -233,6 +233,13 @@
         self.bad_value = bad_value
 
 
+class InvalidCertificate(Exception):
+    def __init__(self, slot):
+        super(InvalidCertificate, self).__init__(
+            'Failed to parse certificate in slot {:x}'.format(slot))
+        self.slot = slot
+
+
 class KeypairMismatch(Exception):
     def __init__(self, slot, cert):
         super(KeypairMismatch, self).__init__(
@@ -915,8 +922,11 @@
         if TAG.CERT_INFO in data:  # Not available in attestation slot
             if data[TAG.CERT_INFO] != b'\0':
                 raise ValueError('Compressed certificates are not supported!')
-        return x509.load_der_x509_certificate(data[TAG.CERTIFICATE],
-                                              default_backend())
+        try:
+            return x509.load_der_x509_certificate(data[TAG.CERTIFICATE],
+                                                  default_backend())
+        except Exception:
+            raise InvalidCertificate(slot)
 
     def delete_certificate(self, slot):
         self.put_data(OBJ.from_slot(slot), b'')
@@ -959,6 +969,9 @@
                 certs[slot] = self.read_certificate(slot)
             except APDUError:
                 pass
+            except InvalidCertificate:
+                certs[slot] = None
+
         return certs
 
     def update_chuid(self):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/yubikey-manager-3.1.0/yubikey_manager.egg-info/PKG-INFO 
new/yubikey-manager-3.1.1/yubikey_manager.egg-info/PKG-INFO
--- old/yubikey-manager-3.1.0/yubikey_manager.egg-info/PKG-INFO 2019-08-20 
09:59:20.000000000 +0200
+++ new/yubikey-manager-3.1.1/yubikey_manager.egg-info/PKG-INFO 2020-01-29 
08:40:47.000000000 +0100
@@ -1,12 +1,13 @@
-Metadata-Version: 1.1
+Metadata-Version: 1.2
 Name: yubikey-manager
-Version: 3.1.0
+Version: 3.1.1
 Summary: Tool for managing your YubiKey configuration.
 Home-page: https://github.com/Yubico/yubikey-manager
-Author: Yubico Open Source Maintainers
-Author-email: [email protected]
+Author: Dain Nilsson
+Author-email: [email protected]
+Maintainer: Yubico Open Source Maintainers
+Maintainer-email: [email protected]
 License: BSD 2 clause
-Description-Content-Type: UNKNOWN
 Description: UNKNOWN
 Platform: UNKNOWN
 Classifier: License :: OSI Approved :: BSD License
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/yubikey-manager-3.1.0/yubikey_manager.egg-info/SOURCES.txt 
new/yubikey-manager-3.1.1/yubikey_manager.egg-info/SOURCES.txt
--- old/yubikey-manager-3.1.0/yubikey_manager.egg-info/SOURCES.txt      
2019-08-20 09:59:20.000000000 +0200
+++ new/yubikey-manager-3.1.1/yubikey_manager.egg-info/SOURCES.txt      
2020-01-29 08:40:47.000000000 +0100
@@ -40,6 +40,7 @@
 test/on_yubikey/cli_piv/test_management_key.py
 test/on_yubikey/cli_piv/test_misc.py
 test/on_yubikey/cli_piv/test_pin_puk.py
+test/on_yubikey/cli_piv/test_read_write_object.py
 test/on_yubikey/cli_piv/util.py
 test/on_yubikey/framework/__init__.py
 test/on_yubikey/framework/yubikey_conditions.py


Reply via email to