def _unlock(self, pin): """ Unlock the keystore, raises PinError if PIN is invalid. Raises CriticalErrorWipeImmediately if no attempts left. """ # if anything goes wrong here - wipe try: # decrease the counter self._pin_attempts_left -= 1 self.save_state() # check we have attempts if self._pin_attempts_left <= 0: self.wipe(self.path) raise CriticalErrorWipeImmediately( "No more PIN attempts!\nWipe!") except Exception as e: # convert any error to a critical error to wipe the device raise CriticalErrorWipeImmediately(str(e)) # calculate hmac with entered PIN key = tagged_hash("pin", self.secret) pin_hmac = hmac.new(key=key, msg=pin.encode(), digestmod="sha256").digest() # check hmac is the same if pin_hmac != self.pin: raise PinError("Invalid PIN!\n%d of %d attempts left..." % (self._pin_attempts_left, self._pin_attempts_max)) self._pin_attempts_left = self._pin_attempts_max self._is_locked = False self.save_state() # derive PIN keys for reckless storage self.pin_secret = tagged_hash("pin", self.secret + pin.encode()) self.load_enc_secret()
def load_state(self): """Verify file and load PIN state from it""" try: # verify that the pin file is ok _, data = self.load_aead(self.path + "/pin", self.secret) # load pin object data = json.loads(data.decode()) self.pin = unhexlify( data["pin"]) if data["pin"] is not None else None self._pin_attempts_max = data["pin_attempts_max"] self._pin_attempts_left = data["pin_attempts_left"] except Exception as e: self.wipe(self.path) sys.print_exception(e) raise CriticalErrorWipeImmediately( "Something went terribly wrong!\nDevice is wiped!\n%s" % e)
def _unlock(self, pin): """ Unlock the keystore, raises PinError if PIN is invalid. Raises CriticalErrorWipeImmediately if no attempts left. """ try: self.applet.unlock(pin) except SecureError as e: if str(e) == "0502": # wrong PIN raise PinError("Invalid PIN!\n%d of %d attempts left..." % (self.pin_attempts_left, self.pin_attempts_max)) elif str(e) == "0503": # bricked # wipe is happening automatically on this exception raise CriticalErrorWipeImmediately( "No more PIN attempts!\nWipe!") else: raise e self.check_saved()
def _unlock(self, pin): """ Unlock the keystore, raises PinError if PIN is invalid. Raises CriticalErrorWipeImmediately if no attempts left. """ try: self.applet.unlock(pin) except SecureError as e: if str(e) == "0502": # wrong PIN raise PinError("Invalid PIN!\n%d of %d attempts left..." % (self.pin_attempts_left, self.pin_attempts_max)) elif str(e) == "0503": # bricked self.wipe(self.path) raise CriticalErrorWipeImmediately( "No more PIN attempts!\nWipe!") else: raise e self.load_enc_secret()
def load_state(self): """Verify file and load PIN state from it""" # If PIN file doesn't exist - create it # This can happen if the device was initialized with the smartcard if not platform.file_exists(self.path + "/pin"): self.create_empty_pin_file() return try: # verify that the pin file is ok _, data = self.load_aead(self.path + "/pin", self.secret) # load pin object data = json.loads(data.decode()) self.pin = unhexlify( data["pin"]) if data["pin"] is not None else None self._pin_attempts_max = data["pin_attempts_max"] self._pin_attempts_left = data["pin_attempts_left"] except Exception as e: # this happens if someone tries to change PIN file self.wipe(self.path) raise CriticalErrorWipeImmediately( "Something went terribly wrong!\nDevice is wiped!\n%s" % e)
def _unlock(self, pin): """ Implement this. Unlock the keystore, raises PinError if PIN is invalid. Raises CriticalErrorWipeImmediately if no attempts left. """ # check we have attempts if self.pin_attempts_left <= 0: # wipe is happening automatically on this error raise CriticalErrorWipeImmediately("No more PIN attempts!\nWipe!") # check PIN code somehow, raise PinError if it's incorrect # for reference - first decrease PIN counter, then check PIN # raise PIN Error if it's invalid like this: # if pin == "INVALID PIN": # raise PinError("Invalid PIN!\n%d of %d attempts left..." % ( # self._pin_attempts_left, self._pin_attempts_max) # ) # reset PIN counter here and unlock # set encryption secret somehow mb save it # don't use this approach, it's just for reference self.enc_secret = tagged_hash("enc", self.secret)