Hello community,

here is the log from the commit of package python-yubico for openSUSE:Factory 
checked in at 2016-02-29 09:14:03
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-yubico (Old)
 and      /work/SRC/openSUSE:Factory/.python-yubico.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-yubico"

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-yubico/python-yubico.changes      
2015-11-10 10:03:01.000000000 +0100
+++ /work/SRC/openSUSE:Factory/.python-yubico.new/python-yubico.changes 
2016-02-29 09:15:54.000000000 +0100
@@ -1,0 +2,10 @@
+Tue Feb 23 11:48:24 UTC 2016 - [email protected]
+
+- update to 1.3.2
+  * yubico/yubikey_usb_hid.py: change logic for pgm seq if no
+    config is valid, seq 0 is ok
+  * yubico/yubikey_usb_hid.py: that the new sequence is 0 is also ok
+  * yubico/yubikey_frame.py: Added comments explaining debug data.
+  * Solved: Unlock code couldn't be set
+
+-------------------------------------------------------------------

Old:
----
  python-yubico-1.3.1.tar.gz
  python-yubico-1.3.1.tar.gz.sig

New:
----
  python-yubico-1.3.2.tar.gz
  python-yubico-1.3.2.tar.gz.sig

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

Other differences:
------------------
++++++ python-yubico.spec ++++++
--- /var/tmp/diff_new_pack.VU8yKY/_old  2016-02-29 09:15:55.000000000 +0100
+++ /var/tmp/diff_new_pack.VU8yKY/_new  2016-02-29 09:15:55.000000000 +0100
@@ -22,7 +22,7 @@
 BuildArch:      noarch
 %endif
 Name:           python-yubico
-Version:        1.3.1
+Version:        1.3.2
 Release:        0
 Summary:        Python code for talking to Yubico's YubiKeys
 License:        BSD-2-Clause

