Quickstart - ChairImpSec/PROLEAD GitHub Wiki
Ready to dive in? This guide is designed for beginners and will walk you through the essential steps to get started with PROLEAD and begin evaluating your masked hardware designs.
- You have reviewed our papers: PROLEAD and PROLEAD_SW.
- PROLEAD is installed.
To verify that PROLEAD was successfully installed and to view a list of available command-line options, run the following command in your terminal:
PROLEAD -h
This will display a help message with usage instructions and a summary of all supported parameters. A list of all available command line parameters is also given here.
To evaluate a masked hardware design using PROLEAD, you'll need the following files:
- Masked hardware design – A gate-level netlist written in Verilog.
- Cell library – A JSON file defining the characteristics of the logic gates used.
- Configuration file – A JSON file specifying the evaluation parameters.
The sections below explain how to obtain and prepare each of these required files.
Note: If you're just getting started, you can run the default example by using the simple command:
PROLEAD
This will evaluate the netlistdesign.v
using the cell library located atlibs/nang45.json
and the configuration fileconfig.json
.
It is possible to download an example dom_indep_d1.v
from the repository.
Do you have a masked hardware design you'd like to analyze with PROLEAD? Great! To get started, simply synthesize your design into a gate-level Verilog netlist. We encourage you to use the synthesizer and standard-cell library of your choice. So far, PROLEAD has been successfully applied to netlists synthesized using the following configurations:
- We used the comercially available Synopsys DC for ASIC synthesis along with the Nangate 45 nm standard-cell library.
- We used the open-source tool Yosys along with a custom standard-cell library to get an ASIC netlist.
- We used the Vivado Design Suite from AMD with the UltraScale library to receive an FPGA netlist.
Note: Designing masked hardware even at the behavioral level can be challenging. If you're new to hardware masking or looking to simplify the development of masked circuits, consider using AGEMA. With AGEMA, you only need to provide your unmasked hardware design—the tool will automatically generate a masked version for you.
PROLEAD requires a custom cell library that defines the behavior of the cells used in your netlist. Accurate simulation is only possible if the library correctly specifies all cell functionalities. Fortunately, if you used one of the synthesis procedures listed above, we've already done the work for you and prepared compatible cell libraries. Depending on your synthesis setup, we recommend using one of the following libraries:
- The nang45 library you can find here.
- The custom library you can find here.
- The xilinx_fpga library you can find here.
Note: Is a specific gate required in your netlist missing from our provided libraries? Or is your preferred standard-cell library currently unsupported? We're here to help! You can request support for additional libraries by starting a discussion, or, if you prefer, write your own cell library.
PROLEAD supports a wide range of settings that allow for precise customization of the evaluation procedure. However, we understand that introducing all of these options at once can be overwhelming for beginners. Therefore, we'll start by guiding you through the most important settings and will introduce the remaining ones as they become relevant. All settings for PROLEAD are provided through a single JSON file. These settings are generally categorized into performance settings, simulation settings, and analysis settings. Additionally, a few extra settings related to hardware configuration are also required. As a starting point, you can ask yourself the following questions to ensure you don’t miss something important:
Question | Setting |
---|---|
What's the name of the clock signal? | clock_signal_name |
How many cycles should the design run? | max_clock_cycle |
It is possible to download a full example configuration dom_indep_d1.json
.
To evaluate a hardware design, PROLEAD requires simulation. This necessitates specifying both the number of inputs and their specific values for the simulation. Defining an input sequence involves selecting a series of suitable (shared) input values. To demonstrate the subsequent steps, we will examine a simple first-order masked DOM-AND. Our example expects two shared intputs
Note: You don't know how to execute this example? Just copy both files into the PROLEAD directory, replacing the existing ones. Then, simply type
PROLEAD
to execute. Or have a look at running the hardware evaluation.
Netlist (design.v) | Configuration File (config.json) |
---|---|
module circuit (clk, a, b, c, r);
input clk;
input [1:0] a;
input [1:0] b;
input r;
output [1:0] c;
wire i0, i1, i2, i3, j0, j1, l0, l1;
AND2_X1 U0 (.A1(a[0]), .A2(b[0]), .ZN(i0));
AND2_X1 U1 (.A1(a[0]), .A2(b[1]), .ZN(i1));
AND2_X1 U2 (.A1(a[1]), .A2(b[0]), .ZN(i2));
AND2_X1 U3 (.A1(a[1]), .A2(b[1]), .ZN(i3));
XOR2_X1 U4 (.A(i1), .B(r), .Z(j0));
XOR2_X1 U5 (.A(i2), .B(r), .Z(j1));
DFF_X1 U6 (.D(j0), .CK(clk), .Q(l0));
DFF_X1 U7 (.D(j1), .CK(clk), .Q(l1));
XOR2_X1 U8 (.A(i0), .B(l0), .Z(c[0]));
XOR2_X1 U9 (.A(i3), .B(l1), .Z(c[1]));
endmodule |
{
"simulation": {
"groups": ["2'b11", "2'b$$"],
"number_of_clock_cycles": 3,
"always_random_inputs": ["r"],
"input_sequence": [
{
"signals": [
{"name": "a[0]", "value": "group_in0[0]"},
{"name": "b[0]", "value": "group_in0[1]"},
{"name": "a[1]", "value": "group_in1[0]"},
{"name": "b[1]", "value": "group_in1[1]"}
]
}
]
},
"hardware": {
"clock_signal_name": "clk"
}
} |
First, you need to define a set of groups, which are bitvectors that PROLEAD uses to derive its simulation inputs. Later, PROLEAD applies statistical methods to analyze the independence between these groups. You can define as many groups as needed; however, a fixed-vs-random setup is often a good choice. In our example, we define two groups, since the circuit computes a shared version of a function with two inputs. Each group is represented as a 2-bit vector. The fixed group sets both input bits to 1, while the random group samples two new bits randomly for each simulation, indicated by the $
symbol.
"groups": [
"2'b11", // 2'b11 is the fixed group (both bits are 1)
"2'b$$" // 2'b$$ is the random group (both bits are randomly sampled for each simulation)
],
PROLEAD randomly selects one of the defined groups for each simulation and generates input values based on the input_sequence
setting. This setting determines how concrete values are assigned to the input signals in the netlist. As a result, all input signals, except for the clock signal and the fresh masks, must be explicitly assigned.
To generate shared input values, shared inputs are assigned using placeholder values with the syntax group_inX[Y]
, defined as follows:
- X refers to the share index of the signal.
- Y refers to the bit index within the selected group.
"input_sequence": [
{
"signals": [
{"name": "a[0]", "value": "group_in0[0]"}, // Set a[0] to the first share of the first input
{"name": "b[0]", "value": "group_in0[1]"}, // Set b[0] to the first share of the second input
{"name": "a[1]", "value": "group_in1[0]"}, // Set a[1] to the second share of the first input
{"name": "b[1]", "value": "group_in1[1]"} // Set b[1] to the second share of the second input
]
}
Note: This is a brief example intended to provide a basic intuition on how to assign inputs for simulation. If it’s still unclear how this example can be extended to more complex scenarios, please refer to the follow-up guide on writing advanced input sequences.
Finally, you can specify how many simulations PROLEAD should perform. There are three settings to specify the number of simulations:
Setting | Meaning |
---|---|
number_of_simulations | The total number of simulations PROLEAD should perform. |
number_of_simulations_per_step | PROLEAD divides the total number of simulations into equal-sized steps. Each step runs a portion of the simulations and evaluates the side-channel resistance. After each step, an intermediate evaluation result is reported. You can specify how many simulations each step should include. |
number_of_simulations_per_write | Once a step is completed, PROLEAD can generate an evaluation report file to provide the results to you. You can specify the frequency of these reports, such as after each step or only once after the entire evaluation is finished. |
Feel free to experiment with different settings to find what works best on your machine. Increasing the number of simulations per step will likely improve runtime performance but also increase RAM usage, and the reverse is also true. For the example above, some possible simulation counts might be the following:
"number_of_simulations": 1536000, // Perform 1536000 simulations in total
"number_of_simulations_per_step": 128000, // Perform 128000 simulations per step. So 12 steps in total.
"number_of_simulations_per_write": 1536000 // Write one report after all simulations.
Once you are confident that your simulations are running as intended, it's time to define the evaluation procedure. This primarily involves specifying the security guarantees to be checked. The most recent settings are listed below:
Question | Setting |
---|---|
Which security order to test? | order |
Consider transitional leakage? | transitional_leakage |
Which clock cycles shall be targeted? | clock_cycles |
Note: More advanced settings provide the ability to fine-tune every probe an adversary can place, along with its extensions. For detailed instructions, refer to our guide on Effective Circuit Probing: A Step‐by‐Step Guide to Placement, Extention, and Removal
Congratulations! You have completed all the preparation steps and are now ready to evaluate your design using PROLEAD. To proceed, use the following command, which includes all the files you previously specified:
PROLEAD -l path/to/your/library -n your_library_name -d path/to/your/netlist -m your_topmodule_name -c path/to/your/config
After completing the evaluation, you may find it helpful to review the guidance on interpreting the results generated by PROLEAD.
To evaluate a masked software using PROLEAD_SW, you will need the following components:
- Masked Software – Files written C or ARM assembly or an externally compiled binary.
- Linker Script – A .ld file.
- Configuration file – A JSON file specifying the evaluation parameters.
The following sections explain how to obtain and prepare each of these required files.
You can implement your masked software using any number of source and header files written in either C or ARM assembly.
Currently, we support ARM instructions from the following instruction sets:
- ARMv6-M
- ARMv7-M
- ARMv7E-M (including the DSP extension)
Note: Floating-point and vector instructions are not supported at this time. If you're unsure which instructions fall under these categories, we recommend referring to page 6 of the Cortex-M for Beginners guide.
When configuring your own software for evaluation with PROLEAD, you must also adhere to the following design choices.
In some cases, your implementation may require fresh randomness. Although you’re free to implement your own pseudorandom number generator (PRNG) in your source files, we also provide a built-in randomness source named randomness
. This 32-bit variable automatically refreshes its value each time it’s accessed. If you choose to use randomness
, keep the following two considerations in mind:
- In your main C-file, you need to globally declare this variable as
uint32_t randomness __attribute__((section(".randomness")));
- In your linker file, you need a dedicated, aligned 4-byte memory area called
.randomness
.
.randomness :
{
. = ALIGN(4);
_random = .;
_erandom = .;
} >ram
To inform PROLEAD_SW where to store the selected simulation inputs in memory, without overwriting existing global variables or arrays, you need to reserve the appropriate number of bytes. This is done by defining global arrays into which PROLEAD_SW will write the input values. For example, if you're evaluating a scheme that takes two shares as input, with each share consisting of 8 bytes, you can define the input storage like this:
unsigned char input_s1[8] __attribute__((section(".data")));
unsigned char input_s2[8] __attribute__((section(".data")));
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.
In addition to the randomness area, 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.
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.
PROLEAD_SW takes the specified source files, header files, and linker file, which defines the format and layout of the final binary, and internally invokes the arm-none-eabi-gcc
compiler. During compilation, it generates three output 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.
- The disassembly file is a textual representation of the binary.
Note: Two examples that invoke PROLEAD_SW's internal compiler can be found here, and here. The source and linker files are stored in the src directory while the outputs of the compilation are stored in bin.
You can use third-party Makefiles and compilation processes, as long as you provide the necessary output files required by PROLEAD_SW. A reference example with the same folder structure is available here. In this folder, a third-party Makefile is included and can be used to compile the software prior to invoking PROLEAD_SW.
Most of the settings are similar to those specified in the configuration files used for hardware evaluation. However, certain options are specifically tailored for software evaluation, as explained below.
Defining inputs for the software simulation is generally easier than for the hardware, as multiple input initializations cannot be distributed across several clock cycles. The only difference from hardware evaluation lies in the type
, which specifies whether the input is a variable (var
) or an array (arr
). Please note that the variable names specified in the configuration must excatly match the name of the
globally declared input variable.
"input_sequence": [
{
"signals": [
{"name": "input_s1[63:0]", "value": "group_in0[63:0]", "type": "arr"}, // Set unsigned char input_s1[8] to the first share
{"name": "input_s2[63:0]", "value": "group_in1[63:0]", "type": "arr"} // Set unsigned char input_s2[8] to the second share
]
}
If you choose to use PROLEAD_SW's internal compilation procedure, you must specify the required compiler flags in the configuration file. However, if you opt for external compilation, specifying compiler flags in PROLEAD_SW is not necessary.
Additionally, you must inform PROLEAD_SW which function calls the cipher
function. This serves as a hint to PROLEAD_SW in case the compiler alters the name of cipher
during internal optimization steps. If such a change occurs, PROLEAD_SW will search within the calling function for any function calls that resemble the original cipher
name. If PROLEAD_SW is still unable to locate the cipher
function, we recommend explicitly preventing it from being inlined by using appropriate compiler directives in your source code.
"software": {
"compiler_flags": "-march=armv7-m -O3",
"location_of_cipher": "main" // The main function calls the cipher function
}
To analyze leakage related to specific micro-architectural effects, you can freely choose which types of probes (as defined in the original PROLEAD_SW paper) to include in the evaluation. A list of possible probes to place is given in the following table:
Probe Specifier | Description |
---|---|
RX | Probes register R0–R16, where X is the register number (0 ≤ X ≤ 16). Each probe captures the i-th bit of register RX. Note: R16 is the special Program Status Register (PSR). |
MEM | Places a probe on each memory location. Used to probe memory overwrites during execution. |
MEMSHADOW | Probes the shadow register R17, which intermediates between memory and the general-purpose registers. |
HR | Generates a horizontal probe. Captures all 32 bits of the destination register of an instruction. |
VR | Generates a pairwise vertical probe. For each bit position i, this probe combines the i-th bit of the destination register with the i-th bit of all other registers. |
FULLHR | Generates a full horizontal probe. Captures all 32 bits of the destination register of an instruction with pairwise combination of all 32 bits of every other register. |
FULLVR | Generates a full vertical probe. Captures the i-th bit of every register (R0–R16) into a single probe. |
PF | Generates a pipeline forwarding probe. Captures all registers involved in the last #pipeline_stages instructions. |
You can include and exclude probes for the simulation with the probe_placement. This option allows you to specify regular expressions that match probe specifiers. In the example provided below, all probes discussed above except the full horizontal probes are considered during evaluation.
"probe_placement": {
"include": {
"signals": ".*" // Initially, include all possible probes.
},
"exclude": {
"signals": "FULLHR" // Then, exclude the full horizontal probes.
}
}
You are now ready to evaluate your implementation with PROLEAD_SW. To proceed, use one the following commands. One command includes the source files for the internal compilation and the paths at which the compilation outputs should be stored. The other command assumes an external compilation and specifies only the paths to the compilation output files.
PROLEAD -p sw -k path/to/your/linker -d path/to/source1 path/to/source2 -b path/to/store/elf -f path/to/store/map -a path/to/store/asm -c path/to/config
PROLEAD -p sw -b path/to/elf -f path/to/map -a path/to/asm -c path/to/config
After completing the evaluation, you may find it helpful to review the guidance on interpreting the results generated by PROLEAD_SW.
Note: You may encounter the following issue when running PROLEAD_SW for the first time.
ModuleNotFoundError: No module named 'inc' terminate called after throwing an instance of 'std::runtime_error' what(): in read binaryfile: PyImport_Import error
In that case, you need to add PROLEAD_SW to your python path by running
export PYTHONPATH="/path/to/PROLEAD/:$PYTHONPATH
Here is an example output from PROLEAD, along with detailed explanations of each reported parameter:
-------------------------------------------------------------------------------------------------------------------------------------
| #Standard Probes | #Extended Probes | #Probing Sets | Minimum #Probes per Set | Maximum #Probes per Set | Average #Probes per Set |
-------------------------------------------------------------------------------------------------------------------------------------
| 63 | 75 | 63 | 4 | 9 | 6.142857 |
-------------------------------------------------------------------------------------------------------------------------------------
Evaluate security under the robust probing model!
----------------------------------------------------------------------------------------------------------------------------------------
| Elapsed Time | Required Ram | Processed Simulations | Probing Set with highest Information Leakage | -log10(p) | Status |
----------------------------------------------------------------------------------------------------------------------------------------
| 0.024586s | 3.792712GB | 3200 / 20325 | [share2[3](2)] | 16.714087 | LEAKAGE |
| 0.029380s | 3.792844GB | 6400 / 20325 | [share2[3](2)] | 34.191856 | LEAKAGE |
| 0.034193s | 3.792844GB | 9600 / 20325 | [share2[3](2)] | 47.404428 | LEAKAGE |
| 0.038922s | 3.792844GB | 12800 / 20325 | [share2[3](2)] | 71.011855 | LEAKAGE |
| 0.042672s | 3.792844GB | 16000 / 20325 | [share2[3](2)] | 89.630361 | LEAKAGE |
| 0.047150s | 3.792844GB | 19200 / 20325 | [share2[3](2)] | 111.988367 | LEAKAGE |
| 0.051861s | 3.792844GB | 22400 / 20325 | [share2[3](2)] | 131.447051 | LEAKAGE |
| 0.056635s | 3.792844GB | 25600 / 20325 | [share2[3](2)] | 142.839991 | LEAKAGE |
| 0.061358s | 3.792844GB | 28800 / 20325 | [share2[3](2)] | 169.059104 | LEAKAGE |
| 0.064959s | 3.792844GB | 32000 / 20325 | [share2[3](2)] | 186.577086 | LEAKAGE |
----------------------------------------------------------------------------------------------------------------------------------------
Evaluation done in 0.06564 seconds!
Initially, PROLEAD provides preliminary information about the evaluation process. This allows you to estimate the required evaluation time and memory usage, enabling to adjust the settings accordingly before the evaluation begins.
Output Parameter | Description |
---|---|
#Standard Probes | The total number of distinct probes that an adversary can place is determined by combinations of wires and their corresponding time instances. Consequently, the number of standard probes increases with both the design complexity and its runtime. |
#Extended Probes | The total number of distinct probes generated by extending the standard probes. |
#Probing Sets | The total number of distinct adversaries, each defined by a unique set of placed standard probes. Each probing set must be stored and evaluated. As the number of probing sets increases, so do the evaluation time and memory consumption. |
Minimum #Probes per Set | The smallest number of probes found in any single probing set. |
Maximum #Probes per Set | The largest number of probes found in any single probing set. |
Average #Probes per Set | The average number of probes across all probing sets. |
PROLEAD continuously updates to reflect the evaluation's progress, including simulation time, memory usage, and potential information leakage.
Output Parameter | Description |
---|---|
Elapsed Time | Total time elapsed since the evaluation began. |
Required RAM | Amount of RAM used by PROLEAD up to the current point in the evaluation. |
Processed Simulations | Number of simulations completed so far. If evaluating in normal mode, the required total for statistical power is shown after a slash (e.g., 3200 / 20325 ). |
Probing Set with Highest Information Leakage | The probe exhibiting the greatest information leakage. Standard probes are denoted by signal name and clock cycle in parentheses (e.g., share2 ). |
-log10(p) | Maximum observed g-test result in logarithmic form. Higher values indicate stronger evidence of leakage. |
Status | Leakage status based on the -log10(p) value: OKAY if below 5 (no significant leakage), or LEAKAGE if 5 or above (leakage detected). |