예제 #1
0
async def remember_bip39_passphrase():
    # Compute current xprv and switch to using that as root secret.
    import stash
    from common import dis, pa

    dis.fullscreen('Check...')

    with stash.SensitiveValues() as sv:
        if sv.mode != 'words':
            # not a BIP39 derived secret, so cannot work.
            await ux_show_story(
                '''The wallet secret was not based on a seed phrase, so we cannot add a BIP39 passphrase at this time.''',
                title='Failed')
            return

        nv = SecretStash.encode(xprv=sv.node)

    # Important: won't write new XFP to nvram if pw still set
    stash.bip39_passphrase = ''

    dis.fullscreen('Saving...')
    pa.change(new_secret=nv)

    # re-read settings since key is now different
    # - also captures xfp, xpub at this point
    pa.new_main_secret(nv)

    # check and reload secret
    pa.reset()
    pa.login()
예제 #2
0
def clear_seed(restart=True):
    from common import dis, pa, settings
    import utime
    import version

    dis.fullscreen('Erasing Seed...')

    # clear settings associated with this key, since it will be no more
    settings.reset()

    # save a blank secret (all zeros is a special case, detected by bootloader)
    nv = bytes(AE_SECRET_LEN)
    pa.change(new_secret=nv)

    # wipe the long secret too
    nv = bytes(AE_LONG_SECRET_LEN)
    pa.ls_change(nv)

    if restart:
        dis.fullscreen('Restarting...')
        utime.sleep(1)

        # security: need to reboot to really be sure to clear the secrets from main memory.
        from machine import reset
        reset()


# EOF
예제 #3
0
def save_wallet_seed(seed_bits):
    from common import dis, pa, settings

    print('save_wallet_seed 1')
    # encode it for our limited secret space
    nv = SecretStash.encode(seed_bits=seed_bits)
    print('save_wallet_seed 2: nv={}'.format(b2a_hex(nv)))

    dis.fullscreen('Saving Wallet...')
    pa.change(new_secret=nv)
    print('save_wallet_seed 3')

    # re-read settings since key is now different
    # - also captures xfp, xpub at this point
    pa.new_main_secret(nv)
    print('save_wallet_seed 4')

    # check and reload secret
    pa.reset()
    print('save_wallet_seed 5')
    pa.login()
    print('save_wallet_seed 6')
예제 #4
0
async def restore_from_dict(vals):
    # Restore from a dict of values. Already JSON decoded.
    # Reboot on success, return string on failure
    from common import pa, dis, settings
    from pincodes import SE_SECRET_LEN

    #print("Restoring from: %r" % vals)

    # step1: the private key
    # - prefer raw_secret over other values
    # - TODO: fail back to other values
    try:
        chain = chains.get_chain(vals.get('chain', 'BTC'))

        assert 'raw_secret' in vals
        raw = bytearray(SE_SECRET_LEN)
        rs = vals.pop('raw_secret')
        if len(rs) % 2:
            rs += '0'
        x = a2b_hex(rs)
        raw[0:len(x)] = x

        # check we can decode this right (might be different firmare)
        opmode, bits, node = stash.SecretStash.decode(raw)
        assert node

        # verify against xprv value (if we have it)
        if 'xprv' in vals:
            check_xprv = chain.serialize_private(node)
            assert check_xprv == vals['xprv'], 'xprv mismatch'

    except Exception as e:
        return ('Unable to decode raw_secret and '
                'restore the seed value!\n\n\n' + str(e))

    ls = None
    if 'long_secret' in vals:
        try:
            ls = a2b_hex(vals.pop('long_secret'))
        except Exception as exc:
            sys.print_exception(exc)
            # but keep going.

    dis.fullscreen("Saving...")
    dis.progress_bar_show(.25)

    # clear (in-memory) settings and change also nvram key
    # - also captures xfp, xpub at this point
    pa.change(new_secret=raw)

    # force the right chain
    pa.new_main_secret(raw, chain)  # updates xfp/xpub

    # NOTE: don't fail after this point... they can muddle thru w/ just right seed

    if ls is not None:
        try:
            pa.ls_change(ls)
        except Exception as exc:
            sys.print_exception(exc)
            # but keep going

    # restore settings from backup file

    for idx, k in enumerate(vals):
        dis.progress_bar_show(idx / len(vals))
        if not k.startswith('setting.'):
            continue

        if k == 'xfp' or k == 'xpub':
            continue

        settings.set(k[8:], vals[k])

    # write out
    settings.save()

    if ('hsm_policy' in vals):
        import hsm
        hsm.restore_backup(vals['hsm_policy'])

    await ux_show_story(
        'Everything has been successfully restored. '
        'We must now reboot to install the '
        'updated settings and/or seed.',
        title='Success!')

    from machine import reset
    reset()
