Flash partition works!
This commit is contained in:
parent
828aa54618
commit
974cb1a7c1
4 changed files with 107 additions and 36 deletions
7
db97.py
7
db97.py
|
|
@ -268,3 +268,10 @@ class Db():
|
||||||
|
|
||||||
return rsp[8:8+sz]
|
return rsp[8:8+sz]
|
||||||
|
|
||||||
|
def write_flash(self, which, addr, buf):
|
||||||
|
self.tls.cmd(wtf_hardcoded)
|
||||||
|
cmd = pack('<BBBHLL', 0x41, which, 1, 0, addr, len(buf)) + buf
|
||||||
|
rsp=self.tls.cmd(cmd)
|
||||||
|
assert_status(rsp)
|
||||||
|
self.flush_changes()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,22 +8,20 @@ from fastecdsa.ecdsa import verify
|
||||||
from fastecdsa.point import Point
|
from fastecdsa.point import Point
|
||||||
from fastecdsa.keys import get_public_key
|
from fastecdsa.keys import get_public_key
|
||||||
|
|
||||||
#4f 0000 0000
|
|
||||||
|
|
||||||
blob4f=unhex('''
|
blob4f=unhex('''
|
||||||
00000c000000100000100000000020000100f000010407000010000000100000000000009da
|
4f0000000000000c000000100000100000000020000100f000010407000010000000100000000000009da
|
||||||
6bb3eb1d4d1641811b0a2402ba5010d6d0f2f7ffd8debc7e7e68c31473333020102000020000000e00300
|
6bb3eb1d4d1641811b0a2402ba5010d6d0f2f7ffd8debc7e7e68c31473333020102000020000000e00300
|
||||||
00000000840acfea4e998b5302df52db54b7654b164a1057681149fcbb3ec7a559c80db20505030000000
|
00000000840acfea4e998b5302df52db54b7654b164a1057681149fcbb3ec7a559c80db20505030000000
|
||||||
40000800000000000005c70f7ccce2fc2d7620f69da63548fc392877c88393e9c45327a10c21d46267f06
|
40000800000000000005c70f7ccce2fc2d7620f69da63548fc392877c88393e9c45327a10c21d46267f06
|
||||||
0603000080040000800000000000005a5eeb284ee05ddae47ee27dc75fafaf09bc8b112a652bde4eab8af
|
0603000080040000800000000000005a5eeb284ee05ddae47ee27dc75fafaf09bc8b112a652bde4eab8af
|
||||||
c61f2df75040305000000050000000300000000000e828eaff826a0454f6a50f60a36d5014372aaaf2621
|
c61f2df75040305000000050000000300000000000e828eaff826a0454f6a50f60a36d5014372aaaf2621
|
||||||
41e5ced9d0a0056907c20500bc01170000002000000000b0330e8b22509dd47b3bc2b48540d5bf8946097
|
41e5ced9d0a0056907c20500bc011700000020000000ebfaf1f684cd4e4739e56588695ba19b515be4c16
|
||||||
678663c23a04ca43911567300000000000000000000000000000000000000000000000000000000000000
|
f3e89bfe6b33f59b209a26b00000000000000000000000000000000000000000000000000000000000000
|
||||||
000000000069ebc98290a346b0b7be5bb697c24c653ee885e12f497bf44cdf563f7f26af0c00000000000
|
00000000003870b373e2a0c3b7b09c16cdb8bd5f04bfdfdd55583c67db236c5b522ad6b49000000000000
|
||||||
0000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
0000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||||
000000000000000000000000000000000000000000000000000000004600000030440220593e87ba9cd31
|
00000000000000000000000000000000000000000000000000000000460000003044022036a452cef79a1
|
||||||
4bbfddb3feaa2392bd23906d0f5191a3f2a886c4e87d55ac469022025fb00eaa8b29896ec891d7fc6f51c
|
f146ca26dcf06eb58b333f95fab2d49eb89abbcb07c39dbe4c602200dc95d991f7f89e66ad8ee546619dc
|
||||||
7dacaba244c4987b772ce221a6f7028c59000000000000000000000000000000000000000000000000000
|
4262617fb813e6e53f4333bbe21fe705d3000000000000000000000000000000000000000000000000000
|
||||||
0000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
0000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||||
0000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
0000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||||
0000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
0000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
|
@ -40,6 +38,9 @@ ffffffffff00000000ffffffff000000000000000000000000000000000000000000000000000000
|
||||||
0000000000000000000000000000000000000000000000000000000000000000
|
0000000000000000000000000000000000000000000000000000000000000000
|
||||||
''')
|
''')
|
||||||
|
|
||||||
|
#skip 4f 0000 0000
|
||||||
|
blob4f=blob4f[5:]
|
||||||
|
|
||||||
while len(blob4f) > 0:
|
while len(blob4f) > 0:
|
||||||
hdr, blob4f = blob4f[:4], blob4f[4:]
|
hdr, blob4f = blob4f[:4], blob4f[4:]
|
||||||
id, l = unpack('<HH', hdr)
|
id, l = unpack('<HH', hdr)
|
||||||
|
|
|
||||||
|
|
@ -4,11 +4,14 @@ from tls97 import *
|
||||||
from hashlib import sha256
|
from hashlib import sha256
|
||||||
from struct import pack
|
from struct import pack
|
||||||
from usb97 import *
|
from usb97 import *
|
||||||
|
from Crypto.Random import get_random_bytes
|
||||||
|
from Crypto.Cipher import AES
|
||||||
from fastecdsa.encoding.der import DEREncoder
|
from fastecdsa.encoding.der import DEREncoder
|
||||||
from fastecdsa.curve import P256
|
from fastecdsa.curve import P256
|
||||||
from fastecdsa.ecdsa import sign
|
from fastecdsa.ecdsa import sign
|
||||||
from fastecdsa.point import Point
|
from fastecdsa.point import Point
|
||||||
from fastecdsa.keys import gen_private_key, get_public_key
|
from fastecdsa.keys import gen_private_key, get_public_key
|
||||||
|
from util import assert_status
|
||||||
|
|
||||||
flash_layout_hardcoded=[
|
flash_layout_hardcoded=[
|
||||||
# id ?? acc offset size
|
# id ?? acc offset size
|
||||||
|
|
@ -20,19 +23,6 @@ flash_layout_hardcoded=[
|
||||||
# unhex('08 08 0500 00000000 000000ff'), # <-- hack to make the whole flash contents readable
|
# unhex('08 08 0500 00000000 000000ff'), # <-- hack to make the whole flash contents readable
|
||||||
]
|
]
|
||||||
|
|
||||||
blk3_hardcoded=unhex('''
|
|
||||||
170000000001000001000000fcffffffffffffffffffffff00000000000000000000000001000000fffff
|
|
||||||
fff0000000000000000000000000000000000000000000000000000000000000000000000004b60d2273e
|
|
||||||
3cce3bf6b053ccb0061d65bc86987655bdebb3e7933aaad835c65a0000000000000000000000000000000
|
|
||||||
0000000000000000000000000000000000000000096c298d84539a1f4a033eb2d817d0377f240a463e5e6
|
|
||||||
bcf847422ce1f2d1176b00000000000000000000000000000000000000000000000000000000000000000
|
|
||||||
0000000f551bf376840b6cbce5e316b5733ce2b169e0f7c4aebe78e9b7f1afee242e34f00000000000000
|
|
||||||
0000000000000000000000000000000000000000000000000000000000512563fcc2cab9f3849e17a7adf
|
|
||||||
ae6bcffffffffffffffff00000000ffffffff000000000000000000000000000000000000000000000000
|
|
||||||
000000000000000000000000ffffffffffffffffffffffff00000000000000000000000001000000fffff
|
|
||||||
fff000000000000000000000000000000000000000000000000000000000000000000000000
|
|
||||||
''')
|
|
||||||
|
|
||||||
enable_blob=unhex('''
|
enable_blob=unhex('''
|
||||||
06020000013920c0cdd8e7e68d6ef897ee686fbf657f83b9514341e1d3c0835a28c9cd1ccd0016644f74d
|
06020000013920c0cdd8e7e68d6ef897ee686fbf657f83b9514341e1d3c0835a28c9cd1ccd0016644f74d
|
||||||
d02a73b85d95f4d352417cee76ba0bca3ce474159c62ade3e10797715a13f15a292f5d57c6d46cf8f5ef6
|
d02a73b85d95f4d352417cee76ba0bca3ce474159c62ade3e10797715a13f15a292f5d57c6d46cf8f5ef6
|
||||||
|
|
@ -330,6 +320,19 @@ def make_cert():
|
||||||
msg += b'\0'*(444 - len(msg))
|
msg += b'\0'*(444 - len(msg))
|
||||||
return msg
|
return msg
|
||||||
|
|
||||||
|
def encrypt_key():
|
||||||
|
x = unhexlify('%064x' % client_public.x)[::-1]
|
||||||
|
y = unhexlify('%064x' % client_public.y)[::-1]
|
||||||
|
d = unhexlify('%064x' % client_private)[::-1]
|
||||||
|
|
||||||
|
m = x+y+d
|
||||||
|
iv = get_random_bytes(AES.block_size)
|
||||||
|
aes = AES.new(psk_encryption_key, AES.MODE_CBC, iv)
|
||||||
|
c = iv + aes.encrypt(m)
|
||||||
|
sig = hmac.new(psk_validation_key, c, sha256).digest()
|
||||||
|
return b'\x02' + c + sig
|
||||||
|
|
||||||
|
|
||||||
def make_flash_params(flash_size, sector_size, erase_cmd):
|
def make_flash_params(flash_size, sector_size, erase_cmd):
|
||||||
return pack('<LLxxBx', flash_size, sector_size, erase_cmd)
|
return pack('<LLxxBx', flash_size, sector_size, erase_cmd)
|
||||||
|
|
||||||
|
|
@ -339,10 +342,17 @@ cmd = unhex('4f 0000 0000')
|
||||||
cmd += with_hdr(0, make_flash_params(0x100000, 0x1000, 0x20))
|
cmd += with_hdr(0, make_flash_params(0x100000, 0x1000, 0x20))
|
||||||
cmd += with_hdr(1, b''.join([i + b'\0'*4 + sha256(i).digest() for i in flash_layout_hardcoded]))
|
cmd += with_hdr(1, b''.join([i + b'\0'*4 + sha256(i).digest() for i in flash_layout_hardcoded]))
|
||||||
cmd += with_hdr(5, make_cert())
|
cmd += with_hdr(5, make_cert())
|
||||||
cmd += with_hdr(3, blk3_hardcoded)
|
cmd += with_hdr(3, crt_hardcoded)
|
||||||
|
|
||||||
usb=Usb()
|
usb=Usb()
|
||||||
usb.trace_enabled=True
|
usb.trace_enabled=True
|
||||||
|
|
||||||
|
tls=Tls(usb)
|
||||||
|
tls.trace_enabled=True
|
||||||
|
tls.handle_priv(encrypt_key())
|
||||||
|
|
||||||
|
db=Db(tls)
|
||||||
|
|
||||||
usb.open()
|
usb.open()
|
||||||
usb.cmd(enable_blob)
|
usb.cmd(enable_blob)
|
||||||
rsp=usb.cmd(unhex('3e'))
|
rsp=usb.cmd(unhex('3e'))
|
||||||
|
|
@ -359,29 +369,44 @@ rsp=usb.cmd(unhex('3e'))
|
||||||
# 05 05 0300 00000400 00800000
|
# 05 05 0300 00000400 00800000
|
||||||
# 06 06 0300 00800400 00800000
|
# 06 06 0300 00800400 00800000
|
||||||
# 04 03 0500 00000500 00000300
|
# 04 03 0500 00000500 00000300
|
||||||
#rsp=usb.cmd(cmd)
|
rsp=usb.cmd(cmd)
|
||||||
# ^ todo validate response
|
assert_status(rsp)
|
||||||
|
rsp=rsp[2:]
|
||||||
|
crt_len, rsp=rsp[:4], rsp[4:]
|
||||||
|
crt_len, = unpack('<L', crt_len)
|
||||||
|
tls.handle_cert(rsp[:crt_len])
|
||||||
|
# ^ TODO - validate cert
|
||||||
|
rsp = rsp[crt_len:]
|
||||||
|
# ^ TODO - figure out what the rest of rsp means
|
||||||
|
|
||||||
rsp=usb.cmd(unhex('01'))
|
rsp=usb.cmd(unhex('01'))
|
||||||
|
assert_status(rsp)
|
||||||
# ^ get device info, contains firmware version which is needed to lookup pubkey for server cert validation
|
# ^ get device info, contains firmware version which is needed to lookup pubkey for server cert validation
|
||||||
|
|
||||||
rsp=usb.cmd(unhex('50'))
|
rsp=usb.cmd(unhex('50'))
|
||||||
# ^ response contains server cert -- TODO validate it
|
# ^ TODO validate response
|
||||||
# It should be signed by the firmware private key.
|
# It should be signed by the firmware private key.
|
||||||
# The corresponding pub key is hardcoded for each fw revision in the synaWudfBioUsb.dll.
|
# The corresponding pub key is hardcoded for each fw revision in the synaWudfBioUsb.dll.
|
||||||
# for my device it is: x=f727653b4e16ce0665a6894d7f3a30d7d0a0be310d1292a743671fdf69f6a8d3, y=a85538f8b6bec50d6eef8bd5f4d07a886243c58b2393948df761a84721a6ca94
|
# 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:])
|
||||||
|
|
||||||
rsp=usb.cmd(unhex('1a'))
|
rsp=usb.cmd(unhex('1a'))
|
||||||
|
assert_status(rsp)
|
||||||
|
|
||||||
tls=Tls(usb)
|
tls.open()
|
||||||
db=Db(tls)
|
|
||||||
# TODO -- explicitly set crypto params on tls object (they are not persisted on flash yet)
|
|
||||||
#tls.open()
|
|
||||||
|
|
||||||
# Wipe newly created partitions clean
|
# Wipe newly created partitions clean
|
||||||
#db.erase_flash(1)
|
db.erase_flash(1)
|
||||||
#db.erase_flash(2)
|
db.erase_flash(2)
|
||||||
#db.erase_flash(5)
|
db.erase_flash(5)
|
||||||
#db.erase_flash(6)
|
db.erase_flash(6)
|
||||||
#db.erase_flash(4)
|
db.erase_flash(4)
|
||||||
|
|
||||||
# Persist certs and keys on cert partition.
|
# Persist certs and keys on cert partition.
|
||||||
#db.write_flash(1, ...)
|
db.write_flash(1, 0, tls.makeTlsFlash())
|
||||||
|
|
||||||
|
# Reboot
|
||||||
|
tls.cmd(unhex('050200'))
|
||||||
|
|
|
||||||
38
tls97.py
38
tls97.py
|
|
@ -3,6 +3,7 @@ import hmac
|
||||||
import sys
|
import sys
|
||||||
from hashlib import sha256, md5, sha1
|
from hashlib import sha256, md5, sha1
|
||||||
from binascii import *
|
from binascii import *
|
||||||
|
from usb97 import unhex
|
||||||
from struct import pack, unpack
|
from struct import pack, unpack
|
||||||
from Crypto.Cipher import AES
|
from Crypto.Cipher import AES
|
||||||
from Crypto.Random import get_random_bytes
|
from Crypto.Random import get_random_bytes
|
||||||
|
|
@ -24,6 +25,19 @@ hw_key= bytes(product_name, 'ascii') + b'\0' + \
|
||||||
password_hardcoded=unhexlify('717cd72d0962bc4a2846138dbb2c24192512a76407065f383846139d4bec2033')
|
password_hardcoded=unhexlify('717cd72d0962bc4a2846138dbb2c24192512a76407065f383846139d4bec2033')
|
||||||
gwk_sign_hardcoded=unhexlify('3a4c76b76a97981d1274247e166610e77f4d9c9d07d3c728e532916bdd28b454')
|
gwk_sign_hardcoded=unhexlify('3a4c76b76a97981d1274247e166610e77f4d9c9d07d3c728e532916bdd28b454')
|
||||||
|
|
||||||
|
crt_hardcoded=unhex('''
|
||||||
|
170000000001000001000000fcffffffffffffffffffffff00000000000000000000000001000000fffff
|
||||||
|
fff0000000000000000000000000000000000000000000000000000000000000000000000004b60d2273e
|
||||||
|
3cce3bf6b053ccb0061d65bc86987655bdebb3e7933aaad835c65a0000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000096c298d84539a1f4a033eb2d817d0377f240a463e5e6
|
||||||
|
bcf847422ce1f2d1176b00000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000f551bf376840b6cbce5e316b5733ce2b169e0f7c4aebe78e9b7f1afee242e34f00000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000512563fcc2cab9f3849e17a7adf
|
||||||
|
ae6bcffffffffffffffff00000000ffffffff000000000000000000000000000000000000000000000000
|
||||||
|
000000000000000000000000ffffffffffffffffffffffff00000000000000000000000001000000fffff
|
||||||
|
fff000000000000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
''')
|
||||||
|
|
||||||
def prf(secret, seed, length):
|
def prf(secret, seed, length):
|
||||||
n = (length + 0x20 - 1) // 0x20
|
n = (length + 0x20 - 1) // 0x20
|
||||||
|
|
||||||
|
|
@ -45,6 +59,7 @@ def hs_key():
|
||||||
key=password_hardcoded[:0x10]
|
key=password_hardcoded[:0x10]
|
||||||
seed=password_hardcoded[0x10:] + b'\xaa'*2
|
seed=password_hardcoded[0x10:] + b'\xaa'*2
|
||||||
hs_key=prf(key, b'HS_KEY_PAIR_GEN' + seed, 0x20)
|
hs_key=prf(key, b'HS_KEY_PAIR_GEN' + seed, 0x20)
|
||||||
|
print(hs_key.hex())
|
||||||
return int(hs_key[::-1].hex(), 16)
|
return int(hs_key[::-1].hex(), 16)
|
||||||
|
|
||||||
def with_2bytes_size(chunk):
|
def with_2bytes_size(chunk):
|
||||||
|
|
@ -383,6 +398,8 @@ class Tls():
|
||||||
if id == 0xffff:
|
if id == 0xffff:
|
||||||
break
|
break
|
||||||
|
|
||||||
|
self.trace('block id %04x (%d bytes)' % (id, sz))
|
||||||
|
|
||||||
m=sha256()
|
m=sha256()
|
||||||
m.update(body)
|
m.update(body)
|
||||||
|
|
||||||
|
|
@ -395,6 +412,8 @@ class Tls():
|
||||||
self.handle_ecdh(body)
|
self.handle_ecdh(body)
|
||||||
elif id == 3:
|
elif id == 3:
|
||||||
self.handle_cert(body)
|
self.handle_cert(body)
|
||||||
|
elif id == 0:
|
||||||
|
self.handle_empty(body)
|
||||||
elif id == 1:
|
elif id == 1:
|
||||||
self.handle_empty(body)
|
self.handle_empty(body)
|
||||||
elif id == 2:
|
elif id == 2:
|
||||||
|
|
@ -402,6 +421,23 @@ class Tls():
|
||||||
else:
|
else:
|
||||||
self.trace('unhandled block id %04x (%d bytes): %s' % (id, sz, hexlify(body)))
|
self.trace('unhandled block id %04x (%d bytes): %s' % (id, sz, hexlify(body)))
|
||||||
|
|
||||||
|
def makeTlsFlashBlock(self, id, body):
|
||||||
|
m=sha256()
|
||||||
|
m.update(body)
|
||||||
|
hdr = pack('<HH', id, len(body))
|
||||||
|
return hdr+m.digest()+body
|
||||||
|
|
||||||
|
def makeTlsFlash(self):
|
||||||
|
b = self.makeTlsFlashBlock(0, b'\0')
|
||||||
|
b+= self.makeTlsFlashBlock(4, self.priv_blob)
|
||||||
|
b+= self.makeTlsFlashBlock(3, self.tls_cert)
|
||||||
|
b+= self.makeTlsFlashBlock(5, crt_hardcoded)
|
||||||
|
b+= self.makeTlsFlashBlock(1, b'\0' * 0x100)
|
||||||
|
b+= self.makeTlsFlashBlock(2, b'\0' * 0x100)
|
||||||
|
b+= self.makeTlsFlashBlock(6, self.ecdh_blob)
|
||||||
|
b+= b'\xff' * (0x1000 - len(b))
|
||||||
|
return b
|
||||||
|
|
||||||
def handle_empty(self, body):
|
def handle_empty(self, body):
|
||||||
if body != b'\0' * len(body):
|
if body != b'\0' * len(body):
|
||||||
raise Exception('Expected empty block')
|
raise Exception('Expected empty block')
|
||||||
|
|
@ -413,6 +449,7 @@ class Tls():
|
||||||
|
|
||||||
def handle_ecdh(self, body):
|
def handle_ecdh(self, body):
|
||||||
# TODO check the signature
|
# TODO check the signature
|
||||||
|
self.ecdh_blob = body
|
||||||
x = body[0x8:0x8+0x20]
|
x = body[0x8:0x8+0x20]
|
||||||
y = body[0x4c:0x4c+0x20]
|
y = body[0x4c:0x4c+0x20]
|
||||||
|
|
||||||
|
|
@ -428,6 +465,7 @@ class Tls():
|
||||||
|
|
||||||
|
|
||||||
def handle_priv(self, body):
|
def handle_priv(self, body):
|
||||||
|
self.priv_blob = body
|
||||||
prefix, body = body[0], body[1:]
|
prefix, body = body[0], body[1:]
|
||||||
if prefix != 2:
|
if prefix != 2:
|
||||||
raise Exception('Unknown private key prefix %02x' % prefix)
|
raise Exception('Unknown private key prefix %02x' % prefix)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue