Example #1
0
async def address_explore(*a):
    # explore addresses based on derivation path chosen
    # by proxy external index=0 address

    while not settings.get('axskip', False):
        ch = await ux_show_story('''\
The following menu lists the first payment address \
produced by various common wallet systems.

Choose the address that your desktop or mobile wallet \
has shown you as the first receive address.

WARNING: Please understand that exceeding the gap limit \
of your wallet, or choosing the wrong address on the next screen \
may make it very difficult to recover your funds.

Press 4 to start or 6 to hide this message forever.''', escape='46')

        if ch == '4': break
        if ch == '6':
            settings.set('axskip', True)
            break
        if ch == 'x': return

    m = AddressListMenu()
    await m.render()        # slow

    the_ux.push(m)
Example #2
0
    def set_it(idx, text):
        settings.set('du', idx)

        import pyb
        from usb import enable_usb, disable_usb
        cur = pyb.usb_mode()
        if cur and idx:
            # usb enabled, but should not be now
            disable_usb()
        elif not cur and not idx:
            # USB disabled, but now should be
            enable_usb()
Example #3
0
    def set_chain(idx, text):
        val = ch[idx][0]
        assert ch[idx][1] == text
        settings.set('chain', val)

        try:
            # update xpub stored in settings
            import stash
            with stash.SensitiveValues() as sv:
                sv.capture_xpub()
        except ValueError:
            # no secrets yet, not an error
            pass
Example #4
0
async def start_selftest():

    try:
        await test_oled()
        await test_microsd()
        await test_numpad()
        await test_sflash()
        await test_secure_element()
        await test_sd_active()

        # add more tests here

        settings.set('tested', True)
        await ux_show_story("Selftest complete", 'PASS')

    except (RuntimeError, AssertionError) as e:
        await ux_show_story("Test failed:\n" + str(e), 'FAIL')
Example #5
0
    def add(cls, prevout, amount):
        # protect privacy, compress a little, and save it.
        # - we know it's not yet in our lists
        key = cls.encode_key(prevout)

        # memory management: can't store very much, so trim as needed
        depth = HISTORY_SAVED
        if settings.capacity > 0.8:
            depth //= 2

        # also limit in-memory use
        cls.load_cache()
        if len(cls.runtime_cache) >= HISTORY_MAX_MEM:
            del cls.runtime_cache[0]

        # save new addition
        assert len(key) == ENCKEY_LEN
        assert amount > 0
        entry = key + cls.encode_value(prevout, amount)
        cls.runtime_cache.append(entry)

        # update what we're going to save long-term
        settings.set(cls.KEY, cls.runtime_cache[-depth:])
Example #6
0
async def test_7z():
    # test full 7z round-trip
    # Altho cleartext mode is not for real, if the code is written, I must test it.
    from backups import write_complete_backup, restore_complete_doit
    from sffile import SFFile
    import ngu, version, uos
    from glob import numpad
    from pincodes import pa
    from nvstore import settings

    if version.has_fatram:
        import hsm
        had_policy = hsm.hsm_policy_available()
    else:
        had_policy = False

    today = ngu.random.uniform(1000000)

    import machine
    machine.reset = lambda: None

    for chain in ['BTC', 'XTN']:
        for words in ([], ['abc', 'def']):
            settings.set('check', today)
            settings.set('chain', chain)

            if version.has_608:
                ls = b'%416d' % today
                pa.ls_change(ls)

            ll, sha = await write_complete_backup(words, None, True)

            result = SFFile(0, ll).read()

            if words:
                #open('debug.7z', 'wb').write(result)
                assert ll > 800
                assert len(sha) == 32
                assert result[0:6] == b"7z\xbc\xaf'\x1c"
                assert ngu.hash.sha256s(result) == sha
                assert len(set(result)) >= 240  # encrypted
            else:
                sr = str(result, 'ascii')
                print("Backup contents:\n" + sr)
                assert sr[0] == '#', result
                assert 'Coldcard' in sr
                assert len(set(sr)) < 100  # cleartext, english
                assert ('chain = "%s"' % chain) in result

            # test restore
            # - cant wipe flash, since the backup file is there
            # - cant wipe all settings becuase PIN and stuff is simulated there
            del settings.current['check']

            if had_policy:
                from hsm import POLICY_FNAME
                uos.unlink(POLICY_FNAME)
                assert not hsm.hsm_policy_available()

            with SFFile(0, ll) as fd:
                numpad.inject('y')  # for 'success' message
                await restore_complete_doit(fd, words)

                assert settings.get('check') == today, \
                            (settings.get('check'), '!=',  today)
                assert settings.get('chain') == chain, \
                            (settings.get('chain'), '!=',  chain)

                if version.has_608:
                    assert pa.ls_fetch() == ls

            if had_policy:
                assert had_policy == hsm.hsm_policy_available()

            today += 3

            import ux
            ux.restore_menu()
