Validate ECDH params signature
This commit is contained in:
parent
616a667c18
commit
520df7333c
3 changed files with 36 additions and 14 deletions
3
pair.py
3
pair.py
|
|
@ -13,7 +13,8 @@ from proto97.init_db import init_db
|
||||||
#tls.trace_enabled=True
|
#tls.trace_enabled=True
|
||||||
|
|
||||||
def restart():
|
def restart():
|
||||||
sleep(2)
|
print('Sleeping...')
|
||||||
|
sleep(3)
|
||||||
tls.reset()
|
tls.reset()
|
||||||
usb.open()
|
usb.open()
|
||||||
usb.send_init()
|
usb.send_init()
|
||||||
|
|
|
||||||
|
|
@ -85,7 +85,6 @@ def partition_flash(layout, client_public):
|
||||||
crt_len, rsp=rsp[:4], rsp[4:]
|
crt_len, rsp=rsp[:4], rsp[4:]
|
||||||
crt_len, = unpack('<L', crt_len)
|
crt_len, = unpack('<L', crt_len)
|
||||||
tls.handle_cert(rsp[:crt_len])
|
tls.handle_cert(rsp[:crt_len])
|
||||||
# ^ TODO - validate cert
|
|
||||||
rsp = rsp[crt_len:]
|
rsp = rsp[crt_len:]
|
||||||
# ^ TODO - figure out what the rest of rsp means
|
# ^ 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
|
# ^ 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'))
|
||||||
# ^ 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)
|
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
|
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.handle_priv(encrypt_key(client_private, client_public))
|
||||||
tls.open()
|
tls.open()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ from Crypto.Random import get_random_bytes
|
||||||
from fastecdsa.curve import P256
|
from fastecdsa.curve import P256
|
||||||
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 fastecdsa.ecdsa import sign
|
from fastecdsa.ecdsa import sign, verify
|
||||||
from fastecdsa.encoding.der import DEREncoder
|
from fastecdsa.encoding.der import DEREncoder
|
||||||
from .util import assert_status
|
from .util import assert_status
|
||||||
import pickle
|
import pickle
|
||||||
|
|
@ -450,10 +450,10 @@ class Tls():
|
||||||
self.trace('TLS cert blob: %s' % hexlify(self.tls_cert))
|
self.trace('TLS cert blob: %s' % hexlify(self.tls_cert))
|
||||||
|
|
||||||
def handle_ecdh(self, body):
|
def handle_ecdh(self, body):
|
||||||
# TODO check the signature
|
|
||||||
self.ecdh_blob = body
|
self.ecdh_blob = body
|
||||||
x = body[0x8:0x8+0x20]
|
key, signature = body[:0x90], body[0x90:]
|
||||||
y = body[0x4c:0x4c+0x20]
|
x = key[0x8:0x8+0x20]
|
||||||
|
y = key[0x4c:0x4c+0x20]
|
||||||
|
|
||||||
x, y = [int(hexlify(i[::-1]), 0x10) for i in [x, y]]
|
x, y = [int(hexlify(i[::-1]), 0x10) for i in [x, y]]
|
||||||
|
|
||||||
|
|
@ -464,6 +464,24 @@ class Tls():
|
||||||
self.trace('ECDH params:')
|
self.trace('ECDH params:')
|
||||||
self.trace('x=0x%x' % x)
|
self.trace('x=0x%x' % x)
|
||||||
self.trace('y=0x%x' % y)
|
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):
|
def handle_priv(self, body):
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue