Example #1
0
async def done_splash2():
    # Boot up code; after splash screen is done.
                
    # MAYBE: check if we're a brick and die again? Or show msg?

    if version.is_factory_mode:
        # in factory mode, turn on USB early to allow debug/setup
        from usb import enable_usb
        enable_usb(loop, True)

        # always start the self test.
        if not settings.get('tested', False):
            from actions import start_selftest
            await start_selftest()

    else:
        # force them to accept terms (unless marked as already done)
        from actions import accept_terms
        await accept_terms()

    # Prompt for PIN and then pick appropriate top-level menu,
    # based on contents of secure chip (ie. is there
    # a wallet defined)
    from actions import start_login_sequence
    await start_login_sequence()

    loop.create_task(mainline())
Example #2
0
async def initial_pin_setup(*a):
    # First time they select a PIN of any type.
    from login import LoginUX
    lll = LoginUX()
    pin = await lll.get_new_pin(
        'Choose PIN', '''\
Pick the main wallet's PIN code now. Be more clever, but an example:

123-4567

It has two parts: prefix (123-) and suffix (-4567). \
Each part must between 2 to 6 digits long. Total length \
can be as long as 12 digits.

The prefix part determines the anti-phishing words you will \
see each time you login.

Your new PIN protects access to \
this Coldcard device and is not a factor in the wallet's \
seed words or private keys.

THERE IS ABSOLUTELY NO WAY TO RECOVER A FORGOTTEN PIN! Write it down.
''')
    del lll

    if pin is None: return

    # A new pin is to be set!
    from main import pa, dis, settings, loop
    dis.fullscreen("Saving...")

    try:
        assert pa.is_blank()

        pa.change(new_pin=pin)

        # check it? kinda, but also get object into normal "logged in" state
        pa.setup(pin)
        ok = pa.login()
        assert ok

        # must re-read settings after login, because they are encrypted
        # with a key derived from the main secret.
        settings.set_key()
        settings.load()
    except Exception as e:
        print("Exception: %s" % e)

    # Allow USB protocol, now that we are auth'ed
    from usb import enable_usb
    enable_usb(loop, False)

    from menu import MenuSystem
    from flow import EmptyWallet
    return MenuSystem(EmptyWallet)
Example #3
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 #4
0
async def dev_enable_protocol(*a):
    # Turn off disk emulation. Keep VCP enabled, since they are still devs.
    from main import loop

    cur = pyb.usb_mode()
    if cur and 'HID' in cur:
        await ux_show_story('Coldcard USB protocol is already enabled (HID mode)')
        return

    # might need to reset stuff?
    from usb import enable_usb

    # reset / re-enable
    pyb.usb_mode(None)
    enable_usb(loop, True)

    await ux_show_story('Back to normal USB mode.')
Example #5
0
async def more_setup():
    # Boot up code; splash screen is being shown

    # MAYBE: check if we're a brick and die again? Or show msg?

    try:
        # Some background "tasks"
        #
        from dev_helper import monitor_usb
        IMPT.start_task('vcp', monitor_usb())

        from files import CardSlot
        CardSlot.setup()

        # This "pa" object holds some state shared w/ bootloader about the PIN
        try:
            from pincodes import pa
            pa.setup(b'')  # just to see where we stand.
        except RuntimeError as e:
            print("Problem: %r" % e)

        if version.is_factory_mode:
            # in factory mode, turn on USB early to allow debug/setup
            from usb import enable_usb
            enable_usb()

            # always start the self test.
            if not settings.get('tested', False):
                from actions import start_selftest
                await start_selftest()

        else:
            # force them to accept terms (unless marked as already done)
            from actions import accept_terms
            await accept_terms()

        # Prompt for PIN and then pick appropriate top-level menu,
        # based on contents of secure chip (ie. is there
        # a wallet defined)
        from actions import start_login_sequence
        await start_login_sequence()
    except BaseException as exc:
        die_with_debug(exc)

    IMPT.start_task('mainline', mainline())
Example #6
0
# (c) Copyright 2018 by Coinkite Inc. This file is covered by license found in COPYING-CC.
#
# This is my personal /lib/boot2.py which enables easier USB access. For v4+ firmware.
#
print("/lib/boot2: runs")

# start the REPL very early
from usb import enable_usb  # very slow, noticable in boot sequence
enable_usb(True)

import uasyncio
from dev_helper import usb_keypad_emu
uasyncio.create_task(usb_keypad_emu())

print("/lib/boot2: done")
Example #7
0
async def start_login_sequence():
    # Boot up login sequence here.
    #
    from main import pa, settings, dis, loop, numpad
    import version

    if pa.is_blank():
        # Blank devices, with no PIN set all, can continue w/o login

        # Do green-light set immediately after firmware upgrade
        if version.is_fresh_version():
            pa.greenlight_firmware()
            dis.show()

        goto_top_menu()
        return

    # Allow impatient devs and crazy people to skip the PIN
    guess = settings.get('_skip_pin', None)
    if guess is not None:
        try:
            dis.fullscreen("(Skip PIN)")
            pa.setup(guess)
            pa.login()
        except:
            pass

    # if that didn't work, or no skip defined, force
    # them to login succefully.
    while not pa.is_successful():
        # always get a PIN and login first
        await block_until_login()

    # Must read settings after login
    settings.set_key()
    settings.load()

    # Restore a login preference or two
    numpad.sensitivity = settings.get('sens', numpad.sensitivity)

    # Do green-light set immediately after firmware upgrade
    if not pa.is_secondary:
        if version.is_fresh_version():
            pa.greenlight_firmware()
            dis.show()

    # Populate xfp/xpub values, if missing.
    # - can happen for first-time login of duress wallet
    # - may indicate lost settings, which we can easily recover from
    # - these values are important to USB protocol
    if not (settings.get('xfp', 0)
            and settings.get('xpub', 0)) and not pa.is_secret_blank():
        try:
            import stash

            # Recalculate xfp/xpub values (depends both on secret and chain)
            with stash.SensitiveValues() as sv:
                sv.capture_xpub()
        except Exception as exc:
            # just in case, keep going; we're not useless and this
            # is early in boot process
            print("XFP save failed: %s" % exc)

    # Allow USB protocol, now that we are auth'ed
    from usb import enable_usb
    enable_usb(loop, False)

    goto_top_menu()
Example #8
0
async def initial_pin_setup(*a):
    # First time they select a PIN of any type.
    from login import LoginUX
    lll = LoginUX()
    title = 'Choose PIN'

    ch = await ux_show_story('''\
Pick the main wallet's PIN code now. Be more clever, but an example:

123-4567

It has two parts: prefix (123-) and suffix (-4567). \
Each part must between 2 to 6 digits long. Total length \
can be as long as 12 digits.

The prefix part determines the anti-phishing words you will \
see each time you login.

Your new PIN protects access to \
this Coldcard device and is not a factor in the wallet's \
seed words or private keys.

THERE IS ABSOLUTELY NO WAY TO RECOVER A FORGOTTEN PIN! Write it down.
''',
                             title=title)
    if ch != 'y': return

    while 1:
        ch = await ux_show_story('''\
There is ABSOLUTELY NO WAY to 'reset the PIN' or 'factory reset' the Coldcard if you forget the PIN.

DO NOT FORGET THE PIN CODE.
 
Press 6 to prove you read to the end of this message.''',
                                 title='WARNING',
                                 escape='6')

        if ch == 'x': return
        if ch == '6': break

    # do the actual picking
    pin = await lll.get_new_pin(title)
    del lll

    if pin is None: return

    # A new pin is to be set!
    from main import pa, dis, settings, loop
    dis.fullscreen("Saving...")

    try:
        dis.busy_bar(True)
        assert pa.is_blank()

        pa.change(new_pin=pin)

        # check it? kinda, but also get object into normal "logged in" state
        pa.setup(pin)
        ok = pa.login()
        assert ok

        # must re-read settings after login, because they are encrypted
        # with a key derived from the main secret.
        settings.set_key()
        settings.load()
    except Exception as e:
        print("Exception: %s" % e)
    finally:
        dis.busy_bar(False)

    # Allow USB protocol, now that we are auth'ed
    from usb import enable_usb
    enable_usb(loop, False)

    from menu import MenuSystem
    from flow import EmptyWallet
    return MenuSystem(EmptyWallet)
