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')
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()
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')
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, }, })
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