International Association for Cryptologic Research

International Association
for Cryptologic Research

Transactions on Cryptographic Hardware and Embedded Systems 2026

UP TO 50% OFF:

Efficient Implementation of Polynomial Masking


README

UP TO 50% OFF: Efficient Implementation of Polynomial Masking

This repository contains the implementation, evaluation, and fault simulation for the paper UP TO 50% OFF: Efficient Implementation of Polynomial Masking. For this work, we have implemented an AES Sbox protected with polynomial masking, using the LaOla multiplication. We provide a microcontroller C implementation for the STM32F415 board, a QEMU reference, Sage code for the generation of polynomial masking parameters, fault simulation scripts, and ChipWhisperer notebooks for side-channel evaluation. Using the code and usage instructions in this repository allows you to reproduce our paper's results. The ChipWhisperer evaluation requires physical hardware; the QEMU correctness tests and fault simulations are fully reproducible without it.

ChipWhisperer Scope and Target

For the experiments in this paper we used the following devices:

While our codebase can be adapted to other targets and capture scopes with minimal changes, it was designed for and evaluated on these devices. If you adapt to different hardware, you might have to adapt the following:

Usage Instructions

Note: While this setup supports standalone Docker usage, it is primarily designed for VS Code together with the Dev Containers extension. Using those will provide the smoothest experience.

  1. Requirements and Preparation: We recommend installing VS Code and the Dev Containers extension before proceeding. The general setup we provide is platform-agnostic, as Dev Containers provide a fully self-contained dependency management, ensuring the reproducibility of our correctness tests and fault simulations. To reproduce the physical evaluation, the ChipWhisperer USB device needs to forwarded into the Dev Container, which is platform and version specific. We provide three options for USB forwarding:

    • Linux Simply install Docker and open the project in VS Code (see Step 2).

    • Windows and macOS

    USB access from Docker containers can be challenging because USB/IP support is limited on these platforms. USB forwarding is only required for physical evaluation with a connected ChipWhisperer device, if you are not running measurements on real hardware, you can use the container without USB forwarding. There is a workaround that uses a dedicated container to forward devices to other containers (see https://blog.golioth.io/usb-docker-windows-macos/).

    Finally, a common strategy is using a Linux virtual machine (e.g., via Oracle VirtualBox) on a Windows or MacOS host and passing the ChipWhisperer USB device through to the VM. Inside the VM, install Docker and open the repository using VS Code with the Dev Containers extension.

  2. Open the Project in VSCode:

Open the directory in VS Code and select the pop-up: Reopen in Container.

Or run Ctrl + Shift + P -> Dev Containers: Reopen in Container.

  1. Sage Setup Scripts: Use the bash script

    cd sage_scripts/
    bash generate_vars.sh
    

    to set up necessary components like polynomial support points, Vandermonde matrices and lookup tables.

  2. Run and Evaluate ChipWhisperer Implementation: Select the (discounted-poly-masking) python kernel and run the ChipWhisperer/ChipWhisperer_Evaluation.ipynb Jupyter notebook from top to bottom and follow its instructions to obtain benchmarking and TVLA results. Results of the TVLA are saved to ChipWhisperer/t-test/t-test-plots, where the TVLA plots of both the LaOla multiplication with 5M traces, and the full Sbox with 1M traces from our paper can be found.

  3. Test Implementation Correctness in QEMU: We provide a QEMU implementation in addition to our microcontroller implementation. The correctness of our implementation is tested by comparing masked computations against an unmasked reference function for parameters d={1,...,3}, e={0,...,3}, k=1 with Frobenius endomorphism enabled/disabled and our new zero-encodings, as well as, the zero-encodings from https://eprint.iacr.org/2023/1143.

    cd qemu_implementation
    bash regression_suite.sh -j <NUM_JOBS>
    

    Running this will test our components and produce either "All tests passed" or "Some tests failed" upon which qemu_implementation/make_run_log.txt can be examined for further detail.

  4. Fault Simulation of LaOla Multiplication: We also evaluate the fault resistance of polynomial masking, as our QEMU implementation is also augmented with the ability to perform simulated fault injection on any field operation. Specifically, the result of any field operation can be set to a value provided by the adversary, thus enabling set-value fault attacks. The experiments in our paper perform set-zero, as well as, set-random value fault injection on the LaOla multiplication and evaluate if and how the outcome of a faulted and unfaulted run, using the same randomness, differ. We consider a fault effective when the encoded values of both runs differ and a fault detected iff one of the higher-order coefficients of the result are non-zero. We thus classify three types of faults:

    1. detected faults: one or more higher-order coefficients are non-zero allowing the fault to be detected
    2. effective undetected faults: fault was not detected and managed to change the encoded secret value
    3. ineffective undetected faults: fault was not detected but did not change the encoded secret value

    Our fault simulation allows performing randomized set-zero/random fault injection by doing the following:

    cd fault_simulation
    bash run_fault_simulation.sh <NUM_FAULT_EXPERIMENTS> <SET_ZERO_FAULTS>
    

    Here NUM_FAULT_EXPERIMENTS specifies the number of runs to perform per parameter set and SET_ZERO_FAULTS is a bool that selects set-zero faults when true and set-random faults when false. The simulations in our paper perform a sweep across d={1,2}, e={1,2,3}, s={1,...,5}, where s denotes the number of injected faults, with 100M runs per parameter set for both set-zero and set-random faults. Our results are saved under set_random_faults/fault_analysis_report_rand_values_100M.log and set_zero_faults/fault_analysis_report_zero_values_100M.log. The associated .csv traces are saved under set_{random,zero}_faults/csv and log files are saved in the fault_simulation directory. To replicate these experiments run:

    bash run_fault_simulation.sh 100000000 true
    bash run_fault_simulation.sh 100000000 false
    

    Note that these experiments and their tracing are computationally heavy and required 8 hours and 500 GB of space on our server-grade machine. We recommend either compressing or deleting the resulting .csv files in the respective set_{random,zero}_faults/csv directories after runs.

    Furthermore, our paper includes a more extensive run of the d=1, e=3, s=5 parameter set that supports multithreaded trace acquisition.

    bash run_fault_simulation_d1_e3_s5.sh <NUM_FAULT_EXPERIMENTS> <SET_ZERO_FAULTS> <NUM_THREADS>
    

    Note: the script spawns NUM_THREADS worker processes for trace generation plus a small amount of auxiliary I/O work. Results depend on NUM_THREADS because the RNG seed is derived from the worker process ID. Our results were produced by merging two runs with 5B traces that were using different, randomly-generated, seeds.

Repository Structure

Here, we outline the general structure of our codebase in case you want to modify or use some of its components: