Hello community,

here is the log from the commit of package yubikey-manager for openSUSE:Factory 
checked in at 2019-06-18 14:56:17
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/yubikey-manager (Old)
 and      /work/SRC/openSUSE:Factory/.yubikey-manager.new.4811 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "yubikey-manager"

Tue Jun 18 14:56:17 2019 rev:10 rq:706248 version:2.1.1

Changes:
--------
--- /work/SRC/openSUSE:Factory/yubikey-manager/yubikey-manager.changes  
2019-03-12 09:55:34.119512299 +0100
+++ 
/work/SRC/openSUSE:Factory/.yubikey-manager.new.4811/yubikey-manager.changes    
    2019-06-18 14:56:18.253404922 +0200
@@ -1,0 +2,12 @@
+Wed May 29 08:52:25 UTC 2019 - Karol Babioch <[email protected]>
+
+- Version 2.1.1 (released 2019-05-28)
+  * OTP: Add initial support for uploading Yubico OTP credentials to YubiCloud
+  * Don’t automatically select the U2F applet on YubiKey NEO, it might be
+    blocked by the OS
+  * ChalResp: Always pad challenge correctly
+  * Bugfix: Don’t crash with older versions of cryptography
+  * Bugfix: Password was always prompted in OATH command, even if sent as
+    argument
+
+-------------------------------------------------------------------

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

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

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

Other differences:
------------------
++++++ yubikey-manager.spec ++++++
--- /var/tmp/diff_new_pack.LN3SUZ/_old  2019-06-18 14:56:18.857404545 +0200
+++ /var/tmp/diff_new_pack.LN3SUZ/_new  2019-06-18 14:56:18.881404530 +0200
@@ -17,7 +17,7 @@
 
 
 Name:           yubikey-manager
-Version:        2.1.0
+Version:        2.1.1
 Release:        0
 Summary:        Python 3 library and command line tool for configuring a 
YubiKey
 License:        BSD-2-Clause

++++++ yubikey-manager-2.1.0.tar.gz -> yubikey-manager-2.1.1.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yubikey-manager-2.1.0/NEWS 
new/yubikey-manager-2.1.1/NEWS
--- old/yubikey-manager-2.1.0/NEWS      2019-03-11 12:11:41.000000000 +0100
+++ new/yubikey-manager-2.1.1/NEWS      2019-05-28 09:04:43.000000000 +0200
@@ -1,3 +1,10 @@
+* Version 2.1.1 (released 2019-05-28)
+ ** OTP: Add initial support for uploading Yubico OTP credentials to YubiCloud
+ ** Don't automatically select the U2F applet on YubiKey NEO, it might be 
blocked by the OS
+ ** ChalResp: Always pad challenge correctly
+ ** Bugfix: Don't crash with older versions of cryptography
+ ** Bugfix: Password was always prompted in OATH command, even if sent as 
argument
+
 * 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
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yubikey-manager-2.1.0/PKG-INFO 
new/yubikey-manager-2.1.1/PKG-INFO
--- old/yubikey-manager-2.1.0/PKG-INFO  2019-03-11 12:16:19.000000000 +0100
+++ new/yubikey-manager-2.1.1/PKG-INFO  2019-05-28 10:05:25.000000000 +0200
@@ -1,12 +1,13 @@
-Metadata-Version: 1.1
+Metadata-Version: 1.2
 Name: yubikey-manager
-Version: 2.1.0
+Version: 2.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-2.1.0/README.adoc 
new/yubikey-manager-2.1.1/README.adoc
--- old/yubikey-manager-2.1.0/README.adoc       2019-03-11 12:11:41.000000000 
+0100
+++ new/yubikey-manager-2.1.1/README.adoc       2019-04-09 09:39:55.000000000 
+0200
@@ -65,7 +65,7 @@
 https://pyscard.sourceforge.io/[Pyscard] is also needed in some form, and if 
it's not installed pip builds it using http://www.swig.org/[swig] and 
potentially https://pcsclite.alioth.debian.org/pcsclite.html[PCSC lite].
 
 ==== Source
-To install from source, see the 
https://github.com/Yubico/yubikey-manager/blob/master/doc/development.adoc[development]
 instructions.
