A bit of refactoring
This commit is contained in:
parent
859f163520
commit
269fd1955e
23 changed files with 304 additions and 701 deletions
110
calibrate.py
110
calibrate.py
|
|
@ -1,110 +0,0 @@
|
|||
|
||||
from hashlib import sha256
|
||||
from binascii import hexlify, unhexlify
|
||||
from os.path import isfile
|
||||
from threading import Thread
|
||||
from struct import unpack, pack
|
||||
|
||||
from tls97 import tls
|
||||
from usb97 import usb
|
||||
from time import ctime
|
||||
from sensor import write_hw_reg32, read_hw_reg32, identify_sensor
|
||||
from flash import erase_flash, read_flash, get_fw_info, write_flash_all
|
||||
from util import assert_status
|
||||
from blobs import calibrate_prg
|
||||
|
||||
#usb.trace_enabled=True
|
||||
#tls.trace_enabled=True
|
||||
|
||||
usb.open()
|
||||
tls.parseTlsFlash(read_flash(1, 0, 0x1000))
|
||||
tls.open()
|
||||
|
||||
# no idea what this is:
|
||||
write_hw_reg32(0x8000205c, 7)
|
||||
if read_hw_reg32(0x80002080) != 2:
|
||||
raise Exception('Unexpected register value')
|
||||
|
||||
dev=identify_sensor()
|
||||
print('Sensor: %s' % dev.name)
|
||||
# ^ TODO -- what is the real reason to detect HW at this stage? -- likely it is required to construct calibrate_prg
|
||||
|
||||
fwi=get_fw_info(2)
|
||||
if fwi == None:
|
||||
raise Exception('No firmware detected')
|
||||
|
||||
print('FWExt version %d.%d (%s), %d modules' % (fwi.major, fwi.minor, ctime(fwi.buildtime), len(fwi.modules)))
|
||||
|
||||
def wait_82():
|
||||
calib_data=usb.read_82()
|
||||
print('len=%d' % len(calib_data))
|
||||
with open('calib-data.bin', 'wb') as f:
|
||||
f.write(calib_data)
|
||||
|
||||
|
||||
if isfile('calib-data.bin'):
|
||||
with open('calib-data.bin', 'rb') as f:
|
||||
calib_data=f.read()
|
||||
print('Calibration data loaded from a file.')
|
||||
else:
|
||||
# TODO Properly construct calibrate_prg.
|
||||
# >>> 6f 000e 000000000000
|
||||
# <<< 0000 880d 0000 07000000
|
||||
# 0800 0000 9400 0e00 0300 0080 07000000 7e7f807f808080808080808080808080808080808080818081808180818080808080818081808080818081808180818081808180818081808180808081808180808081807f80808180808081808180818080808180818081808180818081808080818081808180818081808180818081808180818081808180818081808080808080808080807f807f807f807f7f7e7e
|
||||
# a400 0000 0800 0e00 0200 0000 00000000 0d007100
|
||||
# b400 0000 0800 0e00 0800 0080 db000000 00000000
|
||||
# c400 0000 0400 0e00 0500 0080 1c6f0400
|
||||
# d000 0000 9400 0e00 0700 0080 07000000 2b23203c2d182e1e30182e1c321d341d341e321c301e1e241e201f201d1c321a301e1c211e21341f1e202024201f1e20201f212221221d221e23341e1d1e1d20341f1d193b341c1d1e35201e201c20221f341c1e1e1c221f201d21201e1c1f34242221201f20221f201e241e241d2020221e2420231d221e211e1f1e1e341c321e3220301d2d302f2d2c2b23223a211c
|
||||
# 6c01 0000 1400 0e00 0f00 0080 05550007 7701002805720000080100020811e107
|
||||
# 8801 0000 0c00 0e00 1200 0080 07000000 7002 7800 7002 7800
|
||||
#
|
||||
# Empty reply:
|
||||
# >>> 6f 000a 000000000000
|
||||
# <<< 0000 880d 0000 00000000
|
||||
|
||||
#Thread(target=wait_82).start()
|
||||
|
||||
rsp=tls.cmd(calibrate_prg)
|
||||
assert_status(rsp)
|
||||
print(rsp.hex())
|
||||
# ^ TODO check what the rest of the rsp means
|
||||
|
||||
calib_data=usb.read_82()
|
||||
print('len=%d' % len(calib_data))
|
||||
with open('calib-data.bin', 'wb') as f:
|
||||
f.write(calib_data)
|
||||
|
||||
class Line():
|
||||
def __init__(self, blob):
|
||||
# what's with the rest of fields?
|
||||
self.u0, self.u1, self.line, self.frame, self.u2, self.u3, self.u4, self.u5 = unpack('<BBBBBBBB', blob[:8])
|
||||
self.data = blob[8:]
|
||||
|
||||
def serialize(self):
|
||||
return pack('<BBBBBBBB', self.u0, self.u1, self.line, self.frame, self.u2, self.u3, self.u4, self.u5) + self.data
|
||||
|
||||
def __repr__(self):
|
||||
return 'Line(line=%d, frame=%d)' % (self.line, self.frame)
|
||||
|
||||
lines=[calib_data[i:i+0x90+8] for i in range(0, len(calib_data), 0x90+8)] # TODO work out where "bytes per line" constant is comming from
|
||||
lines=[Line(i) for i in lines]
|
||||
frame4=[i.serialize() for i in lines if i.frame == 4] # why 4?
|
||||
frame4=b''.join(frame4)
|
||||
calib_data=pack('<H', len(frame4)) + frame4 + pack('<H', 0) # what's that 00000 in the end?
|
||||
calib_data=pack('<H', len(calib_data)) + sha256(calib_data).digest() + b'\0'*0x20 + calib_data
|
||||
calib_data=unhexlify('0250') + calib_data
|
||||
|
||||
def persist_calib_data():
|
||||
start=read_flash(6, 0, 0x44)
|
||||
if start != b'\xff' * 0x44:
|
||||
if calib_data[:0x44] == start:
|
||||
print('Calibration data already matches the data on flash.')
|
||||
return
|
||||
else:
|
||||
print('Calibration flash already written. Erasing.')
|
||||
erase_flash(6)
|
||||
|
||||
write_flash_all(6, 0, calib_data)
|
||||
|
||||
persist_calib_data()
|
||||
|
||||
|
|
@ -6,8 +6,8 @@ from pydbus.generic import signal
|
|||
import pkg_resources
|
||||
from time import sleep
|
||||
from prototype import *
|
||||
from db97 import subtype_to_string
|
||||
from sensor import cancel_capture
|
||||
from proto97.db import subtype_to_string
|
||||
from proto97.sensor import cancel_capture
|
||||
import pwd
|
||||
|
||||
print("Starting up")
|
||||
|
|
|
|||
|
|
@ -1,11 +1,6 @@
|
|||
|
||||
from usb97 import usb
|
||||
from util import unhex, assert_status
|
||||
from blobs import reset_blob
|
||||
from sensor import reboot
|
||||
from proto97.usb import usb
|
||||
from proto97.sensor import factory_reset
|
||||
|
||||
#usb.trace_enabled=True
|
||||
usb.open()
|
||||
assert_status(usb.cmd(reset_blob))
|
||||
assert_status(usb.cmd(b'\x10' + b'\0'*0x61))
|
||||
reboot()
|
||||
factory_reset()
|
||||
|
|
|
|||
49
init_db.py
49
init_db.py
|
|
@ -1,49 +0,0 @@
|
|||
|
||||
from struct import pack, unpack
|
||||
|
||||
from db97 import db
|
||||
from usb97 import usb
|
||||
from tls97 import tls
|
||||
from flash import read_flash
|
||||
|
||||
machine_guid='e7260876-58db-4d27-8c40-8d13110d6a71'
|
||||
|
||||
#usb.trace_enabled=True
|
||||
#tls.trace_enabled=True
|
||||
|
||||
usb.open()
|
||||
tls.parseTlsFlash(read_flash(1, 0, 0x1000))
|
||||
tls.open()
|
||||
|
||||
stg=db.get_user_storage(name='StgWindsor')
|
||||
if stg == None:
|
||||
stgid=db.new_record(1, 4, 3, b'StgWindsor\0')
|
||||
stg=db.get_user_storage(stgid)
|
||||
if stg == None:
|
||||
raise Exception('Failed to create StgWindsor')
|
||||
|
||||
def stg_data_records():
|
||||
rc = db.get_record_children(stg.dbid).children
|
||||
return [i['dbid'] for i in rc if i['type'] == 8] # 8 == "data" type
|
||||
|
||||
def machine_id_rec_value(b):
|
||||
b = b.encode('utf-16le')
|
||||
b = b + b'\0' * (0x94 - len(b))
|
||||
return pack('<HH', 0x102, len(b)) + b # 0x102 = Machine ID/GUID?
|
||||
|
||||
rc = stg_data_records()
|
||||
|
||||
if rc == []:
|
||||
db.new_record(stg.dbid, 0x8, stg.dbid, machine_id_rec_value(machine_guid))
|
||||
rc = stg_data_records()
|
||||
|
||||
rc = db.get_record_value(rc[0]).value
|
||||
|
||||
if rc != machine_id_rec_value(machine_guid):
|
||||
u0, l = unpack('<HH', rc[:4])
|
||||
b=rc[4:4+l]
|
||||
b=b.decode('utf-16le')
|
||||
raise Exception('Machine GUID does not match the DB flash ownership record (%s).' % b)
|
||||
|
||||
print('That''s it, pairing''s finished')
|
||||
|
||||
36
pair.py
Normal file
36
pair.py
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
|
||||
from time import sleep
|
||||
|
||||
from proto97.usb import usb
|
||||
from proto97.tls import tls
|
||||
from proto97.flash import read_flash
|
||||
from proto97.init_flash import init_flash
|
||||
from proto97.upload_fwext import upload_fwext
|
||||
from proto97.calibrate import calibrate
|
||||
from proto97.init_db import init_db
|
||||
|
||||
|
||||
def restart():
|
||||
sleep(2)
|
||||
tls.reset()
|
||||
usb.open()
|
||||
usb.send_init()
|
||||
tls.parseTlsFlash(read_flash(1, 0, 0x1000))
|
||||
tls.open()
|
||||
|
||||
usb.open()
|
||||
print('Initializing flash...')
|
||||
init_flash()
|
||||
|
||||
restart()
|
||||
print('Uploading firmware...')
|
||||
upload_fwext()
|
||||
|
||||
restart()
|
||||
print('Calibrating...')
|
||||
calibrate()
|
||||
|
||||
print('Init database...')
|
||||
init_db()
|
||||
|
||||
print('That\'s it, pairing\'s finished')
|
||||
|
|
@ -1,109 +0,0 @@
|
|||
|
||||
from prototype import *
|
||||
from tls97 import hs_key
|
||||
from hashlib import sha256
|
||||
from fastecdsa.encoding.der import DEREncoder
|
||||
from fastecdsa.curve import P256
|
||||
from fastecdsa.ecdsa import verify
|
||||
from fastecdsa.point import Point
|
||||
from fastecdsa.keys import get_public_key
|
||||
|
||||
blob4f=unhex('''
|
||||
4f0000000000000c000000100000100000000020000100f000010407000010000000100000000000009da
|
||||
6bb3eb1d4d1641811b0a2402ba5010d6d0f2f7ffd8debc7e7e68c31473333020102000020000000e00300
|
||||
00000000840acfea4e998b5302df52db54b7654b164a1057681149fcbb3ec7a559c80db20505030000000
|
||||
40000800000000000005c70f7ccce2fc2d7620f69da63548fc392877c88393e9c45327a10c21d46267f06
|
||||
0603000080040000800000000000005a5eeb284ee05ddae47ee27dc75fafaf09bc8b112a652bde4eab8af
|
||||
c61f2df75040305000000050000000300000000000e828eaff826a0454f6a50f60a36d5014372aaaf2621
|
||||
41e5ced9d0a0056907c20500bc011700000020000000ebfaf1f684cd4e4739e56588695ba19b515be4c16
|
||||
f3e89bfe6b33f59b209a26b00000000000000000000000000000000000000000000000000000000000000
|
||||
00000000003870b373e2a0c3b7b09c16cdb8bd5f04bfdfdd55583c67db236c5b522ad6b49000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
00000000000000000000000000000000000000000000000000000000460000003044022036a452cef79a1
|
||||
f146ca26dcf06eb58b333f95fab2d49eb89abbcb07c39dbe4c602200dc95d991f7f89e66ad8ee546619dc
|
||||
4262617fb813e6e53f4333bbe21fe705d3000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000000300a40117000000000
|
||||
1000001000000fcffffffffffffffffffffff00000000000000000000000001000000ffffffff00000000
|
||||
00000000000000000000000000000000000000000000000000000000000000004b60d2273e3cce3bf6b05
|
||||
3ccb0061d65bc86987655bdebb3e7933aaad835c65a000000000000000000000000000000000000000000
|
||||
00000000000000000000000000000096c298d84539a1f4a033eb2d817d0377f240a463e5e6bcf847422ce
|
||||
1f2d1176b000000000000000000000000000000000000000000000000000000000000000000000000f551
|
||||
bf376840b6cbce5e316b5733ce2b169e0f7c4aebe78e9b7f1afee242e34f0000000000000000000000000
|
||||
00000000000000000000000000000000000000000000000512563fcc2cab9f3849e17a7adfae6bcffffff
|
||||
ffffffffff00000000ffffffff00000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000ffffffffffffffffffffffff00000000000000000000000001000000ffffffff00000000
|
||||
0000000000000000000000000000000000000000000000000000000000000000
|
||||
''')
|
||||
|
||||
#skip 4f 0000 0000
|
||||
blob4f=blob4f[5:]
|
||||
|
||||
while len(blob4f) > 0:
|
||||
hdr, blob4f = blob4f[:4], blob4f[4:]
|
||||
id, l = unpack('<HH', hdr)
|
||||
p, blob4f = blob4f[:l], blob4f[l:]
|
||||
print('block %04x: %s' % (id, hexlify(p).decode()))
|
||||
|
||||
if id == 1:
|
||||
while len(p) > 0:
|
||||
d, align, hsh, p = p[:12], p[12:12+4], p[12+4:12+4+32], p[12+4+32:]
|
||||
if align != b'\0' * 4:
|
||||
raise Exception('align should be blank')
|
||||
m=sha256()
|
||||
m.update(d)
|
||||
if m.digest() != hsh:
|
||||
raise Exception('Hash mismatch')
|
||||
|
||||
print('block 1, blob: %s' % hexlify(d).decode())
|
||||
elif id == 5:
|
||||
hdr, p = p[:4+4], p[4+4:]
|
||||
|
||||
magic, keysz = unpack('<LL', hdr)
|
||||
|
||||
if magic != 0x17:
|
||||
raise Exception('Unexpected magic')
|
||||
|
||||
if keysz != 0x20:
|
||||
raise Exception('Unexpected key size')
|
||||
|
||||
x, p = p[:0x20], p[0x20:]
|
||||
x=int(hexlify(x[::-1]).decode(), 16)
|
||||
print('block 5, x=%x' % x)
|
||||
|
||||
nulls, p = p[:0x24], p[0x24:]
|
||||
if nulls != b'\0' * len(nulls):
|
||||
raise Exception('Nulls expected')
|
||||
|
||||
y, p = p[:0x20], p[0x20:]
|
||||
y=int(hexlify(y[::-1]).decode(), 16)
|
||||
print('block 5, y=%x' % y)
|
||||
|
||||
if not P256.is_point_on_curve( (x, y) ):
|
||||
raise Exception('pub key point is not on curve')
|
||||
|
||||
nulls, p = p[:0x4c], p[0x4c:]
|
||||
if nulls != b'\0' * len(nulls):
|
||||
raise Exception('Nulls expected')
|
||||
|
||||
ssz, p = p[:4], p[4:]
|
||||
ssz, = unpack('<L', ssz)
|
||||
signature, nulls = p[:ssz], p[ssz:]
|
||||
|
||||
if nulls != b'\0' * len(nulls):
|
||||
raise Exception('Nulls expected')
|
||||
|
||||
signature = DEREncoder().decode_signature(signature)
|
||||
msg=(pack('<LL', 0x17, 0x20) +
|
||||
unhexlify('%064x' % x)[::-1] +
|
||||
(b'\0'*0x24) +
|
||||
unhexlify('%064x' % y)[::-1] +
|
||||
(b'\0'*0x4c))
|
||||
|
||||
pub=get_public_key(hs_key(), P256)
|
||||
|
||||
if not verify(signature, msg, pub):
|
||||
raise Exception('Signature validation failed')
|
||||
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
|
||||
from util import unhex
|
||||
from .util import unhex
|
||||
|
||||
reset_blob=unhex('''
|
||||
06020000013920c0cdd8e7e68d6ef897ee686fbf657f83b9514341e1d3c0835a28c9cd1ccd0016644f74d
|
||||
96
proto97/calibrate.py
Normal file
96
proto97/calibrate.py
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
|
||||
from hashlib import sha256
|
||||
from binascii import hexlify, unhexlify
|
||||
from os.path import isfile
|
||||
from threading import Thread
|
||||
from struct import unpack, pack
|
||||
|
||||
from .tls import tls
|
||||
from .usb import usb
|
||||
from time import ctime
|
||||
from .sensor import write_hw_reg32, read_hw_reg32, identify_sensor
|
||||
from .flash import erase_flash, read_flash, get_fw_info, write_flash_all
|
||||
from .util import assert_status
|
||||
from .blobs import calibrate_prg
|
||||
|
||||
class Line():
|
||||
def __init__(self, blob):
|
||||
# what's with the rest of fields?
|
||||
self.u0, self.u1, self.line, self.frame, self.u2, self.u3, self.u4, self.u5 = unpack('<BBBBBBBB', blob[:8])
|
||||
self.data = blob[8:]
|
||||
|
||||
def serialize(self):
|
||||
return pack('<BBBBBBBB', self.u0, self.u1, self.line, self.frame, self.u2, self.u3, self.u4, self.u5) + self.data
|
||||
|
||||
def __repr__(self):
|
||||
return 'Line(line=%d, frame=%d)' % (self.line, self.frame)
|
||||
|
||||
def persist_calib_data(calib_data):
|
||||
start=read_flash(6, 0, 0x44)
|
||||
if start != b'\xff' * 0x44:
|
||||
if calib_data[:0x44] == start:
|
||||
print('Calibration data already matches the data on the flash.')
|
||||
return
|
||||
else:
|
||||
print('Calibration flash already written. Erasing.')
|
||||
erase_flash(6)
|
||||
|
||||
write_flash_all(6, 0, calib_data)
|
||||
|
||||
def calibrate():
|
||||
# no idea what this is:
|
||||
write_hw_reg32(0x8000205c, 7)
|
||||
if read_hw_reg32(0x80002080) != 2:
|
||||
raise Exception('Unexpected register value')
|
||||
|
||||
dev=identify_sensor()
|
||||
print('Sensor: %s' % dev.name)
|
||||
# ^ TODO -- what is the real reason to detect HW at this stage? -- likely it is required to construct calibrate_prg
|
||||
|
||||
fwi=get_fw_info(2)
|
||||
if fwi == None:
|
||||
raise Exception('No firmware detected')
|
||||
|
||||
print('FWExt version %d.%d (%s), %d modules' % (fwi.major, fwi.minor, ctime(fwi.buildtime), len(fwi.modules)))
|
||||
|
||||
if isfile('calib-data.bin'):
|
||||
with open('calib-data.bin', 'rb') as f:
|
||||
calib_data=f.read()
|
||||
print('Calibration data loaded from the file.')
|
||||
else:
|
||||
# TODO Properly construct calibrate_prg.
|
||||
# >>> 6f 000e 000000000000
|
||||
# <<< 0000 880d 0000 07000000
|
||||
# 0800 0000 9400 0e00 0300 0080 07000000 7e7f807f808080808080808080808080808080808080818081808180818080808080818081808080818081808180818081808180818081808180808081808180808081807f80808180808081808180818080808180818081808180818081808080818081808180818081808180818081808180818081808180818081808080808080808080807f807f807f807f7f7e7e
|
||||
# a400 0000 0800 0e00 0200 0000 00000000 0d007100
|
||||
# b400 0000 0800 0e00 0800 0080 db000000 00000000
|
||||
# c400 0000 0400 0e00 0500 0080 1c6f0400
|
||||
# d000 0000 9400 0e00 0700 0080 07000000 2b23203c2d182e1e30182e1c321d341d341e321c301e1e241e201f201d1c321a301e1c211e21341f1e202024201f1e20201f212221221d221e23341e1d1e1d20341f1d193b341c1d1e35201e201c20221f341c1e1e1c221f201d21201e1c1f34242221201f20221f201e241e241d2020221e2420231d221e211e1f1e1e341c321e3220301d2d302f2d2c2b23223a211c
|
||||
# 6c01 0000 1400 0e00 0f00 0080 05550007 7701002805720000080100020811e107
|
||||
# 8801 0000 0c00 0e00 1200 0080 07000000 7002 7800 7002 7800
|
||||
#
|
||||
# Empty reply:
|
||||
# >>> 6f 000a 000000000000
|
||||
# <<< 0000 880d 0000 00000000
|
||||
|
||||
rsp=tls.cmd(calibrate_prg)
|
||||
assert_status(rsp)
|
||||
print(rsp.hex())
|
||||
# ^ TODO check what the rest of the rsp means
|
||||
|
||||
calib_data=usb.read_82()
|
||||
print('len=%d' % len(calib_data))
|
||||
with open('calib-data.bin', 'wb') as f:
|
||||
f.write(calib_data)
|
||||
|
||||
lines=[calib_data[i:i+0x90+8] for i in range(0, len(calib_data), 0x90+8)] # TODO work out where "bytes per line" constant is comming from
|
||||
lines=[Line(i) for i in lines]
|
||||
frame4=[i.serialize() for i in lines if i.frame == 4] # why 4?
|
||||
frame4=b''.join(frame4)
|
||||
calib_data=pack('<H', len(frame4)) + frame4 + pack('<H', 0) # what's that 00000 in the end?
|
||||
calib_data=pack('<H', len(calib_data)) + sha256(calib_data).digest() + b'\0'*0x20 + calib_data
|
||||
calib_data=unhexlify('0250') + calib_data
|
||||
|
||||
persist_calib_data(calib_data)
|
||||
# no need to reboot
|
||||
|
||||
|
|
@ -1,12 +1,12 @@
|
|||
|
||||
from util import unhex
|
||||
from tls97 import tls
|
||||
from util import assert_status
|
||||
from .util import unhex
|
||||
from .tls import tls
|
||||
from .util import assert_status
|
||||
from struct import pack, unpack
|
||||
from binascii import hexlify, unhexlify
|
||||
from blobs import db_write_enable
|
||||
from flash import flush_changes
|
||||
from sid import *
|
||||
from .blobs import db_write_enable
|
||||
from .flash import flush_changes
|
||||
from .sid import *
|
||||
|
||||
class UserStorage():
|
||||
def __init__(self, dbid, name):
|
||||
|
|
@ -132,6 +132,14 @@ class Db():
|
|||
|
||||
return parse_user_storage(tls.cmd(pack('<BHH', 0x4b, dbid, len(name)) + name))
|
||||
|
||||
def new_user_storate(self):
|
||||
db.new_record(1, 4, 3, b'StgWindsor\0')
|
||||
|
||||
def get_storage_data(self):
|
||||
stg = self.get_user_storage(name='StgWindsor')
|
||||
rc = self.get_record_children(stg.dbid).children
|
||||
return [i['dbid'] for i in rc if i['type'] == 8] # 8 == "data" type
|
||||
|
||||
def get_user(self, dbid):
|
||||
return parse_user(tls.cmd(pack('<BHHH', 0x4a, dbid, 0, 0)))
|
||||
|
||||
|
|
@ -1,10 +1,10 @@
|
|||
|
||||
from tls97 import tls
|
||||
from .tls import tls
|
||||
from struct import pack, unpack
|
||||
from binascii import hexlify, unhexlify
|
||||
from util import assert_status, unhex
|
||||
from blobs import db_write_enable
|
||||
from hw_tables import flash_ic_table_lookup
|
||||
from .util import assert_status, unhex
|
||||
from .blobs import db_write_enable
|
||||
from .hw_tables import flash_ic_table_lookup
|
||||
|
||||
class FlashInfo():
|
||||
def __init__(self, ic, blocks, unknown0, blocksize, unknown1, partitions):
|
||||
|
|
@ -120,7 +120,7 @@ def write_flash_all(partition, ptr, buf):
|
|||
|
||||
def read_flash_all(partition, start, end):
|
||||
bs = 0x1000
|
||||
blocks = [db.read_flash(partition, addr, bs) for addr in range(start, end, bs)]
|
||||
blocks = [read_flash(partition, addr, bs) for addr in range(start, end, bs)]
|
||||
return b''.join(blocks)
|
||||
|
||||
def write_fw_signature(partition, signature):
|
||||
35
proto97/init_db.py
Normal file
35
proto97/init_db.py
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
|
||||
from struct import pack, unpack
|
||||
|
||||
from .db import db
|
||||
from .usb import usb
|
||||
from .tls import tls
|
||||
from .flash import read_flash
|
||||
|
||||
def machine_id_rec_value(b):
|
||||
b = b.encode('utf-16le')
|
||||
b = b + b'\0' * (0x94 - len(b))
|
||||
return pack('<HH', 0x102, len(b)) + b # 0x102 = Machine ID/GUID?
|
||||
|
||||
def init_db(machine_guid='e7260876-58db-4d27-8c40-8d13110d6a71'):
|
||||
stg=db.get_user_storage(name='StgWindsor')
|
||||
if stg == None:
|
||||
print('Creating new user storage object')
|
||||
db.new_user_storate()
|
||||
|
||||
rc = db.get_storage_data()
|
||||
|
||||
if rc == []:
|
||||
print('Creating host machine GUID record')
|
||||
stg=db.get_user_storage(name='StgWindsor')
|
||||
db.new_record(stg.dbid, 0x8, stg.dbid, machine_id_rec_value(machine_guid))
|
||||
rc = db.get_storage_data()
|
||||
|
||||
rc = db.get_record_value(rc[0]).value
|
||||
|
||||
if rc != machine_id_rec_value(machine_guid):
|
||||
u0, l = unpack('<HH', rc[:4])
|
||||
b=rc[4:4+l]
|
||||
b=b.decode('utf-16le')
|
||||
raise Exception('Machine GUID does not match the DB flash ownership record (%s).' % b)
|
||||
|
||||
|
|
@ -1,28 +1,26 @@
|
|||
|
||||
from tls97 import tls, psk_encryption_key, psk_validation_key, hs_key, crt_hardcoded
|
||||
from .tls import tls, psk_encryption_key, psk_validation_key, hs_key, crt_hardcoded
|
||||
from hashlib import sha256
|
||||
import hmac
|
||||
from struct import pack, unpack
|
||||
from binascii import hexlify, unhexlify
|
||||
from usb97 import usb
|
||||
from flash import write_flash, erase_flash, flush_changes, PartitionInfo, get_flash_info
|
||||
from sensor import reboot
|
||||
from .usb import usb
|
||||
from .flash import write_flash, erase_flash, flush_changes, PartitionInfo, get_flash_info
|
||||
from .sensor import reboot
|
||||
from Crypto.Random import get_random_bytes
|
||||
from Crypto.Cipher import AES
|
||||
from fastecdsa.encoding.der import DEREncoder
|
||||
from fastecdsa.curve import P256
|
||||
from fastecdsa.ecdsa import sign
|
||||
from fastecdsa.point import Point
|
||||
from fastecdsa.keys import gen_private_key, get_public_key
|
||||
from util import assert_status, unhex
|
||||
from blobs import reset_blob
|
||||
from .util import assert_status, unhex
|
||||
from .blobs import reset_blob
|
||||
|
||||
flash_layout_hardcoded=[
|
||||
# id type access offset size
|
||||
# lvl
|
||||
PartitionInfo(1, 4, 7, 0x00001000, 0x00001000), # cert store
|
||||
#PartitionInfo(2, 1, 2, 0x00002000, 0x0003e000), # xpfwext
|
||||
PartitionInfo(2, 1, 7, 0x00002000, 0x0003e000), # xpfwext
|
||||
PartitionInfo(2, 1, 2, 0x00002000, 0x0003e000), # xpfwext
|
||||
PartitionInfo(5, 5, 3, 0x00040000, 0x00008000), # ???
|
||||
PartitionInfo(6, 6, 3, 0x00048000, 0x00008000), # calibration data
|
||||
PartitionInfo(4, 3, 5, 0x00050000, 0x00030000), # template database
|
||||
|
|
@ -32,10 +30,7 @@ flash_layout_hardcoded=[
|
|||
def with_hdr(id, buf):
|
||||
return pack('<HH', id, len(buf)) + buf
|
||||
|
||||
client_private = gen_private_key(P256)
|
||||
client_public = get_public_key(client_private, P256)
|
||||
|
||||
def encrypt_key():
|
||||
def encrypt_key(client_private, client_public):
|
||||
x = unhexlify('%064x' % client_public.x)[::-1]
|
||||
y = unhexlify('%064x' % client_public.y)[::-1]
|
||||
d = unhexlify('%064x' % client_private)[::-1]
|
||||
|
|
@ -50,10 +45,7 @@ def encrypt_key():
|
|||
sig = hmac.new(psk_validation_key, c, sha256).digest()
|
||||
return b'\x02' + c + sig
|
||||
|
||||
tls.handle_priv(encrypt_key())
|
||||
|
||||
|
||||
def make_cert():
|
||||
def make_cert(client_public):
|
||||
msg=(pack('<LL', 0x17, 0x20) +
|
||||
unhexlify('%064x' % client_public.x)[::-1] +
|
||||
(b'\0'*0x24) +
|
||||
|
|
@ -63,7 +55,7 @@ def make_cert():
|
|||
s=DEREncoder().encode_signature(s[0], s[1])
|
||||
s=pack('<L', len(s)) + s
|
||||
msg = msg + s
|
||||
msg += b'\0'*(444 - len(msg)) # not sure this math is right
|
||||
msg += b'\0'*(444 - len(msg)) # FIXME not sure this math is right
|
||||
return msg
|
||||
|
||||
def serialize_flash_params(ic):
|
||||
|
|
@ -74,7 +66,7 @@ def serialize_partition(p):
|
|||
b = b + b'\0'*4 + sha256(b).digest()
|
||||
return b
|
||||
|
||||
def partition_flash(layout):
|
||||
def partition_flash(layout, client_public):
|
||||
info = get_flash_info()
|
||||
|
||||
print('Detected Flash IC: %s, %d bytes' % (info.ic.name, info.ic.size))
|
||||
|
|
@ -85,7 +77,7 @@ def partition_flash(layout):
|
|||
cmd = unhex('4f 0000 0000')
|
||||
cmd += with_hdr(0, serialize_flash_params(info.ic))
|
||||
cmd += with_hdr(1, b''.join([serialize_partition(p) for p in layout]))
|
||||
cmd += with_hdr(5, make_cert())
|
||||
cmd += with_hdr(5, make_cert(client_public))
|
||||
cmd += with_hdr(3, crt_hardcoded)
|
||||
rsp = tls.cmd(cmd)
|
||||
assert_status(rsp)
|
||||
|
|
@ -97,42 +89,42 @@ def partition_flash(layout):
|
|||
rsp = rsp[crt_len:]
|
||||
# ^ TODO - figure out what the rest of rsp means
|
||||
|
||||
#usb.trace_enabled=True
|
||||
#tls.trace_enabled=True
|
||||
def init_flash():
|
||||
assert_status(usb.cmd(reset_blob))
|
||||
|
||||
usb.open()
|
||||
assert_status(usb.cmd(reset_blob))
|
||||
client_private = gen_private_key(P256)
|
||||
client_public = get_public_key(client_private, P256)
|
||||
|
||||
partition_flash(flash_layout_hardcoded)
|
||||
partition_flash(flash_layout_hardcoded, client_public)
|
||||
|
||||
rsp=usb.cmd(unhex('01'))
|
||||
assert_status(rsp)
|
||||
# ^ get device info, contains firmware version which is needed to lookup pubkey for server cert validation
|
||||
rsp=usb.cmd(unhex('01'))
|
||||
assert_status(rsp)
|
||||
# ^ get device info, contains firmware version which is needed to lookup pubkey for server cert validation
|
||||
|
||||
rsp=usb.cmd(unhex('50'))
|
||||
# ^ TODO validate response
|
||||
# It should be signed by the firmware private key.
|
||||
# The corresponding pub key is hardcoded for each fw revision in the synaWudfBioUsb.dll.
|
||||
# for my device it is: x=f727653b4e16ce0665a6894d7f3a30d7d0a0be310d1292a743671fdf69f6a8d3,
|
||||
# y=a85538f8b6bec50d6eef8bd5f4d07a886243c58b2393948df761a84721a6ca94
|
||||
assert_status(rsp)
|
||||
rsp=rsp[2:]
|
||||
l,=unpack('<L', rsp[:4])
|
||||
tls.handle_ecdh(rsp[l-400:]) # not sure offsets are calculated this way
|
||||
rsp=usb.cmd(unhex('50'))
|
||||
# ^ TODO validate the response. It is very insecure to simply trust any device to do the auth.
|
||||
# It should be signed by the firmware private key.
|
||||
# The corresponding pub key is hardcoded for each fw revision in the synaWudfBioUsb.dll.
|
||||
# for my device it is: x=f727653b4e16ce0665a6894d7f3a30d7d0a0be310d1292a743671fdf69f6a8d3,
|
||||
# y=a85538f8b6bec50d6eef8bd5f4d07a886243c58b2393948df761a84721a6ca94
|
||||
assert_status(rsp)
|
||||
rsp=rsp[2:]
|
||||
l,=unpack('<L', rsp[:4])
|
||||
flush_changes()
|
||||
|
||||
flush_changes()
|
||||
tls.handle_ecdh(rsp[l-400:]) # FIXME not sure offsets are calculated this way
|
||||
tls.handle_priv(encrypt_key(client_private, client_public))
|
||||
tls.open()
|
||||
|
||||
tls.open()
|
||||
# Wipe newly created partitions clean
|
||||
erase_flash(1)
|
||||
erase_flash(2)
|
||||
erase_flash(5)
|
||||
erase_flash(6)
|
||||
erase_flash(4)
|
||||
|
||||
# Wipe newly created partitions clean
|
||||
erase_flash(1)
|
||||
erase_flash(2)
|
||||
erase_flash(5)
|
||||
erase_flash(6)
|
||||
erase_flash(4)
|
||||
# Persist certs and keys on cert partition.
|
||||
write_flash(1, 0, tls.makeTlsFlash())
|
||||
|
||||
# Persist certs and keys on cert partition.
|
||||
write_flash(1, 0, tls.makeTlsFlash())
|
||||
|
||||
# Reboot
|
||||
reboot()
|
||||
# Reboot
|
||||
reboot()
|
||||
|
|
@ -1,13 +1,13 @@
|
|||
|
||||
from tls97 import tls
|
||||
from usb97 import usb
|
||||
from db97 import db, subtype_to_string
|
||||
from .tls import tls
|
||||
from .usb import usb
|
||||
from .db import db, subtype_to_string
|
||||
from time import sleep
|
||||
from struct import pack, unpack
|
||||
from binascii import hexlify, unhexlify
|
||||
from util import assert_status, unhex
|
||||
from hw_tables import dev_info_lookup
|
||||
from blobs import identify_prg, enroll_prg
|
||||
from .util import assert_status, unhex
|
||||
from .hw_tables import dev_info_lookup
|
||||
from .blobs import identify_prg, enroll_prg, reset_blob
|
||||
|
||||
|
||||
def glow_start_scan():
|
||||
|
|
@ -279,6 +279,11 @@ def write_hw_reg32(addr, val):
|
|||
def reboot():
|
||||
assert_status(tls.cmd(unhex('050200')))
|
||||
|
||||
def factory_reset():
|
||||
assert_status(usb.cmd(reset_blob))
|
||||
assert_status(usb.cmd(b'\x10' + b'\0'*0x61))
|
||||
reboot()
|
||||
|
||||
def identify_sensor():
|
||||
rsp=tls.cmd(b'\x75')
|
||||
assert_status(rsp)
|
||||
|
|
@ -3,7 +3,7 @@ import hmac
|
|||
import sys
|
||||
from hashlib import sha256, md5, sha1
|
||||
from binascii import *
|
||||
from usb97 import unhex, usb
|
||||
from .usb import unhex, usb
|
||||
from struct import pack, unpack
|
||||
from Crypto.Cipher import AES
|
||||
from Crypto.Random import get_random_bytes
|
||||
|
|
@ -12,7 +12,7 @@ from fastecdsa.point import Point
|
|||
from fastecdsa.keys import gen_private_key, get_public_key
|
||||
from fastecdsa.ecdsa import sign
|
||||
from fastecdsa.encoding.der import DEREncoder
|
||||
from util import assert_status
|
||||
from .util import assert_status
|
||||
import pickle
|
||||
|
||||
|
||||
|
|
@ -91,6 +91,9 @@ class Tls():
|
|||
|
||||
def __init__(self, usb):
|
||||
self.usb = usb
|
||||
self.reset()
|
||||
|
||||
def reset(self):
|
||||
self.trace_enabled = False
|
||||
self.secure_rx = False
|
||||
self.secure_tx = False
|
||||
46
proto97/upload_fwext.py
Normal file
46
proto97/upload_fwext.py
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
|
||||
from binascii import hexlify, unhexlify
|
||||
from time import ctime
|
||||
|
||||
from .tls import tls
|
||||
from .usb import usb
|
||||
from .sensor import reboot, write_hw_reg32, read_hw_reg32, identify_sensor
|
||||
from .flash import flush_changes, read_flash, erase_flash, write_flash_all, write_fw_signature, get_fw_info
|
||||
from .util import assert_status
|
||||
|
||||
def upload_fwext():
|
||||
# no idea what this is:
|
||||
write_hw_reg32(0x8000205c, 7)
|
||||
if read_hw_reg32(0x80002080) != 2:
|
||||
raise Exception('Unexpected register value')
|
||||
|
||||
dev=identify_sensor()
|
||||
print('Sensor: %s' % dev.name)
|
||||
# ^ TODO -- what is the real reason to detect HW at this stage?
|
||||
# just a guess: perhaps it is used to construct fwext filename
|
||||
|
||||
with open('6_07f_lenovo_mis.xpfwext', 'rb') as f:
|
||||
fwext=f.read()
|
||||
|
||||
fwext=fwext[fwext.index(b'\x1a')+1:]
|
||||
fwext, signature = fwext[:-0x100], fwext[-0x100:]
|
||||
|
||||
# get fwext header info
|
||||
rsp=tls.cmd(unhexlify('4302')) # should fail 'cause no fwext uploaded yet
|
||||
|
||||
fwi=get_fw_info(2)
|
||||
if fwi != None:
|
||||
raise Exception('FW is already present (version %d.%d (%s))' % (fwi.major, fwi.minor, ctime(fwi.buildtime)))
|
||||
|
||||
#flush_changes()
|
||||
write_flash_all(2, 0, fwext)
|
||||
write_fw_signature(2, signature)
|
||||
|
||||
fwi=get_fw_info(2)
|
||||
if fwi == None:
|
||||
raise Exception('No firmware detected')
|
||||
|
||||
print('Loaded FWExt version %d.%d (%s), %d modules' % (fwi.major, fwi.minor, ctime(fwi.buildtime), len(fwi.modules)))
|
||||
|
||||
# Reboot
|
||||
reboot()
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
|
||||
import usb.core as ucore
|
||||
from binascii import *
|
||||
from util import assert_status, unhex
|
||||
from .util import assert_status, unhex
|
||||
from struct import unpack
|
||||
from usb.util import claim_interface, release_interface
|
||||
from queue import Queue
|
||||
16
prototype.py
16
prototype.py
|
|
@ -1,14 +1,10 @@
|
|||
|
||||
from util import assert_status
|
||||
from time import sleep
|
||||
from struct import pack, unpack
|
||||
from binascii import hexlify, unhexlify
|
||||
from tls97 import tls
|
||||
from usb97 import usb, unhex
|
||||
from sensor import enroll, identify
|
||||
from db97 import db
|
||||
from flash import read_flash
|
||||
from sid import *
|
||||
from proto97.tls import tls
|
||||
from proto97.usb import usb
|
||||
from proto97.db import db
|
||||
from proto97.flash import read_flash
|
||||
from proto97.sensor import *
|
||||
from proto97.sid import *
|
||||
|
||||
def open97():
|
||||
usb.open()
|
||||
|
|
|
|||
|
|
@ -1,9 +0,0 @@
|
|||
|
||||
from usb97 import usb
|
||||
from sensor import reboot
|
||||
|
||||
#usb.trace_enabled=True
|
||||
#tls.trace_enabled=True
|
||||
|
||||
usb.open()
|
||||
reboot()
|
||||
|
|
@ -1,280 +0,0 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
import re
|
||||
from struct import unpack
|
||||
from binascii import unhexlify, hexlify
|
||||
|
||||
def unhex(x):
|
||||
return unhexlify(re.sub('\W', '', x))
|
||||
|
||||
enroll_prg=unhex('''
|
||||
02980000002300000020000800002000800000010032007000000000802020050024200000502077362820010030200100082170000c210
|
||||
000482102004c210000582000005c20000060200000682005006c20012970200121742001887820018084202000942001809c200902a020
|
||||
0b19b4200000b8203b04bc201400c0200200c4200100c82002003300100000000080cc200000f503d0200000a1013200440000000080dc2
|
||||
0e803e0206401e420d002e8200001f0200500f8200500fc200000b8203b0000080400140800000808000008080000140830000808000014
|
||||
0831001c081a0032000c0000000080501101004c1126003400080310071d10071d10071d10071d10071c01065810080101000007c8078c0
|
||||
6100000204f80007f000003070107010c07032c08fc80095a800afc08fb800b5a095b800afb08fa800b5b095c800afa08f9800b5c095d80
|
||||
0af908f8800b5d095e800af808f7800b5e095f800af708f6800b5f0960800af608f5800b600961800af508f4800b610962800af408f3800
|
||||
b620963800af308f2800b630964800af208f1800b640965800af108f0800b650966800af008ef800b660967800aef08ee800b670968800a
|
||||
ee08ed800b68096c800aed08ec800b6c096d800aec08eb800b6d096e800aeb08ea800b6e096f800aea08e9800b6f0970800ae908e8800b7
|
||||
00971800ae808e7800b710972800ae708e6800b720973800ae608e5800b730974800ae508e4800b740975800ae408e3800b750976800ae3
|
||||
08e2800b760977800ae208e1800b770978800ae108e0800b780979800ae008df800b79097a800adf08de800b7a097b800ade08dd800b7b0
|
||||
97c800add08dc800b7c097d800adc08db800b7d097e800adb08da800b7e097f800ada08d9800b7f0980800ad908d8800b800981800ad808
|
||||
d7800b810982800ad708d6800b820983800ad608d5800b830984800ad508d4800b840985800ad408d3800b850986800ad308d2800b86098
|
||||
7800ad208d1800b870988800ad108d0800b880989800ad008cf800b89098a800acf08ce800b8a098b800ace08cd800b8b098c800acd08cc
|
||||
800b8c098d800acc08cb800b8d098e800acb08ca800b8e098f800aca08c9800b8f0990800ac908c8800b900991800ac808c7800b9109928
|
||||
00ac708c6800b920993800ac608c5800b930994800ac508c4800b940995800ac408c3800b950996800ac308c2800b960997800ac208c180
|
||||
0b970998800ac108c0800b980999800ac008bf800b99099a800abf08be800b9a099b800abe08bd800b9b099c800abd08bc800b9c099d800
|
||||
abc08bb800b9d099e800abb08ba800b9e099f800aba08b9800b9f09a0800ab908b8800ba00801800ab808b7800a010802800ab708b6800a
|
||||
020803800ab608b5800a030804802003070404020000000000002f000400900000002900040000000000350004001000000017000000260
|
||||
02800fbb20f00f2220f00300000006001020040010a00018000000a0200000b19000050c360ea010910002e001c00020018002300000090
|
||||
0090004d01000090017c013c323232640a02013000cc0103000000ff0000001d000003ff00000025000003ff00000022000003101112131
|
||||
415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b
|
||||
4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f8081828
|
||||
38485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f2b23203c2d182e1e30182e1c321d341d341e321c301e1e241e201f
|
||||
201d1c321a301e1c211e21341f1e202024201f1e20201f212221221d221e23341e1d1e1d20341f1d193b341c1d1e35201e201c20221f341
|
||||
c1e1e1c221f201d21201e1c1f34242221201f20221f201e241e241d2020221e2420231d221e211e1f1e1e341c321e3220301d2d302f2d2c
|
||||
2b23223a211c7e7f807f8080808080808080808080808080808080808180818081808180808080808180818080808180818081808180818
|
||||
08180818081808180808081808180808081807f808081808080818081808180808081808180818081808180818080808180818081808180
|
||||
81808180818081808180818081808180818081808080808080808080807f807f807f807f7f7e7e
|
||||
''')
|
||||
|
||||
short=unhex('''
|
||||
029000010023000000320074000000008000200000502077322820020030200000082110000c211000482105004c21050020200000242
|
||||
00000582000005c20000060204300682014006c2001247020012c842020008c20900190202c01942001809c200902a0200b19b4200000
|
||||
b8203a00bc201400c0200200c4200200c82008003300100000000080cc200000a101d0200000a10132004c0000000080dc20e803e0206
|
||||
401e420d002e8200001ec201400f0200500fc200000b8203a00140800000008040008080000080802001408300008080300140831001c
|
||||
081a004c112400501100002a00080020010100100100002c002800802080200000000000013f4000000000080f080f00000000279c100
|
||||
0279c10000000000000000000340040000300000007160000240a59085a0701c9500aaa07010ada08db0701c9460b2107010800800a00
|
||||
88c9590a5a07010aa908aa0701c91f0ac900000c04010000000029000400000000003500040000000000150008000000000020280000
|
||||
''')
|
||||
|
||||
calibrate=unhex('''
|
||||
02980061032300000020000800002000800000010032007000000000802020050024200000502077362820010030200100082170000c2
|
||||
10000482102004c210000582000005c20000060200000682005006c20012970200121742001887820018084202000942001809c200902
|
||||
a0200b19b4200000b8203b04bc201400c0200200c4200100c82002003300100000000080cc200000f503d0200000a1013200440000000
|
||||
080dc20e803e0206401e420d002e8200001f0200500f8200500fc200000b8203b00000804001408000008080000080800001408300008
|
||||
080000140831001c081a0032000c0000000080501101004c1126003400080310071d10071d10071d10071d10071c01065810080101000
|
||||
007c8078c06100000204f80007f000003070107010c07032c08fc80095a800afc08fb800b5a095b800afb08fa800b5b095c800afa08f9
|
||||
800b5c095d800af908f8800b5d095e800af808f7800b5e095f800af708f6800b5f0960800af608f5800b600961800af508f4800b61096
|
||||
2800af408f3800b620963800af308f2800b630964800af208f1800b640965800af108f0800b650966800af008ef800b660967800aef08
|
||||
ee800b670968800aee08ed800b68096c800aed08ec800b6c096d800aec08eb800b6d096e800aeb08ea800b6e096f800aea08e9800b6f0
|
||||
970800ae908e8800b700971800ae808e7800b710972800ae708e6800b720973800ae608e5800b730974800ae508e4800b740975800ae4
|
||||
08e3800b750976800ae308e2800b760977800ae208e1800b770978800ae108e0800b780979800ae008df800b79097a800adf08de800b7
|
||||
a097b800ade08dd800b7b097c800add08dc800b7c097d800adc08db800b7d097e800adb08da800b7e097f800ada08d9800b7f0980800a
|
||||
d908d8800b800981800ad808d7800b810982800ad708d6800b820983800ad608d5800b830984800ad508d4800b840985800ad408d3800
|
||||
b850986800ad308d2800b860987800ad208d1800b870988800ad108d0800b880989800ad008cf800b89098a800acf08ce800b8a098b80
|
||||
0ace08cd800b8b098c800acd08cc800b8c098d800acc08cb800b8d098e800acb08ca800b8e098f800aca08c9800b8f0990800ac908c88
|
||||
00b900991800ac808c7800b910992800ac708c6800b920993800ac608c5800b930994800ac508c4800b940995800ac408c3800b950996
|
||||
800ac308c2800b960997800ac208c1800b970998800ac108c0800b980999800ac008bf800b99099a800abf08be800b9a099b800abe08b
|
||||
d800b9b099c800abd08bc800b9c099d800abc08bb800b9d099e800abb08ba800b9e099f800aba08b9800b9f09a0800ab908b8800ba008
|
||||
01800ab808b7800a010802800ab708b6800a020803800ab608b5800a030804802003070404020000000000002f0004009000000029000
|
||||
400000000003500040010000000170000003000cc0103000000ff0000001d000003ff00000025000003ff000000220000031011121314
|
||||
15161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4
|
||||
b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f8081
|
||||
82838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f2b23203c2d182e1e30182e1c321d341d341e321c301e1e241
|
||||
e201f201d1c321a301e1c211e21341f1e202024201f1e20201f212221221d221e23341e1d1e1d20341f1d193b341c1d1e35201e201c20
|
||||
221f341c1e1e1c221f201d21201e1c1f34242221201f20221f201e241e241d2020221e2420231d221e211e1f1e1e341c321e3220301d2
|
||||
d302f2d2c2b23223a211c7e7f807f80808080808080808080808080808080808081808180818081808080808081808180808081808180
|
||||
8180818081808180818081808180808081808180808081807f80808180808081808180818080808180818081808180818081808080818
|
||||
081808180818081808180818081808180818081808180818081808080808080808080807f807f807f807f7f7e7e
|
||||
''')
|
||||
codes={}
|
||||
codes[0x0] = "No Operation"
|
||||
codes[0x1] = "Swipe"
|
||||
codes[0x2] = "Timeslot Configuration"
|
||||
codes[0x3] = "Register"
|
||||
codes[0x4] = "Register Set 32"
|
||||
codes[0x5] = "Register Operation 32"
|
||||
codes[0x6] = "Security"
|
||||
codes[0x7] = "WOE"
|
||||
codes[0x8] = "Motion 1"
|
||||
codes[0xa] = "CPUCLK"
|
||||
codes[0xb] = "Motion 2"
|
||||
codes[0xc] = "Calibration Block"
|
||||
codes[0xd] = "Sweep"
|
||||
codes[0xe] = "Zone Configuration"
|
||||
codes[0xf] = "Zones Per Sweep"
|
||||
codes[0x10] = "Lines Per Sweep Iteration"
|
||||
codes[0x11] = "Lines Per Sweep"
|
||||
codes[0x12] = "Total Zones"
|
||||
codes[0x13] = "CAL WOE Ctrl"
|
||||
codes[0x14] = "Cal WOE Mask"
|
||||
codes[0x15] = "BW Reduciton"
|
||||
codes[0x16] = "AGC"
|
||||
codes[0x17] = "Reply Configuration"
|
||||
codes[0x18] = "Motion 3"
|
||||
codes[0x19] = "WOVAR"
|
||||
codes[0x1a] = "Block MOde"
|
||||
codes[0x1b] = "Bit Reduction"
|
||||
codes[0x1c] = "Motion 4"
|
||||
codes[0x1d] = "Calibration WOENF"
|
||||
codes[0x1e] = "Calibration"
|
||||
codes[0x1f] = "Zone Configuration A"
|
||||
codes[0x20] = "Set Register 32"
|
||||
codes[0x21] = "Register Operation 32A"
|
||||
codes[0x22] = "Fingerprint Buffering"
|
||||
codes[0x23] = "Reply Config + Timeslot Table"
|
||||
codes[0x24] = "Baseline"
|
||||
codes[0x25] = "SO Alternate"
|
||||
codes[0x26] = "Finger Detect"
|
||||
codes[0x27] = "Finger Detect Sample Register"
|
||||
codes[0x28] = "Finger Detect Scan Registers"
|
||||
codes[0x29] = "Timeslot Table Offset"
|
||||
codes[0x2a] = "ACM Config"
|
||||
codes[0x2b] = "ACM Control"
|
||||
codes[0x2c] = "CEM Config"
|
||||
codes[0x2d] = "CEM Control"
|
||||
codes[0x2e] = "Image Reconstruction"
|
||||
codes[0x2f] = "2D"
|
||||
codes[0x30] = "Line Update"
|
||||
codes[0x31] = "FDetect Timeslot Table"
|
||||
codes[0x32] = "Register List 16"
|
||||
codes[0x33] = "Register list 32"
|
||||
codes[0x34] = "Timeslot Table 2D"
|
||||
codes[0x35] = "Timeslot Table Offset for Finger Detect"
|
||||
codes[0x36] = "Security Aligned"
|
||||
codes[0x37] = "WOF2"
|
||||
codes[0x38] = "WOE WOF"
|
||||
codes[0x39] = "Navigation"
|
||||
codes[0x3a] = "WOE WOF2 Version2"
|
||||
codes[0x3b] = "Cal WOE WOF2"
|
||||
codes[0x3c] = "Event Signal"
|
||||
codes[0x3d] = "IFS Frame Stats"
|
||||
codes[0x3e] = "SNR Method 4"
|
||||
codes[0x3f] = "WOE WOF2 Version 3"
|
||||
codes[0x40] = "Calibrate WOE WOF2 Version 3"
|
||||
codes[0x41] = "Finger Detect Ratchet"
|
||||
codes[0x42] = "Data Encoder"
|
||||
codes[0x43] = "Line Update Transform"
|
||||
codes[0x44] = "Line Update InterLeave"
|
||||
codes[0x45] = "SO Table Values for Macros"
|
||||
codes[0x46] = "Timeslot Macro Definitions"
|
||||
codes[0x47] = "Enable ASP Feature"
|
||||
codes[0x48] = "Baseline Frame"
|
||||
codes[0x49] = "Rx Select"
|
||||
codes[0xffff] = "Unknown"
|
||||
|
||||
def decode_tt_inst(b):
|
||||
if b[0] == 0:
|
||||
return (0, 1, 'NOOP')
|
||||
elif b[0] == 1:
|
||||
return (1, 1, 'End of Table')
|
||||
elif b[0] == 2:
|
||||
return (2, 1, 'Return')
|
||||
elif b[0] == 3:
|
||||
return (3, 1, 'Clear SO')
|
||||
elif b[0] == 4:
|
||||
return (4, 1, 'End of Data')
|
||||
elif b[0] == 6:
|
||||
return (6, 2, 'Enable Rx 0x%02x' % b[1])
|
||||
elif b[0] == 7:
|
||||
return (7, 2, 'Idle Rx 0x%03x' % (0x100 if b[1] == 0 else b[1]))
|
||||
elif b[0] & 0xfe == 8:
|
||||
return (8, 2, 'Enable SO 0x%03x' % ((b[0] & 1) << 8 | b[1]) )
|
||||
elif b[0] & 0xfe == 0xa:
|
||||
return (9, 2, 'Disable SO 0x%03x' % ((b[0] & 1) << 8 | b[1]) )
|
||||
elif b[0] & 0xfc == 0xc:
|
||||
return (0xa, 1, 'Interrupt %x' % (b[0] & 3))
|
||||
elif b[0] & 0xf8 == 0x10:
|
||||
return (0xb, 3, 'Call rx_inc=%d, addr=%x, repeat=%d' % (b[0] & 7, b[1] << 2, 0x100 if b[2] == 0 else b[2]))
|
||||
elif b[0] & 0xe0 == 0x20:
|
||||
return (0xc, 1, 'Features %02x' % (b[0] & 0x1f)) # TODO check how features are converted to op args
|
||||
elif b[0] & 0xc0 == 0x40:
|
||||
reg=b[0] & 0x3f
|
||||
reg=reg*4 + 0x80002000
|
||||
val=b[1] | (b[2] << 8)
|
||||
return (0xd, 3, 'Register Write *0x%08x = 0x%04x' % (reg, val))
|
||||
elif b[0] & 0xc0 == 0x80:
|
||||
return (0xe, 1, 'Sample %x, %x' % ((b[0] & 0x38) >> 3, b[0] & 7 ))
|
||||
elif b[0] & 0xc0 == 0xc0:
|
||||
return (0xf, 2, 'Sample Repeat %x, %x, repeat=%x' % ( (b[0] & 0x38) >> 3, b[0] & 7, 0x100 if b[1] == 0 else b[1] ))
|
||||
elif b[0] == 5:
|
||||
return (5, 2, 'Marco %02x' % b[1])
|
||||
else:
|
||||
raise Exception('Unhandled instruction %02x' % b[0])
|
||||
|
||||
|
||||
|
||||
def decode_tt(b):
|
||||
pc=0
|
||||
while len(b) > 0:
|
||||
(op, sz, txt) = decode_tt_inst(b)
|
||||
if sz > len(b):
|
||||
raise Exception('Truncated instruction')
|
||||
print('%04x: %-6s %s' % (pc, hexlify(b[:sz]).decode(), txt))
|
||||
b = b[sz:]
|
||||
pc += sz
|
||||
|
||||
#b=enroll_prg[5:]
|
||||
#b=short[5:]
|
||||
def dump_prg(b):
|
||||
while len(b) > 0:
|
||||
(typ, sz), b = unpack('<HH', b[:4]), b[4:]
|
||||
p, b = b[:sz], b[sz:]
|
||||
if typ == 0x20:
|
||||
addr, val = unpack('<LL', p)
|
||||
print('Set Register 32:')
|
||||
print(' *0x%08x = 0x%08x' % (addr, val))
|
||||
elif typ == 0x32:
|
||||
print('Set Registers 16:')
|
||||
(base,), p = unpack('<L', p[:4]), p[4:]
|
||||
while len(p) > 0:
|
||||
(off, val), p = unpack('<HH', p[:4]), p[4:]
|
||||
print(' *0x%08x = 0x%04x' % (off + base, val))
|
||||
elif typ == 0x33:
|
||||
print('Set Registers 32:')
|
||||
(base,), p = unpack('<L', p[:4]), p[4:]
|
||||
while len(p) > 0:
|
||||
(off, val), p = unpack('<HL', p[:6]), p[6:]
|
||||
print(' *0x%08x = 0x%08x' % (off + base, val))
|
||||
elif typ == 0x34:
|
||||
print('Timeslot Table 2D:')
|
||||
decode_tt(p)
|
||||
#print('%04x (%20s): %s' % (typ, codes[typ], hexlify(p)))
|
||||
else:
|
||||
print('%04x (%20s): (0x%x bytes) %s' % (typ, codes[typ], len(p), hexlify(p).decode()))
|
||||
|
||||
# rdata.bin is a .rdata segment of synaWudfBioUsb.dll
|
||||
with open('rdata.bin', 'rb') as f:
|
||||
rdata=f.read()
|
||||
|
||||
|
||||
rdata_vma=0x18012d000
|
||||
#0x18012D7B8
|
||||
|
||||
def block(addr, size):
|
||||
addr -= rdata_vma
|
||||
return rdata[addr:addr+size]
|
||||
|
||||
def read16(addr):
|
||||
return unpack('<H', block(addr, 2))[0]
|
||||
|
||||
def read64(addr):
|
||||
return unpack('<Q', block(addr, 8))[0]
|
||||
|
||||
def dump_table(base):
|
||||
while True:
|
||||
sz=read16(base)
|
||||
addr=read64(base+2)
|
||||
|
||||
if sz == 0 or addr == 0:
|
||||
break
|
||||
|
||||
print('*** Prog at %016x, %d bytes' % (addr, sz))
|
||||
dump_prg(block(addr, sz))
|
||||
base+=2+8
|
||||
|
||||
def dump_all_tables(ptr):
|
||||
while True:
|
||||
addr = read64(ptr)
|
||||
if addr == 0:
|
||||
break
|
||||
dump_table(read64(addr+0x34))
|
||||
ptr += 8
|
||||
|
||||
#dump_all_tables(0x1801BF0A0)
|
||||
|
||||
#dump_prg(calibrate[5:])
|
||||
dump_prg(enroll_prg[5:])
|
||||
|
||||
|
|
@ -1,52 +0,0 @@
|
|||
|
||||
from binascii import hexlify, unhexlify
|
||||
from time import ctime
|
||||
|
||||
from tls97 import tls
|
||||
from usb97 import usb
|
||||
from sensor import reboot, write_hw_reg32, read_hw_reg32, identify_sensor
|
||||
from flash import flush_changes, read_flash, erase_flash, write_flash_all, write_fw_signature, get_fw_info
|
||||
from util import assert_status
|
||||
|
||||
|
||||
with open('6_07f_lenovo_mis.xpfwext', 'rb') as f:
|
||||
fwext=f.read()
|
||||
|
||||
fwext=fwext[fwext.index(b'\x1a')+1:]
|
||||
fwext, signature = fwext[:-0x100], fwext[-0x100:]
|
||||
|
||||
#usb.trace_enabled=True
|
||||
#tls.trace_enabled=True
|
||||
|
||||
usb.open()
|
||||
tls.parseTlsFlash(read_flash(1, 0, 0x1000))
|
||||
tls.open()
|
||||
|
||||
# no idea what this is:
|
||||
write_hw_reg32(0x8000205c, 7)
|
||||
if read_hw_reg32(0x80002080) != 2:
|
||||
raise Exception('Unexpected register value')
|
||||
|
||||
dev=identify_sensor()
|
||||
print('Sensor: %s' % dev.name)
|
||||
# ^ TODO -- what is the real reason to detect HW at this stage?
|
||||
|
||||
# get fwext header info
|
||||
rsp=tls.cmd(unhexlify('4302')) # should fail 'cause no fwext uploaded yet
|
||||
|
||||
fwi=get_fw_info(2)
|
||||
if fwi != None:
|
||||
raise Exception('FW is already present (version %d.%d (%s))' % (fwi.major, fwi.minor, ctime(fwi.buildtime)))
|
||||
|
||||
#flush_changes()
|
||||
write_flash_all(2, 0, fwext)
|
||||
write_fw_signature(2, signature)
|
||||
|
||||
fwi=get_fw_info(2)
|
||||
if fwi == None:
|
||||
raise Exception('No firmware detected')
|
||||
|
||||
print('Loaded FWExt version %d.%d (%s), %d modules' % (fwi.major, fwi.minor, ctime(fwi.buildtime), len(fwi.modules)))
|
||||
|
||||
# Reboot
|
||||
reboot()
|
||||
Loading…
Reference in a new issue