class PivTestCase(DestructiveYubikeyTestCase): def setUp(self): self.dev = open_device(transports=TRANSPORT.CCID) self.controller = PivController(self.dev.driver) def tearDown(self): self.dev.driver.close() def assertMgmKeyIs(self, key): self.controller.authenticate(key) def assertMgmKeyIsNot(self, key): with self.assertRaises(AuthenticationFailed): self.controller.authenticate(key) def assertStoredMgmKeyEquals(self, key): self.assertEqual(self.controller._pivman_protected_data.key, key) def assertStoredMgmKeyNotEquals(self, key): self.assertNotEqual(self.controller._pivman_protected_data.key, key) def reconnect(self): self.dev.driver.close() self.dev = open_device(transports=TRANSPORT.CCID) self.controller = PivController(self.dev.driver)
class PivTestCase(unittest.TestCase): def setUp(self): self.conn = open_device()[0] self.controller = PivController(PivSession(self.conn)) def tearDown(self): self.conn.close() def assertMgmKeyIs(self, key): self.controller.authenticate(key) def assertMgmKeyIsNot(self, key): with self.assertRaises(ApduError): self.controller.authenticate(key) def assertStoredMgmKeyEquals(self, key): self.assertEqual(self.controller._pivman_protected_data.key, key) def assertStoredMgmKeyNotEquals(self, key): self.assertNotEqual(self.controller._pivman_protected_data.key, key) def reconnect(self): self.conn.close() self.conn = open_device()[0] self.controller = PivController(PivSession(self.conn))
def authenticate(yubikey: YubiKey, prompt_management_key: bool, cache_lifetime=CachedItem.DEFAULT_LIFETIME_SEC, stream=sys.stderr): """ Authenticates user to the YubiKey """ global _CACHED_PIN, _CACHED_MGMT_KEY # pylint: disable=global-statement _log('Authenticating to the YubiKey...', stream) pin = _CACHED_PIN.value if _CACHED_PIN.expired(): pin = getpass('Enter PIN: ', stream) _CACHED_PIN = CachedItem(None, pin, cache_lifetime) yubikey.verify(pin, touch_callback=prompt_for_touch) mgmt_key = _CACHED_MGMT_KEY.value if not prompt_management_key: mgmt_key = DEFAULT_MANAGEMENT_KEY elif _CACHED_MGMT_KEY.expired(): mgmt_key = getpass('Enter management key: ', stream) _CACHED_MGMT_KEY = CachedItem(None, mgmt_key, cache_lifetime) yubikey.authenticate(mgmt_key, touch_callback=prompt_for_touch) _log('Authenticated', stream)
class ManagementKeyReadOnly(PivTestCase): """ Tests after which the management key is always the default management key. Placing compatible tests here reduces the amount of slow reset calls needed. """ @classmethod def setUpClass(cls): dev = open_device(transports=TRANSPORT.CCID) controller = PivController(dev.driver) controller.reset() def setUp(self): self.dev = open_device(transports=TRANSPORT.CCID) self.controller = PivController(self.dev.driver) def test_authenticate_twice_does_not_throw(self): self.controller.authenticate(a2b_hex(DEFAULT_MANAGEMENT_KEY)) self.controller.authenticate(a2b_hex(DEFAULT_MANAGEMENT_KEY)) def test_reset_resets_has_stored_key_flag(self): self.assertFalse(self.controller.has_stored_key) self.controller.verify(DEFAULT_PIN) self.controller.authenticate(a2b_hex(DEFAULT_MANAGEMENT_KEY)) self.controller.set_mgm_key(None, store_on_device=True) self.assertTrue(self.controller.has_stored_key) self.reconnect() self.controller.reset() self.assertFalse(self.controller.has_stored_key) def test_reset_while_verified_throws_nice_ValueError(self): self.controller.verify(DEFAULT_PIN) with self.assertRaisesRegex(ValueError, '^Failed reading remaining'): self.controller.reset() def test_set_mgm_key_does_not_change_key_if_not_authenticated(self): with self.assertRaises(APDUError): self.controller.set_mgm_key(a2b_hex(NON_DEFAULT_MANAGEMENT_KEY)) self.assertMgmKeyIs(DEFAULT_MANAGEMENT_KEY) def test_set_stored_mgm_key_does_not_destroy_key_if_pin_not_verified(self): self.controller.authenticate(a2b_hex(DEFAULT_MANAGEMENT_KEY)) with self.assertRaises(APDUError): self.controller.set_mgm_key(None, store_on_device=True) self.assertMgmKeyIs(DEFAULT_MANAGEMENT_KEY)
class ManagementKeyReadWrite(PivTestCase): """ Tests after which the management key may not be the default management key. """ def setUp(self): self.dev = open_device(transports=TRANSPORT.CCID) self.controller = PivController(self.dev.driver) self.controller.reset() def test_set_mgm_key_changes_mgm_key(self): self.controller.authenticate(a2b_hex(DEFAULT_MANAGEMENT_KEY)) self.controller.set_mgm_key(a2b_hex(NON_DEFAULT_MANAGEMENT_KEY)) self.assertMgmKeyIsNot(DEFAULT_MANAGEMENT_KEY) self.assertMgmKeyIs(NON_DEFAULT_MANAGEMENT_KEY) def test_set_stored_mgm_key_succeeds_if_pin_is_verified(self): self.controller.verify(DEFAULT_PIN) self.controller.authenticate(a2b_hex(DEFAULT_MANAGEMENT_KEY)) self.controller.set_mgm_key(a2b_hex(NON_DEFAULT_MANAGEMENT_KEY), store_on_device=True) self.assertMgmKeyIsNot(DEFAULT_MANAGEMENT_KEY) self.assertMgmKeyIs(NON_DEFAULT_MANAGEMENT_KEY) self.assertStoredMgmKeyEquals(NON_DEFAULT_MANAGEMENT_KEY) self.assertMgmKeyIs(self.controller._pivman_protected_data.key) def test_set_stored_random_mgm_key_succeeds_if_pin_is_verified(self): self.controller.verify(DEFAULT_PIN) self.controller.authenticate(a2b_hex(DEFAULT_MANAGEMENT_KEY)) self.controller.set_mgm_key(None, store_on_device=True) self.assertMgmKeyIsNot(DEFAULT_MANAGEMENT_KEY) self.assertMgmKeyIsNot(NON_DEFAULT_MANAGEMENT_KEY) self.assertMgmKeyIs(self.controller._pivman_protected_data.key) self.assertStoredMgmKeyNotEquals(DEFAULT_MANAGEMENT_KEY) self.assertStoredMgmKeyNotEquals(NON_DEFAULT_MANAGEMENT_KEY)