+To install from source, see the link:doc/development.adoc[development] 
instructions.
 
 === Bash completion
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yubikey-manager-2.1.0/man/ykman.1 
new/yubikey-manager-2.1.1/man/ykman.1
--- old/yubikey-manager-2.1.0/man/ykman.1       2019-03-11 12:11:41.000000000 
+0100
+++ new/yubikey-manager-2.1.1/man/ykman.1       2019-05-28 08:53:55.000000000 
+0200
@@ -1,4 +1,4 @@
-.TH YKMAN "1" "March 2019" "ykman 2.1.0" "User Commands"
+.TH YKMAN "1" "May 2019" "ykman 2.1.1" "User Commands"
 .SH NAME
 ykman \- YubiKey Manager (ykman)
 .SH SYNOPSIS
Binary files old/yubikey-manager-2.1.0/test/__pycache__/__init__.cpython-36.pyc 
and new/yubikey-manager-2.1.1/test/__pycache__/__init__.cpython-36.pyc differ
Binary files 
old/yubikey-manager-2.1.0/test/__pycache__/test_device.cpython-36.pyc and 
new/yubikey-manager-2.1.1/test/__pycache__/test_device.cpython-36.pyc differ
Binary files 
old/yubikey-manager-2.1.0/test/__pycache__/test_external_libs.cpython-36.pyc 
and 
new/yubikey-manager-2.1.1/test/__pycache__/test_external_libs.cpython-36.pyc 
differ
Binary files 
old/yubikey-manager-2.1.0/test/__pycache__/test_oath.cpython-36.pyc and 
new/yubikey-manager-2.1.1/test/__pycache__/test_oath.cpython-36.pyc differ
Binary files old/yubikey-manager-2.1.0/test/__pycache__/test_piv.cpython-36.pyc 
and new/yubikey-manager-2.1.1/test/__pycache__/test_piv.cpython-36.pyc differ
Binary files 
old/yubikey-manager-2.1.0/test/__pycache__/test_scancodes.cpython-36.pyc and 
new/yubikey-manager-2.1.1/test/__pycache__/test_scancodes.cpython-36.pyc differ
Binary files 
old/yubikey-manager-2.1.0/test/__pycache__/test_util.cpython-36.pyc and 
new/yubikey-manager-2.1.1/test/__pycache__/test_util.cpython-36.pyc differ
Binary files old/yubikey-manager-2.1.0/test/__pycache__/util.cpython-36.pyc and 
new/yubikey-manager-2.1.1/test/__pycache__/util.cpython-36.pyc differ
Binary files 
old/yubikey-manager-2.1.0/test/on_yubikey/__pycache__/__init__.cpython-36.pyc 
and 
new/yubikey-manager-2.1.1/test/on_yubikey/__pycache__/__init__.cpython-36.pyc 
differ
Binary files 
old/yubikey-manager-2.1.0/test/on_yubikey/__pycache__/test_cli_config.cpython-36.pyc
 and 
new/yubikey-manager-2.1.1/test/on_yubikey/__pycache__/test_cli_config.cpython-36.pyc
 differ
Binary files 
old/yubikey-manager-2.1.0/test/on_yubikey/__pycache__/test_cli_misc.cpython-36.pyc
 and 
new/yubikey-manager-2.1.1/test/on_yubikey/__pycache__/test_cli_misc.cpython-36.pyc
 differ
Binary files 
old/yubikey-manager-2.1.0/test/on_yubikey/__pycache__/test_cli_oath.cpython-36.pyc
 and 
new/yubikey-manager-2.1.1/test/on_yubikey/__pycache__/test_cli_oath.cpython-36.pyc
 differ
Binary files 
old/yubikey-manager-2.1.0/test/on_yubikey/__pycache__/test_cli_openpgp.cpython-36.pyc
 and 
new/yubikey-manager-2.1.1/test/on_yubikey/__pycache__/test_cli_openpgp.cpython-36.pyc
 differ
Binary files 
old/yubikey-manager-2.1.0/test/on_yubikey/__pycache__/test_cli_otp.cpython-36.pyc
 and 
new/yubikey-manager-2.1.1/test/on_yubikey/__pycache__/test_cli_otp.cpython-36.pyc
 differ
Binary files 
old/yubikey-manager-2.1.0/test/on_yubikey/__pycache__/test_fips_u2f_commands.cpython-36.pyc
 and 
new/yubikey-manager-2.1.1/test/on_yubikey/__pycache__/test_fips_u2f_commands.cpython-36.pyc
 differ
Binary files 
old/yubikey-manager-2.1.0/test/on_yubikey/__pycache__/test_interfaces.cpython-36.pyc
 and 
