def gen_datagram(): """Generate random data, with a length between 0 and 255 bytes. Returns: a bytes object """ length = ucrypto.getrandbits(32)[0] data = ucrypto.getrandbits(length * 8)[:length] return data
def get_update_manifest(self): """Get the manifest data from server and check signature. Gets the data, splits it into the strings for manifest (JSON), signature type, and signature data using the headers. Then checks the signature and finally parses the JSON of the manifest. """ #generate request id string (based on random bits) request_id = ubinascii.hexlify( ucrypto.getrandbits(128)).decode('utf-8') req = "manifest.json?current_ver={}&devid={}&reqid={}&protocol={}".format( self.get_current_version(), self.get_device_id(), request_id, self.PROTOCOL_VERSION) response = self.get_data(req).decode() # print("response: {}".format(response)) if len(response) == 0 or response is None: raise Exception("No response received from server") # get the data from the headers and repeat with the remaining response # we get/remove the manifest json first as it is the most critical to remove # since it's data is arbitrary and might contain 'header-like' strings manifest_str, response = self.extract_from_response( "MANIFEST", response) sig_type_str, response = self.extract_from_response( "SIGNATURE_TYPE", response) sig_data_str, response = self.extract_from_response( "SIGNATURE_DATA", response) # print("manifest:{}".format(manifest_str)) # print("sig_type:{}".format(sig_type_str)) # print("sig_data:{}".format(sig_data_str)) #check that all data was found if len(manifest_str) == 0 or \ len(sig_type_str) == 0 or \ len(sig_data_str) == 0 : raise Exception("Could not find all required headers in response.") #check signature if self.check_manifest_signature(manifest_str, sig_type_str, sig_data_str): print("Signature OK, parsing manifest") manifest = ujson.loads(manifest_str) else: raise Exception("Signature of manifest is invalid") # check that this is the signature we requested and not a replay try: returned_req_id = manifest['request_id'] except KeyError: raise Exception("Manifest invalid: no request ID returned") if returned_req_id != request_id: raise Exception( "Manifest invalid: returned request ID does not match query request ID" ) gc.collect() return manifest
def connect(uri): """ Connect a websocket. """ uri = urlparse(uri) assert uri if __DEBUG: print("open connection %s:%s" % (uri.hostname, uri.port)) sock = socket.socket() addr = socket.getaddrinfo(uri.hostname, uri.port) sock.connect(addr[0][4]) if uri.protocol == 'wss': sock = ussl.wrap_socket(sock) def send_header(header, *args): if __DEBUG: print(str(header), *args) sock.write(header % args + '\r\n') # Sec-WebSocket-Key is 16 bytes of random base64 encoded key = binascii.b2a_base64(ucrypto.getrandbits(16 * 8)).strip() send_header(b'GET %s HTTP/1.1', uri.path or '/') send_header(b'Host: %s:%s', uri.hostname, uri.port) send_header(b'Connection: Upgrade') send_header(b'Upgrade: websocket') send_header(b'Sec-WebSocket-Key: %s', key) send_header(b'Sec-WebSocket-Version: 13') send_header(b'Origin: http://localhost') send_header(b'') header = sock.readline()[:-2] assert header.startswith(b'HTTP/1.1 101 '), header # We don't (currently) need these headers # FIXME: should we check the return key? while header: if __DEBUG: print(str(header)) header = sock.readline()[:-2] return WebsocketClient(sock)
def write_frame(self, opcode, data=b''): """ Write a frame to the socket. See https://tools.ietf.org/html/rfc6455#section-5.2 for the details. """ fin = True mask = self.is_client # messages sent by client are masked length = len(data) # Frame header # Byte 1: FIN(1) _(1) _(1) _(1) OPCODE(4) byte1 = 0x80 if fin else 0 byte1 |= opcode # Byte 2: MASK(1) LENGTH(7) byte2 = 0x80 if mask else 0 if length < 126: # 126 is magic value to use 2-byte length header byte2 |= length self.sock.write(struct.pack('!BB', byte1, byte2)) elif length < (1 << 16): # Length fits in 2-bytes byte2 |= 126 # Magic code self.sock.write(struct.pack('!BBH', byte1, byte2, length)) elif length < (1 << 64): byte2 |= 127 # Magic code self.sock.write(struct.pack('!BBQ', byte1, byte2, length)) else: raise ValueError() if mask: # Mask is 4 bytes mask_bits = ucrypto.getrandbits(32) self.sock.write(mask_bits) data = bytes(b ^ mask_bits[i % 4] for i, b in enumerate(data)) self.sock.write(data)
def random_in_range(l=0, h=1000): r1 = ucrypto.getrandbits(32) r2 = ((r1[0] << 24) + (r1[1] << 16) + (r1[2] << 8) + r1[3]) / 4294967295.0 return math.floor(r2 * h + l)
def Random(): r = crypto.getrandbits(32) return ((r[0] << 24) + (r[1] << 16) + (r[2] << 8) + r[3]) / 4294967295.0
def generate_heartbeat_offset(self): randomBytes = crypto.getrandbits(32) rand = struct.unpack('h', randomBytes)[0] # max 32k min -32k return rand
def generateDataFuzzRandomLength(): length = int(ucrypto.getrandbits(8)[0]) return b"\x20" + ucrypto.getrandbits(length * 8)[:length]
def generateDataFuzz32Bytes(): return b"\x20" + ucrypto.getrandbits(32 * 8)[:32]