blob: 5d802b4bf83faf01faa45722739352c1add19f47 [file] [log] [blame] [view]
# AES Formal Masking Verification Using Alma
This directory contains support files to formally verify the masking employed
inside AES unit using the tool [Alma:
Execution-aware Masking Verification](https://github.com/IAIK/coco-alma).
## Prerequisites
Note that this flow is experimental. It has been developed using Yosys 0.9+4306
(git sha1 3931b3a03) and sv2v v0.0.9-24-gf868f06. Other tool versions might not
be compatible.
1. Download the Alma tool
Note that since we are primarily interested in verifying the masking of a
hardware implementation, we are using the `hw-verif` branch of the tool. In
addition, we currently need to use a patched version of the tool, to work
around a limitation.
```sh
git clone git@github.com:vogelpi/coco-alma.git alma -b fix-yosys-synth-template
```
The tip of this branch should be c8c7f67.
Enter the directory using
```sh
cd alma
```
Set up a new virtual Python environment
```sh
python3 -m venv dev
source dev/bin/activate
```
And install the Python requirements
```sh
pip3 install -r requirements.txt
```
1. Generate a Verilog netlist
A netlist of the DUT can be generated using the Yosys synthesis flow from
the OpenTitan repository. From the OpenTitan top level, run
```sh
cd hw/ip/aes/pre_syn
```
Set up the synthesis flow as described in the corresponding README. Then,
make sure to change the line in `syn_setup.sh`
```sh
export LR_SYNTH_TOP_MODULE=aes
```
to
```sh
export LR_SYNTH_TOP_MODULE=aes_sbox
```
to only synthesize an individual AES S-Box as formally verifying the entire
AES unit or the AES cipher core is currently out of scope from a tool run
time point of view. Alternatively, it is possible to verify `aes_sub_bytes`
containing all 16 S-Boxes of the data path or even `aes_reduced_round` which
besides the S-Boxes also includes the ShiftRows and MixColumns operations.
Then run the synthesis
```sh
./syn_yosys.sh
```
## Formally verifying the masking of the AES unit
After downloading the Alma tool, installing dependencies and synthesizing AES,
the masking can finally be formally verified.
1. Make sure to source the `build_consts.sh` script from the OpenTitan
repository
```sh
source util/build_consts.sh
```
in order to set up some shell variables.
1. Enter the directory where you have downloaded Alma and load the virtual
Python environment
```sh
source dev/bin/activate
```
1. Launch the Alma tool to parse, trace (simulate) and formally verify the
netlist. For simplicity, a single script is provided to launch all the
required steps with a single command. Simply run
```sh
${REPO_TOP}/hw/ip/aes/pre_sca/alma/verify_aes.sh
```
This should produce output similar to the one below:
```sh
Verifying aes_sbox using Alma
File tmp/circuit.v already exists, do you want to overwrite it? (y/n) y
Starting yosys synthesis...
| CircuitGraph | Total: 1692 | Linear: 504 | Non-linear: 375 | Registers: 167 | Mux: 228 |
parse.py successful (2.80s)
1: Running verilator on given netlist
2: Compiling verilated netlist library
3: Compiling provided verilator testbench
4: Simulating circuit and generating VCD
| CircuitGraph | Total: 1692 | Linear: 504 | Non-linear: 375 | Registers: 167 | Mux: 228 |
tmp/tmp.vcd:1286: [WARNING] Entry for name clk_i already exists in namemap (clk_i -> K,)
tmp/tmp.vcd:1287: [WARNING] Entry for name data_i already exists in namemap (data_i -> L,)
tmp/tmp.vcd:1288: [WARNING] Entry for name data_o already exists in namemap (data_o -> M,)
tmp/tmp.vcd:1289: [WARNING] Entry for name en_i already exists in namemap (en_i -> N,)
tmp/tmp.vcd:1381: [WARNING] Entry for name mask_i already exists in namemap (mask_i -> O,)
tmp/tmp.vcd:1382: [WARNING] Entry for name mask_o already exists in namemap (mask_o -> P,)
tmp/tmp.vcd:1383: [WARNING] Entry for name op_i already exists in namemap (op_i -> Q,)
tmp/tmp.vcd:1384: [WARNING] Entry for name out_ack_i already exists in namemap (out_ack_i -> R,)
tmp/tmp.vcd:1385: [WARNING] Entry for name out_req_o already exists in namemap (out_req_o -> S,)
tmp/tmp.vcd:1386: [WARNING] Entry for name prd_i already exists in namemap (prd_i -> T,)
tmp/tmp.vcd:1387: [WARNING] Entry for name rst_ni already exists in namemap (rst_ni -> U,)
0
0
Building formula for cycle 0: vars 0 clauses 0
Checking cycle 0:
Building formula for cycle 1: vars 114 clauses 312
Checking cycle 1:
Building formula for cycle 2: vars 3276 clauses 10534
Checking cycle 2:
Checking probe (cycle 2, and _0436_[0]): 0.00
Checking probe (cycle 2, and _0378_[0]): 0.00
...
Checking probe (cycle 5, not gen_sbox_masked.gen_sbox_dom.u_aes_sbox.u_aes_dom_inverse_gf2p8.u_aes_dom_inverse_gf2p4.u_aes_dom_mul_gamma1_gamma0.u_prim_xilinx_buf_mul_abx_z0.out_o[2]): 0.00
Checking probe (cycle 5, xor gen_sbox_masked.gen_sbox_dom.u_aes_sbox.u_aes_dom_inverse_gf2p8.u_aes_dom_inverse_gf2p4.u_aes_dom_mul_gamma1_gamma0.u_prim_xilinx_buf_mul_abx_z0.out_o[3]): 0.00
Checking probe (cycle 5, mux _0914_[0]): 0.00
Checking probe (cycle 5, mux _0912_[0]): 0.00
Checking probe (cycle 5, mux _0925_[0]): 0.00
Checking probe (cycle 5, mux _0923_[0]): 0.00
Checking probe (cycle 5, mux _0945_[0]): 0.00
Checking probe (cycle 5, mux _0943_[0]): 0.00
Checking probe (cycle 5, mux _0898_[0]): 0.00
Checking probe (cycle 5, mux _0913_[0]): 0.00
Checking probe (cycle 5, mux _0911_[0]): 0.00
Checking probe (cycle 5, mux _0897_[0]): 0.00
Finished in 50.74
The execution is secure
```
By default, this script will verify the AES S-Box. But you can actually
specify the top module to verify. For example, to verify a single, reduced
AES round without AddKey operation, first re-run the Yosys synthesis with
```sh
export LR_SYNTH_TOP_MODULE=aes_reduced_round
```
and then execute
```sh
${REPO_TOP}/hw/ip/aes/pre_sca/alma/verify_aes.sh aes_reduced_round
```
## Individual steps in detail
Below we outline the individual steps performed by the `verify_aes.sh` script.
This is useful if you, e.g., want to verify the masking of your own module.
For this how to, we focus on the most simple case, i.e., the formal
verification of a single AES S-Box.
For more details, please refer to the [Alma tutorial](https://github.com/IAIK/coco-alma/tree/hw-verif#usage).
1. The first step involves the parsing the synthesized netlist.
```sh
./parse.py --top-module aes_sbox \
--source ${REPO_TOP}/hw/ip/aes/pre_syn/syn_out/latest/generated/aes_sbox.alma.v \
--netlist tmp/circuit.v --log-yosys
```
1. Next, the automatically generated labeling file `tmp/labels.txt` needs to be
adapted. This file tells Alma which inputs of the DUT correspond to the
secret shares and which ones are used to provide randomness for
(re-)masking. Open the file and change the lines
```
data_i [7:0] = unimportant
mask_i [7:0] = unimportant
prd_i [27:0] = unimportant
```
to
```
data_i [7:0] = secret 7:0
mask_i [7:0] = secret 7:0
prd_i [27:0] = random
```
1. Then the Verilator testbench can be compiled and run required to identify
control signals and the like
```sh
./trace.py --testbench ${REPO_TOP}/hw/ip/aes/pre_sca/alma/cpp/verilator_tb_aes_sbox.cpp \
--netlist tmp/circuit.v -o tmp/circuit
```
1. Finally the verification of the masking implementation can be started.
```sh
./verify.py --json tmp/circuit.json \
--label tmp/labels.txt \
--top-module aes_sbox \
--vcd tmp/tmp.vcd \
--rst-name rst_ni --rst-phase 0 \
--probe-duration once --mode transient \
--glitch-behavior loose --cycles 6
```
## Details of the provided support files
- `cpp`: SystemVerilog testbench, instantiates and drives the synthesized
netlist of the DUT.
- `verify_aes.sh`: Script to run the parse, trace and compile steps with
one single command.