コード例 #1
0
def test_backup_accept(dev, need_keypress):
    time.sleep(0.050)

    r = dev.send_recv(CCProtocolPacker.start_backup())
    assert r == None

    need_keypress('y')

    while 1:
        if dev.is_simulator:
            # work our way thru the password quiz... eventually pressing '1' will work.
            need_keypress('1')

        time.sleep(0.10)
        done = dev.send_recv(CCProtocolPacker.get_backup_file(), timeout=5000)
        if done: break

    assert len(done) == 2, done

    ll, sha = done
    assert ll > 500
    assert len(sha) == 32

    result = dev.download_file(ll, sha, file_number=0)

    assert result[0:2] == b'7z'
    assert len(set(result)) > 200
コード例 #2
0
def test_b9p_vectors(dev,
                     set_seed_words,
                     need_keypress,
                     vector,
                     pw='RoZert'[::-1].upper()):
    # Test all BIP39 vectors. Slow.
    _, words, cooked, xprv = vector

    seed = Mnemonic.to_seed(words, passphrase=pw)
    assert seed == a2b_hex(cooked)

    set_seed_words(words)

    dev.send_recv(CCProtocolPacker.bip39_passphrase(pw), timeout=None)

    need_keypress('y')

    xpub = None
    while xpub == None:
        time.sleep(0.050)
        xpub = dev.send_recv(CCProtocolPacker.get_passphrase_done(),
                             timeout=None)

    # check our math (ignore testnet vs. mainnet)
    got = BIP32Node.from_wallet_key(xpub)
    exp = BIP32Node.from_wallet_key(xprv)

    assert got.public_pair() == exp.public_pair()
コード例 #3
0
ファイル: test_sign.py プロジェクト: Davdegreat/firmware
    def doit(accept=True, in_psbt=None, finalize=False):

        if accept != None:
            need_keypress('y' if accept else 'x')

        if accept == False:
            with pytest.raises(CCUserRefused):
                done = None
                while done == None:
                    time.sleep(0.050)
                    done = dev.send_recv(CCProtocolPacker.get_signed_txn(), timeout=None)
            return
        else:
            done = None
            while done == None:
                time.sleep(0.050)
                done = dev.send_recv(CCProtocolPacker.get_signed_txn(), timeout=None)

        assert len(done) == 2

        resp_len, chk = done
        psbt_out = dev.download_file(resp_len, chk)

        if not finalize:
            if in_psbt:
                assert BasicPSBT().parse(in_psbt) == BasicPSBT().parse(psbt_out)
        else:
            from pycoin.tx.Tx import Tx
            # parse it
            res = psbt_out
            assert res[0:4] != b'psbt'
            t = Tx.from_bin(res)
            assert t.version in [1, 2]

        return psbt_out
コード例 #4
0
ファイル: test_hsm.py プロジェクト: vmalarcon/firmware
def test_show_p2sh_addr(dev, hsm_reset, start_hsm, change_hsm, make_myself_wallet, addr_vs_path):
    # MULTISIG addrs
    from test_multisig import HARD, make_redeem
    M = 4
    pm = lambda i: [HARD(45), i, 0,0]

    # can't amke ms wallets inside HSM mode
    hsm_reset()
    keys, _ = make_myself_wallet(M)       # slow AF

    permit = ['p2sh', 'm/73']
    start_hsm(DICT(share_addrs=permit))


    scr, pubkeys, xfp_paths = make_redeem(M, keys, path_mapper=pm)
    assert len(scr) <= 520, "script too long for standard!"

    got_addr = dev.send_recv(CCProtocolPacker.show_p2sh_address(
                                    M, xfp_paths, scr, addr_fmt=AF_P2WSH))
    addr_vs_path(got_addr, addr_fmt=AF_P2WSH, script=scr)

    # turn it off; p2sh must be explicitly allowed
    for allow in ['m', 'any']:
        change_hsm(DICT(share_addrs=[allow]))
        dev.send_recv(CCProtocolPacker.show_address('m', AF_CLASSIC))

        with pytest.raises(CCProtoError) as ee:
            got_addr = dev.send_recv(CCProtocolPacker.show_p2sh_address(
                                    M, xfp_paths, scr, addr_fmt=AF_P2WSH))
        assert 'Not allowed in HSM mode' in str(ee)
