eculocate

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README

otaclient.py (1943B)


      1 import socket
      2 import struct
      3 import sys
      4 import nacl
      5 import os
      6 import nacl.hash
      7 
      8 from nacl.signing import SigningKey
      9 from nacl.encoding import RawEncoder
     10 
     11 HASHER = nacl.hash.sha256
     12 
     13 BLOCK_SIZE=4096
     14 
     15 with open("privkey.bin", "rb") as f:
     16     signing_key = SigningKey(f.read(), encoder=RawEncoder)
     17 
     18 PEER=("eculocate.local", 5000)
     19 # PEER=("localhost",5000)
     20 sock = socket.create_connection(PEER)
     21 
     22 with open(sys.argv[1], "rb") as f:
     23     rom_image = f.read()
     24 
     25 def data_for_block(n):
     26     # block 0 is header information, so actual data blocks start at 1
     27     return rom_image[(n-1)*BLOCK_SIZE : n*BLOCK_SIZE]
     28 
     29 # suppose 102 blocks
     30 
     31 # 100: hash(hash(<00000> + data102) + data101) + data100
     32 # 101: hash(<00000> + data102) + data101
     33 # 102: <00000> + data102
     34 
     35 def sha256sum(bytes):
     36     return HASHER(bytes, encoder=RawEncoder)
     37 
     38 def hash_for_block(n):
     39     if (n-1)*BLOCK_SIZE < len(rom_image):
     40         data = linked_block(n)
     41         return sha256sum(data)
     42     else:
     43         return b"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
     44 
     45 def linked_block(n):
     46     if n==0:
     47         return hash_for_block(1) + struct.pack(">L", len(rom_image))
     48     else:
     49         return hash_for_block(n+1) + data_for_block(n)
     50 
     51 sig = signing_key.sign(linked_block(0), encoder=RawEncoder)
     52 sock.send(b"ROM0" + sig.signature)
     53 
     54 def hexy(h):
     55     return "".join("{:02x} ".format(x) for x in bytearray(h))
     56 
     57 def ddec(h):
     58     return "".join("{:02d} ".format(x) for x in bytearray(h))
     59 
     60 # header block 0 plus n full blocks plus partial block at end
     61 num_blocks = 2 + len(rom_image)//BLOCK_SIZE
     62 print(f"{num_blocks} blocks to send")
     63 
     64 for i in range(0, num_blocks):
     65     h = hash_for_block(i)
     66     print(f"block {i}")
     67     sock.send(linked_block(i))
     68 
     69 
     70 
     71 # Read a line from the socket (until newline)
     72 response = b""
     73 while not response.endswith(b"\n"):
     74     chunk = sock.recv(1)
     75     if not chunk:
     76         break
     77     response += chunk
     78 
     79 print(response.decode(errors="replace"))
     80 
     81 sock.close()