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]
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.keys import get_public_key
#4f 0000 0000
blob4f=unhex('''
00000c000000100000100000000020000100f000010407000010000000100000000000009da
4f0000000000000c000000100000100000000020000100f000010407000010000000100000000000009da
6bb3eb1d4d1641811b0a2402ba5010d6d0f2f7ffd8debc7e7e68c31473333020102000020000000e00300
00000000840acfea4e998b5302df52db54b7654b164a1057681149fcbb3ec7a559c80db20505030000000
40000800000000000005c70f7ccce2fc2d7620f69da63548fc392877c88393e9c45327a10c21d46267f06
0603000080040000800000000000005a5eeb284ee05ddae47ee27dc75fafaf09bc8b112a652bde4eab8af
c61f2df75040305000000050000000300000000000e828eaff826a0454f6a50f60a36d5014372aaaf2621
41e5ced9d0a0056907c20500bc01170000002000000000b0330e8b22509dd47b3bc2b48540d5bf8946097
678663c23a04ca43911567300000000000000000000000000000000000000000000000000000000000000
000000000069ebc98290a346b0b7be5bb697c24c653ee885e12f497bf44cdf563f7f26af0c00000000000
41e5ced9d0a0056907c20500bc011700000020000000ebfaf1f684cd4e4739e56588695ba19b515be4c16
f3e89bfe6b33f59b209a26b00000000000000000000000000000000000000000000000000000000000000
00000000003870b373e2a0c3b7b09c16cdb8bd5f04bfdfdd55583c67db236c5b522ad6b49000000000000
0000000000000000000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000004600000030440220593e87ba9cd31
4bbfddb3feaa2392bd23906d0f5191a3f2a886c4e87d55ac469022025fb00eaa8b29896ec891d7fc6f51c
7dacaba244c4987b772ce221a6f7028c59000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000460000003044022036a452cef79a1
f146ca26dcf06eb58b333f95fab2d49eb89abbcb07c39dbe4c602200dc95d991f7f89e66ad8ee546619dc
4262617fb813e6e53f4333bbe21fe705d3000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000000000000000000000000
@ -40,6 +38,9 @@ ffffffffff00000000ffffffff000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000
''')
#skip 4f 0000 0000
blob4f=blob4f[5:]
while len(blob4f) > 0:
hdr, blob4f = blob4f[:4], blob4f[4:]
id, l = unpack('<HH', hdr)

View file

