├── .github └── workflows │ └── oncici.yml ├── CMakeLists.txt ├── LICENSE ├── README.md ├── bench ├── CMakeLists.txt ├── bench.c ├── bench.h ├── bench_fp25519_x64.c ├── bench_fp448_x64.c ├── bench_x25519.c ├── bench_x448.c ├── clocks.c ├── clocks.h └── gbench.cpp ├── designers ├── fuzz ├── CMakeLists.txt ├── Makefile ├── README.md ├── fp.h ├── hacl │ ├── Hacl_Curve25519.c │ ├── Hacl_Curve25519.h │ ├── kremlib.c │ ├── kremlib.h │ └── kremlib_base.h ├── hacl_keygen.c ├── hacl_shared.c ├── opA24.c ├── opAdd.c ├── opInv.c ├── opMul.c ├── opRed.c ├── opSqr.c └── opSub.c ├── include ├── fp25519_x64.h ├── fp448_x64.h ├── rfc7748_precomputed.h ├── table_ladder_x25519.h └── table_ladder_x448.h ├── samples ├── CMakeLists.txt ├── sample_x25519.c └── sample_x448.c ├── src ├── CMakeLists.txt ├── fp25519_x64.c ├── fp448_x64.c ├── x25519_x64.c └── x448_x64.c ├── tests ├── CMakeLists.txt ├── runTests.cpp ├── test_fp25519_x64.cpp ├── test_fp448_x64.cpp ├── test_x25519.cpp └── test_x448.cpp └── third_party ├── random.c └── random.h /.github/workflows/oncici.yml: -------------------------------------------------------------------------------- 1 | name: OnCICI 2 | 3 | on: [push] 4 | 5 | jobs: 6 | build: 7 | name: Benchmarking 8 | runs-on: ubuntu-latest 9 | strategy: 10 | matrix: 11 | compiler: [ [gcc,g++], [clang,clang++] ] 12 | steps: 13 | - uses: actions/checkout@master 14 | - name: Building 15 | env: 16 | CC: ${{ matrix.compiler[0] }} 17 | CXX: ${{ matrix.compiler[1] }} 18 | run: | 19 | mkdir build 20 | cd build 21 | cmake .. 22 | make gbench 23 | - name: Benchmarking 24 | run: | 25 | cd build 26 | bin/gbench --benchmark_out=timings_${{ matrix.compiler[0] }}.txt --benchmark_out_format=console 27 | - uses: actions/upload-artifact@v1 28 | with: 29 | name: Timings 30 | path: build/timings_${{ matrix.compiler[0] }}.txt 31 | test: 32 | name: Testing 33 | runs-on: ubuntu-latest 34 | steps: 35 | - uses: actions/checkout@master 36 | - name: Building 37 | run: | 38 | mkdir build 39 | cd build 40 | cmake .. 41 | make tests 42 | - name: Testing 43 | run: | 44 | cd build 45 | bin/tests 46 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.0.2) 2 | project(rfc7748_precomputed C) 3 | 4 | set(EXECUTABLE_OUTPUT_PATH ../bin) 5 | set(LIBRARY_OUTPUT_PATH ../lib) 6 | set(TARGET rfc7748_precomputed) 7 | 8 | 9 | add_subdirectory(src) 10 | add_subdirectory(samples) 11 | add_subdirectory(tests EXCLUDE_FROM_ALL) 12 | add_subdirectory(bench EXCLUDE_FROM_ALL) 13 | add_subdirectory(fuzz) 14 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD-3 License. 2 | 3 | Copyright (c) 2017, Armando Faz . All rights reserved. 4 | Institute of Computing. 5 | University of Campinas, Brazil. 6 | 7 | Redistribution and use in source and binary forms, with or without 8 | modification, are permitted provided that the following conditions 9 | are met: 10 | 11 | * Redistributions of source code must retain the above copyright 12 | notice, this list of conditions and the following disclaimer. 13 | * Redistributions in binary form must reproduce the above 14 | copyright notice, this list of conditions and the following 15 | disclaimer in the documentation and/or other materials provided 16 | with the distribution. 17 | * Neither the name of University of Campinas nor the names of its 18 | contributors may be used to endorse or promote products derived 19 | from this software without specific prior written permission. 20 | 21 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 24 | FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 25 | COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 26 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 27 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 28 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 30 | STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 31 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 32 | OF THE POSSIBILITY OF SUCH DAMAGE. 33 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # How to (pre-)compute a ladder 3 | 4 | 5 | This is a C-language software library that provides optimized implementations of the Diffie-Hellman functions known as X25519 and X448 ([RFC-7748](https://datatracker.ietf.org/doc/rfc7748/)) for 64-bit architectures. 6 | 7 | This source code is part of the research work titled: _"How to (pre-)compute a ladder"_ by the authors: 8 | * [Thomaz Oliveira](http://dblp.uni-trier.de/pers/hd/o/Oliveira:Thomaz), Computer Science Department, Cinvestav-IPN, Mexico. 9 | * [Julio López](http://www.ic.unicamp.br/pessoas/docentes/jlopez), University of Campinas, Brazil. 10 | * [Hüseyin Hisil](http://hhisil.yasar.edu.tr/), Yasar University, Turkey. 11 | * [Armando Faz-Hernández](http://www.ic.unicamp.br/~armfazh), University of Campinas, Brazil. 12 | * [Francisco Rodríguez-Henríquez](http://delta.cs.cinvestav.mx/~francisco/), Computer Science Department, Cinvestav-IPN, Mexico. 13 | 14 | 15 | ---- 16 | 17 | ### Research Resources 18 | 19 | A peer-reviewed paper was presented in the 24th Annual Conference on Selected Areas in Cryptography ([SAC2017](http://sacworkshop.org/SAC17/SAC2017.htm)). 20 | - Paper [[DOI](http://doi.org/10.1007/978-3-319-72565-9_9)] 21 | - Slides [[PDF](http://www.ic.unicamp.br/~ra142685/userfiles/papers/oliveira_sac2017.pdf)]. 22 | - Pre-print (IACR ePrint Archive) [http://iacr.eprint.org/2017/264](https://eprint.iacr.org/2017/264) [[PDF](https://eprint.iacr.org/2017/264.pdf)] 23 | 24 | 25 | To cite this work use: 26 | 27 | ```tex 28 | @inproceedings{oliveira_sac2017, 29 | author = {Thomaz Oliveira and Julio L\'opez and 30 | H\"useyin H{\i}\c{s}{\i}l and Armando Faz-Hern\'andez and 31 | Francisco Rodr\'iguez-Henr\'iquez}, 32 | editor = {Adams, Carlisle and Camenisch, Jan}, 33 | title = {How to (pre-)compute a ladder}, 34 | booktitle = {Selected Areas in Cryptography – SAC 2017: 35 | 24th International Conference, Ottawa, Ontario, 36 | Canada, August 16 - 18, 2017, Revised Selected Papers}, 37 | year = {2018}, 38 | publisher = {Springer International Publishing}, 39 | pages = {172-191}, 40 | doi = {10.1007/978-3-319-72565-9_9}, 41 | } 42 | ``` 43 | ---- 44 | 45 | ### Implementation Details 46 | * Prime field arithmetic is optimized for the 4th and 6th generation of Intel Core processors (Haswell and Skylake micro-architectures). 47 | * Efficient integer multiplication using MULX instruction. 48 | * Integer additions accelerated with ADCX/ADOX instructions. 49 | * Key generation uses a read-only table of 8 KB (25 KB) for X25519 (X448). 50 | * It follows secure coding countermeasures. 51 | 52 | ---- 53 | 54 | ### Pre-requirements 55 | 56 | This library is a standalone C-language code. However, for tests we use C++ code. 57 | - C and C++ compilers. 58 | - git 59 | - cmake 60 | 61 | ### Compilation 62 | First, clone the repository and configure project using the [CMake](https://cmake.org/) tool: 63 | 64 | ```sh 65 | $ git clone https://github.com/armfazh/rfc7748_precomputed 66 | $ cd rfc7748_precomputed 67 | $ mkdir build 68 | $ cd build 69 | ``` 70 | 71 | To specify an alternative C/C++ compiler set the following variables: 72 | 73 | ```sh 74 | $ CC=gcc CXX=g++ cmake .. 75 | ``` 76 | 77 | Also, to specify a custom install directory (`install_dir`) use: 78 | 79 | ```sh 80 | $ cmake -DCMAKE_INSTALL_PREFIX=install_dir .. 81 | ``` 82 | 83 | Finally, compile and install: 84 | 85 | ```sh 86 | $ make 87 | $ make install (optional) 88 | ``` 89 | 90 | ---- 91 | 92 | ### Running Companion Programs 93 | Once compilation was done, you can run some companion programs. 94 | 95 | For running a sample program use: 96 | ```sh 97 | $ bin/sample_x25519 98 | $ bin/sample_x448 99 | ``` 100 | 101 | For running a performance benchmark (in clock cycles) use: 102 | ```sh 103 | $ make bench 104 | $ bin/bench 105 | ``` 106 | 107 | For running the [Google benchmark](https://github.com/google/benchmark) tool use: 108 | 109 | ```sh 110 | $ make gbench 111 | $ bin/gbench --benchmark_repetitions=10 --benchmark_display_aggregates_only=true 112 | ``` 113 | 114 | For running the [Google Test](https://github.com/google/googletest) tool use: 115 | 116 | ```sh 117 | $ make tests 118 | $ bin/tests 119 | ``` 120 | 121 | #### Fuzzing Test 122 | 123 | In the *fuzz* folder, there are several tests against `gmp` library and the `HACL` project. Read the compilation instructions at *fuzz/README.md* for more information. 124 | 125 | ---- 126 | 127 | 128 | ### Timings 129 | Benchmark performance on 64-bit Intel architectures (table entries are clock cycles). 130 | 131 | | X25519 | Haswell | Skylake | 132 | | ------ | ------:| ------:| 133 | | Key Generation | 92,400 | 69,500 | 134 | | Shared Secret | 145,800 | 108,700 | 135 | 136 | | X448 | Haswell | Skylake | 137 | | ------ | ------:| ------:| 138 | | Key Generation | 401,902 | 322,040 | 139 | | Shared Secret | 670,747 | 528,470 | 140 | 141 | **Haswell** is a Core i7-4770 processor. 142 | 143 | **Skylake** is a Core i7-6700K processor. 144 | 145 | ---- 146 | 147 | ### License 148 | BSD-3 Clause License ([LICENSE](./LICENSE)) 149 | 150 | ---- 151 | 152 | ### Contact 153 | 154 | To report some issues or comments of this project, please use the issues webpage [[here](https://github.com/armfazh/rfc7748_precomputed/issues)]. 155 | 156 | ---- 157 | -------------------------------------------------------------------------------- /bench/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.0.2) 2 | enable_language(CXX) 3 | set(CMAKE_CXX_STANDARD 11) 4 | 5 | include(ExternalProject) 6 | include("GNUInstallDirs") 7 | set(GBENCH_VERSION "v1.5.0") 8 | ExternalProject_Add(benchmark-download 9 | URL "https://api.github.com/repos/google/benchmark/tarball/${GBENCH_VERSION}" 10 | CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${CMAKE_CURRENT_BINARY_DIR} 11 | -DCMAKE_CXX_COMPILER:FILEPATH=${CMAKE_CXX_COMPILER} 12 | -DCMAKE_POSITION_INDEPENDENT_CODE=ON 13 | -DCMAKE_BUILD_TYPE=Release 14 | -DBENCHMARK_ENABLE_TESTING=OFF 15 | -DBENCHMARK_ENABLE_GTEST_TESTS=OFF 16 | TEST_COMMAND "" 17 | UPDATE_COMMAND "" 18 | ) 19 | include_directories(${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_INSTALL_INCLUDEDIR}) 20 | link_directories(${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}) 21 | 22 | include_directories(../include) 23 | include_directories(../third_party) 24 | 25 | add_executable(bench 26 | clocks.h 27 | clocks.c 28 | bench.h 29 | bench_fp25519_x64.c 30 | bench_fp448_x64.c 31 | bench_x25519.c 32 | bench_x448.c 33 | bench.c 34 | ../third_party/random.c 35 | ) 36 | add_dependencies(bench ${TARGET}) 37 | target_link_libraries(bench ${TARGET}) 38 | 39 | add_executable(gbench gbench.cpp ../third_party/random.c) 40 | add_dependencies(gbench ${TARGET} benchmark-download) 41 | target_link_libraries(gbench ${TARGET} benchmark pthread) 42 | -------------------------------------------------------------------------------- /bench/bench.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2017, Armando Faz . All rights reserved. 3 | * Institute of Computing. 4 | * University of Campinas, Brazil. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions 8 | * are met: 9 | * 10 | * * Redistributions of source code must retain the above copyright 11 | * notice, this list of conditions and the following disclaimer. 12 | * * Redistributions in binary form must reproduce the above 13 | * copyright notice, this list of conditions and the following 14 | * disclaimer in the documentation and/or other materials provided 15 | * with the distribution. 16 | * * Neither the name of University of Campinas nor the names of its 17 | * contributors may be used to endorse or promote products derived 18 | * from this software without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 23 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 24 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 25 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 26 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 29 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 31 | * OF THE POSSIBILITY OF SUCH DAMAGE. 32 | */ 33 | 34 | #include "bench.h" 35 | #include 36 | 37 | int main(void) { 38 | printf("== Start of Benchmark ===\n"); 39 | bench_fp25519_x64(); 40 | bench_x25519(); 41 | bench_fp448_x64(); 42 | bench_x448(); 43 | printf("== End of Benchmark =====\n"); 44 | return 0; 45 | } 46 | -------------------------------------------------------------------------------- /bench/bench.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2017, Armando Faz . All rights reserved. 3 | * Institute of Computing. 4 | * University of Campinas, Brazil. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions 8 | * are met: 9 | * 10 | * * Redistributions of source code must retain the above copyright 11 | * notice, this list of conditions and the following disclaimer. 12 | * * Redistributions in binary form must reproduce the above 13 | * copyright notice, this list of conditions and the following 14 | * disclaimer in the documentation and/or other materials provided 15 | * with the distribution. 16 | * * Neither the name of University of Campinas nor the names of its 17 | * contributors may be used to endorse or promote products derived 18 | * from this software without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 23 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 24 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 25 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 26 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 29 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 31 | * OF THE POSSIBILITY OF SUCH DAMAGE. 32 | */ 33 | 34 | #ifndef BENCH_H 35 | #define BENCH_H 36 | 37 | void bench_fp25519_x64(); 38 | void bench_x25519(); 39 | void bench_fp448_x64(); 40 | void bench_x448(); 41 | 42 | #endif /* BENCH_H */ 43 | -------------------------------------------------------------------------------- /bench/bench_fp25519_x64.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2017, Armando Faz . All rights reserved. 3 | * Institute of Computing. 4 | * University of Campinas, Brazil. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions 8 | * are met: 9 | * 10 | * * Redistributions of source code must retain the above copyright 11 | * notice, this list of conditions and the following disclaimer. 12 | * * Redistributions in binary form must reproduce the above 13 | * copyright notice, this list of conditions and the following 14 | * disclaimer in the documentation and/or other materials provided 15 | * with the distribution. 16 | * * Neither the name of University of Campinas nor the names of its 17 | * contributors may be used to endorse or promote products derived 18 | * from this software without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 23 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 24 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 25 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 26 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 29 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 31 | * OF THE POSSIBILITY OF SUCH DAMAGE. 32 | */ 33 | 34 | #include 35 | #include 36 | #include "clocks.h" 37 | #include "random.h" 38 | 39 | static void random_EltFp25519_1w_x64(uint64_t *A) { 40 | random_bytes((uint8_t *)A, SIZE_BYTES_FP25519); 41 | } 42 | 43 | void bench_fp25519_x64(void) { 44 | int BENCH = 3000; 45 | 46 | EltFp25519_1w_x64 a, b, c; 47 | EltFp25519_2w_x64 BB, CC; 48 | EltFp25519_1w_Buffer_x64 buffer_1w; 49 | EltFp25519_2w_Buffer_x64 buffer_2w; 50 | 51 | random_EltFp25519_1w_x64(a); 52 | random_EltFp25519_1w_x64(b); 53 | random_EltFp25519_1w_x64(c); 54 | 55 | printf("=== GF(2^255-19) ===\n"); 56 | printf("== 1-way x64 \n"); 57 | CLOCKS("add", add_EltFp25519_1w_x64(c, a, b)); 58 | CLOCKS("sub", sub_EltFp25519_1w_x64(c, a, b)); 59 | CLOCKS("mul", mul_EltFp25519_1w_x64(c, c, b)); 60 | CLOCKS("m24", mul_a24_EltFp25519_1w_x64(c, a)); 61 | CLOCKS("sqr", sqr_EltFp25519_1w_x64(c)); 62 | 63 | BENCH /= 10; 64 | CLOCKS("inv", inv_EltFp25519_1w_x64(c, a)); 65 | BENCH *= 10; 66 | 67 | printf("== 2-way x64 \n"); 68 | CLOCKS("mul", mul_EltFp25519_2w_x64(CC, CC, BB)); 69 | CLOCKS("sqr", sqr_EltFp25519_2w_x64(CC)); 70 | } 71 | -------------------------------------------------------------------------------- /bench/bench_fp448_x64.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2017, Armando Faz . All rights reserved. 3 | * Institute of Computing. 4 | * University of Campinas, Brazil. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions 8 | * are met: 9 | * 10 | * * Redistributions of source code must retain the above copyright 11 | * notice, this list of conditions and the following disclaimer. 12 | * * Redistributions in binary form must reproduce the above 13 | * copyright notice, this list of conditions and the following 14 | * disclaimer in the documentation and/or other materials provided 15 | * with the distribution. 16 | * * Neither the name of University of Campinas nor the names of its 17 | * contributors may be used to endorse or promote products derived 18 | * from this software without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 23 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 24 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 25 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 26 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 29 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 31 | * OF THE POSSIBILITY OF SUCH DAMAGE. 32 | */ 33 | 34 | #include 35 | #include 36 | #include "clocks.h" 37 | #include "random.h" 38 | 39 | static void random_EltFp448_1w_x64(uint64_t *A) { 40 | random_bytes((uint8_t *)A, SIZE_BYTES_FP448); 41 | } 42 | 43 | void bench_fp448_x64(void) { 44 | int BENCH = 3000; 45 | 46 | EltFp448_1w_x64 a, b, c; 47 | EltFp448_1w_Buffer_x64 buffer_1w; 48 | 49 | random_EltFp448_1w_x64(a); 50 | random_EltFp448_1w_x64(b); 51 | random_EltFp448_1w_x64(c); 52 | 53 | printf("= GF(2^448-2^224-1) =\n"); 54 | printf("== 1-way x64 \n"); 55 | CLOCKS("add", add_EltFp448_1w_x64(c, a, b)); 56 | CLOCKS("sub", sub_EltFp448_1w_x64(c, a, b)); 57 | CLOCKS("mul", mul_EltFp448_1w_x64(c, c, b)); 58 | CLOCKS("m24", mul_a24_EltFp448_1w_x64(c, a)); 59 | CLOCKS("sqr", sqr_EltFp448_1w_x64(c)); 60 | 61 | BENCH /= 10; 62 | CLOCKS("inv", inv_EltFp448_1w_x64(c, a)); 63 | } 64 | -------------------------------------------------------------------------------- /bench/bench_x25519.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2017, Armando Faz . All rights reserved. 3 | * Institute of Computing. 4 | * University of Campinas, Brazil. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions 8 | * are met: 9 | * 10 | * * Redistributions of source code must retain the above copyright 11 | * notice, this list of conditions and the following disclaimer. 12 | * * Redistributions in binary form must reproduce the above 13 | * copyright notice, this list of conditions and the following 14 | * disclaimer in the documentation and/or other materials provided 15 | * with the distribution. 16 | * * Neither the name of University of Campinas nor the names of its 17 | * contributors may be used to endorse or promote products derived 18 | * from this software without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 23 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 24 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 25 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 26 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 29 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 31 | * OF THE POSSIBILITY OF SUCH DAMAGE. 32 | */ 33 | 34 | #include 35 | #include "clocks.h" 36 | #include "random.h" 37 | 38 | static void random_X25519_key(argKey key) { 39 | random_bytes(key, X25519_KEYSIZE_BYTES); 40 | } 41 | 42 | void bench_x25519(void) { 43 | X25519_KEY secret_key; 44 | X25519_KEY public_key; 45 | X25519_KEY shared_secret; 46 | 47 | printf("===== X225519 =====\n"); 48 | oper_second(random_X25519_key(secret_key), "KeyGen", 49 | X25519_KeyGen(public_key, secret_key)); 50 | oper_second(random_X25519_key(secret_key); 51 | random_X25519_key(public_key), "Shared", 52 | X25519_Shared(shared_secret, public_key, secret_key)); 53 | } 54 | -------------------------------------------------------------------------------- /bench/bench_x448.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2017, Armando Faz . All rights reserved. 3 | * Institute of Computing. 4 | * University of Campinas, Brazil. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions 8 | * are met: 9 | * 10 | * * Redistributions of source code must retain the above copyright 11 | * notice, this list of conditions and the following disclaimer. 12 | * * Redistributions in binary form must reproduce the above 13 | * copyright notice, this list of conditions and the following 14 | * disclaimer in the documentation and/or other materials provided 15 | * with the distribution. 16 | * * Neither the name of University of Campinas nor the names of its 17 | * contributors may be used to endorse or promote products derived 18 | * from this software without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 23 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 24 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 25 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 26 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 29 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 31 | * OF THE POSSIBILITY OF SUCH DAMAGE. 32 | */ 33 | 34 | #include 35 | #include 36 | #include "clocks.h" 37 | #include "random.h" 38 | 39 | static void random_X448_key(argKey key) { 40 | random_bytes(key, X448_KEYSIZE_BYTES); 41 | } 42 | 43 | void bench_x448(void) { 44 | X448_KEY secret_key; 45 | X448_KEY public_key; 46 | X448_KEY shared_secret; 47 | 48 | printf("===== X448 =====\n"); 49 | oper_second(random_X448_key(secret_key), "KeyGen", 50 | X448_KeyGen(public_key, secret_key)); 51 | oper_second(random_X448_key(secret_key); 52 | random_X448_key(public_key), "Shared", 53 | X448_Shared(shared_secret, public_key, secret_key)); 54 | } 55 | -------------------------------------------------------------------------------- /bench/clocks.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2017, Armando Faz . All rights reserved. 3 | * Institute of Computing. 4 | * University of Campinas, Brazil. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions 8 | * are met: 9 | * 10 | * * Redistributions of source code must retain the above copyright 11 | * notice, this list of conditions and the following disclaimer. 12 | * * Redistributions in binary form must reproduce the above 13 | * copyright notice, this list of conditions and the following 14 | * disclaimer in the documentation and/or other materials provided 15 | * with the distribution. 16 | * * Neither the name of University of Campinas nor the names of its 17 | * contributors may be used to endorse or promote products derived 18 | * from this software without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 23 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 24 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 25 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 26 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 29 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 31 | * OF THE POSSIBILITY OF SUCH DAMAGE. 32 | */ 33 | 34 | #include "clocks.h" 35 | #include 36 | 37 | uint64_t time_now() { 38 | struct timeval tv; 39 | uint64_t ret; 40 | 41 | gettimeofday(&tv, NULL); 42 | ret = tv.tv_sec; 43 | ret *= 1000000; 44 | ret += tv.tv_usec; 45 | 46 | return ret; 47 | } 48 | 49 | /** 50 | * Taken from 51 | * agl/curve25519-donna 52 | * https://github.com/agl/curve25519-donna/blob/master/speed-curve25519.c 53 | * 54 | * ticks - not tested on anything other than x86 55 | * */ 56 | uint64_t cycles_now(void) { 57 | #if defined(__GNUC__) 58 | uint32_t lo, hi; 59 | __asm__ __volatile__("rdtsc" : "=a"(lo), "=d"(hi)); 60 | return ((uint64_t)lo | ((uint64_t)hi << 32)); 61 | #else 62 | return 0; /* Undefined for now; should be obvious in the output */ 63 | #endif 64 | } 65 | -------------------------------------------------------------------------------- /bench/clocks.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2017, Armando Faz . All rights reserved. 3 | * Institute of Computing. 4 | * University of Campinas, Brazil. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions 8 | * are met: 9 | * 10 | * * Redistributions of source code must retain the above copyright 11 | * notice, this list of conditions and the following disclaimer. 12 | * * Redistributions in binary form must reproduce the above 13 | * copyright notice, this list of conditions and the following 14 | * disclaimer in the documentation and/or other materials provided 15 | * with the distribution. 16 | * * Neither the name of University of Campinas nor the names of its 17 | * contributors may be used to endorse or promote products derived 18 | * from this software without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 23 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 24 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 25 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 26 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 29 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 31 | * OF THE POSSIBILITY OF SUCH DAMAGE. 32 | */ 33 | 34 | #ifndef CLOCKS_H 35 | #define CLOCKS_H 36 | 37 | #include 38 | #include 39 | #include 40 | 41 | #ifdef __INTEL_COMPILER 42 | #define BARRIER __memory_barrier() 43 | #else 44 | #define BARRIER __asm__ __volatile__("" ::: "memory") 45 | #endif 46 | 47 | #define CLOCKS_RANDOM(RANDOM, LABEL, FUNCTION) \ 48 | do { \ 49 | uint64_t start, end; \ 50 | int64_t i_bench, j_bench; \ 51 | unsigned cycles_high0, cycles_low0; \ 52 | unsigned cycles_high1, cycles_low1; \ 53 | __asm__ __volatile__( \ 54 | "mfence\n\t" \ 55 | "RDTSC\n\t" \ 56 | "mov %%edx, %0\n\t" \ 57 | "mov %%eax, %1\n\t" \ 58 | : "=r"(cycles_high0), "=r"(cycles_low0)::"%rax", "%rbx", "%rcx", \ 59 | "%rdx"); \ 60 | BARRIER; \ 61 | i_bench = BENCH; \ 62 | do { \ 63 | j_bench = BENCH; \ 64 | RANDOM; \ 65 | do { \ 66 | FUNCTION; \ 67 | j_bench--; \ 68 | } while (j_bench != 0); \ 69 | i_bench--; \ 70 | } while (i_bench != 0); \ 71 | BARRIER; \ 72 | __asm__ __volatile__( \ 73 | "RDTSCP\n\t" \ 74 | "mov %%edx, %0\n\t" \ 75 | "mov %%eax, %1\n\t" \ 76 | "mfence\n\t" \ 77 | : "=r"(cycles_high1), "=r"(cycles_low1)::"%rax", "%rbx", "%rcx", \ 78 | "%rdx"); \ 79 | start = (((uint64_t)cycles_high0) << 32) | cycles_low0; \ 80 | end = (((uint64_t)cycles_high1) << 32) | cycles_low1; \ 81 | printf("%-8s: %5lu cc\n", LABEL, (end - start) / (BENCH * BENCH)); \ 82 | } while (0) 83 | 84 | #define CLOCKS(LABEL, FUNCTION) CLOCKS_RANDOM(while (0), LABEL, FUNCTION) 85 | 86 | #define oper_second(RANDOM, LABEL, FUNCTION) \ 87 | do { \ 88 | printf("%-8s: ", LABEL); \ 89 | RANDOM; \ 90 | \ 91 | unsigned i; \ 92 | uint64_t start, end; \ 93 | const unsigned iterations = 10000; \ 94 | uint64_t start_c, end_c; \ 95 | \ 96 | /* Load the caches*/ \ 97 | for (i = 0; i < 500; ++i) { \ 98 | FUNCTION; \ 99 | } \ 100 | \ 101 | start = time_now(); \ 102 | start_c = cycles_now(); \ 103 | for (i = 0; i < iterations; ++i) { \ 104 | FUNCTION; \ 105 | } \ 106 | end = time_now(); \ 107 | end_c = cycles_now(); \ 108 | \ 109 | printf("%3lu µs, %8.1f oper/s, %6lu cycles/op\n", \ 110 | (uint64_t)((end - start) / iterations), \ 111 | iterations*(double)1e6 / (end - start), \ 112 | (uint64_t)((end_c - start_c) / iterations)); \ 113 | } while (0) 114 | 115 | uint64_t time_now(); 116 | uint64_t cycles_now(void); 117 | 118 | #endif /* CLOCKS_H */ 119 | -------------------------------------------------------------------------------- /bench/gbench.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2017, Armando Faz . All rights reserved. 3 | * Institute of Computing. 4 | * University of Campinas, Brazil. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions 8 | * are met: 9 | * 10 | * * Redistributions of source code must retain the above copyright 11 | * notice, this list of conditions and the following disclaimer. 12 | * * Redistributions in binary form must reproduce the above 13 | * copyright notice, this list of conditions and the following 14 | * disclaimer in the documentation and/or other materials provided 15 | * with the distribution. 16 | * * Neither the name of University of Campinas nor the names of its 17 | * contributors may be used to endorse or promote products derived 18 | * from this software without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 23 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 24 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 25 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 26 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 29 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 31 | * OF THE POSSIBILITY OF SUCH DAMAGE. 32 | */ 33 | 34 | #include "benchmark/benchmark.h" 35 | #include "random.h" 36 | #include 37 | 38 | static void BM_X25519_KeyGen(benchmark::State &state) { 39 | X25519_KEY secret_key; 40 | X25519_KEY public_key; 41 | random_bytes(secret_key, X25519_KEYSIZE_BYTES); 42 | for (auto _ : state) { 43 | X25519_KeyGen(public_key, secret_key); 44 | } 45 | } 46 | 47 | static void BM_X25519_Shared(benchmark::State &state) { 48 | X25519_KEY secret_key; 49 | X25519_KEY public_key; 50 | X25519_KEY shared_key; 51 | random_bytes(secret_key, X25519_KEYSIZE_BYTES); 52 | random_bytes(public_key, X25519_KEYSIZE_BYTES); 53 | for (auto _ : state) { 54 | X25519_Shared(shared_key, public_key, secret_key); 55 | } 56 | } 57 | 58 | static void BM_X448_KeyGen(benchmark::State &state) { 59 | X448_KEY secret_key; 60 | X448_KEY public_key; 61 | random_bytes(secret_key, X448_KEYSIZE_BYTES); 62 | for (auto _ : state) { 63 | X448_KeyGen(public_key, secret_key); 64 | } 65 | } 66 | 67 | static void BM_X448_Shared(benchmark::State &state) { 68 | X448_KEY secret_key; 69 | X448_KEY public_key; 70 | X448_KEY shared_key; 71 | random_bytes(secret_key, X448_KEYSIZE_BYTES); 72 | random_bytes(public_key, X448_KEYSIZE_BYTES); 73 | for (auto _ : state) { 74 | X448_Shared(shared_key, public_key, secret_key); 75 | } 76 | } 77 | 78 | BENCHMARK(BM_X25519_KeyGen)->Unit(benchmark::kMicrosecond); 79 | BENCHMARK(BM_X25519_Shared)->Unit(benchmark::kMicrosecond); 80 | BENCHMARK(BM_X448_KeyGen)->Unit(benchmark::kMicrosecond); 81 | BENCHMARK(BM_X448_Shared)->Unit(benchmark::kMicrosecond); 82 | 83 | BENCHMARK_MAIN(); 84 | -------------------------------------------------------------------------------- /designers: -------------------------------------------------------------------------------- 1 | Thomaz Oliveira, Computer Science Department, Cinvestav-IPN, Mexico. 2 | Julio López, University of Campinas, Brazil. 3 | Hüseyin Hisil, Yasar University, Turkey. 4 | Armando Faz-Hernández, University of Campinas, Brazil. 5 | Francisco Rodríguez-Henríquez, Computer Science Department, Cinvestav-IPN, Mexico. 6 | -------------------------------------------------------------------------------- /fuzz/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.0.2) 2 | 3 | include_directories(../include) 4 | include_directories(./hacl) 5 | 6 | set(CMAKE_C_COMPILER clang) 7 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=fuzzer,address") 8 | find_package(GMP QUIET) 9 | 10 | add_custom_target(fuzz) 11 | set_target_properties(fuzz PROPERTIES EXCLUDE_FROM_ALL true) 12 | 13 | add_custom_target(fuzz_hacl) 14 | add_dependencies(fuzz fuzz_hacl) 15 | file(GLOB FUZZ_HACL_SOURCES ./hacl_*.c) 16 | foreach (file ${FUZZ_HACL_SOURCES}) 17 | get_filename_component(tmp_name ${file} NAME_WE) 18 | add_executable(fuzz_${tmp_name} EXCLUDE_FROM_ALL ${file} ./hacl/Hacl_Curve25519.c) 19 | target_link_libraries(fuzz_${tmp_name} ${TARGET}) 20 | add_dependencies(fuzz_hacl fuzz_${tmp_name}) 21 | endforeach (file ${FUZZ_HACL_SOURCES}) 22 | 23 | file(GLOB FUZZ_GMP_OPER ./op*.c) 24 | foreach (fp 25519;448) 25 | add_custom_target(fuzz${fp}) 26 | add_dependencies(fuzz fuzz${fp}) 27 | foreach (op_file ${FUZZ_GMP_OPER}) 28 | get_filename_component(op ${op_file} NAME_WE) 29 | set(fileName fuzz${fp}_${op}) 30 | add_executable(${fileName} EXCLUDE_FROM_ALL ${op_file}) 31 | target_compile_definitions(${fileName} PRIVATE "FIELD=${fp}") 32 | target_link_libraries(${fileName} ${TARGET} gmp) 33 | add_dependencies(fuzz${fp} ${fileName}) 34 | endforeach (op_file ${FUZZ_GMP_OPER}) 35 | endforeach (fp ${FUZZ_GMP_FP}) 36 | -------------------------------------------------------------------------------- /fuzz/Makefile: -------------------------------------------------------------------------------- 1 | ## See: 2 | ## https://llvm.org/docs/LibFuzzer.html 3 | ## Requires clang version > 6.0 4 | 5 | FUZZER=clang -fsanitize=fuzzer,address 6 | 7 | RFC7748_PATH=../build 8 | RFC7748_LIB=rfc7748_precomputed 9 | CFLAGS+=-O3 -Wall -Wextra -pedantic -fno-omit-frame-pointer -I../include/ 10 | 11 | all: fp hacl 12 | 13 | fp: $(patsubst %.c,%,$(wildcard op*.c)) 14 | op%: op%.c 15 | @for fp in 25519 448 ; do \ 16 | echo "fuzz$${fp}_$@"; \ 17 | $(FUZZER) $^ -DFIELD=$${fp} \ 18 | -o "fuzz$${fp}_$@" $(CFLAGS) \ 19 | -lgmp $(RFC7748_PATH)/lib/lib$(RFC7748_LIB).a; \ 20 | done 21 | 22 | hacl: fuzz_hacl_keygen fuzz_hacl_shared 23 | fuzz_hacl_%: hacl_%.c ./hacl/Hacl_Curve25519.o $(RFC7748_PATH)/lib/lib$(RFC7748_LIB).a 24 | $(FUZZER) -o $@ $(CFLAGS) $^ -I./hacl 25 | 26 | $(RFC7748_PATH)/lib/lib$(RFC7748_LIB).a: 27 | $(MAKE) -C $(RFC7748_PATH) $(RFC7748_LIB) 28 | 29 | .PHONY: $(RFC7748_PATH)/lib/lib$(RFC7748_LIB).a 30 | 31 | clean: 32 | rm -f fuzz_hacl_keygen fuzz_hacl_shared fuzz25519_* fuzz448_* 33 | -------------------------------------------------------------------------------- /fuzz/README.md: -------------------------------------------------------------------------------- 1 | ## Pre-requirements 2 | 3 | Fuzzing test is performed using [`libFuzzer`](https://llvm.org/docs/LibFuzzer.html) library available in Clang v6 or major. 4 | 5 | ---- 6 | 7 | ## Compiling Fuzz Test 8 | 9 | 1. Assume the project was cloned into the folder: `rfc7748_precomputed/` 10 | 2. Compile the source code: 11 | 12 | ```sh 13 | $ mkdir rfc7748_precomputed/build 14 | $ cd rfc7748_precomputed/build 15 | $ cmake .. 16 | $ make fuzz 17 | ``` 18 | 19 | ## Running Fuzz Test 20 | After compilation two testing programs will be generated fuzzing against HACL library: 21 | 22 | ```sh 23 | $ ./bin/fuzz_hacl_keygen 24 | $ ./bin/fuzz_hacl_shared 25 | ``` 26 | Each program will stop when an error is found; otherwise, it will run forever. You can stop the execution using CTRL+C (^C). 27 | 28 | Additionally, there are fuzzing tests for each field operation against the GMP library. 29 | ```sh 30 | $ ./bin/fuzz25519_opAdd 31 | ``` 32 | Each program will stop when an error is found; otherwise, it will run forever. You can stop the execution using CTRL+C (^C). 33 | 34 | ---- 35 | 36 | ## Known issues 37 | If clang is requesting the `libtinfo` library, you can install the following `ncurses` library: 38 | 39 | ```sh 40 | $ dnf install ncurses ncurses-compat-libs 41 | ``` 42 | ---- 43 | -------------------------------------------------------------------------------- /fuzz/fp.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2017, Armando Faz . All rights reserved. 3 | * Institute of Computing. 4 | * University of Campinas, Brazil. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions 8 | * are met: 9 | * 10 | * * Redistributions of source code must retain the above copyright 11 | * notice, this list of conditions and the following disclaimer. 12 | * * Redistributions in binary form must reproduce the above 13 | * copyright notice, this list of conditions and the following 14 | * disclaimer in the documentation and/or other materials provided 15 | * with the distribution. 16 | * * Neither the name of University of Campinas nor the names of its 17 | * contributors may be used to endorse or promote products derived 18 | * from this software without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 23 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 24 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 25 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 26 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 29 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 31 | * OF THE POSSIBILITY OF SUCH DAMAGE. 32 | */ 33 | 34 | #ifdef __cplusplus 35 | extern "C" { 36 | #endif 37 | 38 | #include 39 | #include 40 | #include 41 | 42 | #define getTwoPowerK(X, K) \ 43 | mpz_init_set_ui(X, 1); \ 44 | mpz_mul_2exp(X, X, K); 45 | 46 | #if FIELD == 25519 47 | 48 | #include 49 | #define N SIZE_BYTES_FP25519 50 | #define NUM_WORDS NUM_WORDS_ELTFP25519_X64 51 | #define K 256 52 | #define A24 121666 53 | #define TYPE EltFp25519_1w_x64 54 | #define TYPE_BUFFER EltFp25519_1w_Buffer_x64 55 | #define getPrime(X) \ 56 | mpz_init_set_ui(X, 1); \ 57 | mpz_mul_2exp(X, X, 255); \ 58 | mpz_sub_ui(X, X, 19); 59 | #define getTwoPrime(X) \ 60 | mpz_init_set_ui(X, 1); \ 61 | mpz_mul_2exp(X, X, 256); \ 62 | mpz_sub_ui(X, X, 38); 63 | #define getTwoPower(X) getTwoPowerK(X, K) 64 | #define getPModTwoK(X) mpz_init_set_ui(X, 38); 65 | #define getPminus2(X) \ 66 | mpz_init_set_ui(X, 1); \ 67 | mpz_mul_2exp(X, X, 255); \ 68 | mpz_sub_ui(X, X, 21); 69 | 70 | #define FpZero setzero_EltFp25519_1w_x64 71 | #define FpAdd add_EltFp25519_1w_x64 72 | #define FpSub sub_EltFp25519_1w_x64 73 | #define FpMul mul_EltFp25519_1w_x64 74 | #define FpSqr sqr_EltFp25519_1w_x64 75 | #define FpRed red_EltFp25519_1w_x64 76 | #define FpInv inv_EltFp25519_1w_x64 77 | #define FpMod fred_EltFp25519_1w_x64 78 | #define FpMulA24 mul_a24_EltFp25519_1w_x64 79 | 80 | #elif FIELD == 448 81 | 82 | #include 83 | #define N SIZE_BYTES_FP448 84 | #define NUM_WORDS NUM_WORDS_ELTFP448_X64 85 | #define K 448 86 | #define A24 39082 87 | #define TYPE EltFp448_1w_x64 88 | #define TYPE_BUFFER EltFp448_1w_Buffer_x64 89 | #define getPrime(X) \ 90 | mpz_init_set_ui(X, 1); \ 91 | mpz_mul_2exp(X, X, 224); \ 92 | mpz_sub_ui(X, X, 1); \ 93 | mpz_mul_2exp(X, X, 224); \ 94 | mpz_sub_ui(X, X, 1); 95 | #define getTwoPrime(X) getPrime(X) 96 | #define getTwoPower(X) getTwoPowerK(X, K) 97 | #define getPModTwoK(X) \ 98 | mpz_init_set_ui(X, 1); \ 99 | mpz_mul_2exp(X, X, 224); \ 100 | mpz_add_ui(X, X, 1); 101 | #define getPminus2(X) \ 102 | mpz_init_set_ui(X, 1); \ 103 | mpz_mul_2exp(X, X, 224); \ 104 | mpz_sub_ui(X, X, 1); \ 105 | mpz_mul_2exp(X, X, 224); \ 106 | mpz_sub_ui(X, X, 3); 107 | #define FpZero setzero_EltFp448_1w_x64 108 | #define FpAdd add_EltFp448_1w_x64 109 | #define FpSub sub_EltFp448_1w_x64 110 | #define FpMul mul_EltFp448_1w_x64 111 | #define FpSqr sqr_EltFp448_1w_x64 112 | #define FpRed red_EltFp448_1w_x64 113 | #define FpInv inv_EltFp448_1w_x64 114 | #define FpMod fred_EltFp448_1w_x64 115 | #define FpMulA24 mul_a24_EltFp448_1w_x64 116 | 117 | #endif 118 | 119 | #ifdef __cplusplus 120 | } 121 | #endif 122 | -------------------------------------------------------------------------------- /fuzz/hacl/Hacl_Curve25519.c: -------------------------------------------------------------------------------- 1 | /* MIT License 2 | * 3 | * Copyright (c) 2016-2017 INRIA and Microsoft Corporation 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 | */ 23 | 24 | 25 | #include "Hacl_Curve25519.h" 26 | 27 | static void Hacl_Bignum_Modulo_carry_top(uint64_t *b) 28 | { 29 | uint64_t b4 = b[4U]; 30 | uint64_t b0 = b[0U]; 31 | uint64_t b4_ = b4 & (uint64_t)0x7ffffffffffffU; 32 | uint64_t b0_ = b0 + (uint64_t)19U * (b4 >> (uint32_t)51U); 33 | b[4U] = b4_; 34 | b[0U] = b0_; 35 | } 36 | 37 | inline static void 38 | Hacl_Bignum_Fproduct_copy_from_wide_(uint64_t *output, FStar_UInt128_t *input) 39 | { 40 | { 41 | FStar_UInt128_t xi = input[0U]; 42 | output[0U] = FStar_UInt128_uint128_to_uint64(xi); 43 | } 44 | { 45 | FStar_UInt128_t xi = input[1U]; 46 | output[1U] = FStar_UInt128_uint128_to_uint64(xi); 47 | } 48 | { 49 | FStar_UInt128_t xi = input[2U]; 50 | output[2U] = FStar_UInt128_uint128_to_uint64(xi); 51 | } 52 | { 53 | FStar_UInt128_t xi = input[3U]; 54 | output[3U] = FStar_UInt128_uint128_to_uint64(xi); 55 | } 56 | { 57 | FStar_UInt128_t xi = input[4U]; 58 | output[4U] = FStar_UInt128_uint128_to_uint64(xi); 59 | } 60 | } 61 | 62 | inline static void 63 | Hacl_Bignum_Fproduct_sum_scalar_multiplication_( 64 | FStar_UInt128_t *output, 65 | uint64_t *input, 66 | uint64_t s 67 | ) 68 | { 69 | { 70 | FStar_UInt128_t xi = output[0U]; 71 | uint64_t yi = input[0U]; 72 | output[0U] = FStar_UInt128_add_mod(xi, FStar_UInt128_mul_wide(yi, s)); 73 | } 74 | { 75 | FStar_UInt128_t xi = output[1U]; 76 | uint64_t yi = input[1U]; 77 | output[1U] = FStar_UInt128_add_mod(xi, FStar_UInt128_mul_wide(yi, s)); 78 | } 79 | { 80 | FStar_UInt128_t xi = output[2U]; 81 | uint64_t yi = input[2U]; 82 | output[2U] = FStar_UInt128_add_mod(xi, FStar_UInt128_mul_wide(yi, s)); 83 | } 84 | { 85 | FStar_UInt128_t xi = output[3U]; 86 | uint64_t yi = input[3U]; 87 | output[3U] = FStar_UInt128_add_mod(xi, FStar_UInt128_mul_wide(yi, s)); 88 | } 89 | { 90 | FStar_UInt128_t xi = output[4U]; 91 | uint64_t yi = input[4U]; 92 | output[4U] = FStar_UInt128_add_mod(xi, FStar_UInt128_mul_wide(yi, s)); 93 | } 94 | } 95 | 96 | inline static void Hacl_Bignum_Fproduct_carry_wide_(FStar_UInt128_t *tmp) 97 | { 98 | { 99 | uint32_t ctr = (uint32_t)0U; 100 | FStar_UInt128_t tctr = tmp[ctr]; 101 | FStar_UInt128_t tctrp1 = tmp[ctr + (uint32_t)1U]; 102 | uint64_t r0 = FStar_UInt128_uint128_to_uint64(tctr) & (uint64_t)0x7ffffffffffffU; 103 | FStar_UInt128_t c = FStar_UInt128_shift_right(tctr, (uint32_t)51U); 104 | tmp[ctr] = FStar_UInt128_uint64_to_uint128(r0); 105 | tmp[ctr + (uint32_t)1U] = FStar_UInt128_add(tctrp1, c); 106 | } 107 | { 108 | uint32_t ctr = (uint32_t)1U; 109 | FStar_UInt128_t tctr = tmp[ctr]; 110 | FStar_UInt128_t tctrp1 = tmp[ctr + (uint32_t)1U]; 111 | uint64_t r0 = FStar_UInt128_uint128_to_uint64(tctr) & (uint64_t)0x7ffffffffffffU; 112 | FStar_UInt128_t c = FStar_UInt128_shift_right(tctr, (uint32_t)51U); 113 | tmp[ctr] = FStar_UInt128_uint64_to_uint128(r0); 114 | tmp[ctr + (uint32_t)1U] = FStar_UInt128_add(tctrp1, c); 115 | } 116 | { 117 | uint32_t ctr = (uint32_t)2U; 118 | FStar_UInt128_t tctr = tmp[ctr]; 119 | FStar_UInt128_t tctrp1 = tmp[ctr + (uint32_t)1U]; 120 | uint64_t r0 = FStar_UInt128_uint128_to_uint64(tctr) & (uint64_t)0x7ffffffffffffU; 121 | FStar_UInt128_t c = FStar_UInt128_shift_right(tctr, (uint32_t)51U); 122 | tmp[ctr] = FStar_UInt128_uint64_to_uint128(r0); 123 | tmp[ctr + (uint32_t)1U] = FStar_UInt128_add(tctrp1, c); 124 | } 125 | { 126 | uint32_t ctr = (uint32_t)3U; 127 | FStar_UInt128_t tctr = tmp[ctr]; 128 | FStar_UInt128_t tctrp1 = tmp[ctr + (uint32_t)1U]; 129 | uint64_t r0 = FStar_UInt128_uint128_to_uint64(tctr) & (uint64_t)0x7ffffffffffffU; 130 | FStar_UInt128_t c = FStar_UInt128_shift_right(tctr, (uint32_t)51U); 131 | tmp[ctr] = FStar_UInt128_uint64_to_uint128(r0); 132 | tmp[ctr + (uint32_t)1U] = FStar_UInt128_add(tctrp1, c); 133 | } 134 | } 135 | 136 | inline static void Hacl_Bignum_Fmul_shift_reduce(uint64_t *output) 137 | { 138 | uint64_t tmp = output[4U]; 139 | { 140 | uint32_t ctr = (uint32_t)5U - (uint32_t)0U - (uint32_t)1U; 141 | uint64_t z = output[ctr - (uint32_t)1U]; 142 | output[ctr] = z; 143 | } 144 | { 145 | uint32_t ctr = (uint32_t)5U - (uint32_t)1U - (uint32_t)1U; 146 | uint64_t z = output[ctr - (uint32_t)1U]; 147 | output[ctr] = z; 148 | } 149 | { 150 | uint32_t ctr = (uint32_t)5U - (uint32_t)2U - (uint32_t)1U; 151 | uint64_t z = output[ctr - (uint32_t)1U]; 152 | output[ctr] = z; 153 | } 154 | { 155 | uint32_t ctr = (uint32_t)5U - (uint32_t)3U - (uint32_t)1U; 156 | uint64_t z = output[ctr - (uint32_t)1U]; 157 | output[ctr] = z; 158 | } 159 | output[0U] = tmp; 160 | uint64_t b0 = output[0U]; 161 | output[0U] = (uint64_t)19U * b0; 162 | } 163 | 164 | static void 165 | Hacl_Bignum_Fmul_mul_shift_reduce_(FStar_UInt128_t *output, uint64_t *input, uint64_t *input21) 166 | { 167 | { 168 | uint64_t input2i = input21[0U]; 169 | Hacl_Bignum_Fproduct_sum_scalar_multiplication_(output, input, input2i); 170 | Hacl_Bignum_Fmul_shift_reduce(input); 171 | } 172 | { 173 | uint64_t input2i = input21[1U]; 174 | Hacl_Bignum_Fproduct_sum_scalar_multiplication_(output, input, input2i); 175 | Hacl_Bignum_Fmul_shift_reduce(input); 176 | } 177 | { 178 | uint64_t input2i = input21[2U]; 179 | Hacl_Bignum_Fproduct_sum_scalar_multiplication_(output, input, input2i); 180 | Hacl_Bignum_Fmul_shift_reduce(input); 181 | } 182 | { 183 | uint64_t input2i = input21[3U]; 184 | Hacl_Bignum_Fproduct_sum_scalar_multiplication_(output, input, input2i); 185 | Hacl_Bignum_Fmul_shift_reduce(input); 186 | } 187 | uint32_t i = (uint32_t)4U; 188 | uint64_t input2i = input21[i]; 189 | Hacl_Bignum_Fproduct_sum_scalar_multiplication_(output, input, input2i); 190 | } 191 | 192 | inline static void Hacl_Bignum_Fmul_fmul(uint64_t *output, uint64_t *input, uint64_t *input21) 193 | { 194 | uint64_t tmp[5U] = { 0U }; 195 | memcpy(tmp, input, (uint32_t)5U * sizeof input[0U]); 196 | KRML_CHECK_SIZE(FStar_UInt128_uint64_to_uint128((uint64_t)0U), (uint32_t)5U); 197 | FStar_UInt128_t t[5U]; 198 | for (uint32_t _i = 0U; _i < (uint32_t)5U; ++_i) 199 | t[_i] = FStar_UInt128_uint64_to_uint128((uint64_t)0U); 200 | Hacl_Bignum_Fmul_mul_shift_reduce_(t, tmp, input21); 201 | Hacl_Bignum_Fproduct_carry_wide_(t); 202 | FStar_UInt128_t b4 = t[4U]; 203 | FStar_UInt128_t b0 = t[0U]; 204 | FStar_UInt128_t 205 | b4_ = FStar_UInt128_logand(b4, FStar_UInt128_uint64_to_uint128((uint64_t)0x7ffffffffffffU)); 206 | FStar_UInt128_t 207 | b0_ = 208 | FStar_UInt128_add(b0, 209 | FStar_UInt128_mul_wide((uint64_t)19U, 210 | FStar_UInt128_uint128_to_uint64(FStar_UInt128_shift_right(b4, (uint32_t)51U)))); 211 | t[4U] = b4_; 212 | t[0U] = b0_; 213 | Hacl_Bignum_Fproduct_copy_from_wide_(output, t); 214 | uint64_t i0 = output[0U]; 215 | uint64_t i1 = output[1U]; 216 | uint64_t i0_ = i0 & (uint64_t)0x7ffffffffffffU; 217 | uint64_t i1_ = i1 + (i0 >> (uint32_t)51U); 218 | output[0U] = i0_; 219 | output[1U] = i1_; 220 | } 221 | 222 | inline static void Hacl_Bignum_Fsquare_fsquare__(FStar_UInt128_t *tmp, uint64_t *output) 223 | { 224 | uint64_t r0 = output[0U]; 225 | uint64_t r1 = output[1U]; 226 | uint64_t r2 = output[2U]; 227 | uint64_t r3 = output[3U]; 228 | uint64_t r4 = output[4U]; 229 | uint64_t d0 = r0 * (uint64_t)2U; 230 | uint64_t d1 = r1 * (uint64_t)2U; 231 | uint64_t d2 = r2 * (uint64_t)2U * (uint64_t)19U; 232 | uint64_t d419 = r4 * (uint64_t)19U; 233 | uint64_t d4 = d419 * (uint64_t)2U; 234 | FStar_UInt128_t 235 | s0 = 236 | FStar_UInt128_add(FStar_UInt128_add(FStar_UInt128_mul_wide(r0, r0), 237 | FStar_UInt128_mul_wide(d4, r1)), 238 | FStar_UInt128_mul_wide(d2, r3)); 239 | FStar_UInt128_t 240 | s1 = 241 | FStar_UInt128_add(FStar_UInt128_add(FStar_UInt128_mul_wide(d0, r1), 242 | FStar_UInt128_mul_wide(d4, r2)), 243 | FStar_UInt128_mul_wide(r3 * (uint64_t)19U, r3)); 244 | FStar_UInt128_t 245 | s2 = 246 | FStar_UInt128_add(FStar_UInt128_add(FStar_UInt128_mul_wide(d0, r2), 247 | FStar_UInt128_mul_wide(r1, r1)), 248 | FStar_UInt128_mul_wide(d4, r3)); 249 | FStar_UInt128_t 250 | s3 = 251 | FStar_UInt128_add(FStar_UInt128_add(FStar_UInt128_mul_wide(d0, r3), 252 | FStar_UInt128_mul_wide(d1, r2)), 253 | FStar_UInt128_mul_wide(r4, d419)); 254 | FStar_UInt128_t 255 | s4 = 256 | FStar_UInt128_add(FStar_UInt128_add(FStar_UInt128_mul_wide(d0, r4), 257 | FStar_UInt128_mul_wide(d1, r3)), 258 | FStar_UInt128_mul_wide(r2, r2)); 259 | tmp[0U] = s0; 260 | tmp[1U] = s1; 261 | tmp[2U] = s2; 262 | tmp[3U] = s3; 263 | tmp[4U] = s4; 264 | } 265 | 266 | inline static void Hacl_Bignum_Fsquare_fsquare_(FStar_UInt128_t *tmp, uint64_t *output) 267 | { 268 | Hacl_Bignum_Fsquare_fsquare__(tmp, output); 269 | Hacl_Bignum_Fproduct_carry_wide_(tmp); 270 | FStar_UInt128_t b4 = tmp[4U]; 271 | FStar_UInt128_t b0 = tmp[0U]; 272 | FStar_UInt128_t 273 | b4_ = FStar_UInt128_logand(b4, FStar_UInt128_uint64_to_uint128((uint64_t)0x7ffffffffffffU)); 274 | FStar_UInt128_t 275 | b0_ = 276 | FStar_UInt128_add(b0, 277 | FStar_UInt128_mul_wide((uint64_t)19U, 278 | FStar_UInt128_uint128_to_uint64(FStar_UInt128_shift_right(b4, (uint32_t)51U)))); 279 | tmp[4U] = b4_; 280 | tmp[0U] = b0_; 281 | Hacl_Bignum_Fproduct_copy_from_wide_(output, tmp); 282 | uint64_t i0 = output[0U]; 283 | uint64_t i1 = output[1U]; 284 | uint64_t i0_ = i0 & (uint64_t)0x7ffffffffffffU; 285 | uint64_t i1_ = i1 + (i0 >> (uint32_t)51U); 286 | output[0U] = i0_; 287 | output[1U] = i1_; 288 | } 289 | 290 | static void 291 | Hacl_Bignum_Fsquare_fsquare_times_(uint64_t *input, FStar_UInt128_t *tmp, uint32_t count1) 292 | { 293 | Hacl_Bignum_Fsquare_fsquare_(tmp, input); 294 | for (uint32_t i = (uint32_t)1U; i < count1; i = i + (uint32_t)1U) 295 | Hacl_Bignum_Fsquare_fsquare_(tmp, input); 296 | } 297 | 298 | inline static void 299 | Hacl_Bignum_Fsquare_fsquare_times(uint64_t *output, uint64_t *input, uint32_t count1) 300 | { 301 | KRML_CHECK_SIZE(FStar_UInt128_uint64_to_uint128((uint64_t)0U), (uint32_t)5U); 302 | FStar_UInt128_t t[5U]; 303 | for (uint32_t _i = 0U; _i < (uint32_t)5U; ++_i) 304 | t[_i] = FStar_UInt128_uint64_to_uint128((uint64_t)0U); 305 | memcpy(output, input, (uint32_t)5U * sizeof input[0U]); 306 | Hacl_Bignum_Fsquare_fsquare_times_(output, t, count1); 307 | } 308 | 309 | inline static void Hacl_Bignum_Fsquare_fsquare_times_inplace(uint64_t *output, uint32_t count1) 310 | { 311 | KRML_CHECK_SIZE(FStar_UInt128_uint64_to_uint128((uint64_t)0U), (uint32_t)5U); 312 | FStar_UInt128_t t[5U]; 313 | for (uint32_t _i = 0U; _i < (uint32_t)5U; ++_i) 314 | t[_i] = FStar_UInt128_uint64_to_uint128((uint64_t)0U); 315 | Hacl_Bignum_Fsquare_fsquare_times_(output, t, count1); 316 | } 317 | 318 | inline static void Hacl_Bignum_Crecip_crecip(uint64_t *out, uint64_t *z) 319 | { 320 | uint64_t buf[20U] = { 0U }; 321 | uint64_t *a = buf; 322 | uint64_t *t00 = buf + (uint32_t)5U; 323 | uint64_t *b0 = buf + (uint32_t)10U; 324 | Hacl_Bignum_Fsquare_fsquare_times(a, z, (uint32_t)1U); 325 | Hacl_Bignum_Fsquare_fsquare_times(t00, a, (uint32_t)2U); 326 | Hacl_Bignum_Fmul_fmul(b0, t00, z); 327 | Hacl_Bignum_Fmul_fmul(a, b0, a); 328 | Hacl_Bignum_Fsquare_fsquare_times(t00, a, (uint32_t)1U); 329 | Hacl_Bignum_Fmul_fmul(b0, t00, b0); 330 | Hacl_Bignum_Fsquare_fsquare_times(t00, b0, (uint32_t)5U); 331 | uint64_t *t01 = buf + (uint32_t)5U; 332 | uint64_t *b1 = buf + (uint32_t)10U; 333 | uint64_t *c0 = buf + (uint32_t)15U; 334 | Hacl_Bignum_Fmul_fmul(b1, t01, b1); 335 | Hacl_Bignum_Fsquare_fsquare_times(t01, b1, (uint32_t)10U); 336 | Hacl_Bignum_Fmul_fmul(c0, t01, b1); 337 | Hacl_Bignum_Fsquare_fsquare_times(t01, c0, (uint32_t)20U); 338 | Hacl_Bignum_Fmul_fmul(t01, t01, c0); 339 | Hacl_Bignum_Fsquare_fsquare_times_inplace(t01, (uint32_t)10U); 340 | Hacl_Bignum_Fmul_fmul(b1, t01, b1); 341 | Hacl_Bignum_Fsquare_fsquare_times(t01, b1, (uint32_t)50U); 342 | uint64_t *a0 = buf; 343 | uint64_t *t0 = buf + (uint32_t)5U; 344 | uint64_t *b = buf + (uint32_t)10U; 345 | uint64_t *c = buf + (uint32_t)15U; 346 | Hacl_Bignum_Fmul_fmul(c, t0, b); 347 | Hacl_Bignum_Fsquare_fsquare_times(t0, c, (uint32_t)100U); 348 | Hacl_Bignum_Fmul_fmul(t0, t0, c); 349 | Hacl_Bignum_Fsquare_fsquare_times_inplace(t0, (uint32_t)50U); 350 | Hacl_Bignum_Fmul_fmul(t0, t0, b); 351 | Hacl_Bignum_Fsquare_fsquare_times_inplace(t0, (uint32_t)5U); 352 | Hacl_Bignum_Fmul_fmul(out, t0, a0); 353 | } 354 | 355 | inline static void Hacl_Bignum_fsum(uint64_t *a, uint64_t *b) 356 | { 357 | { 358 | uint64_t xi = a[0U]; 359 | uint64_t yi = b[0U]; 360 | a[0U] = xi + yi; 361 | } 362 | { 363 | uint64_t xi = a[1U]; 364 | uint64_t yi = b[1U]; 365 | a[1U] = xi + yi; 366 | } 367 | { 368 | uint64_t xi = a[2U]; 369 | uint64_t yi = b[2U]; 370 | a[2U] = xi + yi; 371 | } 372 | { 373 | uint64_t xi = a[3U]; 374 | uint64_t yi = b[3U]; 375 | a[3U] = xi + yi; 376 | } 377 | { 378 | uint64_t xi = a[4U]; 379 | uint64_t yi = b[4U]; 380 | a[4U] = xi + yi; 381 | } 382 | } 383 | 384 | inline static void Hacl_Bignum_fdifference(uint64_t *a, uint64_t *b) 385 | { 386 | uint64_t tmp[5U] = { 0U }; 387 | memcpy(tmp, b, (uint32_t)5U * sizeof b[0U]); 388 | uint64_t b0 = tmp[0U]; 389 | uint64_t b1 = tmp[1U]; 390 | uint64_t b2 = tmp[2U]; 391 | uint64_t b3 = tmp[3U]; 392 | uint64_t b4 = tmp[4U]; 393 | tmp[0U] = b0 + (uint64_t)0x3fffffffffff68U; 394 | tmp[1U] = b1 + (uint64_t)0x3ffffffffffff8U; 395 | tmp[2U] = b2 + (uint64_t)0x3ffffffffffff8U; 396 | tmp[3U] = b3 + (uint64_t)0x3ffffffffffff8U; 397 | tmp[4U] = b4 + (uint64_t)0x3ffffffffffff8U; 398 | { 399 | uint64_t xi = a[0U]; 400 | uint64_t yi = tmp[0U]; 401 | a[0U] = yi - xi; 402 | } 403 | { 404 | uint64_t xi = a[1U]; 405 | uint64_t yi = tmp[1U]; 406 | a[1U] = yi - xi; 407 | } 408 | { 409 | uint64_t xi = a[2U]; 410 | uint64_t yi = tmp[2U]; 411 | a[2U] = yi - xi; 412 | } 413 | { 414 | uint64_t xi = a[3U]; 415 | uint64_t yi = tmp[3U]; 416 | a[3U] = yi - xi; 417 | } 418 | { 419 | uint64_t xi = a[4U]; 420 | uint64_t yi = tmp[4U]; 421 | a[4U] = yi - xi; 422 | } 423 | } 424 | 425 | inline static void Hacl_Bignum_fscalar(uint64_t *output, uint64_t *b, uint64_t s) 426 | { 427 | KRML_CHECK_SIZE(FStar_UInt128_uint64_to_uint128((uint64_t)0U), (uint32_t)5U); 428 | FStar_UInt128_t tmp[5U]; 429 | for (uint32_t _i = 0U; _i < (uint32_t)5U; ++_i) 430 | tmp[_i] = FStar_UInt128_uint64_to_uint128((uint64_t)0U); 431 | { 432 | uint64_t xi = b[0U]; 433 | tmp[0U] = FStar_UInt128_mul_wide(xi, s); 434 | } 435 | { 436 | uint64_t xi = b[1U]; 437 | tmp[1U] = FStar_UInt128_mul_wide(xi, s); 438 | } 439 | { 440 | uint64_t xi = b[2U]; 441 | tmp[2U] = FStar_UInt128_mul_wide(xi, s); 442 | } 443 | { 444 | uint64_t xi = b[3U]; 445 | tmp[3U] = FStar_UInt128_mul_wide(xi, s); 446 | } 447 | { 448 | uint64_t xi = b[4U]; 449 | tmp[4U] = FStar_UInt128_mul_wide(xi, s); 450 | } 451 | Hacl_Bignum_Fproduct_carry_wide_(tmp); 452 | FStar_UInt128_t b4 = tmp[4U]; 453 | FStar_UInt128_t b0 = tmp[0U]; 454 | FStar_UInt128_t 455 | b4_ = FStar_UInt128_logand(b4, FStar_UInt128_uint64_to_uint128((uint64_t)0x7ffffffffffffU)); 456 | FStar_UInt128_t 457 | b0_ = 458 | FStar_UInt128_add(b0, 459 | FStar_UInt128_mul_wide((uint64_t)19U, 460 | FStar_UInt128_uint128_to_uint64(FStar_UInt128_shift_right(b4, (uint32_t)51U)))); 461 | tmp[4U] = b4_; 462 | tmp[0U] = b0_; 463 | Hacl_Bignum_Fproduct_copy_from_wide_(output, tmp); 464 | } 465 | 466 | inline static void Hacl_Bignum_fmul(uint64_t *output, uint64_t *a, uint64_t *b) 467 | { 468 | Hacl_Bignum_Fmul_fmul(output, a, b); 469 | } 470 | 471 | inline static void Hacl_Bignum_crecip(uint64_t *output, uint64_t *input) 472 | { 473 | Hacl_Bignum_Crecip_crecip(output, input); 474 | } 475 | 476 | static void 477 | Hacl_EC_Point_swap_conditional_step(uint64_t *a, uint64_t *b, uint64_t swap1, uint32_t ctr) 478 | { 479 | uint32_t i = ctr - (uint32_t)1U; 480 | uint64_t ai = a[i]; 481 | uint64_t bi = b[i]; 482 | uint64_t x = swap1 & (ai ^ bi); 483 | uint64_t ai1 = ai ^ x; 484 | uint64_t bi1 = bi ^ x; 485 | a[i] = ai1; 486 | b[i] = bi1; 487 | } 488 | 489 | static void 490 | Hacl_EC_Point_swap_conditional_(uint64_t *a, uint64_t *b, uint64_t swap1, uint32_t ctr) 491 | { 492 | if (!(ctr == (uint32_t)0U)) 493 | { 494 | Hacl_EC_Point_swap_conditional_step(a, b, swap1, ctr); 495 | uint32_t i = ctr - (uint32_t)1U; 496 | Hacl_EC_Point_swap_conditional_(a, b, swap1, i); 497 | } 498 | } 499 | 500 | static void Hacl_EC_Point_swap_conditional(uint64_t *a, uint64_t *b, uint64_t iswap) 501 | { 502 | uint64_t swap1 = (uint64_t)0U - iswap; 503 | Hacl_EC_Point_swap_conditional_(a, b, swap1, (uint32_t)5U); 504 | Hacl_EC_Point_swap_conditional_(a + (uint32_t)5U, b + (uint32_t)5U, swap1, (uint32_t)5U); 505 | } 506 | 507 | static void Hacl_EC_Point_copy(uint64_t *output, uint64_t *input) 508 | { 509 | memcpy(output, input, (uint32_t)5U * sizeof input[0U]); 510 | memcpy(output + (uint32_t)5U, 511 | input + (uint32_t)5U, 512 | (uint32_t)5U * sizeof (input + (uint32_t)5U)[0U]); 513 | } 514 | 515 | static void 516 | Hacl_EC_AddAndDouble_fmonty( 517 | uint64_t *pp, 518 | uint64_t *ppq, 519 | uint64_t *p, 520 | uint64_t *pq, 521 | uint64_t *qmqp 522 | ) 523 | { 524 | uint64_t *qx = qmqp; 525 | uint64_t *x2 = pp; 526 | uint64_t *z2 = pp + (uint32_t)5U; 527 | uint64_t *x3 = ppq; 528 | uint64_t *z3 = ppq + (uint32_t)5U; 529 | uint64_t *x = p; 530 | uint64_t *z = p + (uint32_t)5U; 531 | uint64_t *xprime = pq; 532 | uint64_t *zprime = pq + (uint32_t)5U; 533 | uint64_t buf[40U] = { 0U }; 534 | uint64_t *origx = buf; 535 | uint64_t *origxprime = buf + (uint32_t)5U; 536 | uint64_t *xxprime0 = buf + (uint32_t)25U; 537 | uint64_t *zzprime0 = buf + (uint32_t)30U; 538 | memcpy(origx, x, (uint32_t)5U * sizeof x[0U]); 539 | Hacl_Bignum_fsum(x, z); 540 | Hacl_Bignum_fdifference(z, origx); 541 | memcpy(origxprime, xprime, (uint32_t)5U * sizeof xprime[0U]); 542 | Hacl_Bignum_fsum(xprime, zprime); 543 | Hacl_Bignum_fdifference(zprime, origxprime); 544 | Hacl_Bignum_fmul(xxprime0, xprime, z); 545 | Hacl_Bignum_fmul(zzprime0, x, zprime); 546 | uint64_t *origxprime0 = buf + (uint32_t)5U; 547 | uint64_t *xx0 = buf + (uint32_t)15U; 548 | uint64_t *zz0 = buf + (uint32_t)20U; 549 | uint64_t *xxprime = buf + (uint32_t)25U; 550 | uint64_t *zzprime = buf + (uint32_t)30U; 551 | uint64_t *zzzprime = buf + (uint32_t)35U; 552 | memcpy(origxprime0, xxprime, (uint32_t)5U * sizeof xxprime[0U]); 553 | Hacl_Bignum_fsum(xxprime, zzprime); 554 | Hacl_Bignum_fdifference(zzprime, origxprime0); 555 | Hacl_Bignum_Fsquare_fsquare_times(x3, xxprime, (uint32_t)1U); 556 | Hacl_Bignum_Fsquare_fsquare_times(zzzprime, zzprime, (uint32_t)1U); 557 | Hacl_Bignum_fmul(z3, zzzprime, qx); 558 | Hacl_Bignum_Fsquare_fsquare_times(xx0, x, (uint32_t)1U); 559 | Hacl_Bignum_Fsquare_fsquare_times(zz0, z, (uint32_t)1U); 560 | uint64_t *zzz = buf + (uint32_t)10U; 561 | uint64_t *xx = buf + (uint32_t)15U; 562 | uint64_t *zz = buf + (uint32_t)20U; 563 | Hacl_Bignum_fmul(x2, xx, zz); 564 | Hacl_Bignum_fdifference(zz, xx); 565 | uint64_t scalar = (uint64_t)121665U; 566 | Hacl_Bignum_fscalar(zzz, zz, scalar); 567 | Hacl_Bignum_fsum(zzz, xx); 568 | Hacl_Bignum_fmul(z2, zzz, zz); 569 | } 570 | 571 | static void 572 | Hacl_EC_Ladder_SmallLoop_cmult_small_loop_step( 573 | uint64_t *nq, 574 | uint64_t *nqpq, 575 | uint64_t *nq2, 576 | uint64_t *nqpq2, 577 | uint64_t *q, 578 | uint8_t byt 579 | ) 580 | { 581 | uint64_t bit = (uint64_t)(byt >> (uint32_t)7U); 582 | Hacl_EC_Point_swap_conditional(nq, nqpq, bit); 583 | Hacl_EC_AddAndDouble_fmonty(nq2, nqpq2, nq, nqpq, q); 584 | uint64_t bit0 = (uint64_t)(byt >> (uint32_t)7U); 585 | Hacl_EC_Point_swap_conditional(nq2, nqpq2, bit0); 586 | } 587 | 588 | static void 589 | Hacl_EC_Ladder_SmallLoop_cmult_small_loop_double_step( 590 | uint64_t *nq, 591 | uint64_t *nqpq, 592 | uint64_t *nq2, 593 | uint64_t *nqpq2, 594 | uint64_t *q, 595 | uint8_t byt 596 | ) 597 | { 598 | Hacl_EC_Ladder_SmallLoop_cmult_small_loop_step(nq, nqpq, nq2, nqpq2, q, byt); 599 | uint8_t byt1 = byt << (uint32_t)1U; 600 | Hacl_EC_Ladder_SmallLoop_cmult_small_loop_step(nq2, nqpq2, nq, nqpq, q, byt1); 601 | } 602 | 603 | static void 604 | Hacl_EC_Ladder_SmallLoop_cmult_small_loop( 605 | uint64_t *nq, 606 | uint64_t *nqpq, 607 | uint64_t *nq2, 608 | uint64_t *nqpq2, 609 | uint64_t *q, 610 | uint8_t byt, 611 | uint32_t i 612 | ) 613 | { 614 | if (!(i == (uint32_t)0U)) 615 | { 616 | uint32_t i_ = i - (uint32_t)1U; 617 | Hacl_EC_Ladder_SmallLoop_cmult_small_loop_double_step(nq, nqpq, nq2, nqpq2, q, byt); 618 | uint8_t byt_ = byt << (uint32_t)2U; 619 | Hacl_EC_Ladder_SmallLoop_cmult_small_loop(nq, nqpq, nq2, nqpq2, q, byt_, i_); 620 | } 621 | } 622 | 623 | static void 624 | Hacl_EC_Ladder_BigLoop_cmult_big_loop( 625 | uint8_t *n1, 626 | uint64_t *nq, 627 | uint64_t *nqpq, 628 | uint64_t *nq2, 629 | uint64_t *nqpq2, 630 | uint64_t *q, 631 | uint32_t i 632 | ) 633 | { 634 | if (!(i == (uint32_t)0U)) 635 | { 636 | uint32_t i1 = i - (uint32_t)1U; 637 | uint8_t byte = n1[i1]; 638 | Hacl_EC_Ladder_SmallLoop_cmult_small_loop(nq, nqpq, nq2, nqpq2, q, byte, (uint32_t)4U); 639 | Hacl_EC_Ladder_BigLoop_cmult_big_loop(n1, nq, nqpq, nq2, nqpq2, q, i1); 640 | } 641 | } 642 | 643 | static void Hacl_EC_Ladder_cmult(uint64_t *result, uint8_t *n1, uint64_t *q) 644 | { 645 | uint64_t point_buf[40U] = { 0U }; 646 | uint64_t *nq = point_buf; 647 | uint64_t *nqpq = point_buf + (uint32_t)10U; 648 | uint64_t *nq2 = point_buf + (uint32_t)20U; 649 | uint64_t *nqpq2 = point_buf + (uint32_t)30U; 650 | Hacl_EC_Point_copy(nqpq, q); 651 | nq[0U] = (uint64_t)1U; 652 | Hacl_EC_Ladder_BigLoop_cmult_big_loop(n1, nq, nqpq, nq2, nqpq2, q, (uint32_t)32U); 653 | Hacl_EC_Point_copy(result, nq); 654 | } 655 | 656 | static void Hacl_EC_Format_fexpand(uint64_t *output, uint8_t *input) 657 | { 658 | uint64_t i0 = load64_le(input); 659 | uint8_t *x00 = input + (uint32_t)6U; 660 | uint64_t i1 = load64_le(x00); 661 | uint8_t *x01 = input + (uint32_t)12U; 662 | uint64_t i2 = load64_le(x01); 663 | uint8_t *x02 = input + (uint32_t)19U; 664 | uint64_t i3 = load64_le(x02); 665 | uint8_t *x0 = input + (uint32_t)24U; 666 | uint64_t i4 = load64_le(x0); 667 | uint64_t output0 = i0 & (uint64_t)0x7ffffffffffffU; 668 | uint64_t output1 = i1 >> (uint32_t)3U & (uint64_t)0x7ffffffffffffU; 669 | uint64_t output2 = i2 >> (uint32_t)6U & (uint64_t)0x7ffffffffffffU; 670 | uint64_t output3 = i3 >> (uint32_t)1U & (uint64_t)0x7ffffffffffffU; 671 | uint64_t output4 = i4 >> (uint32_t)12U & (uint64_t)0x7ffffffffffffU; 672 | output[0U] = output0; 673 | output[1U] = output1; 674 | output[2U] = output2; 675 | output[3U] = output3; 676 | output[4U] = output4; 677 | } 678 | 679 | static void Hacl_EC_Format_fcontract_first_carry_pass(uint64_t *input) 680 | { 681 | uint64_t t0 = input[0U]; 682 | uint64_t t1 = input[1U]; 683 | uint64_t t2 = input[2U]; 684 | uint64_t t3 = input[3U]; 685 | uint64_t t4 = input[4U]; 686 | uint64_t t1_ = t1 + (t0 >> (uint32_t)51U); 687 | uint64_t t0_ = t0 & (uint64_t)0x7ffffffffffffU; 688 | uint64_t t2_ = t2 + (t1_ >> (uint32_t)51U); 689 | uint64_t t1__ = t1_ & (uint64_t)0x7ffffffffffffU; 690 | uint64_t t3_ = t3 + (t2_ >> (uint32_t)51U); 691 | uint64_t t2__ = t2_ & (uint64_t)0x7ffffffffffffU; 692 | uint64_t t4_ = t4 + (t3_ >> (uint32_t)51U); 693 | uint64_t t3__ = t3_ & (uint64_t)0x7ffffffffffffU; 694 | input[0U] = t0_; 695 | input[1U] = t1__; 696 | input[2U] = t2__; 697 | input[3U] = t3__; 698 | input[4U] = t4_; 699 | } 700 | 701 | static void Hacl_EC_Format_fcontract_first_carry_full(uint64_t *input) 702 | { 703 | Hacl_EC_Format_fcontract_first_carry_pass(input); 704 | Hacl_Bignum_Modulo_carry_top(input); 705 | } 706 | 707 | static void Hacl_EC_Format_fcontract_second_carry_pass(uint64_t *input) 708 | { 709 | uint64_t t0 = input[0U]; 710 | uint64_t t1 = input[1U]; 711 | uint64_t t2 = input[2U]; 712 | uint64_t t3 = input[3U]; 713 | uint64_t t4 = input[4U]; 714 | uint64_t t1_ = t1 + (t0 >> (uint32_t)51U); 715 | uint64_t t0_ = t0 & (uint64_t)0x7ffffffffffffU; 716 | uint64_t t2_ = t2 + (t1_ >> (uint32_t)51U); 717 | uint64_t t1__ = t1_ & (uint64_t)0x7ffffffffffffU; 718 | uint64_t t3_ = t3 + (t2_ >> (uint32_t)51U); 719 | uint64_t t2__ = t2_ & (uint64_t)0x7ffffffffffffU; 720 | uint64_t t4_ = t4 + (t3_ >> (uint32_t)51U); 721 | uint64_t t3__ = t3_ & (uint64_t)0x7ffffffffffffU; 722 | input[0U] = t0_; 723 | input[1U] = t1__; 724 | input[2U] = t2__; 725 | input[3U] = t3__; 726 | input[4U] = t4_; 727 | } 728 | 729 | static void Hacl_EC_Format_fcontract_second_carry_full(uint64_t *input) 730 | { 731 | Hacl_EC_Format_fcontract_second_carry_pass(input); 732 | Hacl_Bignum_Modulo_carry_top(input); 733 | uint64_t i0 = input[0U]; 734 | uint64_t i1 = input[1U]; 735 | uint64_t i0_ = i0 & (uint64_t)0x7ffffffffffffU; 736 | uint64_t i1_ = i1 + (i0 >> (uint32_t)51U); 737 | input[0U] = i0_; 738 | input[1U] = i1_; 739 | } 740 | 741 | static void Hacl_EC_Format_fcontract_trim(uint64_t *input) 742 | { 743 | uint64_t a0 = input[0U]; 744 | uint64_t a1 = input[1U]; 745 | uint64_t a2 = input[2U]; 746 | uint64_t a3 = input[3U]; 747 | uint64_t a4 = input[4U]; 748 | uint64_t mask0 = FStar_UInt64_gte_mask(a0, (uint64_t)0x7ffffffffffedU); 749 | uint64_t mask1 = FStar_UInt64_eq_mask(a1, (uint64_t)0x7ffffffffffffU); 750 | uint64_t mask2 = FStar_UInt64_eq_mask(a2, (uint64_t)0x7ffffffffffffU); 751 | uint64_t mask3 = FStar_UInt64_eq_mask(a3, (uint64_t)0x7ffffffffffffU); 752 | uint64_t mask4 = FStar_UInt64_eq_mask(a4, (uint64_t)0x7ffffffffffffU); 753 | uint64_t mask = (((mask0 & mask1) & mask2) & mask3) & mask4; 754 | uint64_t a0_ = a0 - ((uint64_t)0x7ffffffffffedU & mask); 755 | uint64_t a1_ = a1 - ((uint64_t)0x7ffffffffffffU & mask); 756 | uint64_t a2_ = a2 - ((uint64_t)0x7ffffffffffffU & mask); 757 | uint64_t a3_ = a3 - ((uint64_t)0x7ffffffffffffU & mask); 758 | uint64_t a4_ = a4 - ((uint64_t)0x7ffffffffffffU & mask); 759 | input[0U] = a0_; 760 | input[1U] = a1_; 761 | input[2U] = a2_; 762 | input[3U] = a3_; 763 | input[4U] = a4_; 764 | } 765 | 766 | static void Hacl_EC_Format_fcontract_store(uint8_t *output, uint64_t *input) 767 | { 768 | uint64_t t0 = input[0U]; 769 | uint64_t t1 = input[1U]; 770 | uint64_t t2 = input[2U]; 771 | uint64_t t3 = input[3U]; 772 | uint64_t t4 = input[4U]; 773 | uint64_t o0 = t1 << (uint32_t)51U | t0; 774 | uint64_t o1 = t2 << (uint32_t)38U | t1 >> (uint32_t)13U; 775 | uint64_t o2 = t3 << (uint32_t)25U | t2 >> (uint32_t)26U; 776 | uint64_t o3 = t4 << (uint32_t)12U | t3 >> (uint32_t)39U; 777 | uint8_t *b0 = output; 778 | uint8_t *b1 = output + (uint32_t)8U; 779 | uint8_t *b2 = output + (uint32_t)16U; 780 | uint8_t *b3 = output + (uint32_t)24U; 781 | store64_le(b0, o0); 782 | store64_le(b1, o1); 783 | store64_le(b2, o2); 784 | store64_le(b3, o3); 785 | } 786 | 787 | static void Hacl_EC_Format_fcontract(uint8_t *output, uint64_t *input) 788 | { 789 | Hacl_EC_Format_fcontract_first_carry_full(input); 790 | Hacl_EC_Format_fcontract_second_carry_full(input); 791 | Hacl_EC_Format_fcontract_trim(input); 792 | Hacl_EC_Format_fcontract_store(output, input); 793 | } 794 | 795 | static void Hacl_EC_Format_scalar_of_point(uint8_t *scalar, uint64_t *point) 796 | { 797 | uint64_t *x = point; 798 | uint64_t *z = point + (uint32_t)5U; 799 | uint64_t buf[10U] = { 0U }; 800 | uint64_t *zmone = buf; 801 | uint64_t *sc = buf + (uint32_t)5U; 802 | Hacl_Bignum_crecip(zmone, z); 803 | Hacl_Bignum_fmul(sc, x, zmone); 804 | Hacl_EC_Format_fcontract(scalar, sc); 805 | } 806 | 807 | void Hacl_EC_crypto_scalarmult(uint8_t *mypublic, uint8_t *secret, uint8_t *basepoint) 808 | { 809 | uint64_t buf0[10U] = { 0U }; 810 | uint64_t *x0 = buf0; 811 | uint64_t *z = buf0 + (uint32_t)5U; 812 | Hacl_EC_Format_fexpand(x0, basepoint); 813 | z[0U] = (uint64_t)1U; 814 | uint64_t *q = buf0; 815 | uint8_t e[32U] = { 0U }; 816 | memcpy(e, secret, (uint32_t)32U * sizeof secret[0U]); 817 | uint8_t e0 = e[0U]; 818 | uint8_t e31 = e[31U]; 819 | uint8_t e01 = e0 & (uint8_t)248U; 820 | uint8_t e311 = e31 & (uint8_t)127U; 821 | uint8_t e312 = e311 | (uint8_t)64U; 822 | e[0U] = e01; 823 | e[31U] = e312; 824 | uint8_t *scalar = e; 825 | uint64_t buf[15U] = { 0U }; 826 | uint64_t *nq = buf; 827 | uint64_t *x = nq; 828 | x[0U] = (uint64_t)1U; 829 | Hacl_EC_Ladder_cmult(nq, scalar, q); 830 | Hacl_EC_Format_scalar_of_point(mypublic, nq); 831 | } 832 | 833 | void Hacl_Curve25519_crypto_scalarmult(uint8_t *mypublic, uint8_t *secret, uint8_t *basepoint) 834 | { 835 | Hacl_EC_crypto_scalarmult(mypublic, secret, basepoint); 836 | } 837 | 838 | -------------------------------------------------------------------------------- /fuzz/hacl/Hacl_Curve25519.h: -------------------------------------------------------------------------------- 1 | /* MIT License 2 | * 3 | * Copyright (c) 2016-2017 INRIA and Microsoft Corporation 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 | */ 23 | 24 | #include "kremlib.h" 25 | #ifndef __Hacl_Curve25519_H 26 | #define __Hacl_Curve25519_H 27 | 28 | 29 | 30 | 31 | 32 | typedef uint64_t Hacl_Bignum_Constants_limb; 33 | 34 | typedef FStar_UInt128_t Hacl_Bignum_Constants_wide; 35 | 36 | typedef uint64_t Hacl_Bignum_Parameters_limb; 37 | 38 | typedef FStar_UInt128_t Hacl_Bignum_Parameters_wide; 39 | 40 | typedef uint32_t Hacl_Bignum_Parameters_ctr; 41 | 42 | typedef uint64_t *Hacl_Bignum_Parameters_felem; 43 | 44 | typedef FStar_UInt128_t *Hacl_Bignum_Parameters_felem_wide; 45 | 46 | typedef void *Hacl_Bignum_Parameters_seqelem; 47 | 48 | typedef void *Hacl_Bignum_Parameters_seqelem_wide; 49 | 50 | typedef FStar_UInt128_t Hacl_Bignum_Wide_t; 51 | 52 | typedef uint64_t Hacl_Bignum_Limb_t; 53 | 54 | extern void Hacl_Bignum_lemma_diff(Prims_int x0, Prims_int x1, Prims_pos x2); 55 | 56 | typedef uint64_t *Hacl_EC_Point_point; 57 | 58 | typedef uint8_t *Hacl_EC_Ladder_SmallLoop_uint8_p; 59 | 60 | typedef uint8_t *Hacl_EC_Ladder_uint8_p; 61 | 62 | typedef uint8_t *Hacl_EC_Format_uint8_p; 63 | 64 | void Hacl_EC_crypto_scalarmult(uint8_t *mypublic, uint8_t *secret, uint8_t *basepoint); 65 | 66 | typedef uint8_t *Hacl_Curve25519_uint8_p; 67 | 68 | void Hacl_Curve25519_crypto_scalarmult(uint8_t *mypublic, uint8_t *secret, uint8_t *basepoint); 69 | #endif 70 | -------------------------------------------------------------------------------- /fuzz/hacl/kremlib.c: -------------------------------------------------------------------------------- 1 | /* MIT License 2 | * 3 | * Copyright (c) 2016-2017 INRIA and Microsoft Corporation 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 | */ 23 | #include "kremlib.h" 24 | #include 25 | 26 | int exit_success = EXIT_SUCCESS; 27 | int exit_failure = EXIT_FAILURE; 28 | 29 | void print_string(const char *s) { 30 | printf("%s", s); 31 | } 32 | 33 | void print_bytes(uint8_t *b, uint32_t len) { 34 | uint32_t i; 35 | for (i = 0; i < len; i++){ 36 | printf("%02x", b[i]); 37 | } 38 | printf("\n"); 39 | } 40 | -------------------------------------------------------------------------------- /fuzz/hacl/kremlib.h: -------------------------------------------------------------------------------- 1 | /* MIT License 2 | * 3 | * Copyright (c) 2016-2017 INRIA and Microsoft Corporation 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 | */ 23 | #ifndef __KREMLIB_H 24 | #define __KREMLIB_H 25 | 26 | #include "kremlib_base.h" 27 | 28 | 29 | /* For tests only: we might need this function to be forward-declared, because 30 | * the dependency on WasmSupport appears very late, after SimplifyWasm, and 31 | * sadly, after the topological order has been done. */ 32 | void WasmSupport_check_buffer_size(uint32_t s); 33 | 34 | /******************************************************************************/ 35 | /* Stubs to ease compilation of non-Low* code */ 36 | /******************************************************************************/ 37 | 38 | /* Some types that KreMLin has no special knowledge of; many of them appear in 39 | * signatures of ghost functions, meaning that it suffices to give them (any) 40 | * definition. */ 41 | typedef void *FStar_Seq_Base_seq, *Prims_prop, *FStar_HyperStack_mem, 42 | *FStar_Set_set, *Prims_st_pre_h, *FStar_Heap_heap, *Prims_all_pre_h, 43 | *FStar_TSet_set, *Prims_list, *FStar_Map_t, *FStar_UInt63_t_, 44 | *FStar_Int63_t_, *FStar_UInt63_t, *FStar_Int63_t, *FStar_UInt_uint_t, 45 | *FStar_Int_int_t, *FStar_HyperStack_stackref, *FStar_Bytes_bytes, 46 | *FStar_HyperHeap_rid, *FStar_Heap_aref, *FStar_Monotonic_Heap_heap, 47 | *FStar_Monotonic_Heap_aref, *FStar_Monotonic_HyperHeap_rid, 48 | *FStar_Monotonic_HyperStack_mem, *FStar_Char_char_; 49 | 50 | typedef const char *Prims_string; 51 | 52 | /* For "bare" targets that do not have a C stdlib, the user might want to use 53 | * [-add-include '"mydefinitions.h"'] and override these. */ 54 | #ifndef KRML_HOST_PRINTF 55 | # define KRML_HOST_PRINTF printf 56 | #endif 57 | 58 | #ifndef KRML_HOST_EXIT 59 | # define KRML_HOST_EXIT exit 60 | #endif 61 | 62 | #ifndef KRML_HOST_MALLOC 63 | # define KRML_HOST_MALLOC malloc 64 | #endif 65 | 66 | /* In statement position, exiting is easy. */ 67 | #define KRML_EXIT \ 68 | do { \ 69 | KRML_HOST_PRINTF("Unimplemented function at %s:%d\n", __FILE__, __LINE__); \ 70 | KRML_HOST_EXIT(254); \ 71 | } while (0) 72 | 73 | /* In expression position, use the comma-operator and a malloc to return an 74 | * expression of the right size. KreMLin passes t as the parameter to the macro. 75 | */ 76 | #define KRML_EABORT(t, msg) \ 77 | (KRML_HOST_PRINTF("KreMLin abort at %s:%d\n%s\n", __FILE__, __LINE__, msg), \ 78 | KRML_HOST_EXIT(255), *((t *)KRML_HOST_MALLOC(sizeof(t)))) 79 | 80 | /* In FStar.Buffer.fst, the size of arrays is uint32_t, but it's a number of 81 | * *elements*. Do an ugly, run-time check (some of which KreMLin can eliminate). 82 | */ 83 | #define KRML_CHECK_SIZE(elt, size) \ 84 | if (((size_t)size) > SIZE_MAX / sizeof(elt)) { \ 85 | KRML_HOST_PRINTF( \ 86 | "Maximum allocatable size exceeded, aborting before overflow at " \ 87 | "%s:%d\n", \ 88 | __FILE__, __LINE__); \ 89 | KRML_HOST_EXIT(253); \ 90 | } 91 | 92 | /* A series of GCC atrocities to trace function calls (kremlin's [-d c-calls] 93 | * option). Useful when trying to debug, say, Wasm, to compare traces. */ 94 | /* clang-format off */ 95 | #ifdef __GNUC__ 96 | #define KRML_FORMAT(X) _Generic((X), \ 97 | uint8_t : "0x%08" PRIx8, \ 98 | uint16_t: "0x%08" PRIx16, \ 99 | uint32_t: "0x%08" PRIx32, \ 100 | uint64_t: "0x%08" PRIx64, \ 101 | int8_t : "0x%08" PRIx8, \ 102 | int16_t : "0x%08" PRIx16, \ 103 | int32_t : "0x%08" PRIx32, \ 104 | int64_t : "0x%08" PRIx64, \ 105 | default : "%s") 106 | 107 | #define KRML_FORMAT_ARG(X) _Generic((X), \ 108 | uint8_t : X, \ 109 | uint16_t: X, \ 110 | uint32_t: X, \ 111 | uint64_t: X, \ 112 | int8_t : X, \ 113 | int16_t : X, \ 114 | int32_t : X, \ 115 | int64_t : X, \ 116 | default : "unknown") 117 | /* clang-format on */ 118 | 119 | # define KRML_DEBUG_RETURN(X) \ 120 | ({ \ 121 | __auto_type _ret = (X); \ 122 | KRML_HOST_PRINTF("returning: "); \ 123 | KRML_HOST_PRINTF(KRML_FORMAT(_ret), KRML_FORMAT_ARG(_ret)); \ 124 | KRML_HOST_PRINTF(" \n"); \ 125 | _ret; \ 126 | }) 127 | #endif 128 | 129 | #define FStar_Buffer_eqb(b1, b2, n) \ 130 | (memcmp((b1), (b2), (n) * sizeof((b1)[0])) == 0) 131 | 132 | /* Stubs to make ST happy. Important note: you must generate a use of the macro 133 | * argument, otherwise, you may have FStar_ST_recall(f) as the only use of f; 134 | * KreMLin will think that this is a valid use, but then the C compiler, after 135 | * macro expansion, will error out. */ 136 | #define FStar_HyperHeap_root 0 137 | #define FStar_Pervasives_Native_fst(x) (x).fst 138 | #define FStar_Pervasives_Native_snd(x) (x).snd 139 | #define FStar_Seq_Base_createEmpty(x) 0 140 | #define FStar_Seq_Base_create(len, init) 0 141 | #define FStar_Seq_Base_upd(s, i, e) 0 142 | #define FStar_Seq_Base_eq(l1, l2) 0 143 | #define FStar_Seq_Base_length(l1) 0 144 | #define FStar_Seq_Base_append(x, y) 0 145 | #define FStar_Seq_Base_slice(x, y, z) 0 146 | #define FStar_Seq_Properties_snoc(x, y) 0 147 | #define FStar_Seq_Properties_cons(x, y) 0 148 | #define FStar_Seq_Base_index(x, y) 0 149 | #define FStar_HyperStack_is_eternal_color(x) 0 150 | #define FStar_Monotonic_HyperHeap_root 0 151 | #define FStar_Buffer_to_seq_full(x) 0 152 | #define FStar_Buffer_recall(x) 153 | #define FStar_HyperStack_ST_op_Colon_Equals(x, v) KRML_EXIT 154 | #define FStar_HyperStack_ST_op_Bang(x) 0 155 | #define FStar_HyperStack_ST_salloc(x) 0 156 | #define FStar_HyperStack_ST_ralloc(x, y) 0 157 | #define FStar_HyperStack_ST_new_region(x) (0) 158 | #define FStar_Monotonic_RRef_m_alloc(x) \ 159 | { 0 } 160 | 161 | #define FStar_HyperStack_ST_recall(x) \ 162 | do { \ 163 | (void)(x); \ 164 | } while (0) 165 | 166 | #define FStar_HyperStack_ST_recall_region(x) \ 167 | do { \ 168 | (void)(x); \ 169 | } while (0) 170 | 171 | #define FStar_Monotonic_RRef_m_recall(x1, x2) \ 172 | do { \ 173 | (void)(x1); \ 174 | (void)(x2); \ 175 | } while (0) 176 | 177 | #define FStar_Monotonic_RRef_m_write(x1, x2, x3, x4, x5) \ 178 | do { \ 179 | (void)(x1); \ 180 | (void)(x2); \ 181 | (void)(x3); \ 182 | (void)(x4); \ 183 | (void)(x5); \ 184 | } while (0) 185 | 186 | /******************************************************************************/ 187 | /* Endian-ness macros that can only be implemented in C */ 188 | /******************************************************************************/ 189 | 190 | /* ... for Linux */ 191 | #if defined(__linux__) || defined(__CYGWIN__) 192 | # include 193 | 194 | /* ... for OSX */ 195 | #elif defined(__APPLE__) 196 | # include 197 | # define htole64(x) OSSwapHostToLittleInt64(x) 198 | # define le64toh(x) OSSwapLittleToHostInt64(x) 199 | # define htobe64(x) OSSwapHostToBigInt64(x) 200 | # define be64toh(x) OSSwapBigToHostInt64(x) 201 | 202 | # define htole16(x) OSSwapHostToLittleInt16(x) 203 | # define le16toh(x) OSSwapLittleToHostInt16(x) 204 | # define htobe16(x) OSSwapHostToBigInt16(x) 205 | # define be16toh(x) OSSwapBigToHostInt16(x) 206 | 207 | # define htole32(x) OSSwapHostToLittleInt32(x) 208 | # define le32toh(x) OSSwapLittleToHostInt32(x) 209 | # define htobe32(x) OSSwapHostToBigInt32(x) 210 | # define be32toh(x) OSSwapBigToHostInt32(x) 211 | 212 | /* ... for Solaris */ 213 | #elif defined(__sun__) 214 | # include 215 | # define htole64(x) LE_64(x) 216 | # define le64toh(x) LE_64(x) 217 | # define htobe64(x) BE_64(x) 218 | # define be64toh(x) BE_64(x) 219 | 220 | # define htole16(x) LE_16(x) 221 | # define le16toh(x) LE_16(x) 222 | # define htobe16(x) BE_16(x) 223 | # define be16toh(x) BE_16(x) 224 | 225 | # define htole32(x) LE_32(x) 226 | # define le32toh(x) LE_32(x) 227 | # define htobe32(x) BE_32(x) 228 | # define be32toh(x) BE_32(x) 229 | 230 | /* ... for the BSDs */ 231 | #elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__) 232 | # include 233 | #elif defined(__OpenBSD__) 234 | # include 235 | 236 | /* ... for Windows (MSVC)... not targeting XBOX 360! */ 237 | #elif defined(_MSC_VER) 238 | 239 | # include 240 | # define htobe16(x) _byteswap_ushort(x) 241 | # define htole16(x) (x) 242 | # define be16toh(x) _byteswap_ushort(x) 243 | # define le16toh(x) (x) 244 | 245 | # define htobe32(x) _byteswap_ulong(x) 246 | # define htole32(x) (x) 247 | # define be32toh(x) _byteswap_ulong(x) 248 | # define le32toh(x) (x) 249 | 250 | # define htobe64(x) _byteswap_uint64(x) 251 | # define htole64(x) (x) 252 | # define be64toh(x) _byteswap_uint64(x) 253 | # define le64toh(x) (x) 254 | 255 | /* ... for Windows (GCC-like, e.g. mingw or clang) */ 256 | #elif (defined(_WIN32) || defined(_WIN64)) && \ 257 | (defined(__GNUC__) || defined(__clang__)) 258 | 259 | # define htobe16(x) __builtin_bswap16(x) 260 | # define htole16(x) (x) 261 | # define be16toh(x) __builtin_bswap16(x) 262 | # define le16toh(x) (x) 263 | 264 | # define htobe32(x) __builtin_bswap32(x) 265 | # define htole32(x) (x) 266 | # define be32toh(x) __builtin_bswap32(x) 267 | # define le32toh(x) (x) 268 | 269 | # define htobe64(x) __builtin_bswap64(x) 270 | # define htole64(x) (x) 271 | # define be64toh(x) __builtin_bswap64(x) 272 | # define le64toh(x) (x) 273 | 274 | /* ... generic big-endian fallback code */ 275 | #elif defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ 276 | 277 | /* byte swapping code inspired by: 278 | * https://github.com/rweather/arduinolibs/blob/master/libraries/Crypto/utility/EndianUtil.h 279 | * */ 280 | 281 | # define htobe32(x) (x) 282 | # define be32toh(x) (x) 283 | # define htole32(x) \ 284 | (__extension__({ \ 285 | uint32_t _temp = (x); \ 286 | ((_temp >> 24) & 0x000000FF) | ((_temp >> 8) & 0x0000FF00) | \ 287 | ((_temp << 8) & 0x00FF0000) | ((_temp << 24) & 0xFF000000); \ 288 | })) 289 | # define le32toh(x) (htole32((x))) 290 | 291 | # define htobe64(x) (x) 292 | # define be64toh(x) (x) 293 | # define htole64(x) \ 294 | (__extension__({ \ 295 | uint64_t __temp = (x); \ 296 | uint32_t __low = htobe32((uint32_t)__temp); \ 297 | uint32_t __high = htobe32((uint32_t)(__temp >> 32)); \ 298 | (((uint64_t)__low) << 32) | __high; \ 299 | })) 300 | # define le64toh(x) (htole64((x))) 301 | 302 | /* ... generic little-endian fallback code */ 303 | #elif defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ 304 | 305 | # define htole32(x) (x) 306 | # define le32toh(x) (x) 307 | # define htobe32(x) \ 308 | (__extension__({ \ 309 | uint32_t _temp = (x); \ 310 | ((_temp >> 24) & 0x000000FF) | ((_temp >> 8) & 0x0000FF00) | \ 311 | ((_temp << 8) & 0x00FF0000) | ((_temp << 24) & 0xFF000000); \ 312 | })) 313 | # define be32toh(x) (htobe32((x))) 314 | 315 | # define htole64(x) (x) 316 | # define le64toh(x) (x) 317 | # define htobe64(x) \ 318 | (__extension__({ \ 319 | uint64_t __temp = (x); \ 320 | uint32_t __low = htobe32((uint32_t)__temp); \ 321 | uint32_t __high = htobe32((uint32_t)(__temp >> 32)); \ 322 | (((uint64_t)__low) << 32) | __high; \ 323 | })) 324 | # define be64toh(x) (htobe64((x))) 325 | 326 | /* ... couldn't determine endian-ness of the target platform */ 327 | #else 328 | # error "Please define __BYTE_ORDER__!" 329 | 330 | #endif /* defined(__linux__) || ... */ 331 | 332 | /* Loads and stores. These avoid undefined behavior due to unaligned memory 333 | * accesses, via memcpy. */ 334 | 335 | inline static uint16_t load16(uint8_t *b) { 336 | uint16_t x; 337 | memcpy(&x, b, 2); 338 | return x; 339 | } 340 | 341 | inline static uint32_t load32(uint8_t *b) { 342 | uint32_t x; 343 | memcpy(&x, b, 4); 344 | return x; 345 | } 346 | 347 | inline static uint64_t load64(uint8_t *b) { 348 | uint64_t x; 349 | memcpy(&x, b, 8); 350 | return x; 351 | } 352 | 353 | inline static void store16(uint8_t *b, uint16_t i) { memcpy(b, &i, 2); } 354 | 355 | inline static void store32(uint8_t *b, uint32_t i) { memcpy(b, &i, 4); } 356 | 357 | inline static void store64(uint8_t *b, uint64_t i) { memcpy(b, &i, 8); } 358 | 359 | #define load16_le(b) (le16toh(load16(b))) 360 | #define store16_le(b, i) (store16(b, htole16(i))) 361 | #define load16_be(b) (be16toh(load16(b))) 362 | #define store16_be(b, i) (store16(b, htobe16(i))) 363 | 364 | #define load32_le(b) (le32toh(load32(b))) 365 | #define store32_le(b, i) (store32(b, htole32(i))) 366 | #define load32_be(b) (be32toh(load32(b))) 367 | #define store32_be(b, i) (store32(b, htobe32(i))) 368 | 369 | #define load64_le(b) (le64toh(load64(b))) 370 | #define store64_le(b, i) (store64(b, htole64(i))) 371 | #define load64_be(b) (be64toh(load64(b))) 372 | #define store64_be(b, i) (store64(b, htobe64(i))) 373 | 374 | /******************************************************************************/ 375 | /* Checked integers to ease the compilation of non-Low* code */ 376 | /******************************************************************************/ 377 | 378 | typedef int32_t Prims_pos, Prims_nat, Prims_nonzero, Prims_int, 379 | krml_checked_int_t; 380 | 381 | inline static bool Prims_op_GreaterThanOrEqual(int32_t x, int32_t y) { 382 | return x >= y; 383 | } 384 | 385 | inline static bool Prims_op_LessThanOrEqual(int32_t x, int32_t y) { 386 | return x <= y; 387 | } 388 | 389 | inline static bool Prims_op_GreaterThan(int32_t x, int32_t y) { return x > y; } 390 | 391 | inline static bool Prims_op_LessThan(int32_t x, int32_t y) { return x < y; } 392 | 393 | #define RETURN_OR(x) \ 394 | do { \ 395 | int64_t __ret = x; \ 396 | if (__ret < INT32_MIN || INT32_MAX < __ret) { \ 397 | KRML_HOST_PRINTF("Prims.{int,nat,pos} integer overflow at %s:%d\n", \ 398 | __FILE__, __LINE__); \ 399 | KRML_HOST_EXIT(252); \ 400 | } \ 401 | return (int32_t)__ret; \ 402 | } while (0) 403 | 404 | inline static int32_t Prims_pow2(int32_t x) { 405 | RETURN_OR((int64_t)1 << (int64_t)x); 406 | } 407 | 408 | inline static int32_t Prims_op_Multiply(int32_t x, int32_t y) { 409 | RETURN_OR((int64_t)x * (int64_t)y); 410 | } 411 | 412 | inline static int32_t Prims_op_Addition(int32_t x, int32_t y) { 413 | RETURN_OR((int64_t)x + (int64_t)y); 414 | } 415 | 416 | inline static int32_t Prims_op_Subtraction(int32_t x, int32_t y) { 417 | RETURN_OR((int64_t)x - (int64_t)y); 418 | } 419 | 420 | inline static int32_t Prims_op_Division(int32_t x, int32_t y) { 421 | RETURN_OR((int64_t)x / (int64_t)y); 422 | } 423 | 424 | inline static int32_t Prims_op_Modulus(int32_t x, int32_t y) { 425 | RETURN_OR((int64_t)x % (int64_t)y); 426 | } 427 | 428 | inline static int8_t FStar_UInt8_uint_to_t(int8_t x) { return x; } 429 | inline static int16_t FStar_UInt16_uint_to_t(int16_t x) { return x; } 430 | inline static int32_t FStar_UInt32_uint_to_t(int32_t x) { return x; } 431 | inline static int64_t FStar_UInt64_uint_to_t(int64_t x) { return x; } 432 | 433 | inline static int8_t FStar_UInt8_v(int8_t x) { return x; } 434 | inline static int16_t FStar_UInt16_v(int16_t x) { return x; } 435 | inline static int32_t FStar_UInt32_v(int32_t x) { return x; } 436 | inline static int64_t FStar_UInt64_v(int64_t x) { return x; } 437 | 438 | 439 | /* Platform-specific 128-bit arithmetic. These are static functions in a header, 440 | * so that each translation unit gets its own copy and the C compiler can 441 | * optimize. */ 442 | #ifndef KRML_NOUINT128 443 | typedef unsigned __int128 FStar_UInt128_t, FStar_UInt128_t_, uint128_t; 444 | 445 | static inline void print128(const char *where, uint128_t n) { 446 | KRML_HOST_PRINTF("%s: [%" PRIu64 ",%" PRIu64 "]\n", where, 447 | (uint64_t)(n >> 64), (uint64_t)n); 448 | } 449 | 450 | static inline uint128_t load128_le(uint8_t *b) { 451 | uint128_t l = (uint128_t)load64_le(b); 452 | uint128_t h = (uint128_t)load64_le(b + 8); 453 | return (h << 64 | l); 454 | } 455 | 456 | static inline void store128_le(uint8_t *b, uint128_t n) { 457 | store64_le(b, (uint64_t)n); 458 | store64_le(b + 8, (uint64_t)(n >> 64)); 459 | } 460 | 461 | static inline uint128_t load128_be(uint8_t *b) { 462 | uint128_t h = (uint128_t)load64_be(b); 463 | uint128_t l = (uint128_t)load64_be(b + 8); 464 | return (h << 64 | l); 465 | } 466 | 467 | static inline void store128_be(uint8_t *b, uint128_t n) { 468 | store64_be(b, (uint64_t)(n >> 64)); 469 | store64_be(b + 8, (uint64_t)n); 470 | } 471 | 472 | # define FStar_UInt128_add(x, y) ((x) + (y)) 473 | # define FStar_UInt128_mul(x, y) ((x) * (y)) 474 | # define FStar_UInt128_add_mod(x, y) ((x) + (y)) 475 | # define FStar_UInt128_sub(x, y) ((x) - (y)) 476 | # define FStar_UInt128_sub_mod(x, y) ((x) - (y)) 477 | # define FStar_UInt128_logand(x, y) ((x) & (y)) 478 | # define FStar_UInt128_logor(x, y) ((x) | (y)) 479 | # define FStar_UInt128_logxor(x, y) ((x) ^ (y)) 480 | # define FStar_UInt128_lognot(x) (~(x)) 481 | # define FStar_UInt128_shift_left(x, y) ((x) << (y)) 482 | # define FStar_UInt128_shift_right(x, y) ((x) >> (y)) 483 | # define FStar_UInt128_uint64_to_uint128(x) ((uint128_t)(x)) 484 | # define FStar_UInt128_uint128_to_uint64(x) ((uint64_t)(x)) 485 | # define FStar_UInt128_mul_wide(x, y) ((uint128_t)(x) * (y)) 486 | # define FStar_UInt128_op_Hat_Hat(x, y) ((x) ^ (y)) 487 | 488 | static inline uint128_t FStar_UInt128_eq_mask(uint128_t x, uint128_t y) { 489 | uint64_t mask = 490 | FStar_UInt64_eq_mask((uint64_t)(x >> 64), (uint64_t)(y >> 64)) & 491 | FStar_UInt64_eq_mask(x, y); 492 | return ((uint128_t)mask) << 64 | mask; 493 | } 494 | 495 | static inline uint128_t FStar_UInt128_gte_mask(uint128_t x, uint128_t y) { 496 | uint64_t mask = 497 | (FStar_UInt64_gte_mask(x >> 64, y >> 64) & 498 | ~(FStar_UInt64_eq_mask(x >> 64, y >> 64))) | 499 | (FStar_UInt64_eq_mask(x >> 64, y >> 64) & FStar_UInt64_gte_mask(x, y)); 500 | return ((uint128_t)mask) << 64 | mask; 501 | } 502 | 503 | 504 | 505 | # else /* !defined(KRML_NOUINT128) */ 506 | 507 | /* This is a bad circular dependency... should fix it properly. */ 508 | # include "FStar.h" 509 | 510 | typedef FStar_UInt128_uint128 FStar_UInt128_t_, uint128_t; 511 | 512 | /* A series of definitions written using pointers. */ 513 | static inline void print128_(const char *where, uint128_t *n) { 514 | KRML_HOST_PRINTF("%s: [0x%08" PRIx64 ",0x%08" PRIx64 "]\n", where, n->high, n->low); 515 | } 516 | 517 | static inline void load128_le_(uint8_t *b, uint128_t *r) { 518 | r->low = load64_le(b); 519 | r->high = load64_le(b + 8); 520 | } 521 | 522 | static inline void store128_le_(uint8_t *b, uint128_t *n) { 523 | store64_le(b, n->low); 524 | store64_le(b + 8, n->high); 525 | } 526 | 527 | static inline void load128_be_(uint8_t *b, uint128_t *r) { 528 | r->high = load64_be(b); 529 | r->low = load64_be(b + 8); 530 | } 531 | 532 | static inline void store128_be_(uint8_t *b, uint128_t *n) { 533 | store64_be(b, n->high); 534 | store64_be(b + 8, n->low); 535 | } 536 | 537 | # ifndef KRML_NOSTRUCT_PASSING 538 | 539 | static inline void print128(const char *where, uint128_t n) { 540 | print128_(where, &n); 541 | } 542 | 543 | static inline uint128_t load128_le(uint8_t *b) { 544 | uint128_t r; 545 | load128_le_(b, &r); 546 | return r; 547 | } 548 | 549 | static inline void store128_le(uint8_t *b, uint128_t n) { store128_le_(b, &n); } 550 | 551 | static inline uint128_t load128_be(uint8_t *b) { 552 | uint128_t r; 553 | load128_be_(b, &r); 554 | return r; 555 | } 556 | 557 | static inline void store128_be(uint8_t *b, uint128_t n) { store128_be_(b, &n); } 558 | 559 | # else /* !defined(KRML_STRUCT_PASSING) */ 560 | 561 | # define print128 print128_ 562 | # define load128_le load128_le_ 563 | # define store128_le store128_le_ 564 | # define load128_be load128_be_ 565 | # define store128_be store128_be_ 566 | 567 | # endif /* KRML_STRUCT_PASSING */ 568 | # endif /* KRML_UINT128 */ 569 | #endif /* __KREMLIB_H */ 570 | -------------------------------------------------------------------------------- /fuzz/hacl/kremlib_base.h: -------------------------------------------------------------------------------- 1 | /* MIT License 2 | * 3 | * Copyright (c) 2016-2017 INRIA and Microsoft Corporation 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 | */ 23 | #ifndef __KREMLIB_BASE_H 24 | #define __KREMLIB_BASE_H 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | /******************************************************************************/ 34 | /* Some macros to ease compatibility */ 35 | /******************************************************************************/ 36 | 37 | /* Define __cdecl and friends when using GCC, so that we can safely compile code 38 | * that contains __cdecl on all platforms. Note that this is in a separate 39 | * header so that Dafny-generated code can include just this file. */ 40 | #ifndef _MSC_VER 41 | /* Use the gcc predefined macros if on a platform/architectures that set them. 42 | * Otherwise define them to be empty. */ 43 | #ifndef __cdecl 44 | #define __cdecl 45 | #endif 46 | #ifndef __stdcall 47 | #define __stdcall 48 | #endif 49 | #ifndef __fastcall 50 | #define __fastcall 51 | #endif 52 | #endif 53 | 54 | #ifdef __GNUC__ 55 | # define inline __inline__ 56 | #endif 57 | 58 | /* GCC-specific attribute syntax; everyone else gets the standard C inline 59 | * attribute. */ 60 | #ifdef __GNU_C__ 61 | # ifndef __clang__ 62 | # define force_inline inline __attribute__((always_inline)) 63 | # else 64 | # define force_inline inline 65 | # endif 66 | #else 67 | # define force_inline inline 68 | #endif 69 | 70 | 71 | /******************************************************************************/ 72 | /* Implementing C.fst */ 73 | /******************************************************************************/ 74 | 75 | /* Uppercase issue; we have to define lowercase versions of the C macros (as we 76 | * have no way to refer to an uppercase *variable* in F*). */ 77 | extern int exit_success; 78 | extern int exit_failure; 79 | 80 | /* This one allows the user to write C.EXIT_SUCCESS. */ 81 | typedef int exit_code; 82 | 83 | void print_string(const char *s); 84 | void print_bytes(uint8_t *b, uint32_t len); 85 | 86 | /* The universal null pointer defined in C.Nullity.fst */ 87 | #define C_Nullity_null(X) 0 88 | 89 | /* If some globals need to be initialized before the main, then kremlin will 90 | * generate and try to link last a function with this type: */ 91 | void kremlinit_globals(void); 92 | 93 | /******************************************************************************/ 94 | /* Implementation of machine integers (possibly of 128-bit integers) */ 95 | /******************************************************************************/ 96 | 97 | /* Integer types */ 98 | typedef uint64_t FStar_UInt64_t, FStar_UInt64_t_; 99 | typedef int64_t FStar_Int64_t, FStar_Int64_t_; 100 | typedef uint32_t FStar_UInt32_t, FStar_UInt32_t_; 101 | typedef int32_t FStar_Int32_t, FStar_Int32_t_; 102 | typedef uint16_t FStar_UInt16_t, FStar_UInt16_t_; 103 | typedef int16_t FStar_Int16_t, FStar_Int16_t_; 104 | typedef uint8_t FStar_UInt8_t, FStar_UInt8_t_; 105 | typedef int8_t FStar_Int8_t, FStar_Int8_t_; 106 | 107 | static inline uint32_t rotate32_left(uint32_t x, uint32_t n) { 108 | /* assert (n<32); */ 109 | return (x << n) | (x >> (32 - n)); 110 | } 111 | static inline uint32_t rotate32_right(uint32_t x, uint32_t n) { 112 | /* assert (n<32); */ 113 | return (x >> n) | (x << (32 - n)); 114 | } 115 | 116 | /* Constant time comparisons */ 117 | static inline uint8_t FStar_UInt8_eq_mask(uint8_t x, uint8_t y) { 118 | x = ~(x ^ y); 119 | x &= x << 4; 120 | x &= x << 2; 121 | x &= x << 1; 122 | return (int8_t)x >> 7; 123 | } 124 | 125 | static inline uint8_t FStar_UInt8_gte_mask(uint8_t x, uint8_t y) { 126 | return ~(uint8_t)(((int32_t)x - y) >> 31); 127 | } 128 | 129 | static inline uint16_t FStar_UInt16_eq_mask(uint16_t x, uint16_t y) { 130 | x = ~(x ^ y); 131 | x &= x << 8; 132 | x &= x << 4; 133 | x &= x << 2; 134 | x &= x << 1; 135 | return (int16_t)x >> 15; 136 | } 137 | 138 | static inline uint16_t FStar_UInt16_gte_mask(uint16_t x, uint16_t y) { 139 | return ~(uint16_t)(((int32_t)x - y) >> 31); 140 | } 141 | 142 | static inline uint32_t FStar_UInt32_eq_mask(uint32_t x, uint32_t y) { 143 | x = ~(x ^ y); 144 | x &= x << 16; 145 | x &= x << 8; 146 | x &= x << 4; 147 | x &= x << 2; 148 | x &= x << 1; 149 | return ((int32_t)x) >> 31; 150 | } 151 | 152 | static inline uint32_t FStar_UInt32_gte_mask(uint32_t x, uint32_t y) { 153 | return ~((uint32_t)(((int64_t)x - y) >> 63)); 154 | } 155 | 156 | static inline uint64_t FStar_UInt64_eq_mask(uint64_t x, uint64_t y) { 157 | x = ~(x ^ y); 158 | x &= x << 32; 159 | x &= x << 16; 160 | x &= x << 8; 161 | x &= x << 4; 162 | x &= x << 2; 163 | x &= x << 1; 164 | return ((int64_t)x) >> 63; 165 | } 166 | 167 | static inline uint64_t FStar_UInt64_gte_mask(uint64_t x, uint64_t y) { 168 | uint64_t low63 = 169 | ~((uint64_t)((int64_t)((int64_t)(x & UINT64_C(0x7fffffffffffffff)) - 170 | (int64_t)(y & UINT64_C(0x7fffffffffffffff))) >> 171 | 63)); 172 | uint64_t high_bit = 173 | ~((uint64_t)((int64_t)((int64_t)(x & UINT64_C(0x8000000000000000)) - 174 | (int64_t)(y & UINT64_C(0x8000000000000000))) >> 175 | 63)); 176 | return low63 & high_bit; 177 | } 178 | 179 | 180 | #endif 181 | -------------------------------------------------------------------------------- /fuzz/hacl_keygen.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | #define N X25519_KEYSIZE_BYTES 11 | 12 | int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { 13 | if (Size != N) return 0; 14 | 15 | X25519_KEY session1, session2; 16 | X25519_KEY priv1, priv2; 17 | X25519_KEY point1; 18 | 19 | memcpy(priv1, Data + 0, N); 20 | memcpy(priv2, Data + 0, N); 21 | memset(point1, 0, N); 22 | point1[0] = 9; 23 | 24 | Hacl_Curve25519_crypto_scalarmult(session1, priv1, point1); 25 | X25519_KeyGen(session2, priv2); 26 | 27 | assert(memcmp(session1, session2, N) == 0); 28 | return 0; 29 | } 30 | 31 | #ifdef __cplusplus 32 | } 33 | #endif 34 | -------------------------------------------------------------------------------- /fuzz/hacl_shared.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | #define N X25519_KEYSIZE_BYTES 11 | 12 | int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { 13 | if (Size != 2 * N) return 0; 14 | 15 | X25519_KEY shared1, shared2; 16 | X25519_KEY priv1, priv2; 17 | X25519_KEY point1, point2; 18 | 19 | memcpy(priv1, Data + 0, N); 20 | memcpy(priv2, Data + 0, N); 21 | memcpy(point1, Data + N, N); 22 | memcpy(point2, Data + N, N); 23 | 24 | Hacl_Curve25519_crypto_scalarmult(shared1, priv1, point1); 25 | X25519_Shared(shared2, point2, priv2); 26 | 27 | assert(memcmp(shared1, shared2, N) == 0); 28 | return 0; 29 | } 30 | 31 | #ifdef __cplusplus 32 | } 33 | #endif 34 | -------------------------------------------------------------------------------- /fuzz/opA24.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2017, Armando Faz . All rights reserved. 3 | * Institute of Computing. 4 | * University of Campinas, Brazil. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions 8 | * are met: 9 | * 10 | * * Redistributions of source code must retain the above copyright 11 | * notice, this list of conditions and the following disclaimer. 12 | * * Redistributions in binary form must reproduce the above 13 | * copyright notice, this list of conditions and the following 14 | * disclaimer in the documentation and/or other materials provided 15 | * with the distribution. 16 | * * Neither the name of University of Campinas nor the names of its 17 | * contributors may be used to endorse or promote products derived 18 | * from this software without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 23 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 24 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 25 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 26 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 29 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 31 | * OF THE POSSIBILITY OF SUCH DAMAGE. 32 | */ 33 | 34 | #include "fp.h" 35 | 36 | /** 37 | * Verifies that 0<= c=a24*a < 2^K and that c be congruent to a24*a mod p 38 | * @param Data Random binary data. 39 | * @param Size Non-trivial input size is set -max_len=N 40 | * @return Always return 0 in case of success. 41 | */ 42 | #ifdef __cplusplus 43 | extern "C" { 44 | #endif 45 | 46 | int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { 47 | if (Size != N) return 0; 48 | TYPE a, get_c, want_c; 49 | 50 | mpz_t gmp_a, gmp_c, gmp_low, gmp_high, two_to_K, pModTwoK; 51 | mpz_init(gmp_a); 52 | mpz_init(gmp_c); 53 | mpz_init(gmp_low); 54 | mpz_init(gmp_high); 55 | getTwoPower(two_to_K); // two_to_256 = 2^K 56 | getPModTwoK(pModTwoK); 57 | 58 | FpZero(get_c); 59 | FpZero(want_c); 60 | 61 | memcpy(a, Data + 0, N); 62 | 63 | FpMulA24(get_c, a); 64 | 65 | mpz_import(gmp_a, N, -1, sizeof(Data[0]), 0, 0, Data + 0); 66 | mpz_mul_ui(gmp_c, gmp_a, A24); 67 | 68 | while (mpz_cmp(gmp_c, two_to_K) >= 0) { 69 | mpz_mod_2exp(gmp_low, gmp_c, K); 70 | mpz_div_2exp(gmp_high, gmp_c, K); 71 | mpz_mul(gmp_high, gmp_high, pModTwoK); 72 | mpz_add(gmp_c, gmp_low, gmp_high); 73 | } 74 | mpz_export(want_c, NULL, -1, N, 0, 0, gmp_c); 75 | 76 | assert(memcmp(get_c, want_c, N) == 0); 77 | 78 | mpz_clear(gmp_a); 79 | mpz_clear(gmp_c); 80 | mpz_clear(gmp_low); 81 | mpz_clear(gmp_high); 82 | mpz_clear(two_to_K); 83 | mpz_clear(pModTwoK); 84 | return 0; 85 | } 86 | 87 | #ifdef __cplusplus 88 | } 89 | #endif 90 | -------------------------------------------------------------------------------- /fuzz/opAdd.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2017, Armando Faz . All rights reserved. 3 | * Institute of Computing. 4 | * University of Campinas, Brazil. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions 8 | * are met: 9 | * 10 | * * Redistributions of source code must retain the above copyright 11 | * notice, this list of conditions and the following disclaimer. 12 | * * Redistributions in binary form must reproduce the above 13 | * copyright notice, this list of conditions and the following 14 | * disclaimer in the documentation and/or other materials provided 15 | * with the distribution. 16 | * * Neither the name of University of Campinas nor the names of its 17 | * contributors may be used to endorse or promote products derived 18 | * from this software without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 23 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 24 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 25 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 26 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 29 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 31 | * OF THE POSSIBILITY OF SUCH DAMAGE. 32 | */ 33 | 34 | #include "fp.h" 35 | 36 | /** 37 | * Verifies that 0 <= c=a+b < 2^K and that c be congruent to a+b mod p 38 | * @param Data Random binary data. 39 | * @param Size Non-trivial input size is set -max_len=2*N 40 | * @return Always return 0 in case of success. 41 | */ 42 | #ifdef __cplusplus 43 | extern "C" { 44 | #endif 45 | 46 | int LLVMFuzzerTestOneInput(const uint8_t* Data, size_t Size) { 47 | if (Size != 2 * N) return 0; 48 | TYPE a, b, get_c, want_c; 49 | 50 | mpz_t gmp_a, gmp_b, gmp_c, two_prime, two_to_K; 51 | mpz_init(gmp_a); 52 | mpz_init(gmp_b); 53 | mpz_init(gmp_c); 54 | getTwoPrime(two_prime); // two_prime = 2p 55 | getTwoPower(two_to_K); // two_to_K = 2^K 56 | 57 | memcpy(a, Data + 0 * N, N); 58 | memcpy(b, Data + 1 * N, N); 59 | 60 | FpZero(get_c); 61 | FpZero(want_c); 62 | 63 | FpAdd(get_c, a, b); 64 | 65 | mpz_import(gmp_a, N, -1, sizeof(Data[0]), 0, 0, Data + 0 * N); 66 | mpz_import(gmp_b, N, -1, sizeof(Data[0]), 0, 0, Data + 1 * N); 67 | 68 | mpz_add(gmp_c, gmp_a, gmp_b); 69 | while (mpz_cmp(gmp_c, two_to_K) >= 0) { 70 | mpz_sub(gmp_c, gmp_c, two_prime); 71 | } 72 | mpz_export(want_c, NULL, -1, N, 0, 0, gmp_c); 73 | assert(memcmp(get_c, want_c, N) == 0); 74 | 75 | mpz_clear(gmp_a); 76 | mpz_clear(gmp_b); 77 | mpz_clear(gmp_c); 78 | mpz_clear(two_prime); 79 | mpz_clear(two_to_K); 80 | return 0; 81 | } 82 | 83 | #ifdef __cplusplus 84 | } 85 | #endif 86 | -------------------------------------------------------------------------------- /fuzz/opInv.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2017, Armando Faz . All rights reserved. 3 | * Institute of Computing. 4 | * University of Campinas, Brazil. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions 8 | * are met: 9 | * 10 | * * Redistributions of source code must retain the above copyright 11 | * notice, this list of conditions and the following disclaimer. 12 | * * Redistributions in binary form must reproduce the above 13 | * copyright notice, this list of conditions and the following 14 | * disclaimer in the documentation and/or other materials provided 15 | * with the distribution. 16 | * * Neither the name of University of Campinas nor the names of its 17 | * contributors may be used to endorse or promote products derived 18 | * from this software without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 23 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 24 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 25 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 26 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 29 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 31 | * OF THE POSSIBILITY OF SUCH DAMAGE. 32 | */ 33 | 34 | #include "fp.h" 35 | 36 | /** 37 | * Verifies that 0 <= a < 2^K and that c be congruent to a^-1 mod p 38 | * @param Data Random binary data. 39 | * @param Size Non-trivial input size is set -max_len=N 40 | * @return Always return 0 in case of success. 41 | */ 42 | #ifdef __cplusplus 43 | extern "C" { 44 | #endif 45 | 46 | int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { 47 | if (Size != N) return 0; 48 | 49 | TYPE a, get_c, want_c; 50 | 51 | mpz_t gmp_a, gmp_c, prime, prime_minus_two; 52 | mpz_init(gmp_a); 53 | mpz_init(gmp_c); 54 | getPrime(prime); 55 | getPminus2(prime_minus_two); 56 | 57 | memcpy(a, Data + 0, N); 58 | 59 | FpZero(get_c); 60 | FpZero(want_c); 61 | 62 | FpInv(get_c, a); 63 | FpMod(get_c); 64 | 65 | mpz_import(gmp_a, N, -1, sizeof(Data[0]), 0, 0, Data + 0); 66 | mpz_powm(gmp_c, gmp_a, prime_minus_two, prime); 67 | mpz_export(want_c, NULL, -1, N, 0, 0, gmp_c); 68 | assert(memcmp(get_c, want_c, N) == 0); 69 | 70 | mpz_clear(gmp_a); 71 | mpz_clear(gmp_c); 72 | mpz_clear(prime); 73 | mpz_clear(prime_minus_two); 74 | return 0; 75 | } 76 | 77 | #ifdef __cplusplus 78 | } 79 | #endif 80 | -------------------------------------------------------------------------------- /fuzz/opMul.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2017, Armando Faz . All rights reserved. 3 | * Institute of Computing. 4 | * University of Campinas, Brazil. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions 8 | * are met: 9 | * 10 | * * Redistributions of source code must retain the above copyright 11 | * notice, this list of conditions and the following disclaimer. 12 | * * Redistributions in binary form must reproduce the above 13 | * copyright notice, this list of conditions and the following 14 | * disclaimer in the documentation and/or other materials provided 15 | * with the distribution. 16 | * * Neither the name of University of Campinas nor the names of its 17 | * contributors may be used to endorse or promote products derived 18 | * from this software without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 23 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 24 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 25 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 26 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 29 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 31 | * OF THE POSSIBILITY OF SUCH DAMAGE. 32 | */ 33 | 34 | #include "fp.h" 35 | 36 | /** 37 | * Verifies that 0 <= c=a*b < 2^(2K) 38 | * @param Data Random binary data. 39 | * @param Size Non-trivial input size is set -max_len=2*N 40 | * @return Always return 0 in case of success. 41 | */ 42 | #ifdef __cplusplus 43 | extern "C" { 44 | #endif 45 | 46 | int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { 47 | if (Size != 2 * N) return 0; 48 | 49 | TYPE a, b, get_c, want_c; 50 | TYPE_BUFFER buffer_1w; 51 | 52 | mpz_t gmp_a, gmp_b, gmp_c, gmp_low, gmp_high, two_to_K, pModTwoK; 53 | mpz_init(gmp_a); 54 | mpz_init(gmp_b); 55 | mpz_init(gmp_c); 56 | mpz_init(gmp_low); 57 | mpz_init(gmp_high); 58 | getTwoPower(two_to_K); 59 | getPModTwoK(pModTwoK); 60 | 61 | memcpy(a, Data + 0 * N, N); 62 | memcpy(b, Data + 1 * N, N); 63 | 64 | FpZero(get_c); 65 | FpZero(want_c); 66 | 67 | FpMul(get_c, a, b); 68 | 69 | mpz_import(gmp_a, N, -1, sizeof(Data[0]), 0, 0, Data + 0 * N); 70 | mpz_import(gmp_b, N, -1, sizeof(Data[0]), 0, 0, Data + 1 * N); 71 | 72 | mpz_mul(gmp_c, gmp_a, gmp_b); 73 | while (mpz_cmp(gmp_c, two_to_K) >= 0) { 74 | mpz_mod_2exp(gmp_low, gmp_c, K); 75 | mpz_div_2exp(gmp_high, gmp_c, K); 76 | mpz_mul(gmp_high, gmp_high, pModTwoK); 77 | mpz_add(gmp_c, gmp_low, gmp_high); 78 | } 79 | mpz_export(want_c, NULL, -1, N, 0, 0, gmp_c); 80 | 81 | assert(memcmp(get_c, want_c, N) == 0); 82 | 83 | mpz_clear(gmp_a); 84 | mpz_clear(gmp_b); 85 | mpz_clear(gmp_c); 86 | mpz_clear(gmp_low); 87 | mpz_clear(gmp_high); 88 | mpz_clear(two_to_K); 89 | mpz_clear(pModTwoK); 90 | return 0; 91 | } 92 | 93 | #ifdef __cplusplus 94 | } 95 | #endif 96 | -------------------------------------------------------------------------------- /fuzz/opRed.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2017, Armando Faz . All rights reserved. 3 | * Institute of Computing. 4 | * University of Campinas, Brazil. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions 8 | * are met: 9 | * 10 | * * Redistributions of source code must retain the above copyright 11 | * notice, this list of conditions and the following disclaimer. 12 | * * Redistributions in binary form must reproduce the above 13 | * copyright notice, this list of conditions and the following 14 | * disclaimer in the documentation and/or other materials provided 15 | * with the distribution. 16 | * * Neither the name of University of Campinas nor the names of its 17 | * contributors may be used to endorse or promote products derived 18 | * from this software without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 23 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 24 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 25 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 26 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 29 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 31 | * OF THE POSSIBILITY OF SUCH DAMAGE. 32 | */ 33 | 34 | #include "fp.h" 35 | 36 | /** 37 | * Verifies that 0 <= c < 2^K be congruent (mod p) to 0<= a < 2^(2*K) 38 | * @param Data Random binary data. 39 | * @param Size Non-trivial input size is set -max_len=2*N 40 | * @return Always return 0 in case of success. 41 | */ 42 | #ifdef __cplusplus 43 | extern "C" { 44 | #endif 45 | 46 | int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { 47 | if (Size != 2 * N) return 0; 48 | TYPE get_c, want_c; 49 | TYPE_BUFFER a; 50 | 51 | mpz_t gmp_a, gmp_low, gmp_high, two_to_K, pModTwoK; 52 | mpz_init(gmp_a); 53 | mpz_init(gmp_low); 54 | mpz_init(gmp_high); 55 | getTwoPower(two_to_K); // two_to_256 = 2^K 56 | getPModTwoK(pModTwoK); 57 | 58 | FpZero(get_c); 59 | FpZero(want_c); 60 | 61 | memcpy(a, Data + 0, 2 * N); 62 | 63 | FpRed(get_c, a); 64 | 65 | mpz_import(gmp_a, 2 * N, -1, sizeof(Data[0]), 0, 0, Data + 0); 66 | 67 | while (mpz_cmp(gmp_a, two_to_K) >= 0) { 68 | mpz_mod_2exp(gmp_low, gmp_a, K); 69 | mpz_div_2exp(gmp_high, gmp_a, K); 70 | mpz_mul(gmp_high, gmp_high, pModTwoK); 71 | mpz_add(gmp_a, gmp_low, gmp_high); 72 | } 73 | mpz_export(want_c, NULL, -1, N, 0, 0, gmp_a); 74 | 75 | assert(memcmp(get_c, want_c, N) == 0); 76 | 77 | mpz_clear(gmp_a); 78 | mpz_clear(gmp_low); 79 | mpz_clear(gmp_high); 80 | mpz_clear(two_to_K); 81 | mpz_clear(pModTwoK); 82 | return 0; 83 | } 84 | 85 | #ifdef __cplusplus 86 | } 87 | #endif 88 | -------------------------------------------------------------------------------- /fuzz/opSqr.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2017, Armando Faz . All rights reserved. 3 | * Institute of Computing. 4 | * University of Campinas, Brazil. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions 8 | * are met: 9 | * 10 | * * Redistributions of source code must retain the above copyright 11 | * notice, this list of conditions and the following disclaimer. 12 | * * Redistributions in binary form must reproduce the above 13 | * copyright notice, this list of conditions and the following 14 | * disclaimer in the documentation and/or other materials provided 15 | * with the distribution. 16 | * * Neither the name of University of Campinas nor the names of its 17 | * contributors may be used to endorse or promote products derived 18 | * from this software without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 23 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 24 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 25 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 26 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 29 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 31 | * OF THE POSSIBILITY OF SUCH DAMAGE. 32 | */ 33 | 34 | #include "fp.h" 35 | 36 | /** 37 | * Verifies that 0 <= c=a^2 < 2^(2K) 38 | * @param Data Random binary data. 39 | * @param Size Non-trivial input size is set -max_len=N 40 | * @return Always return 0 in case of success. 41 | */ 42 | #ifdef __cplusplus 43 | extern "C" { 44 | #endif 45 | 46 | int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { 47 | if (Size != N) return 0; 48 | 49 | TYPE get_c, want_c; 50 | TYPE_BUFFER buffer_1w; 51 | 52 | mpz_t gmp_a, gmp_c, gmp_low, gmp_high, two_to_K, pModTwoK; 53 | mpz_init(gmp_a); 54 | mpz_init(gmp_c); 55 | mpz_init(gmp_low); 56 | mpz_init(gmp_high); 57 | getTwoPower(two_to_K); 58 | getPModTwoK(pModTwoK); 59 | 60 | memcpy(get_c, Data + 0 * N, N); 61 | 62 | FpZero(want_c); 63 | 64 | FpSqr(get_c); 65 | 66 | mpz_import(gmp_a, N, -1, sizeof(Data[0]), 0, 0, Data + 0 * N); 67 | 68 | mpz_mul(gmp_c, gmp_a, gmp_a); 69 | while (mpz_cmp(gmp_c, two_to_K) >= 0) { 70 | mpz_mod_2exp(gmp_low, gmp_c, K); 71 | mpz_div_2exp(gmp_high, gmp_c, K); 72 | mpz_mul(gmp_high, gmp_high, pModTwoK); 73 | mpz_add(gmp_c, gmp_low, gmp_high); 74 | } 75 | mpz_export(want_c, NULL, -1, N, 0, 0, gmp_c); 76 | 77 | assert(memcmp(get_c, want_c, N) == 0); 78 | 79 | mpz_clear(gmp_a); 80 | mpz_clear(gmp_c); 81 | mpz_clear(gmp_low); 82 | mpz_clear(gmp_high); 83 | mpz_clear(two_to_K); 84 | mpz_clear(pModTwoK); 85 | return 0; 86 | } 87 | 88 | #ifdef __cplusplus 89 | } 90 | #endif 91 | -------------------------------------------------------------------------------- /fuzz/opSub.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2017, Armando Faz . All rights reserved. 3 | * Institute of Computing. 4 | * University of Campinas, Brazil. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions 8 | * are met: 9 | * 10 | * * Redistributions of source code must retain the above copyright 11 | * notice, this list of conditions and the following disclaimer. 12 | * * Redistributions in binary form must reproduce the above 13 | * copyright notice, this list of conditions and the following 14 | * disclaimer in the documentation and/or other materials provided 15 | * with the distribution. 16 | * * Neither the name of University of Campinas nor the names of its 17 | * contributors may be used to endorse or promote products derived 18 | * from this software without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 23 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 24 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 25 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 26 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 29 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 31 | * OF THE POSSIBILITY OF SUCH DAMAGE. 32 | */ 33 | 34 | #include "fp.h" 35 | 36 | /** 37 | * Verifies that 0 <= c=a-b < 2^K and that c be congruent to a-b mod p 38 | * @param Data Random binary data. 39 | * @param Size Non-trivial input size is set -max_len=2*N 40 | * @return Always return 0 in case of success. 41 | */ 42 | #ifdef __cplusplus 43 | extern "C" { 44 | #endif 45 | 46 | int LLVMFuzzerTestOneInput(const uint8_t* Data, size_t Size) { 47 | if (Size != 2 * N) return 0; 48 | TYPE a, b, get_c, want_c; 49 | 50 | mpz_t gmp_a, gmp_b, gmp_c, two_prime, zero; 51 | mpz_init(gmp_a); 52 | mpz_init(gmp_b); 53 | mpz_init(gmp_c); 54 | getTwoPrime(two_prime); // two_prime = 2p 55 | mpz_init_set_ui(zero, 0); 56 | 57 | memcpy(a, Data + 0 * N, N); 58 | memcpy(b, Data + 1 * N, N); 59 | 60 | FpZero(get_c); 61 | FpZero(want_c); 62 | 63 | FpSub(get_c, a, b); 64 | 65 | mpz_import(gmp_a, N, -1, sizeof(Data[0]), 0, 0, Data + 0 * N); 66 | mpz_import(gmp_b, N, -1, sizeof(Data[0]), 0, 0, Data + 1 * N); 67 | 68 | mpz_sub(gmp_c, gmp_a, gmp_b); 69 | while (mpz_cmp(gmp_c, zero) < 0) { 70 | mpz_add(gmp_c, gmp_c, two_prime); 71 | } 72 | mpz_export(want_c, NULL, -1, N, 0, 0, gmp_c); 73 | assert(memcmp(get_c, want_c, N) == 0); 74 | 75 | mpz_clear(gmp_a); 76 | mpz_clear(gmp_b); 77 | mpz_clear(gmp_c); 78 | mpz_clear(two_prime); 79 | mpz_clear(zero); 80 | return 0; 81 | } 82 | 83 | #ifdef __cplusplus 84 | } 85 | #endif 86 | -------------------------------------------------------------------------------- /include/fp25519_x64.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2017, Armando Faz . All rights reserved. 3 | * Institute of Computing. 4 | * University of Campinas, Brazil. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions 8 | * are met: 9 | * 10 | * * Redistributions of source code must retain the above copyright 11 | * notice, this list of conditions and the following disclaimer. 12 | * * Redistributions in binary form must reproduce the above 13 | * copyright notice, this list of conditions and the following 14 | * disclaimer in the documentation and/or other materials provided 15 | * with the distribution. 16 | * * Neither the name of University of Campinas nor the names of its 17 | * contributors may be used to endorse or promote products derived 18 | * from this software without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 23 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 24 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 25 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 26 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 29 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 31 | * OF THE POSSIBILITY OF SUCH DAMAGE. 32 | */ 33 | 34 | #ifndef FP25519_X64_H 35 | #define FP25519_X64_H 36 | 37 | #include 38 | 39 | #ifndef ALIGN_BYTES 40 | #define ALIGN_BYTES 32 41 | #endif 42 | 43 | #ifndef ALIGN 44 | #ifdef __INTEL_COMPILER 45 | #define ALIGN __declspec(align(ALIGN_BYTES)) 46 | #else 47 | #define ALIGN __attribute__((aligned(ALIGN_BYTES))) 48 | #endif 49 | #endif 50 | 51 | #define SIZE_BYTES_FP25519 32 52 | #define NUM_WORDS_ELTFP25519_X64 4 53 | typedef ALIGN uint64_t EltFp25519_1w_x64[NUM_WORDS_ELTFP25519_X64]; 54 | typedef ALIGN uint64_t EltFp25519_1w_Buffer_x64[2 * NUM_WORDS_ELTFP25519_X64]; 55 | typedef ALIGN uint64_t EltFp25519_2w_x64[2 * NUM_WORDS_ELTFP25519_X64]; 56 | typedef ALIGN uint64_t EltFp25519_2w_Buffer_x64[4 * NUM_WORDS_ELTFP25519_X64]; 57 | 58 | #ifdef __cplusplus 59 | extern "C" { 60 | #endif 61 | 62 | /* Integer Arithmetic */ 63 | void mul2_256x256_integer_x64(uint64_t *const c, uint64_t *const a, 64 | uint64_t *const b); 65 | 66 | void sqr2_256x256_integer_x64(uint64_t *const c, uint64_t *const a); 67 | 68 | void red_EltFp25519_2w_x64(uint64_t *const c, uint64_t *const a); 69 | 70 | void mul_256x256_integer_x64(uint64_t *const c, uint64_t *const a, 71 | uint64_t *const b); 72 | 73 | void sqr_256x256_integer_x64(uint64_t *const c, uint64_t *const a); 74 | 75 | void red_EltFp25519_1w_x64(uint64_t *const c, uint64_t *const a); 76 | 77 | /* Prime Field Arithmetic */ 78 | void add_EltFp25519_1w_x64(uint64_t *const c, uint64_t *const a, 79 | uint64_t *const b); 80 | 81 | void sub_EltFp25519_1w_x64(uint64_t *const c, uint64_t *const a, 82 | uint64_t *const b); 83 | 84 | void mul_a24_EltFp25519_1w_x64(uint64_t *const c, uint64_t *const a); 85 | 86 | void inv_EltFp25519_1w_x64(uint64_t *const c, uint64_t *const a); 87 | 88 | void fred_EltFp25519_1w_x64(uint64_t *const c); 89 | 90 | #ifdef __cplusplus 91 | } 92 | #endif 93 | 94 | #define mul_EltFp25519_1w_x64(c, a, b) \ 95 | mul_256x256_integer_x64(buffer_1w, a, b); \ 96 | red_EltFp25519_1w_x64(c, buffer_1w); 97 | 98 | #define sqr_EltFp25519_1w_x64(a) \ 99 | sqr_256x256_integer_x64(buffer_1w, a); \ 100 | red_EltFp25519_1w_x64(a, buffer_1w); 101 | 102 | #define mul_EltFp25519_2w_x64(c, a, b) \ 103 | mul2_256x256_integer_x64(buffer_2w, a, b); \ 104 | red_EltFp25519_2w_x64(c, buffer_2w); 105 | 106 | #define sqr_EltFp25519_2w_x64(a) \ 107 | sqr2_256x256_integer_x64(buffer_2w, a); \ 108 | red_EltFp25519_2w_x64(a, buffer_2w); 109 | 110 | #define copy_EltFp25519_1w_x64(C, A) \ 111 | (C)[0] = (A)[0]; \ 112 | (C)[1] = (A)[1]; \ 113 | (C)[2] = (A)[2]; \ 114 | (C)[3] = (A)[3]; 115 | 116 | #define setzero_EltFp25519_1w_x64(C) \ 117 | (C)[0] = 0; \ 118 | (C)[1] = 0; \ 119 | (C)[2] = 0; \ 120 | (C)[3] = 0; 121 | 122 | #endif /* FP25519_X64_H */ 123 | -------------------------------------------------------------------------------- /include/fp448_x64.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2017, Armando Faz . All rights reserved. 3 | * Institute of Computing. 4 | * University of Campinas, Brazil. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions 8 | * are met: 9 | * 10 | * * Redistributions of source code must retain the above copyright 11 | * notice, this list of conditions and the following disclaimer. 12 | * * Redistributions in binary form must reproduce the above 13 | * copyright notice, this list of conditions and the following 14 | * disclaimer in the documentation and/or other materials provided 15 | * with the distribution. 16 | * * Neither the name of University of Campinas nor the names of its 17 | * contributors may be used to endorse or promote products derived 18 | * from this software without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 23 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 24 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 25 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 26 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 29 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 31 | * OF THE POSSIBILITY OF SUCH DAMAGE. 32 | */ 33 | 34 | #ifndef FP448_X64_H 35 | #define FP448_X64_H 36 | 37 | #include 38 | 39 | #ifndef ALIGN_BYTES 40 | #define ALIGN_BYTES 32 41 | #endif 42 | 43 | #ifndef ALIGN 44 | #ifdef __INTEL_COMPILER 45 | #define ALIGN __declspec(align(ALIGN_BYTES)) 46 | #else 47 | #define ALIGN __attribute__((aligned(ALIGN_BYTES))) 48 | #endif 49 | #endif 50 | 51 | #define SIZE_BYTES_FP448 56 52 | #define NUM_WORDS_ELTFP448_X64 7 53 | typedef ALIGN uint64_t EltFp448_1w_x64[NUM_WORDS_ELTFP448_X64]; 54 | typedef ALIGN uint64_t EltFp448_1w_Buffer_x64[2 * NUM_WORDS_ELTFP448_X64]; 55 | 56 | #ifdef __cplusplus 57 | extern "C" { 58 | #endif 59 | 60 | /* Integer Arithmetic */ 61 | void mul_448x448_integer_x64(uint64_t *const c, uint64_t *const a, 62 | uint64_t *const b); 63 | 64 | void sqr_448x448_integer_x64(uint64_t *const c, uint64_t *const a); 65 | 66 | void red_EltFp448_1w_x64(uint64_t *const c, uint64_t *const a); 67 | 68 | /* Prime Field Arithmetic */ 69 | void add_EltFp448_1w_x64(uint64_t *const c, uint64_t *const a, 70 | uint64_t *const b); 71 | 72 | void sub_EltFp448_1w_x64(uint64_t *const c, uint64_t *const a, 73 | uint64_t *const b); 74 | 75 | void mul_a24_EltFp448_1w_x64(uint64_t *const c, uint64_t *const a); 76 | 77 | void inv_EltFp448_1w_x64(uint64_t *const pC, uint64_t *const pA); 78 | 79 | void fred_EltFp448_1w_x64(uint64_t *const c); 80 | 81 | #ifdef __cplusplus 82 | } 83 | #endif 84 | 85 | #define mul_EltFp448_1w_x64(C, A, B) \ 86 | mul_448x448_integer_x64(buffer_1w, A, B); \ 87 | red_EltFp448_1w_x64(C, buffer_1w); 88 | 89 | #define sqr_EltFp448_1w_x64(A) \ 90 | sqr_448x448_integer_x64(buffer_1w, A); \ 91 | red_EltFp448_1w_x64(A, buffer_1w); 92 | 93 | #define copy_EltFp448_1w_x64(C, A) \ 94 | C[0] = A[0]; \ 95 | C[1] = A[1]; \ 96 | C[2] = A[2]; \ 97 | C[3] = A[3]; \ 98 | C[4] = A[4]; \ 99 | C[5] = A[5]; \ 100 | C[6] = A[6]; 101 | 102 | #define setzero_EltFp448_1w_x64(C) \ 103 | (C)[0] = 0; \ 104 | (C)[1] = 0; \ 105 | (C)[2] = 0; \ 106 | (C)[3] = 0; \ 107 | (C)[4] = 0; \ 108 | (C)[5] = 0; \ 109 | (C)[6] = 0; 110 | 111 | #endif /* FP448_X64_H */ 112 | -------------------------------------------------------------------------------- /include/rfc7748_precomputed.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2017, Armando Faz . All rights reserved. 3 | * Institute of Computing. 4 | * University of Campinas, Brazil. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions 8 | * are met: 9 | * 10 | * * Redistributions of source code must retain the above copyright 11 | * notice, this list of conditions and the following disclaimer. 12 | * * Redistributions in binary form must reproduce the above 13 | * copyright notice, this list of conditions and the following 14 | * disclaimer in the documentation and/or other materials provided 15 | * with the distribution. 16 | * * Neither the name of University of Campinas nor the names of its 17 | * contributors may be used to endorse or promote products derived 18 | * from this software without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 23 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 24 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 25 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 26 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 29 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 31 | * OF THE POSSIBILITY OF SUCH DAMAGE. 32 | */ 33 | 34 | #ifndef RFC7748_PRECOMPUTED_H 35 | #define RFC7748_PRECOMPUTED_H 36 | 37 | #include 38 | 39 | #ifndef ALIGN_BYTES 40 | #define ALIGN_BYTES 32 41 | #endif 42 | 43 | #ifndef ALIGN 44 | #ifdef __INTEL_COMPILER 45 | #define ALIGN __declspec(align(ALIGN_BYTES)) 46 | #else 47 | #define ALIGN __attribute__((aligned(ALIGN_BYTES))) 48 | #endif 49 | #endif 50 | 51 | #define X25519_KEYSIZE_BYTES 32 52 | typedef ALIGN uint8_t X25519_KEY[X25519_KEYSIZE_BYTES]; 53 | #define X448_KEYSIZE_BYTES 56 54 | typedef ALIGN uint8_t X448_KEY[X448_KEYSIZE_BYTES]; 55 | 56 | typedef uint8_t *argKey; 57 | 58 | typedef void (*KeyGen)(argKey session_key, argKey private_key); 59 | 60 | typedef void (*Shared)(argKey shared, argKey session_key, argKey private_key); 61 | 62 | extern const KeyGen X25519_KeyGen; 63 | extern const Shared X25519_Shared; 64 | extern const KeyGen X448_KeyGen; 65 | extern const Shared X448_Shared; 66 | 67 | #endif /* RFC7748_PRECOMPUTED_H */ 68 | -------------------------------------------------------------------------------- /samples/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.0.2) 2 | 3 | include_directories(../include) 4 | include_directories(../third_party) 5 | 6 | add_executable(sample_x25519 sample_x25519.c ../third_party/random.c) 7 | add_executable(sample_x448 sample_x448.c ../third_party/random.c) 8 | add_dependencies(sample_x25519 ${TARGET}) 9 | add_dependencies(sample_x448 ${TARGET}) 10 | target_link_libraries(sample_x25519 ${TARGET}) 11 | target_link_libraries(sample_x448 ${TARGET}) 12 | -------------------------------------------------------------------------------- /samples/sample_x25519.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "random.h" 4 | 5 | static void random_X25519_key(argKey key) { 6 | random_bytes(key, X25519_KEYSIZE_BYTES); 7 | } 8 | 9 | static void print_X25519_key(argKey key) { 10 | print_bytes(key, X25519_KEYSIZE_BYTES); 11 | } 12 | 13 | int main(void) { 14 | X25519_KEY alice_private_key, alice_session_key, alice_shared; 15 | X25519_KEY bob_private_key, bob_session_key, bob_shared; 16 | 17 | random_X25519_key(alice_private_key); 18 | printf("Alice's Private Key: "); 19 | print_X25519_key(alice_private_key); 20 | 21 | random_X25519_key(bob_private_key); 22 | printf("Bob's Private Key: "); 23 | print_X25519_key(bob_private_key); 24 | 25 | X25519_KeyGen(alice_session_key, alice_private_key); 26 | printf("Alice's Session Key: "); 27 | print_X25519_key(alice_session_key); 28 | 29 | X25519_KeyGen(bob_session_key, bob_private_key); 30 | printf("Bob's Session Key: "); 31 | print_X25519_key(bob_session_key); 32 | 33 | X25519_Shared(alice_shared, bob_session_key, alice_private_key); 34 | printf("Alice's Shared Secreet:"); 35 | print_X25519_key(alice_shared); 36 | 37 | X25519_Shared(bob_shared, alice_session_key, bob_private_key); 38 | printf("Bob's Shared Secreet: "); 39 | print_X25519_key(bob_shared); 40 | 41 | return 0; 42 | } 43 | -------------------------------------------------------------------------------- /samples/sample_x448.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "random.h" 4 | 5 | static void random_X448_key(argKey key) { 6 | random_bytes(key, X448_KEYSIZE_BYTES); 7 | } 8 | 9 | static void print_X448_key(argKey key) { print_bytes(key, X448_KEYSIZE_BYTES); } 10 | 11 | int main(void) { 12 | X448_KEY alice_private_key, alice_session_key, alice_shared; 13 | X448_KEY bob_private_key, bob_session_key, bob_shared; 14 | 15 | random_X448_key(alice_private_key); 16 | printf("Alice's Private Key: "); 17 | print_X448_key(alice_private_key); 18 | 19 | random_X448_key(bob_private_key); 20 | printf("Bob's Private Key: "); 21 | print_X448_key(bob_private_key); 22 | 23 | X448_KeyGen(alice_session_key, alice_private_key); 24 | printf("Alice's Session Key: "); 25 | print_X448_key(alice_session_key); 26 | 27 | X448_KeyGen(bob_session_key, bob_private_key); 28 | printf("Bob's Session Key: "); 29 | print_X448_key(bob_session_key); 30 | 31 | X448_Shared(alice_shared, bob_session_key, alice_private_key); 32 | printf("Alice's Shared Secreet:"); 33 | print_X448_key(alice_shared); 34 | 35 | X448_Shared(bob_shared, alice_session_key, bob_private_key); 36 | printf("Bob's Shared Secreet: "); 37 | print_X448_key(bob_shared); 38 | 39 | return 0; 40 | } 41 | -------------------------------------------------------------------------------- /src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.0.2) 2 | enable_language(C) 3 | 4 | set(PROJECT_FLAGS "-Wall -Wextra -O3 -pedantic -std=c99 -mbmi2 -march=native -mtune=native") 5 | set(CMAKE_BUILD_TYPE Release) 6 | set(CMAKE_POSITION_INDEPENDENT_CODE ON) 7 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${PROJECT_FLAGS}") 8 | set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${PROJECT_FLAGS}") 9 | 10 | include_directories(../include) 11 | set(c_files 12 | fp25519_x64.c 13 | x25519_x64.c 14 | fp448_x64.c 15 | x448_x64.c) 16 | 17 | add_library(${TARGET} STATIC ${c_files}) 18 | add_library(${TARGET}-shared SHARED ${c_files}) 19 | 20 | set_target_properties(${TARGET} PROPERTIES 21 | OUTPUT_NAME ${TARGET} CLEAN_DIRECT_OUTPUT 1 22 | PUBLIC_HEADER ../include/${TARGET}.h) 23 | 24 | set_target_properties(${TARGET}-shared PROPERTIES 25 | OUTPUT_NAME ${TARGET} CLEAN_DIRECT_OUTPUT 1 26 | PUBLIC_HEADER ../include/${TARGET}.h) 27 | 28 | include("GNUInstallDirs") 29 | INSTALL(TARGETS ${TARGET} 30 | PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} 31 | ARCHIVE DESTINATION ${CMAKE_INSTALL_PREFIX}) 32 | INSTALL(TARGETS ${TARGET}-shared 33 | PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} 34 | LIBRARY DESTINATION ${CMAKE_INSTALL_PREFIX}) 35 | -------------------------------------------------------------------------------- /src/x25519_x64.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2017, Armando Faz . All rights reserved. 3 | * Institute of Computing. 4 | * University of Campinas, Brazil. 5 | * 6 | * Copyright (C) 2018 Jason A. Donenfeld . All Rights Reserved. 7 | * 8 | * Redistribution and use in source and binary forms, with or without 9 | * modification, are permitted provided that the following conditions 10 | * are met: 11 | * 12 | * * Redistributions of source code must retain the above copyright 13 | * notice, this list of conditions and the following disclaimer. 14 | * * Redistributions in binary form must reproduce the above 15 | * copyright notice, this list of conditions and the following 16 | * disclaimer in the documentation and/or other materials provided 17 | * with the distribution. 18 | * * Neither the name of University of Campinas nor the names of its 19 | * contributors may be used to endorse or promote products derived 20 | * from this software without specific prior written permission. 21 | * 22 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 23 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 24 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 25 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 26 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 27 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 28 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 29 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 31 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 32 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 33 | * OF THE POSSIBILITY OF SUCH DAMAGE. 34 | */ 35 | 36 | #include 37 | #include "fp25519_x64.h" 38 | #include "rfc7748_precomputed.h" 39 | #include "table_ladder_x25519.h" 40 | 41 | static inline void cswap(uint8_t bit, uint64_t *const px, uint64_t *const py) { 42 | uint64_t temp; 43 | __asm__ __volatile__( 44 | "test %9, %9;" 45 | "movq %0, %8; cmovnzq %4, %0; cmovnzq %8, %4;" 46 | "movq %1, %8; cmovnzq %5, %1; cmovnzq %8, %5;" 47 | "movq %2, %8; cmovnzq %6, %2; cmovnzq %8, %6;" 48 | "movq %3, %8; cmovnzq %7, %3; cmovnzq %8, %7;" 49 | : "+r"(px[0]), "+r"(px[1]), "+r"(px[2]), "+r"(px[3]), "+r"(py[0]), 50 | "+r"(py[1]), "+r"(py[2]), "+r"(py[3]), "=r"(temp) 51 | : "r"(bit) 52 | : "cc"); 53 | } 54 | 55 | static inline void cselect(uint8_t bit, uint64_t *const px, 56 | uint64_t *const py) { 57 | __asm__ __volatile__( 58 | "test %4, %4;" 59 | "cmovnzq %5, %0; cmovnzq %6, %1; cmovnzq %7, %2; cmovnzq %8, %3;" 60 | : "+r"(px[0]), "+r"(px[1]), "+r"(px[2]), "+r"(px[3]) 61 | : "r"(bit), "rm"(py[0]), "rm"(py[1]), "rm"(py[2]), "rm"(py[3]) 62 | : "cc"); 63 | } 64 | 65 | static void x25519_shared_secret_x64(argKey shared, argKey session_key, 66 | argKey private_key) { 67 | ALIGN uint64_t buffer[4 * NUM_WORDS_ELTFP25519_X64]; 68 | ALIGN uint64_t coordinates[4 * NUM_WORDS_ELTFP25519_X64]; 69 | ALIGN uint64_t workspace[6 * NUM_WORDS_ELTFP25519_X64]; 70 | ALIGN uint8_t session[X25519_KEYSIZE_BYTES]; 71 | ALIGN uint8_t private[X25519_KEYSIZE_BYTES]; 72 | 73 | int i = 0, j = 0; 74 | uint64_t prev = 0; 75 | uint64_t *const X1 = (uint64_t *)session; 76 | uint64_t *const key = (uint64_t *)private; 77 | uint64_t *const Px = coordinates + 0; 78 | uint64_t *const Pz = coordinates + 4; 79 | uint64_t *const Qx = coordinates + 8; 80 | uint64_t *const Qz = coordinates + 12; 81 | uint64_t *const X2 = Qx; 82 | uint64_t *const Z2 = Qz; 83 | uint64_t *const X3 = Px; 84 | uint64_t *const Z3 = Pz; 85 | uint64_t *const X2Z2 = Qx; 86 | uint64_t *const X3Z3 = Px; 87 | 88 | uint64_t *const A = workspace + 0; 89 | uint64_t *const B = workspace + 4; 90 | uint64_t *const D = workspace + 8; 91 | uint64_t *const C = workspace + 12; 92 | uint64_t *const DA = workspace + 16; 93 | uint64_t *const CB = workspace + 20; 94 | uint64_t *const AB = A; 95 | uint64_t *const DC = D; 96 | uint64_t *const DACB = DA; 97 | uint64_t *const buffer_1w = buffer; 98 | uint64_t *const buffer_2w = buffer; 99 | 100 | memcpy(private, private_key, sizeof(private)); 101 | memcpy(session, session_key, sizeof(session)); 102 | 103 | /* clampC function */ 104 | private 105 | [0] = private[0] & (~(uint8_t)0x7); 106 | private 107 | [X25519_KEYSIZE_BYTES - 1] = 108 | (uint8_t)64 | (private[X25519_KEYSIZE_BYTES - 1] & (uint8_t)0x7F); 109 | 110 | /** 111 | * As in the RFC-7748: 112 | * When receiving such an array, implementations of X25519 113 | * (but not X448) MUST mask the most significant bit in the final byte. 114 | * This is done to preserve compatibility with point formats that 115 | * reserve the sign bit for use in other protocols and to increase 116 | * resistance to implementation fingerprinting. 117 | **/ 118 | session[X25519_KEYSIZE_BYTES - 1] &= (1 << (255 % 8)) - 1; 119 | 120 | copy_EltFp25519_1w_x64(Px, X1); 121 | setzero_EltFp25519_1w_x64(Pz); 122 | setzero_EltFp25519_1w_x64(Qx); 123 | setzero_EltFp25519_1w_x64(Qz); 124 | 125 | Pz[0] = 1; 126 | Qx[0] = 1; 127 | 128 | /* main-loop */ 129 | prev = 0; 130 | j = 62; 131 | for (i = 3; i >= 0; i--) { 132 | while (j >= 0) { 133 | uint64_t bit = (key[i] >> j) & 0x1; 134 | uint64_t swap = bit ^ prev; 135 | prev = bit; 136 | 137 | add_EltFp25519_1w_x64(A, X2, Z2); /* A = (X2+Z2) */ 138 | sub_EltFp25519_1w_x64(B, X2, Z2); /* B = (X2-Z2) */ 139 | add_EltFp25519_1w_x64(C, X3, Z3); /* C = (X3+Z3) */ 140 | sub_EltFp25519_1w_x64(D, X3, Z3); /* D = (X3-Z3) */ 141 | mul_EltFp25519_2w_x64(DACB, AB, DC); /* [DA|CB] = [A|B]*[D|C] */ 142 | 143 | cselect(swap, A, C); 144 | cselect(swap, B, D); 145 | 146 | sqr_EltFp25519_2w_x64(AB); /* [AA|BB] = [A^2|B^2] */ 147 | add_EltFp25519_1w_x64(X3, DA, CB); /* X3 = (DA+CB) */ 148 | sub_EltFp25519_1w_x64(Z3, DA, CB); /* Z3 = (DA-CB) */ 149 | sqr_EltFp25519_2w_x64(X3Z3); /* [X3|Z3] = [(DA+CB)|(DA+CB)]^2 */ 150 | 151 | copy_EltFp25519_1w_x64(X2, B); /* X2 = B^2 */ 152 | sub_EltFp25519_1w_x64(Z2, A, B); /* Z2 = E = AA-BB */ 153 | 154 | mul_a24_EltFp25519_1w_x64(B, Z2); /* B = a24*E */ 155 | add_EltFp25519_1w_x64(B, B, X2); /* B = a24*E+B */ 156 | mul_EltFp25519_2w_x64(X2Z2, X2Z2, AB); /* [X2|Z2] = [B|E]*[A|a24*E+B] */ 157 | mul_EltFp25519_1w_x64(Z3, Z3, X1); /* Z3 = Z3*X1 */ 158 | j--; 159 | } 160 | j = 63; 161 | } 162 | 163 | inv_EltFp25519_1w_x64(A, Qz); 164 | mul_EltFp25519_1w_x64((uint64_t *)shared, Qx, A); 165 | fred_EltFp25519_1w_x64((uint64_t *)shared); 166 | } 167 | 168 | static void x25519_keygen_precmp_x64(argKey session_key, argKey private_key) { 169 | ALIGN uint64_t buffer[4 * NUM_WORDS_ELTFP25519_X64]; 170 | ALIGN uint64_t coordinates[4 * NUM_WORDS_ELTFP25519_X64]; 171 | ALIGN uint64_t workspace[4 * NUM_WORDS_ELTFP25519_X64]; 172 | ALIGN uint8_t private[X25519_KEYSIZE_BYTES]; 173 | 174 | int i = 0, j = 0, k = 0; 175 | uint64_t *const key = (uint64_t *)private; 176 | uint64_t *const Ur1 = coordinates + 0; 177 | uint64_t *const Zr1 = coordinates + 4; 178 | uint64_t *const Ur2 = coordinates + 8; 179 | uint64_t *const Zr2 = coordinates + 12; 180 | 181 | uint64_t *const UZr1 = coordinates + 0; 182 | uint64_t *const ZUr2 = coordinates + 8; 183 | 184 | uint64_t *const A = workspace + 0; 185 | uint64_t *const B = workspace + 4; 186 | uint64_t *const C = workspace + 8; 187 | uint64_t *const D = workspace + 12; 188 | 189 | uint64_t *const AB = workspace + 0; 190 | uint64_t *const CD = workspace + 8; 191 | 192 | uint64_t *const buffer_1w = buffer; 193 | uint64_t *const buffer_2w = buffer; 194 | uint64_t *P = (uint64_t *)Table_Ladder_8k; 195 | 196 | memcpy(private, private_key, sizeof(private)); 197 | 198 | /* clampC function */ 199 | private 200 | [0] = private[0] & (~(uint8_t)0x7); 201 | private 202 | [X25519_KEYSIZE_BYTES - 1] = 203 | (uint8_t)64 | (private[X25519_KEYSIZE_BYTES - 1] & (uint8_t)0x7F); 204 | 205 | setzero_EltFp25519_1w_x64(Ur1); 206 | setzero_EltFp25519_1w_x64(Zr1); 207 | setzero_EltFp25519_1w_x64(Zr2); 208 | Ur1[0] = 1; 209 | Zr1[0] = 1; 210 | Zr2[0] = 1; 211 | 212 | /* G-S */ 213 | Ur2[3] = 0x1eaecdeee27cab34; 214 | Ur2[2] = 0xadc7a0b9235d48e2; 215 | Ur2[1] = 0xbbf095ae14b2edf8; 216 | Ur2[0] = 0x7e94e1fec82faabd; 217 | 218 | /* main-loop */ 219 | const int ite[4] = {64, 64, 64, 63}; 220 | const int q = 3; 221 | uint64_t swap = 1; 222 | 223 | j = q; 224 | for (i = 0; i < NUM_WORDS_ELTFP25519_X64; i++) { 225 | while (j < ite[i]) { 226 | k = (64 * i + j - q); 227 | uint64_t bit = (key[i] >> j) & 0x1; 228 | swap = swap ^ bit; 229 | cswap(swap, Ur1, Ur2); 230 | cswap(swap, Zr1, Zr2); 231 | swap = bit; 232 | /** Addition */ 233 | sub_EltFp25519_1w_x64(B, Ur1, Zr1); /* B = Ur1-Zr1 */ 234 | add_EltFp25519_1w_x64(A, Ur1, Zr1); /* A = Ur1+Zr1 */ 235 | mul_EltFp25519_1w_x64(C, &P[4 * k], B); /* C = M0-B */ 236 | sub_EltFp25519_1w_x64(B, A, C); /* B = (Ur1+Zr1) - M*(Ur1-Zr1) */ 237 | add_EltFp25519_1w_x64(A, A, C); /* A = (Ur1+Zr1) + M*(Ur1-Zr1) */ 238 | sqr_EltFp25519_2w_x64(AB); /* A = A^2 | B = B^2 */ 239 | mul_EltFp25519_2w_x64(UZr1, ZUr2, AB); /* Ur1 = Zr2*A | Zr1 = Ur2*B */ 240 | j++; 241 | } 242 | j = 0; 243 | } 244 | 245 | /** Doubling */ 246 | for (i = 0; i < q; i++) { 247 | add_EltFp25519_1w_x64(A, Ur1, Zr1); /* A = Ur1+Zr1 */ 248 | sub_EltFp25519_1w_x64(B, Ur1, Zr1); /* B = Ur1-Zr1 */ 249 | sqr_EltFp25519_2w_x64(AB); /* A = A**2 B = B**2 */ 250 | copy_EltFp25519_1w_x64(C, B); /* C = B */ 251 | sub_EltFp25519_1w_x64(B, A, B); /* B = A-B */ 252 | mul_a24_EltFp25519_1w_x64(D, B); /* D = my_a24*B */ 253 | add_EltFp25519_1w_x64(D, D, C); /* D = D+C */ 254 | mul_EltFp25519_2w_x64(UZr1, AB, CD); /* Ur1 = A*B Zr1 = Zr1*A */ 255 | } 256 | 257 | /* Convert to affine coordinates */ 258 | inv_EltFp25519_1w_x64(A, Zr1); 259 | mul_EltFp25519_1w_x64((uint64_t *)session_key, Ur1, A); 260 | fred_EltFp25519_1w_x64((uint64_t *)session_key); 261 | } 262 | 263 | const KeyGen X25519_KeyGen = x25519_keygen_precmp_x64; 264 | const Shared X25519_Shared = x25519_shared_secret_x64; 265 | -------------------------------------------------------------------------------- /src/x448_x64.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2017, Armando Faz . All rights reserved. 3 | * Institute of Computing. 4 | * University of Campinas, Brazil. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions 8 | * are met: 9 | * 10 | * * Redistributions of source code must retain the above copyright 11 | * notice, this list of conditions and the following disclaimer. 12 | * * Redistributions in binary form must reproduce the above 13 | * copyright notice, this list of conditions and the following 14 | * disclaimer in the documentation and/or other materials provided 15 | * with the distribution. 16 | * * Neither the name of University of Campinas nor the names of its 17 | * contributors may be used to endorse or promote products derived 18 | * from this software without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 23 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 24 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 25 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 26 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 29 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 31 | * OF THE POSSIBILITY OF SUCH DAMAGE. 32 | */ 33 | 34 | #include "fp448_x64.h" 35 | #include "rfc7748_precomputed.h" 36 | #include "table_ladder_x448.h" 37 | 38 | static inline void cswap_x64(uint64_t bit, uint64_t *const px, 39 | uint64_t *const py) { 40 | int i = 0; 41 | uint64_t mask = (uint64_t)0 - bit; 42 | for (i = 0; i < NUM_WORDS_ELTFP448_X64; i++) { 43 | uint64_t t = mask & (px[i] ^ py[i]); 44 | px[i] = px[i] ^ t; 45 | py[i] = py[i] ^ t; 46 | } 47 | } 48 | 49 | static void x448_shared_x64(argKey shared, argKey session_key, 50 | argKey private_key) { 51 | ALIGN uint64_t buffer[4 * NUM_WORDS_ELTFP448_X64]; 52 | ALIGN uint64_t coordinates[4 * NUM_WORDS_ELTFP448_X64]; 53 | ALIGN uint64_t workspace[6 * NUM_WORDS_ELTFP448_X64]; 54 | uint64_t save; 55 | 56 | int i = 0, j = 0; 57 | uint64_t prev = 0; 58 | uint64_t *const X1 = (uint64_t *)session_key; 59 | uint64_t *const key = (uint64_t *)private_key; 60 | uint64_t *const Px = coordinates + 0; 61 | uint64_t *const Pz = coordinates + 7; 62 | uint64_t *const Qx = coordinates + 14; 63 | uint64_t *const Qz = coordinates + 21; 64 | uint64_t *const X2 = Qx; 65 | uint64_t *const Z2 = Qz; 66 | uint64_t *const X3 = Px; 67 | uint64_t *const Z3 = Pz; 68 | 69 | uint64_t *const A = workspace + 0; 70 | uint64_t *const B = workspace + 7; 71 | uint64_t *const D = workspace + 14; 72 | uint64_t *const C = workspace + 21; 73 | uint64_t *const DA = workspace + 28; 74 | uint64_t *const CB = workspace + 35; 75 | uint64_t *const buffer_1w = buffer; 76 | 77 | /** clamp function */ 78 | save = private_key[X448_KEYSIZE_BYTES - 1] << 16 | private_key[0]; 79 | private_key[0] = private_key[0] & (~(uint8_t)0x3); 80 | private_key[X448_KEYSIZE_BYTES - 1] |= 0x80; 81 | 82 | for (i = 0; i < NUM_WORDS_ELTFP448_X64; i++) { 83 | Px[i] = ((uint64_t *)session_key)[i]; 84 | Pz[i] = 0; 85 | Qx[i] = 0; 86 | Qz[i] = 0; 87 | } 88 | 89 | Pz[0] = 1; 90 | Qx[0] = 1; 91 | 92 | /* main-loop */ 93 | j = 63; 94 | for (i = 6; i >= 0; i--) { 95 | while (j >= 0) { 96 | uint64_t bit = (key[i] >> j) & 0x1; 97 | uint64_t swap = bit ^ prev; 98 | prev = bit; 99 | 100 | add_EltFp448_1w_x64(A, X2, Z2); /* A = (X2+Z2) */ 101 | sub_EltFp448_1w_x64(B, X2, Z2); /* B = (X2-Z2) */ 102 | add_EltFp448_1w_x64(C, X3, Z3); /* C = (X3+Z3) */ 103 | sub_EltFp448_1w_x64(D, X3, Z3); /* D = (X3-Z3) */ 104 | 105 | mul_EltFp448_1w_x64(DA, A, D); /* DA = A*D */ 106 | mul_EltFp448_1w_x64(CB, C, B); /* CB = C*B */ 107 | 108 | cswap_x64(swap, A, C); 109 | cswap_x64(swap, B, D); 110 | 111 | sqr_EltFp448_1w_x64(A); /* A = A^2 */ 112 | sqr_EltFp448_1w_x64(B); /* B = B^2 */ 113 | 114 | add_EltFp448_1w_x64(X3, DA, CB); /* X3 = (DA+CB) */ 115 | sub_EltFp448_1w_x64(Z3, DA, CB); /* Z3 = (DA-CB) */ 116 | sqr_EltFp448_1w_x64(X3); /* X3 = (DA+CB)^2 */ 117 | sqr_EltFp448_1w_x64(Z3); /* Z3 = (DA*CB)^2 */ 118 | 119 | copy_EltFp448_1w_x64(X2, B); /* X2 = B^2 */ 120 | sub_EltFp448_1w_x64(Z2, A, B); /* Z2 = E = AA-BB */ 121 | mul_a24_EltFp448_1w_x64(B, Z2); /* B = a24*E */ 122 | add_EltFp448_1w_x64(B, B, X2); /* B = a24*E+B */ 123 | mul_EltFp448_1w_x64(X2, X2, A); /* X2 = A*B */ 124 | mul_EltFp448_1w_x64(Z2, Z2, B); /* Z2 = E*(a24*E+B) */ 125 | mul_EltFp448_1w_x64(Z3, Z3, X1); /* Z3 = Z3*X1 */ 126 | 127 | j--; 128 | } 129 | j = 63; 130 | } 131 | inv_EltFp448_1w_x64(A, Qz); 132 | mul_EltFp448_1w_x64((uint64_t *)shared, Qx, A); 133 | fred_EltFp448_1w_x64((uint64_t *)shared); 134 | private_key[X448_KEYSIZE_BYTES - 1] = (uint8_t)((save >> 16) & 0xFF); 135 | private_key[0] = (uint8_t)(save & 0xFF); 136 | } 137 | 138 | static void x448_keygen_x64(argKey public_key, argKey private_key) { 139 | ALIGN uint64_t buffer[4 * NUM_WORDS_ELTFP448_X64]; 140 | ALIGN uint64_t coordinates[4 * NUM_WORDS_ELTFP448_X64]; 141 | ALIGN uint64_t workspace[4 * NUM_WORDS_ELTFP448_X64]; 142 | uint64_t save; 143 | 144 | int i = 0, j = 0, k = 0; 145 | uint64_t *const key = (uint64_t *)private_key; 146 | uint64_t *const Ur1 = coordinates + 0; 147 | uint64_t *const Zr1 = coordinates + 7; 148 | uint64_t *const Ur2 = coordinates + 14; 149 | uint64_t *const Zr2 = coordinates + 21; 150 | uint64_t *const A = workspace + 0; 151 | uint64_t *const B = workspace + 7; 152 | uint64_t *const C = workspace + 14; 153 | uint64_t *const D = workspace + 21; 154 | uint64_t *const buffer_1w = buffer; 155 | 156 | uint64_t *P = (uint64_t *)Table_Ladder_24k; 157 | 158 | /** clamp function */ 159 | save = private_key[X448_KEYSIZE_BYTES - 1] << 16 | private_key[0]; 160 | private_key[0] = private_key[0] & (~(uint8_t)0x3); 161 | private_key[X448_KEYSIZE_BYTES - 1] |= 0x80; 162 | 163 | for (i = 0; i < NUM_WORDS_ELTFP448_X64; i++) { 164 | Ur1[i] = 0; 165 | Zr1[i] = 0; 166 | Zr2[i] = 0; 167 | } 168 | 169 | /* G-S */ 170 | Ur2[0] = 0xacb1197dc99d2720; 171 | Ur2[1] = 0x23ac33ff1c69baf8; 172 | Ur2[2] = 0xf1bd65643ace1b51; 173 | Ur2[3] = 0x2954459d84c1f823; 174 | Ur2[4] = 0xdacdd1031c81b967; 175 | Ur2[5] = 0x3acf03881affeb7b; 176 | Ur2[6] = 0xf0fab72501324442; 177 | 178 | /* Ur1 = -1 mod p */ 179 | Ur1[0] = 0xfffffffffffffffe; 180 | Ur1[1] = 0xffffffffffffffff; 181 | Ur1[2] = 0xffffffffffffffff; 182 | Ur1[3] = 0xfffffffeffffffff; 183 | Ur1[4] = 0xffffffffffffffff; 184 | Ur1[5] = 0xffffffffffffffff; 185 | Ur1[6] = 0xffffffffffffffff; 186 | 187 | Zr1[0] = 1; 188 | Zr2[0] = 1; 189 | 190 | /* main-loop */ 191 | const int q = 2; 192 | uint64_t swap = 1; 193 | 194 | j = q; 195 | for (i = 0; i < NUM_WORDS_ELTFP448_X64; i++) { 196 | while (j < 64) { 197 | k = (64 * i + j - q); 198 | uint64_t bit = (key[i] >> j) & 0x1; 199 | swap = swap ^ bit; 200 | cswap_x64(swap, Ur1, Ur2); 201 | cswap_x64(swap, Zr1, Zr2); 202 | swap = bit; 203 | 204 | /** Addition */ 205 | add_EltFp448_1w_x64(A, Ur1, Zr1); /* A = Ur1+Zr1 */ 206 | sub_EltFp448_1w_x64(B, Ur1, Zr1); /* B = Ur1-Zr1 */ 207 | mul_EltFp448_1w_x64(C, &P[7 * k], B); /* C = M0-B */ 208 | sub_EltFp448_1w_x64(B, A, C); /* B = (Ur1+Zr1) - M*(Ur1-Zr1) */ 209 | add_EltFp448_1w_x64(A, A, C); /* A = (Ur1+Zr1) + M*(Ur1-Zr1) */ 210 | sqr_EltFp448_1w_x64(A); /* A = A^2 */ 211 | sqr_EltFp448_1w_x64(B); /* B = B^2 */ 212 | mul_EltFp448_1w_x64(Ur1, Zr2, A); /* Ur1 = Zr2*A */ 213 | mul_EltFp448_1w_x64(Zr1, Ur2, B); /* Zr1 = Ur2*B */ 214 | 215 | j++; 216 | } 217 | j = 0; 218 | } 219 | 220 | /** Doubling */ 221 | for (i = 0; i < q; i++) { 222 | add_EltFp448_1w_x64(A, Ur1, Zr1); /* A = Ur1+Zr1 */ 223 | sub_EltFp448_1w_x64(B, Ur1, Zr1); /* B = Ur1-Zr1 */ 224 | sqr_EltFp448_1w_x64(A); /* A = A**2 B = B**2 */ 225 | sqr_EltFp448_1w_x64(B); /* A = A**2 B = B**2 */ 226 | copy_EltFp448_1w_x64(C, B); /* C = B */ 227 | sub_EltFp448_1w_x64(B, A, B); /* B = A-B */ 228 | mul_a24_EltFp448_1w_x64(D, B); /* D = my_a24*B */ 229 | add_EltFp448_1w_x64(D, D, C); /* D = D+C */ 230 | mul_EltFp448_1w_x64(Ur1, A, C); /* Ur1 = A*B Zr1 = Zr1*A */ 231 | mul_EltFp448_1w_x64(Zr1, B, D); /* Ur1 = A*B Zr1 = Zr1*A */ 232 | } 233 | 234 | /* Convert to affine coordinates */ 235 | inv_EltFp448_1w_x64(A, Zr1); 236 | mul_EltFp448_1w_x64((uint64_t *)public_key, Ur1, A); 237 | fred_EltFp448_1w_x64((uint64_t *)public_key); 238 | private_key[X448_KEYSIZE_BYTES - 1] = (uint8_t)((save >> 16) & 0xFF); 239 | private_key[0] = (uint8_t)(save & 0xFF); 240 | } 241 | 242 | const KeyGen X448_KeyGen = x448_keygen_x64; 243 | const Shared X448_Shared = x448_shared_x64; 244 | -------------------------------------------------------------------------------- /tests/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.0.2) 2 | enable_language(CXX) 3 | set(CMAKE_CXX_STANDARD 11) 4 | 5 | include(ExternalProject) 6 | include("GNUInstallDirs") 7 | set(GTEST_VERSION "release-1.10.0") 8 | ExternalProject_Add(googletest-download 9 | URL "https://api.github.com/repos/google/googletest/tarball/${GTEST_VERSION}" 10 | CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${CMAKE_CURRENT_BINARY_DIR} 11 | -DCMAKE_POSITION_INDEPENDENT_CODE=ON 12 | -DCMAKE_CXX_COMPILER:FILEPATH=${CMAKE_CXX_COMPILER} 13 | TEST_COMMAND "" 14 | UPDATE_COMMAND "" 15 | ) 16 | include_directories(${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_INSTALL_INCLUDEDIR}) 17 | link_directories(${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}) 18 | 19 | find_package(GMP QUIET) 20 | include_directories(../include) 21 | include_directories(../third_party) 22 | set(c_files 23 | runTests.cpp 24 | test_fp25519_x64.cpp 25 | test_fp448_x64.cpp 26 | test_x25519.cpp 27 | test_x448.cpp 28 | ) 29 | 30 | add_executable(tests ${c_files} ../third_party/random.c) 31 | add_dependencies(tests ${TARGET} googletest-download) 32 | target_link_libraries(tests ${TARGET} gtest pthread gmp) 33 | -------------------------------------------------------------------------------- /tests/runTests.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2017, Armando Faz . All rights reserved. 3 | * Institute of Computing. 4 | * University of Campinas, Brazil. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions 8 | * are met: 9 | * 10 | * * Redistributions of source code must retain the above copyright 11 | * notice, this list of conditions and the following disclaimer. 12 | * * Redistributions in binary form must reproduce the above 13 | * copyright notice, this list of conditions and the following 14 | * disclaimer in the documentation and/or other materials provided 15 | * with the distribution. 16 | * * Neither the name of University of Campinas nor the names of its 17 | * contributors may be used to endorse or promote products derived 18 | * from this software without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 23 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 24 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 25 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 26 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 29 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 31 | * OF THE POSSIBILITY OF SUCH DAMAGE. 32 | */ 33 | 34 | #include 35 | 36 | int main(int argc, char **argv) { 37 | testing::InitGoogleTest(&argc, argv); 38 | return RUN_ALL_TESTS(); 39 | } 40 | -------------------------------------------------------------------------------- /tests/test_fp25519_x64.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2017, Armando Faz . All rights reserved. 3 | * Institute of Computing. 4 | * University of Campinas, Brazil. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions 8 | * are met: 9 | * 10 | * * Redistributions of source code must retain the above copyright 11 | * notice, this list of conditions and the following disclaimer. 12 | * * Redistributions in binary form must reproduce the above 13 | * copyright notice, this list of conditions and the following 14 | * disclaimer in the documentation and/or other materials provided 15 | * with the distribution. 16 | * * Neither the name of University of Campinas nor the names of its 17 | * contributors may be used to endorse or promote products derived 18 | * from this software without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 23 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 24 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 25 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 26 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 29 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 31 | * OF THE POSSIBILITY OF SUCH DAMAGE. 32 | */ 33 | 34 | #include 35 | #include 36 | #include 37 | #include "random.h" 38 | 39 | #define TEST_TIMES 50000 40 | 41 | static void random_EltFp25519_1w_x64(uint64_t *A) { 42 | random_bytes(reinterpret_cast(A), SIZE_BYTES_FP25519); 43 | } 44 | 45 | static std::ostream &operator<<(std::ostream &os, 46 | const EltFp25519_1w_x64 &number) { 47 | os << "0x"; 48 | for (int i = NUM_WORDS_ELTFP25519_X64 - 1; i >= 0; i--) { 49 | os << std::setbase(16) << std::setfill('0') << std::setw(16) << number[i]; 50 | } 51 | return os << std::endl; 52 | } 53 | 54 | /* Verifies that (a^2-b^2) == (a+b)(a-b) */ 55 | TEST(FP25519, MUL_VS_SQR) { 56 | int64_t i; 57 | int64_t cnt = 0; 58 | EltFp25519_1w_x64 a, b, c, e, f; 59 | EltFp25519_1w_Buffer_x64 buffer_1w; 60 | 61 | for (i = 0; i < TEST_TIMES; i++) { 62 | random_EltFp25519_1w_x64(a); 63 | random_EltFp25519_1w_x64(b); 64 | 65 | add_EltFp25519_1w_x64(e, a, b); 66 | sub_EltFp25519_1w_x64(f, a, b); 67 | mul_EltFp25519_1w_x64(e, e, f); 68 | 69 | sqr_EltFp25519_1w_x64(a); 70 | sqr_EltFp25519_1w_x64(b); 71 | sub_EltFp25519_1w_x64(c, a, b); 72 | 73 | fred_EltFp25519_1w_x64(c); 74 | fred_EltFp25519_1w_x64(e); 75 | 76 | ASSERT_EQ(memcmp(c, e, SIZE_BYTES_FP25519), 0) << "got: " << c 77 | << "want: " << e; 78 | cnt++; 79 | } 80 | EXPECT_EQ(cnt, TEST_TIMES) << "passed: " << cnt << "/" << TEST_TIMES 81 | << std::endl; 82 | } 83 | 84 | /* Verifies that (a*b*a^1) == (b) */ 85 | TEST(FP25519, MUL_VS_INV) { 86 | int64_t i; 87 | int64_t cnt = 0; 88 | EltFp25519_1w_x64 a, b, d; 89 | EltFp25519_1w_Buffer_x64 buffer_1w; 90 | 91 | for (i = 0; i < TEST_TIMES; i++) { 92 | random_EltFp25519_1w_x64(a); 93 | random_EltFp25519_1w_x64(b); 94 | 95 | inv_EltFp25519_1w_x64(d, a); 96 | mul_EltFp25519_1w_x64(a, a, b); 97 | mul_EltFp25519_1w_x64(a, a, d); 98 | fred_EltFp25519_1w_x64(a); 99 | fred_EltFp25519_1w_x64(b); 100 | 101 | ASSERT_EQ(memcmp(a, b, SIZE_BYTES_FP25519), 0) << "got: " << a 102 | << "want: " << b; 103 | cnt++; 104 | } 105 | EXPECT_EQ(cnt, TEST_TIMES) << "passed: " << cnt << "/" << TEST_TIMES 106 | << std::endl; 107 | } 108 | 109 | /* Verifies that 0 <= c=a+b < 2^256 and that c be congruent to a+b mod p */ 110 | TEST(FP25519, ADDITION) { 111 | int count = 0; 112 | EltFp25519_1w_x64 a, b, get_c, want_c; 113 | 114 | mpz_t gmp_a, gmp_b, gmp_c, two_prime, two_to_256; 115 | mpz_init(gmp_a); 116 | mpz_init(gmp_b); 117 | mpz_init(gmp_c); 118 | 119 | // two_prime = 2^256-38 120 | mpz_init_set_ui(two_prime, 1); 121 | mpz_mul_2exp(two_prime, two_prime, 256); 122 | mpz_sub_ui(two_prime, two_prime, 38); 123 | 124 | // two_to_256 = 2^256 125 | mpz_init_set_ui(two_to_256, 1); 126 | mpz_mul_2exp(two_to_256, two_to_256, 256); 127 | 128 | for (int i = 0; i < TEST_TIMES; i++) { 129 | setzero_EltFp25519_1w_x64(get_c); 130 | setzero_EltFp25519_1w_x64(want_c); 131 | 132 | random_EltFp25519_1w_x64(a); 133 | random_EltFp25519_1w_x64(b); 134 | 135 | add_EltFp25519_1w_x64(get_c, a, b); 136 | 137 | mpz_import(gmp_a, NUM_WORDS_ELTFP25519_X64, -1, sizeof(a[0]), 0, 0, a); 138 | mpz_import(gmp_b, NUM_WORDS_ELTFP25519_X64, -1, sizeof(b[0]), 0, 0, b); 139 | 140 | mpz_add(gmp_c, gmp_a, gmp_b); 141 | while (mpz_cmp(gmp_c, two_to_256) >= 0) { 142 | mpz_sub(gmp_c, gmp_c, two_prime); 143 | } 144 | mpz_export(want_c, NULL, -1, SIZE_BYTES_FP25519, 0, 0, gmp_c); 145 | 146 | ASSERT_EQ(memcmp(get_c, want_c, SIZE_BYTES_FP25519), 0) 147 | << "a: " << a << "b: " << b << "got: " << get_c << "want: " << want_c; 148 | count++; 149 | } 150 | EXPECT_EQ(count, TEST_TIMES) << "passed: " << count << "/" << TEST_TIMES 151 | << std::endl; 152 | 153 | mpz_clear(gmp_a); 154 | mpz_clear(gmp_b); 155 | mpz_clear(gmp_c); 156 | mpz_clear(two_prime); 157 | mpz_clear(two_to_256); 158 | } 159 | 160 | /* Verifies that 0 <= c=a-b < 2^256 and that c be congruent to a-b mod p */ 161 | TEST(FP25519, SUBTRACTION) { 162 | int count = 0; 163 | EltFp25519_1w_x64 a, b, get_c, want_c; 164 | 165 | mpz_t gmp_a, gmp_b, gmp_c, two_prime, zero; 166 | mpz_init(gmp_a); 167 | mpz_init(gmp_b); 168 | mpz_init(gmp_c); 169 | 170 | // two_prime = 2^256-38 171 | mpz_init_set_ui(two_prime, 1); 172 | mpz_mul_2exp(two_prime, two_prime, 256); 173 | mpz_sub_ui(two_prime, two_prime, 38); 174 | 175 | // zero = 0 176 | mpz_init_set_ui(zero, 0); 177 | 178 | for (int i = 0; i < TEST_TIMES; i++) { 179 | setzero_EltFp25519_1w_x64(get_c); 180 | setzero_EltFp25519_1w_x64(want_c); 181 | 182 | random_EltFp25519_1w_x64(a); 183 | random_EltFp25519_1w_x64(b); 184 | 185 | sub_EltFp25519_1w_x64(get_c, a, b); 186 | 187 | mpz_import(gmp_a, NUM_WORDS_ELTFP25519_X64, -1, sizeof(a[0]), 0, 0, a); 188 | mpz_import(gmp_b, NUM_WORDS_ELTFP25519_X64, -1, sizeof(b[0]), 0, 0, b); 189 | 190 | mpz_sub(gmp_c, gmp_a, gmp_b); 191 | while (mpz_cmp(gmp_c, zero) < 0) { 192 | mpz_add(gmp_c, gmp_c, two_prime); 193 | } 194 | mpz_export(want_c, NULL, -1, SIZE_BYTES_FP25519, 0, 0, gmp_c); 195 | 196 | ASSERT_EQ(memcmp(get_c, want_c, SIZE_BYTES_FP25519), 0) 197 | << "a: " << a << "b: " << b << "got: " << get_c << "want: " << want_c; 198 | count++; 199 | } 200 | EXPECT_EQ(count, TEST_TIMES) << "passed: " << count << "/" << TEST_TIMES 201 | << std::endl; 202 | 203 | mpz_clear(gmp_a); 204 | mpz_clear(gmp_b); 205 | mpz_clear(gmp_c); 206 | mpz_clear(two_prime); 207 | mpz_clear(zero); 208 | } 209 | 210 | /* Verifies that 0 <= c=a*b < 2^512 */ 211 | TEST(FP25519, MULTIPLICATION) { 212 | int count = 0; 213 | EltFp25519_1w_x64 a, b; 214 | EltFp25519_1w_Buffer_x64 get_c, want_c; 215 | 216 | mpz_t gmp_a, gmp_b, gmp_c; 217 | mpz_init(gmp_a); 218 | mpz_init(gmp_b); 219 | mpz_init(gmp_c); 220 | 221 | for (int i = 0; i < TEST_TIMES; i++) { 222 | setzero_EltFp25519_1w_x64(get_c); 223 | setzero_EltFp25519_1w_x64(get_c + NUM_WORDS_ELTFP25519_X64); 224 | setzero_EltFp25519_1w_x64(want_c); 225 | setzero_EltFp25519_1w_x64(want_c + NUM_WORDS_ELTFP25519_X64); 226 | 227 | random_EltFp25519_1w_x64(a); 228 | random_EltFp25519_1w_x64(b); 229 | 230 | mul_256x256_integer_x64(get_c, a, b); 231 | 232 | mpz_import(gmp_a, NUM_WORDS_ELTFP25519_X64, -1, sizeof(a[0]), 0, 0, a); 233 | mpz_import(gmp_b, NUM_WORDS_ELTFP25519_X64, -1, sizeof(b[0]), 0, 0, b); 234 | 235 | mpz_mul(gmp_c, gmp_a, gmp_b); 236 | mpz_export(want_c, NULL, -1, 2 * SIZE_BYTES_FP25519, 0, 0, gmp_c); 237 | 238 | ASSERT_EQ(memcmp(get_c, want_c, 2 * SIZE_BYTES_FP25519), 0) 239 | << "a: " << a << "b: " << b << "got: " << get_c << "want: " << want_c; 240 | count++; 241 | } 242 | EXPECT_EQ(count, TEST_TIMES) << "passed: " << count << "/" << TEST_TIMES 243 | << std::endl; 244 | 245 | mpz_clear(gmp_a); 246 | mpz_clear(gmp_b); 247 | mpz_clear(gmp_c); 248 | } 249 | 250 | /* Verifies that 0 <= c=a*a < 2^512 */ 251 | TEST(FP25519, SQUARING) { 252 | int count = 0; 253 | EltFp25519_1w_x64 a; 254 | EltFp25519_1w_Buffer_x64 get_c, want_c; 255 | 256 | mpz_t gmp_a, gmp_c; 257 | mpz_init(gmp_a); 258 | mpz_init(gmp_c); 259 | 260 | for (int i = 0; i < TEST_TIMES; i++) { 261 | setzero_EltFp25519_1w_x64(get_c); 262 | setzero_EltFp25519_1w_x64(get_c + NUM_WORDS_ELTFP25519_X64); 263 | setzero_EltFp25519_1w_x64(want_c); 264 | setzero_EltFp25519_1w_x64(want_c + NUM_WORDS_ELTFP25519_X64); 265 | 266 | random_EltFp25519_1w_x64(a); 267 | 268 | sqr_256x256_integer_x64(get_c, a); 269 | 270 | mpz_import(gmp_a, NUM_WORDS_ELTFP25519_X64, -1, sizeof(a[0]), 0, 0, a); 271 | 272 | mpz_mul(gmp_c, gmp_a, gmp_a); 273 | mpz_export(want_c, NULL, -1, 2 * SIZE_BYTES_FP25519, 0, 0, gmp_c); 274 | 275 | ASSERT_EQ(memcmp(get_c, want_c, 2 * SIZE_BYTES_FP25519), 0) 276 | << "a: " << a << "got: " << get_c << "want: " << want_c; 277 | count++; 278 | } 279 | EXPECT_EQ(count, TEST_TIMES) << "passed: " << count << "/" << TEST_TIMES 280 | << std::endl; 281 | 282 | mpz_clear(gmp_a); 283 | mpz_clear(gmp_c); 284 | } 285 | 286 | /* Verifies that 0 <= c=a^-1 < 2^256 and that c be congruent to a^-1 mod p */ 287 | TEST(FP25519, INVERSION) { 288 | int count = 0; 289 | EltFp25519_1w_x64 a, get_c, want_c; 290 | 291 | mpz_t gmp_a, gmp_c, two_prime, prime_minus_two; 292 | mpz_init(gmp_a); 293 | mpz_init(gmp_c); 294 | 295 | // two_prime = 2^256-38 296 | mpz_init_set_ui(two_prime, 1); 297 | mpz_mul_2exp(two_prime, two_prime, 256); 298 | mpz_sub_ui(two_prime, two_prime, 38); 299 | 300 | // expo = p-2 = 2^255-19-2 = 2^255-21 301 | mpz_init_set_ui(prime_minus_two, 1); 302 | mpz_mul_2exp(prime_minus_two, prime_minus_two, 255); 303 | mpz_sub_ui(prime_minus_two, prime_minus_two, 21); 304 | 305 | for (int i = 0; i < TEST_TIMES; i++) { 306 | setzero_EltFp25519_1w_x64(get_c); 307 | setzero_EltFp25519_1w_x64(want_c); 308 | 309 | random_EltFp25519_1w_x64(a); 310 | 311 | inv_EltFp25519_1w_x64(get_c, a); 312 | 313 | mpz_import(gmp_a, NUM_WORDS_ELTFP25519_X64, -1, sizeof(a[0]), 0, 0, a); 314 | mpz_powm(gmp_c, gmp_a, prime_minus_two, two_prime); 315 | mpz_export(want_c, NULL, -1, SIZE_BYTES_FP25519, 0, 0, gmp_c); 316 | 317 | ASSERT_EQ(memcmp(get_c, want_c, SIZE_BYTES_FP25519), 0) 318 | << "a: " << a << "got: " << get_c << "want: " << want_c; 319 | count++; 320 | } 321 | EXPECT_EQ(count, TEST_TIMES) << "passed: " << count << "/" << TEST_TIMES 322 | << std::endl; 323 | 324 | mpz_clear(gmp_a); 325 | mpz_clear(gmp_c); 326 | mpz_clear(two_prime); 327 | mpz_clear(prime_minus_two); 328 | } 329 | 330 | /* Verifies that 0<= c=a*b < 2^256 and that c be congruent to a*b mod p */ 331 | TEST(FP25519, REDUCTION) { 332 | int count = 0; 333 | EltFp25519_1w_x64 a, b, get_c, want_c; 334 | EltFp25519_1w_Buffer_x64 buffer_c; 335 | 336 | mpz_t gmp_a, gmp_b, gmp_c, gmp_low, gmp_high, two_to_256; 337 | mpz_init(gmp_a); 338 | mpz_init(gmp_b); 339 | mpz_init(gmp_c); 340 | mpz_init(gmp_low); 341 | mpz_init(gmp_high); 342 | 343 | // two_to_256 = 2^256 344 | mpz_init_set_ui(two_to_256, 1); 345 | mpz_mul_2exp(two_to_256, two_to_256, 256); 346 | 347 | for (int i = 0; i < TEST_TIMES; i++) { 348 | setzero_EltFp25519_1w_x64(get_c); 349 | setzero_EltFp25519_1w_x64(want_c); 350 | 351 | random_EltFp25519_1w_x64(a); 352 | random_EltFp25519_1w_x64(b); 353 | 354 | mul_256x256_integer_x64(buffer_c, a, b); 355 | red_EltFp25519_1w_x64(get_c, buffer_c); 356 | 357 | mpz_import(gmp_a, NUM_WORDS_ELTFP25519_X64, -1, sizeof(a[0]), 0, 0, a); 358 | mpz_import(gmp_b, NUM_WORDS_ELTFP25519_X64, -1, sizeof(b[0]), 0, 0, b); 359 | mpz_mul(gmp_c, gmp_a, gmp_b); 360 | 361 | while (mpz_cmp(gmp_c, two_to_256) >= 0) { 362 | mpz_mod_2exp(gmp_low, gmp_c, 256); 363 | mpz_div_2exp(gmp_high, gmp_c, 256); 364 | mpz_mul_ui(gmp_high, gmp_high, 38); 365 | mpz_add(gmp_c, gmp_low, gmp_high); 366 | } 367 | mpz_export(want_c, NULL, -1, SIZE_BYTES_FP25519, 0, 0, gmp_c); 368 | 369 | ASSERT_EQ(memcmp(get_c, want_c, SIZE_BYTES_FP25519), 0) 370 | << "a: " << a << "b: " << b << "got: " << get_c << "want: " << want_c; 371 | count++; 372 | } 373 | EXPECT_EQ(count, TEST_TIMES) << "passed: " << count << "/" << TEST_TIMES 374 | << std::endl; 375 | 376 | mpz_clear(gmp_a); 377 | mpz_clear(gmp_b); 378 | mpz_clear(gmp_c); 379 | mpz_clear(gmp_low); 380 | mpz_clear(gmp_high); 381 | mpz_clear(two_to_256); 382 | } 383 | 384 | /* Verifies that 0<= c=a24*a < 2^256 and that c be congruent to a24*a mod p */ 385 | TEST(FP25519, MULA24) { 386 | int count = 0; 387 | const uint64_t a24 = 121666; 388 | EltFp25519_1w_x64 a, get_c, want_c; 389 | 390 | mpz_t gmp_a, gmp_c, gmp_low, gmp_high, two_to_256; 391 | mpz_init(gmp_a); 392 | mpz_init(gmp_c); 393 | mpz_init(gmp_low); 394 | mpz_init(gmp_high); 395 | 396 | // two_to_256 = 2^256 397 | mpz_init_set_ui(two_to_256, 1); 398 | mpz_mul_2exp(two_to_256, two_to_256, 256); 399 | 400 | for (int i = 0; i < TEST_TIMES; i++) { 401 | setzero_EltFp25519_1w_x64(get_c); 402 | setzero_EltFp25519_1w_x64(want_c); 403 | 404 | random_EltFp25519_1w_x64(a); 405 | mul_a24_EltFp25519_1w_x64(get_c, a); 406 | 407 | mpz_import(gmp_a, NUM_WORDS_ELTFP25519_X64, -1, sizeof(a[0]), 0, 0, a); 408 | mpz_mul_ui(gmp_c, gmp_a, a24); 409 | 410 | while (mpz_cmp(gmp_c, two_to_256) >= 0) { 411 | mpz_mod_2exp(gmp_low, gmp_c, 256); 412 | mpz_div_2exp(gmp_high, gmp_c, 256); 413 | mpz_mul_ui(gmp_high, gmp_high, 38); 414 | mpz_add(gmp_c, gmp_low, gmp_high); 415 | } 416 | mpz_export(want_c, NULL, -1, SIZE_BYTES_FP25519, 0, 0, gmp_c); 417 | 418 | ASSERT_EQ(memcmp(get_c, want_c, SIZE_BYTES_FP25519), 0) 419 | << "a: " << a << "got: " << get_c << "want: " << want_c; 420 | count++; 421 | } 422 | EXPECT_EQ(count, TEST_TIMES) << "passed: " << count << "/" << TEST_TIMES 423 | << std::endl; 424 | 425 | mpz_clear(gmp_a); 426 | mpz_clear(gmp_c); 427 | mpz_clear(gmp_low); 428 | mpz_clear(gmp_high); 429 | mpz_clear(two_to_256); 430 | } 431 | 432 | /* Verifies that 0 <= c=a mod p < 2^255-19 for a number 0 <= a < 2^256 */ 433 | TEST(FP25519, FREDUCTION) { 434 | int count = 0; 435 | EltFp25519_1w_x64 a, get_c, want_c; 436 | 437 | mpz_t gmp_a, gmp_c, prime; 438 | mpz_init(gmp_a); 439 | mpz_init(gmp_c); 440 | 441 | // prime = p-2 = 2^255-19 442 | mpz_init_set_ui(prime, 1); 443 | mpz_mul_2exp(prime, prime, 255); 444 | mpz_sub_ui(prime, prime, 19); 445 | 446 | for (int i = 0; i < TEST_TIMES; i++) { 447 | setzero_EltFp25519_1w_x64(get_c); 448 | setzero_EltFp25519_1w_x64(want_c); 449 | 450 | random_EltFp25519_1w_x64(a); 451 | copy_EltFp25519_1w_x64(get_c, a); 452 | mpz_import(gmp_a, NUM_WORDS_ELTFP25519_X64, -1, sizeof(a[0]), 0, 0, a); 453 | 454 | fred_EltFp25519_1w_x64(get_c); 455 | mpz_mod(gmp_c, gmp_a, prime); 456 | 457 | mpz_export(want_c, NULL, -1, SIZE_BYTES_FP25519, 0, 0, gmp_c); 458 | 459 | ASSERT_EQ(memcmp(get_c, want_c, SIZE_BYTES_FP25519), 0) 460 | << "a: " << a << "got: " << get_c << "want: " << want_c; 461 | count++; 462 | } 463 | EXPECT_EQ(count, TEST_TIMES) << "passed: " << count << "/" << TEST_TIMES 464 | << std::endl; 465 | 466 | mpz_clear(gmp_a); 467 | mpz_clear(gmp_c); 468 | mpz_clear(prime); 469 | } 470 | -------------------------------------------------------------------------------- /tests/test_fp448_x64.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2017, Armando Faz . All rights reserved. 3 | * Institute of Computing. 4 | * University of Campinas, Brazil. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions 8 | * are met: 9 | * 10 | * * Redistributions of source code must retain the above copyright 11 | * notice, this list of conditions and the following disclaimer. 12 | * * Redistributions in binary form must reproduce the above 13 | * copyright notice, this list of conditions and the following 14 | * disclaimer in the documentation and/or other materials provided 15 | * with the distribution. 16 | * * Neither the name of University of Campinas nor the names of its 17 | * contributors may be used to endorse or promote products derived 18 | * from this software without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 23 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 24 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 25 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 26 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 29 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 31 | * OF THE POSSIBILITY OF SUCH DAMAGE. 32 | */ 33 | 34 | #include 35 | #include 36 | #include "random.h" 37 | 38 | #define TEST_TIMES 50000 39 | 40 | static void random_EltFp448_1w_x64(uint64_t *A) { 41 | random_bytes(reinterpret_cast(A), SIZE_BYTES_FP448); 42 | } 43 | 44 | // Verifies that (a^2-b^2) == (a+b)(a-b) 45 | TEST(FP448, MUL_VS_SQR) { 46 | int64_t i; 47 | int64_t cnt = 0; 48 | EltFp448_1w_x64 a, b, c, e, f; 49 | EltFp448_1w_Buffer_x64 buffer_1w; 50 | 51 | for (i = 0; i < TEST_TIMES; i++) { 52 | random_EltFp448_1w_x64(a); 53 | random_EltFp448_1w_x64(b); 54 | 55 | add_EltFp448_1w_x64(e, a, b); 56 | sub_EltFp448_1w_x64(f, a, b); 57 | mul_EltFp448_1w_x64(e, e, f); 58 | 59 | sqr_EltFp448_1w_x64(a); 60 | sqr_EltFp448_1w_x64(b); 61 | sub_EltFp448_1w_x64(c, a, b); 62 | 63 | fred_EltFp448_1w_x64(c); 64 | fred_EltFp448_1w_x64(e); 65 | 66 | EXPECT_EQ(memcmp(c, e, SIZE_BYTES_FP448), 0) << "got: " << c 67 | << "want: " << e; 68 | cnt++; 69 | } 70 | EXPECT_EQ(cnt, TEST_TIMES) << "passed: " << cnt << "/" << TEST_TIMES 71 | << std::endl; 72 | } 73 | 74 | // Verifies that (a*b*a^1) == (b) 75 | TEST(FP448, MUL_VS_INV) { 76 | int64_t i; 77 | int64_t cnt = 0; 78 | EltFp448_1w_x64 a, b, d; 79 | EltFp448_1w_Buffer_x64 buffer_1w; 80 | 81 | for (i = 0; i < TEST_TIMES; i++) { 82 | random_EltFp448_1w_x64(a); 83 | random_EltFp448_1w_x64(b); 84 | 85 | inv_EltFp448_1w_x64(d, a); 86 | mul_EltFp448_1w_x64(a, a, b); 87 | mul_EltFp448_1w_x64(a, a, d); 88 | fred_EltFp448_1w_x64(a); 89 | fred_EltFp448_1w_x64(b); 90 | 91 | EXPECT_EQ(memcmp(a, b, SIZE_BYTES_FP448), 0) << "got: " << a 92 | << "want: " << b; 93 | cnt++; 94 | } 95 | EXPECT_EQ(cnt, TEST_TIMES) << "passed: " << cnt << "/" << TEST_TIMES 96 | << std::endl; 97 | } 98 | -------------------------------------------------------------------------------- /tests/test_x25519.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2017, Armando Faz . All rights reserved. 3 | * Institute of Computing. 4 | * University of Campinas, Brazil. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions 8 | * are met: 9 | * 10 | * * Redistributions of source code must retain the above copyright 11 | * notice, this list of conditions and the following disclaimer. 12 | * * Redistributions in binary form must reproduce the above 13 | * copyright notice, this list of conditions and the following 14 | * disclaimer in the documentation and/or other materials provided 15 | * with the distribution. 16 | * * Neither the name of University of Campinas nor the names of its 17 | * contributors may be used to endorse or promote products derived 18 | * from this software without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 23 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 24 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 25 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 26 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 29 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 31 | * OF THE POSSIBILITY OF SUCH DAMAGE. 32 | */ 33 | 34 | #include "random.h" 35 | #include "gtest/gtest.h" 36 | #include 37 | #include 38 | #include 39 | #include 40 | 41 | static std::ostream &operator<<(std::ostream &os, const X25519_KEY &key) { 42 | int i = 0; 43 | for (i = 0; i < X25519_KEYSIZE_BYTES; i++) { 44 | os << std::setbase(16) << std::setfill('0') << std::setw(2) 45 | << static_cast(key[i]); 46 | } 47 | return os << std::endl; 48 | } 49 | 50 | static void random_X25519_key(argKey key) { 51 | random_bytes(key, X25519_KEYSIZE_BYTES); 52 | } 53 | 54 | static void times(int n, uint8_t *k) { 55 | X25519_KEY r, u; 56 | int i; 57 | for (i = 0; i < X25519_KEYSIZE_BYTES; i++) { 58 | u[i] = 0; 59 | k[i] = 0; 60 | r[i] = 0; 61 | } 62 | u[0] = 9; 63 | k[0] = 9; 64 | 65 | for (i = 0; i < n; i++) { 66 | X25519_Shared(r, u, k); 67 | memcpy(u, k, X25519_KEYSIZE_BYTES); 68 | memcpy(k, r, X25519_KEYSIZE_BYTES); 69 | } 70 | } 71 | 72 | TEST(X25519, NACL_CRYPTO) { 73 | X25519_KEY alicesk = {0x77, 0x07, 0x6d, 0x0a, 0x73, 0x18, 0xa5, 0x7d, 74 | 0x3c, 0x16, 0xc1, 0x72, 0x51, 0xb2, 0x66, 0x45, 75 | 0xdf, 0x4c, 0x2f, 0x87, 0xeb, 0xc0, 0x99, 0x2a, 76 | 0xb1, 0x77, 0xfb, 0xa5, 0x1d, 0xb9, 0x2c, 0x2a}; 77 | X25519_KEY alicepk; 78 | 79 | X25519_KeyGen(alicepk, alicesk); 80 | 81 | X25519_KEY bobsk = {0x5d, 0xab, 0x08, 0x7e, 0x62, 0x4a, 0x8a, 0x4b, 82 | 0x79, 0xe1, 0x7f, 0x8b, 0x83, 0x80, 0x0e, 0xe6, 83 | 0x6f, 0x3b, 0xb1, 0x29, 0x26, 0x18, 0xb6, 0xfd, 84 | 0x1c, 0x2f, 0x8b, 0x27, 0xff, 0x88, 0xe0, 0xeb}; 85 | X25519_KEY bobpk; 86 | 87 | X25519_KeyGen(bobpk, bobsk); 88 | X25519_KEY alice_shared_secret; 89 | X25519_KEY bob_shared_secret; 90 | X25519_Shared(alice_shared_secret, bobpk, alicesk); 91 | X25519_Shared(bob_shared_secret, alicepk, bobsk); 92 | 93 | X25519_KEY shared = {0x4a, 0x5d, 0x9d, 0x5b, 0xa4, 0xce, 0x2d, 0xe1, 94 | 0x72, 0x8e, 0x3b, 0xf4, 0x80, 0x35, 0x0f, 0x25, 95 | 0xe0, 0x7e, 0x21, 0xc9, 0x47, 0xd1, 0x9e, 0x33, 96 | 0x76, 0xf0, 0x9b, 0x3c, 0x1e, 0x16, 0x17, 0x42}; 97 | EXPECT_EQ(memcmp(alice_shared_secret, shared, X25519_KEYSIZE_BYTES), 0) 98 | << "got: " << alice_shared_secret << "want: " << shared; 99 | EXPECT_EQ(memcmp(bob_shared_secret, shared, X25519_KEYSIZE_BYTES), 0) 100 | << "got: " << alice_shared_secret << "want: " << shared; 101 | } 102 | 103 | TEST(X25519, IETF_CFRG0) { 104 | X25519_KEY shared; 105 | 106 | X25519_KEY key0 = {0xa5, 0x46, 0xe3, 0x6b, 0xf0, 0x52, 0x7c, 0x9d, 107 | 0x3b, 0x16, 0x15, 0x4b, 0x82, 0x46, 0x5e, 0xdd, 108 | 0x62, 0x14, 0x4c, 0x0a, 0xc1, 0xfc, 0x5a, 0x18, 109 | 0x50, 0x6a, 0x22, 0x44, 0xba, 0x44, 0x9a, 0xc4}; 110 | 111 | X25519_KEY input_coord0 = {0xe6, 0xdb, 0x68, 0x67, 0x58, 0x30, 0x30, 0xdb, 112 | 0x35, 0x94, 0xc1, 0xa4, 0x24, 0xb1, 0x5f, 0x7c, 113 | 0x72, 0x66, 0x24, 0xec, 0x26, 0xb3, 0x35, 0x3b, 114 | 0x10, 0xa9, 0x03, 0xa6, 0xd0, 0xab, 0x1c, 0x4c}; 115 | 116 | X25519_KEY output_coord0 = {0xc3, 0xda, 0x55, 0x37, 0x9d, 0xe9, 0xc6, 0x90, 117 | 0x8e, 0x94, 0xea, 0x4d, 0xf2, 0x8d, 0x08, 0x4f, 118 | 0x32, 0xec, 0xcf, 0x03, 0x49, 0x1c, 0x71, 0xf7, 119 | 0x54, 0xb4, 0x07, 0x55, 0x77, 0xa2, 0x85, 0x52}; 120 | 121 | X25519_Shared(shared, input_coord0, key0); 122 | EXPECT_EQ(memcmp(shared, output_coord0, X25519_KEYSIZE_BYTES), 0) 123 | << "got: " << shared << "want: " << output_coord0; 124 | 125 | X25519_KEY key1 = {0x4b, 0x66, 0xe9, 0xd4, 0xd1, 0xb4, 0x67, 0x3c, 126 | 0x5a, 0xd2, 0x26, 0x91, 0x95, 0x7d, 0x6a, 0xf5, 127 | 0xc1, 0x1b, 0x64, 0x21, 0xe0, 0xea, 0x01, 0xd4, 128 | 0x2c, 0xa4, 0x16, 0x9e, 0x79, 0x18, 0xba, 0x0d}; 129 | 130 | X25519_KEY input_coord1 = {0xe5, 0x21, 0x0f, 0x12, 0x78, 0x68, 0x11, 0xd3, 131 | 0xf4, 0xb7, 0x95, 0x9d, 0x05, 0x38, 0xae, 0x2c, 132 | 0x31, 0xdb, 0xe7, 0x10, 0x6f, 0xc0, 0x3c, 0x3e, 133 | 0xfc, 0x4c, 0xd5, 0x49, 0xc7, 0x15, 0xa4, 0x93}; 134 | 135 | X25519_KEY output_coord1 = {0x95, 0xcb, 0xde, 0x94, 0x76, 0xe8, 0x90, 0x7d, 136 | 0x7a, 0xad, 0xe4, 0x5c, 0xb4, 0xb8, 0x73, 0xf8, 137 | 0x8b, 0x59, 0x5a, 0x68, 0x79, 0x9f, 0xa1, 0x52, 138 | 0xe6, 0xf8, 0xf7, 0x64, 0x7a, 0xac, 0x79, 0x57}; 139 | 140 | X25519_Shared(shared, input_coord1, key1); 141 | EXPECT_EQ(memcmp(shared, output_coord1, X25519_KEYSIZE_BYTES), 0) 142 | << "got: " << shared << "want: " << output_coord1; 143 | 144 | X25519_KEY alice_sk = {0x77, 0x07, 0x6d, 0x0a, 0x73, 0x18, 0xa5, 0x7d, 145 | 0x3c, 0x16, 0xc1, 0x72, 0x51, 0xb2, 0x66, 0x45, 146 | 0xdf, 0x4c, 0x2f, 0x87, 0xeb, 0xc0, 0x99, 0x2a, 147 | 0xb1, 0x77, 0xfb, 0xa5, 0x1d, 0xb9, 0x2c, 0x2a}; 148 | 149 | X25519_KEY alice_pk = {0x85, 0x20, 0xf0, 0x09, 0x89, 0x30, 0xa7, 0x54, 150 | 0x74, 0x8b, 0x7d, 0xdc, 0xb4, 0x3e, 0xf7, 0x5a, 151 | 0x0d, 0xbf, 0x3a, 0x0d, 0x26, 0x38, 0x1a, 0xf4, 152 | 0xeb, 0xa4, 0xa9, 0x8e, 0xaa, 0x9b, 0x4e, 0x6a}; 153 | X25519_KEY alice_public; 154 | 155 | X25519_KeyGen(alice_public, alice_sk); 156 | EXPECT_EQ(memcmp(alice_public, alice_pk, X25519_KEYSIZE_BYTES), 0) 157 | << "got: " << alice_public << "want: " << alice_pk; 158 | 159 | X25519_KEY bob_sk = {0x5d, 0xab, 0x08, 0x7e, 0x62, 0x4a, 0x8a, 0x4b, 160 | 0x79, 0xe1, 0x7f, 0x8b, 0x83, 0x80, 0x0e, 0xe6, 161 | 0x6f, 0x3b, 0xb1, 0x29, 0x26, 0x18, 0xb6, 0xfd, 162 | 0x1c, 0x2f, 0x8b, 0x27, 0xff, 0x88, 0xe0, 0xeb}; 163 | 164 | X25519_KEY bob_pk = {0xde, 0x9e, 0xdb, 0x7d, 0x7b, 0x7d, 0xc1, 0xb4, 165 | 0xd3, 0x5b, 0x61, 0xc2, 0xec, 0xe4, 0x35, 0x37, 166 | 0x3f, 0x83, 0x43, 0xc8, 0x5b, 0x78, 0x67, 0x4d, 167 | 0xad, 0xfc, 0x7e, 0x14, 0x6f, 0x88, 0x2b, 0x4f}; 168 | 169 | X25519_KEY bob_public; 170 | 171 | X25519_KeyGen(bob_public, bob_sk); 172 | EXPECT_EQ(memcmp(bob_public, bob_pk, X25519_KEYSIZE_BYTES), 0) 173 | << "got: " << bob_public << "want: " << bob_pk; 174 | 175 | X25519_KEY shared_secret = {0x4a, 0x5d, 0x9d, 0x5b, 0xa4, 0xce, 0x2d, 0xe1, 176 | 0x72, 0x8e, 0x3b, 0xf4, 0x80, 0x35, 0x0f, 0x25, 177 | 0xe0, 0x7e, 0x21, 0xc9, 0x47, 0xd1, 0x9e, 0x33, 178 | 0x76, 0xf0, 0x9b, 0x3c, 0x1e, 0x16, 0x17, 0x42}; 179 | 180 | X25519_KEY alice_shared_secret; 181 | X25519_KEY bob_shared_secret; 182 | 183 | X25519_Shared(bob_shared_secret, alice_public, bob_sk); 184 | X25519_Shared(alice_shared_secret, bob_public, alice_sk); 185 | EXPECT_EQ(memcmp(alice_shared_secret, shared_secret, X25519_KEYSIZE_BYTES), 0) 186 | << "got: " << alice_shared_secret << "want: " << shared_secret; 187 | EXPECT_EQ(memcmp(bob_shared_secret, shared_secret, X25519_KEYSIZE_BYTES), 0) 188 | << "got: " << bob_shared_secret << "want: " << shared_secret; 189 | } 190 | 191 | TEST(X25519, IETF_CFRG1_0) { 192 | X25519_KEY k; 193 | X25519_KEY k_1_times = {0x42, 0x2c, 0x8e, 0x7a, 0x62, 0x27, 0xd7, 0xbc, 194 | 0xa1, 0x35, 0x0b, 0x3e, 0x2b, 0xb7, 0x27, 0x9f, 195 | 0x78, 0x97, 0xb8, 0x7b, 0xb6, 0x85, 0x4b, 0x78, 196 | 0x3c, 0x60, 0xe8, 0x03, 0x11, 0xae, 0x30, 0x79}; 197 | times(1, k); 198 | EXPECT_EQ(memcmp(k, k_1_times, X25519_KEYSIZE_BYTES), 0) 199 | << "got: " << k << "want: " << k_1_times; 200 | } 201 | 202 | TEST(X25519, IETF_CFRG1_1) { 203 | X25519_KEY k; 204 | X25519_KEY k_1000_times = {0x68, 0x4c, 0xf5, 0x9b, 0xa8, 0x33, 0x09, 0x55, 205 | 0x28, 0x00, 0xef, 0x56, 0x6f, 0x2f, 0x4d, 0x3c, 206 | 0x1c, 0x38, 0x87, 0xc4, 0x93, 0x60, 0xe3, 0x87, 207 | 0x5f, 0x2e, 0xb9, 0x4d, 0x99, 0x53, 0x2c, 0x51}; 208 | times(1000, k); 209 | EXPECT_EQ(memcmp(k, k_1000_times, X25519_KEYSIZE_BYTES), 0) 210 | << "got: " << k << "want: " << k_1000_times; 211 | } 212 | 213 | TEST(X25519, DISABLED_IETF_CFRG1_2) { 214 | X25519_KEY k; 215 | X25519_KEY k_1000000_times = {0x7c, 0x39, 0x11, 0xe0, 0xab, 0x25, 0x86, 0xfd, 216 | 0x86, 0x44, 0x97, 0x29, 0x7e, 0x57, 0x5e, 0x6f, 217 | 0x3b, 0xc6, 0x01, 0xc0, 0x88, 0x3c, 0x30, 0xdf, 218 | 0x5f, 0x4d, 0xd2, 0xd2, 0x4f, 0x66, 0x54, 0x24}; 219 | times(1000000, k); 220 | EXPECT_EQ(memcmp(k, k_1000000_times, X25519_KEYSIZE_BYTES), 0) 221 | << "got: " << k << "want: " << k_1000000_times; 222 | } 223 | 224 | TEST(X25519, DIFFIE_HELLMAN) { 225 | int64_t i = 0, TIMES = 1000; 226 | int64_t cnt = 0; 227 | 228 | for (i = 0; i < TIMES; i++) { 229 | X25519_KEY alicesk, alicepk; 230 | random_X25519_key(alicesk); 231 | X25519_KeyGen(alicepk, alicesk); 232 | 233 | X25519_KEY bobsk, bobpk; 234 | random_X25519_key(bobsk); 235 | X25519_KeyGen(bobpk, bobsk); 236 | 237 | X25519_KEY alice_shared_secret; 238 | X25519_KEY bob_shared_secret; 239 | X25519_Shared(alice_shared_secret, bobpk, alicesk); 240 | X25519_Shared(bob_shared_secret, alicepk, bobsk); 241 | EXPECT_EQ( 242 | memcmp(alice_shared_secret, bob_shared_secret, X25519_KEYSIZE_BYTES), 0) 243 | << "got: " << alice_shared_secret << "want: " << bob_shared_secret; 244 | cnt++; 245 | } 246 | EXPECT_EQ(cnt, TIMES) << "passed: " << cnt << "/" << TIMES << std::endl; 247 | } 248 | -------------------------------------------------------------------------------- /tests/test_x448.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2017, Armando Faz . All rights reserved. 3 | * Institute of Computing. 4 | * University of Campinas, Brazil. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions 8 | * are met: 9 | * 10 | * * Redistributions of source code must retain the above copyright 11 | * notice, this list of conditions and the following disclaimer. 12 | * * Redistributions in binary form must reproduce the above 13 | * copyright notice, this list of conditions and the following 14 | * disclaimer in the documentation and/or other materials provided 15 | * with the distribution. 16 | * * Neither the name of University of Campinas nor the names of its 17 | * contributors may be used to endorse or promote products derived 18 | * from this software without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 23 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 24 | * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 25 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 26 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 29 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 31 | * OF THE POSSIBILITY OF SUCH DAMAGE. 32 | */ 33 | 34 | #include "random.h" 35 | #include "gtest/gtest.h" 36 | #include 37 | #include 38 | #include 39 | #include 40 | 41 | static std::ostream &operator<<(std::ostream &os, const X448_KEY &key) { 42 | int i = 0; 43 | for (i = 0; i < X448_KEYSIZE_BYTES; i++) { 44 | os << std::setbase(16) << std::setfill('0') << std::setw(2) 45 | << static_cast(key[i]); 46 | } 47 | return os << std::endl; 48 | } 49 | 50 | static void random_X448_key(argKey key) { 51 | random_bytes(key, X448_KEYSIZE_BYTES); 52 | } 53 | 54 | static void times(int n, uint8_t *k) { 55 | X448_KEY r, u; 56 | int i; 57 | for (i = 0; i < X448_KEYSIZE_BYTES; i++) { 58 | u[i] = 0; 59 | k[i] = 0; 60 | r[i] = 0; 61 | } 62 | u[0] = 5; 63 | k[0] = 5; 64 | 65 | for (i = 0; i < n; i++) { 66 | X448_Shared(r, u, k); 67 | memcpy(u, k, X448_KEYSIZE_BYTES); 68 | memcpy(k, r, X448_KEYSIZE_BYTES); 69 | } 70 | } 71 | 72 | TEST(X448, IETF_CFRG0) { 73 | X448_KEY shared; 74 | 75 | X448_KEY key0 = {0x3d, 0x26, 0x2f, 0xdd, 0xf9, 0xec, 0x8e, 0x88, 0x49, 0x52, 76 | 0x66, 0xfe, 0xa1, 0x9a, 0x34, 0xd2, 0x88, 0x82, 0xac, 0xef, 77 | 0x04, 0x51, 0x04, 0xd0, 0xd1, 0xaa, 0xe1, 0x21, 0x70, 0x0a, 78 | 0x77, 0x9c, 0x98, 0x4c, 0x24, 0xf8, 0xcd, 0xd7, 0x8f, 0xbf, 79 | 0xf4, 0x49, 0x43, 0xeb, 0xa3, 0x68, 0xf5, 0x4b, 0x29, 0x25, 80 | 0x9a, 0x4f, 0x1c, 0x60, 0x0a, 0xd3}; 81 | 82 | X448_KEY input_coord0 = { 83 | 0x06, 0xfc, 0xe6, 0x40, 0xfa, 0x34, 0x87, 0xbf, 0xda, 0x5f, 0x6c, 0xf2, 84 | 0xd5, 0x26, 0x3f, 0x8a, 0xad, 0x88, 0x33, 0x4c, 0xbd, 0x07, 0x43, 0x7f, 85 | 0x02, 0x0f, 0x08, 0xf9, 0x81, 0x4d, 0xc0, 0x31, 0xdd, 0xbd, 0xc3, 0x8c, 86 | 0x19, 0xc6, 0xda, 0x25, 0x83, 0xfa, 0x54, 0x29, 0xdb, 0x94, 0xad, 0xa1, 87 | 0x8a, 0xa7, 0xa7, 0xfb, 0x4e, 0xf8, 0xa0, 0x86}; 88 | 89 | X448_KEY output_coord0 = { 90 | 0xce, 0x3e, 0x4f, 0xf9, 0x5a, 0x60, 0xdc, 0x66, 0x97, 0xda, 0x1d, 0xb1, 91 | 0xd8, 0x5e, 0x6a, 0xfb, 0xdf, 0x79, 0xb5, 0x0a, 0x24, 0x12, 0xd7, 0x54, 92 | 0x6d, 0x5f, 0x23, 0x9f, 0xe1, 0x4f, 0xba, 0xad, 0xeb, 0x44, 0x5f, 0xc6, 93 | 0x6a, 0x01, 0xb0, 0x77, 0x9d, 0x98, 0x22, 0x39, 0x61, 0x11, 0x1e, 0x21, 94 | 0x76, 0x62, 0x82, 0xf7, 0x3d, 0xd9, 0x6b, 0x6f}; 95 | X448_Shared(shared, input_coord0, key0); 96 | EXPECT_EQ(memcmp(shared, output_coord0, X448_KEYSIZE_BYTES), 0) 97 | << "got: " << shared << "want: " << output_coord0; 98 | 99 | X448_KEY key1 = {0x20, 0x3d, 0x49, 0x44, 0x28, 0xb8, 0x39, 0x93, 0x52, 0x66, 100 | 0x5d, 0xdc, 0xa4, 0x2f, 0x9d, 0xe8, 0xfe, 0xf6, 0x00, 0x90, 101 | 0x8e, 0x0d, 0x46, 0x1c, 0xb0, 0x21, 0xf8, 0xc5, 0x38, 0x34, 102 | 0x5d, 0xd7, 0x7c, 0x3e, 0x48, 0x06, 0xe2, 0x5f, 0x46, 0xd3, 103 | 0x31, 0x5c, 0x44, 0xe0, 0xa5, 0xb4, 0x37, 0x12, 0x82, 0xdd, 104 | 0x2c, 0x8d, 0x5b, 0xe3, 0x09, 0x5f}; 105 | 106 | X448_KEY input_coord1 = { 107 | 0x0f, 0xbc, 0xc2, 0xf9, 0x93, 0xcd, 0x56, 0xd3, 0x30, 0x5b, 0x0b, 0x7d, 108 | 0x9e, 0x55, 0xd4, 0xc1, 0xa8, 0xfb, 0x5d, 0xbb, 0x52, 0xf8, 0xe9, 0xa1, 109 | 0xe9, 0xb6, 0x20, 0x1b, 0x16, 0x5d, 0x01, 0x58, 0x94, 0xe5, 0x6c, 0x4d, 110 | 0x35, 0x70, 0xbe, 0xe5, 0x2f, 0xe2, 0x05, 0xe2, 0x8a, 0x78, 0xb9, 0x1c, 111 | 0xdf, 0xbd, 0xe7, 0x1c, 0xe8, 0xd1, 0x57, 0xdb}; 112 | 113 | X448_KEY output_coord1 = { 114 | 0x88, 0x4a, 0x02, 0x57, 0x62, 0x39, 0xff, 0x7a, 0x2f, 0x2f, 0x63, 0xb2, 115 | 0xdb, 0x6a, 0x9f, 0xf3, 0x70, 0x47, 0xac, 0x13, 0x56, 0x8e, 0x1e, 0x30, 116 | 0xfe, 0x63, 0xc4, 0xa7, 0xad, 0x1b, 0x3e, 0xe3, 0xa5, 0x70, 0x0d, 0xf3, 117 | 0x43, 0x21, 0xd6, 0x20, 0x77, 0xe6, 0x36, 0x33, 0xc5, 0x75, 0xc1, 0xc9, 118 | 0x54, 0x51, 0x4e, 0x99, 0xda, 0x7c, 0x17, 0x9d}; 119 | 120 | X448_Shared(shared, input_coord1, key1); 121 | EXPECT_EQ(memcmp(shared, output_coord1, X448_KEYSIZE_BYTES), 0) 122 | << "got: " << shared << "want: " << output_coord1; 123 | 124 | X448_KEY alice_sk = { 125 | 0x9a, 0x8f, 0x49, 0x25, 0xd1, 0x51, 0x9f, 0x57, 0x75, 0xcf, 0x46, 0xb0, 126 | 0x4b, 0x58, 0x00, 0xd4, 0xee, 0x9e, 0xe8, 0xba, 0xe8, 0xbc, 0x55, 0x65, 127 | 0xd4, 0x98, 0xc2, 0x8d, 0xd9, 0xc9, 0xba, 0xf5, 0x74, 0xa9, 0x41, 0x97, 128 | 0x44, 0x89, 0x73, 0x91, 0x00, 0x63, 0x82, 0xa6, 0xf1, 0x27, 0xab, 0x1d, 129 | 0x9a, 0xc2, 0xd8, 0xc0, 0xa5, 0x98, 0x72, 0x6b}; 130 | 131 | X448_KEY alice_pk = { 132 | 0x9b, 0x08, 0xf7, 0xcc, 0x31, 0xb7, 0xe3, 0xe6, 0x7d, 0x22, 0xd5, 0xae, 133 | 0xa1, 0x21, 0x07, 0x4a, 0x27, 0x3b, 0xd2, 0xb8, 0x3d, 0xe0, 0x9c, 0x63, 134 | 0xfa, 0xa7, 0x3d, 0x2c, 0x22, 0xc5, 0xd9, 0xbb, 0xc8, 0x36, 0x64, 0x72, 135 | 0x41, 0xd9, 0x53, 0xd4, 0x0c, 0x5b, 0x12, 0xda, 0x88, 0x12, 0x0d, 0x53, 136 | 0x17, 0x7f, 0x80, 0xe5, 0x32, 0xc4, 0x1f, 0xa0}; 137 | X448_KEY alice_public; 138 | 139 | X448_KeyGen(alice_public, alice_sk); 140 | EXPECT_EQ(memcmp(alice_public, alice_pk, X448_KEYSIZE_BYTES), 0) 141 | << "got: " << alice_public << "want: " << alice_pk; 142 | 143 | X448_KEY bob_sk = {0x1c, 0x30, 0x6a, 0x7a, 0xc2, 0xa0, 0xe2, 0xe0, 0x99, 0x0b, 144 | 0x29, 0x44, 0x70, 0xcb, 0xa3, 0x39, 0xe6, 0x45, 0x37, 0x72, 145 | 0xb0, 0x75, 0x81, 0x1d, 0x8f, 0xad, 0x0d, 0x1d, 0x69, 0x27, 146 | 0xc1, 0x20, 0xbb, 0x5e, 0xe8, 0x97, 0x2b, 0x0d, 0x3e, 0x21, 147 | 0x37, 0x4c, 0x9c, 0x92, 0x1b, 0x09, 0xd1, 0xb0, 0x36, 0x6f, 148 | 0x10, 0xb6, 0x51, 0x73, 0x99, 0x2d}; 149 | 150 | X448_KEY bob_pk = {0x3e, 0xb7, 0xa8, 0x29, 0xb0, 0xcd, 0x20, 0xf5, 0xbc, 0xfc, 151 | 0x0b, 0x59, 0x9b, 0x6f, 0xec, 0xcf, 0x6d, 0xa4, 0x62, 0x71, 152 | 0x07, 0xbd, 0xb0, 0xd4, 0xf3, 0x45, 0xb4, 0x30, 0x27, 0xd8, 153 | 0xb9, 0x72, 0xfc, 0x3e, 0x34, 0xfb, 0x42, 0x32, 0xa1, 0x3c, 154 | 0xa7, 0x06, 0xdc, 0xb5, 0x7a, 0xec, 0x3d, 0xae, 0x07, 0xbd, 155 | 0xc1, 0xc6, 0x7b, 0xf3, 0x36, 0x09}; 156 | 157 | X448_KEY bob_public; 158 | 159 | X448_KeyGen(bob_public, bob_sk); 160 | EXPECT_EQ(memcmp(bob_public, bob_pk, X448_KEYSIZE_BYTES), 0) 161 | << "got: " << bob_public << "want: " << bob_pk; 162 | 163 | X448_KEY shared_secret = { 164 | 0x07, 0xff, 0xf4, 0x18, 0x1a, 0xc6, 0xcc, 0x95, 0xec, 0x1c, 0x16, 0xa9, 165 | 0x4a, 0x0f, 0x74, 0xd1, 0x2d, 0xa2, 0x32, 0xce, 0x40, 0xa7, 0x75, 0x52, 166 | 0x28, 0x1d, 0x28, 0x2b, 0xb6, 0x0c, 0x0b, 0x56, 0xfd, 0x24, 0x64, 0xc3, 167 | 0x35, 0x54, 0x39, 0x36, 0x52, 0x1c, 0x24, 0x40, 0x30, 0x85, 0xd5, 0x9a, 168 | 0x44, 0x9a, 0x50, 0x37, 0x51, 0x4a, 0x87, 0x9d}; 169 | 170 | X448_KEY alice_shared_secret; 171 | X448_KEY bob_shared_secret; 172 | 173 | X448_Shared(bob_shared_secret, alice_public, bob_sk); 174 | X448_Shared(alice_shared_secret, bob_public, alice_sk); 175 | EXPECT_EQ(memcmp(alice_shared_secret, shared_secret, X448_KEYSIZE_BYTES), 0) 176 | << "got: " << alice_shared_secret << "want: " << shared_secret; 177 | EXPECT_EQ(memcmp(bob_shared_secret, shared_secret, X448_KEYSIZE_BYTES), 0) 178 | << "got: " << bob_shared_secret << "want: " << shared_secret; 179 | } 180 | 181 | TEST(X448, IETF_CFRG1_0) { 182 | X448_KEY k; 183 | X448_KEY k_1_times = { 184 | 0x3f, 0x48, 0x2c, 0x8a, 0x9f, 0x19, 0xb0, 0x1e, 0x6c, 0x46, 0xee, 0x97, 185 | 0x11, 0xd9, 0xdc, 0x14, 0xfd, 0x4b, 0xf6, 0x7a, 0xf3, 0x07, 0x65, 0xc2, 186 | 0xae, 0x2b, 0x84, 0x6a, 0x4d, 0x23, 0xa8, 0xcd, 0x0d, 0xb8, 0x97, 0x08, 187 | 0x62, 0x39, 0x49, 0x2c, 0xaf, 0x35, 0x0b, 0x51, 0xf8, 0x33, 0x86, 0x8b, 188 | 0x9b, 0xc2, 0xb3, 0xbc, 0xa9, 0xcf, 0x41, 0x13}; 189 | times(1, k); 190 | EXPECT_EQ(memcmp(k, k_1_times, X448_KEYSIZE_BYTES), 0) 191 | << "got: " << k << "want: " << k_1_times; 192 | } 193 | 194 | TEST(X448, IETF_CFRG1_1) { 195 | X448_KEY k; 196 | X448_KEY k_1000_times = { 197 | 0xaa, 0x3b, 0x47, 0x49, 0xd5, 0x5b, 0x9d, 0xaf, 0x1e, 0x5b, 0x00, 0x28, 198 | 0x88, 0x26, 0xc4, 0x67, 0x27, 0x4c, 0xe3, 0xeb, 0xbd, 0xd5, 0xc1, 0x7b, 199 | 0x97, 0x5e, 0x09, 0xd4, 0xaf, 0x6c, 0x67, 0xcf, 0x10, 0xd0, 0x87, 0x20, 200 | 0x2d, 0xb8, 0x82, 0x86, 0xe2, 0xb7, 0x9f, 0xce, 0xea, 0x3e, 0xc3, 0x53, 201 | 0xef, 0x54, 0xfa, 0xa2, 0x6e, 0x21, 0x9f, 0x38}; 202 | times(1000, k); 203 | EXPECT_EQ(memcmp(k, k_1000_times, X448_KEYSIZE_BYTES), 0) 204 | << "got: " << k << "want: " << k_1000_times; 205 | } 206 | 207 | TEST(X448, DISABLED_IETF_CFRG1_2) { 208 | X448_KEY k; 209 | X448_KEY k_1000000_times = { 210 | 0x07, 0x7f, 0x45, 0x36, 0x81, 0xca, 0xca, 0x36, 0x93, 0x19, 0x84, 0x20, 211 | 0xbb, 0xe5, 0x15, 0xca, 0xe0, 0x00, 0x24, 0x72, 0x51, 0x9b, 0x3e, 0x67, 212 | 0x66, 0x1a, 0x7e, 0x89, 0xca, 0xb9, 0x46, 0x95, 0xc8, 0xf4, 0xbc, 0xd6, 213 | 0x6e, 0x61, 0xb9, 0xb9, 0xc9, 0x46, 0xda, 0x8d, 0x52, 0x4d, 0xe3, 0xd6, 214 | 0x9b, 0xd9, 0xd9, 0xd6, 0x6b, 0x99, 0x7e, 0x37}; 215 | times(1000000, k); 216 | EXPECT_EQ(memcmp(k, k_1000000_times, X448_KEYSIZE_BYTES), 0) 217 | << "got: " << k << "want: " << k_1000000_times; 218 | } 219 | 220 | TEST(X448, DIFFIE_HELLMAN) { 221 | int64_t i = 0, TIMES = 1000; 222 | int64_t cnt = 0; 223 | 224 | for (i = 0; i < TIMES; i++) { 225 | X448_KEY alicesk, alicepk; 226 | random_X448_key(alicesk); 227 | X448_KeyGen(alicepk, alicesk); 228 | 229 | X448_KEY bobsk, bobpk; 230 | random_X448_key(bobsk); 231 | X448_KeyGen(bobpk, bobsk); 232 | 233 | X448_KEY alice_shared_secret; 234 | X448_KEY bob_shared_secret; 235 | X448_Shared(alice_shared_secret, bobpk, alicesk); 236 | X448_Shared(bob_shared_secret, alicepk, bobsk); 237 | EXPECT_EQ( 238 | memcmp(alice_shared_secret, bob_shared_secret, X448_KEYSIZE_BYTES), 0) 239 | << "got: " << alice_shared_secret << "want: " << bob_shared_secret; 240 | cnt++; 241 | } 242 | EXPECT_EQ(cnt, TIMES) << "passed: " << cnt << "/" << TIMES << std::endl; 243 | } 244 | -------------------------------------------------------------------------------- /third_party/random.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | /** Random number Generator: 7 | * Taken from: https://github.com/relic-toolkit/relic/src/rand/relic_rand_call.c 8 | * 9 | * @warning Provide a secure random number generator. 10 | * @param buffer 11 | * @param num_bytes 12 | */ 13 | void random_bytes(uint8_t *buffer, int num_bytes) { 14 | int c, l, fd = open("/dev/urandom", O_RDONLY); 15 | 16 | if (fd == -1) { 17 | printf("Error opening /dev/urandom\n"); 18 | } 19 | 20 | l = 0; 21 | do { 22 | c = read(fd, buffer + l, num_bytes - l); 23 | l += c; 24 | if (c == -1) { 25 | printf("Error reading /dev/urandom\n"); 26 | } 27 | } while (l < num_bytes); 28 | 29 | close(fd); 30 | } 31 | 32 | void print_bytes(uint8_t *A, int num_bytes) { 33 | int i; 34 | 35 | printf("0x"); 36 | for (i = num_bytes - 1; i >= 0; i--) { 37 | printf("%02x", A[i]); 38 | } 39 | printf("\n"); 40 | } 41 | -------------------------------------------------------------------------------- /third_party/random.h: -------------------------------------------------------------------------------- 1 | #ifndef RANDOM_H 2 | #define RANDOM_H 3 | 4 | #include 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | void random_bytes(uint8_t *A, int length); 11 | void print_bytes(uint8_t *A, int num_bytes); 12 | 13 | #ifdef __cplusplus 14 | } 15 | #endif 16 | 17 | #endif /* RANDOM_H */ 18 | --------------------------------------------------------------------------------