コード例 #5
0
ファイル: test_msg.py プロジェクト: Coldcard/firmware
def test_sign_msg_good(dev, need_keypress, msg, path, addr_fmt, addr_vs_path):

    msg = msg.encode('ascii')
    dev.send_recv(CCProtocolPacker.sign_message(msg, path, addr_fmt=addr_fmt),
                  timeout=None)

    need_keypress('y')

    done = None
    while done == None:
        time.sleep(0.050)
        done = dev.send_recv(CCProtocolPacker.get_signed_msg(), timeout=None)

    assert len(done) == 2, done

    addr, raw = done
    sig = str(b64encode(raw), 'ascii').replace('\n', '')

    assert 40 <= len(raw) <= 65

    if addr_fmt != AF_CLASSIC:
        # TODO
        # - need bech32 decoder here
        # - pycoin can't do signature decode
        if addr_fmt & AFC_BECH32:
            assert '1' in addr
        return

    # check expected addr was used
    sk = addr_vs_path(addr, path, addr_fmt)

    # verify signature
    assert verify_message(sk, sig, message=msg.decode('ascii')) == True
    assert verify_message(addr, sig, message=msg.decode('ascii')) == True
コード例 #6
0
ファイル: test_sign.py プロジェクト: ramsemune/firmware
def xxx_test_sign_truncated(dev):
    ll, sha = dev.upload_file(open('data/truncated.psbt', 'rb').read())

    dev.send_recv(CCProtocolPacker.sign_transaction(ll, sha))

    with pytest.raises(CCProtoError):
        done = None
        while done == None:
            time.sleep(0.050)
            done = dev.send_recv(CCProtocolPacker.get_signed_txn(), timeout=None)
コード例 #7
0
def test_b39p_refused(dev, need_keypress, pw='testing 123'):
    # user can refuse the passphrase (cancel)

    dev.send_recv(CCProtocolPacker.bip39_passphrase(pw), timeout=None)

    need_keypress('x')

    with pytest.raises(CCUserRefused):
        done = None
        while done == None:
            time.sleep(0.050)
            done = dev.send_recv(CCProtocolPacker.get_passphrase_done(), timeout=None)
コード例 #8
0
def test_upload_fails(dev):
    # incorrect file upload cases

    data = b'3' * 60

    with pytest.raises(CCProtoError):
        # misaligned
        v = dev.send_recv(CCProtocolPacker.upload(23, 23, data))

    with pytest.raises(CCProtoError):
        # bad position
        v = dev.send_recv(CCProtocolPacker.upload(1000, 3, data))
コード例 #9
0
    def doit(data, pkt_len=2048):

        from hashlib import sha256
        import os

        for pos in range(0, len(data), pkt_len):
            v = dev.send_recv(
                CCProtocolPacker.upload(pos, len(data),
                                        data[pos:pos + pkt_len]))
            assert v == pos
            chk = dev.send_recv(CCProtocolPacker.sha256())
            assert chk == sha256(data[0:pos + pkt_len]).digest(), 'bad hash'
コード例 #10
0
def test_sign_msg_refused(dev, need_keypress, msg=b'testing 123', path='m'):
    # user can refuse to sign (cancel)

    dev.send_recv(CCProtocolPacker.sign_message(msg, path), timeout=None)

    need_keypress('x')

    with pytest.raises(CCUserRefused):
        done = None
        while done == None:
            time.sleep(0.050)
            done = dev.send_recv(CCProtocolPacker.get_signed_msg(), timeout=None)
コード例 #11
0
def test_backup_refuse(dev, need_keypress):
    time.sleep(0.050)

    r = dev.send_recv(CCProtocolPacker.start_backup())
    assert r == None

    need_keypress('x')

    with pytest.raises(CCUserRefused):
        done = None
        while done == None:
            time.sleep(0.050)
            done = dev.send_recv(CCProtocolPacker.get_backup_file())