예제 #5
0
    async def show(self):
        while True:
            print('show: state={}'.format(self.state))
            if self.state == self.ENTER_PIN1:
                self.pin1[self.round] = await ux_enter_pin(
                    title='Security Code',
                    heading='{} Security Code'.format('Old' if self.round ==
                                                      0 else 'New'))
                if self.pin1[self.round] != None and len(
                        self.pin1[self.round]) >= MIN_PIN_PART_LEN:
                    if self.round == 1:
                        self.goto(self.SHOW_ANTI_PHISHING_WORDS)
                    else:
                        self.goto(self.ENTER_PIN2)

            elif self.state == self.SHOW_ANTI_PHISHING_WORDS:
                start = utime.ticks_us()
                words = pincodes.PinAttempt.anti_phishing_words(
                    self.pin1[self.round].encode())
                end = utime.ticks_us()
                result = await ux_show_word_list('Security Words',
                                                 words,
                                                 heading1='Remember these',
                                                 heading2='Security Words:',
                                                 left_btn='BACK',
                                                 right_btn='OK')
                if result == 'x':
                    self.pin1[self.round] = None
                    self.goto(self.ENTER_PIN1)
                else:
                    self.goto(self.ENTER_PIN2)

            elif self.state == self.ENTER_PIN2:
                self.pin2[self.round] = await ux_enter_pin(
                    title='Login PIN',
                    heading='{} Login PIN'.format('Old' if self.round ==
                                                  0 else 'New'))
                if self.pin2[self.round] != None and len(
                        self.pin2[self.round]) >= MIN_PIN_PART_LEN:
                    if self.round == 0:
                        self.round = 1
                        self.goto(self.ENTER_PIN1)
                    else:
                        self.goto(self.CHANGE_PIN)

            elif self.state == self.CHANGE_PIN:
                try:
                    print('pin1={} pin2={}'.format(self.pin1, self.pin2))
                    args = {}
                    args['old_pin'] = (self.pin1[0] + self.pin2[0]).encode()
                    args['new_pin'] = (self.pin1[1] + self.pin2[1]).encode()
                    print('pa.change: args={}'.format(args))
                    pa.change(**args)
                    self.goto(self.CHANGE_SUCCESS)
                except Exception as err:
                    print('err={}'.format(err))
                    self.goto(self.CHANGE_FAILED)

            elif self.state == self.CHANGE_FAILED:
                result = await ux_show_story(
                    'Unable to change PIN.  The old PIN you entered was incorrect.',
                    title='PIN Error',
                    right_btn='RETRY')
                if result == 'y':
                    self.pin1 = [None, None]
                    self.pin2 = [None, None]
                    self.round = 0
                    self.goto(self.ENTER_PIN1)
                else:
                    return

            elif self.state == self.CHANGE_SUCCESS:
                dis.fullscreen('PIN changed')
                utime.sleep(1)
                return

            else:
                while True:
                    print('ERROR: Should never hit this else case!')
                    from uasyncio import sleep_ms
                    await sleep_ms(1000)