new/yubikey-manager-2.1.1/test/on_yubikey/__pycache__/test_interfaces.cpython-36.pyc
 differ
Binary files 
old/yubikey-manager-2.1.0/test/on_yubikey/__pycache__/test_piv.cpython-36.pyc 
and 
new/yubikey-manager-2.1.1/test/on_yubikey/__pycache__/test_piv.cpython-36.pyc 
differ
Binary files 
old/yubikey-manager-2.1.0/test/on_yubikey/__pycache__/util.cpython-36.pyc and 
new/yubikey-manager-2.1.1/test/on_yubikey/__pycache__/util.cpython-36.pyc differ
Binary files 
old/yubikey-manager-2.1.0/test/on_yubikey/cli_piv/__pycache__/__init__.cpython-36.pyc
 and 
new/yubikey-manager-2.1.1/test/on_yubikey/cli_piv/__pycache__/__init__.cpython-36.pyc
 differ
Binary files 
old/yubikey-manager-2.1.0/test/on_yubikey/cli_piv/__pycache__/test_fips.cpython-36.pyc
 and 
new/yubikey-manager-2.1.1/test/on_yubikey/cli_piv/__pycache__/test_fips.cpython-36.pyc
 differ
Binary files 
old/yubikey-manager-2.1.0/test/on_yubikey/cli_piv/__pycache__/test_generate_cert_and_csr.cpython-36.pyc
 and 
new/yubikey-manager-2.1.1/test/on_yubikey/cli_piv/__pycache__/test_generate_cert_and_csr.cpython-36.pyc
 differ
Binary files 
old/yubikey-manager-2.1.0/test/on_yubikey/cli_piv/__pycache__/test_key_management.cpython-36.pyc
 and 
new/yubikey-manager-2.1.1/test/on_yubikey/cli_piv/__pycache__/test_key_management.cpython-36.pyc
 differ
Binary files 
old/yubikey-manager-2.1.0/test/on_yubikey/cli_piv/__pycache__/test_management_key.cpython-36.pyc
 and 
new/yubikey-manager-2.1.1/test/on_yubikey/cli_piv/__pycache__/test_management_key.cpython-36.pyc
 differ
Binary files 
old/yubikey-manager-2.1.0/test/on_yubikey/cli_piv/__pycache__/test_misc.cpython-36.pyc
 and 
new/yubikey-manager-2.1.1/test/on_yubikey/cli_piv/__pycache__/test_misc.cpython-36.pyc
 differ
Binary files 
old/yubikey-manager-2.1.0/test/on_yubikey/cli_piv/__pycache__/test_pin_puk.cpython-36.pyc
 and 
new/yubikey-manager-2.1.1/test/on_yubikey/cli_piv/__pycache__/test_pin_puk.cpython-36.pyc
 differ
Binary files 
old/yubikey-manager-2.1.0/test/on_yubikey/cli_piv/__pycache__/util.cpython-36.pyc
 and 
new/yubikey-manager-2.1.1/test/on_yubikey/cli_piv/__pycache__/util.cpython-36.pyc
 differ
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/yubikey-manager-2.1.0/test/on_yubikey/test_cli_otp.py 
new/yubikey-manager-2.1.1/test/on_yubikey/test_cli_otp.py
--- old/yubikey-manager-2.1.0/test/on_yubikey/test_cli_otp.py   2019-03-11 
12:11:41.000000000 +0100
+++ new/yubikey-manager-2.1.1/test/on_yubikey/test_cli_otp.py   2019-05-16 
09:16:32.000000000 +0200
@@ -151,6 +151,7 @@
             'otp', 'yubiotp', '2', input='vvccccfiluij\n'
                                          '267e0a88949b\n'
                                          'b8e31ab90bb8830e3c1fe1b483a8e0d4\n'
+                                         'n\n'
                                          'y\n')
         self._check_slot_2_programmed()
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yubikey-manager-2.1.0/ykman/VERSION 
new/yubikey-manager-2.1.1/ykman/VERSION
--- old/yubikey-manager-2.1.0/ykman/VERSION     2019-03-11 12:11:41.000000000 
+0100
+++ new/yubikey-manager-2.1.1/ykman/VERSION     2019-05-27 12:35:48.000000000 
+0200
@@ -1 +1 @@
-2.1.0
+2.1.1
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yubikey-manager-2.1.0/ykman/cli/__main__.py 
new/yubikey-manager-2.1.1/ykman/cli/__main__.py
--- old/yubikey-manager-2.1.0/ykman/cli/__main__.py     2019-03-11 
12:11:41.000000000 +0100
+++ new/yubikey-manager-2.1.1/ykman/cli/__main__.py     2019-05-27 
12:35:48.000000000 +0200
@@ -127,7 +127,8 @@
         try:
             return descriptor.open_device(transports)
         except FailedOpeningDeviceException:
