├── .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 | --------------------------------------------------------------------------------