Exemplo n.º 1
0
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)
Exemplo n.º 2
0
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)
Exemplo n.º 3
0
    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))
Exemplo n.º 4
0
    def piv_reset(self):
        try:
            with self._open_device(TRANSPORT.CCID) as dev:
                controller = PivController(dev.driver)
                controller.reset()
                return True

        except Exception as e:
            logger.error('Failed to reset PIV applet', exc_info=e)
            return False
Exemplo n.º 5
0
def _get_jwt(yubikey: YubiKey, slot: int, prompt_management_key: bool,
             service_account_email: str, audience: str, scopes: List[str],
             token_lifetime: int, cache_lifetime: int, stream=sys.stderr):
    """ Generates a general-purpose Google JWT with a YubiKey """
    authenticate(yubikey, prompt_management_key, cache_lifetime, stream)

    iat = time()
    header = {
        'typ': 'JWT',
        'alg': 'RS256',
    }
    payload = {
        'iss': service_account_email,
        'aud': audience,
        'iat': iat,
        'exp': iat + token_lifetime,
    }
    if scopes:
        payload['scope'] = ' '.join(scopes)

    msg = f'{_json_b64encode(header)}.{_json_b64encode(payload)}'
    sig = yubikey.sign(slot, _KEY_ALG, msg.encode('utf-8'))
    sig = _b64encode_str(sig)

    return f'{msg}.{sig}'
Exemplo n.º 6
0
def gen_private_key(yubikey: YubiKey, slot: SLOT, prompt_management_key: bool,
                    pin_policy: PIN_POLICY, touch_policy: TOUCH_POLICY,
                    subject: str, valid_days: int):
    """ Generates a private key and certificate on the YubiKey """
    authenticate(yubikey, prompt_management_key)

    _log('Generating private key on YubiKey...')
    public_key = yubikey.generate_key(
        slot.value, _KEY_ALG, pin_policy.value, touch_policy.value,
    )

    _log('Generating certificate on YubiKey...')
    start = datetime.now()
    end = start + timedelta(days=valid_days)
    yubikey.generate_self_signed_certificate(
        slot.value, public_key, subject, start, end,
        touch_callback=prompt_for_touch,
    )
    return get_public_key(yubikey, slot)
Exemplo n.º 7
0
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)
Exemplo n.º 8
0
 def reconnect(self):
     self.dev.driver.close()
     self.dev = open_device()
     self.controller = PivController(self.dev.driver)
Exemplo n.º 9
0
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)
Exemplo n.º 10
0
 def setUpClass(cls):
     dev = open_device(transports=TRANSPORT.CCID)
     controller = PivController(dev.driver)
     controller.reset()
Exemplo n.º 11
0
 def reconnect(self):
     self.dev.driver.close()
     self.dev = open_device(transports=TRANSPORT.CCID)
     self.controller = PivController(self.dev.driver)
Exemplo n.º 12
0
 def setUpClass(cls):
     with open_device(transports=TRANSPORT.CCID) as dev:
         controller = PivController(dev.driver)
         controller.reset()
Exemplo n.º 13
0
def get_public_key(yubikey: YubiKey, slot: SLOT):
    """ Reads public key from YubiKey """
    cert = yubikey.read_certificate(slot.value)
    return cert.public_bytes(serialization.Encoding.PEM)
Exemplo n.º 14
0
 def setUpClass(cls):
     with open_device() as dev:
         controller = PivController(dev.driver)
         controller.reset()
Exemplo n.º 15
0
 def setUp(self):
     self.dev = open_device(transports=TRANSPORT.CCID)
     self.controller = PivController(self.dev.driver)
Exemplo n.º 16
0
 def reconnect(self):
     self.dev.driver.close()
     self.dev = open_device(transports=TRANSPORT.CCID)
     self.controller = PivController(self.dev.driver)
Exemplo n.º 17
0
 def setUp(self):
     self.conn = open_device()[0]
     self.controller = PivController(PivSession(self.conn))
Exemplo n.º 18
0
def _yk_piv_ctrl():
    yk = open_device(transports=TRANSPORT.CCID)
    yield PivController(yk.driver)
    yk.close()
Exemplo n.º 19
0
 def reconnect(self):
     self.conn.close()
     self.conn = open_device()[0]
     self.controller = PivController(PivSession(self.conn))
Exemplo n.º 20
0
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)
Exemplo n.º 21
0
 def setUpClass(cls):
     with open_device()[0] as conn:
         controller = PivController(PivSession(conn))
         controller.reset()
Exemplo n.º 22
0
 def setUp(self):
     self.dev = open_device(transports=TRANSPORT.CCID)
     self.controller = PivController(self.dev.driver)
Exemplo n.º 23
0
 def setUpClass(cls):
     with open_device(transports=TRANSPORT.CCID) as dev:
         PivController(dev.driver).reset()
Exemplo n.º 24
0
 def __enter__(self):
     return PivController(self._dev.driver)
Exemplo n.º 25
0
 def setUp(self):
     self.dev = open_device()
     self.controller = PivController(self.dev.driver)