Example #7
0
if '--mainnet' in sys.argv:
    sim_defaults['chain'] = 'BTC'

if '--seed' in sys.argv:
    # --seed "word1 word2 ... word24" => import that seed phrase at start
    from ustruct import unpack
    from utils import xfp2str
    from seed import set_seed_value
    from main import pa
    from nvstore import settings

    words = sys.argv[sys.argv.index('--seed') + 1].split(' ')
    assert len(words) in {12, 18, 24}, "Expected space-separated words: add some quotes"
    pa.pin = b'12-12'
    set_seed_value(words)
    settings.set('terms_ok', 1)
    settings.set('_skip_pin', '12-12')
    settings.set('chain', 'XTN')
    print("Seed phrase set, resulting XFP: " + xfp2str(settings.get('xfp')))

if '--secret' in sys.argv:
    # --secret 01a1a1a....   Set SE master secret directly. See SecretStash.encode
    from ubinascii import unhexlify as a2b_hex
    from ubinascii import hexlify as b2a_hex

    val = sys.argv[sys.argv.index('--secret') + 1]
    val = a2b_hex(val)
    assert val[0] in { 0x01, 0x80, 0x81, 0x82} or 16 <= val[0] <= 64, "bad first byte"
    val += bytes(72 - len(val))

    SECRETS.update({
Example #8
0
# (c) Copyright 2020 by Coinkite Inc. This file is covered by license found in COPYING-CC.
#
# load up the simulator w/ indicated test master key
from sim_settings import sim_defaults
import stash, chains
from h import b2a_hex
from pincodes import pa
from nvstore import settings
from stash import SecretStash, SensitiveValues
from utils import xfp2str

import main
rs = main.RAW_SECRET
print("New raw secret: %s" % b2a_hex(rs))

if 1:
    settings.current = dict(sim_defaults)
    settings.overrides.clear()
    settings.set('chain', 'XTN')

    pa.change(new_secret=rs)
    pa.new_main_secret(rs)

    print("New key in effect: %s" % settings.get('xpub', 'MISSING'))
    print("Fingerprint: %s" % xfp2str(settings.get('xfp', 0)))
Example #9
0
from sim_settings import sim_defaults
import stash, chains
from h import b2a_hex
from pincodes import pa
from nvstore import settings
import stash
from seed import set_seed_value
from utils import xfp2str

tn = chains.BitcoinTestnet

if 1:
    stash.bip39_passphrase = ''
    settings.current = sim_defaults
    settings.overrides.clear()
    settings.set('chain', 'XTN')
    settings.set('words', True)
    settings.set('terms_ok', True)
    settings.set('idle_to', 0)

    import main
    pa.tmp_value = None
    set_seed_value(main.WORDS)

    print("New key in effect: %s" % settings.get('xpub', 'MISSING'))
    print("Fingerprint: %s" % xfp2str(settings.get('xfp', 0)))

    # impt: if going from xprv => seed words, main menu needs updating
    from actions import goto_top_menu
    goto_top_menu()
Example #10
0
 def doit(idx, text):
     settings.set('rz', va[idx])
Example #11
0
 def set_idle_timeout(idx, text):
     settings.set('idle_to', va[idx])
Example #12
0
 def set_del_psbt(idx, text):
     settings.set('del', idx)
Example #13
0
 def set(idx, text):
     settings.set('fee_limit', va[idx])
Example #14
0
async def restore_from_dict(vals):
    # Restore from a dict of values. Already JSON decoded.
    # Reboot on success, return string on failure
    from glob import dis

    #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(AE_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) and version.has_608:
        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 version.has_fatram and ('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 seed.',
        title='Success!')

    from machine import reset
    reset()
Example #15
0
# run manually with:
#   execfile('../../testing/devtest/nvram.py')

from ubinascii import hexlify as b2a_hex
from ubinascii import unhexlify as a2b_hex

import ustruct
from sflash import SF
from nvstore import SLOTS, settings

# reset whatever's there
SF.chip_erase()
settings.load()

for v in [123, 'hello', 34.56, dict(a=45)]:
    settings.set('abc', v)
    assert settings.get('abc') == v

a = settings.get('_age', -1)
settings.save()
assert settings.get('_age') >= a+1, [settings.get('_age'), a+1]

chk = dict(settings.current)
settings.load()

# some minor differences in values: bytes vs. strings, so just check keys
assert sorted(list(chk)) == sorted(list(settings.current)), \
    'readback fail: \n%r != \n%r' % (chk, settings.current)

if 1:
    # fill it up