@ -4,11 +4,14 @@ from tls97 import *
from hashlib import sha256
from struct import pack
from usb97 import *
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
flash_layout_hardcoded=[
# 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
]
blk3_hardcoded=unhex('''
170000000001000001000000fcffffffffffffffffffffff00000000000000000000000001000000fffff
fff0000000000000000000000000000000000000000000000000000000000000000000000004b60d2273e
3cce3bf6b053ccb0061d65bc86987655bdebb3e7933aaad835c65a0000000000000000000000000000000
0000000000000000000000000000000000000000096c298d84539a1f4a033eb2d817d0377f240a463e5e6
bcf847422ce1f2d1176b00000000000000000000000000000000000000000000000000000000000000000
0000000f551bf376840b6cbce5e316b5733ce2b169e0f7c4aebe78e9b7f1afee242e34f00000000000000
0000000000000000000000000000000000000000000000000000000000512563fcc2cab9f3849e17a7adf
ae6bcffffffffffffffff00000000ffffffff000000000000000000000000000000000000000000000000
000000000000000000000000ffffffffffffffffffffffff00000000000000000000000001000000fffff
fff000000000000000000000000000000000000000000000000000000000000000000000000
''')
enable_blob=unhex('''
06020000013920c0cdd8e7e68d6ef897ee686fbf657f83b9514341e1d3c0835a28c9cd1ccd0016644f74d
d02a73b85d95f4d352417cee76ba0bca3ce474159c62ade3e10797715a13f15a292f5d57c6d46cf8f5ef6
@ -330,6 +320,19 @@ def make_cert():
msg += b'\0'*(444 - len(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):
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(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(3, blk3_hardcoded)
cmd += with_hdr(3, crt_hardcoded)
usb=Usb()
usb.trace_enabled=True
tls=Tls(usb)
tls.trace_enabled=True
tls.handle_priv(encrypt_key())
db=Db(tls)
usb.open()
usb.cmd(enable_blob)
rsp=usb.cmd(unhex('3e'))
@ -359,29 +369,44 @@ rsp=usb.cmd(unhex('3e'))
# 05 05 0300 00000400 00800000
# 06 06 0300 00800400 00800000
# 04 03 0500 00000500 00000300
#rsp=usb.cmd(cmd)
# ^ todo validate response
rsp=usb.cmd(cmd)
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'))
assert_status(rsp)
# ^ get device info, contains firmware version which is needed to lookup pubkey for server cert validation
rsp=usb.cmd(unhex('50'))
# ^ response contains server cert -- TODO validate it
# ^ 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:])
rsp=usb.cmd(unhex('1a'))
assert_status(rsp)
tls=Tls(usb)
db=Db(tls)
# TODO -- explicitly set crypto params on tls object (they are not persisted on flash yet)
#tls.open()
tls.open()
# Wipe newly created partitions clean
#db.erase_flash(1)
#db.erase_flash(2)
#db.erase_flash(5)
#db.erase_flash(6)
#db.erase_flash(4)
db.erase_flash(1)
db.erase_flash(2)
db.erase_flash(5)
db.erase_flash(6)
db.erase_flash(4)
# 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
from hashlib import sha256, md5, sha1
from binascii import *
from usb97 import unhex
from struct import pack, unpack
from Crypto.Cipher import AES
from Crypto.Random import get_random_bytes
@ -24,6 +25,19 @@ hw_key= bytes(product_name, 'ascii') + b'\0' + \
password_hardcoded=unhexlify('717cd72d0962bc4a2846138dbb2c24192512a76407065f383846139d4bec2033')
gwk_sign_hardcoded=unhexlify('3a4c76b76a97981d1274247e166610e77f4d9c9d07d3c728e532916bdd28b454')
crt_hardcoded=unhex('''
170000000001000001000000fcffffffffffffffffffffff00000000000000000000000001000000fffff
fff0000000000000000000000000000000000000000000000000000000000000000000000004b60d2273e
3cce3bf6b053ccb0061d65bc86987655bdebb3e7933aaad835c65a0000000000000000000000000000000
0000000000000000000000000000000000000000096c298d84539a1f4a033eb2d817d0377f240a463e5e6
bcf847422ce1f2d1176b00000000000000000000000000000000000000000000000000000000000000000
0000000f551bf376840b6cbce5e316b5733ce2b169e0f7c4aebe78e9b7f1afee242e34f00000000000000
0000000000000000000000000000000000000000000000000000000000512563fcc2cab9f3849e17a7adf
ae6bcffffffffffffffff00000000ffffffff000000000000000000000000000000000000000000000000
000000000000000000000000ffffffffffffffffffffffff00000000000000000000000001000000fffff
fff000000000000000000000000000000000000000000000000000000000000000000000000
''')
def prf(secret, seed, length):
n = (length + 0x20 - 1) // 0x20
@ -45,6 +59,7 @@ def hs_key():
key=password_hardcoded[:0x10]
seed=password_hardcoded[0x10:] + b'\xaa'*2
hs_key=prf(key, b'HS_KEY_PAIR_GEN' + seed, 0x20)
print(hs_key.hex())
return int(hs_key[::-1].hex(), 16)
def with_2bytes_size(chunk):
@ -383,6 +398,8 @@ class Tls():
if id == 0xffff:
break
self.trace('block id %04x (%d bytes)' % (id, sz))
m=sha256()
m.update(body)
@ -395,6 +412,8 @@ class Tls():
self.handle_ecdh(body)
elif id == 3:
self.handle_cert(body)
elif id == 0:
self.handle_empty(body)
elif id == 1:
self.handle_empty(body)
elif id == 2:
@ -402,6 +421,23 @@ class Tls():
else:
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):
if body != b'\0' * len(body):
raise Exception('Expected empty block')
@ -413,6 +449,7 @@ class Tls():
def handle_ecdh(self, body):
# TODO check the signature
self.ecdh_blob = body
x = body[0x8:0x8+0x20]
y = body[0x4c:0x4c+0x20]
@ -428,6 +465,7 @@ class Tls():
def handle_priv(self, body):
self.priv_blob = body
prefix, body = body[0], body[1:]
if prefix != 2:
raise Exception('Unknown private key prefix %02x' % prefix)