コード例 #12
0
ファイル: test_sign.py プロジェクト: ramsemune/firmware
def test_sign1(dev, need_keypress, finalize):
    in_psbt = a2b_hex(open('data/p2pkh-in-scriptsig.psbt', 'rb').read())

    ll, sha = dev.upload_file(in_psbt)

    dev.send_recv(CCProtocolPacker.sign_transaction(ll, sha, finalize))

    #need_keypress('y')

    with pytest.raises(CCProtoError) as ee:
        while dev.send_recv(CCProtocolPacker.get_signed_txn(), timeout=None) == None:
            pass

    assert 'None of the keys' in str(ee)
コード例 #13
0
def test_upload_short(dev, data_len):
    # upload a few really short files

    from hashlib import sha256

    data = b'a' * data_len

    v = dev.send_recv(CCProtocolPacker.upload(0, len(data), data))
    assert v == 0
    chk = dev.send_recv(CCProtocolPacker.sha256())

    assert chk == sha256(data).digest(), 'bad hash'

    # clear screen / test a degerate case
    dev.send_recv(CCProtocolPacker.upload(256, 256, b''))
コード例 #14
0
ファイル: test_hsm.py プロジェクト: vmalarcon/firmware
def test_storage_locker(package, count, start_hsm, dev):
    # read and write (limited) of storage locker.

    policy = DICT(set_sl=package, allow_sl=count)
    start_hsm(policy)


    for t in range(count+3):
        if t < count:
            got = dev.send_recv(CCProtocolPacker.get_storage_locker(), timeout=None)
            assert got == package.encode('ascii')
        else:
            with pytest.raises(CCProtoError) as ee:
                got = dev.send_recv(CCProtocolPacker.get_storage_locker(), timeout=None)
            assert 'consumed' in str(ee)
コード例 #15
0
ファイル: test_hsm.py プロジェクト: vmalarcon/firmware
    def doit(refuse, *args, **kws):
        tt = kws.pop('timeout', None)
        dev.send_recv(CCProtocolPacker.sign_message(*args, **kws), timeout=tt)

        try:
            done = None
            while done == None:
                time.sleep(0.050)
                done = dev.send_recv(CCProtocolPacker.get_signed_msg(), timeout=tt)

            assert len(done) == 2
            assert refuse == None, "signing didn't fail, but expected to"
        except CCUserRefused:
            msg = hsm_status().last_refusal
            assert refuse != None, "should not have been refused: " + msg
            assert refuse in msg
コード例 #16
0
ファイル: test_hsm.py プロジェクト: ramsemune/firmware
def wait_til_signed(dev):
    result = None
    while result == None:
        time.sleep(0.050)
        result = dev.send_recv(CCProtocolPacker.get_signed_txn(), timeout=None)

    return result
コード例 #17
0
ファイル: test_usb.py プロジェクト: twetch-inc/cold-firmware
def test_upload_long(dev, pkt_len, count=5, data=None):
    # upload a larger "file"
    
    from hashlib import sha256
    import os

    data = data or os.urandom(pkt_len * count)

    for pos in range(0, len(data), pkt_len):
        v = dev.send_recv(CCProtocolPacker.upload(pos, len(data), data[pos:pos+pkt_len]))
        assert v == pos
        chk = dev.send_recv(CCProtocolPacker.sha256())
        assert chk == sha256(data[0:pos+pkt_len]).digest(), 'bad hash'

    # clear screen / test a degerate case
    dev.send_recv(CCProtocolPacker.upload(256, 256, b''))
