Skip to content

Commit

Permalink
Merge pull request #538 from Foundation-Devices/SFT-3903-clear-passph…
Browse files Browse the repository at this point in the history
…rase-when-clearing-temporary-seed

SFT-3903: fixed passphrase and temporary seed interactions
  • Loading branch information
mjg-foundation committed Aug 7, 2024
2 parents dce2ec5 + 8dc6dae commit 620cc2b
Show file tree
Hide file tree
Showing 11 changed files with 56 additions and 32 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ def __init__(self, passphrase=None):

# Caller wants to set this passphrase
self.attempted = False
self.prev_passphrase = stash.bip39_passphrase
self.prev_passphrase = stash.get_passphrase()
self.passphrase = passphrase
self.msg = 'Apply'
if self.passphrase is not None:
Expand Down
5 changes: 2 additions & 3 deletions ports/stm32/boards/Passport/modules/flows/backup_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,7 @@ def __init__(self, initial_backup=False, left_micron=microns.Back):

async def show_intro(self):
from pages import InfoPage
from utils import recolor
import stash
from utils import recolor, is_passphrase_active

if self.backup_quiz_passed:
msgs = ['Passport is about to create an updated microSD backup.',
Expand All @@ -37,7 +36,7 @@ async def show_intro(self):
recolor(HIGHLIGHT_TEXT_HEX, 'REQUIRED')),
'We recommend writing down the Backup Code on the included security card.',
'We consider this safe since physical access to the microSD card is required to access the backup.']
if stash.bip39_passphrase != '':
if is_passphrase_active():
msgs.append('The current passphrase applied to Passport will not be saved as part of this backup.')

result = await InfoPage(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,10 @@ async def key_limit_warning(self):

async def passphrase_warning(self):
from pages import LongTextPage
from utils import is_passphrase_active
import microns
import stash

if len(stash.bip39_passphrase) > 0:
if is_passphrase_active():
text = '''\
\n\nThis new key will be linked to your active passphrase. \
It will only be displayed when this same passphrase is applied. Continue?'''
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,9 @@ async def show_intro(self):
import lvgl as lv
import microns
from pages import InfoPage
import stash
from utils import is_passphrase_active

if self.mention_passphrase and stash.bip39_passphrase:
if self.mention_passphrase and is_passphrase_active():
text = 'Passport is about to {} and passphrase'.format(self.action_text)
else:
text = 'Passport is about to {}'.format(self.action_text)
Expand Down
25 changes: 18 additions & 7 deletions ports/stm32/boards/Passport/modules/flows/temporary_seed_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,24 @@ async def enter_seed(self):
self.set_result(result)

async def clear_seed(self):
from utils import spinner_task, start_task
from utils import spinner_task, start_task, is_passphrase_active
from tasks import delay_task
from pages import SuccessPage
from pages import SuccessPage, QuestionPage

if is_passphrase_active():
text = 'Clear temporary seed? The current passphrase will be removed.'
else:
text = 'Clear temporary seed?'

result = await QuestionPage(text=text).show()

if not result:
# Setting result to false exits temporary mode
self.set_result(True)
return

settings.exit_temporary_mode()
# await spinner_task('Clearing temporary seed', delay_task, args=[1000, False])
await SuccessPage(text='Temporary Seed Cleared').show()
await SuccessPage(text='Temporary seed cleared').show()
await self.finalize()

async def use_child_seed(self):
Expand All @@ -64,7 +75,7 @@ async def use_child_seed(self):
self.set_result(False)
return

(vals, error) = await spinner_task(text='Retrieving Key',
(vals, error) = await spinner_task(text='Retrieving key',
task=self.key_type['task'],
args=[self.key['index']])
pk = vals['priv']
Expand All @@ -74,13 +85,13 @@ async def use_child_seed(self):
return

settings.enter_temporary_mode()
(error,) = await spinner_task('Applying Seed', save_seed_task, args=[pk])
(error,) = await spinner_task('Applying seed', save_seed_task, args=[pk])

if error is not None:
self.set_result(None)
return

await SuccessPage(text='Temporary Seed Applied').show()
await SuccessPage(text='Temporary seed applied').show()
await self.finalize(child=True)

async def finalize(self, child=False):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -230,8 +230,9 @@ async def qr_button(self):

async def show_passphrase(self):
import stash
from utils import is_passphrase_active
from pages import InfoPage

if stash.bip39_passphrase != '' and not self.external_key:
await InfoPage(text='Passphrase: {}'.format(stash.bip39_passphrase)).show()
if is_passphrase_active() and not self.external_key:
await InfoPage(text='Passphrase: {}'.format(stash.get_passphrase())).show()
self.set_result(True)
2 changes: 1 addition & 1 deletion ports/stm32/boards/Passport/modules/multisig_wallet.py
Original file line number Diff line number Diff line change
Expand Up @@ -726,7 +726,7 @@ def from_file(cls, config, name=None):
unique_id = b2a_hex(unique_id).decode('utf-8')

# TODO: why does this band-aid "multisig object is not iterable" error?
passphrase = stash.bip39_passphrase
passphrase = stash.get_passphrase()
if passphrase != '':
await spinner_task('Checking Multisig Config', apply_passphrase_task, args=[passphrase])

Expand Down
19 changes: 14 additions & 5 deletions ports/stm32/boards/Passport/modules/stash.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,9 +121,18 @@ def decode(secret, _bip39pw=''):
return 'master', ms, hd


# optional global value: user-supplied passphrase to salt BIP39 seed process
bip39_passphrase = ''
bip39_hash = ''
def set_passphrase(passphrase=''):
from common import settings
settings.set_volatile('bip39_passphrase', passphrase)


def clear_passphrase():
set_passphrase('')


def get_passphrase():
from common import settings
return settings.get('bip39_passphrase', '')


class SensitiveValues:
Expand Down Expand Up @@ -154,7 +163,7 @@ def __init__(self, secret=None, for_backup=False):
self.spots = []

# backup during volatile bip39 encryption: do not use passphrase
self._bip39pw = '' if for_backup else str(bip39_passphrase)
self._bip39pw = '' if for_backup else str(get_passphrase())
# print('self._bip39pw={}'.format(self._bip39pw))

def __enter__(self):
Expand Down Expand Up @@ -228,7 +237,7 @@ def capture_xpub(self, save=False):

# Always store these volatile - Takes less than 1 second to recreate, and it will change whenever
# a passphrase is entered, so no need to waste flash cycles on storing it.
if bip39_passphrase == '':
if get_passphrase() == '':
settings.set_volatile('root_xfp', xfp)
if save:
settings.set('xfp', xfp)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,22 +12,22 @@
from errors import Error
import stash
import foundation
from utils import bytes_to_hex_str
from utils import bytes_to_hex_str, is_passphrase_active
import common


async def apply_passphrase_task(on_done, passphrase):
if stash.bip39_passphrase == '':
if not is_passphrase_active():
# This checks if the root_xfp has been generated and saved,
# If not, it's saved to settings for future use
common.settings.get('root_xfp')

stash.bip39_passphrase = passphrase
stash.set_passphrase(passphrase)

# Create a hash from the passphrase
if len(stash.bip39_passphrase) > 0:
if len(passphrase) > 0:
digest = bytearray(32)
foundation.sha256(stash.bip39_passphrase, digest)
foundation.sha256(passphrase, digest)
digest_hex = bytes_to_hex_str(digest)
stash.bip39_hash = digest_hex[:8] # Take first 8 characters (32-bits)
# print('stash.bip39_hash={}'.format(stash.bip39_hash))
Expand Down
10 changes: 7 additions & 3 deletions ports/stm32/boards/Passport/modules/ui/ui.py
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,11 @@ def update_cards(self,
is_init=False,
stay_on_last_card=False):
from flows import MenuFlow
from utils import get_accounts_by_xfp, has_seed, is_extension_enabled, escape_text
from utils import (get_accounts_by_xfp,
has_seed,
is_extension_enabled,
escape_text,
is_passphrase_active)
from menus import account_menu, plus_menu
from extensions.extensions import supported_extensions
from constants import DEFAULT_ACCOUNT_ENTRY
Expand Down Expand Up @@ -268,7 +272,7 @@ def update_cards(self,
'args': {'menu': account_menu, 'is_top_level': True},
'account': account
}
if len(stash.bip39_passphrase) > 0:
if is_passphrase_active():
account_card['icon'] = 'ICON_PASSPHRASE'

card_descs.append(account_card)
Expand All @@ -277,7 +281,7 @@ def update_cards(self,

for extension in supported_extensions:
if is_extension_enabled(extension['name']):
if len(stash.bip39_passphrase) > 0:
if is_passphrase_active():
extension['card']['icon'] = 'ICON_PASSPHRASE'
else:
extension['card']['icon'] = None
Expand Down
2 changes: 1 addition & 1 deletion ports/stm32/boards/Passport/modules/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -1295,7 +1295,7 @@ def are_hidden_keys_showing():

def is_passphrase_active():
import stash
return stash.bip39_passphrase != ''
return stash.get_passphrase() != ''


MSG_CHARSET = range(32, 127)
Expand Down

0 comments on commit 620cc2b

Please sign in to comment.