-            ctx.fail('Failed connecting to the YubiKey.')
+            ctx.fail('Failed connecting to {} [{}]'.format(
+                descriptor.name, descriptor.mode))
     else:
         _disabled_transport(ctx, transports, cmd)
 
@@ -201,45 +202,51 @@
     """
     List connected YubiKeys.
     """
+
+    def _print_device(dev, serial):
+        if serials:
+            if serial:
+                click.echo(serial)
+        else:
+            click.echo('{} [{}]{}'.format(
+                dev.device_name,
+                dev.mode,
+                ' Serial: {}'.format(serial) if serial else '')
+            )
+
     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)
+    descriptors = get_descriptors()
     handled_serials = set()
     for dev in list_devices():
-        handled = False
-        if skys > 0 and dev.key_type == YUBIKEY.SKY:
-            skys -= 1
-            serial = None
-            handled = True
+        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)
-                    handled = True
-        if handled:
-            if serials:
-                if serial:
-                    click.echo(serial)
-            else:
-                click.echo('{} [{}]{}'.format(
-                    dev.device_name,
-                    dev.mode,
-                    ' Serial: {}'.format(serial) if serial else '')
-                )
+                    _print_device(dev, serial)
         dev.close()
-        if not descriptors and not skys:
+        if not descriptors:
             break
 
+    # List descriptors that failed to open.
+    logger.debug('Failed to open all devices, listing based on descriptors')
+    for desc in descriptors:
+        click.echo('{} [{}]'.format(desc.name, desc.mode))
+
 
 COMMANDS = (list_keys, info, mode, otp, openpgp, oath, piv, fido, config)
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yubikey-manager-2.1.0/ykman/cli/oath.py 
new/yubikey-manager-2.1.1/ykman/cli/oath.py
--- old/yubikey-manager-2.1.0/ykman/cli/oath.py 2019-03-11 12:11:41.000000000 
+0100
+++ new/yubikey-manager-2.1.1/ykman/cli/oath.py 2019-05-13 08:49:32.000000000 
+0200
@@ -499,9 +499,11 @@
 def ensure_validated(ctx, prompt='Enter your password', remember=False):
     controller = ctx.obj['controller']
     if controller.locked:
+
         # If password given as arg, use it
         if 'key' in ctx.obj:
             _validate(ctx, ctx.obj['key'], remember)
+            return
 
         # Use stored key if available
         keys = ctx.obj['settings'].setdefault('keys', {})
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yubikey-manager-2.1.0/ykman/cli/otp.py 
new/yubikey-manager-2.1.1/ykman/cli/otp.py
--- old/yubikey-manager-2.1.0/ykman/cli/otp.py  2019-03-11 12:11:41.000000000 
+0100
+++ new/yubikey-manager-2.1.1/ykman/cli/otp.py  2019-05-27 12:04:25.000000000 
+0200
@@ -34,13 +34,15 @@
     TRANSPORT, generate_static_pw, modhex_decode,
     modhex_encode, parse_key, parse_b32_key)
 from binascii import a2b_hex, b2a_hex
+from .. import __version__
 from ..driver_otp import YkpersError
-from ..otp import OtpController
+from ..otp import OtpController, PrepareUploadFailed
 from ..scancodes import KEYBOARD_LAYOUT
 import logging
 import os
 import struct
 import click
+import webbrowser
 
 
 logger = logging.getLogger(__name__)
@@ -118,7 +120,7 @@
       $ ykman otp chalresp --generate 2
 
     \b
-      Program a Yubico OTP credential to slot 2, using the serial as public id:
+      Program a Yubico OTP credential to slot 1, using the serial as public id:
       $ ykman otp yubiotp 1 --serial-public-id
 
     \b
@@ -242,11 +244,15 @@
 @click.option(
     '-G', '--generate-key', is_flag=True, required=False,
     help='Generate a random secret key. Conflicts with --key.')
[email protected](
+    '-u', '--upload', is_flag=True, required=False,
+    help='Upload credential to YubiCloud (opens in browser). '
+    'Conflicts with --force.')
 @click_force_option
 @click.pass_context
 def yubiotp(ctx, slot, public_id, private_id, key, no_enter, force,
             serial_public_id, generate_private_id,
-            generate_key):
+            generate_key, upload):
     """
     Program a Yubico OTP credential.
 
@@ -263,6 +269,9 @@
         ctx.fail('Invalid options: --private-id conflicts with '
                  '--generate-public-id.')
 
+    if upload and force:
+        ctx.fail('Invalid options: --upload conflicts with --force.')
+
     if key and generate_key:
         ctx.fail('Invalid options: --key conflicts with --generate-key.')
 
@@ -313,13 +322,31 @@
             key = click.prompt('Enter secret key', err=True)
             key = a2b_hex(key)
 
+    if not upload and not force:
+        upload = click.confirm('Upload credential to YubiCloud?',
+                               abort=False, err=True)
+    if upload:
+        try:
+            upload_url = controller.prepare_upload_key(
+                key, public_id, private_id, serial=dev.serial,
+                user_agent='ykman/' + __version__)
+            click.echo('Upload to YubiCloud initiated successfully.')
+        except PrepareUploadFailed as e:
+            error_msg = '\n'.join(e.messages())
+            ctx.fail('Upload to YubiCloud failed.\n' + error_msg)
+
     force or click.confirm('Program an OTP credential in slot 
{}?'.format(slot),
                            abort=True, err=True)
+
     try:
         controller.program_otp(slot, key, public_id, private_id, not no_enter)
     except YkpersError as e:
         _failed_to_write_msg(ctx, e)
 
+    if upload:
+        click.echo('Opening upload form in browser: ' + upload_url)
+        webbrowser.open_new_tab(upload_url)
+
 
 @otp.command()
 @click_slot_argument
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yubikey-manager-2.1.0/ykman/cli/piv.py 
new/yubikey-manager-2.1.1/ykman/cli/piv.py
--- old/yubikey-manager-2.1.0/ykman/cli/piv.py  2019-03-11 12:11:41.000000000 
+0100
+++ new/yubikey-manager-2.1.1/ykman/cli/piv.py  2019-04-30 12:51:29.000000000 
+0200
@@ -163,11 +163,12 @@
             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 len(cn) > 0 else 'None'
+            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 len(cn) > 0 else 'None'
+            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)
@@ -181,7 +182,7 @@
         not_after = cert.not_valid_after
 
         # Print out everything
-        click.echo('\tAlgorithm:\t%s' % algo)
+        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)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yubikey-manager-2.1.0/ykman/descriptor.py 
new/yubikey-manager-2.1.1/ykman/descriptor.py
--- old/yubikey-manager-2.1.0/ykman/descriptor.py       2019-03-11 
12:11:41.000000000 +0100
+++ new/yubikey-manager-2.1.1/ykman/descriptor.py       2019-05-27 
12:35:48.000000000 +0200
@@ -27,7 +27,7 @@
 
 from __future__ import absolute_import
 
-from .util import PID, TRANSPORT, Mode
+from .util import PID, TRANSPORT, Mode, YUBIKEY
 from .device import YubiKey
 from .driver_ccid import open_devices as open_ccid
 from .driver_fido import open_devices as open_fido
@@ -70,6 +70,15 @@
     def key_type(self):
         return self._key_type
 
+    @property
+    def name(self):
+        if self.key_type == YUBIKEY.SKY and self.version < (5, 0, 0):
+            return 'FIDO U2F Security Key'
+        elif self.key_type == YUBIKEY.YK4 and self.version >= (5, 0, 0):
+            return 'YubiKey 5'
+        else:
+            return self.key_type.value
+
     def open_device(self, transports=sum(TRANSPORT), serial=None, attempts=10):
         self._logger.debug('transports: 0x%x, self.mode.transports: 0x%x',
                            transports, self.mode.transports)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yubikey-manager-2.1.0/ykman/device.py 
new/yubikey-manager-2.1.1/ykman/device.py
--- old/yubikey-manager-2.1.0/ykman/device.py   2019-03-11 12:11:41.000000000 
+0100
+++ new/yubikey-manager-2.1.1/ykman/device.py   2019-05-27 12:04:25.000000000 
+0200
@@ -231,10 +231,10 @@
                 else:  # Assume base capabilities
                     logger.debug('CCID not available, guess capabilities')
                     usb_supported = _NEO_BASE_CAPABILITIES
-                    if TRANSPORT.has(self.mode.transports, TRANSPORT.FIDO) \
-                            or (version and version >= (3, 3, 0)):
-                        usb_supported |= APPLICATION.U2F
-
+                # NEO over 3.3.0 have U2F (which might be blocked by OS)
+                if TRANSPORT.has(self.mode.transports, TRANSPORT.FIDO) \
+                        or (version and version >= (3, 3, 0)):
+                    usb_supported |= APPLICATION.U2F
                 config._set(TAG.USB_SUPPORTED, usb_supported)
                 config._set(TAG.NFC_SUPPORTED, usb_supported)
                 config._set(TAG.NFC_ENABLED, usb_supported)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yubikey-manager-2.1.0/ykman/driver_ccid.py 
new/yubikey-manager-2.1.1/ykman/driver_ccid.py
--- old/yubikey-manager-2.1.0/ykman/driver_ccid.py      2019-03-11 
12:11:41.000000000 +0100
+++ new/yubikey-manager-2.1.1/ykman/driver_ccid.py      2019-05-27 
12:04:25.000000000 +0200
@@ -215,6 +215,10 @@
             except APDUError:
                 logger.debug(
                     'Missing applet: aid: %s , capability: %s', aid, code)
+            except CCIDError as e:
+                logger.debug(
+                    'Failed reading applet: aid: %s , capability: %s , %s',
+                    aid, code, e)
         return capa
 
     def send_apdu(self, cl, ins, p1, p2, data=b'', check=SW.OK):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yubikey-manager-2.1.0/ykman/otp.py 
new/yubikey-manager-2.1.1/ykman/otp.py
--- old/yubikey-manager-2.1.0/ykman/otp.py      2019-03-11 12:11:41.000000000 
+0100
+++ new/yubikey-manager-2.1.1/ykman/otp.py      2019-05-16 09:16:05.000000000 
+0200
@@ -27,18 +27,27 @@
 
 from __future__ import absolute_import
 
-import time
+import json
 import logging
+import time
 from ctypes import sizeof, byref, c_uint, create_string_buffer
+from enum import Enum
+from six.moves import http_client
 from .driver_otp import ykpers, check, YkpersError
-from .util import time_challenge, parse_totp_hash, format_code, 
hmac_shorten_key
+from .util import (time_challenge, parse_totp_hash, format_code,
+                   hmac_shorten_key, modhex_encode)
 from .scancodes import encode, KEYBOARD_LAYOUT
+from . import __version__
 from enum import IntEnum, unique
 from binascii import a2b_hex, b2a_hex
 
 logger = logging.getLogger(__name__)
 
 
+UPLOAD_HOST = 'upload.yubico.com'
+UPLOAD_PATH = '/prepare'
+
+
 @unique
 class SLOT(IntEnum):
     CONFIG = 0x01
@@ -62,6 +71,46 @@
         raise ValueError('slot must be 1 or 2')
 
 
+class PrepareUploadError(Enum):
+    # Defined here
+    CONNECTION_FAILED = 'Failed to open HTTPS connection.'
+    NOT_FOUND = 'Upload request not recognized by server.'
+    SERVICE_UNAVAILABLE = 'Service temporarily unavailable, please try again 
later.'  # noqa: E501
+
+    # Defined in upload project
+    PRIVATE_ID_INVALID_LENGTH = 'Private ID must be 12 characters long.'
+    PRIVATE_ID_NOT_HEX = 'Private ID must consist only of hex characters 
(0-9A-F).'  # noqa: E501
+    PRIVATE_ID_UNDEFINED = 'Private ID is required.'
+    PUBLIC_ID_INVALID_LENGTH = 'Public ID must be 12 characters long.'
+    PUBLIC_ID_NOT_MODHEX = 'Public ID must consist only of modhex characters 
(cbdefghijklnrtuv).'  # noqa: E501
+    PUBLIC_ID_NOT_VV = 'Public ID must begin with "vv".'
+    PUBLIC_ID_OCCUPIED = 'Public ID is already in use.'
+    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.'
+    SERIAL_NOT_INT = 'Serial number must be an integer.'
+    SERIAL_TOO_LONG = 'Serial number too long.'
+
+    def message(self):
+        return self.value
+
+
+class PrepareUploadFailed(Exception):
+    def __init__(self, status, content, error_ids):
+        super().__init__(
+            'Upload to YubiCloud failed with status {}: {}'
+            .format(status, content))
+        self.status = status
+        self.content = content
+        self.errors = [
+            e if e in PrepareUploadError else PrepareUploadError[e]
+            for e in error_ids]
+
+    def messages(self):
+        return [e.message() for e in self.errors]
+
+
 class OtpController(object):
 
     def __init__(self, driver):
@@ -123,6 +172,52 @@
         finally:
             ykpers.ykp_free_config(cfg)
 
+    def prepare_upload_key(self, key, public_id, private_id, serial=None,
+                           user_agent='python-yubikey-manager/' + __version__):
+        modhex_public_id = modhex_encode(public_id)
+        data = {
+            'aes_key': b2a_hex(key).decode('utf-8'),
+            'serial': serial or 0,
+            'public_id': modhex_public_id,
+            'private_id': b2a_hex(private_id).decode('utf-8'),
+        }
+
+        httpconn = http_client.HTTPSConnection(UPLOAD_HOST, timeout=1)
+        try:
+            httpconn.request('POST', UPLOAD_PATH,
+                             body=json.dumps(data, indent=False, 
sort_keys=True)
+                             .encode('utf-8'),
+                             headers={
+                                 'Content-Type': 'application/json',
+                                 'User-Agent': user_agent,
+                             })
+        except Exception as e:
+            logger.error('Failed to connect to %s', UPLOAD_HOST, exc_info=e)
+            raise PrepareUploadFailed(
+                None, None, [PrepareUploadError.CONNECTION_FAILED])
+
+        resp = httpconn.getresponse()
+        if resp.status == 200:
+            url = json.loads(resp.read().decode('utf-8'))['finish_url']
+            return url
+        else:
+            resp_body = resp.read()
+            logger.debug('Upload failed with status %d: %s',
+                         resp.status, resp_body)
+            if resp.status == 404:
+                raise PrepareUploadFailed(
+                    resp.status, resp_body, [PrepareUploadError.NOT_FOUND])
+            elif resp.status == 503:
+                raise PrepareUploadFailed(
+                    resp.status, resp_body,
+                    [PrepareUploadError.SERVICE_UNAVAILABLE])
+            else:
+                try:
+                    errors = 
json.loads(resp_body.decode('utf-8')).get('errors')
+                except Exception:
+                    errors = []
+                raise PrepareUploadFailed(resp.status, resp_body, errors)
+
     def program_static(self, slot, password, append_cr=True,
                        keyboard_layout=KEYBOARD_LAYOUT.MODHEX):
         pw_len = len(password)
@@ -192,6 +287,9 @@
                 challenge = time_challenge(challenge)
         else:
             challenge = a2b_hex(challenge)
+        # Pad challenge when < 64 bytes
+        challenge = challenge.ljust(
+            64, b'\1' if challenge.endswith(b'\0') else b'\0')
         resp = create_string_buffer(64)
         # Some versions of the NEO firmware returns error 11 too often.
         # Give the YubiKey 10 tries to do the calculation.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/yubikey-manager-2.1.0/yubikey_manager.egg-info/PKG-INFO 
new/yubikey-manager-2.1.1/yubikey_manager.egg-info/PKG-INFO
--- old/yubikey-manager-2.1.0/yubikey_manager.egg-info/PKG-INFO 2019-03-11 
12:16:19.000000000 +0100
+++ new/yubikey-manager-2.1.1/yubikey_manager.egg-info/PKG-INFO 2019-05-28 
10:05:25.000000000 +0200
@@ -1,12 +1,13 @@
-Metadata-Version: 1.1
+Metadata-Version: 1.2
 Name: yubikey-manager
-Version: 2.1.0
+Version: 2.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-2.1.0/yubikey_manager.egg-info/SOURCES.txt 
new/yubikey-manager-2.1.1/yubikey_manager.egg-info/SOURCES.txt
--- old/yubikey-manager-2.1.0/yubikey_manager.egg-info/SOURCES.txt      
2019-03-11 12:16:19.000000000 +0100
+++ new/yubikey-manager-2.1.1/yubikey_manager.egg-info/SOURCES.txt      
2019-05-28 10:05:25.000000000 +0200
@@ -14,14 +14,6 @@
 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
@@ -40,16 +32,6 @@
 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
@@ -58,14 +40,6 @@
 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


Reply via email to