コード例 #18
0
def test_show_addr_displayed(dev, need_keypress, addr_vs_path, path, addr_fmt,
                             cap_story, show_qr, cap_screen_qr):
    time.sleep(0.1)

    addr = dev.send_recv(CCProtocolPacker.show_address(path, addr_fmt),
                         timeout=None)

    time.sleep(0.1)
    title, story = cap_story()

    #need_keypress('x')

    # check expected addr was used
    addr_vs_path(addr, path, addr_fmt)

    print('addr_fmt = 0x%x' % addr_fmt)

    assert title == 'Address:'
    assert path in story
    assert addr in story
    assert addr in story.split('\n')

    if show_qr:
        need_keypress('4')
        time.sleep(0.1)
        qr = cap_screen_qr()

        assert qr == addr or qr == addr.upper()
コード例 #19
0
ファイル: test_sign.py プロジェクト: ramsemune/firmware
def test_speed_test(request, fake_txn, is_mark3, start_sign, end_sign, dev, need_keypress):
    import time
    # measure time to sign a larger txn
    if is_mark3:
        num_in = 20
        num_out = 250
    else:
        num_in = 9
        num_out = 100

    psbt = fake_txn(num_in, num_out, dev.master_xpub, segwit_in=True)

    open('debug/speed.psbt', 'wb').write(psbt)
    dt = time.time()
    start_sign(psbt, finalize=False)

    tx_time = time.time() - dt

    need_keypress('y', timeout=None)

    dt = time.time()
    done = None
    while done == None:
        time.sleep(0.05)
        done = dev.send_recv(CCProtocolPacker.get_signed_txn(), timeout=None)

    ready_time = time.time() - dt

    print("  Tx time: %.1f" % tx_time)
    print("Sign time: %.1f" % ready_time)
コード例 #20
0
ファイル: test_hsm.py プロジェクト: ramsemune/firmware
    def doit(policy):
        try:
            # on simulator, can read screen and provide keystrokes
            cap_story = request.getfixturevalue('cap_story')
        except:
            # real hardware
            cap_story = None

        # send policy, start it, approve it
        data = json.dumps(policy).encode('ascii')

        ll, sha = dev.upload_file(data)
        assert ll == len(data)

        dev.send_recv(CCProtocolPacker.hsm_start(ll, sha))

        if cap_story:
            # capture explanation given user
            time.sleep(.2)
            title, body = cap_story()
            assert title == "Start HSM?"

        if cap_story:
            # approve it
            need_keypress('y')
            time.sleep(.1)

            title, body2 = cap_story()
            assert 'Last chance' in body2
            ll = body2.split('\n')[-1]
            assert ll.startswith("Press ")
            ch = ll[6]

            need_keypress(ch)
            time.sleep(.100)

            j = hsm_status()
            assert j.active == True
            if 'summary' in j:
                assert not body or j.summary in body

        else:
            # do keypresses blindly
            need_keypress('y')
            time.sleep(.1)
            for ch in '12346':
                need_keypress(ch, timeout=10000)

            # needs bless firmware step; can take >10 seconds?
            j = hsm_status(10000)
            assert j.active == True

            if 0:
                for retry in range(30):
                    time.sleep(1)
                    #try: except: pass
                assert j.active == True

        return j
コード例 #21
0
def test_show_addr_usb(dev, need_keypress, addr_vs_path, path, addr_fmt,):

    addr = dev.send_recv(CCProtocolPacker.show_address(path, addr_fmt), timeout=None)

    need_keypress('y')

    # check expected addr was used
    addr_vs_path(addr, path, addr_fmt)
コード例 #22
0
def test_version(dev):
    # read the version, yawn.
    v = dev.send_recv(CCProtocolPacker.version())
    assert '\n' in v
    date, label, bl, *extras = v.split('\n')
    assert '-' in date
    assert '.' in label
    assert '.' in bl
    print("date=%s" % date)
