1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2024-11-16 04:29:08 +00:00

add transport for bridge

This commit is contained in:
Pavol Rusnak 2014-07-26 16:27:28 +02:00
parent 58711df5d3
commit a527456db5
10 changed files with 103 additions and 21 deletions

View File

@ -12,7 +12,7 @@ from trezorlib.protobuf_json import pb2json
def parse_args(commands): def parse_args(commands):
parser = argparse.ArgumentParser(description='Commandline tool for Trezor devices.') parser = argparse.ArgumentParser(description='Commandline tool for Trezor devices.')
parser.add_argument('-v', '--verbose', dest='verbose', action='store_true', help='Prints communication to device') parser.add_argument('-v', '--verbose', dest='verbose', action='store_true', help='Prints communication to device')
parser.add_argument('-t', '--transport', dest='transport', choices=['usb', 'serial', 'pipe', 'socket'], default='usb', help="Transport used for talking with the device") parser.add_argument('-t', '--transport', dest='transport', choices=['usb', 'serial', 'pipe', 'socket', 'bridge'], default='usb', help="Transport used for talking with the device")
parser.add_argument('-p', '--path', dest='path', default='', help="Path used by the transport (usually serial port)") parser.add_argument('-p', '--path', dest='path', default='', help="Path used by the transport (usually serial port)")
# parser.add_argument('-dt', '--debuglink-transport', dest='debuglink_transport', choices=['usb', 'serial', 'pipe', 'socket'], default='usb', help="Debuglink transport") # parser.add_argument('-dt', '--debuglink-transport', dest='debuglink_transport', choices=['usb', 'serial', 'pipe', 'socket'], default='usb', help="Debuglink transport")
# parser.add_argument('-dp', '--debuglink-path', dest='debuglink_path', default='', help="Path used by the transport (usually serial port)") # parser.add_argument('-dp', '--debuglink-path', dest='debuglink_path', default='', help="Path used by the transport (usually serial port)")
@ -67,6 +67,10 @@ def get_transport(transport_string, path, **kwargs):
from trezorlib.transport_socket import SocketTransportClient from trezorlib.transport_socket import SocketTransportClient
return SocketTransportClient(path, **kwargs) return SocketTransportClient(path, **kwargs)
if transport_string == 'bridge':
from trezorlib.transport_bridge import BridgeTransport
return BridgeTransport(path, **kwargs)
if transport_string == 'fake': if transport_string == 'fake':
from trezorlib.transport_fake import FakeTransport from trezorlib.transport_fake import FakeTransport
return FakeTransport(path, **kwargs) return FakeTransport(path, **kwargs)

View File

@ -4,13 +4,14 @@ sys.path = ['../',] + sys.path
from trezorlib.transport_pipe import PipeTransport from trezorlib.transport_pipe import PipeTransport
from trezorlib.transport_hid import HidTransport from trezorlib.transport_hid import HidTransport
from trezorlib.transport_socket import SocketTransportClient from trezorlib.transport_socket import SocketTransportClient
from trezorlib.transport_bridge import BridgeTransport
devices = HidTransport.enumerate() devices = HidTransport.enumerate()
if len(devices) > 0: if len(devices) > 0:
if devices[0][1] != None: if devices[0][1] != None:
print 'Using TREZOR' print 'Using TREZOR'
TRANSPORT = HidTransport TRANSPORT = BridgeTransport
TRANSPORT_ARGS = (devices[0],) TRANSPORT_ARGS = (devices[0],)
TRANSPORT_KWARGS = {'debug_link': False} TRANSPORT_KWARGS = {'debug_link': False}
DEBUG_TRANSPORT = HidTransport DEBUG_TRANSPORT = HidTransport

View File

