Post-quantum masked crypto library for the ARM Cortex-M4. Currently, Kyber768 and saber are implemented. See the research paper.
This is an updated version to fix weaknesses identified by Zeitschner et al..
For the version evaluated in the paper, see the tches
tag.
The pqm4_masked library is based on pqm4.
The main differences are
-
the addition of masked implementations of the following schemes:
- Kyber768 (in
crypto_kem/kyber768/m4fspeed_masked
, tested on thenucleo-l4r5zi
target); /!\This implementation is provided for demonstration and benchmarking purposes. It has NOT been subjected to any leakage assessment. Use it at your own risk./!\ - SABER (in
crypto_kem/saber/m4fspeed_masked
, tested on thenucleo-l4r5zi
target); /!\This implementation is provided for demonstration and benchmarking purposes. It has NOT been subjected to any leakage assessment. Use it at your own risk./!\
- Kyber768 (in
-
some changes in the tooling to allow for finer-grained benchmarking and testing (for this, we use a slightly modified version of the
mupq
submodule located at <https//github.com/uclcrypto/mupq>).
The provided code has not been extensively optimized. Simple programming tricks can improve the performances, especially for small number of shares.
Same as pqm4.
For the purpose of simple testing and benchmarking, the pqm4_masked library uses the NIST/SUPERCOP/PQClean API. (See pqm4.)
/!\As a result, the secret key is stored unmasked, which is insecure./!\
/!\The epheremal (encapsulated) key is also unprotected similarly as this paper./!\
In addition to pqm4 common testing (testvectors.py
and benchmarking benchmarking.py
), pqm4\_masked
supports:
- testing a single implementation (e.g.
kyber768/m4fspeed_masked
as command-line parameter) - benchmarking components of the masked implementation
subspeed
inbenchmarks.py
Before running any code, run cd libopencm3; make; cd ..
, otherwise the scripts fail.
# Testvectors
CFLAGS="-DNSHARES=2" python3 testvectors.py -p nucleo-l4r5zi --uart /dev/ttyACM0 kyber768/m4fspeed_masked
# Benchmark whole
CFLAGS="-DNSHARES=2 -DBENCH=0" python3 benchmarks.py -p nucleo-l4r5zi --uart /dev/ttyACM0 kyber768/m4fspeed_masked --speed
# Benchmark components
CFLAGS="-DNSHARES=2 -DBENCH=1" python3 benchmarks.py -p nucleo-l4r5zi --uart /dev/ttyACM0 kyber768/m4fspeed_masked --subspeed
By default, the implementations use a mix of C and Assembly (implementation
S3
and K3
in the research paper). In order to enforce the usage of pure C
implementation, the CFLAGS
must contain -DUSEC
. With the USEC
defined,
the implementations S2
and K2
are used.
You can run all the benchmarks for saber
or kyber768
, then show a plot of
the results by runing:
./run_bench.sh kyber768
python3 parse_bench.py kyber768 asm
python3 parse_bench.py kyber768 c
We provide a profiling framework that measures the execution time of
sub-parts of the implementations.
To configure the measured parts, first edit BENCH_CASES
in
common/bench.h
(we provide a reasonable default).
Example (to measure my_function
and my_other_function
):
#define BENCH_CASES X(my_function) X(my_other_function)
Then you increase the performance counter of that part where it is called:
start_bench(my_function);
my_function(...); // This can be any block of code you want to measure.
stop_bench(my_function);
See also common/bench.c
and common/speed_sub.c
for additional details about
the profiling framework.
Note that the profiling framework can be configured with define
s (e.g. using
CFLAGS
configuration).
To activate the profiling framework, the flag BENCH=1
must be defined.
In order to measure randomness usage instead of cycle count, BENCH_RND=1
must be defined.
When referring to this framework in academic literature, please consider using the following bibTeX excerpt:
@article{DBLP:journals/tches/BronchainC22,
author = {Olivier Bronchain and
Ga{\"{e}}tan Cassiers},
title = {Bitslicing Arithmetic/Boolean Masking Conversions for Fun and Profit
with Application to Lattice-Based KEMs},
journal = {{IACR} Trans. Cryptogr. Hardw. Embed. Syst.},
volume = {2022},
number = {4},
pages = {553--588},
year = {2022}
}
Different parts of pqm4_masked have different licenses. Each subdirectory containing implementations contains a LICENSE or COPYING file stating under what license that specific implementation is released. The files in common contain licensing information at the top of the file (and are currently either public domain or MIT). All other code in this repository is released under the conditions of CC0.
Note: masked implementations are released under the conditions of the GPLv3.