Flash partition works!

This commit is contained in:
Viktor Dragomiretskyy 2019-06-19 18:21:19 +12:00
parent 828aa54618
commit 974cb1a7c1
4 changed files with 107 additions and 36 deletions

View file

@ -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()

View file

@ -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)

View file

@ -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'))

View file

@ -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)