Example #9
0
async def start_login_sequence():
    # Boot up login sequence here.
    #
    from main import pa, settings, dis, loop, numpad
    from ux import idle_logout

    if pa.is_blank():
        # Blank devices, with no PIN set all, can continue w/o login

        # Do green-light set immediately after firmware upgrade
        if version.is_fresh_version():
            pa.greenlight_firmware()
            dis.show()

        goto_top_menu()
        return

    # maybe show a nickname before we do anything
    nickname = settings.get('nick', None)
    if nickname:
        try:
            await show_nickname(nickname)
        except: pass

    # Allow impatient devs and crazy people to skip the PIN
    guess = settings.get('_skip_pin', None)
    if guess is not None:
        try:
            dis.fullscreen("(Skip PIN)")
            pa.setup(guess)
            pa.login()
        except: pass

    # if that didn't work, or no skip defined, force
    # them to login succefully.
    while not pa.is_successful():
        # always get a PIN and login first
        await block_until_login()

    # Must re-read settings after login
    settings.set_key()
    settings.load()

    # implement "login countdown" feature
    delay = settings.get('lgto', 0)
    if delay:
        pa.reset()
        await login_countdown(delay)
        await block_until_login()

    # implement idle timeout now that we are logged-in
    loop.create_task(idle_logout())

    # Do green-light set immediately after firmware upgrade
    if not pa.is_secondary:
        if version.is_fresh_version():
            pa.greenlight_firmware()
            dis.show()

    # Populate xfp/xpub values, if missing.
    # - can happen for first-time login of duress wallet
    # - may indicate lost settings, which we can easily recover from
    # - these values are important to USB protocol
    if not (settings.get('xfp', 0) and settings.get('xpub', 0)) and not pa.is_secret_blank():
        try:
            import stash

            # Recalculate xfp/xpub values (depends both on secret and chain)
            with stash.SensitiveValues() as sv:
                sv.capture_xpub()
        except Exception as exc:
            # just in case, keep going; we're not useless and this
            # is early in boot process
            print("XFP save failed: %s" % exc)

    # If HSM policy file is available, offer to start that,
    # **before** the USB is even enabled.
    if version.has_fatram:
        try:
            import hsm, hsm_ux

            if hsm.hsm_policy_available():
                ar = await hsm_ux.start_hsm_approval(usb_mode=False, startup_mode=True)
                if ar:
                    await ar.interact()
        except: pass

    # Allow USB protocol, now that we are auth'ed
    from usb import enable_usb
    enable_usb(loop, False)

    goto_top_menu()
Example #10
0
# (c) Copyright 2018 by Coinkite Inc. This file is part of Coldcard <coldcardwallet.com>
# and is covered by GPLv3 license found in COPYING.
#
# This is my personal /lib/boot2.py which enables easier USB access.
#
print("/lib/boot2: runs")

# start the REPL very early
import uasyncio.core as asyncio
from usb import enable_usb

loop = asyncio.get_event_loop()
enable_usb(loop, True)

from dev_helper import usb_keypad_emu
loop.create_task(usb_keypad_emu())

print("/lib/boot2: done")
Example #11
0
# - cannot be changed by /flash/lib overrides, because already imported before that.
#

# see RAM_HEADER_BASE, and coldcardFirmwareHeader_t in sigheader.h
import pyb, sys, version, gc

# this makes the GC run when larger objects are free in an attempt to reduce fragmentation.
gc.threshold(4096)

# what firmware signing key did we boot with? are we in dev mode?
is_devmode = version.is_devmode()

if 0:
    # useful for debug: keep this stub
    from usb import enable_usb
    enable_usb(None, True)
    raise SystemExit

if is_devmode:
    # For devs only: allow code in this directory to overide compiled-in stuff. Dangerous!
    # - using relative paths here so works better on simulator
    # - you must boot w/ non-production-signed firmware to get here
    sys.path.insert(0, 'flash/lib')

    # Give external devs a way to start stuff early
    try:
        import boot2
    except:
        pass

import ckcc