@ -41,10 +41,10 @@ __version__='0.0.5'
__author__='Paul Dovbush <dpp@dpp.su>' __author__='Paul Dovbush <dpp@dpp.su>'
import json # py2.6+ TODO: add support for other JSON serialization modules import json
from google.protobuf.descriptor import FieldDescriptor as FD from google.protobuf.descriptor import FieldDescriptor as FD
import binascii import binascii
import types_pb2 as types
class ParseError(Exception): pass class ParseError(Exception): pass
@ -112,7 +112,7 @@ _ftype2js = {
#FD.TYPE_MESSAGE: pb2json, #handled specially #FD.TYPE_MESSAGE: pb2json, #handled specially
FD.TYPE_BYTES: lambda x: binascii.hexlify(x), FD.TYPE_BYTES: lambda x: binascii.hexlify(x),
FD.TYPE_UINT32: int, FD.TYPE_UINT32: int,
FD.TYPE_ENUM: int, FD.TYPE_ENUM: str,
FD.TYPE_SFIXED32: float, FD.TYPE_SFIXED32: float,
FD.TYPE_SFIXED64: float, FD.TYPE_SFIXED64: float,
FD.TYPE_SINT32: int, FD.TYPE_SINT32: int,
@ -132,7 +132,7 @@ _js2ftype = {
# FD.TYPE_MESSAGE: json2pb, #handled specially # FD.TYPE_MESSAGE: json2pb, #handled specially
FD.TYPE_BYTES: lambda x: binascii.unhexlify(x), FD.TYPE_BYTES: lambda x: binascii.unhexlify(x),
FD.TYPE_UINT32: int, FD.TYPE_UINT32: int,
FD.TYPE_ENUM: int, FD.TYPE_ENUM: lambda x: getattr(types, x),
FD.TYPE_SFIXED32: float, FD.TYPE_SFIXED32: float,
FD.TYPE_SFIXED64: float, FD.TYPE_SFIXED64: float,
FD.TYPE_SINT32: int, FD.TYPE_SINT32: int,

View File

@ -19,7 +19,7 @@ class Transport(object):
def _close(self): def _close(self):
raise NotImplementedException("Not implemented") raise NotImplementedException("Not implemented")
def _write(self, msg): def _write(self, msg, protobuf_msg):
raise NotImplementedException("Not implemented") raise NotImplementedException("Not implemented")
def _read(self): def _read(self):
@ -51,7 +51,7 @@ class Transport(object):
def write(self, msg): def write(self, msg):
ser = msg.SerializeToString() ser = msg.SerializeToString()
header = struct.pack(">HL", mapping.get_type(msg), len(ser)) header = struct.pack(">HL", mapping.get_type(msg), len(ser))
self._write("##%s%s" % (header, ser)) self._write("##%s%s" % (header, ser), msg)
def read(self): def read(self):
if not self.ready_to_read(): if not self.ready_to_read():
@ -73,6 +73,9 @@ class Transport(object):
def _parse_message(self, data): def _parse_message(self, data):
(msg_type, data) = data (msg_type, data) = data
if msg_type == 'protobuf':
return data
else:
inst = mapping.get_class(msg_type)() inst = mapping.get_class(msg_type)()
inst.ParseFromString(data) inst.ParseFromString(data)
return inst return inst

View File

@ -0,0 +1,74 @@
'''BridgeTransport implements transport TREZOR Bridge (aka trezord).'''
import binascii
import requests
import protobuf_json
import json
import mapping
from transport import Transport
import messages_pb2 as proto
TREZORD_HOST = 'http://localhost:21324'
CONFIG_URL = 'https://mytrezor.com/data/plugin/config_signed.bin'
class BridgeTransport(Transport):
def __init__(self, device, *args, **kwargs):
r = requests.get(CONFIG_URL)
if r.status_code != 200:
raise Exception('Could not fetch config from %s' % CONFIG_URL)
config = binascii.unhexlify(r.text)
r = requests.post(TREZORD_HOST + '/configure', data=config)
if r.status_code != 200:
raise Exception('trezord: Could not configure')
r = requests.get(TREZORD_HOST + '/enumerate')
if r.status_code != 200:
raise Exception('trezord: Could not enumerate devices')
enum = r.json()
if len(enum) < 1:
raise Exception('trezord: No devices found')
self.path = enum[0]['path']
self.session = None
self.response = None
super(BridgeTransport, self).__init__(device, *args, **kwargs)
def _open(self):
r = requests.post(TREZORD_HOST + '/acquire/%s' % self.path)
if r.status_code != 200:
raise Exception('trezord: Could not acquire session')
resp = r.json()
self.session = resp['session']
def _close(self):
r = requests.post(TREZORD_HOST + '/release/%s' % self.session)
if r.status_code != 200:
raise Exception('trezord: Could not release session')
else:
self.session = None
def ready_to_read(self):
return self.response != None
def _write(self, msg, protobuf_msg):
cls = protobuf_msg.__class__.__name__
msg = protobuf_json.pb2json(protobuf_msg)
payload = '{"type": "%s","message": %s}' % (cls, json.dumps(msg))
r = requests.post(TREZORD_HOST + '/call/%s' % self.session, data=payload)
if r.status_code != 200:
raise Exception('trezord: Could not write message')
else:
self.response = r.json()
def _read(self):
if self.response == None:
raise Exception('No response stored')
cls = getattr(proto, self.response['type'])
inst = cls()
pb = protobuf_json.json2pb(inst, self.response['message'])
return ('protobuf', pb)

View File

@ -17,7 +17,7 @@ class FakeTransport(Transport):
def ready_to_read(self): def ready_to_read(self):
return False return False
def _write(self, msg): def _write(self, msg, protobuf_msg):
pass pass
def _read(self): def _read(self):

View File

@ -96,7 +96,7 @@ class HidTransport(Transport):
def ready_to_read(self): def ready_to_read(self):
return False return False
def _write(self, msg): def _write(self, msg, protobuf_msg):
msg = bytearray(msg) msg = bytearray(msg)
while len(msg): while len(msg):
# Report ID, data padded to 63 bytes # Report ID, data padded to 63 bytes

View File

@ -1,4 +1,4 @@
'''TransportFake implements fake wire transport over local named pipe. '''PipeTransport implements fake wire transport over local named pipe.
Use this transport for talking with trezor simulator.''' Use this transport for talking with trezor simulator.'''
import os import os
@ -42,7 +42,7 @@ class PipeTransport(Transport):
rlist, _, _ = select([self.read_f], [], [], 0) rlist, _, _ = select([self.read_f], [], [], 0)
return len(rlist) > 0 return len(rlist) > 0
def _write(self, msg): def _write(self, msg, protobuf_msg):
try: try:
self.write_f.write(msg) self.write_f.write(msg)
self.write_f.flush() self.write_f.flush()

View File

@ -22,7 +22,7 @@ class SerialTransport(Transport):
rlist, _, _ = select([self.serial], [], [], 0) rlist, _, _ = select([self.serial], [], [], 0)
return len(rlist) > 0 return len(rlist) > 0
def _write(self, msg): def _write(self, msg, protobuf_msg):
try: try:
self.serial.write(msg) self.serial.write(msg)
self.serial.flush() self.serial.flush()

View File

@ -29,7 +29,7 @@ class SocketTransportClient(Transport):
rlist, _, _ = select([self.socket], [], [], 0) rlist, _, _ = select([self.socket], [], [], 0)
return len(rlist) > 0 return len(rlist) > 0
def _write(self, msg): def _write(self, msg, protobuf_msg):
self.socket.sendall(msg) self.socket.sendall(msg)
def _read(self): def _read(self):
@ -89,7 +89,7 @@ class SocketTransport(Transport):
return self.ready_to_read() return self.ready_to_read()
return False return False
def _write(self, msg): def _write(self, msg, protobuf_msg):
if self.filelike: if self.filelike:
# None on disconnected client # None on disconnected client