Software beginner's guide - ChairImpSec/PROLEAD GitHub Wiki

Welcome to the beginner's guide to PROLEAD_SW for ARM binary evaluation! Whether you are a side-channel expert or a software developer without deep knowledge about side-channels, PROLEAD_SW is here to assist you in evaluating your masked software designs.

Installation

Before diving into the evaluation process with PROLEAD, it's important to ensure that you have successfully installed the tool. If you haven't done so already, please refer to Installation for detailed instructions on the installation steps. For PROLEAD_SW it is only necessary to follow installation section of PROLEAD, i.e., you can ignore the chapters from Icarus Verilog onward.

Implementation

The first step in evaluating the side-channel security of a masked software design is to implement the software that should be tested. You can use arbitrary many source and header files written in either C or ARM assembly. Note that for ARM instructions we currently support the ARMv6-M, ARMv7-M and ARMv7E-M (DSP extension) instruction sets. We would also like to note that we do not currently support Floating Point instructions and Vector instruction. If you are not familiar which instructions this coveres we refere to page six of the Cortex-M for Beginners guide.

Feature Requirements

PROLEAD_SW is a simulation based tool. This means it generates different inputs, feeds those inputs into the software design and simulates the execution under those inputs. In order to guarantee a correct execution we use certain design choices in the software that need to be considered when configuring your own use case.

Using PROLEAD_SW's internal randomness source

In certain designs it might be necessary to use fresh randomness. While you are able to write your own PRNG in one of your source files, we also provide a randomness source called randomness. It is a 32-bit variable that when used will refresh its content. If you want to use this randomness source you need to consider two things. First of all in your main C-file you need to globally declare this variable as uint32_t randomness __attribute__((section(".randomness")));. Secondly, in your Linker file you will need a dedicated, aligned 4-byte memory area called .randomness. You can find an example how this could look like in your Linker file here. Afterwards you can use the variable like any other variable.

Declaring inputs for the simulation

To let PROLEAD_SW know where it can store the chosen inputs for simulation into memory without overwriting other global variables or arrays, we have to reserve the amount of bytes required for the inputs in memory. PROLEAD_SW does this by defining global arrays where it will write the values into. For example if we want to evaluate a scheme which takes two shares, where each share consists of 8 bytes, as input we would write something like this:

unsigned char input_s1[8] __attribute__((section(".data")));
unsigned char input_s2[8] __attribute__((section(".data")));

The cipher function

Every software that will be tested with PROLEAD_SW needs a cipher function. This is the core function of PROLEAD_SW and contains all the code that should be evaluated. In here will be placed your actual masked implementation. What you do inside this cipher function is completely up to you. You are able to call assembly functions, other C functions or have recursion.

The Linker Script

To make use of the randomness variable provided by PROLEAD_SW we recommned to use the following section to declare the memory area containing the 4 byte randomness.

.randomness : 
{
    . = ALIGN(4);
    _random = .;
    _erandom = .;
} >ram

Furthermore, PROLEAD_SW requires an additional symbol _end = . ; within the Linker file that marks the end of all memory sections and symbols _data = .; and _edata = .; to mark the start, respective end of the .data section.

Compilation

For the compilation we use the arm-none-eabi-gcc compiler for all our examples provided. However, as long as a compiler is able to generate the required files (i.e. ELF-binary, disassembly file, and map file) PROLEAD_SW should be able to handle those compilers as well. For compilation you have two options choose from.

Let PROLEAD_SW compile your code

PROLEAD_SW takes your specified source- and headerfiles and the Linker file, which specifies the format and layout of the final binary, and invokes internally our arm-none-eabi-gcc compiler. During the compilation it will generate three important files. The ELF binary contains the final binary that was created from all your source files. The map file contains details about the memory mapping, and the disassembly file is a textual representation of the binary. Two examples that use PROLEAD_SW's internal compiler can be found here, and here. In the respective folders binary we can find the three required output files, the corresponding invocation flags under results\normal_mode\run.sh and the source and linker files can be found under source.

Compile externally

You are able to use third-party makefiles and compilations and only provide the necessary output files that are required by PROLEAD_SW. An example with the same folder structure can be found here. Note that we have in this folder now a third party makefile which can be used to compile the software before invoking PROLEAD_SW. To call now PROLEAD_SW we change the invocation flags in results\normal_mode\run.sh so that it takes now as input flags the three files from the compilation procedure.

Evaluation

In the final step, we utilize PROLEAD_SW to assess the probing security of the generated binary. Prior to running the evaluation, it is necessary for the user to provide specific details about the implemented design and the desired security parameter for analysis. Once the configuration is set, PROLEAD_SW takes in the provided information along with the binary to evaluate the design's security.

Customization

