Ejemplo n.º 1
0
async def import_xprv(*A):
    # read an XPRV from a text file and use it.
    import tcc, chains, ure
    from main import pa
    from stash import SecretStash
    from ubinascii import hexlify as b2a_hex
    from backups import restore_from_dict

    assert pa.is_secret_blank()  # "must not have secret"

    def contains_xprv(fname):
        # just check if likely to be valid; not full check
        try:
            with open(fname, 'rt') as fd:
                for ln in fd:
                    # match tprv and xprv, plus y/zprv etc
                    if 'prv' in ln: return True
                return False
        except OSError:
            # directories?
            return False

    # pick a likely-looking file.
    fn = await file_picker('Select file containing the XPRV to be imported.',
                           min_size=50,
                           max_size=2000,
                           taster=contains_xprv)

    if not fn: return

    node, chain, addr_fmt = None, None, None

    # open file and do it
    pat = ure.compile(r'.prv[A-Za-z0-9]+')
    with CardSlot() as card:
        with open(fn, 'rt') as fd:
            for ln in fd.readlines():
                if 'prv' not in ln: continue

                found = pat.search(ln)
                if not found: continue

                found = found.group(0)

                for ch in chains.AllChains:
                    for kk in ch.slip132:
                        if found[0] == ch.slip132[kk].hint:
                            try:
                                node = tcc.bip32.deserialize(
                                    found, ch.slip132[kk].pub,
                                    ch.slip132[kk].priv)
                                chain = ch
                                addr_fmt = kk
                                break
                            except ValueError:
                                pass
                if node:
                    break

    if not node:
        # unable
        await ux_show_story('''\
Sorry, wasn't able to find an extended private key to import. It should be at \
the start of a line, and probably starts with "xprv".''',
                            title="FAILED")
        return

    # encode it in our style
    d = dict(chain=chain.ctype,
             raw_secret=b2a_hex(SecretStash.encode(xprv=node)))
    node.blank()

    # TODO: capture the address format implied by SLIP32 version bytes
    #addr_fmt =

    # restore as if it was a backup (code reuse)
    await restore_from_dict(d)
Ejemplo n.º 2
0
async def microsd_upgrade(*a):
    # Upgrade vis MicroSD card
    # - search for a particular file
    # - verify it lightly
    # - erase serial flash
    # - copy it over (slow)
    # - reboot into bootloader, which finishes install

    fn = await file_picker('Pick firmware image to use (.DFU)',
                           suffix='.dfu',
                           min_size=0x7800)

    if not fn: return

    failed = None

    with CardSlot() as card:
        with open(fn, 'rb') as fp:
            from main import sf, dis
            from files import dfu_parse
            from ustruct import unpack_from

            offset, size = dfu_parse(fp)

            # get a copy of special signed heaer at the end of the flash as well
            from sigheader import FW_HEADER_OFFSET, FW_HEADER_SIZE, FW_HEADER_MAGIC, FWH_PY_FORMAT
            hdr = bytearray(FW_HEADER_SIZE)
            fp.seek(offset + FW_HEADER_OFFSET)

            # basic checks only: for confused customers, not attackers.
            try:
                rv = fp.readinto(hdr)
                assert rv == FW_HEADER_SIZE

                magic_value, timestamp, version_string, pk, fw_size = \
                                unpack_from(FWH_PY_FORMAT, hdr)[0:5]
                assert magic_value == FW_HEADER_MAGIC
                assert fw_size == size

                # TODO: maybe show the version string? Warn them that downgrade doesn't work?

            except Exception as exc:
                failed = "Sorry! That does not look like a firmware " \
                            "file we would want to use.\n\n\n%s" % exc

            if not failed:

                # copy binary into serial flash
                fp.seek(offset)

                buf = bytearray(256)  # must be flash page size
                pos = 0
                dis.fullscreen("Loading...")
                while pos <= size + FW_HEADER_SIZE:
                    dis.progress_bar_show(pos / size)

                    if pos == size:
                        # save an extra copy of the header (also means we got done)
                        buf = hdr
                    else:
                        here = fp.readinto(buf)
                        if not here: break

                    if pos % 4096 == 0:
                        # erase here
                        sf.sector_erase(pos)
                        while sf.is_busy():
                            await sleep_ms(10)

                    sf.write(pos, buf)

                    # full page write: 0.6 to 3ms
                    while sf.is_busy():
                        await sleep_ms(1)

                    pos += here

    if failed:
        await ux_show_story(failed, title='Corrupt')
        return

    # continue process...
    import machine
    machine.reset()