def fill_memory(self, _addr, is_ptr_in_buffer, _ptr, _ptr_offset, _sig, _sig_offset): # # Fill in contents at PA = _addr with known pattern to check later if any SMI handler modifies them # fill_buf = FILL_BUFFER(self.fill_byte, self.fill_size, is_ptr_in_buffer, _ptr, _ptr_offset, _sig, _sig_offset) s = "[*] writing 0x{:X} bytes at 0x{:016X}".format( self.fill_size, _addr) if is_ptr_in_buffer: s += " -> PTR at +0x{:X}".format(_ptr_offset) if _sig is not None: s += " -> SIG at +0x{:X}".format(_sig_offset) self.logger.log(s) self.cs.mem.write_physical_mem(_addr, self.fill_size, fill_buf) if self.logger.VERBOSE: self.logger.log( "filling in contents at PA 0x{:016X}:".format(_addr)) print_buffer_bytes(fill_buf, 16) if is_ptr_in_buffer and _ptr is not None: self.logger.log( "[*] writing buffer at PA 0x{:016X} with 0x{:X} bytes '{}'". format(_ptr, self.fill_size, self.fill_byte)) self.cs.mem.write_physical_mem(_ptr, self.fill_size, self.fill_byte * self.fill_size) return True
def read_spi(self, spi_fla, data_byte_count ): self.check_hardware_sequencing() buf = bytearray() dbc = SPI_READ_WRITE_DEF_DBC if (data_byte_count >= SPI_READ_WRITE_MAX_DBC): dbc = SPI_READ_WRITE_MAX_DBC n = data_byte_count // dbc r = data_byte_count % dbc if self.logger.UTIL_TRACE or self.logger.HAL: self.logger.log( "[spi] reading 0x{:x} bytes from SPI at FLA = 0x{:x} (in {:d} 0x{:x}-byte chunks + 0x{:x}-byte remainder)".format(data_byte_count, spi_fla, n, dbc, r) ) cycle_done = self._wait_SPI_flash_cycle_done() if not cycle_done: self.logger.error( "SPI cycle not ready" ) return None for i in range(n): if self.logger.HAL: self.logger.log( "[spi] reading chunk {:d} of 0x{:x} bytes from 0x{:x}".format(i, dbc, spi_fla + i *dbc) ) if not self._send_spi_cycle( HSFCTL_READ_CYCLE, dbc -1, spi_fla + i *dbc ): self.logger.error( "SPI flash read failed" ) else: for fdata_idx in range(0, dbc //4): dword_value = self.spi_reg_read( self.fdata0_off + fdata_idx *4 ) if self.logger.HAL: self.logger.log( "[spi] FDATA00 + 0x{:x}: 0x{:x}".format(fdata_idx *4, dword_value) ) buf += struct.pack("I", dword_value) if (0 != r): if self.logger.HAL: self.logger.log( "[spi] reading remaining 0x{:x} bytes from 0x{:x}".format(r, spi_fla + n *dbc) ) if not self._send_spi_cycle( HSFCTL_READ_CYCLE, r -1, spi_fla + n *dbc ): self.logger.error( "SPI flash read failed" ) else: t = 4 n_dwords = (r +3) //4 for fdata_idx in range(0, n_dwords): dword_value = self.spi_reg_read( self.fdata0_off + fdata_idx *4 ) if self.logger.HAL: self.logger.log( "[spi] FDATA00 + 0x{:x}: 0x{:08X}".format(fdata_idx *4, dword_value) ) if (fdata_idx == (n_dwords -1)) and (0 != r%4): t = r%4 for j in range(t): buf += struct.pack('B', (dword_value >> (8 *j)) & 0xff) if self.logger.HAL: self.logger.log( "[spi] buffer read from SPI:" ) print_buffer_bytes(buf) return buf
def send_smmc_SMI(self, smmc, guid, payload, payload_loc, CommandPort=0x0, DataPort=0x0): guid_b = uuid.UUID(guid).bytes_le payload_sz = len(payload) data_hdr = guid_b + struct.pack("Q", payload_sz) + payload # write payload to payload_loc CommBuffer_offset = 56 BufferSize_offset = CommBuffer_offset + 8 ReturnStatus_offset = BufferSize_offset + 8 self.cs.mem.write_physical_mem(smmc + CommBuffer_offset, 8, struct.pack("Q", payload_loc)) self.cs.mem.write_physical_mem(smmc + BufferSize_offset, 8, struct.pack("Q", len(data_hdr))) self.cs.mem.write_physical_mem(payload_loc, len(data_hdr), data_hdr) if self.logger.VERBOSE: self.logger.log("[*] Communication buffer on input") print_buffer_bytes( self.cs.mem.read_physical_mem(payload_loc, len(data_hdr))) self.logger.log("") self.send_SMI_APMC(CommandPort, DataPort) if self.logger.VERBOSE: self.logger.log("[*] Communication buffer on output") print_buffer_bytes( self.cs.mem.read_physical_mem(payload_loc, len(data_hdr))) self.logger.log("") ReturnStatus = struct.unpack( "Q", self.cs.mem.read_physical_mem(smmc + ReturnStatus_offset, 8))[0] return ReturnStatus
def command( self, commandName, locality, command_argv ): """ Send command to the TPM and receive data """ try: Locality = LOCALITY[locality] except: if self.logger.HAL: self.logger.log_bad("Invalid locality value\n") return requestedUse = False # # Request locality use if needed # access_address = self.TPM_BASE | Locality | TPM_ACCESS if self.helper.read_mmio_reg( access_address, 4 ) == BEENSEIZED: self.helper.write_mmio_reg( access_address, 4, REQUESTUSE ) requestedUse = True # # Build command (big endian) and send/receive # ( command, size ) = COMMANDS[commandName]( command_argv ) self._send_command( Locality, command, size ) ( header, data, header_blob, data_blob ) = self._read_response( Locality ) self.logger.log( header ) print_buffer_bytes( data_blob ) self.logger.log( '\n' ) # # Release locality if needed # if requestedUse==True: self.helper.write_mmio_reg( access_address, 4, BEENSEIZED ) self.helper.write_mmio_reg( access_address, 1, ACTIVELOCALITY )
def check_memory(self, _addr, _smi_desc, fn, restore_contents=False): _ptr = _smi_desc.ptr filler = self.fill_byte * self.fill_size # # Check if contents have changed at physical address passed in GPRs to SMI handler # If changed, SMI handler might have written to that address # self.logger.log(" < checking buffers") expected_buf = FILL_BUFFER(self.fill_byte, self.fill_size, _smi_desc.ptr_in_buffer, _smi_desc.ptr, _smi_desc.ptr_offset, _smi_desc.sig, _smi_desc.sig_offset) buf = self.cs.mem.read_physical_mem(_addr, self.fill_size) differences = DIFF(expected_buf, buf, self.fill_size) _changed = (len(differences) > 0) if self.logger.VERBOSE: self.logger.log("checking contents at PA 0x{:016X}:".format(_addr)) print_buffer_bytes(buf, 16) self.logger.log("expected contents:") print_buffer_bytes(expected_buf, 16) if _changed: self.logger.log(" contents changed at 0x{:016X} +{}".format( _addr, differences)) if restore_contents: self.logger.log( " restoring 0x{:X} bytes at 0x{:016X}".format( self.fill_size, _addr)) self.cs.mem.write_physical_mem(_addr, self.fill_size, expected_buf) if DUMP_MEMORY_ON_DETECT: _pth_smi = os.path.join( _pth, '{:X}_{}'.format(_smi_desc.smi_code, _smi_desc.name)) if not os.path.exists(_pth_smi): os.makedirs(_pth_smi) _f = os.path.join(_pth_smi, fn + '.dmp') self.logger.log(" dumping buffer to '{}'".format(_f)) write_file(_f, buf) _changed1 = False expected_buf = filler if _smi_desc.ptr_in_buffer and _ptr is not None: buf1 = self.cs.mem.read_physical_mem(_ptr, self.fill_size) differences1 = DIFF(expected_buf, buf1, self.fill_size) _changed1 = (len(differences1) > 0) if self.logger.VERBOSE: self.logger.log( "checking contents at PA 0x{:016X}:".format(_ptr)) print_buffer_bytes(buf1, 16) if _changed1: self.logger.log(" contents changed at 0x{:016X} +{}".format( _ptr, differences1)) if restore_contents: self.logger.log( " restoring 0x{:X} bytes at PA 0x{:016X}".format( self.fill_size, _ptr)) self.cs.mem.write_physical_mem(_ptr, self.fill_size, expected_buf) if DUMP_MEMORY_ON_DETECT: _pth_smi = os.path.join( _pth, '{:X}_{}'.format(_smi_desc.smi_code, _smi_desc.name)) if not os.path.exists(_pth_smi): os.makedirs(_pth_smi) _f = os.path.join( _pth_smi, fn + ('_ptr{:X}.dmp'.format(_smi_desc.ptr_offset))) self.logger.log(" dumping buffer to '{}'".format(_f)) write_file(_f, buf1) return (_changed or _changed1)