From 690bb53267ef10ac83d46eb02867f2060016878f Mon Sep 17 00:00:00 2001 From: Daniel Jobson Date: Fri, 15 Nov 2024 09:28:01 +0100 Subject: [PATCH] Introduce new bit to mark ROM as non-executable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is dynamically set by hw in system_mode_ctrl. ROM will reset to executable, but will be marked as non-executable as soon as we are no longer executing in ROM, like system_mode. ROM will be marked as executable again, if function calls are made to either `syscall_addr_reg` or `blake2s_addr_reg`. Set reset value of `blake2s_addr_reg` to an illegal address, halting the CPU if it is called unset. The blake2s function is 4-byte aligned, to ensure the cpu_addr is is aligned with the address in the register. Co-authored-by: Mikael Ă…gren --- hw/application_fpga/core/tk1/rtl/tk1.v | 117 +++++++++++++------ hw/application_fpga/fw/tk1/blake2s/blake2s.c | 2 +- 2 files changed, 81 insertions(+), 38 deletions(-) diff --git a/hw/application_fpga/core/tk1/rtl/tk1.v b/hw/application_fpga/core/tk1/rtl/tk1.v index 97ef15d..d9cd96e 100644 --- a/hw/application_fpga/core/tk1/rtl/tk1.v +++ b/hw/application_fpga/core/tk1/rtl/tk1.v @@ -117,13 +117,17 @@ module tk1 #( //---------------------------------------------------------------- // Registers including update variables and write enable. //---------------------------------------------------------------- - reg [31 : 0] cdi_mem [0 : 7]; + reg [31 : 0] cdi_mem [0 : 7]; reg cdi_mem_we; reg system_mode_reg; reg system_mode_new; reg system_mode_we; + reg rom_executable_reg; + reg rom_executable_new; + reg rom_executable_we; + reg [ 2 : 0] led_reg; reg led_we; @@ -260,33 +264,34 @@ module tk1 #( //---------------------------------------------------------------- always @(posedge clk) begin : reg_update if (!reset_n) begin - system_mode_reg <= 1'h0; - led_reg <= 3'h6; - gpio1_reg <= 2'h0; - gpio2_reg <= 2'h0; - gpio3_reg <= 1'h0; - gpio4_reg <= 1'h0; - app_start_reg <= 32'h0; - app_size_reg <= APP_SIZE; - blake2s_addr_reg <= 32'h0; - syscall_addr_reg <= ILLEGAL_ADDR; - cdi_mem[0] <= 32'h0; - cdi_mem[1] <= 32'h0; - cdi_mem[2] <= 32'h0; - cdi_mem[3] <= 32'h0; - cdi_mem[4] <= 32'h0; - cdi_mem[5] <= 32'h0; - cdi_mem[6] <= 32'h0; - cdi_mem[7] <= 32'h0; - cpu_trap_ctr_reg <= 24'h0; - cpu_trap_led_reg <= 3'h0; - cpu_mon_en_reg <= 1'h0; - cpu_mon_first_reg <= 32'h0; - cpu_mon_last_reg <= 32'h0; - ram_addr_rand_reg <= 15'h0; - ram_data_rand_reg <= 32'h0; - force_trap_reg <= 1'h0; - system_reset_reg <= 1'h0; + system_mode_reg <= 1'h0; + rom_executable_reg <= 1'h1; + led_reg <= 3'h6; + gpio1_reg <= 2'h0; + gpio2_reg <= 2'h0; + gpio3_reg <= 1'h0; + gpio4_reg <= 1'h0; + app_start_reg <= 32'h0; + app_size_reg <= APP_SIZE; + blake2s_addr_reg <= ILLEGAL_ADDR; + syscall_addr_reg <= ILLEGAL_ADDR; + cdi_mem[0] <= 32'h0; + cdi_mem[1] <= 32'h0; + cdi_mem[2] <= 32'h0; + cdi_mem[3] <= 32'h0; + cdi_mem[4] <= 32'h0; + cdi_mem[5] <= 32'h0; + cdi_mem[6] <= 32'h0; + cdi_mem[7] <= 32'h0; + cpu_trap_ctr_reg <= 24'h0; + cpu_trap_led_reg <= 3'h0; + cpu_mon_en_reg <= 1'h0; + cpu_mon_first_reg <= 32'h0; + cpu_mon_last_reg <= 32'h0; + ram_addr_rand_reg <= 15'h0; + ram_data_rand_reg <= 32'h0; + force_trap_reg <= 1'h0; + system_reset_reg <= 1'h0; end else begin @@ -304,6 +309,10 @@ module tk1 #( system_mode_reg <= system_mode_new; end + if (rom_executable_we) begin + rom_executable_reg <= rom_executable_new; + end + if (led_we) begin led_reg <= write_data[2 : 0]; end @@ -400,6 +409,13 @@ module tk1 #( // // Trying to execute instructions in FW-RAM. // + // Executing instructions in ROM, while ROM is marked as not + // executable. Note that there is an exception, if the cpu_addr is + // the first instruction in either functions set in syscall_addr_reg + // or blake2s_addr_reg, it is allowed. For the next instruction ROM + // will be marked as executable. + // Note that the address to the functions needs to be 4-bytes aligned. + // // Trying to execute code in mem area set to be data access only. // This requires execution monitor to have been setup and // enabled. @@ -417,6 +433,14 @@ module tk1 #( force_trap_set = 1'h1; end + if (!rom_executable_reg) begin + if ((cpu_addr != syscall_addr_reg) && (cpu_addr != blake2s_addr_reg)) begin + if (cpu_addr <= FW_ROM_LAST) begin // Only valid as long as ROM starts at address 0x00. + force_trap_set = 1'h1; + end + end + end + if (cpu_mon_en_reg) begin if ((cpu_addr >= cpu_mon_first_reg) && (cpu_addr <= cpu_mon_last_reg)) begin force_trap_set = 1'h1; @@ -427,24 +451,43 @@ module tk1 #( end //---------------------------------------------------------------- - // system_mode_ctrl will raise the privilege when the function in - // `syscall_addr_reg` is called. + // system_mode_ctrl dynamically sets the system mode and if ROM is + // executable depending on where we are currently executing. // - // Automatically lowers the privilege when executing above ROM + // If the function in `syscall_addr_reg` is called system_mode will + // be set to firmware mode, and ROM will be marked as executable. + // + // If the function in `blake2s_addr_reg` is called only ROM will be + // marked as executable. + // + // Automatically lowers the privilege and removes ROM execution when + // executing above ROM. + // + // Note that the address to the functions needs to be 4-bytes aligned. // ---------------------------------------------------------------- always @* begin : system_mode_ctrl - system_mode_new = 1'h0; - system_mode_we = 1'h0; + system_mode_new = 1'h0; + system_mode_we = 1'h0; + rom_executable_new = 1'h0; + rom_executable_we = 1'h0; if (cpu_valid & cpu_instr) begin if (cpu_addr == syscall_addr_reg) begin - system_mode_new = 1'h0; - system_mode_we = 1'h1; + system_mode_new = 1'h0; + system_mode_we = 1'h1; + rom_executable_new = 1'h1; + rom_executable_we = 1'h1; + end + if (cpu_addr == blake2s_addr_reg) begin + rom_executable_new = 1'h1; + rom_executable_we = 1'h1; end if (cpu_addr > FW_ROM_LAST) begin - system_mode_new = 1'h1; - system_mode_we = 1'h1; + system_mode_new = 1'h1; + system_mode_we = 1'h1; + rom_executable_new = 1'h0; + rom_executable_we = 1'h1; end end end diff --git a/hw/application_fpga/fw/tk1/blake2s/blake2s.c b/hw/application_fpga/fw/tk1/blake2s/blake2s.c index b46ad8a..eacd753 100644 --- a/hw/application_fpga/fw/tk1/blake2s/blake2s.c +++ b/hw/application_fpga/fw/tk1/blake2s/blake2s.c @@ -332,7 +332,7 @@ void blake2s_final(blake2s_ctx *ctx, void *out) //------------------------------------------------------------------ // Convenience function for all-in-one computation. //------------------------------------------------------------------ -int blake2s(void *out, size_t outlen, +int __attribute__((aligned(4))) blake2s(void *out, size_t outlen, const void *key, size_t keylen, const void *in, size_t inlen, blake2s_ctx *ctx)