In addition to the netlist, PROLEAD_SW requires an accompanying configuration file to customize its capabilities. While multiple settings inside this configuration file overlap with the hardware version, we have certain options specifically for software that we would like to mention and explain.

no_of_initial_inputs

The first line in this setting is a number that specifies the number of inputs used for the simulation. Afterwards you have to enumerate all inputs used for the simulation. Using the same example from the Declaring inputs for the simulation section your setting would look like this

2

[63:0] arr input_s1 group_in0[63:0]
[63:0] arr input_s2 group_in1[63:0]

The first position specifies the length of the input in bits. As in our example the input is 8 bytes long we have 64 bits. Secondly, you have to define if the input is a array (arr) or a variable (var). Then you specify the name of the input. Here it is important that the name of the input matches exactly the name of the global input defined in your source file (see Declaring inputs for the simulation). This is required as it gives PROLEAD_SW the possibility to create a unique mapping and thus to know where to write the chosen inputs to memory. Then you need to specify if the inputs should be in a shared form or not. If you want to create two shares from the respecitve input you have to specify it with group_inX where X starts at 0 and represents the share index. In the example above we have input_s1 and input_s2 which are two shares that will be generated from the 64 bit input. If you want to pass a fix value to the simulation you remove group_inX and replace it with the concrete value, e.g. 64'h00112233deadbeef

compiler_flags

Specifies the compiler flags if you want to use PROLEAD_SW's internal compiler. Leave this flag empty if you use an external compilation.

location_of_cipher

Specifies the function that calls the cipher function. This is a hint for PROLEAD_SW if the compiler during compilation slightly changes the name of cipher. This can happen during some internal optimizations steps in the compiler. If so, PROLEAD_SW searches in the function that calls cipher for function calls that are related to the original cipher name. If PROLEAD_SW still does not manage to find the function we suggest to explicitely state that cipher should not be inlined by using compiler hints in your source file.

pipeline_stages

Specifies the number of pipeline stages for the processor you want to run the simulation on. For M0, M0+ and M4 this will always be 3. For other processors we recommend to search for the specific processor here and check the respective data sheet.

Possible probes to choose from

PROLEAD_SW's probe name Setting
RX X is a number between 0 and 16. Tells PROLEAD_SW to probe register RX. One probe contains the i-th bit of register RX. R16 is the special PSR register.
MEM Tells PROLEAD_SW to place a probe on each memory position. Will detect overwrites in memory.
MEMSHADOW Tells PROLEAD_SW to place a probe on the shadow register R17 which is placed between memory and the registers.
HR Tells PROLEAD_SW to generate a horizontal probe. One probe contains all 32 bits of the destination register of a instruction.
VR Tells PROLEAD_SW to generate a pairwise vertical probe. One probe contains the i-th bit of the destination register of a instruction with the pairwise combination of the i-th bit of every other register.
FULLHR Tells PROLEAD_SW to generate a full horizontal probe. One probe contains all 32 bits of the destination register of a instruction with the pairwise combination of all 32 bits of every other register.
FULLVR Tells PROLEAD_SW to generate a full vertical probe. One probe contains the i-th bit of every register, i.e. the i-th bit of R0 to R16.
PF Tells PROLEAD_SW to generate a pipeline forwarding probe. One probe contains all registers in #pipeline_stages instructions.

Run

Finally, the design and PROLEAD_SW are ready for evaluation. To simplify the process, we have provided an execution script run.sh in each results\normal_mode and results\compact_mode directory. This script executes PROLEAD and redirects the console output to a separate file. To execute the script simply go into the respective directory that contains the run.sh file and run it by calling ./run.sh in your console.

To test the implementations used in our publication all you have to do is execute run.sh in the respective resuts\normal_mode folder. We adapted the config.set files to match our evaluations for the paper. Please note that all case-studies were executed using 30 threads. Differences in runtime and/or memory consumption can arise through different platforms, processors, number of threads etc.

Trouble Shooting

In this Section we provide some solutions if you run into problems during the execution of PROLEAD_SW.

The ARM GCC Toolchain

With newer versions of the ARM toolchain, PROLEAD_SW might throw linker errors when trying to compile your software. If so we recommend to add the --specs=nosys.specs compiler flag in the respective config.set under the compiler_flags setting.

The Linker Script

In order for PROLEAD_SW to detect and distinguish different memory sections in your program, it requires certain symbols to be present within the Linker file and the map file. In particular, the .data section needs to start with the _data = .; symbol and needs to end with the _edata = .; symbol. Additionally, to mark the end of all sections we need to add the _end = .; symbol at the end of our linker script. An specific example can be found here.

Python.h not found

If during compilation of PROLEAD you get the error message Python.h not found please run sudo apt-get install python-dev if you have python 2.x installed or sudo apt-get install python3-dev if you have python 3.x installed and reboot your system. For other package managers we refer to here.