コード例 #23
0
    def doit(pw):
        # reset from previous runs
        words = reset_seed_words()

        # optimization
        if pw == '':
            return simulator_fixed_xfp

        print(f"Setting BIP39 pw: {pw}")
        dev.send_recv(CCProtocolPacker.bip39_passphrase(pw), timeout=None)

        if pw:
            time.sleep(0.050)
            title, body = cap_story()

            assert pw not in body

            # verify display of passphrase
            need_keypress('2')
            time.sleep(0.050)
            title, body = cap_story()
            assert pw in body

        need_keypress('y')

        done = None
        while done == None:
            time.sleep(0.050)
            done = dev.send_recv(CCProtocolPacker.get_passphrase_done(),
                                 timeout=None)

        xpub = done
        assert xpub[1:4] == 'pub'
        got = BIP32Node.from_wallet_key(xpub)

        # what it should be
        seed = Mnemonic.to_seed(words, passphrase=pw)
        expect = BIP32Node.from_master_secret(seed)

        assert got.public_pair() == expect.public_pair()

        xfp, = struct.unpack('I', expect.fingerprint())

        return xfp
コード例 #24
0
ファイル: test_hsm.py プロジェクト: ramsemune/firmware
 def doit(timeout=1000):
     txt = dev.send_recv(CCProtocolPacker.hsm_status(), timeout=timeout)
     assert txt[0] == '{'
     assert txt[-1] == '}'
     j = json.loads(txt, object_hook=DICT)
     assert j.active in {True, False}
     if 'users' in j or 'wallets' in j:
         assert 'users' in j
         assert j.active or ('wallets' in j)
     assert 'chain' in j
     return j
コード例 #25
0
def test_sign_msg_good(dev, need_keypress, master_xpub, msg, path, addr_fmt,
                       addr_vs_path):

    msg = msg.encode('ascii')
    dev.send_recv(CCProtocolPacker.sign_message(msg, path, addr_fmt=addr_fmt),
                  timeout=None)

    need_keypress('y')

    done = None
    while done == None:
        time.sleep(0.050)
        done = dev.send_recv(CCProtocolPacker.get_signed_msg(), timeout=None)

    assert len(done) == 2, done

    addr, raw = done
    sig = str(b64encode(raw), 'ascii').replace('\n', '')

    assert 40 <= len(raw) <= 65

    if addr_fmt != AF_CLASSIC:
        # TODO
        # - need bech32 decoder here
        # - pycoin can't do signature decode
        if addr_fmt & AFC_BECH32:
            assert '1' in addr
        return

    if "'" not in path and 'p' not in path:
        # check expected addr was used
        mk = BIP32Node.from_wallet_key(master_xpub)
        sk = mk.subkey_for_path(path[2:])

        addr_vs_path(addr, path, addr_fmt)

        # verify signature
        assert verify_message(sk, sig, message=msg.decode('ascii')) == True
    else:
        # just verify signature
        assert verify_message(addr, sig, message=msg.decode('ascii')) == True
コード例 #26
0
ファイル: test_msg.py プロジェクト: Coldcard/firmware
def test_low_R_cases(msg, num_iter, expect, dev, set_seed_words, use_mainnet,
                     need_keypress):
    # Thanks to @craigraw of Sparrow for this test case, copied from:
    # <https://github.com/sparrowwallet/drongo/blob/master/src/test/java/com/sparrowwallet/drongo/crypto/ECKeyTest.java>

    set_seed_words(
        'absent essay fox snake vast pumpkin height crouch silent bulb excuse razor'
    )
    use_mainnet()
    path = "m/44'/0'/0'/0/0"  # first address, P2PKH
    addr_fmt = AF_CLASSIC

    #addr = dev.send_recv(CCProtocolPacker.show_address(path, addr_fmt), timeout=None)
    #assert addr == '14JmU9a7SzieZNEtBnsZo688rt3mGrw6hr'

    msg = msg.encode('ascii')
    dev.send_recv(CCProtocolPacker.sign_message(msg, path, addr_fmt=addr_fmt),
                  timeout=None)

    need_keypress('y')

    done = None
    while done == None:
        time.sleep(0.050)
        done = dev.send_recv(CCProtocolPacker.get_signed_msg(), timeout=None)

    assert len(done) == 2, done
    got_addr, raw = done

    assert got_addr == '14JmU9a7SzieZNEtBnsZo688rt3mGrw6hr'
    assert 40 <= len(raw) <= 65

    sig = str(b64encode(raw), 'ascii').replace('\n', '')

    if num_iter != 1:
        # I have gotten these cases to pass, but I didn't want to keep the code
        # that grinded for low R in message signing... Ok for txn signing, but
        # needless delay for message signing.
        raise pytest.xfail('no code')

    assert sig == expect
