Esempio n. 1
0
    def _piv_ensure_authenticated(self, session, pin=None,
                                  mgm_key_hex=None):
        pivman = get_pivman_data(session)

        try:
            key_type = session.get_management_key_metadata().key_type
        except NotSupportedError:
            key_type = MANAGEMENT_KEY_TYPE.TDES

        if pivman.has_protected_key:
            return self._piv_verify_pin(session, pin)
        else:
            if mgm_key_hex:

                try:
                    mgm_key_bytes = a2b_hex(mgm_key_hex)
                except Exception:
                    return failure('mgm_key_bad_format')

                try:
                    with PromptTimeout():
                        session.authenticate(
                            key_type, mgm_key_bytes
                        )
                except ApduError as e:
                    if (e.sw == SW.SECURITY_CONDITION_NOT_SATISFIED):
                        return failure('wrong_mgm_key')
                    raise


            else:
                return failure('mgm_key_required')
Esempio n. 2
0
    def piv_change_mgm_key(self, pin, current_key_hex, new_key_hex, key_type,
                           store_on_device=False):
        with self._open_device([SmartCardConnection]) as conn:
            session = PivSession(conn)

            pivman = get_pivman_data(session)

            if pivman.has_protected_key or store_on_device:
                pin_failed = self._piv_verify_pin(
                    session, pin=pin)
                if pin_failed:
                    return pin_failed
            with PromptTimeout():

                auth_failed = self._piv_ensure_authenticated(
                    session, pin=pin, mgm_key_hex=current_key_hex)
            if auth_failed:
                return auth_failed

            try:

                new_key = a2b_hex(new_key_hex) if new_key_hex else None
            except Exception as e:
                logger.debug('Failed to parse new management key', exc_info=e)
                return failure('new_mgm_key_bad_hex')

            if new_key is not None and len(new_key) != MANAGEMENT_KEY_TYPE(key_type).key_len:
                logger.debug('Wrong length for new management key: %d',
                             len(new_key))
                return failure('new_mgm_key_bad_length')

            pivman_set_mgm_key(
                        session, new_key, MANAGEMENT_KEY_TYPE(key_type), touch=False, store_on_device=store_on_device
                    )
            return success()
Esempio n. 3
0
    def _piv_verify_pin(self, session, pin=None):
        if pin:
            try:
                pivman = get_pivman_data(session)
                session.verify_pin(pin)

                try:
                    key_type = session.get_management_key_metadata().key_type
                except NotSupportedError:
                    key_type = MANAGEMENT_KEY_TYPE.TDES

                if pivman.has_derived_key:
                    with PromptTimeout():
                        session.authenticate(
                            key_type, derive_management_key(pin, pivman.salt)
                        )
                    session.verify_pin(pin)
                elif pivman.has_stored_key:
                    pivman_prot = get_pivman_protected_data(session)
                    with PromptTimeout():
                        session.authenticate(key_type, pivman_prot.key)
                    session.verify_pin(pin)
            except InvalidPinError as e:
                attempts = e.attempts_remaining
                if attempts:
                    logger.debug("Failed to verify PIN, %d tries left", attempts, exc_info=e)
                    return failure('wrong_pin', {'tries_left': attempts})
                else:
                    logger.debug("PIN is blocked.", exc_info=e)
                    return failure('pin_blocked')

        else:
            return failure('pin_required')
Esempio n. 4
0
    def refresh_piv(self):
        with self._open_device([SmartCardConnection]) as conn:
            session = PivSession(conn)
            pivman = get_pivman_data(session)

            try:
                key_type = session.get_management_key_metadata().key_type
            except NotSupportedError:
                key_type = MANAGEMENT_KEY_TYPE.TDES

            return success({
                'piv_data': {
                    'certs':
                    self._piv_list_certificates(session),
                    'has_derived_key':
                    pivman.has_derived_key,
                    'has_protected_key':
                    pivman.has_protected_key,
                    'has_stored_key':
                    pivman.has_stored_key,
                    'pin_tries':
                    session.get_pin_attempts(),
                    'puk_blocked':
                    pivman.puk_blocked,
                    'supported_algorithms':
                    _supported_algorithms(
                        self._dev_info['version'].split('.')),
                    'key_type':
                    key_type,
                },
            })
Esempio n. 5
0
    def test_reset_resets_has_stored_key_flag(self, session):
        pivman = get_pivman_data(session)
        assert not pivman.has_stored_key

        session.verify_pin(DEFAULT_PIN)
        session.authenticate(MANAGEMENT_KEY_TYPE.TDES, DEFAULT_MANAGEMENT_KEY)
        pivman_set_mgm_key(
            session,
            NON_DEFAULT_MANAGEMENT_KEY,
            MANAGEMENT_KEY_TYPE.TDES,
            store_on_device=True,
        )

        pivman = get_pivman_data(session)
        assert pivman.has_stored_key

        reset_state(session)
        session.reset()

        pivman = get_pivman_data(session)
        assert not pivman.has_stored_key