Validate ECDH params signature

This commit is contained in:
Viktor Dragomiretskyy 2019-09-21 19:12:25 +12:00
parent 616a667c18
commit 520df7333c
3 changed files with 36 additions and 14 deletions

View file

@ -13,7 +13,8 @@ from proto97.init_db import init_db
#tls.trace_enabled=True
def restart():
sleep(2)
print('Sleeping...')
sleep(3)
tls.reset()
usb.open()
usb.send_init()

View file

@ -85,7 +85,6 @@ def partition_flash(layout, client_public):
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
@ -102,17 +101,21 @@ def init_flash():
# ^ get device info, contains firmware version which is needed to lookup pubkey for server cert validation
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()
tls.handle_ecdh(rsp[l-400:]) # FIXME not sure offsets are calculated this way
rsp=rsp[2:]
l,=unpack('<L', rsp[:4])
if len(rsp) != l:
raise Exception('Length mismatch')
zeroes, rsp = rsp[4:-400], rsp[-400:]
if zeroes != b'\0' * len(zeroes):
raise Exception('Expected zeroes')
tls.handle_ecdh(rsp)
tls.handle_priv(encrypt_key(client_private, client_public))
tls.open()

View file

@ -10,7 +10,7 @@ from Crypto.Random import get_random_bytes
from fastecdsa.curve import P256
from fastecdsa.point import Point
from fastecdsa.keys import gen_private_key, get_public_key
from fastecdsa.ecdsa import sign
from fastecdsa.ecdsa import sign, verify
from fastecdsa.encoding.der import DEREncoder
from .util import assert_status
import pickle
@ -450,10 +450,10 @@ class Tls():
self.trace('TLS cert blob: %s' % hexlify(self.tls_cert))
def handle_ecdh(self, body):
# TODO check the signature
self.ecdh_blob = body
x = body[0x8:0x8+0x20]
y = body[0x4c:0x4c+0x20]
key, signature = body[:0x90], body[0x90:]
x = key[0x8:0x8+0x20]
y = key[0x4c:0x4c+0x20]
x, y = [int(hexlify(i[::-1]), 0x10) for i in [x, y]]
@ -464,6 +464,24 @@ class Tls():
self.trace('ECDH params:')
self.trace('x=0x%x' % x)
self.trace('y=0x%x' % y)
l, signature = signature[:4], signature[4:]
l, = unpack('<L', l)
signature, zeroes = signature[:l], signature[l:]
if zeroes != b'\0'*len(zeroes):
raise Exception('Zeroes expected')
# The following pub key is hardcoded for each fw revision in the synaWudfBioUsb.dll.
# Corresponding private key should only be known to a genuine Synaptic device.
fwpub=Point(
0xf727653b4e16ce0665a6894d7f3a30d7d0a0be310d1292a743671fdf69f6a8d3,
0xa85538f8b6bec50d6eef8bd5f4d07a886243c58b2393948df761a84721a6ca94, P256)
signature=DEREncoder().decode_signature(signature)
if not verify(signature, key, fwpub):
raise Exception('Untrusted device')
def handle_priv(self, body):