Your message dated Thu, 21 Mar 2019 18:37:00 +0000
with message-id <275c126b-6306-c179-5fa9-323dd5d4d...@thykier.net>
and subject line Re: Bug#925213: unblock: yubikey-manager/2.1.0-1
has caused the Debian Bug report #925213,
regarding unblock: yubikey-manager/2.1.0-1
to be marked as done.

This means that you claim that the problem has been dealt with.
If this is not the case it is now your responsibility to reopen the
Bug report if necessary, and/or fix the problem forthwith.

(NB: If you are a system administrator and have no idea what this
message is talking about, this may indicate a serious mail system
misconfiguration somewhere. Please contact ow...@bugs.debian.org
immediately.)


-- 
925213: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=925213
Debian Bug Tracking System
Contact ow...@bugs.debian.org with problems
--- Begin Message ---
Package: release.debian.org
Severity: normal
User: release.debian....@packages.debian.org
Usertags: unblock
Control: block 925212 by -1

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA512

Please unblock package yubikey-manager

The new upstream release fixes support of non-QWERTY keyboards
in the OTP “static password” functionality (see #925212).

The debdiff is attached.

unblock yubikey-manager/2.1.0-1

- -- System Information:
Debian Release: buster/sid
  APT prefers testing
  APT policy: (990, 'testing'), (500, 'unstable'), (1, 'experimental')
Architecture: amd64 (x86_64)

Kernel: Linux 4.19.0-2-amd64 (SMP w/4 CPU cores)
Kernel taint flags: TAINT_PROPRIETARY_MODULE, TAINT_OOT_MODULE, 
TAINT_UNSIGNED_MODULE
Locale: LANG=en_US.UTF-8, LC_CTYPE=en_US.UTF-8 (charmap=UTF-8) (ignored: LC_ALL 
set to en_US.UTF-8), LANGUAGE=en_US.UTF-8 (charmap=UTF-8) (ignored: LC_ALL set 
to en_US.UTF-8)
Shell: /bin/sh linked to /bin/dash
Init: systemd (via /run/systemd/system)
LSM: AppArmor: enabled

-----BEGIN PGP SIGNATURE-----

iQJFBAEBCgAvFiEEU7EqA8ZVHYoLJhPE5vmO4pLV7MsFAlyTeIkRHG5pY29vQGRl
Ymlhbi5vcmcACgkQ5vmO4pLV7MvWiQ/+JW/SVSrGmK9YtGmhrdb6mRniig48JWVe
elgPJaZPxjTTgv+5yGCxqPilO7tUcyVQjTz4ystBBGGPJ/L6hIJEEAdgpSsEayQs
smRmeBXuQt/Seb5bPMaieI+zVcLLDoz8dia9BOhE5UB+4kfgliTSa30KOM00CbEF
Pu7lM/+yH5RhyOMcIxQKB/092is9ytJhhGNJGydxIUswjMPFdGI0L67kzsmoza9t
SlPeg/jvEuwa6k+glTUGE/PvhW7fikr6Ek08ISMkcTRSmS0ZS7GoWd3UT3JH1H1U
Iwepxrc44DlJCR/xjp6yKdJ5UWvEcY5rUb7Bl8ahHrr/QJ0hZvjtrfHECbA1m123
mDhA/ZPPDDuVK15chQjBZLWn8QvPUjoxYABC5QIBvG/oxglIw6l4Bp5fEOJYgTnn
VeTq6cNWb/XTdXrOyKbg8/BGic7e+8MxV1Ily6H17lwNUkCK5aKspMal5XNXKdMj
FlG3ZRLdR99P2F7Ic3oYdUDPv0K9KIKP3Rx4Fbe3/jzv/7efuRhC5chNUhNJSR/I
2Jsk7IXpdnp9tigOeQd7Wn1EAYMqUxRgujcXMXyKW1zOL9LBwy2+jHxl5YMdsue5
p26QUAzW6mAA4hWZ4uPs8SDj2MxXyimRUauFBNz+BMpiLe3mC6qiqAbojW9P49t/
tPPjRJ5+DrY=
=N3Pa
-----END PGP SIGNATURE-----
diff -Nru yubikey-manager-2.0.0/debian/changelog 
yubikey-manager-2.1.0/debian/changelog
--- yubikey-manager-2.0.0/debian/changelog      2019-03-09 16:41:28.000000000 
+0100
+++ yubikey-manager-2.1.0/debian/changelog      2019-03-21 12:30:40.000000000 
+0100
@@ -1,3 +1,16 @@
+yubikey-manager (2.1.0-1) unstable; urgency=medium
+
+  * New upstream release (2019-03-11)
+    + PIV: Verify that the PIN must be between 6 - 8 characters long
+    + PIV: Malformed certificates are now handled better
+    + OpenPGP: The openpgp touch command now shows current touch policies
+    + Bugfix: Fix support for german (DE) keyboard layout for static passwords
+      Closes: #925212
+
+  * debian/control: Add Afif Elghraoui as uploader
+
+ -- Nicolas Braud-Santoni <ni...@debian.org>  Thu, 21 Mar 2019 12:30:40 +0100
+
 yubikey-manager (2.0.0-2) unstable; urgency=low
 
   [ Nicolas Braud-Santoni ]
diff -Nru yubikey-manager-2.0.0/debian/control 
yubikey-manager-2.1.0/debian/control
--- yubikey-manager-2.0.0/debian/control        2019-03-09 16:41:28.000000000 
+0100
+++ yubikey-manager-2.1.0/debian/control        2019-03-21 12:30:40.000000000 
+0100
@@ -1,6 +1,7 @@
 Source: yubikey-manager
 Maintainer: Debian Authentication Maintainers 
<pkg-auth-maintain...@lists.alioth.debian.org>
-Uploaders: Nicolas Braud-Santoni <ni...@debian.org>
+Uploaders: Afif Elghraoui <a...@debian.org>,
+           Nicolas Braud-Santoni <ni...@debian.org>
 Section: utils
 Priority: optional
 Rules-Requires-Root: no
diff -Nru 
yubikey-manager-2.0.0/debian/patches/0001-Fix-upstream-changelog.patch 
yubikey-manager-2.1.0/debian/patches/0001-Fix-upstream-changelog.patch
--- yubikey-manager-2.0.0/debian/patches/0001-Fix-upstream-changelog.patch      
2019-03-09 16:41:28.000000000 +0100
+++ yubikey-manager-2.1.0/debian/patches/0001-Fix-upstream-changelog.patch      
2019-03-21 12:30:40.000000000 +0100
@@ -1,18 +1,22 @@
-From: Nicolas Braud-Santoni <nico...@braud-santoni.eu>
-Date: Thu, 7 Feb 2019 21:43:47 +0100
 Subject: Fix upstream changelog
 
 ---
- NEWS | 3 +--
- 1 file changed, 1 insertion(+), 2 deletions(-)
+ NEWS | 1 -
+ 1 file changed, 1 deletion(-)
 
 diff --git a/NEWS b/NEWS
-index 5c1b9c3..68d1d77 100644
+index 6defabb..09f0ffb 100644
+Origin: vendor
+Forwarded: no
+Applied-Upstream: not-needed
+From: Nicolas Braud-Santoni <ni...@debian.org>
+Reviewed-by: Nicolas Braud-Santoni <ni...@debian.org>
+Last-Update: 2019-03-21
+
 --- a/NEWS
 +++ b/NEWS
-@@ -1,7 +1,6 @@
--* Version 2.0.0 (unreleased)
-+* Version 2.0.0 (released 2019-01-09)
+@@ -14,7 +14,6 @@
+ * Version 2.0.0 (released 2019-01-09)
   ** Add support for Security Key NFC
   ** Add experimental support for external smart card reader. See --reader flag
 - ** Add a minimal manpage
diff -Nru yubikey-manager-2.0.0/doc/development.adoc 
yubikey-manager-2.1.0/doc/development.adoc
--- yubikey-manager-2.0.0/doc/development.adoc  2018-11-08 12:33:42.000000000 
+0100
+++ yubikey-manager-2.1.0/doc/development.adoc  2019-03-11 12:11:41.000000000 
+0100
@@ -64,3 +64,7 @@
 To run integration tests, indicate the serial number (given by `ykman list`) 
of the YubiKey to test with:
 
    $ DESTRUCTIVE_TEST_YUBIKEY_SERIAL=123456 python setup.py test
+
+=== Packaging
+
+For third-party packaging, use the source releases and signatures available 
https://developers.yubico.com/yubikey-manager/Releases/[here].
diff -Nru yubikey-manager-2.0.0/man/ykman.1 yubikey-manager-2.1.0/man/ykman.1
--- yubikey-manager-2.0.0/man/ykman.1   1970-01-01 01:00:00.000000000 +0100
+++ yubikey-manager-2.1.0/man/ykman.1   2019-03-11 12:11:41.000000000 +0100
@@ -0,0 +1,66 @@
+.TH YKMAN "1" "March 2019" "ykman 2.1.0" "User Commands"
+.SH NAME
+ykman \- YubiKey Manager (ykman)
+.SH SYNOPSIS
+.B ykman
+[\fI\,OPTIONS\/\fR] \fI\,COMMAND \/\fR[\fI\,ARGS\/\fR]...
+.SH DESCRIPTION
+.PP
+Configure your YubiKey via the command line.
+.SH OPTIONS
+.HP
+\fB\-v\fR, \fB\-\-version\fR
+.HP
+\fB\-d\fR, \fB\-\-device\fR SERIAL
+.TP
+\fB\-l\fR, \fB\-\-log\-level\fR [DEBUG|INFO|WARNING|ERROR|CRITICAL]
+Enable logging at given verbosity level.
+.TP
+\fB\-\-log\-file\fR FILE
+Write logs to the given FILE instead of
+standard error; ignored unless \fB\-\-log\-level\fR
+is also set.
+.TP
+\fB\-r\fR, \fB\-\-reader\fR NAME
+Use an external smart card reader. Conflicts
+with \fB\-\-device\fR and list.
+.TP
+\fB\-h\fR, \fB\-\-help\fR
+Show this message and exit.
+.SS "Commands:"
+.TP
+config
+Enable/Disable applications.
+.TP
+fido
+Manage FIDO applications.
+.TP
+info
+Show general information.
+.TP
+list
+List connected YubiKeys.
+.TP
+mode
+Manage connection modes (USB Interfaces).
+.TP
+oath
+Manage OATH Application.
+.TP
+openpgp
+Manage OpenPGP Application.
+.TP
+otp
+Manage OTP Application.
+.TP
+piv
+Manage PIV Application.
+.SH EXAMPLES
+.PP
+List connected YubiKeys, only output serial number:
+.PP
+$ ykman list --serials
+.PP
+Show information about YubiKey with serial number 0123456:
+.PP
+$ ykman --device 0123456 info
diff -Nru yubikey-manager-2.0.0/MANIFEST.in yubikey-manager-2.1.0/MANIFEST.in
--- yubikey-manager-2.0.0/MANIFEST.in   2019-01-07 11:25:27.000000000 +0100
+++ yubikey-manager-2.1.0/MANIFEST.in   2019-03-11 12:11:41.000000000 +0100
@@ -5,4 +5,6 @@
 include doc/*.adoc
 recursive-include test *
 include README.adoc
+include man/*
 include ykman/VERSION
+recursive-exclude *.pyc
diff -Nru yubikey-manager-2.0.0/NEWS yubikey-manager-2.1.0/NEWS
--- yubikey-manager-2.0.0/NEWS  2019-01-08 08:53:33.000000000 +0100
+++ yubikey-manager-2.1.0/NEWS  2019-03-11 12:11:41.000000000 +0100
@@ -1,4 +1,17 @@
-* Version 2.0.0 (unreleased)
+* Version 2.1.0 (released 2019-03-11)
+ ** Add --reader flag to ykman list, to list available smart card readers
+ ** FIPS: Checking if a YubiKey FIPS is in FIPS mode is now opt-in, with the 
--check-fips flag
+ ** PIV: Add commands for writing and reading arbitrary PIV objects
+ ** PIV: Verify that the PIN must be between 6 - 8 characters long
+ ** PIV: In import-certificate, make the verification that the certificate and 
private key matches opt-in, with the --verify flag
+ ** PIV: The piv info command now shows the serial number of the certificates
+ ** PIV: The piv info command now shows the full Distinguished Name (DN) of 
the certificate subject and issuer, if possible
+ ** PIV: Malformed certificates are now handled better
+ ** OpenPGP: The openpgp touch command now shows current touch policies
+ ** The ykman usb/nfc config command now accepts openpgp as well as opgp as an 
argument
+ ** Bugfix: Fix support for german (DE) keyboard layout for static passwords
+
+* Version 2.0.0 (released 2019-01-09)
  ** Add support for Security Key NFC
  ** Add experimental support for external smart card reader. See --reader flag
  ** Add a minimal manpage
diff -Nru yubikey-manager-2.0.0/PKG-INFO yubikey-manager-2.1.0/PKG-INFO
--- yubikey-manager-2.0.0/PKG-INFO      2019-01-08 09:00:36.000000000 +0100
+++ yubikey-manager-2.1.0/PKG-INFO      2019-03-11 12:16:19.000000000 +0100
@@ -1,13 +1,12 @@
-Metadata-Version: 1.2
+Metadata-Version: 1.1
 Name: yubikey-manager
-Version: 2.0.0
+Version: 2.1.0
 Summary: Tool for managing your YubiKey configuration.
 Home-page: https://github.com/Yubico/yubikey-manager
-Author: Dain Nilsson
-Author-email: d...@yubico.com
-Maintainer: Yubico Open Source Maintainers
-Maintainer-email: ossma...@yubico.com
+Author: Yubico Open Source Maintainers
+Author-email: ossma...@yubico.com
 License: BSD 2 clause
+Description-Content-Type: UNKNOWN
 Description: UNKNOWN
 Platform: UNKNOWN
 Classifier: License :: OSI Approved :: BSD License
diff -Nru yubikey-manager-2.0.0/README.adoc yubikey-manager-2.1.0/README.adoc
--- yubikey-manager-2.0.0/README.adoc   2018-11-08 12:33:42.000000000 +0100
+++ yubikey-manager-2.1.0/README.adoc   2019-03-11 12:11:41.000000000 +0100
@@ -6,17 +6,27 @@
 
 === Usage
 For more usage information and examples, see the 
https://support.yubico.com/support/solutions/articles/15000012643-yubikey-manager-cli-ykman-user-guide[YubiKey
 Manager CLI User Manual].
+
 ....
 Usage: ykman [OPTIONS] COMMAND [ARGS]...
 
   Configure your YubiKey via the command line.
 
+  Examples:
+
+    List connected YubiKeys, only output serial number:
+    $ ykman list --serials
+
+    Show information about YubiKey with serial number 0123456:
+    $ ykman --device 0123456 info
+
 Options:
   -v, --version
   -d, --device SERIAL
   -l, --log-level [DEBUG|INFO|WARNING|ERROR|CRITICAL]
                                   Enable logging at given verbosity level.
   --log-file FILE                 Write logs to the given FILE instead of 
standard error; ignored unless --log-level is also set.
+  -r, --reader NAME               Use an external smart card reader. Conflicts 
with --device and list.
   -h, --help                      Show this message and exit.
 
 Commands:
Binary files 
/tmp/or4OSNFsIk/yubikey-manager-2.0.0/test/on_yubikey/cli_piv/__pycache__/__init__.cpython-36.pyc
 and 
/tmp/AYxoHw5Ptz/yubikey-manager-2.1.0/test/on_yubikey/cli_piv/__pycache__/__init__.cpython-36.pyc
 differ
Binary files 
/tmp/or4OSNFsIk/yubikey-manager-2.0.0/test/on_yubikey/cli_piv/__pycache__/test_fips.cpython-36.pyc
 and 
/tmp/AYxoHw5Ptz/yubikey-manager-2.1.0/test/on_yubikey/cli_piv/__pycache__/test_fips.cpython-36.pyc
 differ
Binary files 
/tmp/or4OSNFsIk/yubikey-manager-2.0.0/test/on_yubikey/cli_piv/__pycache__/test_generate_cert_and_csr.cpython-36.pyc
 and 
/tmp/AYxoHw5Ptz/yubikey-manager-2.1.0/test/on_yubikey/cli_piv/__pycache__/test_generate_cert_and_csr.cpython-36.pyc
 differ
Binary files 
/tmp/or4OSNFsIk/yubikey-manager-2.0.0/test/on_yubikey/cli_piv/__pycache__/test_key_management.cpython-36.pyc
 and 
/tmp/AYxoHw5Ptz/yubikey-manager-2.1.0/test/on_yubikey/cli_piv/__pycache__/test_key_management.cpython-36.pyc
 differ
Binary files 
/tmp/or4OSNFsIk/yubikey-manager-2.0.0/test/on_yubikey/cli_piv/__pycache__/test_management_key.cpython-36.pyc
 and 
/tmp/AYxoHw5Ptz/yubikey-manager-2.1.0/test/on_yubikey/cli_piv/__pycache__/test_management_key.cpython-36.pyc
 differ
Binary files 
/tmp/or4OSNFsIk/yubikey-manager-2.0.0/test/on_yubikey/cli_piv/__pycache__/test_misc.cpython-36.pyc
 and 
/tmp/AYxoHw5Ptz/yubikey-manager-2.1.0/test/on_yubikey/cli_piv/__pycache__/test_misc.cpython-36.pyc
 differ
Binary files 
/tmp/or4OSNFsIk/yubikey-manager-2.0.0/test/on_yubikey/cli_piv/__pycache__/test_pin_puk.cpython-36.pyc
 and 
/tmp/AYxoHw5Ptz/yubikey-manager-2.1.0/test/on_yubikey/cli_piv/__pycache__/test_pin_puk.cpython-36.pyc
 differ
Binary files 
/tmp/or4OSNFsIk/yubikey-manager-2.0.0/test/on_yubikey/cli_piv/__pycache__/util.cpython-36.pyc
 and 
/tmp/AYxoHw5Ptz/yubikey-manager-2.1.0/test/on_yubikey/cli_piv/__pycache__/util.cpython-36.pyc
 differ
diff -Nru yubikey-manager-2.0.0/test/on_yubikey/cli_piv/test_key_management.py 
yubikey-manager-2.1.0/test/on_yubikey/cli_piv/test_key_management.py
--- yubikey-manager-2.0.0/test/on_yubikey/cli_piv/test_key_management.py        
2018-12-20 14:58:43.000000000 +0100
+++ yubikey-manager-2.1.0/test/on_yubikey/cli_piv/test_key_management.py        
2019-03-11 12:11:41.000000000 +0100
@@ -182,7 +182,7 @@
 
         ykman_cli(
             'piv', 'import-certificate', '9a', '-',
-            '-m', DEFAULT_MANAGEMENT_KEY, '-P', DEFAULT_PIN, '--no-verify',
+            '-m', DEFAULT_MANAGEMENT_KEY, '-P', DEFAULT_PIN,
             input=cert_pem)
 
     @unittest.skipIf(*no_attestation)
diff -Nru yubikey-manager-2.0.0/test/on_yubikey/cli_piv/test_misc.py 
yubikey-manager-2.1.0/test/on_yubikey/cli_piv/test_misc.py
--- yubikey-manager-2.0.0/test/on_yubikey/cli_piv/test_misc.py  2018-11-08 
12:33:42.000000000 +0100
+++ yubikey-manager-2.1.0/test/on_yubikey/cli_piv/test_misc.py  2019-03-11 
12:11:41.000000000 +0100
@@ -1,6 +1,5 @@
 from ..util import ykman_cli
-from .util import PivTestCase
-
+from .util import PivTestCase, DEFAULT_MANAGEMENT_KEY
 
 class Misc(PivTestCase):
 
@@ -11,3 +10,11 @@
     def test_reset(self):
         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)
Binary files 
/tmp/or4OSNFsIk/yubikey-manager-2.0.0/test/on_yubikey/__pycache__/__init__.cpython-36.pyc
 and 
/tmp/AYxoHw5Ptz/yubikey-manager-2.1.0/test/on_yubikey/__pycache__/__init__.cpython-36.pyc
 differ
Binary files 
/tmp/or4OSNFsIk/yubikey-manager-2.0.0/test/on_yubikey/__pycache__/test_cli_config.cpython-36.pyc
 and 
/tmp/AYxoHw5Ptz/yubikey-manager-2.1.0/test/on_yubikey/__pycache__/test_cli_config.cpython-36.pyc
 differ
Binary files 
/tmp/or4OSNFsIk/yubikey-manager-2.0.0/test/on_yubikey/__pycache__/test_cli_misc.cpython-36.pyc
 and 
/tmp/AYxoHw5Ptz/yubikey-manager-2.1.0/test/on_yubikey/__pycache__/test_cli_misc.cpython-36.pyc
 differ
Binary files 
/tmp/or4OSNFsIk/yubikey-manager-2.0.0/test/on_yubikey/__pycache__/test_cli_oath.cpython-36.pyc
 and 
/tmp/AYxoHw5Ptz/yubikey-manager-2.1.0/test/on_yubikey/__pycache__/test_cli_oath.cpython-36.pyc
 differ
Binary files 
/tmp/or4OSNFsIk/yubikey-manager-2.0.0/test/on_yubikey/__pycache__/test_cli_openpgp.cpython-36.pyc
 and 
/tmp/AYxoHw5Ptz/yubikey-manager-2.1.0/test/on_yubikey/__pycache__/test_cli_openpgp.cpython-36.pyc
 differ
Binary files 
/tmp/or4OSNFsIk/yubikey-manager-2.0.0/test/on_yubikey/__pycache__/test_cli_otp.cpython-36.pyc
 and 
/tmp/AYxoHw5Ptz/yubikey-manager-2.1.0/test/on_yubikey/__pycache__/test_cli_otp.cpython-36.pyc
 differ
Binary files 
/tmp/or4OSNFsIk/yubikey-manager-2.0.0/test/on_yubikey/__pycache__/test_fips_u2f_commands.cpython-36.pyc
 and 
/tmp/AYxoHw5Ptz/yubikey-manager-2.1.0/test/on_yubikey/__pycache__/test_fips_u2f_commands.cpython-36.pyc
 differ
Binary files 
/tmp/or4OSNFsIk/yubikey-manager-2.0.0/test/on_yubikey/__pycache__/test_interfaces.cpython-36.pyc
 and 
/tmp/AYxoHw5Ptz/yubikey-manager-2.1.0/test/on_yubikey/__pycache__/test_interfaces.cpython-36.pyc
 differ
Binary files 
/tmp/or4OSNFsIk/yubikey-manager-2.0.0/test/on_yubikey/__pycache__/test_piv.cpython-36.pyc
 and 
/tmp/AYxoHw5Ptz/yubikey-manager-2.1.0/test/on_yubikey/__pycache__/test_piv.cpython-36.pyc
 differ
Binary files 
/tmp/or4OSNFsIk/yubikey-manager-2.0.0/test/on_yubikey/__pycache__/util.cpython-36.pyc
 and 
/tmp/AYxoHw5Ptz/yubikey-manager-2.1.0/test/on_yubikey/__pycache__/util.cpython-36.pyc
 differ
diff -Nru yubikey-manager-2.0.0/test/on_yubikey/test_cli_config.py 
yubikey-manager-2.1.0/test/on_yubikey/test_cli_config.py
--- yubikey-manager-2.0.0/test/on_yubikey/test_cli_config.py    2018-11-08 
12:33:42.000000000 +0100
+++ yubikey-manager-2.1.0/test/on_yubikey/test_cli_config.py    2019-03-11 
12:11:41.000000000 +0100
@@ -30,6 +30,11 @@
         output = ykman_cli('config', 'usb', '--list')
         self.assertNotIn('OpenPGP', output)
 
+    def test_disable_openpgp_alternative_syntax(self):
+        ykman_cli('config', 'usb', '--disable', 'openpgp', '-f')
+        output = ykman_cli('config', 'usb', '--list')
+        self.assertNotIn('OpenPGP', output)
+
     def test_disable_piv(self):
         ykman_cli('config', 'usb', '--disable', 'PIV', '-f')
         output = ykman_cli('config', 'usb', '--list')
diff -Nru yubikey-manager-2.0.0/test/on_yubikey/test_cli_misc.py 
yubikey-manager-2.1.0/test/on_yubikey/test_cli_misc.py
--- yubikey-manager-2.0.0/test/on_yubikey/test_cli_misc.py      2018-11-08 
12:33:42.000000000 +0100
+++ yubikey-manager-2.1.0/test/on_yubikey/test_cli_misc.py      2019-03-11 
12:11:41.000000000 +0100
@@ -13,12 +13,12 @@
 
     @unittest.skipIf(is_fips(), 'Not applicable to YubiKey FIPS.')
     def test_ykman_info_does_not_report_fips_for_non_fips_device(self):
-        info = ykman_cli('info')
+        info = ykman_cli('info --check-fips')
         self.assertNotIn('FIPS', info)
 
     @unittest.skipIf(not is_fips(), 'YubiKey FIPS required.')
     def test_ykman_info_reports_fips_status(self):
-        info = ykman_cli('info')
+        info = ykman_cli('info', '--check-fips')
         self.assertIn('FIPS Approved Mode:', info)
         self.assertIn('  FIDO U2F:', info)
         self.assertIn('  OATH:', info)
Binary files 
/tmp/or4OSNFsIk/yubikey-manager-2.0.0/test/__pycache__/__init__.cpython-36.pyc 
and 
/tmp/AYxoHw5Ptz/yubikey-manager-2.1.0/test/__pycache__/__init__.cpython-36.pyc 
differ
Binary files 
/tmp/or4OSNFsIk/yubikey-manager-2.0.0/test/__pycache__/test_device.cpython-36.pyc
 and 
/tmp/AYxoHw5Ptz/yubikey-manager-2.1.0/test/__pycache__/test_device.cpython-36.pyc
 differ
Binary files 
/tmp/or4OSNFsIk/yubikey-manager-2.0.0/test/__pycache__/test_external_libs.cpython-36.pyc
 and 
/tmp/AYxoHw5Ptz/yubikey-manager-2.1.0/test/__pycache__/test_external_libs.cpython-36.pyc
 differ
Binary files 
/tmp/or4OSNFsIk/yubikey-manager-2.0.0/test/__pycache__/test_oath.cpython-36.pyc 
and 
/tmp/AYxoHw5Ptz/yubikey-manager-2.1.0/test/__pycache__/test_oath.cpython-36.pyc 
differ
Binary files 
/tmp/or4OSNFsIk/yubikey-manager-2.0.0/test/__pycache__/test_piv.cpython-36.pyc 
and 
/tmp/AYxoHw5Ptz/yubikey-manager-2.1.0/test/__pycache__/test_piv.cpython-36.pyc 
differ
Binary files 
/tmp/or4OSNFsIk/yubikey-manager-2.0.0/test/__pycache__/test_scancodes.cpython-36.pyc
 and 
/tmp/AYxoHw5Ptz/yubikey-manager-2.1.0/test/__pycache__/test_scancodes.cpython-36.pyc
 differ
Binary files 
/tmp/or4OSNFsIk/yubikey-manager-2.0.0/test/__pycache__/test_util.cpython-36.pyc 
and 
/tmp/AYxoHw5Ptz/yubikey-manager-2.1.0/test/__pycache__/test_util.cpython-36.pyc 
differ
Binary files 
/tmp/or4OSNFsIk/yubikey-manager-2.0.0/test/__pycache__/util.cpython-36.pyc and 
/tmp/AYxoHw5Ptz/yubikey-manager-2.1.0/test/__pycache__/util.cpython-36.pyc 
differ
diff -Nru yubikey-manager-2.0.0/test/test_util.py 
yubikey-manager-2.1.0/test/test_util.py
--- yubikey-manager-2.0.0/test/test_util.py     2018-12-20 14:58:43.000000000 
+0100
+++ yubikey-manager-2.1.0/test/test_util.py     2019-03-11 12:11:41.000000000 
+0100
@@ -31,10 +31,9 @@
 
     def test_generate_static_pw(self):
         for l in range(0, 38):
-            self.assertRegex(generate_static_pw(l),
-                             b'^[cbdefghijklnrtuvCBDEFGHIJKLNRTUV]{' +
-                             '{:d}'.format(l).encode('ascii') +
-                             b'}$')
+            self.assertRegex(
+                generate_static_pw(l),
+                '^[cbdefghijklnrtuvCBDEFGHIJKLNRTUV]{' + '{:d}'.format(l) + 
'}$')
 
     def test_hmac_shorten_key(self):
         self.assertEqual(b'short', hmac_shorten_key(b'short', 'sha1'))
diff -Nru yubikey-manager-2.0.0/ykman/cli/config.py 
yubikey-manager-2.1.0/ykman/cli/config.py
--- yubikey-manager-2.0.0/ykman/cli/config.py   2019-01-02 09:11:40.000000000 
+0100
+++ yubikey-manager-2.1.0/ykman/cli/config.py   2019-03-11 12:11:41.000000000 
+0100
@@ -42,6 +42,15 @@
 CLEAR_LOCK_CODE = '0' * 32
 
 
+class ApplicationsChoice(UpperCaseChoice):
+    """
+    Special version of UpperCaseChoice that accepts openpgp as OPGP
+    """
+    def convert(self, value, param, ctx):
+        return 'OPGP' if value.lower() == 'openpgp' \
+            else super().convert(value, param, ctx)
+
+
 def prompt_lock_code(prompt='Enter your lock code'):
     return click.prompt(
         prompt, default='', hide_input=True, show_default=False, err=True)
@@ -174,10 +183,10 @@
 @click.pass_context
 @click_force_option
 @click.option(
-    '-e', '--enable', multiple=True, type=UpperCaseChoice(
+    '-e', '--enable', multiple=True, type=ApplicationsChoice(
         APPLICATION.__members__.keys()), help='Enable applications.')
 @click.option(
-    '-d', '--disable', multiple=True, type=UpperCaseChoice(
+    '-d', '--disable', multiple=True, type=ApplicationsChoice(
         APPLICATION.__members__.keys()), help='Disable applications.')
 @click.option('-l', '--list', is_flag=True, help='List enabled applications.')
 @click.option(
@@ -307,10 +316,10 @@
 @click.pass_context
 @click_force_option
 @click.option(
-    '-e', '--enable', multiple=True, type=UpperCaseChoice(
+    '-e', '--enable', multiple=True, type=ApplicationsChoice(
         APPLICATION.__members__.keys()), help='Enable applications.')
 @click.option(
-    '-d', '--disable', multiple=True, type=UpperCaseChoice(
+    '-d', '--disable', multiple=True, type=ApplicationsChoice(
         APPLICATION.__members__.keys()), help='Disable applications.')
 @click.option(
     '-a', '--enable-all', is_flag=True, help='Enable all applications.')
diff -Nru yubikey-manager-2.0.0/ykman/cli/info.py 
yubikey-manager-2.1.0/ykman/cli/info.py
--- yubikey-manager-2.0.0/ykman/cli/info.py     2018-11-08 12:33:42.000000000 
+0100
+++ yubikey-manager-2.1.0/ykman/cli/info.py     2019-03-11 12:11:41.000000000 
+0100
@@ -121,9 +121,13 @@
     return statuses
 
 
+@click.option(
+    '-c', '--check-fips',
+    help='Check if YubiKey is in FIPS Approved mode.',
+    is_flag=True)
 @click.command()
 @click.pass_context
-def info(ctx):
+def info(ctx, check_fips):
     """
     Show general information.
 
@@ -132,7 +136,7 @@
     """
     dev = ctx.obj['dev']
 
-    if dev.is_fips:
+    if dev.is_fips and check_fips:
         fips_status = get_overall_fips_status(dev.serial, dev.config)
 
     click.echo('Device type: {}'.format(dev.device_name))
@@ -158,7 +162,7 @@
 
     print_app_status_table(config)
 
-    if dev.is_fips:
+    if dev.is_fips and check_fips:
         click.echo()
 
         click.echo('FIPS Approved Mode: {}'.format(
diff -Nru yubikey-manager-2.0.0/ykman/cli/__main__.py 
yubikey-manager-2.1.0/ykman/cli/__main__.py
--- yubikey-manager-2.0.0/ykman/cli/__main__.py 2018-12-11 12:33:30.000000000 
+0100
+++ yubikey-manager-2.1.0/ykman/cli/__main__.py 2019-03-11 12:11:41.000000000 
+0100
@@ -32,7 +32,7 @@
 from ..util import TRANSPORT, Cve201715361VulnerableError, YUBIKEY
 from ..native.pyusb import get_usb_backend_version
 from ..driver_otp import libversion as ykpers_version
-from ..driver_ccid import open_devices as open_ccid
+from ..driver_ccid import open_devices as open_ccid, list_readers
 from ..device import YubiKey
 from ..descriptor import (get_descriptors, list_devices, open_device,
                           FailedOpeningDeviceException, Descriptor)
@@ -194,11 +194,18 @@
 @cli.command('list')
 @click.option('-s', '--serials', is_flag=True, help='Output only serial '
               'numbers, one per line (devices without serial will be 
omitted).')
+@click.option(
+    '-r', '--readers', is_flag=True, help='List available smart card readers.')
 @click.pass_context
-def list_keys(ctx, serials):
+def list_keys(ctx, serials, readers):
     """
     List connected YubiKeys.
     """
+    if readers:
+        for reader in list_readers():
+            click.echo(reader.name)
+        ctx.exit()
+
     all_descriptors = get_descriptors()
     descriptors = [d for d in all_descriptors if d.key_type != YUBIKEY.SKY]
     skys = len(all_descriptors) - len(descriptors)
diff -Nru yubikey-manager-2.0.0/ykman/cli/opgp.py 
yubikey-manager-2.1.0/ykman/cli/opgp.py
--- yubikey-manager-2.0.0/ykman/cli/opgp.py     2019-01-02 09:11:40.000000000 
+0100
+++ yubikey-manager-2.1.0/ykman/cli/opgp.py     2019-03-11 12:11:41.000000000 
+0100
@@ -39,15 +39,15 @@
 
 
 KEY_NAMES = dict(
-    sig=KEY_SLOT.SIGN,
-    enc=KEY_SLOT.ENCRYPT,
-    aut=KEY_SLOT.AUTHENTICATE
+    sig=KEY_SLOT.SIGNATURE,
+    enc=KEY_SLOT.ENCRYPTION,
+    aut=KEY_SLOT.AUTHENTICATION
 )
 
 MODE_NAMES = dict(
     off=TOUCH_MODE.OFF,
     on=TOUCH_MODE.ON,
-    fixed=TOUCH_MODE.ON_FIXED
+    fixed=TOUCH_MODE.FIXED
 )
 
 
@@ -116,6 +116,17 @@
     click.echo('PIN tries remaining: {}'.format(retries.pin))
     click.echo('Reset code tries remaining: {}'.format(retries.reset))
     click.echo('Admin PIN tries remaining: {}'.format(retries.admin))
+    click.echo()
+    click.echo('Touch policies')
+    click.echo(
+        'Signature key           {.name}'.format(
+            controller.get_touch(KEY_SLOT.SIGNATURE)))
+    click.echo(
+        'Encryption key          {.name}'.format(
+            controller.get_touch(KEY_SLOT.ENCRYPTION)))
+    click.echo(
+        'Authentication key      {.name}'.format(
+            controller.get_touch(KEY_SLOT.AUTHENTICATION)))
 
 
 @openpgp.command()
@@ -143,10 +154,10 @@
 
 
 @openpgp.command()
-@click.argument('key', type=click.Choice(sorted(KEY_NAMES)),
+@click.argument('key', metavar='KEY', type=click.Choice(sorted(KEY_NAMES)),
                 callback=lambda c, p, k: KEY_NAMES.get(k))
-@click.argument('policy', type=click.Choice(sorted(MODE_NAMES)),
-                callback=lambda c, p, k: MODE_NAMES.get(k), required=False)
+@click.argument('policy', metavar='POLICY', 
type=click.Choice(sorted(MODE_NAMES)),
+                callback=lambda c, p, k: MODE_NAMES.get(k))
 @click.option('--admin-pin', required=False, metavar='PIN',
               help='Admin PIN for OpenPGP.')
 @click_force_option
@@ -156,17 +167,13 @@
     Manage touch policy for OpenPGP keys.
 
     \b
-    KEY     Key slot to get/set (sig, enc or aut).
+    KEY     Key slot to set (sig, enc or aut).
     POLICY  Touch policy to set (on, off or fixed).
     """
     controller = ctx.obj['controller']
     old_policy = controller.get_touch(key)
-    click.echo('Current touch policy of {.name} key is {.name}.'.format(
-        key, old_policy))
-    if policy is None:
-        return
 
-    if old_policy == TOUCH_MODE.ON_FIXED:
+    if old_policy == TOUCH_MODE.FIXED:
         ctx.fail('A FIXED policy cannot be changed!')
 
     force or click.confirm('Set touch policy of {.name} key to 
{.name}?'.format(
@@ -174,7 +181,6 @@
     if admin_pin is None:
         admin_pin = click.prompt('Enter admin PIN', hide_input=True, err=True)
     controller.set_touch(key, policy, admin_pin.encode('utf8'))
-    click.echo('Touch policy successfully set.')
 
 
 @openpgp.command('set-pin-retries')
diff -Nru yubikey-manager-2.0.0/ykman/cli/otp.py 
yubikey-manager-2.1.0/ykman/cli/otp.py
--- yubikey-manager-2.0.0/ykman/cli/otp.py      2019-01-02 09:11:40.000000000 
+0100
+++ yubikey-manager-2.1.0/ykman/cli/otp.py      2019-03-11 12:11:41.000000000 
+0100
@@ -362,7 +362,7 @@
     if not password and not generate:
         password = click.prompt('Enter a static password', err=True)
     elif not password and generate:
-        password = generate_static_pw(length, keyboard_layout).decode()
+        password = generate_static_pw(length, keyboard_layout)
 
     if not force:
         _confirm_slot_overwrite(controller, slot)
diff -Nru yubikey-manager-2.0.0/ykman/cli/piv.py 
yubikey-manager-2.1.0/ykman/cli/piv.py
--- yubikey-manager-2.0.0/ykman/cli/piv.py      2019-01-02 09:11:40.000000000 
+0100
+++ yubikey-manager-2.1.0/ykman/cli/piv.py      2019-03-11 12:11:41.000000000 
+0100
@@ -37,7 +37,8 @@
     UnsupportedAlgorithm, WrongPin, WrongPuk)
 from ..driver_ccid import APDUError, SW
 from .util import (
-    click_force_option, click_postpone_execution, click_callback,
+    click_force_option, click_format_option,
+    click_postpone_execution, click_callback,
     prompt_for_touch, UpperCaseChoice)
 from cryptography import x509
 from cryptography.hazmat.primitives import hashes, serialization
@@ -60,16 +61,6 @@
 
 
 @click_callback()
-def click_parse_format(ctx, param, val):
-    if val == 'PEM':
-        return serialization.Encoding.PEM
-    elif val == 'DER':
-        return serialization.Encoding.DER
-    else:
-        raise ValueError(val)
-
-
-@click_callback()
 def click_parse_management_key(ctx, param, val):
     try:
         key = a2b_hex(val)
@@ -88,10 +79,6 @@
     callback=click_parse_management_key)
 click_pin_option = click.option(
     '-P', '--pin', help='PIN code.')
-click_format_option = click.option(
-    '-F', '--format',
-    type=UpperCaseChoice(['PEM', 'DER']), default='PEM', show_default=True,
-    help='Encoding format.', callback=click_parse_format)
 click_pin_policy_option = click.option(
     '--pin-policy',
     type=UpperCaseChoice(['DEFAULT', 'NEVER', 'ONCE', 'ALWAYS']),
@@ -168,18 +155,43 @@
 
     for (slot, cert) in controller.list_certificates().items():
         click.echo('Slot %02x:' % slot)
-        click.echo('\tAlgorithm:\t%s' % ALGO.from_public_key(cert.public_key())
-                   .name)
-        cn = cert.subject.get_attributes_for_oid(x509.NameOID.COMMON_NAME)
-        cn = cn[0].value if len(cn) > 0 else 'None'
-        click.echo('\tSubject CN:\t%s' % cn)
-        cn = cert.issuer.get_attributes_for_oid(x509.NameOID.COMMON_NAME)
-        cn = cn[0].value if len(cn) > 0 else 'None'
-        click.echo('\tIssuer CN:\t%s' % cn)
-        click.echo('\tFingerprint:\t%s' % b2a_hex(
-            cert.fingerprint(hashes.SHA256())).decode('ascii'))
-        click.echo('\tNot before:\t%s' % cert.not_valid_before)
-        click.echo('\tNot after:\t%s' % cert.not_valid_after)
+
+        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:
+            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 len(cn) > 0 else 'None'
+            issuer_cn = 
cert.issuer.get_attributes_for_oid(x509.NameOID.COMMON_NAME)
+            issuer_cn = issuer_cn[0].value if len(cn) > 0 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
+        not_before = cert.not_valid_before
+        not_after = cert.not_valid_after
+
+        # Print out everything
+        click.echo('\tAlgorithm:\t%s' % algo)
+        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)
+        click.echo('\tNot before:\t%s' % not_before)
+        click.echo('\tNot after:\t%s' % not_after)
 
 
 @piv.command()
@@ -274,10 +286,8 @@
 @click.option(
     '-p', '--password', help='A password may be needed to decrypt the data.')
 @click.option(
-    '--no-verify', 'verify', is_flag=True, default=False,
-    callback=lambda ctx, param, value: not value,
-    help='Skip verifying that the certificate matches the private key in the '
-         'slot.')
+    '-v', '--verify', is_flag=True,
+    help='Verify that the certificate matches the private key in the slot.')
 @click.argument('cert', type=click.File('rb'), metavar='CERTIFICATE')
 def import_certificate(
         ctx, slot, management_key, pin, cert, password, verify):
@@ -324,7 +334,9 @@
 
     def do_import(retry=True):
         try:
-            controller.import_certificate(slot, cert_to_import, verify=verify)
+            controller.import_certificate(
+                slot, cert_to_import, verify=verify,
+                touch_callback=prompt_for_touch)
 
         except KeypairMismatch:
             ctx.fail('This certificate is not tied to the private key in the '
@@ -521,7 +533,7 @@
 @click.argument('public-key', type=click.File('rb'), metavar='PUBLIC-KEY')
 @click.option(
     '-s', '--subject',
-    help='A subject name for the certificate.', required=True)
+    help='Subject common name (CN) for the certificate.', required=True)
 @click.option(
     '-d', '--valid-days',
     help='Number of days until the certificate expires.',
@@ -568,7 +580,8 @@
 @click.argument('csr-output', type=click.File('wb'), metavar='CSR')
 @click.option(
     '-s', '--subject',
-    help='A subject name for the requested certificate.', required=True)
+    help='Subject common name (CN) for the requested certificate.',
+    required=True)
 def generate_certificate_signing_request(
         ctx, slot, pin, public_key, csr_output, subject):
     """
@@ -622,17 +635,26 @@
     """
     Change the PIN code.
 
-    The PIN can be up to 8 characters long, and supports any type of
+    The PIN must be between 6 and 8 characters long, and supports any type of
     alphanumeric characters. For cross-platform compatibility,
-    a PIN of 6 - 8 numeric digits is recommended.
+    numeric digits are recommended.
     """
+
     controller = ctx.obj['controller']
+
     if not pin:
         pin = _prompt_pin(ctx, prompt='Enter your current PIN')
     if not new_pin:
         new_pin = click.prompt(
             'Enter your new PIN', default='', hide_input=True,
             show_default=False, confirmation_prompt=True, err=True)
+
+    if not _valid_pin_length(pin):
+        ctx.fail('Current PIN must be between 6 and 8 characters long.')
+
+    if not _valid_pin_length(new_pin):
+        ctx.fail('New PIN must be between 6 and 8 characters long.')
+
     try:
         controller.change_pin(pin, new_pin)
         click.echo('New PIN set.')
@@ -656,6 +678,8 @@
     Change the PUK code.
 
     If the PIN is lost or blocked it can be reset using a PUK.
+    The PUK must be between 6 and 8 characters long, and supports any type of
+    alphanumeric characters.
     """
     controller = ctx.obj['controller']
     if not puk:
@@ -666,6 +690,12 @@
             show_default=False, confirmation_prompt=True,
             err=True)
 
+    if not _valid_pin_length(puk):
+        ctx.fail('Current PUK must be between 6 and 8 characters long.')
+
+    if not _valid_pin_length(new_puk):
+        ctx.fail('New PUK must be between 6 and 8 characters long.')
+
     try:
         controller.change_puk(puk, new_puk)
         click.echo('New PUK set.')
@@ -792,6 +822,76 @@
             show_default=False, hide_input=True, err=True)
     controller.unblock_pin(puk, new_pin)
 
+@piv.command('read-object')
+@click_pin_option
+@click.pass_context
+@click.argument(
+    'object-id',
+    callback=lambda ctx, param, value: int(value, 16),
+    metavar='OBJECT-ID')
+def read_object(ctx, pin, object_id):
+    """
+    Read arbitrary PIV object.
+
+    Read PIV object by providing the object id.
+
+    \b
+    OBJECT-ID       Id of PIV object in HEX.
+    """
+
+    controller = ctx.obj['controller']
+
+    def do_read_object(retry=True):
+        try:
+            click.echo(controller.get_data(object_id))
+        except APDUError as e:
+            if e.sw == SW.NOT_FOUND:
+                ctx.fail('No data found.')
+            elif e.sw == SW.SECURITY_CONDITION_NOT_SATISFIED:
+                _verify_pin(ctx, controller, pin)
+                do_read_object(retry=False)
+            else:
+                raise
+
+    do_read_object()
+
+
+@piv.command('write-object')
+@click_pin_option
+@click_management_key_option
+@click.pass_context
+@click.argument(
+    'object-id',
+    callback=lambda ctx, param, value: int(value, 16),
+    metavar='OBJECT-ID')
+@click.argument('data', type=click.File('rb'), metavar='DATA')
+def write_object(ctx, pin, management_key, object_id, data):
+    """
+    Write an arbitrary PIV object.
+
+    Write a PIV object by providing the object id.
+    Yubico writable PIV objects are available in
+    the range 5f0000 - 5fffff.
+
+    \b
+    OBJECT-ID       Id of PIV object in HEX.
+    DATA            File containing the data to be written. Use '-' to use 
stdin.
+    """
+
+    controller = ctx.obj['controller']
+    _ensure_authenticated(ctx, controller, pin, management_key)
+
+    def do_write_object(retry=True):
+        try:
+            controller.put_data(object_id, data.read())
+        except APDUError as e:
+            logger.debug('Failed writing object', exc_info=e)
+            if e.sw == SW.INCORRECT_PARAMETERS:
+                ctx.fail('Something went wrong, is the object id valid?')
+            raise
+
+    do_write_object()
+
 
 def _prompt_management_key(
         ctx, prompt='Enter a management key [blank to use default key]'):
@@ -810,6 +910,10 @@
         prompt, default='', hide_input=True, show_default=False, err=True)
 
 
+def _valid_pin_length(pin):
+    return 6 <= len(pin) <= 8
+
+
 def _ensure_authenticated(
         ctx, controller, pin=None, management_key=None,
         require_pin_and_key=False,
diff -Nru yubikey-manager-2.0.0/ykman/cli/util.py 
yubikey-manager-2.1.0/ykman/cli/util.py
--- yubikey-manager-2.0.0/ykman/cli/util.py     2018-11-08 12:33:42.000000000 
+0100
+++ yubikey-manager-2.1.0/ykman/cli/util.py     2019-03-11 12:11:41.000000000 
+0100
@@ -32,9 +32,7 @@
 import sys
 from ..util import parse_b32_key
 from collections import OrderedDict, MutableMapping
-
-click_force_option = click.option('-f', '--force', is_flag=True,
-                                  help='Confirm the action without prompting.')
+from cryptography.hazmat.primitives import serialization
 
 
 class UpperCaseChoice(click.Choice):
@@ -68,6 +66,26 @@
     return wrap
 
 
+@click_callback()
+def click_parse_format(ctx, param, val):
+    if val == 'PEM':
+        return serialization.Encoding.PEM
+    elif val == 'DER':
+        return serialization.Encoding.DER
+    else:
+        raise ValueError(val)
+
+
+click_force_option = click.option(
+    '-f', '--force', is_flag=True, help='Confirm the action without 
prompting.')
+
+
+click_format_option = click.option(
+    '-F', '--format',
+    type=UpperCaseChoice(['PEM', 'DER']), default='PEM', show_default=True,
+    help='Encoding format.', callback=click_parse_format)
+
+
 class YkmanContextObject(MutableMapping):
     def __init__(self):
         self._objects = OrderedDict()
@@ -81,7 +99,7 @@
     def resolve(self):
         if not self._resolved:
             self._resolved = True
-            for k, f in self._objects.items():
+            for k, f in self._objects.copy().items():
                 self._objects[k] = f()
 
     def __getitem__(self, key):
diff -Nru yubikey-manager-2.0.0/ykman/driver_ccid.py 
yubikey-manager-2.1.0/ykman/driver_ccid.py
--- yubikey-manager-2.0.0/ykman/driver_ccid.py  2018-12-20 14:58:43.000000000 
+0100
+++ yubikey-manager-2.1.0/ykman/driver_ccid.py  2019-03-11 12:11:41.000000000 
+0100
@@ -307,7 +307,7 @@
     return killed
 
 
-def _list_readers():
+def list_readers():
     try:
         return System.readers()
     except ListReadersException:
@@ -319,11 +319,11 @@
 
 
 def open_devices(name_filter=YK_READER_NAME):
-    readers = _list_readers()
+    readers = list_readers()
     while readers:
         try_again = []
         for reader in readers:
-            if reader.name.lower().startswith(name_filter.lower()):
+            if name_filter.lower() in reader.name.lower():
                 try:
                     conn = reader.createConnection()
                     conn.connect()
diff -Nru yubikey-manager-2.0.0/ykman/driver_otp.py 
yubikey-manager-2.1.0/ykman/driver_otp.py
--- yubikey-manager-2.0.0/ykman/driver_otp.py   2018-11-08 12:33:42.000000000 
+0100
+++ yubikey-manager-2.1.0/ykman/driver_otp.py   2019-03-11 12:11:41.000000000 
+0100
@@ -41,6 +41,7 @@
 
 CMD_VERIFY_FIPS_MODE = 0x14
 
+MISSING_LIBYKPERS_MSG = 'libykpers not found, OTP functionality not available'
 
 try:
     ykpers = Ykpers('ykpers-1', '1')
@@ -50,8 +51,7 @@
                        .decode('ascii').split('.'))
 except Exception as e:
     logger.error('libykpers not found', exc_info=e)
-    ykpers = MissingLibrary(
-        'libykpers not found, slot functionality not available!')
+    ykpers = MissingLibrary(MISSING_LIBYKPERS_MSG)
     libversion = None
 
 
@@ -210,6 +210,9 @@
 
 
 def open_devices():
+    if not libversion:
+        logger.error(MISSING_LIBYKPERS_MSG)
+        return
     if libversion < (1, 18):
         yield OTPDriver(ykpers.yk_open_first_key())
     else:
diff -Nru yubikey-manager-2.0.0/ykman/opgp.py 
yubikey-manager-2.1.0/ykman/opgp.py
--- yubikey-manager-2.0.0/ykman/opgp.py 2018-12-20 14:58:43.000000000 +0100
+++ yubikey-manager-2.1.0/ykman/opgp.py 2019-03-11 12:11:41.000000000 +0100
@@ -37,16 +37,16 @@
 
 @unique
 class KEY_SLOT(IntEnum):  # noqa: N801
-    SIGN = 0xd6
-    ENCRYPT = 0xd7
-    AUTHENTICATE = 0xd8
+    SIGNATURE = 0xd6
+    ENCRYPTION = 0xd7
+    AUTHENTICATION = 0xd8
 
 
 @unique
 class TOUCH_MODE(IntEnum):  # noqa: N801
     OFF = 0x00
     ON = 0x01
-    ON_FIXED = 0x02
+    FIXED = 0x02
 
 
 @unique
diff -Nru yubikey-manager-2.0.0/ykman/piv.py yubikey-manager-2.1.0/ykman/piv.py
--- yubikey-manager-2.0.0/ykman/piv.py  2019-01-07 12:22:56.000000000 +0100
+++ yubikey-manager-2.1.0/ykman/piv.py  2019-03-11 12:11:41.000000000 +0100
@@ -810,7 +810,7 @@
         id_bytes = struct.pack(b'>I', object_id).lstrip(b'\0')
         tlv = Tlv(self.send_cmd(INS.GET_DATA, 0x3f, 0xff,
                                 Tlv(TAG.OBJ_ID, id_bytes)))
-        if tlv.tag != TAG.OBJ_DATA:
+        if tlv.tag not in [TAG.OBJ_DATA, OBJ.DISCOVERY]:
             raise ValueError('Wrong tag in response data!')
         return tlv.value
 
@@ -912,7 +912,8 @@
         self.send_cmd(INS.IMPORT_KEY, algorithm, slot, data)
         return algorithm
 
-    def import_certificate(self, slot, certificate, verify=False):
+    def import_certificate(
+            self, slot, certificate, verify=False, touch_callback=None):
         cert_data = certificate.public_bytes(Encoding.DER)
 
         if verify:
@@ -922,9 +923,17 @@
                 public_key = certificate.public_key()
 
                 test_data = b'test'
+
+                if touch_callback is not None:
+                    touch_timer = Timer(0.500, touch_callback)
+                    touch_timer.start()
+
                 test_sig = self.sign(
                     slot, ALGO.from_public_key(public_key), test_data)
 
+                if touch_callback is not None:
+                    touch_timer.cancel()
+
                 if isinstance(public_key, rsa.RSAPublicKey):
                     public_key.verify(
                         test_sig, test_data, padding.PKCS1v15(),
diff -Nru yubikey-manager-2.0.0/ykman/util.py 
yubikey-manager-2.1.0/ykman/util.py
--- yubikey-manager-2.0.0/ykman/util.py 2018-12-20 14:58:43.000000000 +0100
+++ yubikey-manager-2.1.0/ykman/util.py 2019-03-11 12:11:41.000000000 +0100
@@ -27,11 +27,11 @@
 
 from __future__ import absolute_import
 
-import os
 import six
 import struct
 import re
 import logging
+import random
 from cryptography.hazmat.primitives import hashes, serialization
 from cryptography.hazmat.backends import default_backend
 from cryptography import x509
@@ -94,11 +94,11 @@
         return APPLICATION.OPGP | APPLICATION.OATH | APPLICATION.PIV
 
     def __str__(self):
-        if self == self.U2F:
+        if self == APPLICATION.U2F:
             return 'FIDO U2F'
-        elif self == self.FIDO2:
+        elif self == APPLICATION.FIDO2:
             return 'FIDO2'
-        elif self == self.OPGP:
+        elif self == APPLICATION.OPGP:
             return 'OpenPGP'
         else:
             return self.name
@@ -113,15 +113,15 @@
     USB_C_NANO = 0x04
 
     def __str__(self):
-        if self == self.USB_A_KEYCHAIN:
+        if self == FORM_FACTOR.USB_A_KEYCHAIN:
             return 'Keychain (USB-A)'
-        elif self == self.USB_A_NANO:
+        elif self == FORM_FACTOR.USB_A_NANO:
             return 'Nano (USB-A)'
-        elif self == self.USB_C_KEYCHAIN:
+        elif self == FORM_FACTOR.USB_C_KEYCHAIN:
             return 'Keychain (USB-C)'
-        elif self == self.USB_C_NANO:
+        elif self == FORM_FACTOR.USB_C_NANO:
             return 'Nano (USB-C)'
-        elif self == self.UNKNOWN:
+        elif self == FORM_FACTOR.UNKNOWN:
             return 'Unknown.'
 
     @classmethod
@@ -351,14 +351,12 @@
 
 
 def generate_static_pw(
-    length, keyboard_layout=KEYBOARD_LAYOUT.MODHEX,
+        length,
+        keyboard_layout=KEYBOARD_LAYOUT.MODHEX,
         blacklist=DEFAULT_PW_CHAR_BLACKLIST):
-    data = os.urandom(length)
-    keys = ''.join([
-        k for k in keyboard_layout.value.keys() if k not in 
blacklist]).encode()
-    return bytes(
-            bytearray(six.indexbytes(
-                keys, d % len(keys)) for d in six.iterbytes(data)))
+    chars = [k for k in keyboard_layout.value.keys() if k not in blacklist]
+    sr = random.SystemRandom()
+    return ''.join([sr.choice(chars) for _ in range(length)])
 
 
 def format_code(code, digits=6, steam=False):
@@ -473,7 +471,9 @@
                         PEM_IDENTIFIER + cert, default_backend()))
             except Exception:
                 pass
-        return certs
+        # Could be valid PEM but not certificates.
+        if len(certs) > 0:
+            return certs
 
     # PKCS12
     if is_pkcs12(data):
diff -Nru yubikey-manager-2.0.0/ykman/VERSION 
yubikey-manager-2.1.0/ykman/VERSION
--- yubikey-manager-2.0.0/ykman/VERSION 2019-01-08 08:55:19.000000000 +0100
+++ yubikey-manager-2.1.0/ykman/VERSION 2019-03-11 12:11:41.000000000 +0100
@@ -1 +1 @@
-2.0.0
+2.1.0
diff -Nru yubikey-manager-2.0.0/yubikey_manager.egg-info/PKG-INFO 
yubikey-manager-2.1.0/yubikey_manager.egg-info/PKG-INFO
--- yubikey-manager-2.0.0/yubikey_manager.egg-info/PKG-INFO     2019-01-08 
09:00:36.000000000 +0100
+++ yubikey-manager-2.1.0/yubikey_manager.egg-info/PKG-INFO     2019-03-11 
12:16:19.000000000 +0100
@@ -1,13 +1,12 @@
-Metadata-Version: 1.2
+Metadata-Version: 1.1
 Name: yubikey-manager
-Version: 2.0.0
+Version: 2.1.0
 Summary: Tool for managing your YubiKey configuration.
 Home-page: https://github.com/Yubico/yubikey-manager
-Author: Dain Nilsson
-Author-email: d...@yubico.com
-Maintainer: Yubico Open Source Maintainers
-Maintainer-email: ossma...@yubico.com
+Author: Yubico Open Source Maintainers
+Author-email: ossma...@yubico.com
 License: BSD 2 clause
+Description-Content-Type: UNKNOWN
 Description: UNKNOWN
 Platform: UNKNOWN
 Classifier: License :: OSI Approved :: BSD License
diff -Nru yubikey-manager-2.0.0/yubikey_manager.egg-info/SOURCES.txt 
yubikey-manager-2.1.0/yubikey_manager.egg-info/SOURCES.txt
--- yubikey-manager-2.0.0/yubikey_manager.egg-info/SOURCES.txt  2019-01-08 
09:00:36.000000000 +0100
+++ yubikey-manager-2.1.0/yubikey_manager.egg-info/SOURCES.txt  2019-03-11 
12:16:19.000000000 +0100
@@ -5,6 +5,7 @@
 setup.cfg
 setup.py
 doc/development.adoc
+man/ykman.1
 test/__init__.py
 test/test_device.py
 test/test_external_libs.py
@@ -13,6 +14,14 @@
 test/test_scancodes.py
 test/test_util.py
 test/util.py
+test/__pycache__/__init__.cpython-36.pyc
+test/__pycache__/test_device.cpython-36.pyc
+test/__pycache__/test_external_libs.cpython-36.pyc
+test/__pycache__/test_oath.cpython-36.pyc
+test/__pycache__/test_piv.cpython-36.pyc
+test/__pycache__/test_scancodes.cpython-36.pyc
+test/__pycache__/test_util.cpython-36.pyc
+test/__pycache__/util.cpython-36.pyc
 test/files/rsa_1024_key.pem
 test/files/rsa_2048_cert.der
 test/files/rsa_2048_cert.pem
@@ -31,6 +40,16 @@
 test/on_yubikey/test_interfaces.py
 test/on_yubikey/test_piv.py
 test/on_yubikey/util.py
+test/on_yubikey/__pycache__/__init__.cpython-36.pyc
+test/on_yubikey/__pycache__/test_cli_config.cpython-36.pyc
+test/on_yubikey/__pycache__/test_cli_misc.cpython-36.pyc
+test/on_yubikey/__pycache__/test_cli_oath.cpython-36.pyc
+test/on_yubikey/__pycache__/test_cli_openpgp.cpython-36.pyc
+test/on_yubikey/__pycache__/test_cli_otp.cpython-36.pyc
+test/on_yubikey/__pycache__/test_fips_u2f_commands.cpython-36.pyc
+test/on_yubikey/__pycache__/test_interfaces.cpython-36.pyc
+test/on_yubikey/__pycache__/test_piv.cpython-36.pyc
+test/on_yubikey/__pycache__/util.cpython-36.pyc
 test/on_yubikey/cli_piv/__init__.py
 test/on_yubikey/cli_piv/test_fips.py
 test/on_yubikey/cli_piv/test_generate_cert_and_csr.py
@@ -39,6 +58,14 @@
 test/on_yubikey/cli_piv/test_misc.py
 test/on_yubikey/cli_piv/test_pin_puk.py
 test/on_yubikey/cli_piv/util.py
+test/on_yubikey/cli_piv/__pycache__/__init__.cpython-36.pyc
+test/on_yubikey/cli_piv/__pycache__/test_fips.cpython-36.pyc
+test/on_yubikey/cli_piv/__pycache__/test_generate_cert_and_csr.cpython-36.pyc
+test/on_yubikey/cli_piv/__pycache__/test_key_management.cpython-36.pyc
+test/on_yubikey/cli_piv/__pycache__/test_management_key.cpython-36.pyc
+test/on_yubikey/cli_piv/__pycache__/test_misc.cpython-36.pyc
+test/on_yubikey/cli_piv/__pycache__/test_pin_puk.cpython-36.pyc
+test/on_yubikey/cli_piv/__pycache__/util.cpython-36.pyc
 ykman/VERSION
 ykman/__init__.py
 ykman/descriptor.py

--- End Message ---
--- Begin Message ---
Nicolas Braud-Santoni:
> Package: release.debian.org
> Severity: normal
> User: release.debian....@packages.debian.org
> Usertags: unblock
> Control: block 925212 by -1
> 
> Please unblock package yubikey-manager
> 
> The new upstream release fixes support of non-QWERTY keyboards
> in the OTP “static password” functionality (see #925212).
> 
> The debdiff is attached.
> 
> unblock yubikey-manager/2.1.0-1
> 
> [...]

Unblocked, thanks.
~Niels

--- End Message ---

Reply via email to