コード例 #27
0
def test_show_addr_usb(dev, need_keypress, addr_vs_path, path, addr_fmt,
                       is_simulator):

    addr = dev.send_recv(CCProtocolPacker.show_address(path, addr_fmt),
                         timeout=None)

    need_keypress('y')

    if "'" in path and not is_simulator():
        raise pytest.skip('we cant confirm hardened-derived keypaths')

    # check expected addr was used
    addr_vs_path(addr, path, addr_fmt)
コード例 #28
0
ファイル: test_hsm.py プロジェクト: ramsemune/firmware
def test_xpub_sharing(dev, start_hsm, change_hsm, addr_fmt=AF_CLASSIC):
    # xpub sharing, but only at certain derivations
    # - note 'm' is always shared
    permit = ['m', 'm/73', "m/43/44/*'", 'm/1p/3h/4/5/6/7']
    block = ['m/72', 'm/43/44/99', permit[-1][:-2]]

    policy = DICT(share_xpubs=permit)
    start_hsm(policy)

    for p in permit:
        p = p.replace('*', '99')
        xpub = dev.send_recv(CCProtocolPacker.get_xpub(p), timeout=5000)

    for p in block:
        with pytest.raises(CCProtoError) as ee:
            xpub = dev.send_recv(CCProtocolPacker.get_xpub(p), timeout=5000)
            assert 'Not allowed in HSM mode' in str(ee)

    policy = DICT(share_xpubs=['any'])
    change_hsm(policy)

    for p in block + permit:
        p = p.replace('*', '99')
        xpub = dev.send_recv(CCProtocolPacker.get_xpub(p), timeout=5000)

    # default is block all but 'm'
    policy = DICT()
    change_hsm(policy)
    for p in block + permit:
        if p == 'm': continue
        p = p.replace('*', '99')
        with pytest.raises(CCProtoError) as ee:
            xpub = dev.send_recv(CCProtocolPacker.get_xpub(p), timeout=5000)
        assert 'Not allowed in HSM mode' in str(ee)

    # 'm' always works
    xpub = dev.send_recv(CCProtocolPacker.get_xpub('m'), timeout=5000)
    assert xpub[0:4] == 'tpub'
コード例 #29
0
def test_encryption(dev):
    "Setup session key and test link encryption works"

    #dev = ColdcardDevice(sn=force_serial, encrypt=False)
    #dev.start_encryption()

    print("Session key: " + str(b2a_hex(dev.session_key), 'utf'))

    for blen in [4, 8, 60, 128, 256, MAX_MSG_LEN - 4]:
        rb = dev.send_recv(CCProtocolPacker.ping(bytes(blen)), encrypt=1)
        assert set(rb) == {0} and len(rb) == blen

        rb = dev.send_recv(CCProtocolPacker.ping(bytes(blen)), encrypt=0)
        assert set(rb) == {0} and len(rb) == blen

    was = dev.session_key
    assert len(was) == 32
    assert len(set(was)) > 8

    # rekey
    dev.start_encryption()
    assert dev.session_key != was
    assert len(set(dev.session_key)) > 8
コード例 #30
0
ファイル: conftest.py プロジェクト: Davdegreat/firmware
 def doit(k):
     if hasattr(dev.dev, 'pipe'):
         dev.send_recv(CCProtocolPacker.sim_keypress(k.encode('ascii')))
     else:
         # try to use debug interface to simulate the press
         # XXX for some reason, picocom must **already** be running for this to work.
         # - otherwise, this locks up
         devs = list(glob.glob('/dev/tty.usbmodem*'))
         if len(devs) == 1:
             with open(devs[0], 'wb', 0) as fd:
                 fd.write(k.encode('ascii'))
         else:
             # need actual user interaction
             print("NOW, on the Coldcard, press key: %s" % k)