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