++++++ python-yubico-1.3.1.tar.gz -> python-yubico-1.3.2.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/python-yubico-1.3.1/ChangeLog 
new/python-yubico-1.3.2/ChangeLog
--- old/python-yubico-1.3.1/ChangeLog   2015-10-01 15:59:08.000000000 +0200
+++ new/python-yubico-1.3.2/ChangeLog   2016-02-23 12:24:39.000000000 +0100
@@ -1,3 +1,32 @@
+2016-02-23  Dain Nilsson <[email protected]>
+
+       * NEWS, release.py, yubico/yubico_version.py: Bumped version and
+       updated NEWS for release.
+
+2015-11-03  Klas Lindfors <[email protected]>
+
+       * yubico/yubikey_usb_hid.py: change logic for pgm seq if no config is 
valid, seq 0 is ok
+
+2015-11-03  Klas Lindfors <[email protected]>
+
+       * yubico/yubikey_usb_hid.py: that the new sequence is 0 is also ok
+
+2015-10-07  Dain Nilsson <[email protected]>
+
+       * yubico/yubikey_frame.py: Added comments explaining debug data.
+
+2015-10-07  Dain Nilsson <[email protected]>
+
+       * : Merge pull request #31 from axhoffmann/master Solved: Unlock code 
couldn't be set
+
+2015-10-01  Dain Nilsson <[email protected]>
+
+       * MANIFEST.in: Include tests.
+
+2015-10-01  Dain Nilsson <[email protected]>
+
+       * NEWS, yubico/yubico_version.py: Bumped version post release.
+
 2015-10-01  Dain Nilsson <[email protected]>
 
        * NEWS, yubico/yubico_version.py: Update version and NEWS for
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/python-yubico-1.3.1/MANIFEST.in 
new/python-yubico-1.3.2/MANIFEST.in
--- old/python-yubico-1.3.1/MANIFEST.in 2015-10-01 15:51:28.000000000 +0200
+++ new/python-yubico-1.3.2/MANIFEST.in 2016-02-23 12:21:35.000000000 +0100
@@ -5,3 +5,4 @@
 include examples/*
 include util/*
 include doc/*
+recursive-include test *.py
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/python-yubico-1.3.1/NEWS new/python-yubico-1.3.2/NEWS
--- old/python-yubico-1.3.1/NEWS        2015-10-01 15:58:46.000000000 +0200
+++ new/python-yubico-1.3.2/NEWS        2016-02-23 12:21:35.000000000 +0100
@@ -1,3 +1,7 @@
+* Version 1.3.2 (released 2016-02-23)
+ ** Various fixes to sequence number checking.
+ ** Fix issue with using an access code with the debug flag on.
+
 * Version 1.3.1 (released 2015-10-01)
  ** Fixup release to correct packages listed in last release.
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/python-yubico-1.3.1/PKG-INFO 
new/python-yubico-1.3.2/PKG-INFO
--- old/python-yubico-1.3.1/PKG-INFO    2015-10-01 15:59:08.000000000 +0200
+++ new/python-yubico-1.3.2/PKG-INFO    2016-02-23 12:24:40.000000000 +0100
@@ -1,6 +1,6 @@
 Metadata-Version: 1.1
 Name: python-yubico
-Version: 1.3.1
+Version: 1.3.2
 Summary: Python code for talking to Yubico's YubiKeys
 Home-page: https://github.com/Yubico/python-yubico
 Author: Yubico Open Source Maintainers
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/python-yubico-1.3.1/python_yubico.egg-info/PKG-INFO 
new/python-yubico-1.3.2/python_yubico.egg-info/PKG-INFO
--- old/python-yubico-1.3.1/python_yubico.egg-info/PKG-INFO     2015-10-01 
15:59:08.000000000 +0200
+++ new/python-yubico-1.3.2/python_yubico.egg-info/PKG-INFO     2016-02-23 
12:24:39.000000000 +0100
@@ -1,6 +1,6 @@
 Metadata-Version: 1.1
 Name: python-yubico
-Version: 1.3.1
+Version: 1.3.2
 Summary: Python code for talking to Yubico's YubiKeys
 Home-page: https://github.com/Yubico/python-yubico
 Author: Yubico Open Source Maintainers
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/python-yubico-1.3.1/python_yubico.egg-info/SOURCES.txt 
new/python-yubico-1.3.2/python_yubico.egg-info/SOURCES.txt
--- old/python-yubico-1.3.1/python_yubico.egg-info/SOURCES.txt  2015-10-01 
15:59:08.000000000 +0200
+++ new/python-yubico-1.3.2/python_yubico.egg-info/SOURCES.txt  2016-02-23 
12:24:39.000000000 +0100
@@ -19,7 +19,12 @@
 python_yubico.egg-info/requires.txt
 python_yubico.egg-info/top_level.txt
 test/__init__.py
-test/__init__.pyc
+test/soft/__init__.py
+test/soft/test_yubico.py
+test/soft/test_yubikey_config.py
+test/soft/test_yubikey_frame.py
+test/usb/__init__.py
+test/usb/test_yubikey_usb_hid.py
 util/yubikey-totp
 util/yubikey-totp.1
 yubico/__init__.py
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/python-yubico-1.3.1/release.py 
new/python-yubico-1.3.2/release.py
--- old/python-yubico-1.3.1/release.py  2015-10-01 15:51:09.000000000 +0200
+++ new/python-yubico-1.3.2/release.py  2016-02-23 12:21:35.000000000 +0100
@@ -123,9 +123,8 @@
 
         if not self.skip_tests:
             self.run_command('check')
-            # Nosetests calls sys.exit(status)
             try:
-                self.run_command('nosetests')
+                self.run_command('test')
             except SystemExit as e:
                 if e.code != 0:
                     raise DistutilsSetupError("There were test failures!")
Files old/python-yubico-1.3.1/test/__init__.pyc and 
new/python-yubico-1.3.2/test/__init__.pyc differ
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/python-yubico-1.3.1/test/soft/__init__.py 
new/python-yubico-1.3.2/test/soft/__init__.py
--- old/python-yubico-1.3.1/test/soft/__init__.py       1970-01-01 
01:00:00.000000000 +0100
+++ new/python-yubico-1.3.2/test/soft/__init__.py       2016-02-23 
12:21:35.000000000 +0100
@@ -0,0 +1,7 @@
+# Copyright (c) 2010, 2011, 2012 Yubico AB
+# See the file COPYING for licence statement.
+
+"""
+Unit tests testing logic of the library.
+These do not require a physical YubiKey to run.
+"""
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/python-yubico-1.3.1/test/soft/test_yubico.py 
new/python-yubico-1.3.2/test/soft/test_yubico.py
--- old/python-yubico-1.3.1/test/soft/test_yubico.py    1970-01-01 
01:00:00.000000000 +0100
+++ new/python-yubico-1.3.2/test/soft/test_yubico.py    2016-02-23 
12:21:35.000000000 +0100
@@ -0,0 +1,49 @@
+#!/usr/bin/env python
+#
+# Simple test cases for a Python version of the yubikey_crc16() function in 
ykcrc.c.
+#
+
+import struct
+import unittest
+import yubico.yubico_util as yubico_util
+from yubico.yubico_util import crc16
+
+CRC_OK_RESIDUAL=0xf0b8
+
+class TestCRC(unittest.TestCase):
+
+    def test_first(self):
+        """ Test CRC16 trivial case """
+        buffer = b'\x01\x02\x03\x04'
+        crc = crc16(buffer)
+        self.assertEqual(crc, 0xc66e)
+        return buffer,crc
+
+    def test_second(self):
+        """ Test CRC16 residual calculation """
+        buffer,crc = self.test_first()
+        # Append 1st complement for a "self-verifying" block -
+        # from example in Yubikey low level interface
+        crc_inv = 0xffff - crc
+        buffer += struct.pack('<H', crc_inv)
+        crc2 = crc16(buffer)
+        self.assertEqual(crc2, CRC_OK_RESIDUAL)
+
+    def test_hexdump(self):
+        """ Test hexdump function, normal use """
+        bytes = b'\x01\x02\x03\x04\x05\x06\x07\x08'
+        self.assertEqual(yubico_util.hexdump(bytes, length=4), \
+                             '0000   01 02 03 04\n0004   05 06 07 08\n')
+
+    def test_hexdump2(self):
+        """ Test hexdump function, with colors """
+        bytes = b'\x01\x02\x03\x04\x05\x06\x07\x08'
+        self.assertEqual(yubico_util.hexdump(bytes, length=4, colorize=True), \
+                             '0000   \x1b[0m01 02 03\x1b[0m 04\n0004   
\x1b[0m05 06 07\x1b[0m 08\n')
+
+    def test_modhex_decode(self):
+        """ Test modhex decoding """
+        self.assertEqual(b"0123456789abcdef", 
yubico_util.modhex_decode(b"cbdefghijklnrtuv"))
+
+if __name__ == '__main__':
+    unittest.main()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/python-yubico-1.3.1/test/soft/test_yubikey_config.py 
new/python-yubico-1.3.2/test/soft/test_yubikey_config.py
--- old/python-yubico-1.3.1/test/soft/test_yubikey_config.py    1970-01-01 
01:00:00.000000000 +0100
+++ new/python-yubico-1.3.2/test/soft/test_yubikey_config.py    2016-02-23 
12:21:35.000000000 +0100
@@ -0,0 +1,307 @@
+#!/usr/bin/env python
+
+import unittest
+import yubico
+import yubico.yubikey_config
+from yubico.yubikey_usb_hid import YubiKeyConfigUSBHID
+import yubico.yubico_util
+import yubico.yubico_exception
+
+class YubiKeyTests(unittest.TestCase):
+
+    def setUp(self):
+        version = (2, 2, 0,)
+        capa = yubico.yubikey_usb_hid.YubiKeyUSBHIDCapabilities( \
+            model = 'YubiKey', version = version, default_answer = False)
+        self.Config = YubiKeyConfigUSBHID(ykver = version, capabilities = capa)
+
+    def test_static_ticket(self):
+        """ Test static ticket """
+
+        #fixed: m:
+        #uid: h:000000000000
+        #key: h:e2bee9a36568a00d026a02f85e61e6fb
+        #acc_code: h:000000000000
+        #ticket_flags: APPEND_CR
+        #config_flags: STATIC_TICKET
+
+        expected = [b'\x00\x00\x00\x00\x00\x00\x00\x80',
+                    b'\x00\xe2\xbe\xe9\xa3\x65\x68\x83',
+                    b'\xa0\x0d\x02\x6a\x02\xf8\x5e\x84',
+                    b'\x61\xe6\xfb\x00\x00\x00\x00\x85',
+                    b'\x00\x00\x00\x00\x20\x20\x00\x86',
+                    b'\x00\x5a\x93\x00\x00\x00\x00\x87',
+                    b'\x00\x01\x95\x56\x00\x00\x00\x89'
+                    ]
+
+        Config = self.Config
+        Config.aes_key(b'h:e2bee9a36568a00d026a02f85e61e6fb')
+        Config.ticket_flag('APPEND_CR', True)
+        Config.config_flag('STATIC_TICKET', True)
+
+        data = Config.to_frame(slot=1).to_feature_reports()
+
+        print("EXPECT:\n%s\nGOT:\n%s\n" %( 
yubico.yubico_util.hexdump(b''.join(expected)),
+                                           
yubico.yubico_util.hexdump(b''.join(data))))
+
+        self.assertEqual(data, expected)
+
+
+    def test_static_ticket_with_access_code(self):
+        """ Test static ticket with unlock code """
+
+        #fixed: m:
+        #uid: h:000000000000
+        #key: h:e2bee9a36568a00d026a02f85e61e6fb
+        #acc_code: h:010203040506
+        #ticket_flags: APPEND_CR
+        #config_flags: STATIC_TICKET
+
+        expected = [b'\x00\x00\x00\x00\x00\x00\x00\x80',
+                    b'\x00\xe2\xbe\xe9\xa3\x65\x68\x83',
+                    b'\xa0\x0d\x02\x6a\x02\xf8\x5e\x84',
+                    b'\x61\xe6\xfb\x01\x02\x03\x04\x85',
+                    b'\x05\x06\x00\x00\x20\x20\x00\x86',
+                    b'\x00\x0d\x39\x01\x02\x03\x04\x87',
+                    b'\x05\x06\x00\x00\x00\x00\x00\x88',
+                    b'\x00\x01\xc2\xfc\x00\x00\x00\x89',
+                    ]
+
+        Config = self.Config
+        Config.aes_key(b'h:e2bee9a36568a00d026a02f85e61e6fb')
+        Config.ticket_flag('APPEND_CR', True)
+        Config.config_flag('STATIC_TICKET', True)
+        Config.unlock_key(b'h:010203040506')
+
+        data = Config.to_frame(slot=1).to_feature_reports()
+
+        print("EXPECT:\n%s\nGOT:\n%s\n" %( 
yubico.yubico_util.hexdump(b''.join(expected)),
+                                           
yubico.yubico_util.hexdump(b''.join(data))))
+
+        self.assertEqual(data, expected)
+
+    def test_fixed_and_oath_hotp(self):
+        """ Test OATH HOTP with a fixed prefix-string """
+
+        #fixed: m:ftftftft
+        #uid: h:000000000000
+        #key: h:523d7ce7e7b6ee853517a3e3cc1985c7
+        #acc_code: h:000000000000
+        #ticket_flags: APPEND_CR|OATH_HOTP
+        #config_flags: OATH_FIXED_MODHEX1|OATH_FIXED_MODHEX2|STATIC_TICKET
+
+        expected = [b'\x4d\x4d\x4d\x4d\x00\x00\x00\x80',
+                    b'\x00\x52\x3d\x7c\xe7\xe7\xb6\x83',
+                    b'\xee\x85\x35\x17\xa3\xe3\xcc\x84',
+                    b'\x19\x85\xc7\x00\x00\x00\x00\x85',
+                    b'\x00\x00\x04\x00\x60\x70\x00\x86',
+                    b'\x00\x72\xad\xaa\xbb\xcc\xdd\x87',
+                    b'\xee\xff\x00\x00\x00\x00\x00\x88',
+                    b'\x00\x03\xfe\xc4\x00\x00\x00\x89',
+                    ]
+
+        Config = self.Config
+        Config.aes_key(b'h:523d7ce7e7b6ee853517a3e3cc1985c7')
+        Config.fixed_string(b'm:ftftftft')
+        Config.ticket_flag('APPEND_CR', True)
+        Config.ticket_flag('OATH_HOTP', True)
+        Config.config_flag('OATH_FIXED_MODHEX1', True)
+        Config.config_flag('OATH_FIXED_MODHEX2', True)
+        Config.config_flag('STATIC_TICKET', True)
+        Config.unlock_key(b'h:aabbccddeeff')
+        Config.access_key(b'h:000000000000')
+
+        data = Config.to_frame(slot=2).to_feature_reports()
+
+        print("EXPECT:\n%s\nGOT:\n%s\n" %( 
yubico.yubico_util.hexdump(b''.join(expected)),
+                                           
yubico.yubico_util.hexdump(b''.join(data))))
+
+        self.assertEqual(data, expected)
+
+    def test_challenge_response_hmac_nist(self):
+        """ Test HMAC challenge response with NIST test vector """
+
+        expected = [b'\x00\x00\x00\x00\x00\x00\x00\x80',
+                    b'\x00\x00\x40\x41\x42\x43\x00\x82',
+                    b'\x00\x30\x31\x32\x33\x34\x35\x83',
+                    b'\x36\x37\x38\x39\x3a\x3b\x3c\x84',
+                    b'\x3d\x3e\x3f\x00\x00\x00\x00\x85',
+                    b'\x00\x00\x00\x04\x40\x26\x00\x86',
+                    b'\x00\x98\x41\x00\x00\x00\x00\x87',
+                    b'\x00\x03\x95\x56\x00\x00\x00\x89',
+                    ]
+
+        Config = self.Config
+        secret = b'h:303132333435363738393a3b3c3d3e3f40414243'
+        Config.mode_challenge_response(secret, type='HMAC', variable=True)
+        Config.extended_flag('SERIAL_API_VISIBLE', True)
+
+        data = Config.to_frame(slot=2).to_feature_reports()
+
+        print("EXPECT:\n%s\nGOT:\n%s\n" %( 
yubico.yubico_util.hexdump(b''.join(expected)),
+                                           
yubico.yubico_util.hexdump(b''.join(data))))
+
+        self.assertEqual(data, expected)
+
+    def test_unknown_ticket_flag(self):
+        """ Test setting unknown ticket flag  """
+        Config = self.Config
+        self.assertRaises(yubico.yubico_exception.InputError, 
Config.ticket_flag, 'YK_UNIT_TEST123', True)
+
+    def test_unknown_ticket_flag_integer(self):
+        """ Test setting unknown ticket flag as integer """
+        future_flag = 0xff
+        Config = self.Config
+        Config.ticket_flag(future_flag, True)
+        self.assertEqual(future_flag, Config.ticket_flags.to_integer())
+
+    def test_too_long_fixed_string(self):
+        """ Test too long fixed string, and set as plain string """
+        Config = self.Config
+        self.assertRaises(yubico.yubico_exception.InputError, 
Config.ticket_flag, 'YK_UNIT_TEST123', True)
+
+    def test_default_flags(self):
+        """ Test that no flags get set by default """
+        Config = self.Config
+        self.assertEqual(0x0, Config.ticket_flags.to_integer())
+        self.assertEqual(0x0, Config.config_flags.to_integer())
+        self.assertEqual(0x0, Config.extended_flags.to_integer())
+
+    def test_oath_hotp_like_windows(self):
+        """ Test plain OATH-HOTP with NIST test vector """
+
+        expected = [b'\x00\x00\x00\x00\x00\x00\x00\x80',
+                    b'\x00\x00\x40\x41\x42\x43\x00\x82',
+                    b'\x00\x30\x31\x32\x33\x34\x35\x83',
+                    b'\x36\x37\x38\x39\x3a\x3b\x3c\x84',
+                    b'\x3d\x3e\x3f\x00\x00\x00\x00\x85',
+                    b'\x00\x00\x00\x00\x40\x00\x00\x86',
+                    b'\x00\x6a\xb9\x00\x00\x00\x00\x87',
+                    b'\x00\x03\x95\x56\x00\x00\x00\x89',
+                    ]
+
+        Config = self.Config
+        secret = b'h:303132333435363738393a3b3c3d3e3f40414243'
+        Config.mode_oath_hotp(secret)
+
+        data = Config.to_frame(slot=2).to_feature_reports()
+
+        print("EXPECT:\n%s\nGOT:\n%s\n" %( 
yubico.yubico_util.hexdump(b''.join(expected)),
+                                           
yubico.yubico_util.hexdump(b''.join(data))))
+
+        self.assertEqual(data, expected)
+
+    def test_oath_hotp_like_windows2(self):
+        """ Test OATH-HOTP with NIST test vector and token identifier """
+
+        expected = [b'\x01\x02\x03\x04\x05\x06\x00\x80',
+                    b'\x00\x00\x40\x41\x42\x43\x00\x82',
+                    b'\x00\x30\x31\x32\x33\x34\x35\x83',
+                    b'\x36\x37\x38\x39\x3a\x3b\x3c\x84',
+                    b'\x3d\x3e\x3f\x00\x00\x00\x00\x85',
+                    b'\x00\x00\x06\x00\x40\x42\x00\x86',
+                    b'\x00\x0e\xec\x00\x00\x00\x00\x87',
+                    b'\x00\x03\x95\x56\x00\x00\x00\x89',
+                    ]
+
+        Config = self.Config
+        secret = b'h:303132333435363738393a3b3c3d3e3f40414243'
+        Config.mode_oath_hotp(secret, digits=8, factor_seed='', omp=0x01, 
tt=0x02, mui=b'\x03\x04\x05\x06')
+        Config.config_flag('OATH_FIXED_MODHEX2', True)
+
+        data = Config.to_frame(slot=2).to_feature_reports()
+
+        print("EXPECT:\n%s\nGOT:\n%s\n" %( 
yubico.yubico_util.hexdump(b''.join(expected)),
+                                           
yubico.yubico_util.hexdump(b''.join(data))))
+
+        self.assertEqual(data, expected)
+
+    def test_oath_hotp_like_windows_factory_seed(self):
+        """ Test OATH-HOTP factor_seed """
+
+        expected = [b'\x01\x02\x03\x04\x05\x06\x00\x80',
+                    b'\x00\x00\x40\x41\x42\x43\x01\x82',
+                    b'\x21\x30\x31\x32\x33\x34\x35\x83',
+                    b'\x36\x37\x38\x39\x3a\x3b\x3c\x84',
+                    b'\x3d\x3e\x3f\x00\x00\x00\x00\x85',
+                    b'\x00\x00\x06\x00\x40\x42\x00\x86',
+                    b'\x00\x03\xea\x00\x00\x00\x00\x87',
+                    b'\x00\x03\x95\x56\x00\x00\x00\x89',
+                    ]
+
+        Config = self.Config
+        secret = b'h:303132333435363738393a3b3c3d3e3f40414243'
+        Config.mode_oath_hotp(secret, digits=8, factor_seed=0x2101, omp=0x01, 
tt=0x02, mui=b'\x03\x04\x05\x06')
+        Config.config_flag('OATH_FIXED_MODHEX2', True)
+
+        data = Config.to_frame(slot=2).to_feature_reports()
+
+        print("EXPECT:\n%s\nGOT:\n%s\n" %( 
yubico.yubico_util.hexdump(b''.join(expected)),
+                                           
yubico.yubico_util.hexdump(b''.join(data))))
+
+        self.assertEqual(data, expected)
+
+    def test_fixed_length_hmac_like_windows(self):
+        """ Test fixed length HMAC SHA1 """
+
+        expected = [b'\x00\x00\x00\x00\x00\x00\x00\x80',
+                    b'\x00\x00\x40\x41\x42\x43\x00\x82',
+                    b'\x00\x30\x31\x32\x33\x34\x35\x83',
+                    b'\x36\x37\x38\x39\x3a\x3b\x3c\x84',
+                    b'\x3d\x3e\x3f\x00\x00\x00\x00\x85',
+                    b'\x00\x00\x00\x00\x40\x22\x00\x86',
+                    b'\x00\xe9\x0f\x00\x00\x00\x00\x87',
+                    b'\x00\x03\x95\x56\x00\x00\x00\x89',
+                    ]
+
+        Config = self.Config
+        secret = b'h:303132333435363738393a3b3c3d3e3f40414243'
+        Config.mode_challenge_response(secret, type='HMAC', variable=False)
+
+        data = Config.to_frame(slot=2).to_feature_reports()
+
+        print("EXPECT:\n%s\nGOT:\n%s\n" %( 
yubico.yubico_util.hexdump(b''.join(expected)),
+                                           
yubico.yubico_util.hexdump(b''.join(data))))
+
+        self.assertEqual(data, expected)
+
+    def test_version_required_1(self):
+        """ Test YubiKey 1 with v2 option """
+        version = (1, 3, 0,)
+        capa = yubico.yubikey_usb_hid.YubiKeyUSBHIDCapabilities( \
+            model = 'YubiKey', version = version, default_answer = False)
+        Config = YubiKeyConfigUSBHID(ykver = version, capabilities = capa)
+        self.assertRaises(yubico.yubikey.YubiKeyVersionError, 
Config.config_flag, 'SHORT_TICKET', True)
+
+    def test_version_required_2(self):
+        """ Test YubiKey 2 with v2 option """
+
+        Config = self.Config
+        Config.config_flag('SHORT_TICKET', True)
+        self.assertEqual((2, 0), Config.version_required())
+
+    def test_version_required_3(self):
+        """ Test YubiKey 2 with v1 option """
+
+        Config = self.Config
+        self.assertRaises(yubico.yubikey.YubiKeyVersionError, 
Config.config_flag, 'TICKET_FIRST', True)
+
+    def test_version_required_4(self):
+        """ Test YubiKey 2.1 with v2.2 mode """
+        version = (2, 1, 0,)
+        capa = yubico.yubikey_usb_hid.YubiKeyUSBHIDCapabilities( \
+            model = 'YubiKey', version = version, default_answer = False)
+        Config = YubiKeyConfigUSBHID(ykver = version, capabilities = capa)
+        secret = b'h:303132333435363738393a3b3c3d3e3f40414243'
+        self.assertRaises(yubico.yubikey.YubiKeyVersionError, 
Config.mode_challenge_response, secret)
+
+    def test_version_required_5(self):
+        """ Test YubiKey 2.2 with v2.2 mode """
+
+        Config = self.Config
+        secret = b'h:303132333435363738393a3b3c3d3e3f'
+        Config.mode_challenge_response(secret, type='OTP')
+        self.assertEqual('CHAL_RESP', Config._mode)
+
+if __name__ == '__main__':
+    unittest.main()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/python-yubico-1.3.1/test/soft/test_yubikey_frame.py 
new/python-yubico-1.3.2/test/soft/test_yubikey_frame.py
--- old/python-yubico-1.3.1/test/soft/test_yubikey_frame.py     1970-01-01 
01:00:00.000000000 +0100
+++ new/python-yubico-1.3.2/test/soft/test_yubikey_frame.py     2016-02-23 
12:21:35.000000000 +0100
@@ -0,0 +1,58 @@
+#!/usr/bin/env python
+
+from yubico import *
+from yubico.yubikey_frame import *
+import yubico.yubico_exception
+import unittest
+import struct
+import re
+
+class YubiKeyTests(unittest.TestCase):
+
+  def test_get_ykframe(self):
+    """ Test normal use """
+    buffer = YubiKeyFrame(command=0x01).to_string()
+
+    # check number of bytes returned
+    self.assertEqual(len(buffer), 70, "yubikey command buffer should always be 
70 bytes")
+
+    # check that empty payload works (64 * '\x00')
+    all_zeros = b'\x00' * 64
+
+    self.assertTrue(buffer.startswith(all_zeros))
+
+
+  def test_get_ykframe_feature_reports(self):
+    """ Test normal use """
+    res = YubiKeyFrame(command=0x32).to_feature_reports()
+
+    self.assertEqual(res, [b'\x00\x00\x00\x00\x00\x00\x00\x80',
+                           b'\x00\x32\x6b\x5b\x00\x00\x00\x89'
+                           ])
+
+
+  def test_get_ykframe_feature_reports2(self):
+    """ Test one serie of non-zero bytes in the middle of the payload """
+    payload = b'\x00' * 38
+    payload += b'\x01\x02\x03'
+    payload += b'\x00' * 23
+    res = YubiKeyFrame(command=0x32, payload=payload).to_feature_reports()
+
+    self.assertEqual(res, [b'\x00\x00\x00\x00\x00\x00\x00\x80',
+                           b'\x00\x00\x00\x01\x02\x03\x00\x85',
+                           b'\x002\x01s\x00\x00\x00\x89'])
+
+  def test_bad_payload(self):
+    """ Test that we get an exception for four bytes payload """
+    self.assertRaises(yubico_exception.InputError, YubiKeyFrame, command=0x32, 
payload=b'test')
+
+  def test_repr(self):
+    """ Test string representation of object """
+    # to achieve 100% test coverage ;)
+    frame = YubiKeyFrame(command=0x4d)
+    print("Frame is represented as %s" % frame)
+    re_match = re.search("YubiKeyFrame instance at .*: 77.$", str(frame))
+    self.assertNotEqual(re_match, None)
+
+if __name__ == '__main__':
+    unittest.main()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/python-yubico-1.3.1/test/usb/__init__.py 
new/python-yubico-1.3.2/test/usb/__init__.py
--- old/python-yubico-1.3.1/test/usb/__init__.py        1970-01-01 
01:00:00.000000000 +0100
+++ new/python-yubico-1.3.2/test/usb/__init__.py        2016-02-23 
12:21:35.000000000 +0100
@@ -0,0 +1,7 @@
+# Copyright (c) 2010, 2011, 2012 Yubico AB
+# See the file COPYING for licence statement.
+
+"""
+Tests that run against a physical YubiKey.
+These tests require an attached YubiKey that has been correctly configured.
+"""
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/python-yubico-1.3.1/test/usb/test_yubikey_usb_hid.py 
new/python-yubico-1.3.2/test/usb/test_yubikey_usb_hid.py
--- old/python-yubico-1.3.1/test/usb/test_yubikey_usb_hid.py    1970-01-01 
01:00:00.000000000 +0100
+++ new/python-yubico-1.3.2/test/usb/test_yubikey_usb_hid.py    2016-02-23 
12:21:35.000000000 +0100
@@ -0,0 +1,56 @@
+#!/usr/bin/env python
+#
+# Test cases for talking to a USB HID YubiKey.
+#
+
+import struct
+import unittest
+import yubico
+import yubico.yubikey_usb_hid
+from yubico.yubikey_usb_hid import *
+import re
+
+class TestYubiKeyUSBHID(unittest.TestCase):
+
+    YK = None
+
+    def setUp(self):
+        """ Test connecting to the YubiKey """
+        if self.YK is None:
+            try:
+                print("open key")
+                self.YK = YubiKeyUSBHID()
+                return
+            except YubiKeyUSBHIDError as err:
+                self.fail("No YubiKey connected (?) : %s" % str(err))
+
+    def tearDown(self):
+        if self.YK is not None:
+            del self.YK
+
+    #@unittest.skipIf(YK is None, "No USB HID YubiKey found")
+    def test_status(self):
+        """ Test the simplest form of communication : a status read request """
+        status = self.YK.status()
+        version = self.YK.version()
+        print("Version returned: %s" % version)
+        re_match = re.match("\d+\.\d+\.\d+$", version)
+        self.assertNotEqual(re_match, None)
+
+    #@unittest.skipIf(self.YK is None, "No USB HID YubiKey found")
+    def test_challenge_response(self):
+        """ Test challenge-response, assumes a NIST PUB 198 A.2 20 bytes test 
vector in Slot 2 (variable input) """
+
+        secret = struct.pack('64s', b'Sample #2')
+        response = self.YK.challenge_response(secret, mode='HMAC', slot=2)
+        self.assertEqual(response, 
b'\x09\x22\xd3\x40\x5f\xaa\x3d\x19\x4f\x82\xa4\x58\x30\x73\x7d\x5c\xc6\xc7\x5d\x24')
+
+    #@unittest.skipIf(self.YK is None, "No USB HID YubiKey found")
+    def test_serial(self):
+        """ Test serial number retrieval (requires YubiKey 2) """
+        serial = self.YK.serial()
+        print("Serial returned : %s" % serial)
+        self.assertEqual(type(serial), type(1))
+
+if __name__ == '__main__':
+    unittest.main()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/python-yubico-1.3.1/yubico/yubico_version.py 
new/python-yubico-1.3.2/yubico/yubico_version.py
--- old/python-yubico-1.3.1/yubico/yubico_version.py    2015-10-01 
15:58:55.000000000 +0200
+++ new/python-yubico-1.3.2/yubico/yubico_version.py    2016-02-23 
12:21:35.000000000 +0100
@@ -1 +1 @@
-__version__ = "1.3.1"
+__version__ = "1.3.2"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/python-yubico-1.3.1/yubico/yubikey_frame.py 
new/python-yubico-1.3.2/yubico/yubikey_frame.py
--- old/python-yubico-1.3.1/yubico/yubikey_frame.py     2015-09-09 
17:12:31.000000000 +0200
+++ new/python-yubico-1.3.2/yubico/yubikey_frame.py     2016-02-23 
12:21:35.000000000 +0100
@@ -103,25 +103,32 @@
             SLOT.UPDATE2,
             SLOT.SWAP,
         ]:
-            # annotate according to config_st (see yubikey_defs.to_string())
+            # annotate according to config_st (see ykdef.h)
             if yubico_util.ord_byte(data[-1]) == 0x80:
-                return (data, "FFFFFFF")
+                return (data, "FFFFFFF")  # F = Fixed data (16 bytes)
             if yubico_util.ord_byte(data[-1]) == 0x81:
                 return (data, "FFFFFFF")
             if yubico_util.ord_byte(data[-1]) == 0x82:
-                return (data, "FFUUUUU")
+                return (data, "FFUUUUU")  # U = UID (6 bytes)
             if yubico_util.ord_byte(data[-1]) == 0x83:
-                return (data, "UKKKKKK")
+                return (data, "UKKKKKK")  # K = Key (16 bytes)
             if yubico_util.ord_byte(data[-1]) == 0x84:
                 return (data, "KKKKKKK")
             if yubico_util.ord_byte(data[-1]) == 0x85:
-                return (data, "KKKAAAA")
+                return (data, "KKKAAAA")  # A = Access code to set (6 bytes)
             if yubico_util.ord_byte(data[-1]) == 0x86:
-                return (data, "AAlETCr")
+                return (data, "AAlETCr")  # l = Length of fixed field (1 byte)
+                                          # E = extFlags (1 byte)
+                                          # T = tktFlags (1 byte)
+                                          # C = cfgFlags (1 byte)
+                                          # r = RFU (2 bytes)
             if yubico_util.ord_byte(data[-1]) == 0x87:
-                return (data, "rCR")
+                return (data, "rCRaaaa")  # CR = CRC16 checksum (2 bytes)
+                                          # a = Access code to use (6 bytes)
+            if yubico_util.ord_byte(data[-1]) == 0x88:
+                return (data, 'aa')
             # after payload
             if yubico_util.ord_byte(data[-1]) == 0x89:
                 return (data, " Scr")
-        else:
-            return (data, '')
+
+        return (data, '')
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/python-yubico-1.3.1/yubico/yubikey_usb_hid.py 
new/python-yubico-1.3.2/yubico/yubikey_usb_hid.py
--- old/python-yubico-1.3.1/yubico/yubikey_usb_hid.py   2015-09-30 
12:53:22.000000000 +0200
+++ new/python-yubico-1.3.2/yubico/yubikey_usb_hid.py   2016-02-23 
12:21:35.000000000 +0100
@@ -151,10 +151,10 @@
         self.status()
         self._debug("Programmed slot %i, sequence %i -> %i\n" % (slot, 
old_pgm_seq, self._status.pgm_seq))
 
-        if slot in [SLOT.CONFIG, SLOT.CONFIG2] or old_pgm_seq != 0:
-            if self._status.pgm_seq == old_pgm_seq + 1:
-                return
-        elif self._status.pgm_seq == 1:
+        cfgs = self._status.valid_configs()
+        if not cfgs and self._status.pgm_seq == 0:
+            return
+        if self._status.pgm_seq == old_pgm_seq + 1:
             return
 
         raise YubiKeyUSBHIDError('YubiKey programming failed (seq %i not 
increased (%i))' % \


Reply via email to