├── .github
└── workflows
│ ├── c.yml
│ ├── c_ephemeral.yml
│ ├── python.yml
│ └── python_ephemeral.yml
├── CONTRIBUTING.md
├── FrodoKEM
├── .gitignore
├── KAT
│ ├── PQCkemKAT_19888.rsp
│ ├── PQCkemKAT_19888_shake.rsp
│ ├── PQCkemKAT_31296.rsp
│ ├── PQCkemKAT_31296_shake.rsp
│ ├── PQCkemKAT_43088.rsp
│ └── PQCkemKAT_43088_shake.rsp
├── Makefile
├── README.md
├── VisualStudio
│ ├── frodoKEM-1344.vcxproj
│ ├── frodoKEM-1344.vcxproj.filters
│ ├── frodoKEM-640.vcxproj
│ ├── frodoKEM-640.vcxproj.filters
│ ├── frodoKEM-976.vcxproj
│ ├── frodoKEM-976.vcxproj.filters
│ ├── frodoKEM.sln
│ └── test_kem
│ │ ├── test_KEM1344.vcxproj
│ │ ├── test_KEM1344.vcxproj.filters
│ │ ├── test_KEM640.vcxproj
│ │ ├── test_KEM640.vcxproj.filters
│ │ ├── test_KEM976.vcxproj
│ │ └── test_KEM976.vcxproj.filters
├── python3
│ ├── LICENSE
│ ├── frodokem.py
│ └── nist_kat.py
├── src
│ ├── api_frodo1344.h
│ ├── api_frodo640.h
│ ├── api_frodo976.h
│ ├── config.h
│ ├── frodo1344.c
│ ├── frodo640.c
│ ├── frodo976.c
│ ├── frodo_macrify.c
│ ├── frodo_macrify.h
│ ├── frodo_macrify_reference.c
│ ├── kem.c
│ ├── noise.c
│ └── util.c
└── tests
│ ├── PQCtestKAT_kem1344.c
│ ├── PQCtestKAT_kem1344_shake.c
│ ├── PQCtestKAT_kem640.c
│ ├── PQCtestKAT_kem640_shake.c
│ ├── PQCtestKAT_kem976.c
│ ├── PQCtestKAT_kem976_shake.c
│ ├── ds_benchmark.h
│ ├── rng.c
│ ├── rng.h
│ ├── test_KEM1344.c
│ ├── test_KEM640.c
│ ├── test_KEM976.c
│ └── test_kem.c
├── LICENSE
├── README.md
├── SECURITY.md
├── common
├── aes
│ ├── aes.h
│ ├── aes_c.c
│ ├── aes_ni.c
│ ├── aes_openssl.c
│ └── aes_openssl.h
├── random
│ ├── random.c
│ └── random.h
└── sha3
│ ├── fips202.c
│ ├── fips202.h
│ ├── fips202x4.c
│ ├── fips202x4.h
│ └── keccak4x
│ ├── KeccakP-1600-times4-SIMD256.c
│ ├── KeccakP-1600-times4-SnP.h
│ ├── KeccakP-1600-unrolling.macros
│ ├── SIMD256-config.h
│ ├── align.h
│ └── brg_endian.h
└── eFrodoKEM
├── .gitignore
├── KAT
├── PQCkemKAT_19888.rsp
├── PQCkemKAT_19888_shake.rsp
├── PQCkemKAT_31296.rsp
├── PQCkemKAT_31296_shake.rsp
├── PQCkemKAT_43088.rsp
└── PQCkemKAT_43088_shake.rsp
├── Makefile
├── README.md
├── VisualStudio
├── efrodoKEM-1344.vcxproj
├── efrodoKEM-1344.vcxproj.filters
├── efrodoKEM-640.vcxproj
├── efrodoKEM-640.vcxproj.filters
├── efrodoKEM-976.vcxproj
├── efrodoKEM-976.vcxproj.filters
├── efrodoKEM.sln
└── test_kem
│ ├── test_KEM1344.vcxproj
│ ├── test_KEM1344.vcxproj.filters
│ ├── test_KEM640.vcxproj
│ ├── test_KEM640.vcxproj.filters
│ ├── test_KEM976.vcxproj
│ └── test_KEM976.vcxproj.filters
├── python3
├── LICENSE
├── efrodokem.py
└── nist_kat.py
├── src
├── api_efrodo1344.h
├── api_efrodo640.h
├── api_efrodo976.h
├── config.h
├── efrodo1344.c
├── efrodo640.c
├── efrodo976.c
├── ekem.c
├── frodo_macrify.c
├── frodo_macrify.h
├── frodo_macrify_reference.c
├── noise.c
└── util.c
└── tests
├── PQCtestKAT_kem1344.c
├── PQCtestKAT_kem1344_shake.c
├── PQCtestKAT_kem640.c
├── PQCtestKAT_kem640_shake.c
├── PQCtestKAT_kem976.c
├── PQCtestKAT_kem976_shake.c
├── ds_benchmark.h
├── rng.c
├── rng.h
├── test_KEM1344.c
├── test_KEM640.c
├── test_KEM976.c
└── test_kem.c
/.github/workflows/c.yml:
--------------------------------------------------------------------------------
1 | name: Test C implementation
2 |
3 | on:
4 | push:
5 | paths:
6 | - '.github/workflows/c.yml'
7 | - Makefile
8 | - 'KAT/**'
9 | - 'src/**'
10 | - 'tests/**'
11 | pull_request:
12 | paths:
13 | - '.github/workflows/c.yml'
14 | - Makefile
15 | - 'KAT/**'
16 | - 'src/**'
17 | - 'tests/**'
18 |
19 | jobs:
20 | test-basic:
21 | runs-on: ubuntu-latest
22 | strategy:
23 | matrix:
24 | generation_a: ['AES128', 'SHAKE128']
25 | opt_level: ['REFERENCE', 'FAST_GENERIC', 'FAST']
26 | steps:
27 | - uses: actions/checkout@v3
28 | - name: Build
29 | env:
30 | GENERATION_A: ${{ matrix.generation_a }}
31 | OPT_LEVEL: ${{ matrix.opt_level }}
32 | run: |
33 | cd FrodoKEM
34 | make
35 | - name: Frodo640
36 | run: |
37 | cd FrodoKEM
38 | make test640
39 | - name: Frodo976
40 | run: |
41 | cd FrodoKEM
42 | make test976
43 | - name: Frodo1344
44 | run: |
45 | cd FrodoKEM
46 | make test1344
47 | - name: Frodo640-AES KATs
48 | if: ${{ matrix.generation_a == 'AES128' }}
49 | run: |
50 | cd FrodoKEM
51 | frodo640/PQCtestKAT_kem
52 | - name: Frodo640-SHAKE KATs
53 | if: ${{ matrix.generation_a == 'SHAKE128' }}
54 | run: |
55 | cd FrodoKEM
56 | frodo640/PQCtestKAT_kem_shake
57 | - name: Frodo976-AES KATs
58 | if: ${{ matrix.generation_a == 'AES128' }}
59 | run: |
60 | cd FrodoKEM
61 | frodo976/PQCtestKAT_kem
62 | - name: Frodo976-SHAKE KATs
63 | if: ${{ matrix.generation_a == 'SHAKE128' }}
64 | run: |
65 | cd FrodoKEM
66 | frodo976/PQCtestKAT_kem_shake
67 | - name: Frodo1344-AES KATs
68 | if: ${{ matrix.generation_a == 'AES128' }}
69 | run: |
70 | cd FrodoKEM
71 | frodo1344/PQCtestKAT_kem
72 | - name: Frodo1344-SHAKE KATs
73 | if: ${{ matrix.generation_a == 'SHAKE128' }}
74 | run: |
75 | cd FrodoKEM
76 | frodo1344/PQCtestKAT_kem_shake
77 | test-sanitize:
78 | runs-on: ubuntu-latest
79 | strategy:
80 | matrix:
81 | generation_a: ['AES128', 'SHAKE128']
82 | opt_level: ['REFERENCE', 'FAST_GENERIC', 'FAST']
83 | sanitizer: ['address', 'undefined']
84 | steps:
85 | - uses: actions/checkout@v3
86 | - name: Build
87 | env:
88 | GENERATION_A: ${{ matrix.generation_a }}
89 | OPT_LEVEL: ${{ matrix.opt_level }}
90 | EXTRA_CFLAGS: -g3 -fno-omit-frame-pointer -fno-optimize-sibling-calls -fsanitize-address-use-after-scope -fsanitize=${{ matrix.sanitizer }} -fno-sanitize-recover=${{ matrix.sanitizer }}
91 | run: |
92 | cd FrodoKEM
93 | make CC=clang-13
94 | - name: Frodo640
95 | run: |
96 | cd FrodoKEM
97 | frodo640/test_KEM nobench
98 | - name: Frodo976
99 | run: |
100 | cd FrodoKEM
101 | frodo976/test_KEM nobench
102 | - name: Frodo1344
103 | run: |
104 | cd FrodoKEM
105 | frodo1344/test_KEM nobench
106 | test-valgrind-constant-time:
107 | runs-on: ubuntu-latest
108 | strategy:
109 | matrix:
110 | generation_a: ['AES128', 'SHAKE128']
111 | opt_level: ['REFERENCE', 'FAST_GENERIC', 'FAST']
112 | steps:
113 | - uses: actions/checkout@v3
114 | - name: Install valgrind
115 | run: |
116 | cd FrodoKEM
117 | sudo apt-get install -y valgrind
118 | - name: Build
119 | env:
120 | DO_VALGRIND_CHECK: "TRUE"
121 | GENERATION_A: ${{ matrix.generation_a }}
122 | OPT_LEVEL: ${{ matrix.opt_level }}
123 | run: |
124 | cd FrodoKEM
125 | make CC=clang-13
126 | - name: Frodo640
127 | env:
128 | DO_VALGRIND_CHECK: "TRUE"
129 | run: |
130 | cd FrodoKEM
131 | make test640
132 | - name: Frodo976
133 | env:
134 | DO_VALGRIND_CHECK: "TRUE"
135 | run: |
136 | cd FrodoKEM
137 | make test976
138 | - name: Frodo1344
139 | env:
140 | DO_VALGRIND_CHECK: "TRUE"
141 | run: |
142 | cd FrodoKEM
143 | make test1344
144 | test-ppc:
145 | runs-on: ubuntu-latest
146 | strategy:
147 | matrix:
148 | generation_a: ['AES128', 'SHAKE128']
149 | opt_level: ['REFERENCE']
150 | steps:
151 | - uses: actions/checkout@v3
152 | - name: Install Docker and QEMU
153 | run: |
154 | cd FrodoKEM
155 | sudo apt-get install -y qemu
156 | - name: Register qemu-user-static
157 | run: |
158 | cd FrodoKEM
159 | docker run --rm --privileged multiarch/qemu-user-static:register --reset
160 | - name: Run tests in container
161 | env:
162 | GENERATION_A: ${{ matrix.generation_a }}
163 | OPT_LEVEL: ${{ matrix.opt_level }}
164 | run: |
165 | cd FrodoKEM
166 | docker run --rm -v $PWD:$PWD -w $PWD pqclean/ci-container:unstable-ppc /bin/bash -c "\
167 | make ARCH=PPC GENERATION_A=${{ matrix.generation_a }} USE_OPENSSL=FALSE OPT_LEVEL=${{ matrix.opt_level }} && \
168 | make test640 && \
169 | make test976 && \
170 | make test1344"
171 |
--------------------------------------------------------------------------------
/.github/workflows/c_ephemeral.yml:
--------------------------------------------------------------------------------
1 | name: Test C implementation
2 |
3 | on:
4 | push:
5 | paths:
6 | - '.github/workflows/c_ephemeral.yml'
7 | - Makefile
8 | - 'KAT/**'
9 | - 'src/**'
10 | - 'tests/**'
11 | pull_request:
12 | paths:
13 | - '.github/workflows/c_ephemeral.yml'
14 | - Makefile
15 | - 'KAT/**'
16 | - 'src/**'
17 | - 'tests/**'
18 |
19 | jobs:
20 | test-basic:
21 | runs-on: ubuntu-latest
22 | strategy:
23 | matrix:
24 | generation_a: ['AES128', 'SHAKE128']
25 | opt_level: ['REFERENCE', 'FAST_GENERIC', 'FAST']
26 | steps:
27 | - uses: actions/checkout@v2
28 | - name: Build
29 | env:
30 | GENERATION_A: ${{ matrix.generation_a }}
31 | OPT_LEVEL: ${{ matrix.opt_level }}
32 | run: |
33 | cd eFrodoKEM
34 | make
35 | - name: eFrodo640
36 | run: |
37 | cd eFrodoKEM
38 | make test640
39 | - name: eFrodo976
40 | run: |
41 | cd eFrodoKEM
42 | make test976
43 | - name: eFrodo1344
44 | run: |
45 | cd eFrodoKEM
46 | make test1344
47 | - name: eFrodo640-AES KATs
48 | if: ${{ matrix.generation_a == 'AES128' }}
49 | run: |
50 | cd eFrodoKEM
51 | efrodo640/PQCtestKAT_kem
52 | - name: eFrodo640-SHAKE KATs
53 | if: ${{ matrix.generation_a == 'SHAKE128' }}
54 | run: |
55 | cd eFrodoKEM
56 | efrodo640/PQCtestKAT_kem_shake
57 | - name: eFrodo976-AES KATs
58 | if: ${{ matrix.generation_a == 'AES128' }}
59 | run: |
60 | cd eFrodoKEM
61 | efrodo976/PQCtestKAT_kem
62 | - name: eFrodo976-SHAKE KATs
63 | if: ${{ matrix.generation_a == 'SHAKE128' }}
64 | run: |
65 | cd eFrodoKEM
66 | efrodo976/PQCtestKAT_kem_shake
67 | - name: eFrodo1344-AES KATs
68 | if: ${{ matrix.generation_a == 'AES128' }}
69 | run: |
70 | cd eFrodoKEM
71 | efrodo1344/PQCtestKAT_kem
72 | - name: eFrodo1344-SHAKE KATs
73 | if: ${{ matrix.generation_a == 'SHAKE128' }}
74 | run: |
75 | cd eFrodoKEM
76 | efrodo1344/PQCtestKAT_kem_shake
77 | test-sanitize:
78 | runs-on: ubuntu-latest
79 | strategy:
80 | matrix:
81 | generation_a: ['AES128', 'SHAKE128']
82 | opt_level: ['REFERENCE', 'FAST_GENERIC', 'FAST']
83 | sanitizer: ['address', 'undefined']
84 | steps:
85 | - uses: actions/checkout@v2
86 | - name: Build
87 | env:
88 | GENERATION_A: ${{ matrix.generation_a }}
89 | OPT_LEVEL: ${{ matrix.opt_level }}
90 | EXTRA_CFLAGS: -g3 -fno-omit-frame-pointer -fno-optimize-sibling-calls -fsanitize-address-use-after-scope -fsanitize=${{ matrix.sanitizer }} -fno-sanitize-recover=${{ matrix.sanitizer }}
91 | run: |
92 | cd eFrodoKEM
93 | make CC=clang-13
94 | - name: eFrodo640
95 | run: |
96 | cd eFrodoKEM
97 | efrodo640/test_KEM nobench
98 | - name: eFrodo976
99 | run: |
100 | cd eFrodoKEM
101 | efrodo976/test_KEM nobench
102 | - name: eFrodo1344
103 | run: |
104 | cd eFrodoKEM
105 | efrodo1344/test_KEM nobench
106 | test-valgrind-constant-time:
107 | runs-on: ubuntu-latest
108 | strategy:
109 | matrix:
110 | generation_a: ['AES128', 'SHAKE128']
111 | opt_level: ['REFERENCE', 'FAST_GENERIC', 'FAST']
112 | steps:
113 | - uses: actions/checkout@v2
114 | - name: Install valgrind
115 | run: |
116 | cd eFrodoKEM
117 | sudo apt-get install -y valgrind
118 | - name: Build
119 | env:
120 | DO_VALGRIND_CHECK: "TRUE"
121 | GENERATION_A: ${{ matrix.generation_a }}
122 | OPT_LEVEL: ${{ matrix.opt_level }}
123 | run: |
124 | cd eFrodoKEM
125 | make CC=clang-13
126 | - name: eFrodo640
127 | env:
128 | DO_VALGRIND_CHECK: "TRUE"
129 | run: |
130 | cd eFrodoKEM
131 | make test640
132 | - name: eFrodo976
133 | env:
134 | DO_VALGRIND_CHECK: "TRUE"
135 | run: |
136 | cd eFrodoKEM
137 | make test976
138 | - name: eFrodo1344
139 | env:
140 | DO_VALGRIND_CHECK: "TRUE"
141 | run: |
142 | cd eFrodoKEM
143 | make test1344
144 | test-ppc:
145 | runs-on: ubuntu-latest
146 | strategy:
147 | matrix:
148 | generation_a: ['AES128', 'SHAKE128']
149 | opt_level: ['REFERENCE']
150 | steps:
151 | - uses: actions/checkout@v2
152 | - name: Install Docker and QEMU
153 | run: |
154 | cd eFrodoKEM
155 | sudo apt-get install -y qemu
156 | - name: Register qemu-user-static
157 | run: |
158 | cd eFrodoKEM
159 | docker run --rm --privileged multiarch/qemu-user-static:register --reset
160 | - name: Run tests in container
161 | env:
162 | GENERATION_A: ${{ matrix.generation_a }}
163 | OPT_LEVEL: ${{ matrix.opt_level }}
164 | run: |
165 | cd eFrodoKEM
166 | docker run --rm -v $PWD:$PWD -w $PWD pqclean/ci-container:unstable-ppc /bin/bash -c "\
167 | make ARCH=PPC GENERATION_A=${{ matrix.generation_a }} USE_OPENSSL=FALSE OPT_LEVEL=${{ matrix.opt_level }} && \
168 | make test640 && \
169 | make test976 && \
170 | make test1344"
171 |
--------------------------------------------------------------------------------
/.github/workflows/python.yml:
--------------------------------------------------------------------------------
1 | name: Test Python implementation
2 |
3 | on:
4 | push:
5 | paths:
6 | - '.github/workflows/python.yml'
7 | - 'python3/**'
8 | pull_request:
9 | paths:
10 | - '.github/workflows/python.yml'
11 | - 'python3/**'
12 |
13 | jobs:
14 | test:
15 | runs-on: ubuntu-latest
16 | steps:
17 | - uses: actions/checkout@v3
18 | - name: Install prerequisites
19 | run: |
20 | cd FrodoKEM
21 | pip3 install bitstring cryptography
22 | - name: Run basic test
23 | run: |
24 | cd FrodoKEM/python3
25 | python3 nist_kat.py
26 |
--------------------------------------------------------------------------------
/.github/workflows/python_ephemeral.yml:
--------------------------------------------------------------------------------
1 | name: Test Python implementation
2 |
3 | on:
4 | push:
5 | paths:
6 | - '.github/workflows/python_ephemeral.yml'
7 | - 'python3/**'
8 | pull_request:
9 | paths:
10 | - '.github/workflows/python_ephemeral.yml'
11 | - 'python3/**'
12 |
13 | jobs:
14 | test:
15 | runs-on: ubuntu-latest
16 | steps:
17 | - uses: actions/checkout@v2
18 | - name: Install prerequisites
19 | run: |
20 | cd eFrodoKEM
21 | pip3 install bitstring cryptography
22 | - name: Run basic test
23 | run: |
24 | cd eFrodoKEM/python3
25 | python3 nist_kat.py
26 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Instructions for Contributing Code
2 |
3 | ## Contributing bug fixes and features
4 | LWEKE is currently accepting contributions in the form of bug fixes and new features. Any submission must have an issue tracking it in the issue tracker that has been approved by the LWEKE team. Your pull request should include a link to the bug that you are fixing. If you've submitted a PR for a bug, please post a comment in the bug to avoid duplication of effort.
5 |
6 | ## Legal
7 | If your contribution is more than 15 lines of code, you will need to complete a Contributor License Agreement (CLA). Briefly, this agreement testifies that you are granting us permission to use the submitted change according to the terms of the project's license, and that the work being submitted is under appropriate copyright.
8 |
9 | Please submit a Contributor License Agreement (CLA) before submitting a pull request. You may visit https://cla.microsoft.com to sign digitally. Alternatively, download the agreement ([Microsoft Contribution License Agreement.docx](https://www.codeplex.com/Download?ProjectName=typescript&DownloadId=822190) or [Microsoft Contribution License Agreement.pdf](https://www.codeplex.com/Download?ProjectName=typescript&DownloadId=921298)), sign, scan, and email it back to cla@microsoft.com. Be sure to include your github user name along with the agreement. Once we have received the signed CLA, we'll review the request.
10 |
--------------------------------------------------------------------------------
/FrodoKEM/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore temporary files and build results
2 |
3 | # User-specific files
4 | *.suo
5 | *.user
6 |
7 | # Build results
8 | Debug/
9 | Win32/
10 | x64/
11 | /frodo640
12 | /frodo976
13 | /frodo1344
14 | objs/
15 |
16 | # Visual Studio cache directory and files
17 | .vs/
18 | *.VC.db
19 | *.VC.VC.opendb
--------------------------------------------------------------------------------
/FrodoKEM/README.md:
--------------------------------------------------------------------------------
1 | Standard FrodoKEM
2 | =================
3 |
4 | This variant, referred to as simply **FrodoKEM**, includes countermeasures against some multi-ciphertext attacks and, thus, allows for key reuse
5 | (i.e., it is suitable for applications in which a large number of ciphertexts may be encrypted to a single public key).
6 |
7 |
8 | ## Contents
9 |
10 | * [`KAT` folder](KAT/): Known Answer Test (KAT) files for the KEM.
11 | * [`src` folder](src/): C and header files. Public APIs can be found in [`api_frodo640.h`](src/api_frodo640.h), [`api_frodo976.h`](src/api_frodo976.h) and [`api_frodo1344.h`](src/api_frodo1344.h).
12 | * [Optimized matrix operations](src/frodo_macrify.c): optimized implementation of the matrix operations.
13 | * [Reference matrix operations](src/frodo_macrify_reference.c): reference implementation of the matrix operations.
14 | * [`src/aes` folder](src/aes/): AES implementation.
15 | * [`src/random` folder](src/random/): randombytes function using the system random number generator.
16 | * [`src/sha3` folder](src/sha3/): SHA-3 / SHAKE128 / SHAKE256 implementation.
17 | * [`tests` folder](tests/): test files.
18 | * [`VisualStudio` folder](VisualStudio/): Visual Studio 2022 files for compilation in Windows.
19 | * [`Makefile`](Makefile): Makefile for compilation using the GNU GCC or clang compilers on Unix-like operative systems.
20 | * [`README.md`](README.md): this readme file.
21 | * [`python3` folder](python3): a Python3 reference implementation
22 |
23 | ### Complementary crypto functions
24 |
25 | Random values are generated with /dev/urandom on Unix-like operative systems, and CNG's BCryptGenRandom function in Windows.
26 | Check the folder [`random`](src/random/) for details.
27 |
28 | The library includes standalone implementations of AES and SHAKE. The generation of the matrix
29 | "A" (see the specification document [1]) can be carried out with either AES128 or SHAKE128. By
30 | default AES128 is used.
31 |
32 | There are two options for AES: the standalone implementation that is included in the software or
33 | OpenSSL's AES implementation. OpenSSL's AES implementation is used by default.
34 |
35 | ## Implementation Options
36 |
37 | The following implementation options are available:
38 | - Reference portable implementation enabled by setting `OPT_LEVEL=REFERENCE`.
39 | - Optimized portable implementation enabled by setting `OPT_LEVEL=FAST_GENERIC`.
40 | - Optimized x64 implementation using AVX2 intrinsics and AES-NI instructions enabled by setting `ARCH=x64` and `OPT_LEVEL=FAST`.
41 |
42 | Follow the instructions in the sections "_Instructions for Linux_" or "_Instructions for Windows_" below to configure these different implementation options.
43 |
44 | ## Instructions for Linux
45 |
46 | ### Using AES128
47 |
48 | By simply executing:
49 |
50 | ```sh
51 | $ make
52 | ```
53 |
54 | the library is compiled for x64 using gcc, and optimization level `FAST`, which uses AVX2 instrinsics.
55 | AES128 is used by default to generate the matrix "A". For AES, OpenSSL's AES implementation is used by default.
56 |
57 | Testing and benchmarking results are obtained by running:
58 |
59 | ```sh
60 | $ ./frodo640/test_KEM
61 | $ ./frodo976/test_KEM
62 | $ ./frodo1344/test_KEM
63 | ```
64 |
65 | To run the implementations against the KATs, execute:
66 |
67 | ```sh
68 | $ ./frodo640/PQCtestKAT_kem
69 | $ ./frodo976/PQCtestKAT_kem
70 | $ ./frodo1344/PQCtestKAT_kem
71 | ```
72 |
73 | ### Using SHAKE128
74 |
75 | By executing:
76 |
77 | ```sh
78 | $ make GENERATION_A=SHAKE128
79 | ```
80 |
81 | the library is compiled for x64 using gcc, and optimization level `FAST`, which uses AVX2 instrinsics.
82 | SHAKE128 is used to generate the matrix "A".
83 |
84 | Testing and benchmarking results are obtained by running:
85 |
86 | ```sh
87 | $ ./frodo640/test_KEM
88 | $ ./frodo976/test_KEM
89 | $ ./frodo1344/test_KEM
90 | ```
91 |
92 | To run the implementations against the KATs, execute:
93 |
94 | ```sh
95 | $ ./frodo640/PQCtestKAT_kem_shake
96 | $ ./frodo976/PQCtestKAT_kem_shake
97 | $ ./frodo1344/PQCtestKAT_kem_shake
98 | ```
99 |
100 | ### Additional options
101 |
102 | These are all the available options for compilation:
103 |
104 | ```sh
105 | $ make CC=[gcc/clang] ARCH=[x64/x86/ARM/PPC/s390x] OPT_LEVEL=[REFERENCE/FAST_GENERIC/FAST] GENERATION_A=[AES128/SHAKE128] USE_OPENSSL=[TRUE/FALSE]
106 | ```
107 |
108 | Note that the `FAST` option is only available for x64 with support for AVX2 and AES-NI instructions.
109 | The USE_OPENSSL flag specifies whether OpenSSL's AES implementation is used (`=TRUE`) or if the
110 | standalone AES implementation is used (`=FALSE`). Therefore, this flag only applies when `GENERATION_A=
111 | AES128` (or if `GENERATION_A` is left blank).
112 |
113 | If OpenSSL is being used and is installed in an alternate location, use the following make options:
114 |
115 | ```sh
116 | OPENSSL_INCLUDE_DIR=/path/to/openssl/include
117 | OPENSSL_LIB_DIR=/path/to/openssl/lib
118 | ```
119 |
120 | The program tries its best at auto-correcting unsupported configurations.
121 | For example, since the `FAST` implementation is currently only available for x64 doing `make ARCH=x86 OPT_LEVEL=FAST`
122 | is actually processed using `ARCH=x86 OPT_LEVEL=FAST_GENERIC`.
123 |
124 | ## Instructions for Windows
125 |
126 | ### Building the library with Visual Studio:
127 |
128 | Open the solution file [`frodoKEM.sln`](VisualStudio/frodoKEM.sln) in Visual Studio, and choose either x64 or x86 from the platform menu.
129 | Make sure `Fast_generic` is selected in the configuration menu. Finally, select "Build Solution" from the "Build" menu.
130 |
131 | ### Running the tests:
132 |
133 | After building the solution file, there should be three executable files: `test_KEM640.exe`, `test_KEM976.exe` and `test_KEM1344.exe`, to run tests for the KEM.
134 |
135 | ### Using the library:
136 |
137 | After building the solution file, add the generated `FrodoKEM-640.lib`, `FrodoKEM-976.lib` and `FrodoKEM-1344.lib` library files to the set of References for a project,
138 | and add [`api_frodo640.h`](src/api_frodo640.h), [`api_frodo976.h`](src/api_frodo976.h) and [`api_frodo1344.h`](src/api_frodo1344.h) to the list of header files of a project.
139 |
140 | ## Python3 implementation
141 |
142 | The [`python3`](python3) folder contains a Python3 implementation of FrodoKEM.
143 | This reference implementation is a line-by-line transcription of the pseudocode from the [FrodoKEM specification](https://frodokem.org) and includes extensive comments.
144 | The file [`frodokem.py`](python3/frodokem.py) contains a Python3 class implementing all 6 variants of FrodoKEM.
145 | The file [`nist_kat.py`](python3/nist_kat.py) contains a minimal Python port of the known answer test (KAT) code; it should generate the same output as the C version for the first test vector (except that the line `seed = ` will differ).
146 |
147 | It can be run as follows:
148 |
149 | ```sh
150 | pip3 install bitstring cryptography
151 | cd python3
152 | python3 nist_kat.py
153 | ```
154 |
155 | **WARNING**: This Python3 implementation of FrodoKEM is not designed to be fast or secure, and may leak secret information via timing or other side channels; it should not be used in production environments.
--------------------------------------------------------------------------------
/FrodoKEM/VisualStudio/frodoKEM-1344.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Source Files
6 |
7 |
8 | Source Files
9 |
10 |
11 | Source Files
12 |
13 |
14 | Source Files
15 |
16 |
17 | Source Files
18 |
19 |
20 | Source Files
21 |
22 |
23 | Source Files\AES
24 |
25 |
26 | Source Files\AES
27 |
28 |
29 | Source Files\random
30 |
31 |
32 | Source Files\sha3
33 |
34 |
35 |
36 |
37 | Header Files
38 |
39 |
40 | Header Files
41 |
42 |
43 | Header Files
44 |
45 |
46 | Source Files\AES
47 |
48 |
49 | Source Files\random
50 |
51 |
52 | Source Files\sha3
53 |
54 |
55 |
56 |
57 | {47469e83-ec7a-4d69-baf0-ab15e961629e}
58 |
59 |
60 | {7041c366-2ed8-4a00-8e92-4f6e2471eb9d}
61 |
62 |
63 | {71c917ec-9181-4b88-bdfc-9611ee1abe9a}
64 |
65 |
66 | {fd44eb34-2f81-411e-a55f-f279c4b101de}
67 |
68 |
69 | {656e58e0-96ef-4f93-9711-0ebe15c55da2}
70 |
71 |
72 |
--------------------------------------------------------------------------------
/FrodoKEM/VisualStudio/frodoKEM-640.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Source Files
6 |
7 |
8 | Source Files
9 |
10 |
11 | Source Files
12 |
13 |
14 | Source Files
15 |
16 |
17 | Source Files
18 |
19 |
20 | Source Files
21 |
22 |
23 | Source Files\AES
24 |
25 |
26 | Source Files\AES
27 |
28 |
29 | Source Files\random
30 |
31 |
32 | Source Files\sha3
33 |
34 |
35 |
36 |
37 | Header Files
38 |
39 |
40 | Header Files
41 |
42 |
43 | Header Files
44 |
45 |
46 | Source Files\AES
47 |
48 |
49 | Source Files\random
50 |
51 |
52 | Source Files\sha3
53 |
54 |
55 |
56 |
57 | {47469e83-ec7a-4d69-baf0-ab15e961629e}
58 |
59 |
60 | {7041c366-2ed8-4a00-8e92-4f6e2471eb9d}
61 |
62 |
63 | {71c917ec-9181-4b88-bdfc-9611ee1abe9a}
64 |
65 |
66 | {fd44eb34-2f81-411e-a55f-f279c4b101de}
67 |
68 |
69 | {656e58e0-96ef-4f93-9711-0ebe15c55da2}
70 |
71 |
72 |
--------------------------------------------------------------------------------
/FrodoKEM/VisualStudio/frodoKEM-976.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Source Files
6 |
7 |
8 | Source Files
9 |
10 |
11 | Source Files
12 |
13 |
14 | Source Files
15 |
16 |
17 | Source Files
18 |
19 |
20 | Source Files
21 |
22 |
23 | Source Files\AES
24 |
25 |
26 | Source Files\AES
27 |
28 |
29 | Source Files\random
30 |
31 |
32 | Source Files\sha3
33 |
34 |
35 |
36 |
37 | Header Files
38 |
39 |
40 | Header Files
41 |
42 |
43 | Header Files
44 |
45 |
46 | Source Files\AES
47 |
48 |
49 | Source Files\random
50 |
51 |
52 | Source Files\sha3
53 |
54 |
55 |
56 |
57 | {47469e83-ec7a-4d69-baf0-ab15e961629e}
58 |
59 |
60 | {7041c366-2ed8-4a00-8e92-4f6e2471eb9d}
61 |
62 |
63 | {71c917ec-9181-4b88-bdfc-9611ee1abe9a}
64 |
65 |
66 | {fd44eb34-2f81-411e-a55f-f279c4b101de}
67 |
68 |
69 | {656e58e0-96ef-4f93-9711-0ebe15c55da2}
70 |
71 |
72 |
--------------------------------------------------------------------------------
/FrodoKEM/VisualStudio/test_kem/test_KEM1344.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
7 |
8 |
9 | {93995380-89BD-4b04-88EB-625FBE52EBFB}
10 | h;hh;hpp;hxx;hm;inl;inc;xsd
11 |
12 |
13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
15 |
16 |
17 |
18 |
19 | Header Files
20 |
21 |
22 |
23 |
24 | Source Files
25 |
26 |
27 | Source Files
28 |
29 |
30 |
--------------------------------------------------------------------------------
/FrodoKEM/VisualStudio/test_kem/test_KEM640.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
7 |
8 |
9 | {93995380-89BD-4b04-88EB-625FBE52EBFB}
10 | h;hh;hpp;hxx;hm;inl;inc;xsd
11 |
12 |
13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
15 |
16 |
17 |
18 |
19 | Header Files
20 |
21 |
22 |
23 |
24 | Source Files
25 |
26 |
27 | Source Files
28 |
29 |
30 |
--------------------------------------------------------------------------------
/FrodoKEM/VisualStudio/test_kem/test_KEM976.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
7 |
8 |
9 | {93995380-89BD-4b04-88EB-625FBE52EBFB}
10 | h;hh;hpp;hxx;hm;inl;inc;xsd
11 |
12 |
13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
15 |
16 |
17 |
18 |
19 | Header Files
20 |
21 |
22 |
23 |
24 | Source Files
25 |
26 |
27 | Source Files
28 |
29 |
30 |
--------------------------------------------------------------------------------
/FrodoKEM/python3/LICENSE:
--------------------------------------------------------------------------------
1 | Creative Commons Legal Code
2 |
3 | CC0 1.0 Universal
4 |
5 | CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED HEREUNDER.
6 |
7 | Statement of Purpose
8 |
9 | The laws of most jurisdictions throughout the world automatically confer exclusive Copyright and Related Rights (defined below) upon the creator and subsequent owner(s) (each and all, an "owner") of an original work of authorship and/or a database (each, a "Work").
10 |
11 | Certain owners wish to permanently relinquish those rights to a Work for the purpose of contributing to a commons of creative, cultural and scientific works ("Commons") that the public can reliably and without fear of later claims of infringement build upon, modify, incorporate in other works, reuse and redistribute as freely as possible in any form whatsoever and for any purposes, including without limitation commercial purposes. These owners may contribute to the Commons to promote the ideal of a free culture and the further production of creative, cultural and scientific works, or to gain reputation or greater distribution for their Work in part through the use and efforts of others.
12 |
13 | For these and/or other purposes and motivations, and without any expectation of additional consideration or compensation, the person associating CC0 with a Work (the "Affirmer"), to the extent that he or she is an owner of Copyright and Related Rights in the Work, voluntarily elects to apply CC0 to the Work and publicly distribute the Work under its terms, with knowledge of his or her Copyright and Related Rights in the Work and the meaning and intended legal effect of CC0 on those rights.
14 |
15 | 1. Copyright and Related Rights. A Work made available under CC0 may be protected by copyright and related or neighboring rights ("Copyright and Related Rights"). Copyright and Related Rights include, but are not limited to, the following:
16 | i. the right to reproduce, adapt, distribute, perform, display, communicate, and translate a Work;
17 | ii. moral rights retained by the original author(s) and/or performer(s);
18 | iii. publicity and privacy rights pertaining to a person's image or likeness depicted in a Work;
19 | iv. rights protecting against unfair competition in regards to a Work, subject to the limitations in paragraph 4(a), below;
20 | v. rights protecting the extraction, dissemination, use and reuse of data in a Work;
21 | vi. database rights (such as those arising under Directive 96/9/EC of the European Parliament and of the Council of 11 March 1996 on the legal protection of databases, and under any national implementation thereof, including any amended or successor version of such directive); and
22 | vii. other similar, equivalent or corresponding rights throughout the world based on applicable law or treaty, and any national implementations thereof.
23 |
24 | 2. Waiver. To the greatest extent permitted by, but not in contravention of, applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and unconditionally waives, abandons, and surrenders all of Affirmer's Copyright and Related Rights and associated claims and causes of action, whether now known or unknown (including existing as well as future claims and causes of action), in the Work (i) in all territories worldwide, (ii) for the maximum duration provided by applicable law or treaty (including future time extensions), (iii) in any current or future medium and for any number of copies, and (iv) for any purpose whatsoever, including without limitation commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each member of the public at large and to the detriment of Affirmer's heirs and successors, fully intending that such Waiver shall not be subject to revocation, rescission, cancellation, termination, or any other legal or equitable action to disrupt the quiet enjoyment of the Work by the public as contemplated by Affirmer's express Statement of Purpose.
25 |
26 | 3. Public License Fallback. Should any part of the Waiver for any reason be judged legally invalid or ineffective under applicable law, then the Waiver shall be preserved to the maximum extent permitted taking into account Affirmer's express Statement of Purpose. In addition, to the extent the Waiver is so judged Affirmer hereby grants to each affected person a royalty-free, non transferable, non sublicensable, non exclusive, irrevocable and unconditional license to exercise Affirmer's Copyright and Related Rights in the Work (i) in all territories worldwide, (ii) for the maximum duration provided by applicable law or treaty (including future time extensions), (iii) in any current or future medium and for any number of copies, and (iv) for any purpose whatsoever, including without limitation commercial, advertising or promotional purposes (the "License"). The License shall be deemed effective as of the date CC0 was applied by Affirmer to the Work. Should any part of the License for any reason be judged legally invalid or ineffective under applicable law, such partial invalidity or ineffectiveness shall not invalidate the remainder of the License, and in such case Affirmer hereby affirms that he or she will not (i) exercise any of his or her remaining Copyright and Related Rights in the Work or (ii) assert any associated claims and causes of action with respect to the Work, in either case contrary to Affirmer's express Statement of Purpose.
27 |
28 | 4. Limitations and Disclaimers.
29 | a. No trademark or patent rights held by Affirmer are waived, abandoned, surrendered, licensed or otherwise affected by this document.
30 | b. Affirmer offers the Work as-is and makes no representations or warranties of any kind concerning the Work, express, implied, statutory or otherwise, including without limitation warranties of title, merchantability, fitness for a particular purpose, non infringement, or the absence of latent or other defects, accuracy, or the present or absence of errors, whether or not discoverable, all to the greatest extent permissible under applicable law.
31 | c. Affirmer disclaims responsibility for clearing rights of other persons that may apply to the Work or any use thereof, including without limitation any person's Copyright and Related Rights in the Work. Further, Affirmer disclaims responsibility for obtaining any necessary consents, permissions or other rights required for any use of the Work.
32 | d. Affirmer understands and acknowledges that Creative Commons is not a party to this document and has no duty or obligation with respect to this CC0 or use of the Work.
33 |
--------------------------------------------------------------------------------
/FrodoKEM/python3/nist_kat.py:
--------------------------------------------------------------------------------
1 | # Creative Commons Zero v1.0 Universal
2 | # SPDX-License-Identifier: CC0-1.0
3 | # Created by Douglas Stebila
4 |
5 | import os
6 | from frodokem import FrodoKEM
7 |
8 | class NISTKAT(object):
9 |
10 | @staticmethod
11 | def run(kem):
12 | """Generate a NIST KAT output for the given KEM"""
13 | rng = NISTKAT.NISTRNG()
14 | kem.randombytes = rng.randombytes
15 | print("===============================================")
16 | print(kem.variant)
17 | print("count = 0")
18 | print("seed = ")
19 | (pk, sk) = kem.kem_keygen()
20 | print("pk =", pk.hex().upper())
21 | print("sk =", sk.hex().upper())
22 | (ct, ss_e) = kem.kem_encaps(pk)
23 | print("ct =", ct.hex().upper())
24 | print("ss =", ss_e.hex().upper())
25 | ss_d = kem.kem_decaps(sk, ct)
26 | assert ss_e.hex() == ss_d.hex(), "Shared secrets not equal"
27 | return {
28 | 'variant': kem.variant,
29 | 'count': '0',
30 | 'seed': '',
31 | 'pk': pk.hex().upper(),
32 | 'sk': sk.hex().upper(),
33 | 'ct': ct.hex().upper(),
34 | 'ss': ss_e.hex().upper()
35 | }
36 |
37 | def check(katvalues, katfile):
38 | """Check that KAT values in the dictionary katvalues match those stored in katfile"""
39 | with open(os.path.join('..', 'KAT', katfile), 'r') as fh:
40 | basekatvalues = dict()
41 | basekatvalues['variant'] = fh.readline().replace('#', '').strip()
42 | fh.readline()
43 | # count
44 | a = fh.readline().strip().replace(' = ', ',').split(',')
45 | basekatvalues[a[0]] = a[1]
46 | # seed
47 | a = fh.readline().strip().replace(' = ', ',').split(',')
48 | basekatvalues[a[0]] = a[1]
49 | # pk
50 | a = fh.readline().strip().replace(' = ', ',').split(',')
51 | basekatvalues[a[0]] = a[1]
52 | # sk
53 | a = fh.readline().strip().replace(' = ', ',').split(',')
54 | basekatvalues[a[0]] = a[1]
55 | # ct
56 | a = fh.readline().strip().replace(' = ', ',').split(',')
57 | basekatvalues[a[0]] = a[1]
58 | # ss
59 | a = fh.readline().strip().replace(' = ', ',').split(',')
60 | basekatvalues[a[0]] = a[1]
61 | for x in ['variant', 'count', 'pk', 'sk', 'ct', 'ss']:
62 | assert katvalues[x] == basekatvalues[x], "{:s} not equal".format(x)
63 | print("Computed KAT values match for {:s}".format(basekatvalues['variant']))
64 |
65 | class NISTRNG(object):
66 | """Dummy object that contains a serialization of the randombytes outputs that
67 | would be generated by the deterministic RNG in the NIST KAT generation algorithm
68 | when run on FrodoKEM; note that this is not a proper implementation of that RNG,
69 | it has the exact values generated hard-coded."""
70 |
71 | # To get these values, add the following lines to rng.c in the C implementation to print out the required RNG outputs:
72 | # printf("randombytes_output (%llu): ", xlen_original);
73 | # for (size_t i = 0; i < xlen_original; i++) {
74 | # printf("%02X", x[i]);
75 | # }
76 | # printf("\n");
77 |
78 | def __init__(self):
79 | self.current_outputs = None
80 | self.possible_outputs = [
81 | [
82 | bytes.fromhex('7C9935A0B07694AA0C6D10E4DB6B1ADD2FD81A25CCB148032DCD739936737F2DB505D7CFAD1B497499323C8686325E4792F267AAFA3F87CA60D01CB54F29202A'),
83 | bytes.fromhex('EB4A7C66EF4EBA2DDB38C88D8BC706B1D639002198172A7B1942ECA8F6C001BA26202BEE59AC275484EA767D41D8D357'),
84 | ],
85 | [
86 | bytes.fromhex('7C9935A0B07694AA0C6D10E4DB6B1ADD2FD81A25CCB148032DCD739936737F2DB505D7CFAD1B497499323C8686325E4792F267AAFA3F87CA60D01CB54F29202A3E784CCB7EBCDCFD45542B7F6AF778742E0F4479175084AA'),
87 | bytes.fromhex('EE716762C15E3B72AA7650A63B9A510040B03C0FE70475C0463BBC45A0BA5B7980DD46EEF82FB062035077D042F306BB6391040E0DD965F1FDA9D183CA9FCCB48FC010B184AB0033'),
88 | ],
89 | [
90 | bytes.fromhex('7C9935A0B07694AA0C6D10E4DB6B1ADD2FD81A25CCB148032DCD739936737F2DB505D7CFAD1B497499323C8686325E4792F267AAFA3F87CA60D01CB54F29202A3E784CCB7EBCDCFD45542B7F6AF778742E0F4479175084AA488B3B74340678AA38E22E9628B0A161FDEB0BD252173B9C'),
91 | bytes.fromhex('9F08587687FF66765C671DE73E918D2823CA573FF4E7A31A9160324026E540EACB3A04E0D54C75DEB9705BFDFBDF935A7528802EE6E5B0C6A73B2B761D9BD0848A6E4CF3FC4CA84F14E0331AF35BFEF41E42B13A6DAE6DF937F738C1857BA1CA'),
92 | ],
93 | ]
94 |
95 | def randombytes(self, n):
96 | # On each use, check if the output length requested matches one of the pre-programmed values
97 | if self.current_outputs == None:
98 | for i in range(len(self.possible_outputs)):
99 | if n == len(self.possible_outputs[i][0]):
100 | self.current_outputs = self.possible_outputs[i]
101 | assert self.current_outputs != None, "Could not find pre-programmed output of desired length {:d}".format(n)
102 | assert len(self.current_outputs) > 0, "No remaining outputs available"
103 | assert n == len(self.current_outputs[0]), "Next output not of the appropriate length"
104 | r = self.current_outputs.pop(0)
105 | return r
106 |
107 | if __name__ == "__main__":
108 | # Run KATs for all supported FrodoKEM variants
109 | katvalues = NISTKAT.run(FrodoKEM('FrodoKEM-640-AES'))
110 | NISTKAT.check(katvalues, 'PQCkemKAT_19888.rsp')
111 | katvalues = NISTKAT.run(FrodoKEM('FrodoKEM-640-SHAKE'))
112 | NISTKAT.check(katvalues, 'PQCkemKAT_19888_shake.rsp')
113 | katvalues = NISTKAT.run(FrodoKEM('FrodoKEM-976-AES'))
114 | NISTKAT.check(katvalues, 'PQCkemKAT_31296.rsp')
115 | katvalues = NISTKAT.run(FrodoKEM('FrodoKEM-976-SHAKE'))
116 | NISTKAT.check(katvalues, 'PQCkemKAT_31296_shake.rsp')
117 | katvalues = NISTKAT.run(FrodoKEM('FrodoKEM-1344-AES'))
118 | NISTKAT.check(katvalues, 'PQCkemKAT_43088.rsp')
119 | katvalues = NISTKAT.run(FrodoKEM('FrodoKEM-1344-SHAKE'))
120 | NISTKAT.check(katvalues, 'PQCkemKAT_43088_shake.rsp')
121 |
--------------------------------------------------------------------------------
/FrodoKEM/src/api_frodo1344.h:
--------------------------------------------------------------------------------
1 | /********************************************************************************************
2 | * FrodoKEM: Learning with Errors Key Encapsulation
3 | *
4 | * Abstract: parameters and API for FrodoKEM-1344
5 | *********************************************************************************************/
6 |
7 | #ifndef _API_Frodo1344_H_
8 | #define _API_Frodo1344_H_
9 |
10 |
11 | #define CRYPTO_SECRETKEYBYTES 43088 // sizeof(s) + CRYPTO_PUBLICKEYBYTES + 2*PARAMS_N*PARAMS_NBAR + BYTES_PKHASH
12 | #define CRYPTO_PUBLICKEYBYTES 21520 // sizeof(seed_A) + (PARAMS_LOGQ*PARAMS_N*PARAMS_NBAR)/8
13 | #define CRYPTO_BYTES 32
14 | #define CRYPTO_CIPHERTEXTBYTES 21696 // (PARAMS_LOGQ*PARAMS_N*PARAMS_NBAR)/8 + (PARAMS_LOGQ*PARAMS_NBAR*PARAMS_NBAR)/8 + BYTES_SALT
15 |
16 | // Algorithm name
17 | #define CRYPTO_ALGNAME "FrodoKEM-1344"
18 |
19 |
20 | int crypto_kem_keypair_Frodo1344(unsigned char *pk, unsigned char *sk);
21 | int crypto_kem_enc_Frodo1344(unsigned char *ct, unsigned char *ss, const unsigned char *pk);
22 | int crypto_kem_dec_Frodo1344(unsigned char *ss, const unsigned char *ct, const unsigned char *sk);
23 |
24 |
25 | #endif
26 |
--------------------------------------------------------------------------------
/FrodoKEM/src/api_frodo640.h:
--------------------------------------------------------------------------------
1 | /********************************************************************************************
2 | * FrodoKEM: Learning with Errors Key Encapsulation
3 | *
4 | * Abstract: parameters and API for FrodoKEM-640
5 | *********************************************************************************************/
6 |
7 | #ifndef _API_Frodo640_H_
8 | #define _API_Frodo640_H_
9 |
10 |
11 | #define CRYPTO_SECRETKEYBYTES 19888 // sizeof(s) + CRYPTO_PUBLICKEYBYTES + 2*PARAMS_N*PARAMS_NBAR + BYTES_PKHASH
12 | #define CRYPTO_PUBLICKEYBYTES 9616 // sizeof(seed_A) + (PARAMS_LOGQ*PARAMS_N*PARAMS_NBAR)/8
13 | #define CRYPTO_BYTES 16
14 | #define CRYPTO_CIPHERTEXTBYTES 9752 // (PARAMS_LOGQ*PARAMS_N*PARAMS_NBAR)/8 + (PARAMS_LOGQ*PARAMS_NBAR*PARAMS_NBAR)/8 + BYTES_SALT
15 |
16 | // Algorithm name
17 | #define CRYPTO_ALGNAME "FrodoKEM-640"
18 |
19 |
20 | int crypto_kem_keypair_Frodo640(unsigned char *pk, unsigned char *sk);
21 | int crypto_kem_enc_Frodo640(unsigned char *ct, unsigned char *ss, const unsigned char *pk);
22 | int crypto_kem_dec_Frodo640(unsigned char *ss, const unsigned char *ct, const unsigned char *sk);
23 |
24 |
25 | #endif
26 |
--------------------------------------------------------------------------------
/FrodoKEM/src/api_frodo976.h:
--------------------------------------------------------------------------------
1 | /********************************************************************************************
2 | * FrodoKEM: Learning with Errors Key Encapsulation
3 | *
4 | * Abstract: parameters and API for FrodoKEM-976
5 | *********************************************************************************************/
6 |
7 | #ifndef _API_Frodo976_H_
8 | #define _API_Frodo976_H_
9 |
10 |
11 | #define CRYPTO_SECRETKEYBYTES 31296 // sizeof(s) + CRYPTO_PUBLICKEYBYTES + 2*PARAMS_N*PARAMS_NBAR + BYTES_PKHASH
12 | #define CRYPTO_PUBLICKEYBYTES 15632 // sizeof(seed_A) + (PARAMS_LOGQ*PARAMS_N*PARAMS_NBAR)/8
13 | #define CRYPTO_BYTES 24
14 | #define CRYPTO_CIPHERTEXTBYTES 15792 // (PARAMS_LOGQ*PARAMS_N*PARAMS_NBAR)/8 + (PARAMS_LOGQ*PARAMS_NBAR*PARAMS_NBAR)/8 + BYTES_SALT
15 |
16 | // Algorithm name
17 | #define CRYPTO_ALGNAME "FrodoKEM-976"
18 |
19 |
20 | int crypto_kem_keypair_Frodo976(unsigned char *pk, unsigned char *sk);
21 | int crypto_kem_enc_Frodo976(unsigned char *ct, unsigned char *ss, const unsigned char *pk);
22 | int crypto_kem_dec_Frodo976(unsigned char *ss, const unsigned char *ct, const unsigned char *sk);
23 |
24 |
25 | #endif
26 |
--------------------------------------------------------------------------------
/FrodoKEM/src/config.h:
--------------------------------------------------------------------------------
1 | /********************************************************************************************
2 | * FrodoKEM: Learning with Errors Key Encapsulation
3 | *
4 | * Abstract: configuration file
5 | *********************************************************************************************/
6 |
7 | #ifndef _CONFIG_H_
8 | #define _CONFIG_H_
9 |
10 |
11 | // Definition of operating system
12 |
13 | #define OS_WIN 1
14 | #define OS_NIX 2
15 |
16 | #if defined(WINDOWS) // Microsoft Windows
17 | #define OS_TARGET OS_WIN
18 | #elif defined(NIX) // Unix-like operative systems
19 | #define OS_TARGET OS_NIX
20 | #else
21 | #error -- "Unsupported OS"
22 | #endif
23 |
24 |
25 | // Definition of compiler
26 |
27 | #define COMPILER_VC 1
28 | #define COMPILER_GCC 2
29 | #define COMPILER_CLANG 3
30 |
31 | #if defined(_MSC_VER) // Microsoft Visual C compiler
32 | #define COMPILER COMPILER_VC
33 | #elif defined(__GNUC__) // GNU GCC compiler
34 | #define COMPILER COMPILER_GCC
35 | #elif defined(__clang__) // Clang compiler
36 | #define COMPILER COMPILER_CLANG
37 | #else
38 | #error -- "Unsupported COMPILER"
39 | #endif
40 |
41 |
42 | // Definition of the targeted architecture and basic data types
43 |
44 | #define TARGET_AMD64 1
45 | #define TARGET_x86 2
46 | #define TARGET_ARM 3
47 | #define TARGET_PPC 4
48 | #define TARGET_S390X 5
49 |
50 | #if defined(_AMD64_)
51 | #define TARGET TARGET_AMD64
52 | #elif defined(_X86_)
53 | #define TARGET TARGET_x86
54 | #elif defined(_ARM_)
55 | #define TARGET TARGET_ARM
56 | #elif defined(_PPC_)
57 | #define TARGET TARGET_PPC
58 | #elif defined(_S390X_)
59 | #define TARGET TARGET_S390X
60 | #else
61 | #error -- "Unsupported ARCHITECTURE"
62 | #endif
63 |
64 |
65 | #if defined(WINDOWS)
66 | #define ALIGN_HEADER(N) __declspec(align(N))
67 | #define ALIGN_FOOTER(N)
68 | #else
69 | #define ALIGN_HEADER(N)
70 | #define ALIGN_FOOTER(N) __attribute__((aligned(N)))
71 | #endif
72 |
73 |
74 | // Selecting implementation: fast, generic or reference
75 | #if defined(_FAST_) // The "fast" implementation requires support for AVX2 and AES_NI instructions
76 | #define USE_AVX2
77 | #define AES_ENABLE_NI
78 | #define USE_FAST
79 | #elif defined(_FAST_GENERIC_)
80 | #define USE_FAST_GENERIC
81 | #elif defined(_REFERENCE_)
82 | #define USE_REFERENCE
83 | #else
84 | #error -- unsupported implementation
85 | #endif
86 |
87 |
88 | // Defining method for generating matrix A
89 | #if defined(_AES128_FOR_A_)
90 | #define USE_AES128_FOR_A
91 | #elif defined(_SHAKE128_FOR_A_)
92 | #define USE_SHAKE128_FOR_A
93 | #else
94 | ##error -- missing method for generating matrix A
95 | #endif
96 |
97 |
98 | // Selecting use of OpenSSL's AES functions
99 | #if defined(_USE_OPENSSL_)
100 | #define USE_OPENSSL
101 | #endif
102 |
103 |
104 | // Configuration for endianness
105 | #if (TARGET == TARGET_PPC || TARGET == TARGET_S390X) || (defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__))
106 | #define LE_TO_UINT16(n) (((((unsigned short)(n) & 0xFF)) << 8) | (((unsigned short)(n) & 0xFF00) >> 8))
107 | #define UINT16_TO_LE(n) (((((unsigned short)(n) & 0xFF)) << 8) | (((unsigned short)(n) & 0xFF00) >> 8))
108 | #elif (TARGET == TARGET_x86 || TARGET == TARGET_AMD64) || (defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__))
109 | #define LE_TO_UINT16(n) (n)
110 | #define UINT16_TO_LE(n) (n)
111 | #else
112 | #define LE_TO_UINT16(n) (((uint8_t *) &(n))[0] | (((uint8_t *) &(n))[1] << 8))
113 | static inline uint16_t UINT16_TO_LE(const uint16_t x) {
114 | uint16_t y;
115 | uint8_t *z = (uint8_t *) &y;
116 | z[0] = x & 0xFF;
117 | z[1] = x >> 8;
118 | return y;
119 | }
120 | #endif
121 |
122 | #endif
123 |
--------------------------------------------------------------------------------
/FrodoKEM/src/frodo1344.c:
--------------------------------------------------------------------------------
1 | /********************************************************************************************
2 | * FrodoKEM: Learning with Errors Key Encapsulation
3 | *
4 | * Abstract: functions for FrodoKEM-1344
5 | * Instantiates "frodo_macrify.c" with the necessary matrix arithmetic functions
6 | *********************************************************************************************/
7 |
8 | #include "api_frodo1344.h"
9 | #include "frodo_macrify.h"
10 |
11 |
12 | // Parameters for "FrodoKEM-1344"
13 | #define PARAMS_N 1344
14 | #define PARAMS_NBAR 8
15 | #define PARAMS_LOGQ 16
16 | #define PARAMS_Q (1 << PARAMS_LOGQ)
17 | #define PARAMS_EXTRACTED_BITS 4
18 | #define PARAMS_STRIPE_STEP 8
19 | #define PARAMS_PARALLEL 4
20 | #define BYTES_SEED_A 16
21 | #define BYTES_MU (PARAMS_EXTRACTED_BITS*PARAMS_NBAR*PARAMS_NBAR)/8
22 | #define BYTES_SALT (2*CRYPTO_BYTES)
23 | #define BYTES_SEED_SE (2*CRYPTO_BYTES)
24 | #define BYTES_PKHASH CRYPTO_BYTES
25 |
26 | #if (PARAMS_NBAR % 8 != 0)
27 | #error You have modified the cryptographic parameters. FrodoKEM assumes PARAMS_NBAR is a multiple of 8.
28 | #endif
29 |
30 | // Selecting SHAKE XOF function for the KEM and noise sampling
31 | #define shake shake256
32 |
33 | // CDF table
34 | uint16_t CDF_TABLE[7] = {9142, 23462, 30338, 32361, 32725, 32765, 32767};
35 | uint16_t CDF_TABLE_LEN = 7;
36 |
37 | #define crypto_kem_keypair crypto_kem_keypair_Frodo1344
38 | #define crypto_kem_enc crypto_kem_enc_Frodo1344
39 | #define crypto_kem_dec crypto_kem_dec_Frodo1344
40 |
41 | #include "kem.c"
42 | #include "noise.c"
43 | #if defined(USE_REFERENCE)
44 | #include "frodo_macrify_reference.c"
45 | #else
46 | #include "frodo_macrify.c"
47 | #endif
48 |
--------------------------------------------------------------------------------
/FrodoKEM/src/frodo640.c:
--------------------------------------------------------------------------------
1 | /********************************************************************************************
2 | * FrodoKEM: Learning with Errors Key Encapsulation
3 | *
4 | * Abstract: functions for FrodoKEM-640
5 | * Instantiates "frodo_macrify.c" with the necessary matrix arithmetic functions
6 | *********************************************************************************************/
7 |
8 | #include "api_frodo640.h"
9 | #include "frodo_macrify.h"
10 |
11 |
12 | // Parameters for "FrodoKEM-640"
13 | #define PARAMS_N 640
14 | #define PARAMS_NBAR 8
15 | #define PARAMS_LOGQ 15
16 | #define PARAMS_Q (1 << PARAMS_LOGQ)
17 | #define PARAMS_EXTRACTED_BITS 2
18 | #define PARAMS_STRIPE_STEP 8
19 | #define PARAMS_PARALLEL 4
20 | #define BYTES_SEED_A 16
21 | #define BYTES_MU (PARAMS_EXTRACTED_BITS*PARAMS_NBAR*PARAMS_NBAR)/8
22 | #define BYTES_SALT (2*CRYPTO_BYTES)
23 | #define BYTES_SEED_SE (2*CRYPTO_BYTES)
24 | #define BYTES_PKHASH CRYPTO_BYTES
25 |
26 | #if (PARAMS_NBAR % 8 != 0)
27 | #error You have modified the cryptographic parameters. FrodoKEM assumes PARAMS_NBAR is a multiple of 8.
28 | #endif
29 |
30 | // Selecting SHAKE XOF function for the KEM and noise sampling
31 | #define shake shake128
32 |
33 | // CDF table
34 | uint16_t CDF_TABLE[13] = {4643, 13363, 20579, 25843, 29227, 31145, 32103, 32525, 32689, 32745, 32762, 32766, 32767};
35 | uint16_t CDF_TABLE_LEN = 13;
36 |
37 | #define crypto_kem_keypair crypto_kem_keypair_Frodo640
38 | #define crypto_kem_enc crypto_kem_enc_Frodo640
39 | #define crypto_kem_dec crypto_kem_dec_Frodo640
40 |
41 | #include "kem.c"
42 | #include "noise.c"
43 | #if defined(USE_REFERENCE)
44 | #include "frodo_macrify_reference.c"
45 | #else
46 | #include "frodo_macrify.c"
47 | #endif
48 |
--------------------------------------------------------------------------------
/FrodoKEM/src/frodo976.c:
--------------------------------------------------------------------------------
1 | /********************************************************************************************
2 | * FrodoKEM: Learning with Errors Key Encapsulation
3 | *
4 | * Abstract: functions for FrodoKEM-976
5 | * Instantiates "frodo_macrify.c" with the necessary matrix arithmetic functions
6 | *********************************************************************************************/
7 |
8 | #include "api_frodo976.h"
9 | #include "frodo_macrify.h"
10 |
11 |
12 | // Parameters for "FrodoKEM-976"
13 | #define PARAMS_N 976
14 | #define PARAMS_NBAR 8
15 | #define PARAMS_LOGQ 16
16 | #define PARAMS_Q (1 << PARAMS_LOGQ)
17 | #define PARAMS_EXTRACTED_BITS 3
18 | #define PARAMS_STRIPE_STEP 8
19 | #define PARAMS_PARALLEL 4
20 | #define BYTES_SEED_A 16
21 | #define BYTES_MU (PARAMS_EXTRACTED_BITS*PARAMS_NBAR*PARAMS_NBAR)/8
22 | #define BYTES_SALT (2*CRYPTO_BYTES)
23 | #define BYTES_SEED_SE (2*CRYPTO_BYTES)
24 | #define BYTES_PKHASH CRYPTO_BYTES
25 |
26 | #if (PARAMS_NBAR % 8 != 0)
27 | #error You have modified the cryptographic parameters. FrodoKEM assumes PARAMS_NBAR is a multiple of 8.
28 | #endif
29 |
30 | // Selecting SHAKE XOF function for the KEM and noise sampling
31 | #define shake shake256
32 |
33 | // CDF table
34 | uint16_t CDF_TABLE[11] = {5638, 15915, 23689, 28571, 31116, 32217, 32613, 32731, 32760, 32766, 32767};
35 | uint16_t CDF_TABLE_LEN = 11;
36 |
37 | #define crypto_kem_keypair crypto_kem_keypair_Frodo976
38 | #define crypto_kem_enc crypto_kem_enc_Frodo976
39 | #define crypto_kem_dec crypto_kem_dec_Frodo976
40 |
41 | #include "kem.c"
42 | #include "noise.c"
43 | #if defined(USE_REFERENCE)
44 | #include "frodo_macrify_reference.c"
45 | #else
46 | #include "frodo_macrify.c"
47 | #endif
48 |
--------------------------------------------------------------------------------
/FrodoKEM/src/frodo_macrify.h:
--------------------------------------------------------------------------------
1 | /********************************************************************************************
2 | * FrodoKEM: Learning with Errors Key Encapsulation
3 | *
4 | * Abstract: header for internal functions
5 | *********************************************************************************************/
6 |
7 | #ifndef _FRODO_MACRIFY_H_
8 | #define _FRODO_MACRIFY_H_
9 |
10 | #include
11 | #include
12 | #include "config.h"
13 |
14 |
15 | void frodo_pack(unsigned char *out, const size_t outlen, const uint16_t *in, const size_t inlen, const unsigned char lsb);
16 | void frodo_unpack(uint16_t *out, const size_t outlen, const unsigned char *in, const size_t inlen, const unsigned char lsb);
17 | void frodo_sample_n(uint16_t *s, const size_t n);
18 | int8_t ct_verify(const uint16_t *a, const uint16_t *b, size_t len);
19 | void ct_select(uint8_t *r, const uint8_t *a, const uint8_t *b, size_t len, int8_t selector);
20 | void clear_bytes(uint8_t *mem, size_t n);
21 |
22 | int frodo_mul_add_as_plus_e(uint16_t *b, const uint16_t *s, const uint16_t *e, const uint8_t *seed_A);
23 | int frodo_mul_add_sa_plus_e(uint16_t *b, const uint16_t *s, uint16_t *e, const uint8_t *seed_A);
24 | void frodo_mul_add_sb_plus_e(uint16_t *out, const uint16_t *b, const uint16_t *s, const uint16_t *e);
25 | void frodo_mul_bs(uint16_t *out, const uint16_t *b, const uint16_t *s);
26 |
27 | void frodo_add(uint16_t *out, const uint16_t *a, const uint16_t *b);
28 | void frodo_sub(uint16_t *out, const uint16_t *a, const uint16_t *b);
29 | void frodo_key_encode(uint16_t *out, const uint16_t *in);
30 | void frodo_key_decode(uint16_t *out, const uint16_t *in);
31 |
32 | #endif
33 |
--------------------------------------------------------------------------------
/FrodoKEM/src/noise.c:
--------------------------------------------------------------------------------
1 | /********************************************************************************************
2 | * FrodoKEM: Learning with Errors Key Encapsulation
3 | *
4 | * Abstract: noise sampling functions
5 | *********************************************************************************************/
6 |
7 | #include "../../common/sha3/fips202.h"
8 |
9 |
10 | void frodo_sample_n(uint16_t *s, const size_t n)
11 | { // Fills vector s with n samples from the noise distribution which requires 16 bits to sample.
12 | // The distribution is specified by its CDF.
13 | // Input: pseudo-random values (2*n bytes) passed in s. The input is overwritten by the output.
14 | unsigned int i, j;
15 |
16 | for (i = 0; i < n; ++i) {
17 | uint16_t sample = 0;
18 | uint16_t prnd = s[i] >> 1; // Drop the least significant bit
19 | uint16_t sign = s[i] & 0x1; // Pick the least significant bit
20 |
21 | // No need to compare with the last value.
22 | for (j = 0; j < (unsigned int)(CDF_TABLE_LEN - 1); j++) {
23 | // Constant time comparison: 1 if CDF_TABLE[j] < s, 0 otherwise. Uses the fact that CDF_TABLE[j] and s fit in 15 bits.
24 | sample += (uint16_t)(CDF_TABLE[j] - prnd) >> 15;
25 | }
26 | // Assuming that sign is either 0 or 1, flips sample iff sign = 1
27 | s[i] = ((-sign) ^ sample) + sign;
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/FrodoKEM/src/util.c:
--------------------------------------------------------------------------------
1 | /********************************************************************************************
2 | * FrodoKEM: Learning with Errors Key Encapsulation
3 | *
4 | * Abstract: additional functions for FrodoKEM
5 | *********************************************************************************************/
6 |
7 | #include
8 | #include "frodo_macrify.h"
9 |
10 | #define min(x, y) (((x) < (y)) ? (x) : (y))
11 |
12 |
13 | void frodo_pack(unsigned char *out, const size_t outlen, const uint16_t *in, const size_t inlen, const unsigned char lsb)
14 | { // Pack the input uint16 vector into a char output vector, copying lsb bits from each input element.
15 | // If inlen * lsb / 8 > outlen, only outlen * 8 bits are copied.
16 | memset(out, 0, outlen);
17 |
18 | size_t i = 0; // whole bytes already filled in
19 | size_t j = 0; // whole uint16_t already copied
20 | uint16_t w = 0; // the leftover, not yet copied
21 | unsigned char bits = 0; // the number of lsb in w
22 |
23 | while (i < outlen && (j < inlen || ((j == inlen) && (bits > 0)))) {
24 | /*
25 | in: | | |********|********|
26 | ^
27 | j
28 | w : | ****|
29 | ^
30 | bits
31 | out:|**|**|**|**|**|**|**|**|* |
32 | ^^
33 | ib
34 | */
35 | unsigned char b = 0; // bits in out[i] already filled in
36 | while (b < 8) {
37 | int nbits = min(8 - b, bits);
38 | uint16_t mask = (1 << nbits) - 1;
39 | unsigned char t = (w >> (bits - nbits)) & mask; // the bits to copy from w to out
40 | out[i] = out[i] + (t << (8 - b - nbits));
41 | b += nbits;
42 | bits -= nbits;
43 | w &= ~(mask << bits); // not strictly necessary; mostly for debugging
44 |
45 | if (bits == 0) {
46 | if (j < inlen) {
47 | w = in[j];
48 | bits = lsb;
49 | j++;
50 | } else {
51 | break; // the input vector is exhausted
52 | }
53 | }
54 | }
55 | if (b == 8) { // out[i] is filled in
56 | i++;
57 | }
58 | }
59 | }
60 |
61 |
62 | void frodo_unpack(uint16_t *out, const size_t outlen, const unsigned char *in, const size_t inlen, const unsigned char lsb)
63 | { // Unpack the input char vector into a uint16_t output vector, copying lsb bits
64 | // for each output element from input. outlen must be at least ceil(inlen * 8 / lsb).
65 | memset(out, 0, outlen * sizeof(uint16_t));
66 |
67 | size_t i = 0; // whole uint16_t already filled in
68 | size_t j = 0; // whole bytes already copied
69 | unsigned char w = 0; // the leftover, not yet copied
70 | unsigned char bits = 0; // the number of lsb bits of w
71 |
72 | while (i < outlen && (j < inlen || ((j == inlen) && (bits > 0)))) {
73 | /*
74 | in: | | | | | | |**|**|...
75 | ^
76 | j
77 | w : | *|
78 | ^
79 | bits
80 | out:| *****| *****| *** | |...
81 | ^ ^
82 | i b
83 | */
84 | unsigned char b = 0; // bits in out[i] already filled in
85 | while (b < lsb) {
86 | int nbits = min(lsb - b, bits);
87 | uint16_t mask = (1 << nbits) - 1;
88 | unsigned char t = (w >> (bits - nbits)) & mask; // the bits to copy from w to out
89 | out[i] = out[i] + (t << (lsb - b - nbits));
90 | b += nbits;
91 | bits -= nbits;
92 | w &= ~(mask << bits); // not strictly necessary; mostly for debugging
93 |
94 | if (bits == 0) {
95 | if (j < inlen) {
96 | w = in[j];
97 | bits = 8;
98 | j++;
99 | } else {
100 | break; // the input vector is exhausted
101 | }
102 | }
103 | }
104 | if (b == lsb) { // out[i] is filled in
105 | i++;
106 | }
107 | }
108 | }
109 |
110 |
111 | int8_t ct_verify(const uint16_t *a, const uint16_t *b, size_t len)
112 | { // Compare two arrays in constant time.
113 | // Returns 0 if the byte arrays are equal, -1 otherwise.
114 | uint16_t r = 0;
115 |
116 | for (size_t i = 0; i < len; i++) {
117 | r |= a[i] ^ b[i];
118 | }
119 |
120 | r = (-(int16_t)(r >> 1) | -(int16_t)(r & 1)) >> (8*sizeof(uint16_t)-1);
121 | return (int8_t)r;
122 | }
123 |
124 |
125 | void ct_select(uint8_t *r, const uint8_t *a, const uint8_t *b, size_t len, int8_t selector)
126 | { // Select one of the two input arrays to be moved to r
127 | // If (selector == 0) then load r with a, else if (selector == -1) load r with b
128 |
129 | for (size_t i = 0; i < len; i++) {
130 | r[i] = (~selector & a[i]) | (selector & b[i]);
131 | }
132 | }
133 |
134 |
135 | void clear_bytes(uint8_t *mem, size_t n)
136 | { // Clear 8-bit bytes from memory. "n" indicates the number of bytes to be zeroed.
137 | // This function uses the volatile type qualifier to inform the compiler not to optimize out the memory clearing.
138 | volatile uint8_t *v = mem;
139 |
140 | for (size_t i = 0; i < n; i++) {
141 | v[i] = 0;
142 | }
143 | }
144 |
--------------------------------------------------------------------------------
/FrodoKEM/tests/ds_benchmark.h:
--------------------------------------------------------------------------------
1 | /********************************************************************************************
2 | * ds_benchmark.h: Macros for simple benchmarking of C code.
3 | *
4 | * See instructions for usage below.
5 | * Software originally developed by Douglas Stebila.
6 | * Most recent version at https://gist.github.com/dstebila/6980008ec98209ef6075
7 | *
8 | * This is free and unencumbered software released into the public domain.
9 | *
10 | * Anyone is free to copy, modify, publish, use, compile, sell, or
11 | * distribute this software, either in source code form or as a compiled
12 | * binary, for any purpose, commercial or non-commercial, and by any
13 | * means.
14 | *
15 | * In jurisdictions that recognize copyright laws, the author or authors
16 | * of this software dedicate any and all copyright interest in the
17 | * software to the public domain. We make this dedication for the benefit
18 | * of the public at large and to the detriment of our heirs and
19 | * successors. We intend this dedication to be an overt act of
20 | * relinquishment in perpetuity of all present and future rights to this
21 | * software under copyright law.
22 | *
23 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
26 | * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
27 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
28 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
29 | * OTHER DEALINGS IN THE SOFTWARE.
30 | *
31 | * For more information, please refer to
32 | ********************************************************************************************/
33 |
34 | /** \file ds_benchmark.h
35 | * Macros for simple benchmarking of C code.
36 | */
37 |
38 | #ifndef _DS_BENCHMARK_H
39 | #define _DS_BENCHMARK_H
40 |
41 | #include "../src/config.h"
42 | #include
43 | #include
44 | #include
45 | #if (OS_TARGET == OS_NIX)
46 | #include
47 | #endif
48 | #include
49 | #include
50 |
51 |
52 | #if (OS_TARGET == OS_WIN)
53 | #include
54 |
55 | int gettimeofday(struct timeval *tp, struct timezone *tzp) {
56 | // Note: some broken versions only have 8 trailing zero's, the correct epoch has 9 trailing zero's
57 | static const uint64_t EPOCH = ((uint64_t)116444736000000000ULL);
58 |
59 | SYSTEMTIME system_time;
60 | FILETIME file_time;
61 | uint64_t time;
62 |
63 | GetSystemTime(&system_time);
64 | SystemTimeToFileTime(&system_time, &file_time);
65 | time = ((uint64_t)file_time.dwLowDateTime);
66 | time += ((uint64_t)file_time.dwHighDateTime) << 32;
67 |
68 | tp->tv_sec = (long)((time - EPOCH) / 10000000L);
69 | tp->tv_usec = (long)(system_time.wMilliseconds * 1000);
70 | return 0;
71 | }
72 | #endif
73 |
74 |
75 | static uint64_t rdtsc(void) {
76 | #if (OS_TARGET == OS_WIN)
77 | return __rdtsc();
78 | #elif (OS_TARGET == OS_NIX) && (TARGET == TARGET_AMD64 || TARGET == TARGET_x86)
79 | uint64_t x;
80 | __asm__ volatile (".byte 0x0f, 0x31" : "=A" (x));
81 | return x;
82 | #elif (OS_TARGET == OS_NIX && TARGET == TARGET_ARM)
83 | struct timespec time;
84 | clock_gettime(CLOCK_REALTIME, &time);
85 | return (int64_t)(time.tv_sec*1e9 + time.tv_nsec);
86 | #else
87 | return 0;
88 | #endif
89 | }
90 |
91 |
92 | #define DEFINE_TIMER_VARIABLES \
93 | volatile uint64_t _bench_cycles_start, _bench_cycles_end; \
94 | uint64_t _bench_cycles_cumulative = 0; \
95 | int64_t _bench_cycles_diff, _bench_iterations; \
96 | struct timeval _bench_timeval_start, _bench_timeval_end; \
97 | double _bench_cycles_x, _bench_cycles_mean, _bench_cycles_delta, _bench_cycles_M2, _bench_cycles_stdev; \
98 | double _bench_time_x, _bench_time_mean, _bench_time_delta, _bench_time_M2, _bench_time_stdev, _bench_time_cumulative;
99 |
100 | #define INITIALIZE_TIMER \
101 | _bench_iterations = 0; \
102 | _bench_cycles_mean = 0.0; \
103 | _bench_cycles_M2 = 0.0; \
104 | _bench_time_cumulative = 0.0; \
105 | _bench_time_mean = 0.0; \
106 | _bench_time_M2 = 0.0;
107 |
108 | #define START_TIMER \
109 | gettimeofday(&_bench_timeval_start, NULL); \
110 | _bench_cycles_start = rdtsc();
111 |
112 |
113 | // Mean and population standard deviation are calculated in an online way using the algorithm in
114 | // http://en.wikipedia.org/wiki/Algorithms_for_calculating_variance#Online_algorithm
115 |
116 | #define STOP_TIMER \
117 | _bench_cycles_end = rdtsc(); \
118 | gettimeofday(&_bench_timeval_end, NULL); \
119 | _bench_iterations += 1; \
120 | if (_bench_cycles_end < _bench_cycles_start) { _bench_cycles_end += (uint64_t)1 << 32; } \
121 | _bench_cycles_diff = _bench_cycles_end; \
122 | _bench_cycles_diff -= _bench_cycles_start; \
123 | _bench_cycles_cumulative += _bench_cycles_diff; \
124 | _bench_cycles_x = (double) (_bench_cycles_diff); \
125 | _bench_cycles_delta = _bench_cycles_x - _bench_cycles_mean; \
126 | _bench_cycles_mean += _bench_cycles_delta / (double) _bench_iterations; \
127 | _bench_cycles_M2 += _bench_cycles_delta * (_bench_cycles_x - _bench_cycles_mean); \
128 | _bench_time_x = (double) ((_bench_timeval_end.tv_sec * 1000000 + _bench_timeval_end.tv_usec) - (_bench_timeval_start.tv_sec * 1000000 + _bench_timeval_start.tv_usec)); \
129 | _bench_time_delta = _bench_time_x - _bench_time_mean; \
130 | _bench_time_mean += _bench_time_delta / (double) _bench_iterations; \
131 | _bench_time_M2 += _bench_time_delta * (_bench_time_x - _bench_time_mean); \
132 | _bench_time_cumulative += _bench_time_x;
133 |
134 | #define FINALIZE_TIMER \
135 | if (_bench_iterations == 2) { _bench_cycles_stdev = 0.0; } \
136 | else { _bench_cycles_stdev = sqrt(_bench_cycles_M2 / (double) _bench_iterations); } \
137 | if (_bench_iterations == 2) { _bench_time_stdev = 0.0; } \
138 | else { _bench_time_stdev = sqrt(_bench_time_M2 / (double) _bench_iterations); }
139 |
140 | #if (TARGET == TARGET_ARM)
141 | #define PRINT_TIMER_HEADER \
142 | printf("%-30s %15s %15s %15s %15s\n", "Operation", "Iterations", "Total time (s)", "Time(us): mean", "pop. stdev");
143 | #else
144 | #define PRINT_TIMER_HEADER \
145 | printf("%-30s %15s %15s %15s %15s %15s %15s\n", "Operation", "Iterations", "Total time (s)", "Time(us): mean", "pop. stdev", "Cycles: mean", "pop. stdev");
146 | #endif
147 |
148 | #if (TARGET == TARGET_ARM)
149 | #define PRINT_TIMER_AVG(op_name) \
150 | printf("%-30s %15" PRIu64 " %15.3f %15.3f %15.3f\n", (op_name), _bench_iterations, _bench_time_cumulative / 1000000.0, _bench_time_mean, _bench_time_stdev); \
151 | (void)_bench_cycles_stdev;
152 | #else
153 | #define PRINT_TIMER_AVG(op_name) \
154 | printf("%-30s %15" PRIu64 " %15.3f %15.3f %15.3f %15.0f %15.0f\n", (op_name), _bench_iterations, _bench_time_cumulative / 1000000.0, _bench_time_mean, _bench_time_stdev, ((double) _bench_cycles_cumulative) / (double) _bench_iterations, _bench_cycles_stdev);
155 | #endif
156 |
157 | #define TIME_OPERATION_ITERATIONS(op, op_name, it) \
158 | { \
159 | DEFINE_TIMER_VARIABLES \
160 | INITIALIZE_TIMER \
161 | for (int i = 0; i < (it); i++) { \
162 | START_TIMER \
163 | { op ; } \
164 | STOP_TIMER \
165 | } \
166 | FINALIZE_TIMER \
167 | PRINT_TIMER_AVG(op_name) \
168 | }
169 |
170 | #define TIME_OPERATION_SECONDS(op, op_name, secs) \
171 | { \
172 | DEFINE_TIMER_VARIABLES \
173 | INITIALIZE_TIMER \
174 | uint64_t _bench_time_goal_usecs = 1000000 * secs; \
175 | while ((uint64_t)_bench_time_cumulative < _bench_time_goal_usecs) { \
176 | START_TIMER \
177 | { op ; } \
178 | STOP_TIMER \
179 | } \
180 | FINALIZE_TIMER \
181 | PRINT_TIMER_AVG(op_name) \
182 | }
183 | #endif
184 |
--------------------------------------------------------------------------------
/FrodoKEM/tests/rng.c:
--------------------------------------------------------------------------------
1 | //
2 | // rng.c
3 | //
4 | // Created by Bassham, Lawrence E (Fed) on 8/29/17.
5 | // Copyright © 2017 Bassham, Lawrence E (Fed). All rights reserved.
6 | //
7 | // Modified to use OpenSSL's AES256_ECB or a standalone implementation
8 |
9 | #include
10 | #include "rng.h"
11 |
12 | AES256_CTR_DRBG_struct DRBG_ctx;
13 |
14 | void
15 | randombytes_init(unsigned char *entropy_input,
16 | unsigned char *personalization_string,
17 | int security_strength)
18 | {
19 | unsigned char seed_material[48];
20 |
21 | (void)security_strength; // Unused parameter
22 | memcpy(seed_material, entropy_input, 48);
23 | if (personalization_string)
24 | for (int i=0; i<48; i++)
25 | seed_material[i] ^= personalization_string[i];
26 | memset(DRBG_ctx.Key, 0x00, 32);
27 | memset(DRBG_ctx.V, 0x00, 16);
28 | AES256_CTR_DRBG_Update(seed_material, DRBG_ctx.Key, DRBG_ctx.V);
29 | DRBG_ctx.reseed_counter = 1;
30 | }
31 |
32 | int
33 | randombytes(unsigned char *x, unsigned long long xlen)
34 | {
35 | unsigned char block[16];
36 | int i = 0;
37 |
38 | while ( xlen > 0 ) {
39 | //increment V
40 | for (int j=15; j>=0; j--) {
41 | if ( DRBG_ctx.V[j] == 0xff )
42 | DRBG_ctx.V[j] = 0x00;
43 | else {
44 | DRBG_ctx.V[j]++;
45 | break;
46 | }
47 | }
48 | AES256_ECB(DRBG_ctx.Key, DRBG_ctx.V, block);
49 | if ( xlen > 15 ) {
50 | memcpy(x+i, block, 16);
51 | i += 16;
52 | xlen -= 16;
53 | }
54 | else {
55 | memcpy(x+i, block, xlen);
56 | xlen = 0;
57 | }
58 | }
59 | AES256_CTR_DRBG_Update(NULL, DRBG_ctx.Key, DRBG_ctx.V);
60 | DRBG_ctx.reseed_counter++;
61 |
62 | return RNG_SUCCESS;
63 | }
64 |
65 | void
66 | AES256_CTR_DRBG_Update(unsigned char *provided_data,
67 | unsigned char *Key,
68 | unsigned char *V)
69 | {
70 | unsigned char temp[48];
71 |
72 | for (int i=0; i<3; i++) {
73 | //increment V
74 | for (int j=15; j>=0; j--) {
75 | if ( V[j] == 0xff )
76 | V[j] = 0x00;
77 | else {
78 | V[j]++;
79 | break;
80 | }
81 | }
82 |
83 | AES256_ECB(Key, V, temp+16*i);
84 | }
85 | if ( provided_data != NULL )
86 | for (int i=0; i<48; i++)
87 | temp[i] ^= provided_data[i];
88 | memcpy(Key, temp, 32);
89 | memcpy(V, temp+32, 16);
90 | }
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
--------------------------------------------------------------------------------
/FrodoKEM/tests/rng.h:
--------------------------------------------------------------------------------
1 | //
2 | // rng.h
3 | //
4 | // Created by Bassham, Lawrence E (Fed) on 8/29/17.
5 | // Copyright © 2017 Bassham, Lawrence E (Fed). All rights reserved.
6 | //
7 | // Modified to use OpenSSL's AES256_ECB or a standalone implementation
8 |
9 | #ifndef rng_h
10 | #define rng_h
11 |
12 | #include
13 | #include "../src/config.h"
14 | #if !defined(USE_OPENSSL)
15 | #include "../../common/aes/aes.h"
16 | #else
17 | #include "../../common/aes/aes_openssl.h"
18 | #endif
19 |
20 | #define RNG_SUCCESS 0
21 | #define RNG_BAD_MAXLEN -1
22 | #define RNG_BAD_OUTBUF -2
23 | #define RNG_BAD_REQ_LEN -3
24 |
25 | static __inline void AES256_ECB(unsigned char *key, unsigned char *ctr, unsigned char *buffer) {
26 | #if !defined(USE_OPENSSL)
27 | uint8_t schedule[16*15];
28 | AES256_load_schedule(key, schedule);
29 | AES256_ECB_enc_sch(ctr, 16, schedule, buffer);
30 | AES256_free_schedule(schedule);
31 | #else
32 | EVP_CIPHER_CTX *ctx;
33 | int len;
34 |
35 | /* Create and initialise the context */
36 | if(!(ctx = EVP_CIPHER_CTX_new())) handleErrors();
37 |
38 | if(1 != EVP_EncryptInit_ex(ctx, EVP_aes_256_ecb(), NULL, key, NULL))
39 | handleErrors();
40 |
41 | if(1 != EVP_EncryptUpdate(ctx, buffer, &len, ctr, 16))
42 | handleErrors();
43 |
44 | /* Clean up */
45 | EVP_CIPHER_CTX_free(ctx);
46 | #endif
47 | }
48 |
49 | typedef struct {
50 | unsigned char buffer[16];
51 | int buffer_pos;
52 | unsigned long length_remaining;
53 | unsigned char key[32];
54 | unsigned char ctr[16];
55 | } AES_XOF_struct;
56 |
57 | typedef struct {
58 | unsigned char Key[32];
59 | unsigned char V[16];
60 | int reseed_counter;
61 | } AES256_CTR_DRBG_struct;
62 |
63 |
64 | void
65 | AES256_CTR_DRBG_Update(unsigned char *provided_data,
66 | unsigned char *Key,
67 | unsigned char *V);
68 |
69 | void
70 | randombytes_init(unsigned char *entropy_input,
71 | unsigned char *personalization_string,
72 | int security_strength);
73 |
74 | int
75 | randombytes(unsigned char *x, unsigned long long xlen);
76 |
77 | #endif /* rng_h */
78 |
--------------------------------------------------------------------------------
/FrodoKEM/tests/test_KEM1344.c:
--------------------------------------------------------------------------------
1 | /********************************************************************************************
2 | * FrodoKEM: Learning with Errors Key Encapsulation
3 | *
4 | * Abstract: setting parameters to test FrodoKEM-1344
5 | *********************************************************************************************/
6 |
7 | #include
8 | #include
9 | #include
10 | #include
11 | #include "ds_benchmark.h"
12 | #include "../src/api_frodo1344.h"
13 |
14 |
15 | #define SYSTEM_NAME "FrodoKEM-1344"
16 |
17 | #define crypto_kem_keypair crypto_kem_keypair_Frodo1344
18 | #define crypto_kem_enc crypto_kem_enc_Frodo1344
19 | #define crypto_kem_dec crypto_kem_dec_Frodo1344
20 | #define shake shake256
21 |
22 | #include "test_kem.c"
23 |
--------------------------------------------------------------------------------
/FrodoKEM/tests/test_KEM640.c:
--------------------------------------------------------------------------------
1 | /********************************************************************************************
2 | * FrodoKEM: Learning with Errors Key Encapsulation
3 | *
4 | * Abstract: setting parameters to test FrodoKEM-640
5 | *********************************************************************************************/
6 |
7 | #include
8 | #include
9 | #include
10 | #include
11 | #include "ds_benchmark.h"
12 | #include "../src/api_frodo640.h"
13 |
14 |
15 | #define SYSTEM_NAME "FrodoKEM-640"
16 |
17 | #define crypto_kem_keypair crypto_kem_keypair_Frodo640
18 | #define crypto_kem_enc crypto_kem_enc_Frodo640
19 | #define crypto_kem_dec crypto_kem_dec_Frodo640
20 | #define shake shake128
21 |
22 | #include "test_kem.c"
23 |
--------------------------------------------------------------------------------
/FrodoKEM/tests/test_KEM976.c:
--------------------------------------------------------------------------------
1 | /********************************************************************************************
2 | * FrodoKEM: Learning with Errors Key Encapsulation
3 | *
4 | * Abstract: setting parameters to test FrodoKEM-976
5 | *********************************************************************************************/
6 |
7 | #include
8 | #include
9 | #include
10 | #include
11 | #include "ds_benchmark.h"
12 | #include "../src/api_frodo976.h"
13 |
14 |
15 | #define SYSTEM_NAME "FrodoKEM-976"
16 |
17 | #define crypto_kem_keypair crypto_kem_keypair_Frodo976
18 | #define crypto_kem_enc crypto_kem_enc_Frodo976
19 | #define crypto_kem_dec crypto_kem_dec_Frodo976
20 | #define shake shake256
21 |
22 | #include "test_kem.c"
23 |
--------------------------------------------------------------------------------
/FrodoKEM/tests/test_kem.c:
--------------------------------------------------------------------------------
1 | /********************************************************************************************
2 | * FrodoKEM: Learning with Errors Key Encapsulation
3 | *
4 | * Abstract: benchmarking/testing KEM scheme
5 | *********************************************************************************************/
6 |
7 | #include "../../common/random/random.h"
8 | #include "../../common/sha3/fips202.h"
9 |
10 | #ifdef DO_VALGRIND_CHECK
11 | #include
12 | #endif
13 |
14 | #if defined(DO_VALGRIND_CHECK) || defined(_PPC_)
15 | #define KEM_TEST_ITERATIONS 1
16 | #else
17 | #define KEM_TEST_ITERATIONS 100
18 | #endif
19 | #define KEM_BENCH_SECONDS 1
20 |
21 |
22 | static int kem_test(const char *named_parameters, int iterations)
23 | {
24 | uint8_t pk[CRYPTO_PUBLICKEYBYTES];
25 | uint8_t sk[CRYPTO_SECRETKEYBYTES];
26 | uint8_t ss_encap[CRYPTO_BYTES], ss_decap[CRYPTO_BYTES];
27 | uint8_t ct[CRYPTO_CIPHERTEXTBYTES];
28 | unsigned char bytes[4];
29 | uint32_t* pos = (uint32_t*)bytes;
30 | uint8_t Fin[CRYPTO_CIPHERTEXTBYTES + CRYPTO_BYTES];
31 |
32 | #ifdef DO_VALGRIND_CHECK
33 | if (!RUNNING_ON_VALGRIND) {
34 | fprintf(stderr, "This test can only usefully be run inside valgrind.\n");
35 | fprintf(stderr, "valgrind frodo640/test_KEM (or frodo976 or frodo1344)\n");
36 | exit(1);
37 | }
38 | #endif
39 |
40 | printf("\n");
41 | printf("=============================================================================================================================\n");
42 | printf("Testing correctness of key encapsulation mechanism (KEM), system %s, tests for %d iterations\n", named_parameters, iterations);
43 | printf("=============================================================================================================================\n");
44 |
45 | for (int i = 0; i < iterations; i++) {
46 | if (crypto_kem_keypair(pk, sk) != 0) {
47 | printf("\n ERROR -- key generation failed!\n");
48 | return false;
49 | }
50 | if (crypto_kem_enc(ct, ss_encap, pk) != 0) {
51 | printf("\n ERROR -- encapsulation mechanism failed!\n");
52 | return false;
53 | }
54 | crypto_kem_dec(ss_decap, ct, sk);
55 | #ifdef DO_VALGRIND_CHECK
56 | VALGRIND_MAKE_MEM_DEFINED(ss_encap, CRYPTO_BYTES);
57 | VALGRIND_MAKE_MEM_DEFINED(ss_decap, CRYPTO_BYTES);
58 | #endif
59 | if (memcmp(ss_encap, ss_decap, CRYPTO_BYTES) != 0) {
60 | printf("\n ERROR -- encapsulation/decapsulation mechanism failed!\n");
61 | return false;
62 | }
63 |
64 | // Testing decapsulation after changing random bits of a random 16-bit digit of ct
65 | randombytes(bytes, 4);
66 | *pos %= CRYPTO_CIPHERTEXTBYTES/2;
67 | if (*pos == 0) {
68 | *pos = 1;
69 | }
70 | ((uint16_t*)ct)[*pos] ^= *pos;
71 | crypto_kem_dec(ss_decap, ct, sk);
72 | #ifdef DO_VALGRIND_CHECK
73 | VALGRIND_MAKE_MEM_DEFINED(ss_decap, CRYPTO_BYTES);
74 | #endif
75 |
76 | // Compute ss = F(ct || s) with modified ct
77 | memcpy(Fin, ct, CRYPTO_CIPHERTEXTBYTES);
78 | memcpy(&Fin[CRYPTO_CIPHERTEXTBYTES], sk, CRYPTO_BYTES);
79 | shake(ss_encap, CRYPTO_BYTES, Fin, CRYPTO_CIPHERTEXTBYTES + CRYPTO_BYTES);
80 |
81 | #ifdef DO_VALGRIND_CHECK
82 | VALGRIND_MAKE_MEM_DEFINED(ss_encap, CRYPTO_BYTES);
83 | #endif
84 | if (memcmp(ss_encap, ss_decap, CRYPTO_BYTES) != 0) {
85 | printf("\n ERROR -- changing random bits of the ciphertext should cause a failure!\n");
86 | return false;
87 | }
88 | }
89 | printf("Tests PASSED. All session keys matched.\n");
90 | printf("\n\n");
91 |
92 | return true;
93 | }
94 |
95 |
96 | static void kem_bench(const int seconds)
97 | {
98 | uint8_t pk[CRYPTO_PUBLICKEYBYTES];
99 | uint8_t sk[CRYPTO_SECRETKEYBYTES];
100 | uint8_t ss_encap[CRYPTO_BYTES], ss_decap[CRYPTO_BYTES];
101 | uint8_t ct[CRYPTO_CIPHERTEXTBYTES];
102 |
103 | TIME_OPERATION_SECONDS({ crypto_kem_keypair(pk, sk); }, "Key generation", seconds);
104 |
105 | crypto_kem_keypair(pk, sk);
106 | TIME_OPERATION_SECONDS({ crypto_kem_enc(ct, ss_encap, pk); }, "KEM encapsulate", seconds);
107 |
108 | crypto_kem_enc(ct, ss_encap, pk);
109 | TIME_OPERATION_SECONDS({ crypto_kem_dec(ss_decap, ct, sk); }, "KEM decapsulate", seconds);
110 | }
111 |
112 |
113 | int main(int argc, char **argv)
114 | {
115 | int OK = true;
116 |
117 | OK = kem_test(SYSTEM_NAME, KEM_TEST_ITERATIONS);
118 | if (OK != true) {
119 | goto exit;
120 | }
121 |
122 | if ((argc > 1) && (strcmp("nobench", argv[1]) == 0)) {}
123 | else {
124 | PRINT_TIMER_HEADER
125 | kem_bench(KEM_BENCH_SECONDS);
126 | }
127 |
128 | exit:
129 | return (OK == true) ? EXIT_SUCCESS : EXIT_FAILURE;
130 | }
131 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) Microsoft Corporation. All rights reserved.
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | FrodoKEM: Learning with Errors Key Encapsulation
2 | ================================================
3 |
4 | This C library implements **FrodoKEM**, an IND-CCA secure key encapsulation (KEM) protocol based on the well-studied Learning with Errors (LWE) problem [1,3], which in turn has close connections to conjectured-hard problems on generic,
5 | "algebraically unstructured" lattices. This package also includes Python reference implementations. **FrodoKEM** is conjectured to be secure against quantum computer attacks.
6 |
7 | **FrodoKEM** consists of two main variants:
8 |
9 | * A *standard* variant (simply called **FrodoKEM**) that does not impose any restriction on the reuse of key pairs (i.e., it is suitable for applications in which a large number of ciphertexts may be encrypted to a single public key), and
10 | * An *ephemeral* variant (called **eFrodoKEM**) that is suitable for applications in which not many ciphertexts are encrypted to a single public-key.
11 |
12 | In contrast to **eFrodoKEM**, standard **FrodoKEM** uses an enlarged seed for generating the seed for sampling the secret and error matrices, and includes an additional salt in one of the hashing computations in encapsulation and decapsulation.
13 | These countermeasures safeguard standard **FrodoKEM** against some multi-ciphertext attacks. Refer to [3] for more details on these two variants.
14 |
15 | Concretely, this library includes the following KEM schemes using AES128 for the generation of the public matrix "A":
16 |
17 | * FrodoKEM-640-AES and eFrodoKEM-640-AES: matching the post-quantum security of AES128.
18 | * FrodoKEM-976-AES and eFrodoKEM-976-AES: matching the post-quantum security of AES192.
19 | * FrodoKEM-1344-AES and eFrodoKEM-1344-AES: matching the post-quantum security of AES256.
20 |
21 | And the following KEM schemes using SHAKE128 for the generation of the public matrix "A":
22 |
23 | * FrodoKEM-640-SHAKE and eFrodoKEM-640-SHAKE: matching the post-quantum security of AES128.
24 | * FrodoKEM-976-SHAKE and eFrodoKEM-976-SHAKE: matching the post-quantum security of AES192.
25 | * FrodoKEM-1344-SHAKE and eFrodoKEM-1344-SHAKE: matching the post-quantum security of AES256.
26 |
27 | The label "eFrodoKEM" corresponds to the ephemeral variants.
28 |
29 | The library was developed by the [FrodoKEM team](https://frodokem.org/#team) and [Microsoft Research](http://research.microsoft.com/) for experimentation purposes.
30 |
31 | ## Contents
32 |
33 | * [`eFrodoKEM` folder](eFrodoKEM/): C and Python3 implementations of eFrodoKEM.
34 | * [`FrodoKEM` folder](FrodoKEM/): C and Python3 implementations of standard FrodoKEM.
35 | * [`LICENSE`](LICENSE): MIT license file.
36 | * [`README.md`](README.md): this readme file.
37 |
38 | ## Supported Platforms
39 |
40 | The FrodoKEM library is supported on a wide range of platforms including x64, x86, ARM, PowerPC and s390x processors running Windows, Linux or macOS,
41 | and supports both little-endian and big-endian formats.
42 | We have tested the library with Microsoft Visual Studio, GNU GCC, and clang.
43 |
44 | ## License
45 |
46 | This software is licensed under the MIT License; see the LICENSE file for details.
47 | The Python3 implementation is licensed under the Creative Commons Zero v1.0 Universal license.
48 | It includes some third party modules that are licensed differently. In particular:
49 |
50 | - `/src/aes/aes_c.c`: public domain
51 | - `/src/aes/aes_ni.c`: public domain
52 | - `/src/sha3/fips202.c`: public domain
53 | - `/src/sha3/fips202x4.c`: public domain
54 | - `/src/sha3/keccak4x`: all files in this folder are public domain ([CC0](http://creativecommons.org/publicdomain/zero/1.0/)), excepting
55 | - `/src/sha3/keccak4x/brg_endian.h` which is copyrighted by Brian Gladman and comes with a BSD 3-clause license.
56 | - `/tests/ds_benchmark.h`: public domain
57 | - `/tests/PQCtestKAT_kem<#>.c`: copyrighted by Lawrence E. Bassham
58 | - `/tests/PQCtestKAT_kem<#>_shake.c`: copyrighted by Lawrence E. Bassham
59 | - `/tests/rng.c`: copyrighted by Lawrence E. Bassham
60 |
61 | # References
62 |
63 | [1] Erdem Alkim, Joppe W. Bos, Léo Ducas, Karen Easterbrook, Brian LaMacchia, Patrick Longa, Ilya Mironov, Michael Naehrig, Valeria Nikolaenko, Chris Peikert, Ananth Raghunathan, and Douglas Stebila,
64 | "FrodoKEM: Learning With Errors Key Encapsulation". Submission to the NIST Post-Quantum Standardization project, 2021-2023. The round 3 specification of FrodoKEM is available [`here`](https://frodokem.org/files/FrodoKEM-specification-20210604.pdf).
65 |
66 | [2] Joppe W. Bos, Craig Costello, Léo Ducas, Ilya Mironov, Michael Naehrig, Valeria Nikolaenko, Ananth Raghunathan, and Douglas Stebila,
67 | "Frodo: Take off the ring! Practical, quantum-secure key exchange from LWE".
68 | ACM CCS 2016, 2016. The preprint version is available [`here`](http://eprint.iacr.org/2016/659).
69 |
70 | [3] FrodoKEM team, "FrodoKEM: Learning With Errors Key Encapsulation - Preliminary Draft Standards". Submission to ISO/IEC JTC1/SC27/WG2, 2023. The preliminary draft is available [`here`](https://frodokem.org/files/FrodoKEM-ISO-20230314.pdf).
71 |
72 | # Contributing
73 |
74 | This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.
75 |
--------------------------------------------------------------------------------
/SECURITY.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | ## Security
4 |
5 | Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/Microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/).
6 |
7 | If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](https://aka.ms/opensource/security/definition), please report it to us as described below.
8 |
9 | ## Reporting Security Issues
10 |
11 | **Please do not report security vulnerabilities through public GitHub issues.**
12 |
13 | Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://aka.ms/opensource/security/create-report).
14 |
15 | If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://aka.ms/opensource/security/pgpkey).
16 |
17 | You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://aka.ms/opensource/security/msrc).
18 |
19 | Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue:
20 |
21 | * Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.)
22 | * Full paths of source file(s) related to the manifestation of the issue
23 | * The location of the affected source code (tag/branch/commit or direct URL)
24 | * Any special configuration required to reproduce the issue
25 | * Step-by-step instructions to reproduce the issue
26 | * Proof-of-concept or exploit code (if possible)
27 | * Impact of the issue, including how an attacker might exploit the issue
28 |
29 | This information will help us triage your report more quickly.
30 |
31 | If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://aka.ms/opensource/security/bounty) page for more details about our active programs.
32 |
33 | ## Preferred Languages
34 |
35 | We prefer all communications to be in English.
36 |
37 | ## Policy
38 |
39 | Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://aka.ms/opensource/security/cvd).
40 |
41 |
42 |
--------------------------------------------------------------------------------
/common/aes/aes.h:
--------------------------------------------------------------------------------
1 | /********************************************************************************************
2 | * Header defining the APIs for standalone AES
3 | *********************************************************************************************/
4 |
5 | #ifndef __AES_H
6 | #define __AES_H
7 |
8 | #include
9 | #include
10 |
11 |
12 | /**
13 | * Function to fill a key schedule given an initial key.
14 | *
15 | * @param key Initial Key.
16 | * @param schedule Abstract data structure for a key schedule.
17 | */
18 | void AES128_load_schedule(const uint8_t *key, uint8_t *schedule);
19 |
20 | /**
21 | * Same as AES128_ECB_enc() except a schedule generated by
22 | * AES128_load_schedule() is passed rather than a key. This is faster
23 | * if the same schedule is used for multiple encryptions since it does
24 | * not have to be regenerated from the key.
25 | */
26 | void AES128_ECB_enc_sch(const uint8_t *plaintext, const size_t plaintext_len, const uint8_t *schedule, uint8_t *ciphertext);
27 |
28 | /**
29 | * Function to free a key schedule.
30 | *
31 | * @param schedule Schedule generated with AES128_load_schedule().
32 | */
33 | void AES128_free_schedule(uint8_t *schedule);
34 |
35 | /**
36 | * Function to fill a key schedule given an initial key.
37 | *
38 | * @param key Initial Key.
39 | * @param schedule Abstract data structure for a key schedule.
40 | */
41 | void AES256_load_schedule(const uint8_t *key, uint8_t *schedule);
42 |
43 | /**
44 | * Same as AES256_ECB_enc() except a schedule generated by
45 | * AES256_load_schedule() is passed rather than a key. This is faster
46 | * if the same schedule is used for multiple encryptions since it does
47 | * not have to be regenerated from the key.
48 | */
49 | void AES256_ECB_enc_sch(const uint8_t *plaintext, const size_t plaintext_len, const uint8_t *schedule, uint8_t *ciphertext);
50 |
51 | /**
52 | * Function to free a key schedule.
53 | *
54 | * @param schedule Schedule generated with AES256_load_schedule().
55 | */
56 | void AES256_free_schedule(uint8_t *schedule);
57 |
58 |
59 | #endif
60 |
--------------------------------------------------------------------------------
/common/aes/aes_ni.c:
--------------------------------------------------------------------------------
1 | // Public domain AES implementation using AES-NI instructions
2 | //
3 | // This version includes AES128 and AES256, and only implements encryption.
4 |
5 | #include
6 | #include
7 | #include
8 | #include "aes.h"
9 |
10 |
11 | static __m128i key_expand(__m128i key, __m128i keygened) {
12 | key = _mm_xor_si128(key, _mm_slli_si128(key, 4));
13 | key = _mm_xor_si128(key, _mm_slli_si128(key, 4));
14 | key = _mm_xor_si128(key, _mm_slli_si128(key, 4));
15 | keygened = _mm_shuffle_epi32(keygened, _MM_SHUFFLE(3, 3, 3, 3));
16 | return _mm_xor_si128(key, keygened);
17 | }
18 |
19 |
20 | static __m128i key_expand1(__m128i key, __m128i keygened) {
21 | key = _mm_xor_si128(key, _mm_slli_si128(key, 4));
22 | key = _mm_xor_si128(key, _mm_slli_si128(key, 4));
23 | key = _mm_xor_si128(key, _mm_slli_si128(key, 4));
24 | keygened = _mm_shuffle_epi32(keygened, _MM_SHUFFLE(2, 2, 2, 2));
25 | return _mm_xor_si128(key, keygened);
26 | }
27 |
28 |
29 | #define key_exp(k, rcon) key_expand(k, _mm_aeskeygenassist_si128(k, rcon))
30 | #define key_exp256(k, r, rcon) key_expand(k, _mm_aeskeygenassist_si128(r, rcon))
31 | #define key_exp256b(k, r, rcon) key_expand1(k, _mm_aeskeygenassist_si128(r, rcon))
32 |
33 | void AES128_load_schedule(const uint8_t *key, uint8_t *_schedule) {
34 | __m128i *schedule = (__m128i *) _schedule;
35 | schedule[0] = _mm_loadu_si128((const __m128i *) key);
36 | schedule[1] = key_exp(schedule[0], 0x01);
37 | schedule[2] = key_exp(schedule[1], 0x02);
38 | schedule[3] = key_exp(schedule[2], 0x04);
39 | schedule[4] = key_exp(schedule[3], 0x08);
40 | schedule[5] = key_exp(schedule[4], 0x10);
41 | schedule[6] = key_exp(schedule[5], 0x20);
42 | schedule[7] = key_exp(schedule[6], 0x40);
43 | schedule[8] = key_exp(schedule[7], 0x80);
44 | schedule[9] = key_exp(schedule[8], 0x1b);
45 | schedule[10] = key_exp(schedule[9], 0x36);
46 | }
47 |
48 |
49 | void AES256_load_schedule(const uint8_t *key, uint8_t *_schedule) {
50 | __m128i *schedule = (__m128i *) _schedule;
51 | schedule[0] = _mm_loadu_si128((const __m128i *) key);
52 | schedule[1] = _mm_loadu_si128((const __m128i *) (key+16));
53 | schedule[2] = key_exp256(schedule[0], schedule[1], 0x01);
54 | schedule[3] = key_exp256b(schedule[1], schedule[2], 0x00);
55 | schedule[4] = key_exp256(schedule[2], schedule[3], 0x02);
56 | schedule[5] = key_exp256b(schedule[3], schedule[4], 0x00);
57 | schedule[6] = key_exp256(schedule[4], schedule[5], 0x04);
58 | schedule[7] = key_exp256b(schedule[5], schedule[6], 0x00);
59 | schedule[8] = key_exp256(schedule[6], schedule[7], 0x08);
60 | schedule[9] = key_exp256b(schedule[7], schedule[8], 0x00);
61 | schedule[10] = key_exp256(schedule[8], schedule[9], 0x10);
62 | schedule[11] = key_exp256b(schedule[9], schedule[10], 0x00);
63 | schedule[12] = key_exp256(schedule[10], schedule[11], 0x20);
64 | schedule[13] = key_exp256b(schedule[11], schedule[12], 0x00);
65 | schedule[14] = key_exp256(schedule[12], schedule[13], 0x40);
66 | }
67 |
68 |
69 | static inline void aes128_enc(const uint8_t *plaintext, const uint8_t *_schedule, uint8_t *ciphertext) {
70 | __m128i *schedule = (__m128i *) _schedule;
71 | __m128i m = _mm_loadu_si128((__m128i *) plaintext);
72 |
73 | m = _mm_xor_si128(m, schedule[0]);
74 | for (size_t i = 1; i < 10; i++) {
75 | m = _mm_aesenc_si128(m, schedule[i]);
76 | }
77 | m = _mm_aesenclast_si128(m, schedule[10]);
78 |
79 | _mm_storeu_si128((__m128i *) ciphertext, m);
80 | }
81 |
82 |
83 | static inline void aes256_enc(const uint8_t *plaintext, const uint8_t *_schedule, uint8_t *ciphertext) {
84 | __m128i *schedule = (__m128i *) _schedule;
85 | __m128i m = _mm_loadu_si128((__m128i *) plaintext);
86 |
87 | m = _mm_xor_si128(m, schedule[0]);
88 | for (size_t i = 1; i < 14; i++) {
89 | m = _mm_aesenc_si128(m, schedule[i]);
90 | }
91 | m = _mm_aesenclast_si128(m, schedule[14]);
92 |
93 | _mm_storeu_si128((__m128i *) ciphertext, m);
94 | }
95 |
96 |
97 | void AES128_ECB_enc_sch(const uint8_t* plaintext, const size_t plaintext_len, const uint8_t* schedule, uint8_t* ciphertext) {
98 | assert(plaintext_len % 16 == 0);
99 | for (size_t block = 0; block < plaintext_len / 16; block++) {
100 | aes128_enc(plaintext + (16 * block), schedule, ciphertext + (16 * block));
101 | }
102 | }
103 |
104 |
105 | void AES256_ECB_enc_sch(const uint8_t* plaintext, const size_t plaintext_len, const uint8_t* schedule, uint8_t* ciphertext) {
106 | assert(plaintext_len % 16 == 0);
107 | for (size_t block = 0; block < plaintext_len / 16; block++) {
108 | aes256_enc(plaintext + (16 * block), schedule, ciphertext + (16 * block));
109 | }
110 | }
111 |
112 |
113 | void AES128_free_schedule(uint8_t* schedule) {
114 | memset(schedule, 0, 16 * 11);
115 | }
116 |
117 |
118 | void AES256_free_schedule(uint8_t* schedule) {
119 | memset(schedule, 0, 16 * 15);
120 | }
121 |
--------------------------------------------------------------------------------
/common/aes/aes_openssl.c:
--------------------------------------------------------------------------------
1 | /********************************************************************************************
2 | * Functions for OpenSSL's AES implementation
3 | *********************************************************************************************/
4 |
5 | #include "aes_openssl.h"
6 |
7 |
8 | void handleErrors(void)
9 | {
10 | ERR_print_errors_fp(stderr);
11 | abort();
12 | }
13 |
14 |
15 | void AES128_free_schedule(EVP_CIPHER_CTX *schedule) {
16 | EVP_CIPHER_CTX_free(schedule);
17 | }
18 |
19 |
20 | void AES256_free_schedule(EVP_CIPHER_CTX *schedule) {
21 | EVP_CIPHER_CTX_free(schedule);
22 | }
23 |
--------------------------------------------------------------------------------
/common/aes/aes_openssl.h:
--------------------------------------------------------------------------------
1 | /********************************************************************************************
2 | * Header defining the APIs for OpenSSL's AES implementation
3 | *********************************************************************************************/
4 |
5 | #ifndef __AES_OPENSSL_H
6 | #define __AES_OPENSSL_H
7 |
8 | #include
9 | #include
10 | #include
11 | #include
12 |
13 |
14 | void handleErrors(void);
15 | void AES128_free_schedule(EVP_CIPHER_CTX *schedule);
16 | void AES256_free_schedule(EVP_CIPHER_CTX *schedule);
17 |
18 |
19 | #endif
20 |
--------------------------------------------------------------------------------
/common/random/random.c:
--------------------------------------------------------------------------------
1 | /********************************************************************************************
2 | * Hardware-based random number generation function
3 | *
4 | * It uses /dev/urandom in Unix-like OSs and CNG's BCryptGenRandom function in Windows
5 | *********************************************************************************************/
6 |
7 | #include "random.h"
8 | #include
9 | #if defined(WINDOWS)
10 | #include
11 | #include
12 | #elif defined(NIX)
13 | #include
14 | #include
15 | static int lock = -1;
16 | #endif
17 |
18 | #define passed 0
19 | #define failed 1
20 |
21 |
22 | int randombytes(unsigned char* random_array, unsigned long long nbytes)
23 | { // Generation of "nbytes" of random values
24 |
25 | #if defined(WINDOWS)
26 | if (!BCRYPT_SUCCESS(BCryptGenRandom(NULL, random_array, (unsigned long)nbytes, BCRYPT_USE_SYSTEM_PREFERRED_RNG))) {
27 | return failed;
28 | }
29 |
30 | #elif defined(NIX)
31 | int r, n = (int)nbytes, count = 0;
32 |
33 | if (lock == -1) {
34 | do {
35 | lock = open("/dev/urandom", O_RDONLY);
36 | if (lock == -1) {
37 | sleep(1);
38 | }
39 | } while (lock == -1);
40 | }
41 |
42 | while (n > 0) {
43 | do {
44 | r = read(lock, random_array+count, n);
45 | if (r == -1) {
46 | sleep(1);
47 | }
48 | } while (r == -1);
49 | count += r;
50 | n -= r;
51 | }
52 | #endif
53 |
54 | return passed;
55 | }
--------------------------------------------------------------------------------
/common/random/random.h:
--------------------------------------------------------------------------------
1 | #ifndef __RANDOM_H__
2 | #define __RANDOM_H__
3 |
4 |
5 | // Generate random bytes and output the result to random_array
6 | int randombytes(unsigned char* random_array, unsigned long long nbytes);
7 |
8 |
9 | #endif
--------------------------------------------------------------------------------
/common/sha3/fips202.h:
--------------------------------------------------------------------------------
1 | #ifndef FIPS202_H
2 | #define FIPS202_H
3 |
4 | #include
5 |
6 |
7 | #define SHAKE128_RATE 168
8 | #define SHAKE256_RATE 136
9 |
10 | void shake128_absorb(uint64_t *s, const unsigned char *input, unsigned int inputByteLen);
11 | void shake128_squeezeblocks(unsigned char *output, unsigned long long nblocks, uint64_t *s);
12 | void shake128(unsigned char *output, unsigned long long outlen, const unsigned char *input, unsigned long long inlen);
13 |
14 | void shake256_absorb(uint64_t *s, const unsigned char *input, unsigned int inputByteLen);
15 | void shake256_squeezeblocks(unsigned char *output, unsigned long long nblocks, uint64_t *s);
16 | void shake256(unsigned char *output, unsigned long long outlen, const unsigned char *input, unsigned long long inlen);
17 |
18 |
19 | #endif
20 |
--------------------------------------------------------------------------------
/common/sha3/fips202x4.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include "fips202.h"
5 |
6 | #define NROUNDS 24
7 | #define ROL(a, offset) ((a << offset) ^ (a >> (64-offset)))
8 |
9 |
10 | static uint64_t load64(const unsigned char *x)
11 | {
12 | unsigned long long r = 0, i;
13 |
14 | for (i = 0; i < 8; ++i) {
15 | r |= (unsigned long long)x[i] << 8 * i;
16 | }
17 | return r;
18 | }
19 |
20 |
21 | static void store64(uint8_t *x, uint64_t u)
22 | {
23 | unsigned int i;
24 |
25 | for (i = 0; i < 8; ++i) {
26 | x[i] = u;
27 | u >>= 8;
28 | }
29 | }
30 |
31 |
32 | /* Use implementation from the Keccak Code Package */
33 | extern void KeccakP1600times4_PermuteAll_24rounds(__m256i *s);
34 | #define KeccakF1600_StatePermute4x KeccakP1600times4_PermuteAll_24rounds
35 |
36 |
37 | static void keccak_absorb4x(__m256i *s, unsigned int r, const unsigned char *m0, const unsigned char *m1, const unsigned char *m2, const unsigned char *m3,
38 | unsigned long long int mlen, unsigned char p)
39 | {
40 | unsigned long long i;
41 | unsigned char t0[200];
42 | unsigned char t1[200];
43 | unsigned char t2[200];
44 | unsigned char t3[200];
45 | unsigned long long *ss = (unsigned long long *)s;
46 |
47 | while (mlen >= r)
48 | {
49 | for (i = 0; i < r / 8; ++i)
50 | {
51 | ss[4*i+0] ^= load64(m0 + 8 * i);
52 | ss[4*i+1] ^= load64(m1 + 8 * i);
53 | ss[4*i+2] ^= load64(m2 + 8 * i);
54 | ss[4*i+3] ^= load64(m3 + 8 * i);
55 | }
56 |
57 | KeccakF1600_StatePermute4x(s);
58 | mlen -= r;
59 | m0 += r;
60 | m1 += r;
61 | m2 += r;
62 | m3 += r;
63 | }
64 |
65 | for (i = 0; i < r; ++i)
66 | {
67 | t0[i] = 0;
68 | t1[i] = 0;
69 | t2[i] = 0;
70 | t3[i] = 0;
71 | }
72 | for (i = 0; i < mlen; ++i)
73 | {
74 | t0[i] = m0[i];
75 | t1[i] = m1[i];
76 | t2[i] = m2[i];
77 | t3[i] = m3[i];
78 | }
79 |
80 | t0[i] = p;
81 | t1[i] = p;
82 | t2[i] = p;
83 | t3[i] = p;
84 |
85 | t0[r - 1] |= 128;
86 | t1[r - 1] |= 128;
87 | t2[r - 1] |= 128;
88 | t3[r - 1] |= 128;
89 |
90 | for (i = 0; i < r / 8; ++i)
91 | {
92 | ss[4*i+0] ^= load64(t0 + 8 * i);
93 | ss[4*i+1] ^= load64(t1 + 8 * i);
94 | ss[4*i+2] ^= load64(t2 + 8 * i);
95 | ss[4*i+3] ^= load64(t3 + 8 * i);
96 | }
97 | }
98 |
99 |
100 | static void keccak_squeezeblocks4x(unsigned char *h0, unsigned char *h1, unsigned char *h2, unsigned char *h3, unsigned long long int nblocks, __m256i *s, unsigned int r)
101 | {
102 | unsigned int i;
103 | unsigned long long *ss = (unsigned long long *)s;
104 |
105 | while (nblocks > 0)
106 | {
107 | KeccakF1600_StatePermute4x(s);
108 | for (i = 0; i < (r>>3); i++)
109 | {
110 | store64(h0+8*i, ss[4*i+0]);
111 | store64(h1+8*i, ss[4*i+1]);
112 | store64(h2+8*i, ss[4*i+2]);
113 | store64(h3+8*i, ss[4*i+3]);
114 | }
115 | h0 += r;
116 | h1 += r;
117 | h2 += r;
118 | h3 += r;
119 | nblocks--;
120 | }
121 | }
122 |
123 |
124 | /********** SHAKE128 ***********/
125 |
126 | void shake128_absorb4x(__m256i *s, const unsigned char *in0, const unsigned char *in1, const unsigned char *in2, const unsigned char *in3, unsigned long long inlen)
127 | {
128 | unsigned int i;
129 |
130 | for (i = 0; i < 25; i++)
131 | s[i] = _mm256_xor_si256(s[i], s[i]); // zero state
132 |
133 | /* Absorb input */
134 | keccak_absorb4x(s, SHAKE128_RATE, in0, in1, in2, in3, inlen, 0x1F);
135 | }
136 |
137 |
138 | void shake128_squeezeblocks4x(unsigned char *output0, unsigned char *output1, unsigned char *output2, unsigned char *output3, unsigned long long outlen, __m256i *s)
139 | {
140 | keccak_squeezeblocks4x(output0, output1, output2, output3, outlen/SHAKE128_RATE, s, SHAKE128_RATE);
141 | }
142 |
143 |
144 | /* N is assumed to be empty; S is assumed to have at most 2 characters */
145 | void shake128_4x(unsigned char *output0, unsigned char *output1, unsigned char *output2, unsigned char *output3, unsigned long long outlen,
146 | const unsigned char *in0, const unsigned char *in1, const unsigned char *in2, const unsigned char *in3, unsigned long long inlen)
147 | {
148 | __m256i s[25];
149 | unsigned char t0[SHAKE128_RATE];
150 | unsigned char t1[SHAKE128_RATE];
151 | unsigned char t2[SHAKE128_RATE];
152 | unsigned char t3[SHAKE128_RATE];
153 | unsigned int i;
154 |
155 | shake128_absorb4x(s, in0, in1, in2, in3, inlen);
156 |
157 | /* Squeeze output */
158 | keccak_squeezeblocks4x(output0, output1, output2, output3, outlen/SHAKE128_RATE, s, SHAKE128_RATE);
159 | output0 += (outlen/SHAKE128_RATE)*SHAKE128_RATE;
160 | output1 += (outlen/SHAKE128_RATE)*SHAKE128_RATE;
161 | output2 += (outlen/SHAKE128_RATE)*SHAKE128_RATE;
162 | output3 += (outlen/SHAKE128_RATE)*SHAKE128_RATE;
163 |
164 | if (outlen%SHAKE128_RATE)
165 | {
166 | keccak_squeezeblocks4x(t0, t1, t2, t3, 1, s, SHAKE128_RATE);
167 | for (i = 0; i < outlen%SHAKE128_RATE; i++)
168 | {
169 | output0[i] = t0[i];
170 | output1[i] = t1[i];
171 | output2[i] = t2[i];
172 | output3[i] = t3[i];
173 | }
174 | }
175 | }
176 |
--------------------------------------------------------------------------------
/common/sha3/fips202x4.h:
--------------------------------------------------------------------------------
1 | #ifndef FIPS202X4_H
2 | #define FIPS202X4_H
3 |
4 | #include
5 |
6 | void shake128_absorb4x(__m256i *s, const unsigned char *in0, const unsigned char *in1, const unsigned char *in2, const unsigned char *in3, unsigned long long inlen);
7 |
8 | void shake128_squeezeblocks4x(unsigned char *output0, unsigned char *output1, unsigned char *output2, unsigned char *output3, unsigned long long outlen, __m256i *s);
9 |
10 | /* N is assumed to be empty; S is assumed to have at most 2 characters */
11 | void shake128_4x(unsigned char *output0, unsigned char *output1, unsigned char *output2, unsigned char *output3, unsigned long long outlen,
12 | const unsigned char *in0, const unsigned char *in1, const unsigned char *in2, const unsigned char *in3, unsigned long long inlen);
13 |
14 | #endif
15 |
--------------------------------------------------------------------------------
/common/sha3/keccak4x/KeccakP-1600-times4-SnP.h:
--------------------------------------------------------------------------------
1 | /*
2 | Implementation by the Keccak, Keyak and Ketje Teams, namely, Guido Bertoni,
3 | Joan Daemen, Michaël Peeters, Gilles Van Assche and Ronny Van Keer, hereby
4 | denoted as "the implementer".
5 |
6 | For more information, feedback or questions, please refer to our websites:
7 | http://keccak.noekeon.org/
8 | http://keyak.noekeon.org/
9 | http://ketje.noekeon.org/
10 |
11 | To the extent possible under law, the implementer has waived all copyright
12 | and related or neighboring rights to the source code in this file.
13 | http://creativecommons.org/publicdomain/zero/1.0/
14 | */
15 |
16 | #ifndef _KeccakP_1600_times4_SnP_h_
17 | #define _KeccakP_1600_times4_SnP_h_
18 |
19 | /** For the documentation, see PlSnP-documentation.h.
20 | */
21 |
22 | #include "SIMD256-config.h"
23 |
24 | #define KeccakP1600times4_implementation "256-bit SIMD implementation (" KeccakP1600times4_implementation_config ")"
25 | #define KeccakP1600times4_statesSizeInBytes 800
26 | #define KeccakP1600times4_statesAlignment 32
27 | #define KeccakF1600times4_FastLoop_supported
28 | #define KeccakP1600times4_12rounds_FastLoop_supported
29 |
30 | #include
31 |
32 | #define KeccakP1600times4_StaticInitialize()
33 | void KeccakP1600times4_InitializeAll(void *states);
34 | #define KeccakP1600times4_AddByte(states, instanceIndex, byte, offset) \
35 | ((unsigned char*)(states))[(instanceIndex)*8 + ((offset)/8)*4*8 + (offset)%8] ^= (byte)
36 | void KeccakP1600times4_AddBytes(void *states, unsigned int instanceIndex, const unsigned char *data, unsigned int offset, unsigned int length);
37 | void KeccakP1600times4_AddLanesAll(void *states, const unsigned char *data, unsigned int laneCount, unsigned int laneOffset);
38 | void KeccakP1600times4_OverwriteBytes(void *states, unsigned int instanceIndex, const unsigned char *data, unsigned int offset, unsigned int length);
39 | void KeccakP1600times4_OverwriteLanesAll(void *states, const unsigned char *data, unsigned int laneCount, unsigned int laneOffset);
40 | void KeccakP1600times4_OverwriteWithZeroes(void *states, unsigned int instanceIndex, unsigned int byteCount);
41 | void KeccakP1600times4_PermuteAll_12rounds(void *states);
42 | void KeccakP1600times4_PermuteAll_24rounds(void *states);
43 | void KeccakP1600times4_ExtractBytes(const void *states, unsigned int instanceIndex, unsigned char *data, unsigned int offset, unsigned int length);
44 | void KeccakP1600times4_ExtractLanesAll(const void *states, unsigned char *data, unsigned int laneCount, unsigned int laneOffset);
45 | void KeccakP1600times4_ExtractAndAddBytes(const void *states, unsigned int instanceIndex, const unsigned char *input, unsigned char *output, unsigned int offset, unsigned int length);
46 | void KeccakP1600times4_ExtractAndAddLanesAll(const void *states, const unsigned char *input, unsigned char *output, unsigned int laneCount, unsigned int laneOffset);
47 | size_t KeccakF1600times4_FastLoop_Absorb(void *states, unsigned int laneCount, unsigned int laneOffsetParallel, unsigned int laneOffsetSerial, const unsigned char *data, size_t dataByteLen);
48 | size_t KeccakP1600times4_12rounds_FastLoop_Absorb(void *states, unsigned int laneCount, unsigned int laneOffsetParallel, unsigned int laneOffsetSerial, const unsigned char *data, size_t dataByteLen);
49 |
50 | #endif
51 |
--------------------------------------------------------------------------------
/common/sha3/keccak4x/KeccakP-1600-unrolling.macros:
--------------------------------------------------------------------------------
1 | /*
2 | Implementation by the Keccak, Keyak and Ketje Teams, namely, Guido Bertoni,
3 | Joan Daemen, Michaël Peeters, Gilles Van Assche and Ronny Van Keer, hereby
4 | denoted as "the implementer".
5 |
6 | For more information, feedback or questions, please refer to our websites:
7 | http://keccak.noekeon.org/
8 | http://keyak.noekeon.org/
9 | http://ketje.noekeon.org/
10 |
11 | To the extent possible under law, the implementer has waived all copyright
12 | and related or neighboring rights to the source code in this file.
13 | http://creativecommons.org/publicdomain/zero/1.0/
14 | */
15 |
16 | #if (defined(FullUnrolling))
17 | #define rounds24 \
18 | prepareTheta \
19 | thetaRhoPiChiIotaPrepareTheta( 0, A, E) \
20 | thetaRhoPiChiIotaPrepareTheta( 1, E, A) \
21 | thetaRhoPiChiIotaPrepareTheta( 2, A, E) \
22 | thetaRhoPiChiIotaPrepareTheta( 3, E, A) \
23 | thetaRhoPiChiIotaPrepareTheta( 4, A, E) \
24 | thetaRhoPiChiIotaPrepareTheta( 5, E, A) \
25 | thetaRhoPiChiIotaPrepareTheta( 6, A, E) \
26 | thetaRhoPiChiIotaPrepareTheta( 7, E, A) \
27 | thetaRhoPiChiIotaPrepareTheta( 8, A, E) \
28 | thetaRhoPiChiIotaPrepareTheta( 9, E, A) \
29 | thetaRhoPiChiIotaPrepareTheta(10, A, E) \
30 | thetaRhoPiChiIotaPrepareTheta(11, E, A) \
31 | thetaRhoPiChiIotaPrepareTheta(12, A, E) \
32 | thetaRhoPiChiIotaPrepareTheta(13, E, A) \
33 | thetaRhoPiChiIotaPrepareTheta(14, A, E) \
34 | thetaRhoPiChiIotaPrepareTheta(15, E, A) \
35 | thetaRhoPiChiIotaPrepareTheta(16, A, E) \
36 | thetaRhoPiChiIotaPrepareTheta(17, E, A) \
37 | thetaRhoPiChiIotaPrepareTheta(18, A, E) \
38 | thetaRhoPiChiIotaPrepareTheta(19, E, A) \
39 | thetaRhoPiChiIotaPrepareTheta(20, A, E) \
40 | thetaRhoPiChiIotaPrepareTheta(21, E, A) \
41 | thetaRhoPiChiIotaPrepareTheta(22, A, E) \
42 | thetaRhoPiChiIota(23, E, A) \
43 |
44 | #define rounds12 \
45 | prepareTheta \
46 | thetaRhoPiChiIotaPrepareTheta(12, A, E) \
47 | thetaRhoPiChiIotaPrepareTheta(13, E, A) \
48 | thetaRhoPiChiIotaPrepareTheta(14, A, E) \
49 | thetaRhoPiChiIotaPrepareTheta(15, E, A) \
50 | thetaRhoPiChiIotaPrepareTheta(16, A, E) \
51 | thetaRhoPiChiIotaPrepareTheta(17, E, A) \
52 | thetaRhoPiChiIotaPrepareTheta(18, A, E) \
53 | thetaRhoPiChiIotaPrepareTheta(19, E, A) \
54 | thetaRhoPiChiIotaPrepareTheta(20, A, E) \
55 | thetaRhoPiChiIotaPrepareTheta(21, E, A) \
56 | thetaRhoPiChiIotaPrepareTheta(22, A, E) \
57 | thetaRhoPiChiIota(23, E, A) \
58 |
59 | #elif (Unrolling == 12)
60 | #define rounds24 \
61 | prepareTheta \
62 | for(i=0; i<24; i+=12) { \
63 | thetaRhoPiChiIotaPrepareTheta(i , A, E) \
64 | thetaRhoPiChiIotaPrepareTheta(i+ 1, E, A) \
65 | thetaRhoPiChiIotaPrepareTheta(i+ 2, A, E) \
66 | thetaRhoPiChiIotaPrepareTheta(i+ 3, E, A) \
67 | thetaRhoPiChiIotaPrepareTheta(i+ 4, A, E) \
68 | thetaRhoPiChiIotaPrepareTheta(i+ 5, E, A) \
69 | thetaRhoPiChiIotaPrepareTheta(i+ 6, A, E) \
70 | thetaRhoPiChiIotaPrepareTheta(i+ 7, E, A) \
71 | thetaRhoPiChiIotaPrepareTheta(i+ 8, A, E) \
72 | thetaRhoPiChiIotaPrepareTheta(i+ 9, E, A) \
73 | thetaRhoPiChiIotaPrepareTheta(i+10, A, E) \
74 | thetaRhoPiChiIotaPrepareTheta(i+11, E, A) \
75 | } \
76 |
77 | #define rounds12 \
78 | prepareTheta \
79 | thetaRhoPiChiIotaPrepareTheta(12, A, E) \
80 | thetaRhoPiChiIotaPrepareTheta(13, E, A) \
81 | thetaRhoPiChiIotaPrepareTheta(14, A, E) \
82 | thetaRhoPiChiIotaPrepareTheta(15, E, A) \
83 | thetaRhoPiChiIotaPrepareTheta(16, A, E) \
84 | thetaRhoPiChiIotaPrepareTheta(17, E, A) \
85 | thetaRhoPiChiIotaPrepareTheta(18, A, E) \
86 | thetaRhoPiChiIotaPrepareTheta(19, E, A) \
87 | thetaRhoPiChiIotaPrepareTheta(20, A, E) \
88 | thetaRhoPiChiIotaPrepareTheta(21, E, A) \
89 | thetaRhoPiChiIotaPrepareTheta(22, A, E) \
90 | thetaRhoPiChiIota(23, E, A) \
91 |
92 | #elif (Unrolling == 6)
93 | #define rounds24 \
94 | prepareTheta \
95 | for(i=0; i<24; i+=6) { \
96 | thetaRhoPiChiIotaPrepareTheta(i , A, E) \
97 | thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \
98 | thetaRhoPiChiIotaPrepareTheta(i+2, A, E) \
99 | thetaRhoPiChiIotaPrepareTheta(i+3, E, A) \
100 | thetaRhoPiChiIotaPrepareTheta(i+4, A, E) \
101 | thetaRhoPiChiIotaPrepareTheta(i+5, E, A) \
102 | } \
103 |
104 | #define rounds12 \
105 | prepareTheta \
106 | for(i=12; i<24; i+=6) { \
107 | thetaRhoPiChiIotaPrepareTheta(i , A, E) \
108 | thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \
109 | thetaRhoPiChiIotaPrepareTheta(i+2, A, E) \
110 | thetaRhoPiChiIotaPrepareTheta(i+3, E, A) \
111 | thetaRhoPiChiIotaPrepareTheta(i+4, A, E) \
112 | thetaRhoPiChiIotaPrepareTheta(i+5, E, A) \
113 | } \
114 |
115 | #elif (Unrolling == 4)
116 | #define rounds24 \
117 | prepareTheta \
118 | for(i=0; i<24; i+=4) { \
119 | thetaRhoPiChiIotaPrepareTheta(i , A, E) \
120 | thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \
121 | thetaRhoPiChiIotaPrepareTheta(i+2, A, E) \
122 | thetaRhoPiChiIotaPrepareTheta(i+3, E, A) \
123 | } \
124 |
125 | #define rounds12 \
126 | prepareTheta \
127 | for(i=12; i<24; i+=4) { \
128 | thetaRhoPiChiIotaPrepareTheta(i , A, E) \
129 | thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \
130 | thetaRhoPiChiIotaPrepareTheta(i+2, A, E) \
131 | thetaRhoPiChiIotaPrepareTheta(i+3, E, A) \
132 | } \
133 |
134 | #elif (Unrolling == 3)
135 | #define rounds24 \
136 | prepareTheta \
137 | for(i=0; i<24; i+=3) { \
138 | thetaRhoPiChiIotaPrepareTheta(i , A, E) \
139 | thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \
140 | thetaRhoPiChiIotaPrepareTheta(i+2, A, E) \
141 | copyStateVariables(A, E) \
142 | } \
143 |
144 | #define rounds12 \
145 | prepareTheta \
146 | for(i=12; i<24; i+=3) { \
147 | thetaRhoPiChiIotaPrepareTheta(i , A, E) \
148 | thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \
149 | thetaRhoPiChiIotaPrepareTheta(i+2, A, E) \
150 | copyStateVariables(A, E) \
151 | } \
152 |
153 | #elif (Unrolling == 2)
154 | #define rounds24 \
155 | prepareTheta \
156 | for(i=0; i<24; i+=2) { \
157 | thetaRhoPiChiIotaPrepareTheta(i , A, E) \
158 | thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \
159 | } \
160 |
161 | #define rounds12 \
162 | prepareTheta \
163 | for(i=12; i<24; i+=2) { \
164 | thetaRhoPiChiIotaPrepareTheta(i , A, E) \
165 | thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \
166 | } \
167 |
168 | #elif (Unrolling == 1)
169 | #define rounds24 \
170 | prepareTheta \
171 | for(i=0; i<24; i++) { \
172 | thetaRhoPiChiIotaPrepareTheta(i , A, E) \
173 | copyStateVariables(A, E) \
174 | } \
175 |
176 | #define rounds12 \
177 | prepareTheta \
178 | for(i=12; i<24; i++) { \
179 | thetaRhoPiChiIotaPrepareTheta(i , A, E) \
180 | copyStateVariables(A, E) \
181 | } \
182 |
183 | #else
184 | #error "Unrolling is not correctly specified!"
185 | #endif
186 |
187 | #define roundsN(__nrounds) \
188 | prepareTheta \
189 | i = 24 - (__nrounds); \
190 | if ((i&1) != 0) { \
191 | thetaRhoPiChiIotaPrepareTheta(i, A, E) \
192 | copyStateVariables(A, E) \
193 | ++i; \
194 | } \
195 | for( /* empty */; i<24; i+=2) { \
196 | thetaRhoPiChiIotaPrepareTheta(i , A, E) \
197 | thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \
198 | }
199 |
--------------------------------------------------------------------------------
/common/sha3/keccak4x/SIMD256-config.h:
--------------------------------------------------------------------------------
1 | #define KeccakP1600times4_implementation_config "AVX2, all rounds unrolled"
2 | #define KeccakP1600times4_fullUnrolling
3 | #define KeccakP1600times4_useAVX2
4 |
--------------------------------------------------------------------------------
/common/sha3/keccak4x/align.h:
--------------------------------------------------------------------------------
1 | /*
2 | Implementation by the Keccak, Keyak and Ketje Teams, namely, Guido Bertoni,
3 | Joan Daemen, Michaël Peeters, Gilles Van Assche and Ronny Van Keer, hereby
4 | denoted as "the implementer".
5 |
6 | For more information, feedback or questions, please refer to our websites:
7 | http://keccak.noekeon.org/
8 | http://keyak.noekeon.org/
9 | http://ketje.noekeon.org/
10 |
11 | To the extent possible under law, the implementer has waived all copyright
12 | and related or neighboring rights to the source code in this file.
13 | http://creativecommons.org/publicdomain/zero/1.0/
14 | */
15 |
16 | #ifndef _align_h_
17 | #define _align_h_
18 |
19 | /* on Mac OS-X and possibly others, ALIGN(x) is defined in param.h, and -Werror chokes on the redef. */
20 | #ifdef ALIGN
21 | #undef ALIGN
22 | #endif
23 |
24 | #if defined(__GNUC__)
25 | #define ALIGN(x) __attribute__ ((aligned(x)))
26 | #elif defined(_MSC_VER)
27 | #define ALIGN(x) __declspec(align(x))
28 | #elif defined(__ARMCC_VERSION)
29 | #define ALIGN(x) __align(x)
30 | #else
31 | #define ALIGN(x)
32 | #endif
33 |
34 | #endif
35 |
--------------------------------------------------------------------------------
/common/sha3/keccak4x/brg_endian.h:
--------------------------------------------------------------------------------
1 | /*
2 | ---------------------------------------------------------------------------
3 | Copyright (c) 1998-2008, Brian Gladman, Worcester, UK. All rights reserved.
4 |
5 | LICENSE TERMS
6 |
7 | The redistribution and use of this software (with or without changes)
8 | is allowed without the payment of fees or royalties provided that:
9 |
10 | 1. source code distributions include the above copyright notice, this
11 | list of conditions and the following disclaimer;
12 |
13 | 2. binary distributions include the above copyright notice, this list
14 | of conditions and the following disclaimer in their documentation;
15 |
16 | 3. the name of the copyright holder is not used to endorse products
17 | built using this software without specific written permission.
18 |
19 | DISCLAIMER
20 |
21 | This software is provided 'as is' with no explicit or implied warranties
22 | in respect of its properties, including, but not limited to, correctness
23 | and/or fitness for purpose.
24 | ---------------------------------------------------------------------------
25 | Issue Date: 20/12/2007
26 | Changes for ARM 9/9/2010
27 | */
28 |
29 | #ifndef _BRG_ENDIAN_H
30 | #define _BRG_ENDIAN_H
31 |
32 | #define IS_BIG_ENDIAN 4321 /* byte 0 is most significant (mc68k) */
33 | #define IS_LITTLE_ENDIAN 1234 /* byte 0 is least significant (i386) */
34 |
35 | #if 0
36 | /* Include files where endian defines and byteswap functions may reside */
37 | #if defined( __sun )
38 | # include
39 | #elif defined( __FreeBSD__ ) || defined( __OpenBSD__ ) || defined( __NetBSD__ )
40 | # include
41 | #elif defined( BSD ) && ( BSD >= 199103 ) || defined( __APPLE__ ) || \
42 | defined( __CYGWIN32__ ) || defined( __DJGPP__ ) || defined( __osf__ )
43 | # include
44 | #elif defined( __linux__ ) || defined( __GNUC__ ) || defined( __GNU_LIBRARY__ )
45 | # if !defined( __MINGW32__ ) && !defined( _AIX )
46 | # include
47 | # if !defined( __BEOS__ )
48 | # include
49 | # endif
50 | # endif
51 | #endif
52 | #endif
53 |
54 | /* Now attempt to set the define for platform byte order using any */
55 | /* of the four forms SYMBOL, _SYMBOL, __SYMBOL & __SYMBOL__, which */
56 | /* seem to encompass most endian symbol definitions */
57 |
58 | #if defined( BIG_ENDIAN ) && defined( LITTLE_ENDIAN )
59 | # if defined( BYTE_ORDER ) && BYTE_ORDER == BIG_ENDIAN
60 | # define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
61 | # elif defined( BYTE_ORDER ) && BYTE_ORDER == LITTLE_ENDIAN
62 | # define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
63 | # endif
64 | #elif defined( BIG_ENDIAN )
65 | # define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
66 | #elif defined( LITTLE_ENDIAN )
67 | # define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
68 | #endif
69 |
70 | #if defined( _BIG_ENDIAN ) && defined( _LITTLE_ENDIAN )
71 | # if defined( _BYTE_ORDER ) && _BYTE_ORDER == _BIG_ENDIAN
72 | # define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
73 | # elif defined( _BYTE_ORDER ) && _BYTE_ORDER == _LITTLE_ENDIAN
74 | # define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
75 | # endif
76 | #elif defined( _BIG_ENDIAN )
77 | # define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
78 | #elif defined( _LITTLE_ENDIAN )
79 | # define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
80 | #endif
81 |
82 | #if defined( __BIG_ENDIAN ) && defined( __LITTLE_ENDIAN )
83 | # if defined( __BYTE_ORDER ) && __BYTE_ORDER == __BIG_ENDIAN
84 | # define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
85 | # elif defined( __BYTE_ORDER ) && __BYTE_ORDER == __LITTLE_ENDIAN
86 | # define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
87 | # endif
88 | #elif defined( __BIG_ENDIAN )
89 | # define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
90 | #elif defined( __LITTLE_ENDIAN )
91 | # define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
92 | #endif
93 |
94 | #if defined( __BIG_ENDIAN__ ) && defined( __LITTLE_ENDIAN__ )
95 | # if defined( __BYTE_ORDER__ ) && __BYTE_ORDER__ == __BIG_ENDIAN__
96 | # define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
97 | # elif defined( __BYTE_ORDER__ ) && __BYTE_ORDER__ == __LITTLE_ENDIAN__
98 | # define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
99 | # endif
100 | #elif defined( __BIG_ENDIAN__ )
101 | # define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
102 | #elif defined( __LITTLE_ENDIAN__ )
103 | # define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
104 | #endif
105 |
106 | /* if the platform byte order could not be determined, then try to */
107 | /* set this define using common machine defines */
108 | #if !defined(PLATFORM_BYTE_ORDER)
109 |
110 | #if defined( __alpha__ ) || defined( __alpha ) || defined( i386 ) || \
111 | defined( __i386__ ) || defined( _M_I86 ) || defined( _M_IX86 ) || \
112 | defined( __OS2__ ) || defined( sun386 ) || defined( __TURBOC__ ) || \
113 | defined( vax ) || defined( vms ) || defined( VMS ) || \
114 | defined( __VMS ) || defined( _M_X64 )
115 | # define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
116 |
117 | #elif defined( AMIGA ) || defined( applec ) || defined( __AS400__ ) || \
118 | defined( _CRAY ) || defined( __hppa ) || defined( __hp9000 ) || \
119 | defined( ibm370 ) || defined( mc68000 ) || defined( m68k ) || \
120 | defined( __MRC__ ) || defined( __MVS__ ) || defined( __MWERKS__ ) || \
121 | defined( sparc ) || defined( __sparc) || defined( SYMANTEC_C ) || \
122 | defined( __VOS__ ) || defined( __TIGCC__ ) || defined( __TANDEM ) || \
123 | defined( THINK_C ) || defined( __VMCMS__ ) || defined( _AIX )
124 | # define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
125 |
126 | #elif defined(__arm__)
127 | # ifdef __BIG_ENDIAN
128 | # define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
129 | # else
130 | # define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
131 | # endif
132 | #elif 1 /* **** EDIT HERE IF NECESSARY **** */
133 | # define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
134 | #elif 0 /* **** EDIT HERE IF NECESSARY **** */
135 | # define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
136 | #else
137 | # error Please edit lines 132 or 134 in brg_endian.h to set the platform byte order
138 | #endif
139 |
140 | #endif
141 |
142 | #endif
143 |
--------------------------------------------------------------------------------
/eFrodoKEM/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore temporary files and build results
2 |
3 | # User-specific files
4 | *.suo
5 | *.user
6 |
7 | # Build results
8 | Debug/
9 | Win32/
10 | x64/
11 | /efrodo640
12 | /efrodo976
13 | /efrodo1344
14 | objs/
15 |
16 | # Visual Studio cache directory and files
17 | .vs/
18 | *.VC.db
19 | *.VC.VC.opendb
20 |
--------------------------------------------------------------------------------
/eFrodoKEM/README.md:
--------------------------------------------------------------------------------
1 | Ephemeral FrodoKEM
2 | ==================
3 |
4 | This variant, referred to as **eFrodoKEM**, does not include countermeasures against multi-ciphertext attacks and, thus, it is only suitable for applications in which not many ciphertexts are encrypted to a single public-key.
5 |
6 | The public API in the software is designed to be extra conservative and forces a fresh key pair per connection (key generation and encapsulation are exposed through a unified API; see [`ekem.c`](src/ekem.c)).
7 | Any modification to the code to enable some key reuse should be done with care and only if a given application guarantees a limited number of ciphertexts per public key.
8 |
9 |
10 | ## Contents
11 |
12 | * [`KAT` folder](KAT/): Known Answer Test (KAT) files for the KEM.
13 | * [`src` folder](src/): C and header files. Public APIs can be found in [`api_efrodo640.h`](src/api_efrodo640.h), [`api_efrodo976.h`](src/api_efrodo976.h) and [`api_efrodo1344.h`](src/api_efrodo1344.h).
14 | * [Optimized matrix operations](src/frodo_macrify.c): optimized implementation of the matrix operations.
15 | * [Reference matrix operations](src/frodo_macrify_reference.c): reference implementation of the matrix operations.
16 | * [`src/aes` folder](src/aes/): AES implementation.
17 | * [`src/random` folder](src/random/): randombytes function using the system random number generator.
18 | * [`src/sha3` folder](src/sha3/): SHA-3 / SHAKE128 / SHAKE256 implementation.
19 | * [`tests` folder](tests/): test files.
20 | * [`VisualStudio` folder](VisualStudio/): Visual Studio 2022 files for compilation in Windows.
21 | * [`Makefile`](Makefile): Makefile for compilation using the GNU GCC or clang compilers on Unix-like operative systems.
22 | * [`README.md`](README.md): this readme file.
23 | * [`python3` folder](python3): a Python3 reference implementation
24 |
25 | ### Complementary crypto functions
26 |
27 | Random values are generated with /dev/urandom on Unix-like operative systems, and CNG's BCryptGenRandom function in Windows.
28 | Check the folder [`random`](src/random/) for details.
29 |
30 | The library includes standalone implementations of AES and SHAKE. The generation of the matrix
31 | "A" (see the specification document [1]) can be carried out with either AES128 or SHAKE128. By
32 | default AES128 is used.
33 |
34 | There are two options for AES: the standalone implementation that is included in the software or
35 | OpenSSL's AES implementation. OpenSSL's AES implementation is used by default.
36 |
37 | ## Implementation Options
38 |
39 | The following implementation options are available:
40 | - Reference portable implementation enabled by setting `OPT_LEVEL=REFERENCE`.
41 | - Optimized portable implementation enabled by setting `OPT_LEVEL=FAST_GENERIC`.
42 | - Optimized x64 implementation using AVX2 intrinsics and AES-NI instructions enabled by setting `ARCH=x64` and `OPT_LEVEL=FAST`.
43 |
44 | Follow the instructions in the sections "_Instructions for Linux_" or "_Instructions for Windows_" below to configure these different implementation options.
45 |
46 | ## Instructions for Linux
47 |
48 | ### Using AES128
49 |
50 | By simply executing:
51 |
52 | ```sh
53 | $ make
54 | ```
55 |
56 | the library is compiled for x64 using gcc, and optimization level `FAST`, which uses AVX2 instrinsics.
57 | AES128 is used by default to generate the matrix "A". For AES, OpenSSL's AES implementation is used by default.
58 |
59 | Testing and benchmarking results are obtained by running:
60 |
61 | ```sh
62 | $ ./efrodo640/test_KEM
63 | $ ./efrodo976/test_KEM
64 | $ ./efrodo1344/test_KEM
65 | ```
66 |
67 | To run the implementations against the KATs, execute:
68 |
69 | ```sh
70 | $ ./efrodo640/PQCtestKAT_kem
71 | $ ./efrodo976/PQCtestKAT_kem
72 | $ ./efrodo1344/PQCtestKAT_kem
73 | ```
74 |
75 | ### Using SHAKE128
76 |
77 | By executing:
78 |
79 | ```sh
80 | $ make GENERATION_A=SHAKE128
81 | ```
82 |
83 | the library is compiled for x64 using gcc, and optimization level `FAST`, which uses AVX2 instrinsics.
84 | SHAKE128 is used to generate the matrix "A".
85 |
86 | Testing and benchmarking results are obtained by running:
87 |
88 | ```sh
89 | $ ./efrodo640/test_KEM
90 | $ ./efrodo976/test_KEM
91 | $ ./efrodo1344/test_KEM
92 | ```
93 |
94 | To run the implementations against the KATs, execute:
95 |
96 | ```sh
97 | $ ./efrodo640/PQCtestKAT_kem_shake
98 | $ ./efrodo976/PQCtestKAT_kem_shake
99 | $ ./efrodo1344/PQCtestKAT_kem_shake
100 | ```
101 |
102 | ### Additional options
103 |
104 | These are all the available options for compilation:
105 |
106 | ```sh
107 | $ make CC=[gcc/clang] ARCH=[x64/x86/ARM/PPC/s390x] OPT_LEVEL=[REFERENCE/FAST_GENERIC/FAST] GENERATION_A=[AES128/SHAKE128] USE_OPENSSL=[TRUE/FALSE]
108 | ```
109 |
110 | Note that the `FAST` option is only available for x64 with support for AVX2 and AES-NI instructions.
111 | The USE_OPENSSL flag specifies whether OpenSSL's AES implementation is used (`=TRUE`) or if the
112 | standalone AES implementation is used (`=FALSE`). Therefore, this flag only applies when `GENERATION_A=
113 | AES128` (or if `GENERATION_A` is left blank).
114 |
115 | If OpenSSL is being used and is installed in an alternate location, use the following make options:
116 |
117 | ```sh
118 | OPENSSL_INCLUDE_DIR=/path/to/openssl/include
119 | OPENSSL_LIB_DIR=/path/to/openssl/lib
120 | ```
121 |
122 | The program tries its best at auto-correcting unsupported configurations.
123 | For example, since the `FAST` implementation is currently only available for x64 doing `make ARCH=x86 OPT_LEVEL=FAST`
124 | is actually processed using `ARCH=x86 OPT_LEVEL=FAST_GENERIC`.
125 |
126 | ## Instructions for Windows
127 |
128 | ### Building the library with Visual Studio:
129 |
130 | Open the solution file [`efrodoKEM.sln`](VisualStudio/efrodoKEM.sln) in Visual Studio, and choose either x64 or x86 from the platform menu.
131 | Make sure `Fast_generic` is selected in the configuration menu. Finally, select "Build Solution" from the "Build" menu.
132 |
133 | ### Running the tests:
134 |
135 | After building the solution file, there should be three executable files: `test_KEM640.exe`, `test_KEM976.exe` and `test_KEM1344.exe`, to run tests for the KEM.
136 |
137 | ### Using the library:
138 |
139 | After building the solution file, add the generated `eFrodoKEM-640.lib`, `eFrodoKEM-976.lib` and `eFrodoKEM-1344.lib` library files to the set of References for a project,
140 | and add [`api_efrodo640.h`](src/api_efrodo640.h), [`api_efrodo976.h`](src/api_efrodo976.h) and [`api_efrodo1344.h`](src/api_efrodo1344.h) to the list of header files of a project.
141 |
142 | ## Python3 implementation
143 |
144 | The [`python3`](python3) folder contains a Python3 implementation of FrodoKEM.
145 | This reference implementation is a line-by-line transcription of the pseudocode from the [FrodoKEM specification](https://frodokem.org) and includes extensive comments.
146 | The file [`efrodokem.py`](python3/efrodokem.py) contains a Python3 class implementing all 6 variants of eFrodoKEM.
147 | The file [`nist_kat.py`](python3/nist_kat.py) contains a minimal Python port of the known answer test (KAT) code; it should generate the same output as the C version for the first test vector (except that the line `seed = ` will differ).
148 |
149 | It can be run as follows:
150 |
151 | ```sh
152 | pip3 install bitstring cryptography
153 | cd python3
154 | python3 nist_kat.py
155 | ```
156 |
157 | **WARNING**: This Python3 implementation of eFrodoKEM is not designed to be fast or secure, and may leak secret information via timing or other side channels; it should not be used in production environments.
--------------------------------------------------------------------------------
/eFrodoKEM/VisualStudio/efrodoKEM-1344.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Source Files
6 |
7 |
8 | Source Files
9 |
10 |
11 | Source Files
12 |
13 |
14 | Source Files
15 |
16 |
17 | Source Files
18 |
19 |
20 | Source Files
21 |
22 |
23 | Source Files\AES
24 |
25 |
26 | Source Files\AES
27 |
28 |
29 | Source Files\random
30 |
31 |
32 | Source Files\sha3
33 |
34 |
35 |
36 |
37 | Header Files
38 |
39 |
40 | Header Files
41 |
42 |
43 | Header Files
44 |
45 |
46 | Source Files\AES
47 |
48 |
49 | Source Files\random
50 |
51 |
52 | Source Files\sha3
53 |
54 |
55 |
56 |
57 | {47469e83-ec7a-4d69-baf0-ab15e961629e}
58 |
59 |
60 | {7041c366-2ed8-4a00-8e92-4f6e2471eb9d}
61 |
62 |
63 | {71c917ec-9181-4b88-bdfc-9611ee1abe9a}
64 |
65 |
66 | {fd44eb34-2f81-411e-a55f-f279c4b101de}
67 |
68 |
69 | {656e58e0-96ef-4f93-9711-0ebe15c55da2}
70 |
71 |
72 |
--------------------------------------------------------------------------------
/eFrodoKEM/VisualStudio/efrodoKEM-640.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Source Files
6 |
7 |
8 | Source Files
9 |
10 |
11 | Source Files
12 |
13 |
14 | Source Files
15 |
16 |
17 | Source Files
18 |
19 |
20 | Source Files
21 |
22 |
23 | Source Files\AES
24 |
25 |
26 | Source Files\AES
27 |
28 |
29 | Source Files\random
30 |
31 |
32 | Source Files\sha3
33 |
34 |
35 |
36 |
37 | Header Files
38 |
39 |
40 | Header Files
41 |
42 |
43 | Header Files
44 |
45 |
46 | Source Files\AES
47 |
48 |
49 | Source Files\random
50 |
51 |
52 | Source Files\sha3
53 |
54 |
55 |
56 |
57 | {47469e83-ec7a-4d69-baf0-ab15e961629e}
58 |
59 |
60 | {7041c366-2ed8-4a00-8e92-4f6e2471eb9d}
61 |
62 |
63 | {71c917ec-9181-4b88-bdfc-9611ee1abe9a}
64 |
65 |
66 | {fd44eb34-2f81-411e-a55f-f279c4b101de}
67 |
68 |
69 | {656e58e0-96ef-4f93-9711-0ebe15c55da2}
70 |
71 |
72 |
--------------------------------------------------------------------------------
/eFrodoKEM/VisualStudio/efrodoKEM-976.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Source Files
6 |
7 |
8 | Source Files
9 |
10 |
11 | Source Files
12 |
13 |
14 | Source Files
15 |
16 |
17 | Source Files
18 |
19 |
20 | Source Files
21 |
22 |
23 | Source Files\AES
24 |
25 |
26 | Source Files\AES
27 |
28 |
29 | Source Files\random
30 |
31 |
32 | Source Files\sha3
33 |
34 |
35 |
36 |
37 | Header Files
38 |
39 |
40 | Header Files
41 |
42 |
43 | Header Files
44 |
45 |
46 | Source Files\AES
47 |
48 |
49 | Source Files\random
50 |
51 |
52 | Source Files\sha3
53 |
54 |
55 |
56 |
57 | {47469e83-ec7a-4d69-baf0-ab15e961629e}
58 |
59 |
60 | {7041c366-2ed8-4a00-8e92-4f6e2471eb9d}
61 |
62 |
63 | {71c917ec-9181-4b88-bdfc-9611ee1abe9a}
64 |
65 |
66 | {fd44eb34-2f81-411e-a55f-f279c4b101de}
67 |
68 |
69 | {656e58e0-96ef-4f93-9711-0ebe15c55da2}
70 |
71 |
72 |
--------------------------------------------------------------------------------
/eFrodoKEM/VisualStudio/test_kem/test_KEM1344.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
7 |
8 |
9 | {93995380-89BD-4b04-88EB-625FBE52EBFB}
10 | h;hh;hpp;hxx;hm;inl;inc;xsd
11 |
12 |
13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
15 |
16 |
17 |
18 |
19 | Header Files
20 |
21 |
22 |
23 |
24 | Source Files
25 |
26 |
27 | Source Files
28 |
29 |
30 |
--------------------------------------------------------------------------------
/eFrodoKEM/VisualStudio/test_kem/test_KEM640.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
7 |
8 |
9 | {93995380-89BD-4b04-88EB-625FBE52EBFB}
10 | h;hh;hpp;hxx;hm;inl;inc;xsd
11 |
12 |
13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
15 |
16 |
17 |
18 |
19 | Header Files
20 |
21 |
22 |
23 |
24 | Source Files
25 |
26 |
27 | Source Files
28 |
29 |
30 |
--------------------------------------------------------------------------------
/eFrodoKEM/VisualStudio/test_kem/test_KEM976.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
7 |
8 |
9 | {93995380-89BD-4b04-88EB-625FBE52EBFB}
10 | h;hh;hpp;hxx;hm;inl;inc;xsd
11 |
12 |
13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
15 |
16 |
17 |
18 |
19 | Header Files
20 |
21 |
22 |
23 |
24 | Source Files
25 |
26 |
27 | Source Files
28 |
29 |
30 |
--------------------------------------------------------------------------------
/eFrodoKEM/python3/LICENSE:
--------------------------------------------------------------------------------
1 | Creative Commons Legal Code
2 |
3 | CC0 1.0 Universal
4 |
5 | CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED HEREUNDER.
6 |
7 | Statement of Purpose
8 |
9 | The laws of most jurisdictions throughout the world automatically confer exclusive Copyright and Related Rights (defined below) upon the creator and subsequent owner(s) (each and all, an "owner") of an original work of authorship and/or a database (each, a "Work").
10 |
11 | Certain owners wish to permanently relinquish those rights to a Work for the purpose of contributing to a commons of creative, cultural and scientific works ("Commons") that the public can reliably and without fear of later claims of infringement build upon, modify, incorporate in other works, reuse and redistribute as freely as possible in any form whatsoever and for any purposes, including without limitation commercial purposes. These owners may contribute to the Commons to promote the ideal of a free culture and the further production of creative, cultural and scientific works, or to gain reputation or greater distribution for their Work in part through the use and efforts of others.
12 |
13 | For these and/or other purposes and motivations, and without any expectation of additional consideration or compensation, the person associating CC0 with a Work (the "Affirmer"), to the extent that he or she is an owner of Copyright and Related Rights in the Work, voluntarily elects to apply CC0 to the Work and publicly distribute the Work under its terms, with knowledge of his or her Copyright and Related Rights in the Work and the meaning and intended legal effect of CC0 on those rights.
14 |
15 | 1. Copyright and Related Rights. A Work made available under CC0 may be protected by copyright and related or neighboring rights ("Copyright and Related Rights"). Copyright and Related Rights include, but are not limited to, the following:
16 | i. the right to reproduce, adapt, distribute, perform, display, communicate, and translate a Work;
17 | ii. moral rights retained by the original author(s) and/or performer(s);
18 | iii. publicity and privacy rights pertaining to a person's image or likeness depicted in a Work;
19 | iv. rights protecting against unfair competition in regards to a Work, subject to the limitations in paragraph 4(a), below;
20 | v. rights protecting the extraction, dissemination, use and reuse of data in a Work;
21 | vi. database rights (such as those arising under Directive 96/9/EC of the European Parliament and of the Council of 11 March 1996 on the legal protection of databases, and under any national implementation thereof, including any amended or successor version of such directive); and
22 | vii. other similar, equivalent or corresponding rights throughout the world based on applicable law or treaty, and any national implementations thereof.
23 |
24 | 2. Waiver. To the greatest extent permitted by, but not in contravention of, applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and unconditionally waives, abandons, and surrenders all of Affirmer's Copyright and Related Rights and associated claims and causes of action, whether now known or unknown (including existing as well as future claims and causes of action), in the Work (i) in all territories worldwide, (ii) for the maximum duration provided by applicable law or treaty (including future time extensions), (iii) in any current or future medium and for any number of copies, and (iv) for any purpose whatsoever, including without limitation commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each member of the public at large and to the detriment of Affirmer's heirs and successors, fully intending that such Waiver shall not be subject to revocation, rescission, cancellation, termination, or any other legal or equitable action to disrupt the quiet enjoyment of the Work by the public as contemplated by Affirmer's express Statement of Purpose.
25 |
26 | 3. Public License Fallback. Should any part of the Waiver for any reason be judged legally invalid or ineffective under applicable law, then the Waiver shall be preserved to the maximum extent permitted taking into account Affirmer's express Statement of Purpose. In addition, to the extent the Waiver is so judged Affirmer hereby grants to each affected person a royalty-free, non transferable, non sublicensable, non exclusive, irrevocable and unconditional license to exercise Affirmer's Copyright and Related Rights in the Work (i) in all territories worldwide, (ii) for the maximum duration provided by applicable law or treaty (including future time extensions), (iii) in any current or future medium and for any number of copies, and (iv) for any purpose whatsoever, including without limitation commercial, advertising or promotional purposes (the "License"). The License shall be deemed effective as of the date CC0 was applied by Affirmer to the Work. Should any part of the License for any reason be judged legally invalid or ineffective under applicable law, such partial invalidity or ineffectiveness shall not invalidate the remainder of the License, and in such case Affirmer hereby affirms that he or she will not (i) exercise any of his or her remaining Copyright and Related Rights in the Work or (ii) assert any associated claims and causes of action with respect to the Work, in either case contrary to Affirmer's express Statement of Purpose.
27 |
28 | 4. Limitations and Disclaimers.
29 | a. No trademark or patent rights held by Affirmer are waived, abandoned, surrendered, licensed or otherwise affected by this document.
30 | b. Affirmer offers the Work as-is and makes no representations or warranties of any kind concerning the Work, express, implied, statutory or otherwise, including without limitation warranties of title, merchantability, fitness for a particular purpose, non infringement, or the absence of latent or other defects, accuracy, or the present or absence of errors, whether or not discoverable, all to the greatest extent permissible under applicable law.
31 | c. Affirmer disclaims responsibility for clearing rights of other persons that may apply to the Work or any use thereof, including without limitation any person's Copyright and Related Rights in the Work. Further, Affirmer disclaims responsibility for obtaining any necessary consents, permissions or other rights required for any use of the Work.
32 | d. Affirmer understands and acknowledges that Creative Commons is not a party to this document and has no duty or obligation with respect to this CC0 or use of the Work.
33 |
--------------------------------------------------------------------------------
/eFrodoKEM/python3/nist_kat.py:
--------------------------------------------------------------------------------
1 | # Creative Commons Zero v1.0 Universal
2 | # SPDX-License-Identifier: CC0-1.0
3 | # Created by Douglas Stebila
4 |
5 | import os
6 | from frodokem import FrodoKEM
7 |
8 | class NISTKAT(object):
9 |
10 | @staticmethod
11 | def run(kem):
12 | """Generate a NIST KAT output for the given KEM"""
13 | rng = NISTKAT.NISTRNG()
14 | kem.randombytes = rng.randombytes
15 | print("===============================================")
16 | print(kem.variant)
17 | print("count = 0")
18 | print("seed = ")
19 | (pk, sk) = kem.kem_keygen()
20 | print("pk =", pk.hex().upper())
21 | print("sk =", sk.hex().upper())
22 | (ct, ss_e) = kem.kem_encaps(pk)
23 | print("ct =", ct.hex().upper())
24 | print("ss =", ss_e.hex().upper())
25 | ss_d = kem.kem_decaps(sk, ct)
26 | assert ss_e.hex() == ss_d.hex(), "Shared secrets not equal"
27 | return {
28 | 'variant': kem.variant,
29 | 'count': '0',
30 | 'seed': '',
31 | 'pk': pk.hex().upper(),
32 | 'sk': sk.hex().upper(),
33 | 'ct': ct.hex().upper(),
34 | 'ss': ss_e.hex().upper()
35 | }
36 |
37 | def check(katvalues, katfile):
38 | """Check that KAT values in the dictionary katvalues match those stored in katfile"""
39 | with open(os.path.join('..', 'KAT', katfile), 'r') as fh:
40 | basekatvalues = dict()
41 | basekatvalues['variant'] = fh.readline().replace('#', '').strip()
42 | fh.readline()
43 | # count
44 | a = fh.readline().strip().replace(' = ', ',').split(',')
45 | basekatvalues[a[0]] = a[1]
46 | # seed
47 | a = fh.readline().strip().replace(' = ', ',').split(',')
48 | basekatvalues[a[0]] = a[1]
49 | # pk
50 | a = fh.readline().strip().replace(' = ', ',').split(',')
51 | basekatvalues[a[0]] = a[1]
52 | # sk
53 | a = fh.readline().strip().replace(' = ', ',').split(',')
54 | basekatvalues[a[0]] = a[1]
55 | # ct
56 | a = fh.readline().strip().replace(' = ', ',').split(',')
57 | basekatvalues[a[0]] = a[1]
58 | # ss
59 | a = fh.readline().strip().replace(' = ', ',').split(',')
60 | basekatvalues[a[0]] = a[1]
61 | for x in ['variant', 'count', 'pk', 'sk', 'ct', 'ss']:
62 | assert katvalues[x] == basekatvalues[x], "{:s} not equal".format(x)
63 | print("Computed KAT values match for {:s}".format(basekatvalues['variant']))
64 |
65 | class NISTRNG(object):
66 | """Dummy object that contains a serialization of the randombytes outputs that
67 | would be generated by the deterministic RNG in the NIST KAT generation algorithm
68 | when run on FrodoKEM; note that this is not a proper implementation of that RNG,
69 | it has the exact values generated hard-coded."""
70 |
71 | def __init__(self):
72 | self.current_outputs = None
73 | self.possible_outputs = [
74 | [
75 | bytes.fromhex('7C9935A0B07694AA0C6D10E4DB6B1ADD2FD81A25CCB148032DCD739936737F2DB505D7CFAD1B497499323C8686325E47'),
76 | bytes.fromhex('33B3C07507E4201748494D832B6EE2A6'),
77 | ],
78 | [
79 | bytes.fromhex('7C9935A0B07694AA0C6D10E4DB6B1ADD2FD81A25CCB148032DCD739936737F2DB505D7CFAD1B497499323C8686325E4792F267AAFA3F87CA60D01CB54F29202A'),
80 | bytes.fromhex('EB4A7C66EF4EBA2DDB38C88D8BC706B1D639002198172A7B'),
81 | ],
82 | [
83 | bytes.fromhex('7C9935A0B07694AA0C6D10E4DB6B1ADD2FD81A25CCB148032DCD739936737F2DB505D7CFAD1B497499323C8686325E4792F267AAFA3F87CA60D01CB54F29202A3E784CCB7EBCDCFD45542B7F6AF77874'),
84 | bytes.fromhex('8BF0F459F0FB3EA8D32764C259AE631178976BAF3683D33383188A65A4C2449B'),
85 | ],
86 | ]
87 |
88 | def randombytes(self, n):
89 | # On each use, check if the output length requested matches one of the pre-programmed values
90 | if self.current_outputs == None:
91 | for i in range(len(self.possible_outputs)):
92 | if n == len(self.possible_outputs[i][0]):
93 | self.current_outputs = self.possible_outputs[i]
94 | assert self.current_outputs != None, "Could not find pre-programmed output of desired length {:d}".format(n)
95 | assert len(self.current_outputs) > 0, "No remaining outputs available"
96 | assert n == len(self.current_outputs[0]), "Next output not of the appropriate length"
97 | r = self.current_outputs.pop(0)
98 | return r
99 |
100 | if __name__ == "__main__":
101 | # Run KATs for all supported FrodoKEM variants
102 | katvalues = NISTKAT.run(FrodoKEM('FrodoKEM-640-AES'))
103 | NISTKAT.check(katvalues, 'PQCkemKAT_19888.rsp')
104 | katvalues = NISTKAT.run(FrodoKEM('FrodoKEM-640-SHAKE'))
105 | NISTKAT.check(katvalues, 'PQCkemKAT_19888_shake.rsp')
106 | katvalues = NISTKAT.run(FrodoKEM('FrodoKEM-976-AES'))
107 | NISTKAT.check(katvalues, 'PQCkemKAT_31296.rsp')
108 | katvalues = NISTKAT.run(FrodoKEM('FrodoKEM-976-SHAKE'))
109 | NISTKAT.check(katvalues, 'PQCkemKAT_31296_shake.rsp')
110 | katvalues = NISTKAT.run(FrodoKEM('FrodoKEM-1344-AES'))
111 | NISTKAT.check(katvalues, 'PQCkemKAT_43088.rsp')
112 | katvalues = NISTKAT.run(FrodoKEM('FrodoKEM-1344-SHAKE'))
113 | NISTKAT.check(katvalues, 'PQCkemKAT_43088_shake.rsp')
114 |
--------------------------------------------------------------------------------
/eFrodoKEM/src/api_efrodo1344.h:
--------------------------------------------------------------------------------
1 | /********************************************************************************************
2 | * FrodoKEM: Learning with Errors Key Encapsulation
3 | *
4 | * Abstract: parameters and API for eFrodoKEM-1344
5 | *********************************************************************************************/
6 |
7 | #ifndef _API_eFrodo1344_H_
8 | #define _API_eFrodo1344_H_
9 |
10 |
11 | #define CRYPTO_SECRETKEYBYTES 43088 // sizeof(s) + CRYPTO_PUBLICKEYBYTES + 2*PARAMS_N*PARAMS_NBAR + BYTES_PKHASH
12 | #define CRYPTO_PUBLICKEYBYTES 21520 // sizeof(seed_A) + (PARAMS_LOGQ*PARAMS_N*PARAMS_NBAR)/8
13 | #define CRYPTO_BYTES 32
14 | #define CRYPTO_CIPHERTEXTBYTES 21632 // (PARAMS_LOGQ*PARAMS_N*PARAMS_NBAR)/8 + (PARAMS_LOGQ*PARAMS_NBAR*PARAMS_NBAR)/8
15 |
16 | // Algorithm name
17 | #define CRYPTO_ALGNAME "eFrodoKEM-1344"
18 |
19 |
20 | int crypto_kem_keypair_enc_eFrodo1344(unsigned char* ct, unsigned char* ss, unsigned char* pk, unsigned char* sk);
21 | int crypto_kem_dec_eFrodo1344(unsigned char *ss, const unsigned char *ct, const unsigned char *sk);
22 |
23 |
24 | #endif
25 |
--------------------------------------------------------------------------------
/eFrodoKEM/src/api_efrodo640.h:
--------------------------------------------------------------------------------
1 | /********************************************************************************************
2 | * FrodoKEM: Learning with Errors Key Encapsulation
3 | *
4 | * Abstract: parameters and API for eFrodoKEM-640
5 | *********************************************************************************************/
6 |
7 | #ifndef _API_eFrodo640_H_
8 | #define _API_eFrodo640_H_
9 |
10 |
11 | #define CRYPTO_SECRETKEYBYTES 19888 // sizeof(s) + CRYPTO_PUBLICKEYBYTES + 2*PARAMS_N*PARAMS_NBAR + BYTES_PKHASH
12 | #define CRYPTO_PUBLICKEYBYTES 9616 // sizeof(seed_A) + (PARAMS_LOGQ*PARAMS_N*PARAMS_NBAR)/8
13 | #define CRYPTO_BYTES 16
14 | #define CRYPTO_CIPHERTEXTBYTES 9720 // (PARAMS_LOGQ*PARAMS_N*PARAMS_NBAR)/8 + (PARAMS_LOGQ*PARAMS_NBAR*PARAMS_NBAR)/8
15 |
16 | // Algorithm name
17 | #define CRYPTO_ALGNAME "eFrodoKEM-640"
18 |
19 |
20 | int crypto_kem_keypair_enc_eFrodo640(unsigned char* ct, unsigned char* ss, unsigned char* pk, unsigned char* sk);
21 | int crypto_kem_dec_eFrodo640(unsigned char *ss, const unsigned char *ct, const unsigned char *sk);
22 |
23 |
24 | #endif
25 |
--------------------------------------------------------------------------------
/eFrodoKEM/src/api_efrodo976.h:
--------------------------------------------------------------------------------
1 | /********************************************************************************************
2 | * FrodoKEM: Learning with Errors Key Encapsulation
3 | *
4 | * Abstract: parameters and API for eFrodoKEM-976
5 | *********************************************************************************************/
6 |
7 | #ifndef _API_eFrodo976_H_
8 | #define _API_eFrodo976_H_
9 |
10 |
11 | #define CRYPTO_SECRETKEYBYTES 31296 // sizeof(s) + CRYPTO_PUBLICKEYBYTES + 2*PARAMS_N*PARAMS_NBAR + BYTES_PKHASH
12 | #define CRYPTO_PUBLICKEYBYTES 15632 // sizeof(seed_A) + (PARAMS_LOGQ*PARAMS_N*PARAMS_NBAR)/8
13 | #define CRYPTO_BYTES 24
14 | #define CRYPTO_CIPHERTEXTBYTES 15744 // (PARAMS_LOGQ*PARAMS_N*PARAMS_NBAR)/8 + (PARAMS_LOGQ*PARAMS_NBAR*PARAMS_NBAR)/8
15 |
16 | // Algorithm name
17 | #define CRYPTO_ALGNAME "eFrodoKEM-976"
18 |
19 |
20 | int crypto_kem_keypair_enc_eFrodo976(unsigned char *ct, unsigned char *ss, unsigned char *pk, unsigned char* sk);
21 | int crypto_kem_dec_eFrodo976(unsigned char *ss, const unsigned char *ct, const unsigned char *sk);
22 |
23 |
24 | #endif
25 |
--------------------------------------------------------------------------------
/eFrodoKEM/src/config.h:
--------------------------------------------------------------------------------
1 | /********************************************************************************************
2 | * FrodoKEM: Learning with Errors Key Encapsulation
3 | *
4 | * Abstract: configuration file
5 | *********************************************************************************************/
6 |
7 | #ifndef _CONFIG_H_
8 | #define _CONFIG_H_
9 |
10 |
11 | // Definition of operating system
12 |
13 | #define OS_WIN 1
14 | #define OS_NIX 2
15 |
16 | #if defined(WINDOWS) // Microsoft Windows
17 | #define OS_TARGET OS_WIN
18 | #elif defined(NIX) // Unix-like operative systems
19 | #define OS_TARGET OS_NIX
20 | #else
21 | #error -- "Unsupported OS"
22 | #endif
23 |
24 |
25 | // Definition of compiler
26 |
27 | #define COMPILER_VC 1
28 | #define COMPILER_GCC 2
29 | #define COMPILER_CLANG 3
30 |
31 | #if defined(_MSC_VER) // Microsoft Visual C compiler
32 | #define COMPILER COMPILER_VC
33 | #elif defined(__GNUC__) // GNU GCC compiler
34 | #define COMPILER COMPILER_GCC
35 | #elif defined(__clang__) // Clang compiler
36 | #define COMPILER COMPILER_CLANG
37 | #else
38 | #error -- "Unsupported COMPILER"
39 | #endif
40 |
41 |
42 | // Definition of the targeted architecture and basic data types
43 |
44 | #define TARGET_AMD64 1
45 | #define TARGET_x86 2
46 | #define TARGET_ARM 3
47 | #define TARGET_PPC 4
48 | #define TARGET_S390X 5
49 |
50 | #if defined(_AMD64_)
51 | #define TARGET TARGET_AMD64
52 | #elif defined(_X86_)
53 | #define TARGET TARGET_x86
54 | #elif defined(_ARM_)
55 | #define TARGET TARGET_ARM
56 | #elif defined(_PPC_)
57 | #define TARGET TARGET_PPC
58 | #elif defined(_S390X_)
59 | #define TARGET TARGET_S390X
60 | #else
61 | #error -- "Unsupported ARCHITECTURE"
62 | #endif
63 |
64 |
65 | #if defined(WINDOWS)
66 | #define ALIGN_HEADER(N) __declspec(align(N))
67 | #define ALIGN_FOOTER(N)
68 | #else
69 | #define ALIGN_HEADER(N)
70 | #define ALIGN_FOOTER(N) __attribute__((aligned(N)))
71 | #endif
72 |
73 |
74 | // Selecting implementation: fast, generic or reference
75 | #if defined(_FAST_) // The "fast" implementation requires support for AVX2 and AES_NI instructions
76 | #define USE_AVX2
77 | #define AES_ENABLE_NI
78 | #define USE_FAST
79 | #elif defined(_FAST_GENERIC_)
80 | #define USE_FAST_GENERIC
81 | #elif defined(_REFERENCE_)
82 | #define USE_REFERENCE
83 | #else
84 | #error -- unsupported implementation
85 | #endif
86 |
87 |
88 | // Defining method for generating matrix A
89 | #if defined(_AES128_FOR_A_)
90 | #define USE_AES128_FOR_A
91 | #elif defined(_SHAKE128_FOR_A_)
92 | #define USE_SHAKE128_FOR_A
93 | #else
94 | ##error -- missing method for generating matrix A
95 | #endif
96 |
97 |
98 | // Selecting use of OpenSSL's AES functions
99 | #if defined(_USE_OPENSSL_)
100 | #define USE_OPENSSL
101 | #endif
102 |
103 |
104 | // Configuration for endianness
105 | #if (TARGET == TARGET_PPC || TARGET == TARGET_S390X) || (defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__))
106 | #define LE_TO_UINT16(n) (((((unsigned short)(n) & 0xFF)) << 8) | (((unsigned short)(n) & 0xFF00) >> 8))
107 | #define UINT16_TO_LE(n) (((((unsigned short)(n) & 0xFF)) << 8) | (((unsigned short)(n) & 0xFF00) >> 8))
108 | #elif (TARGET == TARGET_x86 || TARGET == TARGET_AMD64) || (defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__))
109 | #define LE_TO_UINT16(n) (n)
110 | #define UINT16_TO_LE(n) (n)
111 | #else
112 | #define LE_TO_UINT16(n) (((uint8_t *) &(n))[0] | (((uint8_t *) &(n))[1] << 8))
113 | static inline uint16_t UINT16_TO_LE(const uint16_t x) {
114 | uint16_t y;
115 | uint8_t *z = (uint8_t *) &y;
116 | z[0] = x & 0xFF;
117 | z[1] = x >> 8;
118 | return y;
119 | }
120 | #endif
121 |
122 | #endif
123 |
--------------------------------------------------------------------------------
/eFrodoKEM/src/efrodo1344.c:
--------------------------------------------------------------------------------
1 | /********************************************************************************************
2 | * FrodoKEM: Learning with Errors Key Encapsulation
3 | *
4 | * Abstract: functions for eFrodoKEM-1344
5 | * Instantiates "frodo_macrify.c" with the necessary matrix arithmetic functions
6 | *********************************************************************************************/
7 |
8 | #include "api_efrodo1344.h"
9 | #include "frodo_macrify.h"
10 |
11 |
12 | // Parameters for "eFrodoKEM-1344"
13 | #define PARAMS_N 1344
14 | #define PARAMS_NBAR 8
15 | #define PARAMS_LOGQ 16
16 | #define PARAMS_Q (1 << PARAMS_LOGQ)
17 | #define PARAMS_EXTRACTED_BITS 4
18 | #define PARAMS_STRIPE_STEP 8
19 | #define PARAMS_PARALLEL 4
20 | #define BYTES_SEED_A 16
21 | #define BYTES_MU (PARAMS_EXTRACTED_BITS*PARAMS_NBAR*PARAMS_NBAR)/8
22 | #define BYTES_PKHASH CRYPTO_BYTES
23 |
24 | #if (PARAMS_NBAR % 8 != 0)
25 | #error You have modified the cryptographic parameters. FrodoKEM assumes PARAMS_NBAR is a multiple of 8.
26 | #endif
27 |
28 | // Selecting SHAKE XOF function for the KEM and noise sampling
29 | #define shake shake256
30 |
31 | // CDF table
32 | uint16_t CDF_TABLE[7] = {9142, 23462, 30338, 32361, 32725, 32765, 32767};
33 | uint16_t CDF_TABLE_LEN = 7;
34 |
35 | #define crypto_kem_keypair_enc crypto_kem_keypair_enc_eFrodo1344
36 | #define crypto_kem_dec crypto_kem_dec_eFrodo1344
37 |
38 | #include "ekem.c"
39 | #include "noise.c"
40 | #if defined(USE_REFERENCE)
41 | #include "frodo_macrify_reference.c"
42 | #else
43 | #include "frodo_macrify.c"
44 | #endif
45 |
--------------------------------------------------------------------------------
/eFrodoKEM/src/efrodo640.c:
--------------------------------------------------------------------------------
1 | /********************************************************************************************
2 | * FrodoKEM: Learning with Errors Key Encapsulation
3 | *
4 | * Abstract: functions for eFrodoKEM-640
5 | * Instantiates "frodo_macrify.c" with the necessary matrix arithmetic functions
6 | *********************************************************************************************/
7 |
8 | #include "api_efrodo640.h"
9 | #include "frodo_macrify.h"
10 |
11 |
12 | // Parameters for "eFrodoKEM-640"
13 | #define PARAMS_N 640
14 | #define PARAMS_NBAR 8
15 | #define PARAMS_LOGQ 15
16 | #define PARAMS_Q (1 << PARAMS_LOGQ)
17 | #define PARAMS_EXTRACTED_BITS 2
18 | #define PARAMS_STRIPE_STEP 8
19 | #define PARAMS_PARALLEL 4
20 | #define BYTES_SEED_A 16
21 | #define BYTES_MU (PARAMS_EXTRACTED_BITS*PARAMS_NBAR*PARAMS_NBAR)/8
22 | #define BYTES_PKHASH CRYPTO_BYTES
23 |
24 | #if (PARAMS_NBAR % 8 != 0)
25 | #error You have modified the cryptographic parameters. FrodoKEM assumes PARAMS_NBAR is a multiple of 8.
26 | #endif
27 |
28 | // Selecting SHAKE XOF function for the KEM and noise sampling
29 | #define shake shake128
30 |
31 | // CDF table
32 | uint16_t CDF_TABLE[13] = {4643, 13363, 20579, 25843, 29227, 31145, 32103, 32525, 32689, 32745, 32762, 32766, 32767};
33 | uint16_t CDF_TABLE_LEN = 13;
34 |
35 | #define crypto_kem_keypair_enc crypto_kem_keypair_enc_eFrodo640
36 | #define crypto_kem_dec crypto_kem_dec_eFrodo640
37 |
38 | #include "ekem.c"
39 | #include "noise.c"
40 | #if defined(USE_REFERENCE)
41 | #include "frodo_macrify_reference.c"
42 | #else
43 | #include "frodo_macrify.c"
44 | #endif
45 |
--------------------------------------------------------------------------------
/eFrodoKEM/src/efrodo976.c:
--------------------------------------------------------------------------------
1 | /********************************************************************************************
2 | * FrodoKEM: Learning with Errors Key Encapsulation
3 | *
4 | * Abstract: functions for eFrodoKEM-976
5 | * Instantiates "frodo_macrify.c" with the necessary matrix arithmetic functions
6 | *********************************************************************************************/
7 |
8 | #include "api_efrodo976.h"
9 | #include "frodo_macrify.h"
10 |
11 |
12 | // Parameters for "eFrodoKEM-976"
13 | #define PARAMS_N 976
14 | #define PARAMS_NBAR 8
15 | #define PARAMS_LOGQ 16
16 | #define PARAMS_Q (1 << PARAMS_LOGQ)
17 | #define PARAMS_EXTRACTED_BITS 3
18 | #define PARAMS_STRIPE_STEP 8
19 | #define PARAMS_PARALLEL 4
20 | #define BYTES_SEED_A 16
21 | #define BYTES_MU (PARAMS_EXTRACTED_BITS*PARAMS_NBAR*PARAMS_NBAR)/8
22 | #define BYTES_PKHASH CRYPTO_BYTES
23 |
24 | #if (PARAMS_NBAR % 8 != 0)
25 | #error You have modified the cryptographic parameters. FrodoKEM assumes PARAMS_NBAR is a multiple of 8.
26 | #endif
27 |
28 | // Selecting SHAKE XOF function for the KEM and noise sampling
29 | #define shake shake256
30 |
31 | // CDF table
32 | uint16_t CDF_TABLE[11] = {5638, 15915, 23689, 28571, 31116, 32217, 32613, 32731, 32760, 32766, 32767};
33 | uint16_t CDF_TABLE_LEN = 11;
34 |
35 | #define crypto_kem_keypair_enc crypto_kem_keypair_enc_eFrodo976
36 | #define crypto_kem_dec crypto_kem_dec_eFrodo976
37 |
38 | #include "ekem.c"
39 | #include "noise.c"
40 | #if defined(USE_REFERENCE)
41 | #include "frodo_macrify_reference.c"
42 | #else
43 | #include "frodo_macrify.c"
44 | #endif
45 |
--------------------------------------------------------------------------------
/eFrodoKEM/src/frodo_macrify.h:
--------------------------------------------------------------------------------
1 | /********************************************************************************************
2 | * FrodoKEM: Learning with Errors Key Encapsulation
3 | *
4 | * Abstract: header for internal functions
5 | *********************************************************************************************/
6 |
7 | #ifndef _FRODO_MACRIFY_H_
8 | #define _FRODO_MACRIFY_H_
9 |
10 | #include
11 | #include
12 | #include "config.h"
13 |
14 |
15 | void frodo_pack(unsigned char *out, const size_t outlen, const uint16_t *in, const size_t inlen, const unsigned char lsb);
16 | void frodo_unpack(uint16_t *out, const size_t outlen, const unsigned char *in, const size_t inlen, const unsigned char lsb);
17 | void frodo_sample_n(uint16_t *s, const size_t n);
18 | int8_t ct_verify(const uint16_t *a, const uint16_t *b, size_t len);
19 | void ct_select(uint8_t *r, const uint8_t *a, const uint8_t *b, size_t len, int8_t selector);
20 | void clear_bytes(uint8_t *mem, size_t n);
21 |
22 | int frodo_mul_add_as_plus_e(uint16_t *b, const uint16_t *s, const uint16_t *e, const uint8_t *seed_A);
23 | int frodo_mul_add_sa_plus_e(uint16_t *b, const uint16_t *s, uint16_t *e, const uint8_t *seed_A);
24 | void frodo_mul_add_sb_plus_e(uint16_t *out, const uint16_t *b, const uint16_t *s, const uint16_t *e);
25 | void frodo_mul_bs(uint16_t *out, const uint16_t *b, const uint16_t *s);
26 |
27 | void frodo_add(uint16_t *out, const uint16_t *a, const uint16_t *b);
28 | void frodo_sub(uint16_t *out, const uint16_t *a, const uint16_t *b);
29 | void frodo_key_encode(uint16_t *out, const uint16_t *in);
30 | void frodo_key_decode(uint16_t *out, const uint16_t *in);
31 |
32 | #endif
33 |
--------------------------------------------------------------------------------
/eFrodoKEM/src/noise.c:
--------------------------------------------------------------------------------
1 | /********************************************************************************************
2 | * FrodoKEM: Learning with Errors Key Encapsulation
3 | *
4 | * Abstract: noise sampling functions
5 | *********************************************************************************************/
6 |
7 | #include "../../common/sha3/fips202.h"
8 |
9 |
10 | void frodo_sample_n(uint16_t *s, const size_t n)
11 | { // Fills vector s with n samples from the noise distribution which requires 16 bits to sample.
12 | // The distribution is specified by its CDF.
13 | // Input: pseudo-random values (2*n bytes) passed in s. The input is overwritten by the output.
14 | unsigned int i, j;
15 |
16 | for (i = 0; i < n; ++i) {
17 | uint16_t sample = 0;
18 | uint16_t prnd = s[i] >> 1; // Drop the least significant bit
19 | uint16_t sign = s[i] & 0x1; // Pick the least significant bit
20 |
21 | // No need to compare with the last value.
22 | for (j = 0; j < (unsigned int)(CDF_TABLE_LEN - 1); j++) {
23 | // Constant time comparison: 1 if CDF_TABLE[j] < s, 0 otherwise. Uses the fact that CDF_TABLE[j] and s fit in 15 bits.
24 | sample += (uint16_t)(CDF_TABLE[j] - prnd) >> 15;
25 | }
26 | // Assuming that sign is either 0 or 1, flips sample iff sign = 1
27 | s[i] = ((-sign) ^ sample) + sign;
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/eFrodoKEM/src/util.c:
--------------------------------------------------------------------------------
1 | /********************************************************************************************
2 | * FrodoKEM: Learning with Errors Key Encapsulation
3 | *
4 | * Abstract: additional functions for FrodoKEM
5 | *********************************************************************************************/
6 |
7 | #include
8 | #include "frodo_macrify.h"
9 |
10 | #define min(x, y) (((x) < (y)) ? (x) : (y))
11 |
12 |
13 | void frodo_pack(unsigned char *out, const size_t outlen, const uint16_t *in, const size_t inlen, const unsigned char lsb)
14 | { // Pack the input uint16 vector into a char output vector, copying lsb bits from each input element.
15 | // If inlen * lsb / 8 > outlen, only outlen * 8 bits are copied.
16 | memset(out, 0, outlen);
17 |
18 | size_t i = 0; // whole bytes already filled in
19 | size_t j = 0; // whole uint16_t already copied
20 | uint16_t w = 0; // the leftover, not yet copied
21 | unsigned char bits = 0; // the number of lsb in w
22 |
23 | while (i < outlen && (j < inlen || ((j == inlen) && (bits > 0)))) {
24 | /*
25 | in: | | |********|********|
26 | ^
27 | j
28 | w : | ****|
29 | ^
30 | bits
31 | out:|**|**|**|**|**|**|**|**|* |
32 | ^^
33 | ib
34 | */
35 | unsigned char b = 0; // bits in out[i] already filled in
36 | while (b < 8) {
37 | int nbits = min(8 - b, bits);
38 | uint16_t mask = (1 << nbits) - 1;
39 | unsigned char t = (w >> (bits - nbits)) & mask; // the bits to copy from w to out
40 | out[i] = out[i] + (t << (8 - b - nbits));
41 | b += nbits;
42 | bits -= nbits;
43 | w &= ~(mask << bits); // not strictly necessary; mostly for debugging
44 |
45 | if (bits == 0) {
46 | if (j < inlen) {
47 | w = in[j];
48 | bits = lsb;
49 | j++;
50 | } else {
51 | break; // the input vector is exhausted
52 | }
53 | }
54 | }
55 | if (b == 8) { // out[i] is filled in
56 | i++;
57 | }
58 | }
59 | }
60 |
61 |
62 | void frodo_unpack(uint16_t *out, const size_t outlen, const unsigned char *in, const size_t inlen, const unsigned char lsb)
63 | { // Unpack the input char vector into a uint16_t output vector, copying lsb bits
64 | // for each output element from input. outlen must be at least ceil(inlen * 8 / lsb).
65 | memset(out, 0, outlen * sizeof(uint16_t));
66 |
67 | size_t i = 0; // whole uint16_t already filled in
68 | size_t j = 0; // whole bytes already copied
69 | unsigned char w = 0; // the leftover, not yet copied
70 | unsigned char bits = 0; // the number of lsb bits of w
71 |
72 | while (i < outlen && (j < inlen || ((j == inlen) && (bits > 0)))) {
73 | /*
74 | in: | | | | | | |**|**|...
75 | ^
76 | j
77 | w : | *|
78 | ^
79 | bits
80 | out:| *****| *****| *** | |...
81 | ^ ^
82 | i b
83 | */
84 | unsigned char b = 0; // bits in out[i] already filled in
85 | while (b < lsb) {
86 | int nbits = min(lsb - b, bits);
87 | uint16_t mask = (1 << nbits) - 1;
88 | unsigned char t = (w >> (bits - nbits)) & mask; // the bits to copy from w to out
89 | out[i] = out[i] + (t << (lsb - b - nbits));
90 | b += nbits;
91 | bits -= nbits;
92 | w &= ~(mask << bits); // not strictly necessary; mostly for debugging
93 |
94 | if (bits == 0) {
95 | if (j < inlen) {
96 | w = in[j];
97 | bits = 8;
98 | j++;
99 | } else {
100 | break; // the input vector is exhausted
101 | }
102 | }
103 | }
104 | if (b == lsb) { // out[i] is filled in
105 | i++;
106 | }
107 | }
108 | }
109 |
110 |
111 | int8_t ct_verify(const uint16_t *a, const uint16_t *b, size_t len)
112 | { // Compare two arrays in constant time.
113 | // Returns 0 if the byte arrays are equal, -1 otherwise.
114 | uint16_t r = 0;
115 |
116 | for (size_t i = 0; i < len; i++) {
117 | r |= a[i] ^ b[i];
118 | }
119 |
120 | r = (-(int16_t)(r >> 1) | -(int16_t)(r & 1)) >> (8*sizeof(uint16_t)-1);
121 | return (int8_t)r;
122 | }
123 |
124 |
125 | void ct_select(uint8_t *r, const uint8_t *a, const uint8_t *b, size_t len, int8_t selector)
126 | { // Select one of the two input arrays to be moved to r
127 | // If (selector == 0) then load r with a, else if (selector == -1) load r with b
128 |
129 | for (size_t i = 0; i < len; i++) {
130 | r[i] = (~selector & a[i]) | (selector & b[i]);
131 | }
132 | }
133 |
134 |
135 | void clear_bytes(uint8_t *mem, size_t n)
136 | { // Clear 8-bit bytes from memory. "n" indicates the number of bytes to be zeroed.
137 | // This function uses the volatile type qualifier to inform the compiler not to optimize out the memory clearing.
138 | volatile uint8_t *v = mem;
139 |
140 | for (size_t i = 0; i < n; i++) {
141 | v[i] = 0;
142 | }
143 | }
144 |
--------------------------------------------------------------------------------
/eFrodoKEM/tests/PQCtestKAT_kem640.c:
--------------------------------------------------------------------------------
1 | /********************************************************************************************
2 | * Abstract: run tests against known answer test vectors for eFrodoKEM-640 using AES128
3 | *
4 | * Modified from a file created by Bassham, Lawrence E (Fed) on 8/29/17.
5 | * Copyright © 2017 Bassham, Lawrence E (Fed). All rights reserved.
6 | *********************************************************************************************/
7 |
8 | #include
9 | #include
10 | #include
11 | #include
12 | #include "rng.h"
13 | #include "../src/api_efrodo640.h"
14 |
15 | char AlgName[] = "eFrodoKEM-640-AES";
16 |
17 |
18 | #define MAX_MARKER_LEN 50
19 | #define KAT_SUCCESS 0
20 | #define KAT_FILE_OPEN_ERROR -1
21 | #define KAT_VERIFICATION_ERROR -2
22 | #define KAT_DATA_ERROR -3
23 | #define KAT_CRYPTO_FAILURE -4
24 |
25 | int FindMarker(FILE *infile, const char *marker);
26 | int ReadHex(FILE *infile, unsigned char *A, int Length, char *str);
27 | void fprintBstr(FILE *fp, char *S, unsigned char *A, unsigned long long L);
28 |
29 | int
30 | main()
31 | {
32 | char fn_rsp[32];
33 | FILE *fp_rsp;
34 | unsigned char seed[48];
35 | unsigned char ct[CRYPTO_CIPHERTEXTBYTES], ss[CRYPTO_BYTES], ss1[CRYPTO_BYTES], ct_rsp[CRYPTO_CIPHERTEXTBYTES], ss_rsp[CRYPTO_BYTES];
36 | int count;
37 | int done;
38 | unsigned char pk[CRYPTO_PUBLICKEYBYTES], sk[CRYPTO_SECRETKEYBYTES], pk_rsp[CRYPTO_PUBLICKEYBYTES], sk_rsp[CRYPTO_SECRETKEYBYTES];
39 | int ret_val;
40 |
41 | sprintf(fn_rsp, "KAT/PQCkemKAT_%d.rsp", CRYPTO_SECRETKEYBYTES);
42 | if ( (fp_rsp = fopen(fn_rsp, "r")) == NULL ) {
43 | printf("Couldn't open <%s> for read\n", fn_rsp);
44 | return KAT_FILE_OPEN_ERROR;
45 | }
46 |
47 | printf("# %s\n\n", AlgName);
48 | done = 0;
49 | do {
50 | if ( FindMarker(fp_rsp, "count = ") ) {
51 | if (fscanf(fp_rsp, "%d", &count) != 1) {
52 | done = 1;
53 | break;
54 | }
55 | } else {
56 | done = 1;
57 | break;
58 | }
59 |
60 | if ( !ReadHex(fp_rsp, seed, 48, "seed = ") ) {
61 | printf("ERROR: unable to read 'seed' from <%s>\n", fn_rsp);
62 | return KAT_DATA_ERROR;
63 | }
64 |
65 | randombytes_init(seed, NULL, 256);
66 |
67 | // Generate the public/private keypair
68 | if ( (ret_val = crypto_kem_keypair_enc_eFrodo640(ct, ss, pk, sk)) != 0) {
69 | printf("crypto_kem_keypair_enc returned <%d>\n", ret_val);
70 | return KAT_CRYPTO_FAILURE;
71 | }
72 | if ( !ReadHex(fp_rsp, pk_rsp, CRYPTO_PUBLICKEYBYTES, "pk = ") ) {
73 | printf("ERROR: unable to read 'pk' from <%s>\n", fn_rsp);
74 | return KAT_DATA_ERROR;
75 | }
76 | if ( !ReadHex(fp_rsp, sk_rsp, CRYPTO_SECRETKEYBYTES, "sk = ") ) {
77 | printf("ERROR: unable to read 'sk' from <%s>\n", fn_rsp);
78 | return KAT_DATA_ERROR;
79 | }
80 |
81 | if(memcmp(pk,pk_rsp,CRYPTO_PUBLICKEYBYTES)!=0){
82 | printf("ERROR: pk is different from <%s>\n", fn_rsp);
83 | return KAT_VERIFICATION_ERROR;
84 | }
85 | if(memcmp(sk,sk_rsp,CRYPTO_SECRETKEYBYTES)!=0){
86 | printf("ERROR: sk is different from <%s>\n", fn_rsp);
87 | return KAT_VERIFICATION_ERROR;
88 | }
89 |
90 | if (!ReadHex(fp_rsp, ct_rsp, CRYPTO_CIPHERTEXTBYTES, "ct = ")) {
91 | printf("ERROR: unable to read 'pk' from <%s>\n", fn_rsp);
92 | return KAT_DATA_ERROR;
93 | }
94 | if (!ReadHex(fp_rsp, ss_rsp, CRYPTO_BYTES, "ss = ")) {
95 | printf("ERROR: unable to read 'sk' from <%s>\n", fn_rsp);
96 | return KAT_DATA_ERROR;
97 | }
98 |
99 | if(memcmp(ct,ct_rsp,CRYPTO_CIPHERTEXTBYTES)!=0){
100 | printf("ERROR: ct is different from <%s>\n", fn_rsp);
101 | return KAT_VERIFICATION_ERROR;
102 | }
103 | if(memcmp(ss,ss_rsp,CRYPTO_BYTES)!=0){
104 | printf("ERROR: ss is different from <%s>\n", fn_rsp);
105 | return KAT_VERIFICATION_ERROR;
106 | }
107 |
108 | if ( (ret_val = crypto_kem_dec_eFrodo640(ss1, ct, sk)) != 0) {
109 | printf("crypto_kem_dec returned <%d>\n", ret_val);
110 | return KAT_CRYPTO_FAILURE;
111 | }
112 |
113 | if ( memcmp(ss, ss1, CRYPTO_BYTES) ) {
114 | printf("crypto_kem_dec returned bad 'ss' value\n");
115 | return KAT_CRYPTO_FAILURE;
116 | }
117 |
118 | } while ( !done );
119 |
120 | fclose(fp_rsp);
121 | printf("Known Answer Tests PASSED. \n");
122 | printf("\n\n");
123 |
124 | return KAT_SUCCESS;
125 | }
126 |
127 |
128 | //
129 | // ALLOW TO READ HEXADECIMAL ENTRY (KEYS, DATA, TEXT, etc.)
130 | //
131 |
132 | int
133 | FindMarker(FILE *infile, const char *marker)
134 | {
135 | char line[MAX_MARKER_LEN];
136 | int i, len;
137 | int curr_line;
138 |
139 | len = (int)strlen(marker);
140 | if ( len > MAX_MARKER_LEN-1 )
141 | len = MAX_MARKER_LEN-1;
142 |
143 | for ( i=0; i= '0') && (ch <= '9') )
198 | ich = ch - '0';
199 | else if ( (ch >= 'A') && (ch <= 'F') )
200 | ich = ch - 'A' + 10;
201 | else if ( (ch >= 'a') && (ch <= 'f') )
202 | ich = ch - 'a' + 10;
203 | else // shouldn't ever get here
204 | ich = 0;
205 |
206 | for ( i=0; i> 4);
208 | A[Length-1] = (A[Length-1] << 4) | ich;
209 | }
210 | else
211 | return 0;
212 |
213 | return 1;
214 | }
215 |
216 | void
217 | fprintBstr(FILE *fp, char *S, unsigned char *A, unsigned long long L)
218 | {
219 | unsigned long long i;
220 |
221 | fprintf(fp, "%s", S);
222 |
223 | for ( i=0; i
9 | #include
10 | #include
11 | #include
12 | #include "rng.h"
13 | #include "../src/api_efrodo976.h"
14 |
15 | char AlgName[] = "eFrodoKEM-976-AES";
16 |
17 |
18 | #define MAX_MARKER_LEN 50
19 | #define KAT_SUCCESS 0
20 | #define KAT_FILE_OPEN_ERROR -1
21 | #define KAT_VERIFICATION_ERROR -2
22 | #define KAT_DATA_ERROR -3
23 | #define KAT_CRYPTO_FAILURE -4
24 |
25 | int FindMarker(FILE *infile, const char *marker);
26 | int ReadHex(FILE *infile, unsigned char *A, int Length, char *str);
27 | void fprintBstr(FILE *fp, char *S, unsigned char *A, unsigned long long L);
28 |
29 | int
30 | main()
31 | {
32 | char fn_rsp[32];
33 | FILE *fp_rsp;
34 | unsigned char seed[48];
35 | unsigned char ct[CRYPTO_CIPHERTEXTBYTES], ss[CRYPTO_BYTES], ss1[CRYPTO_BYTES], ct_rsp[CRYPTO_CIPHERTEXTBYTES], ss_rsp[CRYPTO_BYTES];
36 | int count;
37 | int done;
38 | unsigned char pk[CRYPTO_PUBLICKEYBYTES], sk[CRYPTO_SECRETKEYBYTES], pk_rsp[CRYPTO_PUBLICKEYBYTES], sk_rsp[CRYPTO_SECRETKEYBYTES];
39 | int ret_val;
40 |
41 | sprintf(fn_rsp, "KAT/PQCkemKAT_%d.rsp", CRYPTO_SECRETKEYBYTES);
42 | if ( (fp_rsp = fopen(fn_rsp, "r")) == NULL ) {
43 | printf("Couldn't open <%s> for read\n", fn_rsp);
44 | return KAT_FILE_OPEN_ERROR;
45 | }
46 |
47 | printf("# %s\n\n", AlgName);
48 | done = 0;
49 | do {
50 | if ( FindMarker(fp_rsp, "count = ") ) {
51 | if (fscanf(fp_rsp, "%d", &count) != 1) {
52 | done = 1;
53 | break;
54 | }
55 | } else {
56 | done = 1;
57 | break;
58 | }
59 |
60 | if ( !ReadHex(fp_rsp, seed, 48, "seed = ") ) {
61 | printf("ERROR: unable to read 'seed' from <%s>\n", fn_rsp);
62 | return KAT_DATA_ERROR;
63 | }
64 |
65 | randombytes_init(seed, NULL, 256);
66 |
67 | // Generate the public/private keypair
68 | if ( (ret_val = crypto_kem_keypair_enc_eFrodo976(ct, ss, pk, sk)) != 0) {
69 | printf("crypto_kem_keypair_enc returned <%d>\n", ret_val);
70 | return KAT_CRYPTO_FAILURE;
71 | }
72 | if ( !ReadHex(fp_rsp, pk_rsp, CRYPTO_PUBLICKEYBYTES, "pk = ") ) {
73 | printf("ERROR: unable to read 'pk' from <%s>\n", fn_rsp);
74 | return KAT_DATA_ERROR;
75 | }
76 | if ( !ReadHex(fp_rsp, sk_rsp, CRYPTO_SECRETKEYBYTES, "sk = ") ) {
77 | printf("ERROR: unable to read 'sk' from <%s>\n", fn_rsp);
78 | return KAT_DATA_ERROR;
79 | }
80 |
81 | if(memcmp(pk,pk_rsp,CRYPTO_PUBLICKEYBYTES)!=0){
82 | printf("ERROR: pk is different from <%s>\n", fn_rsp);
83 | return KAT_VERIFICATION_ERROR;
84 | }
85 | if(memcmp(sk,sk_rsp,CRYPTO_SECRETKEYBYTES)!=0){
86 | printf("ERROR: sk is different from <%s>\n", fn_rsp);
87 | return KAT_VERIFICATION_ERROR;
88 | }
89 |
90 | if (!ReadHex(fp_rsp, ct_rsp, CRYPTO_CIPHERTEXTBYTES, "ct = ")) {
91 | printf("ERROR: unable to read 'pk' from <%s>\n", fn_rsp);
92 | return KAT_DATA_ERROR;
93 | }
94 | if (!ReadHex(fp_rsp, ss_rsp, CRYPTO_BYTES, "ss = ")) {
95 | printf("ERROR: unable to read 'sk' from <%s>\n", fn_rsp);
96 | return KAT_DATA_ERROR;
97 | }
98 |
99 | if(memcmp(ct,ct_rsp,CRYPTO_CIPHERTEXTBYTES)!=0){
100 | printf("ERROR: ct is different from <%s>\n", fn_rsp);
101 | return KAT_VERIFICATION_ERROR;
102 | }
103 | if(memcmp(ss,ss_rsp,CRYPTO_BYTES)!=0){
104 | printf("ERROR: ss is different from <%s>\n", fn_rsp);
105 | return KAT_VERIFICATION_ERROR;
106 | }
107 |
108 | if ( (ret_val = crypto_kem_dec_eFrodo976(ss1, ct, sk)) != 0) {
109 | printf("crypto_kem_dec returned <%d>\n", ret_val);
110 | return KAT_CRYPTO_FAILURE;
111 | }
112 |
113 | if ( memcmp(ss, ss1, CRYPTO_BYTES) ) {
114 | printf("crypto_kem_dec returned bad 'ss' value\n");
115 | return KAT_CRYPTO_FAILURE;
116 | }
117 |
118 | } while ( !done );
119 |
120 | fclose(fp_rsp);
121 | printf("Known Answer Tests PASSED. \n");
122 | printf("\n\n");
123 |
124 | return KAT_SUCCESS;
125 | }
126 |
127 |
128 | //
129 | // ALLOW TO READ HEXADECIMAL ENTRY (KEYS, DATA, TEXT, etc.)
130 | //
131 |
132 | int
133 | FindMarker(FILE *infile, const char *marker)
134 | {
135 | char line[MAX_MARKER_LEN];
136 | int i, len;
137 | int curr_line;
138 |
139 | len = (int)strlen(marker);
140 | if ( len > MAX_MARKER_LEN-1 )
141 | len = MAX_MARKER_LEN-1;
142 |
143 | for ( i=0; i= '0') && (ch <= '9') )
198 | ich = ch - '0';
199 | else if ( (ch >= 'A') && (ch <= 'F') )
200 | ich = ch - 'A' + 10;
201 | else if ( (ch >= 'a') && (ch <= 'f') )
202 | ich = ch - 'a' + 10;
203 | else // shouldn't ever get here
204 | ich = 0;
205 |
206 | for ( i=0; i> 4);
208 | A[Length-1] = (A[Length-1] << 4) | ich;
209 | }
210 | else
211 | return 0;
212 |
213 | return 1;
214 | }
215 |
216 | void
217 | fprintBstr(FILE *fp, char *S, unsigned char *A, unsigned long long L)
218 | {
219 | unsigned long long i;
220 |
221 | fprintf(fp, "%s", S);
222 |
223 | for ( i=0; i
32 | ********************************************************************************************/
33 |
34 | /** \file ds_benchmark.h
35 | * Macros for simple benchmarking of C code.
36 | */
37 |
38 | #ifndef _DS_BENCHMARK_H
39 | #define _DS_BENCHMARK_H
40 |
41 | #include "../src/config.h"
42 | #include
43 | #include
44 | #include
45 | #if (OS_TARGET == OS_NIX)
46 | #include
47 | #endif
48 | #include
49 | #include
50 |
51 |
52 | #if (OS_TARGET == OS_WIN)
53 | #include
54 |
55 | int gettimeofday(struct timeval *tp, struct timezone *tzp) {
56 | // Note: some broken versions only have 8 trailing zero's, the correct epoch has 9 trailing zero's
57 | static const uint64_t EPOCH = ((uint64_t)116444736000000000ULL);
58 |
59 | SYSTEMTIME system_time;
60 | FILETIME file_time;
61 | uint64_t time;
62 |
63 | GetSystemTime(&system_time);
64 | SystemTimeToFileTime(&system_time, &file_time);
65 | time = ((uint64_t)file_time.dwLowDateTime);
66 | time += ((uint64_t)file_time.dwHighDateTime) << 32;
67 |
68 | tp->tv_sec = (long)((time - EPOCH) / 10000000L);
69 | tp->tv_usec = (long)(system_time.wMilliseconds * 1000);
70 | return 0;
71 | }
72 | #endif
73 |
74 |
75 | static uint64_t rdtsc(void) {
76 | #if (OS_TARGET == OS_WIN)
77 | return __rdtsc();
78 | #elif (OS_TARGET == OS_NIX) && (TARGET == TARGET_AMD64 || TARGET == TARGET_x86)
79 | uint64_t x;
80 | __asm__ volatile (".byte 0x0f, 0x31" : "=A" (x));
81 | return x;
82 | #elif (OS_TARGET == OS_NIX && TARGET == TARGET_ARM)
83 | struct timespec time;
84 | clock_gettime(CLOCK_REALTIME, &time);
85 | return (int64_t)(time.tv_sec*1e9 + time.tv_nsec);
86 | #else
87 | return 0;
88 | #endif
89 | }
90 |
91 |
92 | #define DEFINE_TIMER_VARIABLES \
93 | volatile uint64_t _bench_cycles_start, _bench_cycles_end; \
94 | uint64_t _bench_cycles_cumulative = 0; \
95 | int64_t _bench_cycles_diff, _bench_iterations; \
96 | struct timeval _bench_timeval_start, _bench_timeval_end; \
97 | double _bench_cycles_x, _bench_cycles_mean, _bench_cycles_delta, _bench_cycles_M2, _bench_cycles_stdev; \
98 | double _bench_time_x, _bench_time_mean, _bench_time_delta, _bench_time_M2, _bench_time_stdev, _bench_time_cumulative;
99 |
100 | #define INITIALIZE_TIMER \
101 | _bench_iterations = 0; \
102 | _bench_cycles_mean = 0.0; \
103 | _bench_cycles_M2 = 0.0; \
104 | _bench_time_cumulative = 0.0; \
105 | _bench_time_mean = 0.0; \
106 | _bench_time_M2 = 0.0;
107 |
108 | #define START_TIMER \
109 | gettimeofday(&_bench_timeval_start, NULL); \
110 | _bench_cycles_start = rdtsc();
111 |
112 |
113 | // Mean and population standard deviation are calculated in an online way using the algorithm in
114 | // http://en.wikipedia.org/wiki/Algorithms_for_calculating_variance#Online_algorithm
115 |
116 | #define STOP_TIMER \
117 | _bench_cycles_end = rdtsc(); \
118 | gettimeofday(&_bench_timeval_end, NULL); \
119 | _bench_iterations += 1; \
120 | if (_bench_cycles_end < _bench_cycles_start) { _bench_cycles_end += (uint64_t)1 << 32; } \
121 | _bench_cycles_diff = _bench_cycles_end; \
122 | _bench_cycles_diff -= _bench_cycles_start; \
123 | _bench_cycles_cumulative += _bench_cycles_diff; \
124 | _bench_cycles_x = (double) (_bench_cycles_diff); \
125 | _bench_cycles_delta = _bench_cycles_x - _bench_cycles_mean; \
126 | _bench_cycles_mean += _bench_cycles_delta / (double) _bench_iterations; \
127 | _bench_cycles_M2 += _bench_cycles_delta * (_bench_cycles_x - _bench_cycles_mean); \
128 | _bench_time_x = (double) ((_bench_timeval_end.tv_sec * 1000000 + _bench_timeval_end.tv_usec) - (_bench_timeval_start.tv_sec * 1000000 + _bench_timeval_start.tv_usec)); \
129 | _bench_time_delta = _bench_time_x - _bench_time_mean; \
130 | _bench_time_mean += _bench_time_delta / (double) _bench_iterations; \
131 | _bench_time_M2 += _bench_time_delta * (_bench_time_x - _bench_time_mean); \
132 | _bench_time_cumulative += _bench_time_x;
133 |
134 | #define FINALIZE_TIMER \
135 | if (_bench_iterations == 2) { _bench_cycles_stdev = 0.0; } \
136 | else { _bench_cycles_stdev = sqrt(_bench_cycles_M2 / (double) _bench_iterations); } \
137 | if (_bench_iterations == 2) { _bench_time_stdev = 0.0; } \
138 | else { _bench_time_stdev = sqrt(_bench_time_M2 / (double) _bench_iterations); }
139 |
140 | #if (TARGET == TARGET_ARM)
141 | #define PRINT_TIMER_HEADER \
142 | printf("%-30s %15s %15s %15s %15s\n", "Operation", "Iterations", "Total time (s)", "Time(us): mean", "pop. stdev");
143 | #else
144 | #define PRINT_TIMER_HEADER \
145 | printf("%-30s %15s %15s %15s %15s %15s %15s\n", "Operation", "Iterations", "Total time (s)", "Time(us): mean", "pop. stdev", "Cycles: mean", "pop. stdev");
146 | #endif
147 |
148 | #if (TARGET == TARGET_ARM)
149 | #define PRINT_TIMER_AVG(op_name) \
150 | printf("%-30s %15" PRIu64 " %15.3f %15.3f %15.3f\n", (op_name), _bench_iterations, _bench_time_cumulative / 1000000.0, _bench_time_mean, _bench_time_stdev); \
151 | (void)_bench_cycles_stdev;
152 | #else
153 | #define PRINT_TIMER_AVG(op_name) \
154 | printf("%-30s %15" PRIu64 " %15.3f %15.3f %15.3f %15.0f %15.0f\n", (op_name), _bench_iterations, _bench_time_cumulative / 1000000.0, _bench_time_mean, _bench_time_stdev, ((double) _bench_cycles_cumulative) / (double) _bench_iterations, _bench_cycles_stdev);
155 | #endif
156 |
157 | #define TIME_OPERATION_ITERATIONS(op, op_name, it) \
158 | { \
159 | DEFINE_TIMER_VARIABLES \
160 | INITIALIZE_TIMER \
161 | for (int i = 0; i < (it); i++) { \
162 | START_TIMER \
163 | { op ; } \
164 | STOP_TIMER \
165 | } \
166 | FINALIZE_TIMER \
167 | PRINT_TIMER_AVG(op_name) \
168 | }
169 |
170 | #define TIME_OPERATION_SECONDS(op, op_name, secs) \
171 | { \
172 | DEFINE_TIMER_VARIABLES \
173 | INITIALIZE_TIMER \
174 | uint64_t _bench_time_goal_usecs = 1000000 * secs; \
175 | while ((uint64_t)_bench_time_cumulative < _bench_time_goal_usecs) { \
176 | START_TIMER \
177 | { op ; } \
178 | STOP_TIMER \
179 | } \
180 | FINALIZE_TIMER \
181 | PRINT_TIMER_AVG(op_name) \
182 | }
183 | #endif
184 |
--------------------------------------------------------------------------------
/eFrodoKEM/tests/rng.c:
--------------------------------------------------------------------------------
1 | //
2 | // rng.c
3 | //
4 | // Created by Bassham, Lawrence E (Fed) on 8/29/17.
5 | // Copyright © 2017 Bassham, Lawrence E (Fed). All rights reserved.
6 | //
7 | // Modified to use OpenSSL's AES256_ECB or a standalone implementation
8 |
9 | #include
10 | #include "rng.h"
11 |
12 | AES256_CTR_DRBG_struct DRBG_ctx;
13 |
14 | void
15 | randombytes_init(unsigned char *entropy_input,
16 | unsigned char *personalization_string,
17 | int security_strength)
18 | {
19 | unsigned char seed_material[48];
20 |
21 | (void)security_strength; // Unused parameter
22 | memcpy(seed_material, entropy_input, 48);
23 | if (personalization_string)
24 | for (int i=0; i<48; i++)
25 | seed_material[i] ^= personalization_string[i];
26 | memset(DRBG_ctx.Key, 0x00, 32);
27 | memset(DRBG_ctx.V, 0x00, 16);
28 | AES256_CTR_DRBG_Update(seed_material, DRBG_ctx.Key, DRBG_ctx.V);
29 | DRBG_ctx.reseed_counter = 1;
30 | }
31 |
32 | int
33 | randombytes(unsigned char *x, unsigned long long xlen)
34 | {
35 | unsigned char block[16];
36 | int i = 0;
37 |
38 | while ( xlen > 0 ) {
39 | //increment V
40 | for (int j=15; j>=0; j--) {
41 | if ( DRBG_ctx.V[j] == 0xff )
42 | DRBG_ctx.V[j] = 0x00;
43 | else {
44 | DRBG_ctx.V[j]++;
45 | break;
46 | }
47 | }
48 | AES256_ECB(DRBG_ctx.Key, DRBG_ctx.V, block);
49 | if ( xlen > 15 ) {
50 | memcpy(x+i, block, 16);
51 | i += 16;
52 | xlen -= 16;
53 | }
54 | else {
55 | memcpy(x+i, block, xlen);
56 | xlen = 0;
57 | }
58 | }
59 | AES256_CTR_DRBG_Update(NULL, DRBG_ctx.Key, DRBG_ctx.V);
60 | DRBG_ctx.reseed_counter++;
61 |
62 | return RNG_SUCCESS;
63 | }
64 |
65 | void
66 | AES256_CTR_DRBG_Update(unsigned char *provided_data,
67 | unsigned char *Key,
68 | unsigned char *V)
69 | {
70 | unsigned char temp[48];
71 |
72 | for (int i=0; i<3; i++) {
73 | //increment V
74 | for (int j=15; j>=0; j--) {
75 | if ( V[j] == 0xff )
76 | V[j] = 0x00;
77 | else {
78 | V[j]++;
79 | break;
80 | }
81 | }
82 |
83 | AES256_ECB(Key, V, temp+16*i);
84 | }
85 | if ( provided_data != NULL )
86 | for (int i=0; i<48; i++)
87 | temp[i] ^= provided_data[i];
88 | memcpy(Key, temp, 32);
89 | memcpy(V, temp+32, 16);
90 | }
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
--------------------------------------------------------------------------------
/eFrodoKEM/tests/rng.h:
--------------------------------------------------------------------------------
1 | //
2 | // rng.h
3 | //
4 | // Created by Bassham, Lawrence E (Fed) on 8/29/17.
5 | // Copyright © 2017 Bassham, Lawrence E (Fed). All rights reserved.
6 | //
7 | // Modified to use OpenSSL's AES256_ECB or a standalone implementation
8 |
9 | #ifndef rng_h
10 | #define rng_h
11 |
12 | #include
13 | #include "../src/config.h"
14 | #if !defined(USE_OPENSSL)
15 | #include "../../common/aes/aes.h"
16 | #else
17 | #include "../../common/aes/aes_openssl.h"
18 | #endif
19 |
20 | #define RNG_SUCCESS 0
21 | #define RNG_BAD_MAXLEN -1
22 | #define RNG_BAD_OUTBUF -2
23 | #define RNG_BAD_REQ_LEN -3
24 |
25 | static __inline void AES256_ECB(unsigned char *key, unsigned char *ctr, unsigned char *buffer) {
26 | #if !defined(USE_OPENSSL)
27 | uint8_t schedule[16*15];
28 | AES256_load_schedule(key, schedule);
29 | AES256_ECB_enc_sch(ctr, 16, schedule, buffer);
30 | AES256_free_schedule(schedule);
31 | #else
32 | EVP_CIPHER_CTX *ctx;
33 | int len;
34 |
35 | /* Create and initialise the context */
36 | if(!(ctx = EVP_CIPHER_CTX_new())) handleErrors();
37 |
38 | if(1 != EVP_EncryptInit_ex(ctx, EVP_aes_256_ecb(), NULL, key, NULL))
39 | handleErrors();
40 |
41 | if(1 != EVP_EncryptUpdate(ctx, buffer, &len, ctr, 16))
42 | handleErrors();
43 |
44 | /* Clean up */
45 | EVP_CIPHER_CTX_free(ctx);
46 | #endif
47 | }
48 |
49 | typedef struct {
50 | unsigned char buffer[16];
51 | int buffer_pos;
52 | unsigned long length_remaining;
53 | unsigned char key[32];
54 | unsigned char ctr[16];
55 | } AES_XOF_struct;
56 |
57 | typedef struct {
58 | unsigned char Key[32];
59 | unsigned char V[16];
60 | int reseed_counter;
61 | } AES256_CTR_DRBG_struct;
62 |
63 |
64 | void
65 | AES256_CTR_DRBG_Update(unsigned char *provided_data,
66 | unsigned char *Key,
67 | unsigned char *V);
68 |
69 | void
70 | randombytes_init(unsigned char *entropy_input,
71 | unsigned char *personalization_string,
72 | int security_strength);
73 |
74 | int
75 | randombytes(unsigned char *x, unsigned long long xlen);
76 |
77 | #endif /* rng_h */
78 |
--------------------------------------------------------------------------------
/eFrodoKEM/tests/test_KEM1344.c:
--------------------------------------------------------------------------------
1 | /********************************************************************************************
2 | * FrodoKEM: Learning with Errors Key Encapsulation
3 | *
4 | * Abstract: setting parameters to test eFrodoKEM-1344
5 | *********************************************************************************************/
6 |
7 | #include
8 | #include
9 | #include
10 | #include
11 | #include "ds_benchmark.h"
12 | #include "../src/api_efrodo1344.h"
13 |
14 |
15 | #define SYSTEM_NAME "eFrodoKEM-1344"
16 |
17 | #define crypto_kem_keypair_enc crypto_kem_keypair_enc_eFrodo1344
18 | #define crypto_kem_dec crypto_kem_dec_eFrodo1344
19 | #define shake shake256
20 |
21 | #include "test_kem.c"
22 |
--------------------------------------------------------------------------------
/eFrodoKEM/tests/test_KEM640.c:
--------------------------------------------------------------------------------
1 | /********************************************************************************************
2 | * FrodoKEM: Learning with Errors Key Encapsulation
3 | *
4 | * Abstract: setting parameters to test eFrodoKEM-640
5 | *********************************************************************************************/
6 |
7 | #include
8 | #include
9 | #include
10 | #include
11 | #include "ds_benchmark.h"
12 | #include "../src/api_efrodo640.h"
13 |
14 |
15 | #define SYSTEM_NAME "eFrodoKEM-640"
16 |
17 | #define crypto_kem_keypair_enc crypto_kem_keypair_enc_eFrodo640
18 | #define crypto_kem_dec crypto_kem_dec_eFrodo640
19 | #define shake shake128
20 |
21 | #include "test_kem.c"
22 |
--------------------------------------------------------------------------------
/eFrodoKEM/tests/test_KEM976.c:
--------------------------------------------------------------------------------
1 | /********************************************************************************************
2 | * FrodoKEM: Learning with Errors Key Encapsulation
3 | *
4 | * Abstract: setting parameters to test eFrodoKEM-976
5 | *********************************************************************************************/
6 |
7 | #include
8 | #include
9 | #include
10 | #include
11 | #include "ds_benchmark.h"
12 | #include "../src/api_efrodo976.h"
13 |
14 |
15 | #define SYSTEM_NAME "eFrodoKEM-976"
16 |
17 | #define crypto_kem_keypair_enc crypto_kem_keypair_enc_eFrodo976
18 | #define crypto_kem_dec crypto_kem_dec_eFrodo976
19 | #define shake shake256
20 |
21 | #include "test_kem.c"
22 |
--------------------------------------------------------------------------------
/eFrodoKEM/tests/test_kem.c:
--------------------------------------------------------------------------------
1 | /********************************************************************************************
2 | * FrodoKEM: Learning with Errors Key Encapsulation
3 | *
4 | * Abstract: benchmarking/testing ephemeral KEM scheme
5 | *********************************************************************************************/
6 |
7 | #include "../../common/random/random.h"
8 | #include "../../common/sha3/fips202.h"
9 |
10 | #ifdef DO_VALGRIND_CHECK
11 | #include
12 | #endif
13 |
14 | #if defined(DO_VALGRIND_CHECK) || defined(_PPC_)
15 | #define KEM_TEST_ITERATIONS 1
16 | #else
17 | #define KEM_TEST_ITERATIONS 100
18 | #endif
19 | #define KEM_BENCH_SECONDS 1
20 |
21 |
22 | static int kem_test(const char *named_parameters, int iterations)
23 | {
24 | uint8_t pk[CRYPTO_PUBLICKEYBYTES];
25 | uint8_t sk[CRYPTO_SECRETKEYBYTES];
26 | uint8_t ss_encap[CRYPTO_BYTES], ss_decap[CRYPTO_BYTES];
27 | uint8_t ct[CRYPTO_CIPHERTEXTBYTES];
28 | unsigned char bytes[4];
29 | uint32_t* pos = (uint32_t*)bytes;
30 | uint8_t Fin[CRYPTO_CIPHERTEXTBYTES + CRYPTO_BYTES];
31 |
32 | #ifdef DO_VALGRIND_CHECK
33 | if (!RUNNING_ON_VALGRIND) {
34 | fprintf(stderr, "This test can only usefully be run inside valgrind.\n");
35 | fprintf(stderr, "valgrind efrodo640/test_KEM (or efrodo976 or efrodo1344)\n");
36 | exit(1);
37 | }
38 | #endif
39 |
40 | printf("\n");
41 | printf("=======================================================================================================================================\n");
42 | printf("Testing correctness of ephemeral key encapsulation mechanism (KEM), system %s, tests for %d iterations\n", named_parameters, iterations);
43 | printf("=======================================================================================================================================\n");
44 |
45 | for (int i = 0; i < iterations; i++) {
46 | if (crypto_kem_keypair_enc(ct, ss_encap, pk, sk) != 0) {
47 | printf("\n ERROR -- key generation and encapsulation mechanism failed!\n");
48 | return false;
49 | }
50 | crypto_kem_dec(ss_decap, ct, sk);
51 | #ifdef DO_VALGRIND_CHECK
52 | VALGRIND_MAKE_MEM_DEFINED(ss_encap, CRYPTO_BYTES);
53 | VALGRIND_MAKE_MEM_DEFINED(ss_decap, CRYPTO_BYTES);
54 | #endif
55 | if (memcmp(ss_encap, ss_decap, CRYPTO_BYTES) != 0) {
56 | printf("\n ERROR -- encapsulation/decapsulation mechanism failed!\n");
57 | return false;
58 | }
59 |
60 | // Testing decapsulation after changing random bits of a random 16-bit digit of ct
61 | randombytes(bytes, 4);
62 | *pos %= CRYPTO_CIPHERTEXTBYTES/2;
63 | if (*pos == 0) {
64 | *pos = 1;
65 | }
66 | ((uint16_t*)ct)[*pos] ^= *pos;
67 | crypto_kem_dec(ss_decap, ct, sk);
68 | #ifdef DO_VALGRIND_CHECK
69 | VALGRIND_MAKE_MEM_DEFINED(ss_decap, CRYPTO_BYTES);
70 | #endif
71 |
72 | // Compute ss = F(ct || s) with modified ct
73 | memcpy(Fin, ct, CRYPTO_CIPHERTEXTBYTES);
74 | memcpy(&Fin[CRYPTO_CIPHERTEXTBYTES], sk, CRYPTO_BYTES);
75 | shake(ss_encap, CRYPTO_BYTES, Fin, CRYPTO_CIPHERTEXTBYTES + CRYPTO_BYTES);
76 |
77 | #ifdef DO_VALGRIND_CHECK
78 | VALGRIND_MAKE_MEM_DEFINED(ss_encap, CRYPTO_BYTES);
79 | #endif
80 | if (memcmp(ss_encap, ss_decap, CRYPTO_BYTES) != 0) {
81 | printf("\n ERROR -- changing random bits of the ciphertext should cause a failure!\n");
82 | return false;
83 | }
84 | }
85 | printf("Tests PASSED. All session keys matched.\n");
86 | printf("\n\n");
87 |
88 | return true;
89 | }
90 |
91 |
92 | static void kem_bench(const int seconds)
93 | {
94 | uint8_t pk[CRYPTO_PUBLICKEYBYTES];
95 | uint8_t sk[CRYPTO_SECRETKEYBYTES];
96 | uint8_t ss_encap[CRYPTO_BYTES], ss_decap[CRYPTO_BYTES];
97 | uint8_t ct[CRYPTO_CIPHERTEXTBYTES];
98 |
99 | TIME_OPERATION_SECONDS({ crypto_kem_keypair_enc(ct, ss_encap, pk, sk); }, "Keygen and KEM encapsulate", seconds);
100 |
101 | crypto_kem_keypair_enc(ct, ss_encap, pk, sk);
102 | TIME_OPERATION_SECONDS({ crypto_kem_dec(ss_decap, ct, sk); }, "KEM decapsulate", seconds);
103 | }
104 |
105 |
106 | int main(int argc, char **argv)
107 | {
108 | int OK = true;
109 |
110 | OK = kem_test(SYSTEM_NAME, KEM_TEST_ITERATIONS);
111 | if (OK != true) {
112 | goto exit;
113 | }
114 |
115 | if ((argc > 1) && (strcmp("nobench", argv[1]) == 0)) {}
116 | else {
117 | PRINT_TIMER_HEADER
118 | kem_bench(KEM_BENCH_SECONDS);
119 | }
120 |
121 | exit:
122 | return (OK == true) ? EXIT_SUCCESS : EXIT_FAILURE;
123 | }
124 |
--------------------------------------------------------------------------------