trezor-agent/trezor_agent/factory.py

93 lines
3.3 KiB
Python
Raw Normal View History

2016-02-19 08:08:36 +00:00
"""Thin wrapper around trezor/keepkey libraries."""
2016-01-15 11:07:01 +00:00
import binascii
import collections
import logging
import semver
log = logging.getLogger(__name__)
ClientWrapper = collections.namedtuple(
'ClientWrapper',
2016-03-06 19:58:11 +00:00
['connection', 'identity_type', 'device_name', 'call_exception'])
2016-01-15 11:07:01 +00:00
# pylint: disable=too-many-arguments
def _load_client(name, client_type, hid_transport,
2016-03-06 19:58:11 +00:00
passphrase_ack, identity_type,
required_version, call_exception):
2016-01-15 11:07:01 +00:00
def empty_passphrase_handler(_):
return passphrase_ack(passphrase='')
for d in hid_transport.enumerate():
connection = client_type(hid_transport(d))
connection.callback_PassphraseRequest = empty_passphrase_handler
f = connection.features
log.debug('connected to %s %s', name, f.device_id)
log.debug('label : %s', f.label)
log.debug('vendor : %s', f.vendor)
current_version = '{}.{}.{}'.format(f.major_version,
f.minor_version,
f.patch_version)
log.debug('version : %s', current_version)
log.debug('revision : %s', binascii.hexlify(f.revision))
if not semver.match(current_version, required_version):
fmt = 'Please upgrade your {} firmware to {} version (current: {})'
raise ValueError(fmt.format(name,
required_version,
current_version))
yield ClientWrapper(connection=connection,
identity_type=identity_type,
2016-03-06 19:58:11 +00:00
device_name=name,
call_exception=call_exception)
2016-01-15 11:07:01 +00:00
def _load_trezor():
# pylint: disable=import-error
2016-03-06 19:58:11 +00:00
from trezorlib.client import TrezorClient, CallException
2016-01-15 11:07:01 +00:00
from trezorlib.transport_hid import HidTransport
from trezorlib.messages_pb2 import PassphraseAck
from trezorlib.types_pb2 import IdentityType
return _load_client(name='Trezor',
client_type=TrezorClient,
hid_transport=HidTransport,
passphrase_ack=PassphraseAck,
identity_type=IdentityType,
2016-03-06 19:58:11 +00:00
required_version='>=1.3.4',
call_exception=CallException)
2016-01-15 11:07:01 +00:00
def _load_keepkey():
# pylint: disable=import-error
2016-03-06 19:58:11 +00:00
from keepkeylib.client import KeepKeyClient, CallException
2016-01-15 11:07:01 +00:00
from keepkeylib.transport_hid import HidTransport
from keepkeylib.messages_pb2 import PassphraseAck
from keepkeylib.types_pb2 import IdentityType
return _load_client(name='KeepKey',
client_type=KeepKeyClient,
hid_transport=HidTransport,
passphrase_ack=PassphraseAck,
identity_type=IdentityType,
2016-03-06 19:58:11 +00:00
required_version='>=1.0.4',
call_exception=CallException)
2016-01-15 11:07:01 +00:00
2016-01-19 20:52:52 +00:00
LOADERS = [
_load_trezor,
_load_keepkey
]
2016-01-15 11:07:01 +00:00
2016-01-19 20:52:52 +00:00
def load(loaders=None):
2016-02-19 08:08:36 +00:00
"""Load a single device, via specified loaders' list."""
2016-01-19 20:52:52 +00:00
loaders = loaders if loaders is not None else LOADERS
device_list = []
for loader in loaders:
device_list.extend(loader())
if len(device_list) == 1:
return device_list[0]
msg = '{:d} devices found'.format(len(device_list))
2016-01-15 11:07:01 +00:00
raise IOError(msg)