diff --git a/.gitignore b/.gitignore index 254da15..339fae8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,3 @@ -target/ build/ dist/ *.o @@ -7,3 +6,8 @@ __pycache__ python/build/ *.egg-info/ node_modules/ +**.gcno +**.lcov +**/target/ +tags +TAGS diff --git a/CMakeLists.txt b/CMakeLists.txt index 57e9366..3efcb43 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,22 +15,11 @@ set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) -# Platform-specific settings -if(APPLE) - # Set strict floating-point model for macOS to match other platforms - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -ffp-contract=off -fno-fast-math") - # Define FPEMU macro for Falcon to use emulated floating-point on macOS - # This avoids platform-specific floating-point behavior - add_definitions(-DFALCON_FPEMU=1) - message(STATUS "macOS detected: Using emulated floating-point for Falcon") -endif() - # Include directories include_directories( ${CMAKE_CURRENT_SOURCE_DIR}/include ${CMAKE_CURRENT_SOURCE_DIR}/dilithium/ref ${CMAKE_CURRENT_SOURCE_DIR}/sphincsplus/ref - ${CMAKE_CURRENT_SOURCE_DIR}/falcon ) # Custom randombytes implementation @@ -67,20 +56,6 @@ set(SLH_DSA_SOURCES sphincsplus/ref/fips202.c ) -# FN-DSA-512 (FALCON) source files -set(FN_DSA_SOURCES - falcon/codec.c - falcon/common.c - falcon/falcon.c - falcon/fft.c - falcon/fpr.c - falcon/keygen.c - falcon/shake.c - falcon/sign.c - falcon/vrfy.c - falcon/rng.c -) - # libbitcoinpqc source files set(BITCOINPQC_SOURCES src/bitcoinpqc.c @@ -92,10 +67,6 @@ set(BITCOINPQC_SOURCES src/slh_dsa/keygen.c src/slh_dsa/sign.c src/slh_dsa/verify.c - src/fn_dsa/utils.c - src/fn_dsa/keygen.c - src/fn_dsa/sign.c - src/fn_dsa/verify.c ) # Define the main library target @@ -103,7 +74,6 @@ add_library(bitcoinpqc STATIC ${BITCOINPQC_SOURCES} ${ML_DSA_SOURCES} ${SLH_DSA_SOURCES} - ${FN_DSA_SOURCES} ${CUSTOM_RANDOMBYTES} ) @@ -116,7 +86,6 @@ target_include_directories(bitcoinpqc PUBLIC target_compile_definitions(bitcoinpqc PRIVATE DILITHIUM_MODE=2 # ML-DSA-44 (Dilithium2) PARAMS=sphincs-shake-128s - FALCON_LOGN_512=9 CUSTOM_RANDOMBYTES=1 ) diff --git a/Cargo.lock b/Cargo.lock index df68853..7a41a75 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -19,9 +19,9 @@ checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" [[package]] name = "anstyle" -version = "1.0.10" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" +checksum = "862ed96ca487e809f1c8e5a8447f6ee2cf102f846893800b20cebdf541fc6bbd" [[package]] name = "arrayvec" @@ -31,9 +31,9 @@ checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" [[package]] name = "autocfg" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" [[package]] name = "bindgen" @@ -90,9 +90,9 @@ dependencies = [ [[package]] name = "bitflags" -version = "2.9.0" +version = "2.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd" +checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" [[package]] name = "bitmask-enum" @@ -115,9 +115,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.17.0" +version = "3.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf" +checksum = "793db76d6187cd04dff33004d8e6c9cc4e05cd330500379d2394209271b4aeee" [[package]] name = "cast" @@ -127,9 +127,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.2.20" +version = "1.2.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04da6a0d40b948dfc4fa8f5bbf402b0fc1a64a28dbf7d12ffd683550f2c1b63a" +checksum = "d487aa071b5f64da6f19a3e848e3578944b726ee5a4854b82172f02aa876bfdc" dependencies = [ "shlex", ] @@ -145,9 +145,9 @@ dependencies = [ [[package]] name = "cfg-if" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268" [[package]] name = "ciborium" @@ -189,18 +189,18 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.37" +version = "4.5.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eccb054f56cbd38340b380d4a8e69ef1f02f1af43db2f0cc817a4774d80ae071" +checksum = "40b6887a1d8685cebccf115538db5c0efe625ccac9696ad45c409d96566e910f" dependencies = [ "clap_builder", ] [[package]] name = "clap_builder" -version = "4.5.37" +version = "4.5.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efd9466fac8543255d3b1fcad4762c5e116ffe808c8a3043d4263cd4fd4862a2" +checksum = "e0c66c08ce9f0c698cbce5c0279d0bb6ac936d8674174fe48f736533b964f59e" dependencies = [ "anstyle", "clap_lex", @@ -208,9 +208,9 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.7.4" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6" +checksum = "b94f61472cee1439c0b966b47e3aca9ae07e45d070759512cd390ea2bebc6675" [[package]] name = "cmake" @@ -335,9 +335,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73fea8450eea4bac3940448fb7ae50d91f034f941199fcd9d909a5a07aa455f0" +checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" dependencies = [ "cfg-if", "libc", @@ -363,9 +363,9 @@ dependencies = [ [[package]] name = "hermit-abi" -version = "0.5.0" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbd780fe5cc30f81464441920d82ac8740e2e46b29a6fad543ddd075229ce37e" +checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" [[package]] name = "hex" @@ -429,18 +429,18 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.172" +version = "0.2.174" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa" +checksum = "1171693293099992e19cddea4e8b849964e9846f4acee11b3948bcc337be8776" [[package]] name = "libloading" -version = "0.8.6" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc2f4eb4bc735547cfed7c0a4922cbd04a4655978c09b54f1f7b228750664c34" +checksum = "07033963ba89ebaf1584d767badaa2e8fcec21aedea6b8c0346d487d49c28667" dependencies = [ "cfg-if", - "windows-targets", + "windows-targets 0.53.2", ] [[package]] @@ -451,9 +451,9 @@ checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" [[package]] name = "memchr" -version = "2.7.4" +version = "2.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" +checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" [[package]] name = "minimal-lexical" @@ -531,9 +531,9 @@ dependencies = [ [[package]] name = "prettyplease" -version = "0.2.32" +version = "0.2.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "664ec5419c51e34154eec046ebcba56312d5a2fc3b09a06da188e1ad21afadf6" +checksum = "6837b9e10d61f45f987d50808f83d1ee3d206c66acf650c3e4ae2e1f6ddedf55" dependencies = [ "proc-macro2", "syn", @@ -559,9 +559,9 @@ dependencies = [ [[package]] name = "r-efi" -version = "5.2.0" +version = "5.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" [[package]] name = "rand" @@ -649,9 +649,9 @@ checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" [[package]] name = "rustversion" -version = "1.0.20" +version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eded382c5f5f786b989652c49544c4877d9f015cc22e145a5ea8ea66c2921cd2" +checksum = "8a0d197bd2c9dc6e53b84da9556a69ba4cdfab8619eb41a8bd1cc2027a0f6b1d" [[package]] name = "ryu" @@ -723,9 +723,9 @@ dependencies = [ [[package]] name = "sha2" -version = "0.10.8" +version = "0.10.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" dependencies = [ "cfg-if", "cpufeatures", @@ -740,9 +740,9 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "syn" -version = "2.0.101" +version = "2.0.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ce2b7fc941b3a24138a0a7cf8e858bfc6a992e7978a068a5c760deb0ed43caf" +checksum = "e4307e30089d6fd6aff212f2da3a1f9e32f3223b1f010fb09b7c95f90f3ca1e8" dependencies = [ "proc-macro2", "quote", @@ -879,7 +879,7 @@ version = "0.59.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" dependencies = [ - "windows-targets", + "windows-targets 0.52.6", ] [[package]] @@ -888,14 +888,30 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_gnullvm", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm 0.52.6", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", +] + +[[package]] +name = "windows-targets" +version = "0.53.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c66f69fcc9ce11da9966ddb31a40968cad001c5bedeb5c2b82ede4253ab48aef" +dependencies = [ + "windows_aarch64_gnullvm 0.53.0", + "windows_aarch64_msvc 0.53.0", + "windows_i686_gnu 0.53.0", + "windows_i686_gnullvm 0.53.0", + "windows_i686_msvc 0.53.0", + "windows_x86_64_gnu 0.53.0", + "windows_x86_64_gnullvm 0.53.0", + "windows_x86_64_msvc 0.53.0", ] [[package]] @@ -904,48 +920,96 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" + [[package]] name = "windows_aarch64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" +[[package]] +name = "windows_aarch64_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" + [[package]] name = "windows_i686_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" +[[package]] +name = "windows_i686_gnu" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" + [[package]] name = "windows_i686_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" +[[package]] +name = "windows_i686_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" + [[package]] name = "windows_i686_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" +[[package]] +name = "windows_i686_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" + [[package]] name = "windows_x86_64_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" +[[package]] +name = "windows_x86_64_gnu" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" + [[package]] name = "windows_x86_64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" + [[package]] name = "windows_x86_64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" +[[package]] +name = "windows_x86_64_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" + [[package]] name = "wit-bindgen-rt" version = "0.39.0" @@ -957,18 +1021,18 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.8.25" +version = "0.8.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1702d9583232ddb9174e01bb7c15a2ab8fb1bc6f227aa1233858c351a3ba0cb" +checksum = "1039dd0d3c310cf05de012d8a39ff557cb0d23087fd44cad61df08fc31907a2f" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.25" +version = "0.8.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28a6e20d751156648aa063f3800b706ee209a32c0b4d9f24be3d980b01be55ef" +checksum = "9ecf5b4cc5364572d7f4c329661bcc82724222973f2cab6f050a4e5c22f75181" dependencies = [ "proc-macro2", "quote", diff --git a/README.md b/README.md index 9a7a7fe..d49d7f6 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,9 @@ # libbitcoinpqc -A C library with Rust bindings for Post-Quantum Cryptographic (PQC) signature algorithms. This library implements three NIST PQC standardized or candidate signature algorithms for use with [BIP-360](https://github.com/cryptoquick/bips/blob/p2qrh/bip-0360.mediawiki) and the Bitcoin QuBit soft fork: +A C library, with Rust bindings, for Post-Quantum Cryptographic (PQC) signature algorithms. This library implements two NIST PQC standard signature algorithms for use with [BIP-360](https://github.com/cryptoquick/bips/blob/p2qrh/bip-0360.mediawiki) and the Bitcoin QuBit soft fork: 1. **ML-DSA-44** (formerly CRYSTALS-Dilithium): A structured lattice-based digital signature scheme that is part of the NIST PQC standardization. 2. **SLH-DSA-Shake-128s** (formerly SPHINCS+): A stateless hash-based signature scheme with minimal security assumptions. -3. **FN-DSA-512** (formerly FALCON): A lattice-based signature scheme designed for efficiency and compact signatures. Notice that all PQC signature algorithms used are certified according to the Federal Information Processing Standards, or FIPS. This should help in the future with native hardware support. @@ -27,7 +26,6 @@ This library serves as the cryptographic foundation for the Bitcoin QuBit soft f | Algorithm | Public Key Size | Secret Key Size | Signature Size | Security Level | |-----------|----------------|----------------|----------------|----------------| | secp256k1 | 32 bytes | 32 bytes | 64 bytes | Classical | -| FN-DSA-512 | 897 bytes | 1,281 bytes | ~666 bytes (average) | NIST Level 1 | | ML-DSA-44 | 1,312 bytes | 2,528 bytes | 2,420 bytes | NIST Level 2 | | SLH-DSA-SHAKE-128s | 32 bytes | 64 bytes | 7,856 bytes | NIST Level 1 | @@ -35,7 +33,7 @@ See [REPORT.md](benches/REPORT.md) for performance and size comparison to secp25 ## Security Notes -- This library does not provide its own random number generation. Users must provide entropy from a secure source. +- This library does not provide its own random number generation. It is essential that the user provide entropy from a cryptographically secure source. - Random data is required for key generation, but not for signing. All signatures are deterministic, based on the message and secret key. - The implementations are based on reference code from the NIST PQC standardization process and are not production-hardened. - Care should be taken to securely manage secret keys in applications. @@ -54,7 +52,6 @@ Cryptographic dependencies included in this project: - https://github.com/sphincs/sphincsplus - `7ec789ace6874d875f4bb84cb61b81155398167e` - https://github.com/pq-crystals/dilithium - `444cdcc84eb36b66fe27b3a2529ee48f6d8150c2` -- https://falcon-sign.info/Falcon-impl-20211101.zip ## Building the Library @@ -223,7 +220,6 @@ The Python API mirrors the C API closely, with some Pythonic improvements: - **Algorithm** - Enum class for algorithm selection - `SECP256K1_SCHNORR` - - `FN_DSA_512` (FALCON) - `ML_DSA_44` (CRYSTALS-Dilithium) - `SLH_DSA_SHAKE_128S` (SPHINCS+) @@ -292,7 +288,6 @@ The TypeScript API provides a clean, modern interface: - **Algorithm** - Enum for algorithm selection - `SECP256K1_SCHNORR` - - `FN_DSA_512` (FALCON) - `ML_DSA_44` (CRYSTALS-Dilithium) - `SLH_DSA_SHAKE_128S` (SPHINCS+) diff --git a/benches/README.md b/benches/README.md index c3f140f..e6decfd 100644 --- a/benches/README.md +++ b/benches/README.md @@ -26,12 +26,6 @@ cargo bench -- ml_dsa_44 cargo bench -- slh_dsa_128s ``` -### FN-DSA-512 (FALCON) - -``` -cargo bench -- fn_dsa_512 -``` - ### secp256k1 (for comparison) ``` @@ -89,7 +83,7 @@ cargo bench -- sizes If you encounter any issues with a specific algorithm, try running only that algorithm's benchmarks: ``` -cargo bench -- fn_dsa_512 +cargo bench -- ml_dsa_44 ``` This can help identify any issues with the algorithm implementation. diff --git a/benches/REPORT.md b/benches/REPORT.md index 26a00ba..e8538ee 100644 --- a/benches/REPORT.md +++ b/benches/REPORT.md @@ -9,11 +9,10 @@ All values show relative performance compared to secp256k1 (lower is better). | Algorithm | Key Generation | Signing | Verification | |-----------|----------------|---------|--------------| | secp256k1 | 1.00x | 1.00x | 1.00x | -| FN-DSA-512 | ~8.5x | ~9.2x | ~7.6x | -| ML-DSA-44 | ~5.2x | ~3.7x | ~4.1x | -| SLH-DSA-128S | ~120x | ~80x | ~90x | +| ML-DSA-44 | *Needs Update* | *Needs Update* | *Needs Update* | +| SLH-DSA-128S | *Needs Update* | *Needs Update* | *Needs Update* | -*Note: Performance values are estimates based on benchmarks. Lower values are better (e.g., 2x means twice as slow as secp256k1).* +*Note: Performance values require parsing Criterion output and are not yet updated automatically.* ## Size Comparison @@ -22,7 +21,6 @@ All values show actual sizes with relative comparison to secp256k1. | Algorithm | Secret Key | Public Key | Signature | Public Key + Signature | |-----------|------------|------------|-----------|------------------------| | secp256k1 | 32 bytes (1.00x) | 32 bytes (1.00x) | 64 bytes (1.00x) | 96 bytes (1.00x) | -| FN-DSA-512 | 1281 bytes (40.03x) | 897 bytes (28.03x) | 654 bytes (10.22x) | 1551 bytes (16.16x) | | ML-DSA-44 | 2560 bytes (80.00x) | 1312 bytes (41.00x) | 2420 bytes (37.81x) | 3732 bytes (38.88x) | | SLH-DSA-128S | 64 bytes (2.00x) | 32 bytes (1.00x) | 7856 bytes (122.75x) | 7888 bytes (82.17x) | diff --git a/benches/sig_benchmarks.rs b/benches/sig_benchmarks.rs index 18b0dc1..796bdbb 100644 --- a/benches/sig_benchmarks.rs +++ b/benches/sig_benchmarks.rs @@ -146,79 +146,6 @@ fn bench_slh_dsa_128s_verification(c: &mut Criterion) { group.finish(); } -// FN-DSA-512 BENCHMARKS - -fn bench_fn_dsa_512_keygen(c: &mut Criterion) { - let mut group = c.benchmark_group("fn_dsa_keygen"); - configure_group(&mut group); - - group.bench_function("FN_DSA_512", |b| { - b.iter(|| { - let random_data = get_random_data(256); - generate_keypair(Algorithm::FN_DSA_512, &random_data).unwrap() - }); - }); - - group.finish(); -} - -fn bench_fn_dsa_512_signing(c: &mut Criterion) { - let mut group = c.benchmark_group("fn_dsa_signing"); - configure_group(&mut group); - - let message = b"This is a test message for benchmarking"; - let random_data = get_random_data(256); - let fn_keypair = generate_keypair(Algorithm::FN_DSA_512, &random_data).unwrap(); - - // Only print debug info if DEBUG_MODE is true - if DEBUG_MODE { - println!("FN-DSA-512 Keypair created for benchmarking:"); - println!( - "Public key size: {}, Secret key size: {}", - fn_keypair.public_key.bytes.len(), - fn_keypair.secret_key.bytes.len() - ); - println!( - "Secret key first bytes: {:02x?}", - &fn_keypair.secret_key.bytes[..8.min(fn_keypair.secret_key.bytes.len())] - ); - - // Verify we can sign once before benchmarking - let test_sig = sign(&fn_keypair.secret_key, message).unwrap(); - println!("Test signature size: {}", test_sig.bytes.len()); - println!( - "Test signature first bytes: {:02x?}", - &test_sig.bytes[..8.min(test_sig.bytes.len())] - ); - } else { - // Generate a test signature without debug output - sign(&fn_keypair.secret_key, message).unwrap(); - } - - // Now benchmark - group.bench_function("FN_DSA_512", |b| { - b.iter(|| sign(&fn_keypair.secret_key, message)); - }); - - group.finish(); -} - -fn bench_fn_dsa_512_verification(c: &mut Criterion) { - let mut group = c.benchmark_group("fn_dsa_verification"); - configure_group(&mut group); - - let message = b"This is a test message for benchmarking"; - let random_data = get_random_data(256); - let fn_keypair = generate_keypair(Algorithm::FN_DSA_512, &random_data).unwrap(); - let fn_sig = sign(&fn_keypair.secret_key, message).unwrap(); - - group.bench_function("FN_DSA_512", |b| { - b.iter(|| verify(&fn_keypair.public_key, message, &fn_sig).unwrap()); - }); - - group.finish(); -} - // SIZE REPORTING - Combined in one benchmark fn bench_sizes(c: &mut Criterion) { @@ -256,21 +183,6 @@ fn bench_sizes(c: &mut Criterion) { store_size_result("slh_dsa_128s_sig", slh_sig_size); store_size_result("slh_dsa_128s_pk_sig", slh_pk_sig_size); - // FN-DSA-512 - let random_data = get_random_data(256); - let fn_keypair = generate_keypair(Algorithm::FN_DSA_512, &random_data).unwrap(); - let fn_sig = sign(&fn_keypair.secret_key, message).unwrap(); - let fn_pk_size = fn_keypair.public_key.bytes.len(); - let fn_sk_size = fn_keypair.secret_key.bytes.len(); - let fn_sig_size = fn_sig.bytes.len(); - let fn_pk_sig_size = fn_pk_size + fn_sig_size; - - // Store size results - store_size_result("fn_dsa_512_pubkey", fn_pk_size); - store_size_result("fn_dsa_512_seckey", fn_sk_size); - store_size_result("fn_dsa_512_sig", fn_sig_size); - store_size_result("fn_dsa_512_pk_sig", fn_pk_sig_size); - // Print key and signature sizes debug_println!("Key and Signature Sizes (bytes):"); debug_println!("ML-DSA-44:"); @@ -289,14 +201,6 @@ fn bench_sizes(c: &mut Criterion) { slh_sig_size ); - debug_println!("FN-DSA-512:"); - debug_println!( - " Public key: {}, Secret key: {}, Signature: {}", - fn_pk_size, - fn_sk_size, - fn_sig_size - ); - group.finish(); } @@ -411,19 +315,6 @@ fn generate_report(_c: &mut Criterion) { "| secp256k1 | {} bytes (1.00x) | {} bytes (1.00x) | {} bytes (1.00x) | {} bytes (1.00x) |", secp_seckey_size, secp_pubkey_size, secp_sig_size, secp_pk_sig_size ); - } else if trimmed_line.starts_with("| FN-DSA-512 |") { - // Order matches commit diff - let fn_pubkey_size = size_results.get("fn_dsa_512_pubkey").cloned().unwrap_or(0); - let fn_seckey_size = size_results.get("fn_dsa_512_seckey").cloned().unwrap_or(0); - let fn_sig_size = size_results.get("fn_dsa_512_sig").cloned().unwrap_or(0); - let fn_pk_sig_size = size_results.get("fn_dsa_512_pk_sig").cloned().unwrap_or(0); - line_to_push = format!( - "| FN-DSA-512 | {} bytes ({:.2}x) | {} bytes ({:.2}x) | {} bytes ({:.2}x) | {} bytes ({:.2}x) |", - fn_seckey_size, if secp_seckey_size > 0 { fn_seckey_size as f64 / secp_seckey_size as f64 } else { 0.0 }, - fn_pubkey_size, if secp_pubkey_size > 0 { fn_pubkey_size as f64 / secp_pubkey_size as f64 } else { 0.0 }, - fn_sig_size, if secp_sig_size > 0 { fn_sig_size as f64 / secp_sig_size as f64 } else { 0.0 }, - fn_pk_sig_size, if secp_pk_sig_size > 0 { fn_pk_sig_size as f64 / secp_pk_sig_size as f64 } else { 0.0 } - ); } else if trimmed_line.starts_with("| ML-DSA-44 |") { let ml_pubkey_size = size_results.get("ml_dsa_44_pubkey").cloned().unwrap_or(0); let ml_seckey_size = size_results.get("ml_dsa_44_seckey").cloned().unwrap_or(0); @@ -484,8 +375,6 @@ fn generate_report(_c: &mut Criterion) { updated_lines.push("| Algorithm | Key Generation | Signing | Verification |".to_string()); updated_lines.push("|-----------|----------------|---------|--------------|".to_string()); updated_lines.push("| secp256k1 | 1.00x | 1.00x | 1.00x |".to_string()); - updated_lines - .push("| FN-DSA-512 | *Needs Update* | *Needs Update* | *Needs Update* |".to_string()); // Placeholders - Order matches commit updated_lines .push("| ML-DSA-44 | *Needs Update* | *Needs Update* | *Needs Update* |".to_string()); // Placeholders updated_lines.push( @@ -507,19 +396,6 @@ fn generate_report(_c: &mut Criterion) { secp_seckey_size, secp_pubkey_size, secp_sig_size, secp_pk_sig_size )); - // FN-DSA line (Order matches commit) - let fn_pubkey_size = size_results.get("fn_dsa_512_pubkey").cloned().unwrap_or(0); - let fn_seckey_size = size_results.get("fn_dsa_512_seckey").cloned().unwrap_or(0); - let fn_sig_size = size_results.get("fn_dsa_512_sig").cloned().unwrap_or(0); - let fn_pk_sig_size = size_results.get("fn_dsa_512_pk_sig").cloned().unwrap_or(0); - updated_lines.push(format!( - "| FN-DSA-512 | {} bytes ({:.2}x) | {} bytes ({:.2}x) | {} bytes ({:.2}x) | {} bytes ({:.2}x) |", - fn_seckey_size, if secp_seckey_size > 0 { fn_seckey_size as f64 / secp_seckey_size as f64 } else { 0.0 }, - fn_pubkey_size, if secp_pubkey_size > 0 { fn_pubkey_size as f64 / secp_pubkey_size as f64 } else { 0.0 }, - fn_sig_size, if secp_sig_size > 0 { fn_sig_size as f64 / secp_sig_size as f64 } else { 0.0 }, - fn_pk_sig_size, if secp_pk_sig_size > 0 { fn_pk_sig_size as f64 / secp_pk_sig_size as f64 } else { 0.0 } - )); - // ML-DSA line let ml_pubkey_size = size_results.get("ml_dsa_44_pubkey").cloned().unwrap_or(0); let ml_seckey_size = size_results.get("ml_dsa_44_seckey").cloned().unwrap_or(0); @@ -597,9 +473,6 @@ criterion_group!( bench_slh_dsa_128s_keygen, bench_slh_dsa_128s_signing, bench_slh_dsa_128s_verification, - bench_fn_dsa_512_keygen, - bench_fn_dsa_512_signing, - bench_fn_dsa_512_verification, bench_sizes, generate_report ); diff --git a/build.rs b/build.rs index e44e35f..eb5e25a 100644 --- a/build.rs +++ b/build.rs @@ -13,7 +13,6 @@ fn main() { println!("cargo:rerun-if-changed=include/libbitcoinpqc/bitcoinpqc.h"); println!("cargo:rerun-if-changed=include/libbitcoinpqc/ml_dsa.h"); println!("cargo:rerun-if-changed=include/libbitcoinpqc/slh_dsa.h"); - println!("cargo:rerun-if-changed=include/libbitcoinpqc/fn_dsa.h"); // The bindgen::Builder is the main entry point to bindgen let bindings = bindgen::Builder::default() diff --git a/examples/basic.rs b/examples/basic.rs index b3c7319..2305e45 100644 --- a/examples/basic.rs +++ b/examples/basic.rs @@ -14,7 +14,6 @@ fn main() { // Test each algorithm test_algorithm(Algorithm::ML_DSA_44, "ML-DSA-44", &random_data); test_algorithm(Algorithm::SLH_DSA_128S, "SLH-DSA-Shake-128s", &random_data); - test_algorithm(Algorithm::FN_DSA_512, "FN-DSA-512", &random_data); } fn test_algorithm(algorithm: Algorithm, name: &str, random_data: &[u8]) { diff --git a/falcon/Makefile b/falcon/Makefile deleted file mode 100644 index 238f5df..0000000 --- a/falcon/Makefile +++ /dev/null @@ -1,101 +0,0 @@ -# Build script for the Falcon implementation. -# -# ==========================(LICENSE BEGIN)============================ -# -# Copyright (c) 2017-2019 Falcon Project -# -# Permission is hereby granted, free of charge, to any person obtaining -# a copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, -# distribute, sublicense, and/or sell copies of the Software, and to -# permit persons to whom the Software is furnished to do so, subject to -# the following conditions: -# -# The above copyright notice and this permission notice shall be -# included in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -# -# ===========================(LICENSE END)============================= -# -# @author Thomas Pornin - -.POSIX: - -# ===================================================================== -# -# Configurable options: -# CC C compiler; GCC or Clang are fine; MSVC (2015+) works too. -# CFLAGS Compilation flags: -# * Optimization level -O2 or higher is recommended -# See config.h for some possible configuration macros. -# LD Linker; normally the same command as the compiler. -# LDFLAGS Linker options, not counting the extra libs. -# LIBS Extra libraries for linking: -# * If using the native FPU, test_falcon and application -# code that calls this library may need: -lm -# (normally not needed on x86, both 32-bit and 64-bit) - -CC = clang -CFLAGS = -Wall -Wextra -Wshadow -Wundef -O3 #-pg -fno-pie -LD = clang -LDFLAGS = #-pg -no-pie -LIBS = #-lm - -# ===================================================================== - -OBJ = codec.o common.o falcon.o fft.o fpr.o keygen.o rng.o shake.o sign.o vrfy.o - -all: test_falcon speed - -clean: - -rm -f $(OBJ) test_falcon test_falcon.o speed speed.o - -test_falcon: test_falcon.o $(OBJ) - $(LD) $(LDFLAGS) -o test_falcon test_falcon.o $(OBJ) $(LIBS) - -speed: speed.o $(OBJ) - $(LD) $(LDFLAGS) -o speed speed.o $(OBJ) $(LIBS) - -codec.o: codec.c config.h inner.h fpr.h - $(CC) $(CFLAGS) -c -o codec.o codec.c - -common.o: common.c config.h inner.h fpr.h - $(CC) $(CFLAGS) -c -o common.o common.c - -falcon.o: falcon.c falcon.h config.h inner.h fpr.h - $(CC) $(CFLAGS) -c -o falcon.o falcon.c - -fft.o: fft.c config.h inner.h fpr.h - $(CC) $(CFLAGS) -c -o fft.o fft.c - -fpr.o: fpr.c config.h inner.h fpr.h - $(CC) $(CFLAGS) -c -o fpr.o fpr.c - -keygen.o: keygen.c config.h inner.h fpr.h - $(CC) $(CFLAGS) -c -o keygen.o keygen.c - -rng.o: rng.c config.h inner.h fpr.h - $(CC) $(CFLAGS) -c -o rng.o rng.c - -shake.o: shake.c config.h inner.h fpr.h - $(CC) $(CFLAGS) -c -o shake.o shake.c - -sign.o: sign.c config.h inner.h fpr.h - $(CC) $(CFLAGS) -c -o sign.o sign.c - -speed.o: speed.c falcon.h - $(CC) $(CFLAGS) -c -o speed.o speed.c - -test_falcon.o: test_falcon.c falcon.h config.h inner.h fpr.h - $(CC) $(CFLAGS) -c -o test_falcon.o test_falcon.c - -vrfy.o: vrfy.c config.h inner.h fpr.h - $(CC) $(CFLAGS) -c -o vrfy.o vrfy.c diff --git a/falcon/README.txt b/falcon/README.txt deleted file mode 100644 index ae4c651..0000000 --- a/falcon/README.txt +++ /dev/null @@ -1,120 +0,0 @@ -FALCON IMPLEMENTATION -===================== - -Version: 2020-09-30 - -Falcon is a post-quantum signature algorithm, submitted to NIST's -Post-Quantum Cryptography project: - - https://csrc.nist.gov/Projects/Post-Quantum-Cryptography - -Falcon is based on NTRU lattices, used with a hash-and-sign structure -and a Fourier-based sampling method that allows efficient signature -generation and verification, while producing and using relatively -compact signatures and public keys. The official Falcon Web site is: - - https://falcon-sign.info/ - - -This implementation is written in C and is configurable at compile-time -through macros which are documented in config.h; each macro is a boolean -option and can be enabled or disabled in config.h and/or as a -command-line parameter to the compiler. Several implementation strategies -are available; however, in all cases, the same API is implemented. - -Main options are the following: - - - FALCON_FPNATIVE and FALCON_FPEMU - - If using FALCON_FPNATIVE, then the C 'double' type is used for all - floating-point operations. This is the default. This requires the - 'double' type to implement IEEE-754 semantics, in particular - rounding to the exact precision of the 'binary64' type (i.e. "53 - bits"). The Falcon implementation takes special steps to ensure - these properties on most common architectures. When using this - engine, the code _may_ need to call the standard library function - sqrt() (depending on the local architecture), which may in turn - require linking with a specific library (e.g. adding '-lm' to the - link command on Unix-like systems). - - FALCON_FPEMU does not use the C 'double' type, but instead works - over only 64-bit integers and embeds its own emulation of IEEE-754 - operations. This is slower but portable, since it will work on any - machine with a C99-compliant compiler. - - - FALCON_AVX2 and FALCON_FMA - - FALCON_AVX2, when enabled, activates the use of AVX2 compiler - intrinsics. This works only on x86 CPU that offer AVX2 opcodes. - Use of AVX2 improves performance. FALCON_AVX2 has no effect if - FALCON_FPEMU is used. - - FALCON_FMA further enables the use for FMA ("fused multiply-add") - compiler intrinsics for an extra boost to performance. This - setting is ignored unless FALCON_FPNATIVE and FALCON_AVX2 are - both used. Occasionally (but rarely), use of FALCON_FMA will - change the keys and/or signatures generated from a given random - seed, impacting reproducibility of test vectors; however, this - has no bearing on the security of normal usage. - - - FALCON_ASM_CORTEXM4 - - When enabled, inline assembly routines for FP emulation and SHAKE256 - will be used. This will work only on the ARM Cortex M3, M4 and - compatible CPU. This assembly code is constant-time on the M4, and - about twice faster than the generic C code used by FALCON_FPEMU. - - -USAGE ------ - -See the Makefile for compilation flags, and config.h for configurable -options. Type 'make' to compile: this will generate two binaries called -'test_falcon' and 'speed'. 'test_falcon' runs unit tests to verify that -everything computes the expected values. 'speed' runs performance -benchmarks on Falcon-256, Falcon-512 and Falcon-1024 (Falcon-256 is a -reduced version that is faster and smaller than Falcon-512, but provides -only reduced security, and not part of the "official" Falcon). - -Applications that want to use Falcon normally work on the external API, -which is documented in the "falcon.h" file. This is the only file that -an external application needs to use. - -For research purposes, the inner API is documented in "inner.h". This -API gives access to many internal functions that perform some elementary -operations used in Falcon. That API also has some non-obvious -requirements, such as alignment on temporary buffers, or the need to -adjust FPU precision on 32-bit x86 systems. - - -LICENSE -------- - -This code is provided under the MIT license: - -==========================(LICENSE BEGIN)============================ -Copyright (c) 2017-2020 Falcon Project - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -===========================(LICENSE END)============================= - -The code was written by Thomas Pornin , to -whom questions may be addressed. I'll endeavour to respond more or less -promptly. diff --git a/falcon/codec.c b/falcon/codec.c deleted file mode 100644 index bfd8b3c..0000000 --- a/falcon/codec.c +++ /dev/null @@ -1,575 +0,0 @@ -/* - * Encoding/decoding of keys and signatures. - * - * ==========================(LICENSE BEGIN)============================ - * - * Copyright (c) 2017-2019 Falcon Project - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * ===========================(LICENSE END)============================= - * - * @author Thomas Pornin - */ - -#include "inner.h" - -/* see inner.h */ -size_t -Zf(modq_encode)( - void *out, size_t max_out_len, - const uint16_t *x, unsigned logn) -{ - size_t n, out_len, u; - uint8_t *buf; - uint32_t acc; - int acc_len; - - n = (size_t)1 << logn; - for (u = 0; u < n; u ++) { - if (x[u] >= 12289) { - return 0; - } - } - out_len = ((n * 14) + 7) >> 3; - if (out == NULL) { - return out_len; - } - if (out_len > max_out_len) { - return 0; - } - buf = out; - acc = 0; - acc_len = 0; - for (u = 0; u < n; u ++) { - acc = (acc << 14) | x[u]; - acc_len += 14; - while (acc_len >= 8) { - acc_len -= 8; - *buf ++ = (uint8_t)(acc >> acc_len); - } - } - if (acc_len > 0) { - *buf = (uint8_t)(acc << (8 - acc_len)); - } - return out_len; -} - -/* see inner.h */ -size_t -Zf(modq_decode)( - uint16_t *x, unsigned logn, - const void *in, size_t max_in_len) -{ - size_t n, in_len, u; - const uint8_t *buf; - uint32_t acc; - int acc_len; - - n = (size_t)1 << logn; - in_len = ((n * 14) + 7) >> 3; - if (in_len > max_in_len) { - return 0; - } - buf = in; - acc = 0; - acc_len = 0; - u = 0; - while (u < n) { - acc = (acc << 8) | (*buf ++); - acc_len += 8; - if (acc_len >= 14) { - unsigned w; - - acc_len -= 14; - w = (acc >> acc_len) & 0x3FFF; - if (w >= 12289) { - return 0; - } - x[u ++] = (uint16_t)w; - } - } - if ((acc & (((uint32_t)1 << acc_len) - 1)) != 0) { - return 0; - } - return in_len; -} - -/* see inner.h */ -size_t -Zf(trim_i16_encode)( - void *out, size_t max_out_len, - const int16_t *x, unsigned logn, unsigned bits) -{ - size_t n, u, out_len; - int minv, maxv; - uint8_t *buf; - uint32_t acc, mask; - unsigned acc_len; - - n = (size_t)1 << logn; - maxv = (1 << (bits - 1)) - 1; - minv = -maxv; - for (u = 0; u < n; u ++) { - if (x[u] < minv || x[u] > maxv) { - return 0; - } - } - out_len = ((n * bits) + 7) >> 3; - if (out == NULL) { - return out_len; - } - if (out_len > max_out_len) { - return 0; - } - buf = out; - acc = 0; - acc_len = 0; - mask = ((uint32_t)1 << bits) - 1; - for (u = 0; u < n; u ++) { - acc = (acc << bits) | ((uint16_t)x[u] & mask); - acc_len += bits; - while (acc_len >= 8) { - acc_len -= 8; - *buf ++ = (uint8_t)(acc >> acc_len); - } - } - if (acc_len > 0) { - *buf ++ = (uint8_t)(acc << (8 - acc_len)); - } - return out_len; -} - -/* see inner.h */ -size_t -Zf(trim_i16_decode)( - int16_t *x, unsigned logn, unsigned bits, - const void *in, size_t max_in_len) -{ - size_t n, in_len; - const uint8_t *buf; - size_t u; - uint32_t acc, mask1, mask2; - unsigned acc_len; - - n = (size_t)1 << logn; - in_len = ((n * bits) + 7) >> 3; - if (in_len > max_in_len) { - return 0; - } - buf = in; - u = 0; - acc = 0; - acc_len = 0; - mask1 = ((uint32_t)1 << bits) - 1; - mask2 = (uint32_t)1 << (bits - 1); - while (u < n) { - acc = (acc << 8) | *buf ++; - acc_len += 8; - while (acc_len >= bits && u < n) { - uint32_t w; - - acc_len -= bits; - w = (acc >> acc_len) & mask1; - w |= -(w & mask2); - if (w == -mask2) { - /* - * The -2^(bits-1) value is forbidden. - */ - return 0; - } - w |= -(w & mask2); - x[u ++] = (int16_t)*(int32_t *)&w; - } - } - if ((acc & (((uint32_t)1 << acc_len) - 1)) != 0) { - /* - * Extra bits in the last byte must be zero. - */ - return 0; - } - return in_len; -} - -/* see inner.h */ -size_t -Zf(trim_i8_encode)( - void *out, size_t max_out_len, - const int8_t *x, unsigned logn, unsigned bits) -{ - size_t n, u, out_len; - int minv, maxv; - uint8_t *buf; - uint32_t acc, mask; - unsigned acc_len; - - n = (size_t)1 << logn; - maxv = (1 << (bits - 1)) - 1; - minv = -maxv; - for (u = 0; u < n; u ++) { - if (x[u] < minv || x[u] > maxv) { - return 0; - } - } - out_len = ((n * bits) + 7) >> 3; - if (out == NULL) { - return out_len; - } - if (out_len > max_out_len) { - return 0; - } - buf = out; - acc = 0; - acc_len = 0; - mask = ((uint32_t)1 << bits) - 1; - for (u = 0; u < n; u ++) { - acc = (acc << bits) | ((uint8_t)x[u] & mask); - acc_len += bits; - while (acc_len >= 8) { - acc_len -= 8; - *buf ++ = (uint8_t)(acc >> acc_len); - } - } - if (acc_len > 0) { - *buf ++ = (uint8_t)(acc << (8 - acc_len)); - } - return out_len; -} - -/* see inner.h */ -size_t -Zf(trim_i8_decode)( - int8_t *x, unsigned logn, unsigned bits, - const void *in, size_t max_in_len) -{ - size_t n, in_len; - const uint8_t *buf; - size_t u; - uint32_t acc, mask1, mask2; - unsigned acc_len; - - n = (size_t)1 << logn; - in_len = ((n * bits) + 7) >> 3; - if (in_len > max_in_len) { - return 0; - } - buf = in; - u = 0; - acc = 0; - acc_len = 0; - mask1 = ((uint32_t)1 << bits) - 1; - mask2 = (uint32_t)1 << (bits - 1); - while (u < n) { - acc = (acc << 8) | *buf ++; - acc_len += 8; - while (acc_len >= bits && u < n) { - uint32_t w; - - acc_len -= bits; - w = (acc >> acc_len) & mask1; - w |= -(w & mask2); - if (w == -mask2) { - /* - * The -2^(bits-1) value is forbidden. - */ - return 0; - } - x[u ++] = (int8_t)*(int32_t *)&w; - } - } - if ((acc & (((uint32_t)1 << acc_len) - 1)) != 0) { - /* - * Extra bits in the last byte must be zero. - */ - return 0; - } - return in_len; -} - -/* see inner.h */ -size_t -Zf(comp_encode)( - void *out, size_t max_out_len, - const int16_t *x, unsigned logn) -{ - uint8_t *buf; - size_t n, u, v; - uint32_t acc; - unsigned acc_len; - - n = (size_t)1 << logn; - buf = out; - - /* - * Make sure that all values are within the -2047..+2047 range. - */ - for (u = 0; u < n; u ++) { - if (x[u] < -2047 || x[u] > +2047) { - return 0; - } - } - - acc = 0; - acc_len = 0; - v = 0; - for (u = 0; u < n; u ++) { - int t; - unsigned w; - - /* - * Get sign and absolute value of next integer; push the - * sign bit. - */ - acc <<= 1; - t = x[u]; - if (t < 0) { - t = -t; - acc |= 1; - } - w = (unsigned)t; - - /* - * Push the low 7 bits of the absolute value. - */ - acc <<= 7; - acc |= w & 127u; - w >>= 7; - - /* - * We pushed exactly 8 bits. - */ - acc_len += 8; - - /* - * Push as many zeros as necessary, then a one. Since the - * absolute value is at most 2047, w can only range up to - * 15 at this point, thus we will add at most 16 bits - * here. With the 8 bits above and possibly up to 7 bits - * from previous iterations, we may go up to 31 bits, which - * will fit in the accumulator, which is an uint32_t. - */ - acc <<= (w + 1); - acc |= 1; - acc_len += w + 1; - - /* - * Produce all full bytes. - */ - while (acc_len >= 8) { - acc_len -= 8; - if (buf != NULL) { - if (v >= max_out_len) { - return 0; - } - buf[v] = (uint8_t)(acc >> acc_len); - } - v ++; - } - } - - /* - * Flush remaining bits (if any). - */ - if (acc_len > 0) { - if (buf != NULL) { - if (v >= max_out_len) { - return 0; - } - buf[v] = (uint8_t)(acc << (8 - acc_len)); - } - v ++; - } - - return v; -} - -/* see inner.h */ -size_t -Zf(comp_decode)( - int16_t *x, unsigned logn, - const void *in, size_t max_in_len) -{ - const uint8_t *buf; - size_t n, u, v; - uint32_t acc; - unsigned acc_len; - - n = (size_t)1 << logn; - buf = in; - acc = 0; - acc_len = 0; - v = 0; - for (u = 0; u < n; u ++) { - unsigned b, s, m; - - /* - * Get next eight bits: sign and low seven bits of the - * absolute value. - */ - if (v >= max_in_len) { - return 0; - } - acc = (acc << 8) | (uint32_t)buf[v ++]; - b = acc >> acc_len; - s = b & 128; - m = b & 127; - - /* - * Get next bits until a 1 is reached. - */ - for (;;) { - if (acc_len == 0) { - if (v >= max_in_len) { - return 0; - } - acc = (acc << 8) | (uint32_t)buf[v ++]; - acc_len = 8; - } - acc_len --; - if (((acc >> acc_len) & 1) != 0) { - break; - } - m += 128; - if (m > 2047) { - return 0; - } - } - - /* - * "-0" is forbidden. - */ - if (s && m == 0) { - return 0; - } - - x[u] = (int16_t)(s ? -(int)m : (int)m); - } - - /* - * Unused bits in the last byte must be zero. - */ - if ((acc & ((1u << acc_len) - 1u)) != 0) { - return 0; - } - - return v; -} - -/* - * Key elements and signatures are polynomials with small integer - * coefficients. Here are some statistics gathered over many - * generated key pairs (10000 or more for each degree): - * - * log(n) n max(f,g) std(f,g) max(F,G) std(F,G) - * 1 2 129 56.31 143 60.02 - * 2 4 123 40.93 160 46.52 - * 3 8 97 28.97 159 38.01 - * 4 16 100 21.48 154 32.50 - * 5 32 71 15.41 151 29.36 - * 6 64 59 11.07 138 27.77 - * 7 128 39 7.91 144 27.00 - * 8 256 32 5.63 148 26.61 - * 9 512 22 4.00 137 26.46 - * 10 1024 15 2.84 146 26.41 - * - * We want a compact storage format for private key, and, as part of - * key generation, we are allowed to reject some keys which would - * otherwise be fine (this does not induce any noticeable vulnerability - * as long as we reject only a small proportion of possible keys). - * Hence, we enforce at key generation time maximum values for the - * elements of f, g, F and G, so that their encoding can be expressed - * in fixed-width values. Limits have been chosen so that generated - * keys are almost always within bounds, thus not impacting neither - * security or performance. - * - * IMPORTANT: the code assumes that all coefficients of f, g, F and G - * ultimately fit in the -127..+127 range. Thus, none of the elements - * of max_fg_bits[] and max_FG_bits[] shall be greater than 8. - */ - -const uint8_t Zf(max_fg_bits)[] = { - 0, /* unused */ - 8, - 8, - 8, - 8, - 8, - 7, - 7, - 6, - 6, - 5 -}; - -const uint8_t Zf(max_FG_bits)[] = { - 0, /* unused */ - 8, - 8, - 8, - 8, - 8, - 8, - 8, - 8, - 8, - 8 -}; - -/* - * When generating a new key pair, we can always reject keys which - * feature an abnormally large coefficient. This can also be done for - * signatures, albeit with some care: in case the signature process is - * used in a derandomized setup (explicitly seeded with the message and - * private key), we have to follow the specification faithfully, and the - * specification only enforces a limit on the L2 norm of the signature - * vector. The limit on the L2 norm implies that the absolute value of - * a coefficient of the signature cannot be more than the following: - * - * log(n) n max sig coeff (theoretical) - * 1 2 412 - * 2 4 583 - * 3 8 824 - * 4 16 1166 - * 5 32 1649 - * 6 64 2332 - * 7 128 3299 - * 8 256 4665 - * 9 512 6598 - * 10 1024 9331 - * - * However, the largest observed signature coefficients during our - * experiments was 1077 (in absolute value), hence we can assume that, - * with overwhelming probability, signature coefficients will fit - * in -2047..2047, i.e. 12 bits. - */ - -const uint8_t Zf(max_sig_bits)[] = { - 0, /* unused */ - 10, - 11, - 11, - 12, - 12, - 12, - 12, - 12, - 12, - 12 -}; diff --git a/falcon/common.c b/falcon/common.c deleted file mode 100644 index d0c1a40..0000000 --- a/falcon/common.c +++ /dev/null @@ -1,306 +0,0 @@ -/* - * Support functions for signatures (hash-to-point, norm). - * - * ==========================(LICENSE BEGIN)============================ - * - * Copyright (c) 2017-2019 Falcon Project - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * ===========================(LICENSE END)============================= - * - * @author Thomas Pornin - */ - -#include "inner.h" - -/* see inner.h */ -void -Zf(hash_to_point_vartime)( - inner_shake256_context *sc, - uint16_t *x, unsigned logn) -{ - /* - * This is the straightforward per-the-spec implementation. It - * is not constant-time, thus it might reveal information on the - * plaintext (at least, enough to check the plaintext against a - * list of potential plaintexts) in a scenario where the - * attacker does not have access to the signature value or to - * the public key, but knows the nonce (without knowledge of the - * nonce, the hashed output cannot be matched against potential - * plaintexts). - */ - size_t n; - - n = (size_t)1 << logn; - while (n > 0) { - uint8_t buf[2]; - uint32_t w; - - inner_shake256_extract(sc, (void *)buf, sizeof buf); - w = ((unsigned)buf[0] << 8) | (unsigned)buf[1]; - if (w < 61445) { - while (w >= 12289) { - w -= 12289; - } - *x ++ = (uint16_t)w; - n --; - } - } -} - -/* see inner.h */ -void -Zf(hash_to_point_ct)( - inner_shake256_context *sc, - uint16_t *x, unsigned logn, uint8_t *tmp) -{ - /* - * Each 16-bit sample is a value in 0..65535. The value is - * kept if it falls in 0..61444 (because 61445 = 5*12289) - * and rejected otherwise; thus, each sample has probability - * about 0.93758 of being selected. - * - * We want to oversample enough to be sure that we will - * have enough values with probability at least 1 - 2^(-256). - * Depending on degree N, this leads to the following - * required oversampling: - * - * logn n oversampling - * 1 2 65 - * 2 4 67 - * 3 8 71 - * 4 16 77 - * 5 32 86 - * 6 64 100 - * 7 128 122 - * 8 256 154 - * 9 512 205 - * 10 1024 287 - * - * If logn >= 7, then the provided temporary buffer is large - * enough. Otherwise, we use a stack buffer of 63 entries - * (i.e. 126 bytes) for the values that do not fit in tmp[]. - */ - - static const uint16_t overtab[] = { - 0, /* unused */ - 65, - 67, - 71, - 77, - 86, - 100, - 122, - 154, - 205, - 287 - }; - - unsigned n, n2, u, m, p, over; - uint16_t *tt1, tt2[63]; - - /* - * We first generate m 16-bit value. Values 0..n-1 go to x[]. - * Values n..2*n-1 go to tt1[]. Values 2*n and later go to tt2[]. - * We also reduce modulo q the values; rejected values are set - * to 0xFFFF. - */ - n = 1U << logn; - n2 = n << 1; - over = overtab[logn]; - m = n + over; - tt1 = (uint16_t *)tmp; - for (u = 0; u < m; u ++) { - uint8_t buf[2]; - uint32_t w, wr; - - inner_shake256_extract(sc, buf, sizeof buf); - w = ((uint32_t)buf[0] << 8) | (uint32_t)buf[1]; - wr = w - ((uint32_t)24578 & (((w - 24578) >> 31) - 1)); - wr = wr - ((uint32_t)24578 & (((wr - 24578) >> 31) - 1)); - wr = wr - ((uint32_t)12289 & (((wr - 12289) >> 31) - 1)); - wr |= ((w - 61445) >> 31) - 1; - if (u < n) { - x[u] = (uint16_t)wr; - } else if (u < n2) { - tt1[u - n] = (uint16_t)wr; - } else { - tt2[u - n2] = (uint16_t)wr; - } - } - - /* - * Now we must "squeeze out" the invalid values. We do this in - * a logarithmic sequence of passes; each pass computes where a - * value should go, and moves it down by 'p' slots if necessary, - * where 'p' uses an increasing powers-of-two scale. It can be - * shown that in all cases where the loop decides that a value - * has to be moved down by p slots, the destination slot is - * "free" (i.e. contains an invalid value). - */ - for (p = 1; p <= over; p <<= 1) { - unsigned v; - - /* - * In the loop below: - * - * - v contains the index of the final destination of - * the value; it is recomputed dynamically based on - * whether values are valid or not. - * - * - u is the index of the value we consider ("source"); - * its address is s. - * - * - The loop may swap the value with the one at index - * u-p. The address of the swap destination is d. - */ - v = 0; - for (u = 0; u < m; u ++) { - uint16_t *s, *d; - unsigned j, sv, dv, mk; - - if (u < n) { - s = &x[u]; - } else if (u < n2) { - s = &tt1[u - n]; - } else { - s = &tt2[u - n2]; - } - sv = *s; - - /* - * The value in sv should ultimately go to - * address v, i.e. jump back by u-v slots. - */ - j = u - v; - - /* - * We increment v for the next iteration, but - * only if the source value is valid. The mask - * 'mk' is -1 if the value is valid, 0 otherwise, - * so we _subtract_ mk. - */ - mk = (sv >> 15) - 1U; - v -= mk; - - /* - * In this loop we consider jumps by p slots; if - * u < p then there is nothing more to do. - */ - if (u < p) { - continue; - } - - /* - * Destination for the swap: value at address u-p. - */ - if ((u - p) < n) { - d = &x[u - p]; - } else if ((u - p) < n2) { - d = &tt1[(u - p) - n]; - } else { - d = &tt2[(u - p) - n2]; - } - dv = *d; - - /* - * The swap should be performed only if the source - * is valid AND the jump j has its 'p' bit set. - */ - mk &= -(((j & p) + 0x1FF) >> 9); - - *s = (uint16_t)(sv ^ (mk & (sv ^ dv))); - *d = (uint16_t)(dv ^ (mk & (sv ^ dv))); - } - } -} - -/* - * Acceptance bound for the (squared) l2-norm of the signature depends - * on the degree. This array is indexed by logn (1 to 10). These bounds - * are _inclusive_ (they are equal to floor(beta^2)). - */ -static const uint32_t l2bound[] = { - 0, /* unused */ - 101498, - 208714, - 428865, - 892039, - 1852696, - 3842630, - 7959734, - 16468416, - 34034726, - 70265242 -}; - -/* see inner.h */ -int -Zf(is_short)( - const int16_t *s1, const int16_t *s2, unsigned logn) -{ - /* - * We use the l2-norm. Code below uses only 32-bit operations to - * compute the square of the norm with saturation to 2^32-1 if - * the value exceeds 2^31-1. - */ - size_t n, u; - uint32_t s, ng; - - n = (size_t)1 << logn; - s = 0; - ng = 0; - for (u = 0; u < n; u ++) { - int32_t z; - - z = s1[u]; - s += (uint32_t)(z * z); - ng |= s; - z = s2[u]; - s += (uint32_t)(z * z); - ng |= s; - } - s |= -(ng >> 31); - - return s <= l2bound[logn]; -} - -/* see inner.h */ -int -Zf(is_short_half)( - uint32_t sqn, const int16_t *s2, unsigned logn) -{ - size_t n, u; - uint32_t ng; - - n = (size_t)1 << logn; - ng = -(sqn >> 31); - for (u = 0; u < n; u ++) { - int32_t z; - - z = s2[u]; - sqn += (uint32_t)(z * z); - ng |= sqn; - } - sqn |= -(ng >> 31); - - return sqn <= l2bound[logn]; -} diff --git a/falcon/config.h b/falcon/config.h deleted file mode 100644 index 8fc0eb2..0000000 --- a/falcon/config.h +++ /dev/null @@ -1,203 +0,0 @@ -/* - * Manual configuration file for the Falcon implementation. Here can - * be set some compilation-time options. - * - * ==========================(LICENSE BEGIN)============================ - * - * Copyright (c) 2017-2019 Falcon Project - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * ===========================(LICENSE END)============================= - * - * @author Thomas Pornin - */ - -#ifndef FALCON_CONFIG_H__ -#define FALCON_CONFIG_H__ - -/* - * Each option is a macro which should be defined to either 1 or 0. - * If any of the options below is left undefined, then a default value - * will be used by the code, possibly using compile-time autodetection - * from compiler-defined macros. - * - * Explicitly setting a parameter can be done by uncommenting/modifying - * its definition below, in this file, or equivalently by setting it as - * a compiler flag. - */ - -/* - * Use the native 'double' C type for floating-point computations. Exact - * reproducibility of all tests requires that type to faithfully follow - * IEEE-754 "round-to-nearest" rules. - * - * Native double support will use the CPU hardware and/or - * compiler-provided functions; the latter is typically NOT - * constant-time, while the former MAY be constant-time, or not. On - * recent x86 CPU in 64-bit mode, SSE2 opcodes are used and they provide - * constant-time operations for all the operations used in Falcon, - * except for some special cases of divisions and square roots, but it - * can be shown that theses cases imply only negligible leak of - * information that cannot be leveraged into a full attack. - * - * If neither FALCON_FPNATIVE nor FALCON_FPEMU is defined, then use of - * the native 'double' C type is the default behaviour unless - * FALCON_ASM_CORTEXM4 is defined to 1, in which case the emulated code - * will be used. - * -#define FALCON_FPNATIVE 1 - */ - -/* - * Use emulated floating-point implementation. - * - * Emulation uses only integer operations with uint32_t and uint64_t - * types. This is constant-time, provided that the underlying platform - * offers constant-time opcodes for the following operations: - * - * - Multiplication of two 32-bit unsigned integers into a 64-bit result. - * - Left-shift or right-shift of a 32-bit unsigned integer by a - * potentially secret shift count in the 0..31 range. - * - * Notably, the ARM Cortex M3 does not fulfill the first condition, - * while the Pentium IV does not fulfill the second. - * - * If neither FALCON_FPNATIVE nor FALCON_FPEMU is defined, then use of - * the native 'double' C type is the default behaviour unless - * FALCON_ASM_CORTEXM4 is defined to 1, in which case the emulated code - * will be used. - * -#define FALCON_FPEMU 1 - */ - -/* - * Enable use of assembly for ARM Cortex-M4 CPU. By default, such - * support will be used based on some autodection on the compiler - * version and target architecture. Define this variable to 1 to force - * use of the assembly code, or 0 to disable it regardless of the - * autodetection. - * - * When FALCON_ASM_CORTEXM4 is enabled (whether defined explicitly or - * autodetected), emulated floating-point code will be used, unless - * FALCON_FPNATIVE or FALCON_FPEMU is explicitly set to override the - * choice. Emulated code with ARM assembly is constant-time and provides - * better performance than emulated code with plain C. - * - * The assembly code for the M4 can also work on a Cortex-M3. If the - * compiler is instructed to target the M3 (e.g. '-mcpu=cortex-m3' with - * GCC) then FALCON_ASM_CORTEXM4 won't be autodetected, but it can be - * enabled explicitly. Take care, though, that the M3 multiplication - * opcode (multiplication of two 32-bit unsigned integers with a 64-bit - * result) is NOT constant-time. - * -#define FALCON_ASM_CORTEXM4 1 - */ - -/* - * Enable use of AVX2 intrinsics. If enabled, then the code will compile - * only when targeting x86 with a compiler that supports AVX2 intrinsics - * (tested with GCC 7.4.0, Clang 6.0.0, and MSVC 2015, both in 32-bit - * and 64-bit modes), and run only on systems that offer the AVX2 - * opcodes. Some operations leverage AVX2 for better performance. - * -#define FALCON_AVX2 1 - */ - -/* - * Enable use of FMA intrinsics. This setting has any effect only if - * FALCON_AVX2 is also enabled. The FMA intrinsics are normally available - * on any x86 CPU that also has AVX2. Note that setting this option will - * slightly modify the values of expanded private keys, but will normally - * not change the values of non-expanded private keys, public keys or - * signatures, for a given keygen/sign seed (non-expanded private keys - * and signatures might theoretically change, but only with low probability, - * less than 2^(-40); produced signatures are still safe and interoperable). - * -#define FALCON_FMA 1 - */ - -/* - * Assert that the platform uses little-endian encoding. If enabled, - * then encoding and decoding of aligned multibyte values will be - * slightly faster (especially for hashing and random number - * generation). If not defined explicitly, then autodetection is - * applied. - * -#define FALCON_LE 1 - */ - -/* - * Assert that the platform tolerates accesses to unaligned multibyte - * values. If enabled, then some operations are slightly faster. Note - * that ARM Cortex M4 do _not_ fully tolerate unaligned accesses; for - * such systems, this option should not be enabled. If not defined - * explicitly, then autodetection is applied. - * -#define FALCON_UNALIGNED 1 - */ - -/* - * Use a PRNG based on ChaCha20 and seeded with SHAKE256, instead of - * SHAKE256 directly, for key pair generation purposes. This speeds up - * key pair generation, especially on platforms where SHAKE256 is - * comparatively slow: on the ARM Cortex M4, average key generation time - * is reduced by 19% with this setting; on a recent x86 Skylake, the - * reduction is smaller (less than 8%). - * - * However, this setting changes the private/public key pair obtained - * from a given seed, thus preventing reproducibility of the - * known-answer tests vectors. For compatibility with existing KAT - * vectors (e.g. in PQClean, pqm4 and NIST implementations), this - * setting is not enabled by default. - * -#define FALCON_KG_CHACHA20 1 - */ - -/* - * Use an explicit OS-provided source of randomness for seeding (for the - * Zf(get_seed)() function implementation). Three possible sources are - * defined: - * - * - getentropy() system call - * - /dev/urandom special file - * - CryptGenRandom() function call - * - * More than one source may be enabled, in which case they will be tried - * in the order above, until a success is reached. - * - * By default, sources are enabled at compile-time based on these - * conditions: - * - * - getentropy(): target is one of: Linux with Glibc-2.25+, FreeBSD 12+, - * or OpenBSD. - * - /dev/urandom: target is a Unix-like system (including Linux, - * FreeBSD, NetBSD, OpenBSD, DragonFly, macOS, Android, Solaris, AIX). - * - CryptGenRandom(): target is Windows (Win32 or Win64). - * - * On most small embedded systems, none will be enabled and Zf(get_seed)() - * will always return 0. Applications will need to provide their own seeds. - * -#define FALCON_RAND_GETENTROPY 1 -#define FALCON_RAND_URANDOM 1 -#define FALCON_RAND_WIN32 1 - */ - -#endif diff --git a/falcon/falcon.c b/falcon/falcon.c deleted file mode 100644 index 4c38130..0000000 --- a/falcon/falcon.c +++ /dev/null @@ -1,936 +0,0 @@ -/* - * Implementation of the external Falcon API. - * - * ==========================(LICENSE BEGIN)============================ - * - * Copyright (c) 2017-2019 Falcon Project - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * ===========================(LICENSE END)============================= - * - * @author Thomas Pornin - */ - -#include "falcon.h" -#include "inner.h" - -/* see falcon.h */ -void -shake256_init(shake256_context *sc) -{ - inner_shake256_init((inner_shake256_context *)sc); -} - -/* see falcon.h */ -void -shake256_inject(shake256_context *sc, const void *data, size_t len) -{ - inner_shake256_inject((inner_shake256_context *)sc, data, len); -} - -/* see falcon.h */ -void -shake256_flip(shake256_context *sc) -{ - inner_shake256_flip((inner_shake256_context *)sc); -} - -/* see falcon.h */ -void -shake256_extract(shake256_context *sc, void *out, size_t len) -{ - inner_shake256_extract((inner_shake256_context *)sc, out, len); -} - -/* see falcon.h */ -void -shake256_init_prng_from_seed(shake256_context *sc, - const void *seed, size_t seed_len) -{ - shake256_init(sc); - shake256_inject(sc, seed, seed_len); - shake256_flip(sc); -} - -/* see falcon.h */ -int -shake256_init_prng_from_system(shake256_context *sc) -{ - uint8_t seed[48]; - - if (!Zf(get_seed)(seed, sizeof seed)) { - return FALCON_ERR_RANDOM; - } - shake256_init(sc); - shake256_inject(sc, seed, sizeof seed); - shake256_flip(sc); - return 0; -} - -static inline uint8_t * -align_u64(void *tmp) -{ - uint8_t *atmp; - unsigned off; - - atmp = tmp; - off = (uintptr_t)atmp & 7u; - if (off != 0) { - atmp += 8u - off; - } - return atmp; -} - -static inline uint8_t * -align_u16(void *tmp) -{ - uint8_t *atmp; - - atmp = tmp; - if (((uintptr_t)atmp & 1u) != 0) { - atmp ++; - } - return atmp; -} - -static inline fpr * -align_fpr(void *tmp) -{ - uint8_t *atmp; - unsigned off; - - atmp = tmp; - off = (uintptr_t)atmp & 7u; - if (off != 0) { - atmp += 8u - off; - } - return (fpr *)atmp; -} - -/* see falcon.h */ -int -falcon_keygen_make( - shake256_context *rng, - unsigned logn, - void *privkey, size_t privkey_len, - void *pubkey, size_t pubkey_len, - void *tmp, size_t tmp_len) -{ - int8_t *f, *g, *F; - uint16_t *h; - uint8_t *atmp; - size_t n, u, v, sk_len, pk_len; - uint8_t *sk, *pk; - unsigned oldcw; - - /* - * Check parameters. - */ - if (logn < 1 || logn > 10) { - return FALCON_ERR_BADARG; - } - if (privkey_len < FALCON_PRIVKEY_SIZE(logn) - || (pubkey != NULL && pubkey_len < FALCON_PUBKEY_SIZE(logn)) - || tmp_len < FALCON_TMPSIZE_KEYGEN(logn)) - { - return FALCON_ERR_SIZE; - } - - /* - * Prepare buffers and generate private key. - */ - n = (size_t)1 << logn; - f = tmp; - g = f + n; - F = g + n; - atmp = align_u64(F + n); - oldcw = set_fpu_cw(2); - Zf(keygen)((inner_shake256_context *)rng, - f, g, F, NULL, NULL, logn, atmp); - set_fpu_cw(oldcw); - - /* - * Encode private key. - */ - sk = privkey; - sk_len = FALCON_PRIVKEY_SIZE(logn); - sk[0] = 0x50 + logn; - u = 1; - v = Zf(trim_i8_encode)(sk + u, sk_len - u, - f, logn, Zf(max_fg_bits)[logn]); - if (v == 0) { - return FALCON_ERR_INTERNAL; - } - u += v; - v = Zf(trim_i8_encode)(sk + u, sk_len - u, - g, logn, Zf(max_fg_bits)[logn]); - if (v == 0) { - return FALCON_ERR_INTERNAL; - } - u += v; - v = Zf(trim_i8_encode)(sk + u, sk_len - u, - F, logn, Zf(max_FG_bits)[logn]); - if (v == 0) { - return FALCON_ERR_INTERNAL; - } - u += v; - if (u != sk_len) { - return FALCON_ERR_INTERNAL; - } - - /* - * Recompute public key and encode it. - */ - if (pubkey != NULL) { - h = (uint16_t *)align_u16(g + n); - atmp = (uint8_t *)(h + n); - if (!Zf(compute_public)(h, f, g, logn, atmp)) { - return FALCON_ERR_INTERNAL; - } - pk = pubkey; - pk_len = FALCON_PUBKEY_SIZE(logn); - pk[0] = 0x00 + logn; - v = Zf(modq_encode)(pk + 1, pk_len - 1, h, logn); - if (v != pk_len - 1) { - return FALCON_ERR_INTERNAL; - } - } - - return 0; -} - -/* see falcon.h */ -int -falcon_make_public( - void *pubkey, size_t pubkey_len, - const void *privkey, size_t privkey_len, - void *tmp, size_t tmp_len) -{ - uint8_t *pk, *atmp; - const uint8_t *sk; - unsigned logn; - size_t u, v, n, pk_len; - int8_t *f, *g; - uint16_t *h; - - /* - * Get degree from private key header byte, and check - * parameters. - */ - if (privkey_len == 0) { - return FALCON_ERR_FORMAT; - } - sk = privkey; - if ((sk[0] & 0xF0) != 0x50) { - return FALCON_ERR_FORMAT; - } - logn = sk[0] & 0x0F; - if (logn < 1 || logn > 10) { - return FALCON_ERR_FORMAT; - } - if (privkey_len != FALCON_PRIVKEY_SIZE(logn)) { - return FALCON_ERR_FORMAT; - } - if (pubkey_len < FALCON_PUBKEY_SIZE(logn) - || tmp_len < FALCON_TMPSIZE_MAKEPUB(logn)) - { - return FALCON_ERR_SIZE; - } - - /* - * Decode private key (f and g). - */ - n = (size_t)1 << logn; - f = (int8_t *)tmp; - g = f + n; - u = 1; - v = Zf(trim_i8_decode)(f, logn, Zf(max_fg_bits)[logn], - sk + u, privkey_len - u); - if (v == 0) { - return FALCON_ERR_FORMAT; - } - u += v; - v = Zf(trim_i8_decode)(g, logn, Zf(max_fg_bits)[logn], - sk + u, privkey_len - u); - if (v == 0) { - return FALCON_ERR_FORMAT; - } - - /* - * Compute public key. - */ - h = (uint16_t *)align_u16(g + n); - atmp = (uint8_t *)(h + n); - if (!Zf(compute_public)(h, f, g, logn, atmp)) { - return FALCON_ERR_FORMAT; - } - - /* - * Encode public key. - */ - pk = pubkey; - pk_len = FALCON_PUBKEY_SIZE(logn); - pk[0] = 0x00 + logn; - v = Zf(modq_encode)(pk + 1, pk_len - 1, h, logn); - if (v != pk_len - 1) { - return FALCON_ERR_INTERNAL; - } - return 0; -} - -/* see falcon.h */ -int -falcon_get_logn(void *obj, size_t len) -{ - int logn; - - if (len == 0) { - return FALCON_ERR_FORMAT; - } - logn = *(uint8_t *)obj & 0x0F; - if (logn < 1 || logn > 10) { - return FALCON_ERR_FORMAT; - } - return logn; -} - -/* see falcon.h */ -int -falcon_sign_start(shake256_context *rng, - void *nonce, - shake256_context *hash_data) -{ - shake256_extract(rng, nonce, 40); - shake256_init(hash_data); - shake256_inject(hash_data, nonce, 40); - return 0; -} - -/* see falcon.h */ -int -falcon_sign_dyn_finish(shake256_context *rng, - void *sig, size_t *sig_len, int sig_type, - const void *privkey, size_t privkey_len, - shake256_context *hash_data, const void *nonce, - void *tmp, size_t tmp_len) -{ - unsigned logn; - const uint8_t *sk; - uint8_t *es; - int8_t *f, *g, *F, *G; - uint16_t *hm; - int16_t *sv; - uint8_t *atmp; - size_t u, v, n, es_len; - unsigned oldcw; - inner_shake256_context sav_hash_data; - - /* - * Get degree from private key header byte, and check - * parameters. - */ - if (privkey_len == 0) { - return FALCON_ERR_FORMAT; - } - sk = privkey; - if ((sk[0] & 0xF0) != 0x50) { - return FALCON_ERR_FORMAT; - } - logn = sk[0] & 0x0F; - if (logn < 1 || logn > 10) { - return FALCON_ERR_FORMAT; - } - if (privkey_len != FALCON_PRIVKEY_SIZE(logn)) { - return FALCON_ERR_FORMAT; - } - if (tmp_len < FALCON_TMPSIZE_SIGNDYN(logn)) { - return FALCON_ERR_SIZE; - } - es_len = *sig_len; - if (es_len < 41) { - return FALCON_ERR_SIZE; - } - switch (sig_type) { - case FALCON_SIG_COMPRESSED: - break; - case FALCON_SIG_PADDED: - if (*sig_len < FALCON_SIG_PADDED_SIZE(logn)) { - return FALCON_ERR_SIZE; - } - break; - case FALCON_SIG_CT: - if (*sig_len < FALCON_SIG_CT_SIZE(logn)) { - return FALCON_ERR_SIZE; - } - break; - default: - return FALCON_ERR_BADARG; - } - - /* - * Decode private key elements, and complete private key. - */ - n = (size_t)1 << logn; - f = (int8_t *)tmp; - g = f + n; - F = g + n; - G = F + n; - hm = (uint16_t *)(G + n); - sv = (int16_t *)hm; - atmp = align_u64(hm + n); - u = 1; - v = Zf(trim_i8_decode)(f, logn, Zf(max_fg_bits)[logn], - sk + u, privkey_len - u); - if (v == 0) { - return FALCON_ERR_FORMAT; - } - u += v; - v = Zf(trim_i8_decode)(g, logn, Zf(max_fg_bits)[logn], - sk + u, privkey_len - u); - if (v == 0) { - return FALCON_ERR_FORMAT; - } - u += v; - v = Zf(trim_i8_decode)(F, logn, Zf(max_FG_bits)[logn], - sk + u, privkey_len - u); - if (v == 0) { - return FALCON_ERR_FORMAT; - } - u += v; - if (u != privkey_len) { - return FALCON_ERR_FORMAT; - } - if (!Zf(complete_private)(G, f, g, F, logn, atmp)) { - return FALCON_ERR_FORMAT; - } - - /* - * Hash message to a point. - */ - shake256_flip(hash_data); - sav_hash_data = *(inner_shake256_context *)hash_data; - - /* - * Compute and encode signature. - */ - for (;;) { - /* - * Hash message to a point. We must redo it when looping - * (in case of a padded signature format and a failed - * attempt due to an oversized compressed signature), because - * we overwrite the hash output with the signature (in order - * to save some RAM). - */ - *(inner_shake256_context *)hash_data = sav_hash_data; - if (sig_type == FALCON_SIG_CT) { - Zf(hash_to_point_ct)( - (inner_shake256_context *)hash_data, - hm, logn, atmp); - } else { - Zf(hash_to_point_vartime)( - (inner_shake256_context *)hash_data, - hm, logn); - } - oldcw = set_fpu_cw(2); - Zf(sign_dyn)(sv, (inner_shake256_context *)rng, - f, g, F, G, hm, logn, atmp); - set_fpu_cw(oldcw); - es = sig; - es_len = *sig_len; - memcpy(es + 1, nonce, 40); - u = 41; - switch (sig_type) { - size_t tu; - - case FALCON_SIG_COMPRESSED: - es[0] = 0x30 + logn; - v = Zf(comp_encode)(es + u, es_len - u, sv, logn); - if (v == 0) { - return FALCON_ERR_SIZE; - } - break; - case FALCON_SIG_PADDED: - es[0] = 0x30 + logn; - tu = FALCON_SIG_PADDED_SIZE(logn); - v = Zf(comp_encode)(es + u, tu - u, sv, logn); - if (v == 0) { - /* - * Signature does not fit, loop. - */ - continue; - } - if (u + v < tu) { - memset(es + u + v, 0, tu - (u + v)); - v = tu - u; - } - break; - case FALCON_SIG_CT: - es[0] = 0x50 + logn; - v = Zf(trim_i16_encode)(es + u, es_len - u, - sv, logn, Zf(max_sig_bits)[logn]); - if (v == 0) { - return FALCON_ERR_SIZE; - } - break; - } - *sig_len = u + v; - return 0; - } -} - -/* see falcon.h */ -int -falcon_expand_privkey(void *expanded_key, size_t expanded_key_len, - const void *privkey, size_t privkey_len, - void *tmp, size_t tmp_len) -{ - unsigned logn; - const uint8_t *sk; - int8_t *f, *g, *F, *G; - uint8_t *atmp; - size_t u, v, n; - fpr *expkey; - unsigned oldcw; - - /* - * Get degree from private key header byte, and check - * parameters. - */ - if (privkey_len == 0) { - return FALCON_ERR_FORMAT; - } - sk = privkey; - if ((sk[0] & 0xF0) != 0x50) { - return FALCON_ERR_FORMAT; - } - logn = sk[0] & 0x0F; - if (logn < 1 || logn > 10) { - return FALCON_ERR_FORMAT; - } - if (privkey_len != FALCON_PRIVKEY_SIZE(logn)) { - return FALCON_ERR_FORMAT; - } - if (expanded_key_len < FALCON_EXPANDEDKEY_SIZE(logn) - || tmp_len < FALCON_TMPSIZE_EXPANDPRIV(logn)) - { - return FALCON_ERR_SIZE; - } - - /* - * Decode private key elements, and complete private key. - */ - n = (size_t)1 << logn; - f = (int8_t *)tmp; - g = f + n; - F = g + n; - G = F + n; - atmp = align_u64(G + n); - u = 1; - v = Zf(trim_i8_decode)(f, logn, Zf(max_fg_bits)[logn], - sk + u, privkey_len - u); - if (v == 0) { - return FALCON_ERR_FORMAT; - } - u += v; - v = Zf(trim_i8_decode)(g, logn, Zf(max_fg_bits)[logn], - sk + u, privkey_len - u); - if (v == 0) { - return FALCON_ERR_FORMAT; - } - u += v; - v = Zf(trim_i8_decode)(F, logn, Zf(max_FG_bits)[logn], - sk + u, privkey_len - u); - if (v == 0) { - return FALCON_ERR_FORMAT; - } - u += v; - if (u != privkey_len) { - return FALCON_ERR_FORMAT; - } - if (!Zf(complete_private)(G, f, g, F, logn, atmp)) { - return FALCON_ERR_FORMAT; - } - - /* - * Expand private key. - */ - *(uint8_t *)expanded_key = logn; - expkey = align_fpr((uint8_t *)expanded_key + 1); - oldcw = set_fpu_cw(2); - Zf(expand_privkey)(expkey, f, g, F, G, logn, atmp); - set_fpu_cw(oldcw); - return 0; -} - -/* see falcon.h */ -int -falcon_sign_tree_finish(shake256_context *rng, - void *sig, size_t *sig_len, int sig_type, - const void *expanded_key, - shake256_context *hash_data, const void *nonce, - void *tmp, size_t tmp_len) -{ - unsigned logn; - uint8_t *es; - const fpr *expkey; - uint16_t *hm; - int16_t *sv; - uint8_t *atmp; - size_t u, v, n, es_len; - unsigned oldcw; - inner_shake256_context sav_hash_data; - - /* - * Get degree from private key header byte, and check - * parameters. - */ - logn = *(const uint8_t *)expanded_key; - if (logn < 1 || logn > 10) { - return FALCON_ERR_FORMAT; - } - if (tmp_len < FALCON_TMPSIZE_SIGNTREE(logn)) { - return FALCON_ERR_SIZE; - } - es_len = *sig_len; - if (es_len < 41) { - return FALCON_ERR_SIZE; - } - expkey = (const fpr *)align_fpr((uint8_t *)expanded_key + 1); - switch (sig_type) { - case FALCON_SIG_COMPRESSED: - break; - case FALCON_SIG_PADDED: - if (*sig_len < FALCON_SIG_PADDED_SIZE(logn)) { - return FALCON_ERR_SIZE; - } - break; - case FALCON_SIG_CT: - if (*sig_len < FALCON_SIG_CT_SIZE(logn)) { - return FALCON_ERR_SIZE; - } - break; - default: - return FALCON_ERR_BADARG; - } - - n = (size_t)1 << logn; - hm = (uint16_t *)align_u16(tmp); - sv = (int16_t *)hm; - atmp = align_u64(sv + n); - - /* - * Hash message to a point. - */ - shake256_flip(hash_data); - sav_hash_data = *(inner_shake256_context *)hash_data; - - /* - * Compute and encode signature. - */ - for (;;) { - /* - * Hash message to a point. We must redo it when looping - * (in case of a padded signature format and a failed - * attempt due to an oversized compressed signature), because - * we overwrite the hash output with the signature (in order - * to save some RAM). - */ - *(inner_shake256_context *)hash_data = sav_hash_data; - if (sig_type == FALCON_SIG_CT) { - Zf(hash_to_point_ct)( - (inner_shake256_context *)hash_data, - hm, logn, atmp); - } else { - Zf(hash_to_point_vartime)( - (inner_shake256_context *)hash_data, - hm, logn); - } - oldcw = set_fpu_cw(2); - Zf(sign_tree)(sv, (inner_shake256_context *)rng, - expkey, hm, logn, atmp); - set_fpu_cw(oldcw); - es = sig; - es_len = *sig_len; - memcpy(es + 1, nonce, 40); - u = 41; - switch (sig_type) { - size_t tu; - - case FALCON_SIG_COMPRESSED: - es[0] = 0x30 + logn; - v = Zf(comp_encode)(es + u, es_len - u, sv, logn); - if (v == 0) { - return FALCON_ERR_SIZE; - } - break; - case FALCON_SIG_PADDED: - es[0] = 0x30 + logn; - tu = FALCON_SIG_PADDED_SIZE(logn); - v = Zf(comp_encode)(es + u, tu - u, sv, logn); - if (v == 0) { - /* - * Signature does not fit, loop. - */ - continue; - } - if (u + v < tu) { - memset(es + u + v, 0, tu - (u + v)); - v = tu - u; - } - break; - case FALCON_SIG_CT: - es[0] = 0x50 + logn; - v = Zf(trim_i16_encode)(es + u, es_len - u, - sv, logn, Zf(max_sig_bits)[logn]); - if (v == 0) { - return FALCON_ERR_SIZE; - } - break; - } - *sig_len = u + v; - return 0; - } -} - -/* see falcon.h */ -int -falcon_sign_dyn(shake256_context *rng, - void *sig, size_t *sig_len, int sig_type, - const void *privkey, size_t privkey_len, - const void *data, size_t data_len, - void *tmp, size_t tmp_len) -{ - shake256_context hd; - uint8_t nonce[40]; - int r; - - r = falcon_sign_start(rng, nonce, &hd); - if (r != 0) { - return r; - } - shake256_inject(&hd, data, data_len); - return falcon_sign_dyn_finish(rng, sig, sig_len, sig_type, - privkey, privkey_len, &hd, nonce, tmp, tmp_len); -} - -/* see falcon.h */ -int -falcon_sign_tree(shake256_context *rng, - void *sig, size_t *sig_len, int sig_type, - const void *expanded_key, - const void *data, size_t data_len, - void *tmp, size_t tmp_len) -{ - shake256_context hd; - uint8_t nonce[40]; - int r; - - r = falcon_sign_start(rng, nonce, &hd); - if (r != 0) { - return r; - } - shake256_inject(&hd, data, data_len); - return falcon_sign_tree_finish(rng, sig, sig_len, sig_type, - expanded_key, &hd, nonce, tmp, tmp_len); -} - -/* see falcon.h */ -int -falcon_verify_start(shake256_context *hash_data, - const void *sig, size_t sig_len) -{ - if (sig_len < 41) { - return FALCON_ERR_FORMAT; - } - shake256_init(hash_data); - shake256_inject(hash_data, (const uint8_t *)sig + 1, 40); - return 0; -} - -/* see falcon.h */ -int -falcon_verify_finish(const void *sig, size_t sig_len, int sig_type, - const void *pubkey, size_t pubkey_len, - shake256_context *hash_data, - void *tmp, size_t tmp_len) -{ - unsigned logn; - uint8_t *atmp; - const uint8_t *pk, *es; - size_t u, v, n; - uint16_t *h, *hm; - int16_t *sv; - int ct; - - /* - * Get Falcon degree from public key; verify consistency with - * signature value, and check parameters. - */ - if (sig_len < 41 || pubkey_len == 0) { - return FALCON_ERR_FORMAT; - } - es = sig; - pk = pubkey; - if ((pk[0] & 0xF0) != 0x00) { - return FALCON_ERR_FORMAT; - } - logn = pk[0] & 0x0F; - if (logn < 1 || logn > 10) { - return FALCON_ERR_FORMAT; - } - if ((es[0] & 0x0F) != logn) { - return FALCON_ERR_BADSIG; - } - ct = 0; - switch (sig_type) { - case 0: - switch (es[0] & 0xF0) { - case 0x30: - break; - case 0x50: - if (sig_len != FALCON_SIG_CT_SIZE(logn)) { - return FALCON_ERR_FORMAT; - } - ct = 1; - break; - default: - return FALCON_ERR_BADSIG; - } - break; - case FALCON_SIG_COMPRESSED: - if ((es[0] & 0xF0) != 0x30) { - return FALCON_ERR_FORMAT; - } - break; - case FALCON_SIG_PADDED: - if ((es[0] & 0xF0) != 0x30) { - return FALCON_ERR_FORMAT; - } - if (sig_len != FALCON_SIG_PADDED_SIZE(logn)) { - return FALCON_ERR_FORMAT; - } - break; - case FALCON_SIG_CT: - if ((es[0] & 0xF0) != 0x50) { - return FALCON_ERR_FORMAT; - } - if (sig_len != FALCON_SIG_CT_SIZE(logn)) { - return FALCON_ERR_FORMAT; - } - ct = 1; - break; - default: - return FALCON_ERR_BADARG; - } - if (pubkey_len != FALCON_PUBKEY_SIZE(logn)) { - return FALCON_ERR_FORMAT; - } - if (tmp_len < FALCON_TMPSIZE_VERIFY(logn)) { - return FALCON_ERR_SIZE; - } - - n = (size_t)1 << logn; - h = (uint16_t *)align_u16(tmp); - hm = h + n; - sv = (int16_t *)(hm + n); - atmp = (uint8_t *)(sv + n); - - /* - * Decode public key. - */ - if (Zf(modq_decode)(h, logn, pk + 1, pubkey_len - 1) - != pubkey_len - 1) - { - return FALCON_ERR_FORMAT; - } - - /* - * Decode signature value. - */ - u = 41; - if (ct) { - v = Zf(trim_i16_decode)(sv, logn, - Zf(max_sig_bits)[logn], es + u, sig_len - u); - } else { - v = Zf(comp_decode)(sv, logn, es + u, sig_len - u); - } - if (v == 0) { - return FALCON_ERR_FORMAT; - } - if ((u + v) != sig_len) { - /* - * Extra bytes of value 0 are tolerated only for the - * "padded" format. - */ - if ((sig_type == 0 && sig_len == FALCON_SIG_PADDED_SIZE(logn)) - || sig_type == FALCON_SIG_PADDED) - { - while (u + v < sig_len) { - if (es[u + v] != 0) { - return FALCON_ERR_FORMAT; - } - v ++; - } - } else { - return FALCON_ERR_FORMAT; - } - } - - /* - * Hash message to point. - */ - shake256_flip(hash_data); - if (ct) { - Zf(hash_to_point_ct)( - (inner_shake256_context *)hash_data, hm, logn, atmp); - } else { - Zf(hash_to_point_vartime)( - (inner_shake256_context *)hash_data, hm, logn); - } - - /* - * Verify signature. - */ - Zf(to_ntt_monty)(h, logn); - if (!Zf(verify_raw)(hm, sv, h, logn, atmp)) { - return FALCON_ERR_BADSIG; - } - return 0; -} - -/* see falcon.h */ -int -falcon_verify(const void *sig, size_t sig_len, int sig_type, - const void *pubkey, size_t pubkey_len, - const void *data, size_t data_len, - void *tmp, size_t tmp_len) -{ - shake256_context hd; - int r; - - r = falcon_verify_start(&hd, sig, sig_len); - if (r < 0) { - return r; - } - shake256_inject(&hd, data, data_len); - return falcon_verify_finish(sig, sig_len, sig_type, - pubkey, pubkey_len, &hd, tmp, tmp_len); -} diff --git a/falcon/falcon.h b/falcon/falcon.h deleted file mode 100644 index de984d0..0000000 --- a/falcon/falcon.h +++ /dev/null @@ -1,811 +0,0 @@ -/* - * External Falcon API. - * - * ==========================(LICENSE BEGIN)============================ - * - * Copyright (c) 2017-2019 Falcon Project - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * ===========================(LICENSE END)============================= - * - * @author Thomas Pornin - */ - -#ifndef FALCON_H__ -#define FALCON_H__ - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/* ==================================================================== */ -/* - * Falcon API Notes - * ---------------- - * - * - * FALCON DEGREE - * - * Falcon is parameterized by a degree, which is a power of two. Formally, - * two values are possible: 512 and 1024 (for Falcon-512 and Falcon-1024, - * respectively). This implementation also supports lower degrees, from - * 2 to 256; these reduced variants do not provide adequate security and - * should be used for research purposes only. - * - * In all functions and macros defined below, the degree is provided - * logarithmically as the 'logn' parameter: logn ranges from 1 to 10, - * and represents the degree 2^logn. - * - * - * ERROR REPORTING - * - * All functions that may fail for some reason return an 'int' value. A - * returned value of zero is a success; all error conditions are - * reported as an error code. Error codes are negative. Macros are - * defined for some error codes; in the interest of forward - * compatiblity, applications that use this implementation should be - * prepared to receive other error codes not listed in the macros below. - * - * - * TEMPORARY BUFFERS - * - * Many functions expect temporary areas, provided as the parameter - * 'tmp'. The caller is responsible for allocating these areas with the - * proper size; the FALCON_TMPSIZE_* macros evaluate to constant - * expressions that yield the proper size (in bytes) and can be used to - * allocate the temporaries on the stack or elsewhere. There are no - * alignment requirements on temporaries (the functions handle alignment - * internally). - * - * The caller is responsible for clearing temporary buffer contents, - * if such memory scrubbing is deemed relevant in the context where this - * implementation is used. - * - * The same temporary buffer can be reused for several operations, - * possibly distinct from each other. For all degrees from 8 to 1024 - * (logn = 3 to 10), the following sizes are in ascending order: - * - * FALCON_TMPSIZE_MAKEPUB - * FALCON_TMPSIZE_VERIFY - * FALCON_TMPSIZE_KEYGEN - * FALCON_TMPSIZE_SIGNTREE - * FALCON_TMPSIZE_EXPANDPRIV - * FALCON_TMPSIZE_SIGNDYN - * - * i.e. a temporary buffer large enough for computing signatures with - * an expanded key ("SIGNTREE") will also be large enough for a - * key pair generation ("KEYGEN"). For logn = 1 or 2, the same order - * holds, except that the KEYGEN buffer is larger. - * - * Here are the actual values for the temporary buffer sizes (in bytes): - * - * degree mkpub verify keygen signtree expkey signdyn - * 2 13 17 285 107 111 163 - * 4 25 33 291 207 215 319 - * 8 49 65 303 407 423 631 - * 16 97 129 503 807 839 1255 - * 32 193 257 999 1607 1671 2503 - * 64 385 513 1991 3207 3335 4999 - * 128 769 1025 3975 6407 6663 9991 - * 256 1537 2049 7943 12807 13319 19975 - * 512 3073 4097 15879 25607 26631 39943 - * 1024 6145 8193 31751 51207 53255 79879 - * - * Take care that the "expkey" column here qualifies the temporary buffer - * for the key expansion process, but NOT the expanded key itself (which - * has size FALCON_EXPANDEDKEY_SIZE(logn) and is larger than that). - * - * - * FORMATS - * - * Public and private keys are exchanged as serialized sequences of - * bytes. Their respective sizes are fixed (for a given degree) and the - * FALCON_PRIVKEY_SIZE and FALCON_PUBKEY_SIZE macros return that value - * as constant expressions. - * - * There are three formats for signatures: - * - * - COMPRESSED: this is the default format, which yields the shortest - * signatures on average. However, the size is variable (see below) - * though within a limited range. - * - * - PADDED: this is the compressed format, but with extra padding bytes - * to obtain a fixed size known at compile-time. The size depends only - * on the degree; the FALCON_SIG_PADDED_SIZE macro computes it. The - * signature process enforces that size by restarting the process - * until an appropriate size is obtained (such restarts are uncommon - * enough that the computational overhead is negligible). - * - * - CT: this is a fixed-size format, which furthermore allows - * constant-time processing with regard to the signature value and - * message data. This is meant for uncommon situations in which - * the signed data is secret but of low entropy, and the public key - * is not actually public. The CT format is larger than the - * COMPRESSED and PADDED formats. - * - * The signature format is selected by the 'sig_type' parameter to - * the signature generation and verification functions. - * - * Actual signature size has been measured over 10000 signatures for each - * degree (100 random keys, 100 signatures per key): - * - * degree ct padded compressed (with std. dev) comp_max - * 2 44 44 44.00 (+/- 0.00) 44 - * 4 47 47 46.03 (+/- 0.17) 47 - * 8 52 52 50.97 (+/- 0.26) 52 - * 16 65 63 60.45 (+/- 0.52) 64 - * 32 89 82 79.53 (+/- 0.68) 86 - * 64 137 122 117.69 (+/- 0.94) 130 - * 128 233 200 193.96 (+/- 1.30) 219 - * 256 425 356 346.53 (+/- 1.84) 397 - * 512 809 666 651.59 (+/- 2.55) 752 - * 1024 1577 1280 1261.06 (+/- 3.57) 1462 - * - * with: - * degree = Falcon degree = 2^logn - * ct = FALCON_SIG_CT_SIZE(logn) (size of a CT signature) - * padded = FALCON_SIG_PADDED_SIZE(logn) (size of a PADDED signature) - * compressed = measured average length of a COMPRESSED signature - * v_max = FALCON_SIG_COMPRESSED_MAXSIZE(logn) (maximum theoretical - * size of a COMPRESSED signature) - * All lengths are in bytes. - * - * A private key, in its encoded format, can be used as parameter to - * falcon_sign_dyn(). An "expanded private key" is computed with - * falcon_expand_privkey(), to be used with falcon_sign_tree(). The - * expanded private key is much larger than the encoded private key, and - * its format is not portable. Its size (in bytes) is provided by - * FALCON_EXPANDEDKEY_SIZE. There are no specific alignment requirements - * on expanded keys, except that the alignment of a given expanded key - * must not change (i.e. if an expanded key is moved from address addr1 - * to address addr2, then it must hold that addr1 = addr2 mod 8). - * Expanded private keys are meant to be used when several signatures are - * to be computed with the same private key: amortized cost per signature - * is about halved when using expanded private keys (for short messages, - * and depending on underlying architecture and implementation choices). - * - * - * USE OF SHAKE256 - * - * SHAKE256 is used in two places: - * - * - As a PRNG: all functions that require randomness (key pair - * generation, signature generation) receive as parameter a SHAKE256 - * object, in output mode, from which pseudorandom data is obtained. - * - * A SHAKE256 instance, to be used as a RNG, can be initialized - * from an explicit 48-byte seed, or from an OS-provided RNG. Using - * an explicit seed is meant for reproducibility of test vectors, - * or to be used in cases where no OS-provided RNG is available and - * supported. - * - * - As the hashing mechanism for the message which should be signed. - * The streamed signature API exposes that SHAKE256 object, since - * the caller then performs the hashing externally. - */ - -/* ==================================================================== */ -/* - * Error codes. - * - * Most functions in this API that may fail for some reason return an - * 'int' value which will be 0 on success, or a negative error code. - * The macros below define the error codes. In the interest of forward - * compatibility, callers should be prepared to receive additional error - * codes not included in the list below. - */ - -/* - * FALCON_ERR_RANDOM is returned when the library tries to use an - * OS-provided RNG, but either none is supported, or that RNG fails. - */ -#define FALCON_ERR_RANDOM -1 - -/* - * FALCON_ERR_SIZE is returned when a buffer has been provided to - * the library but is too small to receive the intended value. - */ -#define FALCON_ERR_SIZE -2 - -/* - * FALCON_ERR_FORMAT is returned when decoding of an external object - * (public key, private key, signature) fails. - */ -#define FALCON_ERR_FORMAT -3 - -/* - * FALCON_ERR_BADSIG is returned when verifying a signature, the signature - * is validly encoded, but its value does not match the provided message - * and public key. - */ -#define FALCON_ERR_BADSIG -4 - -/* - * FALCON_ERR_BADARG is returned when a provided parameter is not in - * a valid range. - */ -#define FALCON_ERR_BADARG -5 - -/* - * FALCON_ERR_INTERNAL is returned when some internal computation failed. - */ -#define FALCON_ERR_INTERNAL -6 - -/* ==================================================================== */ -/* - * Signature formats. - */ - -/* - * Variable-size signature. This format produces the most compact - * signatures on average, but the signature size may vary depending - * on private key, signed data, and random seed. - */ -#define FALCON_SIG_COMPRESSED 1 - -/* - * Fixed-size signature. This format produces is equivalent to the - * "compressed" format, but includes padding to a known fixed size - * (specified by FALCON_SIG_PADDED_SIZE). With this format, the - * signature generation loops until an appropriate signature size is - * achieved (such looping is uncommon) and adds the padding bytes; - * the verification functions check the presence and contents of the - * padding bytes. - */ -#define FALCON_SIG_PADDED 2 - -/* - * Fixed-size format amenable to constant-time implementation. All formats - * allow constant-time code with regard to the private key; the 'CT' - * format of signature also prevents information about the signature value - * and the signed data hash to leak through timing-based side channels - * (this feature is rarely needed). - */ -#define FALCON_SIG_CT 3 - -/* ==================================================================== */ -/* - * Sizes. - * - * The sizes are expressed in bytes. Each size depends on the Falcon - * degree, which is provided logarithmically: use logn=9 for Falcon-512, - * logn=10 for Falcon-1024. Valid values for logn range from 1 to 10 - * (values 1 to 8 correspond to reduced variants of Falcon that do not - * provided adequate security and are meant for research purposes only). - * - * The sizes are provided as macros that evaluate to constant - * expressions, as long as the 'logn' parameter is itself a constant - * expression. Moreover, all sizes are monotonic (for each size category, - * increasing logn cannot result in a shorter length). - * - * Note: each macro may evaluate its argument 'logn' several times. - */ - -/* - * Private key size (in bytes). The size is exact. - */ -#define FALCON_PRIVKEY_SIZE(logn) \ - (((logn) <= 3 \ - ? (3u << (logn)) \ - : ((10u - ((logn) >> 1)) << ((logn) - 2)) + (1 << (logn))) \ - + 1) - -/* - * Public key size (in bytes). The size is exact. - */ -#define FALCON_PUBKEY_SIZE(logn) \ - (((logn) <= 1 \ - ? 4u \ - : (7u << ((logn) - 2))) \ - + 1) - -/* - * Maximum signature size (in bytes) when using the COMPRESSED format. - * In practice, the signature will be shorter. - */ -#define FALCON_SIG_COMPRESSED_MAXSIZE(logn) \ - (((((11u << (logn)) + (101u >> (10 - (logn)))) \ - + 7) >> 3) + 41) - -/* - * Signature size (in bytes) when using the PADDED format. The size - * is exact. - */ -#define FALCON_SIG_PADDED_SIZE(logn) \ - (44u + 3 * (256u >> (10 - (logn))) + 2 * (128u >> (10 - (logn))) \ - + 3 * (64u >> (10 - (logn))) + 2 * (16u >> (10 - (logn))) \ - - 2 * (2u >> (10 - (logn))) - 8 * (1u >> (10 - (logn)))) - -/* - * Signature size (in bytes) when using the CT format. The size is exact. - */ -#define FALCON_SIG_CT_SIZE(logn) \ - ((3u << ((logn) - 1)) - ((logn) == 3) + 41) - -/* - * Temporary buffer size for key pair generation. - */ -#define FALCON_TMPSIZE_KEYGEN(logn) \ - (((logn) <= 3 ? 272u : (28u << (logn))) + (3u << (logn)) + 7) - -/* - * Temporary buffer size for computing the pubic key from the private key. - */ -#define FALCON_TMPSIZE_MAKEPUB(logn) \ - ((6u << (logn)) + 1) - -/* - * Temporary buffer size for generating a signature ("dynamic" variant). - */ -#define FALCON_TMPSIZE_SIGNDYN(logn) \ - ((78u << (logn)) + 7) - -/* - * Temporary buffer size for generating a signature ("tree" variant, with - * an expanded key). - */ -#define FALCON_TMPSIZE_SIGNTREE(logn) \ - ((50u << (logn)) + 7) - -/* - * Temporary buffer size for expanding a private key. - */ -#define FALCON_TMPSIZE_EXPANDPRIV(logn) \ - ((52u << (logn)) + 7) - -/* - * Size of an expanded private key. - */ -#define FALCON_EXPANDEDKEY_SIZE(logn) \ - (((8u * (logn) + 40) << (logn)) + 8) - -/* - * Temporary buffer size for verifying a signature. - */ -#define FALCON_TMPSIZE_VERIFY(logn) \ - ((8u << (logn)) + 1) - -/* ==================================================================== */ -/* - * SHAKE256. - */ - -/* - * Context for a SHAKE256 computation. Contents are opaque. - * Contents are pure data with no pointer; they need not be released - * explicitly and don't reference any other allocated resource. The - * caller is responsible for allocating the context structure itself, - * typically on the stack. - */ -typedef struct { - uint64_t opaque_contents[26]; -} shake256_context; - -/* - * Initialize a SHAKE256 context to its initial state. The state is - * then ready to receive data (with shake256_inject()). - */ -void shake256_init(shake256_context *sc); - -/* - * Inject some data bytes into the SHAKE256 context ("absorb" operation). - * This function can be called several times, to inject several chunks - * of data of arbitrary length. - */ -void shake256_inject(shake256_context *sc, const void *data, size_t len); - -/* - * Flip the SHAKE256 state to output mode. After this call, shake256_inject() - * can no longer be called on the context, but shake256_extract() can be - * called. - * - * Flipping is one-way; a given context can be converted back to input - * mode only by initializing it again, which forgets all previously - * injected data. - */ -void shake256_flip(shake256_context *sc); - -/* - * Extract bytes from the SHAKE256 context ("squeeze" operation). The - * context must have been flipped to output mode (with shake256_flip()). - * Arbitrary amounts of data can be extracted, in one or several calls - * to this function. - */ -void shake256_extract(shake256_context *sc, void *out, size_t len); - -/* - * Initialize a SHAKE256 context as a PRNG from the provided seed. - * This initializes the context, injects the seed, then flips the context - * to output mode to make it ready to produce bytes. - */ -void shake256_init_prng_from_seed(shake256_context *sc, - const void *seed, size_t seed_len); - -/* - * Initialize a SHAKE256 context as a PRNG, using an initial seed from - * the OS-provided RNG. If there is no known/supported OS-provided RNG, - * or if that RNG fails, then the context is not properly initialized - * and FALCON_ERR_RANDOM is returned. - * - * Returned value: 0 on success, or a negative error code. - */ -int shake256_init_prng_from_system(shake256_context *sc); - -/* ==================================================================== */ -/* - * Key pair generation. - */ - -/* - * Generate a new keypair. - * - * The logarithm of the Falcon degree (logn) must be in the 1 to 10 - * range; values 1 to 8 correspond to reduced versions of Falcon that do - * not provide adequate security and are meant for research purposes - * only. - * - * The source of randomness is the provided SHAKE256 context *rng, which - * must have been already initialized, seeded, and set to output mode (see - * shake256_init_prng_from_seed() and shake256_init_prng_from_system()). - * - * The new private key is written in the buffer pointed to by privkey. - * The size of that buffer must be specified in privkey_len; if that - * size is too low, then this function fails with FALCON_ERR_SIZE. The - * actual private key length can be obtained from the FALCON_PRIVKEY_SIZE() - * macro. - * - * If pubkey is not NULL, then the new public key is written in the buffer - * pointed to by pubkey. The size of that buffer must be specified in - * pubkey_len; if that size is too low, then this function fails with - * FALCON_ERR_SIZE. The actual public key length can be obtained from the - * FALCON_PUBKEY_SIZE() macro. - * - * If pubkey is NULL then pubkey_len is ignored; the private key will - * still be generated and written to privkey[], but the public key - * won't be written anywhere. The public key can be later on recomputed - * from the private key with falcon_make_public(). - * - * The tmp[] buffer is used to hold temporary values. Its size tmp_len - * MUST be at least FALCON_TMPSIZE_KEYGEN(logn) bytes. - * - * Returned value: 0 on success, or a negative error code. - */ -int falcon_keygen_make( - shake256_context *rng, - unsigned logn, - void *privkey, size_t privkey_len, - void *pubkey, size_t pubkey_len, - void *tmp, size_t tmp_len); - -/* - * Recompute the public key from the private key. - * - * The private key is provided encoded. This function decodes the - * private key and verifies that its length (in bytes) is exactly - * the provided value privkey_len (trailing extra bytes are not - * tolerated). - * - * The public key is written in the buffer pointed to by pubkey. The - * size (in bytes) of the pubkey buffer must be provided in pubkey_len; - * if it is too short for the public key, then FALCON_ERR_SIZE is - * returned. The actual public key size can be obtained from the - * FALCON_PUBKEY_SIZE() macro. - * - * The tmp[] buffer is used to hold temporary values. Its size tmp_len - * MUST be at least FALCON_TMPSIZE_MAKEPUB(logn) bytes. - * - * Returned value: 0 on success, or a negative error code. - */ -int falcon_make_public( - void *pubkey, size_t pubkey_len, - const void *privkey, size_t privkey_len, - void *tmp, size_t tmp_len); - -/* - * Get the Falcon degree from an encoded private key, public key or - * signature. Returned value is the logarithm of the degree (1 to 10), - * or a negative error code. - */ -int falcon_get_logn(void *obj, size_t len); - -/* ==================================================================== */ -/* - * Signature generation. - */ - -/* - * Sign the data provided in buffer data[] (of length data_len bytes), - * using the private key held in privkey[] (of length privkey_len bytes). - * - * The source of randomness is the provided SHAKE256 context *rng, which - * must have been already initialized, seeded, and set to output mode (see - * shake256_init_prng_from_seed() and shake256_init_prng_from_system()). - * - * The signature is written in sig[]. The caller must set *sig_len to - * the maximum size of sig[]; if the signature computation is - * successful, then *sig_len will be set to the actual length of the - * signature. The signature length depends on the signature type, - * which is specified with the sig_type parameter to one of the three - * defined values FALCON_SIG_COMPRESSED, FALCON_SIG_PADDED or - * FALCON_SIG_CT; for the last two of these, the signature length is - * fixed (for a given Falcon degree). - * - * Regardless of the signature type, the process is constant-time with - * regard to the private key. When sig_type is FALCON_SIG_CT, it is also - * constant-time with regard to the signature value and the message data, - * i.e. no information on the signature and the message may be inferred - * from timing-related side channels. - * - * The tmp[] buffer is used to hold temporary values. Its size tmp_len - * MUST be at least FALCON_TMPSIZE_SIGNDYN(logn) bytes. - * - * Returned value: 0 on success, or a negative error code. - */ -int falcon_sign_dyn(shake256_context *rng, - void *sig, size_t *sig_len, int sig_type, - const void *privkey, size_t privkey_len, - const void *data, size_t data_len, - void *tmp, size_t tmp_len); - -/* - * Expand a private key. The provided Falcon private key (privkey, of - * size privkey_len bytes) is decoded and expanded into expanded_key[]. - * - * The expanded_key[] buffer has size expanded_key_len, which MUST be at - * least FALCON_EXPANDEDKEY_SIZE(logn) bytes (where 'logn' qualifies the - * Falcon degree encoded in the private key and can be obtained with - * falcon_get_logn()). Expanded key contents have an internal, - * implementation-specific format. Expanded keys may be moved in RAM - * only if their 8-byte alignment remains unchanged. - * - * The tmp[] buffer is used to hold temporary values. Its size tmp_len - * MUST be at least FALCON_TMPSIZE_EXPANDPRIV(logn) bytes. - * - * Returned value: 0 on success, or a negative error code. - */ -int falcon_expand_privkey(void *expanded_key, size_t expanded_key_len, - const void *privkey, size_t privkey_len, - void *tmp, size_t tmp_len); - -/* - * Sign the data provided in buffer data[] (of length data_len bytes), - * using the expanded private key held in expanded_key[], as generated - * by falcon_expand_privkey(). - * - * The source of randomness is the provided SHAKE256 context *rng, which - * must have been already initialized, seeded, and set to output mode (see - * shake256_init_prng_from_seed() and shake256_init_prng_from_system()). - * - * The signature is written in sig[]. The caller must set *sig_len to - * the maximum size of sig[]; if the signature computation is - * successful, then *sig_len will be set to the actual length of the - * signature. The signature length depends on the signature type, - * which is specified with the sig_type parameter to one of the three - * defined values FALCON_SIG_COMPRESSED, FALCON_SIG_PADDED or - * FALCON_SIG_CT; for the last two of these, the signature length is - * fixed (for a given Falcon degree). - * - * Regardless of the signature type, the process is constant-time with - * regard to the private key. When sig_type is FALCON_SIG_CT, it is also - * constant-time with regard to the signature value and the message data, - * i.e. no information on the signature and the message may be inferred - * from timing-related side channels. - * - * The tmp[] buffer is used to hold temporary values. Its size tmp_len - * MUST be at least FALCON_TMPSIZE_SIGNTREE(logn) bytes. - * - * Returned value: 0 on success, or a negative error code. - */ -int falcon_sign_tree(shake256_context *rng, - void *sig, size_t *sig_len, int sig_type, - const void *expanded_key, - const void *data, size_t data_len, - void *tmp, size_t tmp_len); - -/* ==================================================================== */ -/* - * Signature generation, streamed API. - * - * In the streamed API, the caller performs the data hashing externally. - * An initialization function (falcon_sign_start()) is first called; it - * generates and returns a random 40-byte nonce value; it also initializes - * a SHAKE256 context and injects the nonce value in that context. The - * caller must then inject the data to sign in the SHAKE256 context, and - * finally call falcon_sign_dyn_finish() or falcon_sign_tree_finish() to - * finalize the signature generation. - */ - -/* - * Start a signature generation context. - * - * A 40-byte nonce is generated and written in nonce[]. The *hash_data - * context is also initialized, and the nonce is injected in that context. - * - * The source of randomness is the provided SHAKE256 context *rng, which - * must have been already initialized, seeded, and set to output mode (see - * shake256_init_prng_from_seed() and shake256_init_prng_from_system()). - * - * Returned value: 0 on success, or a negative error code. - */ -int falcon_sign_start(shake256_context *rng, - void *nonce, - shake256_context *hash_data); - -/* - * Finish a signature generation operation, using the private key held - * in privkey[] (of length privkey_len bytes). The hashed nonce + message - * is provided as the SHAKE256 context *hash_data, which must still be - * in input mode (i.e. not yet flipped to output mode). That context is - * modified in the process. - * - * The nonce value (which was used at the start of the hashing process, - * usually as part of a falcon_sign_start() call) must be provided again, - * because it is encoded into the signature. The nonce length is 40 bytes. - * - * The source of randomness is the provided SHAKE256 context *rng, which - * must have been already initialized, seeded, and set to output mode (see - * shake256_init_prng_from_seed() and shake256_init_prng_from_system()). - * - * The signature is written in sig[]. The caller must set *sig_len to - * the maximum size of sig[]; if the signature computation is - * successful, then *sig_len will be set to the actual length of the - * signature. The signature length depends on the signature type, - * which is specified with the sig_type parameter to one of the three - * defined values FALCON_SIG_COMPRESSED, FALCON_SIG_PADDED or - * FALCON_SIG_CT; for the last two of these, the signature length is - * fixed (for a given Falcon degree). - * - * Regardless of the signature type, the process is constant-time with - * regard to the private key. When sig_type is FALCON_SIG_CT, it is also - * constant-time with regard to the signature value and the message data, - * i.e. no information on the signature and the message may be inferred - * from timing-related side channels. - * - * The tmp[] buffer is used to hold temporary values. Its size tmp_len - * MUST be at least FALCON_TMPSIZE_SIGNDYN(logn) bytes. - * - * Returned value: 0 on success, or a negative error code. - */ -int falcon_sign_dyn_finish(shake256_context *rng, - void *sig, size_t *sig_len, int sig_type, - const void *privkey, size_t privkey_len, - shake256_context *hash_data, const void *nonce, - void *tmp, size_t tmp_len); - -/* - * Finish a signature generation operation, using the expanded private - * key held in expanded_key[] (as obtained from - * falcon_expand_privkey()). The hashed nonce + message is provided as - * the SHAKE256 context *hash_data, which must still be in input mode - * (i.e. not yet flipped to output mode). That context is modified in - * the process. - * - * The nonce value (which was used at the start of the hashing process, - * usually as part of a falcon_sign_start() call) must be provided again, - * because it is encoded into the signature. The nonce length is 40 bytes. - * - * The source of randomness is the provided SHAKE256 context *rng, which - * must have been already initialized, seeded, and set to output mode (see - * shake256_init_prng_from_seed() and shake256_init_prng_from_system()). - * - * The signature is written in sig[]. The caller must set *sig_len to - * the maximum size of sig[]; if the signature computation is - * successful, then *sig_len will be set to the actual length of the - * signature. The signature length depends on the signature type, - * which is specified with the sig_type parameter to one of the three - * defined values FALCON_SIG_COMPRESSED, FALCON_SIG_PADDED or - * FALCON_SIG_CT; for the last two of these, the signature length is - * fixed (for a given Falcon degree). - * - * Regardless of the signature type, the process is constant-time with - * regard to the private key. When sig_type is FALCON_SIG_CT, it is also - * constant-time with regard to the signature value and the message data, - * i.e. no information on the signature and the message may be inferred - * from timing-related side channels. - * - * The tmp[] buffer is used to hold temporary values. Its size tmp_len - * MUST be at least FALCON_TMPSIZE_SIGNTREE(logn) bytes. - * - * Returned value: 0 on success, or a negative error code. - */ -int falcon_sign_tree_finish(shake256_context *rng, - void *sig, size_t *sig_len, int sig_type, - const void *expanded_key, - shake256_context *hash_data, const void *nonce, - void *tmp, size_t tmp_len); - -/* ==================================================================== */ -/* - * Signature verification. - */ - -/* - * Verify the signature sig[] (of length sig_len bytes) with regards to - * the provided public key pubkey[] (of length pubkey_len bytes) and the - * message data[] (of length data_len bytes). - * - * The sig_type parameter must be zero, or one of FALCON_SIG_COMPRESSED, - * FALCON_SIG_PADDED or FALCON_SIG_CT. The function verifies that - * the provided signature has the correct format. If sig_type is zero, - * then the signature format is inferred from the signature header byte; - * note that in that case, the signature is malleable (since a signature - * value can be transcoded to other formats). - * - * The tmp[] buffer is used to hold temporary values. Its size tmp_len - * MUST be at least FALCON_TMPSIZE_VERIFY(logn) bytes. - * - * Returned value: 0 on success, or a negative error code. - */ -int falcon_verify(const void *sig, size_t sig_len, int sig_type, - const void *pubkey, size_t pubkey_len, - const void *data, size_t data_len, - void *tmp, size_t tmp_len); - -/* - * Start a streamed signature verification. The provided SHAKE256 context - * *hash_data is initialized, and the nonce value (extracted from the - * signature) is injected into it. The caller shall then inject the - * message data into the SHAKE256 context, and finally call - * falcon_verify_finish(). - * - * Returned value: 0 on success, or a negative error code. - */ -int falcon_verify_start(shake256_context *hash_data, - const void *sig, size_t sig_len); - -/* - * Finish a streamed signature verification. The signature sig[] (of - * length sig_len bytes) is verified against the provided public key - * pubkey[] (of length pubkey_len bytes) and the hashed message. The - * hashed message is provided as a SHAKE256 context *hash_data; - * that context must have received the nonce and the message itself - * (usually, the context is initialized and the nonce injected as - * part of a falcon_verify_start() call), and still be in input - * mode (not yet flipped to output mode). *hash_data is modified by - * the verification process. - * - * The sig_type parameter must be zero, or one of FALCON_SIG_COMPRESSED, - * FALCON_SIG_PADDED or FALCON_SIG_CT. The function verifies that - * the provided signature has the correct format. If sig_type is zero, - * then the signature format is inferred from the signature header byte; - * note that in that case, the signature is malleable (since a signature - * value can be transcoded to other formats). - * - * The tmp[] buffer is used to hold temporary values. Its size tmp_len - * MUST be at least FALCON_TMPSIZE_VERIFY(logn) bytes. - * - * Returned value: 0 on success, or a negative error code. - */ -int falcon_verify_finish(const void *sig, size_t sig_len, int sig_type, - const void *pubkey, size_t pubkey_len, - shake256_context *hash_data, - void *tmp, size_t tmp_len); - -/* ==================================================================== */ - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/falcon/fft.c b/falcon/fft.c deleted file mode 100644 index b1904b2..0000000 --- a/falcon/fft.c +++ /dev/null @@ -1,1412 +0,0 @@ -/* - * FFT code. - * - * ==========================(LICENSE BEGIN)============================ - * - * Copyright (c) 2017-2019 Falcon Project - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * ===========================(LICENSE END)============================= - * - * @author Thomas Pornin - */ - -#include "inner.h" - -/* - * Rules for complex number macros: - * -------------------------------- - * - * Operand order is: destination, source1, source2... - * - * Each operand is a real and an imaginary part. - * - * All overlaps are allowed. - */ - -/* - * Addition of two complex numbers (d = a + b). - */ -#define FPC_ADD(d_re, d_im, a_re, a_im, b_re, b_im) do { \ - fpr fpct_re, fpct_im; \ - fpct_re = fpr_add(a_re, b_re); \ - fpct_im = fpr_add(a_im, b_im); \ - (d_re) = fpct_re; \ - (d_im) = fpct_im; \ - } while (0) - -/* - * Subtraction of two complex numbers (d = a - b). - */ -#define FPC_SUB(d_re, d_im, a_re, a_im, b_re, b_im) do { \ - fpr fpct_re, fpct_im; \ - fpct_re = fpr_sub(a_re, b_re); \ - fpct_im = fpr_sub(a_im, b_im); \ - (d_re) = fpct_re; \ - (d_im) = fpct_im; \ - } while (0) - -/* - * Multplication of two complex numbers (d = a * b). - */ -#define FPC_MUL(d_re, d_im, a_re, a_im, b_re, b_im) do { \ - fpr fpct_a_re, fpct_a_im; \ - fpr fpct_b_re, fpct_b_im; \ - fpr fpct_d_re, fpct_d_im; \ - fpct_a_re = (a_re); \ - fpct_a_im = (a_im); \ - fpct_b_re = (b_re); \ - fpct_b_im = (b_im); \ - fpct_d_re = fpr_sub( \ - fpr_mul(fpct_a_re, fpct_b_re), \ - fpr_mul(fpct_a_im, fpct_b_im)); \ - fpct_d_im = fpr_add( \ - fpr_mul(fpct_a_re, fpct_b_im), \ - fpr_mul(fpct_a_im, fpct_b_re)); \ - (d_re) = fpct_d_re; \ - (d_im) = fpct_d_im; \ - } while (0) - -/* - * Squaring of a complex number (d = a * a). - */ -#define FPC_SQR(d_re, d_im, a_re, a_im) do { \ - fpr fpct_a_re, fpct_a_im; \ - fpr fpct_d_re, fpct_d_im; \ - fpct_a_re = (a_re); \ - fpct_a_im = (a_im); \ - fpct_d_re = fpr_sub(fpr_sqr(fpct_a_re), fpr_sqr(fpct_a_im)); \ - fpct_d_im = fpr_double(fpr_mul(fpct_a_re, fpct_a_im)); \ - (d_re) = fpct_d_re; \ - (d_im) = fpct_d_im; \ - } while (0) - -/* - * Inversion of a complex number (d = 1 / a). - */ -#define FPC_INV(d_re, d_im, a_re, a_im) do { \ - fpr fpct_a_re, fpct_a_im; \ - fpr fpct_d_re, fpct_d_im; \ - fpr fpct_m; \ - fpct_a_re = (a_re); \ - fpct_a_im = (a_im); \ - fpct_m = fpr_add(fpr_sqr(fpct_a_re), fpr_sqr(fpct_a_im)); \ - fpct_m = fpr_inv(fpct_m); \ - fpct_d_re = fpr_mul(fpct_a_re, fpct_m); \ - fpct_d_im = fpr_mul(fpr_neg(fpct_a_im), fpct_m); \ - (d_re) = fpct_d_re; \ - (d_im) = fpct_d_im; \ - } while (0) - -/* - * Division of complex numbers (d = a / b). - */ -#define FPC_DIV(d_re, d_im, a_re, a_im, b_re, b_im) do { \ - fpr fpct_a_re, fpct_a_im; \ - fpr fpct_b_re, fpct_b_im; \ - fpr fpct_d_re, fpct_d_im; \ - fpr fpct_m; \ - fpct_a_re = (a_re); \ - fpct_a_im = (a_im); \ - fpct_b_re = (b_re); \ - fpct_b_im = (b_im); \ - fpct_m = fpr_add(fpr_sqr(fpct_b_re), fpr_sqr(fpct_b_im)); \ - fpct_m = fpr_inv(fpct_m); \ - fpct_b_re = fpr_mul(fpct_b_re, fpct_m); \ - fpct_b_im = fpr_mul(fpr_neg(fpct_b_im), fpct_m); \ - fpct_d_re = fpr_sub( \ - fpr_mul(fpct_a_re, fpct_b_re), \ - fpr_mul(fpct_a_im, fpct_b_im)); \ - fpct_d_im = fpr_add( \ - fpr_mul(fpct_a_re, fpct_b_im), \ - fpr_mul(fpct_a_im, fpct_b_re)); \ - (d_re) = fpct_d_re; \ - (d_im) = fpct_d_im; \ - } while (0) - -/* - * Let w = exp(i*pi/N); w is a primitive 2N-th root of 1. We define the - * values w_j = w^(2j+1) for all j from 0 to N-1: these are the roots - * of X^N+1 in the field of complex numbers. A crucial property is that - * w_{N-1-j} = conj(w_j) = 1/w_j for all j. - * - * FFT representation of a polynomial f (taken modulo X^N+1) is the - * set of values f(w_j). Since f is real, conj(f(w_j)) = f(conj(w_j)), - * thus f(w_{N-1-j}) = conj(f(w_j)). We thus store only half the values, - * for j = 0 to N/2-1; the other half can be recomputed easily when (if) - * needed. A consequence is that FFT representation has the same size - * as normal representation: N/2 complex numbers use N real numbers (each - * complex number is the combination of a real and an imaginary part). - * - * We use a specific ordering which makes computations easier. Let rev() - * be the bit-reversal function over log(N) bits. For j in 0..N/2-1, we - * store the real and imaginary parts of f(w_j) in slots: - * - * Re(f(w_j)) -> slot rev(j)/2 - * Im(f(w_j)) -> slot rev(j)/2+N/2 - * - * (Note that rev(j) is even for j < N/2.) - */ - -/* see inner.h */ -TARGET_AVX2 -void -Zf(FFT)(fpr *f, unsigned logn) -{ - /* - * FFT algorithm in bit-reversal order uses the following - * iterative algorithm: - * - * t = N - * for m = 1; m < N; m *= 2: - * ht = t/2 - * for i1 = 0; i1 < m; i1 ++: - * j1 = i1 * t - * s = GM[m + i1] - * for j = j1; j < (j1 + ht); j ++: - * x = f[j] - * y = s * f[j + ht] - * f[j] = x + y - * f[j + ht] = x - y - * t = ht - * - * GM[k] contains w^rev(k) for primitive root w = exp(i*pi/N). - * - * In the description above, f[] is supposed to contain complex - * numbers. In our in-memory representation, the real and - * imaginary parts of f[k] are in array slots k and k+N/2. - * - * We only keep the first half of the complex numbers. We can - * see that after the first iteration, the first and second halves - * of the array of complex numbers have separate lives, so we - * simply ignore the second part. - */ - - unsigned u; - size_t t, n, hn, m; - - /* - * First iteration: compute f[j] + i * f[j+N/2] for all j < N/2 - * (because GM[1] = w^rev(1) = w^(N/2) = i). - * In our chosen representation, this is a no-op: everything is - * already where it should be. - */ - - /* - * Subsequent iterations are truncated to use only the first - * half of values. - */ - n = (size_t)1 << logn; - hn = n >> 1; - t = hn; - for (u = 1, m = 2; u < logn; u ++, m <<= 1) { - size_t ht, hm, i1, j1; - - ht = t >> 1; - hm = m >> 1; - for (i1 = 0, j1 = 0; i1 < hm; i1 ++, j1 += t) { - size_t j, j2; - - j2 = j1 + ht; -#if FALCON_AVX2 // yyyAVX2+1 - if (ht >= 4) { - __m256d s_re, s_im; - - s_re = _mm256_set1_pd( - fpr_gm_tab[((m + i1) << 1) + 0].v); - s_im = _mm256_set1_pd( - fpr_gm_tab[((m + i1) << 1) + 1].v); - for (j = j1; j < j2; j += 4) { - __m256d x_re, x_im, y_re, y_im; - __m256d z_re, z_im; - - x_re = _mm256_loadu_pd(&f[j].v); - x_im = _mm256_loadu_pd(&f[j + hn].v); - z_re = _mm256_loadu_pd(&f[j+ht].v); - z_im = _mm256_loadu_pd(&f[j+ht + hn].v); - y_re = FMSUB(z_re, s_re, - _mm256_mul_pd(z_im, s_im)); - y_im = FMADD(z_re, s_im, - _mm256_mul_pd(z_im, s_re)); - _mm256_storeu_pd(&f[j].v, - _mm256_add_pd(x_re, y_re)); - _mm256_storeu_pd(&f[j + hn].v, - _mm256_add_pd(x_im, y_im)); - _mm256_storeu_pd(&f[j + ht].v, - _mm256_sub_pd(x_re, y_re)); - _mm256_storeu_pd(&f[j + ht + hn].v, - _mm256_sub_pd(x_im, y_im)); - } - } else { - fpr s_re, s_im; - - s_re = fpr_gm_tab[((m + i1) << 1) + 0]; - s_im = fpr_gm_tab[((m + i1) << 1) + 1]; - for (j = j1; j < j2; j ++) { - fpr x_re, x_im, y_re, y_im; - - x_re = f[j]; - x_im = f[j + hn]; - y_re = f[j + ht]; - y_im = f[j + ht + hn]; - FPC_MUL(y_re, y_im, - y_re, y_im, s_re, s_im); - FPC_ADD(f[j], f[j + hn], - x_re, x_im, y_re, y_im); - FPC_SUB(f[j + ht], f[j + ht + hn], - x_re, x_im, y_re, y_im); - } - } -#else // yyyAVX2+0 - fpr s_re, s_im; - - s_re = fpr_gm_tab[((m + i1) << 1) + 0]; - s_im = fpr_gm_tab[((m + i1) << 1) + 1]; - for (j = j1; j < j2; j ++) { - fpr x_re, x_im, y_re, y_im; - - x_re = f[j]; - x_im = f[j + hn]; - y_re = f[j + ht]; - y_im = f[j + ht + hn]; - FPC_MUL(y_re, y_im, y_re, y_im, s_re, s_im); - FPC_ADD(f[j], f[j + hn], - x_re, x_im, y_re, y_im); - FPC_SUB(f[j + ht], f[j + ht + hn], - x_re, x_im, y_re, y_im); - } -#endif // yyyAVX2- - } - t = ht; - } -} - -/* see inner.h */ -TARGET_AVX2 -void -Zf(iFFT)(fpr *f, unsigned logn) -{ - /* - * Inverse FFT algorithm in bit-reversal order uses the following - * iterative algorithm: - * - * t = 1 - * for m = N; m > 1; m /= 2: - * hm = m/2 - * dt = t*2 - * for i1 = 0; i1 < hm; i1 ++: - * j1 = i1 * dt - * s = iGM[hm + i1] - * for j = j1; j < (j1 + t); j ++: - * x = f[j] - * y = f[j + t] - * f[j] = x + y - * f[j + t] = s * (x - y) - * t = dt - * for i1 = 0; i1 < N; i1 ++: - * f[i1] = f[i1] / N - * - * iGM[k] contains (1/w)^rev(k) for primitive root w = exp(i*pi/N) - * (actually, iGM[k] = 1/GM[k] = conj(GM[k])). - * - * In the main loop (not counting the final division loop), in - * all iterations except the last, the first and second half of f[] - * (as an array of complex numbers) are separate. In our chosen - * representation, we do not keep the second half. - * - * The last iteration recombines the recomputed half with the - * implicit half, and should yield only real numbers since the - * target polynomial is real; moreover, s = i at that step. - * Thus, when considering x and y: - * y = conj(x) since the final f[j] must be real - * Therefore, f[j] is filled with 2*Re(x), and f[j + t] is - * filled with 2*Im(x). - * But we already have Re(x) and Im(x) in array slots j and j+t - * in our chosen representation. That last iteration is thus a - * simple doubling of the values in all the array. - * - * We make the last iteration a no-op by tweaking the final - * division into a division by N/2, not N. - */ - size_t u, n, hn, t, m; - - n = (size_t)1 << logn; - t = 1; - m = n; - hn = n >> 1; - for (u = logn; u > 1; u --) { - size_t hm, dt, i1, j1; - - hm = m >> 1; - dt = t << 1; - for (i1 = 0, j1 = 0; j1 < hn; i1 ++, j1 += dt) { - size_t j, j2; - - j2 = j1 + t; -#if FALCON_AVX2 // yyyAVX2+1 - if (t >= 4) { - __m256d s_re, s_im; - - s_re = _mm256_set1_pd( - fpr_gm_tab[((hm + i1) << 1) + 0].v); - s_im = _mm256_set1_pd( - fpr_gm_tab[((hm + i1) << 1) + 1].v); - for (j = j1; j < j2; j += 4) { - __m256d x_re, x_im, y_re, y_im; - __m256d z_re, z_im; - - x_re = _mm256_loadu_pd(&f[j].v); - x_im = _mm256_loadu_pd(&f[j + hn].v); - y_re = _mm256_loadu_pd(&f[j+t].v); - y_im = _mm256_loadu_pd(&f[j+t + hn].v); - _mm256_storeu_pd(&f[j].v, - _mm256_add_pd(x_re, y_re)); - _mm256_storeu_pd(&f[j + hn].v, - _mm256_add_pd(x_im, y_im)); - x_re = _mm256_sub_pd(y_re, x_re); - x_im = _mm256_sub_pd(x_im, y_im); - z_re = FMSUB(x_im, s_im, - _mm256_mul_pd(x_re, s_re)); - z_im = FMADD(x_re, s_im, - _mm256_mul_pd(x_im, s_re)); - _mm256_storeu_pd(&f[j+t].v, z_re); - _mm256_storeu_pd(&f[j+t + hn].v, z_im); - } - } else { - fpr s_re, s_im; - - s_re = fpr_gm_tab[((hm + i1) << 1)+0]; - s_im = fpr_neg(fpr_gm_tab[((hm + i1) << 1)+1]); - for (j = j1; j < j2; j ++) { - fpr x_re, x_im, y_re, y_im; - - x_re = f[j]; - x_im = f[j + hn]; - y_re = f[j + t]; - y_im = f[j + t + hn]; - FPC_ADD(f[j], f[j + hn], - x_re, x_im, y_re, y_im); - FPC_SUB(x_re, x_im, - x_re, x_im, y_re, y_im); - FPC_MUL(f[j + t], f[j + t + hn], - x_re, x_im, s_re, s_im); - } - } -#else // yyyAVX2+0 - fpr s_re, s_im; - - s_re = fpr_gm_tab[((hm + i1) << 1) + 0]; - s_im = fpr_neg(fpr_gm_tab[((hm + i1) << 1) + 1]); - for (j = j1; j < j2; j ++) { - fpr x_re, x_im, y_re, y_im; - - x_re = f[j]; - x_im = f[j + hn]; - y_re = f[j + t]; - y_im = f[j + t + hn]; - FPC_ADD(f[j], f[j + hn], - x_re, x_im, y_re, y_im); - FPC_SUB(x_re, x_im, x_re, x_im, y_re, y_im); - FPC_MUL(f[j + t], f[j + t + hn], - x_re, x_im, s_re, s_im); - } -#endif // yyyAVX2- - } - t = dt; - m = hm; - } - - /* - * Last iteration is a no-op, provided that we divide by N/2 - * instead of N. We need to make a special case for logn = 0. - */ - if (logn > 0) { - fpr ni; - - ni = fpr_p2_tab[logn]; - for (u = 0; u < n; u ++) { - f[u] = fpr_mul(f[u], ni); - } - } -} - -/* see inner.h */ -TARGET_AVX2 -void -Zf(poly_add)( - fpr *restrict a, const fpr *restrict b, unsigned logn) -{ - size_t n, u; - - n = (size_t)1 << logn; -#if FALCON_AVX2 // yyyAVX2+1 - if (n >= 4) { - for (u = 0; u < n; u += 4) { - _mm256_storeu_pd(&a[u].v, - _mm256_add_pd( - _mm256_loadu_pd(&a[u].v), - _mm256_loadu_pd(&b[u].v))); - } - } else { - for (u = 0; u < n; u ++) { - a[u] = fpr_add(a[u], b[u]); - } - } -#else // yyyAVX2+0 - for (u = 0; u < n; u ++) { - a[u] = fpr_add(a[u], b[u]); - } -#endif // yyyAVX2- -} - -/* see inner.h */ -TARGET_AVX2 -void -Zf(poly_sub)( - fpr *restrict a, const fpr *restrict b, unsigned logn) -{ - size_t n, u; - - n = (size_t)1 << logn; -#if FALCON_AVX2 // yyyAVX2+1 - if (n >= 4) { - for (u = 0; u < n; u += 4) { - _mm256_storeu_pd(&a[u].v, - _mm256_sub_pd( - _mm256_loadu_pd(&a[u].v), - _mm256_loadu_pd(&b[u].v))); - } - } else { - for (u = 0; u < n; u ++) { - a[u] = fpr_sub(a[u], b[u]); - } - } -#else // yyyAVX2+0 - for (u = 0; u < n; u ++) { - a[u] = fpr_sub(a[u], b[u]); - } -#endif // yyyAVX2- -} - -/* see inner.h */ -TARGET_AVX2 -void -Zf(poly_neg)(fpr *a, unsigned logn) -{ - size_t n, u; - - n = (size_t)1 << logn; -#if FALCON_AVX2 // yyyAVX2+1 - if (n >= 4) { - __m256d s; - - s = _mm256_set1_pd(-0.0); - for (u = 0; u < n; u += 4) { - _mm256_storeu_pd(&a[u].v, - _mm256_xor_pd(_mm256_loadu_pd(&a[u].v), s)); - } - } else { - for (u = 0; u < n; u ++) { - a[u] = fpr_neg(a[u]); - } - } -#else // yyyAVX2+0 - for (u = 0; u < n; u ++) { - a[u] = fpr_neg(a[u]); - } -#endif // yyyAVX2- -} - -/* see inner.h */ -TARGET_AVX2 -void -Zf(poly_adj_fft)(fpr *a, unsigned logn) -{ - size_t n, u; - - n = (size_t)1 << logn; -#if FALCON_AVX2 // yyyAVX2+1 - if (n >= 8) { - __m256d s; - - s = _mm256_set1_pd(-0.0); - for (u = (n >> 1); u < n; u += 4) { - _mm256_storeu_pd(&a[u].v, - _mm256_xor_pd(_mm256_loadu_pd(&a[u].v), s)); - } - } else { - for (u = (n >> 1); u < n; u ++) { - a[u] = fpr_neg(a[u]); - } - } -#else // yyyAVX2+0 - for (u = (n >> 1); u < n; u ++) { - a[u] = fpr_neg(a[u]); - } -#endif // yyyAVX2- -} - -/* see inner.h */ -TARGET_AVX2 -void -Zf(poly_mul_fft)( - fpr *restrict a, const fpr *restrict b, unsigned logn) -{ - size_t n, hn, u; - - n = (size_t)1 << logn; - hn = n >> 1; -#if FALCON_AVX2 // yyyAVX2+1 - if (n >= 8) { - for (u = 0; u < hn; u += 4) { - __m256d a_re, a_im, b_re, b_im, c_re, c_im; - - a_re = _mm256_loadu_pd(&a[u].v); - a_im = _mm256_loadu_pd(&a[u + hn].v); - b_re = _mm256_loadu_pd(&b[u].v); - b_im = _mm256_loadu_pd(&b[u + hn].v); - c_re = FMSUB( - a_re, b_re, _mm256_mul_pd(a_im, b_im)); - c_im = FMADD( - a_re, b_im, _mm256_mul_pd(a_im, b_re)); - _mm256_storeu_pd(&a[u].v, c_re); - _mm256_storeu_pd(&a[u + hn].v, c_im); - } - } else { - for (u = 0; u < hn; u ++) { - fpr a_re, a_im, b_re, b_im; - - a_re = a[u]; - a_im = a[u + hn]; - b_re = b[u]; - b_im = b[u + hn]; - FPC_MUL(a[u], a[u + hn], a_re, a_im, b_re, b_im); - } - } -#else // yyyAVX2+0 - for (u = 0; u < hn; u ++) { - fpr a_re, a_im, b_re, b_im; - - a_re = a[u]; - a_im = a[u + hn]; - b_re = b[u]; - b_im = b[u + hn]; - FPC_MUL(a[u], a[u + hn], a_re, a_im, b_re, b_im); - } -#endif // yyyAVX2- -} - -/* see inner.h */ -TARGET_AVX2 -void -Zf(poly_muladj_fft)( - fpr *restrict a, const fpr *restrict b, unsigned logn) -{ - size_t n, hn, u; - - n = (size_t)1 << logn; - hn = n >> 1; -#if FALCON_AVX2 // yyyAVX2+1 - if (n >= 8) { - for (u = 0; u < hn; u += 4) { - __m256d a_re, a_im, b_re, b_im, c_re, c_im; - - a_re = _mm256_loadu_pd(&a[u].v); - a_im = _mm256_loadu_pd(&a[u + hn].v); - b_re = _mm256_loadu_pd(&b[u].v); - b_im = _mm256_loadu_pd(&b[u + hn].v); - c_re = FMADD( - a_re, b_re, _mm256_mul_pd(a_im, b_im)); - c_im = FMSUB( - a_im, b_re, _mm256_mul_pd(a_re, b_im)); - _mm256_storeu_pd(&a[u].v, c_re); - _mm256_storeu_pd(&a[u + hn].v, c_im); - } - } else { - for (u = 0; u < hn; u ++) { - fpr a_re, a_im, b_re, b_im; - - a_re = a[u]; - a_im = a[u + hn]; - b_re = b[u]; - b_im = fpr_neg(b[u + hn]); - FPC_MUL(a[u], a[u + hn], a_re, a_im, b_re, b_im); - } - } -#else // yyyAVX2+0 - for (u = 0; u < hn; u ++) { - fpr a_re, a_im, b_re, b_im; - - a_re = a[u]; - a_im = a[u + hn]; - b_re = b[u]; - b_im = fpr_neg(b[u + hn]); - FPC_MUL(a[u], a[u + hn], a_re, a_im, b_re, b_im); - } -#endif // yyyAVX2- -} - -/* see inner.h */ -TARGET_AVX2 -void -Zf(poly_mulselfadj_fft)(fpr *a, unsigned logn) -{ - /* - * Since each coefficient is multiplied with its own conjugate, - * the result contains only real values. - */ - size_t n, hn, u; - - n = (size_t)1 << logn; - hn = n >> 1; -#if FALCON_AVX2 // yyyAVX2+1 - if (n >= 8) { - __m256d zero; - - zero = _mm256_setzero_pd(); - for (u = 0; u < hn; u += 4) { - __m256d a_re, a_im; - - a_re = _mm256_loadu_pd(&a[u].v); - a_im = _mm256_loadu_pd(&a[u + hn].v); - _mm256_storeu_pd(&a[u].v, - FMADD(a_re, a_re, - _mm256_mul_pd(a_im, a_im))); - _mm256_storeu_pd(&a[u + hn].v, zero); - } - } else { - for (u = 0; u < hn; u ++) { - fpr a_re, a_im; - - a_re = a[u]; - a_im = a[u + hn]; - a[u] = fpr_add(fpr_sqr(a_re), fpr_sqr(a_im)); - a[u + hn] = fpr_zero; - } - } -#else // yyyAVX2+0 - for (u = 0; u < hn; u ++) { - fpr a_re, a_im; - - a_re = a[u]; - a_im = a[u + hn]; - a[u] = fpr_add(fpr_sqr(a_re), fpr_sqr(a_im)); - a[u + hn] = fpr_zero; - } -#endif // yyyAVX2- -} - -/* see inner.h */ -TARGET_AVX2 -void -Zf(poly_mulconst)(fpr *a, fpr x, unsigned logn) -{ - size_t n, u; - - n = (size_t)1 << logn; -#if FALCON_AVX2 // yyyAVX2+1 - if (n >= 4) { - __m256d x4; - - x4 = _mm256_set1_pd(x.v); - for (u = 0; u < n; u += 4) { - _mm256_storeu_pd(&a[u].v, - _mm256_mul_pd(x4, _mm256_loadu_pd(&a[u].v))); - } - } else { - for (u = 0; u < n; u ++) { - a[u] = fpr_mul(a[u], x); - } - } -#else // yyyAVX2+0 - for (u = 0; u < n; u ++) { - a[u] = fpr_mul(a[u], x); - } -#endif // yyyAVX2- -} - -/* see inner.h */ -TARGET_AVX2 -void -Zf(poly_div_fft)( - fpr *restrict a, const fpr *restrict b, unsigned logn) -{ - size_t n, hn, u; - - n = (size_t)1 << logn; - hn = n >> 1; -#if FALCON_AVX2 // yyyAVX2+1 - if (n >= 8) { - __m256d one; - - one = _mm256_set1_pd(1.0); - for (u = 0; u < hn; u += 4) { - __m256d a_re, a_im, b_re, b_im, c_re, c_im, t; - - a_re = _mm256_loadu_pd(&a[u].v); - a_im = _mm256_loadu_pd(&a[u + hn].v); - b_re = _mm256_loadu_pd(&b[u].v); - b_im = _mm256_loadu_pd(&b[u + hn].v); - t = _mm256_div_pd(one, - FMADD(b_re, b_re, - _mm256_mul_pd(b_im, b_im))); - b_re = _mm256_mul_pd(b_re, t); - b_im = _mm256_mul_pd(b_im, t); - c_re = FMADD( - a_re, b_re, _mm256_mul_pd(a_im, b_im)); - c_im = FMSUB( - a_im, b_re, _mm256_mul_pd(a_re, b_im)); - _mm256_storeu_pd(&a[u].v, c_re); - _mm256_storeu_pd(&a[u + hn].v, c_im); - } - } else { - for (u = 0; u < hn; u ++) { - fpr a_re, a_im, b_re, b_im; - - a_re = a[u]; - a_im = a[u + hn]; - b_re = b[u]; - b_im = b[u + hn]; - FPC_DIV(a[u], a[u + hn], a_re, a_im, b_re, b_im); - } - } -#else // yyyAVX2+0 - for (u = 0; u < hn; u ++) { - fpr a_re, a_im, b_re, b_im; - - a_re = a[u]; - a_im = a[u + hn]; - b_re = b[u]; - b_im = b[u + hn]; - FPC_DIV(a[u], a[u + hn], a_re, a_im, b_re, b_im); - } -#endif // yyyAVX2- -} - -/* see inner.h */ -TARGET_AVX2 -void -Zf(poly_invnorm2_fft)(fpr *restrict d, - const fpr *restrict a, const fpr *restrict b, unsigned logn) -{ - size_t n, hn, u; - - n = (size_t)1 << logn; - hn = n >> 1; -#if FALCON_AVX2 // yyyAVX2+1 - if (n >= 8) { - __m256d one; - - one = _mm256_set1_pd(1.0); - for (u = 0; u < hn; u += 4) { - __m256d a_re, a_im, b_re, b_im, dv; - - a_re = _mm256_loadu_pd(&a[u].v); - a_im = _mm256_loadu_pd(&a[u + hn].v); - b_re = _mm256_loadu_pd(&b[u].v); - b_im = _mm256_loadu_pd(&b[u + hn].v); - dv = _mm256_div_pd(one, - _mm256_add_pd( - FMADD(a_re, a_re, - _mm256_mul_pd(a_im, a_im)), - FMADD(b_re, b_re, - _mm256_mul_pd(b_im, b_im)))); - _mm256_storeu_pd(&d[u].v, dv); - } - } else { - for (u = 0; u < hn; u ++) { - fpr a_re, a_im; - fpr b_re, b_im; - - a_re = a[u]; - a_im = a[u + hn]; - b_re = b[u]; - b_im = b[u + hn]; - d[u] = fpr_inv(fpr_add( - fpr_add(fpr_sqr(a_re), fpr_sqr(a_im)), - fpr_add(fpr_sqr(b_re), fpr_sqr(b_im)))); - } - } -#else // yyyAVX2+0 - for (u = 0; u < hn; u ++) { - fpr a_re, a_im; - fpr b_re, b_im; - - a_re = a[u]; - a_im = a[u + hn]; - b_re = b[u]; - b_im = b[u + hn]; - d[u] = fpr_inv(fpr_add( - fpr_add(fpr_sqr(a_re), fpr_sqr(a_im)), - fpr_add(fpr_sqr(b_re), fpr_sqr(b_im)))); - } -#endif // yyyAVX2- -} - -/* see inner.h */ -TARGET_AVX2 -void -Zf(poly_add_muladj_fft)(fpr *restrict d, - const fpr *restrict F, const fpr *restrict G, - const fpr *restrict f, const fpr *restrict g, unsigned logn) -{ - size_t n, hn, u; - - n = (size_t)1 << logn; - hn = n >> 1; -#if FALCON_AVX2 // yyyAVX2+1 - if (n >= 8) { - for (u = 0; u < hn; u += 4) { - __m256d F_re, F_im, G_re, G_im; - __m256d f_re, f_im, g_re, g_im; - __m256d a_re, a_im, b_re, b_im; - - F_re = _mm256_loadu_pd(&F[u].v); - F_im = _mm256_loadu_pd(&F[u + hn].v); - G_re = _mm256_loadu_pd(&G[u].v); - G_im = _mm256_loadu_pd(&G[u + hn].v); - f_re = _mm256_loadu_pd(&f[u].v); - f_im = _mm256_loadu_pd(&f[u + hn].v); - g_re = _mm256_loadu_pd(&g[u].v); - g_im = _mm256_loadu_pd(&g[u + hn].v); - - a_re = FMADD(F_re, f_re, - _mm256_mul_pd(F_im, f_im)); - a_im = FMSUB(F_im, f_re, - _mm256_mul_pd(F_re, f_im)); - b_re = FMADD(G_re, g_re, - _mm256_mul_pd(G_im, g_im)); - b_im = FMSUB(G_im, g_re, - _mm256_mul_pd(G_re, g_im)); - _mm256_storeu_pd(&d[u].v, - _mm256_add_pd(a_re, b_re)); - _mm256_storeu_pd(&d[u + hn].v, - _mm256_add_pd(a_im, b_im)); - } - } else { - for (u = 0; u < hn; u ++) { - fpr F_re, F_im, G_re, G_im; - fpr f_re, f_im, g_re, g_im; - fpr a_re, a_im, b_re, b_im; - - F_re = F[u]; - F_im = F[u + hn]; - G_re = G[u]; - G_im = G[u + hn]; - f_re = f[u]; - f_im = f[u + hn]; - g_re = g[u]; - g_im = g[u + hn]; - - FPC_MUL(a_re, a_im, F_re, F_im, f_re, fpr_neg(f_im)); - FPC_MUL(b_re, b_im, G_re, G_im, g_re, fpr_neg(g_im)); - d[u] = fpr_add(a_re, b_re); - d[u + hn] = fpr_add(a_im, b_im); - } - } -#else // yyyAVX2+0 - for (u = 0; u < hn; u ++) { - fpr F_re, F_im, G_re, G_im; - fpr f_re, f_im, g_re, g_im; - fpr a_re, a_im, b_re, b_im; - - F_re = F[u]; - F_im = F[u + hn]; - G_re = G[u]; - G_im = G[u + hn]; - f_re = f[u]; - f_im = f[u + hn]; - g_re = g[u]; - g_im = g[u + hn]; - - FPC_MUL(a_re, a_im, F_re, F_im, f_re, fpr_neg(f_im)); - FPC_MUL(b_re, b_im, G_re, G_im, g_re, fpr_neg(g_im)); - d[u] = fpr_add(a_re, b_re); - d[u + hn] = fpr_add(a_im, b_im); - } -#endif // yyyAVX2- -} - -/* see inner.h */ -TARGET_AVX2 -void -Zf(poly_mul_autoadj_fft)( - fpr *restrict a, const fpr *restrict b, unsigned logn) -{ - size_t n, hn, u; - - n = (size_t)1 << logn; - hn = n >> 1; -#if FALCON_AVX2 // yyyAVX2+1 - if (n >= 8) { - for (u = 0; u < hn; u += 4) { - __m256d a_re, a_im, bv; - - a_re = _mm256_loadu_pd(&a[u].v); - a_im = _mm256_loadu_pd(&a[u + hn].v); - bv = _mm256_loadu_pd(&b[u].v); - _mm256_storeu_pd(&a[u].v, - _mm256_mul_pd(a_re, bv)); - _mm256_storeu_pd(&a[u + hn].v, - _mm256_mul_pd(a_im, bv)); - } - } else { - for (u = 0; u < hn; u ++) { - a[u] = fpr_mul(a[u], b[u]); - a[u + hn] = fpr_mul(a[u + hn], b[u]); - } - } -#else // yyyAVX2+0 - for (u = 0; u < hn; u ++) { - a[u] = fpr_mul(a[u], b[u]); - a[u + hn] = fpr_mul(a[u + hn], b[u]); - } -#endif // yyyAVX2- -} - -/* see inner.h */ -TARGET_AVX2 -void -Zf(poly_div_autoadj_fft)( - fpr *restrict a, const fpr *restrict b, unsigned logn) -{ - size_t n, hn, u; - - n = (size_t)1 << logn; - hn = n >> 1; -#if FALCON_AVX2 // yyyAVX2+1 - if (n >= 8) { - __m256d one; - - one = _mm256_set1_pd(1.0); - for (u = 0; u < hn; u += 4) { - __m256d ib, a_re, a_im; - - ib = _mm256_div_pd(one, _mm256_loadu_pd(&b[u].v)); - a_re = _mm256_loadu_pd(&a[u].v); - a_im = _mm256_loadu_pd(&a[u + hn].v); - _mm256_storeu_pd(&a[u].v, _mm256_mul_pd(a_re, ib)); - _mm256_storeu_pd(&a[u + hn].v, _mm256_mul_pd(a_im, ib)); - } - } else { - for (u = 0; u < hn; u ++) { - fpr ib; - - ib = fpr_inv(b[u]); - a[u] = fpr_mul(a[u], ib); - a[u + hn] = fpr_mul(a[u + hn], ib); - } - } -#else // yyyAVX2+0 - for (u = 0; u < hn; u ++) { - fpr ib; - - ib = fpr_inv(b[u]); - a[u] = fpr_mul(a[u], ib); - a[u + hn] = fpr_mul(a[u + hn], ib); - } -#endif // yyyAVX2- -} - -/* see inner.h */ -TARGET_AVX2 -void -Zf(poly_LDL_fft)( - const fpr *restrict g00, - fpr *restrict g01, fpr *restrict g11, unsigned logn) -{ - size_t n, hn, u; - - n = (size_t)1 << logn; - hn = n >> 1; -#if FALCON_AVX2 // yyyAVX2+1 - if (n >= 8) { - __m256d one; - - one = _mm256_set1_pd(1.0); - for (u = 0; u < hn; u += 4) { - __m256d g00_re, g00_im, g01_re, g01_im, g11_re, g11_im; - __m256d t, mu_re, mu_im, xi_re, xi_im; - - g00_re = _mm256_loadu_pd(&g00[u].v); - g00_im = _mm256_loadu_pd(&g00[u + hn].v); - g01_re = _mm256_loadu_pd(&g01[u].v); - g01_im = _mm256_loadu_pd(&g01[u + hn].v); - g11_re = _mm256_loadu_pd(&g11[u].v); - g11_im = _mm256_loadu_pd(&g11[u + hn].v); - - t = _mm256_div_pd(one, - FMADD(g00_re, g00_re, - _mm256_mul_pd(g00_im, g00_im))); - g00_re = _mm256_mul_pd(g00_re, t); - g00_im = _mm256_mul_pd(g00_im, t); - mu_re = FMADD(g01_re, g00_re, - _mm256_mul_pd(g01_im, g00_im)); - mu_im = FMSUB(g01_re, g00_im, - _mm256_mul_pd(g01_im, g00_re)); - xi_re = FMSUB(mu_re, g01_re, - _mm256_mul_pd(mu_im, g01_im)); - xi_im = FMADD(mu_im, g01_re, - _mm256_mul_pd(mu_re, g01_im)); - _mm256_storeu_pd(&g11[u].v, - _mm256_sub_pd(g11_re, xi_re)); - _mm256_storeu_pd(&g11[u + hn].v, - _mm256_add_pd(g11_im, xi_im)); - _mm256_storeu_pd(&g01[u].v, mu_re); - _mm256_storeu_pd(&g01[u + hn].v, mu_im); - } - } else { - for (u = 0; u < hn; u ++) { - fpr g00_re, g00_im, g01_re, g01_im, g11_re, g11_im; - fpr mu_re, mu_im; - - g00_re = g00[u]; - g00_im = g00[u + hn]; - g01_re = g01[u]; - g01_im = g01[u + hn]; - g11_re = g11[u]; - g11_im = g11[u + hn]; - FPC_DIV(mu_re, mu_im, g01_re, g01_im, g00_re, g00_im); - FPC_MUL(g01_re, g01_im, - mu_re, mu_im, g01_re, fpr_neg(g01_im)); - FPC_SUB(g11[u], g11[u + hn], - g11_re, g11_im, g01_re, g01_im); - g01[u] = mu_re; - g01[u + hn] = fpr_neg(mu_im); - } - } -#else // yyyAVX2+0 - for (u = 0; u < hn; u ++) { - fpr g00_re, g00_im, g01_re, g01_im, g11_re, g11_im; - fpr mu_re, mu_im; - - g00_re = g00[u]; - g00_im = g00[u + hn]; - g01_re = g01[u]; - g01_im = g01[u + hn]; - g11_re = g11[u]; - g11_im = g11[u + hn]; - FPC_DIV(mu_re, mu_im, g01_re, g01_im, g00_re, g00_im); - FPC_MUL(g01_re, g01_im, mu_re, mu_im, g01_re, fpr_neg(g01_im)); - FPC_SUB(g11[u], g11[u + hn], g11_re, g11_im, g01_re, g01_im); - g01[u] = mu_re; - g01[u + hn] = fpr_neg(mu_im); - } -#endif // yyyAVX2- -} - -/* see inner.h */ -TARGET_AVX2 -void -Zf(poly_LDLmv_fft)( - fpr *restrict d11, fpr *restrict l10, - const fpr *restrict g00, const fpr *restrict g01, - const fpr *restrict g11, unsigned logn) -{ - size_t n, hn, u; - - n = (size_t)1 << logn; - hn = n >> 1; -#if FALCON_AVX2 // yyyAVX2+1 - if (n >= 8) { - __m256d one; - - one = _mm256_set1_pd(1.0); - for (u = 0; u < hn; u += 4) { - __m256d g00_re, g00_im, g01_re, g01_im, g11_re, g11_im; - __m256d t, mu_re, mu_im, xi_re, xi_im; - - g00_re = _mm256_loadu_pd(&g00[u].v); - g00_im = _mm256_loadu_pd(&g00[u + hn].v); - g01_re = _mm256_loadu_pd(&g01[u].v); - g01_im = _mm256_loadu_pd(&g01[u + hn].v); - g11_re = _mm256_loadu_pd(&g11[u].v); - g11_im = _mm256_loadu_pd(&g11[u + hn].v); - - t = _mm256_div_pd(one, - FMADD(g00_re, g00_re, - _mm256_mul_pd(g00_im, g00_im))); - g00_re = _mm256_mul_pd(g00_re, t); - g00_im = _mm256_mul_pd(g00_im, t); - mu_re = FMADD(g01_re, g00_re, - _mm256_mul_pd(g01_im, g00_im)); - mu_im = FMSUB(g01_re, g00_im, - _mm256_mul_pd(g01_im, g00_re)); - xi_re = FMSUB(mu_re, g01_re, - _mm256_mul_pd(mu_im, g01_im)); - xi_im = FMADD(mu_im, g01_re, - _mm256_mul_pd(mu_re, g01_im)); - _mm256_storeu_pd(&d11[u].v, - _mm256_sub_pd(g11_re, xi_re)); - _mm256_storeu_pd(&d11[u + hn].v, - _mm256_add_pd(g11_im, xi_im)); - _mm256_storeu_pd(&l10[u].v, mu_re); - _mm256_storeu_pd(&l10[u + hn].v, mu_im); - } - } else { - for (u = 0; u < hn; u ++) { - fpr g00_re, g00_im, g01_re, g01_im, g11_re, g11_im; - fpr mu_re, mu_im; - - g00_re = g00[u]; - g00_im = g00[u + hn]; - g01_re = g01[u]; - g01_im = g01[u + hn]; - g11_re = g11[u]; - g11_im = g11[u + hn]; - FPC_DIV(mu_re, mu_im, g01_re, g01_im, g00_re, g00_im); - FPC_MUL(g01_re, g01_im, - mu_re, mu_im, g01_re, fpr_neg(g01_im)); - FPC_SUB(d11[u], d11[u + hn], - g11_re, g11_im, g01_re, g01_im); - l10[u] = mu_re; - l10[u + hn] = fpr_neg(mu_im); - } - } -#else // yyyAVX2+0 - for (u = 0; u < hn; u ++) { - fpr g00_re, g00_im, g01_re, g01_im, g11_re, g11_im; - fpr mu_re, mu_im; - - g00_re = g00[u]; - g00_im = g00[u + hn]; - g01_re = g01[u]; - g01_im = g01[u + hn]; - g11_re = g11[u]; - g11_im = g11[u + hn]; - FPC_DIV(mu_re, mu_im, g01_re, g01_im, g00_re, g00_im); - FPC_MUL(g01_re, g01_im, mu_re, mu_im, g01_re, fpr_neg(g01_im)); - FPC_SUB(d11[u], d11[u + hn], g11_re, g11_im, g01_re, g01_im); - l10[u] = mu_re; - l10[u + hn] = fpr_neg(mu_im); - } -#endif // yyyAVX2- -} - -/* see inner.h */ -TARGET_AVX2 -void -Zf(poly_split_fft)( - fpr *restrict f0, fpr *restrict f1, - const fpr *restrict f, unsigned logn) -{ - /* - * The FFT representation we use is in bit-reversed order - * (element i contains f(w^(rev(i))), where rev() is the - * bit-reversal function over the ring degree. This changes - * indexes with regards to the Falcon specification. - */ - size_t n, hn, qn, u; - - n = (size_t)1 << logn; - hn = n >> 1; - qn = hn >> 1; - -#if FALCON_AVX2 // yyyAVX2+1 - if (n >= 8) { - __m256d half, sv; - - half = _mm256_set1_pd(0.5); - sv = _mm256_set_pd(-0.0, 0.0, -0.0, 0.0); - for (u = 0; u < qn; u += 2) { - __m256d ab_re, ab_im, ff0, ff1, ff2, ff3, gmt; - - ab_re = _mm256_loadu_pd(&f[(u << 1)].v); - ab_im = _mm256_loadu_pd(&f[(u << 1) + hn].v); - ff0 = _mm256_mul_pd(_mm256_hadd_pd(ab_re, ab_im), half); - ff0 = _mm256_permute4x64_pd(ff0, 0xD8); - _mm_storeu_pd(&f0[u].v, - _mm256_extractf128_pd(ff0, 0)); - _mm_storeu_pd(&f0[u + qn].v, - _mm256_extractf128_pd(ff0, 1)); - - ff1 = _mm256_mul_pd(_mm256_hsub_pd(ab_re, ab_im), half); - gmt = _mm256_loadu_pd(&fpr_gm_tab[(u + hn) << 1].v); - ff2 = _mm256_shuffle_pd(ff1, ff1, 0x5); - ff3 = _mm256_hadd_pd( - _mm256_mul_pd(ff1, gmt), - _mm256_xor_pd(_mm256_mul_pd(ff2, gmt), sv)); - ff3 = _mm256_permute4x64_pd(ff3, 0xD8); - _mm_storeu_pd(&f1[u].v, - _mm256_extractf128_pd(ff3, 0)); - _mm_storeu_pd(&f1[u + qn].v, - _mm256_extractf128_pd(ff3, 1)); - } - } else { - f0[0] = f[0]; - f1[0] = f[hn]; - - for (u = 0; u < qn; u ++) { - fpr a_re, a_im, b_re, b_im; - fpr t_re, t_im; - - a_re = f[(u << 1) + 0]; - a_im = f[(u << 1) + 0 + hn]; - b_re = f[(u << 1) + 1]; - b_im = f[(u << 1) + 1 + hn]; - - FPC_ADD(t_re, t_im, a_re, a_im, b_re, b_im); - f0[u] = fpr_half(t_re); - f0[u + qn] = fpr_half(t_im); - - FPC_SUB(t_re, t_im, a_re, a_im, b_re, b_im); - FPC_MUL(t_re, t_im, t_re, t_im, - fpr_gm_tab[((u + hn) << 1) + 0], - fpr_neg(fpr_gm_tab[((u + hn) << 1) + 1])); - f1[u] = fpr_half(t_re); - f1[u + qn] = fpr_half(t_im); - } - } -#else // yyyAVX2+0 - /* - * We process complex values by pairs. For logn = 1, there is only - * one complex value (the other one is the implicit conjugate), - * so we add the two lines below because the loop will be - * skipped. - */ - f0[0] = f[0]; - f1[0] = f[hn]; - - for (u = 0; u < qn; u ++) { - fpr a_re, a_im, b_re, b_im; - fpr t_re, t_im; - - a_re = f[(u << 1) + 0]; - a_im = f[(u << 1) + 0 + hn]; - b_re = f[(u << 1) + 1]; - b_im = f[(u << 1) + 1 + hn]; - - FPC_ADD(t_re, t_im, a_re, a_im, b_re, b_im); - f0[u] = fpr_half(t_re); - f0[u + qn] = fpr_half(t_im); - - FPC_SUB(t_re, t_im, a_re, a_im, b_re, b_im); - FPC_MUL(t_re, t_im, t_re, t_im, - fpr_gm_tab[((u + hn) << 1) + 0], - fpr_neg(fpr_gm_tab[((u + hn) << 1) + 1])); - f1[u] = fpr_half(t_re); - f1[u + qn] = fpr_half(t_im); - } -#endif // yyyAVX2- -} - -/* see inner.h */ -TARGET_AVX2 -void -Zf(poly_merge_fft)( - fpr *restrict f, - const fpr *restrict f0, const fpr *restrict f1, unsigned logn) -{ - size_t n, hn, qn, u; - - n = (size_t)1 << logn; - hn = n >> 1; - qn = hn >> 1; - -#if FALCON_AVX2 // yyyAVX2+1 - if (n >= 16) { - for (u = 0; u < qn; u += 4) { - __m256d a_re, a_im, b_re, b_im, c_re, c_im; - __m256d gm1, gm2, g_re, g_im; - __m256d t_re, t_im, u_re, u_im; - __m256d tu1_re, tu2_re, tu1_im, tu2_im; - - a_re = _mm256_loadu_pd(&f0[u].v); - a_im = _mm256_loadu_pd(&f0[u + qn].v); - c_re = _mm256_loadu_pd(&f1[u].v); - c_im = _mm256_loadu_pd(&f1[u + qn].v); - - gm1 = _mm256_loadu_pd(&fpr_gm_tab[(u + hn) << 1].v); - gm2 = _mm256_loadu_pd(&fpr_gm_tab[(u + 2 + hn) << 1].v); - g_re = _mm256_unpacklo_pd(gm1, gm2); - g_im = _mm256_unpackhi_pd(gm1, gm2); - g_re = _mm256_permute4x64_pd(g_re, 0xD8); - g_im = _mm256_permute4x64_pd(g_im, 0xD8); - - b_re = FMSUB( - c_re, g_re, _mm256_mul_pd(c_im, g_im)); - b_im = FMADD( - c_re, g_im, _mm256_mul_pd(c_im, g_re)); - - t_re = _mm256_add_pd(a_re, b_re); - t_im = _mm256_add_pd(a_im, b_im); - u_re = _mm256_sub_pd(a_re, b_re); - u_im = _mm256_sub_pd(a_im, b_im); - - tu1_re = _mm256_unpacklo_pd(t_re, u_re); - tu2_re = _mm256_unpackhi_pd(t_re, u_re); - tu1_im = _mm256_unpacklo_pd(t_im, u_im); - tu2_im = _mm256_unpackhi_pd(t_im, u_im); - _mm256_storeu_pd(&f[(u << 1)].v, - _mm256_permute2f128_pd(tu1_re, tu2_re, 0x20)); - _mm256_storeu_pd(&f[(u << 1) + 4].v, - _mm256_permute2f128_pd(tu1_re, tu2_re, 0x31)); - _mm256_storeu_pd(&f[(u << 1) + hn].v, - _mm256_permute2f128_pd(tu1_im, tu2_im, 0x20)); - _mm256_storeu_pd(&f[(u << 1) + 4 + hn].v, - _mm256_permute2f128_pd(tu1_im, tu2_im, 0x31)); - } - } else { - f[0] = f0[0]; - f[hn] = f1[0]; - - for (u = 0; u < qn; u ++) { - fpr a_re, a_im, b_re, b_im; - fpr t_re, t_im; - - a_re = f0[u]; - a_im = f0[u + qn]; - FPC_MUL(b_re, b_im, f1[u], f1[u + qn], - fpr_gm_tab[((u + hn) << 1) + 0], - fpr_gm_tab[((u + hn) << 1) + 1]); - FPC_ADD(t_re, t_im, a_re, a_im, b_re, b_im); - f[(u << 1) + 0] = t_re; - f[(u << 1) + 0 + hn] = t_im; - FPC_SUB(t_re, t_im, a_re, a_im, b_re, b_im); - f[(u << 1) + 1] = t_re; - f[(u << 1) + 1 + hn] = t_im; - } - } -#else // yyyAVX2+0 - /* - * An extra copy to handle the special case logn = 1. - */ - f[0] = f0[0]; - f[hn] = f1[0]; - - for (u = 0; u < qn; u ++) { - fpr a_re, a_im, b_re, b_im; - fpr t_re, t_im; - - a_re = f0[u]; - a_im = f0[u + qn]; - FPC_MUL(b_re, b_im, f1[u], f1[u + qn], - fpr_gm_tab[((u + hn) << 1) + 0], - fpr_gm_tab[((u + hn) << 1) + 1]); - FPC_ADD(t_re, t_im, a_re, a_im, b_re, b_im); - f[(u << 1) + 0] = t_re; - f[(u << 1) + 0 + hn] = t_im; - FPC_SUB(t_re, t_im, a_re, a_im, b_re, b_im); - f[(u << 1) + 1] = t_re; - f[(u << 1) + 1 + hn] = t_im; - } -#endif // yyyAVX2- -} diff --git a/falcon/fpr.c b/falcon/fpr.c deleted file mode 100644 index eb23a44..0000000 --- a/falcon/fpr.c +++ /dev/null @@ -1,3460 +0,0 @@ -/* - * Floating-point operations. - * - * This file implements the non-inline functions declared in - * fpr.h, as well as the constants for FFT / iFFT. - * - * ==========================(LICENSE BEGIN)============================ - * - * Copyright (c) 2017-2019 Falcon Project - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * ===========================(LICENSE END)============================= - * - * @author Thomas Pornin - */ - -#include "inner.h" - -#if FALCON_FPEMU // yyyFPEMU+1 - -/* - * Normalize a provided unsigned integer to the 2^63..2^64-1 range by - * left-shifting it if necessary. The exponent e is adjusted accordingly - * (i.e. if the value was left-shifted by n bits, then n is subtracted - * from e). If source m is 0, then it remains 0, but e is altered. - * Both m and e must be simple variables (no expressions allowed). - */ -#define FPR_NORM64(m, e) do { \ - uint32_t nt; \ - \ - (e) -= 63; \ - \ - nt = (uint32_t)((m) >> 32); \ - nt = (nt | -nt) >> 31; \ - (m) ^= ((m) ^ ((m) << 32)) & ((uint64_t)nt - 1); \ - (e) += (int)(nt << 5); \ - \ - nt = (uint32_t)((m) >> 48); \ - nt = (nt | -nt) >> 31; \ - (m) ^= ((m) ^ ((m) << 16)) & ((uint64_t)nt - 1); \ - (e) += (int)(nt << 4); \ - \ - nt = (uint32_t)((m) >> 56); \ - nt = (nt | -nt) >> 31; \ - (m) ^= ((m) ^ ((m) << 8)) & ((uint64_t)nt - 1); \ - (e) += (int)(nt << 3); \ - \ - nt = (uint32_t)((m) >> 60); \ - nt = (nt | -nt) >> 31; \ - (m) ^= ((m) ^ ((m) << 4)) & ((uint64_t)nt - 1); \ - (e) += (int)(nt << 2); \ - \ - nt = (uint32_t)((m) >> 62); \ - nt = (nt | -nt) >> 31; \ - (m) ^= ((m) ^ ((m) << 2)) & ((uint64_t)nt - 1); \ - (e) += (int)(nt << 1); \ - \ - nt = (uint32_t)((m) >> 63); \ - (m) ^= ((m) ^ ((m) << 1)) & ((uint64_t)nt - 1); \ - (e) += (int)(nt); \ - } while (0) - -#if FALCON_ASM_CORTEXM4 // yyyASM_CORTEXM4+1 - -__attribute__((naked)) -fpr -fpr_scaled(int64_t i __attribute__((unused)), int sc __attribute__((unused))) -{ - __asm__ ( - "push { r4, r5, r6, lr }\n\t" - "\n\t" - "@ Input i is in r0:r1, and sc in r2.\n\t" - "@ Extract the sign bit, and compute the absolute value.\n\t" - "@ -> sign bit in r3, with value 0 or -1\n\t" - "asrs r3, r1, #31\n\t" - "eors r0, r3\n\t" - "eors r1, r3\n\t" - "subs r0, r3\n\t" - "sbcs r1, r3\n\t" - "\n\t" - "@ Scale exponent to account for the encoding; if the source is\n\t" - "@ zero or if the scaled exponent is negative, it is set to 32.\n\t" - "addw r2, r2, #1022\n\t" - "orrs r4, r0, r1\n\t" - "bics r4, r4, r2, asr #31\n\t" - "rsbs r5, r4, #0\n\t" - "orrs r4, r5\n\t" - "ands r2, r2, r4, asr #31\n\t" - "adds r2, #32\n\t" - "\n\t" - "@ Normalize value to a full 64-bit width, by shifting it left.\n\t" - "@ The shift count is subtracted from the exponent (in r2).\n\t" - "@ If the mantissa is 0, the exponent is set to 0.\n\t" - "\n\t" - "@ If top word is 0, replace with low word; otherwise, add 32 to\n\t" - "@ the exponent.\n\t" - "rsbs r4, r1, #0\n\t" - "orrs r4, r1\n\t" - "eors r5, r0, r1\n\t" - "bics r5, r5, r4, asr #31\n\t" - "eors r1, r5\n\t" - "ands r0, r0, r4, asr #31\n\t" - "lsrs r4, r4, #31\n\t" - "adds r2, r2, r4, lsl #5\n\t" - "\n\t" - "@ Count leading zeros of r1 to finish the shift.\n\t" - "clz r4, r1\n\t" - "subs r2, r4\n\t" - "rsbs r5, r4, #32\n\t" - "lsls r1, r4\n\t" - "lsrs r5, r0, r5\n\t" - "lsls r0, r4\n\t" - "orrs r1, r5\n\t" - "\n\t" - "@ Clear the top bit; we know it's a 1 (unless the whole mantissa\n\t" - "@ was zero, but then it's still OK to clear it)\n\t" - "bfc r1, #31, #1\n\t" - "\n\t" - "@ Now shift right the value by 11 bits; this puts the value in\n\t" - "@ the 2^52..2^53-1 range. We also keep a copy of the pre-shift\n\t" - "@ low bits in r5.\n\t" - "movs r5, r0\n\t" - "lsrs r0, #11\n\t" - "orrs r0, r0, r1, lsl #21\n\t" - "lsrs r1, #11\n\t" - "\n\t" - "@ Also plug the exponent at the right place. This must be done\n\t" - "@ now so that, in case the rounding creates a carry, that carry\n\t" - "@ adds to the exponent, which would be exactly what we want at\n\t" - "@ that point.\n\t" - "orrs r1, r1, r2, lsl #20\n\t" - "\n\t" - "@ Rounding: we must add 1 to the mantissa in the following cases:\n\t" - "@ - bits 11 to 9 of r5 are '011', '110' or '111'\n\t" - "@ - bits 11 to 9 of r5 are '010' and one of the\n\t" - "@ bits 0 to 8 is non-zero\n\t" - "ubfx r6, r5, #0, #9\n\t" - "addw r6, r6, #511\n\t" - "orrs r5, r6\n\t" - "\n\t" - "ubfx r5, r5, #9, #3\n\t" - "movs r6, #0xC8\n\t" - "lsrs r6, r5\n\t" - "ands r6, #1\n\t" - "adds r0, r6\n\t" - "adcs r1, #0\n\t" - "\n\t" - "@ Put back the sign.\n\t" - "orrs r1, r1, r3, lsl #31\n\t" - "\n\t" - "pop { r4, r5, r6, pc}\n\t" - ); -} - -#else // yyyASM_CORTEXM4+0 - -fpr -fpr_scaled(int64_t i, int sc) -{ - /* - * To convert from int to float, we have to do the following: - * 1. Get the absolute value of the input, and its sign - * 2. Shift right or left the value as appropriate - * 3. Pack the result - * - * We can assume that the source integer is not -2^63. - */ - int s, e; - uint32_t t; - uint64_t m; - - /* - * Extract sign bit. - * We have: -i = 1 + ~i - */ - s = (int)((uint64_t)i >> 63); - i ^= -(int64_t)s; - i += s; - - /* - * For now we suppose that i != 0. - * Otherwise, we set m to i and left-shift it as much as needed - * to get a 1 in the top bit. We can do that in a logarithmic - * number of conditional shifts. - */ - m = (uint64_t)i; - e = 9 + sc; - FPR_NORM64(m, e); - - /* - * Now m is in the 2^63..2^64-1 range. We must divide it by 512; - * if one of the dropped bits is a 1, this should go into the - * "sticky bit". - */ - m |= ((uint32_t)m & 0x1FF) + 0x1FF; - m >>= 9; - - /* - * Corrective action: if i = 0 then all of the above was - * incorrect, and we clamp e and m down to zero. - */ - t = (uint32_t)((uint64_t)(i | -i) >> 63); - m &= -(uint64_t)t; - e &= -(int)t; - - /* - * Assemble back everything. The FPR() function will handle cases - * where e is too low. - */ - return FPR(s, e, m); -} - -#endif // yyyASM_CORTEXM4- - -#if FALCON_ASM_CORTEXM4 // yyyASM_CORTEXM4+1 - -// yyyPQCLEAN+0 -#if 0 -/* Debug code -- To get a printout of registers from a specific point - in ARM Cortex M4 assembly code, uncomment this code and add a - "bl DEBUG" call where wished for. */ - -void -print_regs(uint32_t *rr, uint32_t flags) -{ - int i; - extern int printf(const char *fmt, ...); - - printf("\nRegs:\n"); - for (i = 0; i < 7; i ++) { - int j; - - j = i + 7; - printf(" %2d = %08X %2d = %08X\n", i, rr[i], j, rr[j]); - } - printf(" flags = %08X ", flags); - if ((flags >> 31) & 1) { - printf("N"); - } - if ((flags >> 30) & 1) { - printf("Z"); - } - if ((flags >> 29) & 1) { - printf("C"); - } - if ((flags >> 28) & 1) { - printf("V"); - } - if ((flags >> 27) & 1) { - printf("Q"); - } - printf("\n"); -} - -__attribute__((naked)) -void -DEBUG(void) -{ - __asm__ ( - "push { r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, lr }\n\t" - "mov r0, sp\n\t" - "mrs r1, apsr\n\t" - "bl print_regs\n\t" - "pop { r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, pc }\n\t" - ); -} -#endif -// yyyPQCLEAN- - -__attribute__((naked)) -fpr -fpr_add(fpr x __attribute__((unused)), fpr y __attribute__((unused))) -{ - __asm__ ( - "push { r4, r5, r6, r7, r8, r10, r11, lr }\n\t" - "\n\t" - "@ Make sure that the first operand (x) has the larger absolute\n\t" - "@ value. This guarantees that the exponent of y is less than\n\t" - "@ or equal to the exponent of x, and, if they are equal, then\n\t" - "@ the mantissa of y will not be greater than the mantissa of x.\n\t" - "@ However, if absolute values are equal and the sign of x is 1,\n\t" - "@ then we want to also swap the values.\n\t" - "ubfx r4, r1, #0, #31 @ top word without sign bit\n\t" - "ubfx r5, r3, #0, #31 @ top word without sign bit\n\t" - "subs r7, r0, r2 @ difference in r7:r4\n\t" - "sbcs r4, r5\n\t" - "orrs r7, r4\n\t" - "rsbs r5, r7, #0\n\t" - "orrs r7, r5 @ bit 31 of r7 is 0 iff difference is zero\n\t" - "bics r6, r1, r7\n\t" - "orrs r6, r4 @ bit 31 of r6 is 1 iff the swap must be done\n\t" - "\n\t" - "@ Conditional swap\n\t" - "eors r4, r0, r2\n\t" - "eors r5, r1, r3\n\t" - "ands r4, r4, r6, asr #31\n\t" - "ands r5, r5, r6, asr #31\n\t" - "eors r0, r4\n\t" - "eors r1, r5\n\t" - "eors r2, r4\n\t" - "eors r3, r5\n\t" - "\n\t" - "@ Extract mantissa of x into r0:r1, exponent in r4, sign in r5\n\t" - "ubfx r4, r1, #20, #11 @ Exponent in r4 (without sign)\n\t" - "addw r5, r4, #2047 @ Get a carry to test r4 for zero\n\t" - "lsrs r5, #11 @ r5 is the mantissa implicit high bit\n\t" - "bfc r1, #20, #11 @ Clear exponent bits (not the sign)\n\t" - "orrs r1, r1, r5, lsl #20 @ Set mantissa high bit\n\t" - "asrs r5, r1, #31 @ Get sign bit (sign-extended)\n\t" - "bfc r1, #31, #1 @ Clear the sign bit\n\t" - "\n\t" - "@ Extract mantissa of y into r2:r3, exponent in r6, sign in r7\n\t" - "ubfx r6, r3, #20, #11 @ Exponent in r6 (without sign)\n\t" - "addw r7, r6, #2047 @ Get a carry to test r6 for zero\n\t" - "lsrs r7, #11 @ r7 is the mantissa implicit high bit\n\t" - "bfc r3, #20, #11 @ Clear exponent bits (not the sign)\n\t" - "orrs r3, r3, r7, lsl #20 @ Set mantissa high bit\n\t" - "asrs r7, r3, #31 @ Get sign bit (sign-extended)\n\t" - "bfc r3, #31, #1 @ Clear the sign bit\n\t" - "\n\t" - "@ Scale mantissas up by three bits.\n\t" - "lsls r1, #3\n\t" - "orrs r1, r1, r0, lsr #29\n\t" - "lsls r0, #3\n\t" - "lsls r3, #3\n\t" - "orrs r3, r3, r2, lsr #29\n\t" - "lsls r2, #3\n\t" - "\n\t" - "@ x: exponent=r4, sign=r5, mantissa=r0:r1 (scaled up 3 bits)\n\t" - "@ y: exponent=r6, sign=r7, mantissa=r2:r3 (scaled up 3 bits)\n\t" - "\n\t" - "@ At that point, the exponent of x (in r4) is larger than that\n\t" - "@ of y (in r6). The difference is the amount of shifting that\n\t" - "@ should be done on y. If that amount is larger than 59 then\n\t" - "@ we clamp y to 0. We won't need y's exponent beyond that point,\n\t" - "@ so we store that shift count in r6.\n\t" - "subs r6, r4, r6\n\t" - "subs r8, r6, #60\n\t" - "ands r2, r2, r8, asr #31\n\t" - "ands r3, r3, r8, asr #31\n\t" - "\n\t" - "@ Shift right r2:r3 by r6 bits. The shift count is in the 0..59\n\t" - "@ range. r11 will be non-zero if and only if some non-zero bits\n\t" - "@ were dropped.\n\t" - "subs r8, r6, #32\n\t" - "bics r11, r2, r8, asr #31\n\t" - "ands r2, r2, r8, asr #31\n\t" - "bics r10, r3, r8, asr #31\n\t" - "orrs r2, r2, r10\n\t" - "ands r3, r3, r8, asr #31\n\t" - "ands r6, r6, #31\n\t" - "rsbs r8, r6, #32\n\t" - "lsls r10, r2, r8\n\t" - "orrs r11, r11, r10\n\t" - "lsrs r2, r2, r6\n\t" - "lsls r10, r3, r8\n\t" - "orrs r2, r2, r10\n\t" - "lsrs r3, r3, r6\n\t" - "\n\t" - "@ If r11 is non-zero then some non-zero bit was dropped and the\n\t" - "@ low bit of r2 must be forced to 1 ('sticky bit').\n\t" - "rsbs r6, r11, #0\n\t" - "orrs r6, r6, r11\n\t" - "orrs r2, r2, r6, lsr #31\n\t" - "\n\t" - "@ x: exponent=r4, sign=r5, mantissa=r0:r1 (scaled up 3 bits)\n\t" - "@ y: sign=r7, value=r2:r3 (scaled to same exponent as x)\n\t" - "\n\t" - "@ If x and y don't have the same sign, then we should negate r2:r3\n\t" - "@ (i.e. subtract the mantissa instead of adding it). Signs of x\n\t" - "@ and y are in r5 and r7, as full-width words. We won't need r7\n\t" - "@ afterwards.\n\t" - "eors r7, r5 @ r7 = -1 if y must be negated, 0 otherwise\n\t" - "eors r2, r7\n\t" - "eors r3, r7\n\t" - "subs r2, r7\n\t" - "sbcs r3, r7\n\t" - "\n\t" - "@ r2:r3 has been shifted, we can add to r0:r1.\n\t" - "adds r0, r2\n\t" - "adcs r1, r3\n\t" - "\n\t" - "@ result: exponent=r4, sign=r5, mantissa=r0:r1 (scaled up 3 bits)\n\t" - "\n\t" - "@ Normalize the result with some left-shifting to full 64-bit\n\t" - "@ width. Shift count goes to r2, and exponent (r4) is adjusted.\n\t" - "clz r2, r0\n\t" - "clz r3, r1\n\t" - "sbfx r6, r3, #5, #1\n\t" - "ands r2, r6\n\t" - "adds r2, r2, r3\n\t" - "subs r4, r4, r2\n\t" - "\n\t" - "@ Shift r0:r1 to the left by r2 bits.\n\t" - "subs r7, r2, #32\n\t" - "lsls r7, r0, r7\n\t" - "lsls r1, r1, r2\n\t" - "rsbs r6, r2, #32\n\t" - "orrs r1, r1, r7\n\t" - "lsrs r6, r0, r6\n\t" - "orrs r1, r1, r6\n\t" - "lsls r0, r0, r2\n\t" - "\n\t" - "@ The exponent of x was in r4. The left-shift operation has\n\t" - "@ subtracted some value from it, 8 in case the result has the\n\t" - "@ same exponent as x. However, the high bit of the mantissa will\n\t" - "@ add 1 to the exponent, so we only add back 7 (the exponent is\n\t" - "@ added in because rounding might have produced a carry, which\n\t" - "@ should then spill into the exponent).\n\t" - "adds r4, #7\n\t" - "\n\t" - "@ If the mantissa new mantissa is non-zero, then its bit 63 is\n\t" - "@ non-zero (thanks to the normalizing shift). Otherwise, that bit\n\t" - "@ is zero, and we should then set the exponent to zero as well.\n\t" - "ands r4, r4, r1, asr #31\n\t" - "\n\t" - "@ Shrink back the value to a 52-bit mantissa. This requires\n\t" - "@ right-shifting by 11 bits; we keep a copy of the pre-shift\n\t" - "@ low word in r3.\n\t" - "movs r3, r0\n\t" - "lsrs r0, #11\n\t" - "orrs r0, r0, r1, lsl #21\n\t" - "lsrs r1, #11\n\t" - "\n\t" - "@ Apply rounding.\n\t" - "ubfx r6, r3, #0, #9\n\t" - "addw r6, r6, #511\n\t" - "orrs r3, r6\n\t" - "ubfx r3, r3, #9, #3\n\t" - "movs r6, #0xC8\n\t" - "lsrs r6, r3\n\t" - "ands r6, #1\n\t" - "adds r0, r6\n\t" - "adcs r1, #0\n\t" - "\n\t" - "@Plug in the exponent with an addition.\n\t" - "adds r1, r1, r4, lsl #20\n\t" - "\n\t" - "@ If the new exponent is negative or zero, then it underflowed\n\t" - "@ and we must clear the whole mantissa and exponent.\n\t" - "rsbs r4, r4, #0\n\t" - "ands r0, r0, r4, asr #31\n\t" - "ands r1, r1, r4, asr #31\n\t" - "\n\t" - "@ Put back the sign. This is the sign of x: thanks to the\n\t" - "@ conditional swap at the start, this is always correct.\n\t" - "bfi r1, r5, #31, #1\n\t" - "\n\t" - "pop { r4, r5, r6, r7, r8, r10, r11, pc }\n\t" - ); -} - -#else // yyyASM_CORTEXM4+0 - -fpr -fpr_add(fpr x, fpr y) -{ - uint64_t m, xu, yu, za; - uint32_t cs; - int ex, ey, sx, sy, cc; - - /* - * Make sure that the first operand (x) has the larger absolute - * value. This guarantees that the exponent of y is less than - * or equal to the exponent of x, and, if they are equal, then - * the mantissa of y will not be greater than the mantissa of x. - * - * After this swap, the result will have the sign x, except in - * the following edge case: abs(x) = abs(y), and x and y have - * opposite sign bits; in that case, the result shall be +0 - * even if the sign bit of x is 1. To handle this case properly, - * we do the swap is abs(x) = abs(y) AND the sign of x is 1. - */ - m = ((uint64_t)1 << 63) - 1; - za = (x & m) - (y & m); - cs = (uint32_t)(za >> 63) - | ((1U - (uint32_t)(-za >> 63)) & (uint32_t)(x >> 63)); - m = (x ^ y) & -(uint64_t)cs; - x ^= m; - y ^= m; - - /* - * Extract sign bits, exponents and mantissas. The mantissas are - * scaled up to 2^55..2^56-1, and the exponent is unbiased. If - * an operand is zero, its mantissa is set to 0 at this step, and - * its exponent will be -1078. - */ - ex = (int)(x >> 52); - sx = ex >> 11; - ex &= 0x7FF; - m = (uint64_t)(uint32_t)((ex + 0x7FF) >> 11) << 52; - xu = ((x & (((uint64_t)1 << 52) - 1)) | m) << 3; - ex -= 1078; - ey = (int)(y >> 52); - sy = ey >> 11; - ey &= 0x7FF; - m = (uint64_t)(uint32_t)((ey + 0x7FF) >> 11) << 52; - yu = ((y & (((uint64_t)1 << 52) - 1)) | m) << 3; - ey -= 1078; - - /* - * x has the larger exponent; hence, we only need to right-shift y. - * If the shift count is larger than 59 bits then we clamp the - * value to zero. - */ - cc = ex - ey; - yu &= -(uint64_t)((uint32_t)(cc - 60) >> 31); - cc &= 63; - - /* - * The lowest bit of yu is "sticky". - */ - m = fpr_ulsh(1, cc) - 1; - yu |= (yu & m) + m; - yu = fpr_ursh(yu, cc); - - /* - * If the operands have the same sign, then we add the mantissas; - * otherwise, we subtract the mantissas. - */ - xu += yu - ((yu << 1) & -(uint64_t)(sx ^ sy)); - - /* - * The result may be smaller, or slightly larger. We normalize - * it to the 2^63..2^64-1 range (if xu is zero, then it stays - * at zero). - */ - FPR_NORM64(xu, ex); - - /* - * Scale down the value to 2^54..s^55-1, handling the last bit - * as sticky. - */ - xu |= ((uint32_t)xu & 0x1FF) + 0x1FF; - xu >>= 9; - ex += 9; - - /* - * In general, the result has the sign of x. However, if the - * result is exactly zero, then the following situations may - * be encountered: - * x > 0, y = -x -> result should be +0 - * x < 0, y = -x -> result should be +0 - * x = +0, y = +0 -> result should be +0 - * x = -0, y = +0 -> result should be +0 - * x = +0, y = -0 -> result should be +0 - * x = -0, y = -0 -> result should be -0 - * - * But at the conditional swap step at the start of the - * function, we ensured that if abs(x) = abs(y) and the - * sign of x was 1, then x and y were swapped. Thus, the - * two following cases cannot actually happen: - * x < 0, y = -x - * x = -0, y = +0 - * In all other cases, the sign bit of x is conserved, which - * is what the FPR() function does. The FPR() function also - * properly clamps values to zero when the exponent is too - * low, but does not alter the sign in that case. - */ - return FPR(sx, ex, xu); -} - -#endif // yyyASM_CORTEXM4- - -#if FALCON_ASM_CORTEXM4 // yyyASM_CORTEXM4+1 - -__attribute__((naked)) -fpr -fpr_mul(fpr x __attribute__((unused)), fpr y __attribute__((unused))) -{ - __asm__ ( - "push { r4, r5, r6, r7, r8, r10, r11, lr }\n\t" - "\n\t" - "@ Extract mantissas: x.m = r4:r5, y.m = r6:r7\n\t" - "@ r4 and r6 contain only 25 bits each.\n\t" - "bics r4, r0, #0xFE000000\n\t" - "lsls r5, r1, #7\n\t" - "orrs r5, r5, r0, lsr #25\n\t" - "orrs r5, r5, #0x08000000\n\t" - "bics r5, r5, #0xF0000000\n\t" - "bics r6, r2, #0xFE000000\n\t" - "lsls r7, r3, #7\n\t" - "orrs r7, r7, r2, lsr #25\n\t" - "orrs r7, r7, #0x08000000\n\t" - "bics r7, r7, #0xF0000000\n\t" - "\n\t" - "@ Perform product. Values are in the 2^52..2^53-1 range, so\n\t" - "@ the product is at most 106-bit long. Of the low 50 bits,\n\t" - "@ we only want to know if they are all zeros or not. Here,\n\t" - "@ we get the top 56 bits in r10:r11, and r8 will be non-zero\n\t" - "@ if and only if at least one of the low 50 bits is non-zero.\n\t" - "umull r8, r10, r4, r6 @ x0*y0\n\t" - "lsls r10, #7\n\t" - "orrs r10, r10, r8, lsr #25\n\t" - "eors r11, r11\n\t" - "umlal r10, r11, r4, r7 @ x0*y1\n\t" - "umlal r10, r11, r5, r6 @ x1*y0\n\t" - "orrs r8, r8, r10, lsl #7\n\t" - "lsrs r10, #25\n\t" - "orrs r10, r10, r11, lsl #7\n\t" - "eors r11, r11\n\t" - "umlal r10, r11, r5, r7 @ x1*y1\n\t" - "\n\t" - "@ Now r0, r2, r4, r5, r6 and r7 are free.\n\t" - "@ If any of the low 50 bits was non-zero, then we force the\n\t" - "@ low bit of r10 to 1.\n\t" - "rsbs r4, r8, #0\n\t" - "orrs r8, r8, r4\n\t" - "orrs r10, r10, r8, lsr #31\n\t" - "\n\t" - "@ r8 is free.\n\t" - "@ r10:r11 contains the product in the 2^54..2^56-1 range. We\n\t" - "@ normalize it to 2^54..2^55-1 (into r6:r7) with a conditional\n\t" - "@ shift (low bit is sticky). r5 contains -1 if the shift was done,\n\t" - "@ 0 otherwise.\n\t" - "ands r6, r10, #1\n\t" - "lsrs r5, r11, #23\n\t" - "rsbs r5, r5, #0\n\t" - "orrs r6, r6, r10, lsr #1\n\t" - "orrs r6, r6, r11, lsl #31\n\t" - "lsrs r7, r11, #1\n\t" - "eors r10, r10, r6\n\t" - "eors r11, r11, r7\n\t" - "bics r10, r10, r5\n\t" - "bics r11, r11, r5\n\t" - "eors r6, r6, r10\n\t" - "eors r7, r7, r11\n\t" - "\n\t" - "@ Compute aggregate exponent: ex + ey - 1023 + w\n\t" - "@ (where w = 1 if the conditional shift was done, 0 otherwise)\n\t" - "@ But we subtract 1 because the injection of the mantissa high\n\t" - "@ bit will increment the exponent by 1.\n\t" - "lsls r0, r1, #1\n\t" - "lsls r2, r3, #1\n\t" - "lsrs r0, #21\n\t" - "addw r4, r0, #0x7FF @ save ex + 2047 in r4\n\t" - "lsrs r2, #21\n\t" - "addw r8, r2, #0x7FF @ save ey + 2047 in r8\n\t" - "adds r2, r0\n\t" - "subw r2, r2, #1024\n\t" - "subs r2, r5\n\t" - "\n\t" - "@ r5 is free.\n\t" - "@ Also, if either of the source exponents is 0, or the result\n\t" - "@ exponent is 0 or negative, then the result is zero and the\n\t" - "@ mantissa and the exponent shall be clamped to zero. Since\n\t" - "@ r2 contains the result exponent minus 1, we test on r2\n\t" - "@ being strictly negative.\n\t" - "ands r4, r8 @ if bit 11 = 0 then one of the exponents was 0\n\t" - "mvns r5, r2\n\t" - "ands r5, r5, r4, lsl #20\n\t" - "ands r2, r2, r5, asr #31\n\t" - "ands r6, r6, r5, asr #31\n\t" - "ands r7, r7, r5, asr #31\n\t" - "\n\t" - "@ Sign is the XOR of the sign of the operands. This is true in\n\t" - "@ all cases, including very small results (exponent underflow)\n\t" - "@ and zeros.\n\t" - "eors r1, r3\n\t" - "bfc r1, #0, #31\n\t" - "\n\t" - "@ Plug in the exponent.\n\t" - "bfi r1, r2, #20, #11\n\t" - "\n\t" - "@ r2 and r3 are free.\n\t" - "@ Shift back to the normal 53-bit mantissa, with rounding.\n\t" - "@ Mantissa goes into r0:r1. For r1, we must use an addition\n\t" - "@ because the rounding may have triggered a carry, that should\n\t" - "@ be added to the exponent.\n\t" - "movs r4, r6\n\t" - "lsrs r0, r6, #2\n\t" - "orrs r0, r0, r7, lsl #30\n\t" - "adds r1, r1, r7, lsr #2\n\t" - "ands r4, #0x7\n\t" - "movs r3, #0xC8\n\t" - "lsrs r3, r4\n\t" - "ands r3, #1\n\t" - "adds r0, r3\n\t" - "adcs r1, #0\n\t" - "\n\t" - "pop { r4, r5, r6, r7, r8, r10, r11, pc }\n\t" - ); -} - -#else // yyyASM_CORTEXM4+0 - -fpr -fpr_mul(fpr x, fpr y) -{ - uint64_t xu, yu, w, zu, zv; - uint32_t x0, x1, y0, y1, z0, z1, z2; - int ex, ey, d, e, s; - - /* - * Extract absolute values as scaled unsigned integers. We - * don't extract exponents yet. - */ - xu = (x & (((uint64_t)1 << 52) - 1)) | ((uint64_t)1 << 52); - yu = (y & (((uint64_t)1 << 52) - 1)) | ((uint64_t)1 << 52); - - /* - * We have two 53-bit integers to multiply; we need to split - * each into a lower half and a upper half. Moreover, we - * prefer to have lower halves to be of 25 bits each, for - * reasons explained later on. - */ - x0 = (uint32_t)xu & 0x01FFFFFF; - x1 = (uint32_t)(xu >> 25); - y0 = (uint32_t)yu & 0x01FFFFFF; - y1 = (uint32_t)(yu >> 25); - w = (uint64_t)x0 * (uint64_t)y0; - z0 = (uint32_t)w & 0x01FFFFFF; - z1 = (uint32_t)(w >> 25); - w = (uint64_t)x0 * (uint64_t)y1; - z1 += (uint32_t)w & 0x01FFFFFF; - z2 = (uint32_t)(w >> 25); - w = (uint64_t)x1 * (uint64_t)y0; - z1 += (uint32_t)w & 0x01FFFFFF; - z2 += (uint32_t)(w >> 25); - zu = (uint64_t)x1 * (uint64_t)y1; - z2 += (z1 >> 25); - z1 &= 0x01FFFFFF; - zu += z2; - - /* - * Since xu and yu are both in the 2^52..2^53-1 range, the - * product is in the 2^104..2^106-1 range. We first reassemble - * it and round it into the 2^54..2^56-1 range; the bottom bit - * is made "sticky". Since the low limbs z0 and z1 are 25 bits - * each, we just take the upper part (zu), and consider z0 and - * z1 only for purposes of stickiness. - * (This is the reason why we chose 25-bit limbs above.) - */ - zu |= ((z0 | z1) + 0x01FFFFFF) >> 25; - - /* - * We normalize zu to the 2^54..s^55-1 range: it could be one - * bit too large at this point. This is done with a conditional - * right-shift that takes into account the sticky bit. - */ - zv = (zu >> 1) | (zu & 1); - w = zu >> 55; - zu ^= (zu ^ zv) & -w; - - /* - * Get the aggregate scaling factor: - * - * - Each exponent is biased by 1023. - * - * - Integral mantissas are scaled by 2^52, hence an - * extra 52 bias for each exponent. - * - * - However, we right-shifted z by 50 bits, and then - * by 0 or 1 extra bit (depending on the value of w). - * - * In total, we must add the exponents, then subtract - * 2 * (1023 + 52), then add 50 + w. - */ - ex = (int)((x >> 52) & 0x7FF); - ey = (int)((y >> 52) & 0x7FF); - e = ex + ey - 2100 + (int)w; - - /* - * Sign bit is the XOR of the operand sign bits. - */ - s = (int)((x ^ y) >> 63); - - /* - * Corrective actions for zeros: if either of the operands is - * zero, then the computations above were wrong. Test for zero - * is whether ex or ey is zero. We just have to set the mantissa - * (zu) to zero, the FPR() function will normalize e. - */ - d = ((ex + 0x7FF) & (ey + 0x7FF)) >> 11; - zu &= -(uint64_t)d; - - /* - * FPR() packs the result and applies proper rounding. - */ - return FPR(s, e, zu); -} - -#endif // yyyASM_CORTEXM4- - -#if FALCON_ASM_CORTEXM4 // yyyASM_CORTEXM4+1 - -__attribute__((naked)) -fpr -fpr_div(fpr x __attribute__((unused)), fpr y __attribute__((unused))) -{ - __asm__ ( - "push { r4, r5, r6, r7, r8, r10, r11, lr }\n\t" - - "@ Extract mantissas of x and y, in r0:r4 and r2:r5, respectively.\n\t" - "@ We don't touch r1 and r3 as they contain the exponents and\n\t" - "@ signs, which we'll need later on.\n\t" - "ubfx r4, r1, #0, #20\n\t" - "ubfx r5, r3, #0, #20\n\t" - "orrs r4, r4, #0x00100000\n\t" - "orrs r5, r5, #0x00100000\n\t" - "\n\t" - "@ Perform bit-by-bit division. We want a 56-bit result in r8:r10\n\t" - "@ (low bit is 0). Bits come from the carry flag and are\n\t" - "@ injected with rrx, i.e. in position 31; we thus get bits in\n\t" - "@ the reverse order. Bits accumulate in r8; after the first 24\n\t" - "@ bits, we move the quotient bits to r10.\n\t" - "eors r8, r8\n\t" - "\n\t" - -#define DIVSTEP \ - "subs r6, r0, r2\n\t" \ - "sbcs r7, r4, r5\n\t" \ - "rrx r8, r8\n\t" \ - "ands r6, r2, r8, asr #31\n\t" \ - "ands r7, r5, r8, asr #31\n\t" \ - "subs r0, r6\n\t" \ - "sbcs r4, r7\n\t" \ - "adds r0, r0, r0\n\t" \ - "adcs r4, r4, r4\n\t" - -#define DIVSTEP4 DIVSTEP DIVSTEP DIVSTEP DIVSTEP -#define DIVSTEP8 DIVSTEP4 DIVSTEP4 - - DIVSTEP8 - DIVSTEP8 - DIVSTEP8 - - "\n\t" - "@ We have the first 24 bits of the quotient, move them to r10.\n\t" - "rbit r10, r8\n\t" - "\n\t" - - DIVSTEP8 - DIVSTEP8 - DIVSTEP8 - DIVSTEP4 DIVSTEP DIVSTEP DIVSTEP - -#undef DIVSTEP -#undef DIVSTEP4 -#undef DIVSTEP8 - - "\n\t" - "@ Lowest bit will be set if remainder is non-zero at this point\n\t" - "@ (this is the 'sticky' bit).\n\t" - "subs r0, #1\n\t" - "sbcs r4, #0\n\t" - "rrx r8, r8\n\t" - "\n\t" - "@ We now have the next (low) 32 bits of the quotient.\n\t" - "rbit r8, r8\n\t" - "\n\t" - "@ Since both operands had their top bit set, we know that the\n\t" - "@ result at this point is in 2^54..2^56-1. We scale it down\n\t" - "@ to 2^54..2^55-1 with a conditional shift. We also write the\n\t" - "@ result in r4:r5. If the shift is done, r6 will contain -1.\n\t" - "ands r4, r8, #1\n\t" - "lsrs r6, r10, #23\n\t" - "rsbs r6, r6, #0\n\t" - "orrs r4, r4, r8, lsr #1\n\t" - "orrs r4, r4, r10, lsl #31\n\t" - "lsrs r5, r10, #1\n\t" - "eors r8, r8, r4\n\t" - "eors r10, r10, r5\n\t" - "bics r8, r8, r6\n\t" - "bics r10, r10, r6\n\t" - "eors r4, r4, r8\n\t" - "eors r5, r5, r10\n\t" - "\n\t" - "@ Compute aggregate exponent: ex - ey + 1022 + w\n\t" - "@ (where w = 1 if the conditional shift was done, 0 otherwise)\n\t" - "@ But we subtract 1 because the injection of the mantissa high\n\t" - "@ bit will increment the exponent by 1.\n\t" - "lsls r0, r1, #1\n\t" - "lsls r2, r3, #1\n\t" - "lsrs r0, r0, #21\n\t" - "addw r7, r0, #0x7FF @ save ex + 2047 in r7\n\t" - "subs r0, r0, r2, lsr #21\n\t" - "addw r0, r0, #1021\n\t" - "subs r0, r6\n\t" - "\n\t" - "@ If the x operand was zero, then the computation was wrong and\n\t" - "@ the result is zero. Also, if the result exponent is zero or\n\t" - "@ negative, then the mantissa shall be clamped to zero. Since r0\n\t" - "@ contains the result exponent minus 1, we test on r0 being\n\t" - "@ strictly negative.\n\t" - "mvns r2, r0\n\t" - "ands r2, r2, r7, lsl #20\n\t" - "ands r0, r0, r2, asr #31\n\t" - "ands r4, r4, r2, asr #31\n\t" - "ands r5, r5, r2, asr #31\n\t" - "\n\t" - "@ Sign is the XOR of the sign of the operands. This is true in\n\t" - "@ all cases, including very small results (exponent underflow)\n\t" - "@ and zeros.\n\t" - "eors r1, r3\n\t" - "bfc r1, #0, #31\n\t" - "\n\t" - "@ Plug in the exponent.\n\t" - "bfi r1, r0, #20, #11\n\t" - "\n\t" - "@ Shift back to the normal 53-bit mantissa, with rounding.\n\t" - "@ Mantissa goes into r0:r1. For r1, we must use an addition\n\t" - "@ because the rounding may have triggered a carry, that should\n\t" - "@ be added to the exponent.\n\t" - "movs r6, r4\n\t" - "lsrs r0, r4, #2\n\t" - "orrs r0, r0, r5, lsl #30\n\t" - "adds r1, r1, r5, lsr #2\n\t" - "ands r6, #0x7\n\t" - "movs r3, #0xC8\n\t" - "lsrs r3, r6\n\t" - "ands r3, #1\n\t" - "adds r0, r3\n\t" - "adcs r1, #0\n\t" - "\n\t" - "pop { r4, r5, r6, r7, r8, r10, r11, pc }\n\t" - ); -} - -#else // yyyASM_CORTEXM4+0 - -fpr -fpr_div(fpr x, fpr y) -{ - uint64_t xu, yu, q, q2, w; - int i, ex, ey, e, d, s; - - /* - * Extract mantissas of x and y (unsigned). - */ - xu = (x & (((uint64_t)1 << 52) - 1)) | ((uint64_t)1 << 52); - yu = (y & (((uint64_t)1 << 52) - 1)) | ((uint64_t)1 << 52); - - /* - * Perform bit-by-bit division of xu by yu. We run it for 55 bits. - */ - q = 0; - for (i = 0; i < 55; i ++) { - /* - * If yu is less than or equal xu, then subtract it and - * push a 1 in the quotient; otherwise, leave xu unchanged - * and push a 0. - */ - uint64_t b; - - b = ((xu - yu) >> 63) - 1; - xu -= b & yu; - q |= b & 1; - xu <<= 1; - q <<= 1; - } - - /* - * We got 55 bits in the quotient, followed by an extra zero. We - * want that 56th bit to be "sticky": it should be a 1 if and - * only if the remainder (xu) is non-zero. - */ - q |= (xu | -xu) >> 63; - - /* - * Quotient is at most 2^56-1. Its top bit may be zero, but in - * that case the next-to-top bit will be a one, since the - * initial xu and yu were both in the 2^52..2^53-1 range. - * We perform a conditional shift to normalize q to the - * 2^54..2^55-1 range (with the bottom bit being sticky). - */ - q2 = (q >> 1) | (q & 1); - w = q >> 55; - q ^= (q ^ q2) & -w; - - /* - * Extract exponents to compute the scaling factor: - * - * - Each exponent is biased and we scaled them up by - * 52 bits; but these biases will cancel out. - * - * - The division loop produced a 55-bit shifted result, - * so we must scale it down by 55 bits. - * - * - If w = 1, we right-shifted the integer by 1 bit, - * hence we must add 1 to the scaling. - */ - ex = (int)((x >> 52) & 0x7FF); - ey = (int)((y >> 52) & 0x7FF); - e = ex - ey - 55 + (int)w; - - /* - * Sign is the XOR of the signs of the operands. - */ - s = (int)((x ^ y) >> 63); - - /* - * Corrective actions for zeros: if x = 0, then the computation - * is wrong, and we must clamp e and q to 0. We do not care - * about the case y = 0 (as per assumptions in this module, - * the caller does not perform divisions by zero). - */ - d = (ex + 0x7FF) >> 11; - s &= d; - e &= -d; - q &= -(uint64_t)d; - - /* - * FPR() packs the result and applies proper rounding. - */ - return FPR(s, e, q); -} - -#endif // yyyASM_CORTEXM4- - -#if FALCON_ASM_CORTEXM4 // yyyASM_CORTEXM4+1 - -__attribute__((naked)) -fpr -fpr_sqrt(fpr x __attribute__((unused))) -{ - __asm__ ( - "push { r4, r5, r6, r7, r8, r10, r11, lr }\n\t" - "\n\t" - "@ Extract mantissa (r0:r1) and exponent (r2). We assume that the\n\t" - "@ sign is positive. If the source is zero, then the mantissa is\n\t" - "@ set to 0.\n\t" - "lsrs r2, r1, #20\n\t" - "bfc r1, #20, #12\n\t" - "addw r3, r2, #0x7FF\n\t" - "subw r2, r2, #1023\n\t" - "lsrs r3, r3, #11\n\t" - "orrs r1, r1, r3, lsl #20\n\t" - "\n\t" - "@ If the exponent is odd, then multiply mantissa by 2 and subtract\n\t" - "@ 1 from the exponent.\n\t" - "ands r3, r2, #1\n\t" - "subs r2, r2, r3\n\t" - "rsbs r3, r3, #0\n\t" - "ands r4, r1, r3\n\t" - "ands r3, r0\n\t" - "adds r0, r3\n\t" - "adcs r1, r4\n\t" - "\n\t" - "@ Left-shift the mantissa by 9 bits to put it in the\n\t" - "@ 2^61..2^63-1 range (unless it is exactly 0).\n\t" - "lsls r1, r1, #9\n\t" - "orrs r1, r1, r0, lsr #23\n\t" - "lsls r0, r0, #9\n\t" - "\n\t" - "@ Compute the square root bit-by-bit.\n\t" - "@ There are 54 iterations; first 30 can work on top word only.\n\t" - "@ q = r3 (bit-reversed)\n\t" - "@ s = r5\n\t" - "eors r3, r3\n\t" - "eors r5, r5\n\t" - -#define SQRT_STEP_HI(bit) \ - "orrs r6, r5, #(1 << (" #bit "))\n\t" \ - "subs r7, r1, r6\n\t" \ - "rrx r3, r3\n\t" \ - "ands r6, r6, r3, asr #31\n\t" \ - "subs r1, r1, r6\n\t" \ - "lsrs r6, r3, #31\n\t" \ - "orrs r5, r5, r6, lsl #((" #bit ") + 1)\n\t" \ - "adds r0, r0\n\t" \ - "adcs r1, r1\n\t" - -#define SQRT_STEP_HIx5(b) \ - SQRT_STEP_HI((b)+4) \ - SQRT_STEP_HI((b)+3) \ - SQRT_STEP_HI((b)+2) \ - SQRT_STEP_HI((b)+1) \ - SQRT_STEP_HI(b) - - SQRT_STEP_HIx5(25) - SQRT_STEP_HIx5(20) - SQRT_STEP_HIx5(15) - SQRT_STEP_HIx5(10) - SQRT_STEP_HIx5(5) - SQRT_STEP_HIx5(0) - -#undef SQRT_STEP_HI -#undef SQRT_STEP_HIx5 - - "@ Top 30 bits of the result must be reversed: they were\n\t" - "@ accumulated with rrx (hence from the top bit).\n\t" - "rbit r3, r3\n\t" - "\n\t" - "@ For the next 24 iterations, we must use two-word operations.\n\t" - "@ bits of q now accumulate in r4\n\t" - "@ s is in r6:r5\n\t" - "eors r4, r4\n\t" - "eors r6, r6\n\t" - "\n\t" - "@ First iteration is special because the potential bit goes into\n\t" - "@ r5, not r6.\n\t" - "orrs r7, r6, #(1 << 31)\n\t" - "subs r8, r0, r7\n\t" - "sbcs r10, r1, r5\n\t" - "rrx r4, r4\n\t" - "ands r7, r7, r4, asr #31\n\t" - "ands r8, r5, r4, asr #31\n\t" - "subs r0, r0, r7\n\t" - "sbcs r1, r1, r8\n\t" - "lsrs r7, r4, #31\n\t" - "orrs r5, r5, r4, lsr #31\n\t" - "adds r0, r0\n\t" - "adcs r1, r1\n\t" - -#define SQRT_STEP_LO(bit) \ - "orrs r7, r6, #(1 << (" #bit "))\n\t" \ - "subs r8, r0, r7\n\t" \ - "sbcs r10, r1, r5\n\t" \ - "rrx r4, r4\n\t" \ - "ands r7, r7, r4, asr #31\n\t" \ - "ands r8, r5, r4, asr #31\n\t" \ - "subs r0, r0, r7\n\t" \ - "sbcs r1, r1, r8\n\t" \ - "lsrs r7, r4, #31\n\t" \ - "orrs r6, r6, r7, lsl #((" #bit ") + 1)\n\t" \ - "adds r0, r0\n\t" \ - "adcs r1, r1\n\t" - -#define SQRT_STEP_LOx4(b) \ - SQRT_STEP_LO((b)+3) \ - SQRT_STEP_LO((b)+2) \ - SQRT_STEP_LO((b)+1) \ - SQRT_STEP_LO(b) - - SQRT_STEP_LO(30) - SQRT_STEP_LO(29) - SQRT_STEP_LO(28) - SQRT_STEP_LOx4(24) - SQRT_STEP_LOx4(20) - SQRT_STEP_LOx4(16) - SQRT_STEP_LOx4(12) - SQRT_STEP_LOx4(8) - -#undef SQRT_STEP_LO -#undef SQRT_STEP_LOx4 - - "@ Put low 24 bits in the right order.\n\t" - "rbit r4, r4\n\t" - "\n\t" - "@ We have a 54-bit result; compute the 55-th bit as the 'sticky'\n\t" - "@ bit: it is non-zero if and only if r0:r1 is non-zero. We put the\n\t" - "@ three low bits (including the sticky bit) in r5.\n\t" - "orrs r0, r1\n\t" - "rsbs r1, r0, #0\n\t" - "orrs r0, r1\n\t" - "lsls r5, r4, #1\n\t" - "orrs r5, r5, r0, lsr #31\n\t" - "ands r5, #0x7\n\t" - "\n\t" - "@ Compute the rounding: r6 is set to 0 or 1, and will be added\n\t" - "@ to the mantissa.\n\t" - "movs r6, #0xC8\n\t" - "lsrs r6, r5\n\t" - "ands r6, #1\n\t" - "\n\t" - "@ Put the mantissa (53 bits, in the 2^52..2^53-1 range) in r0:r1\n\t" - "@ (rounding not applied yet).\n\t" - "lsrs r0, r4, #1\n\t" - "orrs r0, r0, r3, lsl #23\n\t" - "lsrs r1, r3, #9\n\t" - "\n\t" - "@ Compute new exponent. This is half the old one (then reencoded\n\t" - "@ by adding 1023). Exception: if the mantissa is zero, then the\n\t" - "@ encoded exponent is set to 0. At that point, if the mantissa\n\t" - "@ is non-zero, then its high bit (bit 52, i.e. bit 20 of r1) is\n\t" - "@ non-zero. Note that the exponent cannot go out of range.\n\t" - "lsrs r2, r2, #1\n\t" - "addw r2, r2, #1023\n\t" - "lsrs r5, r1, #20\n\t" - "rsbs r5, r5, #0\n\t" - "ands r2, r5\n\t" - "\n\t" - "@ Place exponent. This overwrites the high bit of the mantissa.\n\t" - "bfi r1, r2, #20, #11\n\t" - "\n\t" - "@ Apply rounding. This may create a carry that will spill into\n\t" - "@ the exponent, which is exactly what should be done in that case\n\t" - "@ (i.e. increment the exponent).\n\t" - "adds r0, r0, r6\n\t" - "adcs r1, r1, #0\n\t" - "\n\t" - "pop { r4, r5, r6, r7, r8, r10, r11, pc }\n\t" - ); -} - -#else // yyyASM_CORTEXM4+0 - -fpr -fpr_sqrt(fpr x) -{ - uint64_t xu, q, s, r; - int ex, e; - - /* - * Extract the mantissa and the exponent. We don't care about - * the sign: by assumption, the operand is nonnegative. - * We want the "true" exponent corresponding to a mantissa - * in the 1..2 range. - */ - xu = (x & (((uint64_t)1 << 52) - 1)) | ((uint64_t)1 << 52); - ex = (int)((x >> 52) & 0x7FF); - e = ex - 1023; - - /* - * If the exponent is odd, double the mantissa and decrement - * the exponent. The exponent is then halved to account for - * the square root. - */ - xu += xu & -(uint64_t)(e & 1); - e >>= 1; - - /* - * Double the mantissa. - */ - xu <<= 1; - - /* - * We now have a mantissa in the 2^53..2^55-1 range. It - * represents a value between 1 (inclusive) and 4 (exclusive) - * in fixed point notation (with 53 fractional bits). We - * compute the square root bit by bit. - */ - q = 0; - s = 0; - r = (uint64_t)1 << 53; - for (int i = 0; i < 54; i ++) { - uint64_t t, b; - - t = s + r; - b = ((xu - t) >> 63) - 1; - s += (r << 1) & b; - xu -= t & b; - q += r & b; - xu <<= 1; - r >>= 1; - } - - /* - * Now, q is a rounded-low 54-bit value, with a leading 1, - * 52 fractional digits, and an additional guard bit. We add - * an extra sticky bit to account for what remains of the operand. - */ - q <<= 1; - q |= (xu | -xu) >> 63; - - /* - * Result q is in the 2^54..2^55-1 range; we bias the exponent - * by 54 bits (the value e at that point contains the "true" - * exponent, but q is now considered an integer, i.e. scaled - * up. - */ - e -= 54; - - /* - * Corrective action for an operand of value zero. - */ - q &= -(uint64_t)((ex + 0x7FF) >> 11); - - /* - * Apply rounding and back result. - */ - return FPR(0, e, q); -} - -#endif // yyyASM_CORTEXM4- - -uint64_t -fpr_expm_p63(fpr x, fpr ccs) -{ - /* - * Polynomial approximation of exp(-x) is taken from FACCT: - * https://eprint.iacr.org/2018/1234 - * Specifically, values are extracted from the implementation - * referenced from the FACCT article, and available at: - * https://github.com/raykzhao/gaussian - * Here, the coefficients have been scaled up by 2^63 and - * converted to integers. - * - * Tests over more than 24 billions of random inputs in the - * 0..log(2) range have never shown a deviation larger than - * 2^(-50) from the true mathematical value. - */ - static const uint64_t C[] = { - 0x00000004741183A3u, - 0x00000036548CFC06u, - 0x0000024FDCBF140Au, - 0x0000171D939DE045u, - 0x0000D00CF58F6F84u, - 0x000680681CF796E3u, - 0x002D82D8305B0FEAu, - 0x011111110E066FD0u, - 0x0555555555070F00u, - 0x155555555581FF00u, - 0x400000000002B400u, - 0x7FFFFFFFFFFF4800u, - 0x8000000000000000u - }; - - uint64_t z, y; - unsigned u; - uint32_t z0, z1, y0, y1; - uint64_t a, b; - - y = C[0]; - z = (uint64_t)fpr_trunc(fpr_mul(x, fpr_ptwo63)) << 1; - for (u = 1; u < (sizeof C) / sizeof(C[0]); u ++) { - /* - * Compute product z * y over 128 bits, but keep only - * the top 64 bits. - * - * TODO: On some architectures/compilers we could use - * some intrinsics (__umulh() on MSVC) or other compiler - * extensions (unsigned __int128 on GCC / Clang) for - * improved speed; however, most 64-bit architectures - * also have appropriate IEEE754 floating-point support, - * which is better. - */ - uint64_t c; - - z0 = (uint32_t)z; - z1 = (uint32_t)(z >> 32); - y0 = (uint32_t)y; - y1 = (uint32_t)(y >> 32); - a = ((uint64_t)z0 * (uint64_t)y1) - + (((uint64_t)z0 * (uint64_t)y0) >> 32); - b = ((uint64_t)z1 * (uint64_t)y0); - c = (a >> 32) + (b >> 32); - c += (((uint64_t)(uint32_t)a + (uint64_t)(uint32_t)b) >> 32); - c += (uint64_t)z1 * (uint64_t)y1; - y = C[u] - c; - } - - /* - * The scaling factor must be applied at the end. Since y is now - * in fixed-point notation, we have to convert the factor to the - * same format, and do an extra integer multiplication. - */ - z = (uint64_t)fpr_trunc(fpr_mul(ccs, fpr_ptwo63)) << 1; - z0 = (uint32_t)z; - z1 = (uint32_t)(z >> 32); - y0 = (uint32_t)y; - y1 = (uint32_t)(y >> 32); - a = ((uint64_t)z0 * (uint64_t)y1) - + (((uint64_t)z0 * (uint64_t)y0) >> 32); - b = ((uint64_t)z1 * (uint64_t)y0); - y = (a >> 32) + (b >> 32); - y += (((uint64_t)(uint32_t)a + (uint64_t)(uint32_t)b) >> 32); - y += (uint64_t)z1 * (uint64_t)y1; - - return y; -} - -const fpr fpr_gm_tab[] = { - 0, 0, - 9223372036854775808U, 4607182418800017408U, - 4604544271217802189U, 4604544271217802189U, - 13827916308072577997U, 4604544271217802189U, - 4606496786581982534U, 4600565431771507043U, - 13823937468626282851U, 4606496786581982534U, - 4600565431771507043U, 4606496786581982534U, - 13829868823436758342U, 4600565431771507043U, - 4607009347991985328U, 4596196889902818827U, - 13819568926757594635U, 4607009347991985328U, - 4603179351334086856U, 4605664432017547683U, - 13829036468872323491U, 4603179351334086856U, - 4605664432017547683U, 4603179351334086856U, - 13826551388188862664U, 4605664432017547683U, - 4596196889902818827U, 4607009347991985328U, - 13830381384846761136U, 4596196889902818827U, - 4607139046673687846U, 4591727299969791020U, - 13815099336824566828U, 4607139046673687846U, - 4603889326261607894U, 4605137878724712257U, - 13828509915579488065U, 4603889326261607894U, - 4606118860100255153U, 4602163548591158843U, - 13825535585445934651U, 4606118860100255153U, - 4598900923775164166U, 4606794571824115162U, - 13830166608678890970U, 4598900923775164166U, - 4606794571824115162U, 4598900923775164166U, - 13822272960629939974U, 4606794571824115162U, - 4602163548591158843U, 4606118860100255153U, - 13829490896955030961U, 4602163548591158843U, - 4605137878724712257U, 4603889326261607894U, - 13827261363116383702U, 4605137878724712257U, - 4591727299969791020U, 4607139046673687846U, - 13830511083528463654U, 4591727299969791020U, - 4607171569234046334U, 4587232218149935124U, - 13810604255004710932U, 4607171569234046334U, - 4604224084862889120U, 4604849113969373103U, - 13828221150824148911U, 4604224084862889120U, - 4606317631232591731U, 4601373767755717824U, - 13824745804610493632U, 4606317631232591731U, - 4599740487990714333U, 4606655894547498725U, - 13830027931402274533U, 4599740487990714333U, - 4606912484326125783U, 4597922303871901467U, - 13821294340726677275U, 4606912484326125783U, - 4602805845399633902U, 4605900952042040894U, - 13829272988896816702U, 4602805845399633902U, - 4605409869824231233U, 4603540801876750389U, - 13826912838731526197U, 4605409869824231233U, - 4594454542771183930U, 4607084929468638487U, - 13830456966323414295U, 4594454542771183930U, - 4607084929468638487U, 4594454542771183930U, - 13817826579625959738U, 4607084929468638487U, - 4603540801876750389U, 4605409869824231233U, - 13828781906679007041U, 4603540801876750389U, - 4605900952042040894U, 4602805845399633902U, - 13826177882254409710U, 4605900952042040894U, - 4597922303871901467U, 4606912484326125783U, - 13830284521180901591U, 4597922303871901467U, - 4606655894547498725U, 4599740487990714333U, - 13823112524845490141U, 4606655894547498725U, - 4601373767755717824U, 4606317631232591731U, - 13829689668087367539U, 4601373767755717824U, - 4604849113969373103U, 4604224084862889120U, - 13827596121717664928U, 4604849113969373103U, - 4587232218149935124U, 4607171569234046334U, - 13830543606088822142U, 4587232218149935124U, - 4607179706000002317U, 4582730748936808062U, - 13806102785791583870U, 4607179706000002317U, - 4604386048625945823U, 4604698657331085206U, - 13828070694185861014U, 4604386048625945823U, - 4606409688975526202U, 4600971798440897930U, - 13824343835295673738U, 4606409688975526202U, - 4600154912527631775U, 4606578871587619388U, - 13829950908442395196U, 4600154912527631775U, - 4606963563043808649U, 4597061974398750563U, - 13820434011253526371U, 4606963563043808649U, - 4602994049708411683U, 4605784983948558848U, - 13829157020803334656U, 4602994049708411683U, - 4605539368864982914U, 4603361638657888991U, - 13826733675512664799U, 4605539368864982914U, - 4595327571478659014U, 4607049811591515049U, - 13830421848446290857U, 4595327571478659014U, - 4607114680469659603U, 4593485039402578702U, - 13816857076257354510U, 4607114680469659603U, - 4603716733069447353U, 4605276012900672507U, - 13828648049755448315U, 4603716733069447353U, - 4606012266443150634U, 4602550884377336506U, - 13825922921232112314U, 4606012266443150634U, - 4598476289818621559U, 4606856142606846307U, - 13830228179461622115U, 4598476289818621559U, - 4606727809065869586U, 4599322407794599425U, - 13822694444649375233U, 4606727809065869586U, - 4601771097584682078U, 4606220668805321205U, - 13829592705660097013U, 4601771097584682078U, - 4604995550503212910U, 4604058477489546729U, - 13827430514344322537U, 4604995550503212910U, - 4589965306122607094U, 4607158013403433018U, - 13830530050258208826U, 4589965306122607094U, - 4607158013403433018U, 4589965306122607094U, - 13813337342977382902U, 4607158013403433018U, - 4604058477489546729U, 4604995550503212910U, - 13828367587357988718U, 4604058477489546729U, - 4606220668805321205U, 4601771097584682078U, - 13825143134439457886U, 4606220668805321205U, - 4599322407794599425U, 4606727809065869586U, - 13830099845920645394U, 4599322407794599425U, - 4606856142606846307U, 4598476289818621559U, - 13821848326673397367U, 4606856142606846307U, - 4602550884377336506U, 4606012266443150634U, - 13829384303297926442U, 4602550884377336506U, - 4605276012900672507U, 4603716733069447353U, - 13827088769924223161U, 4605276012900672507U, - 4593485039402578702U, 4607114680469659603U, - 13830486717324435411U, 4593485039402578702U, - 4607049811591515049U, 4595327571478659014U, - 13818699608333434822U, 4607049811591515049U, - 4603361638657888991U, 4605539368864982914U, - 13828911405719758722U, 4603361638657888991U, - 4605784983948558848U, 4602994049708411683U, - 13826366086563187491U, 4605784983948558848U, - 4597061974398750563U, 4606963563043808649U, - 13830335599898584457U, 4597061974398750563U, - 4606578871587619388U, 4600154912527631775U, - 13823526949382407583U, 4606578871587619388U, - 4600971798440897930U, 4606409688975526202U, - 13829781725830302010U, 4600971798440897930U, - 4604698657331085206U, 4604386048625945823U, - 13827758085480721631U, 4604698657331085206U, - 4582730748936808062U, 4607179706000002317U, - 13830551742854778125U, 4582730748936808062U, - 4607181740574479067U, 4578227681973159812U, - 13801599718827935620U, 4607181740574479067U, - 4604465633578481725U, 4604621949701367983U, - 13827993986556143791U, 4604465633578481725U, - 4606453861145241227U, 4600769149537129431U, - 13824141186391905239U, 4606453861145241227U, - 4600360675823176935U, 4606538458821337243U, - 13829910495676113051U, 4600360675823176935U, - 4606987119037722413U, 4596629994023683153U, - 13820002030878458961U, 4606987119037722413U, - 4603087070374583113U, 4605725276488455441U, - 13829097313343231249U, 4603087070374583113U, - 4605602459698789090U, 4603270878689749849U, - 13826642915544525657U, 4605602459698789090U, - 4595762727260045105U, 4607030246558998647U, - 13830402283413774455U, 4595762727260045105U, - 4607127537664763515U, 4592606767730311893U, - 13815978804585087701U, 4607127537664763515U, - 4603803453461190356U, 4605207475328619533U, - 13828579512183395341U, 4603803453461190356U, - 4606066157444814153U, 4602357870542944470U, - 13825729907397720278U, 4606066157444814153U, - 4598688984595225406U, 4606826008603986804U, - 13830198045458762612U, 4598688984595225406U, - 4606761837001494797U, 4599112075441176914U, - 13822484112295952722U, 4606761837001494797U, - 4601967947786150793U, 4606170366472647579U, - 13829542403327423387U, 4601967947786150793U, - 4605067233569943231U, 4603974338538572089U, - 13827346375393347897U, 4605067233569943231U, - 4590846768565625881U, 4607149205763218185U, - 13830521242617993993U, 4590846768565625881U, - 4607165468267934125U, 4588998070480937184U, - 13812370107335712992U, 4607165468267934125U, - 4604141730443515286U, 4604922840319727473U, - 13828294877174503281U, 4604141730443515286U, - 4606269759522929756U, 4601573027631668967U, - 13824945064486444775U, 4606269759522929756U, - 4599531889160152938U, 4606692493141721470U, - 13830064529996497278U, 4599531889160152938U, - 4606884969294623682U, 4598262871476403630U, - 13821634908331179438U, 4606884969294623682U, - 4602710690099904183U, 4605957195211051218U, - 13829329232065827026U, 4602710690099904183U, - 4605343481119364930U, 4603629178146150899U, - 13827001215000926707U, 4605343481119364930U, - 4594016801320007031U, 4607100477024622401U, - 13830472513879398209U, 4594016801320007031U, - 4607068040143112603U, 4594891488091520602U, - 13818263524946296410U, 4607068040143112603U, - 4603451617570386922U, 4605475169017376660U, - 13828847205872152468U, 4603451617570386922U, - 4605843545406134034U, 4602900303344142735U, - 13826272340198918543U, 4605843545406134034U, - 4597492765973365521U, 4606938683557690074U, - 13830310720412465882U, 4597492765973365521U, - 4606618018794815019U, 4599948172872067014U, - 13823320209726842822U, 4606618018794815019U, - 4601173347964633034U, 4606364276725003740U, - 13829736313579779548U, 4601173347964633034U, - 4604774382555066977U, 4604305528345395596U, - 13827677565200171404U, 4604774382555066977U, - 4585465300892538317U, 4607176315382986589U, - 13830548352237762397U, 4585465300892538317U, - 4607176315382986589U, 4585465300892538317U, - 13808837337747314125U, 4607176315382986589U, - 4604305528345395596U, 4604774382555066977U, - 13828146419409842785U, 4604305528345395596U, - 4606364276725003740U, 4601173347964633034U, - 13824545384819408842U, 4606364276725003740U, - 4599948172872067014U, 4606618018794815019U, - 13829990055649590827U, 4599948172872067014U, - 4606938683557690074U, 4597492765973365521U, - 13820864802828141329U, 4606938683557690074U, - 4602900303344142735U, 4605843545406134034U, - 13829215582260909842U, 4602900303344142735U, - 4605475169017376660U, 4603451617570386922U, - 13826823654425162730U, 4605475169017376660U, - 4594891488091520602U, 4607068040143112603U, - 13830440076997888411U, 4594891488091520602U, - 4607100477024622401U, 4594016801320007031U, - 13817388838174782839U, 4607100477024622401U, - 4603629178146150899U, 4605343481119364930U, - 13828715517974140738U, 4603629178146150899U, - 4605957195211051218U, 4602710690099904183U, - 13826082726954679991U, 4605957195211051218U, - 4598262871476403630U, 4606884969294623682U, - 13830257006149399490U, 4598262871476403630U, - 4606692493141721470U, 4599531889160152938U, - 13822903926014928746U, 4606692493141721470U, - 4601573027631668967U, 4606269759522929756U, - 13829641796377705564U, 4601573027631668967U, - 4604922840319727473U, 4604141730443515286U, - 13827513767298291094U, 4604922840319727473U, - 4588998070480937184U, 4607165468267934125U, - 13830537505122709933U, 4588998070480937184U, - 4607149205763218185U, 4590846768565625881U, - 13814218805420401689U, 4607149205763218185U, - 4603974338538572089U, 4605067233569943231U, - 13828439270424719039U, 4603974338538572089U, - 4606170366472647579U, 4601967947786150793U, - 13825339984640926601U, 4606170366472647579U, - 4599112075441176914U, 4606761837001494797U, - 13830133873856270605U, 4599112075441176914U, - 4606826008603986804U, 4598688984595225406U, - 13822061021450001214U, 4606826008603986804U, - 4602357870542944470U, 4606066157444814153U, - 13829438194299589961U, 4602357870542944470U, - 4605207475328619533U, 4603803453461190356U, - 13827175490315966164U, 4605207475328619533U, - 4592606767730311893U, 4607127537664763515U, - 13830499574519539323U, 4592606767730311893U, - 4607030246558998647U, 4595762727260045105U, - 13819134764114820913U, 4607030246558998647U, - 4603270878689749849U, 4605602459698789090U, - 13828974496553564898U, 4603270878689749849U, - 4605725276488455441U, 4603087070374583113U, - 13826459107229358921U, 4605725276488455441U, - 4596629994023683153U, 4606987119037722413U, - 13830359155892498221U, 4596629994023683153U, - 4606538458821337243U, 4600360675823176935U, - 13823732712677952743U, 4606538458821337243U, - 4600769149537129431U, 4606453861145241227U, - 13829825898000017035U, 4600769149537129431U, - 4604621949701367983U, 4604465633578481725U, - 13827837670433257533U, 4604621949701367983U, - 4578227681973159812U, 4607181740574479067U, - 13830553777429254875U, 4578227681973159812U, - 4607182249242036882U, 4573724215515480177U, - 13797096252370255985U, 4607182249242036882U, - 4604505071555817232U, 4604583231088591477U, - 13827955267943367285U, 4604505071555817232U, - 4606475480113671417U, 4600667422348321968U, - 13824039459203097776U, 4606475480113671417U, - 4600463181646572228U, 4606517779747998088U, - 13829889816602773896U, 4600463181646572228U, - 4606998399608725124U, 4596413578358834022U, - 13819785615213609830U, 4606998399608725124U, - 4603133304188877240U, 4605694995810664660U, - 13829067032665440468U, 4603133304188877240U, - 4605633586259814045U, 4603225210076562971U, - 13826597246931338779U, 4605633586259814045U, - 4595979936813835462U, 4607019963775302583U, - 13830392000630078391U, 4595979936813835462U, - 4607133460805585796U, 4592167175087283203U, - 13815539211942059011U, 4607133460805585796U, - 4603846496621587377U, 4605172808754305228U, - 13828544845609081036U, 4603846496621587377U, - 4606092657816072624U, 4602260871257280788U, - 13825632908112056596U, 4606092657816072624U, - 4598795050632330097U, 4606810452769876110U, - 13830182489624651918U, 4598795050632330097U, - 4606778366364612594U, 4599006600037663623U, - 13822378636892439431U, 4606778366364612594U, - 4602065906208722008U, 4606144763310860551U, - 13829516800165636359U, 4602065906208722008U, - 4605102686554936490U, 4603931940768740167U, - 13827303977623515975U, 4605102686554936490U, - 4591287158938884897U, 4607144295058764886U, - 13830516331913540694U, 4591287158938884897U, - 4607168688050493276U, 4588115294056142819U, - 13811487330910918627U, 4607168688050493276U, - 4604183020748362039U, 4604886103475043762U, - 13828258140329819570U, 4604183020748362039U, - 4606293848208650998U, 4601473544562720001U, - 13824845581417495809U, 4606293848208650998U, - 4599636300858866724U, 4606674353838411301U, - 13830046390693187109U, 4599636300858866724U, - 4606898891031025132U, 4598136582470364665U, - 13821508619325140473U, 4606898891031025132U, - 4602758354025980442U, 4605929219593405673U, - 13829301256448181481U, 4602758354025980442U, - 4605376811039722786U, 4603585091850767959U, - 13826957128705543767U, 4605376811039722786U, - 4594235767444503503U, 4607092871118901179U, - 13830464907973676987U, 4594235767444503503U, - 4607076652372832968U, 4594673119063280916U, - 13818045155918056724U, 4607076652372832968U, - 4603496309891590679U, 4605442656228245717U, - 13828814693083021525U, 4603496309891590679U, - 4605872393621214213U, 4602853162432841185U, - 13826225199287616993U, 4605872393621214213U, - 4597707695679609371U, 4606925748668145757U, - 13830297785522921565U, 4597707695679609371U, - 4606637115963965612U, 4599844446633109139U, - 13823216483487884947U, 4606637115963965612U, - 4601273700967202825U, 4606341107699334546U, - 13829713144554110354U, 4601273700967202825U, - 4604811873195349477U, 4604264921241055824U, - 13827636958095831632U, 4604811873195349477U, - 4586348876009622851U, 4607174111710118367U, - 13830546148564894175U, 4586348876009622851U, - 4607178180169683960U, 4584498631466405633U, - 13807870668321181441U, 4607178180169683960U, - 4604345904647073908U, 4604736643460027021U, - 13828108680314802829U, 4604345904647073908U, - 4606387137437298591U, 4601072712526242277U, - 13824444749381018085U, 4606387137437298591U, - 4600051662802353687U, 4606598603759044570U, - 13829970640613820378U, 4600051662802353687U, - 4606951288507767453U, 4597277522845151878U, - 13820649559699927686U, 4606951288507767453U, - 4602947266358709886U, 4605814408482919348U, - 13829186445337695156U, 4602947266358709886U, - 4605507406967535927U, 4603406726595779752U, - 13826778763450555560U, 4605507406967535927U, - 4595109641634432498U, 4607059093103722971U, - 13830431129958498779U, 4595109641634432498U, - 4607107746899444102U, 4593797652641645341U, - 13817169689496421149U, 4607107746899444102U, - 4603673059103075106U, 4605309881318010327U, - 13828681918172786135U, 4603673059103075106U, - 4605984877841711338U, 4602646891659203088U, - 13826018928513978896U, 4605984877841711338U, - 4598369669086960528U, 4606870719641066940U, - 13830242756495842748U, 4598369669086960528U, - 4606710311774494716U, 4599427256825614420U, - 13822799293680390228U, 4606710311774494716U, - 4601672213217083403U, 4606245366082353408U, - 13829617402937129216U, 4601672213217083403U, - 4604959323120302796U, 4604100215502905499U, - 13827472252357681307U, 4604959323120302796U, - 4589524267239410099U, 4607161910007591876U, - 13830533946862367684U, 4589524267239410099U, - 4607153778602162496U, 4590406145430462614U, - 13813778182285238422U, 4607153778602162496U, - 4604016517974851588U, 4605031521104517324U, - 13828403557959293132U, 4604016517974851588U, - 4606195668621671667U, 4601869677011524443U, - 13825241713866300251U, 4606195668621671667U, - 4599217346014614711U, 4606744984357082948U, - 13830117021211858756U, 4599217346014614711U, - 4606841238740778884U, 4598582729657176439U, - 13821954766511952247U, 4606841238740778884U, - 4602454542796181607U, 4606039359984203741U, - 13829411396838979549U, 4602454542796181607U, - 4605241877142478242U, 4603760198400967492U, - 13827132235255743300U, 4605241877142478242U, - 4593046061348462537U, 4607121277474223905U, - 13830493314328999713U, 4593046061348462537U, - 4607040195955932526U, 4595545269419264690U, - 13818917306274040498U, 4607040195955932526U, - 4603316355454250015U, 4605571053506370248U, - 13828943090361146056U, 4603316355454250015U, - 4605755272910869620U, 4603040651631881451U, - 13826412688486657259U, 4605755272910869620U, - 4596846128749438754U, 4606975506703684317U, - 13830347543558460125U, 4596846128749438754U, - 4606558823023444576U, 4600257918160607478U, - 13823629955015383286U, 4606558823023444576U, - 4600870609507958271U, 4606431930490633905U, - 13829803967345409713U, 4600870609507958271U, - 4604660425598397818U, 4604425958770613225U, - 13827797995625389033U, 4604660425598397818U, - 4580962600092897021U, 4607180892816495009U, - 13830552929671270817U, 4580962600092897021U, - 4607180892816495009U, 4580962600092897021U, - 13804334636947672829U, 4607180892816495009U, - 4604425958770613225U, 4604660425598397818U, - 13828032462453173626U, 4604425958770613225U, - 4606431930490633905U, 4600870609507958271U, - 13824242646362734079U, 4606431930490633905U, - 4600257918160607478U, 4606558823023444576U, - 13829930859878220384U, 4600257918160607478U, - 4606975506703684317U, 4596846128749438754U, - 13820218165604214562U, 4606975506703684317U, - 4603040651631881451U, 4605755272910869620U, - 13829127309765645428U, 4603040651631881451U, - 4605571053506370248U, 4603316355454250015U, - 13826688392309025823U, 4605571053506370248U, - 4595545269419264690U, 4607040195955932526U, - 13830412232810708334U, 4595545269419264690U, - 4607121277474223905U, 4593046061348462537U, - 13816418098203238345U, 4607121277474223905U, - 4603760198400967492U, 4605241877142478242U, - 13828613913997254050U, 4603760198400967492U, - 4606039359984203741U, 4602454542796181607U, - 13825826579650957415U, 4606039359984203741U, - 4598582729657176439U, 4606841238740778884U, - 13830213275595554692U, 4598582729657176439U, - 4606744984357082948U, 4599217346014614711U, - 13822589382869390519U, 4606744984357082948U, - 4601869677011524443U, 4606195668621671667U, - 13829567705476447475U, 4601869677011524443U, - 4605031521104517324U, 4604016517974851588U, - 13827388554829627396U, 4605031521104517324U, - 4590406145430462614U, 4607153778602162496U, - 13830525815456938304U, 4590406145430462614U, - 4607161910007591876U, 4589524267239410099U, - 13812896304094185907U, 4607161910007591876U, - 4604100215502905499U, 4604959323120302796U, - 13828331359975078604U, 4604100215502905499U, - 4606245366082353408U, 4601672213217083403U, - 13825044250071859211U, 4606245366082353408U, - 4599427256825614420U, 4606710311774494716U, - 13830082348629270524U, 4599427256825614420U, - 4606870719641066940U, 4598369669086960528U, - 13821741705941736336U, 4606870719641066940U, - 4602646891659203088U, 4605984877841711338U, - 13829356914696487146U, 4602646891659203088U, - 4605309881318010327U, 4603673059103075106U, - 13827045095957850914U, 4605309881318010327U, - 4593797652641645341U, 4607107746899444102U, - 13830479783754219910U, 4593797652641645341U, - 4607059093103722971U, 4595109641634432498U, - 13818481678489208306U, 4607059093103722971U, - 4603406726595779752U, 4605507406967535927U, - 13828879443822311735U, 4603406726595779752U, - 4605814408482919348U, 4602947266358709886U, - 13826319303213485694U, 4605814408482919348U, - 4597277522845151878U, 4606951288507767453U, - 13830323325362543261U, 4597277522845151878U, - 4606598603759044570U, 4600051662802353687U, - 13823423699657129495U, 4606598603759044570U, - 4601072712526242277U, 4606387137437298591U, - 13829759174292074399U, 4601072712526242277U, - 4604736643460027021U, 4604345904647073908U, - 13827717941501849716U, 4604736643460027021U, - 4584498631466405633U, 4607178180169683960U, - 13830550217024459768U, 4584498631466405633U, - 4607174111710118367U, 4586348876009622851U, - 13809720912864398659U, 4607174111710118367U, - 4604264921241055824U, 4604811873195349477U, - 13828183910050125285U, 4604264921241055824U, - 4606341107699334546U, 4601273700967202825U, - 13824645737821978633U, 4606341107699334546U, - 4599844446633109139U, 4606637115963965612U, - 13830009152818741420U, 4599844446633109139U, - 4606925748668145757U, 4597707695679609371U, - 13821079732534385179U, 4606925748668145757U, - 4602853162432841185U, 4605872393621214213U, - 13829244430475990021U, 4602853162432841185U, - 4605442656228245717U, 4603496309891590679U, - 13826868346746366487U, 4605442656228245717U, - 4594673119063280916U, 4607076652372832968U, - 13830448689227608776U, 4594673119063280916U, - 4607092871118901179U, 4594235767444503503U, - 13817607804299279311U, 4607092871118901179U, - 4603585091850767959U, 4605376811039722786U, - 13828748847894498594U, 4603585091850767959U, - 4605929219593405673U, 4602758354025980442U, - 13826130390880756250U, 4605929219593405673U, - 4598136582470364665U, 4606898891031025132U, - 13830270927885800940U, 4598136582470364665U, - 4606674353838411301U, 4599636300858866724U, - 13823008337713642532U, 4606674353838411301U, - 4601473544562720001U, 4606293848208650998U, - 13829665885063426806U, 4601473544562720001U, - 4604886103475043762U, 4604183020748362039U, - 13827555057603137847U, 4604886103475043762U, - 4588115294056142819U, 4607168688050493276U, - 13830540724905269084U, 4588115294056142819U, - 4607144295058764886U, 4591287158938884897U, - 13814659195793660705U, 4607144295058764886U, - 4603931940768740167U, 4605102686554936490U, - 13828474723409712298U, 4603931940768740167U, - 4606144763310860551U, 4602065906208722008U, - 13825437943063497816U, 4606144763310860551U, - 4599006600037663623U, 4606778366364612594U, - 13830150403219388402U, 4599006600037663623U, - 4606810452769876110U, 4598795050632330097U, - 13822167087487105905U, 4606810452769876110U, - 4602260871257280788U, 4606092657816072624U, - 13829464694670848432U, 4602260871257280788U, - 4605172808754305228U, 4603846496621587377U, - 13827218533476363185U, 4605172808754305228U, - 4592167175087283203U, 4607133460805585796U, - 13830505497660361604U, 4592167175087283203U, - 4607019963775302583U, 4595979936813835462U, - 13819351973668611270U, 4607019963775302583U, - 4603225210076562971U, 4605633586259814045U, - 13829005623114589853U, 4603225210076562971U, - 4605694995810664660U, 4603133304188877240U, - 13826505341043653048U, 4605694995810664660U, - 4596413578358834022U, 4606998399608725124U, - 13830370436463500932U, 4596413578358834022U, - 4606517779747998088U, 4600463181646572228U, - 13823835218501348036U, 4606517779747998088U, - 4600667422348321968U, 4606475480113671417U, - 13829847516968447225U, 4600667422348321968U, - 4604583231088591477U, 4604505071555817232U, - 13827877108410593040U, 4604583231088591477U, - 4573724215515480177U, 4607182249242036882U, - 13830554286096812690U, 4573724215515480177U, - 4607182376410422530U, 4569220649180767418U, - 13792592686035543226U, 4607182376410422530U, - 4604524701268679793U, 4604563781218984604U, - 13827935818073760412U, 4604524701268679793U, - 4606486172460753999U, 4600616459743653188U, - 13823988496598428996U, 4606486172460753999U, - 4600514338912178239U, 4606507322377452870U, - 13829879359232228678U, 4600514338912178239U, - 4607003915349878877U, 4596305267720071930U, - 13819677304574847738U, 4607003915349878877U, - 4603156351203636159U, 4605679749231851918U, - 13829051786086627726U, 4603156351203636159U, - 4605649044311923410U, 4603202304363743346U, - 13826574341218519154U, 4605649044311923410U, - 4596088445927168004U, 4607014697483910382U, - 13830386734338686190U, 4596088445927168004U, - 4607136295912168606U, 4591947271803021404U, - 13815319308657797212U, 4607136295912168606U, - 4603867938232615808U, 4605155376589456981U, - 13828527413444232789U, 4603867938232615808U, - 4606105796280968177U, 4602212250118051877U, - 13825584286972827685U, 4606105796280968177U, - 4598848011564831930U, 4606802552898869248U, - 13830174589753645056U, 4598848011564831930U, - 4606786509620734768U, 4598953786765296928U, - 13822325823620072736U, 4606786509620734768U, - 4602114767134999006U, 4606131849150971908U, - 13829503886005747716U, 4602114767134999006U, - 4605120315324767624U, 4603910660507251362U, - 13827282697362027170U, 4605120315324767624U, - 4591507261658050721U, 4607141713064252300U, - 13830513749919028108U, 4591507261658050721U, - 4607170170974224083U, 4587673791460508439U, - 13811045828315284247U, 4607170170974224083U, - 4604203581176243359U, 4604867640218014515U, - 13828239677072790323U, 4604203581176243359U, - 4606305777984577632U, 4601423692641949331U, - 13824795729496725139U, 4606305777984577632U, - 4599688422741010356U, 4606665164148251002U, - 13830037201003026810U, 4599688422741010356U, - 4606905728766014348U, 4598029484874872834U, - 13821401521729648642U, 4606905728766014348U, - 4602782121393764535U, 4605915122243179241U, - 13829287159097955049U, 4602782121393764535U, - 4605393374401988274U, 4603562972219549215U, - 13826935009074325023U, 4605393374401988274U, - 4594345179472540681U, 4607088942243446236U, - 13830460979098222044U, 4594345179472540681U, - 4607080832832247697U, 4594563856311064231U, - 13817935893165840039U, 4607080832832247697U, - 4603518581031047189U, 4605426297151190466U, - 13828798334005966274U, 4603518581031047189U, - 4605886709123365959U, 4602829525820289164U, - 13826201562675064972U, 4605886709123365959U, - 4597815040470278984U, 4606919157647773535U, - 13830291194502549343U, 4597815040470278984U, - 4606646545123403481U, 4599792496117920694U, - 13823164532972696502U, 4606646545123403481U, - 4601323770373937522U, 4606329407841126011U, - 13829701444695901819U, 4601323770373937522U, - 4604830524903495634U, 4604244531615310815U, - 13827616568470086623U, 4604830524903495634U, - 4586790578280679046U, 4607172882816799076U, - 13830544919671574884U, 4586790578280679046U, - 4607178985458280057U, 4583614727651146525U, - 13806986764505922333U, 4607178985458280057U, - 4604366005771528720U, 4604717681185626434U, - 13828089718040402242U, 4604366005771528720U, - 4606398451906509788U, 4601022290077223616U, - 13824394326931999424U, 4606398451906509788U, - 4600103317933788342U, 4606588777269136769U, - 13829960814123912577U, 4600103317933788342U, - 4606957467106717424U, 4597169786279785693U, - 13820541823134561501U, 4606957467106717424U, - 4602970680601913687U, 4605799732098147061U, - 13829171768952922869U, 4602970680601913687U, - 4605523422498301790U, 4603384207141321914U, - 13826756243996097722U, 4605523422498301790U, - 4595218635031890910U, 4607054494135176056U, - 13830426530989951864U, 4595218635031890910U, - 4607111255739239816U, 4593688012422887515U, - 13817060049277663323U, 4607111255739239816U, - 4603694922063032361U, 4605292980606880364U, - 13828665017461656172U, 4603694922063032361U, - 4605998608960791335U, 4602598930031891166U, - 13825970966886666974U, 4605998608960791335U, - 4598423001813699022U, 4606863472012527185U, - 13830235508867302993U, 4598423001813699022U, - 4606719100629313491U, 4599374859150636784U, - 13822746896005412592U, 4606719100629313491U, - 4601721693286060937U, 4606233055365547081U, - 13829605092220322889U, 4601721693286060937U, - 4604977468824438271U, 4604079374282302598U, - 13827451411137078406U, 4604977468824438271U, - 4589744810590291021U, 4607160003989618959U, - 13830532040844394767U, 4589744810590291021U, - 4607155938267770208U, 4590185751760970393U, - 13813557788615746201U, 4607155938267770208U, - 4604037525321326463U, 4605013567986435066U, - 13828385604841210874U, 4604037525321326463U, - 4606208206518262803U, 4601820425647934753U, - 13825192462502710561U, 4606208206518262803U, - 4599269903251194481U, 4606736437002195879U, - 13830108473856971687U, 4599269903251194481U, - 4606848731493011465U, 4598529532600161144U, - 13821901569454936952U, 4606848731493011465U, - 4602502755147763107U, 4606025850160239809U, - 13829397887015015617U, 4602502755147763107U, - 4605258978359093269U, 4603738491917026584U, - 13827110528771802392U, 4605258978359093269U, - 4593265590854265407U, 4607118021058468598U, - 13830490057913244406U, 4593265590854265407U, - 4607045045516813836U, 4595436449949385485U, - 13818808486804161293U, 4607045045516813836U, - 4603339021357904144U, 4605555245917486022U, - 13828927282772261830U, 4603339021357904144U, - 4605770164172969910U, 4603017373458244943U, - 13826389410313020751U, 4605770164172969910U, - 4596954088216812973U, 4606969576261663845U, - 13830341613116439653U, 4596954088216812973U, - 4606568886807728474U, 4600206446098256018U, - 13823578482953031826U, 4606568886807728474U, - 4600921238092511730U, 4606420848538580260U, - 13829792885393356068U, 4600921238092511730U, - 4604679572075463103U, 4604406033021674239U, - 13827778069876450047U, 4604679572075463103U, - 4581846703643734566U, 4607180341788068727U, - 13830552378642844535U, 4581846703643734566U, - 4607181359080094673U, 4579996072175835083U, - 13803368109030610891U, 4607181359080094673U, - 4604445825685214043U, 4604641218080103285U, - 13828013254934879093U, 4604445825685214043U, - 4606442934727379583U, 4600819913163773071U, - 13824191950018548879U, 4606442934727379583U, - 4600309328230211502U, 4606548680329491866U, - 13829920717184267674U, 4600309328230211502U, - 4606981354314050484U, 4596738097012783531U, - 13820110133867559339U, 4606981354314050484U, - 4603063884010218172U, 4605740310302420207U, - 13829112347157196015U, 4603063884010218172U, - 4605586791482848547U, 4603293641160266722U, - 13826665678015042530U, 4605586791482848547U, - 4595654028864046335U, 4607035262954517034U, - 13830407299809292842U, 4595654028864046335U, - 4607124449686274900U, 4592826452951465409U, - 13816198489806241217U, 4607124449686274900U, - 4603781852316960384U, 4605224709411790590U, - 13828596746266566398U, 4603781852316960384U, - 4606052795787882823U, 4602406247776385022U, - 13825778284631160830U, 4606052795787882823U, - 4598635880488956483U, 4606833664420673202U, - 13830205701275449010U, 4598635880488956483U, - 4606753451050079834U, 4599164736579548843U, - 13822536773434324651U, 4606753451050079834U, - 4601918851211878557U, 4606183055233559255U, - 13829555092088335063U, 4601918851211878557U, - 4605049409688478101U, 4603995455647851249U, - 13827367492502627057U, 4605049409688478101U, - 4590626485056654602U, 4607151534426937478U, - 13830523571281713286U, 4590626485056654602U, - 4607163731439411601U, 4589303678145802340U, - 13812675715000578148U, 4607163731439411601U, - 4604121000955189926U, 4604941113561600762U, - 13828313150416376570U, 4604121000955189926U, - 4606257600839867033U, 4601622657843474729U, - 13824994694698250537U, 4606257600839867033U, - 4599479600326345459U, 4606701442584137310U, - 13830073479438913118U, 4599479600326345459U, - 4606877885424248132U, 4598316292140394014U, - 13821688328995169822U, 4606877885424248132U, - 4602686793990243041U, 4605971073215153165U, - 13829343110069928973U, 4602686793990243041U, - 4605326714874986465U, 4603651144395358093U, - 13827023181250133901U, 4605326714874986465U, - 4593907249284540294U, 4607104153983298999U, - 13830476190838074807U, 4593907249284540294U, - 4607063608453868552U, 4595000592312171144U, - 13818372629166946952U, 4607063608453868552U, - 4603429196809300824U, 4605491322423429598U, - 13828863359278205406U, 4603429196809300824U, - 4605829012964735987U, 4602923807199184054U, - 13826295844053959862U, 4605829012964735987U, - 4597385183080791534U, 4606945027305114062U, - 13830317064159889870U, 4597385183080791534U, - 4606608350964852124U, 4599999947619525579U, - 13823371984474301387U, 4606608350964852124U, - 4601123065313358619U, 4606375745674388705U, - 13829747782529164513U, 4601123065313358619U, - 4604755543975806820U, 4604325745441780828U, - 13827697782296556636U, 4604755543975806820U, - 4585023436363055487U, 4607177290141793710U, - 13830549326996569518U, 4585023436363055487U, - 4607175255902437396U, 4585907115494236537U, - 13809279152349012345U, 4607175255902437396U, - 4604285253548209224U, 4604793159020491611U, - 13828165195875267419U, 4604285253548209224U, - 4606352730697093817U, 4601223560006786057U, - 13824595596861561865U, 4606352730697093817U, - 4599896339047301634U, 4606627607157935956U, - 13829999644012711764U, 4599896339047301634U, - 4606932257325205256U, 4597600270510262682U, - 13820972307365038490U, 4606932257325205256U, - 4602876755014813164U, 4605858005670328613U, - 13829230042525104421U, 4602876755014813164U, - 4605458946901419122U, 4603473988668005304U, - 13826846025522781112U, 4605458946901419122U, - 4594782329999411347U, 4607072388129742377U, - 13830444424984518185U, 4594782329999411347U, - 4607096716058023245U, 4594126307716900071U, - 13817498344571675879U, 4607096716058023245U, - 4603607160562208225U, 4605360179893335444U, - 13828732216748111252U, 4603607160562208225U, - 4605943243960030558U, 4602734543519989142U, - 13826106580374764950U, 4605943243960030558U, - 4598209407597805010U, 4606891971185517504U, - 13830264008040293312U, 4598209407597805010U, - 4606683463531482757U, 4599584122834874440U, - 13822956159689650248U, 4606683463531482757U, - 4601523323048804569U, 4606281842017099424U, - 13829653878871875232U, 4601523323048804569U, - 4604904503566677638U, 4604162403772767740U, - 13827534440627543548U, 4604904503566677638U, - 4588556721781247689U, 4607167120476811757U, - 13830539157331587565U, 4588556721781247689U, - 4607146792632922887U, 4591066993883984169U, - 13814439030738759977U, 4607146792632922887U, - 4603953166845776383U, 4605084992581147553U, - 13828457029435923361U, 4603953166845776383U, - 4606157602458368090U, 4602016966272225497U, - 13825389003127001305U, 4606157602458368090U, - 4599059363095165615U, 4606770142132396069U, - 13830142178987171877U, 4599059363095165615U, - 4606818271362779153U, 4598742041476147134U, - 13822114078330922942U, 4606818271362779153U, - 4602309411551204896U, 4606079444829232727U, - 13829451481684008535U, 4602309411551204896U, - 4605190175055178825U, 4603825001630339212U, - 13827197038485115020U, 4605190175055178825U, - 4592387007752762956U, 4607130541380624519U, - 13830502578235400327U, 4592387007752762956U, - 4607025146816593591U, 4595871363584150300U, - 13819243400438926108U, 4607025146816593591U, - 4603248068256948438U, 4605618058006716661U, - 13828990094861492469U, 4603248068256948438U, - 4605710171610479304U, 4603110210506737381U, - 13826482247361513189U, 4605710171610479304U, - 4596521820799644122U, 4606992800820440327U, - 13830364837675216135U, 4596521820799644122U, - 4606528158595189433U, 4600411960456200676U, - 13823783997310976484U, 4606528158595189433U, - 4600718319105833937U, 4606464709641375231U, - 13829836746496151039U, 4600718319105833937U, - 4604602620643553229U, 4604485382263976838U, - 13827857419118752646U, 4604602620643553229U, - 4576459225186735875U, 4607182037296057423U, - 13830554074150833231U, 4576459225186735875U, - 4607182037296057423U, 4576459225186735875U, - 13799831262041511683U, 4607182037296057423U, - 4604485382263976838U, 4604602620643553229U, - 13827974657498329037U, 4604485382263976838U, - 4606464709641375231U, 4600718319105833937U, - 13824090355960609745U, 4606464709641375231U, - 4600411960456200676U, 4606528158595189433U, - 13829900195449965241U, 4600411960456200676U, - 4606992800820440327U, 4596521820799644122U, - 13819893857654419930U, 4606992800820440327U, - 4603110210506737381U, 4605710171610479304U, - 13829082208465255112U, 4603110210506737381U, - 4605618058006716661U, 4603248068256948438U, - 13826620105111724246U, 4605618058006716661U, - 4595871363584150300U, 4607025146816593591U, - 13830397183671369399U, 4595871363584150300U, - 4607130541380624519U, 4592387007752762956U, - 13815759044607538764U, 4607130541380624519U, - 4603825001630339212U, 4605190175055178825U, - 13828562211909954633U, 4603825001630339212U, - 4606079444829232727U, 4602309411551204896U, - 13825681448405980704U, 4606079444829232727U, - 4598742041476147134U, 4606818271362779153U, - 13830190308217554961U, 4598742041476147134U, - 4606770142132396069U, 4599059363095165615U, - 13822431399949941423U, 4606770142132396069U, - 4602016966272225497U, 4606157602458368090U, - 13829529639313143898U, 4602016966272225497U, - 4605084992581147553U, 4603953166845776383U, - 13827325203700552191U, 4605084992581147553U, - 4591066993883984169U, 4607146792632922887U, - 13830518829487698695U, 4591066993883984169U, - 4607167120476811757U, 4588556721781247689U, - 13811928758636023497U, 4607167120476811757U, - 4604162403772767740U, 4604904503566677638U, - 13828276540421453446U, 4604162403772767740U, - 4606281842017099424U, 4601523323048804569U, - 13824895359903580377U, 4606281842017099424U, - 4599584122834874440U, 4606683463531482757U, - 13830055500386258565U, 4599584122834874440U, - 4606891971185517504U, 4598209407597805010U, - 13821581444452580818U, 4606891971185517504U, - 4602734543519989142U, 4605943243960030558U, - 13829315280814806366U, 4602734543519989142U, - 4605360179893335444U, 4603607160562208225U, - 13826979197416984033U, 4605360179893335444U, - 4594126307716900071U, 4607096716058023245U, - 13830468752912799053U, 4594126307716900071U, - 4607072388129742377U, 4594782329999411347U, - 13818154366854187155U, 4607072388129742377U, - 4603473988668005304U, 4605458946901419122U, - 13828830983756194930U, 4603473988668005304U, - 4605858005670328613U, 4602876755014813164U, - 13826248791869588972U, 4605858005670328613U, - 4597600270510262682U, 4606932257325205256U, - 13830304294179981064U, 4597600270510262682U, - 4606627607157935956U, 4599896339047301634U, - 13823268375902077442U, 4606627607157935956U, - 4601223560006786057U, 4606352730697093817U, - 13829724767551869625U, 4601223560006786057U, - 4604793159020491611U, 4604285253548209224U, - 13827657290402985032U, 4604793159020491611U, - 4585907115494236537U, 4607175255902437396U, - 13830547292757213204U, 4585907115494236537U, - 4607177290141793710U, 4585023436363055487U, - 13808395473217831295U, 4607177290141793710U, - 4604325745441780828U, 4604755543975806820U, - 13828127580830582628U, 4604325745441780828U, - 4606375745674388705U, 4601123065313358619U, - 13824495102168134427U, 4606375745674388705U, - 4599999947619525579U, 4606608350964852124U, - 13829980387819627932U, 4599999947619525579U, - 4606945027305114062U, 4597385183080791534U, - 13820757219935567342U, 4606945027305114062U, - 4602923807199184054U, 4605829012964735987U, - 13829201049819511795U, 4602923807199184054U, - 4605491322423429598U, 4603429196809300824U, - 13826801233664076632U, 4605491322423429598U, - 4595000592312171144U, 4607063608453868552U, - 13830435645308644360U, 4595000592312171144U, - 4607104153983298999U, 4593907249284540294U, - 13817279286139316102U, 4607104153983298999U, - 4603651144395358093U, 4605326714874986465U, - 13828698751729762273U, 4603651144395358093U, - 4605971073215153165U, 4602686793990243041U, - 13826058830845018849U, 4605971073215153165U, - 4598316292140394014U, 4606877885424248132U, - 13830249922279023940U, 4598316292140394014U, - 4606701442584137310U, 4599479600326345459U, - 13822851637181121267U, 4606701442584137310U, - 4601622657843474729U, 4606257600839867033U, - 13829629637694642841U, 4601622657843474729U, - 4604941113561600762U, 4604121000955189926U, - 13827493037809965734U, 4604941113561600762U, - 4589303678145802340U, 4607163731439411601U, - 13830535768294187409U, 4589303678145802340U, - 4607151534426937478U, 4590626485056654602U, - 13813998521911430410U, 4607151534426937478U, - 4603995455647851249U, 4605049409688478101U, - 13828421446543253909U, 4603995455647851249U, - 4606183055233559255U, 4601918851211878557U, - 13825290888066654365U, 4606183055233559255U, - 4599164736579548843U, 4606753451050079834U, - 13830125487904855642U, 4599164736579548843U, - 4606833664420673202U, 4598635880488956483U, - 13822007917343732291U, 4606833664420673202U, - 4602406247776385022U, 4606052795787882823U, - 13829424832642658631U, 4602406247776385022U, - 4605224709411790590U, 4603781852316960384U, - 13827153889171736192U, 4605224709411790590U, - 4592826452951465409U, 4607124449686274900U, - 13830496486541050708U, 4592826452951465409U, - 4607035262954517034U, 4595654028864046335U, - 13819026065718822143U, 4607035262954517034U, - 4603293641160266722U, 4605586791482848547U, - 13828958828337624355U, 4603293641160266722U, - 4605740310302420207U, 4603063884010218172U, - 13826435920864993980U, 4605740310302420207U, - 4596738097012783531U, 4606981354314050484U, - 13830353391168826292U, 4596738097012783531U, - 4606548680329491866U, 4600309328230211502U, - 13823681365084987310U, 4606548680329491866U, - 4600819913163773071U, 4606442934727379583U, - 13829814971582155391U, 4600819913163773071U, - 4604641218080103285U, 4604445825685214043U, - 13827817862539989851U, 4604641218080103285U, - 4579996072175835083U, 4607181359080094673U, - 13830553395934870481U, 4579996072175835083U, - 4607180341788068727U, 4581846703643734566U, - 13805218740498510374U, 4607180341788068727U, - 4604406033021674239U, 4604679572075463103U, - 13828051608930238911U, 4604406033021674239U, - 4606420848538580260U, 4600921238092511730U, - 13824293274947287538U, 4606420848538580260U, - 4600206446098256018U, 4606568886807728474U, - 13829940923662504282U, 4600206446098256018U, - 4606969576261663845U, 4596954088216812973U, - 13820326125071588781U, 4606969576261663845U, - 4603017373458244943U, 4605770164172969910U, - 13829142201027745718U, 4603017373458244943U, - 4605555245917486022U, 4603339021357904144U, - 13826711058212679952U, 4605555245917486022U, - 4595436449949385485U, 4607045045516813836U, - 13830417082371589644U, 4595436449949385485U, - 4607118021058468598U, 4593265590854265407U, - 13816637627709041215U, 4607118021058468598U, - 4603738491917026584U, 4605258978359093269U, - 13828631015213869077U, 4603738491917026584U, - 4606025850160239809U, 4602502755147763107U, - 13825874792002538915U, 4606025850160239809U, - 4598529532600161144U, 4606848731493011465U, - 13830220768347787273U, 4598529532600161144U, - 4606736437002195879U, 4599269903251194481U, - 13822641940105970289U, 4606736437002195879U, - 4601820425647934753U, 4606208206518262803U, - 13829580243373038611U, 4601820425647934753U, - 4605013567986435066U, 4604037525321326463U, - 13827409562176102271U, 4605013567986435066U, - 4590185751760970393U, 4607155938267770208U, - 13830527975122546016U, 4590185751760970393U, - 4607160003989618959U, 4589744810590291021U, - 13813116847445066829U, 4607160003989618959U, - 4604079374282302598U, 4604977468824438271U, - 13828349505679214079U, 4604079374282302598U, - 4606233055365547081U, 4601721693286060937U, - 13825093730140836745U, 4606233055365547081U, - 4599374859150636784U, 4606719100629313491U, - 13830091137484089299U, 4599374859150636784U, - 4606863472012527185U, 4598423001813699022U, - 13821795038668474830U, 4606863472012527185U, - 4602598930031891166U, 4605998608960791335U, - 13829370645815567143U, 4602598930031891166U, - 4605292980606880364U, 4603694922063032361U, - 13827066958917808169U, 4605292980606880364U, - 4593688012422887515U, 4607111255739239816U, - 13830483292594015624U, 4593688012422887515U, - 4607054494135176056U, 4595218635031890910U, - 13818590671886666718U, 4607054494135176056U, - 4603384207141321914U, 4605523422498301790U, - 13828895459353077598U, 4603384207141321914U, - 4605799732098147061U, 4602970680601913687U, - 13826342717456689495U, 4605799732098147061U, - 4597169786279785693U, 4606957467106717424U, - 13830329503961493232U, 4597169786279785693U, - 4606588777269136769U, 4600103317933788342U, - 13823475354788564150U, 4606588777269136769U, - 4601022290077223616U, 4606398451906509788U, - 13829770488761285596U, 4601022290077223616U, - 4604717681185626434U, 4604366005771528720U, - 13827738042626304528U, 4604717681185626434U, - 4583614727651146525U, 4607178985458280057U, - 13830551022313055865U, 4583614727651146525U, - 4607172882816799076U, 4586790578280679046U, - 13810162615135454854U, 4607172882816799076U, - 4604244531615310815U, 4604830524903495634U, - 13828202561758271442U, 4604244531615310815U, - 4606329407841126011U, 4601323770373937522U, - 13824695807228713330U, 4606329407841126011U, - 4599792496117920694U, 4606646545123403481U, - 13830018581978179289U, 4599792496117920694U, - 4606919157647773535U, 4597815040470278984U, - 13821187077325054792U, 4606919157647773535U, - 4602829525820289164U, 4605886709123365959U, - 13829258745978141767U, 4602829525820289164U, - 4605426297151190466U, 4603518581031047189U, - 13826890617885822997U, 4605426297151190466U, - 4594563856311064231U, 4607080832832247697U, - 13830452869687023505U, 4594563856311064231U, - 4607088942243446236U, 4594345179472540681U, - 13817717216327316489U, 4607088942243446236U, - 4603562972219549215U, 4605393374401988274U, - 13828765411256764082U, 4603562972219549215U, - 4605915122243179241U, 4602782121393764535U, - 13826154158248540343U, 4605915122243179241U, - 4598029484874872834U, 4606905728766014348U, - 13830277765620790156U, 4598029484874872834U, - 4606665164148251002U, 4599688422741010356U, - 13823060459595786164U, 4606665164148251002U, - 4601423692641949331U, 4606305777984577632U, - 13829677814839353440U, 4601423692641949331U, - 4604867640218014515U, 4604203581176243359U, - 13827575618031019167U, 4604867640218014515U, - 4587673791460508439U, 4607170170974224083U, - 13830542207828999891U, 4587673791460508439U, - 4607141713064252300U, 4591507261658050721U, - 13814879298512826529U, 4607141713064252300U, - 4603910660507251362U, 4605120315324767624U, - 13828492352179543432U, 4603910660507251362U, - 4606131849150971908U, 4602114767134999006U, - 13825486803989774814U, 4606131849150971908U, - 4598953786765296928U, 4606786509620734768U, - 13830158546475510576U, 4598953786765296928U, - 4606802552898869248U, 4598848011564831930U, - 13822220048419607738U, 4606802552898869248U, - 4602212250118051877U, 4606105796280968177U, - 13829477833135743985U, 4602212250118051877U, - 4605155376589456981U, 4603867938232615808U, - 13827239975087391616U, 4605155376589456981U, - 4591947271803021404U, 4607136295912168606U, - 13830508332766944414U, 4591947271803021404U, - 4607014697483910382U, 4596088445927168004U, - 13819460482781943812U, 4607014697483910382U, - 4603202304363743346U, 4605649044311923410U, - 13829021081166699218U, 4603202304363743346U, - 4605679749231851918U, 4603156351203636159U, - 13826528388058411967U, 4605679749231851918U, - 4596305267720071930U, 4607003915349878877U, - 13830375952204654685U, 4596305267720071930U, - 4606507322377452870U, 4600514338912178239U, - 13823886375766954047U, 4606507322377452870U, - 4600616459743653188U, 4606486172460753999U, - 13829858209315529807U, 4600616459743653188U, - 4604563781218984604U, 4604524701268679793U, - 13827896738123455601U, 4604563781218984604U, - 4569220649180767418U, 4607182376410422530U, - 13830554413265198338U, 4569220649180767418U -}; - -const fpr fpr_p2_tab[] = { - 4611686018427387904U, - 4607182418800017408U, - 4602678819172646912U, - 4598175219545276416U, - 4593671619917905920U, - 4589168020290535424U, - 4584664420663164928U, - 4580160821035794432U, - 4575657221408423936U, - 4571153621781053440U, - 4566650022153682944U -}; - -#elif FALCON_FPNATIVE // yyyFPEMU+0 yyyFPNATIVE+1 - -const fpr fpr_gm_tab[] = { - {0}, {0}, /* unused */ - {-0.000000000000000000000000000}, { 1.000000000000000000000000000}, - { 0.707106781186547524400844362}, { 0.707106781186547524400844362}, - {-0.707106781186547524400844362}, { 0.707106781186547524400844362}, - { 0.923879532511286756128183189}, { 0.382683432365089771728459984}, - {-0.382683432365089771728459984}, { 0.923879532511286756128183189}, - { 0.382683432365089771728459984}, { 0.923879532511286756128183189}, - {-0.923879532511286756128183189}, { 0.382683432365089771728459984}, - { 0.980785280403230449126182236}, { 0.195090322016128267848284868}, - {-0.195090322016128267848284868}, { 0.980785280403230449126182236}, - { 0.555570233019602224742830814}, { 0.831469612302545237078788378}, - {-0.831469612302545237078788378}, { 0.555570233019602224742830814}, - { 0.831469612302545237078788378}, { 0.555570233019602224742830814}, - {-0.555570233019602224742830814}, { 0.831469612302545237078788378}, - { 0.195090322016128267848284868}, { 0.980785280403230449126182236}, - {-0.980785280403230449126182236}, { 0.195090322016128267848284868}, - { 0.995184726672196886244836953}, { 0.098017140329560601994195564}, - {-0.098017140329560601994195564}, { 0.995184726672196886244836953}, - { 0.634393284163645498215171613}, { 0.773010453362736960810906610}, - {-0.773010453362736960810906610}, { 0.634393284163645498215171613}, - { 0.881921264348355029712756864}, { 0.471396736825997648556387626}, - {-0.471396736825997648556387626}, { 0.881921264348355029712756864}, - { 0.290284677254462367636192376}, { 0.956940335732208864935797887}, - {-0.956940335732208864935797887}, { 0.290284677254462367636192376}, - { 0.956940335732208864935797887}, { 0.290284677254462367636192376}, - {-0.290284677254462367636192376}, { 0.956940335732208864935797887}, - { 0.471396736825997648556387626}, { 0.881921264348355029712756864}, - {-0.881921264348355029712756864}, { 0.471396736825997648556387626}, - { 0.773010453362736960810906610}, { 0.634393284163645498215171613}, - {-0.634393284163645498215171613}, { 0.773010453362736960810906610}, - { 0.098017140329560601994195564}, { 0.995184726672196886244836953}, - {-0.995184726672196886244836953}, { 0.098017140329560601994195564}, - { 0.998795456205172392714771605}, { 0.049067674327418014254954977}, - {-0.049067674327418014254954977}, { 0.998795456205172392714771605}, - { 0.671558954847018400625376850}, { 0.740951125354959091175616897}, - {-0.740951125354959091175616897}, { 0.671558954847018400625376850}, - { 0.903989293123443331586200297}, { 0.427555093430282094320966857}, - {-0.427555093430282094320966857}, { 0.903989293123443331586200297}, - { 0.336889853392220050689253213}, { 0.941544065183020778412509403}, - {-0.941544065183020778412509403}, { 0.336889853392220050689253213}, - { 0.970031253194543992603984207}, { 0.242980179903263889948274162}, - {-0.242980179903263889948274162}, { 0.970031253194543992603984207}, - { 0.514102744193221726593693839}, { 0.857728610000272069902269984}, - {-0.857728610000272069902269984}, { 0.514102744193221726593693839}, - { 0.803207531480644909806676513}, { 0.595699304492433343467036529}, - {-0.595699304492433343467036529}, { 0.803207531480644909806676513}, - { 0.146730474455361751658850130}, { 0.989176509964780973451673738}, - {-0.989176509964780973451673738}, { 0.146730474455361751658850130}, - { 0.989176509964780973451673738}, { 0.146730474455361751658850130}, - {-0.146730474455361751658850130}, { 0.989176509964780973451673738}, - { 0.595699304492433343467036529}, { 0.803207531480644909806676513}, - {-0.803207531480644909806676513}, { 0.595699304492433343467036529}, - { 0.857728610000272069902269984}, { 0.514102744193221726593693839}, - {-0.514102744193221726593693839}, { 0.857728610000272069902269984}, - { 0.242980179903263889948274162}, { 0.970031253194543992603984207}, - {-0.970031253194543992603984207}, { 0.242980179903263889948274162}, - { 0.941544065183020778412509403}, { 0.336889853392220050689253213}, - {-0.336889853392220050689253213}, { 0.941544065183020778412509403}, - { 0.427555093430282094320966857}, { 0.903989293123443331586200297}, - {-0.903989293123443331586200297}, { 0.427555093430282094320966857}, - { 0.740951125354959091175616897}, { 0.671558954847018400625376850}, - {-0.671558954847018400625376850}, { 0.740951125354959091175616897}, - { 0.049067674327418014254954977}, { 0.998795456205172392714771605}, - {-0.998795456205172392714771605}, { 0.049067674327418014254954977}, - { 0.999698818696204220115765650}, { 0.024541228522912288031734529}, - {-0.024541228522912288031734529}, { 0.999698818696204220115765650}, - { 0.689540544737066924616730630}, { 0.724247082951466920941069243}, - {-0.724247082951466920941069243}, { 0.689540544737066924616730630}, - { 0.914209755703530654635014829}, { 0.405241314004989870908481306}, - {-0.405241314004989870908481306}, { 0.914209755703530654635014829}, - { 0.359895036534988148775104572}, { 0.932992798834738887711660256}, - {-0.932992798834738887711660256}, { 0.359895036534988148775104572}, - { 0.975702130038528544460395766}, { 0.219101240156869797227737547}, - {-0.219101240156869797227737547}, { 0.975702130038528544460395766}, - { 0.534997619887097210663076905}, { 0.844853565249707073259571205}, - {-0.844853565249707073259571205}, { 0.534997619887097210663076905}, - { 0.817584813151583696504920884}, { 0.575808191417845300745972454}, - {-0.575808191417845300745972454}, { 0.817584813151583696504920884}, - { 0.170961888760301226363642357}, { 0.985277642388941244774018433}, - {-0.985277642388941244774018433}, { 0.170961888760301226363642357}, - { 0.992479534598709998156767252}, { 0.122410675199216198498704474}, - {-0.122410675199216198498704474}, { 0.992479534598709998156767252}, - { 0.615231590580626845484913563}, { 0.788346427626606262009164705}, - {-0.788346427626606262009164705}, { 0.615231590580626845484913563}, - { 0.870086991108711418652292404}, { 0.492898192229784036873026689}, - {-0.492898192229784036873026689}, { 0.870086991108711418652292404}, - { 0.266712757474898386325286515}, { 0.963776065795439866686464356}, - {-0.963776065795439866686464356}, { 0.266712757474898386325286515}, - { 0.949528180593036667195936074}, { 0.313681740398891476656478846}, - {-0.313681740398891476656478846}, { 0.949528180593036667195936074}, - { 0.449611329654606600046294579}, { 0.893224301195515320342416447}, - {-0.893224301195515320342416447}, { 0.449611329654606600046294579}, - { 0.757208846506484547575464054}, { 0.653172842953776764084203014}, - {-0.653172842953776764084203014}, { 0.757208846506484547575464054}, - { 0.073564563599667423529465622}, { 0.997290456678690216135597140}, - {-0.997290456678690216135597140}, { 0.073564563599667423529465622}, - { 0.997290456678690216135597140}, { 0.073564563599667423529465622}, - {-0.073564563599667423529465622}, { 0.997290456678690216135597140}, - { 0.653172842953776764084203014}, { 0.757208846506484547575464054}, - {-0.757208846506484547575464054}, { 0.653172842953776764084203014}, - { 0.893224301195515320342416447}, { 0.449611329654606600046294579}, - {-0.449611329654606600046294579}, { 0.893224301195515320342416447}, - { 0.313681740398891476656478846}, { 0.949528180593036667195936074}, - {-0.949528180593036667195936074}, { 0.313681740398891476656478846}, - { 0.963776065795439866686464356}, { 0.266712757474898386325286515}, - {-0.266712757474898386325286515}, { 0.963776065795439866686464356}, - { 0.492898192229784036873026689}, { 0.870086991108711418652292404}, - {-0.870086991108711418652292404}, { 0.492898192229784036873026689}, - { 0.788346427626606262009164705}, { 0.615231590580626845484913563}, - {-0.615231590580626845484913563}, { 0.788346427626606262009164705}, - { 0.122410675199216198498704474}, { 0.992479534598709998156767252}, - {-0.992479534598709998156767252}, { 0.122410675199216198498704474}, - { 0.985277642388941244774018433}, { 0.170961888760301226363642357}, - {-0.170961888760301226363642357}, { 0.985277642388941244774018433}, - { 0.575808191417845300745972454}, { 0.817584813151583696504920884}, - {-0.817584813151583696504920884}, { 0.575808191417845300745972454}, - { 0.844853565249707073259571205}, { 0.534997619887097210663076905}, - {-0.534997619887097210663076905}, { 0.844853565249707073259571205}, - { 0.219101240156869797227737547}, { 0.975702130038528544460395766}, - {-0.975702130038528544460395766}, { 0.219101240156869797227737547}, - { 0.932992798834738887711660256}, { 0.359895036534988148775104572}, - {-0.359895036534988148775104572}, { 0.932992798834738887711660256}, - { 0.405241314004989870908481306}, { 0.914209755703530654635014829}, - {-0.914209755703530654635014829}, { 0.405241314004989870908481306}, - { 0.724247082951466920941069243}, { 0.689540544737066924616730630}, - {-0.689540544737066924616730630}, { 0.724247082951466920941069243}, - { 0.024541228522912288031734529}, { 0.999698818696204220115765650}, - {-0.999698818696204220115765650}, { 0.024541228522912288031734529}, - { 0.999924701839144540921646491}, { 0.012271538285719926079408262}, - {-0.012271538285719926079408262}, { 0.999924701839144540921646491}, - { 0.698376249408972853554813503}, { 0.715730825283818654125532623}, - {-0.715730825283818654125532623}, { 0.698376249408972853554813503}, - { 0.919113851690057743908477789}, { 0.393992040061048108596188661}, - {-0.393992040061048108596188661}, { 0.919113851690057743908477789}, - { 0.371317193951837543411934967}, { 0.928506080473215565937167396}, - {-0.928506080473215565937167396}, { 0.371317193951837543411934967}, - { 0.978317370719627633106240097}, { 0.207111376192218549708116020}, - {-0.207111376192218549708116020}, { 0.978317370719627633106240097}, - { 0.545324988422046422313987347}, { 0.838224705554838043186996856}, - {-0.838224705554838043186996856}, { 0.545324988422046422313987347}, - { 0.824589302785025264474803737}, { 0.565731810783613197389765011}, - {-0.565731810783613197389765011}, { 0.824589302785025264474803737}, - { 0.183039887955140958516532578}, { 0.983105487431216327180301155}, - {-0.983105487431216327180301155}, { 0.183039887955140958516532578}, - { 0.993906970002356041546922813}, { 0.110222207293883058807899140}, - {-0.110222207293883058807899140}, { 0.993906970002356041546922813}, - { 0.624859488142386377084072816}, { 0.780737228572094478301588484}, - {-0.780737228572094478301588484}, { 0.624859488142386377084072816}, - { 0.876070094195406607095844268}, { 0.482183772079122748517344481}, - {-0.482183772079122748517344481}, { 0.876070094195406607095844268}, - { 0.278519689385053105207848526}, { 0.960430519415565811199035138}, - {-0.960430519415565811199035138}, { 0.278519689385053105207848526}, - { 0.953306040354193836916740383}, { 0.302005949319228067003463232}, - {-0.302005949319228067003463232}, { 0.953306040354193836916740383}, - { 0.460538710958240023633181487}, { 0.887639620402853947760181617}, - {-0.887639620402853947760181617}, { 0.460538710958240023633181487}, - { 0.765167265622458925888815999}, { 0.643831542889791465068086063}, - {-0.643831542889791465068086063}, { 0.765167265622458925888815999}, - { 0.085797312344439890461556332}, { 0.996312612182778012627226190}, - {-0.996312612182778012627226190}, { 0.085797312344439890461556332}, - { 0.998118112900149207125155861}, { 0.061320736302208577782614593}, - {-0.061320736302208577782614593}, { 0.998118112900149207125155861}, - { 0.662415777590171761113069817}, { 0.749136394523459325469203257}, - {-0.749136394523459325469203257}, { 0.662415777590171761113069817}, - { 0.898674465693953843041976744}, { 0.438616238538527637647025738}, - {-0.438616238538527637647025738}, { 0.898674465693953843041976744}, - { 0.325310292162262934135954708}, { 0.945607325380521325730945387}, - {-0.945607325380521325730945387}, { 0.325310292162262934135954708}, - { 0.966976471044852109087220226}, { 0.254865659604514571553980779}, - {-0.254865659604514571553980779}, { 0.966976471044852109087220226}, - { 0.503538383725717558691867071}, { 0.863972856121586737918147054}, - {-0.863972856121586737918147054}, { 0.503538383725717558691867071}, - { 0.795836904608883536262791915}, { 0.605511041404325513920626941}, - {-0.605511041404325513920626941}, { 0.795836904608883536262791915}, - { 0.134580708507126186316358409}, { 0.990902635427780025108237011}, - {-0.990902635427780025108237011}, { 0.134580708507126186316358409}, - { 0.987301418157858382399815802}, { 0.158858143333861441684385360}, - {-0.158858143333861441684385360}, { 0.987301418157858382399815802}, - { 0.585797857456438860328080838}, { 0.810457198252594791726703434}, - {-0.810457198252594791726703434}, { 0.585797857456438860328080838}, - { 0.851355193105265142261290312}, { 0.524589682678468906215098464}, - {-0.524589682678468906215098464}, { 0.851355193105265142261290312}, - { 0.231058108280671119643236018}, { 0.972939952205560145467720114}, - {-0.972939952205560145467720114}, { 0.231058108280671119643236018}, - { 0.937339011912574923201899593}, { 0.348418680249434568419308588}, - {-0.348418680249434568419308588}, { 0.937339011912574923201899593}, - { 0.416429560097637182562598911}, { 0.909167983090522376563884788}, - {-0.909167983090522376563884788}, { 0.416429560097637182562598911}, - { 0.732654271672412834615546649}, { 0.680600997795453050594430464}, - {-0.680600997795453050594430464}, { 0.732654271672412834615546649}, - { 0.036807222941358832324332691}, { 0.999322384588349500896221011}, - {-0.999322384588349500896221011}, { 0.036807222941358832324332691}, - { 0.999322384588349500896221011}, { 0.036807222941358832324332691}, - {-0.036807222941358832324332691}, { 0.999322384588349500896221011}, - { 0.680600997795453050594430464}, { 0.732654271672412834615546649}, - {-0.732654271672412834615546649}, { 0.680600997795453050594430464}, - { 0.909167983090522376563884788}, { 0.416429560097637182562598911}, - {-0.416429560097637182562598911}, { 0.909167983090522376563884788}, - { 0.348418680249434568419308588}, { 0.937339011912574923201899593}, - {-0.937339011912574923201899593}, { 0.348418680249434568419308588}, - { 0.972939952205560145467720114}, { 0.231058108280671119643236018}, - {-0.231058108280671119643236018}, { 0.972939952205560145467720114}, - { 0.524589682678468906215098464}, { 0.851355193105265142261290312}, - {-0.851355193105265142261290312}, { 0.524589682678468906215098464}, - { 0.810457198252594791726703434}, { 0.585797857456438860328080838}, - {-0.585797857456438860328080838}, { 0.810457198252594791726703434}, - { 0.158858143333861441684385360}, { 0.987301418157858382399815802}, - {-0.987301418157858382399815802}, { 0.158858143333861441684385360}, - { 0.990902635427780025108237011}, { 0.134580708507126186316358409}, - {-0.134580708507126186316358409}, { 0.990902635427780025108237011}, - { 0.605511041404325513920626941}, { 0.795836904608883536262791915}, - {-0.795836904608883536262791915}, { 0.605511041404325513920626941}, - { 0.863972856121586737918147054}, { 0.503538383725717558691867071}, - {-0.503538383725717558691867071}, { 0.863972856121586737918147054}, - { 0.254865659604514571553980779}, { 0.966976471044852109087220226}, - {-0.966976471044852109087220226}, { 0.254865659604514571553980779}, - { 0.945607325380521325730945387}, { 0.325310292162262934135954708}, - {-0.325310292162262934135954708}, { 0.945607325380521325730945387}, - { 0.438616238538527637647025738}, { 0.898674465693953843041976744}, - {-0.898674465693953843041976744}, { 0.438616238538527637647025738}, - { 0.749136394523459325469203257}, { 0.662415777590171761113069817}, - {-0.662415777590171761113069817}, { 0.749136394523459325469203257}, - { 0.061320736302208577782614593}, { 0.998118112900149207125155861}, - {-0.998118112900149207125155861}, { 0.061320736302208577782614593}, - { 0.996312612182778012627226190}, { 0.085797312344439890461556332}, - {-0.085797312344439890461556332}, { 0.996312612182778012627226190}, - { 0.643831542889791465068086063}, { 0.765167265622458925888815999}, - {-0.765167265622458925888815999}, { 0.643831542889791465068086063}, - { 0.887639620402853947760181617}, { 0.460538710958240023633181487}, - {-0.460538710958240023633181487}, { 0.887639620402853947760181617}, - { 0.302005949319228067003463232}, { 0.953306040354193836916740383}, - {-0.953306040354193836916740383}, { 0.302005949319228067003463232}, - { 0.960430519415565811199035138}, { 0.278519689385053105207848526}, - {-0.278519689385053105207848526}, { 0.960430519415565811199035138}, - { 0.482183772079122748517344481}, { 0.876070094195406607095844268}, - {-0.876070094195406607095844268}, { 0.482183772079122748517344481}, - { 0.780737228572094478301588484}, { 0.624859488142386377084072816}, - {-0.624859488142386377084072816}, { 0.780737228572094478301588484}, - { 0.110222207293883058807899140}, { 0.993906970002356041546922813}, - {-0.993906970002356041546922813}, { 0.110222207293883058807899140}, - { 0.983105487431216327180301155}, { 0.183039887955140958516532578}, - {-0.183039887955140958516532578}, { 0.983105487431216327180301155}, - { 0.565731810783613197389765011}, { 0.824589302785025264474803737}, - {-0.824589302785025264474803737}, { 0.565731810783613197389765011}, - { 0.838224705554838043186996856}, { 0.545324988422046422313987347}, - {-0.545324988422046422313987347}, { 0.838224705554838043186996856}, - { 0.207111376192218549708116020}, { 0.978317370719627633106240097}, - {-0.978317370719627633106240097}, { 0.207111376192218549708116020}, - { 0.928506080473215565937167396}, { 0.371317193951837543411934967}, - {-0.371317193951837543411934967}, { 0.928506080473215565937167396}, - { 0.393992040061048108596188661}, { 0.919113851690057743908477789}, - {-0.919113851690057743908477789}, { 0.393992040061048108596188661}, - { 0.715730825283818654125532623}, { 0.698376249408972853554813503}, - {-0.698376249408972853554813503}, { 0.715730825283818654125532623}, - { 0.012271538285719926079408262}, { 0.999924701839144540921646491}, - {-0.999924701839144540921646491}, { 0.012271538285719926079408262}, - { 0.999981175282601142656990438}, { 0.006135884649154475359640235}, - {-0.006135884649154475359640235}, { 0.999981175282601142656990438}, - { 0.702754744457225302452914421}, { 0.711432195745216441522130290}, - {-0.711432195745216441522130290}, { 0.702754744457225302452914421}, - { 0.921514039342041943465396332}, { 0.388345046698826291624993541}, - {-0.388345046698826291624993541}, { 0.921514039342041943465396332}, - { 0.377007410216418256726567823}, { 0.926210242138311341974793388}, - {-0.926210242138311341974793388}, { 0.377007410216418256726567823}, - { 0.979569765685440534439326110}, { 0.201104634842091911558443546}, - {-0.201104634842091911558443546}, { 0.979569765685440534439326110}, - { 0.550457972936604802977289893}, { 0.834862874986380056304401383}, - {-0.834862874986380056304401383}, { 0.550457972936604802977289893}, - { 0.828045045257755752067527592}, { 0.560661576197336023839710223}, - {-0.560661576197336023839710223}, { 0.828045045257755752067527592}, - { 0.189068664149806212754997837}, { 0.981963869109555264072848154}, - {-0.981963869109555264072848154}, { 0.189068664149806212754997837}, - { 0.994564570734255452119106243}, { 0.104121633872054579120943880}, - {-0.104121633872054579120943880}, { 0.994564570734255452119106243}, - { 0.629638238914927025372981341}, { 0.776888465673232450040827983}, - {-0.776888465673232450040827983}, { 0.629638238914927025372981341}, - { 0.879012226428633477831323711}, { 0.476799230063322133342158117}, - {-0.476799230063322133342158117}, { 0.879012226428633477831323711}, - { 0.284407537211271843618310615}, { 0.958703474895871555374645792}, - {-0.958703474895871555374645792}, { 0.284407537211271843618310615}, - { 0.955141168305770721498157712}, { 0.296150888243623824121786128}, - {-0.296150888243623824121786128}, { 0.955141168305770721498157712}, - { 0.465976495767966177902756065}, { 0.884797098430937780104007041}, - {-0.884797098430937780104007041}, { 0.465976495767966177902756065}, - { 0.769103337645579639346626069}, { 0.639124444863775743801488193}, - {-0.639124444863775743801488193}, { 0.769103337645579639346626069}, - { 0.091908956497132728624990979}, { 0.995767414467659793982495643}, - {-0.995767414467659793982495643}, { 0.091908956497132728624990979}, - { 0.998475580573294752208559038}, { 0.055195244349689939809447526}, - {-0.055195244349689939809447526}, { 0.998475580573294752208559038}, - { 0.666999922303637506650154222}, { 0.745057785441465962407907310}, - {-0.745057785441465962407907310}, { 0.666999922303637506650154222}, - { 0.901348847046022014570746093}, { 0.433093818853151968484222638}, - {-0.433093818853151968484222638}, { 0.901348847046022014570746093}, - { 0.331106305759876401737190737}, { 0.943593458161960361495301445}, - {-0.943593458161960361495301445}, { 0.331106305759876401737190737}, - { 0.968522094274417316221088329}, { 0.248927605745720168110682816}, - {-0.248927605745720168110682816}, { 0.968522094274417316221088329}, - { 0.508830142543107036931749324}, { 0.860866938637767279344583877}, - {-0.860866938637767279344583877}, { 0.508830142543107036931749324}, - { 0.799537269107905033500246232}, { 0.600616479383868926653875896}, - {-0.600616479383868926653875896}, { 0.799537269107905033500246232}, - { 0.140658239332849230714788846}, { 0.990058210262297105505906464}, - {-0.990058210262297105505906464}, { 0.140658239332849230714788846}, - { 0.988257567730749491404792538}, { 0.152797185258443427720336613}, - {-0.152797185258443427720336613}, { 0.988257567730749491404792538}, - { 0.590759701858874228423887908}, { 0.806847553543799272206514313}, - {-0.806847553543799272206514313}, { 0.590759701858874228423887908}, - { 0.854557988365400520767862276}, { 0.519355990165589587361829932}, - {-0.519355990165589587361829932}, { 0.854557988365400520767862276}, - { 0.237023605994367206867735915}, { 0.971503890986251775537099622}, - {-0.971503890986251775537099622}, { 0.237023605994367206867735915}, - { 0.939459223602189911962669246}, { 0.342660717311994397592781983}, - {-0.342660717311994397592781983}, { 0.939459223602189911962669246}, - { 0.422000270799799685941287941}, { 0.906595704514915365332960588}, - {-0.906595704514915365332960588}, { 0.422000270799799685941287941}, - { 0.736816568877369875090132520}, { 0.676092703575315960360419228}, - {-0.676092703575315960360419228}, { 0.736816568877369875090132520}, - { 0.042938256934940823077124540}, { 0.999077727752645382888781997}, - {-0.999077727752645382888781997}, { 0.042938256934940823077124540}, - { 0.999529417501093163079703322}, { 0.030674803176636625934021028}, - {-0.030674803176636625934021028}, { 0.999529417501093163079703322}, - { 0.685083667772700381362052545}, { 0.728464390448225196492035438}, - {-0.728464390448225196492035438}, { 0.685083667772700381362052545}, - { 0.911706032005429851404397325}, { 0.410843171057903942183466675}, - {-0.410843171057903942183466675}, { 0.911706032005429851404397325}, - { 0.354163525420490382357395796}, { 0.935183509938947577642207480}, - {-0.935183509938947577642207480}, { 0.354163525420490382357395796}, - { 0.974339382785575860518721668}, { 0.225083911359792835991642120}, - {-0.225083911359792835991642120}, { 0.974339382785575860518721668}, - { 0.529803624686294668216054671}, { 0.848120344803297251279133563}, - {-0.848120344803297251279133563}, { 0.529803624686294668216054671}, - { 0.814036329705948361654516690}, { 0.580813958095764545075595272}, - {-0.580813958095764545075595272}, { 0.814036329705948361654516690}, - { 0.164913120489969921418189113}, { 0.986308097244598647863297524}, - {-0.986308097244598647863297524}, { 0.164913120489969921418189113}, - { 0.991709753669099522860049931}, { 0.128498110793793172624415589}, - {-0.128498110793793172624415589}, { 0.991709753669099522860049931}, - { 0.610382806276309452716352152}, { 0.792106577300212351782342879}, - {-0.792106577300212351782342879}, { 0.610382806276309452716352152}, - { 0.867046245515692651480195629}, { 0.498227666972781852410983869}, - {-0.498227666972781852410983869}, { 0.867046245515692651480195629}, - { 0.260794117915275518280186509}, { 0.965394441697689374550843858}, - {-0.965394441697689374550843858}, { 0.260794117915275518280186509}, - { 0.947585591017741134653387321}, { 0.319502030816015677901518272}, - {-0.319502030816015677901518272}, { 0.947585591017741134653387321}, - { 0.444122144570429231642069418}, { 0.895966249756185155914560282}, - {-0.895966249756185155914560282}, { 0.444122144570429231642069418}, - { 0.753186799043612482483430486}, { 0.657806693297078656931182264}, - {-0.657806693297078656931182264}, { 0.753186799043612482483430486}, - { 0.067443919563664057897972422}, { 0.997723066644191609848546728}, - {-0.997723066644191609848546728}, { 0.067443919563664057897972422}, - { 0.996820299291165714972629398}, { 0.079682437971430121147120656}, - {-0.079682437971430121147120656}, { 0.996820299291165714972629398}, - { 0.648514401022112445084560551}, { 0.761202385484261814029709836}, - {-0.761202385484261814029709836}, { 0.648514401022112445084560551}, - { 0.890448723244757889952150560}, { 0.455083587126343823535869268}, - {-0.455083587126343823535869268}, { 0.890448723244757889952150560}, - { 0.307849640041534893682063646}, { 0.951435020969008369549175569}, - {-0.951435020969008369549175569}, { 0.307849640041534893682063646}, - { 0.962121404269041595429604316}, { 0.272621355449948984493347477}, - {-0.272621355449948984493347477}, { 0.962121404269041595429604316}, - { 0.487550160148435954641485027}, { 0.873094978418290098636085973}, - {-0.873094978418290098636085973}, { 0.487550160148435954641485027}, - { 0.784556597155575233023892575}, { 0.620057211763289178646268191}, - {-0.620057211763289178646268191}, { 0.784556597155575233023892575}, - { 0.116318630911904767252544319}, { 0.993211949234794533104601012}, - {-0.993211949234794533104601012}, { 0.116318630911904767252544319}, - { 0.984210092386929073193874387}, { 0.177004220412148756196839844}, - {-0.177004220412148756196839844}, { 0.984210092386929073193874387}, - { 0.570780745886967280232652864}, { 0.821102514991104679060430820}, - {-0.821102514991104679060430820}, { 0.570780745886967280232652864}, - { 0.841554977436898409603499520}, { 0.540171472729892881297845480}, - {-0.540171472729892881297845480}, { 0.841554977436898409603499520}, - { 0.213110319916091373967757518}, { 0.977028142657754351485866211}, - {-0.977028142657754351485866211}, { 0.213110319916091373967757518}, - { 0.930766961078983731944872340}, { 0.365612997804773870011745909}, - {-0.365612997804773870011745909}, { 0.930766961078983731944872340}, - { 0.399624199845646828544117031}, { 0.916679059921042663116457013}, - {-0.916679059921042663116457013}, { 0.399624199845646828544117031}, - { 0.720002507961381629076682999}, { 0.693971460889654009003734389}, - {-0.693971460889654009003734389}, { 0.720002507961381629076682999}, - { 0.018406729905804820927366313}, { 0.999830581795823422015722275}, - {-0.999830581795823422015722275}, { 0.018406729905804820927366313}, - { 0.999830581795823422015722275}, { 0.018406729905804820927366313}, - {-0.018406729905804820927366313}, { 0.999830581795823422015722275}, - { 0.693971460889654009003734389}, { 0.720002507961381629076682999}, - {-0.720002507961381629076682999}, { 0.693971460889654009003734389}, - { 0.916679059921042663116457013}, { 0.399624199845646828544117031}, - {-0.399624199845646828544117031}, { 0.916679059921042663116457013}, - { 0.365612997804773870011745909}, { 0.930766961078983731944872340}, - {-0.930766961078983731944872340}, { 0.365612997804773870011745909}, - { 0.977028142657754351485866211}, { 0.213110319916091373967757518}, - {-0.213110319916091373967757518}, { 0.977028142657754351485866211}, - { 0.540171472729892881297845480}, { 0.841554977436898409603499520}, - {-0.841554977436898409603499520}, { 0.540171472729892881297845480}, - { 0.821102514991104679060430820}, { 0.570780745886967280232652864}, - {-0.570780745886967280232652864}, { 0.821102514991104679060430820}, - { 0.177004220412148756196839844}, { 0.984210092386929073193874387}, - {-0.984210092386929073193874387}, { 0.177004220412148756196839844}, - { 0.993211949234794533104601012}, { 0.116318630911904767252544319}, - {-0.116318630911904767252544319}, { 0.993211949234794533104601012}, - { 0.620057211763289178646268191}, { 0.784556597155575233023892575}, - {-0.784556597155575233023892575}, { 0.620057211763289178646268191}, - { 0.873094978418290098636085973}, { 0.487550160148435954641485027}, - {-0.487550160148435954641485027}, { 0.873094978418290098636085973}, - { 0.272621355449948984493347477}, { 0.962121404269041595429604316}, - {-0.962121404269041595429604316}, { 0.272621355449948984493347477}, - { 0.951435020969008369549175569}, { 0.307849640041534893682063646}, - {-0.307849640041534893682063646}, { 0.951435020969008369549175569}, - { 0.455083587126343823535869268}, { 0.890448723244757889952150560}, - {-0.890448723244757889952150560}, { 0.455083587126343823535869268}, - { 0.761202385484261814029709836}, { 0.648514401022112445084560551}, - {-0.648514401022112445084560551}, { 0.761202385484261814029709836}, - { 0.079682437971430121147120656}, { 0.996820299291165714972629398}, - {-0.996820299291165714972629398}, { 0.079682437971430121147120656}, - { 0.997723066644191609848546728}, { 0.067443919563664057897972422}, - {-0.067443919563664057897972422}, { 0.997723066644191609848546728}, - { 0.657806693297078656931182264}, { 0.753186799043612482483430486}, - {-0.753186799043612482483430486}, { 0.657806693297078656931182264}, - { 0.895966249756185155914560282}, { 0.444122144570429231642069418}, - {-0.444122144570429231642069418}, { 0.895966249756185155914560282}, - { 0.319502030816015677901518272}, { 0.947585591017741134653387321}, - {-0.947585591017741134653387321}, { 0.319502030816015677901518272}, - { 0.965394441697689374550843858}, { 0.260794117915275518280186509}, - {-0.260794117915275518280186509}, { 0.965394441697689374550843858}, - { 0.498227666972781852410983869}, { 0.867046245515692651480195629}, - {-0.867046245515692651480195629}, { 0.498227666972781852410983869}, - { 0.792106577300212351782342879}, { 0.610382806276309452716352152}, - {-0.610382806276309452716352152}, { 0.792106577300212351782342879}, - { 0.128498110793793172624415589}, { 0.991709753669099522860049931}, - {-0.991709753669099522860049931}, { 0.128498110793793172624415589}, - { 0.986308097244598647863297524}, { 0.164913120489969921418189113}, - {-0.164913120489969921418189113}, { 0.986308097244598647863297524}, - { 0.580813958095764545075595272}, { 0.814036329705948361654516690}, - {-0.814036329705948361654516690}, { 0.580813958095764545075595272}, - { 0.848120344803297251279133563}, { 0.529803624686294668216054671}, - {-0.529803624686294668216054671}, { 0.848120344803297251279133563}, - { 0.225083911359792835991642120}, { 0.974339382785575860518721668}, - {-0.974339382785575860518721668}, { 0.225083911359792835991642120}, - { 0.935183509938947577642207480}, { 0.354163525420490382357395796}, - {-0.354163525420490382357395796}, { 0.935183509938947577642207480}, - { 0.410843171057903942183466675}, { 0.911706032005429851404397325}, - {-0.911706032005429851404397325}, { 0.410843171057903942183466675}, - { 0.728464390448225196492035438}, { 0.685083667772700381362052545}, - {-0.685083667772700381362052545}, { 0.728464390448225196492035438}, - { 0.030674803176636625934021028}, { 0.999529417501093163079703322}, - {-0.999529417501093163079703322}, { 0.030674803176636625934021028}, - { 0.999077727752645382888781997}, { 0.042938256934940823077124540}, - {-0.042938256934940823077124540}, { 0.999077727752645382888781997}, - { 0.676092703575315960360419228}, { 0.736816568877369875090132520}, - {-0.736816568877369875090132520}, { 0.676092703575315960360419228}, - { 0.906595704514915365332960588}, { 0.422000270799799685941287941}, - {-0.422000270799799685941287941}, { 0.906595704514915365332960588}, - { 0.342660717311994397592781983}, { 0.939459223602189911962669246}, - {-0.939459223602189911962669246}, { 0.342660717311994397592781983}, - { 0.971503890986251775537099622}, { 0.237023605994367206867735915}, - {-0.237023605994367206867735915}, { 0.971503890986251775537099622}, - { 0.519355990165589587361829932}, { 0.854557988365400520767862276}, - {-0.854557988365400520767862276}, { 0.519355990165589587361829932}, - { 0.806847553543799272206514313}, { 0.590759701858874228423887908}, - {-0.590759701858874228423887908}, { 0.806847553543799272206514313}, - { 0.152797185258443427720336613}, { 0.988257567730749491404792538}, - {-0.988257567730749491404792538}, { 0.152797185258443427720336613}, - { 0.990058210262297105505906464}, { 0.140658239332849230714788846}, - {-0.140658239332849230714788846}, { 0.990058210262297105505906464}, - { 0.600616479383868926653875896}, { 0.799537269107905033500246232}, - {-0.799537269107905033500246232}, { 0.600616479383868926653875896}, - { 0.860866938637767279344583877}, { 0.508830142543107036931749324}, - {-0.508830142543107036931749324}, { 0.860866938637767279344583877}, - { 0.248927605745720168110682816}, { 0.968522094274417316221088329}, - {-0.968522094274417316221088329}, { 0.248927605745720168110682816}, - { 0.943593458161960361495301445}, { 0.331106305759876401737190737}, - {-0.331106305759876401737190737}, { 0.943593458161960361495301445}, - { 0.433093818853151968484222638}, { 0.901348847046022014570746093}, - {-0.901348847046022014570746093}, { 0.433093818853151968484222638}, - { 0.745057785441465962407907310}, { 0.666999922303637506650154222}, - {-0.666999922303637506650154222}, { 0.745057785441465962407907310}, - { 0.055195244349689939809447526}, { 0.998475580573294752208559038}, - {-0.998475580573294752208559038}, { 0.055195244349689939809447526}, - { 0.995767414467659793982495643}, { 0.091908956497132728624990979}, - {-0.091908956497132728624990979}, { 0.995767414467659793982495643}, - { 0.639124444863775743801488193}, { 0.769103337645579639346626069}, - {-0.769103337645579639346626069}, { 0.639124444863775743801488193}, - { 0.884797098430937780104007041}, { 0.465976495767966177902756065}, - {-0.465976495767966177902756065}, { 0.884797098430937780104007041}, - { 0.296150888243623824121786128}, { 0.955141168305770721498157712}, - {-0.955141168305770721498157712}, { 0.296150888243623824121786128}, - { 0.958703474895871555374645792}, { 0.284407537211271843618310615}, - {-0.284407537211271843618310615}, { 0.958703474895871555374645792}, - { 0.476799230063322133342158117}, { 0.879012226428633477831323711}, - {-0.879012226428633477831323711}, { 0.476799230063322133342158117}, - { 0.776888465673232450040827983}, { 0.629638238914927025372981341}, - {-0.629638238914927025372981341}, { 0.776888465673232450040827983}, - { 0.104121633872054579120943880}, { 0.994564570734255452119106243}, - {-0.994564570734255452119106243}, { 0.104121633872054579120943880}, - { 0.981963869109555264072848154}, { 0.189068664149806212754997837}, - {-0.189068664149806212754997837}, { 0.981963869109555264072848154}, - { 0.560661576197336023839710223}, { 0.828045045257755752067527592}, - {-0.828045045257755752067527592}, { 0.560661576197336023839710223}, - { 0.834862874986380056304401383}, { 0.550457972936604802977289893}, - {-0.550457972936604802977289893}, { 0.834862874986380056304401383}, - { 0.201104634842091911558443546}, { 0.979569765685440534439326110}, - {-0.979569765685440534439326110}, { 0.201104634842091911558443546}, - { 0.926210242138311341974793388}, { 0.377007410216418256726567823}, - {-0.377007410216418256726567823}, { 0.926210242138311341974793388}, - { 0.388345046698826291624993541}, { 0.921514039342041943465396332}, - {-0.921514039342041943465396332}, { 0.388345046698826291624993541}, - { 0.711432195745216441522130290}, { 0.702754744457225302452914421}, - {-0.702754744457225302452914421}, { 0.711432195745216441522130290}, - { 0.006135884649154475359640235}, { 0.999981175282601142656990438}, - {-0.999981175282601142656990438}, { 0.006135884649154475359640235}, - { 0.999995293809576171511580126}, { 0.003067956762965976270145365}, - {-0.003067956762965976270145365}, { 0.999995293809576171511580126}, - { 0.704934080375904908852523758}, { 0.709272826438865651316533772}, - {-0.709272826438865651316533772}, { 0.704934080375904908852523758}, - { 0.922701128333878570437264227}, { 0.385516053843918864075607949}, - {-0.385516053843918864075607949}, { 0.922701128333878570437264227}, - { 0.379847208924051170576281147}, { 0.925049240782677590302371869}, - {-0.925049240782677590302371869}, { 0.379847208924051170576281147}, - { 0.980182135968117392690210009}, { 0.198098410717953586179324918}, - {-0.198098410717953586179324918}, { 0.980182135968117392690210009}, - { 0.553016705580027531764226988}, { 0.833170164701913186439915922}, - {-0.833170164701913186439915922}, { 0.553016705580027531764226988}, - { 0.829761233794523042469023765}, { 0.558118531220556115693702964}, - {-0.558118531220556115693702964}, { 0.829761233794523042469023765}, - { 0.192080397049892441679288205}, { 0.981379193313754574318224190}, - {-0.981379193313754574318224190}, { 0.192080397049892441679288205}, - { 0.994879330794805620591166107}, { 0.101069862754827824987887585}, - {-0.101069862754827824987887585}, { 0.994879330794805620591166107}, - { 0.632018735939809021909403706}, { 0.774953106594873878359129282}, - {-0.774953106594873878359129282}, { 0.632018735939809021909403706}, - { 0.880470889052160770806542929}, { 0.474100214650550014398580015}, - {-0.474100214650550014398580015}, { 0.880470889052160770806542929}, - { 0.287347459544729526477331841}, { 0.957826413027532890321037029}, - {-0.957826413027532890321037029}, { 0.287347459544729526477331841}, - { 0.956045251349996443270479823}, { 0.293219162694258650606608599}, - {-0.293219162694258650606608599}, { 0.956045251349996443270479823}, - { 0.468688822035827933697617870}, { 0.883363338665731594736308015}, - {-0.883363338665731594736308015}, { 0.468688822035827933697617870}, - { 0.771060524261813773200605759}, { 0.636761861236284230413943435}, - {-0.636761861236284230413943435}, { 0.771060524261813773200605759}, - { 0.094963495329638998938034312}, { 0.995480755491926941769171600}, - {-0.995480755491926941769171600}, { 0.094963495329638998938034312}, - { 0.998640218180265222418199049}, { 0.052131704680283321236358216}, - {-0.052131704680283321236358216}, { 0.998640218180265222418199049}, - { 0.669282588346636065720696366}, { 0.743007952135121693517362293}, - {-0.743007952135121693517362293}, { 0.669282588346636065720696366}, - { 0.902673318237258806751502391}, { 0.430326481340082633908199031}, - {-0.430326481340082633908199031}, { 0.902673318237258806751502391}, - { 0.333999651442009404650865481}, { 0.942573197601446879280758735}, - {-0.942573197601446879280758735}, { 0.333999651442009404650865481}, - { 0.969281235356548486048290738}, { 0.245955050335794611599924709}, - {-0.245955050335794611599924709}, { 0.969281235356548486048290738}, - { 0.511468850437970399504391001}, { 0.859301818357008404783582139}, - {-0.859301818357008404783582139}, { 0.511468850437970399504391001}, - { 0.801376171723140219430247777}, { 0.598160706996342311724958652}, - {-0.598160706996342311724958652}, { 0.801376171723140219430247777}, - { 0.143695033150294454819773349}, { 0.989622017463200834623694454}, - {-0.989622017463200834623694454}, { 0.143695033150294454819773349}, - { 0.988721691960323767604516485}, { 0.149764534677321517229695737}, - {-0.149764534677321517229695737}, { 0.988721691960323767604516485}, - { 0.593232295039799808047809426}, { 0.805031331142963597922659282}, - {-0.805031331142963597922659282}, { 0.593232295039799808047809426}, - { 0.856147328375194481019630732}, { 0.516731799017649881508753876}, - {-0.516731799017649881508753876}, { 0.856147328375194481019630732}, - { 0.240003022448741486568922365}, { 0.970772140728950302138169611}, - {-0.970772140728950302138169611}, { 0.240003022448741486568922365}, - { 0.940506070593268323787291309}, { 0.339776884406826857828825803}, - {-0.339776884406826857828825803}, { 0.940506070593268323787291309}, - { 0.424779681209108833357226189}, { 0.905296759318118774354048329}, - {-0.905296759318118774354048329}, { 0.424779681209108833357226189}, - { 0.738887324460615147933116508}, { 0.673829000378756060917568372}, - {-0.673829000378756060917568372}, { 0.738887324460615147933116508}, - { 0.046003182130914628814301788}, { 0.998941293186856850633930266}, - {-0.998941293186856850633930266}, { 0.046003182130914628814301788}, - { 0.999618822495178597116830637}, { 0.027608145778965741612354872}, - {-0.027608145778965741612354872}, { 0.999618822495178597116830637}, - { 0.687315340891759108199186948}, { 0.726359155084345976817494315}, - {-0.726359155084345976817494315}, { 0.687315340891759108199186948}, - { 0.912962190428398164628018233}, { 0.408044162864978680820747499}, - {-0.408044162864978680820747499}, { 0.912962190428398164628018233}, - { 0.357030961233430032614954036}, { 0.934092550404258914729877883}, - {-0.934092550404258914729877883}, { 0.357030961233430032614954036}, - { 0.975025345066994146844913468}, { 0.222093620973203534094094721}, - {-0.222093620973203534094094721}, { 0.975025345066994146844913468}, - { 0.532403127877197971442805218}, { 0.846490938774052078300544488}, - {-0.846490938774052078300544488}, { 0.532403127877197971442805218}, - { 0.815814410806733789010772660}, { 0.578313796411655563342245019}, - {-0.578313796411655563342245019}, { 0.815814410806733789010772660}, - { 0.167938294974731178054745536}, { 0.985797509167567424700995000}, - {-0.985797509167567424700995000}, { 0.167938294974731178054745536}, - { 0.992099313142191757112085445}, { 0.125454983411546238542336453}, - {-0.125454983411546238542336453}, { 0.992099313142191757112085445}, - { 0.612810082429409703935211936}, { 0.790230221437310055030217152}, - {-0.790230221437310055030217152}, { 0.612810082429409703935211936}, - { 0.868570705971340895340449876}, { 0.495565261825772531150266670}, - {-0.495565261825772531150266670}, { 0.868570705971340895340449876}, - { 0.263754678974831383611349322}, { 0.964589793289812723836432159}, - {-0.964589793289812723836432159}, { 0.263754678974831383611349322}, - { 0.948561349915730288158494826}, { 0.316593375556165867243047035}, - {-0.316593375556165867243047035}, { 0.948561349915730288158494826}, - { 0.446868840162374195353044389}, { 0.894599485631382678433072126}, - {-0.894599485631382678433072126}, { 0.446868840162374195353044389}, - { 0.755201376896536527598710756}, { 0.655492852999615385312679701}, - {-0.655492852999615385312679701}, { 0.755201376896536527598710756}, - { 0.070504573389613863027351471}, { 0.997511456140303459699448390}, - {-0.997511456140303459699448390}, { 0.070504573389613863027351471}, - { 0.997060070339482978987989949}, { 0.076623861392031492278332463}, - {-0.076623861392031492278332463}, { 0.997060070339482978987989949}, - { 0.650846684996380915068975573}, { 0.759209188978388033485525443}, - {-0.759209188978388033485525443}, { 0.650846684996380915068975573}, - { 0.891840709392342727796478697}, { 0.452349587233770874133026703}, - {-0.452349587233770874133026703}, { 0.891840709392342727796478697}, - { 0.310767152749611495835997250}, { 0.950486073949481721759926101}, - {-0.950486073949481721759926101}, { 0.310767152749611495835997250}, - { 0.962953266873683886347921481}, { 0.269668325572915106525464462}, - {-0.269668325572915106525464462}, { 0.962953266873683886347921481}, - { 0.490226483288291154229598449}, { 0.871595086655951034842481435}, - {-0.871595086655951034842481435}, { 0.490226483288291154229598449}, - { 0.786455213599085757522319464}, { 0.617647307937803932403979402}, - {-0.617647307937803932403979402}, { 0.786455213599085757522319464}, - { 0.119365214810991364593637790}, { 0.992850414459865090793563344}, - {-0.992850414459865090793563344}, { 0.119365214810991364593637790}, - { 0.984748501801904218556553176}, { 0.173983873387463827950700807}, - {-0.173983873387463827950700807}, { 0.984748501801904218556553176}, - { 0.573297166698042212820171239}, { 0.819347520076796960824689637}, - {-0.819347520076796960824689637}, { 0.573297166698042212820171239}, - { 0.843208239641845437161743865}, { 0.537587076295645482502214932}, - {-0.537587076295645482502214932}, { 0.843208239641845437161743865}, - { 0.216106797076219509948385131}, { 0.976369731330021149312732194}, - {-0.976369731330021149312732194}, { 0.216106797076219509948385131}, - { 0.931884265581668106718557199}, { 0.362755724367397216204854462}, - {-0.362755724367397216204854462}, { 0.931884265581668106718557199}, - { 0.402434650859418441082533934}, { 0.915448716088267819566431292}, - {-0.915448716088267819566431292}, { 0.402434650859418441082533934}, - { 0.722128193929215321243607198}, { 0.691759258364157774906734132}, - {-0.691759258364157774906734132}, { 0.722128193929215321243607198}, - { 0.021474080275469507418374898}, { 0.999769405351215321657617036}, - {-0.999769405351215321657617036}, { 0.021474080275469507418374898}, - { 0.999882347454212525633049627}, { 0.015339206284988101044151868}, - {-0.015339206284988101044151868}, { 0.999882347454212525633049627}, - { 0.696177131491462944788582591}, { 0.717870045055731736211325329}, - {-0.717870045055731736211325329}, { 0.696177131491462944788582591}, - { 0.917900775621390457642276297}, { 0.396809987416710328595290911}, - {-0.396809987416710328595290911}, { 0.917900775621390457642276297}, - { 0.368466829953372331712746222}, { 0.929640895843181265457918066}, - {-0.929640895843181265457918066}, { 0.368466829953372331712746222}, - { 0.977677357824509979943404762}, { 0.210111836880469621717489972}, - {-0.210111836880469621717489972}, { 0.977677357824509979943404762}, - { 0.542750784864515906586768661}, { 0.839893794195999504583383987}, - {-0.839893794195999504583383987}, { 0.542750784864515906586768661}, - { 0.822849781375826332046780034}, { 0.568258952670131549790548489}, - {-0.568258952670131549790548489}, { 0.822849781375826332046780034}, - { 0.180022901405699522679906590}, { 0.983662419211730274396237776}, - {-0.983662419211730274396237776}, { 0.180022901405699522679906590}, - { 0.993564135520595333782021697}, { 0.113270952177564349018228733}, - {-0.113270952177564349018228733}, { 0.993564135520595333782021697}, - { 0.622461279374149972519166721}, { 0.782650596166575738458949301}, - {-0.782650596166575738458949301}, { 0.622461279374149972519166721}, - { 0.874586652278176112634431897}, { 0.484869248000791101822951699}, - {-0.484869248000791101822951699}, { 0.874586652278176112634431897}, - { 0.275571819310958163076425168}, { 0.961280485811320641748659653}, - {-0.961280485811320641748659653}, { 0.275571819310958163076425168}, - { 0.952375012719765858529893608}, { 0.304929229735402406490728633}, - {-0.304929229735402406490728633}, { 0.952375012719765858529893608}, - { 0.457813303598877221904961155}, { 0.889048355854664562540777729}, - {-0.889048355854664562540777729}, { 0.457813303598877221904961155}, - { 0.763188417263381271704838297}, { 0.646176012983316364832802220}, - {-0.646176012983316364832802220}, { 0.763188417263381271704838297}, - { 0.082740264549375693111987083}, { 0.996571145790554847093566910}, - {-0.996571145790554847093566910}, { 0.082740264549375693111987083}, - { 0.997925286198596012623025462}, { 0.064382630929857460819324537}, - {-0.064382630929857460819324537}, { 0.997925286198596012623025462}, - { 0.660114342067420478559490747}, { 0.751165131909686411205819422}, - {-0.751165131909686411205819422}, { 0.660114342067420478559490747}, - { 0.897324580705418281231391836}, { 0.441371268731716692879988968}, - {-0.441371268731716692879988968}, { 0.897324580705418281231391836}, - { 0.322407678801069848384807478}, { 0.946600913083283570044599823}, - {-0.946600913083283570044599823}, { 0.322407678801069848384807478}, - { 0.966190003445412555433832961}, { 0.257831102162159005614471295}, - {-0.257831102162159005614471295}, { 0.966190003445412555433832961}, - { 0.500885382611240786241285004}, { 0.865513624090569082825488358}, - {-0.865513624090569082825488358}, { 0.500885382611240786241285004}, - { 0.793975477554337164895083757}, { 0.607949784967773667243642671}, - {-0.607949784967773667243642671}, { 0.793975477554337164895083757}, - { 0.131540028702883111103387493}, { 0.991310859846115418957349799}, - {-0.991310859846115418957349799}, { 0.131540028702883111103387493}, - { 0.986809401814185476970235952}, { 0.161886393780111837641387995}, - {-0.161886393780111837641387995}, { 0.986809401814185476970235952}, - { 0.583308652937698294392830961}, { 0.812250586585203913049744181}, - {-0.812250586585203913049744181}, { 0.583308652937698294392830961}, - { 0.849741768000852489471268395}, { 0.527199134781901348464274575}, - {-0.527199134781901348464274575}, { 0.849741768000852489471268395}, - { 0.228072083170885739254457379}, { 0.973644249650811925318383912}, - {-0.973644249650811925318383912}, { 0.228072083170885739254457379}, - { 0.936265667170278246576310996}, { 0.351292756085567125601307623}, - {-0.351292756085567125601307623}, { 0.936265667170278246576310996}, - { 0.413638312238434547471944324}, { 0.910441292258067196934095369}, - {-0.910441292258067196934095369}, { 0.413638312238434547471944324}, - { 0.730562769227827561177758850}, { 0.682845546385248068164596123}, - {-0.682845546385248068164596123}, { 0.730562769227827561177758850}, - { 0.033741171851377584833716112}, { 0.999430604555461772019008327}, - {-0.999430604555461772019008327}, { 0.033741171851377584833716112}, - { 0.999204758618363895492950001}, { 0.039872927587739811128578738}, - {-0.039872927587739811128578738}, { 0.999204758618363895492950001}, - { 0.678350043129861486873655042}, { 0.734738878095963464563223604}, - {-0.734738878095963464563223604}, { 0.678350043129861486873655042}, - { 0.907886116487666212038681480}, { 0.419216888363223956433010020}, - {-0.419216888363223956433010020}, { 0.907886116487666212038681480}, - { 0.345541324963989065539191723}, { 0.938403534063108112192420774}, - {-0.938403534063108112192420774}, { 0.345541324963989065539191723}, - { 0.972226497078936305708321144}, { 0.234041958583543423191242045}, - {-0.234041958583543423191242045}, { 0.972226497078936305708321144}, - { 0.521975292937154342694258318}, { 0.852960604930363657746588082}, - {-0.852960604930363657746588082}, { 0.521975292937154342694258318}, - { 0.808656181588174991946968128}, { 0.588281548222645304786439813}, - {-0.588281548222645304786439813}, { 0.808656181588174991946968128}, - { 0.155828397654265235743101486}, { 0.987784141644572154230969032}, - {-0.987784141644572154230969032}, { 0.155828397654265235743101486}, - { 0.990485084256457037998682243}, { 0.137620121586486044948441663}, - {-0.137620121586486044948441663}, { 0.990485084256457037998682243}, - { 0.603066598540348201693430617}, { 0.797690840943391108362662755}, - {-0.797690840943391108362662755}, { 0.603066598540348201693430617}, - { 0.862423956111040538690933878}, { 0.506186645345155291048942344}, - {-0.506186645345155291048942344}, { 0.862423956111040538690933878}, - { 0.251897818154216950498106628}, { 0.967753837093475465243391912}, - {-0.967753837093475465243391912}, { 0.251897818154216950498106628}, - { 0.944604837261480265659265493}, { 0.328209843579092526107916817}, - {-0.328209843579092526107916817}, { 0.944604837261480265659265493}, - { 0.435857079922255491032544080}, { 0.900015892016160228714535267}, - {-0.900015892016160228714535267}, { 0.435857079922255491032544080}, - { 0.747100605980180144323078847}, { 0.664710978203344868130324985}, - {-0.664710978203344868130324985}, { 0.747100605980180144323078847}, - { 0.058258264500435759613979782}, { 0.998301544933892840738782163}, - {-0.998301544933892840738782163}, { 0.058258264500435759613979782}, - { 0.996044700901251989887944810}, { 0.088853552582524596561586535}, - {-0.088853552582524596561586535}, { 0.996044700901251989887944810}, - { 0.641481012808583151988739898}, { 0.767138911935820381181694573}, - {-0.767138911935820381181694573}, { 0.641481012808583151988739898}, - { 0.886222530148880631647990821}, { 0.463259783551860197390719637}, - {-0.463259783551860197390719637}, { 0.886222530148880631647990821}, - { 0.299079826308040476750336973}, { 0.954228095109105629780430732}, - {-0.954228095109105629780430732}, { 0.299079826308040476750336973}, - { 0.959571513081984528335528181}, { 0.281464937925757984095231007}, - {-0.281464937925757984095231007}, { 0.959571513081984528335528181}, - { 0.479493757660153026679839798}, { 0.877545290207261291668470750}, - {-0.877545290207261291668470750}, { 0.479493757660153026679839798}, - { 0.778816512381475953374724325}, { 0.627251815495144113509622565}, - {-0.627251815495144113509622565}, { 0.778816512381475953374724325}, - { 0.107172424956808849175529148}, { 0.994240449453187946358413442}, - {-0.994240449453187946358413442}, { 0.107172424956808849175529148}, - { 0.982539302287441255907040396}, { 0.186055151663446648105438304}, - {-0.186055151663446648105438304}, { 0.982539302287441255907040396}, - { 0.563199344013834115007363772}, { 0.826321062845663480311195452}, - {-0.826321062845663480311195452}, { 0.563199344013834115007363772}, - { 0.836547727223511984524285790}, { 0.547894059173100165608820571}, - {-0.547894059173100165608820571}, { 0.836547727223511984524285790}, - { 0.204108966092816874181696950}, { 0.978948175319062194715480124}, - {-0.978948175319062194715480124}, { 0.204108966092816874181696950}, - { 0.927362525650401087274536959}, { 0.374164062971457997104393020}, - {-0.374164062971457997104393020}, { 0.927362525650401087274536959}, - { 0.391170384302253888687512949}, { 0.920318276709110566440076541}, - {-0.920318276709110566440076541}, { 0.391170384302253888687512949}, - { 0.713584868780793592903125099}, { 0.700568793943248366792866380}, - {-0.700568793943248366792866380}, { 0.713584868780793592903125099}, - { 0.009203754782059819315102378}, { 0.999957644551963866333120920}, - {-0.999957644551963866333120920}, { 0.009203754782059819315102378}, - { 0.999957644551963866333120920}, { 0.009203754782059819315102378}, - {-0.009203754782059819315102378}, { 0.999957644551963866333120920}, - { 0.700568793943248366792866380}, { 0.713584868780793592903125099}, - {-0.713584868780793592903125099}, { 0.700568793943248366792866380}, - { 0.920318276709110566440076541}, { 0.391170384302253888687512949}, - {-0.391170384302253888687512949}, { 0.920318276709110566440076541}, - { 0.374164062971457997104393020}, { 0.927362525650401087274536959}, - {-0.927362525650401087274536959}, { 0.374164062971457997104393020}, - { 0.978948175319062194715480124}, { 0.204108966092816874181696950}, - {-0.204108966092816874181696950}, { 0.978948175319062194715480124}, - { 0.547894059173100165608820571}, { 0.836547727223511984524285790}, - {-0.836547727223511984524285790}, { 0.547894059173100165608820571}, - { 0.826321062845663480311195452}, { 0.563199344013834115007363772}, - {-0.563199344013834115007363772}, { 0.826321062845663480311195452}, - { 0.186055151663446648105438304}, { 0.982539302287441255907040396}, - {-0.982539302287441255907040396}, { 0.186055151663446648105438304}, - { 0.994240449453187946358413442}, { 0.107172424956808849175529148}, - {-0.107172424956808849175529148}, { 0.994240449453187946358413442}, - { 0.627251815495144113509622565}, { 0.778816512381475953374724325}, - {-0.778816512381475953374724325}, { 0.627251815495144113509622565}, - { 0.877545290207261291668470750}, { 0.479493757660153026679839798}, - {-0.479493757660153026679839798}, { 0.877545290207261291668470750}, - { 0.281464937925757984095231007}, { 0.959571513081984528335528181}, - {-0.959571513081984528335528181}, { 0.281464937925757984095231007}, - { 0.954228095109105629780430732}, { 0.299079826308040476750336973}, - {-0.299079826308040476750336973}, { 0.954228095109105629780430732}, - { 0.463259783551860197390719637}, { 0.886222530148880631647990821}, - {-0.886222530148880631647990821}, { 0.463259783551860197390719637}, - { 0.767138911935820381181694573}, { 0.641481012808583151988739898}, - {-0.641481012808583151988739898}, { 0.767138911935820381181694573}, - { 0.088853552582524596561586535}, { 0.996044700901251989887944810}, - {-0.996044700901251989887944810}, { 0.088853552582524596561586535}, - { 0.998301544933892840738782163}, { 0.058258264500435759613979782}, - {-0.058258264500435759613979782}, { 0.998301544933892840738782163}, - { 0.664710978203344868130324985}, { 0.747100605980180144323078847}, - {-0.747100605980180144323078847}, { 0.664710978203344868130324985}, - { 0.900015892016160228714535267}, { 0.435857079922255491032544080}, - {-0.435857079922255491032544080}, { 0.900015892016160228714535267}, - { 0.328209843579092526107916817}, { 0.944604837261480265659265493}, - {-0.944604837261480265659265493}, { 0.328209843579092526107916817}, - { 0.967753837093475465243391912}, { 0.251897818154216950498106628}, - {-0.251897818154216950498106628}, { 0.967753837093475465243391912}, - { 0.506186645345155291048942344}, { 0.862423956111040538690933878}, - {-0.862423956111040538690933878}, { 0.506186645345155291048942344}, - { 0.797690840943391108362662755}, { 0.603066598540348201693430617}, - {-0.603066598540348201693430617}, { 0.797690840943391108362662755}, - { 0.137620121586486044948441663}, { 0.990485084256457037998682243}, - {-0.990485084256457037998682243}, { 0.137620121586486044948441663}, - { 0.987784141644572154230969032}, { 0.155828397654265235743101486}, - {-0.155828397654265235743101486}, { 0.987784141644572154230969032}, - { 0.588281548222645304786439813}, { 0.808656181588174991946968128}, - {-0.808656181588174991946968128}, { 0.588281548222645304786439813}, - { 0.852960604930363657746588082}, { 0.521975292937154342694258318}, - {-0.521975292937154342694258318}, { 0.852960604930363657746588082}, - { 0.234041958583543423191242045}, { 0.972226497078936305708321144}, - {-0.972226497078936305708321144}, { 0.234041958583543423191242045}, - { 0.938403534063108112192420774}, { 0.345541324963989065539191723}, - {-0.345541324963989065539191723}, { 0.938403534063108112192420774}, - { 0.419216888363223956433010020}, { 0.907886116487666212038681480}, - {-0.907886116487666212038681480}, { 0.419216888363223956433010020}, - { 0.734738878095963464563223604}, { 0.678350043129861486873655042}, - {-0.678350043129861486873655042}, { 0.734738878095963464563223604}, - { 0.039872927587739811128578738}, { 0.999204758618363895492950001}, - {-0.999204758618363895492950001}, { 0.039872927587739811128578738}, - { 0.999430604555461772019008327}, { 0.033741171851377584833716112}, - {-0.033741171851377584833716112}, { 0.999430604555461772019008327}, - { 0.682845546385248068164596123}, { 0.730562769227827561177758850}, - {-0.730562769227827561177758850}, { 0.682845546385248068164596123}, - { 0.910441292258067196934095369}, { 0.413638312238434547471944324}, - {-0.413638312238434547471944324}, { 0.910441292258067196934095369}, - { 0.351292756085567125601307623}, { 0.936265667170278246576310996}, - {-0.936265667170278246576310996}, { 0.351292756085567125601307623}, - { 0.973644249650811925318383912}, { 0.228072083170885739254457379}, - {-0.228072083170885739254457379}, { 0.973644249650811925318383912}, - { 0.527199134781901348464274575}, { 0.849741768000852489471268395}, - {-0.849741768000852489471268395}, { 0.527199134781901348464274575}, - { 0.812250586585203913049744181}, { 0.583308652937698294392830961}, - {-0.583308652937698294392830961}, { 0.812250586585203913049744181}, - { 0.161886393780111837641387995}, { 0.986809401814185476970235952}, - {-0.986809401814185476970235952}, { 0.161886393780111837641387995}, - { 0.991310859846115418957349799}, { 0.131540028702883111103387493}, - {-0.131540028702883111103387493}, { 0.991310859846115418957349799}, - { 0.607949784967773667243642671}, { 0.793975477554337164895083757}, - {-0.793975477554337164895083757}, { 0.607949784967773667243642671}, - { 0.865513624090569082825488358}, { 0.500885382611240786241285004}, - {-0.500885382611240786241285004}, { 0.865513624090569082825488358}, - { 0.257831102162159005614471295}, { 0.966190003445412555433832961}, - {-0.966190003445412555433832961}, { 0.257831102162159005614471295}, - { 0.946600913083283570044599823}, { 0.322407678801069848384807478}, - {-0.322407678801069848384807478}, { 0.946600913083283570044599823}, - { 0.441371268731716692879988968}, { 0.897324580705418281231391836}, - {-0.897324580705418281231391836}, { 0.441371268731716692879988968}, - { 0.751165131909686411205819422}, { 0.660114342067420478559490747}, - {-0.660114342067420478559490747}, { 0.751165131909686411205819422}, - { 0.064382630929857460819324537}, { 0.997925286198596012623025462}, - {-0.997925286198596012623025462}, { 0.064382630929857460819324537}, - { 0.996571145790554847093566910}, { 0.082740264549375693111987083}, - {-0.082740264549375693111987083}, { 0.996571145790554847093566910}, - { 0.646176012983316364832802220}, { 0.763188417263381271704838297}, - {-0.763188417263381271704838297}, { 0.646176012983316364832802220}, - { 0.889048355854664562540777729}, { 0.457813303598877221904961155}, - {-0.457813303598877221904961155}, { 0.889048355854664562540777729}, - { 0.304929229735402406490728633}, { 0.952375012719765858529893608}, - {-0.952375012719765858529893608}, { 0.304929229735402406490728633}, - { 0.961280485811320641748659653}, { 0.275571819310958163076425168}, - {-0.275571819310958163076425168}, { 0.961280485811320641748659653}, - { 0.484869248000791101822951699}, { 0.874586652278176112634431897}, - {-0.874586652278176112634431897}, { 0.484869248000791101822951699}, - { 0.782650596166575738458949301}, { 0.622461279374149972519166721}, - {-0.622461279374149972519166721}, { 0.782650596166575738458949301}, - { 0.113270952177564349018228733}, { 0.993564135520595333782021697}, - {-0.993564135520595333782021697}, { 0.113270952177564349018228733}, - { 0.983662419211730274396237776}, { 0.180022901405699522679906590}, - {-0.180022901405699522679906590}, { 0.983662419211730274396237776}, - { 0.568258952670131549790548489}, { 0.822849781375826332046780034}, - {-0.822849781375826332046780034}, { 0.568258952670131549790548489}, - { 0.839893794195999504583383987}, { 0.542750784864515906586768661}, - {-0.542750784864515906586768661}, { 0.839893794195999504583383987}, - { 0.210111836880469621717489972}, { 0.977677357824509979943404762}, - {-0.977677357824509979943404762}, { 0.210111836880469621717489972}, - { 0.929640895843181265457918066}, { 0.368466829953372331712746222}, - {-0.368466829953372331712746222}, { 0.929640895843181265457918066}, - { 0.396809987416710328595290911}, { 0.917900775621390457642276297}, - {-0.917900775621390457642276297}, { 0.396809987416710328595290911}, - { 0.717870045055731736211325329}, { 0.696177131491462944788582591}, - {-0.696177131491462944788582591}, { 0.717870045055731736211325329}, - { 0.015339206284988101044151868}, { 0.999882347454212525633049627}, - {-0.999882347454212525633049627}, { 0.015339206284988101044151868}, - { 0.999769405351215321657617036}, { 0.021474080275469507418374898}, - {-0.021474080275469507418374898}, { 0.999769405351215321657617036}, - { 0.691759258364157774906734132}, { 0.722128193929215321243607198}, - {-0.722128193929215321243607198}, { 0.691759258364157774906734132}, - { 0.915448716088267819566431292}, { 0.402434650859418441082533934}, - {-0.402434650859418441082533934}, { 0.915448716088267819566431292}, - { 0.362755724367397216204854462}, { 0.931884265581668106718557199}, - {-0.931884265581668106718557199}, { 0.362755724367397216204854462}, - { 0.976369731330021149312732194}, { 0.216106797076219509948385131}, - {-0.216106797076219509948385131}, { 0.976369731330021149312732194}, - { 0.537587076295645482502214932}, { 0.843208239641845437161743865}, - {-0.843208239641845437161743865}, { 0.537587076295645482502214932}, - { 0.819347520076796960824689637}, { 0.573297166698042212820171239}, - {-0.573297166698042212820171239}, { 0.819347520076796960824689637}, - { 0.173983873387463827950700807}, { 0.984748501801904218556553176}, - {-0.984748501801904218556553176}, { 0.173983873387463827950700807}, - { 0.992850414459865090793563344}, { 0.119365214810991364593637790}, - {-0.119365214810991364593637790}, { 0.992850414459865090793563344}, - { 0.617647307937803932403979402}, { 0.786455213599085757522319464}, - {-0.786455213599085757522319464}, { 0.617647307937803932403979402}, - { 0.871595086655951034842481435}, { 0.490226483288291154229598449}, - {-0.490226483288291154229598449}, { 0.871595086655951034842481435}, - { 0.269668325572915106525464462}, { 0.962953266873683886347921481}, - {-0.962953266873683886347921481}, { 0.269668325572915106525464462}, - { 0.950486073949481721759926101}, { 0.310767152749611495835997250}, - {-0.310767152749611495835997250}, { 0.950486073949481721759926101}, - { 0.452349587233770874133026703}, { 0.891840709392342727796478697}, - {-0.891840709392342727796478697}, { 0.452349587233770874133026703}, - { 0.759209188978388033485525443}, { 0.650846684996380915068975573}, - {-0.650846684996380915068975573}, { 0.759209188978388033485525443}, - { 0.076623861392031492278332463}, { 0.997060070339482978987989949}, - {-0.997060070339482978987989949}, { 0.076623861392031492278332463}, - { 0.997511456140303459699448390}, { 0.070504573389613863027351471}, - {-0.070504573389613863027351471}, { 0.997511456140303459699448390}, - { 0.655492852999615385312679701}, { 0.755201376896536527598710756}, - {-0.755201376896536527598710756}, { 0.655492852999615385312679701}, - { 0.894599485631382678433072126}, { 0.446868840162374195353044389}, - {-0.446868840162374195353044389}, { 0.894599485631382678433072126}, - { 0.316593375556165867243047035}, { 0.948561349915730288158494826}, - {-0.948561349915730288158494826}, { 0.316593375556165867243047035}, - { 0.964589793289812723836432159}, { 0.263754678974831383611349322}, - {-0.263754678974831383611349322}, { 0.964589793289812723836432159}, - { 0.495565261825772531150266670}, { 0.868570705971340895340449876}, - {-0.868570705971340895340449876}, { 0.495565261825772531150266670}, - { 0.790230221437310055030217152}, { 0.612810082429409703935211936}, - {-0.612810082429409703935211936}, { 0.790230221437310055030217152}, - { 0.125454983411546238542336453}, { 0.992099313142191757112085445}, - {-0.992099313142191757112085445}, { 0.125454983411546238542336453}, - { 0.985797509167567424700995000}, { 0.167938294974731178054745536}, - {-0.167938294974731178054745536}, { 0.985797509167567424700995000}, - { 0.578313796411655563342245019}, { 0.815814410806733789010772660}, - {-0.815814410806733789010772660}, { 0.578313796411655563342245019}, - { 0.846490938774052078300544488}, { 0.532403127877197971442805218}, - {-0.532403127877197971442805218}, { 0.846490938774052078300544488}, - { 0.222093620973203534094094721}, { 0.975025345066994146844913468}, - {-0.975025345066994146844913468}, { 0.222093620973203534094094721}, - { 0.934092550404258914729877883}, { 0.357030961233430032614954036}, - {-0.357030961233430032614954036}, { 0.934092550404258914729877883}, - { 0.408044162864978680820747499}, { 0.912962190428398164628018233}, - {-0.912962190428398164628018233}, { 0.408044162864978680820747499}, - { 0.726359155084345976817494315}, { 0.687315340891759108199186948}, - {-0.687315340891759108199186948}, { 0.726359155084345976817494315}, - { 0.027608145778965741612354872}, { 0.999618822495178597116830637}, - {-0.999618822495178597116830637}, { 0.027608145778965741612354872}, - { 0.998941293186856850633930266}, { 0.046003182130914628814301788}, - {-0.046003182130914628814301788}, { 0.998941293186856850633930266}, - { 0.673829000378756060917568372}, { 0.738887324460615147933116508}, - {-0.738887324460615147933116508}, { 0.673829000378756060917568372}, - { 0.905296759318118774354048329}, { 0.424779681209108833357226189}, - {-0.424779681209108833357226189}, { 0.905296759318118774354048329}, - { 0.339776884406826857828825803}, { 0.940506070593268323787291309}, - {-0.940506070593268323787291309}, { 0.339776884406826857828825803}, - { 0.970772140728950302138169611}, { 0.240003022448741486568922365}, - {-0.240003022448741486568922365}, { 0.970772140728950302138169611}, - { 0.516731799017649881508753876}, { 0.856147328375194481019630732}, - {-0.856147328375194481019630732}, { 0.516731799017649881508753876}, - { 0.805031331142963597922659282}, { 0.593232295039799808047809426}, - {-0.593232295039799808047809426}, { 0.805031331142963597922659282}, - { 0.149764534677321517229695737}, { 0.988721691960323767604516485}, - {-0.988721691960323767604516485}, { 0.149764534677321517229695737}, - { 0.989622017463200834623694454}, { 0.143695033150294454819773349}, - {-0.143695033150294454819773349}, { 0.989622017463200834623694454}, - { 0.598160706996342311724958652}, { 0.801376171723140219430247777}, - {-0.801376171723140219430247777}, { 0.598160706996342311724958652}, - { 0.859301818357008404783582139}, { 0.511468850437970399504391001}, - {-0.511468850437970399504391001}, { 0.859301818357008404783582139}, - { 0.245955050335794611599924709}, { 0.969281235356548486048290738}, - {-0.969281235356548486048290738}, { 0.245955050335794611599924709}, - { 0.942573197601446879280758735}, { 0.333999651442009404650865481}, - {-0.333999651442009404650865481}, { 0.942573197601446879280758735}, - { 0.430326481340082633908199031}, { 0.902673318237258806751502391}, - {-0.902673318237258806751502391}, { 0.430326481340082633908199031}, - { 0.743007952135121693517362293}, { 0.669282588346636065720696366}, - {-0.669282588346636065720696366}, { 0.743007952135121693517362293}, - { 0.052131704680283321236358216}, { 0.998640218180265222418199049}, - {-0.998640218180265222418199049}, { 0.052131704680283321236358216}, - { 0.995480755491926941769171600}, { 0.094963495329638998938034312}, - {-0.094963495329638998938034312}, { 0.995480755491926941769171600}, - { 0.636761861236284230413943435}, { 0.771060524261813773200605759}, - {-0.771060524261813773200605759}, { 0.636761861236284230413943435}, - { 0.883363338665731594736308015}, { 0.468688822035827933697617870}, - {-0.468688822035827933697617870}, { 0.883363338665731594736308015}, - { 0.293219162694258650606608599}, { 0.956045251349996443270479823}, - {-0.956045251349996443270479823}, { 0.293219162694258650606608599}, - { 0.957826413027532890321037029}, { 0.287347459544729526477331841}, - {-0.287347459544729526477331841}, { 0.957826413027532890321037029}, - { 0.474100214650550014398580015}, { 0.880470889052160770806542929}, - {-0.880470889052160770806542929}, { 0.474100214650550014398580015}, - { 0.774953106594873878359129282}, { 0.632018735939809021909403706}, - {-0.632018735939809021909403706}, { 0.774953106594873878359129282}, - { 0.101069862754827824987887585}, { 0.994879330794805620591166107}, - {-0.994879330794805620591166107}, { 0.101069862754827824987887585}, - { 0.981379193313754574318224190}, { 0.192080397049892441679288205}, - {-0.192080397049892441679288205}, { 0.981379193313754574318224190}, - { 0.558118531220556115693702964}, { 0.829761233794523042469023765}, - {-0.829761233794523042469023765}, { 0.558118531220556115693702964}, - { 0.833170164701913186439915922}, { 0.553016705580027531764226988}, - {-0.553016705580027531764226988}, { 0.833170164701913186439915922}, - { 0.198098410717953586179324918}, { 0.980182135968117392690210009}, - {-0.980182135968117392690210009}, { 0.198098410717953586179324918}, - { 0.925049240782677590302371869}, { 0.379847208924051170576281147}, - {-0.379847208924051170576281147}, { 0.925049240782677590302371869}, - { 0.385516053843918864075607949}, { 0.922701128333878570437264227}, - {-0.922701128333878570437264227}, { 0.385516053843918864075607949}, - { 0.709272826438865651316533772}, { 0.704934080375904908852523758}, - {-0.704934080375904908852523758}, { 0.709272826438865651316533772}, - { 0.003067956762965976270145365}, { 0.999995293809576171511580126}, - {-0.999995293809576171511580126}, { 0.003067956762965976270145365} -}; - -const fpr fpr_p2_tab[] = { - { 2.00000000000 }, - { 1.00000000000 }, - { 0.50000000000 }, - { 0.25000000000 }, - { 0.12500000000 }, - { 0.06250000000 }, - { 0.03125000000 }, - { 0.01562500000 }, - { 0.00781250000 }, - { 0.00390625000 }, - { 0.00195312500 } -}; - -#else // yyyFPNATIVE+0 yyyFPEMU+0 - -#error No FP implementation selected - -#endif // yyyFPNATIVE- yyyFPEMU- diff --git a/falcon/fpr.h b/falcon/fpr.h deleted file mode 100644 index c55b956..0000000 --- a/falcon/fpr.h +++ /dev/null @@ -1,939 +0,0 @@ -/* - * Floating-point operations. - * - * ==========================(LICENSE BEGIN)============================ - * - * Copyright (c) 2017-2019 Falcon Project - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * ===========================(LICENSE END)============================= - * - * @author Thomas Pornin - */ - -#if FALCON_FPEMU // yyyFPEMU+1 yyyFPNATIVE+0 - -/* ====================================================================== */ -/* - * Custom floating-point implementation with integer arithmetics. We - * use IEEE-754 "binary64" format, with some simplifications: - * - * - Top bit is s = 1 for negative, 0 for positive. - * - * - Exponent e uses the next 11 bits (bits 52 to 62, inclusive). - * - * - Mantissa m uses the 52 low bits. - * - * Encoded value is, in general: (-1)^s * 2^(e-1023) * (1 + m*2^(-52)) - * i.e. the mantissa really is a 53-bit number (less than 2.0, but not - * less than 1.0), but the top bit (equal to 1 by definition) is omitted - * in the encoding. - * - * In IEEE-754, there are some special values: - * - * - If e = 2047, then the value is either an infinite (m = 0) or - * a NaN (m != 0). - * - * - If e = 0, then the value is either a zero (m = 0) or a subnormal, - * aka "denormalized number" (m != 0). - * - * Of these, we only need the zeros. The caller is responsible for not - * providing operands that would lead to infinites, NaNs or subnormals. - * If inputs are such that values go out of range, then indeterminate - * values are returned (it would still be deterministic, but no specific - * value may be relied upon). - * - * At the C level, the three parts are stored in a 64-bit unsigned - * word. - * - * One may note that a property of the IEEE-754 format is that order - * is preserved for positive values: if two positive floating-point - * values x and y are such that x < y, then their respective encodings - * as _signed_ 64-bit integers i64(x) and i64(y) will be such that - * i64(x) < i64(y). For negative values, order is reversed: if x < 0, - * y < 0, and x < y, then ia64(x) > ia64(y). - * - * IMPORTANT ASSUMPTIONS: - * ====================== - * - * For proper computations, and constant-time behaviour, we assume the - * following: - * - * - 32x32->64 multiplication (unsigned) has an execution time that - * is independent of its operands. This is true of most modern - * x86 and ARM cores. Notable exceptions are the ARM Cortex M0, M0+ - * and M3 (in the M0 and M0+, this is done in software, so it depends - * on that routine), and the PowerPC cores from the G3/G4 lines. - * For more info, see: https://www.bearssl.org/ctmul.html - * - * - Left-shifts and right-shifts of 32-bit values have an execution - * time which does not depend on the shifted value nor on the - * shift count. An historical exception is the Pentium IV, but most - * modern CPU have barrel shifters. Some small microcontrollers - * might have varying-time shifts (not the ARM Cortex M*, though). - * - * - Right-shift of a signed negative value performs a sign extension. - * As per the C standard, this operation returns an - * implementation-defined result (this is NOT an "undefined - * behaviour"). On most/all systems, an arithmetic shift is - * performed, because this is what makes most sense. - */ - -/* - * Normally we should declare the 'fpr' type to be a struct or union - * around the internal 64-bit value; however, we want to use the - * direct 64-bit integer type to enable a lighter call convention on - * ARM platforms. This means that direct (invalid) use of operators - * such as '*' or '+' will not be caught by the compiler. We rely on - * the "normal" (non-emulated) code to detect such instances. - */ -typedef uint64_t fpr; - -/* - * For computations, we split values into an integral mantissa in the - * 2^54..2^55 range, and an (adjusted) exponent. The lowest bit is - * "sticky" (it is set to 1 if any of the bits below it is 1); when - * re-encoding, the low two bits are dropped, but may induce an - * increment in the value for proper rounding. - */ - -/* - * Right-shift a 64-bit unsigned value by a possibly secret shift count. - * We assumed that the underlying architecture had a barrel shifter for - * 32-bit shifts, but for 64-bit shifts on a 32-bit system, this will - * typically invoke a software routine that is not necessarily - * constant-time; hence the function below. - * - * Shift count n MUST be in the 0..63 range. - */ -static inline uint64_t -fpr_ursh(uint64_t x, int n) -{ - x ^= (x ^ (x >> 32)) & -(uint64_t)(n >> 5); - return x >> (n & 31); -} - -/* - * Right-shift a 64-bit signed value by a possibly secret shift count - * (see fpr_ursh() for the rationale). - * - * Shift count n MUST be in the 0..63 range. - */ -static inline int64_t -fpr_irsh(int64_t x, int n) -{ - x ^= (x ^ (x >> 32)) & -(int64_t)(n >> 5); - return x >> (n & 31); -} - -/* - * Left-shift a 64-bit unsigned value by a possibly secret shift count - * (see fpr_ursh() for the rationale). - * - * Shift count n MUST be in the 0..63 range. - */ -static inline uint64_t -fpr_ulsh(uint64_t x, int n) -{ - x ^= (x ^ (x << 32)) & -(uint64_t)(n >> 5); - return x << (n & 31); -} - -/* - * Expectations: - * s = 0 or 1 - * exponent e is "arbitrary" and unbiased - * 2^54 <= m < 2^55 - * Numerical value is (-1)^2 * m * 2^e - * - * Exponents which are too low lead to value zero. If the exponent is - * too large, the returned value is indeterminate. - * - * If m = 0, then a zero is returned (using the provided sign). - * If e < -1076, then a zero is returned (regardless of the value of m). - * If e >= -1076 and e != 0, m must be within the expected range - * (2^54 to 2^55-1). - */ -static inline fpr -FPR(int s, int e, uint64_t m) -{ - fpr x; - uint32_t t; - unsigned f; - - /* - * If e >= -1076, then the value is "normal"; otherwise, it - * should be a subnormal, which we clamp down to zero. - */ - e += 1076; - t = (uint32_t)e >> 31; - m &= (uint64_t)t - 1; - - /* - * If m = 0 then we want a zero; make e = 0 too, but conserve - * the sign. - */ - t = (uint32_t)(m >> 54); - e &= -(int)t; - - /* - * The 52 mantissa bits come from m. Value m has its top bit set - * (unless it is a zero); we leave it "as is": the top bit will - * increment the exponent by 1, except when m = 0, which is - * exactly what we want. - */ - x = (((uint64_t)s << 63) | (m >> 2)) + ((uint64_t)(uint32_t)e << 52); - - /* - * Rounding: if the low three bits of m are 011, 110 or 111, - * then the value should be incremented to get the next - * representable value. This implements the usual - * round-to-nearest rule (with preference to even values in case - * of a tie). Note that the increment may make a carry spill - * into the exponent field, which is again exactly what we want - * in that case. - */ - f = (unsigned)m & 7U; - x += (0xC8U >> f) & 1; - return x; -} - -#define fpr_scaled Zf(fpr_scaled) -fpr fpr_scaled(int64_t i, int sc); - -static inline fpr -fpr_of(int64_t i) -{ - return fpr_scaled(i, 0); -} - -static const fpr fpr_q = 4667981563525332992; -static const fpr fpr_inverse_of_q = 4545632735260551042; -static const fpr fpr_inv_2sqrsigma0 = 4594603506513722306; -static const fpr fpr_inv_sigma[] = { - 0, /* unused */ - 4574611497772390042, - 4574501679055810265, - 4574396282908341804, - 4574245855758572086, - 4574103865040221165, - 4573969550563515544, - 4573842244705920822, - 4573721358406441454, - 4573606369665796042, - 4573496814039276259 -}; -static const fpr fpr_sigma_min[] = { - 0, /* unused */ - 4607707126469777035, - 4607777455861499430, - 4607846828256951418, - 4607949175006100261, - 4608049571757433526, - 4608148125896792003, - 4608244935301382692, - 4608340089478362016, - 4608433670533905013, - 4608525754002622308 -}; -static const fpr fpr_log2 = 4604418534313441775; -static const fpr fpr_inv_log2 = 4609176140021203710; -static const fpr fpr_bnorm_max = 4670353323383631276; -static const fpr fpr_zero = 0; -static const fpr fpr_one = 4607182418800017408; -static const fpr fpr_two = 4611686018427387904; -static const fpr fpr_onehalf = 4602678819172646912; -static const fpr fpr_invsqrt2 = 4604544271217802189; -static const fpr fpr_invsqrt8 = 4600040671590431693; -static const fpr fpr_ptwo31 = 4746794007248502784; -static const fpr fpr_ptwo31m1 = 4746794007244308480; -static const fpr fpr_mtwo31m1 = 13970166044099084288U; -static const fpr fpr_ptwo63m1 = 4890909195324358656; -static const fpr fpr_mtwo63m1 = 14114281232179134464U; -static const fpr fpr_ptwo63 = 4890909195324358656; - -static inline int64_t -fpr_rint(fpr x) -{ - uint64_t m, d; - int e; - uint32_t s, dd, f; - - /* - * We assume that the value fits in -(2^63-1)..+(2^63-1). We can - * thus extract the mantissa as a 63-bit integer, then right-shift - * it as needed. - */ - m = ((x << 10) | ((uint64_t)1 << 62)) & (((uint64_t)1 << 63) - 1); - e = 1085 - ((int)(x >> 52) & 0x7FF); - - /* - * If a shift of more than 63 bits is needed, then simply set m - * to zero. This also covers the case of an input operand equal - * to zero. - */ - m &= -(uint64_t)((uint32_t)(e - 64) >> 31); - e &= 63; - - /* - * Right-shift m as needed. Shift count is e. Proper rounding - * mandates that: - * - If the highest dropped bit is zero, then round low. - * - If the highest dropped bit is one, and at least one of the - * other dropped bits is one, then round up. - * - If the highest dropped bit is one, and all other dropped - * bits are zero, then round up if the lowest kept bit is 1, - * or low otherwise (i.e. ties are broken by "rounding to even"). - * - * We thus first extract a word consisting of all the dropped bit - * AND the lowest kept bit; then we shrink it down to three bits, - * the lowest being "sticky". - */ - d = fpr_ulsh(m, 63 - e); - dd = (uint32_t)d | ((uint32_t)(d >> 32) & 0x1FFFFFFF); - f = (uint32_t)(d >> 61) | ((dd | -dd) >> 31); - m = fpr_ursh(m, e) + (uint64_t)((0xC8U >> f) & 1U); - - /* - * Apply the sign bit. - */ - s = (uint32_t)(x >> 63); - return ((int64_t)m ^ -(int64_t)s) + (int64_t)s; -} - -static inline int64_t -fpr_floor(fpr x) -{ - uint64_t t; - int64_t xi; - int e, cc; - - /* - * We extract the integer as a _signed_ 64-bit integer with - * a scaling factor. Since we assume that the value fits - * in the -(2^63-1)..+(2^63-1) range, we can left-shift the - * absolute value to make it in the 2^62..2^63-1 range: we - * will only need a right-shift afterwards. - */ - e = (int)(x >> 52) & 0x7FF; - t = x >> 63; - xi = (int64_t)(((x << 10) | ((uint64_t)1 << 62)) - & (((uint64_t)1 << 63) - 1)); - xi = (xi ^ -(int64_t)t) + (int64_t)t; - cc = 1085 - e; - - /* - * We perform an arithmetic right-shift on the value. This - * applies floor() semantics on both positive and negative values - * (rounding toward minus infinity). - */ - xi = fpr_irsh(xi, cc & 63); - - /* - * If the true shift count was 64 or more, then we should instead - * replace xi with 0 (if nonnegative) or -1 (if negative). Edge - * case: -0 will be floored to -1, not 0 (whether this is correct - * is debatable; in any case, the other functions normalize zero - * to +0). - * - * For an input of zero, the non-shifted xi was incorrect (we used - * a top implicit bit of value 1, not 0), but this does not matter - * since this operation will clamp it down. - */ - xi ^= (xi ^ -(int64_t)t) & -(int64_t)((uint32_t)(63 - cc) >> 31); - return xi; -} - -static inline int64_t -fpr_trunc(fpr x) -{ - uint64_t t, xu; - int e, cc; - - /* - * Extract the absolute value. Since we assume that the value - * fits in the -(2^63-1)..+(2^63-1) range, we can left-shift - * the absolute value into the 2^62..2^63-1 range, and then - * do a right shift afterwards. - */ - e = (int)(x >> 52) & 0x7FF; - xu = ((x << 10) | ((uint64_t)1 << 62)) & (((uint64_t)1 << 63) - 1); - cc = 1085 - e; - xu = fpr_ursh(xu, cc & 63); - - /* - * If the exponent is too low (cc > 63), then the shift was wrong - * and we must clamp the value to 0. This also covers the case - * of an input equal to zero. - */ - xu &= -(uint64_t)((uint32_t)(cc - 64) >> 31); - - /* - * Apply back the sign, if the source value is negative. - */ - t = x >> 63; - xu = (xu ^ -t) + t; - return *(int64_t *)&xu; -} - -#define fpr_add Zf(fpr_add) -fpr fpr_add(fpr x, fpr y); - -static inline fpr -fpr_sub(fpr x, fpr y) -{ - y ^= (uint64_t)1 << 63; - return fpr_add(x, y); -} - -static inline fpr -fpr_neg(fpr x) -{ - x ^= (uint64_t)1 << 63; - return x; -} - -static inline fpr -fpr_half(fpr x) -{ - /* - * To divide a value by 2, we just have to subtract 1 from its - * exponent, but we have to take care of zero. - */ - uint32_t t; - - x -= (uint64_t)1 << 52; - t = (((uint32_t)(x >> 52) & 0x7FF) + 1) >> 11; - x &= (uint64_t)t - 1; - return x; -} - -static inline fpr -fpr_double(fpr x) -{ - /* - * To double a value, we just increment by one the exponent. We - * don't care about infinites or NaNs; however, 0 is a - * special case. - */ - x += (uint64_t)((((unsigned)(x >> 52) & 0x7FFU) + 0x7FFU) >> 11) << 52; - return x; -} - -#define fpr_mul Zf(fpr_mul) -fpr fpr_mul(fpr x, fpr y); - -static inline fpr -fpr_sqr(fpr x) -{ - return fpr_mul(x, x); -} - -#define fpr_div Zf(fpr_div) -fpr fpr_div(fpr x, fpr y); - -static inline fpr -fpr_inv(fpr x) -{ - return fpr_div(4607182418800017408u, x); -} - -#define fpr_sqrt Zf(fpr_sqrt) -fpr fpr_sqrt(fpr x); - -static inline int -fpr_lt(fpr x, fpr y) -{ - /* - * If x >= 0 or y >= 0, a signed comparison yields the proper - * result: - * - For positive values, the order is preserved. - * - The sign bit is at the same place as in integers, so - * sign is preserved. - * - * If both x and y are negative, then the order is reversed. - * We cannot simply invert the comparison result in that case - * because it would not handle the edge case x = y properly. - */ - int cc0, cc1; - - cc0 = *(int64_t *)&x < *(int64_t *)&y; - cc1 = *(int64_t *)&x > *(int64_t *)&y; - return cc0 ^ ((cc0 ^ cc1) & (int)((x & y) >> 63)); -} - -/* - * Compute exp(x) for x such that |x| <= ln 2. We want a precision of 50 - * bits or so. - */ -#define fpr_expm_p63 Zf(fpr_expm_p63) -uint64_t fpr_expm_p63(fpr x, fpr ccs); - -#define fpr_gm_tab Zf(fpr_gm_tab) -extern const fpr fpr_gm_tab[]; - -#define fpr_p2_tab Zf(fpr_p2_tab) -extern const fpr fpr_p2_tab[]; - -/* ====================================================================== */ - -#elif FALCON_FPNATIVE // yyyFPEMU+0 yyyFPNATIVE+1 - -/* ====================================================================== */ - -#include - -/* - * We wrap the native 'double' type into a structure so that the C compiler - * complains if we inadvertently use raw arithmetic operators on the 'fpr' - * type instead of using the inline functions below. This should have no - * extra runtime cost, since all the functions below are 'inline'. - */ -typedef struct { double v; } fpr; - -static inline fpr -FPR(double v) -{ - fpr x; - - x.v = v; - return x; -} - -static inline fpr -fpr_of(int64_t i) -{ - return FPR((double)i); -} - -static const fpr fpr_q = { 12289.0 }; -static const fpr fpr_inverse_of_q = { 1.0 / 12289.0 }; -static const fpr fpr_inv_2sqrsigma0 = { .150865048875372721532312163019 }; -static const fpr fpr_inv_sigma[] = { - { 0.0 }, /* unused */ - { 0.0069054793295940891952143765991630516 }, - { 0.0068102267767177975961393730687908629 }, - { 0.0067188101910722710707826117910434131 }, - { 0.0065883354370073665545865037227681924 }, - { 0.0064651781207602900738053897763485516 }, - { 0.0063486788828078995327741182928037856 }, - { 0.0062382586529084374473367528433697537 }, - { 0.0061334065020930261548984001431770281 }, - { 0.0060336696681577241031668062510953022 }, - { 0.0059386453095331159950250124336477482 } -}; -static const fpr fpr_sigma_min[] = { - { 0.0 }, /* unused */ - { 1.1165085072329102588881898380334015 }, - { 1.1321247692325272405718031785357108 }, - { 1.1475285353733668684571123112513188 }, - { 1.1702540788534828939713084716509250 }, - { 1.1925466358390344011122170489094133 }, - { 1.2144300507766139921088487776957699 }, - { 1.2359260567719808790104525941706723 }, - { 1.2570545284063214162779743112075080 }, - { 1.2778336969128335860256340575729042 }, - { 1.2982803343442918539708792538826807 } -}; -static const fpr fpr_log2 = { 0.69314718055994530941723212146 }; -static const fpr fpr_inv_log2 = { 1.4426950408889634073599246810 }; -static const fpr fpr_bnorm_max = { 16822.4121 }; -static const fpr fpr_zero = { 0.0 }; -static const fpr fpr_one = { 1.0 }; -static const fpr fpr_two = { 2.0 }; -static const fpr fpr_onehalf = { 0.5 }; -static const fpr fpr_invsqrt2 = { 0.707106781186547524400844362105 }; -static const fpr fpr_invsqrt8 = { 0.353553390593273762200422181052 }; -static const fpr fpr_ptwo31 = { 2147483648.0 }; -static const fpr fpr_ptwo31m1 = { 2147483647.0 }; -static const fpr fpr_mtwo31m1 = { -2147483647.0 }; -static const fpr fpr_ptwo63m1 = { 9223372036854775807.0 }; -static const fpr fpr_mtwo63m1 = { -9223372036854775807.0 }; -static const fpr fpr_ptwo63 = { 9223372036854775808.0 }; - -static inline int64_t -fpr_rint(fpr x) -{ - /* - * We do not want to use llrint() since it might be not - * constant-time. - * - * Suppose that x >= 0. If x >= 2^52, then it is already an - * integer. Otherwise, if x < 2^52, then computing x+2^52 will - * yield a value that will be rounded to the nearest integer - * with exactly the right rules (round-to-nearest-even). - * - * In order to have constant-time processing, we must do the - * computation for both x >= 0 and x < 0 cases, and use a - * cast to an integer to access the sign and select the proper - * value. Such casts also allow us to find out if |x| < 2^52. - */ - int64_t sx, tx, rp, rn, m; - uint32_t ub; - - sx = (int64_t)(x.v - 1.0); - tx = (int64_t)x.v; - rp = (int64_t)(x.v + 4503599627370496.0) - 4503599627370496; - rn = (int64_t)(x.v - 4503599627370496.0) + 4503599627370496; - - /* - * If tx >= 2^52 or tx < -2^52, then result is tx. - * Otherwise, if sx >= 0, then result is rp. - * Otherwise, result is rn. We use the fact that when x is - * close to 0 (|x| <= 0.25) then both rp and rn are correct; - * and if x is not close to 0, then trunc(x-1.0) yields the - * appropriate sign. - */ - - /* - * Clamp rp to zero if tx < 0. - * Clamp rn to zero if tx >= 0. - */ - m = sx >> 63; - rn &= m; - rp &= ~m; - - /* - * Get the 12 upper bits of tx; if they are not all zeros or - * all ones, then tx >= 2^52 or tx < -2^52, and we clamp both - * rp and rn to zero. Otherwise, we clamp tx to zero. - */ - ub = (uint32_t)((uint64_t)tx >> 52); - m = -(int64_t)((((ub + 1) & 0xFFF) - 2) >> 31); - rp &= m; - rn &= m; - tx &= ~m; - - /* - * Only one of tx, rn or rp (at most) can be non-zero at this - * point. - */ - return tx | rn | rp; -} - -static inline int64_t -fpr_floor(fpr x) -{ - int64_t r; - - /* - * The cast performs a trunc() (rounding toward 0) and thus is - * wrong by 1 for most negative values. The correction below is - * constant-time as long as the compiler turns the - * floating-point conversion result into a 0/1 integer without a - * conditional branch or another non-constant-time construction. - * This should hold on all modern architectures with an FPU (and - * if it is false on a given arch, then chances are that the FPU - * itself is not constant-time, making the point moot). - */ - r = (int64_t)x.v; - return r - (x.v < (double)r); -} - -static inline int64_t -fpr_trunc(fpr x) -{ - return (int64_t)x.v; -} - -static inline fpr -fpr_add(fpr x, fpr y) -{ - return FPR(x.v + y.v); -} - -static inline fpr -fpr_sub(fpr x, fpr y) -{ - return FPR(x.v - y.v); -} - -static inline fpr -fpr_neg(fpr x) -{ - return FPR(-x.v); -} - -static inline fpr -fpr_half(fpr x) -{ - return FPR(x.v * 0.5); -} - -static inline fpr -fpr_double(fpr x) -{ - return FPR(x.v + x.v); -} - -static inline fpr -fpr_mul(fpr x, fpr y) -{ - return FPR(x.v * y.v); -} - -static inline fpr -fpr_sqr(fpr x) -{ - return FPR(x.v * x.v); -} - -static inline fpr -fpr_inv(fpr x) -{ - return FPR(1.0 / x.v); -} - -static inline fpr -fpr_div(fpr x, fpr y) -{ - return FPR(x.v / y.v); -} - -#if FALCON_AVX2 // yyyAVX2+1 -TARGET_AVX2 -static inline void -fpr_sqrt_avx2(double *t) -{ - __m128d x; - - x = _mm_load1_pd(t); - x = _mm_sqrt_pd(x); - _mm_storel_pd(t, x); -} -#endif // yyyAVX2- - -static inline fpr -fpr_sqrt(fpr x) -{ - /* - * We prefer not to have a dependency on libm when it can be - * avoided. On x86, calling the sqrt() libm function inlines - * the relevant opcode (fsqrt or sqrtsd, depending on whether - * the 387 FPU or SSE2 is used for floating-point operations) - * but then makes an optional call to the library function - * for proper error handling, in case the operand is negative. - * - * To avoid this dependency, we use intrinsics or inline assembly - * on recognized platforms: - * - * - If AVX2 is explicitly enabled, then we use SSE2 intrinsics. - * - * - On GCC/Clang with SSE maths, we use SSE2 intrinsics. - * - * - On GCC/Clang on i386, or MSVC on i386, we use inline assembly - * to call the 387 FPU fsqrt opcode. - * - * - On GCC/Clang/XLC on PowerPC, we use inline assembly to call - * the fsqrt opcode (Clang needs a special hack). - * - * - On GCC/Clang on ARM with hardware floating-point, we use - * inline assembly to call the vqsrt.f64 opcode. Due to a - * complex ecosystem of compilers and assembly syntaxes, we - * have to call it "fsqrt" or "fsqrtd", depending on case. - * - * If the platform is not recognized, a call to the system - * library function sqrt() is performed. On some compilers, this - * may actually inline the relevant opcode, and call the library - * function only when the input is invalid (e.g. negative); - * Falcon never actually calls sqrt() on a negative value, but - * the dependency to libm will still be there. - */ - -#if FALCON_AVX2 // yyyAVX2+1 - fpr_sqrt_avx2(&x.v); - return x; -#else // yyyAVX2+0 -#if defined __GNUC__ && defined __SSE2_MATH__ - return FPR(_mm_cvtsd_f64(_mm_sqrt_pd(_mm_set1_pd(x.v)))); -#elif defined __GNUC__ && defined __i386__ - __asm__ __volatile__ ( - "fldl %0\n\t" - "fsqrt\n\t" - "fstpl %0\n\t" - : "+m" (x.v) : : ); - return x; -#elif defined _M_IX86 - __asm { - fld x.v - fsqrt - fstp x.v - } - return x; -#elif defined __PPC__ && defined __GNUC__ - fpr y; - -#if defined __clang__ - /* - * Normally we should use a 'd' constraint (register that contains - * a 'double' value) but Clang 3.8.1 chokes on it. Instead we use - * an 'f' constraint, counting on the fact that 'float' values - * are managed in double-precision registers anyway, and the - * compiler will not add extra rounding steps. - */ - __asm__ ( "fsqrt %0, %1" : "=f" (y.v) : "f" (x.v) : ); -#else - __asm__ ( "fsqrt %0, %1" : "=d" (y.v) : "d" (x.v) : ); -#endif - return y; -#elif (defined __ARM_FP && ((__ARM_FP & 0x08) == 0x08)) \ - || (!defined __ARM_FP && defined __ARM_VFPV2__) - /* - * On ARM, assembly syntaxes are a bit of a mess, depending on - * whether GCC or Clang is used, and the binutils version, and - * whether this is 32-bit or 64-bit mode. The code below appears - * to work on: - * 32-bit GCC-4.9.2 Clang-3.5 Binutils-2.25 - * 64-bit GCC-6.3.0 Clang-3.9 Binutils-2.28 - */ -#if defined __aarch64__ && __aarch64__ - __asm__ ( "fsqrt %d0, %d0" : "+w" (x.v) : : ); -#else - __asm__ ( "fsqrtd %P0, %P0" : "+w" (x.v) : : ); -#endif - return x; -#else - return FPR(sqrt(x.v)); -#endif -#endif // yyyAVX2- -} - -static inline int -fpr_lt(fpr x, fpr y) -{ - return x.v < y.v; -} - -TARGET_AVX2 -static inline uint64_t -fpr_expm_p63(fpr x, fpr ccs) -{ - /* - * Polynomial approximation of exp(-x) is taken from FACCT: - * https://eprint.iacr.org/2018/1234 - * Specifically, values are extracted from the implementation - * referenced from the FACCT article, and available at: - * https://github.com/raykzhao/gaussian - * Tests over more than 24 billions of random inputs in the - * 0..log(2) range have never shown a deviation larger than - * 2^(-50) from the true mathematical value. - */ - -#if FALCON_AVX2 // yyyAVX2+1 - - /* - * AVX2 implementation uses more operations than Horner's method, - * but with a lower expression tree depth. This helps because - * additions and multiplications have a latency of 4 cycles on - * a Skylake, but the CPU can issue two of them per cycle. - */ - - static const union { - double d[12]; - __m256d v[3]; - } c = { - { - 0.999999999999994892974086724280, - 0.500000000000019206858326015208, - 0.166666666666984014666397229121, - 0.041666666666110491190622155955, - 0.008333333327800835146903501993, - 0.001388888894063186997887560103, - 0.000198412739277311890541063977, - 0.000024801566833585381209939524, - 0.000002755586350219122514855659, - 0.000000275607356160477811864927, - 0.000000025299506379442070029551, - 0.000000002073772366009083061987 - } - }; - - double d1, d2, d4, d8, y; - __m256d d14, d58, d9c; - - d1 = -x.v; - d2 = d1 * d1; - d4 = d2 * d2; - d8 = d4 * d4; - d14 = _mm256_set_pd(d4, d2 * d1, d2, d1); - d58 = _mm256_mul_pd(d14, _mm256_set1_pd(d4)); - d9c = _mm256_mul_pd(d14, _mm256_set1_pd(d8)); - d14 = _mm256_mul_pd(d14, _mm256_loadu_pd(&c.d[0])); - d58 = FMADD(d58, _mm256_loadu_pd(&c.d[4]), d14); - d9c = FMADD(d9c, _mm256_loadu_pd(&c.d[8]), d58); - d9c = _mm256_hadd_pd(d9c, d9c); - y = 1.0 + _mm_cvtsd_f64(_mm256_castpd256_pd128(d9c)) // _mm256_cvtsd_f64(d9c) - + _mm_cvtsd_f64(_mm256_extractf128_pd(d9c, 1)); - y *= ccs.v; - - /* - * Final conversion goes through int64_t first, because that's what - * the underlying opcode (vcvttsd2si) will do, and we know that the - * result will fit, since x >= 0 and ccs < 1. If we did the - * conversion directly to uint64_t, then the compiler would add some - * extra code to cover the case of a source value of 2^63 or more, - * and though the alternate path would never be exercised, the - * extra comparison would cost us some cycles. - */ - return (uint64_t)(int64_t)(y * fpr_ptwo63.v); - -#else // yyyAVX2+0 - - /* - * Normal implementation uses Horner's method, which minimizes - * the number of operations. - */ - - double d, y; - - d = x.v; - y = 0.000000002073772366009083061987; - y = 0.000000025299506379442070029551 - y * d; - y = 0.000000275607356160477811864927 - y * d; - y = 0.000002755586350219122514855659 - y * d; - y = 0.000024801566833585381209939524 - y * d; - y = 0.000198412739277311890541063977 - y * d; - y = 0.001388888894063186997887560103 - y * d; - y = 0.008333333327800835146903501993 - y * d; - y = 0.041666666666110491190622155955 - y * d; - y = 0.166666666666984014666397229121 - y * d; - y = 0.500000000000019206858326015208 - y * d; - y = 0.999999999999994892974086724280 - y * d; - y = 1.000000000000000000000000000000 - y * d; - y *= ccs.v; - return (uint64_t)(y * fpr_ptwo63.v); - -#endif // yyyAVX2- -} - -#define fpr_gm_tab Zf(fpr_gm_tab) -extern const fpr fpr_gm_tab[]; - -#define fpr_p2_tab Zf(fpr_p2_tab) -extern const fpr fpr_p2_tab[]; - -/* ====================================================================== */ - -#else // yyyFPEMU+0 yyyFPNATIVE+0 - -#error No FP implementation selected - -#endif // yyyFPEMU- yyyFPNATIVE- diff --git a/falcon/inner.h b/falcon/inner.h deleted file mode 100644 index 88a8448..0000000 --- a/falcon/inner.h +++ /dev/null @@ -1,1166 +0,0 @@ -#ifndef FALCON_INNER_H__ -#define FALCON_INNER_H__ - -/* - * Internal functions for Falcon. This is not the API intended to be - * used by applications; instead, this internal API provides all the - * primitives on which wrappers build to provide external APIs. - * - * ==========================(LICENSE BEGIN)============================ - * - * Copyright (c) 2017-2019 Falcon Project - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * ===========================(LICENSE END)============================= - * - * @author Thomas Pornin - */ - -/* - * IMPORTANT API RULES - * ------------------- - * - * This API has some non-trivial usage rules: - * - * - * - All public functions (i.e. the non-static ones) must be referenced - * with the Zf() macro (e.g. Zf(verify_raw) for the verify_raw() - * function). That macro adds a prefix to the name, which is - * configurable with the FALCON_PREFIX macro. This allows compiling - * the code into a specific "namespace" and potentially including - * several versions of this code into a single application (e.g. to - * have an AVX2 and a non-AVX2 variants and select the one to use at - * runtime based on availability of AVX2 opcodes). - * - * - Functions that need temporary buffers expects them as a final - * tmp[] array of type uint8_t*, with a size which is documented for - * each function. However, most have some alignment requirements, - * because they will use the array to store 16-bit, 32-bit or 64-bit - * values (e.g. uint64_t or double). The caller must ensure proper - * alignment. What happens on unaligned access depends on the - * underlying architecture, ranging from a slight time penalty - * to immediate termination of the process. - * - * - Some functions rely on specific rounding rules and precision for - * floating-point numbers. On some systems (in particular 32-bit x86 - * with the 387 FPU), this requires setting an hardware control - * word. The caller MUST use set_fpu_cw() to ensure proper precision: - * - * oldcw = set_fpu_cw(2); - * Zf(sign_dyn)(...); - * set_fpu_cw(oldcw); - * - * On systems where the native floating-point precision is already - * proper, or integer-based emulation is used, the set_fpu_cw() - * function does nothing, so it can be called systematically. - */ - -// yyyPQCLEAN+0 yyyNIST+0 yyySUPERCOP+0 -#include "config.h" -// yyyPQCLEAN- yyyNIST- yyySUPERCOP- -// yyySUPERCOP+1 -// yyyCONF* -// yyySUPERCOP- - -#include -#include -#include - -#if defined FALCON_AVX2 && FALCON_AVX2 // yyyAVX2+1 -/* - * This implementation uses AVX2 and optionally FMA intrinsics. - */ -#include -#ifndef FALCON_LE -#define FALCON_LE 1 -#endif -#ifndef FALCON_UNALIGNED -#define FALCON_UNALIGNED 1 -#endif -#if defined __GNUC__ -#if defined FALCON_FMA && FALCON_FMA -#define TARGET_AVX2 __attribute__((target("avx2,fma"))) -#else -#define TARGET_AVX2 __attribute__((target("avx2"))) -#endif -#elif defined _MSC_VER && _MSC_VER -#pragma warning( disable : 4752 ) -#endif -#if defined FALCON_FMA && FALCON_FMA -#define FMADD(a, b, c) _mm256_fmadd_pd(a, b, c) -#define FMSUB(a, b, c) _mm256_fmsub_pd(a, b, c) -#else -#define FMADD(a, b, c) _mm256_add_pd(_mm256_mul_pd(a, b), c) -#define FMSUB(a, b, c) _mm256_sub_pd(_mm256_mul_pd(a, b), c) -#endif -#endif // yyyAVX2- - -// yyyNIST+0 yyyPQCLEAN+0 -/* - * On MSVC, disable warning about applying unary minus on an unsigned - * type: this is perfectly defined standard behaviour and we do it - * quite often. - */ -#if defined _MSC_VER && _MSC_VER -#pragma warning( disable : 4146 ) -#endif - -// yyySUPERCOP+0 -/* - * Enable ARM assembly on any ARMv7m platform (if it was not done before). - */ -#ifndef FALCON_ASM_CORTEXM4 -#if (defined __ARM_ARCH_7EM__ && __ARM_ARCH_7EM__) \ - && (defined __ARM_FEATURE_DSP && __ARM_FEATURE_DSP) -#define FALCON_ASM_CORTEXM4 1 -#else -#define FALCON_ASM_CORTEXM4 0 -#endif -#endif -// yyySUPERCOP- - -#if defined __i386__ || defined _M_IX86 \ - || defined __x86_64__ || defined _M_X64 || \ - (defined _ARCH_PWR8 && \ - (defined __LITTLE_ENDIAN || defined __LITTLE_ENDIAN__)) - -#ifndef FALCON_LE -#define FALCON_LE 1 -#endif -#ifndef FALCON_UNALIGNED -#define FALCON_UNALIGNED 1 -#endif - -#elif defined FALCON_ASM_CORTEXM4 && FALCON_ASM_CORTEXM4 - -#ifndef FALCON_LE -#define FALCON_LE 1 -#endif -#ifndef FALCON_UNALIGNED -#define FALCON_UNALIGNED 0 -#endif - -#elif (defined __LITTLE_ENDIAN__ && __LITTLE_ENDIAN__) \ - || (defined __BYTE_ORDER__ && defined __ORDER_LITTLE_ENDIAN__ \ - && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) - -#ifndef FALCON_LE -#define FALCON_LE 1 -#endif -#ifndef FALCON_UNALIGNED -#define FALCON_UNALIGNED 0 -#endif - -#else - -#ifndef FALCON_LE -#define FALCON_LE 0 -#endif -#ifndef FALCON_UNALIGNED -#define FALCON_UNALIGNED 0 -#endif - -#endif - -/* - * We ensure that both FALCON_FPEMU and FALCON_FPNATIVE are defined, - * with compatible values (exactly one of them must be non-zero). - * If none is defined, then default FP implementation is 'native' - * except on ARM Cortex M4. - */ -#if !defined FALCON_FPEMU && !defined FALCON_FPNATIVE - -#if (defined __ARM_FP && ((__ARM_FP & 0x08) == 0x08)) \ - || (!defined __ARM_FP && defined __ARM_VFPV2__) -#define FALCON_FPEMU 0 -#define FALCON_FPNATIVE 1 -#elif defined FALCON_ASM_CORTEXM4 && FALCON_ASM_CORTEXM4 -#define FALCON_FPEMU 1 -#define FALCON_FPNATIVE 0 -#else -#define FALCON_FPEMU 0 -#define FALCON_FPNATIVE 1 -#endif - -#elif defined FALCON_FPEMU && !defined FALCON_FPNATIVE - -#if FALCON_FPEMU -#define FALCON_FPNATIVE 0 -#else -#define FALCON_FPNATIVE 1 -#endif - -#elif defined FALCON_FPNATIVE && !defined FALCON_FPEMU - -#if FALCON_FPNATIVE -#define FALCON_FPEMU 0 -#else -#define FALCON_FPEMU 1 -#endif - -#endif - -#if (FALCON_FPEMU && FALCON_FPNATIVE) || (!FALCON_FPEMU && !FALCON_FPNATIVE) -#error Exactly one of FALCON_FPEMU and FALCON_FPNATIVE must be selected -#endif - -// yyySUPERCOP+0 -/* - * For seed generation from the operating system: - * - On Linux and glibc-2.25+, FreeBSD 12+ and OpenBSD, use getentropy(). - * - On Unix-like systems, use /dev/urandom (including as a fallback - * for failed getentropy() calls). - * - On Windows, use CryptGenRandom(). - */ - -#ifndef FALCON_RAND_GETENTROPY -#if (defined __linux__ && defined __GLIBC__ \ - && (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 25))) \ - || (defined __FreeBSD__ && __FreeBSD__ >= 12) \ - || defined __OpenBSD__ -#define FALCON_RAND_GETENTROPY 1 -#else -#define FALCON_RAND_GETENTROPY 0 -#endif -#endif - -#ifndef FALCON_RAND_URANDOM -#if defined _AIX \ - || defined __ANDROID__ \ - || defined __FreeBSD__ \ - || defined __NetBSD__ \ - || defined __OpenBSD__ \ - || defined __DragonFly__ \ - || defined __linux__ \ - || (defined __sun && (defined __SVR4 || defined __svr4__)) \ - || (defined __APPLE__ && defined __MACH__) -#define FALCON_RAND_URANDOM 1 -#else -#define FALCON_RAND_URANDOM 0 -#endif -#endif - -#ifndef FALCON_RAND_WIN32 -#if defined _WIN32 || defined _WIN64 -#define FALCON_RAND_WIN32 1 -#else -#define FALCON_RAND_WIN32 0 -#endif -#endif -// yyySUPERCOP- - -/* - * For still undefined compile-time macros, define them to 0 to avoid - * warnings with -Wundef. - */ -#ifndef FALCON_AVX2 -#define FALCON_AVX2 0 -#endif -#ifndef FALCON_FMA -#define FALCON_FMA 0 -#endif -#ifndef FALCON_KG_CHACHA20 -#define FALCON_KG_CHACHA20 0 -#endif -// yyyNIST- yyyPQCLEAN- - -// yyyPQCLEAN+0 yyySUPERCOP+0 -/* - * "Naming" macro used to apply a consistent prefix over all global - * symbols. - */ -#ifndef FALCON_PREFIX -#define FALCON_PREFIX falcon_inner -#endif -#define Zf(name) Zf_(FALCON_PREFIX, name) -#define Zf_(prefix, name) Zf__(prefix, name) -#define Zf__(prefix, name) prefix ## _ ## name -// yyyPQCLEAN- yyySUPERCOP- - -// yyyAVX2+1 -/* - * We use the TARGET_AVX2 macro to tag some functions which, in some - * configurations, may use AVX2 and FMA intrinsics; this depends on - * the compiler. In all other cases, we just define it to emptiness - * (i.e. it will have no effect). - */ -#ifndef TARGET_AVX2 -#define TARGET_AVX2 -#endif -// yyyAVX2- - -/* - * Some computations with floating-point elements, in particular - * rounding to the nearest integer, rely on operations using _exactly_ - * the precision of IEEE-754 binary64 type (i.e. 52 bits). On 32-bit - * x86, the 387 FPU may be used (depending on the target OS) and, in - * that case, may use more precision bits (i.e. 64 bits, for an 80-bit - * total type length); to prevent miscomputations, we define an explicit - * function that modifies the precision in the FPU control word. - * - * set_fpu_cw() sets the precision to the provided value, and returns - * the previously set precision; callers are supposed to restore the - * previous precision on exit. The correct (52-bit) precision is - * configured with the value "2". On unsupported compilers, or on - * targets other than 32-bit x86, or when the native 'double' type is - * not used, the set_fpu_cw() function does nothing at all. - */ -#if FALCON_FPNATIVE // yyyFPNATIVE+1 -#if defined __GNUC__ && defined __i386__ -static inline unsigned -set_fpu_cw(unsigned x) -{ - unsigned short t; - unsigned old; - - __asm__ __volatile__ ("fstcw %0" : "=m" (t) : : ); - old = (t & 0x0300u) >> 8; - t = (unsigned short)((t & ~0x0300u) | (x << 8)); - __asm__ __volatile__ ("fldcw %0" : : "m" (t) : ); - return old; -} -#elif defined _M_IX86 -static inline unsigned -set_fpu_cw(unsigned x) -{ - unsigned short t; - unsigned old; - - __asm { fstcw t } - old = (t & 0x0300u) >> 8; - t = (unsigned short)((t & ~0x0300u) | (x << 8)); - __asm { fldcw t } - return old; -} -#else -static inline unsigned -set_fpu_cw(unsigned x) -{ - return x; -} -#endif -#else // yyyFPNATIVE+0 -static inline unsigned -set_fpu_cw(unsigned x) -{ - return x; -} -#endif // yyyFPNATIVE- - -#if FALCON_FPNATIVE && !FALCON_AVX2 // yyyFPNATIVE+1 yyyAVX2+0 -/* - * If using the native 'double' type but not AVX2 code, on an x86 - * machine with SSE2 activated for maths, then we will use the - * SSE2 intrinsics. - */ -#if defined __GNUC__ && defined __SSE2_MATH__ -#include -#endif -#endif // yyyFPNATIVE- yyyAVX2- - -#if FALCON_FPNATIVE // yyyFPNATIVE+1 -/* - * For optimal reproducibility of values, we need to disable contraction - * of floating-point expressions; otherwise, on some architectures (e.g. - * PowerPC), the compiler may generate fused-multiply-add opcodes that - * may round differently than two successive separate opcodes. C99 defines - * a standard pragma for that, but GCC-6.2.2 appears to ignore it, - * hence the GCC-specific pragma (that Clang does not support). - */ -#if defined __clang__ -#pragma STDC FP_CONTRACT OFF -#elif defined __GNUC__ -#pragma GCC optimize ("fp-contract=off") -#endif -#endif // yyyFPNATIVE- - -// yyyPQCLEAN+0 -/* - * MSVC 2015 does not know the C99 keyword 'restrict'. - */ -#if defined _MSC_VER && _MSC_VER -#ifndef restrict -#define restrict __restrict -#endif -#endif -// yyyPQCLEAN- - -/* ==================================================================== */ -/* - * SHAKE256 implementation (shake.c). - * - * API is defined to be easily replaced with the fips202.h API defined - * as part of PQClean. - */ - -// yyyPQCLEAN+0 -typedef struct { - union { - uint64_t A[25]; - uint8_t dbuf[200]; - } st; - uint64_t dptr; -} inner_shake256_context; - -#define inner_shake256_init Zf(i_shake256_init) -#define inner_shake256_inject Zf(i_shake256_inject) -#define inner_shake256_flip Zf(i_shake256_flip) -#define inner_shake256_extract Zf(i_shake256_extract) - -void Zf(i_shake256_init)( - inner_shake256_context *sc); -void Zf(i_shake256_inject)( - inner_shake256_context *sc, const uint8_t *in, size_t len); -void Zf(i_shake256_flip)( - inner_shake256_context *sc); -void Zf(i_shake256_extract)( - inner_shake256_context *sc, uint8_t *out, size_t len); - -/* -// yyyPQCLEAN+1 - -#include "fips202.h" - -#define inner_shake256_context shake256incctx -#define inner_shake256_init(sc) shake256_inc_init(sc) -#define inner_shake256_inject(sc, in, len) shake256_inc_absorb(sc, in, len) -#define inner_shake256_flip(sc) shake256_inc_finalize(sc) -#define inner_shake256_extract(sc, out, len) shake256_inc_squeeze(out, len, sc) - -// yyyPQCLEAN+0 - */ -// yyyPQCLEAN- - -/* ==================================================================== */ -/* - * Encoding/decoding functions (codec.c). - * - * Encoding functions take as parameters an output buffer (out) with - * a given maximum length (max_out_len); returned value is the actual - * number of bytes which have been written. If the output buffer is - * not large enough, then 0 is returned (some bytes may have been - * written to the buffer). If 'out' is NULL, then 'max_out_len' is - * ignored; instead, the function computes and returns the actual - * required output length (in bytes). - * - * Decoding functions take as parameters an input buffer (in) with - * its maximum length (max_in_len); returned value is the actual number - * of bytes that have been read from the buffer. If the provided length - * is too short, then 0 is returned. - * - * Values to encode or decode are vectors of integers, with N = 2^logn - * elements. - * - * Three encoding formats are defined: - * - * - modq: sequence of values modulo 12289, each encoded over exactly - * 14 bits. The encoder and decoder verify that integers are within - * the valid range (0..12288). Values are arrays of uint16. - * - * - trim: sequence of signed integers, a specified number of bits - * each. The number of bits is provided as parameter and includes - * the sign bit. Each integer x must be such that |x| < 2^(bits-1) - * (which means that the -2^(bits-1) value is forbidden); encode and - * decode functions check that property. Values are arrays of - * int16_t or int8_t, corresponding to names 'trim_i16' and - * 'trim_i8', respectively. - * - * - comp: variable-length encoding for signed integers; each integer - * uses a minimum of 9 bits, possibly more. This is normally used - * only for signatures. - * - */ - -size_t Zf(modq_encode)(void *out, size_t max_out_len, - const uint16_t *x, unsigned logn); -size_t Zf(trim_i16_encode)(void *out, size_t max_out_len, - const int16_t *x, unsigned logn, unsigned bits); -size_t Zf(trim_i8_encode)(void *out, size_t max_out_len, - const int8_t *x, unsigned logn, unsigned bits); -size_t Zf(comp_encode)(void *out, size_t max_out_len, - const int16_t *x, unsigned logn); - -size_t Zf(modq_decode)(uint16_t *x, unsigned logn, - const void *in, size_t max_in_len); -size_t Zf(trim_i16_decode)(int16_t *x, unsigned logn, unsigned bits, - const void *in, size_t max_in_len); -size_t Zf(trim_i8_decode)(int8_t *x, unsigned logn, unsigned bits, - const void *in, size_t max_in_len); -size_t Zf(comp_decode)(int16_t *x, unsigned logn, - const void *in, size_t max_in_len); - -/* - * Number of bits for key elements, indexed by logn (1 to 10). This - * is at most 8 bits for all degrees, but some degrees may have shorter - * elements. - */ -extern const uint8_t Zf(max_fg_bits)[]; -extern const uint8_t Zf(max_FG_bits)[]; - -/* - * Maximum size, in bits, of elements in a signature, indexed by logn - * (1 to 10). The size includes the sign bit. - */ -extern const uint8_t Zf(max_sig_bits)[]; - -/* ==================================================================== */ -/* - * Support functions used for both signature generation and signature - * verification (common.c). - */ - -/* - * From a SHAKE256 context (must be already flipped), produce a new - * point. This is the non-constant-time version, which may leak enough - * information to serve as a stop condition on a brute force attack on - * the hashed message (provided that the nonce value is known). - */ -void Zf(hash_to_point_vartime)(inner_shake256_context *sc, - uint16_t *x, unsigned logn); - -/* - * From a SHAKE256 context (must be already flipped), produce a new - * point. The temporary buffer (tmp) must have room for 2*2^logn bytes. - * This function is constant-time but is typically more expensive than - * Zf(hash_to_point_vartime)(). - * - * tmp[] must have 16-bit alignment. - */ -void Zf(hash_to_point_ct)(inner_shake256_context *sc, - uint16_t *x, unsigned logn, uint8_t *tmp); - -/* - * Tell whether a given vector (2N coordinates, in two halves) is - * acceptable as a signature. This compares the appropriate norm of the - * vector with the acceptance bound. Returned value is 1 on success - * (vector is short enough to be acceptable), 0 otherwise. - */ -int Zf(is_short)(const int16_t *s1, const int16_t *s2, unsigned logn); - -/* - * Tell whether a given vector (2N coordinates, in two halves) is - * acceptable as a signature. Instead of the first half s1, this - * function receives the "saturated squared norm" of s1, i.e. the - * sum of the squares of the coordinates of s1 (saturated at 2^32-1 - * if the sum exceeds 2^31-1). - * - * Returned value is 1 on success (vector is short enough to be - * acceptable), 0 otherwise. - */ -int Zf(is_short_half)(uint32_t sqn, const int16_t *s2, unsigned logn); - -/* ==================================================================== */ -/* - * Signature verification functions (vrfy.c). - */ - -/* - * Convert a public key to NTT + Montgomery format. Conversion is done - * in place. - */ -void Zf(to_ntt_monty)(uint16_t *h, unsigned logn); - -/* - * Internal signature verification code: - * c0[] contains the hashed nonce+message - * s2[] is the decoded signature - * h[] contains the public key, in NTT + Montgomery format - * logn is the degree log - * tmp[] temporary, must have at least 2*2^logn bytes - * Returned value is 1 on success, 0 on error. - * - * tmp[] must have 16-bit alignment. - */ -int Zf(verify_raw)(const uint16_t *c0, const int16_t *s2, - const uint16_t *h, unsigned logn, uint8_t *tmp); - -/* - * Compute the public key h[], given the private key elements f[] and - * g[]. This computes h = g/f mod phi mod q, where phi is the polynomial - * modulus. This function returns 1 on success, 0 on error (an error is - * reported if f is not invertible mod phi mod q). - * - * The tmp[] array must have room for at least 2*2^logn elements. - * tmp[] must have 16-bit alignment. - */ -int Zf(compute_public)(uint16_t *h, - const int8_t *f, const int8_t *g, unsigned logn, uint8_t *tmp); - -/* - * Recompute the fourth private key element. Private key consists in - * four polynomials with small coefficients f, g, F and G, which are - * such that fG - gF = q mod phi; furthermore, f is invertible modulo - * phi and modulo q. This function recomputes G from f, g and F. - * - * The tmp[] array must have room for at least 4*2^logn bytes. - * - * Returned value is 1 in success, 0 on error (f not invertible). - * tmp[] must have 16-bit alignment. - */ -int Zf(complete_private)(int8_t *G, - const int8_t *f, const int8_t *g, const int8_t *F, - unsigned logn, uint8_t *tmp); - -/* - * Test whether a given polynomial is invertible modulo phi and q. - * Polynomial coefficients are small integers. - * - * tmp[] must have 16-bit alignment. - */ -int Zf(is_invertible)( - const int16_t *s2, unsigned logn, uint8_t *tmp); - -/* - * Count the number of elements of value zero in the NTT representation - * of the given polynomial: this is the number of primitive 2n-th roots - * of unity (modulo q = 12289) that are roots of the provided polynomial - * (taken modulo q). - * - * tmp[] must have 16-bit alignment. - */ -int Zf(count_nttzero)(const int16_t *sig, unsigned logn, uint8_t *tmp); - -/* - * Internal signature verification with public key recovery: - * h[] receives the public key (NOT in NTT/Montgomery format) - * c0[] contains the hashed nonce+message - * s1[] is the first signature half - * s2[] is the second signature half - * logn is the degree log - * tmp[] temporary, must have at least 2*2^logn bytes - * Returned value is 1 on success, 0 on error. Success is returned if - * the signature is a short enough vector; in that case, the public - * key has been written to h[]. However, the caller must still - * verify that h[] is the correct value (e.g. with regards to a known - * hash of the public key). - * - * h[] may not overlap with any of the other arrays. - * - * tmp[] must have 16-bit alignment. - */ -int Zf(verify_recover)(uint16_t *h, - const uint16_t *c0, const int16_t *s1, const int16_t *s2, - unsigned logn, uint8_t *tmp); - -/* ==================================================================== */ -/* - * Implementation of floating-point real numbers (fpr.h, fpr.c). - */ - -/* - * Real numbers are implemented by an extra header file, included below. - * This is meant to support pluggable implementations. The default - * implementation relies on the C type 'double'. - * - * The included file must define the following types, functions and - * constants: - * - * fpr - * type for a real number - * - * fpr fpr_of(int64_t i) - * cast an integer into a real number; source must be in the - * -(2^63-1)..+(2^63-1) range - * - * fpr fpr_scaled(int64_t i, int sc) - * compute i*2^sc as a real number; source 'i' must be in the - * -(2^63-1)..+(2^63-1) range - * - * fpr fpr_ldexp(fpr x, int e) - * compute x*2^e - * - * int64_t fpr_rint(fpr x) - * round x to the nearest integer; x must be in the -(2^63-1) - * to +(2^63-1) range - * - * int64_t fpr_trunc(fpr x) - * round to an integer; this rounds towards zero; value must - * be in the -(2^63-1) to +(2^63-1) range - * - * fpr fpr_add(fpr x, fpr y) - * compute x + y - * - * fpr fpr_sub(fpr x, fpr y) - * compute x - y - * - * fpr fpr_neg(fpr x) - * compute -x - * - * fpr fpr_half(fpr x) - * compute x/2 - * - * fpr fpr_double(fpr x) - * compute x*2 - * - * fpr fpr_mul(fpr x, fpr y) - * compute x * y - * - * fpr fpr_sqr(fpr x) - * compute x * x - * - * fpr fpr_inv(fpr x) - * compute 1/x - * - * fpr fpr_div(fpr x, fpr y) - * compute x/y - * - * fpr fpr_sqrt(fpr x) - * compute the square root of x - * - * int fpr_lt(fpr x, fpr y) - * return 1 if x < y, 0 otherwise - * - * uint64_t fpr_expm_p63(fpr x) - * return exp(x), assuming that 0 <= x < log(2). Returned value - * is scaled to 63 bits (i.e. it really returns 2^63*exp(-x), - * rounded to the nearest integer). Computation should have a - * precision of at least 45 bits. - * - * const fpr fpr_gm_tab[] - * array of constants for FFT / iFFT - * - * const fpr fpr_p2_tab[] - * precomputed powers of 2 (by index, 0 to 10) - * - * Constants of type 'fpr': - * - * fpr fpr_q 12289 - * fpr fpr_inverse_of_q 1/12289 - * fpr fpr_inv_2sqrsigma0 1/(2*(1.8205^2)) - * fpr fpr_inv_sigma[] 1/sigma (indexed by logn, 1 to 10) - * fpr fpr_sigma_min[] 1/sigma_min (indexed by logn, 1 to 10) - * fpr fpr_log2 log(2) - * fpr fpr_inv_log2 1/log(2) - * fpr fpr_bnorm_max 16822.4121 - * fpr fpr_zero 0 - * fpr fpr_one 1 - * fpr fpr_two 2 - * fpr fpr_onehalf 0.5 - * fpr fpr_ptwo31 2^31 - * fpr fpr_ptwo31m1 2^31-1 - * fpr fpr_mtwo31m1 -(2^31-1) - * fpr fpr_ptwo63m1 2^63-1 - * fpr fpr_mtwo63m1 -(2^63-1) - * fpr fpr_ptwo63 2^63 - */ -#include "fpr.h" - -/* ==================================================================== */ -/* - * RNG (rng.c). - * - * A PRNG based on ChaCha20 is implemented; it is seeded from a SHAKE256 - * context (flipped) and is used for bulk pseudorandom generation. - * A system-dependent seed generator is also provided. - */ - -/* - * Obtain a random seed from the system RNG. - * - * Returned value is 1 on success, 0 on error. - */ -int Zf(get_seed)(void *seed, size_t seed_len); - -/* - * Structure for a PRNG. This includes a large buffer so that values - * get generated in advance. The 'state' is used to keep the current - * PRNG algorithm state (contents depend on the selected algorithm). - * - * The unions with 'dummy_u64' are there to ensure proper alignment for - * 64-bit direct access. - */ -typedef struct { - union { - uint8_t d[512]; /* MUST be 512, exactly */ - uint64_t dummy_u64; - } buf; - size_t ptr; - union { - uint8_t d[256]; - uint64_t dummy_u64; - } state; - int type; -} prng; - -/* - * Instantiate a PRNG. That PRNG will feed over the provided SHAKE256 - * context (in "flipped" state) to obtain its initial state. - */ -void Zf(prng_init)(prng *p, inner_shake256_context *src); - -/* - * Refill the PRNG buffer. This is normally invoked automatically, and - * is declared here only so that prng_get_u64() may be inlined. - */ -void Zf(prng_refill)(prng *p); - -/* - * Get some bytes from a PRNG. - */ -void Zf(prng_get_bytes)(prng *p, void *dst, size_t len); - -/* - * Get a 64-bit random value from a PRNG. - */ -static inline uint64_t -prng_get_u64(prng *p) -{ - size_t u; - - /* - * If there are less than 9 bytes in the buffer, we refill it. - * This means that we may drop the last few bytes, but this allows - * for faster extraction code. Also, it means that we never leave - * an empty buffer. - */ - u = p->ptr; - if (u >= (sizeof p->buf.d) - 9) { - Zf(prng_refill)(p); - u = 0; - } - p->ptr = u + 8; - - /* - * On systems that use little-endian encoding and allow - * unaligned accesses, we can simply read the data where it is. - */ -#if FALCON_LE && FALCON_UNALIGNED // yyyLEU+1 - return *(uint64_t *)(p->buf.d + u); -#else // yyyLEU+0 - return (uint64_t)p->buf.d[u + 0] - | ((uint64_t)p->buf.d[u + 1] << 8) - | ((uint64_t)p->buf.d[u + 2] << 16) - | ((uint64_t)p->buf.d[u + 3] << 24) - | ((uint64_t)p->buf.d[u + 4] << 32) - | ((uint64_t)p->buf.d[u + 5] << 40) - | ((uint64_t)p->buf.d[u + 6] << 48) - | ((uint64_t)p->buf.d[u + 7] << 56); -#endif // yyyLEU- -} - -/* - * Get an 8-bit random value from a PRNG. - */ -static inline unsigned -prng_get_u8(prng *p) -{ - unsigned v; - - v = p->buf.d[p->ptr ++]; - if (p->ptr == sizeof p->buf.d) { - Zf(prng_refill)(p); - } - return v; -} - -/* ==================================================================== */ -/* - * FFT (falcon-fft.c). - * - * A real polynomial is represented as an array of N 'fpr' elements. - * The FFT representation of a real polynomial contains N/2 complex - * elements; each is stored as two real numbers, for the real and - * imaginary parts, respectively. See falcon-fft.c for details on the - * internal representation. - */ - -/* - * Compute FFT in-place: the source array should contain a real - * polynomial (N coefficients); its storage area is reused to store - * the FFT representation of that polynomial (N/2 complex numbers). - * - * 'logn' MUST lie between 1 and 10 (inclusive). - */ -void Zf(FFT)(fpr *f, unsigned logn); - -/* - * Compute the inverse FFT in-place: the source array should contain the - * FFT representation of a real polynomial (N/2 elements); the resulting - * real polynomial (N coefficients of type 'fpr') is written over the - * array. - * - * 'logn' MUST lie between 1 and 10 (inclusive). - */ -void Zf(iFFT)(fpr *f, unsigned logn); - -/* - * Add polynomial b to polynomial a. a and b MUST NOT overlap. This - * function works in both normal and FFT representations. - */ -void Zf(poly_add)(fpr *restrict a, const fpr *restrict b, unsigned logn); - -/* - * Subtract polynomial b from polynomial a. a and b MUST NOT overlap. This - * function works in both normal and FFT representations. - */ -void Zf(poly_sub)(fpr *restrict a, const fpr *restrict b, unsigned logn); - -/* - * Negate polynomial a. This function works in both normal and FFT - * representations. - */ -void Zf(poly_neg)(fpr *a, unsigned logn); - -/* - * Compute adjoint of polynomial a. This function works only in FFT - * representation. - */ -void Zf(poly_adj_fft)(fpr *a, unsigned logn); - -/* - * Multiply polynomial a with polynomial b. a and b MUST NOT overlap. - * This function works only in FFT representation. - */ -void Zf(poly_mul_fft)(fpr *restrict a, const fpr *restrict b, unsigned logn); - -/* - * Multiply polynomial a with the adjoint of polynomial b. a and b MUST NOT - * overlap. This function works only in FFT representation. - */ -void Zf(poly_muladj_fft)(fpr *restrict a, const fpr *restrict b, unsigned logn); - -/* - * Multiply polynomial with its own adjoint. This function works only in FFT - * representation. - */ -void Zf(poly_mulselfadj_fft)(fpr *a, unsigned logn); - -/* - * Multiply polynomial with a real constant. This function works in both - * normal and FFT representations. - */ -void Zf(poly_mulconst)(fpr *a, fpr x, unsigned logn); - -/* - * Divide polynomial a by polynomial b, modulo X^N+1 (FFT representation). - * a and b MUST NOT overlap. - */ -void Zf(poly_div_fft)(fpr *restrict a, const fpr *restrict b, unsigned logn); - -/* - * Given f and g (in FFT representation), compute 1/(f*adj(f)+g*adj(g)) - * (also in FFT representation). Since the result is auto-adjoint, all its - * coordinates in FFT representation are real; as such, only the first N/2 - * values of d[] are filled (the imaginary parts are skipped). - * - * Array d MUST NOT overlap with either a or b. - */ -void Zf(poly_invnorm2_fft)(fpr *restrict d, - const fpr *restrict a, const fpr *restrict b, unsigned logn); - -/* - * Given F, G, f and g (in FFT representation), compute F*adj(f)+G*adj(g) - * (also in FFT representation). Destination d MUST NOT overlap with - * any of the source arrays. - */ -void Zf(poly_add_muladj_fft)(fpr *restrict d, - const fpr *restrict F, const fpr *restrict G, - const fpr *restrict f, const fpr *restrict g, unsigned logn); - -/* - * Multiply polynomial a by polynomial b, where b is autoadjoint. Both - * a and b are in FFT representation. Since b is autoadjoint, all its - * FFT coefficients are real, and the array b contains only N/2 elements. - * a and b MUST NOT overlap. - */ -void Zf(poly_mul_autoadj_fft)(fpr *restrict a, - const fpr *restrict b, unsigned logn); - -/* - * Divide polynomial a by polynomial b, where b is autoadjoint. Both - * a and b are in FFT representation. Since b is autoadjoint, all its - * FFT coefficients are real, and the array b contains only N/2 elements. - * a and b MUST NOT overlap. - */ -void Zf(poly_div_autoadj_fft)(fpr *restrict a, - const fpr *restrict b, unsigned logn); - -/* - * Perform an LDL decomposition of an auto-adjoint matrix G, in FFT - * representation. On input, g00, g01 and g11 are provided (where the - * matrix G = [[g00, g01], [adj(g01), g11]]). On output, the d00, l10 - * and d11 values are written in g00, g01 and g11, respectively - * (with D = [[d00, 0], [0, d11]] and L = [[1, 0], [l10, 1]]). - * (In fact, d00 = g00, so the g00 operand is left unmodified.) - */ -void Zf(poly_LDL_fft)(const fpr *restrict g00, - fpr *restrict g01, fpr *restrict g11, unsigned logn); - -/* - * Perform an LDL decomposition of an auto-adjoint matrix G, in FFT - * representation. This is identical to poly_LDL_fft() except that - * g00, g01 and g11 are unmodified; the outputs d11 and l10 are written - * in two other separate buffers provided as extra parameters. - */ -void Zf(poly_LDLmv_fft)(fpr *restrict d11, fpr *restrict l10, - const fpr *restrict g00, const fpr *restrict g01, - const fpr *restrict g11, unsigned logn); - -/* - * Apply "split" operation on a polynomial in FFT representation: - * f = f0(x^2) + x*f1(x^2), for half-size polynomials f0 and f1 - * (polynomials modulo X^(N/2)+1). f0, f1 and f MUST NOT overlap. - */ -void Zf(poly_split_fft)(fpr *restrict f0, fpr *restrict f1, - const fpr *restrict f, unsigned logn); - -/* - * Apply "merge" operation on two polynomials in FFT representation: - * given f0 and f1, polynomials moduo X^(N/2)+1, this function computes - * f = f0(x^2) + x*f1(x^2), in FFT representation modulo X^N+1. - * f MUST NOT overlap with either f0 or f1. - */ -void Zf(poly_merge_fft)(fpr *restrict f, - const fpr *restrict f0, const fpr *restrict f1, unsigned logn); - -/* ==================================================================== */ -/* - * Key pair generation. - */ - -/* - * Required sizes of the temporary buffer (in bytes). - * - * This size is 28*2^logn bytes, except for degrees 2 and 4 (logn = 1 - * or 2) where it is slightly greater. - */ -#define FALCON_KEYGEN_TEMP_1 136 -#define FALCON_KEYGEN_TEMP_2 272 -#define FALCON_KEYGEN_TEMP_3 224 -#define FALCON_KEYGEN_TEMP_4 448 -#define FALCON_KEYGEN_TEMP_5 896 -#define FALCON_KEYGEN_TEMP_6 1792 -#define FALCON_KEYGEN_TEMP_7 3584 -#define FALCON_KEYGEN_TEMP_8 7168 -#define FALCON_KEYGEN_TEMP_9 14336 -#define FALCON_KEYGEN_TEMP_10 28672 - -/* - * Generate a new key pair. Randomness is extracted from the provided - * SHAKE256 context, which must have already been seeded and flipped. - * The tmp[] array must have suitable size (see FALCON_KEYGEN_TEMP_* - * macros) and be aligned for the uint32_t, uint64_t and fpr types. - * - * The private key elements are written in f, g, F and G, and the - * public key is written in h. Either or both of G and h may be NULL, - * in which case the corresponding element is not returned (they can - * be recomputed from f, g and F). - * - * tmp[] must have 64-bit alignment. - * This function uses floating-point rounding (see set_fpu_cw()). - */ -void Zf(keygen)(inner_shake256_context *rng, - int8_t *f, int8_t *g, int8_t *F, int8_t *G, uint16_t *h, - unsigned logn, uint8_t *tmp); - -/* ==================================================================== */ -/* - * Signature generation. - */ - -/* - * Expand a private key into the B0 matrix in FFT representation and - * the LDL tree. All the values are written in 'expanded_key', for - * a total of (8*logn+40)*2^logn bytes. - * - * The tmp[] array must have room for at least 48*2^logn bytes. - * - * tmp[] must have 64-bit alignment. - * This function uses floating-point rounding (see set_fpu_cw()). - */ -void Zf(expand_privkey)(fpr *restrict expanded_key, - const int8_t *f, const int8_t *g, const int8_t *F, const int8_t *G, - unsigned logn, uint8_t *restrict tmp); - -/* - * Compute a signature over the provided hashed message (hm); the - * signature value is one short vector. This function uses an - * expanded key (as generated by Zf(expand_privkey)()). - * - * The sig[] and hm[] buffers may overlap. - * - * On successful output, the start of the tmp[] buffer contains the s1 - * vector (as int16_t elements). - * - * The minimal size (in bytes) of tmp[] is 48*2^logn bytes. - * - * tmp[] must have 64-bit alignment. - * This function uses floating-point rounding (see set_fpu_cw()). - */ -void Zf(sign_tree)(int16_t *sig, inner_shake256_context *rng, - const fpr *restrict expanded_key, - const uint16_t *hm, unsigned logn, uint8_t *tmp); - -/* - * Compute a signature over the provided hashed message (hm); the - * signature value is one short vector. This function uses a raw - * key and dynamically recompute the B0 matrix and LDL tree; this - * saves RAM since there is no needed for an expanded key, but - * increases the signature cost. - * - * The sig[] and hm[] buffers may overlap. - * - * On successful output, the start of the tmp[] buffer contains the s1 - * vector (as int16_t elements). - * - * The minimal size (in bytes) of tmp[] is 72*2^logn bytes. - * - * tmp[] must have 64-bit alignment. - * This function uses floating-point rounding (see set_fpu_cw()). - */ -void Zf(sign_dyn)(int16_t *sig, inner_shake256_context *rng, - const int8_t *restrict f, const int8_t *restrict g, - const int8_t *restrict F, const int8_t *restrict G, - const uint16_t *hm, unsigned logn, uint8_t *tmp); - -/* - * Internal sampler engine. Exported for tests. - * - * sampler_context wraps around a source of random numbers (PRNG) and - * the sigma_min value (nominally dependent on the degree). - * - * sampler() takes as parameters: - * ctx pointer to the sampler_context structure - * mu center for the distribution - * isigma inverse of the distribution standard deviation - * It returns an integer sampled along the Gaussian distribution centered - * on mu and of standard deviation sigma = 1/isigma. - * - * gaussian0_sampler() takes as parameter a pointer to a PRNG, and - * returns an integer sampled along a half-Gaussian with standard - * deviation sigma0 = 1.8205 (center is 0, returned value is - * nonnegative). - */ - -typedef struct { - prng p; - fpr sigma_min; -} sampler_context; - -TARGET_AVX2 -int Zf(sampler)(void *ctx, fpr mu, fpr isigma); - -TARGET_AVX2 -int Zf(gaussian0_sampler)(prng *p); - -/* ==================================================================== */ - -#endif diff --git a/falcon/keygen.c b/falcon/keygen.c deleted file mode 100644 index cf7de00..0000000 --- a/falcon/keygen.c +++ /dev/null @@ -1,4301 +0,0 @@ -/* - * Falcon key pair generation. - * - * ==========================(LICENSE BEGIN)============================ - * - * Copyright (c) 2017-2019 Falcon Project - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * ===========================(LICENSE END)============================= - * - * @author Thomas Pornin - */ - -#include "inner.h" - -#define MKN(logn) ((size_t)1 << (logn)) - -/* ==================================================================== */ -/* - * Modular arithmetics. - * - * We implement a few functions for computing modulo a small integer p. - * - * All functions require that 2^30 < p < 2^31. Moreover, operands must - * be in the 0..p-1 range. - * - * Modular addition and subtraction work for all such p. - * - * Montgomery multiplication requires that p is odd, and must be provided - * with an additional value p0i = -1/p mod 2^31. See below for some basics - * on Montgomery multiplication. - * - * Division computes an inverse modulo p by an exponentiation (with - * exponent p-2): this works only if p is prime. Multiplication - * requirements also apply, i.e. p must be odd and p0i must be provided. - * - * The NTT and inverse NTT need all of the above, and also that - * p = 1 mod 2048. - * - * ----------------------------------------------------------------------- - * - * We use Montgomery representation with 31-bit values: - * - * Let R = 2^31 mod p. When 2^30 < p < 2^31, R = 2^31 - p. - * Montgomery representation of an integer x modulo p is x*R mod p. - * - * Montgomery multiplication computes (x*y)/R mod p for - * operands x and y. Therefore: - * - * - if operands are x*R and y*R (Montgomery representations of x and - * y), then Montgomery multiplication computes (x*R*y*R)/R = (x*y)*R - * mod p, which is the Montgomery representation of the product x*y; - * - * - if operands are x*R and y (or x and y*R), then Montgomery - * multiplication returns x*y mod p: mixed-representation - * multiplications yield results in normal representation. - * - * To convert to Montgomery representation, we multiply by R, which is done - * by Montgomery-multiplying by R^2. Stand-alone conversion back from - * Montgomery representation is Montgomery-multiplication by 1. - */ - -/* - * Precomputed small primes. Each element contains the following: - * - * p The prime itself. - * - * g A primitive root of phi = X^N+1 (in field Z_p). - * - * s The inverse of the product of all previous primes in the array, - * computed modulo p and in Montgomery representation. - * - * All primes are such that p = 1 mod 2048, and are lower than 2^31. They - * are listed in decreasing order. - */ - -typedef struct { - uint32_t p; - uint32_t g; - uint32_t s; -} small_prime; - -static const small_prime PRIMES[] = { - { 2147473409, 383167813, 10239 }, - { 2147389441, 211808905, 471403745 }, - { 2147387393, 37672282, 1329335065 }, - { 2147377153, 1977035326, 968223422 }, - { 2147358721, 1067163706, 132460015 }, - { 2147352577, 1606082042, 598693809 }, - { 2147346433, 2033915641, 1056257184 }, - { 2147338241, 1653770625, 421286710 }, - { 2147309569, 631200819, 1111201074 }, - { 2147297281, 2038364663, 1042003613 }, - { 2147295233, 1962540515, 19440033 }, - { 2147239937, 2100082663, 353296760 }, - { 2147235841, 1991153006, 1703918027 }, - { 2147217409, 516405114, 1258919613 }, - { 2147205121, 409347988, 1089726929 }, - { 2147196929, 927788991, 1946238668 }, - { 2147178497, 1136922411, 1347028164 }, - { 2147100673, 868626236, 701164723 }, - { 2147082241, 1897279176, 617820870 }, - { 2147074049, 1888819123, 158382189 }, - { 2147051521, 25006327, 522758543 }, - { 2147043329, 327546255, 37227845 }, - { 2147039233, 766324424, 1133356428 }, - { 2146988033, 1862817362, 73861329 }, - { 2146963457, 404622040, 653019435 }, - { 2146959361, 1936581214, 995143093 }, - { 2146938881, 1559770096, 634921513 }, - { 2146908161, 422623708, 1985060172 }, - { 2146885633, 1751189170, 298238186 }, - { 2146871297, 578919515, 291810829 }, - { 2146846721, 1114060353, 915902322 }, - { 2146834433, 2069565474, 47859524 }, - { 2146818049, 1552824584, 646281055 }, - { 2146775041, 1906267847, 1597832891 }, - { 2146756609, 1847414714, 1228090888 }, - { 2146744321, 1818792070, 1176377637 }, - { 2146738177, 1118066398, 1054971214 }, - { 2146736129, 52057278, 933422153 }, - { 2146713601, 592259376, 1406621510 }, - { 2146695169, 263161877, 1514178701 }, - { 2146656257, 685363115, 384505091 }, - { 2146650113, 927727032, 537575289 }, - { 2146646017, 52575506, 1799464037 }, - { 2146643969, 1276803876, 1348954416 }, - { 2146603009, 814028633, 1521547704 }, - { 2146572289, 1846678872, 1310832121 }, - { 2146547713, 919368090, 1019041349 }, - { 2146508801, 671847612, 38582496 }, - { 2146492417, 283911680, 532424562 }, - { 2146490369, 1780044827, 896447978 }, - { 2146459649, 327980850, 1327906900 }, - { 2146447361, 1310561493, 958645253 }, - { 2146441217, 412148926, 287271128 }, - { 2146437121, 293186449, 2009822534 }, - { 2146430977, 179034356, 1359155584 }, - { 2146418689, 1517345488, 1790248672 }, - { 2146406401, 1615820390, 1584833571 }, - { 2146404353, 826651445, 607120498 }, - { 2146379777, 3816988, 1897049071 }, - { 2146363393, 1221409784, 1986921567 }, - { 2146355201, 1388081168, 849968120 }, - { 2146336769, 1803473237, 1655544036 }, - { 2146312193, 1023484977, 273671831 }, - { 2146293761, 1074591448, 467406983 }, - { 2146283521, 831604668, 1523950494 }, - { 2146203649, 712865423, 1170834574 }, - { 2146154497, 1764991362, 1064856763 }, - { 2146142209, 627386213, 1406840151 }, - { 2146127873, 1638674429, 2088393537 }, - { 2146099201, 1516001018, 690673370 }, - { 2146093057, 1294931393, 315136610 }, - { 2146091009, 1942399533, 973539425 }, - { 2146078721, 1843461814, 2132275436 }, - { 2146060289, 1098740778, 360423481 }, - { 2146048001, 1617213232, 1951981294 }, - { 2146041857, 1805783169, 2075683489 }, - { 2146019329, 272027909, 1753219918 }, - { 2145986561, 1206530344, 2034028118 }, - { 2145976321, 1243769360, 1173377644 }, - { 2145964033, 887200839, 1281344586 }, - { 2145906689, 1651026455, 906178216 }, - { 2145875969, 1673238256, 1043521212 }, - { 2145871873, 1226591210, 1399796492 }, - { 2145841153, 1465353397, 1324527802 }, - { 2145832961, 1150638905, 554084759 }, - { 2145816577, 221601706, 427340863 }, - { 2145785857, 608896761, 316590738 }, - { 2145755137, 1712054942, 1684294304 }, - { 2145742849, 1302302867, 724873116 }, - { 2145728513, 516717693, 431671476 }, - { 2145699841, 524575579, 1619722537 }, - { 2145691649, 1925625239, 982974435 }, - { 2145687553, 463795662, 1293154300 }, - { 2145673217, 771716636, 881778029 }, - { 2145630209, 1509556977, 837364988 }, - { 2145595393, 229091856, 851648427 }, - { 2145587201, 1796903241, 635342424 }, - { 2145525761, 715310882, 1677228081 }, - { 2145495041, 1040930522, 200685896 }, - { 2145466369, 949804237, 1809146322 }, - { 2145445889, 1673903706, 95316881 }, - { 2145390593, 806941852, 1428671135 }, - { 2145372161, 1402525292, 159350694 }, - { 2145361921, 2124760298, 1589134749 }, - { 2145359873, 1217503067, 1561543010 }, - { 2145355777, 338341402, 83865711 }, - { 2145343489, 1381532164, 641430002 }, - { 2145325057, 1883895478, 1528469895 }, - { 2145318913, 1335370424, 65809740 }, - { 2145312769, 2000008042, 1919775760 }, - { 2145300481, 961450962, 1229540578 }, - { 2145282049, 910466767, 1964062701 }, - { 2145232897, 816527501, 450152063 }, - { 2145218561, 1435128058, 1794509700 }, - { 2145187841, 33505311, 1272467582 }, - { 2145181697, 269767433, 1380363849 }, - { 2145175553, 56386299, 1316870546 }, - { 2145079297, 2106880293, 1391797340 }, - { 2145021953, 1347906152, 720510798 }, - { 2145015809, 206769262, 1651459955 }, - { 2145003521, 1885513236, 1393381284 }, - { 2144960513, 1810381315, 31937275 }, - { 2144944129, 1306487838, 2019419520 }, - { 2144935937, 37304730, 1841489054 }, - { 2144894977, 1601434616, 157985831 }, - { 2144888833, 98749330, 2128592228 }, - { 2144880641, 1772327002, 2076128344 }, - { 2144864257, 1404514762, 2029969964 }, - { 2144827393, 801236594, 406627220 }, - { 2144806913, 349217443, 1501080290 }, - { 2144796673, 1542656776, 2084736519 }, - { 2144778241, 1210734884, 1746416203 }, - { 2144759809, 1146598851, 716464489 }, - { 2144757761, 286328400, 1823728177 }, - { 2144729089, 1347555695, 1836644881 }, - { 2144727041, 1795703790, 520296412 }, - { 2144696321, 1302475157, 852964281 }, - { 2144667649, 1075877614, 504992927 }, - { 2144573441, 198765808, 1617144982 }, - { 2144555009, 321528767, 155821259 }, - { 2144550913, 814139516, 1819937644 }, - { 2144536577, 571143206, 962942255 }, - { 2144524289, 1746733766, 2471321 }, - { 2144512001, 1821415077, 124190939 }, - { 2144468993, 917871546, 1260072806 }, - { 2144458753, 378417981, 1569240563 }, - { 2144421889, 175229668, 1825620763 }, - { 2144409601, 1699216963, 351648117 }, - { 2144370689, 1071885991, 958186029 }, - { 2144348161, 1763151227, 540353574 }, - { 2144335873, 1060214804, 919598847 }, - { 2144329729, 663515846, 1448552668 }, - { 2144327681, 1057776305, 590222840 }, - { 2144309249, 1705149168, 1459294624 }, - { 2144296961, 325823721, 1649016934 }, - { 2144290817, 738775789, 447427206 }, - { 2144243713, 962347618, 893050215 }, - { 2144237569, 1655257077, 900860862 }, - { 2144161793, 242206694, 1567868672 }, - { 2144155649, 769415308, 1247993134 }, - { 2144137217, 320492023, 515841070 }, - { 2144120833, 1639388522, 770877302 }, - { 2144071681, 1761785233, 964296120 }, - { 2144065537, 419817825, 204564472 }, - { 2144028673, 666050597, 2091019760 }, - { 2144010241, 1413657615, 1518702610 }, - { 2143952897, 1238327946, 475672271 }, - { 2143940609, 307063413, 1176750846 }, - { 2143918081, 2062905559, 786785803 }, - { 2143899649, 1338112849, 1562292083 }, - { 2143891457, 68149545, 87166451 }, - { 2143885313, 921750778, 394460854 }, - { 2143854593, 719766593, 133877196 }, - { 2143836161, 1149399850, 1861591875 }, - { 2143762433, 1848739366, 1335934145 }, - { 2143756289, 1326674710, 102999236 }, - { 2143713281, 808061791, 1156900308 }, - { 2143690753, 388399459, 1926468019 }, - { 2143670273, 1427891374, 1756689401 }, - { 2143666177, 1912173949, 986629565 }, - { 2143645697, 2041160111, 371842865 }, - { 2143641601, 1279906897, 2023974350 }, - { 2143635457, 720473174, 1389027526 }, - { 2143621121, 1298309455, 1732632006 }, - { 2143598593, 1548762216, 1825417506 }, - { 2143567873, 620475784, 1073787233 }, - { 2143561729, 1932954575, 949167309 }, - { 2143553537, 354315656, 1652037534 }, - { 2143541249, 577424288, 1097027618 }, - { 2143531009, 357862822, 478640055 }, - { 2143522817, 2017706025, 1550531668 }, - { 2143506433, 2078127419, 1824320165 }, - { 2143488001, 613475285, 1604011510 }, - { 2143469569, 1466594987, 502095196 }, - { 2143426561, 1115430331, 1044637111 }, - { 2143383553, 9778045, 1902463734 }, - { 2143377409, 1557401276, 2056861771 }, - { 2143363073, 652036455, 1965915971 }, - { 2143260673, 1464581171, 1523257541 }, - { 2143246337, 1876119649, 764541916 }, - { 2143209473, 1614992673, 1920672844 }, - { 2143203329, 981052047, 2049774209 }, - { 2143160321, 1847355533, 728535665 }, - { 2143129601, 965558457, 603052992 }, - { 2143123457, 2140817191, 8348679 }, - { 2143100929, 1547263683, 694209023 }, - { 2143092737, 643459066, 1979934533 }, - { 2143082497, 188603778, 2026175670 }, - { 2143062017, 1657329695, 377451099 }, - { 2143051777, 114967950, 979255473 }, - { 2143025153, 1698431342, 1449196896 }, - { 2143006721, 1862741675, 1739650365 }, - { 2142996481, 756660457, 996160050 }, - { 2142976001, 927864010, 1166847574 }, - { 2142965761, 905070557, 661974566 }, - { 2142916609, 40932754, 1787161127 }, - { 2142892033, 1987985648, 675335382 }, - { 2142885889, 797497211, 1323096997 }, - { 2142871553, 2068025830, 1411877159 }, - { 2142861313, 1217177090, 1438410687 }, - { 2142830593, 409906375, 1767860634 }, - { 2142803969, 1197788993, 359782919 }, - { 2142785537, 643817365, 513932862 }, - { 2142779393, 1717046338, 218943121 }, - { 2142724097, 89336830, 416687049 }, - { 2142707713, 5944581, 1356813523 }, - { 2142658561, 887942135, 2074011722 }, - { 2142638081, 151851972, 1647339939 }, - { 2142564353, 1691505537, 1483107336 }, - { 2142533633, 1989920200, 1135938817 }, - { 2142529537, 959263126, 1531961857 }, - { 2142527489, 453251129, 1725566162 }, - { 2142502913, 1536028102, 182053257 }, - { 2142498817, 570138730, 701443447 }, - { 2142416897, 326965800, 411931819 }, - { 2142363649, 1675665410, 1517191733 }, - { 2142351361, 968529566, 1575712703 }, - { 2142330881, 1384953238, 1769087884 }, - { 2142314497, 1977173242, 1833745524 }, - { 2142289921, 95082313, 1714775493 }, - { 2142283777, 109377615, 1070584533 }, - { 2142277633, 16960510, 702157145 }, - { 2142263297, 553850819, 431364395 }, - { 2142208001, 241466367, 2053967982 }, - { 2142164993, 1795661326, 1031836848 }, - { 2142097409, 1212530046, 712772031 }, - { 2142087169, 1763869720, 822276067 }, - { 2142078977, 644065713, 1765268066 }, - { 2142074881, 112671944, 643204925 }, - { 2142044161, 1387785471, 1297890174 }, - { 2142025729, 783885537, 1000425730 }, - { 2142011393, 905662232, 1679401033 }, - { 2141974529, 799788433, 468119557 }, - { 2141943809, 1932544124, 449305555 }, - { 2141933569, 1527403256, 841867925 }, - { 2141931521, 1247076451, 743823916 }, - { 2141902849, 1199660531, 401687910 }, - { 2141890561, 150132350, 1720336972 }, - { 2141857793, 1287438162, 663880489 }, - { 2141833217, 618017731, 1819208266 }, - { 2141820929, 999578638, 1403090096 }, - { 2141786113, 81834325, 1523542501 }, - { 2141771777, 120001928, 463556492 }, - { 2141759489, 122455485, 2124928282 }, - { 2141749249, 141986041, 940339153 }, - { 2141685761, 889088734, 477141499 }, - { 2141673473, 324212681, 1122558298 }, - { 2141669377, 1175806187, 1373818177 }, - { 2141655041, 1113654822, 296887082 }, - { 2141587457, 991103258, 1585913875 }, - { 2141583361, 1401451409, 1802457360 }, - { 2141575169, 1571977166, 712760980 }, - { 2141546497, 1107849376, 1250270109 }, - { 2141515777, 196544219, 356001130 }, - { 2141495297, 1733571506, 1060744866 }, - { 2141483009, 321552363, 1168297026 }, - { 2141458433, 505818251, 733225819 }, - { 2141360129, 1026840098, 948342276 }, - { 2141325313, 945133744, 2129965998 }, - { 2141317121, 1871100260, 1843844634 }, - { 2141286401, 1790639498, 1750465696 }, - { 2141267969, 1376858592, 186160720 }, - { 2141255681, 2129698296, 1876677959 }, - { 2141243393, 2138900688, 1340009628 }, - { 2141214721, 1933049835, 1087819477 }, - { 2141212673, 1898664939, 1786328049 }, - { 2141202433, 990234828, 940682169 }, - { 2141175809, 1406392421, 993089586 }, - { 2141165569, 1263518371, 289019479 }, - { 2141073409, 1485624211, 507864514 }, - { 2141052929, 1885134788, 311252465 }, - { 2141040641, 1285021247, 280941862 }, - { 2141028353, 1527610374, 375035110 }, - { 2141011969, 1400626168, 164696620 }, - { 2140999681, 632959608, 966175067 }, - { 2140997633, 2045628978, 1290889438 }, - { 2140993537, 1412755491, 375366253 }, - { 2140942337, 719477232, 785367828 }, - { 2140925953, 45224252, 836552317 }, - { 2140917761, 1157376588, 1001839569 }, - { 2140887041, 278480752, 2098732796 }, - { 2140837889, 1663139953, 924094810 }, - { 2140788737, 802501511, 2045368990 }, - { 2140766209, 1820083885, 1800295504 }, - { 2140764161, 1169561905, 2106792035 }, - { 2140696577, 127781498, 1885987531 }, - { 2140684289, 16014477, 1098116827 }, - { 2140653569, 665960598, 1796728247 }, - { 2140594177, 1043085491, 377310938 }, - { 2140579841, 1732838211, 1504505945 }, - { 2140569601, 302071939, 358291016 }, - { 2140567553, 192393733, 1909137143 }, - { 2140557313, 406595731, 1175330270 }, - { 2140549121, 1748850918, 525007007 }, - { 2140477441, 499436566, 1031159814 }, - { 2140469249, 1886004401, 1029951320 }, - { 2140426241, 1483168100, 1676273461 }, - { 2140420097, 1779917297, 846024476 }, - { 2140413953, 522948893, 1816354149 }, - { 2140383233, 1931364473, 1296921241 }, - { 2140366849, 1917356555, 147196204 }, - { 2140354561, 16466177, 1349052107 }, - { 2140348417, 1875366972, 1860485634 }, - { 2140323841, 456498717, 1790256483 }, - { 2140321793, 1629493973, 150031888 }, - { 2140315649, 1904063898, 395510935 }, - { 2140280833, 1784104328, 831417909 }, - { 2140250113, 256087139, 697349101 }, - { 2140229633, 388553070, 243875754 }, - { 2140223489, 747459608, 1396270850 }, - { 2140200961, 507423743, 1895572209 }, - { 2140162049, 580106016, 2045297469 }, - { 2140149761, 712426444, 785217995 }, - { 2140137473, 1441607584, 536866543 }, - { 2140119041, 346538902, 1740434653 }, - { 2140090369, 282642885, 21051094 }, - { 2140076033, 1407456228, 319910029 }, - { 2140047361, 1619330500, 1488632070 }, - { 2140041217, 2089408064, 2012026134 }, - { 2140008449, 1705524800, 1613440760 }, - { 2139924481, 1846208233, 1280649481 }, - { 2139906049, 989438755, 1185646076 }, - { 2139867137, 1522314850, 372783595 }, - { 2139842561, 1681587377, 216848235 }, - { 2139826177, 2066284988, 1784999464 }, - { 2139824129, 480888214, 1513323027 }, - { 2139789313, 847937200, 858192859 }, - { 2139783169, 1642000434, 1583261448 }, - { 2139770881, 940699589, 179702100 }, - { 2139768833, 315623242, 964612676 }, - { 2139666433, 331649203, 764666914 }, - { 2139641857, 2118730799, 1313764644 }, - { 2139635713, 519149027, 519212449 }, - { 2139598849, 1526413634, 1769667104 }, - { 2139574273, 551148610, 820739925 }, - { 2139568129, 1386800242, 472447405 }, - { 2139549697, 813760130, 1412328531 }, - { 2139537409, 1615286260, 1609362979 }, - { 2139475969, 1352559299, 1696720421 }, - { 2139455489, 1048691649, 1584935400 }, - { 2139432961, 836025845, 950121150 }, - { 2139424769, 1558281165, 1635486858 }, - { 2139406337, 1728402143, 1674423301 }, - { 2139396097, 1727715782, 1483470544 }, - { 2139383809, 1092853491, 1741699084 }, - { 2139369473, 690776899, 1242798709 }, - { 2139351041, 1768782380, 2120712049 }, - { 2139334657, 1739968247, 1427249225 }, - { 2139332609, 1547189119, 623011170 }, - { 2139310081, 1346827917, 1605466350 }, - { 2139303937, 369317948, 828392831 }, - { 2139301889, 1560417239, 1788073219 }, - { 2139283457, 1303121623, 595079358 }, - { 2139248641, 1354555286, 573424177 }, - { 2139240449, 60974056, 885781403 }, - { 2139222017, 355573421, 1221054839 }, - { 2139215873, 566477826, 1724006500 }, - { 2139150337, 871437673, 1609133294 }, - { 2139144193, 1478130914, 1137491905 }, - { 2139117569, 1854880922, 964728507 }, - { 2139076609, 202405335, 756508944 }, - { 2139062273, 1399715741, 884826059 }, - { 2139045889, 1051045798, 1202295476 }, - { 2139033601, 1707715206, 632234634 }, - { 2139006977, 2035853139, 231626690 }, - { 2138951681, 183867876, 838350879 }, - { 2138945537, 1403254661, 404460202 }, - { 2138920961, 310865011, 1282911681 }, - { 2138910721, 1328496553, 103472415 }, - { 2138904577, 78831681, 993513549 }, - { 2138902529, 1319697451, 1055904361 }, - { 2138816513, 384338872, 1706202469 }, - { 2138810369, 1084868275, 405677177 }, - { 2138787841, 401181788, 1964773901 }, - { 2138775553, 1850532988, 1247087473 }, - { 2138767361, 874261901, 1576073565 }, - { 2138757121, 1187474742, 993541415 }, - { 2138748929, 1782458888, 1043206483 }, - { 2138744833, 1221500487, 800141243 }, - { 2138738689, 413465368, 1450660558 }, - { 2138695681, 739045140, 342611472 }, - { 2138658817, 1355845756, 672674190 }, - { 2138644481, 608379162, 1538874380 }, - { 2138632193, 1444914034, 686911254 }, - { 2138607617, 484707818, 1435142134 }, - { 2138591233, 539460669, 1290458549 }, - { 2138572801, 2093538990, 2011138646 }, - { 2138552321, 1149786988, 1076414907 }, - { 2138546177, 840688206, 2108985273 }, - { 2138533889, 209669619, 198172413 }, - { 2138523649, 1975879426, 1277003968 }, - { 2138490881, 1351891144, 1976858109 }, - { 2138460161, 1817321013, 1979278293 }, - { 2138429441, 1950077177, 203441928 }, - { 2138400769, 908970113, 628395069 }, - { 2138398721, 219890864, 758486760 }, - { 2138376193, 1306654379, 977554090 }, - { 2138351617, 298822498, 2004708503 }, - { 2138337281, 441457816, 1049002108 }, - { 2138320897, 1517731724, 1442269609 }, - { 2138290177, 1355911197, 1647139103 }, - { 2138234881, 531313247, 1746591962 }, - { 2138214401, 1899410930, 781416444 }, - { 2138202113, 1813477173, 1622508515 }, - { 2138191873, 1086458299, 1025408615 }, - { 2138183681, 1998800427, 827063290 }, - { 2138173441, 1921308898, 749670117 }, - { 2138103809, 1620902804, 2126787647 }, - { 2138099713, 828647069, 1892961817 }, - { 2138085377, 179405355, 1525506535 }, - { 2138060801, 615683235, 1259580138 }, - { 2138044417, 2030277840, 1731266562 }, - { 2138042369, 2087222316, 1627902259 }, - { 2138032129, 126388712, 1108640984 }, - { 2138011649, 715026550, 1017980050 }, - { 2137993217, 1693714349, 1351778704 }, - { 2137888769, 1289762259, 1053090405 }, - { 2137853953, 199991890, 1254192789 }, - { 2137833473, 941421685, 896995556 }, - { 2137817089, 750416446, 1251031181 }, - { 2137792513, 798075119, 368077456 }, - { 2137786369, 878543495, 1035375025 }, - { 2137767937, 9351178, 1156563902 }, - { 2137755649, 1382297614, 1686559583 }, - { 2137724929, 1345472850, 1681096331 }, - { 2137704449, 834666929, 630551727 }, - { 2137673729, 1646165729, 1892091571 }, - { 2137620481, 778943821, 48456461 }, - { 2137618433, 1730837875, 1713336725 }, - { 2137581569, 805610339, 1378891359 }, - { 2137538561, 204342388, 1950165220 }, - { 2137526273, 1947629754, 1500789441 }, - { 2137516033, 719902645, 1499525372 }, - { 2137491457, 230451261, 556382829 }, - { 2137440257, 979573541, 412760291 }, - { 2137374721, 927841248, 1954137185 }, - { 2137362433, 1243778559, 861024672 }, - { 2137313281, 1341338501, 980638386 }, - { 2137311233, 937415182, 1793212117 }, - { 2137255937, 795331324, 1410253405 }, - { 2137243649, 150756339, 1966999887 }, - { 2137182209, 163346914, 1939301431 }, - { 2137171969, 1952552395, 758913141 }, - { 2137159681, 570788721, 218668666 }, - { 2137147393, 1896656810, 2045670345 }, - { 2137141249, 358493842, 518199643 }, - { 2137139201, 1505023029, 674695848 }, - { 2137133057, 27911103, 830956306 }, - { 2137122817, 439771337, 1555268614 }, - { 2137116673, 790988579, 1871449599 }, - { 2137110529, 432109234, 811805080 }, - { 2137102337, 1357900653, 1184997641 }, - { 2137098241, 515119035, 1715693095 }, - { 2137090049, 408575203, 2085660657 }, - { 2137085953, 2097793407, 1349626963 }, - { 2137055233, 1556739954, 1449960883 }, - { 2137030657, 1545758650, 1369303716 }, - { 2136987649, 332602570, 103875114 }, - { 2136969217, 1499989506, 1662964115 }, - { 2136924161, 857040753, 4738842 }, - { 2136895489, 1948872712, 570436091 }, - { 2136893441, 58969960, 1568349634 }, - { 2136887297, 2127193379, 273612548 }, - { 2136850433, 111208983, 1181257116 }, - { 2136809473, 1627275942, 1680317971 }, - { 2136764417, 1574888217, 14011331 }, - { 2136741889, 14011055, 1129154251 }, - { 2136727553, 35862563, 1838555253 }, - { 2136721409, 310235666, 1363928244 }, - { 2136698881, 1612429202, 1560383828 }, - { 2136649729, 1138540131, 800014364 }, - { 2136606721, 602323503, 1433096652 }, - { 2136563713, 182209265, 1919611038 }, - { 2136555521, 324156477, 165591039 }, - { 2136549377, 195513113, 217165345 }, - { 2136526849, 1050768046, 939647887 }, - { 2136508417, 1886286237, 1619926572 }, - { 2136477697, 609647664, 35065157 }, - { 2136471553, 679352216, 1452259468 }, - { 2136457217, 128630031, 824816521 }, - { 2136422401, 19787464, 1526049830 }, - { 2136420353, 698316836, 1530623527 }, - { 2136371201, 1651862373, 1804812805 }, - { 2136334337, 326596005, 336977082 }, - { 2136322049, 63253370, 1904972151 }, - { 2136297473, 312176076, 172182411 }, - { 2136248321, 381261841, 369032670 }, - { 2136242177, 358688773, 1640007994 }, - { 2136229889, 512677188, 75585225 }, - { 2136219649, 2095003250, 1970086149 }, - { 2136207361, 1909650722, 537760675 }, - { 2136176641, 1334616195, 1533487619 }, - { 2136158209, 2096285632, 1793285210 }, - { 2136143873, 1897347517, 293843959 }, - { 2136133633, 923586222, 1022655978 }, - { 2136096769, 1464868191, 1515074410 }, - { 2136094721, 2020679520, 2061636104 }, - { 2136076289, 290798503, 1814726809 }, - { 2136041473, 156415894, 1250757633 }, - { 2135996417, 297459940, 1132158924 }, - { 2135955457, 538755304, 1688831340 }, - { 0, 0, 0 } -}; - -/* - * Reduce a small signed integer modulo a small prime. The source - * value x MUST be such that -p < x < p. - */ -static inline uint32_t -modp_set(int32_t x, uint32_t p) -{ - uint32_t w; - - w = (uint32_t)x; - w += p & -(w >> 31); - return w; -} - -/* - * Normalize a modular integer around 0. - */ -static inline int32_t -modp_norm(uint32_t x, uint32_t p) -{ - return (int32_t)(x - (p & (((x - ((p + 1) >> 1)) >> 31) - 1))); -} - -/* - * Compute -1/p mod 2^31. This works for all odd integers p that fit - * on 31 bits. - */ -static uint32_t -modp_ninv31(uint32_t p) -{ - uint32_t y; - - y = 2 - p; - y *= 2 - p * y; - y *= 2 - p * y; - y *= 2 - p * y; - y *= 2 - p * y; - return (uint32_t)0x7FFFFFFF & -y; -} - -/* - * Compute R = 2^31 mod p. - */ -static inline uint32_t -modp_R(uint32_t p) -{ - /* - * Since 2^30 < p < 2^31, we know that 2^31 mod p is simply - * 2^31 - p. - */ - return ((uint32_t)1 << 31) - p; -} - -/* - * Addition modulo p. - */ -static inline uint32_t -modp_add(uint32_t a, uint32_t b, uint32_t p) -{ - uint32_t d; - - d = a + b - p; - d += p & -(d >> 31); - return d; -} - -/* - * Subtraction modulo p. - */ -static inline uint32_t -modp_sub(uint32_t a, uint32_t b, uint32_t p) -{ - uint32_t d; - - d = a - b; - d += p & -(d >> 31); - return d; -} - -/* - * Halving modulo p. - */ -/* unused -static inline uint32_t -modp_half(uint32_t a, uint32_t p) -{ - a += p & -(a & 1); - return a >> 1; -} -*/ - -/* - * Montgomery multiplication modulo p. The 'p0i' value is -1/p mod 2^31. - * It is required that p is an odd integer. - */ -static inline uint32_t -modp_montymul(uint32_t a, uint32_t b, uint32_t p, uint32_t p0i) -{ - uint64_t z, w; - uint32_t d; - - z = (uint64_t)a * (uint64_t)b; - w = ((z * p0i) & (uint64_t)0x7FFFFFFF) * p; - d = (uint32_t)((z + w) >> 31) - p; - d += p & -(d >> 31); - return d; -} - -/* - * Compute R2 = 2^62 mod p. - */ -static uint32_t -modp_R2(uint32_t p, uint32_t p0i) -{ - uint32_t z; - - /* - * Compute z = 2^31 mod p (this is the value 1 in Montgomery - * representation), then double it with an addition. - */ - z = modp_R(p); - z = modp_add(z, z, p); - - /* - * Square it five times to obtain 2^32 in Montgomery representation - * (i.e. 2^63 mod p). - */ - z = modp_montymul(z, z, p, p0i); - z = modp_montymul(z, z, p, p0i); - z = modp_montymul(z, z, p, p0i); - z = modp_montymul(z, z, p, p0i); - z = modp_montymul(z, z, p, p0i); - - /* - * Halve the value mod p to get 2^62. - */ - z = (z + (p & -(z & 1))) >> 1; - return z; -} - -/* - * Compute 2^(31*x) modulo p. This works for integers x up to 2^11. - * p must be prime such that 2^30 < p < 2^31; p0i must be equal to - * -1/p mod 2^31; R2 must be equal to 2^62 mod p. - */ -static inline uint32_t -modp_Rx(unsigned x, uint32_t p, uint32_t p0i, uint32_t R2) -{ - int i; - uint32_t r, z; - - /* - * 2^(31*x) = (2^31)*(2^(31*(x-1))); i.e. we want the Montgomery - * representation of (2^31)^e mod p, where e = x-1. - * R2 is 2^31 in Montgomery representation. - */ - x --; - r = R2; - z = modp_R(p); - for (i = 0; (1U << i) <= x; i ++) { - if ((x & (1U << i)) != 0) { - z = modp_montymul(z, r, p, p0i); - } - r = modp_montymul(r, r, p, p0i); - } - return z; -} - -/* - * Division modulo p. If the divisor (b) is 0, then 0 is returned. - * This function computes proper results only when p is prime. - * Parameters: - * a dividend - * b divisor - * p odd prime modulus - * p0i -1/p mod 2^31 - * R 2^31 mod R - */ -static uint32_t -modp_div(uint32_t a, uint32_t b, uint32_t p, uint32_t p0i, uint32_t R) -{ - uint32_t z, e; - int i; - - e = p - 2; - z = R; - for (i = 30; i >= 0; i --) { - uint32_t z2; - - z = modp_montymul(z, z, p, p0i); - z2 = modp_montymul(z, b, p, p0i); - z ^= (z ^ z2) & -(uint32_t)((e >> i) & 1); - } - - /* - * The loop above just assumed that b was in Montgomery - * representation, i.e. really contained b*R; under that - * assumption, it returns 1/b in Montgomery representation, - * which is R/b. But we gave it b in normal representation, - * so the loop really returned R/(b/R) = R^2/b. - * - * We want a/b, so we need one Montgomery multiplication with a, - * which also remove one of the R factors, and another such - * multiplication to remove the second R factor. - */ - z = modp_montymul(z, 1, p, p0i); - return modp_montymul(a, z, p, p0i); -} - -/* - * Bit-reversal index table. - */ -static const uint16_t REV10[] = { - 0, 512, 256, 768, 128, 640, 384, 896, 64, 576, 320, 832, - 192, 704, 448, 960, 32, 544, 288, 800, 160, 672, 416, 928, - 96, 608, 352, 864, 224, 736, 480, 992, 16, 528, 272, 784, - 144, 656, 400, 912, 80, 592, 336, 848, 208, 720, 464, 976, - 48, 560, 304, 816, 176, 688, 432, 944, 112, 624, 368, 880, - 240, 752, 496, 1008, 8, 520, 264, 776, 136, 648, 392, 904, - 72, 584, 328, 840, 200, 712, 456, 968, 40, 552, 296, 808, - 168, 680, 424, 936, 104, 616, 360, 872, 232, 744, 488, 1000, - 24, 536, 280, 792, 152, 664, 408, 920, 88, 600, 344, 856, - 216, 728, 472, 984, 56, 568, 312, 824, 184, 696, 440, 952, - 120, 632, 376, 888, 248, 760, 504, 1016, 4, 516, 260, 772, - 132, 644, 388, 900, 68, 580, 324, 836, 196, 708, 452, 964, - 36, 548, 292, 804, 164, 676, 420, 932, 100, 612, 356, 868, - 228, 740, 484, 996, 20, 532, 276, 788, 148, 660, 404, 916, - 84, 596, 340, 852, 212, 724, 468, 980, 52, 564, 308, 820, - 180, 692, 436, 948, 116, 628, 372, 884, 244, 756, 500, 1012, - 12, 524, 268, 780, 140, 652, 396, 908, 76, 588, 332, 844, - 204, 716, 460, 972, 44, 556, 300, 812, 172, 684, 428, 940, - 108, 620, 364, 876, 236, 748, 492, 1004, 28, 540, 284, 796, - 156, 668, 412, 924, 92, 604, 348, 860, 220, 732, 476, 988, - 60, 572, 316, 828, 188, 700, 444, 956, 124, 636, 380, 892, - 252, 764, 508, 1020, 2, 514, 258, 770, 130, 642, 386, 898, - 66, 578, 322, 834, 194, 706, 450, 962, 34, 546, 290, 802, - 162, 674, 418, 930, 98, 610, 354, 866, 226, 738, 482, 994, - 18, 530, 274, 786, 146, 658, 402, 914, 82, 594, 338, 850, - 210, 722, 466, 978, 50, 562, 306, 818, 178, 690, 434, 946, - 114, 626, 370, 882, 242, 754, 498, 1010, 10, 522, 266, 778, - 138, 650, 394, 906, 74, 586, 330, 842, 202, 714, 458, 970, - 42, 554, 298, 810, 170, 682, 426, 938, 106, 618, 362, 874, - 234, 746, 490, 1002, 26, 538, 282, 794, 154, 666, 410, 922, - 90, 602, 346, 858, 218, 730, 474, 986, 58, 570, 314, 826, - 186, 698, 442, 954, 122, 634, 378, 890, 250, 762, 506, 1018, - 6, 518, 262, 774, 134, 646, 390, 902, 70, 582, 326, 838, - 198, 710, 454, 966, 38, 550, 294, 806, 166, 678, 422, 934, - 102, 614, 358, 870, 230, 742, 486, 998, 22, 534, 278, 790, - 150, 662, 406, 918, 86, 598, 342, 854, 214, 726, 470, 982, - 54, 566, 310, 822, 182, 694, 438, 950, 118, 630, 374, 886, - 246, 758, 502, 1014, 14, 526, 270, 782, 142, 654, 398, 910, - 78, 590, 334, 846, 206, 718, 462, 974, 46, 558, 302, 814, - 174, 686, 430, 942, 110, 622, 366, 878, 238, 750, 494, 1006, - 30, 542, 286, 798, 158, 670, 414, 926, 94, 606, 350, 862, - 222, 734, 478, 990, 62, 574, 318, 830, 190, 702, 446, 958, - 126, 638, 382, 894, 254, 766, 510, 1022, 1, 513, 257, 769, - 129, 641, 385, 897, 65, 577, 321, 833, 193, 705, 449, 961, - 33, 545, 289, 801, 161, 673, 417, 929, 97, 609, 353, 865, - 225, 737, 481, 993, 17, 529, 273, 785, 145, 657, 401, 913, - 81, 593, 337, 849, 209, 721, 465, 977, 49, 561, 305, 817, - 177, 689, 433, 945, 113, 625, 369, 881, 241, 753, 497, 1009, - 9, 521, 265, 777, 137, 649, 393, 905, 73, 585, 329, 841, - 201, 713, 457, 969, 41, 553, 297, 809, 169, 681, 425, 937, - 105, 617, 361, 873, 233, 745, 489, 1001, 25, 537, 281, 793, - 153, 665, 409, 921, 89, 601, 345, 857, 217, 729, 473, 985, - 57, 569, 313, 825, 185, 697, 441, 953, 121, 633, 377, 889, - 249, 761, 505, 1017, 5, 517, 261, 773, 133, 645, 389, 901, - 69, 581, 325, 837, 197, 709, 453, 965, 37, 549, 293, 805, - 165, 677, 421, 933, 101, 613, 357, 869, 229, 741, 485, 997, - 21, 533, 277, 789, 149, 661, 405, 917, 85, 597, 341, 853, - 213, 725, 469, 981, 53, 565, 309, 821, 181, 693, 437, 949, - 117, 629, 373, 885, 245, 757, 501, 1013, 13, 525, 269, 781, - 141, 653, 397, 909, 77, 589, 333, 845, 205, 717, 461, 973, - 45, 557, 301, 813, 173, 685, 429, 941, 109, 621, 365, 877, - 237, 749, 493, 1005, 29, 541, 285, 797, 157, 669, 413, 925, - 93, 605, 349, 861, 221, 733, 477, 989, 61, 573, 317, 829, - 189, 701, 445, 957, 125, 637, 381, 893, 253, 765, 509, 1021, - 3, 515, 259, 771, 131, 643, 387, 899, 67, 579, 323, 835, - 195, 707, 451, 963, 35, 547, 291, 803, 163, 675, 419, 931, - 99, 611, 355, 867, 227, 739, 483, 995, 19, 531, 275, 787, - 147, 659, 403, 915, 83, 595, 339, 851, 211, 723, 467, 979, - 51, 563, 307, 819, 179, 691, 435, 947, 115, 627, 371, 883, - 243, 755, 499, 1011, 11, 523, 267, 779, 139, 651, 395, 907, - 75, 587, 331, 843, 203, 715, 459, 971, 43, 555, 299, 811, - 171, 683, 427, 939, 107, 619, 363, 875, 235, 747, 491, 1003, - 27, 539, 283, 795, 155, 667, 411, 923, 91, 603, 347, 859, - 219, 731, 475, 987, 59, 571, 315, 827, 187, 699, 443, 955, - 123, 635, 379, 891, 251, 763, 507, 1019, 7, 519, 263, 775, - 135, 647, 391, 903, 71, 583, 327, 839, 199, 711, 455, 967, - 39, 551, 295, 807, 167, 679, 423, 935, 103, 615, 359, 871, - 231, 743, 487, 999, 23, 535, 279, 791, 151, 663, 407, 919, - 87, 599, 343, 855, 215, 727, 471, 983, 55, 567, 311, 823, - 183, 695, 439, 951, 119, 631, 375, 887, 247, 759, 503, 1015, - 15, 527, 271, 783, 143, 655, 399, 911, 79, 591, 335, 847, - 207, 719, 463, 975, 47, 559, 303, 815, 175, 687, 431, 943, - 111, 623, 367, 879, 239, 751, 495, 1007, 31, 543, 287, 799, - 159, 671, 415, 927, 95, 607, 351, 863, 223, 735, 479, 991, - 63, 575, 319, 831, 191, 703, 447, 959, 127, 639, 383, 895, - 255, 767, 511, 1023 -}; - -/* - * Compute the roots for NTT and inverse NTT (binary case). Input - * parameter g is a primitive 2048-th root of 1 modulo p (i.e. g^1024 = - * -1 mod p). This fills gm[] and igm[] with powers of g and 1/g: - * gm[rev(i)] = g^i mod p - * igm[rev(i)] = (1/g)^i mod p - * where rev() is the "bit reversal" function over 10 bits. It fills - * the arrays only up to N = 2^logn values. - * - * The values stored in gm[] and igm[] are in Montgomery representation. - * - * p must be a prime such that p = 1 mod 2048. - */ -static void -modp_mkgm2(uint32_t *restrict gm, uint32_t *restrict igm, unsigned logn, - uint32_t g, uint32_t p, uint32_t p0i) -{ - size_t u, n; - unsigned k; - uint32_t ig, x1, x2, R2; - - n = (size_t)1 << logn; - - /* - * We want g such that g^(2N) = 1 mod p, but the provided - * generator has order 2048. We must square it a few times. - */ - R2 = modp_R2(p, p0i); - g = modp_montymul(g, R2, p, p0i); - for (k = logn; k < 10; k ++) { - g = modp_montymul(g, g, p, p0i); - } - - ig = modp_div(R2, g, p, p0i, modp_R(p)); - k = 10 - logn; - x1 = x2 = modp_R(p); - for (u = 0; u < n; u ++) { - size_t v; - - v = REV10[u << k]; - gm[v] = x1; - igm[v] = x2; - x1 = modp_montymul(x1, g, p, p0i); - x2 = modp_montymul(x2, ig, p, p0i); - } -} - -/* - * Compute the NTT over a polynomial (binary case). Polynomial elements - * are a[0], a[stride], a[2 * stride]... - */ -static void -modp_NTT2_ext(uint32_t *a, size_t stride, const uint32_t *gm, unsigned logn, - uint32_t p, uint32_t p0i) -{ - size_t t, m, n; - - if (logn == 0) { - return; - } - n = (size_t)1 << logn; - t = n; - for (m = 1; m < n; m <<= 1) { - size_t ht, u, v1; - - ht = t >> 1; - for (u = 0, v1 = 0; u < m; u ++, v1 += t) { - uint32_t s; - size_t v; - uint32_t *r1, *r2; - - s = gm[m + u]; - r1 = a + v1 * stride; - r2 = r1 + ht * stride; - for (v = 0; v < ht; v ++, r1 += stride, r2 += stride) { - uint32_t x, y; - - x = *r1; - y = modp_montymul(*r2, s, p, p0i); - *r1 = modp_add(x, y, p); - *r2 = modp_sub(x, y, p); - } - } - t = ht; - } -} - -/* - * Compute the inverse NTT over a polynomial (binary case). - */ -static void -modp_iNTT2_ext(uint32_t *a, size_t stride, const uint32_t *igm, unsigned logn, - uint32_t p, uint32_t p0i) -{ - size_t t, m, n, k; - uint32_t ni; - uint32_t *r; - - if (logn == 0) { - return; - } - n = (size_t)1 << logn; - t = 1; - for (m = n; m > 1; m >>= 1) { - size_t hm, dt, u, v1; - - hm = m >> 1; - dt = t << 1; - for (u = 0, v1 = 0; u < hm; u ++, v1 += dt) { - uint32_t s; - size_t v; - uint32_t *r1, *r2; - - s = igm[hm + u]; - r1 = a + v1 * stride; - r2 = r1 + t * stride; - for (v = 0; v < t; v ++, r1 += stride, r2 += stride) { - uint32_t x, y; - - x = *r1; - y = *r2; - *r1 = modp_add(x, y, p); - *r2 = modp_montymul( - modp_sub(x, y, p), s, p, p0i);; - } - } - t = dt; - } - - /* - * We need 1/n in Montgomery representation, i.e. R/n. Since - * 1 <= logn <= 10, R/n is an integer; morever, R/n <= 2^30 < p, - * thus a simple shift will do. - */ - ni = (uint32_t)1 << (31 - logn); - for (k = 0, r = a; k < n; k ++, r += stride) { - *r = modp_montymul(*r, ni, p, p0i); - } -} - -/* - * Simplified macros for NTT and iNTT (binary case) when the elements - * are consecutive in RAM. - */ -#define modp_NTT2(a, gm, logn, p, p0i) modp_NTT2_ext(a, 1, gm, logn, p, p0i) -#define modp_iNTT2(a, igm, logn, p, p0i) modp_iNTT2_ext(a, 1, igm, logn, p, p0i) - -/* - * Given polynomial f in NTT representation modulo p, compute f' of degree - * less than N/2 such that f' = f0^2 - X*f1^2, where f0 and f1 are - * polynomials of degree less than N/2 such that f = f0(X^2) + X*f1(X^2). - * - * The new polynomial is written "in place" over the first N/2 elements - * of f. - * - * If applied logn times successively on a given polynomial, the resulting - * degree-0 polynomial is the resultant of f and X^N+1 modulo p. - * - * This function applies only to the binary case; it is invoked from - * solve_NTRU_binary_depth1(). - */ -static void -modp_poly_rec_res(uint32_t *f, unsigned logn, - uint32_t p, uint32_t p0i, uint32_t R2) -{ - size_t hn, u; - - hn = (size_t)1 << (logn - 1); - for (u = 0; u < hn; u ++) { - uint32_t w0, w1; - - w0 = f[(u << 1) + 0]; - w1 = f[(u << 1) + 1]; - f[u] = modp_montymul(modp_montymul(w0, w1, p, p0i), R2, p, p0i); - } -} - -/* ==================================================================== */ -/* - * Custom bignum implementation. - * - * This is a very reduced set of functionalities. We need to do the - * following operations: - * - * - Rebuild the resultant and the polynomial coefficients from their - * values modulo small primes (of length 31 bits each). - * - * - Compute an extended GCD between the two computed resultants. - * - * - Extract top bits and add scaled values during the successive steps - * of Babai rounding. - * - * When rebuilding values using CRT, we must also recompute the product - * of the small prime factors. We always do it one small factor at a - * time, so the "complicated" operations can be done modulo the small - * prime with the modp_* functions. CRT coefficients (inverses) are - * precomputed. - * - * All values are positive until the last step: when the polynomial - * coefficients have been rebuilt, we normalize them around 0. But then, - * only additions and subtractions on the upper few bits are needed - * afterwards. - * - * We keep big integers as arrays of 31-bit words (in uint32_t values); - * the top bit of each uint32_t is kept equal to 0. Using 31-bit words - * makes it easier to keep track of carries. When negative values are - * used, two's complement is used. - */ - -/* - * Subtract integer b from integer a. Both integers are supposed to have - * the same size. The carry (0 or 1) is returned. Source arrays a and b - * MUST be distinct. - * - * The operation is performed as described above if ctr = 1. If - * ctl = 0, the value a[] is unmodified, but all memory accesses are - * still performed, and the carry is computed and returned. - */ -static uint32_t -zint_sub(uint32_t *restrict a, const uint32_t *restrict b, size_t len, - uint32_t ctl) -{ - size_t u; - uint32_t cc, m; - - cc = 0; - m = -ctl; - for (u = 0; u < len; u ++) { - uint32_t aw, w; - - aw = a[u]; - w = aw - b[u] - cc; - cc = w >> 31; - aw ^= ((w & 0x7FFFFFFF) ^ aw) & m; - a[u] = aw; - } - return cc; -} - -/* - * Mutiply the provided big integer m with a small value x. - * This function assumes that x < 2^31. The carry word is returned. - */ -static uint32_t -zint_mul_small(uint32_t *m, size_t mlen, uint32_t x) -{ - size_t u; - uint32_t cc; - - cc = 0; - for (u = 0; u < mlen; u ++) { - uint64_t z; - - z = (uint64_t)m[u] * (uint64_t)x + cc; - m[u] = (uint32_t)z & 0x7FFFFFFF; - cc = (uint32_t)(z >> 31); - } - return cc; -} - -/* - * Reduce a big integer d modulo a small integer p. - * Rules: - * d is unsigned - * p is prime - * 2^30 < p < 2^31 - * p0i = -(1/p) mod 2^31 - * R2 = 2^62 mod p - */ -static uint32_t -zint_mod_small_unsigned(const uint32_t *d, size_t dlen, - uint32_t p, uint32_t p0i, uint32_t R2) -{ - uint32_t x; - size_t u; - - /* - * Algorithm: we inject words one by one, starting with the high - * word. Each step is: - * - multiply x by 2^31 - * - add new word - */ - x = 0; - u = dlen; - while (u -- > 0) { - uint32_t w; - - x = modp_montymul(x, R2, p, p0i); - w = d[u] - p; - w += p & -(w >> 31); - x = modp_add(x, w, p); - } - return x; -} - -/* - * Similar to zint_mod_small_unsigned(), except that d may be signed. - * Extra parameter is Rx = 2^(31*dlen) mod p. - */ -static uint32_t -zint_mod_small_signed(const uint32_t *d, size_t dlen, - uint32_t p, uint32_t p0i, uint32_t R2, uint32_t Rx) -{ - uint32_t z; - - if (dlen == 0) { - return 0; - } - z = zint_mod_small_unsigned(d, dlen, p, p0i, R2); - z = modp_sub(z, Rx & -(d[dlen - 1] >> 30), p); - return z; -} - -/* - * Add y*s to x. x and y initially have length 'len' words; the new x - * has length 'len+1' words. 's' must fit on 31 bits. x[] and y[] must - * not overlap. - */ -static void -zint_add_mul_small(uint32_t *restrict x, - const uint32_t *restrict y, size_t len, uint32_t s) -{ - size_t u; - uint32_t cc; - - cc = 0; - for (u = 0; u < len; u ++) { - uint32_t xw, yw; - uint64_t z; - - xw = x[u]; - yw = y[u]; - z = (uint64_t)yw * (uint64_t)s + (uint64_t)xw + (uint64_t)cc; - x[u] = (uint32_t)z & 0x7FFFFFFF; - cc = (uint32_t)(z >> 31); - } - x[len] = cc; -} - -/* - * Normalize a modular integer around 0: if x > p/2, then x is replaced - * with x - p (signed encoding with two's complement); otherwise, x is - * untouched. The two integers x and p are encoded over the same length. - */ -static void -zint_norm_zero(uint32_t *restrict x, const uint32_t *restrict p, size_t len) -{ - size_t u; - uint32_t r, bb; - - /* - * Compare x with p/2. We use the shifted version of p, and p - * is odd, so we really compare with (p-1)/2; we want to perform - * the subtraction if and only if x > (p-1)/2. - */ - r = 0; - bb = 0; - u = len; - while (u -- > 0) { - uint32_t wx, wp, cc; - - /* - * Get the two words to compare in wx and wp (both over - * 31 bits exactly). - */ - wx = x[u]; - wp = (p[u] >> 1) | (bb << 30); - bb = p[u] & 1; - - /* - * We set cc to -1, 0 or 1, depending on whether wp is - * lower than, equal to, or greater than wx. - */ - cc = wp - wx; - cc = ((-cc) >> 31) | -(cc >> 31); - - /* - * If r != 0 then it is either 1 or -1, and we keep its - * value. Otherwise, if r = 0, then we replace it with cc. - */ - r |= cc & ((r & 1) - 1); - } - - /* - * At this point, r = -1, 0 or 1, depending on whether (p-1)/2 - * is lower than, equal to, or greater than x. We thus want to - * do the subtraction only if r = -1. - */ - zint_sub(x, p, len, r >> 31); -} - -/* - * Rebuild integers from their RNS representation. There are 'num' - * integers, and each consists in 'xlen' words. 'xx' points at that - * first word of the first integer; subsequent integers are accessed - * by adding 'xstride' repeatedly. - * - * The words of an integer are the RNS representation of that integer, - * using the provided 'primes' are moduli. This function replaces - * each integer with its multi-word value (little-endian order). - * - * If "normalize_signed" is non-zero, then the returned value is - * normalized to the -m/2..m/2 interval (where m is the product of all - * small prime moduli); two's complement is used for negative values. - */ -static void -zint_rebuild_CRT(uint32_t *restrict xx, size_t xlen, size_t xstride, - size_t num, const small_prime *primes, int normalize_signed, - uint32_t *restrict tmp) -{ - size_t u; - uint32_t *x; - - tmp[0] = primes[0].p; - for (u = 1; u < xlen; u ++) { - /* - * At the entry of each loop iteration: - * - the first u words of each array have been - * reassembled; - * - the first u words of tmp[] contains the - * product of the prime moduli processed so far. - * - * We call 'q' the product of all previous primes. - */ - uint32_t p, p0i, s, R2; - size_t v; - - p = primes[u].p; - s = primes[u].s; - p0i = modp_ninv31(p); - R2 = modp_R2(p, p0i); - - for (v = 0, x = xx; v < num; v ++, x += xstride) { - uint32_t xp, xq, xr; - /* - * xp = the integer x modulo the prime p for this - * iteration - * xq = (x mod q) mod p - */ - xp = x[u]; - xq = zint_mod_small_unsigned(x, u, p, p0i, R2); - - /* - * New value is (x mod q) + q * (s * (xp - xq) mod p) - */ - xr = modp_montymul(s, modp_sub(xp, xq, p), p, p0i); - zint_add_mul_small(x, tmp, u, xr); - } - - /* - * Update product of primes in tmp[]. - */ - tmp[u] = zint_mul_small(tmp, u, p); - } - - /* - * Normalize the reconstructed values around 0. - */ - if (normalize_signed) { - for (u = 0, x = xx; u < num; u ++, x += xstride) { - zint_norm_zero(x, tmp, xlen); - } - } -} - -/* - * Negate a big integer conditionally: value a is replaced with -a if - * and only if ctl = 1. Control value ctl must be 0 or 1. - */ -static void -zint_negate(uint32_t *a, size_t len, uint32_t ctl) -{ - size_t u; - uint32_t cc, m; - - /* - * If ctl = 1 then we flip the bits of a by XORing with - * 0x7FFFFFFF, and we add 1 to the value. If ctl = 0 then we XOR - * with 0 and add 0, which leaves the value unchanged. - */ - cc = ctl; - m = -ctl >> 1; - for (u = 0; u < len; u ++) { - uint32_t aw; - - aw = a[u]; - aw = (aw ^ m) + cc; - a[u] = aw & 0x7FFFFFFF; - cc = aw >> 31; - } -} - -/* - * Replace a with (a*xa+b*xb)/(2^31) and b with (a*ya+b*yb)/(2^31). - * The low bits are dropped (the caller should compute the coefficients - * such that these dropped bits are all zeros). If either or both - * yields a negative value, then the value is negated. - * - * Returned value is: - * 0 both values were positive - * 1 new a had to be negated - * 2 new b had to be negated - * 3 both new a and new b had to be negated - * - * Coefficients xa, xb, ya and yb may use the full signed 32-bit range. - */ -static uint32_t -zint_co_reduce(uint32_t *a, uint32_t *b, size_t len, - int64_t xa, int64_t xb, int64_t ya, int64_t yb) -{ - size_t u; - int64_t cca, ccb; - uint32_t nega, negb; - - cca = 0; - ccb = 0; - for (u = 0; u < len; u ++) { - uint32_t wa, wb; - uint64_t za, zb; - - wa = a[u]; - wb = b[u]; - za = wa * (uint64_t)xa + wb * (uint64_t)xb + (uint64_t)cca; - zb = wa * (uint64_t)ya + wb * (uint64_t)yb + (uint64_t)ccb; - if (u > 0) { - a[u - 1] = (uint32_t)za & 0x7FFFFFFF; - b[u - 1] = (uint32_t)zb & 0x7FFFFFFF; - } - cca = *(int64_t *)&za >> 31; - ccb = *(int64_t *)&zb >> 31; - } - a[len - 1] = (uint32_t)cca; - b[len - 1] = (uint32_t)ccb; - - nega = (uint32_t)((uint64_t)cca >> 63); - negb = (uint32_t)((uint64_t)ccb >> 63); - zint_negate(a, len, nega); - zint_negate(b, len, negb); - return nega | (negb << 1); -} - -/* - * Finish modular reduction. Rules on input parameters: - * - * if neg = 1, then -m <= a < 0 - * if neg = 0, then 0 <= a < 2*m - * - * If neg = 0, then the top word of a[] is allowed to use 32 bits. - * - * Modulus m must be odd. - */ -static void -zint_finish_mod(uint32_t *a, size_t len, const uint32_t *m, uint32_t neg) -{ - size_t u; - uint32_t cc, xm, ym; - - /* - * First pass: compare a (assumed nonnegative) with m. Note that - * if the top word uses 32 bits, subtracting m must yield a - * value less than 2^31 since a < 2*m. - */ - cc = 0; - for (u = 0; u < len; u ++) { - cc = (a[u] - m[u] - cc) >> 31; - } - - /* - * If neg = 1 then we must add m (regardless of cc) - * If neg = 0 and cc = 0 then we must subtract m - * If neg = 0 and cc = 1 then we must do nothing - * - * In the loop below, we conditionally subtract either m or -m - * from a. Word xm is a word of m (if neg = 0) or -m (if neg = 1); - * but if neg = 0 and cc = 1, then ym = 0 and it forces mw to 0. - */ - xm = -neg >> 1; - ym = -(neg | (1 - cc)); - cc = neg; - for (u = 0; u < len; u ++) { - uint32_t aw, mw; - - aw = a[u]; - mw = (m[u] ^ xm) & ym; - aw = aw - mw - cc; - a[u] = aw & 0x7FFFFFFF; - cc = aw >> 31; - } -} - -/* - * Replace a with (a*xa+b*xb)/(2^31) mod m, and b with - * (a*ya+b*yb)/(2^31) mod m. Modulus m must be odd; m0i = -1/m[0] mod 2^31. - */ -static void -zint_co_reduce_mod(uint32_t *a, uint32_t *b, const uint32_t *m, size_t len, - uint32_t m0i, int64_t xa, int64_t xb, int64_t ya, int64_t yb) -{ - size_t u; - int64_t cca, ccb; - uint32_t fa, fb; - - /* - * These are actually four combined Montgomery multiplications. - */ - cca = 0; - ccb = 0; - fa = ((a[0] * (uint32_t)xa + b[0] * (uint32_t)xb) * m0i) & 0x7FFFFFFF; - fb = ((a[0] * (uint32_t)ya + b[0] * (uint32_t)yb) * m0i) & 0x7FFFFFFF; - for (u = 0; u < len; u ++) { - uint32_t wa, wb; - uint64_t za, zb; - - wa = a[u]; - wb = b[u]; - za = wa * (uint64_t)xa + wb * (uint64_t)xb - + m[u] * (uint64_t)fa + (uint64_t)cca; - zb = wa * (uint64_t)ya + wb * (uint64_t)yb - + m[u] * (uint64_t)fb + (uint64_t)ccb; - if (u > 0) { - a[u - 1] = (uint32_t)za & 0x7FFFFFFF; - b[u - 1] = (uint32_t)zb & 0x7FFFFFFF; - } - cca = *(int64_t *)&za >> 31; - ccb = *(int64_t *)&zb >> 31; - } - a[len - 1] = (uint32_t)cca; - b[len - 1] = (uint32_t)ccb; - - /* - * At this point: - * -m <= a < 2*m - * -m <= b < 2*m - * (this is a case of Montgomery reduction) - * The top words of 'a' and 'b' may have a 32-th bit set. - * We want to add or subtract the modulus, as required. - */ - zint_finish_mod(a, len, m, (uint32_t)((uint64_t)cca >> 63)); - zint_finish_mod(b, len, m, (uint32_t)((uint64_t)ccb >> 63)); -} - -/* - * Compute a GCD between two positive big integers x and y. The two - * integers must be odd. Returned value is 1 if the GCD is 1, 0 - * otherwise. When 1 is returned, arrays u and v are filled with values - * such that: - * 0 <= u <= y - * 0 <= v <= x - * x*u - y*v = 1 - * x[] and y[] are unmodified. Both input values must have the same - * encoded length. Temporary array must be large enough to accommodate 4 - * extra values of that length. Arrays u, v and tmp may not overlap with - * each other, or with either x or y. - */ -static int -zint_bezout(uint32_t *restrict u, uint32_t *restrict v, - const uint32_t *restrict x, const uint32_t *restrict y, - size_t len, uint32_t *restrict tmp) -{ - /* - * Algorithm is an extended binary GCD. We maintain 6 values - * a, b, u0, u1, v0 and v1 with the following invariants: - * - * a = x*u0 - y*v0 - * b = x*u1 - y*v1 - * 0 <= a <= x - * 0 <= b <= y - * 0 <= u0 < y - * 0 <= v0 < x - * 0 <= u1 <= y - * 0 <= v1 < x - * - * Initial values are: - * - * a = x u0 = 1 v0 = 0 - * b = y u1 = y v1 = x-1 - * - * Each iteration reduces either a or b, and maintains the - * invariants. Algorithm stops when a = b, at which point their - * common value is GCD(a,b) and (u0,v0) (or (u1,v1)) contains - * the values (u,v) we want to return. - * - * The formal definition of the algorithm is a sequence of steps: - * - * - If a is even, then: - * a <- a/2 - * u0 <- u0/2 mod y - * v0 <- v0/2 mod x - * - * - Otherwise, if b is even, then: - * b <- b/2 - * u1 <- u1/2 mod y - * v1 <- v1/2 mod x - * - * - Otherwise, if a > b, then: - * a <- (a-b)/2 - * u0 <- (u0-u1)/2 mod y - * v0 <- (v0-v1)/2 mod x - * - * - Otherwise: - * b <- (b-a)/2 - * u1 <- (u1-u0)/2 mod y - * v1 <- (v1-v0)/2 mod y - * - * We can show that the operations above preserve the invariants: - * - * - If a is even, then u0 and v0 are either both even or both - * odd (since a = x*u0 - y*v0, and x and y are both odd). - * If u0 and v0 are both even, then (u0,v0) <- (u0/2,v0/2). - * Otherwise, (u0,v0) <- ((u0+y)/2,(v0+x)/2). Either way, - * the a = x*u0 - y*v0 invariant is preserved. - * - * - The same holds for the case where b is even. - * - * - If a and b are odd, and a > b, then: - * - * a-b = x*(u0-u1) - y*(v0-v1) - * - * In that situation, if u0 < u1, then x*(u0-u1) < 0, but - * a-b > 0; therefore, it must be that v0 < v1, and the - * first part of the update is: (u0,v0) <- (u0-u1+y,v0-v1+x), - * which preserves the invariants. Otherwise, if u0 > u1, - * then u0-u1 >= 1, thus x*(u0-u1) >= x. But a <= x and - * b >= 0, hence a-b <= x. It follows that, in that case, - * v0-v1 >= 0. The first part of the update is then: - * (u0,v0) <- (u0-u1,v0-v1), which again preserves the - * invariants. - * - * Either way, once the subtraction is done, the new value of - * a, which is the difference of two odd values, is even, - * and the remaining of this step is a subcase of the - * first algorithm case (i.e. when a is even). - * - * - If a and b are odd, and b > a, then the a similar - * argument holds. - * - * The values a and b start at x and y, respectively. Since x - * and y are odd, their GCD is odd, and it is easily seen that - * all steps conserve the GCD (GCD(a-b,b) = GCD(a, b); - * GCD(a/2,b) = GCD(a,b) if GCD(a,b) is odd). Moreover, either a - * or b is reduced by at least one bit at each iteration, so - * the algorithm necessarily converges on the case a = b, at - * which point the common value is the GCD. - * - * In the algorithm expressed above, when a = b, the fourth case - * applies, and sets b = 0. Since a contains the GCD of x and y, - * which are both odd, a must be odd, and subsequent iterations - * (if any) will simply divide b by 2 repeatedly, which has no - * consequence. Thus, the algorithm can run for more iterations - * than necessary; the final GCD will be in a, and the (u,v) - * coefficients will be (u0,v0). - * - * - * The presentation above is bit-by-bit. It can be sped up by - * noticing that all decisions are taken based on the low bits - * and high bits of a and b. We can extract the two top words - * and low word of each of a and b, and compute reduction - * parameters pa, pb, qa and qb such that the new values for - * a and b are: - * a' = (a*pa + b*pb) / (2^31) - * b' = (a*qa + b*qb) / (2^31) - * the two divisions being exact. The coefficients are obtained - * just from the extracted words, and may be slightly off, requiring - * an optional correction: if a' < 0, then we replace pa with -pa - * and pb with -pb. Each such step will reduce the total length - * (sum of lengths of a and b) by at least 30 bits at each - * iteration. - */ - uint32_t *u0, *u1, *v0, *v1, *a, *b; - uint32_t x0i, y0i; - uint32_t num, rc; - size_t j; - - if (len == 0) { - return 0; - } - - /* - * u0 and v0 are the u and v result buffers; the four other - * values (u1, v1, a and b) are taken from tmp[]. - */ - u0 = u; - v0 = v; - u1 = tmp; - v1 = u1 + len; - a = v1 + len; - b = a + len; - - /* - * We'll need the Montgomery reduction coefficients. - */ - x0i = modp_ninv31(x[0]); - y0i = modp_ninv31(y[0]); - - /* - * Initialize a, b, u0, u1, v0 and v1. - * a = x u0 = 1 v0 = 0 - * b = y u1 = y v1 = x-1 - * Note that x is odd, so computing x-1 is easy. - */ - memcpy(a, x, len * sizeof *x); - memcpy(b, y, len * sizeof *y); - u0[0] = 1; - memset(u0 + 1, 0, (len - 1) * sizeof *u0); - memset(v0, 0, len * sizeof *v0); - memcpy(u1, y, len * sizeof *u1); - memcpy(v1, x, len * sizeof *v1); - v1[0] --; - - /* - * Each input operand may be as large as 31*len bits, and we - * reduce the total length by at least 30 bits at each iteration. - */ - for (num = 62 * (uint32_t)len + 30; num >= 30; num -= 30) { - uint32_t c0, c1; - uint32_t a0, a1, b0, b1; - uint64_t a_hi, b_hi; - uint32_t a_lo, b_lo; - int64_t pa, pb, qa, qb; - int i; - uint32_t r; - - /* - * Extract the top words of a and b. If j is the highest - * index >= 1 such that a[j] != 0 or b[j] != 0, then we - * want (a[j] << 31) + a[j-1] and (b[j] << 31) + b[j-1]. - * If a and b are down to one word each, then we use - * a[0] and b[0]. - */ - c0 = (uint32_t)-1; - c1 = (uint32_t)-1; - a0 = 0; - a1 = 0; - b0 = 0; - b1 = 0; - j = len; - while (j -- > 0) { - uint32_t aw, bw; - - aw = a[j]; - bw = b[j]; - a0 ^= (a0 ^ aw) & c0; - a1 ^= (a1 ^ aw) & c1; - b0 ^= (b0 ^ bw) & c0; - b1 ^= (b1 ^ bw) & c1; - c1 = c0; - c0 &= (((aw | bw) + 0x7FFFFFFF) >> 31) - (uint32_t)1; - } - - /* - * If c1 = 0, then we grabbed two words for a and b. - * If c1 != 0 but c0 = 0, then we grabbed one word. It - * is not possible that c1 != 0 and c0 != 0, because that - * would mean that both integers are zero. - */ - a1 |= a0 & c1; - a0 &= ~c1; - b1 |= b0 & c1; - b0 &= ~c1; - a_hi = ((uint64_t)a0 << 31) + a1; - b_hi = ((uint64_t)b0 << 31) + b1; - a_lo = a[0]; - b_lo = b[0]; - - /* - * Compute reduction factors: - * - * a' = a*pa + b*pb - * b' = a*qa + b*qb - * - * such that a' and b' are both multiple of 2^31, but are - * only marginally larger than a and b. - */ - pa = 1; - pb = 0; - qa = 0; - qb = 1; - for (i = 0; i < 31; i ++) { - /* - * At each iteration: - * - * a <- (a-b)/2 if: a is odd, b is odd, a_hi > b_hi - * b <- (b-a)/2 if: a is odd, b is odd, a_hi <= b_hi - * a <- a/2 if: a is even - * b <- b/2 if: a is odd, b is even - * - * We multiply a_lo and b_lo by 2 at each - * iteration, thus a division by 2 really is a - * non-multiplication by 2. - */ - uint32_t rt, oa, ob, cAB, cBA, cA; - uint64_t rz; - - /* - * rt = 1 if a_hi > b_hi, 0 otherwise. - */ - rz = b_hi - a_hi; - rt = (uint32_t)((rz ^ ((a_hi ^ b_hi) - & (a_hi ^ rz))) >> 63); - - /* - * cAB = 1 if b must be subtracted from a - * cBA = 1 if a must be subtracted from b - * cA = 1 if a must be divided by 2 - * - * Rules: - * - * cAB and cBA cannot both be 1. - * If a is not divided by 2, b is. - */ - oa = (a_lo >> i) & 1; - ob = (b_lo >> i) & 1; - cAB = oa & ob & rt; - cBA = oa & ob & ~rt; - cA = cAB | (oa ^ 1); - - /* - * Conditional subtractions. - */ - a_lo -= b_lo & -cAB; - a_hi -= b_hi & -(uint64_t)cAB; - pa -= qa & -(int64_t)cAB; - pb -= qb & -(int64_t)cAB; - b_lo -= a_lo & -cBA; - b_hi -= a_hi & -(uint64_t)cBA; - qa -= pa & -(int64_t)cBA; - qb -= pb & -(int64_t)cBA; - - /* - * Shifting. - */ - a_lo += a_lo & (cA - 1); - pa += pa & ((int64_t)cA - 1); - pb += pb & ((int64_t)cA - 1); - a_hi ^= (a_hi ^ (a_hi >> 1)) & -(uint64_t)cA; - b_lo += b_lo & -cA; - qa += qa & -(int64_t)cA; - qb += qb & -(int64_t)cA; - b_hi ^= (b_hi ^ (b_hi >> 1)) & ((uint64_t)cA - 1); - } - - /* - * Apply the computed parameters to our values. We - * may have to correct pa and pb depending on the - * returned value of zint_co_reduce() (when a and/or b - * had to be negated). - */ - r = zint_co_reduce(a, b, len, pa, pb, qa, qb); - pa -= (pa + pa) & -(int64_t)(r & 1); - pb -= (pb + pb) & -(int64_t)(r & 1); - qa -= (qa + qa) & -(int64_t)(r >> 1); - qb -= (qb + qb) & -(int64_t)(r >> 1); - zint_co_reduce_mod(u0, u1, y, len, y0i, pa, pb, qa, qb); - zint_co_reduce_mod(v0, v1, x, len, x0i, pa, pb, qa, qb); - } - - /* - * At that point, array a[] should contain the GCD, and the - * results (u,v) should already be set. We check that the GCD - * is indeed 1. We also check that the two operands x and y - * are odd. - */ - rc = a[0] ^ 1; - for (j = 1; j < len; j ++) { - rc |= a[j]; - } - return (int)((1 - ((rc | -rc) >> 31)) & x[0] & y[0]); -} - -/* - * Add k*y*2^sc to x. The result is assumed to fit in the array of - * size xlen (truncation is applied if necessary). - * Scale factor 'sc' is provided as sch and scl, such that: - * sch = sc / 31 - * scl = sc % 31 - * xlen MUST NOT be lower than ylen. - * - * x[] and y[] are both signed integers, using two's complement for - * negative values. - */ -static void -zint_add_scaled_mul_small(uint32_t *restrict x, size_t xlen, - const uint32_t *restrict y, size_t ylen, int32_t k, - uint32_t sch, uint32_t scl) -{ - size_t u; - uint32_t ysign, tw; - int32_t cc; - - if (ylen == 0) { - return; - } - - ysign = -(y[ylen - 1] >> 30) >> 1; - tw = 0; - cc = 0; - for (u = sch; u < xlen; u ++) { - size_t v; - uint32_t wy, wys, ccu; - uint64_t z; - - /* - * Get the next word of y (scaled). - */ - v = u - sch; - wy = v < ylen ? y[v] : ysign; - wys = ((wy << scl) & 0x7FFFFFFF) | tw; - tw = wy >> (31 - scl); - - /* - * The expression below does not overflow. - */ - z = (uint64_t)((int64_t)wys * (int64_t)k + (int64_t)x[u] + cc); - x[u] = (uint32_t)z & 0x7FFFFFFF; - - /* - * Right-shifting the signed value z would yield - * implementation-defined results (arithmetic shift is - * not guaranteed). However, we can cast to unsigned, - * and get the next carry as an unsigned word. We can - * then convert it back to signed by using the guaranteed - * fact that 'int32_t' uses two's complement with no - * trap representation or padding bit, and with a layout - * compatible with that of 'uint32_t'. - */ - ccu = (uint32_t)(z >> 31); - cc = *(int32_t *)&ccu; - } -} - -/* - * Subtract y*2^sc from x. The result is assumed to fit in the array of - * size xlen (truncation is applied if necessary). - * Scale factor 'sc' is provided as sch and scl, such that: - * sch = sc / 31 - * scl = sc % 31 - * xlen MUST NOT be lower than ylen. - * - * x[] and y[] are both signed integers, using two's complement for - * negative values. - */ -static void -zint_sub_scaled(uint32_t *restrict x, size_t xlen, - const uint32_t *restrict y, size_t ylen, uint32_t sch, uint32_t scl) -{ - size_t u; - uint32_t ysign, tw; - uint32_t cc; - - if (ylen == 0) { - return; - } - - ysign = -(y[ylen - 1] >> 30) >> 1; - tw = 0; - cc = 0; - for (u = sch; u < xlen; u ++) { - size_t v; - uint32_t w, wy, wys; - - /* - * Get the next word of y (scaled). - */ - v = u - sch; - wy = v < ylen ? y[v] : ysign; - wys = ((wy << scl) & 0x7FFFFFFF) | tw; - tw = wy >> (31 - scl); - - w = x[u] - wys - cc; - x[u] = w & 0x7FFFFFFF; - cc = w >> 31; - } -} - -/* - * Convert a one-word signed big integer into a signed value. - */ -static inline int32_t -zint_one_to_plain(const uint32_t *x) -{ - uint32_t w; - - w = x[0]; - w |= (w & 0x40000000) << 1; - return *(int32_t *)&w; -} - -/* ==================================================================== */ - -/* - * Convert a polynomial to floating-point values. - * - * Each coefficient has length flen words, and starts fstride words after - * the previous. - * - * IEEE-754 binary64 values can represent values in a finite range, - * roughly 2^(-1023) to 2^(+1023); thus, if coefficients are too large, - * they should be "trimmed" by pointing not to the lowest word of each, - * but upper. - */ -static void -poly_big_to_fp(fpr *d, const uint32_t *f, size_t flen, size_t fstride, - unsigned logn) -{ - size_t n, u; - - n = MKN(logn); - if (flen == 0) { - for (u = 0; u < n; u ++) { - d[u] = fpr_zero; - } - return; - } - for (u = 0; u < n; u ++, f += fstride) { - size_t v; - uint32_t neg, cc, xm; - fpr x, fsc; - - /* - * Get sign of the integer; if it is negative, then we - * will load its absolute value instead, and negate the - * result. - */ - neg = -(f[flen - 1] >> 30); - xm = neg >> 1; - cc = neg & 1; - x = fpr_zero; - fsc = fpr_one; - for (v = 0; v < flen; v ++, fsc = fpr_mul(fsc, fpr_ptwo31)) { - uint32_t w; - - w = (f[v] ^ xm) + cc; - cc = w >> 31; - w &= 0x7FFFFFFF; - w -= (w << 1) & neg; - x = fpr_add(x, fpr_mul(fpr_of(*(int32_t *)&w), fsc)); - } - d[u] = x; - } -} - -/* - * Convert a polynomial to small integers. Source values are supposed - * to be one-word integers, signed over 31 bits. Returned value is 0 - * if any of the coefficients exceeds the provided limit (in absolute - * value), or 1 on success. - * - * This is not constant-time; this is not a problem here, because on - * any failure, the NTRU-solving process will be deemed to have failed - * and the (f,g) polynomials will be discarded. - */ -static int -poly_big_to_small(int8_t *d, const uint32_t *s, int lim, unsigned logn) -{ - size_t n, u; - - n = MKN(logn); - for (u = 0; u < n; u ++) { - int32_t z; - - z = zint_one_to_plain(s + u); - if (z < -lim || z > lim) { - return 0; - } - d[u] = (int8_t)z; - } - return 1; -} - -/* - * Subtract k*f from F, where F, f and k are polynomials modulo X^N+1. - * Coefficients of polynomial k are small integers (signed values in the - * -2^31..2^31 range) scaled by 2^sc. Value sc is provided as sch = sc / 31 - * and scl = sc % 31. - * - * This function implements the basic quadratic multiplication algorithm, - * which is efficient in space (no extra buffer needed) but slow at - * high degree. - */ -static void -poly_sub_scaled(uint32_t *restrict F, size_t Flen, size_t Fstride, - const uint32_t *restrict f, size_t flen, size_t fstride, - const int32_t *restrict k, uint32_t sch, uint32_t scl, unsigned logn) -{ - size_t n, u; - - n = MKN(logn); - for (u = 0; u < n; u ++) { - int32_t kf; - size_t v; - uint32_t *x; - const uint32_t *y; - - kf = -k[u]; - x = F + u * Fstride; - y = f; - for (v = 0; v < n; v ++) { - zint_add_scaled_mul_small( - x, Flen, y, flen, kf, sch, scl); - if (u + v == n - 1) { - x = F; - kf = -kf; - } else { - x += Fstride; - } - y += fstride; - } - } -} - -/* - * Subtract k*f from F. Coefficients of polynomial k are small integers - * (signed values in the -2^31..2^31 range) scaled by 2^sc. This function - * assumes that the degree is large, and integers relatively small. - * The value sc is provided as sch = sc / 31 and scl = sc % 31. - */ -static void -poly_sub_scaled_ntt(uint32_t *restrict F, size_t Flen, size_t Fstride, - const uint32_t *restrict f, size_t flen, size_t fstride, - const int32_t *restrict k, uint32_t sch, uint32_t scl, unsigned logn, - uint32_t *restrict tmp) -{ - uint32_t *gm, *igm, *fk, *t1, *x; - const uint32_t *y; - size_t n, u, tlen; - const small_prime *primes; - - n = MKN(logn); - tlen = flen + 1; - gm = tmp; - igm = gm + MKN(logn); - fk = igm + MKN(logn); - t1 = fk + n * tlen; - - primes = PRIMES; - - /* - * Compute k*f in fk[], in RNS notation. - */ - for (u = 0; u < tlen; u ++) { - uint32_t p, p0i, R2, Rx; - size_t v; - - p = primes[u].p; - p0i = modp_ninv31(p); - R2 = modp_R2(p, p0i); - Rx = modp_Rx((unsigned)flen, p, p0i, R2); - modp_mkgm2(gm, igm, logn, primes[u].g, p, p0i); - - for (v = 0; v < n; v ++) { - t1[v] = modp_set(k[v], p); - } - modp_NTT2(t1, gm, logn, p, p0i); - for (v = 0, y = f, x = fk + u; - v < n; v ++, y += fstride, x += tlen) - { - *x = zint_mod_small_signed(y, flen, p, p0i, R2, Rx); - } - modp_NTT2_ext(fk + u, tlen, gm, logn, p, p0i); - for (v = 0, x = fk + u; v < n; v ++, x += tlen) { - *x = modp_montymul( - modp_montymul(t1[v], *x, p, p0i), R2, p, p0i); - } - modp_iNTT2_ext(fk + u, tlen, igm, logn, p, p0i); - } - - /* - * Rebuild k*f. - */ - zint_rebuild_CRT(fk, tlen, tlen, n, primes, 1, t1); - - /* - * Subtract k*f, scaled, from F. - */ - for (u = 0, x = F, y = fk; u < n; u ++, x += Fstride, y += tlen) { - zint_sub_scaled(x, Flen, y, tlen, sch, scl); - } -} - -/* ==================================================================== */ - -#if FALCON_KG_CHACHA20 // yyyKG_CHACHA20+1 - -#define RNG_CONTEXT prng -#define get_rng_u64 prng_get_u64 - -#else // yyyKG_CHACHA20+0 - -#define RNG_CONTEXT inner_shake256_context - -/* - * Get a random 8-byte integer from a SHAKE-based RNG. This function - * ensures consistent interpretation of the SHAKE output so that - * the same values will be obtained over different platforms, in case - * a known seed is used. - */ -static inline uint64_t -get_rng_u64(inner_shake256_context *rng) -{ - /* - * We enforce little-endian representation. - */ - -#if FALCON_LE // yyyLE+1 - /* - * On little-endian systems we just interpret the bytes "as is" - * (this is correct because the exact-width types such as - * 'uint64_t' are guaranteed to have no padding and no trap - * representation). - */ - uint64_t r; - - inner_shake256_extract(rng, (uint8_t *)&r, sizeof r); - return r; -#else // yyyLE+0 - uint8_t tmp[8]; - - inner_shake256_extract(rng, tmp, sizeof tmp); - return (uint64_t)tmp[0] - | ((uint64_t)tmp[1] << 8) - | ((uint64_t)tmp[2] << 16) - | ((uint64_t)tmp[3] << 24) - | ((uint64_t)tmp[4] << 32) - | ((uint64_t)tmp[5] << 40) - | ((uint64_t)tmp[6] << 48) - | ((uint64_t)tmp[7] << 56); -#endif // yyyLE- -} - -#endif // yyyKG_CHACHA20- - -/* - * Table below incarnates a discrete Gaussian distribution: - * D(x) = exp(-(x^2)/(2*sigma^2)) - * where sigma = 1.17*sqrt(q/(2*N)), q = 12289, and N = 1024. - * Element 0 of the table is P(x = 0). - * For k > 0, element k is P(x >= k+1 | x > 0). - * Probabilities are scaled up by 2^63. - */ -static const uint64_t gauss_1024_12289[] = { - 1283868770400643928u, 6416574995475331444u, 4078260278032692663u, - 2353523259288686585u, 1227179971273316331u, 575931623374121527u, - 242543240509105209u, 91437049221049666u, 30799446349977173u, - 9255276791179340u, 2478152334826140u, 590642893610164u, - 125206034929641u, 23590435911403u, 3948334035941u, - 586753615614u, 77391054539u, 9056793210u, - 940121950u, 86539696u, 7062824u, - 510971u, 32764u, 1862u, - 94u, 4u, 0u -}; - -/* - * Generate a random value with a Gaussian distribution centered on 0. - * The RNG must be ready for extraction (already flipped). - * - * Distribution has standard deviation 1.17*sqrt(q/(2*N)). The - * precomputed table is for N = 1024. Since the sum of two independent - * values of standard deviation sigma has standard deviation - * sigma*sqrt(2), then we can just generate more values and add them - * together for lower dimensions. - */ -static int -mkgauss(RNG_CONTEXT *rng, unsigned logn) -{ - unsigned u, g; - int val; - - g = 1U << (10 - logn); - val = 0; - for (u = 0; u < g; u ++) { - /* - * Each iteration generates one value with the - * Gaussian distribution for N = 1024. - * - * We use two random 64-bit values. First value - * decides on whether the generated value is 0, and, - * if not, the sign of the value. Second random 64-bit - * word is used to generate the non-zero value. - * - * For constant-time code we have to read the complete - * table. This has negligible cost, compared with the - * remainder of the keygen process (solving the NTRU - * equation). - */ - uint64_t r; - uint32_t f, v, k, neg; - - /* - * First value: - * - flag 'neg' is randomly selected to be 0 or 1. - * - flag 'f' is set to 1 if the generated value is zero, - * or set to 0 otherwise. - */ - r = get_rng_u64(rng); - neg = (uint32_t)(r >> 63); - r &= ~((uint64_t)1 << 63); - f = (uint32_t)((r - gauss_1024_12289[0]) >> 63); - - /* - * We produce a new random 63-bit integer r, and go over - * the array, starting at index 1. We store in v the - * index of the first array element which is not greater - * than r, unless the flag f was already 1. - */ - v = 0; - r = get_rng_u64(rng); - r &= ~((uint64_t)1 << 63); - for (k = 1; k < (sizeof gauss_1024_12289) - / (sizeof gauss_1024_12289[0]); k ++) - { - uint32_t t; - - t = (uint32_t)((r - gauss_1024_12289[k]) >> 63) ^ 1; - v |= k & -(t & (f ^ 1)); - f |= t; - } - - /* - * We apply the sign ('neg' flag). If the value is zero, - * the sign has no effect. - */ - v = (v ^ -neg) + neg; - - /* - * Generated value is added to val. - */ - val += *(int32_t *)&v; - } - return val; -} - -/* - * The MAX_BL_SMALL[] and MAX_BL_LARGE[] contain the lengths, in 31-bit - * words, of intermediate values in the computation: - * - * MAX_BL_SMALL[depth]: length for the input f and g at that depth - * MAX_BL_LARGE[depth]: length for the unreduced F and G at that depth - * - * Rules: - * - * - Within an array, values grow. - * - * - The 'SMALL' array must have an entry for maximum depth, corresponding - * to the size of values used in the binary GCD. There is no such value - * for the 'LARGE' array (the binary GCD yields already reduced - * coefficients). - * - * - MAX_BL_LARGE[depth] >= MAX_BL_SMALL[depth + 1]. - * - * - Values must be large enough to handle the common cases, with some - * margins. - * - * - Values must not be "too large" either because we will convert some - * integers into floating-point values by considering the top 10 words, - * i.e. 310 bits; hence, for values of length more than 10 words, we - * should take care to have the length centered on the expected size. - * - * The following average lengths, in bits, have been measured on thousands - * of random keys (fg = max length of the absolute value of coefficients - * of f and g at that depth; FG = idem for the unreduced F and G; for the - * maximum depth, F and G are the output of binary GCD, multiplied by q; - * for each value, the average and standard deviation are provided). - * - * Binary case: - * depth: 10 fg: 6307.52 (24.48) FG: 6319.66 (24.51) - * depth: 9 fg: 3138.35 (12.25) FG: 9403.29 (27.55) - * depth: 8 fg: 1576.87 ( 7.49) FG: 4703.30 (14.77) - * depth: 7 fg: 794.17 ( 4.98) FG: 2361.84 ( 9.31) - * depth: 6 fg: 400.67 ( 3.10) FG: 1188.68 ( 6.04) - * depth: 5 fg: 202.22 ( 1.87) FG: 599.81 ( 3.87) - * depth: 4 fg: 101.62 ( 1.02) FG: 303.49 ( 2.38) - * depth: 3 fg: 50.37 ( 0.53) FG: 153.65 ( 1.39) - * depth: 2 fg: 24.07 ( 0.25) FG: 78.20 ( 0.73) - * depth: 1 fg: 10.99 ( 0.08) FG: 39.82 ( 0.41) - * depth: 0 fg: 4.00 ( 0.00) FG: 19.61 ( 0.49) - * - * Integers are actually represented either in binary notation over - * 31-bit words (signed, using two's complement), or in RNS, modulo - * many small primes. These small primes are close to, but slightly - * lower than, 2^31. Use of RNS loses less than two bits, even for - * the largest values. - * - * IMPORTANT: if these values are modified, then the temporary buffer - * sizes (FALCON_KEYGEN_TEMP_*, in inner.h) must be recomputed - * accordingly. - */ - -static const size_t MAX_BL_SMALL[] = { - 1, 1, 2, 2, 4, 7, 14, 27, 53, 106, 209 -}; - -static const size_t MAX_BL_LARGE[] = { - 2, 2, 5, 7, 12, 21, 40, 78, 157, 308 -}; - -/* - * Average and standard deviation for the maximum size (in bits) of - * coefficients of (f,g), depending on depth. These values are used - * to compute bounds for Babai's reduction. - */ -static const struct { - int avg; - int std; -} BITLENGTH[] = { - { 4, 0 }, - { 11, 1 }, - { 24, 1 }, - { 50, 1 }, - { 102, 1 }, - { 202, 2 }, - { 401, 4 }, - { 794, 5 }, - { 1577, 8 }, - { 3138, 13 }, - { 6308, 25 } -}; - -/* - * Minimal recursion depth at which we rebuild intermediate values - * when reconstructing f and g. - */ -#define DEPTH_INT_FG 4 - -/* - * Compute squared norm of a short vector. Returned value is saturated to - * 2^32-1 if it is not lower than 2^31. - */ -static uint32_t -poly_small_sqnorm(const int8_t *f, unsigned logn) -{ - size_t n, u; - uint32_t s, ng; - - n = MKN(logn); - s = 0; - ng = 0; - for (u = 0; u < n; u ++) { - int32_t z; - - z = f[u]; - s += (uint32_t)(z * z); - ng |= s; - } - return s | -(ng >> 31); -} - -/* - * Align (upwards) the provided 'data' pointer with regards to 'base' - * so that the offset is a multiple of the size of 'fpr'. - */ -static fpr * -align_fpr(void *base, void *data) -{ - uint8_t *cb, *cd; - size_t k, km; - - cb = base; - cd = data; - k = (size_t)(cd - cb); - km = k % sizeof(fpr); - if (km) { - k += (sizeof(fpr)) - km; - } - return (fpr *)(cb + k); -} - -/* - * Align (upwards) the provided 'data' pointer with regards to 'base' - * so that the offset is a multiple of the size of 'uint32_t'. - */ -static uint32_t * -align_u32(void *base, void *data) -{ - uint8_t *cb, *cd; - size_t k, km; - - cb = base; - cd = data; - k = (size_t)(cd - cb); - km = k % sizeof(uint32_t); - if (km) { - k += (sizeof(uint32_t)) - km; - } - return (uint32_t *)(cb + k); -} - -/* - * Convert a small vector to floating point. - */ -static void -poly_small_to_fp(fpr *x, const int8_t *f, unsigned logn) -{ - size_t n, u; - - n = MKN(logn); - for (u = 0; u < n; u ++) { - x[u] = fpr_of(f[u]); - } -} - -/* - * Input: f,g of degree N = 2^logn; 'depth' is used only to get their - * individual length. - * - * Output: f',g' of degree N/2, with the length for 'depth+1'. - * - * Values are in RNS; input and/or output may also be in NTT. - */ -static void -make_fg_step(uint32_t *data, unsigned logn, unsigned depth, - int in_ntt, int out_ntt) -{ - size_t n, hn, u; - size_t slen, tlen; - uint32_t *fd, *gd, *fs, *gs, *gm, *igm, *t1; - const small_prime *primes; - - n = (size_t)1 << logn; - hn = n >> 1; - slen = MAX_BL_SMALL[depth]; - tlen = MAX_BL_SMALL[depth + 1]; - primes = PRIMES; - - /* - * Prepare room for the result. - */ - fd = data; - gd = fd + hn * tlen; - fs = gd + hn * tlen; - gs = fs + n * slen; - gm = gs + n * slen; - igm = gm + n; - t1 = igm + n; - memmove(fs, data, 2 * n * slen * sizeof *data); - - /* - * First slen words: we use the input values directly, and apply - * inverse NTT as we go. - */ - for (u = 0; u < slen; u ++) { - uint32_t p, p0i, R2; - size_t v; - uint32_t *x; - - p = primes[u].p; - p0i = modp_ninv31(p); - R2 = modp_R2(p, p0i); - modp_mkgm2(gm, igm, logn, primes[u].g, p, p0i); - - for (v = 0, x = fs + u; v < n; v ++, x += slen) { - t1[v] = *x; - } - if (!in_ntt) { - modp_NTT2(t1, gm, logn, p, p0i); - } - for (v = 0, x = fd + u; v < hn; v ++, x += tlen) { - uint32_t w0, w1; - - w0 = t1[(v << 1) + 0]; - w1 = t1[(v << 1) + 1]; - *x = modp_montymul( - modp_montymul(w0, w1, p, p0i), R2, p, p0i); - } - if (in_ntt) { - modp_iNTT2_ext(fs + u, slen, igm, logn, p, p0i); - } - - for (v = 0, x = gs + u; v < n; v ++, x += slen) { - t1[v] = *x; - } - if (!in_ntt) { - modp_NTT2(t1, gm, logn, p, p0i); - } - for (v = 0, x = gd + u; v < hn; v ++, x += tlen) { - uint32_t w0, w1; - - w0 = t1[(v << 1) + 0]; - w1 = t1[(v << 1) + 1]; - *x = modp_montymul( - modp_montymul(w0, w1, p, p0i), R2, p, p0i); - } - if (in_ntt) { - modp_iNTT2_ext(gs + u, slen, igm, logn, p, p0i); - } - - if (!out_ntt) { - modp_iNTT2_ext(fd + u, tlen, igm, logn - 1, p, p0i); - modp_iNTT2_ext(gd + u, tlen, igm, logn - 1, p, p0i); - } - } - - /* - * Since the fs and gs words have been de-NTTized, we can use the - * CRT to rebuild the values. - */ - zint_rebuild_CRT(fs, slen, slen, n, primes, 1, gm); - zint_rebuild_CRT(gs, slen, slen, n, primes, 1, gm); - - /* - * Remaining words: use modular reductions to extract the values. - */ - for (u = slen; u < tlen; u ++) { - uint32_t p, p0i, R2, Rx; - size_t v; - uint32_t *x; - - p = primes[u].p; - p0i = modp_ninv31(p); - R2 = modp_R2(p, p0i); - Rx = modp_Rx((unsigned)slen, p, p0i, R2); - modp_mkgm2(gm, igm, logn, primes[u].g, p, p0i); - for (v = 0, x = fs; v < n; v ++, x += slen) { - t1[v] = zint_mod_small_signed(x, slen, p, p0i, R2, Rx); - } - modp_NTT2(t1, gm, logn, p, p0i); - for (v = 0, x = fd + u; v < hn; v ++, x += tlen) { - uint32_t w0, w1; - - w0 = t1[(v << 1) + 0]; - w1 = t1[(v << 1) + 1]; - *x = modp_montymul( - modp_montymul(w0, w1, p, p0i), R2, p, p0i); - } - for (v = 0, x = gs; v < n; v ++, x += slen) { - t1[v] = zint_mod_small_signed(x, slen, p, p0i, R2, Rx); - } - modp_NTT2(t1, gm, logn, p, p0i); - for (v = 0, x = gd + u; v < hn; v ++, x += tlen) { - uint32_t w0, w1; - - w0 = t1[(v << 1) + 0]; - w1 = t1[(v << 1) + 1]; - *x = modp_montymul( - modp_montymul(w0, w1, p, p0i), R2, p, p0i); - } - - if (!out_ntt) { - modp_iNTT2_ext(fd + u, tlen, igm, logn - 1, p, p0i); - modp_iNTT2_ext(gd + u, tlen, igm, logn - 1, p, p0i); - } - } -} - -/* - * Compute f and g at a specific depth, in RNS notation. - * - * Returned values are stored in the data[] array, at slen words per integer. - * - * Conditions: - * 0 <= depth <= logn - * - * Space use in data[]: enough room for any two successive values (f', g', - * f and g). - */ -static void -make_fg(uint32_t *data, const int8_t *f, const int8_t *g, - unsigned logn, unsigned depth, int out_ntt) -{ - size_t n, u; - uint32_t *ft, *gt, p0; - unsigned d; - const small_prime *primes; - - n = MKN(logn); - ft = data; - gt = ft + n; - primes = PRIMES; - p0 = primes[0].p; - for (u = 0; u < n; u ++) { - ft[u] = modp_set(f[u], p0); - gt[u] = modp_set(g[u], p0); - } - - if (depth == 0 && out_ntt) { - uint32_t *gm, *igm; - uint32_t p, p0i; - - p = primes[0].p; - p0i = modp_ninv31(p); - gm = gt + n; - igm = gm + MKN(logn); - modp_mkgm2(gm, igm, logn, primes[0].g, p, p0i); - modp_NTT2(ft, gm, logn, p, p0i); - modp_NTT2(gt, gm, logn, p, p0i); - return; - } - - for (d = 0; d < depth; d ++) { - make_fg_step(data, logn - d, d, - d != 0, (d + 1) < depth || out_ntt); - } -} - -/* - * Solving the NTRU equation, deepest level: compute the resultants of - * f and g with X^N+1, and use binary GCD. The F and G values are - * returned in tmp[]. - * - * Returned value: 1 on success, 0 on error. - */ -static int -solve_NTRU_deepest(unsigned logn_top, - const int8_t *f, const int8_t *g, uint32_t *tmp) -{ - size_t len; - uint32_t *Fp, *Gp, *fp, *gp, *t1, q; - const small_prime *primes; - - len = MAX_BL_SMALL[logn_top]; - primes = PRIMES; - - Fp = tmp; - Gp = Fp + len; - fp = Gp + len; - gp = fp + len; - t1 = gp + len; - - make_fg(fp, f, g, logn_top, logn_top, 0); - - /* - * We use the CRT to rebuild the resultants as big integers. - * There are two such big integers. The resultants are always - * nonnegative. - */ - zint_rebuild_CRT(fp, len, len, 2, primes, 0, t1); - - /* - * Apply the binary GCD. The zint_bezout() function works only - * if both inputs are odd. - * - * We can test on the result and return 0 because that would - * imply failure of the NTRU solving equation, and the (f,g) - * values will be abandoned in that case. - */ - if (!zint_bezout(Gp, Fp, fp, gp, len, t1)) { - return 0; - } - - /* - * Multiply the two values by the target value q. Values must - * fit in the destination arrays. - * We can again test on the returned words: a non-zero output - * of zint_mul_small() means that we exceeded our array - * capacity, and that implies failure and rejection of (f,g). - */ - q = 12289; - if (zint_mul_small(Fp, len, q) != 0 - || zint_mul_small(Gp, len, q) != 0) - { - return 0; - } - - return 1; -} - -/* - * Solving the NTRU equation, intermediate level. Upon entry, the F and G - * from the previous level should be in the tmp[] array. - * This function MAY be invoked for the top-level (in which case depth = 0). - * - * Returned value: 1 on success, 0 on error. - */ -static int -solve_NTRU_intermediate(unsigned logn_top, - const int8_t *f, const int8_t *g, unsigned depth, uint32_t *tmp) -{ - /* - * In this function, 'logn' is the log2 of the degree for - * this step. If N = 2^logn, then: - * - the F and G values already in fk->tmp (from the deeper - * levels) have degree N/2; - * - this function should return F and G of degree N. - */ - unsigned logn; - size_t n, hn, slen, dlen, llen, rlen, FGlen, u; - uint32_t *Fd, *Gd, *Ft, *Gt, *ft, *gt, *t1; - fpr *rt1, *rt2, *rt3, *rt4, *rt5; - int scale_fg, minbl_fg, maxbl_fg, maxbl_FG, scale_k; - uint32_t *x, *y; - int32_t *k; - const small_prime *primes; - - logn = logn_top - depth; - n = (size_t)1 << logn; - hn = n >> 1; - - /* - * slen = size for our input f and g; also size of the reduced - * F and G we return (degree N) - * - * dlen = size of the F and G obtained from the deeper level - * (degree N/2 or N/3) - * - * llen = size for intermediary F and G before reduction (degree N) - * - * We build our non-reduced F and G as two independent halves each, - * of degree N/2 (F = F0 + X*F1, G = G0 + X*G1). - */ - slen = MAX_BL_SMALL[depth]; - dlen = MAX_BL_SMALL[depth + 1]; - llen = MAX_BL_LARGE[depth]; - primes = PRIMES; - - /* - * Fd and Gd are the F and G from the deeper level. - */ - Fd = tmp; - Gd = Fd + dlen * hn; - - /* - * Compute the input f and g for this level. Note that we get f - * and g in RNS + NTT representation. - */ - ft = Gd + dlen * hn; - make_fg(ft, f, g, logn_top, depth, 1); - - /* - * Move the newly computed f and g to make room for our candidate - * F and G (unreduced). - */ - Ft = tmp; - Gt = Ft + n * llen; - t1 = Gt + n * llen; - memmove(t1, ft, 2 * n * slen * sizeof *ft); - ft = t1; - gt = ft + slen * n; - t1 = gt + slen * n; - - /* - * Move Fd and Gd _after_ f and g. - */ - memmove(t1, Fd, 2 * hn * dlen * sizeof *Fd); - Fd = t1; - Gd = Fd + hn * dlen; - - /* - * We reduce Fd and Gd modulo all the small primes we will need, - * and store the values in Ft and Gt (only n/2 values in each). - */ - for (u = 0; u < llen; u ++) { - uint32_t p, p0i, R2, Rx; - size_t v; - uint32_t *xs, *ys, *xd, *yd; - - p = primes[u].p; - p0i = modp_ninv31(p); - R2 = modp_R2(p, p0i); - Rx = modp_Rx((unsigned)dlen, p, p0i, R2); - for (v = 0, xs = Fd, ys = Gd, xd = Ft + u, yd = Gt + u; - v < hn; - v ++, xs += dlen, ys += dlen, xd += llen, yd += llen) - { - *xd = zint_mod_small_signed(xs, dlen, p, p0i, R2, Rx); - *yd = zint_mod_small_signed(ys, dlen, p, p0i, R2, Rx); - } - } - - /* - * We do not need Fd and Gd after that point. - */ - - /* - * Compute our F and G modulo sufficiently many small primes. - */ - for (u = 0; u < llen; u ++) { - uint32_t p, p0i, R2; - uint32_t *gm, *igm, *fx, *gx, *Fp, *Gp; - size_t v; - - /* - * All computations are done modulo p. - */ - p = primes[u].p; - p0i = modp_ninv31(p); - R2 = modp_R2(p, p0i); - - /* - * If we processed slen words, then f and g have been - * de-NTTized, and are in RNS; we can rebuild them. - */ - if (u == slen) { - zint_rebuild_CRT(ft, slen, slen, n, primes, 1, t1); - zint_rebuild_CRT(gt, slen, slen, n, primes, 1, t1); - } - - gm = t1; - igm = gm + n; - fx = igm + n; - gx = fx + n; - - modp_mkgm2(gm, igm, logn, primes[u].g, p, p0i); - - if (u < slen) { - for (v = 0, x = ft + u, y = gt + u; - v < n; v ++, x += slen, y += slen) - { - fx[v] = *x; - gx[v] = *y; - } - modp_iNTT2_ext(ft + u, slen, igm, logn, p, p0i); - modp_iNTT2_ext(gt + u, slen, igm, logn, p, p0i); - } else { - uint32_t Rx; - - Rx = modp_Rx((unsigned)slen, p, p0i, R2); - for (v = 0, x = ft, y = gt; - v < n; v ++, x += slen, y += slen) - { - fx[v] = zint_mod_small_signed(x, slen, - p, p0i, R2, Rx); - gx[v] = zint_mod_small_signed(y, slen, - p, p0i, R2, Rx); - } - modp_NTT2(fx, gm, logn, p, p0i); - modp_NTT2(gx, gm, logn, p, p0i); - } - - /* - * Get F' and G' modulo p and in NTT representation - * (they have degree n/2). These values were computed in - * a previous step, and stored in Ft and Gt. - */ - Fp = gx + n; - Gp = Fp + hn; - for (v = 0, x = Ft + u, y = Gt + u; - v < hn; v ++, x += llen, y += llen) - { - Fp[v] = *x; - Gp[v] = *y; - } - modp_NTT2(Fp, gm, logn - 1, p, p0i); - modp_NTT2(Gp, gm, logn - 1, p, p0i); - - /* - * Compute our F and G modulo p. - * - * General case: - * - * we divide degree by d = 2 or 3 - * f'(x^d) = N(f)(x^d) = f * adj(f) - * g'(x^d) = N(g)(x^d) = g * adj(g) - * f'*G' - g'*F' = q - * F = F'(x^d) * adj(g) - * G = G'(x^d) * adj(f) - * - * We compute things in the NTT. We group roots of phi - * such that all roots x in a group share the same x^d. - * If the roots in a group are x_1, x_2... x_d, then: - * - * N(f)(x_1^d) = f(x_1)*f(x_2)*...*f(x_d) - * - * Thus, we have: - * - * G(x_1) = f(x_2)*f(x_3)*...*f(x_d)*G'(x_1^d) - * G(x_2) = f(x_1)*f(x_3)*...*f(x_d)*G'(x_1^d) - * ... - * G(x_d) = f(x_1)*f(x_2)*...*f(x_{d-1})*G'(x_1^d) - * - * In all cases, we can thus compute F and G in NTT - * representation by a few simple multiplications. - * Moreover, in our chosen NTT representation, roots - * from the same group are consecutive in RAM. - */ - for (v = 0, x = Ft + u, y = Gt + u; v < hn; - v ++, x += (llen << 1), y += (llen << 1)) - { - uint32_t ftA, ftB, gtA, gtB; - uint32_t mFp, mGp; - - ftA = fx[(v << 1) + 0]; - ftB = fx[(v << 1) + 1]; - gtA = gx[(v << 1) + 0]; - gtB = gx[(v << 1) + 1]; - mFp = modp_montymul(Fp[v], R2, p, p0i); - mGp = modp_montymul(Gp[v], R2, p, p0i); - x[0] = modp_montymul(gtB, mFp, p, p0i); - x[llen] = modp_montymul(gtA, mFp, p, p0i); - y[0] = modp_montymul(ftB, mGp, p, p0i); - y[llen] = modp_montymul(ftA, mGp, p, p0i); - } - modp_iNTT2_ext(Ft + u, llen, igm, logn, p, p0i); - modp_iNTT2_ext(Gt + u, llen, igm, logn, p, p0i); - } - - /* - * Rebuild F and G with the CRT. - */ - zint_rebuild_CRT(Ft, llen, llen, n, primes, 1, t1); - zint_rebuild_CRT(Gt, llen, llen, n, primes, 1, t1); - - /* - * At that point, Ft, Gt, ft and gt are consecutive in RAM (in that - * order). - */ - - /* - * Apply Babai reduction to bring back F and G to size slen. - * - * We use the FFT to compute successive approximations of the - * reduction coefficient. We first isolate the top bits of - * the coefficients of f and g, and convert them to floating - * point; with the FFT, we compute adj(f), adj(g), and - * 1/(f*adj(f)+g*adj(g)). - * - * Then, we repeatedly apply the following: - * - * - Get the top bits of the coefficients of F and G into - * floating point, and use the FFT to compute: - * (F*adj(f)+G*adj(g))/(f*adj(f)+g*adj(g)) - * - * - Convert back that value into normal representation, and - * round it to the nearest integers, yielding a polynomial k. - * Proper scaling is applied to f, g, F and G so that the - * coefficients fit on 32 bits (signed). - * - * - Subtract k*f from F and k*g from G. - * - * Under normal conditions, this process reduces the size of F - * and G by some bits at each iteration. For constant-time - * operation, we do not want to measure the actual length of - * F and G; instead, we do the following: - * - * - f and g are converted to floating-point, with some scaling - * if necessary to keep values in the representable range. - * - * - For each iteration, we _assume_ a maximum size for F and G, - * and use the values at that size. If we overreach, then - * we get zeros, which is harmless: the resulting coefficients - * of k will be 0 and the value won't be reduced. - * - * - We conservatively assume that F and G will be reduced by - * at least 25 bits at each iteration. - * - * Even when reaching the bottom of the reduction, reduction - * coefficient will remain low. If it goes out-of-range, then - * something wrong occurred and the whole NTRU solving fails. - */ - - /* - * Memory layout: - * - We need to compute and keep adj(f), adj(g), and - * 1/(f*adj(f)+g*adj(g)) (sizes N, N and N/2 fp numbers, - * respectively). - * - At each iteration we need two extra fp buffer (N fp values), - * and produce a k (N 32-bit words). k will be shared with one - * of the fp buffers. - * - To compute k*f and k*g efficiently (with the NTT), we need - * some extra room; we reuse the space of the temporary buffers. - * - * Arrays of 'fpr' are obtained from the temporary array itself. - * We ensure that the base is at a properly aligned offset (the - * source array tmp[] is supposed to be already aligned). - */ - - rt3 = align_fpr(tmp, t1); - rt4 = rt3 + n; - rt5 = rt4 + n; - rt1 = rt5 + (n >> 1); - k = (int32_t *)align_u32(tmp, rt1); - rt2 = align_fpr(tmp, k + n); - if (rt2 < (rt1 + n)) { - rt2 = rt1 + n; - } - t1 = (uint32_t *)k + n; - - /* - * Get f and g into rt3 and rt4 as floating-point approximations. - * - * We need to "scale down" the floating-point representation of - * coefficients when they are too big. We want to keep the value - * below 2^310 or so. Thus, when values are larger than 10 words, - * we consider only the top 10 words. Array lengths have been - * computed so that average maximum length will fall in the - * middle or the upper half of these top 10 words. - */ - rlen = (slen > 10) ? 10 : slen; - poly_big_to_fp(rt3, ft + slen - rlen, rlen, slen, logn); - poly_big_to_fp(rt4, gt + slen - rlen, rlen, slen, logn); - - /* - * Values in rt3 and rt4 are downscaled by 2^(scale_fg). - */ - scale_fg = 31 * (int)(slen - rlen); - - /* - * Estimated boundaries for the maximum size (in bits) of the - * coefficients of (f,g). We use the measured average, and - * allow for a deviation of at most six times the standard - * deviation. - */ - minbl_fg = BITLENGTH[depth].avg - 6 * BITLENGTH[depth].std; - maxbl_fg = BITLENGTH[depth].avg + 6 * BITLENGTH[depth].std; - - /* - * Compute 1/(f*adj(f)+g*adj(g)) in rt5. We also keep adj(f) - * and adj(g) in rt3 and rt4, respectively. - */ - Zf(FFT)(rt3, logn); - Zf(FFT)(rt4, logn); - Zf(poly_invnorm2_fft)(rt5, rt3, rt4, logn); - Zf(poly_adj_fft)(rt3, logn); - Zf(poly_adj_fft)(rt4, logn); - - /* - * Reduce F and G repeatedly. - * - * The expected maximum bit length of coefficients of F and G - * is kept in maxbl_FG, with the corresponding word length in - * FGlen. - */ - FGlen = llen; - maxbl_FG = 31 * (int)llen; - - /* - * Each reduction operation computes the reduction polynomial - * "k". We need that polynomial to have coefficients that fit - * on 32-bit signed integers, with some scaling; thus, we use - * a descending sequence of scaling values, down to zero. - * - * The size of the coefficients of k is (roughly) the difference - * between the size of the coefficients of (F,G) and the size - * of the coefficients of (f,g). Thus, the maximum size of the - * coefficients of k is, at the start, maxbl_FG - minbl_fg; - * this is our starting scale value for k. - * - * We need to estimate the size of (F,G) during the execution of - * the algorithm; we are allowed some overestimation but not too - * much (poly_big_to_fp() uses a 310-bit window). Generally - * speaking, after applying a reduction with k scaled to - * scale_k, the size of (F,G) will be size(f,g) + scale_k + dd, - * where 'dd' is a few bits to account for the fact that the - * reduction is never perfect (intuitively, dd is on the order - * of sqrt(N), so at most 5 bits; we here allow for 10 extra - * bits). - * - * The size of (f,g) is not known exactly, but maxbl_fg is an - * upper bound. - */ - scale_k = maxbl_FG - minbl_fg; - - for (;;) { - int scale_FG, dc, new_maxbl_FG; - uint32_t scl, sch; - fpr pdc, pt; - - /* - * Convert current F and G into floating-point. We apply - * scaling if the current length is more than 10 words. - */ - rlen = (FGlen > 10) ? 10 : FGlen; - scale_FG = 31 * (int)(FGlen - rlen); - poly_big_to_fp(rt1, Ft + FGlen - rlen, rlen, llen, logn); - poly_big_to_fp(rt2, Gt + FGlen - rlen, rlen, llen, logn); - - /* - * Compute (F*adj(f)+G*adj(g))/(f*adj(f)+g*adj(g)) in rt2. - */ - Zf(FFT)(rt1, logn); - Zf(FFT)(rt2, logn); - Zf(poly_mul_fft)(rt1, rt3, logn); - Zf(poly_mul_fft)(rt2, rt4, logn); - Zf(poly_add)(rt2, rt1, logn); - Zf(poly_mul_autoadj_fft)(rt2, rt5, logn); - Zf(iFFT)(rt2, logn); - - /* - * (f,g) are scaled by 'scale_fg', meaning that the - * numbers in rt3/rt4 should be multiplied by 2^(scale_fg) - * to have their true mathematical value. - * - * (F,G) are similarly scaled by 'scale_FG'. Therefore, - * the value we computed in rt2 is scaled by - * 'scale_FG-scale_fg'. - * - * We want that value to be scaled by 'scale_k', hence we - * apply a corrective scaling. After scaling, the values - * should fit in -2^31-1..+2^31-1. - */ - dc = scale_k - scale_FG + scale_fg; - - /* - * We will need to multiply values by 2^(-dc). The value - * 'dc' is not secret, so we can compute 2^(-dc) with a - * non-constant-time process. - * (We could use ldexp(), but we prefer to avoid any - * dependency on libm. When using FP emulation, we could - * use our fpr_ldexp(), which is constant-time.) - */ - if (dc < 0) { - dc = -dc; - pt = fpr_two; - } else { - pt = fpr_onehalf; - } - pdc = fpr_one; - while (dc != 0) { - if ((dc & 1) != 0) { - pdc = fpr_mul(pdc, pt); - } - dc >>= 1; - pt = fpr_sqr(pt); - } - - for (u = 0; u < n; u ++) { - fpr xv; - - xv = fpr_mul(rt2[u], pdc); - - /* - * Sometimes the values can be out-of-bounds if - * the algorithm fails; we must not call - * fpr_rint() (and cast to int32_t) if the value - * is not in-bounds. Note that the test does not - * break constant-time discipline, since any - * failure here implies that we discard the current - * secret key (f,g). - */ - if (!fpr_lt(fpr_mtwo31m1, xv) - || !fpr_lt(xv, fpr_ptwo31m1)) - { - return 0; - } - k[u] = (int32_t)fpr_rint(xv); - } - - /* - * Values in k[] are integers. They really are scaled - * down by maxbl_FG - minbl_fg bits. - * - * If we are at low depth, then we use the NTT to - * compute k*f and k*g. - */ - sch = (uint32_t)(scale_k / 31); - scl = (uint32_t)(scale_k % 31); - if (depth <= DEPTH_INT_FG) { - poly_sub_scaled_ntt(Ft, FGlen, llen, ft, slen, slen, - k, sch, scl, logn, t1); - poly_sub_scaled_ntt(Gt, FGlen, llen, gt, slen, slen, - k, sch, scl, logn, t1); - } else { - poly_sub_scaled(Ft, FGlen, llen, ft, slen, slen, - k, sch, scl, logn); - poly_sub_scaled(Gt, FGlen, llen, gt, slen, slen, - k, sch, scl, logn); - } - - /* - * We compute the new maximum size of (F,G), assuming that - * (f,g) has _maximal_ length (i.e. that reduction is - * "late" instead of "early". We also adjust FGlen - * accordingly. - */ - new_maxbl_FG = scale_k + maxbl_fg + 10; - if (new_maxbl_FG < maxbl_FG) { - maxbl_FG = new_maxbl_FG; - if ((int)FGlen * 31 >= maxbl_FG + 31) { - FGlen --; - } - } - - /* - * We suppose that scaling down achieves a reduction by - * at least 25 bits per iteration. We stop when we have - * done the loop with an unscaled k. - */ - if (scale_k <= 0) { - break; - } - scale_k -= 25; - if (scale_k < 0) { - scale_k = 0; - } - } - - /* - * If (F,G) length was lowered below 'slen', then we must take - * care to re-extend the sign. - */ - if (FGlen < slen) { - for (u = 0; u < n; u ++, Ft += llen, Gt += llen) { - size_t v; - uint32_t sw; - - sw = -(Ft[FGlen - 1] >> 30) >> 1; - for (v = FGlen; v < slen; v ++) { - Ft[v] = sw; - } - sw = -(Gt[FGlen - 1] >> 30) >> 1; - for (v = FGlen; v < slen; v ++) { - Gt[v] = sw; - } - } - } - - /* - * Compress encoding of all values to 'slen' words (this is the - * expected output format). - */ - for (u = 0, x = tmp, y = tmp; - u < (n << 1); u ++, x += slen, y += llen) - { - memmove(x, y, slen * sizeof *y); - } - return 1; -} - -/* - * Solving the NTRU equation, binary case, depth = 1. Upon entry, the - * F and G from the previous level should be in the tmp[] array. - * - * Returned value: 1 on success, 0 on error. - */ -static int -solve_NTRU_binary_depth1(unsigned logn_top, - const int8_t *f, const int8_t *g, uint32_t *tmp) -{ - /* - * The first half of this function is a copy of the corresponding - * part in solve_NTRU_intermediate(), for the reconstruction of - * the unreduced F and G. The second half (Babai reduction) is - * done differently, because the unreduced F and G fit in 53 bits - * of precision, allowing a much simpler process with lower RAM - * usage. - */ - unsigned depth, logn; - size_t n_top, n, hn, slen, dlen, llen, u; - uint32_t *Fd, *Gd, *Ft, *Gt, *ft, *gt, *t1; - fpr *rt1, *rt2, *rt3, *rt4, *rt5, *rt6; - uint32_t *x, *y; - - depth = 1; - n_top = (size_t)1 << logn_top; - logn = logn_top - depth; - n = (size_t)1 << logn; - hn = n >> 1; - - /* - * Equations are: - * - * f' = f0^2 - X^2*f1^2 - * g' = g0^2 - X^2*g1^2 - * F' and G' are a solution to f'G' - g'F' = q (from deeper levels) - * F = F'*(g0 - X*g1) - * G = G'*(f0 - X*f1) - * - * f0, f1, g0, g1, f', g', F' and G' are all "compressed" to - * degree N/2 (their odd-indexed coefficients are all zero). - */ - - /* - * slen = size for our input f and g; also size of the reduced - * F and G we return (degree N) - * - * dlen = size of the F and G obtained from the deeper level - * (degree N/2) - * - * llen = size for intermediary F and G before reduction (degree N) - * - * We build our non-reduced F and G as two independent halves each, - * of degree N/2 (F = F0 + X*F1, G = G0 + X*G1). - */ - slen = MAX_BL_SMALL[depth]; - dlen = MAX_BL_SMALL[depth + 1]; - llen = MAX_BL_LARGE[depth]; - - /* - * Fd and Gd are the F and G from the deeper level. Ft and Gt - * are the destination arrays for the unreduced F and G. - */ - Fd = tmp; - Gd = Fd + dlen * hn; - Ft = Gd + dlen * hn; - Gt = Ft + llen * n; - - /* - * We reduce Fd and Gd modulo all the small primes we will need, - * and store the values in Ft and Gt. - */ - for (u = 0; u < llen; u ++) { - uint32_t p, p0i, R2, Rx; - size_t v; - uint32_t *xs, *ys, *xd, *yd; - - p = PRIMES[u].p; - p0i = modp_ninv31(p); - R2 = modp_R2(p, p0i); - Rx = modp_Rx((unsigned)dlen, p, p0i, R2); - for (v = 0, xs = Fd, ys = Gd, xd = Ft + u, yd = Gt + u; - v < hn; - v ++, xs += dlen, ys += dlen, xd += llen, yd += llen) - { - *xd = zint_mod_small_signed(xs, dlen, p, p0i, R2, Rx); - *yd = zint_mod_small_signed(ys, dlen, p, p0i, R2, Rx); - } - } - - /* - * Now Fd and Gd are not needed anymore; we can squeeze them out. - */ - memmove(tmp, Ft, llen * n * sizeof(uint32_t)); - Ft = tmp; - memmove(Ft + llen * n, Gt, llen * n * sizeof(uint32_t)); - Gt = Ft + llen * n; - ft = Gt + llen * n; - gt = ft + slen * n; - - t1 = gt + slen * n; - - /* - * Compute our F and G modulo sufficiently many small primes. - */ - for (u = 0; u < llen; u ++) { - uint32_t p, p0i, R2; - uint32_t *gm, *igm, *fx, *gx, *Fp, *Gp; - unsigned e; - size_t v; - - /* - * All computations are done modulo p. - */ - p = PRIMES[u].p; - p0i = modp_ninv31(p); - R2 = modp_R2(p, p0i); - - /* - * We recompute things from the source f and g, of full - * degree. However, we will need only the n first elements - * of the inverse NTT table (igm); the call to modp_mkgm() - * below will fill n_top elements in igm[] (thus overflowing - * into fx[]) but later code will overwrite these extra - * elements. - */ - gm = t1; - igm = gm + n_top; - fx = igm + n; - gx = fx + n_top; - modp_mkgm2(gm, igm, logn_top, PRIMES[u].g, p, p0i); - - /* - * Set ft and gt to f and g modulo p, respectively. - */ - for (v = 0; v < n_top; v ++) { - fx[v] = modp_set(f[v], p); - gx[v] = modp_set(g[v], p); - } - - /* - * Convert to NTT and compute our f and g. - */ - modp_NTT2(fx, gm, logn_top, p, p0i); - modp_NTT2(gx, gm, logn_top, p, p0i); - for (e = logn_top; e > logn; e --) { - modp_poly_rec_res(fx, e, p, p0i, R2); - modp_poly_rec_res(gx, e, p, p0i, R2); - } - - /* - * From that point onward, we only need tables for - * degree n, so we can save some space. - */ - if (depth > 0) { /* always true */ - memmove(gm + n, igm, n * sizeof *igm); - igm = gm + n; - memmove(igm + n, fx, n * sizeof *ft); - fx = igm + n; - memmove(fx + n, gx, n * sizeof *gt); - gx = fx + n; - } - - /* - * Get F' and G' modulo p and in NTT representation - * (they have degree n/2). These values were computed - * in a previous step, and stored in Ft and Gt. - */ - Fp = gx + n; - Gp = Fp + hn; - for (v = 0, x = Ft + u, y = Gt + u; - v < hn; v ++, x += llen, y += llen) - { - Fp[v] = *x; - Gp[v] = *y; - } - modp_NTT2(Fp, gm, logn - 1, p, p0i); - modp_NTT2(Gp, gm, logn - 1, p, p0i); - - /* - * Compute our F and G modulo p. - * - * Equations are: - * - * f'(x^2) = N(f)(x^2) = f * adj(f) - * g'(x^2) = N(g)(x^2) = g * adj(g) - * - * f'*G' - g'*F' = q - * - * F = F'(x^2) * adj(g) - * G = G'(x^2) * adj(f) - * - * The NTT representation of f is f(w) for all w which - * are roots of phi. In the binary case, as well as in - * the ternary case for all depth except the deepest, - * these roots can be grouped in pairs (w,-w), and we - * then have: - * - * f(w) = adj(f)(-w) - * f(-w) = adj(f)(w) - * - * and w^2 is then a root for phi at the half-degree. - * - * At the deepest level in the ternary case, this still - * holds, in the following sense: the roots of x^2-x+1 - * are (w,-w^2) (for w^3 = -1, and w != -1), and we - * have: - * - * f(w) = adj(f)(-w^2) - * f(-w^2) = adj(f)(w) - * - * In all case, we can thus compute F and G in NTT - * representation by a few simple multiplications. - * Moreover, the two roots for each pair are consecutive - * in our bit-reversal encoding. - */ - for (v = 0, x = Ft + u, y = Gt + u; - v < hn; v ++, x += (llen << 1), y += (llen << 1)) - { - uint32_t ftA, ftB, gtA, gtB; - uint32_t mFp, mGp; - - ftA = fx[(v << 1) + 0]; - ftB = fx[(v << 1) + 1]; - gtA = gx[(v << 1) + 0]; - gtB = gx[(v << 1) + 1]; - mFp = modp_montymul(Fp[v], R2, p, p0i); - mGp = modp_montymul(Gp[v], R2, p, p0i); - x[0] = modp_montymul(gtB, mFp, p, p0i); - x[llen] = modp_montymul(gtA, mFp, p, p0i); - y[0] = modp_montymul(ftB, mGp, p, p0i); - y[llen] = modp_montymul(ftA, mGp, p, p0i); - } - modp_iNTT2_ext(Ft + u, llen, igm, logn, p, p0i); - modp_iNTT2_ext(Gt + u, llen, igm, logn, p, p0i); - - /* - * Also save ft and gt (only up to size slen). - */ - if (u < slen) { - modp_iNTT2(fx, igm, logn, p, p0i); - modp_iNTT2(gx, igm, logn, p, p0i); - for (v = 0, x = ft + u, y = gt + u; - v < n; v ++, x += slen, y += slen) - { - *x = fx[v]; - *y = gx[v]; - } - } - } - - /* - * Rebuild f, g, F and G with the CRT. Note that the elements of F - * and G are consecutive, and thus can be rebuilt in a single - * loop; similarly, the elements of f and g are consecutive. - */ - zint_rebuild_CRT(Ft, llen, llen, n << 1, PRIMES, 1, t1); - zint_rebuild_CRT(ft, slen, slen, n << 1, PRIMES, 1, t1); - - /* - * Here starts the Babai reduction, specialized for depth = 1. - * - * Candidates F and G (from Ft and Gt), and base f and g (ft and gt), - * are converted to floating point. There is no scaling, and a - * single pass is sufficient. - */ - - /* - * Convert F and G into floating point (rt1 and rt2). - */ - rt1 = align_fpr(tmp, gt + slen * n); - rt2 = rt1 + n; - poly_big_to_fp(rt1, Ft, llen, llen, logn); - poly_big_to_fp(rt2, Gt, llen, llen, logn); - - /* - * Integer representation of F and G is no longer needed, we - * can remove it. - */ - memmove(tmp, ft, 2 * slen * n * sizeof *ft); - ft = tmp; - gt = ft + slen * n; - rt3 = align_fpr(tmp, gt + slen * n); - memmove(rt3, rt1, 2 * n * sizeof *rt1); - rt1 = rt3; - rt2 = rt1 + n; - rt3 = rt2 + n; - rt4 = rt3 + n; - - /* - * Convert f and g into floating point (rt3 and rt4). - */ - poly_big_to_fp(rt3, ft, slen, slen, logn); - poly_big_to_fp(rt4, gt, slen, slen, logn); - - /* - * Remove unneeded ft and gt. - */ - memmove(tmp, rt1, 4 * n * sizeof *rt1); - rt1 = (fpr *)tmp; - rt2 = rt1 + n; - rt3 = rt2 + n; - rt4 = rt3 + n; - - /* - * We now have: - * rt1 = F - * rt2 = G - * rt3 = f - * rt4 = g - * in that order in RAM. We convert all of them to FFT. - */ - Zf(FFT)(rt1, logn); - Zf(FFT)(rt2, logn); - Zf(FFT)(rt3, logn); - Zf(FFT)(rt4, logn); - - /* - * Compute: - * rt5 = F*adj(f) + G*adj(g) - * rt6 = 1 / (f*adj(f) + g*adj(g)) - * (Note that rt6 is half-length.) - */ - rt5 = rt4 + n; - rt6 = rt5 + n; - Zf(poly_add_muladj_fft)(rt5, rt1, rt2, rt3, rt4, logn); - Zf(poly_invnorm2_fft)(rt6, rt3, rt4, logn); - - /* - * Compute: - * rt5 = (F*adj(f)+G*adj(g)) / (f*adj(f)+g*adj(g)) - */ - Zf(poly_mul_autoadj_fft)(rt5, rt6, logn); - - /* - * Compute k as the rounded version of rt5. Check that none of - * the values is larger than 2^63-1 (in absolute value) - * because that would make the fpr_rint() do something undefined; - * note that any out-of-bounds value here implies a failure and - * (f,g) will be discarded, so we can make a simple test. - */ - Zf(iFFT)(rt5, logn); - for (u = 0; u < n; u ++) { - fpr z; - - z = rt5[u]; - if (!fpr_lt(z, fpr_ptwo63m1) || !fpr_lt(fpr_mtwo63m1, z)) { - return 0; - } - rt5[u] = fpr_of(fpr_rint(z)); - } - Zf(FFT)(rt5, logn); - - /* - * Subtract k*f from F, and k*g from G. - */ - Zf(poly_mul_fft)(rt3, rt5, logn); - Zf(poly_mul_fft)(rt4, rt5, logn); - Zf(poly_sub)(rt1, rt3, logn); - Zf(poly_sub)(rt2, rt4, logn); - Zf(iFFT)(rt1, logn); - Zf(iFFT)(rt2, logn); - - /* - * Convert back F and G to integers, and return. - */ - Ft = tmp; - Gt = Ft + n; - rt3 = align_fpr(tmp, Gt + n); - memmove(rt3, rt1, 2 * n * sizeof *rt1); - rt1 = rt3; - rt2 = rt1 + n; - for (u = 0; u < n; u ++) { - Ft[u] = (uint32_t)fpr_rint(rt1[u]); - Gt[u] = (uint32_t)fpr_rint(rt2[u]); - } - - return 1; -} - -/* - * Solving the NTRU equation, top level. Upon entry, the F and G - * from the previous level should be in the tmp[] array. - * - * Returned value: 1 on success, 0 on error. - */ -static int -solve_NTRU_binary_depth0(unsigned logn, - const int8_t *f, const int8_t *g, uint32_t *tmp) -{ - size_t n, hn, u; - uint32_t p, p0i, R2; - uint32_t *Fp, *Gp, *t1, *t2, *t3, *t4, *t5; - uint32_t *gm, *igm, *ft, *gt; - fpr *rt2, *rt3; - - n = (size_t)1 << logn; - hn = n >> 1; - - /* - * Equations are: - * - * f' = f0^2 - X^2*f1^2 - * g' = g0^2 - X^2*g1^2 - * F' and G' are a solution to f'G' - g'F' = q (from deeper levels) - * F = F'*(g0 - X*g1) - * G = G'*(f0 - X*f1) - * - * f0, f1, g0, g1, f', g', F' and G' are all "compressed" to - * degree N/2 (their odd-indexed coefficients are all zero). - * - * Everything should fit in 31-bit integers, hence we can just use - * the first small prime p = 2147473409. - */ - p = PRIMES[0].p; - p0i = modp_ninv31(p); - R2 = modp_R2(p, p0i); - - Fp = tmp; - Gp = Fp + hn; - ft = Gp + hn; - gt = ft + n; - gm = gt + n; - igm = gm + n; - - modp_mkgm2(gm, igm, logn, PRIMES[0].g, p, p0i); - - /* - * Convert F' anf G' in NTT representation. - */ - for (u = 0; u < hn; u ++) { - Fp[u] = modp_set(zint_one_to_plain(Fp + u), p); - Gp[u] = modp_set(zint_one_to_plain(Gp + u), p); - } - modp_NTT2(Fp, gm, logn - 1, p, p0i); - modp_NTT2(Gp, gm, logn - 1, p, p0i); - - /* - * Load f and g and convert them to NTT representation. - */ - for (u = 0; u < n; u ++) { - ft[u] = modp_set(f[u], p); - gt[u] = modp_set(g[u], p); - } - modp_NTT2(ft, gm, logn, p, p0i); - modp_NTT2(gt, gm, logn, p, p0i); - - /* - * Build the unreduced F,G in ft and gt. - */ - for (u = 0; u < n; u += 2) { - uint32_t ftA, ftB, gtA, gtB; - uint32_t mFp, mGp; - - ftA = ft[u + 0]; - ftB = ft[u + 1]; - gtA = gt[u + 0]; - gtB = gt[u + 1]; - mFp = modp_montymul(Fp[u >> 1], R2, p, p0i); - mGp = modp_montymul(Gp[u >> 1], R2, p, p0i); - ft[u + 0] = modp_montymul(gtB, mFp, p, p0i); - ft[u + 1] = modp_montymul(gtA, mFp, p, p0i); - gt[u + 0] = modp_montymul(ftB, mGp, p, p0i); - gt[u + 1] = modp_montymul(ftA, mGp, p, p0i); - } - modp_iNTT2(ft, igm, logn, p, p0i); - modp_iNTT2(gt, igm, logn, p, p0i); - - Gp = Fp + n; - t1 = Gp + n; - memmove(Fp, ft, 2 * n * sizeof *ft); - - /* - * We now need to apply the Babai reduction. At that point, - * we have F and G in two n-word arrays. - * - * We can compute F*adj(f)+G*adj(g) and f*adj(f)+g*adj(g) - * modulo p, using the NTT. We still move memory around in - * order to save RAM. - */ - t2 = t1 + n; - t3 = t2 + n; - t4 = t3 + n; - t5 = t4 + n; - - /* - * Compute the NTT tables in t1 and t2. We do not keep t2 - * (we'll recompute it later on). - */ - modp_mkgm2(t1, t2, logn, PRIMES[0].g, p, p0i); - - /* - * Convert F and G to NTT. - */ - modp_NTT2(Fp, t1, logn, p, p0i); - modp_NTT2(Gp, t1, logn, p, p0i); - - /* - * Load f and adj(f) in t4 and t5, and convert them to NTT - * representation. - */ - t4[0] = t5[0] = modp_set(f[0], p); - for (u = 1; u < n; u ++) { - t4[u] = modp_set(f[u], p); - t5[n - u] = modp_set(-f[u], p); - } - modp_NTT2(t4, t1, logn, p, p0i); - modp_NTT2(t5, t1, logn, p, p0i); - - /* - * Compute F*adj(f) in t2, and f*adj(f) in t3. - */ - for (u = 0; u < n; u ++) { - uint32_t w; - - w = modp_montymul(t5[u], R2, p, p0i); - t2[u] = modp_montymul(w, Fp[u], p, p0i); - t3[u] = modp_montymul(w, t4[u], p, p0i); - } - - /* - * Load g and adj(g) in t4 and t5, and convert them to NTT - * representation. - */ - t4[0] = t5[0] = modp_set(g[0], p); - for (u = 1; u < n; u ++) { - t4[u] = modp_set(g[u], p); - t5[n - u] = modp_set(-g[u], p); - } - modp_NTT2(t4, t1, logn, p, p0i); - modp_NTT2(t5, t1, logn, p, p0i); - - /* - * Add G*adj(g) to t2, and g*adj(g) to t3. - */ - for (u = 0; u < n; u ++) { - uint32_t w; - - w = modp_montymul(t5[u], R2, p, p0i); - t2[u] = modp_add(t2[u], - modp_montymul(w, Gp[u], p, p0i), p); - t3[u] = modp_add(t3[u], - modp_montymul(w, t4[u], p, p0i), p); - } - - /* - * Convert back t2 and t3 to normal representation (normalized - * around 0), and then - * move them to t1 and t2. We first need to recompute the - * inverse table for NTT. - */ - modp_mkgm2(t1, t4, logn, PRIMES[0].g, p, p0i); - modp_iNTT2(t2, t4, logn, p, p0i); - modp_iNTT2(t3, t4, logn, p, p0i); - for (u = 0; u < n; u ++) { - t1[u] = (uint32_t)modp_norm(t2[u], p); - t2[u] = (uint32_t)modp_norm(t3[u], p); - } - - /* - * At that point, array contents are: - * - * F (NTT representation) (Fp) - * G (NTT representation) (Gp) - * F*adj(f)+G*adj(g) (t1) - * f*adj(f)+g*adj(g) (t2) - * - * We want to divide t1 by t2. The result is not integral; it - * must be rounded. We thus need to use the FFT. - */ - - /* - * Get f*adj(f)+g*adj(g) in FFT representation. Since this - * polynomial is auto-adjoint, all its coordinates in FFT - * representation are actually real, so we can truncate off - * the imaginary parts. - */ - rt3 = align_fpr(tmp, t3); - for (u = 0; u < n; u ++) { - rt3[u] = fpr_of(((int32_t *)t2)[u]); - } - Zf(FFT)(rt3, logn); - rt2 = align_fpr(tmp, t2); - memmove(rt2, rt3, hn * sizeof *rt3); - - /* - * Convert F*adj(f)+G*adj(g) in FFT representation. - */ - rt3 = rt2 + hn; - for (u = 0; u < n; u ++) { - rt3[u] = fpr_of(((int32_t *)t1)[u]); - } - Zf(FFT)(rt3, logn); - - /* - * Compute (F*adj(f)+G*adj(g))/(f*adj(f)+g*adj(g)) and get - * its rounded normal representation in t1. - */ - Zf(poly_div_autoadj_fft)(rt3, rt2, logn); - Zf(iFFT)(rt3, logn); - for (u = 0; u < n; u ++) { - t1[u] = modp_set((int32_t)fpr_rint(rt3[u]), p); - } - - /* - * RAM contents are now: - * - * F (NTT representation) (Fp) - * G (NTT representation) (Gp) - * k (t1) - * - * We want to compute F-k*f, and G-k*g. - */ - t2 = t1 + n; - t3 = t2 + n; - t4 = t3 + n; - t5 = t4 + n; - modp_mkgm2(t2, t3, logn, PRIMES[0].g, p, p0i); - for (u = 0; u < n; u ++) { - t4[u] = modp_set(f[u], p); - t5[u] = modp_set(g[u], p); - } - modp_NTT2(t1, t2, logn, p, p0i); - modp_NTT2(t4, t2, logn, p, p0i); - modp_NTT2(t5, t2, logn, p, p0i); - for (u = 0; u < n; u ++) { - uint32_t kw; - - kw = modp_montymul(t1[u], R2, p, p0i); - Fp[u] = modp_sub(Fp[u], - modp_montymul(kw, t4[u], p, p0i), p); - Gp[u] = modp_sub(Gp[u], - modp_montymul(kw, t5[u], p, p0i), p); - } - modp_iNTT2(Fp, t3, logn, p, p0i); - modp_iNTT2(Gp, t3, logn, p, p0i); - for (u = 0; u < n; u ++) { - Fp[u] = (uint32_t)modp_norm(Fp[u], p); - Gp[u] = (uint32_t)modp_norm(Gp[u], p); - } - - return 1; -} - -/* - * Solve the NTRU equation. Returned value is 1 on success, 0 on error. - * G can be NULL, in which case that value is computed but not returned. - * If any of the coefficients of F and G exceeds lim (in absolute value), - * then 0 is returned. - */ -static int -solve_NTRU(unsigned logn, int8_t *F, int8_t *G, - const int8_t *f, const int8_t *g, int lim, uint32_t *tmp) -{ - size_t n, u; - uint32_t *ft, *gt, *Ft, *Gt, *gm; - uint32_t p, p0i, r; - const small_prime *primes; - - n = MKN(logn); - - if (!solve_NTRU_deepest(logn, f, g, tmp)) { - return 0; - } - - /* - * For logn <= 2, we need to use solve_NTRU_intermediate() - * directly, because coefficients are a bit too large and - * do not fit the hypotheses in solve_NTRU_binary_depth0(). - */ - if (logn <= 2) { - unsigned depth; - - depth = logn; - while (depth -- > 0) { - if (!solve_NTRU_intermediate(logn, f, g, depth, tmp)) { - return 0; - } - } - } else { - unsigned depth; - - depth = logn; - while (depth -- > 2) { - if (!solve_NTRU_intermediate(logn, f, g, depth, tmp)) { - return 0; - } - } - if (!solve_NTRU_binary_depth1(logn, f, g, tmp)) { - return 0; - } - if (!solve_NTRU_binary_depth0(logn, f, g, tmp)) { - return 0; - } - } - - /* - * If no buffer has been provided for G, use a temporary one. - */ - if (G == NULL) { - G = (int8_t *)(tmp + 2 * n); - } - - /* - * Final F and G are in fk->tmp, one word per coefficient - * (signed value over 31 bits). - */ - if (!poly_big_to_small(F, tmp, lim, logn) - || !poly_big_to_small(G, tmp + n, lim, logn)) - { - return 0; - } - - /* - * Verify that the NTRU equation is fulfilled. Since all elements - * have short lengths, verifying modulo a small prime p works, and - * allows using the NTT. - * - * We put Gt[] first in tmp[], and process it first, so that it does - * not overlap with G[] in case we allocated it ourselves. - */ - Gt = tmp; - ft = Gt + n; - gt = ft + n; - Ft = gt + n; - gm = Ft + n; - - primes = PRIMES; - p = primes[0].p; - p0i = modp_ninv31(p); - modp_mkgm2(gm, tmp, logn, primes[0].g, p, p0i); - for (u = 0; u < n; u ++) { - Gt[u] = modp_set(G[u], p); - } - for (u = 0; u < n; u ++) { - ft[u] = modp_set(f[u], p); - gt[u] = modp_set(g[u], p); - Ft[u] = modp_set(F[u], p); - } - modp_NTT2(ft, gm, logn, p, p0i); - modp_NTT2(gt, gm, logn, p, p0i); - modp_NTT2(Ft, gm, logn, p, p0i); - modp_NTT2(Gt, gm, logn, p, p0i); - r = modp_montymul(12289, 1, p, p0i); - for (u = 0; u < n; u ++) { - uint32_t z; - - z = modp_sub(modp_montymul(ft[u], Gt[u], p, p0i), - modp_montymul(gt[u], Ft[u], p, p0i), p); - if (z != r) { - return 0; - } - } - - return 1; -} - -/* - * Generate a random polynomial with a Gaussian distribution. This function - * also makes sure that the resultant of the polynomial with phi is odd. - */ -static void -poly_small_mkgauss(RNG_CONTEXT *rng, int8_t *f, unsigned logn) -{ - size_t n, u; - unsigned mod2; - - n = MKN(logn); - mod2 = 0; - for (u = 0; u < n; u ++) { - int s; - - restart: - s = mkgauss(rng, logn); - - /* - * We need the coefficient to fit within -127..+127; - * realistically, this is always the case except for - * the very low degrees (N = 2 or 4), for which there - * is no real security anyway. - */ - if (s < -127 || s > 127) { - goto restart; - } - - /* - * We need the sum of all coefficients to be 1; otherwise, - * the resultant of the polynomial with X^N+1 will be even, - * and the binary GCD will fail. - */ - if (u == n - 1) { - if ((mod2 ^ (unsigned)(s & 1)) == 0) { - goto restart; - } - } else { - mod2 ^= (unsigned)(s & 1); - } - f[u] = (int8_t)s; - } -} - -/* see falcon.h */ -void -Zf(keygen)(inner_shake256_context *rng, - int8_t *f, int8_t *g, int8_t *F, int8_t *G, uint16_t *h, - unsigned logn, uint8_t *tmp) -{ - /* - * Algorithm is the following: - * - * - Generate f and g with the Gaussian distribution. - * - * - If either Res(f,phi) or Res(g,phi) is even, try again. - * - * - If ||(f,g)|| is too large, try again. - * - * - If ||B~_{f,g}|| is too large, try again. - * - * - If f is not invertible mod phi mod q, try again. - * - * - Compute h = g/f mod phi mod q. - * - * - Solve the NTRU equation fG - gF = q; if the solving fails, - * try again. Usual failure condition is when Res(f,phi) - * and Res(g,phi) are not prime to each other. - */ - size_t n, u; - uint16_t *h2, *tmp2; - RNG_CONTEXT *rc; -#if FALCON_KG_CHACHA20 // yyyKG_CHACHA20+1 - prng p; -#endif // yyyKG_CHACHA20- - - n = MKN(logn); -#if FALCON_KG_CHACHA20 // yyyKG_CHACHA20+1 - Zf(prng_init)(&p, rng); - rc = &p; -#else // yyyKG_CHACHA20+0 - rc = rng; -#endif // yyyKG_CHACHA20- - - /* - * We need to generate f and g randomly, until we find values - * such that the norm of (g,-f), and of the orthogonalized - * vector, are satisfying. The orthogonalized vector is: - * (q*adj(f)/(f*adj(f)+g*adj(g)), q*adj(g)/(f*adj(f)+g*adj(g))) - * (it is actually the (N+1)-th row of the Gram-Schmidt basis). - * - * In the binary case, coefficients of f and g are generated - * independently of each other, with a discrete Gaussian - * distribution of standard deviation 1.17*sqrt(q/(2*N)). Then, - * the two vectors have expected norm 1.17*sqrt(q), which is - * also our acceptance bound: we require both vectors to be no - * larger than that (this will be satisfied about 1/4th of the - * time, thus we expect sampling new (f,g) about 4 times for that - * step). - * - * We require that Res(f,phi) and Res(g,phi) are both odd (the - * NTRU equation solver requires it). - */ - for (;;) { - fpr *rt1, *rt2, *rt3; - fpr bnorm; - uint32_t normf, normg, norm; - int lim; - - /* - * The poly_small_mkgauss() function makes sure - * that the sum of coefficients is 1 modulo 2 - * (i.e. the resultant of the polynomial with phi - * will be odd). - */ - poly_small_mkgauss(rc, f, logn); - poly_small_mkgauss(rc, g, logn); - - /* - * Verify that all coefficients are within the bounds - * defined in max_fg_bits. This is the case with - * overwhelming probability; this guarantees that the - * key will be encodable with FALCON_COMP_TRIM. - */ - lim = 1 << (Zf(max_fg_bits)[logn] - 1); - for (u = 0; u < n; u ++) { - /* - * We can use non-CT tests since on any failure - * we will discard f and g. - */ - if (f[u] >= lim || f[u] <= -lim - || g[u] >= lim || g[u] <= -lim) - { - lim = -1; - break; - } - } - if (lim < 0) { - continue; - } - - /* - * Bound is 1.17*sqrt(q). We compute the squared - * norms. With q = 12289, the squared bound is: - * (1.17^2)* 12289 = 16822.4121 - * Since f and g are integral, the squared norm - * of (g,-f) is an integer. - */ - normf = poly_small_sqnorm(f, logn); - normg = poly_small_sqnorm(g, logn); - norm = (normf + normg) | -((normf | normg) >> 31); - if (norm >= 16823) { - continue; - } - - /* - * We compute the orthogonalized vector norm. - */ - rt1 = (fpr *)tmp; - rt2 = rt1 + n; - rt3 = rt2 + n; - poly_small_to_fp(rt1, f, logn); - poly_small_to_fp(rt2, g, logn); - Zf(FFT)(rt1, logn); - Zf(FFT)(rt2, logn); - Zf(poly_invnorm2_fft)(rt3, rt1, rt2, logn); - Zf(poly_adj_fft)(rt1, logn); - Zf(poly_adj_fft)(rt2, logn); - Zf(poly_mulconst)(rt1, fpr_q, logn); - Zf(poly_mulconst)(rt2, fpr_q, logn); - Zf(poly_mul_autoadj_fft)(rt1, rt3, logn); - Zf(poly_mul_autoadj_fft)(rt2, rt3, logn); - Zf(iFFT)(rt1, logn); - Zf(iFFT)(rt2, logn); - bnorm = fpr_zero; - for (u = 0; u < n; u ++) { - bnorm = fpr_add(bnorm, fpr_sqr(rt1[u])); - bnorm = fpr_add(bnorm, fpr_sqr(rt2[u])); - } - if (!fpr_lt(bnorm, fpr_bnorm_max)) { - continue; - } - - /* - * Compute public key h = g/f mod X^N+1 mod q. If this - * fails, we must restart. - */ - if (h == NULL) { - h2 = (uint16_t *)tmp; - tmp2 = h2 + n; - } else { - h2 = h; - tmp2 = (uint16_t *)tmp; - } - if (!Zf(compute_public)(h2, f, g, logn, (uint8_t *)tmp2)) { - continue; - } - - /* - * Solve the NTRU equation to get F and G. - */ - lim = (1 << (Zf(max_FG_bits)[logn] - 1)) - 1; - if (!solve_NTRU(logn, F, G, f, g, lim, (uint32_t *)tmp)) { - continue; - } - - /* - * Key pair is generated. - */ - break; - } -} diff --git a/falcon/rng.c b/falcon/rng.c deleted file mode 100644 index d2ecb7a..0000000 --- a/falcon/rng.c +++ /dev/null @@ -1,379 +0,0 @@ -/* - * PRNG and interface to the system RNG. - * - * ==========================(LICENSE BEGIN)============================ - * - * Copyright (c) 2017-2019 Falcon Project - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * ===========================(LICENSE END)============================= - * - * @author Thomas Pornin - */ - -#include - -#include "inner.h" - -// yyyNIST+0 yyyPQCLEAN+0 -/* - * Include relevant system header files. For Win32, this will also need - * linking with advapi32.dll, which we trigger with an appropriate #pragma. - */ -#if FALCON_RAND_GETENTROPY -#include -#endif -#if FALCON_RAND_URANDOM -#include -#if !FALCON_RAND_GETENTROPY -#include -#endif -#include -#include -#endif -#if FALCON_RAND_WIN32 -#include -#include -#pragma comment(lib, "advapi32") -#endif - -/* see inner.h */ -int -Zf(get_seed)(void *seed, size_t len) -{ - (void)seed; - if (len == 0) { - return 1; - } -#if FALCON_RAND_GETENTROPY - if (getentropy(seed, len) == 0) { - return 1; - } -#endif -#if FALCON_RAND_URANDOM - { - int f; - - f = open("/dev/urandom", O_RDONLY); - if (f >= 0) { - while (len > 0) { - ssize_t rlen; - - rlen = read(f, seed, len); - if (rlen < 0) { - if (errno == EINTR) { - continue; - } - break; - } - seed = (uint8_t *)seed + rlen; - len -= (size_t)rlen; - } - close(f); - if (len == 0) { - return 1; - } - } - } -#endif -#if FALCON_RAND_WIN32 - { - HCRYPTPROV hp; - - if (CryptAcquireContext(&hp, 0, 0, PROV_RSA_FULL, - CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) - { - BOOL r; - - r = CryptGenRandom(hp, (DWORD)len, seed); - CryptReleaseContext(hp, 0); - if (r) { - return 1; - } - } - } -#endif - return 0; -} -// yyyNIST- yyyPQCLEAN- - -/* see inner.h */ -void -Zf(prng_init)(prng *p, inner_shake256_context *src) -{ -#if FALCON_LE // yyyLE+1 - inner_shake256_extract(src, p->state.d, 56); -#else // yyyLE+0 - /* - * To ensure reproducibility for a given seed, we - * must enforce little-endian interpretation of - * the state words. - */ - uint8_t tmp[56]; - uint64_t th, tl; - int i; - - inner_shake256_extract(src, tmp, 56); - for (i = 0; i < 14; i ++) { - uint32_t w; - - w = (uint32_t)tmp[(i << 2) + 0] - | ((uint32_t)tmp[(i << 2) + 1] << 8) - | ((uint32_t)tmp[(i << 2) + 2] << 16) - | ((uint32_t)tmp[(i << 2) + 3] << 24); - *(uint32_t *)(p->state.d + (i << 2)) = w; - } - tl = *(uint32_t *)(p->state.d + 48); - th = *(uint32_t *)(p->state.d + 52); - *(uint64_t *)(p->state.d + 48) = tl + (th << 32); -#endif // yyyLE- - Zf(prng_refill)(p); -} - -/* - * PRNG based on ChaCha20. - * - * State consists in key (32 bytes) then IV (16 bytes) and block counter - * (8 bytes). Normally, we should not care about local endianness (this - * is for a PRNG), but for the NIST competition we need reproducible KAT - * vectors that work across architectures, so we enforce little-endian - * interpretation where applicable. Moreover, output words are "spread - * out" over the output buffer with the interleaving pattern that is - * naturally obtained from the AVX2 implementation that runs eight - * ChaCha20 instances in parallel. - * - * The block counter is XORed into the first 8 bytes of the IV. - */ -TARGET_AVX2 -void -Zf(prng_refill)(prng *p) -{ -#if FALCON_AVX2 // yyyAVX2+1 - - static const uint32_t CW[] = { - 0x61707865, 0x3320646e, 0x79622d32, 0x6b206574 - }; - - uint64_t cc; - size_t u; - int i; - uint32_t *sw; - union { - uint32_t w[16]; - __m256i y[2]; /* for alignment */ - } t; - __m256i state[16], init[16]; - - sw = (uint32_t *)p->state.d; - - /* - * XOR next counter values into state. - */ - cc = *(uint64_t *)(p->state.d + 48); - for (u = 0; u < 8; u ++) { - t.w[u] = (uint32_t)(cc + u); - t.w[u + 8] = (uint32_t)((cc + u) >> 32); - } - *(uint64_t *)(p->state.d + 48) = cc + 8; - - /* - * Load state. - */ - for (u = 0; u < 4; u ++) { - state[u] = init[u] = - _mm256_broadcastd_epi32(_mm_cvtsi32_si128(CW[u])); - } - for (u = 0; u < 10; u ++) { - state[u + 4] = init[u + 4] = - _mm256_broadcastd_epi32(_mm_cvtsi32_si128(sw[u])); - } - state[14] = init[14] = _mm256_xor_si256( - _mm256_broadcastd_epi32(_mm_cvtsi32_si128(sw[10])), - _mm256_loadu_si256((__m256i *)&t.w[0])); - state[15] = init[15] = _mm256_xor_si256( - _mm256_broadcastd_epi32(_mm_cvtsi32_si128(sw[11])), - _mm256_loadu_si256((__m256i *)&t.w[8])); - - /* - * Do all rounds. - */ - for (i = 0; i < 10; i ++) { - -#define QROUND(a, b, c, d) do { \ - state[a] = _mm256_add_epi32(state[a], state[b]); \ - state[d] = _mm256_xor_si256(state[d], state[a]); \ - state[d] = _mm256_or_si256( \ - _mm256_slli_epi32(state[d], 16), \ - _mm256_srli_epi32(state[d], 16)); \ - state[c] = _mm256_add_epi32(state[c], state[d]); \ - state[b] = _mm256_xor_si256(state[b], state[c]); \ - state[b] = _mm256_or_si256( \ - _mm256_slli_epi32(state[b], 12), \ - _mm256_srli_epi32(state[b], 20)); \ - state[a] = _mm256_add_epi32(state[a], state[b]); \ - state[d] = _mm256_xor_si256(state[d], state[a]); \ - state[d] = _mm256_or_si256( \ - _mm256_slli_epi32(state[d], 8), \ - _mm256_srli_epi32(state[d], 24)); \ - state[c] = _mm256_add_epi32(state[c], state[d]); \ - state[b] = _mm256_xor_si256(state[b], state[c]); \ - state[b] = _mm256_or_si256( \ - _mm256_slli_epi32(state[b], 7), \ - _mm256_srli_epi32(state[b], 25)); \ - } while (0) - - QROUND( 0, 4, 8, 12); - QROUND( 1, 5, 9, 13); - QROUND( 2, 6, 10, 14); - QROUND( 3, 7, 11, 15); - QROUND( 0, 5, 10, 15); - QROUND( 1, 6, 11, 12); - QROUND( 2, 7, 8, 13); - QROUND( 3, 4, 9, 14); - -#undef QROUND - - } - - /* - * Add initial state back and encode the result in the destination - * buffer. We can dump the AVX2 values "as is" because the non-AVX2 - * code uses a compatible order of values. - */ - for (u = 0; u < 16; u ++) { - _mm256_storeu_si256((__m256i *)&p->buf.d[u << 5], - _mm256_add_epi32(state[u], init[u])); - } - -#else // yyyAVX2+0 - - static const uint32_t CW[] = { - 0x61707865, 0x3320646e, 0x79622d32, 0x6b206574 - }; - - uint64_t cc; - size_t u; - - /* - * State uses local endianness. Only the output bytes must be - * converted to little endian (if used on a big-endian machine). - */ - cc = *(uint64_t *)(p->state.d + 48); - for (u = 0; u < 8; u ++) { - uint32_t state[16]; - size_t v; - int i; - - memcpy(&state[0], CW, sizeof CW); - memcpy(&state[4], p->state.d, 48); - state[14] ^= (uint32_t)cc; - state[15] ^= (uint32_t)(cc >> 32); - for (i = 0; i < 10; i ++) { - -#define QROUND(a, b, c, d) do { \ - state[a] += state[b]; \ - state[d] ^= state[a]; \ - state[d] = (state[d] << 16) | (state[d] >> 16); \ - state[c] += state[d]; \ - state[b] ^= state[c]; \ - state[b] = (state[b] << 12) | (state[b] >> 20); \ - state[a] += state[b]; \ - state[d] ^= state[a]; \ - state[d] = (state[d] << 8) | (state[d] >> 24); \ - state[c] += state[d]; \ - state[b] ^= state[c]; \ - state[b] = (state[b] << 7) | (state[b] >> 25); \ - } while (0) - - QROUND( 0, 4, 8, 12); - QROUND( 1, 5, 9, 13); - QROUND( 2, 6, 10, 14); - QROUND( 3, 7, 11, 15); - QROUND( 0, 5, 10, 15); - QROUND( 1, 6, 11, 12); - QROUND( 2, 7, 8, 13); - QROUND( 3, 4, 9, 14); - -#undef QROUND - - } - - for (v = 0; v < 4; v ++) { - state[v] += CW[v]; - } - for (v = 4; v < 14; v ++) { - state[v] += ((uint32_t *)p->state.d)[v - 4]; - } - state[14] += ((uint32_t *)p->state.d)[10] - ^ (uint32_t)cc; - state[15] += ((uint32_t *)p->state.d)[11] - ^ (uint32_t)(cc >> 32); - cc ++; - - /* - * We mimic the interleaving that is used in the AVX2 - * implementation. - */ - for (v = 0; v < 16; v ++) { -#if FALCON_LE // yyyLE+1 - ((uint32_t *)p->buf.d)[u + (v << 3)] = state[v]; -#else // yyyLE+0 - p->buf.d[(u << 2) + (v << 5) + 0] = - (uint8_t)state[v]; - p->buf.d[(u << 2) + (v << 5) + 1] = - (uint8_t)(state[v] >> 8); - p->buf.d[(u << 2) + (v << 5) + 2] = - (uint8_t)(state[v] >> 16); - p->buf.d[(u << 2) + (v << 5) + 3] = - (uint8_t)(state[v] >> 24); -#endif // yyyLE- - } - } - *(uint64_t *)(p->state.d + 48) = cc; - -#endif // yyyAVX2- - - p->ptr = 0; -} - -/* see inner.h */ -void -Zf(prng_get_bytes)(prng *p, void *dst, size_t len) -{ - uint8_t *buf; - - buf = dst; - while (len > 0) { - size_t clen; - - clen = (sizeof p->buf.d) - p->ptr; - if (clen > len) { - clen = len; - } - memcpy(buf, p->buf.d, clen); - buf += clen; - len -= clen; - p->ptr += clen; - if (p->ptr == sizeof p->buf.d) { - Zf(prng_refill)(p); - } - } -} diff --git a/falcon/shake.c b/falcon/shake.c deleted file mode 100644 index cfddc81..0000000 --- a/falcon/shake.c +++ /dev/null @@ -1,1177 +0,0 @@ -/* - * SHAKE implementation. - * - * ==========================(LICENSE BEGIN)============================ - * - * Copyright (c) 2017-2019 Falcon Project - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * ===========================(LICENSE END)============================= - * - * @author Thomas Pornin - */ - -#include - -#include "inner.h" - -#if FALCON_ASM_CORTEXM4 // yyyASM_CORTEXM4+1 - -__attribute__((naked)) -static void -process_block(uint64_t *A __attribute__((unused))) -{ - __asm__ ( - "push { r1, r2, r3, r4, r5, r6, r7, r8, r10, r11, r12, lr }\n\t" - "sub sp, sp, #232\n\t" - "\n\t" - "@ Invert some words (alternate internal representation, which\n\t" - "@ saves some operations).\n\t" - "\n\t" - -#define INVERT_WORDS \ - "@ Invert A[1] and A[2].\n\t" \ - "adds r1, r0, #8\n\t" \ - "ldm r1, { r2, r3, r4, r5 }\n\t" \ - "mvns r2, r2\n\t" \ - "mvns r3, r3\n\t" \ - "mvns r4, r4\n\t" \ - "mvns r5, r5\n\t" \ - "stm r1!, { r2, r3, r4, r5 }\n\t" \ - "@ Invert A[8]\n\t" \ - "adds r1, r0, #64\n\t" \ - "ldm r1, { r2, r3 }\n\t" \ - "mvns r2, r2\n\t" \ - "mvns r3, r3\n\t" \ - "stm r1!, { r2, r3 }\n\t" \ - "@ Invert A[12]\n\t" \ - "adds r1, r0, #96\n\t" \ - "ldm r1, { r2, r3 }\n\t" \ - "mvns r2, r2\n\t" \ - "mvns r3, r3\n\t" \ - "stm r1!, { r2, r3 }\n\t" \ - "@ Invert A[17]\n\t" \ - "adds r1, r0, #136\n\t" \ - "ldm r1, { r2, r3 }\n\t" \ - "mvns r2, r2\n\t" \ - "mvns r3, r3\n\t" \ - "stm r1!, { r2, r3 }\n\t" \ - "@ Invert A[20]\n\t" \ - "adds r1, r0, #160\n\t" \ - "ldm r1, { r2, r3 }\n\t" \ - "mvns r2, r2\n\t" \ - "mvns r3, r3\n\t" \ - "stm r1!, { r2, r3 }\n\t" \ - "\n\t" - - INVERT_WORDS - - "@ Do 24 rounds. Each loop iteration performs one rounds. We\n\t" - "@ keep eight times the current round counter in [sp] (i.e.\n\t" - "@ a multiple of 8, from 0 to 184).\n\t" - "\n\t" - "eors r1, r1\n\t" - "str r1, [sp, #0]\n\t" -".process_block_loop:\n\t" - "\n\t" - "@ xor(A[5*i+0]) -> r1:r2\n\t" - "@ xor(A[5*i+1]) -> r3:r4\n\t" - "@ xor(A[5*i+2]) -> r5:r6\n\t" - "@ xor(A[5*i+3]) -> r7:r8\n\t" - "@ xor(A[5*i+4]) -> r10:r11\n\t" - "ldm r0!, { r1, r2, r3, r4, r5, r6, r7, r8 }\n\t" - "adds r0, #8\n\t" - "ldm r0!, { r10, r11, r12 }\n\t" - "eors r1, r10\n\t" - "eors r2, r11\n\t" - "eors r3, r12\n\t" - "ldm r0!, { r10, r11, r12 }\n\t" - "eors r4, r10\n\t" - "eors r5, r11\n\t" - "eors r6, r12\n\t" - "ldm r0!, { r10, r11 }\n\t" - "eors r7, r10\n\t" - "eors r8, r11\n\t" - "adds r0, #8\n\t" - "ldm r0!, { r10, r11, r12 }\n\t" - "eors r1, r10\n\t" - "eors r2, r11\n\t" - "eors r3, r12\n\t" - "ldm r0!, { r10, r11, r12 }\n\t" - "eors r4, r10\n\t" - "eors r5, r11\n\t" - "eors r6, r12\n\t" - "ldm r0!, { r10, r11 }\n\t" - "eors r7, r10\n\t" - "eors r8, r11\n\t" - "adds r0, #8\n\t" - "ldm r0!, { r10, r11, r12 }\n\t" - "eors r1, r10\n\t" - "eors r2, r11\n\t" - "eors r3, r12\n\t" - "ldm r0!, { r10, r11, r12 }\n\t" - "eors r4, r10\n\t" - "eors r5, r11\n\t" - "eors r6, r12\n\t" - "ldm r0!, { r10, r11 }\n\t" - "eors r7, r10\n\t" - "eors r8, r11\n\t" - "adds r0, #8\n\t" - "ldm r0!, { r10, r11, r12 }\n\t" - "eors r1, r10\n\t" - "eors r2, r11\n\t" - "eors r3, r12\n\t" - "ldm r0!, { r10, r11, r12 }\n\t" - "eors r4, r10\n\t" - "eors r5, r11\n\t" - "eors r6, r12\n\t" - "ldm r0!, { r10, r11 }\n\t" - "eors r7, r10\n\t" - "eors r8, r11\n\t" - "ldm r0!, { r10, r11 }\n\t" - "subs r0, #200\n\t" - "ldr r12, [r0, #32]\n\t" - "eors r10, r12\n\t" - "ldr r12, [r0, #36]\n\t" - "eors r11, r12\n\t" - "ldr r12, [r0, #72]\n\t" - "eors r10, r12\n\t" - "ldr r12, [r0, #76]\n\t" - "eors r11, r12\n\t" - "ldr r12, [r0, #112]\n\t" - "eors r10, r12\n\t" - "ldr r12, [r0, #116]\n\t" - "eors r11, r12\n\t" - "ldr r12, [r0, #152]\n\t" - "eors r10, r12\n\t" - "ldr r12, [r0, #156]\n\t" - "eors r11, r12\n\t" - "\n\t" - "@ t0 = xor(A[5*i+4]) ^ rotl1(xor(A[5*i+1])) -> r10:r11\n\t" - "@ t1 = xor(A[5*i+0]) ^ rotl1(xor(A[5*i+2])) -> r1:r2\n\t" - "@ t2 = xor(A[5*i+1]) ^ rotl1(xor(A[5*i+3])) -> r3:r4\n\t" - "@ t3 = xor(A[5*i+2]) ^ rotl1(xor(A[5*i+4])) -> r5:r6\n\t" - "@ t4 = xor(A[5*i+3]) ^ rotl1(xor(A[5*i+0])) -> r7:r8\n\t" - "str r11, [sp, #4]\n\t" - "mov r12, r10\n\t" - "eors r10, r10, r3, lsl #1\n\t" - "eors r10, r10, r4, lsr #31\n\t" - "eors r11, r11, r4, lsl #1\n\t" - "eors r11, r11, r3, lsr #31\n\t" - "eors r3, r3, r7, lsl #1\n\t" - "eors r3, r3, r8, lsr #31\n\t" - "eors r4, r4, r8, lsl #1\n\t" - "eors r4, r4, r7, lsr #31\n\t" - "eors r7, r7, r1, lsl #1\n\t" - "eors r7, r7, r2, lsr #31\n\t" - "eors r8, r8, r2, lsl #1\n\t" - "eors r8, r8, r1, lsr #31\n\t" - "eors r1, r1, r5, lsl #1\n\t" - "eors r1, r1, r6, lsr #31\n\t" - "eors r2, r2, r6, lsl #1\n\t" - "eors r2, r2, r5, lsr #31\n\t" - "eors r5, r5, r12, lsl #1\n\t" - "eors r6, r6, r12, lsr #31\n\t" - "ldr r12, [sp, #4]\n\t" - "eors r5, r5, r12, lsr #31\n\t" - "eors r6, r6, r12, lsl #1\n\t" - "\n\t" - "@ Save t2, t3 and t4 on the stack.\n\t" - "addw r12, sp, #4\n\t" - "stm r12, { r3, r4, r5, r6, r7, r8 }\n\t" - "\n\t" - "@ We XOR one of the t0..t4 values into each A[] word, and\n\t" - "@ rotate the result by some amount (each word has its own\n\t" - "@ amount). The results are written back into a stack buffer\n\t" - "@ that starts at sp+32\n\t" - "addw r12, sp, #32\n\t" - "\n\t" - "@ XOR t0 into A[5*i+0] and t1 into A[5*i+1]; each A[i] is also\n\t" - "@ rotated left by some amount.\n\t" - "\n\t" - "@ A[0] and A[1]\n\t" - "ldm r0!, { r5, r6, r7, r8 }\n\t" - "eors r5, r10\n\t" - "eors r6, r11\n\t" - "eors r3, r7, r1\n\t" - "eors r4, r8, r2\n\t" - "lsl r7, r3, #1\n\t" - "orr r7, r7, r4, lsr #31\n\t" - "lsl r8, r4, #1\n\t" - "orr r8, r8, r3, lsr #31\n\t" - "stm r12!, { r5, r6, r7, r8 }\n\t" - "\n\t" - "@ A[5] and A[6]\n\t" - "adds r0, #24\n\t" - "ldm r0!, { r5, r6, r7, r8 }\n\t" - "eors r3, r5, r10\n\t" - "eors r4, r6, r11\n\t" - "lsl r5, r4, #4\n\t" - "orr r5, r5, r3, lsr #28\n\t" - "lsl r6, r3, #4\n\t" - "orr r6, r6, r4, lsr #28\n\t" - "eors r3, r7, r1\n\t" - "eors r4, r8, r2\n\t" - "lsl r7, r4, #12\n\t" - "orr r7, r7, r3, lsr #20\n\t" - "lsl r8, r3, #12\n\t" - "orr r8, r8, r4, lsr #20\n\t" - "stm r12!, { r5, r6, r7, r8 }\n\t" - "\n\t" - "@ A[10] and A[11]\n\t" - "adds r0, #24\n\t" - "ldm r0!, { r5, r6, r7, r8 }\n\t" - "eors r3, r5, r10\n\t" - "eors r4, r6, r11\n\t" - "lsl r5, r3, #3\n\t" - "orr r5, r5, r4, lsr #29\n\t" - "lsl r6, r4, #3\n\t" - "orr r6, r6, r3, lsr #29\n\t" - "eors r3, r7, r1\n\t" - "eors r4, r8, r2\n\t" - "lsl r7, r3, #10\n\t" - "orr r7, r7, r4, lsr #22\n\t" - "lsl r8, r4, #10\n\t" - "orr r8, r8, r3, lsr #22\n\t" - "stm r12!, { r5, r6, r7, r8 }\n\t" - "\n\t" - "@ A[15] and A[16]\n\t" - "adds r0, #24\n\t" - "ldm r0!, { r5, r6, r7, r8 }\n\t" - "eors r3, r5, r10\n\t" - "eors r4, r6, r11\n\t" - "lsl r5, r4, #9\n\t" - "orr r5, r5, r3, lsr #23\n\t" - "lsl r6, r3, #9\n\t" - "orr r6, r6, r4, lsr #23\n\t" - "eors r3, r7, r1\n\t" - "eors r4, r8, r2\n\t" - "lsl r7, r4, #13\n\t" - "orr r7, r7, r3, lsr #19\n\t" - "lsl r8, r3, #13\n\t" - "orr r8, r8, r4, lsr #19\n\t" - "stm r12!, { r5, r6, r7, r8 }\n\t" - "\n\t" - "@ A[20] and A[21]\n\t" - "adds r0, #24\n\t" - "ldm r0!, { r5, r6, r7, r8 }\n\t" - "eors r3, r5, r10\n\t" - "eors r4, r6, r11\n\t" - "lsl r5, r3, #18\n\t" - "orr r5, r5, r4, lsr #14\n\t" - "lsl r6, r4, #18\n\t" - "orr r6, r6, r3, lsr #14\n\t" - "eors r3, r7, r1\n\t" - "eors r4, r8, r2\n\t" - "lsl r7, r3, #2\n\t" - "orr r7, r7, r4, lsr #30\n\t" - "lsl r8, r4, #2\n\t" - "orr r8, r8, r3, lsr #30\n\t" - "stm r12!, { r5, r6, r7, r8 }\n\t" - "\n\t" - "@ XOR t2 into A[5*i+2] and t3 into A[5*i+3]; each A[i] is also\n\t" - "@ rotated left by some amount. We reload t2 into r1:r2 and t3\n\t" - "@ into r3:r4.\n\t" - "addw r5, sp, #4\n\t" - "ldm r5!, { r1, r2, r3, r4 }\n\t" - "\n\t" - "@ A[2] and A[3]\n\t" - "subs r0, #160\n\t" - "ldm r0!, { r5, r6, r7, r8 }\n\t" - "eors r10, r5, r1\n\t" - "eors r11, r6, r2\n\t" - "lsl r5, r11, #30\n\t" - "orr r5, r5, r10, lsr #2\n\t" - "lsl r6, r10, #30\n\t" - "orr r6, r6, r11, lsr #2\n\t" - "eors r10, r7, r3\n\t" - "eors r11, r8, r4\n\t" - "lsl r7, r10, #28\n\t" - "orr r7, r7, r11, lsr #4\n\t" - "lsl r8, r11, #28\n\t" - "orr r8, r8, r10, lsr #4\n\t" - "stm r12!, { r5, r6, r7, r8 }\n\t" - "\n\t" - "@ A[7] and A[8]\n\t" - "adds r0, #24\n\t" - "ldm r0!, { r5, r6, r7, r8 }\n\t" - "eors r10, r5, r1\n\t" - "eors r11, r6, r2\n\t" - "lsl r5, r10, #6\n\t" - "orr r5, r5, r11, lsr #26\n\t" - "lsl r6, r11, #6\n\t" - "orr r6, r6, r10, lsr #26\n\t" - "eors r10, r7, r3\n\t" - "eors r11, r8, r4\n\t" - "lsl r7, r11, #23\n\t" - "orr r7, r7, r10, lsr #9\n\t" - "lsl r8, r10, #23\n\t" - "orr r8, r8, r11, lsr #9\n\t" - "stm r12!, { r5, r6, r7, r8 }\n\t" - "\n\t" - "@ A[12] and A[13]\n\t" - "adds r0, #24\n\t" - "ldm r0!, { r5, r6, r7, r8 }\n\t" - "eors r10, r5, r1\n\t" - "eors r11, r6, r2\n\t" - "lsl r5, r11, #11\n\t" - "orr r5, r5, r10, lsr #21\n\t" - "lsl r6, r10, #11\n\t" - "orr r6, r6, r11, lsr #21\n\t" - "eors r10, r7, r3\n\t" - "eors r11, r8, r4\n\t" - "lsl r7, r10, #25\n\t" - "orr r7, r7, r11, lsr #7\n\t" - "lsl r8, r11, #25\n\t" - "orr r8, r8, r10, lsr #7\n\t" - "stm r12!, { r5, r6, r7, r8 }\n\t" - "\n\t" - "@ A[17] and A[18]\n\t" - "adds r0, #24\n\t" - "ldm r0!, { r5, r6, r7, r8 }\n\t" - "eors r10, r5, r1\n\t" - "eors r11, r6, r2\n\t" - "lsl r5, r10, #15\n\t" - "orr r5, r5, r11, lsr #17\n\t" - "lsl r6, r11, #15\n\t" - "orr r6, r6, r10, lsr #17\n\t" - "eors r10, r7, r3\n\t" - "eors r11, r8, r4\n\t" - "lsl r7, r10, #21\n\t" - "orr r7, r7, r11, lsr #11\n\t" - "lsl r8, r11, #21\n\t" - "orr r8, r8, r10, lsr #11\n\t" - "stm r12!, { r5, r6, r7, r8 }\n\t" - "\n\t" - "@ A[22] and A[23]\n\t" - "adds r0, #24\n\t" - "ldm r0!, { r5, r6, r7, r8 }\n\t" - "eors r10, r5, r1\n\t" - "eors r11, r6, r2\n\t" - "lsl r5, r11, #29\n\t" - "orr r5, r5, r10, lsr #3\n\t" - "lsl r6, r10, #29\n\t" - "orr r6, r6, r11, lsr #3\n\t" - "eors r10, r7, r3\n\t" - "eors r11, r8, r4\n\t" - "lsl r7, r11, #24\n\t" - "orr r7, r7, r10, lsr #8\n\t" - "lsl r8, r10, #24\n\t" - "orr r8, r8, r11, lsr #8\n\t" - "stm r12!, { r5, r6, r7, r8 }\n\t" - "\n\t" - "@ XOR t4 into A[5*i+4]; each A[i] is also rotated left by some\n\t" - "@ amount. We reload t4 into r1:r2.\n\t" - "ldr r1, [sp, #20]\n\t" - "ldr r2, [sp, #24]\n\t" - "\n\t" - "@ A[4]\n\t" - "subs r0, #160\n\t" - "ldm r0!, { r5, r6 }\n\t" - "eors r3, r5, r1\n\t" - "eors r4, r6, r2\n\t" - "lsl r5, r3, #27\n\t" - "orr r5, r5, r4, lsr #5\n\t" - "lsl r6, r4, #27\n\t" - "orr r6, r6, r3, lsr #5\n\t" - "stm r12!, { r5, r6 }\n\t" - "\n\t" - "@ A[9]\n\t" - "adds r0, #32\n\t" - "ldm r0!, { r5, r6 }\n\t" - "eors r3, r5, r1\n\t" - "eors r4, r6, r2\n\t" - "lsl r5, r3, #20\n\t" - "orr r5, r5, r4, lsr #12\n\t" - "lsl r6, r4, #20\n\t" - "orr r6, r6, r3, lsr #12\n\t" - "stm r12!, { r5, r6 }\n\t" - "\n\t" - "@ A[14]\n\t" - "adds r0, #32\n\t" - "ldm r0!, { r5, r6 }\n\t" - "eors r3, r5, r1\n\t" - "eors r4, r6, r2\n\t" - "lsl r5, r4, #7\n\t" - "orr r5, r5, r3, lsr #25\n\t" - "lsl r6, r3, #7\n\t" - "orr r6, r6, r4, lsr #25\n\t" - "stm r12!, { r5, r6 }\n\t" - "\n\t" - "@ A[19]\n\t" - "adds r0, #32\n\t" - "ldm r0!, { r5, r6 }\n\t" - "eors r3, r5, r1\n\t" - "eors r4, r6, r2\n\t" - "lsl r5, r3, #8\n\t" - "orr r5, r5, r4, lsr #24\n\t" - "lsl r6, r4, #8\n\t" - "orr r6, r6, r3, lsr #24\n\t" - "stm r12!, { r5, r6 }\n\t" - "\n\t" - "@ A[24]\n\t" - "adds r0, #32\n\t" - "ldm r0!, { r5, r6 }\n\t" - "eors r3, r5, r1\n\t" - "eors r4, r6, r2\n\t" - "lsl r5, r3, #14\n\t" - "orr r5, r5, r4, lsr #18\n\t" - "lsl r6, r4, #14\n\t" - "orr r6, r6, r3, lsr #18\n\t" - "stm r12!, { r5, r6 }\n\t" - "\n\t" - "subs r0, #200\n\t" - "\n\t" - "@ At that point, the stack buffer at sp+32 contains the words\n\t" - "@ at the following indexes (0 to 24) and offsets (from sp)\n\t" - "@ A[ 0] 0 32\n\t" - "@ A[ 1] 1 40\n\t" - "@ A[ 2] 10 112\n\t" - "@ A[ 3] 11 120\n\t" - "@ A[ 4] 20 192\n\t" - "@ A[ 5] 2 48\n\t" - "@ A[ 6] 3 56\n\t" - "@ A[ 7] 12 128\n\t" - "@ A[ 8] 13 136\n\t" - "@ A[ 9] 21 200\n\t" - "@ A[10] 4 64\n\t" - "@ A[11] 5 72\n\t" - "@ A[12] 14 144\n\t" - "@ A[13] 15 152\n\t" - "@ A[14] 22 208\n\t" - "@ A[15] 6 80\n\t" - "@ A[16] 7 88\n\t" - "@ A[17] 16 160\n\t" - "@ A[18] 17 168\n\t" - "@ A[19] 23 216\n\t" - "@ A[20] 8 96\n\t" - "@ A[21] 9 104\n\t" - "@ A[22] 18 176\n\t" - "@ A[23] 19 184\n\t" - "@ A[24] 24 224\n\t" - -#define KHI_LOAD(s0, s1, s2, s3, s4) \ - "ldr r1, [sp, #(32 + 8 * " #s0 ")]\n\t" \ - "ldr r2, [sp, #(36 + 8 * " #s0 ")]\n\t" \ - "ldr r3, [sp, #(32 + 8 * " #s1 ")]\n\t" \ - "ldr r4, [sp, #(36 + 8 * " #s1 ")]\n\t" \ - "ldr r5, [sp, #(32 + 8 * " #s2 ")]\n\t" \ - "ldr r6, [sp, #(36 + 8 * " #s2 ")]\n\t" \ - "ldr r7, [sp, #(32 + 8 * " #s3 ")]\n\t" \ - "ldr r8, [sp, #(36 + 8 * " #s3 ")]\n\t" \ - "ldr r10, [sp, #(32 + 8 * " #s4 ")]\n\t" \ - "ldr r11, [sp, #(36 + 8 * " #s4 ")]\n\t" - -#define KHI_STEP(op, x0, x1, x2, x3, x4, x5, d) \ - #op " r12, " #x0 ", " #x2 "\n\t" \ - "eors r12, " #x4 "\n\t" \ - "str r12, [r0, #(8 * " #d ")]\n\t" \ - #op " r12, " #x1 ", " #x3 "\n\t" \ - "eors r12, " #x5 "\n\t" \ - "str r12, [r0, #(4 + 8 * " #d ")]\n\t" - - "@ A[0], A[6], A[12], A[18] and A[24]\n\t" - KHI_LOAD(0, 3, 14, 17, 24) - KHI_STEP(orrs, r3, r4, r5, r6, r1, r2, 0) - KHI_STEP(orns, r7, r8, r5, r6, r3, r4, 1) - KHI_STEP(ands, r7, r8, r10, r11, r5, r6, 2) - KHI_STEP(orrs, r1, r2, r10, r11, r7, r8, 3) - KHI_STEP(ands, r1, r2, r3, r4, r10, r11, 4) - "\n\t" - - "@ A[3], A[9], A[10], A[16] and A[22]\n\t" - KHI_LOAD(11, 21, 4, 7, 18) - KHI_STEP(orrs, r3, r4, r5, r6, r1, r2, 5) - KHI_STEP(ands, r7, r8, r5, r6, r3, r4, 6) - KHI_STEP(orns, r7, r8, r10, r11, r5, r6, 7) - KHI_STEP(orrs, r1, r2, r10, r11, r7, r8, 8) - KHI_STEP(ands, r1, r2, r3, r4, r10, r11, 9) - "\n\t" - - "@ A[1], A[7], A[13], A[19] and A[20]\n\t" - KHI_LOAD(1, 12, 15, 23, 8) - KHI_STEP(orrs, r3, r4, r5, r6, r1, r2, 10) - KHI_STEP(ands, r7, r8, r5, r6, r3, r4, 11) - KHI_STEP(bics, r10, r11, r7, r8, r5, r6, 12) - "mvns r7, r7\n\t" - "mvns r8, r8\n\t" - KHI_STEP(orrs, r1, r2, r10, r11, r7, r8, 13) - KHI_STEP(ands, r1, r2, r3, r4, r10, r11, 14) - "\n\t" - - "@ A[4], A[5], A[11], A[17] and A[23]\n\t" - KHI_LOAD(20, 2, 5, 16, 19) - KHI_STEP(ands, r3, r4, r5, r6, r1, r2, 15) - KHI_STEP(orrs, r7, r8, r5, r6, r3, r4, 16) - KHI_STEP(orns, r10, r11, r7, r8, r5, r6, 17) - "mvns r7, r7\n\t" - "mvns r8, r8\n\t" - KHI_STEP(ands, r1, r2, r10, r11, r7, r8, 18) - KHI_STEP(orrs, r1, r2, r3, r4, r10, r11, 19) - "\n\t" - - "@ A[2], A[8], A[14], A[15] and A[21]\n\t" - KHI_LOAD(10, 13, 22, 6, 9) - KHI_STEP(bics, r5, r6, r3, r4, r1, r2, 20) - KHI_STEP(ands, r1, r2, r3, r4, r10, r11, 24) - "mvns r3, r3\n\t" - "mvns r4, r4\n\t" - KHI_STEP(orrs, r7, r8, r5, r6, r3, r4, 21) - KHI_STEP(ands, r7, r8, r10, r11, r5, r6, 22) - KHI_STEP(orrs, r1, r2, r10, r11, r7, r8, 23) - "\n\t" - - "@ Get round counter XOR round constant into A[0]\n\t" - "ldr r1, [sp, #0]\n\t" - "adr r2, .process_block_RC\n\t" - "adds r2, r1\n\t" - "ldm r2, { r3, r4 }\n\t" - "ldm r0, { r5, r6 }\n\t" - "eors r5, r3\n\t" - "eors r6, r4\n\t" - "stm r0, { r5, r6 }\n\t" - "\n\t" - "@ Increment round counter, loop until all 24 rounds are done.\n\t" - "\n\t" - "adds r1, #8\n\t" - "str r1, [sp, #0]\n\t" - "cmp r1, #192\n\t" - "blo .process_block_loop\n\t" - - INVERT_WORDS - - "add sp, sp, #232\n\t" - "pop { r1, r2, r3, r4, r5, r6, r7, r8, r10, r11, r12, pc }\n\t" - "\n\t" -".process_block_RC:\n\t" - ".word 0x00000001\n\t" - ".word 0x00000000\n\t" - ".word 0x00008082\n\t" - ".word 0x00000000\n\t" - ".word 0x0000808A\n\t" - ".word 0x80000000\n\t" - ".word 0x80008000\n\t" - ".word 0x80000000\n\t" - ".word 0x0000808B\n\t" - ".word 0x00000000\n\t" - ".word 0x80000001\n\t" - ".word 0x00000000\n\t" - ".word 0x80008081\n\t" - ".word 0x80000000\n\t" - ".word 0x00008009\n\t" - ".word 0x80000000\n\t" - ".word 0x0000008A\n\t" - ".word 0x00000000\n\t" - ".word 0x00000088\n\t" - ".word 0x00000000\n\t" - ".word 0x80008009\n\t" - ".word 0x00000000\n\t" - ".word 0x8000000A\n\t" - ".word 0x00000000\n\t" - ".word 0x8000808B\n\t" - ".word 0x00000000\n\t" - ".word 0x0000008B\n\t" - ".word 0x80000000\n\t" - ".word 0x00008089\n\t" - ".word 0x80000000\n\t" - ".word 0x00008003\n\t" - ".word 0x80000000\n\t" - ".word 0x00008002\n\t" - ".word 0x80000000\n\t" - ".word 0x00000080\n\t" - ".word 0x80000000\n\t" - ".word 0x0000800A\n\t" - ".word 0x00000000\n\t" - ".word 0x8000000A\n\t" - ".word 0x80000000\n\t" - ".word 0x80008081\n\t" - ".word 0x80000000\n\t" - ".word 0x00008080\n\t" - ".word 0x80000000\n\t" - ".word 0x80000001\n\t" - ".word 0x00000000\n\t" - ".word 0x80008008\n\t" - ".word 0x80000000\n\t" - -#undef INVERT_WORDS -#undef KHI_LOAD -#undef KHI_STEP - - ); -} - -#else // yyyASM_CORTEXM4+0 - -/* - * Round constants. - */ -static const uint64_t RC[] = { - 0x0000000000000001, 0x0000000000008082, - 0x800000000000808A, 0x8000000080008000, - 0x000000000000808B, 0x0000000080000001, - 0x8000000080008081, 0x8000000000008009, - 0x000000000000008A, 0x0000000000000088, - 0x0000000080008009, 0x000000008000000A, - 0x000000008000808B, 0x800000000000008B, - 0x8000000000008089, 0x8000000000008003, - 0x8000000000008002, 0x8000000000000080, - 0x000000000000800A, 0x800000008000000A, - 0x8000000080008081, 0x8000000000008080, - 0x0000000080000001, 0x8000000080008008 -}; - -/* - * Process the provided state. - */ -static void -process_block(uint64_t *A) -{ - uint64_t t0, t1, t2, t3, t4; - uint64_t tt0, tt1, tt2, tt3; - uint64_t t, kt; - uint64_t c0, c1, c2, c3, c4, bnn; - int j; - - /* - * Invert some words (alternate internal representation, which - * saves some operations). - */ - A[ 1] = ~A[ 1]; - A[ 2] = ~A[ 2]; - A[ 8] = ~A[ 8]; - A[12] = ~A[12]; - A[17] = ~A[17]; - A[20] = ~A[20]; - - /* - * Compute the 24 rounds. This loop is partially unrolled (each - * iteration computes two rounds). - */ - for (j = 0; j < 24; j += 2) { - - tt0 = A[ 1] ^ A[ 6]; - tt1 = A[11] ^ A[16]; - tt0 ^= A[21] ^ tt1; - tt0 = (tt0 << 1) | (tt0 >> 63); - tt2 = A[ 4] ^ A[ 9]; - tt3 = A[14] ^ A[19]; - tt0 ^= A[24]; - tt2 ^= tt3; - t0 = tt0 ^ tt2; - - tt0 = A[ 2] ^ A[ 7]; - tt1 = A[12] ^ A[17]; - tt0 ^= A[22] ^ tt1; - tt0 = (tt0 << 1) | (tt0 >> 63); - tt2 = A[ 0] ^ A[ 5]; - tt3 = A[10] ^ A[15]; - tt0 ^= A[20]; - tt2 ^= tt3; - t1 = tt0 ^ tt2; - - tt0 = A[ 3] ^ A[ 8]; - tt1 = A[13] ^ A[18]; - tt0 ^= A[23] ^ tt1; - tt0 = (tt0 << 1) | (tt0 >> 63); - tt2 = A[ 1] ^ A[ 6]; - tt3 = A[11] ^ A[16]; - tt0 ^= A[21]; - tt2 ^= tt3; - t2 = tt0 ^ tt2; - - tt0 = A[ 4] ^ A[ 9]; - tt1 = A[14] ^ A[19]; - tt0 ^= A[24] ^ tt1; - tt0 = (tt0 << 1) | (tt0 >> 63); - tt2 = A[ 2] ^ A[ 7]; - tt3 = A[12] ^ A[17]; - tt0 ^= A[22]; - tt2 ^= tt3; - t3 = tt0 ^ tt2; - - tt0 = A[ 0] ^ A[ 5]; - tt1 = A[10] ^ A[15]; - tt0 ^= A[20] ^ tt1; - tt0 = (tt0 << 1) | (tt0 >> 63); - tt2 = A[ 3] ^ A[ 8]; - tt3 = A[13] ^ A[18]; - tt0 ^= A[23]; - tt2 ^= tt3; - t4 = tt0 ^ tt2; - - A[ 0] = A[ 0] ^ t0; - A[ 5] = A[ 5] ^ t0; - A[10] = A[10] ^ t0; - A[15] = A[15] ^ t0; - A[20] = A[20] ^ t0; - A[ 1] = A[ 1] ^ t1; - A[ 6] = A[ 6] ^ t1; - A[11] = A[11] ^ t1; - A[16] = A[16] ^ t1; - A[21] = A[21] ^ t1; - A[ 2] = A[ 2] ^ t2; - A[ 7] = A[ 7] ^ t2; - A[12] = A[12] ^ t2; - A[17] = A[17] ^ t2; - A[22] = A[22] ^ t2; - A[ 3] = A[ 3] ^ t3; - A[ 8] = A[ 8] ^ t3; - A[13] = A[13] ^ t3; - A[18] = A[18] ^ t3; - A[23] = A[23] ^ t3; - A[ 4] = A[ 4] ^ t4; - A[ 9] = A[ 9] ^ t4; - A[14] = A[14] ^ t4; - A[19] = A[19] ^ t4; - A[24] = A[24] ^ t4; - A[ 5] = (A[ 5] << 36) | (A[ 5] >> (64 - 36)); - A[10] = (A[10] << 3) | (A[10] >> (64 - 3)); - A[15] = (A[15] << 41) | (A[15] >> (64 - 41)); - A[20] = (A[20] << 18) | (A[20] >> (64 - 18)); - A[ 1] = (A[ 1] << 1) | (A[ 1] >> (64 - 1)); - A[ 6] = (A[ 6] << 44) | (A[ 6] >> (64 - 44)); - A[11] = (A[11] << 10) | (A[11] >> (64 - 10)); - A[16] = (A[16] << 45) | (A[16] >> (64 - 45)); - A[21] = (A[21] << 2) | (A[21] >> (64 - 2)); - A[ 2] = (A[ 2] << 62) | (A[ 2] >> (64 - 62)); - A[ 7] = (A[ 7] << 6) | (A[ 7] >> (64 - 6)); - A[12] = (A[12] << 43) | (A[12] >> (64 - 43)); - A[17] = (A[17] << 15) | (A[17] >> (64 - 15)); - A[22] = (A[22] << 61) | (A[22] >> (64 - 61)); - A[ 3] = (A[ 3] << 28) | (A[ 3] >> (64 - 28)); - A[ 8] = (A[ 8] << 55) | (A[ 8] >> (64 - 55)); - A[13] = (A[13] << 25) | (A[13] >> (64 - 25)); - A[18] = (A[18] << 21) | (A[18] >> (64 - 21)); - A[23] = (A[23] << 56) | (A[23] >> (64 - 56)); - A[ 4] = (A[ 4] << 27) | (A[ 4] >> (64 - 27)); - A[ 9] = (A[ 9] << 20) | (A[ 9] >> (64 - 20)); - A[14] = (A[14] << 39) | (A[14] >> (64 - 39)); - A[19] = (A[19] << 8) | (A[19] >> (64 - 8)); - A[24] = (A[24] << 14) | (A[24] >> (64 - 14)); - - bnn = ~A[12]; - kt = A[ 6] | A[12]; - c0 = A[ 0] ^ kt; - kt = bnn | A[18]; - c1 = A[ 6] ^ kt; - kt = A[18] & A[24]; - c2 = A[12] ^ kt; - kt = A[24] | A[ 0]; - c3 = A[18] ^ kt; - kt = A[ 0] & A[ 6]; - c4 = A[24] ^ kt; - A[ 0] = c0; - A[ 6] = c1; - A[12] = c2; - A[18] = c3; - A[24] = c4; - bnn = ~A[22]; - kt = A[ 9] | A[10]; - c0 = A[ 3] ^ kt; - kt = A[10] & A[16]; - c1 = A[ 9] ^ kt; - kt = A[16] | bnn; - c2 = A[10] ^ kt; - kt = A[22] | A[ 3]; - c3 = A[16] ^ kt; - kt = A[ 3] & A[ 9]; - c4 = A[22] ^ kt; - A[ 3] = c0; - A[ 9] = c1; - A[10] = c2; - A[16] = c3; - A[22] = c4; - bnn = ~A[19]; - kt = A[ 7] | A[13]; - c0 = A[ 1] ^ kt; - kt = A[13] & A[19]; - c1 = A[ 7] ^ kt; - kt = bnn & A[20]; - c2 = A[13] ^ kt; - kt = A[20] | A[ 1]; - c3 = bnn ^ kt; - kt = A[ 1] & A[ 7]; - c4 = A[20] ^ kt; - A[ 1] = c0; - A[ 7] = c1; - A[13] = c2; - A[19] = c3; - A[20] = c4; - bnn = ~A[17]; - kt = A[ 5] & A[11]; - c0 = A[ 4] ^ kt; - kt = A[11] | A[17]; - c1 = A[ 5] ^ kt; - kt = bnn | A[23]; - c2 = A[11] ^ kt; - kt = A[23] & A[ 4]; - c3 = bnn ^ kt; - kt = A[ 4] | A[ 5]; - c4 = A[23] ^ kt; - A[ 4] = c0; - A[ 5] = c1; - A[11] = c2; - A[17] = c3; - A[23] = c4; - bnn = ~A[ 8]; - kt = bnn & A[14]; - c0 = A[ 2] ^ kt; - kt = A[14] | A[15]; - c1 = bnn ^ kt; - kt = A[15] & A[21]; - c2 = A[14] ^ kt; - kt = A[21] | A[ 2]; - c3 = A[15] ^ kt; - kt = A[ 2] & A[ 8]; - c4 = A[21] ^ kt; - A[ 2] = c0; - A[ 8] = c1; - A[14] = c2; - A[15] = c3; - A[21] = c4; - A[ 0] = A[ 0] ^ RC[j + 0]; - - tt0 = A[ 6] ^ A[ 9]; - tt1 = A[ 7] ^ A[ 5]; - tt0 ^= A[ 8] ^ tt1; - tt0 = (tt0 << 1) | (tt0 >> 63); - tt2 = A[24] ^ A[22]; - tt3 = A[20] ^ A[23]; - tt0 ^= A[21]; - tt2 ^= tt3; - t0 = tt0 ^ tt2; - - tt0 = A[12] ^ A[10]; - tt1 = A[13] ^ A[11]; - tt0 ^= A[14] ^ tt1; - tt0 = (tt0 << 1) | (tt0 >> 63); - tt2 = A[ 0] ^ A[ 3]; - tt3 = A[ 1] ^ A[ 4]; - tt0 ^= A[ 2]; - tt2 ^= tt3; - t1 = tt0 ^ tt2; - - tt0 = A[18] ^ A[16]; - tt1 = A[19] ^ A[17]; - tt0 ^= A[15] ^ tt1; - tt0 = (tt0 << 1) | (tt0 >> 63); - tt2 = A[ 6] ^ A[ 9]; - tt3 = A[ 7] ^ A[ 5]; - tt0 ^= A[ 8]; - tt2 ^= tt3; - t2 = tt0 ^ tt2; - - tt0 = A[24] ^ A[22]; - tt1 = A[20] ^ A[23]; - tt0 ^= A[21] ^ tt1; - tt0 = (tt0 << 1) | (tt0 >> 63); - tt2 = A[12] ^ A[10]; - tt3 = A[13] ^ A[11]; - tt0 ^= A[14]; - tt2 ^= tt3; - t3 = tt0 ^ tt2; - - tt0 = A[ 0] ^ A[ 3]; - tt1 = A[ 1] ^ A[ 4]; - tt0 ^= A[ 2] ^ tt1; - tt0 = (tt0 << 1) | (tt0 >> 63); - tt2 = A[18] ^ A[16]; - tt3 = A[19] ^ A[17]; - tt0 ^= A[15]; - tt2 ^= tt3; - t4 = tt0 ^ tt2; - - A[ 0] = A[ 0] ^ t0; - A[ 3] = A[ 3] ^ t0; - A[ 1] = A[ 1] ^ t0; - A[ 4] = A[ 4] ^ t0; - A[ 2] = A[ 2] ^ t0; - A[ 6] = A[ 6] ^ t1; - A[ 9] = A[ 9] ^ t1; - A[ 7] = A[ 7] ^ t1; - A[ 5] = A[ 5] ^ t1; - A[ 8] = A[ 8] ^ t1; - A[12] = A[12] ^ t2; - A[10] = A[10] ^ t2; - A[13] = A[13] ^ t2; - A[11] = A[11] ^ t2; - A[14] = A[14] ^ t2; - A[18] = A[18] ^ t3; - A[16] = A[16] ^ t3; - A[19] = A[19] ^ t3; - A[17] = A[17] ^ t3; - A[15] = A[15] ^ t3; - A[24] = A[24] ^ t4; - A[22] = A[22] ^ t4; - A[20] = A[20] ^ t4; - A[23] = A[23] ^ t4; - A[21] = A[21] ^ t4; - A[ 3] = (A[ 3] << 36) | (A[ 3] >> (64 - 36)); - A[ 1] = (A[ 1] << 3) | (A[ 1] >> (64 - 3)); - A[ 4] = (A[ 4] << 41) | (A[ 4] >> (64 - 41)); - A[ 2] = (A[ 2] << 18) | (A[ 2] >> (64 - 18)); - A[ 6] = (A[ 6] << 1) | (A[ 6] >> (64 - 1)); - A[ 9] = (A[ 9] << 44) | (A[ 9] >> (64 - 44)); - A[ 7] = (A[ 7] << 10) | (A[ 7] >> (64 - 10)); - A[ 5] = (A[ 5] << 45) | (A[ 5] >> (64 - 45)); - A[ 8] = (A[ 8] << 2) | (A[ 8] >> (64 - 2)); - A[12] = (A[12] << 62) | (A[12] >> (64 - 62)); - A[10] = (A[10] << 6) | (A[10] >> (64 - 6)); - A[13] = (A[13] << 43) | (A[13] >> (64 - 43)); - A[11] = (A[11] << 15) | (A[11] >> (64 - 15)); - A[14] = (A[14] << 61) | (A[14] >> (64 - 61)); - A[18] = (A[18] << 28) | (A[18] >> (64 - 28)); - A[16] = (A[16] << 55) | (A[16] >> (64 - 55)); - A[19] = (A[19] << 25) | (A[19] >> (64 - 25)); - A[17] = (A[17] << 21) | (A[17] >> (64 - 21)); - A[15] = (A[15] << 56) | (A[15] >> (64 - 56)); - A[24] = (A[24] << 27) | (A[24] >> (64 - 27)); - A[22] = (A[22] << 20) | (A[22] >> (64 - 20)); - A[20] = (A[20] << 39) | (A[20] >> (64 - 39)); - A[23] = (A[23] << 8) | (A[23] >> (64 - 8)); - A[21] = (A[21] << 14) | (A[21] >> (64 - 14)); - - bnn = ~A[13]; - kt = A[ 9] | A[13]; - c0 = A[ 0] ^ kt; - kt = bnn | A[17]; - c1 = A[ 9] ^ kt; - kt = A[17] & A[21]; - c2 = A[13] ^ kt; - kt = A[21] | A[ 0]; - c3 = A[17] ^ kt; - kt = A[ 0] & A[ 9]; - c4 = A[21] ^ kt; - A[ 0] = c0; - A[ 9] = c1; - A[13] = c2; - A[17] = c3; - A[21] = c4; - bnn = ~A[14]; - kt = A[22] | A[ 1]; - c0 = A[18] ^ kt; - kt = A[ 1] & A[ 5]; - c1 = A[22] ^ kt; - kt = A[ 5] | bnn; - c2 = A[ 1] ^ kt; - kt = A[14] | A[18]; - c3 = A[ 5] ^ kt; - kt = A[18] & A[22]; - c4 = A[14] ^ kt; - A[18] = c0; - A[22] = c1; - A[ 1] = c2; - A[ 5] = c3; - A[14] = c4; - bnn = ~A[23]; - kt = A[10] | A[19]; - c0 = A[ 6] ^ kt; - kt = A[19] & A[23]; - c1 = A[10] ^ kt; - kt = bnn & A[ 2]; - c2 = A[19] ^ kt; - kt = A[ 2] | A[ 6]; - c3 = bnn ^ kt; - kt = A[ 6] & A[10]; - c4 = A[ 2] ^ kt; - A[ 6] = c0; - A[10] = c1; - A[19] = c2; - A[23] = c3; - A[ 2] = c4; - bnn = ~A[11]; - kt = A[ 3] & A[ 7]; - c0 = A[24] ^ kt; - kt = A[ 7] | A[11]; - c1 = A[ 3] ^ kt; - kt = bnn | A[15]; - c2 = A[ 7] ^ kt; - kt = A[15] & A[24]; - c3 = bnn ^ kt; - kt = A[24] | A[ 3]; - c4 = A[15] ^ kt; - A[24] = c0; - A[ 3] = c1; - A[ 7] = c2; - A[11] = c3; - A[15] = c4; - bnn = ~A[16]; - kt = bnn & A[20]; - c0 = A[12] ^ kt; - kt = A[20] | A[ 4]; - c1 = bnn ^ kt; - kt = A[ 4] & A[ 8]; - c2 = A[20] ^ kt; - kt = A[ 8] | A[12]; - c3 = A[ 4] ^ kt; - kt = A[12] & A[16]; - c4 = A[ 8] ^ kt; - A[12] = c0; - A[16] = c1; - A[20] = c2; - A[ 4] = c3; - A[ 8] = c4; - A[ 0] = A[ 0] ^ RC[j + 1]; - t = A[ 5]; - A[ 5] = A[18]; - A[18] = A[11]; - A[11] = A[10]; - A[10] = A[ 6]; - A[ 6] = A[22]; - A[22] = A[20]; - A[20] = A[12]; - A[12] = A[19]; - A[19] = A[15]; - A[15] = A[24]; - A[24] = A[ 8]; - A[ 8] = t; - t = A[ 1]; - A[ 1] = A[ 9]; - A[ 9] = A[14]; - A[14] = A[ 2]; - A[ 2] = A[13]; - A[13] = A[23]; - A[23] = A[ 4]; - A[ 4] = A[21]; - A[21] = A[16]; - A[16] = A[ 3]; - A[ 3] = A[17]; - A[17] = A[ 7]; - A[ 7] = t; - } - - /* - * Invert some words back to normal representation. - */ - A[ 1] = ~A[ 1]; - A[ 2] = ~A[ 2]; - A[ 8] = ~A[ 8]; - A[12] = ~A[12]; - A[17] = ~A[17]; - A[20] = ~A[20]; -} - -#endif // yyyASM_CORTEXM4- - -/* see inner.h */ -void -Zf(i_shake256_init)(inner_shake256_context *sc) -{ - sc->dptr = 0; - - /* - * Representation of an all-ones uint64_t is the same regardless - * of local endianness. - */ - memset(sc->st.A, 0, sizeof sc->st.A); -} - -/* see inner.h */ -void -Zf(i_shake256_inject)(inner_shake256_context *sc, const uint8_t *in, size_t len) -{ - size_t dptr; - - dptr = (size_t)sc->dptr; - while (len > 0) { - size_t clen, u; - - clen = 136 - dptr; - if (clen > len) { - clen = len; - } -#if FALCON_LE // yyyLE+1 - for (u = 0; u < clen; u ++) { - sc->st.dbuf[dptr + u] ^= in[u]; - } -#else // yyyLE+0 - for (u = 0; u < clen; u ++) { - size_t v; - - v = u + dptr; - sc->st.A[v >> 3] ^= (uint64_t)in[u] << ((v & 7) << 3); - } -#endif // yyyLE- - dptr += clen; - in += clen; - len -= clen; - if (dptr == 136) { - process_block(sc->st.A); - dptr = 0; - } - } - sc->dptr = dptr; -} - -/* see falcon.h */ -void -Zf(i_shake256_flip)(inner_shake256_context *sc) -{ - /* - * We apply padding and pre-XOR the value into the state. We - * set dptr to the end of the buffer, so that first call to - * shake_extract() will process the block. - */ -#if FALCON_LE // yyyLE+1 - sc->st.dbuf[sc->dptr] ^= 0x1F; - sc->st.dbuf[135] ^= 0x80; -#else // yyyLE+0 - unsigned v; - - v = sc->dptr; - sc->st.A[v >> 3] ^= (uint64_t)0x1F << ((v & 7) << 3); - sc->st.A[16] ^= (uint64_t)0x80 << 56; -#endif // yyyLE- - sc->dptr = 136; -} - -/* see falcon.h */ -void -Zf(i_shake256_extract)(inner_shake256_context *sc, uint8_t *out, size_t len) -{ - size_t dptr; - - dptr = (size_t)sc->dptr; - while (len > 0) { - size_t clen; - - if (dptr == 136) { - process_block(sc->st.A); - dptr = 0; - } - clen = 136 - dptr; - if (clen > len) { - clen = len; - } - len -= clen; -#if FALCON_LE // yyyLE+1 - memcpy(out, sc->st.dbuf + dptr, clen); - dptr += clen; - out += clen; -#else // yyyLE+0 - while (clen -- > 0) { - *out ++ = sc->st.A[dptr >> 3] >> ((dptr & 7) << 3); - dptr ++; - } -#endif // yyyLE- - } - sc->dptr = dptr; -} diff --git a/falcon/sign.c b/falcon/sign.c deleted file mode 100644 index 24fa8d6..0000000 --- a/falcon/sign.c +++ /dev/null @@ -1,1528 +0,0 @@ -/* - * Falcon signature generation. - * - * ==========================(LICENSE BEGIN)============================ - * - * Copyright (c) 2017-2019 Falcon Project - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * ===========================(LICENSE END)============================= - * - * @author Thomas Pornin - */ - -#include "inner.h" - -/* =================================================================== */ - -/* - * Compute degree N from logarithm 'logn'. - */ -#define MKN(logn) ((size_t)1 << (logn)) - -/* =================================================================== */ -/* - * Binary case: - * N = 2^logn - * phi = X^N+1 - */ - -/* - * Get the size of the LDL tree for an input with polynomials of size - * 2^logn. The size is expressed in the number of elements. - */ -static inline unsigned -ffLDL_treesize(unsigned logn) -{ - /* - * For logn = 0 (polynomials are constant), the "tree" is a - * single element. Otherwise, the tree node has size 2^logn, and - * has two child trees for size logn-1 each. Thus, treesize s() - * must fulfill these two relations: - * - * s(0) = 1 - * s(logn) = (2^logn) + 2*s(logn-1) - */ - return (logn + 1) << logn; -} - -/* - * Inner function for ffLDL_fft(). It expects the matrix to be both - * auto-adjoint and quasicyclic; also, it uses the source operands - * as modifiable temporaries. - * - * tmp[] must have room for at least one polynomial. - */ -static void -ffLDL_fft_inner(fpr *restrict tree, - fpr *restrict g0, fpr *restrict g1, unsigned logn, fpr *restrict tmp) -{ - size_t n, hn; - - n = MKN(logn); - if (n == 1) { - tree[0] = g0[0]; - return; - } - hn = n >> 1; - - /* - * The LDL decomposition yields L (which is written in the tree) - * and the diagonal of D. Since d00 = g0, we just write d11 - * into tmp. - */ - Zf(poly_LDLmv_fft)(tmp, tree, g0, g1, g0, logn); - - /* - * Split d00 (currently in g0) and d11 (currently in tmp). We - * reuse g0 and g1 as temporary storage spaces: - * d00 splits into g1, g1+hn - * d11 splits into g0, g0+hn - */ - Zf(poly_split_fft)(g1, g1 + hn, g0, logn); - Zf(poly_split_fft)(g0, g0 + hn, tmp, logn); - - /* - * Each split result is the first row of a new auto-adjoint - * quasicyclic matrix for the next recursive step. - */ - ffLDL_fft_inner(tree + n, - g1, g1 + hn, logn - 1, tmp); - ffLDL_fft_inner(tree + n + ffLDL_treesize(logn - 1), - g0, g0 + hn, logn - 1, tmp); -} - -/* - * Compute the ffLDL tree of an auto-adjoint matrix G. The matrix - * is provided as three polynomials (FFT representation). - * - * The "tree" array is filled with the computed tree, of size - * (logn+1)*(2^logn) elements (see ffLDL_treesize()). - * - * Input arrays MUST NOT overlap, except possibly the three unmodified - * arrays g00, g01 and g11. tmp[] should have room for at least three - * polynomials of 2^logn elements each. - */ -static void -ffLDL_fft(fpr *restrict tree, const fpr *restrict g00, - const fpr *restrict g01, const fpr *restrict g11, - unsigned logn, fpr *restrict tmp) -{ - size_t n, hn; - fpr *d00, *d11; - - n = MKN(logn); - if (n == 1) { - tree[0] = g00[0]; - return; - } - hn = n >> 1; - d00 = tmp; - d11 = tmp + n; - tmp += n << 1; - - memcpy(d00, g00, n * sizeof *g00); - Zf(poly_LDLmv_fft)(d11, tree, g00, g01, g11, logn); - - Zf(poly_split_fft)(tmp, tmp + hn, d00, logn); - Zf(poly_split_fft)(d00, d00 + hn, d11, logn); - memcpy(d11, tmp, n * sizeof *tmp); - ffLDL_fft_inner(tree + n, - d11, d11 + hn, logn - 1, tmp); - ffLDL_fft_inner(tree + n + ffLDL_treesize(logn - 1), - d00, d00 + hn, logn - 1, tmp); -} - -/* - * Normalize an ffLDL tree: each leaf of value x is replaced with - * sigma / sqrt(x). - */ -static void -ffLDL_binary_normalize(fpr *tree, unsigned orig_logn, unsigned logn) -{ - /* - * TODO: make an iterative version. - */ - size_t n; - - n = MKN(logn); - if (n == 1) { - /* - * We actually store in the tree leaf the inverse of - * the value mandated by the specification: this - * saves a division both here and in the sampler. - */ - tree[0] = fpr_mul(fpr_sqrt(tree[0]), fpr_inv_sigma[orig_logn]); - } else { - ffLDL_binary_normalize(tree + n, orig_logn, logn - 1); - ffLDL_binary_normalize(tree + n + ffLDL_treesize(logn - 1), - orig_logn, logn - 1); - } -} - -/* =================================================================== */ - -/* - * Convert an integer polynomial (with small values) into the - * representation with complex numbers. - */ -static void -smallints_to_fpr(fpr *r, const int8_t *t, unsigned logn) -{ - size_t n, u; - - n = MKN(logn); - for (u = 0; u < n; u ++) { - r[u] = fpr_of(t[u]); - } -} - -/* - * The expanded private key contains: - * - The B0 matrix (four elements) - * - The ffLDL tree - */ - -static inline size_t -skoff_b00(unsigned logn) -{ - (void)logn; - return 0; -} - -static inline size_t -skoff_b01(unsigned logn) -{ - return MKN(logn); -} - -static inline size_t -skoff_b10(unsigned logn) -{ - return 2 * MKN(logn); -} - -static inline size_t -skoff_b11(unsigned logn) -{ - return 3 * MKN(logn); -} - -static inline size_t -skoff_tree(unsigned logn) -{ - return 4 * MKN(logn); -} - -/* see inner.h */ -void -Zf(expand_privkey)(fpr *restrict expanded_key, - const int8_t *f, const int8_t *g, - const int8_t *F, const int8_t *G, - unsigned logn, uint8_t *restrict tmp) -{ - size_t n; - fpr *rf, *rg, *rF, *rG; - fpr *b00, *b01, *b10, *b11; - fpr *g00, *g01, *g11, *gxx; - fpr *tree; - - n = MKN(logn); - b00 = expanded_key + skoff_b00(logn); - b01 = expanded_key + skoff_b01(logn); - b10 = expanded_key + skoff_b10(logn); - b11 = expanded_key + skoff_b11(logn); - tree = expanded_key + skoff_tree(logn); - - /* - * We load the private key elements directly into the B0 matrix, - * since B0 = [[g, -f], [G, -F]]. - */ - rf = b01; - rg = b00; - rF = b11; - rG = b10; - - smallints_to_fpr(rf, f, logn); - smallints_to_fpr(rg, g, logn); - smallints_to_fpr(rF, F, logn); - smallints_to_fpr(rG, G, logn); - - /* - * Compute the FFT for the key elements, and negate f and F. - */ - Zf(FFT)(rf, logn); - Zf(FFT)(rg, logn); - Zf(FFT)(rF, logn); - Zf(FFT)(rG, logn); - Zf(poly_neg)(rf, logn); - Zf(poly_neg)(rF, logn); - - /* - * The Gram matrix is G = B·B*. Formulas are: - * g00 = b00*adj(b00) + b01*adj(b01) - * g01 = b00*adj(b10) + b01*adj(b11) - * g10 = b10*adj(b00) + b11*adj(b01) - * g11 = b10*adj(b10) + b11*adj(b11) - * - * For historical reasons, this implementation uses - * g00, g01 and g11 (upper triangle). - */ - g00 = (fpr *)tmp; - g01 = g00 + n; - g11 = g01 + n; - gxx = g11 + n; - - memcpy(g00, b00, n * sizeof *b00); - Zf(poly_mulselfadj_fft)(g00, logn); - memcpy(gxx, b01, n * sizeof *b01); - Zf(poly_mulselfadj_fft)(gxx, logn); - Zf(poly_add)(g00, gxx, logn); - - memcpy(g01, b00, n * sizeof *b00); - Zf(poly_muladj_fft)(g01, b10, logn); - memcpy(gxx, b01, n * sizeof *b01); - Zf(poly_muladj_fft)(gxx, b11, logn); - Zf(poly_add)(g01, gxx, logn); - - memcpy(g11, b10, n * sizeof *b10); - Zf(poly_mulselfadj_fft)(g11, logn); - memcpy(gxx, b11, n * sizeof *b11); - Zf(poly_mulselfadj_fft)(gxx, logn); - Zf(poly_add)(g11, gxx, logn); - - /* - * Compute the Falcon tree. - */ - ffLDL_fft(tree, g00, g01, g11, logn, gxx); - - /* - * Normalize tree. - */ - ffLDL_binary_normalize(tree, logn, logn); -} - -typedef int (*samplerZ)(void *ctx, fpr mu, fpr sigma); - -/* - * Perform Fast Fourier Sampling for target vector t. The Gram matrix - * is provided (G = [[g00, g01], [adj(g01), g11]]). The sampled vector - * is written over (t0,t1). The Gram matrix is modified as well. The - * tmp[] buffer must have room for four polynomials. - */ -TARGET_AVX2 -static void -ffSampling_fft_dyntree(samplerZ samp, void *samp_ctx, - fpr *restrict t0, fpr *restrict t1, - fpr *restrict g00, fpr *restrict g01, fpr *restrict g11, - unsigned orig_logn, unsigned logn, fpr *restrict tmp) -{ - size_t n, hn; - fpr *z0, *z1; - - /* - * Deepest level: the LDL tree leaf value is just g00 (the - * array has length only 1 at this point); we normalize it - * with regards to sigma, then use it for sampling. - */ - if (logn == 0) { - fpr leaf; - - leaf = g00[0]; - leaf = fpr_mul(fpr_sqrt(leaf), fpr_inv_sigma[orig_logn]); - t0[0] = fpr_of(samp(samp_ctx, t0[0], leaf)); - t1[0] = fpr_of(samp(samp_ctx, t1[0], leaf)); - return; - } - - n = (size_t)1 << logn; - hn = n >> 1; - - /* - * Decompose G into LDL. We only need d00 (identical to g00), - * d11, and l10; we do that in place. - */ - Zf(poly_LDL_fft)(g00, g01, g11, logn); - - /* - * Split d00 and d11 and expand them into half-size quasi-cyclic - * Gram matrices. We also save l10 in tmp[]. - */ - Zf(poly_split_fft)(tmp, tmp + hn, g00, logn); - memcpy(g00, tmp, n * sizeof *tmp); - Zf(poly_split_fft)(tmp, tmp + hn, g11, logn); - memcpy(g11, tmp, n * sizeof *tmp); - memcpy(tmp, g01, n * sizeof *g01); - memcpy(g01, g00, hn * sizeof *g00); - memcpy(g01 + hn, g11, hn * sizeof *g00); - - /* - * The half-size Gram matrices for the recursive LDL tree - * building are now: - * - left sub-tree: g00, g00+hn, g01 - * - right sub-tree: g11, g11+hn, g01+hn - * l10 is in tmp[]. - */ - - /* - * We split t1 and use the first recursive call on the two - * halves, using the right sub-tree. The result is merged - * back into tmp + 2*n. - */ - z1 = tmp + n; - Zf(poly_split_fft)(z1, z1 + hn, t1, logn); - ffSampling_fft_dyntree(samp, samp_ctx, z1, z1 + hn, - g11, g11 + hn, g01 + hn, orig_logn, logn - 1, z1 + n); - Zf(poly_merge_fft)(tmp + (n << 1), z1, z1 + hn, logn); - - /* - * Compute tb0 = t0 + (t1 - z1) * l10. - * At that point, l10 is in tmp, t1 is unmodified, and z1 is - * in tmp + (n << 1). The buffer in z1 is free. - * - * In the end, z1 is written over t1, and tb0 is in t0. - */ - memcpy(z1, t1, n * sizeof *t1); - Zf(poly_sub)(z1, tmp + (n << 1), logn); - memcpy(t1, tmp + (n << 1), n * sizeof *tmp); - Zf(poly_mul_fft)(tmp, z1, logn); - Zf(poly_add)(t0, tmp, logn); - - /* - * Second recursive invocation, on the split tb0 (currently in t0) - * and the left sub-tree. - */ - z0 = tmp; - Zf(poly_split_fft)(z0, z0 + hn, t0, logn); - ffSampling_fft_dyntree(samp, samp_ctx, z0, z0 + hn, - g00, g00 + hn, g01, orig_logn, logn - 1, z0 + n); - Zf(poly_merge_fft)(t0, z0, z0 + hn, logn); -} - -/* - * Perform Fast Fourier Sampling for target vector t and LDL tree T. - * tmp[] must have size for at least two polynomials of size 2^logn. - */ -TARGET_AVX2 -static void -ffSampling_fft(samplerZ samp, void *samp_ctx, - fpr *restrict z0, fpr *restrict z1, - const fpr *restrict tree, - const fpr *restrict t0, const fpr *restrict t1, unsigned logn, - fpr *restrict tmp) -{ - size_t n, hn; - const fpr *tree0, *tree1; - - /* - * When logn == 2, we inline the last two recursion levels. - */ - if (logn == 2) { -#if FALCON_AVX2 // yyyAVX2+1 - fpr w0, w1, w2, w3, sigma; - __m128d ww0, ww1, wa, wb, wc, wd; - __m128d wy0, wy1, wz0, wz1; - __m128d half, invsqrt8, invsqrt2, neghi, neglo; - int si0, si1, si2, si3; - - tree0 = tree + 4; - tree1 = tree + 8; - - half = _mm_set1_pd(0.5); - invsqrt8 = _mm_set1_pd(0.353553390593273762200422181052); - invsqrt2 = _mm_set1_pd(0.707106781186547524400844362105); - neghi = _mm_set_pd(-0.0, 0.0); - neglo = _mm_set_pd(0.0, -0.0); - - /* - * We split t1 into w*, then do the recursive invocation, - * with output in w*. We finally merge back into z1. - */ - ww0 = _mm_loadu_pd(&t1[0].v); - ww1 = _mm_loadu_pd(&t1[2].v); - wa = _mm_unpacklo_pd(ww0, ww1); - wb = _mm_unpackhi_pd(ww0, ww1); - wc = _mm_add_pd(wa, wb); - ww0 = _mm_mul_pd(wc, half); - wc = _mm_sub_pd(wa, wb); - wd = _mm_xor_pd(_mm_permute_pd(wc, 1), neghi); - ww1 = _mm_mul_pd(_mm_add_pd(wc, wd), invsqrt8); - - w2.v = _mm_cvtsd_f64(ww1); - w3.v = _mm_cvtsd_f64(_mm_permute_pd(ww1, 1)); - wa = ww1; - sigma = tree1[3]; - si2 = samp(samp_ctx, w2, sigma); - si3 = samp(samp_ctx, w3, sigma); - ww1 = _mm_set_pd((double)si3, (double)si2); - wa = _mm_sub_pd(wa, ww1); - wb = _mm_loadu_pd(&tree1[0].v); - wc = _mm_mul_pd(wa, wb); - wd = _mm_mul_pd(wa, _mm_permute_pd(wb, 1)); - wa = _mm_unpacklo_pd(wc, wd); - wb = _mm_unpackhi_pd(wc, wd); - ww0 = _mm_add_pd(ww0, _mm_add_pd(wa, _mm_xor_pd(wb, neglo))); - w0.v = _mm_cvtsd_f64(ww0); - w1.v = _mm_cvtsd_f64(_mm_permute_pd(ww0, 1)); - sigma = tree1[2]; - si0 = samp(samp_ctx, w0, sigma); - si1 = samp(samp_ctx, w1, sigma); - ww0 = _mm_set_pd((double)si1, (double)si0); - - wc = _mm_mul_pd( - _mm_set_pd((double)(si2 + si3), (double)(si2 - si3)), - invsqrt2); - wa = _mm_add_pd(ww0, wc); - wb = _mm_sub_pd(ww0, wc); - ww0 = _mm_unpacklo_pd(wa, wb); - ww1 = _mm_unpackhi_pd(wa, wb); - _mm_storeu_pd(&z1[0].v, ww0); - _mm_storeu_pd(&z1[2].v, ww1); - - /* - * Compute tb0 = t0 + (t1 - z1) * L. Value tb0 ends up in w*. - */ - wy0 = _mm_sub_pd(_mm_loadu_pd(&t1[0].v), ww0); - wy1 = _mm_sub_pd(_mm_loadu_pd(&t1[2].v), ww1); - wz0 = _mm_loadu_pd(&tree[0].v); - wz1 = _mm_loadu_pd(&tree[2].v); - ww0 = _mm_sub_pd(_mm_mul_pd(wy0, wz0), _mm_mul_pd(wy1, wz1)); - ww1 = _mm_add_pd(_mm_mul_pd(wy0, wz1), _mm_mul_pd(wy1, wz0)); - ww0 = _mm_add_pd(ww0, _mm_loadu_pd(&t0[0].v)); - ww1 = _mm_add_pd(ww1, _mm_loadu_pd(&t0[2].v)); - - /* - * Second recursive invocation. - */ - wa = _mm_unpacklo_pd(ww0, ww1); - wb = _mm_unpackhi_pd(ww0, ww1); - wc = _mm_add_pd(wa, wb); - ww0 = _mm_mul_pd(wc, half); - wc = _mm_sub_pd(wa, wb); - wd = _mm_xor_pd(_mm_permute_pd(wc, 1), neghi); - ww1 = _mm_mul_pd(_mm_add_pd(wc, wd), invsqrt8); - - w2.v = _mm_cvtsd_f64(ww1); - w3.v = _mm_cvtsd_f64(_mm_permute_pd(ww1, 1)); - wa = ww1; - sigma = tree0[3]; - si2 = samp(samp_ctx, w2, sigma); - si3 = samp(samp_ctx, w3, sigma); - ww1 = _mm_set_pd((double)si3, (double)si2); - wa = _mm_sub_pd(wa, ww1); - wb = _mm_loadu_pd(&tree0[0].v); - wc = _mm_mul_pd(wa, wb); - wd = _mm_mul_pd(wa, _mm_permute_pd(wb, 1)); - wa = _mm_unpacklo_pd(wc, wd); - wb = _mm_unpackhi_pd(wc, wd); - ww0 = _mm_add_pd(ww0, _mm_add_pd(wa, _mm_xor_pd(wb, neglo))); - w0.v = _mm_cvtsd_f64(ww0); - w1.v = _mm_cvtsd_f64(_mm_permute_pd(ww0, 1)); - sigma = tree0[2]; - si0 = samp(samp_ctx, w0, sigma); - si1 = samp(samp_ctx, w1, sigma); - ww0 = _mm_set_pd((double)si1, (double)si0); - - wc = _mm_mul_pd( - _mm_set_pd((double)(si2 + si3), (double)(si2 - si3)), - invsqrt2); - wa = _mm_add_pd(ww0, wc); - wb = _mm_sub_pd(ww0, wc); - ww0 = _mm_unpacklo_pd(wa, wb); - ww1 = _mm_unpackhi_pd(wa, wb); - _mm_storeu_pd(&z0[0].v, ww0); - _mm_storeu_pd(&z0[2].v, ww1); - - return; -#else // yyyAVX2+0 - fpr x0, x1, y0, y1, w0, w1, w2, w3, sigma; - fpr a_re, a_im, b_re, b_im, c_re, c_im; - - tree0 = tree + 4; - tree1 = tree + 8; - - /* - * We split t1 into w*, then do the recursive invocation, - * with output in w*. We finally merge back into z1. - */ - a_re = t1[0]; - a_im = t1[2]; - b_re = t1[1]; - b_im = t1[3]; - c_re = fpr_add(a_re, b_re); - c_im = fpr_add(a_im, b_im); - w0 = fpr_half(c_re); - w1 = fpr_half(c_im); - c_re = fpr_sub(a_re, b_re); - c_im = fpr_sub(a_im, b_im); - w2 = fpr_mul(fpr_add(c_re, c_im), fpr_invsqrt8); - w3 = fpr_mul(fpr_sub(c_im, c_re), fpr_invsqrt8); - - x0 = w2; - x1 = w3; - sigma = tree1[3]; - w2 = fpr_of(samp(samp_ctx, x0, sigma)); - w3 = fpr_of(samp(samp_ctx, x1, sigma)); - a_re = fpr_sub(x0, w2); - a_im = fpr_sub(x1, w3); - b_re = tree1[0]; - b_im = tree1[1]; - c_re = fpr_sub(fpr_mul(a_re, b_re), fpr_mul(a_im, b_im)); - c_im = fpr_add(fpr_mul(a_re, b_im), fpr_mul(a_im, b_re)); - x0 = fpr_add(c_re, w0); - x1 = fpr_add(c_im, w1); - sigma = tree1[2]; - w0 = fpr_of(samp(samp_ctx, x0, sigma)); - w1 = fpr_of(samp(samp_ctx, x1, sigma)); - - a_re = w0; - a_im = w1; - b_re = w2; - b_im = w3; - c_re = fpr_mul(fpr_sub(b_re, b_im), fpr_invsqrt2); - c_im = fpr_mul(fpr_add(b_re, b_im), fpr_invsqrt2); - z1[0] = w0 = fpr_add(a_re, c_re); - z1[2] = w2 = fpr_add(a_im, c_im); - z1[1] = w1 = fpr_sub(a_re, c_re); - z1[3] = w3 = fpr_sub(a_im, c_im); - - /* - * Compute tb0 = t0 + (t1 - z1) * L. Value tb0 ends up in w*. - */ - w0 = fpr_sub(t1[0], w0); - w1 = fpr_sub(t1[1], w1); - w2 = fpr_sub(t1[2], w2); - w3 = fpr_sub(t1[3], w3); - - a_re = w0; - a_im = w2; - b_re = tree[0]; - b_im = tree[2]; - w0 = fpr_sub(fpr_mul(a_re, b_re), fpr_mul(a_im, b_im)); - w2 = fpr_add(fpr_mul(a_re, b_im), fpr_mul(a_im, b_re)); - a_re = w1; - a_im = w3; - b_re = tree[1]; - b_im = tree[3]; - w1 = fpr_sub(fpr_mul(a_re, b_re), fpr_mul(a_im, b_im)); - w3 = fpr_add(fpr_mul(a_re, b_im), fpr_mul(a_im, b_re)); - - w0 = fpr_add(w0, t0[0]); - w1 = fpr_add(w1, t0[1]); - w2 = fpr_add(w2, t0[2]); - w3 = fpr_add(w3, t0[3]); - - /* - * Second recursive invocation. - */ - a_re = w0; - a_im = w2; - b_re = w1; - b_im = w3; - c_re = fpr_add(a_re, b_re); - c_im = fpr_add(a_im, b_im); - w0 = fpr_half(c_re); - w1 = fpr_half(c_im); - c_re = fpr_sub(a_re, b_re); - c_im = fpr_sub(a_im, b_im); - w2 = fpr_mul(fpr_add(c_re, c_im), fpr_invsqrt8); - w3 = fpr_mul(fpr_sub(c_im, c_re), fpr_invsqrt8); - - x0 = w2; - x1 = w3; - sigma = tree0[3]; - w2 = y0 = fpr_of(samp(samp_ctx, x0, sigma)); - w3 = y1 = fpr_of(samp(samp_ctx, x1, sigma)); - a_re = fpr_sub(x0, y0); - a_im = fpr_sub(x1, y1); - b_re = tree0[0]; - b_im = tree0[1]; - c_re = fpr_sub(fpr_mul(a_re, b_re), fpr_mul(a_im, b_im)); - c_im = fpr_add(fpr_mul(a_re, b_im), fpr_mul(a_im, b_re)); - x0 = fpr_add(c_re, w0); - x1 = fpr_add(c_im, w1); - sigma = tree0[2]; - w0 = fpr_of(samp(samp_ctx, x0, sigma)); - w1 = fpr_of(samp(samp_ctx, x1, sigma)); - - a_re = w0; - a_im = w1; - b_re = w2; - b_im = w3; - c_re = fpr_mul(fpr_sub(b_re, b_im), fpr_invsqrt2); - c_im = fpr_mul(fpr_add(b_re, b_im), fpr_invsqrt2); - z0[0] = fpr_add(a_re, c_re); - z0[2] = fpr_add(a_im, c_im); - z0[1] = fpr_sub(a_re, c_re); - z0[3] = fpr_sub(a_im, c_im); - - return; -#endif // yyyAVX2- - } - - /* - * Case logn == 1 is reachable only when using Falcon-2 (the - * smallest size for which Falcon is mathematically defined, but - * of course way too insecure to be of any use). - */ - if (logn == 1) { - fpr x0, x1, y0, y1, sigma; - fpr a_re, a_im, b_re, b_im, c_re, c_im; - - x0 = t1[0]; - x1 = t1[1]; - sigma = tree[3]; - z1[0] = y0 = fpr_of(samp(samp_ctx, x0, sigma)); - z1[1] = y1 = fpr_of(samp(samp_ctx, x1, sigma)); - a_re = fpr_sub(x0, y0); - a_im = fpr_sub(x1, y1); - b_re = tree[0]; - b_im = tree[1]; - c_re = fpr_sub(fpr_mul(a_re, b_re), fpr_mul(a_im, b_im)); - c_im = fpr_add(fpr_mul(a_re, b_im), fpr_mul(a_im, b_re)); - x0 = fpr_add(c_re, t0[0]); - x1 = fpr_add(c_im, t0[1]); - sigma = tree[2]; - z0[0] = fpr_of(samp(samp_ctx, x0, sigma)); - z0[1] = fpr_of(samp(samp_ctx, x1, sigma)); - - return; - } - - /* - * Normal end of recursion is for logn == 0. Since the last - * steps of the recursions were inlined in the blocks above - * (when logn == 1 or 2), this case is not reachable, and is - * retained here only for documentation purposes. - - if (logn == 0) { - fpr x0, x1, sigma; - - x0 = t0[0]; - x1 = t1[0]; - sigma = tree[0]; - z0[0] = fpr_of(samp(samp_ctx, x0, sigma)); - z1[0] = fpr_of(samp(samp_ctx, x1, sigma)); - return; - } - - */ - - /* - * General recursive case (logn >= 3). - */ - - n = (size_t)1 << logn; - hn = n >> 1; - tree0 = tree + n; - tree1 = tree + n + ffLDL_treesize(logn - 1); - - /* - * We split t1 into z1 (reused as temporary storage), then do - * the recursive invocation, with output in tmp. We finally - * merge back into z1. - */ - Zf(poly_split_fft)(z1, z1 + hn, t1, logn); - ffSampling_fft(samp, samp_ctx, tmp, tmp + hn, - tree1, z1, z1 + hn, logn - 1, tmp + n); - Zf(poly_merge_fft)(z1, tmp, tmp + hn, logn); - - /* - * Compute tb0 = t0 + (t1 - z1) * L. Value tb0 ends up in tmp[]. - */ - memcpy(tmp, t1, n * sizeof *t1); - Zf(poly_sub)(tmp, z1, logn); - Zf(poly_mul_fft)(tmp, tree, logn); - Zf(poly_add)(tmp, t0, logn); - - /* - * Second recursive invocation. - */ - Zf(poly_split_fft)(z0, z0 + hn, tmp, logn); - ffSampling_fft(samp, samp_ctx, tmp, tmp + hn, - tree0, z0, z0 + hn, logn - 1, tmp + n); - Zf(poly_merge_fft)(z0, tmp, tmp + hn, logn); -} - -/* - * Compute a signature: the signature contains two vectors, s1 and s2. - * The s1 vector is not returned. The squared norm of (s1,s2) is - * computed, and if it is short enough, then s2 is returned into the - * s2[] buffer, and 1 is returned; otherwise, s2[] is untouched and 0 is - * returned; the caller should then try again. This function uses an - * expanded key. - * - * tmp[] must have room for at least six polynomials. - */ -static int -do_sign_tree(samplerZ samp, void *samp_ctx, int16_t *s2, - const fpr *restrict expanded_key, - const uint16_t *hm, - unsigned logn, fpr *restrict tmp) -{ - size_t n, u; - fpr *t0, *t1, *tx, *ty; - const fpr *b00, *b01, *b10, *b11, *tree; - fpr ni; - uint32_t sqn, ng; - int16_t *s1tmp, *s2tmp; - - n = MKN(logn); - t0 = tmp; - t1 = t0 + n; - b00 = expanded_key + skoff_b00(logn); - b01 = expanded_key + skoff_b01(logn); - b10 = expanded_key + skoff_b10(logn); - b11 = expanded_key + skoff_b11(logn); - tree = expanded_key + skoff_tree(logn); - - /* - * Set the target vector to [hm, 0] (hm is the hashed message). - */ - for (u = 0; u < n; u ++) { - t0[u] = fpr_of(hm[u]); - /* This is implicit. - t1[u] = fpr_zero; - */ - } - - /* - * Apply the lattice basis to obtain the real target - * vector (after normalization with regards to modulus). - */ - Zf(FFT)(t0, logn); - ni = fpr_inverse_of_q; - memcpy(t1, t0, n * sizeof *t0); - Zf(poly_mul_fft)(t1, b01, logn); - Zf(poly_mulconst)(t1, fpr_neg(ni), logn); - Zf(poly_mul_fft)(t0, b11, logn); - Zf(poly_mulconst)(t0, ni, logn); - - tx = t1 + n; - ty = tx + n; - - /* - * Apply sampling. Output is written back in [tx, ty]. - */ - ffSampling_fft(samp, samp_ctx, tx, ty, tree, t0, t1, logn, ty + n); - - /* - * Get the lattice point corresponding to that tiny vector. - */ - memcpy(t0, tx, n * sizeof *tx); - memcpy(t1, ty, n * sizeof *ty); - Zf(poly_mul_fft)(tx, b00, logn); - Zf(poly_mul_fft)(ty, b10, logn); - Zf(poly_add)(tx, ty, logn); - memcpy(ty, t0, n * sizeof *t0); - Zf(poly_mul_fft)(ty, b01, logn); - - memcpy(t0, tx, n * sizeof *tx); - Zf(poly_mul_fft)(t1, b11, logn); - Zf(poly_add)(t1, ty, logn); - - Zf(iFFT)(t0, logn); - Zf(iFFT)(t1, logn); - - /* - * Compute the signature. - */ - s1tmp = (int16_t *)tx; - sqn = 0; - ng = 0; - for (u = 0; u < n; u ++) { - int32_t z; - - z = (int32_t)hm[u] - (int32_t)fpr_rint(t0[u]); - sqn += (uint32_t)(z * z); - ng |= sqn; - s1tmp[u] = (int16_t)z; - } - sqn |= -(ng >> 31); - - /* - * With "normal" degrees (e.g. 512 or 1024), it is very - * improbable that the computed vector is not short enough; - * however, it may happen in practice for the very reduced - * versions (e.g. degree 16 or below). In that case, the caller - * will loop, and we must not write anything into s2[] because - * s2[] may overlap with the hashed message hm[] and we need - * hm[] for the next iteration. - */ - s2tmp = (int16_t *)tmp; - for (u = 0; u < n; u ++) { - s2tmp[u] = (int16_t)-fpr_rint(t1[u]); - } - if (Zf(is_short_half)(sqn, s2tmp, logn)) { - memcpy(s2, s2tmp, n * sizeof *s2); - memcpy(tmp, s1tmp, n * sizeof *s1tmp); - return 1; - } - return 0; -} - -/* - * Compute a signature: the signature contains two vectors, s1 and s2. - * The s1 vector is not returned. The squared norm of (s1,s2) is - * computed, and if it is short enough, then s2 is returned into the - * s2[] buffer, and 1 is returned; otherwise, s2[] is untouched and 0 is - * returned; the caller should then try again. - * - * tmp[] must have room for at least nine polynomials. - */ -static int -do_sign_dyn(samplerZ samp, void *samp_ctx, int16_t *s2, - const int8_t *restrict f, const int8_t *restrict g, - const int8_t *restrict F, const int8_t *restrict G, - const uint16_t *hm, unsigned logn, fpr *restrict tmp) -{ - size_t n, u; - fpr *t0, *t1, *tx, *ty; - fpr *b00, *b01, *b10, *b11, *g00, *g01, *g11; - fpr ni; - uint32_t sqn, ng; - int16_t *s1tmp, *s2tmp; - - n = MKN(logn); - - /* - * Lattice basis is B = [[g, -f], [G, -F]]. We convert it to FFT. - */ - b00 = tmp; - b01 = b00 + n; - b10 = b01 + n; - b11 = b10 + n; - smallints_to_fpr(b01, f, logn); - smallints_to_fpr(b00, g, logn); - smallints_to_fpr(b11, F, logn); - smallints_to_fpr(b10, G, logn); - Zf(FFT)(b01, logn); - Zf(FFT)(b00, logn); - Zf(FFT)(b11, logn); - Zf(FFT)(b10, logn); - Zf(poly_neg)(b01, logn); - Zf(poly_neg)(b11, logn); - - /* - * Compute the Gram matrix G = B·B*. Formulas are: - * g00 = b00*adj(b00) + b01*adj(b01) - * g01 = b00*adj(b10) + b01*adj(b11) - * g10 = b10*adj(b00) + b11*adj(b01) - * g11 = b10*adj(b10) + b11*adj(b11) - * - * For historical reasons, this implementation uses - * g00, g01 and g11 (upper triangle). g10 is not kept - * since it is equal to adj(g01). - * - * We _replace_ the matrix B with the Gram matrix, but we - * must keep b01 and b11 for computing the target vector. - */ - t0 = b11 + n; - t1 = t0 + n; - - memcpy(t0, b01, n * sizeof *b01); - Zf(poly_mulselfadj_fft)(t0, logn); // t0 <- b01*adj(b01) - - memcpy(t1, b00, n * sizeof *b00); - Zf(poly_muladj_fft)(t1, b10, logn); // t1 <- b00*adj(b10) - Zf(poly_mulselfadj_fft)(b00, logn); // b00 <- b00*adj(b00) - Zf(poly_add)(b00, t0, logn); // b00 <- g00 - memcpy(t0, b01, n * sizeof *b01); - Zf(poly_muladj_fft)(b01, b11, logn); // b01 <- b01*adj(b11) - Zf(poly_add)(b01, t1, logn); // b01 <- g01 - - Zf(poly_mulselfadj_fft)(b10, logn); // b10 <- b10*adj(b10) - memcpy(t1, b11, n * sizeof *b11); - Zf(poly_mulselfadj_fft)(t1, logn); // t1 <- b11*adj(b11) - Zf(poly_add)(b10, t1, logn); // b10 <- g11 - - /* - * We rename variables to make things clearer. The three elements - * of the Gram matrix uses the first 3*n slots of tmp[], followed - * by b11 and b01 (in that order). - */ - g00 = b00; - g01 = b01; - g11 = b10; - b01 = t0; - t0 = b01 + n; - t1 = t0 + n; - - /* - * Memory layout at that point: - * g00 g01 g11 b11 b01 t0 t1 - */ - - /* - * Set the target vector to [hm, 0] (hm is the hashed message). - */ - for (u = 0; u < n; u ++) { - t0[u] = fpr_of(hm[u]); - /* This is implicit. - t1[u] = fpr_zero; - */ - } - - /* - * Apply the lattice basis to obtain the real target - * vector (after normalization with regards to modulus). - */ - Zf(FFT)(t0, logn); - ni = fpr_inverse_of_q; - memcpy(t1, t0, n * sizeof *t0); - Zf(poly_mul_fft)(t1, b01, logn); - Zf(poly_mulconst)(t1, fpr_neg(ni), logn); - Zf(poly_mul_fft)(t0, b11, logn); - Zf(poly_mulconst)(t0, ni, logn); - - /* - * b01 and b11 can be discarded, so we move back (t0,t1). - * Memory layout is now: - * g00 g01 g11 t0 t1 - */ - memcpy(b11, t0, n * 2 * sizeof *t0); - t0 = g11 + n; - t1 = t0 + n; - - /* - * Apply sampling; result is written over (t0,t1). - */ - ffSampling_fft_dyntree(samp, samp_ctx, - t0, t1, g00, g01, g11, logn, logn, t1 + n); - - /* - * We arrange the layout back to: - * b00 b01 b10 b11 t0 t1 - * - * We did not conserve the matrix basis, so we must recompute - * it now. - */ - b00 = tmp; - b01 = b00 + n; - b10 = b01 + n; - b11 = b10 + n; - memmove(b11 + n, t0, n * 2 * sizeof *t0); - t0 = b11 + n; - t1 = t0 + n; - smallints_to_fpr(b01, f, logn); - smallints_to_fpr(b00, g, logn); - smallints_to_fpr(b11, F, logn); - smallints_to_fpr(b10, G, logn); - Zf(FFT)(b01, logn); - Zf(FFT)(b00, logn); - Zf(FFT)(b11, logn); - Zf(FFT)(b10, logn); - Zf(poly_neg)(b01, logn); - Zf(poly_neg)(b11, logn); - tx = t1 + n; - ty = tx + n; - - /* - * Get the lattice point corresponding to that tiny vector. - */ - memcpy(tx, t0, n * sizeof *t0); - memcpy(ty, t1, n * sizeof *t1); - Zf(poly_mul_fft)(tx, b00, logn); - Zf(poly_mul_fft)(ty, b10, logn); - Zf(poly_add)(tx, ty, logn); - memcpy(ty, t0, n * sizeof *t0); - Zf(poly_mul_fft)(ty, b01, logn); - - memcpy(t0, tx, n * sizeof *tx); - Zf(poly_mul_fft)(t1, b11, logn); - Zf(poly_add)(t1, ty, logn); - Zf(iFFT)(t0, logn); - Zf(iFFT)(t1, logn); - - s1tmp = (int16_t *)tx; - sqn = 0; - ng = 0; - for (u = 0; u < n; u ++) { - int32_t z; - - z = (int32_t)hm[u] - (int32_t)fpr_rint(t0[u]); - sqn += (uint32_t)(z * z); - ng |= sqn; - s1tmp[u] = (int16_t)z; - } - sqn |= -(ng >> 31); - - /* - * With "normal" degrees (e.g. 512 or 1024), it is very - * improbable that the computed vector is not short enough; - * however, it may happen in practice for the very reduced - * versions (e.g. degree 16 or below). In that case, the caller - * will loop, and we must not write anything into s2[] because - * s2[] may overlap with the hashed message hm[] and we need - * hm[] for the next iteration. - */ - s2tmp = (int16_t *)tmp; - for (u = 0; u < n; u ++) { - s2tmp[u] = (int16_t)-fpr_rint(t1[u]); - } - if (Zf(is_short_half)(sqn, s2tmp, logn)) { - memcpy(s2, s2tmp, n * sizeof *s2); - memcpy(tmp, s1tmp, n * sizeof *s1tmp); - return 1; - } - return 0; -} - -/* - * Sample an integer value along a half-gaussian distribution centered - * on zero and standard deviation 1.8205, with a precision of 72 bits. - */ -TARGET_AVX2 -int -Zf(gaussian0_sampler)(prng *p) -{ -#if FALCON_AVX2 // yyyAVX2+1 - - /* - * High words. - */ - static const union { - uint16_t u16[16]; - __m256i ymm[1]; - } rhi15 = { - { - 0x51FB, 0x2A69, 0x113E, 0x0568, - 0x014A, 0x003B, 0x0008, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000 - } - }; - - static const union { - uint64_t u64[20]; - __m256i ymm[5]; - } rlo57 = { - { - 0x1F42ED3AC391802, 0x12B181F3F7DDB82, - 0x1CDD0934829C1FF, 0x1754377C7994AE4, - 0x1846CAEF33F1F6F, 0x14AC754ED74BD5F, - 0x024DD542B776AE4, 0x1A1FFDC65AD63DA, - 0x01F80D88A7B6428, 0x001C3FDB2040C69, - 0x00012CF24D031FB, 0x00000949F8B091F, - 0x0000003665DA998, 0x00000000EBF6EBB, - 0x0000000002F5D7E, 0x000000000007098, - 0x0000000000000C6, 0x000000000000001, - 0x000000000000000, 0x000000000000000 - } - }; - - uint64_t lo; - unsigned hi; - __m256i xhi, rhi, gthi, eqhi, eqm; - __m256i xlo, gtlo0, gtlo1, gtlo2, gtlo3, gtlo4; - __m128i t, zt; - int r; - - /* - * Get a 72-bit random value and split it into a low part - * (57 bits) and a high part (15 bits) - */ - lo = prng_get_u64(p); - hi = prng_get_u8(p); - hi = (hi << 7) | (unsigned)(lo >> 57); - lo &= 0x1FFFFFFFFFFFFFF; - - /* - * Broadcast the high part and compare it with the relevant - * values. We need both a "greater than" and an "equal" - * comparisons. - */ - xhi = _mm256_broadcastw_epi16(_mm_cvtsi32_si128(hi)); - rhi = _mm256_loadu_si256(&rhi15.ymm[0]); - gthi = _mm256_cmpgt_epi16(rhi, xhi); - eqhi = _mm256_cmpeq_epi16(rhi, xhi); - - /* - * The result is the number of 72-bit values (among the list of 19) - * which are greater than the 72-bit random value. We first count - * all non-zero 16-bit elements in the first eight of gthi. Such - * elements have value -1 or 0, so we first negate them. - */ - t = _mm_srli_epi16(_mm256_castsi256_si128(gthi), 15); - zt = _mm_setzero_si128(); - t = _mm_hadd_epi16(t, zt); - t = _mm_hadd_epi16(t, zt); - t = _mm_hadd_epi16(t, zt); - r = _mm_cvtsi128_si32(t); - - /* - * We must look at the low bits for all values for which the - * high bits are an "equal" match; values 8-18 all have the - * same high bits (0). - * On 32-bit systems, 'lo' really is two registers, requiring - * some extra code. - */ -#if defined(__x86_64__) || defined(_M_X64) - xlo = _mm256_broadcastq_epi64(_mm_cvtsi64_si128(*(int64_t *)&lo)); -#else - { - uint32_t e0, e1; - int32_t f0, f1; - - e0 = (uint32_t)lo; - e1 = (uint32_t)(lo >> 32); - f0 = *(int32_t *)&e0; - f1 = *(int32_t *)&e1; - xlo = _mm256_set_epi32(f1, f0, f1, f0, f1, f0, f1, f0); - } -#endif - gtlo0 = _mm256_cmpgt_epi64(_mm256_loadu_si256(&rlo57.ymm[0]), xlo); - gtlo1 = _mm256_cmpgt_epi64(_mm256_loadu_si256(&rlo57.ymm[1]), xlo); - gtlo2 = _mm256_cmpgt_epi64(_mm256_loadu_si256(&rlo57.ymm[2]), xlo); - gtlo3 = _mm256_cmpgt_epi64(_mm256_loadu_si256(&rlo57.ymm[3]), xlo); - gtlo4 = _mm256_cmpgt_epi64(_mm256_loadu_si256(&rlo57.ymm[4]), xlo); - - /* - * Keep only comparison results that correspond to the non-zero - * elements in eqhi. - */ - gtlo0 = _mm256_and_si256(gtlo0, _mm256_cvtepi16_epi64( - _mm256_castsi256_si128(eqhi))); - gtlo1 = _mm256_and_si256(gtlo1, _mm256_cvtepi16_epi64( - _mm256_castsi256_si128(_mm256_bsrli_epi128(eqhi, 8)))); - eqm = _mm256_permute4x64_epi64(eqhi, 0xFF); - gtlo2 = _mm256_and_si256(gtlo2, eqm); - gtlo3 = _mm256_and_si256(gtlo3, eqm); - gtlo4 = _mm256_and_si256(gtlo4, eqm); - - /* - * Add all values to count the total number of "-1" elements. - * Since the first eight "high" words are all different, only - * one element (at most) in gtlo0:gtlo1 can be non-zero; however, - * if the high word of the random value is zero, then many - * elements of gtlo2:gtlo3:gtlo4 can be non-zero. - */ - gtlo0 = _mm256_or_si256(gtlo0, gtlo1); - gtlo0 = _mm256_add_epi64( - _mm256_add_epi64(gtlo0, gtlo2), - _mm256_add_epi64(gtlo3, gtlo4)); - t = _mm_add_epi64( - _mm256_castsi256_si128(gtlo0), - _mm256_extracti128_si256(gtlo0, 1)); - t = _mm_add_epi64(t, _mm_srli_si128(t, 8)); - r -= _mm_cvtsi128_si32(t); - - return r; - -#else // yyyAVX2+0 - - static const uint32_t dist[] = { - 10745844u, 3068844u, 3741698u, - 5559083u, 1580863u, 8248194u, - 2260429u, 13669192u, 2736639u, - 708981u, 4421575u, 10046180u, - 169348u, 7122675u, 4136815u, - 30538u, 13063405u, 7650655u, - 4132u, 14505003u, 7826148u, - 417u, 16768101u, 11363290u, - 31u, 8444042u, 8086568u, - 1u, 12844466u, 265321u, - 0u, 1232676u, 13644283u, - 0u, 38047u, 9111839u, - 0u, 870u, 6138264u, - 0u, 14u, 12545723u, - 0u, 0u, 3104126u, - 0u, 0u, 28824u, - 0u, 0u, 198u, - 0u, 0u, 1u - }; - - uint32_t v0, v1, v2, hi; - uint64_t lo; - size_t u; - int z; - - /* - * Get a random 72-bit value, into three 24-bit limbs v0..v2. - */ - lo = prng_get_u64(p); - hi = prng_get_u8(p); - v0 = (uint32_t)lo & 0xFFFFFF; - v1 = (uint32_t)(lo >> 24) & 0xFFFFFF; - v2 = (uint32_t)(lo >> 48) | (hi << 16); - - /* - * Sampled value is z, such that v0..v2 is lower than the first - * z elements of the table. - */ - z = 0; - for (u = 0; u < (sizeof dist) / sizeof(dist[0]); u += 3) { - uint32_t w0, w1, w2, cc; - - w0 = dist[u + 2]; - w1 = dist[u + 1]; - w2 = dist[u + 0]; - cc = (v0 - w0) >> 31; - cc = (v1 - w1 - cc) >> 31; - cc = (v2 - w2 - cc) >> 31; - z += (int)cc; - } - return z; - -#endif // yyyAVX2- -} - -/* - * Sample a bit with probability exp(-x) for some x >= 0. - */ -TARGET_AVX2 -static int -BerExp(prng *p, fpr x, fpr ccs) -{ - int s, i; - fpr r; - uint32_t sw, w; - uint64_t z; - - /* - * Reduce x modulo log(2): x = s*log(2) + r, with s an integer, - * and 0 <= r < log(2). Since x >= 0, we can use fpr_trunc(). - */ - s = (int)fpr_trunc(fpr_mul(x, fpr_inv_log2)); - r = fpr_sub(x, fpr_mul(fpr_of(s), fpr_log2)); - - /* - * It may happen (quite rarely) that s >= 64; if sigma = 1.2 - * (the minimum value for sigma), r = 0 and b = 1, then we get - * s >= 64 if the half-Gaussian produced a z >= 13, which happens - * with probability about 0.000000000230383991, which is - * approximatively equal to 2^(-32). In any case, if s >= 64, - * then BerExp will be non-zero with probability less than - * 2^(-64), so we can simply saturate s at 63. - */ - sw = (uint32_t)s; - sw ^= (sw ^ 63) & -((63 - sw) >> 31); - s = (int)sw; - - /* - * Compute exp(-r); we know that 0 <= r < log(2) at this point, so - * we can use fpr_expm_p63(), which yields a result scaled to 2^63. - * We scale it up to 2^64, then right-shift it by s bits because - * we really want exp(-x) = 2^(-s)*exp(-r). - * - * The "-1" operation makes sure that the value fits on 64 bits - * (i.e. if r = 0, we may get 2^64, and we prefer 2^64-1 in that - * case). The bias is negligible since fpr_expm_p63() only computes - * with 51 bits of precision or so. - */ - z = ((fpr_expm_p63(r, ccs) << 1) - 1) >> s; - - /* - * Sample a bit with probability exp(-x). Since x = s*log(2) + r, - * exp(-x) = 2^-s * exp(-r), we compare lazily exp(-x) with the - * PRNG output to limit its consumption, the sign of the difference - * yields the expected result. - */ - i = 64; - do { - i -= 8; - w = prng_get_u8(p) - ((uint32_t)(z >> i) & 0xFF); - } while (!w && i > 0); - return (int)(w >> 31); -} - -/* - * The sampler produces a random integer that follows a discrete Gaussian - * distribution, centered on mu, and with standard deviation sigma. The - * provided parameter isigma is equal to 1/sigma. - * - * The value of sigma MUST lie between 1 and 2 (i.e. isigma lies between - * 0.5 and 1); in Falcon, sigma should always be between 1.2 and 1.9. - */ -TARGET_AVX2 -int -Zf(sampler)(void *ctx, fpr mu, fpr isigma) -{ - sampler_context *spc; - int s; - fpr r, dss, ccs; - - spc = ctx; - - /* - * Center is mu. We compute mu = s + r where s is an integer - * and 0 <= r < 1. - */ - s = (int)fpr_floor(mu); - r = fpr_sub(mu, fpr_of(s)); - - /* - * dss = 1/(2*sigma^2) = 0.5*(isigma^2). - */ - dss = fpr_half(fpr_sqr(isigma)); - - /* - * ccs = sigma_min / sigma = sigma_min * isigma. - */ - ccs = fpr_mul(isigma, spc->sigma_min); - - /* - * We now need to sample on center r. - */ - for (;;) { - int z0, z, b; - fpr x; - - /* - * Sample z for a Gaussian distribution. Then get a - * random bit b to turn the sampling into a bimodal - * distribution: if b = 1, we use z+1, otherwise we - * use -z. We thus have two situations: - * - * - b = 1: z >= 1 and sampled against a Gaussian - * centered on 1. - * - b = 0: z <= 0 and sampled against a Gaussian - * centered on 0. - */ - z0 = Zf(gaussian0_sampler)(&spc->p); - b = (int)prng_get_u8(&spc->p) & 1; - z = b + ((b << 1) - 1) * z0; - - /* - * Rejection sampling. We want a Gaussian centered on r; - * but we sampled against a Gaussian centered on b (0 or - * 1). But we know that z is always in the range where - * our sampling distribution is greater than the Gaussian - * distribution, so rejection works. - * - * We got z with distribution: - * G(z) = exp(-((z-b)^2)/(2*sigma0^2)) - * We target distribution: - * S(z) = exp(-((z-r)^2)/(2*sigma^2)) - * Rejection sampling works by keeping the value z with - * probability S(z)/G(z), and starting again otherwise. - * This requires S(z) <= G(z), which is the case here. - * Thus, we simply need to keep our z with probability: - * P = exp(-x) - * where: - * x = ((z-r)^2)/(2*sigma^2) - ((z-b)^2)/(2*sigma0^2) - * - * Here, we scale up the Bernouilli distribution, which - * makes rejection more probable, but makes rejection - * rate sufficiently decorrelated from the Gaussian - * center and standard deviation that the whole sampler - * can be said to be constant-time. - */ - x = fpr_mul(fpr_sqr(fpr_sub(fpr_of(z), r)), dss); - x = fpr_sub(x, fpr_mul(fpr_of(z0 * z0), fpr_inv_2sqrsigma0)); - if (BerExp(&spc->p, x, ccs)) { - /* - * Rejection sampling was centered on r, but the - * actual center is mu = s + r. - */ - return s + z; - } - } -} - -/* see inner.h */ -void -Zf(sign_tree)(int16_t *sig, inner_shake256_context *rng, - const fpr *restrict expanded_key, - const uint16_t *hm, unsigned logn, uint8_t *tmp) -{ - fpr *ftmp; - - ftmp = (fpr *)tmp; - for (;;) { - /* - * Signature produces short vectors s1 and s2. The - * signature is acceptable only if the aggregate vector - * s1,s2 is short; we must use the same bound as the - * verifier. - * - * If the signature is acceptable, then we return only s2 - * (the verifier recomputes s1 from s2, the hashed message, - * and the public key). - */ - sampler_context spc; - samplerZ samp; - void *samp_ctx; - - /* - * Normal sampling. We use a fast PRNG seeded from our - * SHAKE context ('rng'). - */ - spc.sigma_min = fpr_sigma_min[logn]; - Zf(prng_init)(&spc.p, rng); - samp = Zf(sampler); - samp_ctx = &spc; - - /* - * Do the actual signature. - */ - if (do_sign_tree(samp, samp_ctx, sig, - expanded_key, hm, logn, ftmp)) - { - break; - } - } -} - -/* see inner.h */ -void -Zf(sign_dyn)(int16_t *sig, inner_shake256_context *rng, - const int8_t *restrict f, const int8_t *restrict g, - const int8_t *restrict F, const int8_t *restrict G, - const uint16_t *hm, unsigned logn, uint8_t *tmp) -{ - fpr *ftmp; - - ftmp = (fpr *)tmp; - for (;;) { - /* - * Signature produces short vectors s1 and s2. The - * signature is acceptable only if the aggregate vector - * s1,s2 is short; we must use the same bound as the - * verifier. - * - * If the signature is acceptable, then we return only s2 - * (the verifier recomputes s1 from s2, the hashed message, - * and the public key). - */ - sampler_context spc; - samplerZ samp; - void *samp_ctx; - - /* - * Normal sampling. We use a fast PRNG seeded from our - * SHAKE context ('rng'). - */ - spc.sigma_min = fpr_sigma_min[logn]; - Zf(prng_init)(&spc.p, rng); - samp = Zf(sampler); - samp_ctx = &spc; - - /* - * Do the actual signature. - */ - if (do_sign_dyn(samp, samp_ctx, sig, - f, g, F, G, hm, logn, ftmp)) - { - break; - } - } -} diff --git a/falcon/speed.c b/falcon/speed.c deleted file mode 100644 index 7b7f28a..0000000 --- a/falcon/speed.c +++ /dev/null @@ -1,382 +0,0 @@ -/* - * Speed benchmark code for Falcon implementation. - * - * ==========================(LICENSE BEGIN)============================ - * - * Copyright (c) 2017-2019 Falcon Project - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * ===========================(LICENSE END)============================= - * - * @author Thomas Pornin - */ - -#include -#include -#include -#include - -/* - * This code uses only the external API. - */ - -#include "falcon.h" - -static void * -xmalloc(size_t len) -{ - void *buf; - - if (len == 0) { - return NULL; - } - buf = malloc(len); - if (buf == NULL) { - fprintf(stderr, "memory allocation error\n"); - exit(EXIT_FAILURE); - } - return buf; -} - -static void -xfree(void *buf) -{ - if (buf != NULL) { - free(buf); - } -} - -/* - * Benchmark function takes an opaque context and an iteration count; - * it returns 0 on success, a negative error code on error. - */ -typedef int (*bench_fun)(void *ctx, unsigned long num); - -/* - * Returned value is the time per iteration in nanoseconds. If the - * benchmark function reports an error, 0.0 is returned. - */ -static double -do_bench(bench_fun bf, void *ctx, double threshold) -{ - unsigned long num; - int r; - - /* - * Alsways do a few blank runs to "train" the caches and branch - * prediction. - */ - r = bf(ctx, 5); - if (r != 0) { - fprintf(stderr, "ERR: %d\n", r); - return 0.0; - } - - num = 1; - for (;;) { - clock_t begin, end; - double tt; - - begin = clock(); - r = bf(ctx, num); - end = clock(); - if (r != 0) { - fprintf(stderr, "ERR: %d\n", r); - return 0.0; - } - tt = (double)(end - begin) / (double)CLOCKS_PER_SEC; - if (tt >= threshold) { - return tt * 1000000000.0 / (double)num; - } - - /* - * If the function ran for less than 0.1 seconds then - * we simply double the iteration number; otherwise, we - * use the run time to try to get a "correct" number of - * iterations quickly. - */ - if (tt < 0.1) { - num <<= 1; - } else { - unsigned long num2; - - num2 = (unsigned long)((double)num - * (threshold * 1.1) / tt); - if (num2 <= num) { - num2 = num + 1; - } - num = num2; - } - } -} - -typedef struct { - unsigned logn; - shake256_context rng; - uint8_t *tmp; - size_t tmp_len; - uint8_t *pk; - uint8_t *sk; - uint8_t *esk; - uint8_t *sig; - size_t sig_len; - uint8_t *sigct; - size_t sigct_len; -} bench_context; - -static inline size_t -maxsz(size_t a, size_t b) -{ - return a > b ? a : b; -} - -#define CC(x) do { \ - int ccr = (x); \ - if (ccr != 0) { \ - return ccr; \ - } \ - } while (0) - -static int -bench_keygen(void *ctx, unsigned long num) -{ - bench_context *bc; - - bc = ctx; - while (num -- > 0) { - CC(falcon_keygen_make(&bc->rng, bc->logn, - bc->sk, FALCON_PRIVKEY_SIZE(bc->logn), - bc->pk, FALCON_PUBKEY_SIZE(bc->logn), - bc->tmp, bc->tmp_len)); - } - return 0; -} - -static int -bench_sign_dyn(void *ctx, unsigned long num) -{ - bench_context *bc; - - bc = ctx; - while (num -- > 0) { - bc->sig_len = FALCON_SIG_COMPRESSED_MAXSIZE(bc->logn); - CC(falcon_sign_dyn(&bc->rng, - bc->sig, &bc->sig_len, FALCON_SIG_COMPRESSED, - bc->sk, FALCON_PRIVKEY_SIZE(bc->logn), - "data", 4, bc->tmp, bc->tmp_len)); - } - return 0; -} - -static int -bench_sign_dyn_ct(void *ctx, unsigned long num) -{ - bench_context *bc; - - bc = ctx; - while (num -- > 0) { - bc->sigct_len = FALCON_SIG_CT_SIZE(bc->logn); - CC(falcon_sign_dyn(&bc->rng, - bc->sigct, &bc->sigct_len, FALCON_SIG_CT, - bc->sk, FALCON_PRIVKEY_SIZE(bc->logn), - "data", 4, bc->tmp, bc->tmp_len)); - } - return 0; -} - -static int -bench_expand_privkey(void *ctx, unsigned long num) -{ - bench_context *bc; - - bc = ctx; - while (num -- > 0) { - CC(falcon_expand_privkey( - bc->esk, FALCON_EXPANDEDKEY_SIZE(bc->logn), - bc->sk, FALCON_PRIVKEY_SIZE(bc->logn), - bc->tmp, bc->tmp_len)); - } - return 0; -} - -static int -bench_sign_tree(void *ctx, unsigned long num) -{ - bench_context *bc; - - bc = ctx; - while (num -- > 0) { - bc->sig_len = FALCON_SIG_COMPRESSED_MAXSIZE(bc->logn); - CC(falcon_sign_tree(&bc->rng, - bc->sig, &bc->sig_len, FALCON_SIG_COMPRESSED, - bc->esk, - "data", 4, bc->tmp, bc->tmp_len)); - } - return 0; -} - -static int -bench_sign_tree_ct(void *ctx, unsigned long num) -{ - bench_context *bc; - - bc = ctx; - while (num -- > 0) { - bc->sigct_len = FALCON_SIG_CT_SIZE(bc->logn); - CC(falcon_sign_tree(&bc->rng, - bc->sigct, &bc->sigct_len, FALCON_SIG_CT, - bc->esk, - "data", 4, bc->tmp, bc->tmp_len)); - } - return 0; -} - -static int -bench_verify(void *ctx, unsigned long num) -{ - bench_context *bc; - size_t pk_len; - - bc = ctx; - pk_len = FALCON_PUBKEY_SIZE(bc->logn); - while (num -- > 0) { - CC(falcon_verify( - bc->sig, bc->sig_len, FALCON_SIG_COMPRESSED, - bc->pk, pk_len, - "data", 4, bc->tmp, bc->tmp_len)); - } - return 0; -} - -static int -bench_verify_ct(void *ctx, unsigned long num) -{ - bench_context *bc; - size_t pk_len; - - bc = ctx; - pk_len = FALCON_PUBKEY_SIZE(bc->logn); - while (num -- > 0) { - CC(falcon_verify( - bc->sigct, bc->sigct_len, FALCON_SIG_CT, - bc->pk, pk_len, - "data", 4, bc->tmp, bc->tmp_len)); - } - return 0; -} - -static void -test_speed_falcon(unsigned logn, double threshold) -{ - bench_context bc; - size_t len; - - printf("%4u:", 1u << logn); - fflush(stdout); - - bc.logn = logn; - if (shake256_init_prng_from_system(&bc.rng) != 0) { - fprintf(stderr, "random seeding failed\n"); - exit(EXIT_FAILURE); - } - len = FALCON_TMPSIZE_KEYGEN(logn); - len = maxsz(len, FALCON_TMPSIZE_SIGNDYN(logn)); - len = maxsz(len, FALCON_TMPSIZE_SIGNTREE(logn)); - len = maxsz(len, FALCON_TMPSIZE_EXPANDPRIV(logn)); - len = maxsz(len, FALCON_TMPSIZE_VERIFY(logn)); - bc.tmp = xmalloc(len); - bc.tmp_len = len; - bc.pk = xmalloc(FALCON_PUBKEY_SIZE(logn)); - bc.sk = xmalloc(FALCON_PRIVKEY_SIZE(logn)); - bc.esk = xmalloc(FALCON_EXPANDEDKEY_SIZE(logn)); - bc.sig = xmalloc(FALCON_SIG_COMPRESSED_MAXSIZE(logn)); - bc.sig_len = 0; - bc.sigct = xmalloc(FALCON_SIG_CT_SIZE(logn)); - bc.sigct_len = 0; - - printf(" %8.2f", - do_bench(&bench_keygen, &bc, threshold) / 1000000.0); - fflush(stdout); - printf(" %8.2f", - do_bench(&bench_expand_privkey, &bc, threshold) / 1000.0); - fflush(stdout); - printf(" %8.2f", - do_bench(&bench_sign_dyn, &bc, threshold) / 1000.0); - fflush(stdout); - printf(" %8.2f", - do_bench(&bench_sign_dyn_ct, &bc, threshold) / 1000.0); - fflush(stdout); - printf(" %8.2f", - do_bench(&bench_sign_tree, &bc, threshold) / 1000.0); - fflush(stdout); - printf(" %8.2f", - do_bench(&bench_sign_tree_ct, &bc, threshold) / 1000.0); - fflush(stdout); - printf(" %8.2f", - do_bench(&bench_verify, &bc, threshold) / 1000.0); - fflush(stdout); - printf(" %8.2f", - do_bench(&bench_verify_ct, &bc, threshold) / 1000.0); - fflush(stdout); - - printf("\n"); - fflush(stdout); - - xfree(bc.tmp); - xfree(bc.pk); - xfree(bc.sk); - xfree(bc.esk); - xfree(bc.sig); - xfree(bc.sigct); -} - -int -main(int argc, char *argv[]) -{ - double threshold; - - if (argc < 2) { - threshold = 2.0; - } else if (argc == 2) { - threshold = atof(argv[1]); - } else { - threshold = -1.0; - } - if (threshold <= 0.0 || threshold > 60.0) { - fprintf(stderr, -"usage: speed [ threshold ]\n" -"'threshold' is the minimum time for a bench run, in seconds (must be\n" -"positive and less than 60).\n"); - exit(EXIT_FAILURE); - } - printf("time threshold = %.4f s\n", threshold); - printf("kg = keygen, ek = expand private key, sd = sign (without expanded key)\n"); - printf("st = sign (with expanded key), vv = verify\n"); - printf("sdc, stc, vvc: like sd, st and vv, but with constant-time hash-to-point\n"); - printf("keygen in milliseconds, other values in microseconds\n"); - printf("\n"); - printf("degree kg(ms) ek(us) sd(us) sdc(us) st(us) stc(us) vv(us) vvc(us)\n"); - fflush(stdout); - test_speed_falcon(8, threshold); - test_speed_falcon(9, threshold); - test_speed_falcon(10, threshold); - return 0; -} diff --git a/falcon/test_falcon.c b/falcon/test_falcon.c deleted file mode 100644 index 2af88bf..0000000 --- a/falcon/test_falcon.c +++ /dev/null @@ -1,5030 +0,0 @@ -/* - * Test code for Falcon implementation. - * - * ==========================(LICENSE BEGIN)============================ - * - * Copyright (c) 2017-2019 Falcon Project - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * ===========================(LICENSE END)============================= - * - * @author Thomas Pornin - */ - -#include -#include -#include -#include -#include - -#include "inner.h" -#include "falcon.h" - -/* - * If using ChaCha20 during keygen, then we don't generate the same - * outputs from the same seeds, and we don't faithfully reproduce the - * NIST test vectors (implementation is still safe, but the tests would - * fail). - */ -#if FALCON_KG_CHACHA20 -#define DO_NIST_TESTS 0 -#else -#define DO_NIST_TESTS 1 -#endif - -static void * -xmalloc(size_t len) -{ - void *buf; - - if (len == 0) { - return NULL; - } - buf = malloc(len); - if (buf == NULL) { - fprintf(stderr, "memory allocation error\n"); - exit(EXIT_FAILURE); - } - return buf; -} - -static void -xfree(void *buf) -{ - if (buf != NULL) { - free(buf); - } -} - -static size_t -hextobin(uint8_t *buf, size_t max_len, const char *src) -{ - size_t u; - int acc, z; - - u = 0; - acc = 0; - z = 0; - for (;;) { - int c; - - c = *src ++; - if (c == 0) { - if (z) { - fprintf(stderr, "Lone hex nibble\n"); - exit(EXIT_FAILURE); - } - return u; - } - if (c >= '0' && c <= '9') { - c -= '0'; - } else if (c >= 'A' && c <= 'F') { - c -= 'A' - 10; - } else if (c >= 'a' && c <= 'f') { - c -= 'a' - 10; - } else if (c == ' ' || c == '\t' || c == '\r' || c == '\n') { - continue; - } else { - fprintf(stderr, "Not an hex digit: U+%04X\n", - (unsigned)c); - exit(EXIT_FAILURE); - } - if (z) { - if (u >= max_len) { - fprintf(stderr, - "Hex string too long for buffer\n"); - exit(EXIT_FAILURE); - } - buf[u ++] = (unsigned char)((acc << 4) + c); - } else { - acc = c; - } - z = !z; - } -} - -static void -check_eq(const void *a, const void *b, size_t len, const char *banner) -{ - size_t u; - - if (memcmp(a, b, len) == 0) { - return; - } - fprintf(stderr, "%s: wrong value:\n", banner); - fprintf(stderr, "a: "); - for (u = 0; u < len; u ++) { - fprintf(stderr, "%02x", ((const unsigned char *)a)[u]); - } - fprintf(stderr, "\n"); - fprintf(stderr, "b: "); - for (u = 0; u < len; u ++) { - fprintf(stderr, "%02x", ((const unsigned char *)b)[u]); - } - fprintf(stderr, "\n"); - exit(EXIT_FAILURE); -} - -/* - * tmp[] must have length at least ilen + 2*olen. - */ -static void -test_SHAKE256_KAT(const char *hexsrc, const char *hexout, - uint8_t *tmp, size_t tlen) -{ - uint8_t *in, *out, *ref; - size_t ilen, olen; - inner_shake256_context sc; - size_t u; - - in = tmp; - ilen = hextobin(in, tlen, hexsrc); - ref = in + ilen; - olen = hextobin(ref, tlen - ilen, hexout); - out = ref + olen; - if (tlen < ilen + 2 * olen) { - fprintf(stderr, "Temporary buffer too short\n"); - exit(EXIT_FAILURE); - } - - memset(out, 0, olen); - inner_shake256_init(&sc); - inner_shake256_inject(&sc, in, ilen); - inner_shake256_flip(&sc); - inner_shake256_extract(&sc, out, olen); - check_eq(ref, out, olen, "SHAKE KAT 1"); - - memset(out, 0, olen); - inner_shake256_init(&sc); - for (u = 0; u < ilen; u ++) { - inner_shake256_inject(&sc, in + u, 1); - } - inner_shake256_flip(&sc); - for (u = 0; u < olen; u ++) { - inner_shake256_extract(&sc, out + u, 1); - } - check_eq(ref, out, olen, "SHAKE KAT 2"); -} - -static void -test_SHAKE256(void) -{ - uint8_t *tmp; - size_t tlen; - - printf("Test SHAKE256: "); - fflush(stdout); - tlen = 1000; - tmp = xmalloc(tlen); - test_SHAKE256_KAT("", "46b9dd2b0ba88d13233b3feb743eeb243fcd52ea62b81b82b50c27646ed5762fd75dc4ddd8c0f200cb05019d67b592f6fc821c49479ab48640292eacb3b7c4be", tmp, tlen); - test_SHAKE256_KAT("dc5a100fa16df1583c79722a0d72833d3bf22c109b8889dbd35213c6bfce205813edae3242695cfd9f59b9a1c203c1b72ef1a5423147cb990b5316a85266675894e2644c3f9578cebe451a09e58c53788fe77a9e850943f8a275f830354b0593a762bac55e984db3e0661eca3cb83f67a6fb348e6177f7dee2df40c4322602f094953905681be3954fe44c4c902c8f6bba565a788b38f13411ba76ce0f9f6756a2a2687424c5435a51e62df7a8934b6e141f74c6ccf539e3782d22b5955d3baf1ab2cf7b5c3f74ec2f9447344e937957fd7f0bdfec56d5d25f61cde18c0986e244ecf780d6307e313117256948d4230ebb9ea62bb302cfe80d7dfebabc4a51d7687967ed5b416a139e974c005fff507a96", "2bac5716803a9cda8f9e84365ab0a681327b5ba34fdedfb1c12e6e807f45284b", tmp, tlen); - test_SHAKE256_KAT("8d8001e2c096f1b88e7c9224a086efd4797fbf74a8033a2d422a2b6b8f6747e4", "2e975f6a8a14f0704d51b13667d8195c219f71e6345696c49fa4b9d08e9225d3d39393425152c97e71dd24601c11abcfa0f12f53c680bd3ae757b8134a9c10d429615869217fdd5885c4db174985703a6d6de94a667eac3023443a8337ae1bc601b76d7d38ec3c34463105f0d3949d78e562a039e4469548b609395de5a4fd43c46ca9fd6ee29ada5efc07d84d553249450dab4a49c483ded250c9338f85cd937ae66bb436f3b4026e859fda1ca571432f3bfc09e7c03ca4d183b741111ca0483d0edabc03feb23b17ee48e844ba2408d9dcfd0139d2e8c7310125aee801c61ab7900d1efc47c078281766f361c5e6111346235e1dc38325666c", tmp, tlen); - xfree(tmp); - printf("done.\n"); - fflush(stdout); -} - -static const int8_t ntru_f_16[] = { - 7, -7, 12, 18, 19, 6, 18, -18, 18, -17, -14, 51, 24, -17, 2, 31 -}; - -static const int8_t ntru_g_16[] = { - -2, -35, 3, 28, -21, 10, 4, 20, 15, -28, 31, -26, 5, 33, 0, 5 -}; - -static const int8_t ntru_F_16[] = { - 16, 65, -6, 15, 26, -10, 14, -9, 22, 48, 26, -14, 15, 21, -23, 4 -}; - -static const int8_t ntru_G_16[] = { - 37, -57, 27, 31, -45, -49, -11, 46, -14, 26, 0, 3, -33, -33, -3, 54 -}; - -static const uint16_t ntru_h_16[] = { - 7768, 1837, 4498, 1226, 9594, 8992, 2227, 6132, - 2850, 7612, 4314, 3834, 2585, 3954, 6198, 589 -}; - -static const char *ntru_pkey_16 = "04796072d46484ca95ea32022cd7f42c89dbc4368efa2864f7260d824d"; - -static const int8_t ntru_f_512[] = { - 4, -4, 0, -6, 6, -6, 2, 1, -8, 0, -2, 0, -1, -1, -4, 8, -5, 3, - -2, 2, 0, -5, -2, -1, 3, -4, -5, -1, 8, 1, 1, 7, 5, 1, 6, 2, -1, - -13, 1, -4, 9, -4, -2, 4, -4, 0, -1, -1, -3, 2, 1, 1, 1, 3, -3, - 2, -1, -1, -5, 9, 4, -7, -3, -8, -3, -2, -3, -6, -6, -3, -2, -2, - 2, 1, -10, -2, -2, 4, 2, 0, -2, -2, 4, -3, 5, 2, -2, 3, 8, 1, 8, - -3, -4, 2, 7, -5, -4, -2, -2, -3, 5, -5, 0, -3, -5, 3, -6, -2, - 3, 0, 3, 1, 2, -2, 1, 6, -1, -7, 0, -5, 3, -5, 9, 0, 1, 5, -4, - 0, 5, -1, 4, 3, 5, -6, 2, 0, -7, 1, 0, 0, 2, 4, 1, -7, -3, 4, 4, - -2, -7, -5, 6, 3, 2, -5, 6, -1, -1, -4, 1, 2, 1, 2, -10, -9, -9, - -1, 3, -2, -2, -6, 1, -2, -4, -1, 2, 3, 8, 2, 1, -1, 8, 0, 7, 3, - 1, 5, 0, -7, 1, -6, -4, 4, 2, 0, 0, -3, 2, 0, -3, 0, 7, -1, -1, - -7, 2, 5, 3, 0, 1, 6, -2, -1, 2, 0, -1, -3, -6, -5, -5, -4, 0, - 1, 7, 1, -3, 2, 2, -5, 0, -4, 3, -4, 5, 3, 4, 7, -2, 15, -3, 1, - 1, 4, 5, -9, -3, 4, 2, -4, -4, -3, -1, -4, 3, -1, 1, -8, -4, -1, - 0, -3, 1, -1, 3, 3, 3, -3, -6, -7, 7, 0, -6, 2, -1, 4, 7, 1, 4, - 0, 1, 6, -1, -2, -2, 5, 0, 6, -3, -2, -5, 3, -1, 0, 5, -2, 8, - -5, -4, 1, -3, 8, 2, -4, 1, 6, 0, 0, -1, 0, -4, -5, -2, 3, -2, - 5, 1, 4, 5, -4, 4, -1, 4, -5, -2, 1, 3, -5, 1, 2, -2, 0, -5, 1, - 8, -3, -4, 3, -2, -3, -4, 4, 3, -2, 6, -3, -2, 4, 0, -2, 0, -5, - 1, -9, 5, 6, -2, -6, 1, 5, -1, -7, 1, 2, 5, 2, 0, -1, 0, -2, -4, - -1, -8, 5, -5, 9, -4, -4, 2, -5, -1, 0, 1, 4, 3, 1, -2, -7, -8, - -4, -4, 4, 3, -1, 4, -1, -1, 1, 0, 6, 1, 0, -6, -2, 0, -3, 0, - -1, -1, 0, 3, -5, -2, -5, 6, 2, -4, -3, 4, -8, 1, -1, 4, -3, 5, - -2, 8, 7, -1, -3, -3, -2, 0, -4, 4, 0, -6, -4, -2, 5, 8, -3, 3, - -1, 0, -5, -5, 0, 2, -5, -2, -3, 1, 6, 3, 1, -3, 4, -3, 0, -7, - -1, -3, 1, -5, 1, -4, -2, 2, 4, 0, 1, 5, 2, 2, -3, -5, -8, 4, - -2, -3, 2, 2, 0, 8, -5, 2, -7, 0, 3, -1, 0, 4, -3, 1, -2, -4, - -6, -5, 0, -4, 1, -3, 9, 1, -3, -2, -3, 5, -1, -4, -7, 1, 1 -}; - -static const int8_t ntru_g_512[] = { - -6, -2, 4, -8, -4, 2, 3, 4, 1, -1, 3, 0, 2, 3, -3, 1, -7, -5, 3, - -3, -1, 3, -3, 8, -6, -6, 0, 6, 4, 7, 3, 5, 0, -5, -3, -5, 7, 3, - -1, -4, 3, 4, -1, 1, 3, -3, -4, -4, 4, -5, -1, 3, 7, -2, -4, -2, - -3, -1, -2, -1, -2, -6, -7, -3, -6, -3, -6, 4, -1, -5, 1, 4, -4, - 3, -1, -6, 6, -2, 2, -6, 5, -7, 8, -3, 0, -2, 0, 7, 1, 3, 6, 4, - -5, 2, 2, 2, 4, -4, -5, -4, -3, 4, -7, 7, -6, -2, -7, 1, -2, -2, - -3, 1, 3, 7, 0, -1, -5, 4, -8, -8, 0, 3, 6, -3, 2, 6, -1, 1, -5, - -4, 2, -3, 8, -2, 2, 3, 0, 1, 6, 4, 4, -4, -1, -3, -2, -5, 3, 9, - 0, 4, -1, 1, -4, 0, 3, 0, -2, 8, 0, 1, 0, -1, 1, 9, -1, -4, -1, - 3, 5, -2, -2, 1, -1, 1, -1, 0, 1, 0, -6, -2, 0, 7, -3, -4, -1, - -6, -2, 5, -2, 0, 4, -3, -5, 0, 1, -1, -3, 5, 5, -4, -4, -5, -1, - 9, -1, -5, -7, -1, -2, 4, 2, 5, -4, -1, -5, 8, -3, -6, -2, 1, - -2, 1, 1, 4, -4, -1, 4, 1, 1, 0, -5, 1, 7, 2, -3, 3, -2, -4, 1, - -6, -1, -3, 7, 6, 0, -2, 2, -6, -4, -3, 2, -7, 7, 0, -11, -1, 3, - 4, 0, 6, -8, -4, -1, 1, 0, -3, 7, 0, 0, -2, -1, -4, 0, -1, -3, - 7, -6, -2, -2, -1, 0, -2, 8, -6, 4, 4, 6, -2, -1, 0, -13, 1, 2, - 0, 5, -7, 3, -2, -6, -3, -4, 4, -1, 1, 3, -6, 1, -5, -8, 2, -11, - -1, 2, -2, 0, 0, 1, 1, -4, -5, 0, 1, 0, 1, -6, -2, 2, 0, 7, 1, - -1, 1, -2, 1, -3, 1, 2, 1, -7, -2, 2, -1, 4, 1, -2, -2, 0, 4, - -3, -6, 2, 3, 1, 1, -4, 6, -2, -4, -3, 0, 4, -5, 0, 1, 8, 2, 2, - -1, 1, -2, -4, -1, 4, 4, -1, 7, 2, -1, -3, -8, 3, 1, 1, 0, -1, - 1, -7, -8, 2, 1, -2, 1, 0, 4, 1, 1, -2, -1, -5, 3, -4, -1, -1, - -8, 2, -4, 3, 2, -5, 0, 1, 5, 2, -5, -2, 3, 7, 5, 6, 5, -2, 1, - 3, -7, 7, -3, -8, -2, 2, 3, 3, 5, -2, -4, -1, 7, -2, 7, -3, -2, - 0, 3, 5, 0, 0, 4, 8, -1, -5, 3, -2, -2, -5, -5, -2, 2, 5, -8, - -1, -2, -4, 6, 0, 6, -5, -1, -5, -6, 9, 5, -2, 4, -1, -8, -2, - -2, 1, -8, -5, 6, -1, 0, 5, -6, -3, -3, -2, -6, -2, 0, -1, -3, - 7, -3, -1, 3, 6, 3, -2, -4, 2, 1, -1, 11, 3, 4, -1, -6, 1, 2, 3, - 3 -}; - -static const int8_t ntru_F_512[] = { - -3, -27, 4, 18, 39, 7, 20, -13, 33, -29, 3, 38, 30, 26, -6, 24, - -26, 16, 24, -48, -18, -21, 3, -14, -2, 6, -9, 42, 22, 21, 33, - -27, -14, -14, -56, -68, -2, -33, 6, -38, -43, 21, 13, 6, 2, - -69, -10, -30, -27, 23, -1, 41, -21, 11, -20, 15, 39, 5, 41, 15, - -28, -34, 9, -11, 9, -1, -8, 61, 8, 13, -23, 2, 7, -23, -21, - -54, -11, -9, -19, 40, 37, -2, -16, 19, -16, 2, -78, -35, -19, - 11, 17, -46, -16, 25, 0, 22, 13, -15, -33, 13, -15, -34, 33, - -13, 38, 39, 37, -29, 40, 7, 63, 35, 15, 21, -24, 16, -6, 30, - 12, 18, 61, 17, -11, -15, 11, 0, -15, -2, -14, -26, -1, -42, - -10, -52, 64, 45, 22, 6, -22, 32, -50, -16, -12, -16, -8, 34, - -17, -18, 7, 19, 37, 41, -5, -22, -12, -7, -17, -27, -17, 4, 36, - 0, 22, -4, -50, 24, 30, 5, 1, -50, 43, 0, 0, -6, -9, 34, 0, 14, - -27, 17, 35, -30, -13, 3, -23, -46, 17, -34, 30, 24, 47, 31, -7, - 11, 10, 16, 30, 27, -4, 11, -4, -14, -28, 49, 0, 27, -5, -10, - 53, -50, -13, -15, 13, -10, -26, 2, -3, 88, 22, -27, 40, -23, 3, - -42, 2, -27, -12, 35, 26, -33, 38, -42, -5, 17, -24, 6, -10, 13, - -10, -30, -35, -17, 25, 49, -29, 48, 19, 37, 48, -25, -31, -41, - -15, -1, 19, -17, -7, -16, 2, 5, 12, 0, -15, -19, -6, -32, -4, - -56, 14, -6, -7, 17, 24, -1, 17, -35, 5, 3, -64, -15, 4, 0, -31, - 4, -10, -18, 55, 13, -13, 23, -30, -11, -29, -21, 15, -18, 30, - 39, 16, -27, 31, 4, 31, 39, -49, 11, -25, 37, -42, -72, 28, -57, - 13, 34, 6, 10, -17, -3, -19, -43, -1, -32, 9, -11, 9, 11, -23, - 6, 28, -34, -12, -42, -7, 42, -18, -2, 22, -30, -4, -42, 10, 54, - -16, 19, -23, -4, 18, -58, 26, -3, -38, 20, 38, 23, 20, 0, 10, - 49, 47, 18, 27, -11, -10, -14, 0, 6, 6, -18, -6, 14, -38, -16, - 12, -17, 17, -21, -52, -3, -53, 9, 9, -4, 44, 9, -4, 17, 2, 10, - -28, -13, 28, -12, 11, -33, -2, 33, 0, -51, 2, -33, 20, -47, 23, - 42, 2, 52, -18, -17, 35, 6, 27, 3, 11, 24, -8, 0, -35, -44, -22, - -49, 61, 3, -15, -2, -14, 46, -24, -10, -24, -24, -21, -10, -51, - -3, 31, 20, 1, -44, 18, 9, 38, 26, -17, -8, 2, 33, 24, -8, -9, - -20, 32, 54, 47, -11, 40, 3, -58, 13, 17, 29, -21, 27, 4, -31, - 14, 14, 17, 19, -29, 19, -86, -29, -15, -35, 18, 53, -10, 9, 13, - -38, 9, -4, 80, 0, 6, 1, 15, -14, 0, -5, 45, 26, 50, 28, 21, 1, - -8, -6, 12, 32, 5, -21, -1, 54, 14, 22, 27, 6, 8, -18, 33, -5 -}; - -static const int8_t ntru_G_512[] = { - -58, -47, 36, 14, 2, -20, 24, 35, 38, -31, 20, -1, -17, -29, -6, - 25, 16, 4, -75, 32, 20, 17, -8, 24, 13, 7, -11, -2, 3, -2, 6, - 16, 22, 37, -25, -4, -32, -21, 57, 0, 20, 73, 20, -9, 6, -49, - 12, 14, 60, 15, 50, 15, 9, -2, 13, -8, 38, 12, -5, 9, -7, -1, - -30, -2, -28, -6, 6, -18, 5, 1, -15, -15, -1, 15, -4, -12, -1, - -37, -12, 33, -2, -17, -8, -57, -64, -7, 3, 3, -15, 1, 3, 15, - -21, 67, -29, -4, 7, -21, -7, -8, 12, 38, 3, 45, -26, -37, 10, - 24, -15, -24, 23, -13, -27, 12, 14, -16, 22, -19, 15, 1, -7, 0, - -6, 28, 2, -7, 0, -10, -19, 14, -13, -16, 22, 14, -7, -1, -17, - 31, -7, 12, 4, -8, -13, 18, -8, -38, 6, 49, 40, 1, -5, 1, 17, - -21, -3, -9, 15, 27, 43, 60, 29, -1, -3, 2, -41, 18, -18, -26, - 29, 13, 12, 15, 38, -24, -25, 8, 17, 10, -32, -3, -39, -29, 23, - 30, 6, 3, 23, -15, -26, 34, -59, 3, -54, 37, 27, -26, 23, -40, - -10, -15, 7, 9, -1, 24, -33, -36, 29, -7, 13, 29, 56, -13, 36, - -37, -45, 13, -11, 43, -9, 24, 16, -13, 13, 13, 10, -18, 16, 3, - -14, -27, -16, -5, -35, -25, -42, 51, -5, -41, 20, -27, 47, 14, - 75, 14, -74, 26, -18, 18, -12, -13, 8, -44, 6, 0, -16, 36, 32, - -33, 6, 5, -23, -14, -32, 15, 27, 56, 10, -43, 8, 16, -63, 8, - 34, -24, -3, 15, 13, -3, -31, -14, -24, 28, 11, -41, -4, 14, 1, - -11, 40, 32, -22, 19, -16, 27, -2, 36, 40, -11, -2, 2, -11, -2, - 35, -44, 6, 6, -40, 3, -8, -27, -28, 5, -6, -12, -2, -4, -19, - -64, 36, -33, -16, -5, 20, -9, 10, 59, 16, -8, 27, 28, -6, 10, - -8, 11, -35, 23, 35, 34, 47, 13, 2, 44, 8, 38, 4, 34, 41, 15, - 20, 28, 29, 35, 4, 23, 7, 8, -19, -17, 8, 5, 10, -21, -9, 15, - -28, -4, -23, -17, 18, -15, -2, 9, -24, -7, 7, 51, -31, 40, -57, - 30, 23, -12, -18, -9, 37, -29, -4, 18, -10, 20, -54, -21, 23, - 56, 28, 30, -3, 15, -31, -41, 14, 66, 41, 15, 39, 34, -9, 4, 33, - 18, 25, 6, 38, -27, 63, -21, -24, 43, 11, -37, 16, 26, -31, -30, - 16, -20, -3, 10, 11, -58, 18, 13, 0, 22, -25, 13, -32, -14, 5, - 52, 31, 30, -3, 9, 18, -7, 4, -2, 1, 11, -8, 8, -9, -29, 28, - -25, 51, 47, 24, -72, -4, 41, -15, 17, 50, 2, -1, 2, -41, -33, - -20, 6, -19, -33, 23, 8, -19, 12, -19, -2, -61, -7, -19, 6, 8, - -23, 27, 38, 12, -17, 39, 8, 23, -41, 14, 25, 16, -44, -46, 11, - 31, -6, 9, 24, 23, 37, -57, 22, 21, -22, 21, 44 -}; - -static const uint16_t ntru_h_512[] = { - 3605, 11394, 3623, 9500, 11987, 4336, 3361, 1348, 6563, 8102, - 758, 8455, 5789, 7614, 797, 11215, 7518, 3116, 4556, 1762, - 11267, 9507, 4586, 5420, 4091, 6788, 1729, 6433, 4730, 1830, - 4200, 1416, 3705, 5380, 5767, 9261, 924, 6822, 8978, 2536, 8232, - 10530, 10137, 11653, 11704, 1887, 11653, 10218, 9207, 10699, - 3288, 1478, 7261, 10152, 3871, 10134, 7359, 9993, 9510, 8661, - 419, 1826, 978, 11037, 10899, 3311, 2064, 5939, 11072, 1748, - 9516, 5458, 7665, 4459, 5937, 5615, 7288, 3438, 6009, 3217, 264, - 3696, 608, 11576, 2774, 10976, 11146, 11188, 3237, 10913, 3541, - 11755, 9412, 5720, 4226, 1154, 9010, 9922, 3994, 11252, 11575, - 11077, 9308, 7784, 11086, 12047, 5310, 8524, 4117, 504, 3145, - 12216, 2718, 1181, 5446, 1818, 6156, 1945, 11240, 7398, 8307, - 8259, 10113, 11431, 10691, 2147, 2742, 8242, 12031, 8808, 7609, - 3657, 3567, 2485, 7669, 4388, 3255, 1395, 596, 9635, 6739, - 10284, 4910, 9410, 11788, 10978, 3877, 4006, 1860, 6225, 8834, - 11969, 11742, 9733, 8790, 7871, 10347, 2658, 4468, 947, 3384, - 9733, 6496, 382, 81, 7977, 7138, 8962, 10195, 2830, 10227, 5302, - 9974, 9157, 7442, 4931, 9761, 5759, 2115, 431, 12242, 2353, - 7529, 7822, 6343, 3370, 9369, 8491, 6742, 5681, 10973, 412, - 12105, 6913, 5565, 3760, 4378, 4454, 9070, 1289, 2596, 5355, - 12117, 2787, 3798, 4954, 9708, 2191, 2935, 4073, 7455, 11661, - 4170, 8782, 9611, 8647, 2318, 4779, 11339, 3962, 361, 9358, - 7727, 11723, 9018, 10552, 3025, 6852, 6028, 10603, 7147, 8434, - 5604, 4483, 5954, 426, 11403, 2643, 8294, 9504, 7268, 8958, - 2773, 7764, 5926, 8213, 2100, 8814, 7540, 4212, 7012, 353, 7166, - 5717, 9799, 10379, 7768, 9515, 2534, 4504, 5410, 5358, 1879, - 11581, 10692, 2614, 11002, 11667, 7333, 6932, 4254, 9503, 7386, - 2581, 4153, 6079, 6149, 5496, 2397, 11735, 6496, 9250, 11872, - 10842, 2934, 4022, 10681, 914, 4397, 7287, 9673, 4709, 4895, - 3770, 3146, 7254, 4953, 11018, 9062, 3817, 11979, 8723, 3091, - 2675, 8946, 7376, 3652, 6861, 8298, 5547, 11, 4758, 10734, 7434, - 11702, 6466, 9135, 11199, 10059, 503, 2510, 1730, 6101, 11965, - 10264, 6045, 11690, 11530, 761, 9270, 4531, 5482, 6951, 5776, - 10348, 2668, 5246, 8046, 7106, 11302, 3276, 6632, 12008, 6564, - 8465, 1953, 5904, 1036, 3109, 5020, 11945, 458, 11742, 5271, - 4474, 9918, 7963, 11786, 8318, 756, 560, 11377, 1084, 9634, - 9203, 1062, 8461, 1845, 3719, 6672, 6660, 4711, 11337, 10460, - 5367, 4072, 7043, 5567, 6356, 657, 8877, 3633, 11487, 10421, - 10877, 5052, 2174, 4711, 11853, 4461, 10942, 11619, 7591, 3424, - 3372, 4493, 11393, 7115, 9057, 7145, 2060, 9137, 707, 1968, - 7853, 645, 253, 2697, 9294, 8357, 7503, 6187, 7505, 8302, 4635, - 8899, 9258, 8559, 7988, 9571, 243, 6979, 8233, 11555, 5257, - 8361, 1836, 11185, 3771, 3517, 10585, 4756, 10212, 2035, 2778, - 6798, 11229, 11768, 8707, 7931, 3744, 10939, 5317, 6104, 11137, - 3936, 5418, 4368, 201, 3094, 8211, 6803, 2559, 3164, 6846, 8515, - 8894, 8556, 2219, 9593, 6391, 3374, 4868, 192, 2791, 4309, 62, - 20, 9968, 8831, 11185, 1365, 9722, 5623, 2398, 5049, 2241, 6060, - 998, 4233, 1455, 5324, 1053, 5626, 1726, 11569, 12033, 4897, - 859, 1676, 2097, 11147, 5155, 5187, 2026, 12050, 5615, 5450, - 260, 7526, 11923, 6346, 7221, 405, 882, 842, 4621, 4130, 3513, - 114, 3673, 4914 -}; - -static const char *ntru_pkey_512 = - "093856c82389e51cbb4d0f03484544668dfa60bda1075a75dbe0c76bcf7578c2" - "c47306e2b00e52347a952c3feda841b0592149e872641a058839e55045a1e42d" - "0e71aa68c489e880a29229e66d85b6e075fb6167ea8fde9cb33605c671767a83" - "c7e79672fe709949a1d5068c7220f4ab1daa4ccef2041733ad006d494b155277" - "c516b5cc55ef71e0d6e5de4c910420e700982d382b5aae0ae2abb43296aa1375" - "6deb931165842084828cca6c23e6abf4b4deb459171e68ad3af0f52fa14c4054" - "1f83126fb82a7849d551871a6030799afa1ce681ce0439e06ca7a70c8632ada0" - "32bbfe26876e4e4937bc9b577d512432dc57309525a3694e82c4cba4c2b832ae" - "23c94fa61d118518a0aec1b77a6058959ebfa1aca6245d03b334e2605658017e" - "0145f296f8a3029f4cb0e9fcd4b69bda3c57449343988567f210c1afbf489317" - "5a5e8e631cd2a926612b6959631ab7419cbd25b0156f4eb044691668db850928" - "914ebbd54ae33b5935a97b088f2ddcfe9747ed8d412a24e962e1c724392abb12" - "cf7a05a648e78bedcb8cea9382f45ac45e3296b6fae0f257911835d081aab22c" - "a53819a52071922fe2b55e545c9a01520d226e75d10746d901616ff9655991e8" - "8b796252b279919854894ee1d5ed3da710a36abead937295b14427a51f7368a1" - "540e57bf60155782576dd76582422b982a5a2dd8fb6a6e439244b5c779725265" - "4c7ceba3129c564d66b0a8d98ee9bb2e213304ca738bc9cd03911acd81a95ab0" - "02d296a7b9d0ab6d99428ebebbf9d2c1f727386c25f56ebda06179db6aad0a0b" - "e643646cd56a6c9d690a1b0a6c51f9f6e6f0ac2633319e8bba19a484447a15c4" - "040c309539cbaa41cab77949745ea6be7c6ee0a81f82f408c2c7110f25a28fcc" - "42684347353a1da106811267b1268dc53dcfe86e0d5bf63502918ab4e31b37e8" - "b5a9f53bc21f9267b93516daafad63769cd6034b118db205bcb8d85be920323b" - "10b0c7b07ab428503f4a89913a0a5753d82b754606e486e2c390aa16f7cd2563" - "03cdb4380a6d2352260a91cb2bb13aecdbda5652949f907f32b69a8eaf76df88" - "80defb3a82abb53157d8ae04f6054a91100324c16804da9327fcc5c6afa1438a" - "fa16c22ae57963dcd2e4c100c02b9d0d500f80149bc227faec455597e95f7257" - "93b923057ac0f9908916bd4cc10755fa1afad31bc053210d6c68c20c6b8b508d" - "4431faaf1257bd54a0411d66ba4d8ca70d41950dc834a483502236e407239653" - "32"; - -static const int8_t ntru_f_1024[] = { - 3, 2, -4, -3, 0, -5, 4, -3, -1, 1, -2, 2, 3, 0, -1, 0, 0, 0, 0, - 0, -2, -2, -3, 3, -4, -1, -1, 0, 2, -4, 0, -9, -3, 5, 3, -1, 1, - -5, 1, -1, -6, 0, -1, -1, 5, -1, 4, -1, -2, 2, -3, -1, 1, -3, 1, - 1, -5, -2, -2, 0, 0, 5, -8, -1, -1, 0, 0, 2, 0, 4, -3, 4, 3, -3, - -2, 6, -2, -2, 0, 3, 0, 0, -1, -2, 0, 1, -2, -1, 7, 0, -4, 1, - -1, -2, 2, -1, -5, 5, -1, -4, -2, -1, 2, -1, 2, -1, -3, 3, 1, 2, - 1, -2, 3, 3, 1, 4, 2, 0, 3, 0, -3, 0, 7, -5, 4, -3, -1, 1, -6, - 0, -1, 0, -5, 1, -2, 2, -1, -1, -2, 3, 4, -1, 0, -1, 0, 1, 3, - -2, 6, 4, 1, 1, 1, -1, 3, 1, -3, 0, 0, -1, 2, -3, 2, -4, 1, -1, - -1, 1, -2, -1, -2, -6, -8, -3, 3, -2, 0, 3, -1, 1, 0, 5, -2, 0, - -2, 1, 2, 1, -2, -5, -3, -2, 2, -1, 1, 1, 0, 1, 1, -9, 0, 1, -2, - 2, 5, 0, 3, 4, -1, -5, -2, -2, 0, 2, 0, -2, 3, 0, -1, -2, -3, - -6, -2, 1, -7, -4, -2, 1, -1, -1, -3, -3, 2, -3, 2, 1, 2, -4, - -2, 5, -1, 1, -2, 3, -5, 5, 1, 1, 1, 2, -4, 1, 2, -3, -5, -4, 2, - -3, 3, -4, -4, 5, 2, 0, -4, 3, -3, -3, 3, 0, -2, -3, -2, 0, -3, - 5, 8, -2, 2, 2, -1, 10, -1, -1, 1, -4, 3, -1, 3, 1, -1, 3, -3, - 5, 0, 4, -3, 4, -5, 3, -3, -1, -4, 3, 1, 0, 2, -1, -4, -1, 4, - -5, -6, 3, 5, 4, -2, 0, 5, 1, 1, -1, 1, -3, 6, -3, -3, 1, -6, 3, - -3, 3, 1, 0, 0, -2, -4, -1, 1, 0, -1, -1, 4, -3, 2, 2, -5, 4, 3, - -3, -2, -1, 1, 1, -3, 4, 6, 0, 4, -3, -1, 1, 6, 2, 3, -2, -3, - -2, 3, -5, 3, 0, 0, -2, -1, -3, 2, 5, 0, 4, 2, 3, -2, -4, 3, 1, - -5, -2, 2, -1, -1, -4, 5, 0, 0, 2, -2, -4, 3, 4, 1, 5, 0, 0, 1, - 0, 5, -2, -1, 1, -3, -1, -1, -1, 2, 2, -3, 0, 1, -3, 2, 0, -2, - 3, 2, 0, 3, -1, 0, 2, -4, 0, -3, 3, 3, -1, -1, -2, 3, 2, -1, -5, - 1, 2, 3, 3, 3, -2, 8, 6, -2, 1, 4, -3, 0, 4, 1, 1, 0, 0, 1, 0, - -1, 5, 0, -5, 4, 3, 5, 2, 0, 0, 3, -2, 3, -4, 2, -3, -1, 3, -2, - 1, -1, 5, 1, 0, 5, -1, 0, -1, -2, -1, -4, -1, -2, 2, -6, -2, 5, - 0, -5, -2, 4, -1, -3, -3, -2, 2, -1, -2, 0, 0, -4, 2, -5, 1, -4, - -1, 0, -1, -2, 5, -4, 4, -1, -2, 6, 3, 6, 3, -3, 1, 0, 1, 6, 3, - 1, -3, -1, -2, -1, 0, 0, -1, -1, -1, -2, -2, -1, -1, 2, 1, -4, - -4, -5, -4, 3, 1, 1, 1, 4, -2, 0, 1, 2, 3, 0, 5, -5, 3, -1, 3, - 4, -3, -3, -4, -10, -1, -2, 2, -2, -3, 1, 2, 0, 1, 0, 2, -3, 2, - 1, 1, 0, -2, 1, 0, -3, -1, 0, -3, -1, -4, -5, 3, 3, -1, -5, -1, - 0, -1, 2, -3, 3, 1, 0, 0, -1, 2, 0, 6, -4, 5, -1, 1, 3, -2, -1, - 1, 0, 1, 2, -7, 2, 4, 2, 1, -3, -6, 2, -2, 0, 0, -2, 2, 2, 0, - -2, 1, 0, 1, 0, 1, 2, -3, 2, 3, 1, 1, 2, 7, 0, 1, 0, 0, -1, 2, - 1, -1, -1, 0, 0, 3, 2, 1, 1, 0, -5, 5, 0, 3, 3, 5, 3, -3, 0, 3, - 1, 4, 0, 6, -1, 3, 4, -1, 5, 5, 4, -4, -2, 2, 3, -10, -3, 1, 1, - 4, 2, -3, 4, 2, -2, -4, -2, -4, 1, 0, 0, 2, -3, 1, -1, -4, 0, - -1, 4, 1, -3, 0, -1, 1, 3, 2, 3, 1, 2, -3, -3, 0, 2, 4, 0, 0, 6, - -2, -1, -2, -2, 4, -1, -1, -1, -2, -4, -6, 2, 1, 1, -6, -2, -2, - 1, 0, -3, -3, -3, 3, 3, -1, 1, -3, -1, -1, 1, -6, -1, 2, -1, -4, - 0, 0, -4, 2, 3, 0, -4, -1, 0, 2, 0, -1, 1, 3, 3, -1, -2, 5, 0, - -1, 1, 0, 2, -5, -1, 0, 1, -5, -4, -4, 0, 1, 4, -6, -3, 1, 0, 2, - -5, -1, 0, 1, -5, 1, 1, 0, 1, -1, 3, 4, 3, -1, -1, 1, 1, 0, -2, - 0, -1, -4, 0, 2, 1, 2, 4, 2, -1, -4, 2, 2, -1, 0, -1, 0, 0, -2, - 3, 0, -1, -4, 0, -2, -2, -2, 4, 3, 5, 4, 1, 4, -2, 3, 0, -4, -2, - -3, 2, 2, 0, -6, 2, -7, -1, 3, 1, -2, 4, -2, 0, 1, 2, 4, 0, 1, - 1, 0, 0, 0, 1, 4, -10, -2, -3, -4, 7, -6, -2, -3, 4, 4, -4, -2, - 6, 2, -4, -1, 1, 1, 3, 0, 1, 0, -2, -4, 1, 4, 1, -5, 1, 1, 6, - -3, 0, 1, -2, -4, 0, -1, -3, 2, 6, 5, 1, -1, 3, 1, 1, 1, -1, 4, - -5, -3, -1, -2, -3, 0, 2, 2, 2, 2, -6, 7, 7, -1, 3, -1, -2, -2, - 5, 0, 1, 1, -3, 3, -6, 2, 1, 3, 3, 1, -1, 0, 2, 1, -5, -1, -4, - 1, -2, 5, -3, -2, 0, 3, 0, 1, -1, -1, 1, 0, 3, -1, 3, -1, 1, 2, - 0, -4, 2, -1, -3, -2, 0, -3, -2, 0, 1, 0, -5, -2, 4, 1, 7, -5, - 1, 1 -}; - -static const int8_t ntru_g_1024[] = { - 3, -1, -7, -1, 4, -2, 3, -1, -3, -3, -5, 3, -1, -1, 2, -3, -5, - 0, 0, 1, -3, 3, 3, -2, -2, 0, -4, 2, 1, -1, 3, -5, 5, 0, -1, -3, - -1, -2, 5, 3, 4, -2, -2, 0, -4, 0, 3, 3, 0, 1, 3, -1, -2, -3, - -1, -2, 3, 1, 0, -2, 0, -2, 0, 0, 1, 3, -2, -3, 3, -3, -1, -2, - -1, -3, -3, 1, 1, 8, 1, 4, -2, -1, -5, -4, 3, 5, 0, 0, 7, 4, 1, - 1, -4, -2, 4, 4, -3, -4, 5, 3, 2, 0, 1, -6, 2, -1, -3, -1, -1, - 1, 2, 5, 0, 3, 1, 3, 0, -4, -3, -3, -1, -1, 1, 1, 2, 0, -2, 0, - 3, 3, 3, -4, 1, -2, -4, 3, 3, 5, -4, -5, -1, -1, 3, -2, -4, -1, - -5, 1, -1, 0, 2, -1, 1, 1, -3, -2, -1, -4, -4, -1, -1, 0, -1, - -1, 3, -2, -2, 3, -6, 2, 2, 0, 2, -3, 0, 3, -2, -2, 2, -1, 1, 4, - -2, 0, 0, 0, 0, 4, 0, 2, -4, -1, 5, -2, -6, 2, 1, 3, 1, 3, 0, 3, - 1, 2, 0, -4, -2, -3, 4, 2, 0, -8, -2, 2, 5, 2, 0, 1, -2, 0, -1, - 0, 3, 3, 1, 0, 0, 2, 2, -1, -3, 3, -2, 3, 1, -2, 5, 1, 4, -2, 3, - -2, -3, -2, -1, 2, -5, -4, -2, -3, -6, -3, -2, -3, -3, -3, -1, - 1, -1, 4, -1, -5, -3, 0, 3, 6, 0, 2, -1, 5, -1, 0, 2, 7, 6, -1, - 2, -2, 4, 6, 0, 1, 4, 4, 0, 5, 1, -3, 4, 1, 3, 1, -1, -2, -4, - -1, 0, 0, 3, -6, -1, 2, 4, -3, -1, 0, -3, 2, 1, 2, 4, 1, -1, -2, - -1, -3, -2, -6, -1, 1, 2, -2, 0, 0, 0, -3, 1, -2, 5, 1, 1, -5, - -4, 0, 0, -2, 0, 3, 4, 5, 2, -4, 0, -4, 3, -2, 0, -3, -4, -1, 4, - 0, -3, -2, 1, -1, 2, -3, 1, 0, 0, -3, 0, 5, 2, -2, -4, 2, 0, 0, - -3, 0, -1, -1, -1, -1, 3, 7, -1, -2, -5, 2, 5, 1, 4, 2, -3, 0, - -5, -4, 1, 0, 1, -3, 4, 2, -5, -1, 2, -4, 0, 1, 0, 1, 0, -1, 0, - -2, -4, 4, -2, 0, 1, 1, 0, 2, 0, 0, -4, -5, -3, 0, -4, -5, 2, 1, - 0, -3, 4, -1, 3, -4, -5, -1, 4, -1, 0, 1, -4, 5, -1, 5, 1, -1, - 0, -3, -3, 3, -5, -3, 1, -1, 0, 4, -2, 2, 1, -2, -3, -1, -2, -3, - -3, 1, -2, 8, -2, 0, 3, -2, 3, 3, 3, -2, 4, 0, 2, 3, 1, 3, 0, - -1, -1, 3, 1, 1, -1, 5, 1, -1, 0, -3, 1, -4, 1, -1, -4, -1, 6, - -4, 6, -2, 0, -2, 0, 4, -1, 1, 6, 7, 5, -1, 3, 3, 0, -1, 1, -6, - -1, -4, 4, -1, 3, 4, 3, -3, -1, 2, 0, -3, 2, -1, -2, 1, -3, 0, - -1, -5, -1, 4, -2, -6, 1, 0, 6, 2, 1, -3, 2, 1, -1, -1, 4, -4, - -2, -2, 5, 1, 5, -2, -6, 1, 0, 1, 4, 4, -3, -1, -4, 1, 0, -1, 0, - -3, 4, -2, 4, 3, 1, 4, 6, 2, 1, -1, 1, -5, -2, -3, 2, 0, -1, -1, - -5, 3, -3, 2, 0, 1, -4, -1, 7, -1, 2, -2, 3, 0, 0, -4, 4, 2, 4, - 1, 1, 2, 3, -2, 3, 1, 0, 0, -4, 0, 2, 1, 1, -1, 4, 4, -4, -3, 5, - -1, -1, 1, 3, 3, 1, -9, 0, -6, 5, 0, 0, -2, 3, 0, 2, -2, 3, -6, - 1, 1, -1, 3, 1, 2, 0, 3, -1, 0, -2, -3, 7, 1, -3, -1, -2, 3, -3, - 1, 4, 3, -3, -3, -4, -6, -5, -1, 6, -5, 3, 0, -1, 0, 4, -5, -2, - 1, -2, 3, 6, 2, -4, -5, -6, -3, 2, -3, -4, -2, 1, 1, 0, 1, -2, - 2, -2, -1, 1, 2, 2, -4, -3, -1, 0, -1, 2, -4, 1, -1, 0, -3, 1, - 2, -5, 4, 0, -3, 3, 5, 3, -4, -2, 2, 1, 1, -4, -2, 1, -1, 0, 0, - 3, 0, 1, 0, 1, 1, -1, -4, 3, 3, 1, 0, 1, -1, 1, -2, 3, 3, 5, -1, - 3, -3, -1, 1, -2, -1, 0, 1, 1, -2, 0, 3, -1, -3, -2, 1, 1, 2, - -7, -2, 1, 5, 0, 0, 0, -4, -4, 0, 1, -1, 4, 0, 0, 3, 1, 3, -4, - 7, 4, -4, 0, 5, 4, -3, -1, 0, 0, -3, -4, 3, 0, -1, 2, -2, 0, 6, - 0, -2, 3, 1, 6, 3, -2, 2, 1, -1, -2, -4, -3, -2, -2, 0, 2, 0, - -4, -3, -1, -3, 1, 0, -6, 2, 0, 4, 4, 1, -2, -1, -3, 3, -4, -4, - -2, 1, -5, -1, 2, 1, -2, 0, -2, 2, -1, 0, 3, -2, 1, -6, -2, -1, - 0, -2, -2, 1, 0, 4, -1, 8, 3, 0, 1, 5, 1, -3, 0, 2, 1, 1, -1, 4, - 0, 4, 6, -2, 0, 0, -3, 5, -6, -3, 5, 2, -2, 1, -1, 6, 5, -3, -4, - -3, 2, 3, -5, 2, 2, -2, -4, 6, -4, 2, 0, -4, 5, 2, -1, 1, 0, -2, - 2, 2, 0, -3, 0, -7, 0, -1, 1, 3, 3, 2, -5, -2, 0, 5, -4, 1, 2, - 2, -1, 4, 5, 2, 2, 2, 0, 0, 2, 1, 3, 2, -4, 4, -2, -1, 2, -2, 0, - 3, -2, -1, 6, 1, 3, 0, 4, 0, -2, -1, 1, 0, -3, 3, 2, 3, -1, -3, - -3, 3, -2, 3, -2, 0, -1, 3, -3, -2, 1, 4, -4, 2, 5, -7, 1, 0, - -5, 1, 2, -1, 3, -2, 3, -1, -2, 2, 0, 0, 0, -3, -2, 4, 7, 1 -}; - -static const int8_t ntru_F_1024[] = { - 36, -13, 88, 1, 13, -66, 9, -2, -12, 30, 23, -18, -15, 8, -2, 5, - 19, 13, 14, -22, -22, 29, -18, 8, -45, 28, -4, -46, 30, 40, -26, - -3, -1, -2, -54, 4, 34, -38, -32, 55, -25, -24, 4, -35, -9, 8, - 23, 24, 35, 17, 29, 7, 41, -3, -13, 39, 25, 24, -34, 18, -55, - 22, -61, -23, 18, 3, 1, -3, 32, -20, -2, -63, 19, 21, -13, 3, - -7, -17, 5, -40, -29, 8, 6, -43, 27, 31, 3, -28, -46, 76, 31, - -16, -4, 59, 38, -6, -6, -3, 34, -19, -10, -39, -20, -15, -3, - -11, -41, 9, -90, 21, -26, 24, -2, -18, -36, 18, -2, -4, -18, - -67, 14, 7, -22, -22, -28, 42, -57, 32, 7, 25, 7, 30, -45, -9, - -2, 8, 28, -14, 19, -19, -47, 37, -34, 45, -32, -8, -35, 52, - -31, 35, -14, -10, 36, -65, -16, -21, -5, 4, 21, -61, 22, 13, - -55, -5, -22, 14, -10, -35, 8, -5, 27, -31, -32, 3, 0, -12, -25, - 27, -5, -22, 3, -6, 0, 21, -5, 45, 36, -42, 16, -2, -9, -16, - -44, 0, 44, 3, -9, -51, -32, 11, -4, -7, 33, 15, -9, 13, -6, 15, - 15, -30, 10, 14, -8, 27, 20, -3, -10, 22, 14, 7, -15, 31, -17, - -20, -14, 4, -2, 26, 27, -7, 32, 49, 27, -40, -4, -35, 11, 3, - 17, 35, 11, -14, 35, -6, 7, 10, -38, 12, 43, -42, 44, -20, -3, - 33, 35, 14, 1, 10, -9, -11, -20, 31, 30, -2, -2, -6, 17, -10, - -10, -10, 49, -23, -18, -3, -1, 12, 19, -44, -21, -13, -19, 25, - 4, -23, -20, 6, -15, -2, 21, 19, -6, -4, 43, -24, 31, 22, -15, - 55, -5, -3, -8, -6, -14, 23, 0, 32, -28, 48, 55, 43, 2, 17, -4, - 56, 58, 32, 3, -6, 43, 11, -3, -9, -26, -17, -6, 23, 29, 30, - -31, 5, 27, 11, 9, 30, 32, 66, 10, 33, -40, -26, 19, 38, -11, 4, - 12, -57, 30, -14, 29, -5, 12, -9, -17, 20, 40, -1, -19, -5, -16, - -38, -25, -24, -1, 21, -21, -47, -1, -8, -53, 39, 7, -36, -19, - 4, 0, 2, 16, 6, 20, 8, 8, -7, -42, -1, 4, -17, -7, -10, -24, 0, - -29, -1, -15, -2, 3, 9, -21, -2, -20, -15, -68, -42, 21, -40, - -23, -3, -5, -18, -2, -17, -20, 17, 10, 16, -54, 27, 5, -21, 21, - 4, -54, -25, 2, 61, 39, -25, 47, -5, 20, 12, 8, -21, -12, 16, - -13, 23, -4, -47, -12, -15, 5, 20, -4, -22, 37, -43, -14, -30, - -21, 15, -24, 1, -13, 25, -3, -8, -4, 9, -13, -1, -14, 39, 19, - -8, -11, 45, 32, -25, 18, 77, 13, 14, 21, 38, -42, 15, 28, -17, - 6, -2, 17, -36, 21, -33, 13, 12, -6, 36, -5, 9, 7, 1, -17, 30, - -16, -3, -39, -12, -6, -21, -28, 3, -13, -17, 29, 23, -12, 17, - 35, -18, -10, 1, 26, -33, 69, 57, -12, -15, 43, 18, 27, -31, - -29, 37, -5, 50, -56, -22, -57, -1, 21, -15, -27, -48, -20, -28, - -4, -31, -20, 9, 10, 15, 12, -7, -38, 23, 0, 9, 3, 15, 28, 31, - -8, 4, 19, 3, -7, 30, -14, 27, -7, -25, -20, -10, -20, 27, -6, - -30, -8, 27, -5, -23, 52, -44, -33, 48, -20, 10, -21, 7, -34, - -1, 26, 40, -11, 4, 46, -30, -13, -9, 27, 13, -13, 13, -4, 11, - 34, -32, -3, 51, 24, -45, 39, 14, 15, -55, 12, -28, -21, -14, 3, - -16, -25, -13, 35, 18, -7, -27, 51, -16, 29, -28, 5, 1, -32, 3, - -25, -7, -15, 33, 8, 37, -20, 26, 25, 12, 13, 15, 8, 4, 11, 8, - -31, -1, 8, 13, -31, 22, -7, -3, 7, 12, 10, -12, -62, -49, -12, - -5, -3, -53, -30, -7, -56, 20, 45, 6, -46, -32, -15, -13, 9, - -18, 11, -5, 12, -6, 10, -62, 8, 11, -18, 27, 16, -5, -6, 4, - -28, -6, -30, -58, 11, -8, -40, -51, 20, 27, 17, 12, -9, -28, - -11, -8, -22, -18, -16, -36, 14, 17, -44, 2, 42, 16, -9, -31, - -16, -3, -14, 41, -22, 16, -1, 32, 12, 4, -36, 18, -41, 13, 31, - -35, 14, 8, -10, 19, -9, -4, -36, -15, -62, 0, 16, -28, -54, 4, - 20, -9, 14, 18, -26, -30, 19, 10, 10, -5, -10, 7, 23, -7, -31, - -2, 19, -63, -14, 0, -18, -3, -21, -33, 11, -52, -21, -4, -48, - -35, -6, -4, -14, -13, -1, 14, -16, -21, 9, -37, -31, -16, 4, - -17, 2, -4, -17, 2, -51, -16, -16, 3, 59, 13, -16, -30, 17, 9, - 35, -11, -31, 32, -7, -26, 28, 7, 19, 28, -17, -49, -30, -9, 23, - 19, -2, 1, -3, 9, 48, 11, -54, 9, -22, 25, 8, 22, -52, 37, -14, - -10, -30, 20, 52, 3, 10, 17, 56, 33, -3, 41, 53, 41, 4, -7, -25, - 8, -45, 29, -11, 5, 29, 60, -15, -8, 14, -7, -33, -14, 6, -12, - -2, -2, -10, -12, -16, -21, 2, 5, -14, 53, 41, 61, 12, 31, 4, - 22, -16, 36, -4, -42, 38, -29, -10, 20, 20, 35, 66, 16, 12, -50, - -5, 1, -16, 32, 33, 46, -3, 11, 11, -19, 28, 5, 38, 15, -35, -6, - 1, -6, -17, 2, -28, 25, 42, 8, -2, -11, 14, -33, -42, 23, 21, - -31, 63, -8, 15, 26, -16, 13, -3, 39, -16, 58, -14, -14, -22, - -30, -26, -51, 4, -9, -18, -5, -56, -48, -60, 10, -52, -28, -6, - -12, -35, 31, -22, -31, -13, 8, -14, -8, 23, -20, -45, -12, 30, - 8, 7, 9, -12, -13, -2, -29, 18, -1, 30, -17, -26, -41, 58, -66, - -6, 8, -78, 25, 29, 0, -40, -27, 16, 40, -15, -28, 18, -54, 16, - -12, 1, -4, 17, -21, 12, 30, -7, 45, -8, -28, 8, -41, -1, 42, 3, - -6, -47, 22, 44, -78, -45, 41, 12, -30, -23, 13 -}; - -static const int8_t ntru_G_1024[] = { - 56, -4, -28, 13, 4, 26, -14, -10, -21, -32, 21, -21, 0, 59, 26, - -6, -81, -7, -42, -1, 8, 20, 37, -33, 36, 1, -6, 14, -1, -73, - 15, 18, 7, 34, -45, 7, 19, -30, 8, 8, -56, -13, 7, 20, -20, 14, - 4, 11, -36, 21, 19, -16, -17, 10, -45, -4, -12, 18, -9, 23, 20, - 1, -27, -7, 1, 1, 33, -27, -23, 56, 35, -5, 16, 43, -1, 11, -18, - 5, 59, 14, -39, 11, -34, -59, 6, -18, 43, -25, 22, -7, 9, -28, - -9, -40, 47, 0, -12, -22, -12, -44, -17, -12, -10, -5, 4, -20, - -10, 25, 38, 2, 0, -17, 14, -16, 6, 9, 7, -29, 11, 48, 14, 10, - 0, 24, 4, -5, 56, 20, 1, 35, 62, 7, -31, 36, 36, 24, -19, -33, - 19, 9, -13, -16, 2, 1, -29, 3, -3, 42, 8, 27, -19, 51, 16, 14, - 28, -1, 24, 3, 1, 47, -13, -43, 9, 17, 3, 21, 26, -19, -6, 4, - -36, 7, 26, 19, 40, -44, 27, -20, 9, -1, 19, -1, 0, -51, 5, -5, - -45, 11, 26, -1, 1, 39, -6, 14, -14, -34, -29, -6, -15, -23, 24, - -7, 16, -51, 55, -30, 2, 13, 1, -37, 33, -29, 11, 14, -44, 46, - 40, -45, 59, -6, 3, 18, -46, 20, 17, -2, 0, 27, -20, 1, -7, -16, - -29, 0, -2, -19, 19, -10, 16, -15, -2, 2, -10, 4, 27, -4, 2, 0, - 15, 35, 19, 25, 21, 32, -9, 26, -28, -23, -2, 7, -24, 75, -3, 6, - 21, 45, -8, -12, 21, -12, -29, -7, 34, -13, -22, 28, 32, 20, 18, - -22, 2, 17, -12, 37, 37, -33, 5, 28, 27, 55, -30, -9, 10, 23, - 12, -9, -26, 30, 5, 2, 24, -37, 9, -25, -50, 33, 3, -21, -38, - -19, 44, 41, 9, 1, 34, 6, -26, -44, -26, 15, -3, -21, -24, 40, - -43, 28, 2, -30, -13, -8, -40, 1, 31, -2, -16, -16, -25, 33, 1, - -23, -51, -40, -37, -12, -38, 78, 15, -31, 32, 41, 26, 26, -25, - -60, 15, -43, 27, -54, 0, 25, -7, -27, 15, -18, 20, 20, -76, -3, - 35, -39, 20, 28, 21, 10, 6, -41, -29, -31, -55, -41, 0, -8, 4, - -17, 21, -21, -12, 11, 4, -17, 6, 26, 11, 9, -13, -41, 29, -7, - -4, 21, 12, 2, -1, -23, 3, -5, 1, 30, -10, 9, 40, -63, -27, 51, - -29, 4, -1, -7, 30, 30, -21, 32, -17, -51, 28, 34, 22, -5, -5, - 42, 7, -1, -16, -15, -23, 10, -9, -3, 1, 26, -12, 16, 5, 18, 13, - -1, 28, 8, -52, -42, 12, -3, -28, 30, -3, 11, -14, -3, 34, -75, - -13, 6, -39, 14, 72, -16, 18, -17, -36, -3, 5, -9, -38, -42, 4, - 7, 3, 74, 2, 9, -23, -32, -43, -59, -15, -4, 31, 12, -16, -24, - 35, -7, 0, -8, -3, -8, 6, 1, -57, 13, -8, 22, 31, 40, -16, 35, - 34, -32, -60, -21, 8, -1, -13, -39, 14, 17, -7, 33, -35, -6, - -18, 0, 29, -5, -9, 40, -19, -45, 24, -41, -7, 32, 19, 28, 28, - -17, 10, 18, 6, 29, 1, -1, 17, 28, 18, -22, -16, 20, 51, 8, 2, - 18, 16, -9, 40, -8, -20, -31, 11, -5, 34, -25, -40, -48, -9, - -36, 4, 17, 15, 8, -18, 27, -24, -25, -13, 22, 21, -21, -25, -2, - -32, 7, 20, -8, -26, -23, 21, -3, 34, -15, 0, -17, -21, 56, -38, - -2, 18, -44, -14, 31, -2, -24, 3, -18, 18, 16, -24, -35, -48, 5, - -36, 28, 15, 13, 32, -14, 14, -38, -9, -62, -11, 6, 6, -26, -46, - 72, -63, -35, 16, -4, -19, 45, -20, -28, 1, 26, 36, -35, 30, - -13, 39, -29, 16, -30, 14, 5, 4, -11, -6, 22, -9, 5, -9, 14, - -27, -30, 23, 23, -2, -7, 30, 0, 6, 32, -43, -17, 11, 10, -29, - -15, 111, 15, 10, 13, 7, 16, -2, 3, -3, -6, 38, -10, -11, 5, - -34, -2, 14, -32, -21, 4, -5, 0, -8, 27, -50, -7, 23, 8, -17, - -63, -87, -1, 34, 5, -1, -11, 3, -6, 33, -9, -45, -34, 2, -23, - 46, 43, -11, 12, -21, -7, 17, -48, -42, -3, 7, 2, 24, 8, 71, 6, - 0, 9, -16, 6, 17, 20, -2, 6, -44, -13, 44, 23, 27, 13, 37, -10, - 58, 8, -12, -4, -15, 14, 27, -47, 18, -68, -6, -9, -16, 2, 7, - -15, -47, 34, 1, -38, -25, -19, 1, -10, 14, 7, 9, -20, -1, -21, - 4, -13, 18, -26, -10, 31, 51, -59, 15, -3, -19, -70, -17, 46, - -14, 24, 32, 15, 34, -23, -36, -16, -7, -10, 2, 36, 7, -12, -51, - -25, -8, 23, -18, -17, 7, -48, 9, -26, 44, -25, 44, 32, 28, -10, - 11, 12, -17, 4, 16, 6, -19, 32, 22, -31, 16, 8, 31, -4, 17, -21, - 1, 56, 36, 21, -31, -4, 0, -46, -26, -44, 61, -61, 2, -21, 45, - 15, -14, -35, -13, 5, -38, -10, -19, -7, -7, -33, 33, -11, -12, - 29, 17, -27, -46, -48, -25, -13, 6, 25, -12, -12, -29, -58, -2, - -29, 5, -11, -15, -19, 32, -58, 14, -35, -3, -20, -16, -32, -24, - -45, -18, -3, 0, -1, -43, -9, 12, -29, -2, 1, -9, -26, 5, -2, 9, - -17, 32, 27, -3, -27, 2, -7, -13, 4, 6, 46, 38, 28, -27, -3, - -19, -38, 64, 13, 9, -16, 35, 46, 8, -80, 15, -16, -19, -26, - -10, 48, 8, -11, -8, -2, -16, -22, 50, 9, -14, -52, 39, 11, 49, - 2, 5, -11, 13, -4, 10, 11, -23, -23, -10, 14, 31, 42, 18, 0, 49, - 34, 19, -25, 15, -41, 30, 8, 18, 29, -6, 15, -17, 5, 30, 2, -19, - 12, 43, -32, 31, -39, 8, 21, 16, -12, -8, 24, 37, 8, -13, -54, - 0, -44, -12, -26, 31, 5, -22, 51, 11, -7, -22, 27, 17, 12, 20, - -8, 9, -11, 48, -21, 9, 24, 2, -4 -}; - -static const uint16_t ntru_h_1024[] = { - 6857, 4524, 6980, 4278, 8521, 9214, 399, 11461, 10346, 9318, - 2768, 1272, 396, 5635, 2424, 3623, 2071, 9145, 8766, 3391, 4900, - 10525, 6985, 3336, 5084, 11240, 5203, 4517, 7825, 974, 6450, - 11728, 3727, 1190, 1946, 2049, 10661, 1728, 1985, 8185, 9223, - 9410, 912, 7934, 2032, 377, 5915, 4515, 2076, 4073, 2109, 6749, - 7387, 4215, 11826, 2227, 4483, 10801, 6125, 5658, 4570, 11193, - 3749, 10418, 5800, 7159, 310, 2683, 453, 5616, 5109, 11698, - 1957, 11587, 11845, 11324, 3939, 3660, 6103, 1382, 6149, 6923, - 1333, 7200, 9403, 5990, 10319, 3473, 4771, 3113, 1322, 6743, - 7880, 11899, 3652, 1437, 6650, 8034, 11683, 11315, 2877, 8676, - 9741, 10509, 10783, 10635, 11008, 213, 3492, 8626, 9271, 4771, - 5099, 10209, 6359, 7738, 10860, 5853, 4632, 9862, 5942, 252, - 10959, 11867, 1685, 4189, 5995, 11443, 5328, 10337, 2968, 5209, - 8779, 4330, 7128, 11161, 9016, 12220, 4751, 4429, 7602, 5861, - 7151, 7129, 772, 4128, 8860, 4537, 4010, 1037, 1692, 11048, - 6880, 3575, 11950, 2203, 2670, 3213, 3925, 9414, 6968, 11107, - 11333, 11878, 11390, 3409, 1632, 5743, 11214, 4130, 5383, 10064, - 8173, 11054, 5112, 7029, 2850, 1905, 7673, 3131, 3383, 10728, - 8997, 4775, 6026, 206, 1602, 6698, 84, 8650, 4051, 2857, 1654, - 10234, 3560, 2220, 10072, 4755, 711, 3377, 3830, 1588, 6249, - 9108, 6301, 718, 4896, 4000, 5810, 14, 7962, 11835, 1619, 10486, - 3549, 3698, 4990, 2693, 2161, 7265, 7865, 10853, 5758, 532, - 9771, 9170, 9181, 10730, 943, 12226, 10180, 12238, 7892, 740, - 1961, 2829, 676, 5308, 8939, 9874, 11816, 8850, 2977, 2717, 535, - 11753, 2410, 4915, 8862, 3229, 87, 8181, 6423, 2900, 7322, 2728, - 11030, 9252, 660, 8255, 5084, 9638, 9905, 300, 10871, 8115, - 3921, 10583, 8542, 11888, 8610, 12287, 8303, 4353, 1249, 8437, - 4800, 11879, 11321, 226, 394, 3180, 8426, 8815, 11081, 10343, - 5780, 3187, 8139, 8663, 3271, 8829, 3961, 8000, 10424, 8944, - 8953, 8797, 11506, 9527, 5086, 3654, 2990, 2609, 9285, 10676, - 2126, 8322, 8388, 2907, 1729, 8000, 11960, 10595, 12191, 6735, - 9877, 2994, 5468, 8463, 9718, 2, 1224, 9842, 2220, 7347, 10016, - 5484, 11643, 3603, 4027, 8718, 1504, 5330, 6070, 6726, 10243, - 5581, 11371, 2288, 998, 11901, 9880, 8241, 3448, 10681, 12014, - 564, 4560, 6851, 9235, 5722, 10116, 12008, 702, 9412, 1818, - 2166, 2521, 3449, 9976, 1317, 8202, 2198, 2879, 9909, 8232, - 4358, 9168, 2723, 6954, 7861, 1599, 21, 768, 2337, 8793, 3970, - 3427, 6800, 3319, 10882, 3474, 11336, 6751, 2944, 2916, 2479, - 6692, 10943, 1129, 10958, 9778, 4105, 1160, 1789, 4091, 11799, - 9847, 4003, 7156, 6, 7913, 5539, 930, 5480, 4256, 4410, 11099, - 7276, 858, 2462, 7336, 7936, 10066, 9162, 1859, 4488, 7896, - 9090, 433, 11723, 12017, 2998, 2568, 7557, 3811, 5754, 6153, - 2684, 6011, 745, 3994, 10864, 26, 6792, 4045, 12039, 8465, 9526, - 3324, 4640, 2950, 11189, 11560, 10968, 3467, 9643, 3390, 3105, - 11058, 10171, 7104, 2221, 2882, 10809, 7349, 5094, 2277, 11876, - 5610, 9833, 11556, 9212, 1093, 4875, 1258, 6525, 1379, 6528, - 8903, 6134, 6783, 3749, 7107, 7032, 6685, 5443, 5050, 10430, - 12242, 11782, 9733, 1619, 3481, 11713, 8961, 1719, 6641, 2111, - 578, 6688, 317, 11397, 6930, 6025, 12121, 9635, 11230, 6031, - 4549, 10556, 5810, 915, 9655, 9997, 9300, 11651, 3638, 6822, - 2744, 6442, 11872, 4596, 9029, 6843, 7691, 146, 8712, 5846, - 9537, 2265, 8123, 10530, 3748, 10109, 4081, 8648, 6032, 243, - 5257, 7387, 3266, 11825, 9483, 5681, 8116, 6123, 5512, 1832, - 12174, 6471, 5779, 9994, 5717, 3438, 10887, 7041, 5482, 5776, - 5052, 1277, 113, 1592, 397, 11378, 8540, 5539, 2871, 4794, 3498, - 6522, 9072, 11037, 7679, 7192, 3190, 4453, 10689, 7319, 4307, - 9129, 611, 8733, 7051, 2177, 4032, 400, 8267, 10724, 6343, - 11699, 2709, 2348, 9276, 199, 8140, 1116, 4362, 10542, 7509, - 4463, 3631, 8311, 10476, 4188, 5615, 541, 11358, 10783, 2653, - 5769, 7483, 233, 7151, 7427, 6954, 8993, 8388, 2634, 2867, 8188, - 10115, 9728, 10919, 2716, 2602, 10405, 8148, 7446, 4372, 4018, - 7482, 9473, 6256, 743, 11460, 2574, 10848, 7890, 6186, 277, - 8438, 6377, 9923, 1538, 8021, 1912, 2915, 8575, 7640, 1224, - 6644, 7740, 8476, 7237, 8105, 8741, 8510, 2956, 7727, 5456, - 4878, 6062, 5590, 4643, 2031, 12027, 7298, 11101, 423, 11766, - 6001, 8391, 11344, 7039, 925, 12087, 4715, 7775, 2577, 12100, - 10177, 7515, 8393, 7854, 7358, 2549, 8037, 7490, 9570, 11450, - 7333, 9792, 6517, 6246, 6324, 5652, 4287, 2916, 10244, 6843, - 1032, 10596, 10106, 412, 1649, 796, 787, 9141, 8210, 11119, - 8722, 5557, 8075, 10581, 5333, 646, 11955, 8382, 10460, 249, - 10396, 1425, 10106, 9653, 2083, 9412, 9482, 10358, 5238, 4889, - 10735, 5696, 10184, 10472, 8912, 4715, 4135, 1850, 6734, 788, - 7911, 12091, 5068, 2196, 8528, 1228, 7261, 6719, 5451, 22, 7250, - 5546, 3002, 1364, 3609, 815, 9625, 6174, 11030, 1121, 5227, - 11682, 127, 9743, 2882, 2013, 6410, 3887, 5624, 6044, 6535, - 10445, 11640, 754, 806, 1728, 10444, 3467, 10796, 1342, 560, - 6412, 9877, 4231, 1004, 7563, 6241, 6650, 7678, 9513, 9268, - 5824, 756, 6364, 382, 6099, 11818, 3452, 10664, 9035, 1892, - 3627, 7790, 2766, 4747, 10766, 2582, 8247, 1343, 5404, 8999, - 1306, 2323, 1697, 3027, 3992, 10237, 12264, 2504, 12196, 285, - 3341, 1023, 11597, 65, 3054, 7012, 3354, 3802, 6381, 11090, - 7956, 8016, 5817, 3082, 7822, 10676, 10795, 9182, 3766, 1386, - 7018, 9919, 4122, 4277, 994, 957, 10047, 4963, 6036, 1829, 3699, - 5927, 2986, 11757, 1091, 8586, 4136, 5998, 8614, 738, 7930, - 9614, 1038, 3465, 9461, 8800, 448, 4790, 6902, 557, 2952, 10752, - 10914, 3678, 10642, 6378, 4775, 8587, 424, 160, 4814, 2921, - 4061, 1553, 10018, 3960, 5267, 1357, 11229, 9706, 5480, 3599, - 695, 9316, 12014, 8205, 274, 3219, 7113, 2914, 4379, 2025, 3948, - 10733, 2075, 9903, 6767, 7202, 5303, 10864, 11908, 2946, 1579, - 5946, 11135, 3629, 12006, 1620, 6884, 6120, 9640, 3085, 8987, - 6885, 126, 8477, 119, 7775, 10599, 11996, 1533, 6606, 9624, - 7770, 3292, 11468, 11115, 9034, 44, 1631, 3867, 10484, 8799, - 6863, 10298, 6792, 10913, 1051, 3927, 3297, 5283, 7269, 10315, - 8364, 7328, 2905, 9803, 8593, 1567, 7314, 934, 10166, 7739, - 2512, 8874, 11011, 10479, 7844, 3646, 6388, 7202, 9880, 4708, - 1057, 9014, 11431, 6222, 4398, 2374, 6684, 4743, 7242, 8114, - 8995, 1222, 2096, 5121, 10994, 8697, 10848, 10235, 2380, 8095, - 7857, 6687, 8380, 7399, 3751, 5398, 98, 7175, 3353, 3777, 8408, - 10568, 12088, 5008, 10713, 10027, 3345, 11243, 2602, 2825, 9460, - 2218, 5381, 9106, 12214, 844, 7720, 8328, 3552, 7008, 11397, - 6321, 1422, 2261, 251, 11402, 176, 10570 -}; - -static const char *ntru_pkey_1024 = - "0a6b251ac6d110b685263fe063ecc5a1aa4662b404f8063160325e0e27205e3b" - "988f8d3f4c9291d6d24d084f72be8514d1a57a443ce64cadd03a3c4a61e68801" - "a6946c01f05ff9901e4c20e41efe1fc01795c6d1a32070fe920f5a5d736d077b" - "8c88b3460ea315fb561a476abb93a968b25aa1bf704d8a7b07155f04fd6db21e" - "96d43b916c3c3d8ce4c5f5c5666015b0b14d5c2092ed766a13cd914a8cc2914a" - "9a577b22e7b391059d67e9f62b68ec332cf61e4983690da87e98bac000d53692" - "1b290dd2a34fae7e1635de3aa9b16dd48626865cd80fcab3ee5b1a5505d5daec" - "b353428612e61459892d0ea6f62b998ce2fbc4a3d14d76c96e56fbdbd90c1102" - "08a711b93ea840d1a72b286b80df7bab889b29b8c8d3d564c66ce2b63b116e66" - "b1f8d51198166faf39022541e7507fb6b2e4fe1b752c8877177e4c3b34de9e88" - "c952a75e280ce1909a2a01521ca3f4cb2919da7fa37a08ac9d612930b1cd313b" - "d863461a639462742ce4c80fa05ac800e7c6ae3b194e8f63774e724df8a8521c" - "5c617ae6a6559f821498ae3d28f769ea0ebefc29f12fce7b502e41ea4b0d0a91" - "4bc8bae692b8a22922e84a9d085ede925a93338a78c9d015dff5645cb547268a" - "a8ac5a4240a5203f4f725a69ac412ca9ddfb33d46957857ae70868afff81bd10" - "113860f54b02e67b0e40e20628c6c83aa26fad268675a50c737f2e1d7331e27d" - "3de5f40a2e22f08be625db3ca5374f78e462eb8a3191169b4213a0828310b5b1" - "b05f40bae2963be7da4f9a54bb2557210f97d8002132267222b1cb39c8156cb5" - "ece133eee20e17814d25ed9a46a00d5cdb1ac8f00f9ae7d9a6203135e29b9bbb" - "82344741ac3904d65a9e12ee80afa4c41c688762764d799be052580288962cfe" - "6b580a11068f40aa36ca9eb518fc0150c009218964f82358da9033dea82364ac" - "48697cb802d909af6892abf11a6ace98c900912206fd3feee1799dcfa36fd000" - "67ba55a30e89568428113aad6dc6c0d6899e72a1f009d4a3ca1d0d1887b62382" - "06c6dcbbbc4bb62821d853b8d67a6024a7c5dec2e93e6aa700069a883f36f078" - "44653633f12202e1abb5b4a2ad8362e5ab34f8c21acca7bb6f008ad2d0aa3972" - "d53e62396e6457aa669b4923fc111530b13a997d158d9808b1d7f669fcea56f0" - "db7868755434eea8bebf4ae0698146533666dc18c046b767c483f0909a2004f6" - "c856c49789bd665a3af7978f471693c5ac839396de70d9152d8338d9aa62ae19" - "2ab9811f48d15abb782c09288216d695048d97eee9223a9277d3fc61c85e400f" - "35225cdb330ae31942d6317ed17eb5620728be399475a4e70a5954d6eaa1db81" - "55a96904ef04fd01c46380636c7285715a32cdd2ba36a997a8dc2b1d77fdc183" - "1d9165a705c97434e3a9098e21d6e2c8813f00190812e9e4631edb32a5492c90" - "f00c77f3045c442a92e755516f38be077a3b105c57bc21db17aa1f297568974e" - "c0e96fbdd036caa3218310a4a2ccdffc9e0e600aa9ca9c28aa8a57f51d164450" - "fb274ea50161c02e7b310a0ea981ed260a811583d98e99b0c6027d547782d8e1" - "7f77604c867d1e3c8471c457ea622584f8b8c78bd5504c397ae57592231fbeef" - "b720ab5d069edf65dc60c7b141b7f0e76f3749ade5f2846f449f05d5b8325eae" - "72f89f57d95d42958acba729664065d586662d161442fcb64a011abb10229649" - "de819c19c431c0c4e3b5804ab6f88495b57e2e9555354286bace0bea3700f9a2" - "705919dea5b5208e4c4942a87651d9319a7bd6409f228e88b4126b409c73a693" - "83147b9ef3b4f3089485404cc7175a3f552c01671495aa2ee8554386432f9665" - "81eac5846151aeda201fe60f2d087dd6428f2f57e179c661e8cdb5e02f20c986" - "c0a330d8ba8b053e08c190c9a550870fb1d8b61859fa77fa52990d16c00bd18d" - "c05f97d3b8a8d7ca6a234b1d90e2b79b8ace4a2ea0e285a03714fd51c8c9c51a" - "244c6a12f4cf989ff6fe82722fa40474d0d0ffed4d0104bee6d90d1a3b698eda" - "d49f147d416b93029e8ea6d2a2b8f78eb615a9b6a9afd01a42d43e20ef673f4d" - "8d7941c94e735c9cbaab7b444386290285dba1a60b89efa963840e36264f5898" - "01c04ad9af608b4b88a802aa2397a99263a92a7862c1a802812ce2da4fdd1846" - "7223de14931536bdd97a9568383c2b79192eee8034112324dbc92d8911b1fa4f" - "6ca7b481b9abda6f70894b7a9c2e842e0862b5ceab7f38b6ee61951ae45fa25a" - "8303631b6b9407e8474077797e967bb705fd673a5987968cdcb332b6b8d2802c" - "197cf1ba3d225f6b3e83a6a22aa1106cf5733854a3719684b82b1ca02d6664b8" - "64461f72483a69ed9e3b27422aaac0e8ef7a90e3e63d1c229a612641086336b2" - "9d84e44b894668712877129fb28c8c4c620c1401abca1f9a9827fb2531f9f7ac" - "5a1f82f1ce73a9d5160189c073464ec18362948bce1390a76672b3446beb28a8" - "b0993d08aa5416392bed834c78a20883781b60b2158b116388d503eec8a02c29" - "4a"; - -/* - * Each KAT test consists in three strings: - * - nonce (hexa) - * - message (ASCII) - * - signature (hexa, uncompressed) - */ - -static const char *const KAT_SIG_16[] = { - "895f447be01f4cc0587f79397ecd820d752b1876db1197e653d4b28a88d4c0b7", - "sample 0", - "04fff00097ffd2ff100026ff5f00ed009ffeab00cdff4bffe60012ffcdff8b001a", - - "cd6a86be9c547f5e19f075f5e64068962893a94027eed40d2e8f751b266d4422", - "sample 1", - "04ffd1ff10000000030043ffad012c00b90023ff030095fe5c00710055ff4f002e", - - "0e8abfcaa4fbe1579231543fc504e8a3148ce60bad5606b731839ed669b15f68", - "sample 2", - "04002301530048feefffe50097016dffab000b00920098ffdd0063001b0077ff7f", - - "cf8f0c4c78d4f0df639645092bb454c298a8772644daff56f432f14697c56596", - "sample 3", - "040136ffe90035ff9cff33fef80082003cff91007c000bffd3ffe900ecff200057", - - "3f2de8a15575f0b4e8c6067ee6215e23ac49b7d1d9b4f9c7e9001e5f072e85a1", - "sample 4", - "04009aff4dff9dff39000a0003ff39ffd000570094ffa10086000e0076000a003d", - - "d0215b52167b13b86162d5908e3619ab72af795a7c66d2c3d3267257cdf29216", - "sample 5", - "040009002bffdb00580044ff6b0089006a00acff83004cff5a0083006b003cff51", - - "509a2be909412eef92ec16e6f93dfd7573f9de026fa1add893d8f9ef40511539", - "sample 6", - "04fff00067000a00620045ff200000ffc5ffd3007200ec0027003cffaf00e6ffa8", - - "a73711a028e954430b4aef317ea1d9f79c7e054a3e5314131f4df6c0e0bbfed3", - "sample 7", - "04ff6affd0ff8b00f600710028006a00560029004f005c0045ffcb0047004900e9", - - "546283756c4ca279efa5bf83c7a3a1cb0d8c68b925278f2ec27c7b7ad5b6ded7", - "sample 8", - "04ff7b0059ff260019feedffb9000dffb6ff87ff7f00c7fecaff5a002dffc900a5", - - "3af6b128ffc85e5694bc7a8d4809694d7644b186b31d119e1a2082d5054a4489", - "sample 9", - "0400e6ff98fee3ffab00b4ff5b00aa0023ffbaffa30088ffee00c7000701990023", - - NULL -}; - -static const char *const KAT_SIG_512[] = { - "cd3f225a65b2c6e155c2af799308af940212633fa519a4b4ddd22048ff8a7d06", - "sample 0", - "0900070058ffd7ff7affd9ff1e0015ff7fffce0038ff1affad0006ffceffd0ff" - "0aff26fefcff9700c9ffec008100470071febd01960023ff58004a0150ffeeff" - "a70150ffd6ff22ffafffef000dff43ffa3012b00eb015cff1bffeaffaa001f00" - "120074009cff2efec0ffc10095fe96009bffc90027002c0017ffe1ffc2000900" - "07ff3f0054fefe000a009f0036002e00310128ffaefebbfff9ffc600b4ff4fff" - "31ffa9ffdd01da00a20010fffd010aff8b013cff7dfef3feccffd3001aff92fe" - "3f0042ff35006b0025ff9300b401db0049ff79fe24ffdc001e0061ffe10044fe" - "98ffa2ffff0016ff3200cffeaeff6bff4dfece002effe0fe66ff3aff89ff25ff" - "6afffc007effd4006bff02005b006900c8ff8bfe55003700290071ff5700da00" - "5affc7013a006cfff4007d006d00b3004f0004ff18ffecff2eff940070ffccff" - "4c0086fff7ff51ffc0ff7cff1cff86005b0088ff770099ff8d006ffffa00d500" - "abffdfff2700570076ff6c0091ffd500fe006b00ec01c2007effc90083ffeb00" - "43ffbbfee0ff740004fe86ff8cffe700faff49002d00a4ffb3ff7600dffef100" - "7cff6cff93ffb2005e0073ffd3009100cdff6b0022fffaffd5fffcfff9ff92ff" - "b7001301080011ff9200ca0018012b000500f400f7ff74011500b7004dfffcff" - "48ffd20078ff37001e008e01430086004cffc4ffdbff3fff51ff81009b007400" - "8fffd700870031005dff19ff8d000dff87fffdff8aff63fe97015afffafe9800" - "5300e5ffb4ff4e006affe000e300f80094ff45fec600c600b400d2ffab010e00" - "00ff32feb1002b003f005c003fff3f00be0014ff29ffd4016aff06006e000aff" - "fa0026007d00ae0047ff50ff460078ff36ffd3ff88ffd6ff0500120075009dff" - "c50062009effddfee4ffc80150ff64018f012a007cff78ff83fffb0027007101" - "4e000cff1bff6100ff00220039ffd1ff48ffec004f00390079ff5a0067004c00" - "20ffc7fed300c4004bffacfee4ff2000b60030ffe0fe5d00320015ffc8ff30ff" - "20ff46001b00e50115ff3a0034002cffc2ffe200110007ffe9ff56ffdffff4ff" - "250004ffc30028ff3400b3004000c4009f013bffe7009900350038004dff1301" - "b5ffae008fffdb0084ff44ffad008d0134ff500003013effe1ffc2ffb6fee800" - "34feb40179fff5fed4010bff74ff2aff38ff5500a8ffe10038ff140010fe5400" - "ddff1afff300300014ff2b00240016ffb8ffc000b2ff6a0022007a0067ff7100" - "caff7f0087005eff86ff200098feab0003001300d7ff860106ff96004bffb0ff" - "c500e700f5ffaeff00004cffd8003aff8cff80ffbeff6e0066002f0032ff7afe" - "c9ff80ffc6fe770128ff4eff8800e5ff74ffeb01650048ff3d009bff95ff35ff" - "ad00dcff5302200113feedff94fec9ffc2ffcc0002fe84ffce01c6ff7dffd6ff" - "c9", - - "a1526fcfb875c35db412013937e99fb7796360f3cccfb1a2cbf175c0cb1d6d35", - "sample 1", - "0900bcffd1fe860096fea6ff0ffe5bfe10ff17ffb1fff7ff3400daffe5ffa600" - "71ffaefff4017efeea0050fefdfff5ff84fe96ffb3ff05ff91ffa90072ffff00" - "eaff7cff56ffcefff2ffb5fe8cfff1ffd60011ff4aff9500740024ff27010c00" - "4d004801720098ffe80088ffe3ffb7ff84ff24003500c4ff1000590078008f00" - "68ff75ff5300f90006008c0074fea400a700860119001c00300079ff6dffdb00" - "7700f700c40007013dff8bfeec0024ffaa00420199005cffc7ff25ffcd000f00" - "ecfff9ff39fff90088ffab00b9ff66fe0fff960097fed8ff77ff8c0008001000" - "73ffb0ff4ffe29ffe7ff56ffb20007005c0012ff4bfffa0097ff7bffbcffc400" - "0100d100290058fee000f2ff02fffc00abff2affe6ff7dff7ffede00330049ff" - "fe00a8ffd4ffc400af0035ffe6ff42fe75ff31013a001400f6012f0030002a00" - "19fe770152000700b60030ffce0079ff69004dff930116fe57ff89ff5500dffe" - "dc0058ffbd0065ff6b00e5ff620076ff50003aff5bff4f000e00c0ff8eff3000" - "ebffdfff3dff74ff59002bffe2ff7afffd00890099ffb4fffd00100000006dff" - "be0058fe85ffd4006cfef1ff4900a4ffed00a900e0ff8900740085fff5000f01" - "2b00b00014ff18ffbe00830045ffb8003f0050ff1affb50090ff27ff95001500" - "01ffb800940007ffddff2700a7ff9500fb00b3ff6dff9300d7ff74fff7fec3fe" - "50000e002d00adff3e00b8010c001c00440016010a00b1011eff65003500f6ff" - "c4ff4d00e2ffabffb00056ff480047ffa3ff8bffc20066ff4affdfffe7ff3c00" - "7ffff2fe870068fffeffa40058feca0012ffed0022ffb4ff76008a005000a601" - "f7ffdb00e400660098fe61ffd6002f00d7fe34005f000f0013ff23004e005fff" - "2c0034ffa3ffb5ff070029ff64002a00f0ff24ffb2ff7c00920072fff9fff8ff" - "79ff23fe5dff1c00c100b4ff44008f005c0086ff3e0050002fff3500daff93ff" - "7effed012c008effba0195ff60ffbbffbf002fff210129ff6d001500daff66ff" - "7b005a0095fffb009bff2eff5f0032ffa0ff1c00ddfef800d0ffaffedd0164fe" - "8affc7ff98ff0aff20ffdaff8300b2011affa90092ff5dff7eff760050ff76ff" - "0cff15009effeeff94fff0ffd2fff6ffac010fff6afefaff1dff16ffc60037ff" - "b1ff9effaeff2b008700a6006dffa8fff4ffddff89ffc8ffb30041fe97ff27ff" - "16ffb400b3ff83ff2effcaffb900b900caff5a00b7ffc000330006ff350054ff" - "a2ff90ffcd0014000e0089ff65ffc80025ffdcff00ffe7fed0006200e00082ff" - "34ff700093ff61ffe6fef9ffe60119ffecffb20021ffe40012013000a4ffc1ff" - "2cffdbffc9ff7b006b0147ff91ffd5feea0040fec30015001f00bfffe6febe00" - "d400cdffbafed6fff9fee0ff630044006100b30065007901380084ff8000da00" - "09", - - "0c48305764bd939fcac5f86b9e40a18bdbc7c26fd28d875a24328cd2dac3a224", - "sample 2", - "0900060003ff940042ff8900cd0100ffd1ffe5ff64ffcf017c003500c9fea600" - "04ffa0004aff42fe95ffb7ff3e007d0035ffb4ffa700aa004100baffd3ff2801" - "61ffd9ff940010003b00680020007000c7ff50013cffe9ff63005f004affd8ff" - "f1ffaf000bffa800280120ff8b00d2011fffe00071ffb00137ff5300b70012fe" - "a8fed20068001eff2b0014ffa4ff64008fff32ffeaff310063ff190021002900" - "2e003c0070ffbcffadfea4007c0106006d0071ffbe007a0018fed4ff48001eff" - "8affd1006900a8ffd2009a00edff11ff43ff01005fff42ff65ffe8ff8fffd5ff" - "18ffc500c901180179004dffc10056002c0020ff7fff6c0032fff200f300c300" - "9bfeff0137ffb900f1ff1effec0019fffb00bd0022007c009300ec00d6ff9cff" - "5e0010004d00da023cffffff41004b0036ff6c00b4ffef00b1fed401440044ff" - "1b00f60078004300cf00d00067003fff51004e008f00d5fec000e7000e0062ff" - "bfff8cff20ff9aff9c008e007c0038ff44ffd00156018c0060ffd6ff74005d00" - "0600a4ffaf02a50096ffacffbf005b00bb00c10000fffcff54001aff54ffc200" - "1900edffdb004a002701480135009100d8fefd007cffdfff95018200cc0039ff" - "2a010cff81010bfefc00a0fff80096010fffdc008b0036ff7eff4cffcfffbeff" - "810058007100d7fff2ffec0021008aff7d019dff7c00cb0013fec3ff7e0098fe" - "e1000801c3ff9800c300a500a2005a012fff7500a4001e004e00a00045fef8fe" - "b801afff0800e300f6013d0098ffff007800a8ff00fefe0105ff0fff77ff2d00" - "1bff7a00a900150095ff100011ff99fef700c1ff51ffa50141ff5affdd00b2fe" - "34fff9ffec0013fef2ff2eff91ffdf0021004f005f005eff8b0015ff64ff4401" - "5eff4affea00ff002dfe56005dff02ffe70088ff4a00a5fef9ff5fffc50032ff" - "c400eeff8cfee80111feb5ffb5ff9fffacffcfffbdff0700370042ffddfee700" - "79007e009bff26fe2cff3e00e3ff73002401370056ff9700f6001b0016fefc00" - "aaffc2ffe30005012b0059ff81ffe10005ff7200ea0026017aff92ff7a001d00" - "55ff88ff97fffa00a1003c01a300790157003aff62000e009401460077ffbeff" - "f8003d001701bc000dfff90027ffb100a0ffa000f2ff21ffabffd80114001600" - "b7fecfff20feb4ff33005900a0fef3fedeff9e00de007eff0aff84fff7fedc01" - "13ffaeff9200d1ffd4ff650086ff49ff87ff57004a0065feffff82ff5bffa501" - "43009b0097ff81fee0015000000127ffed005f004fffebffb1ffdc009bff1900" - "88ff790138fff700b30157ffe0ffbefee40083ff830015005e01560146ff4f00" - "26001700fcffef00950069ff4dff43ff30fe51ffea001a0093ffc7ffc6ff81ff" - "faff79ffd40077ff64001eff40ffb1ffb90042ff41ffce01490066ff9f00a000" - "20", - - "782658797c488ce4f873262ce6a9e78561410c258c60c268c3f4be762578a8fc", - "sample 3", - "090065000f00c100fbffa7ffd7ff3e000e008dfff0ffc3ff4dfef3ffb400b401" - "bbfeb4ff12ff5800fb00d3ff5eff0dfeb80095fe9600cdffccffe8fecdffa2ff" - "a4ffe50045ffc70078ff40ffb800340063fecf003900eaffa0feed0077002800" - "aaffcdff470010ffe000edff0800e9ffb00093004efead00e2001bffe70012ff" - "aa006e007a011e004100adffff00aa0144ffb7018c0032005eff620069ff92ff" - "a5ff5b0093001b00ec0113008bff1d00f80057ff6e00d30022ff32ff2d002d00" - "13feb70136005d009200530018009dff5900d70064fed1ff96ffb900a6008bff" - "cdffe20062ffe700effedaffe9ffa1feedffb6ffe40040ff3300530146004eff" - "ec00a8ffdb003d007801000012feab005fff72ff6b00da003effde00c6ff5100" - "51ff5b0059ff1bfff3001dff7900fd011dff4ffeba009ffed7ff6d0080006dff" - "9b00370082003f006fff37007400210029ffe5fedcffa0ff2ffff70091013000" - "3bff3100e300640062fedefff9ffef00640009ffdd00ae00a1ffe0ff61ff9100" - "0d008c009b002500b8fecdffe7ff1fffed005bff7eff73ffa5fffcffdaff9000" - "ccff8e004a003f0052002100b3002a010e0006ff15ffc70121fee5ff7eff91ff" - "bcffb2ff5c004c00aa00b2ff3c007fff8dffdcff830024003ffe45ffb7ff9301" - "03ff2d00aa0088004afea8fffcff30ff35019a013c004dff41ffbc002100dd01" - "31ffd6009aff40fea500880133009bff3100830023fef100a4ff86019aff4fff" - "77fff7ff2cff3100160059ff82ffdf001dff6affb200d5fff60094ff54ffd900" - "29ff6500beff98ff6c005bff29fefdffb5ff58004500a2fea9fedd002400abff" - "fd016e0007ffedffcefffcffa00086fe2efeea0108ffb30051000100680016ff" - "01fff200aa000eff35fffe00d00199ff5e000cfef0ff17ff040061ff8800fa00" - "2b0016ff150018003a0034ffecff9eff83012d01290035ffeefff7ff76ff6e00" - "ff0072ff53ffaafff6ff81ffa600d10030ff82ffc0ff91002affdb0025007700" - "69fed1003d00c80033ff6a00a7ff440060ffcd015bffdb015000d300b3ff94ff" - "59008affeaff4e005b0191fff6001f00c900cdffbbff1cffa5ff670090ff2300" - "37004e006300310116ffddffbdffc800ecff59ff90ffb10024ffe2002f00b300" - "65ffaaff3d015c009ffedd0014000bff4b006700a20063ff51ffc0014bffc000" - "81ffaaffb6ff90005c007c0037000e0122ff0cff3bffc7fff10058013dff91ff" - "62fffa020bff1600880074ffec005c0028ffe80044ff97ff64012a001efff400" - "f7ff3e000e0005fe600007fee2ff4aff13009700ef010400f00064fec8004e00" - "2600920043ff1a007c003200eb0048003dfedaff4400510013ff4700580016ff" - "a3feb201b0fef0fede0048008e0042feb2ff7ffff9000d00b7ff9f00d6ffd600" - "f3", - - "ede0d5c1beeab1de0cf3eb392c3fa53a184ceb8e3745bb9dbf8a13ed01aeef7d", - "sample 4", - "0901390087ffc4001effd6006a004a0089ffb3fedeff8200360071ff7bffe4fe" - "fbff8e00d2ffc3ffc8feb7ff34ff24ff15ff44ff880042004f006afefcffd501" - "09ffc9ffbfff76ffd1ffc4ffe8011fff400128003fff760025ff55009300a100" - "a20018ffc60077004c016eff2bffe4018e002d00b9009b0027ffd5ff1f00de00" - "19ffb0007cff94ffde00b1ff6fff26017cff10ff75ffc6fe62ffce010efed7ff" - "f40069ffe1001e00a6ffd40011ffbc000e013fff91ffdcff51008500a500c7ff" - "ffff4bff9f0021fff3002dffe7ffc8ffa3008500550092ff1cfff7ff60011600" - "a8ffdfffebfff4019f00dfffb4007b016affb000900129015100b5ff7d000f00" - "b800ebff7fff6a00c70043003a00c3ffb000e1ff78006a00fdff84ff65ff68ff" - "d8ff22ff81ff28ffc60075ffec0040ff59ff44ffbb00a4ffe100000026fedffe" - "fdfef2ff67ffc80016ffd5004efe2e01ebffeb0012002cfe3dff46ffd4ffecff" - "aaffdfff46005f007e001e01d5005fffd3ff4c0062fff0004501a8013c0080ff" - "82001bff94fee4fe27ffb6ff9c00320099ffe4ffb9fe8fffee011bff01ff6c01" - "ec006900f500830032ffcc0108fffd0101ffb60019ffe2fffbff2100cbff0800" - "bfff01ffd9ff0dffd0ff3a00be01940084ff5d003d003900310070007c003cff" - "e6003500f800d8ff73ff8cff85ffa900a4ff1efff800edffbb00d7011d000dff" - "b900150041fed4008f0004ffef0035ffe6ffbb00feffc000270015002100a5fe" - "890063ffe5ffafff6000340182ffd8ffbd00fbffa90008ff39ffda0149009600" - "fb005e001c0008ffa60037005d00ed000effb1002e0085ff78004900b300bdff" - "b200effffa0143ff2e000cfff2ffcbffbe003700c001deff7b006efe6f007e00" - "b1ff69ffd8005cffb3ff94000a00c300d300bfff1e0120ff8c00e4ff2f001600" - "2300cbffcc009900e6ffd7003c003200a10057ffdc003ffe7a000600ecfffeff" - "da000e004800a6ff72ff590078004dffd600f4ff580089ffd70049ff15ff74ff" - "9a002600d0007bfecdff9f0013002bffbeff5fffde00f5ffc4001a0052ffaa00" - "3eff9fffb302030091ff9201480034ffb7003a01730059007800eb00fa014f00" - "b1002bfff9ff5cff7cff48005bfff3ff3100bb009d00340047001f0047ff59ff" - "b3ffbbfef3ffda001b002cff1bfe71ffd20091fee100e70048002600f30124ff" - "1000c7fec0ff15ff7600e90046ffa5ff990095febc007cfffc0042004eff7900" - "bafff4fe83ff6effe200f4ff7300c2002bfeccff1a017e0041003301e8ffea00" - "9dffd5ff710082000dffda008100ca004f0151004c00230044001f009e004201" - "0c00a80045ff78006400fe0042005bff4b00d7ff7c00b000ccfecf0024ff4600" - "0f0137ffc4ff6000260002ffb40004ff37005000830032ff6e0105fee1ffeaff" - "4f", - - "fa4ba817c5ccf62fe37a5a3db2804b1d79b3475dd5df51d23a1e0505bc43ce36", - "sample 5", - "090110006ffef1001a004afff9002c01300092ff2bffe20174001a002effbeff" - "4affd50114000b00cbffb5ffccff7e00eb01300018ffdcffaaff72009200eb00" - "3f01c1ff11019affe0ffbe00c3fff5ffe30063012cff2000070001002cfeaf00" - "acffd60094ff4cff16007cff21ff74fef90007004afe610038ff46001eff9100" - "caff6b0080ff88ff67fee0ff61ffc700320032fff70078fef30022018bfe4dff" - "c5003effeb008bffebfef80005fffcff7cff62ffbd014400d8ffee00d1ff41ff" - "4e011900df003800a9006200670000ff9dfefeff74ffaaff73ff4e0057ffd400" - "e300b9015efe6b0021ffa2ffcd00c0ff0f008400d00007ff680014ff56fed0ff" - "330083000eff8d00830062ffe10061ff2c000c006cff70005a0041fffa002e00" - "9e00bbfff500840024ff6cffa30057feb80130ff230070fe890107009dff32ff" - "fb002eff47006200d60062ffdb0092ff4bffc4ffb0009dff61ffb5fee2ff65ff" - "34ffa90012ffabffc1006dfe17ff3b003cff30ff08003afff0ff280156fed7ff" - "c0fecf000c00c6ff5fff37ff75ffc8013f0082fedcffb9fffe0009ffbe0045ff" - "87ff6b0006008bffb7ff34009a000dff5100b80063ffadff8c0113fea3008afe" - "22ff8bffcdfec0ffdeffc6ff37ff35ff230038006800d0ffdc00ba004d000100" - "ebfe8f00230012006effbaffe5ff1000a50044ffd7ff63ff660094ff88ffdaff" - "3d00cf00d900b4ffdb008200540012001400a800b5ff15ffd60016ffb200d4ff" - "e200fdffdeff4b0088ff870125ffa700b50092005c002eff48ffb6006b001a00" - "e700c4002300baff3800bffff6008effb600570047ffd4ff7c00f30037ffb800" - "54ff9b007affd400d3006eff8e0004ffb4ff7c0031fedd005f0019ffe8012300" - "62ffeffe2000680043ff6f0045ff840069ffa3ffa50033018900580117ffd201" - "2aff47ffe9ffc9ffd800d50010ff18fffd011eff70fffaffbcfe9dfef1ff7700" - "bbff9cff76ff17feb80079ff870059ffe6001affb8006fffd400efff64012afe" - "7b002f008bff32ff03ff56000effc900e90156fef30079ff3ffff500be007400" - "8100d7ff6cff18006cffa5008600f5ffdefffc003bff1100180111ffc2ff79ff" - "a5ff25ffca007500f00063ffae011900770044fe780076fff4ff57ff0a000d00" - "6dffee0051002bfffe00caff5efef1ffa6ffea0063009aff7bff3b00acff8600" - "4900b6fe90ffe3ff18ff700079ffabff60ffe70096fef2ff85ff4c001100d500" - "b60052ff98ff09ff62ff8f00cdffb90120ff4a009eff4afff3ffddffcb005eff" - "2500280045ffee00a0ff4e001cffbf002800cf004bffdcfff500abff7eff9800" - "54ff7c00470076ffb6ffce00c60056ffe9006e00140018000200d2ffd2ffa6fe" - "b2ffc3ffb6fffd003dff68ff66ff9c0062ffbf00aefee000bb0048ffdf007eff" - "2a", - - "69e5bf07ea263f1903a46ef2f9aa7551b5be6a784a575441c6a5b59750e41717", - "sample 6", - "09ff8d002b00efff94ff84ffd600a3fea9ffb0ff27005bffd3ffcd019b000cff" - "1b004f00d9014800bbffa6ff60ffa7ffde01e50065006e00e4ff76ffce00b0ff" - "a2ff4e005f00e0002c00450073ff6a000601c3ff7cff96ff94ffa9ff460189ff" - "9b00b400e40005007eff74ff85ff9bff110081ffd5ffadffb50026ff93000dff" - "76ff8dfec5fdb9fec8ffc201d400c9fe32003bff0fff4c0013ffa5fe9d00fbff" - "10009bffe9ff7b004b000dff45ffc5ff7affee0023ff540011ff6e001d001eff" - "ef0123fffbffc10119ffc70042fea1006d0135fecafff1ff46ff1effda01ce00" - "2100daff900027fed7fe48ff61001cff88003400cd005d001e0112ffe2ffbe01" - "67fff90148007e0002ff7e008100100055ff58fee400a6004400c9ff52fe7fff" - "a1ff39ff3bffabffb8ff70ff8b00490003ff96004d006b0058ff6201170025ff" - "a900d60008ffb700d200dc0116ffaeff5dfee7ffd6ffb10041ff59018affac00" - "adff9dff4a0131007d011c0016ff8f0072ffc8ff6bff010103fff8002fffaaff" - "d8ffda00c30054ffa30018ff0c00290088fdeefff6ff54ffd9ff78ff92ff52ff" - "6c0028ffe00014ff7cff28ff8ffedcfeddfe91ff18ff8dff19ff1affa6004801" - "5effba008b0145ffeaffacffbb0043ffd100cdff9eff9600b700b8ffbcff9300" - "15004700920165ffb60077ffacff88005f004a005cff520037ffacff7600cefe" - "e5ffb900af00acffa70065ffa60010006dfff7ff950034fffc00f7ffcb00a100" - "45000e00edff4affbeffea00adff6101a0fe3900c1ffee004cffa6ffb40098ff" - "93ff9aff92004c002bff10ff95ffc8008c0027004dff2600a9ff74fff3ff1b00" - "ca00b0ff23011cffe0ffc7ff530063006bffa6ffee006a0012000cfea3005a00" - "e40085ffb5fedaffe0ff810011ff3bfea2006300d1003300eeff880070feb000" - "3b008e0056004bffe7005c0072011e00d2ffa1ffe80102ffdfff00006fff7b00" - "36000d00340040ff8effc20015ffd5ff9c00cf012afee3ffc30081feb9ff0d00" - "1f00500007013b000b0075006200340016fefc00e700f400b7000cffafff65ff" - "280024ff11002400780081ffd0007fff98003effb600f3005a0054ffde005dff" - "3bfebb014e001c01c50000ff55ff48ff8cfeac0087ff840011ff20015200a4fe" - "df0057ffbaff82ff6a0050ff12ffc0ff99ffbaffce0129ff18ff7bffb2ff9efe" - "fa00caffc3fedcff87ffde004c0002ff4dffad001dffdb007b00e5ff9aff9e00" - "4bff83006fff6f00360009005a001d0006004f01200103ff0f019800a8007f00" - "06ff5fffe1ffa1fff5ff8100470077004500c20005ffc6ff60ff6d012800d701" - "370011ffa900ac0170ffadffbc006efff2007d004600920040ff58ff5effb3ff" - "64004dfe2affcbffcc0050ffef0025fff0ff54fe6cff1c00deffa70034011aff" - "85", - - "4bf3e3db906ad25bbe78cd425485eaa6c54983dc626fd919e11198dc01eb6f13", - "sample 7", - "09ff6900a500150109fffe0078fecbff390148ffe2ff03010bff660052009700" - "7afec40050fef0012d0118ff89ff84fff200fbfee700a000b100e7ff52ffd4ff" - "fdffbfff93ff2e005f00390013017000ceff90ff80ff4dff40ffe900270010ff" - "9effbdff930087ff73ffa300beff2cff97ff9afebdff06005a00a4ffb3ffb400" - "0efff8fe8eff39012c00010009ffbfff7cfffaff4200e3003b0026ff7fffb500" - "eeff76ff95ff5e001600a4019cff000029ff63ffd9000dffa6ff4cff51000200" - "2affabff2c001900a200af01080141001fff71ffca004c009700cd008900db00" - "340050fffd0045ff96010c009200e90089ff60ff1b00bb0161fe47ffb700cbff" - "8dff87ff7bff4dff57ffa000dfffac00b2ff55ffe9fff3ff67ff82fe51009401" - "19fecb004e01730001ffe7ffa1ff600002ffe60183fff5ffa4001900c2ffedff" - "4f00c4fef9001cffeeff65ff2f00bcfee2ff24009e0078ffde0034fe590088ff" - "bdff9c0018ffca014600a7008cff7bff4effecff5300770004ffe4fef2ff8a00" - "510047005500f0ff4f0125fe5700040038000a0043ff06006d00bb00b5ff91ff" - "70fe7e0004ffacff7e00070024fe6dffcbffbe002200b3ff91fe6bfebd0070ff" - "b4fff3ff570127ffdd00d10087004400310005ff4100060098ff960053fff800" - "56ffb4ff40fff5fffe0051ffa2012a00a6004301a5ff2cffa5ff5800f6ff33ff" - "b200b9005fffc000e7006c016a002500b300d4fff1fffdfefcffc200e1ff0fff" - "dc003e002cff38ffdaffc700150092ffc8ff90012a0023fff0011eff74ff3700" - "0aff82ff86ffa4ffcbffc5ff9affa60134ff5afff6ff6eff7d000f00b0ff1eff" - "dc00a500e0006fff2e00b7fff900870162005f0148ff8a00ddff9b0034ff6100" - "3d0103014bff48ff0fff250193000cff4a0063ff7f001e00a4ff95fe99001f00" - "22ff7bffcb014afffa00210088001200c4ff1bffbf00e100bd00ad00af002400" - "f4ff670038ff30006a002f006eff6fff60ff8cfeebff6f0133000e00d5ff93ff" - "2b00b20020ffd90121fff3fed60036001eff92ff6700b0fff7ff5fffe3ffac00" - "95000f0102ff0e00ff0039ff5e0111ff1eff80fff2002affa9ff910002005500" - "0100bb012f001bffaf000b0129005bffa9ff1700ccff54ff91fe5a0063007500" - "0f00f60097006100aefee10042004afdf6fed80083ff6200520002013200a601" - "22ff6c001b003200ab00540031ffa40021ffb800280124ffe6ff8a01310020ff" - "e800df00d1002cffddfe75ffebffe6ff5500af0092ff29ffd8006f011fffdbff" - "7b0041ff49004effb5ff110062002affc2004f017cfe9f0023ff7fff4fff93ff" - "2dfeafff64006b006c00ba00e8ff99ff8e0050ffa2000fff6900be000bfee500" - "04007a00720160007dfffd00f9ffa4ff0000b0fe70ff66ff4f0029000f002dff" - "d2", - - "857241e477e7b1d335e634874a6b61ed590180b7d9d7bccb7609c0e95b47143e", - "sample 8", - "09ffb90006000f011e0034ffbcfe9e0107ffc3fede0107fe55ff4dffea006dff" - "56ffd20064ff71006b0069ffe1002b0035ffd00080009dff37ff6d010500a6ff" - "d000c900f3ffc9fe8fffa400c7ff98ffbfffccffdd00d0006100be0086ffec00" - "82ff8afff8ff6c0111001b003d00220053ff4a00d4014700e7005d005effcb01" - "53ffb3ffe80000ff97007effeeffb1fff600d6ff18fff6ff74ffcbff01000c01" - "560002fef0ff8eff1f000efedd014b0025ff8bff4400d1ff2f012800af0043ff" - "1700b5ff9cff9bff09ff5e00ddff92004cffc9fe3600ad00c3009d004fff1efe" - "ea00aafeccffebffd4ffaeff890047ffb10115009aff04ff6600d300e3008501" - "5b000e00b60058ffcd00d3ff11ff0e00530023005b000000de00ce00b6ffe600" - "3ffe98ff4f0020fff8000f0105ff7bfec0ffc8fffc004bfff4001cff5100bbff" - "ca014100b0ffc8ffb000d1fff4ffbe0109ff63ff7b0021ffa9ff68000c002bfe" - "dfffa8008300a7ff7bfebbffca0031005d008000550039ff2fffa1ff4a01b8ff" - "2b0027ff37ffbf00dfff0a00e3ffc000a80064000efe39ffba00a7005d006f00" - "9e00ddffb7ffe8ffc2004a008cfffdffe6fee300ca0105016e00ffffd6007bff" - "ea001f004dffcc0175004e0123013100a8ffa6ff9b003dffc80046fe77ffb1ff" - "6301aaffb1ffb9ffbeffee00fbfeef0027fecaffe4feaa00b4ff51004b0052ff" - "410072012a0105ff88ffe6ff71ffa0fefe00280033ffe50043ffc40015ffc0ff" - "7e005500caffd6ff330065018affa5000bfff600230164ffa9ffaa0058ff3d00" - "100013ffbd004c00fe008c0029ff11fffd00890020fe84ff39ffe7ff6fff9700" - "b2fff1fecc0027ffabfffdffeb0078ffe5ffd0005afff9ffbc008000b500a400" - "8b0017ff7900710058005bff9b002e00b600090056ff83ffd3ff7dff060041fe" - "ddff9cffc9ffa100aaff98fefcffdc013300bcfed800a1ff9200420057ff1c00" - "07007dff8b009e003a012100b1006d00aa00ae0067fff800f5ff1ffebafebd00" - "ba00a9ff24ffb1feec003701d0ff7eff65ffa6ff2b008efeddffa70058ffb001" - "04ff3b00a7007100040138ffb600bcffdcffcdfe62ffd3005fff52ff6e0029fe" - "cdfdf0ff64ffe1011bff7a0042ffcfff8f015dff200069002fffeafef4002a00" - "8dffb5003c0100fec10019002f0092fe7dff9e00e7ff37ffc7ff26ffbdff5600" - "3c003bffbefff9003c00ffff3a0002001d00fafe69ff34ffe50020ff8dff7bfe" - "d80066007cffb00092ffdbffdd006dffea0047ffb2ff9100d200d80095fff6ff" - "08ff83feb50027fff8ff6300df006e0099007aff71ff5cff9bfff800cdfe4300" - "6aff4e0040007dfff8ffbc013400ae004b0060ff92ff62ffc90071ff5cff9001" - "42fef20085ff8afff7019c0071ffc9012eff73ffb5fecc0014ff97ff58004c00" - "6c", - - "032294bf7a7bbecbb2f4f0f474f7025c9cb6b6abbedba2ae4709fa7f430454ba", - "sample 9", - "0900fdff3800cbffe70017fe9800b0fefe0066fedc006b00e300a1ffee008300" - "5201720063ffdd0008002b0031010eff550029002e013cfffd0075fff6002fff" - "b1ffe100b8ffeb0006002dffe4ff9400b7ffdafe6fff5f005300a0fe94ffe801" - "2901e4ffe1ffbcfef0ff7dffe7ff9300530041005cff900164fe2bff9301a7fe" - "9bff78ff0fffbb0053ffb70017ffc9fecb006fffd801430020ff66005dffb800" - "d20029fee4fef3ffee00050052ff78ff9fffdf0076fff8ff40012d00d400c400" - "480098fff2001afe03ffc3ffe3ffbdff23000600edffefff68ffc70103ff2bfe" - "1100c40067005000e6ffccff8efea0ffc600ca003cffa3ff1e008a003d005d00" - "410041ffa100fb008b00c6ff2c007900300179ffce00dfff400008ffe0ff9800" - "e4ffd5ffa5ff42000fffe6008200a3fffb0030ff79ff6fff4effbcffbe000b00" - "5500aa00de0000ffbe00aa0000004afffa003000ecffe0ffac00b5ffe0fff8ff" - "2c007c000001be009f00cd0044006c003600b200aeff91ffe60149fef000aa00" - "48ffe000c7009fff4f0082001aff76003b0026013800a1fef801c9ff87ffd700" - "3cfe98ffc4003101bbfff2008fff61006a0005005e0022ff66ff2400bbffa401" - "96fef5ff6c004000420075ff38003b0040006cfefe00a7ff4fffcc0060007000" - "4c0064ffe9ff7fffcc002700e20082ff770047ffd2006eff970070ff880064ff" - "e801bb00740001ffd401e00017ffffff67006c0167ff83005200aeff85ffecfe" - "8c0078ff4b002700b00037ff8c00d50086ffa2fe550068013c017e004aff7cff" - "eeff08ffb0008d0018003b004500e0ff70ffb4017fff1b003affa4016fffa000" - "4e006100a2ff09012f00adffb50096fe9efee900cfffdcffcdffbf009dff87ff" - "7bfffa00d00088007cff22ff8700bbfeda01e1ffd20107ff84ffc3002a003600" - "97ff8c0053ffb0ff85ffb2ff25002c000a00160056ffaf00870044006600cd00" - "09002dff2dff64001effe0ffa1ff25ff5800620049010b004e006a00bdfedcff" - "5cffa6008400ffff5fff77ff83ffb600abff9f011dff67ff6200950074018d00" - "94feea01a6feb2003cffb9ffb3fe67014400c4ff6eff44fef60041ffd5ffc2ff" - "ed011cfe07ff9600370114ff5eff80015bff8100c8fed3ff2efeb700a8002b00" - "ba01070082ffc3fe90ffdfff5100580109ff6300080090ff6aff2a0071ffe200" - "e5ffe0ffcaffe6ffb7feeefff1ff03ffb7000a003cffa6fefcff20001e003200" - "4c00c700d8ffdbff2dffc4fea7001200440045fee8ff4d01270034ff75ffe5ff" - "8bff3b0094010b00affebcfff9ff0400f500960055ff02002a006afeedff9900" - "21ff64ff6cffd2009affda0069ffb30012ffe5fef5ffcd0198013dff2501a2ff" - "a3fe15ffccfff9001d009800d2ffdcfe87ffc2ff5c01bcfe8101f5ffcaff8dff" - "a4", - - NULL -}; - -static const char *const KAT_SIG_1024[] = { - "af0228b7e30f8c0a6620c8419cd181acfe6c76d134020a9fedb3839ca732f775", - "sample 0", - "0affe7ff90ff90ffc0ff42000f0151ff18ffaeffa0ff9effaaff72006a005aff" - "affe4fffdeff80ffe00078007800b5fff8ffe4000400b600550106007d0133ff" - "31007effb500730035ff93ffc0ffbc00ca0024ffd7ff46fffe0083009effee00" - "29004800260034ff36ff1bffccffbf0000ffd0005500bcffbe0036ff6900bf00" - "24ff0c007cff59ff15ff470060ffcc00380069ff33ff8000cfff62005cfffb00" - "3c004700d4fff7ffd80123005b00bdff020045ff66ff1d010400adffb100baff" - "f80101ffeaff5bfedbfff9ff85002efe2dff45ff85ffb700f000ceffe3fef200" - "2d000000b300e0ffcfff030178fee2ff0dffb4feb8ff930040ff93ff8aff4a00" - "560226fec9ff53ff50fedcffc5fe6aff8fffacff3dffd9004ffeca0089ffc700" - "3dff92ffffff89ff64fff1ffdb0030003bff75ff1500bfff64ffaaff65ff6900" - "29fec1ffff00ea009cff0fffa1018101ad00e90070ff470081ff9c00950087ff" - "230032002bffd0ff3f00c2fe9700aaffb300caffceff69ffadff96fefbff0cff" - "a2003a0084ff61ff42ff97fefdff58ff81001001bc006dfff700020195ff33ff" - "a0ff63ff6a0097012effd7ffadff32003b00320006ff960026ffeeffa8ffdfff" - "4bffd20014001300220068fee900510059ffa6008600c2007fffc9ffe5ffd7ff" - "ecffb400160109ffd8002e0006ff3dfee6ff83ffdfff62ff3e00200011fef900" - "cf003fffcfff70ff090026ff87ff25ff63007a001700e5ffda004b00b8ff4dff" - "990095ff37ff5b0135ffc0ff9b0159ffab0091010701d3005cfffaffb0ffec00" - "61fed400e000b4ff940079008ffeba00cbffc0ff070091ff90ffd3ff36002400" - "61ff33ffe2ff7900e3ff3900400038ffa500d000fd0080ff69ffe2004a00c2ff" - "f2ff7300dfff07ffcafe4600110113ffd20085003e00afff9d00230049ff03ff" - "1a002a00150041ff75fffcff6200550067003700bb002b0092ffd9fff3000201" - "68ff90000800070011ffb800910095ff10003aff8eff38ff93008f00c5011700" - "2cff2f01400152ffd2ffadff9b005900a80036ffe5fef2fff4febdfff6fff6ff" - "96002e00d3ffc6ffaf00bcff0cffa9ffc9ff3400e20015ff8ffea900ceff4700" - "60ffa3ff62ff73001dff8ffff3004eff54fe6f000dff3300af0028ff62007e00" - "63ff19011fffe3ffb3ff1dff95ffc8ffa40042ff97ffc2ff39ff7dff9bffda00" - "8b000bff6bfebe00540021ffea00320118ffbefee4004eff3c00d3fff700a900" - "1e001d0091015e009200bd00e7ffaffff0ff45012aff49ff010135ffffffc601" - "64ff6cffcfff25ff63fff10026002000e3fffd00650133ffc600b4ffdaff40ff" - "0700e20043003d00210001012500b6ffb4008bffd9ffa2ffd2fefcffaaff7f00" - "ceff0b0063fffc0019000bfee5ff76ffe50026ff92fffeff6f00d0ffcdff26ff" - "9cffe000210090ff720003ffa7ffe2000000e8ff8500afff3100b800a700d300" - "08008201880089007a0055ff500022ffe0ffe8fedaff0eff2d0012fe4cff0400" - "140068fdec004cfff6ffdaff31ff63ffb0ffa3012500ba005300cc0005fff0ff" - "f5013d00bdff50fe3400a40024ff95ff2800c6fed100f1010d001f00ee00d3ff" - "96ff83ffc40010009f0144002a0051ff36ff8b015b001800800067ffabfecd00" - "50000cffc500aaffa600580071fff4007e005fff37ffbffff6ff1ffeb2005600" - "8a004801570051ffafff27ffb400f0ff3eff7200ef00f2ff50ff99ffacff49ff" - "7affd70068fff1ff1c00b6feffffceffd9ffe7ffff00edff95007cff7a00f9ff" - "af0080ffc6fff1ff71ff1401a4ff190054fec6ffe5fea6ff6100eeff89fedf00" - "9600550024ffe4ffba00520080ffffff75ffb1004aff33002f005700e30097fe" - "2a00d50074fea6ff89001d00120007ff0fff38fef70052ff9d00180079007200" - "8a01920116ffee00a0ffca008d006b002affb6ff61ffc90002001800ab009300" - "940054000bff120058ffccff26ff96ffd0ff18ffcbff4fffa9ffc0011301aeff" - "8eff6bffdd00830181004800b30088fff900fd0041ffffff83fee2001dffa8ff" - "c00124ff89010a0050011500a7ff3200d0ff63005aff9900470005ff32ffe2ff" - "7300ec009e00e700f6ff20ff6f013200a9ffb7009cff4cfff4febaffd00009ff" - "08ffb0ff570093fef9ff75ff610016011ffec5ffd2ff84ffc600d6fff1ffcbff" - "0400e8fe88ff730086003bff82ff23ff7efea8000bfeb8ffce0027ff17ffe800" - "1cff840092ff24ffac00440035012dffb2ff950054006effc4ff67005d003bff" - "2fff520007fff4ff7dff68ffe8ff5d00b6ffce0046ff02fe73000b0132ff2b00" - "35fffd0085015d00a900570031008bffe5ff2b0130006effca0043ffdf006800" - "4c00ac00f6ffe8007affa30060002e0077ff47011400d8ff4effd30058003a01" - "76ffd80033ffa9fe8dfe57ffb9ff31ff2600a2ff78012800590072ff7effd400" - "4dff48fe8affe6ffc6ff4b00b70079002001450052002c009c01ed00ccff7b00" - "e3ff34fffe0085ff7f011900b5016d001dff7e007affa600baffe0ff6effe1ff" - "810008feacffb3ff8aff84003efeecffccffde013fffe900230059006c0006ff" - "94ff8b00a60089fff7ff70ff0dff1efef200a9006600810071003bfee9ff3500" - "59ff04ffe5008a002c0035ff8c002a005a006b004bffdd003101f00029001000" - "06ffecff8f00f9ff16012effc4ffd7ffba0020001effd50082ff4fffef0083ff" - "74ffabff8dff6f00680097010c004cff2d00a0ff83ff7b012f0000ffc90121ff" - "73009effcfff5bffd5ffa6ff82ff9dffc80071008bffd1008dffaaff14fe7a00" - "d30089fec3fee6ff6f0041ff7600170104ffceff620026003700430056ff9200" - "2c", - - "0deb2593f9773204e70b1cac2898e54d8c75b8c86918a711120622feaf80994c", - "sample 1", - "0afedbffe8fed8ffc7ff83ff5effd4fffbff71ffca01e9fe37ff2f00be00bc00" - "3a00cfff9300b1ffaeff13010d004bffcc00c50038ff1700abffda0048fef900" - "80ffc7ffbd00150097ffc3ffa8ff500116fee2003bfe5bffa800afff52003300" - "76fe46ffb2ff98007c0043ffdc00a60046009bff8aff99ffbd0008009bffc7ff" - "e5ff2b003cff65ff52ffd80031ffa2ffbc010bff81005c008800fb00dd003800" - "85001900b2fee1006fff79006dffa0febcffc4ff5600ef00d0ff8aff64ff87ff" - "b60027ff540056ff9effbe005b0114ff6aff37004fffb9fe5400e101cfff6500" - "7600d100fe0068000eff25ff5900b9ffeaffbeff11fff600d3fffc0008ff5400" - "e80035ff5bffb1ff6eff9300f0009000c3ff9c003c00d4001fff2afeb6001a00" - "bdfe6500caff880050ff8effb1ff5100a2ffbe0007ff49fe51ff4900f4ff89ff" - "f4001c006e00060017ff35009300c7ffd90031ffc200ba011f016d0008ffe5ff" - "df00e4feb0ff5f00a8ffbcff27ff86ff16015cff6d008e00c900c30055fefb00" - "3f00c300c8005bff540022fece0009ff42ff2e00dfff8dffdefe75008bffc4ff" - "edff6100c601110010ffbc003a00310057ff4dffd8ff7efff5ff35fe6cfffc00" - "a1ff9801510038ff89ff8b008cff78002f004b003e003d006c0152ff57ff9dff" - "27002800d1fffe0134001800660037ff39ff95ff5bff5a0144ffa700d90140ff" - "94fe56ff14ffcf0074ffd600360189003affe2ffe4017f001b0074ff5300f800" - "edfea1fee70033fe1a00f4ff6700250010ffddfed5ffae0094ffd4013dffbaff" - "aa011f00ab0055000c001cffbf004b0031ffa4fff800420102ffa5001b007400" - "a7fffffedcffadff63ff89fff7ffe00039ff9fff1fff7e005dfffdffbbff51ff" - "bb0112003200b80093ffd6ffdeffcd003e000cfffc011aff42ff18ff46ff9fff" - "a90149ff80012dffa000bcff65ffd400560111ff6cffb4ffa3004eff4affa2ff" - "59ff52ffd5001a0089ffb900b6ffaa0150ff93fff300ee0066ffb8ff8a000bfe" - "a90033fff4ff4cff8fffc50081fefd00540108008fffceff330114fffeff99fe" - "9cfffcff5400d1fefdff9eff5bfff600afff7a0090016800aefff8ff4500ad00" - "4fff5afe83012affb5ff18ff40010700a50150ffcafec0014d0016ff58fecf00" - "04fea0ffa7feb6ff88fea6ff45ffdd00ea0012ff86002300c00166fffcffd801" - "bcff6a01a6ffba004fff7c00fe00eb0012ff75ff50003b00d5ffccfee3009aff" - "ff0051018200c2ff3fff48ff7efffdffee002500dfff7e005b0107ffc20054ff" - "f9000800acffbdffb9feb8ff45ffd7ff91ff94fe91016a0097006a00350017ff" - "69ff5c00740033ff32003a008aff4f006f0061003b00b9ff6eff05ffe8ff3fff" - "a9fff800bbff5c0065ffd7feb90019fffdff8fff65feb9ffaefe8b00a8ffe400" - "17ff6c00ee0090ffa700c2006dfec30058003eff17ff6d00f6005600abff18ff" - "c9ffb0ff48fff7ffcaff25018a00140038ff5b005bff8f0037ffcc00a4ffdaff" - "cdff880083ff2bffb1ffc3ffa700bd00a5004f004d014a002100970017fe7f00" - "640104009dffddfecbffed0087ffc1003dfff20061ffa6ff380020001cff21ff" - "a20102005effccfefafe7c00acfff2ffcd0033005f00b9ff6f01600015ffd4ff" - "87ffdbffdbff34ffcaff620012ff4fffbaffe20064fefd0021007100b600a7ff" - "5bfff0fff7ff51ff6100cb004dff6f0077fff90089ff7c00c3ff08ff79016b01" - "1f017200ad0023013e00ae014b00a2ff8efffaff4bff50fe6c006cff85ff9bff" - "4afffd000a006effe201070030fead00dd0033ffe9000efee200cc00bb0077ff" - "ee0028001eff39ff4200b900b70019001e003dffcaffdcffd3ff5cffa300d7ff" - "e8007400320036ffb00028fed0ffdf003afffd007efff10061fff50119ffd8ff" - "8dfefb00b900f7ff94fef300cf00610059007700ad0085ffcfffcb009fff4e00" - "e3005a01600034005cff93ff8eff0c0080ffe2014501200090fe76feb80105ff" - "5d018a015fffc6ffbcff63ffce00aeffadff240018feeeffae01250055ffbf01" - "00008b002a006fffb800d5ff1efe8dfff2ff870100012800d8ffd000d3ff7200" - "0aff7aff3bff0900b000ff00ebffb8ff7c0016007200cafee80089ff7a00f8ff" - "94ffe0ff2dfff3017bff85ff6c004f003affc100dbff22fef5001c0075ff7c00" - "24ffacffee013c00deff3200280064007200e3ffa3ff77ffde006aff2a000401" - "3000e80050ff690043ffa40164002f013000bd00abfeb6ffae012cff00ffd4ff" - "ec003efff00143ffcbff89000a00bdff8200bafff7005e0097ff5b0146ffe1ff" - "dc00a7ffc5ff38004affb5ff6dff7ffed4ffbc0031001c0026003d00a2000400" - "9cff73ffdbfeeaffcdffb9008a002000410079009affe300a9ffb1fffaff7b00" - "b7ff70ff6dff08ff03febcff9f002eff9601660045ffd2011a00540075006e00" - "0bffd0ff870008ffbeffe8ff0700bd0084009d001bffd90068004e00ffff37ff" - "d300e9fef5ff290003ffe000b0001affde003200ed0016ff6a0106ffb4ff7afe" - "baff84ffebffea00a901630075ff11ff84001a0134ff96fffb0057007efeab00" - "f9ffeb002c0063ffb4ffd50069ffaa005f00170020005600090048ffdc00e3ff" - "000020005f0035008f0008ff59feef00a8ff630068ffb6007d00370026ff7d00" - "240095ffbcffa4ffaaffe000940086ffb6ff9a003cffcf003200c5ff08ffe500" - "2700eefe490018002d002300b200c8008aff5bff3bff07ff7000160043ff1500" - "82ff2a00f1006a00f1001800280151ff1bfff7ffe30211ffc6ffbf0005ffd400" - "a700ac005a0079001500f70020ffb8ffdeffa9ffb2ffc8005f00f3ff76fff5ff" - "e2", - - "d6f42222c7d600a0168c614d04927d74c7dc3b3eeab9c97d18637f7d658c8e0e", - "sample 2", - "0a012d005500d3002700b0001cffc1ffe20005012800a9ffd8feda004a0047ff" - "140040ffe1002700d7006d0088ffdefeb80043ffbe00acff56010d002d001600" - "4a0048fffa004700b0ff99ff83009a00910058000bff81ff230033ff4500cc00" - "7effa9ffb100b1ff7aff50ff62ffd4000dfebeff9fff5eff84015e00d1fee800" - "160114ffe10269002efffffefeff45ffd30021ffeefe84ff6f00470029ffa0ff" - "43ffed00590170ff530069ff9b010b00b3ff65ffe0fedb00c9ff89fffd0066ff" - "faff4c00710001fed9ff870014ff89009effdb0059ffe9ff3000b9ff03002b00" - "2c0016ffc7fece0110ffe0ffd3013c0040fe6d0029fedc0010fecb0000ffb8ff" - "6cff760079015a0162fffbff6aff490116ffe70037ff79ffd60022ff0a010c00" - "a8013500280014ff1fff96009fffdcff860026ffb600a300acff8b0032005eff" - "a8ffea00ed0140ffc7009c006e01180040004eff43015700dcffa4ff3b0050ff" - "c6004cffbc0075ff1200f2ffed007e00e100c10012007200b9ffd70013ff52ff" - "ecfe80ff2dffed0061013afff2ff93ff72012c0051fec6fe78ffddffb4005aff" - "6cffc2ff9d0026001d0024006a0023ffc2003cfff50018ffe4ff5dffafff6dff" - "1effbbffc7010cff6aff3e00b9fee6ff4b002bffecffbd00d800fcfe2eff53ff" - "db009ffefc00a1ff48ff56ff83ffb9004c000c0024003f01660056012a0013ff" - "8e000400460025ff75000c001100e200fd0040fff5004f003a00d2002affbdfe" - "b8ff32ffc9ff8d0178ff840091ffba0106006600a200080085ff3fff5900d600" - "b701330032ff66ff980044005f0014ff5f009b00b40032ff570098fee3ffefff" - "96ffebfefffef100acffa70109ff3effc50055ff41ff740090016500acffabff" - "baff0b0077ffc700ef0076fe6eff94ff93002f006d0038febd00da01340184ff" - "9b015fff66ff79003d0117ff6b00760013ff2700360064ff8700a10047002fff" - "bbff6d00d0ff60006000e0fff9013b002300ea01c8010aff07002400d7ffe6ff" - "df01030098ffa0ffdeff380001ff44003d002d007e003cffb1004800da006700" - "9a008f008b003100170031000e0016ff8f00ff00a60063fff4ff9fffc9004d00" - "640128013e002fffd800f00046000effb5008c005b002a00360063ffb7009c00" - "5efffeff750021ffdaff78000cff16ffce00e4ffe7ffecff250078fffbfff500" - "440015fed90009009f001e0067ff42ff7700cf00cb007f0024ffd9ffcfffe500" - "99fe85fe6a0164007500320007011d0009ffd8ffdc004dffed00c30005005afe" - "880038ffb500b6ff0bfffeff27ffc2ff90ff6800180043ffaa000cff2c0022ff" - "9bffd8ff10ff9a0083ff50fffc007bffc900f90054fe860005ff8cffab0080ff" - "7100adff5e00ed0069ff390140ff5800290065ffc7ffc00105fff200940040ff" - "80ffb200c7007fff280020001b01bbff47ff9dffa800b30014ffb6fe3e0028ff" - "d20077ff560069ffac00e9ffba0017fec0001300b2007800570161ffff0025ff" - "6a01930037004d0040ffa0ff6f0040fff100670077ffdfff12ff430099ffaf00" - "f7004e00c500010032fe8c015b0096ff08fed4ffe7ff9e009c0049fef5ffa8ff" - "c0004900edffee0035001500a9015dff9d00dd0061ff82001100740098013500" - "03ff85ffa3ffbb001d0165014b00c400f2ffb8ff5e0054fe63fff1ff90ffcb01" - "0a00aaff36005b01feffdc002effa5007700a7ffc10059ffd7ff53ffbfff72ff" - "caffb6ffac00bdffee0108ff9dffc900c0001c0123ff6900180073ffebff9300" - "140021010f0002fe7fff7b00af004a001bffa7ff24ff3aff0cffd3fe7f003700" - "0affd400b800d8003d00daffa700a5ffbcffb000a7ff7900980063ff7d004a00" - "a3ffcc0007005c00acfedfffd60035fffc001f00feff5effc5011dff42008c01" - "2cfea5ff97ff2d00b700c0fe2dff6e00cffe9d002e01760040ff98ffd400d200" - "f9ffec0064ff3cffe2ff6900c200e5ffaeff80ffe9ffbfffa4ffd2ffa0ffc5ff" - "c4ff84010000c900b9016a00ddffae00b30080fec9fefdffd60014012bffa8ff" - "80ffb20051febb01130082000800b1ffd1fef700d5ff2efedc00b8004cffe3ff" - "e0ff79004a00aa005aff8dff9d002ffed2ffbf0048003100af003200150029fe" - "9e00e500150059ffc4ff750040ffb0ff63ffeeffffff6c00fd008400dcffe900" - "92ff7fffec016d00ccff8aff8a00d7ff47ff210024012dfff90015006e0092ff" - "a30097ff34006c002f0073ff3d0015008bfee1ff0bfe7eff040090ff8affd5ff" - "b200a8ff70ffd3fed0015eff69ffa5ffc7fff3002effdc0096ffdf00a0ffd901" - "00fff8ffb8ffca0036001cfed5012aff84ff80ffaf0078ffcaffd0ffd7ff7bff" - "68ffa10022006bfffb011aff69000d005b006f00a20128ff9dff83ffbdffa100" - "53ff47011f0060fefa001fff6dff6e0046ff94ff4d0180ff90004600ab0015ff" - "faffe60065004c003bffb4ffb6ff98ffaeffed01b200aa00fdfee2ff73ffaaff" - "be0081ffa6ff810012ffe1febbff89001a000eff60002700b20060fe5affcd00" - "ff00acff1dffe100440081ff0500c700bf0090007400b20016ff8dffa10036ff" - "6500fc0043ffb1ffaaff72011efe4200a500090136ff4bff6cffe9ff9cff6eff" - "75fff000c3000a00d1ff85ff8d01d00130ff6fff0d0078009100f8fe690034ff" - "dbff220086ff1dff59004b00da00c0ff37ffd8006400620100ffedfffd004eff" - "a300ed0085002cfedfffcdff78001500c700a0ff6dff71ff6b00b4009f009401" - "33011d009a007dff76005ffee701030017ffb10097006cff4e002c010fff9d01" - "4e0054ffb6fe33008affb6feffff3000a900adff8cff1d00de005dffb0002501" - "31", - - "67b099b366cf45c33e4b0b642d85f59f005333191606e3eee1a1b5a1d1f4d969", - "sample 3", - "0affcbfeee00dc00220058ffc0011effac00a000ff01290005008fff2fff51ff" - "f801260067fefe006eff7efea9004aff87010fffe1009e0047fee60072ff93ff" - "dbffb60022ffdaff75002600f100a900bcffb7ff43008eff5d0017fff4ff5100" - "06feb6ffa2ff9a0136feb1ffd80165fff10050ff98009a004300dfffa1ffe9ff" - "effffbffcdffd0001efff4ffb5001c00a9ff33ffeaffec00720117fea8ffb800" - "6e00190031ffa8fe9d0101ffea002c0010ff16018d002dffa9ffa7fe38006401" - "440058008e004b0083004effcf00a4ffd900940051007600abff9dffa6014200" - "470006ffd1000d001b0031000fffbaffa1fe88007bffa3007cffdbff5900a6ff" - "d601130082ff36ffb2ffe8ff23003dffbaff6fffba0094ffcb003600b3ff71ff" - "8eff360001008800c6ffc20032011dffb60050ffe1ffedffb7ff4fffa7ff7000" - "96fe43ff490019ffcdffa4002400360102ffc7ff0fff780024ff22002eff5701" - "17004affa50145ffa6005effb3ffe00213ffdc000cffe8ff7b000c00cb000b00" - "93009300d5ff0bffadfe8d002cffd5ff36ffb9ffde00c900ce00f50028ff87ff" - "3effcdff9efee70016ff23ffceff2e01a9ff49006d0094ffb90051000cff9cff" - "0d0067ffe4fede0128ff12ff90fffa00c0fff0ff22ff33004efec800deff6500" - "eaff8b001ffff5010b002dff900104010a002b007effed000b00130022ffcc01" - "31ffc1ffcfffc4ffc7007700e6ffe0ffd800350042fffb0051ff93ff8afff8ff" - "4c0179ff08ffb9fff600acffd7001cffe4fff8feb70037ff79ffebfef5ffd6ff" - "f0ff9e01c90052004bffc501630085ffddffd800a7fec1ffb0ffac0058ff25ff" - "f8ff50ffb10085ff4efff60091ffbaff77009bff9f00af002900daffe6009dff" - "ceff7bffdfff330055ff7c0046ff750124005b00db00db001e0053ffd9fff800" - "230012ff70ff68001e00e0ffb4ff360088ffb20036fff5ff05ff50ff94ffdffe" - "93fec0000dff5affc7004d00c30038fef700dafff6ffca002600a60022ffe600" - "e70168ffa8fffaff0cffe5ffedff24007400140075ff380049ff14008dff1a02" - "010083008cffd80061ffb0fea7fe7800f6ffb1fee5018e0031ffd8ffde005200" - "77ffe400600021ffeaffec0131ff540076004eff94002c003eff310050ff60ff" - "4c009cfffb0052014aff0c00e000bbff8c00710052005fffe8ff48ffc8009dff" - "aeff3a00850030ff1eff6500c00067ffe0ffbb01d9ffe6006cff4f0089ff22ff" - "f4ffd7ff54ffb7ff80ff53005d0083006efff3002eff1a00680011ff73ff99ff" - "66001600dc004b005c00b600640040ff9dfebaff300111ff60ffc600dd0040ff" - "2d00a0ff9b00540026ff350011fe8200e20105fff0007d011a000a01ac00a5ff" - "3400340098fef80080feec00560080008600b7ff9fff7b00f7000b00b2ffacff" - "c8005b013aff5f009a00c3002dffd5fecc0177ff7c00ac004bfe500012000201" - "0a009afec90052009affa900980089ff74ff39ff1cffb50000004effc4ff2eff" - "50ffd500f101beff4500950066ff8d00e8ff7f00320229ffdfffbeffdd001200" - "ebfef200760117ffed00f40032001effbbffe1ffeb00130079ffdeff73ff5aff" - "ba00790032ffd7007900c0fedd01bb00c8002cffb5000b0080ffc2ff4500baff" - "3ffed10017ffbb010600edff6dff34ffcc005a008dffc8014cffbc005f0128ff" - "b2ff6d0096ff9600a200730036ff62007dffbcffc500d5ffafffca00a9009900" - "55ffffffd100410024017d0085001000ffff6f002aff86ff870031fec9000001" - "420024ffa200a3febdff14ff76fffdffe1ff73fea4ffbe001b0086ff41000d00" - "34001d0050ff95001bff7ffedfff9aff40ffe300360059fffd002affa7ffe900" - "44fef2ffda0079ff2f004200700060ffbefebafeb8fe6500e5fff9001b006400" - "dbff8efee600ba0100ff230010fe7900a700410036ff0700ea0098006300ebff" - "b800ff0007002c006c0108fe5500f1ff470059ff84003e008e00e4ffc2ff6eff" - "9fffadffd9ffa70034ffe60034ffcc00fb002bff55000dffc9000effee004e01" - "21ffb201d8ffd9ffb9002fff15fed3ffbc0040009dff7e0050ffd0ff06003e00" - "1400150010ff13006cffa4001cfefe00d5ffda00af0041ff9501440154ffbeff" - "a7feb701ab00edffe5ff9d00b5ff640021ff6e00b8ffb700a9000cff040067ff" - "69ffd20109016f0085ffbf0133ffbb000700a1ffc9ff82ffa8001a000a0115fe" - "f4005dffd8007d0047ff370051ffcd003800a3ff540160ff4aff8300cc00a9ff" - "ff002dff7aff870008fff5ff93ff67fff40022ff350110ffd40083ffd9ff2501" - "28ffe700a0ff6affbdffca008dff38ff49ffaa008dff2affff0048ff25000a00" - "9cff40fff1ff9d0072fd76ffdeff37000fff660008ffe7ff7d00250014ffb3ff" - "84ff63ffd8ffe8016dff380094007dffae00450082ffeeffd2ff91ffd0012700" - "06ff4300e1000cff22ff9b0037005e00dfffbd004000e2ffab0090fff600f500" - "dcffd1ffd0ffddff3bffd30094ff5a0063ff9fff4c00970020ffe3ff2dfff500" - "fbff8cff74ff35ff9ffffaff8a00a7fffaffc1ff540003ffcbff690056ffdf00" - "780050ff50008400abff4600d1005eff81fffd007a0007ff9600af0029fff5ff" - "18ff8affb90052ff1900010015fe61ffd6ff19fffdffdb0070ff7cff46fff1ff" - "deffdbffee0041010cff36ff91004f0079ff6cffe10091ffedff9d002a00b200" - "afffbf000cff9a0151ff72ff7a00f4ff4effdd007eff9100a80011ff9b00c1ff" - "21ffa7ffc90096ff6dffb4ffd000a2ffa2ffd10068ffd200600120ff1aff0eff" - "71012d003a007e005f00bf0008008d00420051ff500057ffde0099fffb013300" - "85", - - "036f0921b89631213dc33f05707a0a3fece5aa9e507f6646b6f8443c27ccc843", - "sample 4", - "0a0051ff8c003fff05008bffa30078000eff18ffc000560016001500daffeb00" - "60ff5effa6014900bc007affb600aaffe00013feff01130055ffa2004700cb00" - "5f0003004000cd001a002b0092008d014bfed800c9ff2cffa3fef901c1014d00" - "6efeb4ffa9fff701310072fffbffc0ff62ffea002e003d01400029fff3ffab00" - "ee00730069ffedfeed0061ff69ff4d00f7ff30ffda0017ff600014009f00d5ff" - "d0fff000b6ffe8ffefffee00290005ffc4fffcff9b00bf00bcff41ff8eff7aff" - "b5ff97ff59ff36ffbd007effeefeb8005e0017ffcb003dffc801dc0096fed2ff" - "3eff4effad0021ffbd00baffeb0070ffee007dff79fff6009b007dffc6ff77ff" - "f3ff7afe2500a1012effabffc8ff95ffe3ff79004d0060000900c3ff4bff4f00" - "0aff20ffc8ff4f004cfff900c0ff9a00280037ff3bff18ff7b0050ff2b0189ff" - "8cff2c003d0026ff53006aff180042008dffbd007bff56008c00f9ff15fed6ff" - "3f011afffc005effcbffc2ff30ffaeff65ff3dfff1ffabfffdff1dff870041fe" - "a00095ff5bffee009200c400c6ffbaffd400b9ff4d00a9007500c70010fffb00" - "4b0121ffdb009d006000c8ff5100a4ff02ffbd00bf006e0120015f00910051fe" - "8d012a00f0ff0fffe1ff3d00a300deffbbff780044009e00670189002b0001ff" - "65ff520093ff9f00bbffe6ff71002cff15fec000cf0086005cfef20084ff9cfe" - "adffd4003400ff01080016ff98007700a8ff96001f00740126ff4700e2003600" - "28000c01170007007b0020ff88000100e9ff820005ffdcff4fff650062010100" - "5200a2fffeffb0ff3affbf0051ffd2ffba00b5ffe6fff20078fffcffb20088fe" - "b100550068002f00ebff32ff25005b00300025fe4500ac00120004ff950095ff" - "8c0021ff8aff2b0067009c0003010c00f4000afff100610088ffec00e900fd01" - "9c00c1feec013b0059003cff22feccff16005600ce0069005400f600bb000301" - "11ffb9fe5bff6901850089008fffdb0138000d004dff5bffdd00a4ff59ff9efe" - "6300720197004e003600780130ffb000170172ffb40078ff8cffd8ffeaff9c00" - "0c0049ff62ff0400590048fefc0081ff87ff6600ec002500a6005e0197ff3e00" - "7fff87ffe9ff45008dffe600a600a5ffd800fb009aff7d00180115fea5007300" - "9f0019ff22ffceff200030ff3200a6ffaaff5bff7dff54ff03ff6200db0093ff" - "2fff94ffceff87ffda00ad002a009200ca0182ffb0fff6ff8d015000c100fdff" - "20ff34ff45ff0dfef7018600900019007bffb5ffe8ff8a002bffb700e5ffebfe" - "c8ff8a00e4ff7c00150013000d0092ffc6000b009dff9aff47ff1c00a3005d00" - "0dffcc0090ffcafe9f0058ff6d0027002dff9000d20027ffd9ff5b0119fedafe" - "be006500e80129fea2ffb300b60169fffeffc100510058ff190055001bff9bff" - "cdff81ff820101ff00ffd80136ff7effa8ffeafe8bff340096ff7bffba00f1ff" - "75008a00bc007fff5cffcf0060ff3e00280110008200e9ff7b005200c1ffbfff" - "f800d90049fef0ff9e0155ff79ffb9ff72ff27ff4f00160003ffd600caffbaff" - "9effd3005b000e00380009ff1b0198fffa00feff3c007fff42fff9ffd7ff80fe" - "a3003bff2bff2400cdfefa003bff8f00220026005e00b1ffc7ffeafeceffe401" - "16002b0027ffa1ff8bffa2ffc2fec4001dfefcff8600c100b50049001fff6800" - "0600dffeec0116ff4dffc6ff95ff20ffedff5effd0004d00360035000cffc7ff" - "42006700f9ff69ffec015e0088ffadff41ffda001bfffeff86ffa20031ffa900" - "23ff9efe5f010d00a5011300b1000d0056ffffff59ff11001d0003006e00d0fe" - "edff4cff76ffefff26ff83013800b8ffdbffc7ff71feed00ff006200d8002400" - "690017001100b5fff600fcff230073ff4800a300e60035ffd3ffae0030011301" - "16ff59ffa2ff45001d00590014ff2b00ebff66003fff4a007900e6ff81018700" - "1dfff4fedc00dafefdffe1fef500f9ff8ffff700c90088ffb4009d008effc5ff" - "07ff71ff7affb30001fff500c5ff4e00050025003cffad00c3ff28fef10035ff" - "f4ff78fffcff5c0002001aff0b00c100a400d1012dffbf001afefd0008ffacff" - "3ffeb1ff1affad00dafff6ff94003c00bbff4401360037ff88ffb4007b004300" - "05ff1c0095ff2f0040007b00f2005500b6ffd6fe7e0068fe73ffb5ffd000b700" - "3fff5efff0fe98002700a2ffe6fffb00bb0167ff0200b5002800fb027a0048ff" - "55ff950008007cff91ffabff1a000aff9bfe5100d8001f004400abffda002cff" - "c600d5ff35001bff9d005bffb3ffcdff9ffffc001f00bc0136ffffff2cff2201" - "6cff77ffc1ff99007800830027002cff0d00b1006fff43ff76003e012b00c700" - "0eff32ffd300c6ff7effaaffbcff23ff6fff0f0007008800bc0044fea8ff1400" - "c10058ff6dfff500b8016200ebff930063ff2d0078ff9dff5bff9d011cff9a00" - "e60073ffd7ff59ffd40038007efee4ff22ffb80059ff80ffe8003f0093002600" - "6600c2ffa3fea3002cff2dff650026ff8f0137004300fdff60015f0056ff8900" - "c90037007700ca005ffee00008ff8e0097ffd0ff6bff6500d9ffccff69ff69ff" - "bd00040048ff3400b5018a0099ff9cffe0ff4dffc2ffe3ff89ff65ff7d007e00" - "7200b90094ff560061ffe4ffdd005e004000a6ffc600e6018900180009fe8800" - "f9008d0092001f00d8007ffff001120001009fff99ff18003fff49ffd1ff68ff" - "ae0059ffffffbfff5dffb0ff62ffc5fe83003e0083ffe9ffe200c5007300bbff" - "ac004400a5ffd2fe680064008dffc1002a001500b6001affbeff82ffa401d500" - "06fff40077ffe3000d006eff6cfff3ffe100cdfef0003f004e012ffefb0058ff" - "fa", - - "7cf467172d3c90505ee0ca12051777b73954d6ed8c82515ba2e4e6098f4d9cb3", - "sample 5", - "0affb4ff43fffeff7afff7ffc800b5ff74023000490021fed0ff1f0099ffcfff" - "05ff28ff90fffc013dff9fffd4ffaa00fcfecf0008fffbff9bfe33000300b200" - "bbff2b00f50082000afe9f011500a3ff6fff640091ffaa008a0009fef1ffbb00" - "25ffca001b0024ff99003b0036ffc4009ffe76ff85fed80066ff7e00e5005000" - "4800defecfffc40069ffb8fea9001bff24ffa9ff3a0045ff0d0013ffccff83ff" - "1d002dff9e01db002100d30061ff2c003dff780150ff19ff8a00b100750013fe" - "3b0105ffda008cffb3ff93ff1c0058ff93ff1cffc10043ff910043ffa7ffecff" - "5dff5f001cffb3ff540056ff5afee7ff01005500940030ff70ffd300a4fff500" - "16ff39ff9dff6e00a8000300d1007900a1002cffe3008e01000063000effa700" - "40003a00b50063feb4002a0055ff5fffc4018c01250082fec50075ffccff1bff" - "f7fffe009fffcd001cffb8003e007900df00dd00f50015ff0c00130052002000" - "7dff750016ff5cffb400a4fe13ff640004fff700fa0017ffde000dff68ffbb00" - "c90107002d00ea01cc009c00a5ff9cffd4003bffa8005effdefffcff9eff6aff" - "7200440116ff0b00e10114ff65006bff86003cff57fff5ff9a00a3006dffb7ff" - "effeed002700200158fff9ff7afee20032002ffef8ff2c0003ff2d003dffc100" - "a4ffc9009f007bfff5ffd400ecffa6ff79ffedffa000eeff52ffb0ffe5ffbb01" - "60002c01a5fff3017cfee5ffa6ff96004aff6a0041000cffe9ff6b002e00d400" - "35fff30084ff6eff7effb2fffd009a0071ff270046009b00baff8cff6701e5ff" - "eeffee0109ffbefe8affa6ff2b004d00930032001a00fb0080ff39000f008500" - "a8ffd6001c00670096ffa7fe90ffb90098ff02005100c900350051ffc4ffb800" - "9affd7005400520015ffd000cc00bb0044008effbaff510001ffcdffc100ce01" - "58ff210079fef7fee1fee100a9000100960150ffc100d3006a00390090ffbdff" - "22007000a5ff8a009eff58ffca006500b7ffe90058ffedff450076ff0700d300" - "f7fffc003bffe0ff0cfee1fff5fe66feb0ff96ff02ffd000b7ff4f0071ffcc00" - "090054ffa5ff97000c01c9007c00f400abffee0038ffd4fffbff2bffd80034ff" - "ab01bd00a300b500e1ff9d0025feffff58ff89ffe0fe7bffb3ff42feaefef800" - "6dffa3ff93ffd4feeffff500650095ffc3ffb7ffa00049007dff9c002aff7fff" - "fbff540020ffb30064fffaffed00edffc1006fffe1ffd10012ff1fff9b0028ff" - "f00057ff5cffbf00cdff8d0043ffd900c0ff7fff87feb80074ff46006f006a00" - "73004fffd3ffbcffb7ff2401ba001f01d2fff00011003aff68ff74013cff51ff" - "e800f800310034ff9fff1f0031ff2c012700d700a20093ffc4000000300055ff" - "ac00e60079ffd5ff13ff4efe6e00c50128fff0ffbdff82002100560021ffa6ff" - "9b00020008fff1008d00bc005cfe4c0055fecdff05007bffaf003affcffeaf00" - "10ffa0ffafffa7002d004e008600ffffe9ffd30036006a0034004cff34ff90ff" - "2e003fff78fff0008ffffbfed90075ffbe00a500990047ffcf000dff8bff77ff" - "9dffd7007200800080ff6800f1ffc3002efffa0023ffb2ff650113ff9a003601" - "0aff7effb5ffe7ffccff8b00db002bff56ffd400b3ffda008900ba0052fffbff" - "710012ff7d0034ff9200f5ff5100b7ff0fffeefed3ffce00ff00fd002b0083ff" - "98ffed00790082fedc0093003fffedffa2ff8b002dfffbff4800260089ffe5ff" - "71fec6ffd6ffa90082002800dbff6ffef3ffac0025ffa30088ff180054ffc900" - "62002d0054fff700e2fea30026ff29010f00cbff920032ff8f00b0fef4fff1ff" - "c0ffaefe9a0079ff64ff81000a00a9000cff60fff3002dfffa007d00340032fe" - "930008fff6ff1cff530150ff9c005cff66007101e5004afeccff6dfd9f00b500" - "84ff89003aff33ff8b008dfecf019f008aff1fffacff75fec201e30050ff6fff" - "f5fec300c700e2fed9ffe8ff84001800c6023000a30030ffe40010ff6300c900" - "4f001dff5300b1006300a6ffd80099ffd50127ffae0050ff650086006b0046ff" - "32002a001400e1ff990048ff41001bff5600590011017eff99ffe5ffd3fe6f00" - "73fdf3002d005cff2b006a010d002cff7cfe7cffc4ff56ff940042ffa1ffd9ff" - "6f001efef1feed003900610029ff520050ffd4001cffd700c9004eff70ff5400" - "20008e007aff51ffbf009dff35feb9ffb7011f009f00d300e200a3ffe6ff5600" - "e8fe82fed7ffa6ffea01ee008dfefe001b005500beffac005efff9ffdbffe2ff" - "72ff1e0009ff690034fedbff9700920090013c00a400650055fed8ff92ff38ff" - "edffaafdf8ffae013d0019001ffff40076ffc0000800fbffd6ff1500f400bfff" - "71ffb5001f0076ffd9ffd1ff8fff660121ff92007bff37006ffffbffab00ce00" - "70ff2b00bdff16ff3c0086ff45ff69fdc1ff9800830089ffa4ff4700c8ff8b00" - "6f00d7ff49ff32ff33fea9ff74006e0089ffaeff7300c0ff36ffabffb7ffc2ff" - "9bffd3ffd1fed101370161feebfff9001bfff9ffd3ff9f00590007fff0002eff" - "4e0124ffec0016ffc8003bffbb006200dd00c6ffd6009fffd3fddeff2dff4eff" - "d2ff8affc40128002a00c3ffac0084ff40016b00800087001e0042ffb000c7ff" - "0b017cff1cfffbff9c0045ff31005ffff8fff10136012affec0068001aff88ff" - "d5fffeffd3ffe2001bffaeff78ff750135ff7e00bcff39ffbbffdefeecfff9fe" - "95ff57ff73fe480013ff610063ff220054ff0cffa7ff7200a2ffebffebffc700" - "2c000d006affbfff3f00d500660023fed1ffe2ff94ff09ff1900860010ffd001" - "5effe800760038ff7a0097000800c6ffeb001dffdffffbffdeff4b004c004cff" - "de", - - "acc78539c8b82aa74f435eab9a974b55b80b4258bf480c103a7e6575e31ec822", - "sample 6", - "0affaffee8ff30ff720158008400ccffbdff960148ffee00abff4bff8f00e100" - "5afea10046001900390053009c015200d0013200d6fffa0031febe000b00d601" - "13ff2200b600d4ff5bfebb00c3ff56ff55ffecfffdffef005bff650089000eff" - "cafff6002000daff31ff68ff6b0026000fffda0066ff05ff820083ffb50026ff" - "40ff2600cbfff200c6ff02fff1ffb2000500d6ff670092ff54000b01180105ff" - "9cff65ff9b00d700b00068ff43ffdbffe6003efefc0070ffc9ff7affda004600" - "42007eff9600fbfeabfe66feddffb6004c0017ffe7001ffffe009301040021ff" - "3d0084000c0161006ffe9c00db0026ffd8003d00e9fee70103006d00bc0027ff" - "5500faff8efe9e00670052ff2fff36003bffce004affe2000d00db0004003700" - "9aff9affd100b1fe73ffd1ffa6fffd00aeff43ffdaff44005a00b9ff9f00f000" - "7ffea500bfff9e00bfff9f0033fee9fec8006d005000a4004200d5ffa6ffc400" - "64005e0010002f000e0035ffc8010fff9a00c700670005004eff84ff82ff5b00" - "c500a6003cff880032ff4f0036ffccfffb00680047ff2b002c007500cbffa400" - "b10048feb7ff710002fed4ff91fead0019ffe5ffa5fe9b00f0ffdeff6f00bd00" - "74ff07ff91ffb3004200b0ff8dff6d001ffefa008e0013ffaf003500a600cf00" - "73ffbefff800b9ff54ffb50016ffa7ffad00410045fec8006e01e00189001600" - "850034ffd0fffcffd2002e0074ff6dff9c00ed00c200e1002f0061ffefffe200" - "58ff92ffa9012cffc70036ffadfeed0023fed0ffb5002f005100c5ff16015700" - "d4ffbdff6d00850012ffe7ff0800a6ffc9ff33ffcdff24ffc0ff7e002cfe7c01" - "240090fffdff4f00a1ff000065004000160090ff75ffbfffc3ff00014800faff" - "690047006affeeff8affe8ff65ffc900140061ff0c0030ffc7ffc7ffb4ff7c00" - "7b00ee00d4ff54ff800044ff8400ac007d0014006400130018ff0e00a000f800" - "89008000610016fe41fff70081ff9fff92014fff82001601200035ff3200b100" - "860108012f00d601d3ff490069ffc7ffaafed7008dffe200270048ff48fffaff" - "5d003e00a4000affd0ffe0006eff7c00e60088ffab002bff3c0080005dffaaff" - "e3ff47ff780134015000fafebb00310014ff1c0006ff900070010dffc6ff6300" - "830167ffc1ffa2ffd8ff81ffd7ff8f00d100d5fe2fff47ffc2fecc0077ff83ff" - "7bff6000230107ff8fffecffbc002b00aeffe6ffb400fd00beff05ff090045ff" - "c7ff920005ffbeff6200fcff94ff1400a2004affc9ffe4ff14fe91ff0fff6b00" - "01ff3dff64ffd70009ff7d02380004008f002000e0001f007bff5eff02ff2e00" - "5bff8affca00cd0047002a0109ffcdfffaffc300a5008c0032ff9e0074000dfe" - "f4ffaeffb3005bff61fec40074ff27feda0117ff4900a6fe3d005000080018ff" - "d6feb200970082002800bb0015ffb900fdff7bff94ff68ffecffbeff3901d9ff" - "d2ff85ff8bff540003ffceffa3ffa1fee00031ffd100a3007bffc10013ffee00" - "39fe5500c30034008affb4fe45fffeff5b000fff86ffd600ad013e00a4ff7eff" - "e200330049ffb4ff9fff3bfff2ff22006eff930019ff2c0045ffa7009eff4800" - "7b00cc014400c6ffdc007e000b008d00b700bc0035ffc0ff57ffc8ff58ffee00" - "d7fff0ffb200d9ff28ffc20011ffae0003fffc00edffd1fed2005ffffb00e900" - "3f0086ff3900110101005f00350014000a00ab0098fff3fe20008b00b8ffe000" - "bcfeef005200adffd0ffc7ffb7fff301a900d2003dfff5ffd80095ff2b0037ff" - "a90045ffa3fe6800b80003ffa6ff31fff9ffa6ff1300b8ff80014cffedff9500" - "0bff2cfeecffaaff60ffd2fea0fff3ffff001aff5f00610068ffbcfef90061ff" - "70ffb500a1ff1c0110ff6b005f00b10195ff94ffa4ff8effe5007b00a4ff68ff" - "9800b0009800a500d0ff74006bff5cff47ff82ff16ffcfff3a01b5fee6fff0fd" - "e7fffe003400070006ffcb00b6009d001f0086fdebfff3ffc3ff6b0129ff3b00" - "7f00f6ff9cfe3bff8a0003ff7a0062007effddffb90091ffe0ff9afe30007e00" - "18ff550064ff22000100cffff9fff1ff440047ffe0ff91004f0027ff4b003d00" - "ee00040118000aff2ffebb007500dbff140027ffdc0018ff86fe5a0061002400" - "8dffaa008500ce001fffe2ff5dff9ffe7aff6f0012fffd00360041ffb0ff6100" - "66ffd00041002c017eff79ff44ff1b007f0034fff40036ff9700860083ff1601" - "1d00a10024011dff6b00c5ffa8ff36008eff92009c00c8ffb400550048001fff" - "d0ffabfff0ffc9ff0e0053ffd1ffd0ffd2ff6dffac00500059ffa600b8ff42ff" - "d200daff9d003b00b3ffe3ff89005eff0cff3fff31fefaffcbfffdff90011aff" - "d000ea0088ffd0ff02004a0031ffa00077005cff00000d0082ffbd006affb5ff" - "b6ff9a000dff58004efe570034ff90004b0103ff6f013d005cff79ffdcff1100" - "22ffe90088ff5a00770108ff76006e01a20018fdd600870021005effa5002600" - "bb0096fff1ff91002f0103002f00140038001cffaf0120ffee0024ff8f013cff" - "bdffc9006bff67ff76ff5cffb80076fff4ff8cffbafee3006aff21004a0058fe" - "ae0051ffeeff5fffdc00e5fe03fef40004ffdc00940018005d0045ffb6000400" - "b3ffaaffc7007300e4ffa6ff14ffb20052ff6aff6d0045ff91001afefbffc4ff" - "ca0030ff92ffc70043ff8700b7003dfed20067ff18ffcbffa300a100910045ff" - "2cff4c004dfff5ff9900ac008c001800ee003f000c0101008d008b00240095ff" - "c2ff380098007bff550127fe710086ffdcfffa005001150010005afe90011bff" - "5eff69ffd9012effc5ff07fffbffc60091ff5fff75ffd200d1007afffeff8f00" - "53", - - "519bf3fa8785ccb4b95f2ef0d3f0168245218323450be56a4a5660b9fe097d27", - "sample 7", - "0affc1ff420024fec7000bfea1004e00560023fff40121005eff45ffdbffeaff" - "32ff100024ffaffe8affff012fff4dffe600a0ff6d0016ff6aff24ff1cffc200" - "2ffebdffe2ffbc012eff45ff95fee7009dfec7ff0b00b9ff24ff03014f0070ff" - "f3ffc10053ff8cff8800fa007a0004ff5300bf002aff41ffbc00590009004dff" - "45ffea004efec6007eff8a011201740091ff850121002b018a00050016ff00fe" - "650055002cffa9febe002bff84ff570105ff9f002f00d6007e00780057fedfff" - "020033ff14ffdafff0fee0ff83ff5b0009002c00cdff99ffa9ffceff8f000600" - "bb000a006bffa500ed00a0ffd600bbff3e005501bb0054ffaf00ecff92ff23ff" - "ecff9600bdff26fe72fed3ffd00051ffb300030070ff60fff5ffef0052004100" - "900151002bff97007dfff5ff5c0024ff7eff90ff58ff900138001c000cffec00" - "7b016700dc00ca0034ffce0163ffe6ffc3ff400019008f0063ffaa00f700a400" - "b7ffc70035ff6a006bfedfff0dff69fff5007e006000c10007ff60ff9100c7ff" - "a2fff200ccffa80073ffcfffdd00e40000003a006300c4002d009ffee8ff2bff" - "b3fff8fefb012100e2ffc800ef007dff05000affbaff3000b5ff52ff17feceff" - "beff85ffadff65008bff4affdaff8bfee0ff270014ffb90141ffb5ff21004900" - "8f004d002cfedfff86fed80011ffecff42ffc300bcff44ffd800a0fee5ffd6ff" - "fcffb3fffa0005ff650091009bfef1ff61ff170023ff83ff4800d5ffc1ffe800" - "45ff20ff9800b9ff7e012fff7100e1ff4bfff7fefcffb1ffd0ffbe0035ffd8ff" - "9700a6ffbeff62fff900a2ff2f008eff3a00090084ffb30021ffefff6bff7200" - "49ff3f0009001cffe1ffc0ff3ffea5ffa2ff30ff15ff6b0047ff6c00deffefff" - "2bffaa0022fff100f2004d00cdffcdff91ff6c00a200a30030ffca002dff8100" - "49ffe2ff550149ff3e0050ff20ff17002400700103000fff57ffd7ffe300af00" - "810154ffd9ff2000a8ffbc00310041009dfee1ff0b011dfed70012ffbb0041ff" - "b7ff2e001e006fffd700cffea7fffe00ccffda00440063ff3cff03ffcb003900" - "c300f400b5fec1ff78ffdb007500b3ff9f0012ff8bffc80089ff51ff76004aff" - "0eff7eff1e001e009d004a006affa8fff10093ff97febb0075ffdaffbc0095ff" - "f0ff7cffa80027ffa1005e00150052fee4001a00380018ff6800fd0095007f00" - "89ff94ff98009cffb1ffc6ffe60059ff2affb1ff45ffb20178fecfff39ffb0ff" - "49ffd4ff30001001bc00caffff002efe70ffdefea80048ff6d004effc8ff4300" - "9c0157ffa700c9ff660087003000c1ffa30099ff63ffb9008ffec3fefdfecaff" - "3c0078fff3000bffac000d00610002ffec006400150066ffd700f6ff74ffbeff" - "c30015ff8a009dffc9ffb800ed00cbffcfff3d003500d4ff920058007e005900" - "a9ffd4ffb800a1001600b5001b000dff740137000fffa10002ff540023008fff" - "6b0082000affc50039fefd00bffeddfff7004800a1001e00e70019ff5b0068ff" - "d0ffe9ffe7000c003dff86ffa8fedb0050004a0011002afe7affcefe7d002bff" - "b9ff6800b1ff47ffd10167ffe0ff0eff620095ffe3ff5afe10ffdd0074015600" - "5900890111ffe8ff23ff80ffeeffd7ffc9ffdb000a00ae000c003b00e7ffc1ff" - "b300afff9aff4affbbff70006501580044ff9a006a005affbdff8dff4cffadff" - "aeffbcff91ff4b010500ddfff7015f0004ffbbff7f000fffbd018dfeedff1b00" - "a7fef9ff93ffeefe40003bffc90013ff99ffc400ddff41feac0085ff9c009bff" - "2fffc90007ff5301b90021000c000fff6cfe2effd30020002b004dfedafff100" - "4700c100aeffad00c6ff50ff9300370095015eff25005dffebff1cfff900b600" - "11ff08004800c1004a00a1002e0015fef9ffffff7bffdf005100090056ff5dff" - "11ff76fe6aff60fff5ff76007600d600080030ff7b00d8ffef008fff00ffebff" - "37ff5f0046002fff85003f00b0fdd5ffb9010b0057ff6cff41fea800bb005bff" - "11ffa10033002500190014007b00810075ffca00970048009d0115fff9ffceff" - "040040008dff6f003e000a00c700e5ffb2fe8100080037ffd8ffddffc3ffcb00" - "10ff530010007400d70058003cff980032ffc9ffd8ff540081ffb20047ffeefe" - "f2ff310064005a0072ff86ff9d006eff4eff59fead00e400b2feca01a0ff83ff" - "20002b004ffff10078004600c6ffa90078fff20008fee1ff8c0072002ffeb5ff" - "e5ffe3ff7c0079ffdc012d0019fffbff5bffacff60ffa000690082fff9fe6afe" - "d7ff95008e002dffac009bffe90092ffb8ff4e0042fefeff9c006201b60112fe" - "da01950035feaf00a9006e00b8fe14ffa40095004aff4100d7001700ed012000" - "710026fefdff750049010bff5cff32009500040027009dff3a0051ff3cff94ff" - "fffee3ffceff60000fff7effa20018008bff7a007a0033ffbb011dfee2fff1fe" - "ad002e00840105ff3bff66ff7e008dfed5fffd00affe79010701740015ff8e00" - "f2002200640024feccfff500da0049fffdffa200c00058003dffccffc0ff3300" - "90ff5000cdff72ff9cff3fffb90020ffcaffe300f70075ff6bff98ff4700a700" - "20007f00b7ff8bff3b01020099ffe0ff5800bc006affda000fff4a0077ff9aff" - "b7ffe800d6fffb0064009a0021fffbff83ffc30023ff2c017900380051ff9bfe" - "af006a007c007200c100ca006cffa8ff9e00890006ffe2fed6009d011d010300" - "47002dffbbff10ffcefeb7009400a4002cff9a004b00d0000b00fdff7affc401" - "3e0024008fffc3003200090093ffcbff8a0049fffa0053ff9effd10093010eff" - "57ff88005e00f3009a0158ff3dff9000050064ffb6005d0027ffc700a6ffe900" - "2e", - - "b4c3bb96b3614ca047ee15ce94f3ecce0f0451dfb00877611170e56017e76269", - "sample 8", - "0a0077ffcb00020072ffc2007400c4fea600ec002c00280076002e0075000c00" - "45fffe00c5ffc2ffdeff9b001fff6600dfff0900e6ffae011d005dff840022ff" - "36ffb1ff97ffd5ff0dff9f00a0ff6200b00070ffbcffab0055002dfeac002100" - "9a001f0095ffdf00c2ff2bff5d00f7ffde0003fff00100ffbc008900a2008700" - "290165fef6ffa400a5ff18ffcb006c00af001b0089ff99ffccff9f012700c1ff" - "aa0074ff9affcdfeecffd9fe64003a000aff840085005c00cc0039ff4fffd9ff" - "c900a50144fee700db00a900d1015b003bffbfff80fff0ff2eff0f0033000901" - "60006bffbbffd5001400ffffec0000fef5000100050033007aff90feaeff0f00" - "47ff320028ffbb00d2ff9c003300bc00e3ffd200060061fe5d00f2ffa6ff8a00" - "3eff9affa6fff9ff6aff270037000cff94ff87000e0040ff8eff16000c006900" - "7fffb2ff2b00b8fef8000f007dff3c003f00780028000cffe00079fe66ffd500" - "1eff40fe1fffc50107ffc7008cfe54ffe4ffcd006c0084ff49006fffe5ff6700" - "24fef000a4ffe0ff90fed00051fec8ffc2fff30017ff1affd10097ffe6ffbb00" - "afff8b00870046ff050011008efe9e003ffffdff75ff5bffbefff9ffb100c3ff" - "db004dfeb800270001ff5d006700fb010cffe700aeff990060002eff0900a1fe" - "63fff600c3ff130043009b0177ff4d0024ff50ff45ffafff72fef2fe8fffe7ff" - "c600d7ffb000c20031ffcaffbe002e010bfffbff1e0082fef2fff6ff460031ff" - "650087ff520093011400b600de0007000eff4aff30ffea00540083008fffb000" - "9300b80057018dff1bffdeffda00c6ff87005eff3dfed7ffc90093ff67ff09ff" - "69001c00e0004cff93007affe0ffaeffe4ff140042ffb6ff0f006f00690057ff" - "d0fecafff4ff38fe2f003fffa800930033fed3ffa0ffcaffcd00060032008fff" - "67ffebffa6ffdcffc2ff87000bff1dff9800f900a6ff2400d6fffa0050fecbff" - "74ff86003a010400ddfe5cffbc006a00cf003c0029fffa00dc0075003f000e00" - "54ffa0ffbf010effbeff1dff480002ff87ffaeff3a00c8ffb6ff92008eff8500" - "96ffaaffe8ff95ff47001200fe01020084fea4ffd0fe8a00c0009f0079ffefff" - "4a00efffc7ff5efeecfe9cffba015a0030ff2bffbd0005fffbffefffd30072fe" - "b2ffc100bfffd6ff76008f0065ff55012a003b00aaffc7fee1ffb2feaaff2eff" - "7f00c5fff00044ff7cff9e00a90034006bff48ffff00e700610036fea200cffe" - "b600bcffdbff8b001bff870012008d0019002fff2bff2dffd3ffbcff59002e01" - "01fe8efdad00b3ff98ff3effe201140130ff53ff9a0116007aff29ffc8000a00" - "3b00ba005bffcb010bff7a0052004700e5ff7dff830099003c0036ff70ff7000" - "00005a010cffbfff8e0037ffc8ff2600c0ff54001d00abffa00024fffffff600" - "c1feffff87fedbff88ffde000200be0005003cff5a004700f100deffe9ffe300" - "a4fe97ffaf00560097fed30062fed500ddffdb006300dc00670148ff13fee7ff" - "eefe96ff59ff5bff47ff79ffc100e1ff61ff33007e00afff51fff7ff93ff9000" - "17ffec008701bdffaf003f00db01660078fff70000ff8aff260090005fffc4ff" - "670039ffa0ff62009300f3ffa701b0ff5fff26ff81fff900a8004aff13ffb800" - "86ffd1006f00170074ff440152003a0008ff36ffe600d1ffc9ff20ffe6fefe00" - "0601ce0000006dff7affb9006fff37ff20ffe2004fff9d0182fefdff240019ff" - "44ffb300b6ff19ffd8ffd000180051007f0016ff46ff2100760135ff94011000" - "21ff00ffda000200e5ffc2fef3ff8000e3ffab014800d700a6fff9feb200a2ff" - "9e005c004f011fff9cffe3ff91009dfff6002ffed6fed2005100c3fff2ffcdff" - "6f00a400a4ff8f002a0137fe4c0030fead0050ffce005400010009ff4900be01" - "00ffad00550047ff1500c600ac000b0061016b00ccfff701b6fed80025ffd200" - "93ff19ff34011300aeff6dffe7ffc60002feebff7bfe6aff6fff8aff4c005dff" - "de000500430039fe6a012eff83fea1ff9cff40ff7cfef0001e004aff89010400" - "afffb2007f000c014e00b200e0fe3bfe3eff6fffb100fc0052ffee0028ff6c00" - "8effe5ffa8ffc7ff4bff20009aff1aff870121feddffc100d200c6ffd4ff30ff" - "f4fed1ff28ffd000fd00f0ff67002e002700de0057ff9efff200acfff5ffc5ff" - "c500920116ffccffbcffdbff6cfeccfe970088000100b4ff97003ffff10075ff" - "bc00010012ffc60097ff1f00dfffd4ff94ff9efe6400350035ffc6ffccffb000" - "bb00280008003f00f6008ffee6ff3cffa7ff97fff20004004bff170032fec300" - "54ffeffee0003cff4800d7feba0000ffe7005201820022ff9600540089001100" - "1aff380057fed9ff11011c0022009b002c000efe8eff31ff3f006b00e70037ff" - "230075ffb3ffc600a1fee70051ff2dfffa003f00f9005d0045009bffd0ffc7ff" - "92000c00b300e1ff6f006a0040ffc6ff5aff8f002d009dfefafe15ffe6fe9200" - "9a0077ff82ff73ff0cfee8014cff9000e4ff75ff520058006200dcffabff47ff" - "fc004c005affb00004ffe6ff2f00250046ff20fefaff6c006c00370049ffb3ff" - "e2ff89ffa6ff7fff37fec7003a0059ffe800b70072ffe9fffcffe800ee007700" - "edffbdff9500abfff2fef200670004fecaffd0fef50107ff3aff79ff97ff0e00" - "3fff8300680036006f019f0021ff6dffc1ff0fff45ffa4fee2003f005c008500" - "b40151006bff5dffbbff8b008ffec60003ffac003c00f600430002016b00ec00" - "39011a0159ff1100b7fff80094009700480096ff27ffea00460163ffef00a400" - "fdff9cfe71ffcfffffff4cffc6ffe9ffb7ff99005a007f005bfebb0089ff50ff" - "f9", - - "2b982d5b2aef3932ad1c2aa72cdc2bd8d5badd60d19508d5b7832f12867a41ce", - "sample 9", - "0aff9a001f0058006f008dff280022ff090011010b006e006bffee0009000f00" - "67ffa2ff44ff8000f4005600ff0014ffc80008ff920049001400f4003e006100" - "54ffdfff47ff4dff91ffa800e40065fdee0075002e0044ff40006f0001ff5e00" - "4900b6009bff5c00fcffa4ffd100a6fec80015ff68003300f1ffc3ffc3ffe5ff" - "56002dfec30030ff22ff0bff77ff5700f0ff130066ff4bffa8003fffd8008ffe" - "5c001700a70172008f007bffcb00b50007ffe30050002f0075ff6eff69009300" - "eb0039ffbcfff9ffe0010200250051004a0011ffc5003afefc0026ff7bff88ff" - "8e00d3003cffb9ffbaff87ff9e00fd001bffe5ff31ffef0012ff21002b0099ff" - "cfffa700550003ff6bffe30037ff20ff800073ffca0065ffc0ffa10073ff0f00" - "600048018700b10109ff8cffbbff9e010afffc0022ffc1ff0affaaff80ff4fff" - "e400fa001b0075ff87ffc7ff8fff61001d0019ffea0194002200bd0135ffc8ff" - "6bff73ffcaffb9ffb400e700b20065ffedffbbffe200b20057ff32ff8dff7b00" - "260029ff510076ffb2002100f1ff4ffe3b0027002eff6800d5ff0300910016ff" - "0400ec005cff45ff7f001e0021ff8900420086011f003dfff5002a0082009800" - "00ffcf0035ffaf0065ffb5004fffe5ff5eff990063ffc1000dffa9fff9000bff" - "5900f30131ffd6fff20058ff9d0056ffdcffc501f200cf0106002cff50ff1000" - "f0ff170025febeff9500750022feb70082ff48ff2200bbff18006f006fff75ff" - "ab009600790060005b0012004300cdffcc00b8007f0125fffeff8d000cfff4ff" - "97ff880070ff83ff26012fffd5ffb2ffeb002d00c900d1ff8900a1ffa60133fe" - "ffff64ff79001c0053ffb80161ffd6ffb7fff900cbff84ffbb008affa201ad00" - "d00073ff01ff6a0017ff5b0016ff8d0019feec003dfffb01cb0094ff3f000cff" - "92ffd8ff650044004b0003ffc600080080ff8c00f1ff2600a1ffd0ff58ffecff" - "48001a00dbff4dffd6001cff5a0157ff690177009eff2cffadff62fee60027ff" - "b00034010100780127ffbc0052003e000c00e1ff62008bff250016fee3ffe200" - "a8001effad00efff19ff66005d00b2fed600700112ff5eff690073003901a5ff" - "e9ffb60013ff4bfeb2ffe8ff2cffefff14ffa4004affdf006c016efed900b5fe" - "f9ff5effbd006c0068ffedff6100bf0138002bff7f0016ffb90066012100ef01" - "01fee601490024ffb4005e0038ff1700c3ff5f00d0002e001800ec00850049ff" - "d8ffe8ff90ffb6fff5febc0078fed2ff5dff95000500920084ffe60194004dfe" - "c7ffb300e2ff97ff06ffff00caffa3fed00012ffddffe0002700b3ff4400cbfe" - "af001dff170064ffd60166010b0019001500050085ff0cffc50022ffa4008f00" - "71ff5c0037ff23ffc10060fe8c01070075ffe0ffc90066ff04ff47ff9d006300" - "68001700d3ff7bffce0028fedbff26ffffffdaffe2005f0033fef0fffcfec9ff" - "b3ffe6025100660056ff83ff3e00300097fedc008fff940098feafff81ffb1ff" - "a5005cff98013a00260024007f0031003900cd00ad0075ff69ff860016ff2300" - "a6ffabff9fff8100480056ff97003b003cffc20084001c01090057feffff6100" - "51fea6ff8effe3ff840072fffd00a5005eff770160ff320118fedefffffede00" - "7b0006ff80000f00c50119ffc2fef9008bff5e022aff6200caff03fff3fed2ff" - "550007ffd5ffb2ff11001600f6ffd2ffc1ffad006a003aff280035ff49fff3ff" - "a0ff0e00baffea0095fed700a9001aff1200b3010fff3a006801170042ff4800" - "69ff610109005f002d00220055001fff400068008cffb60070fffdfff60010ff" - "8f0009ffdcff3e0051fff2ff4bff4000c5ff9d00b7009b00f200aa004fff4900" - "fe012c00be000e0060003b000c005c00e0ff2eff6bfefe01b6ff9d00c100a000" - "6aff51ffb3ffde002f00a200c7002bfebe0016ffe0ffbb0093ff2200abff8cff" - "17ff8d002fff0afff8feda006eff040082ffb50058ff73005e00cb0091ff7500" - "e2004a007b002cffacfffcffa001b5009300d300700002ff740009ff9dffe500" - "e400770033006bff7cfea0ff48007dffec002cff8300f6ff34006a011afffc00" - "eeff1000570061006a0028ff92003cffbd001a001100a7ff5b002effcf00bcff" - "7dfff8ffce0030ffc6ff3700bf00070006ff7b00acff53004bff54007c006801" - "34fff80138fe7cff9e002fff700091fff701ad003a007efde8fff30031fffaff" - "6dfffafee10086ffdcffc1ffc3ff37ffe500b00090ff82ff4d00920053ff8801" - "80fefefffdff4100c8004401440066ff49ff73000bff8eff50ffa8008b00dcff" - "5effb0002dffd00024ff3bfefcffcb00e3003800f5ffadff57ffa3ffd40120ff" - "63ffbfffebffd0ffc7ffe0006f0050009d00ce001e00a6ff13ff53001f006efe" - "d50085ffabfedfffa9ff46ffd500280092000c005cff6a0078ff50ff630037ff" - "e9ff34fff9008effb500e1005e00af014800a8ff83005cff98ff6300a9ff2f00" - "74ff770105ffd1fe6bffc3ffb6ff3100b4003b01030077009b011bffb9003800" - "40ff7600b60059ffc70092feee010dffd3ff70ffec0002004eff93ff86ff6f00" - "d60016ffd90149ff7900440004ff3affb1ff76004dff67ffa4008b002b003d01" - "90ff5301990022ff2800f00001fe6dfe90005f007bff280030ff65000b016001" - "7f004fff6fff47ff97fe9d009100fc0009003bff86008500faff7dff4b009700" - "320044ffd4ff13005200b2ff41011a002e002bffcffe95ffe2000effeefffa00" - "35ff3c00b6009bffd0009a00d6feaeffb4ff17003cfec7ff2b0026ffdd0038fe" - "fa011fff400191ff0d00e6ffedff71001bff9e00a10000ff56fed1ffe10157ff" - "fa", - - NULL -}; - -static void -test_codec_inner(unsigned logn, uint8_t *tmp, size_t tlen) -{ - size_t n; - inner_shake256_context sc; - int i; - - n = (size_t)1 << logn; - inner_shake256_init(&sc); - inner_shake256_inject(&sc, (const uint8_t *)"codec", 5); - tmp[0] = logn; - inner_shake256_inject(&sc, tmp, 1); - inner_shake256_flip(&sc); - - for (i = 0; i < 10; i ++) { - size_t u, maxlen, len1, len2; - uint16_t *m1, *m2; - int16_t *s1, *s2; - int8_t *b1, *b2; - uint8_t *ee; - unsigned bits; - - m1 = (uint16_t *)tmp; - m2 = m1 + n; - ee = (uint8_t *)(m2 + n); - maxlen = tlen - 4 * n; - for (u = 0; u < n; u ++) { - uint8_t tt[4]; - uint32_t w; - - inner_shake256_extract(&sc, tt, sizeof tt); - w = (uint32_t)tt[0] - | ((uint32_t)tt[1] << 8) - | ((uint32_t)tt[2] << 16) - | ((uint32_t)tt[3] << 24); - m1[u] = w % 12289u; - } - len1 = Zf(modq_encode)(NULL, 0, m1, logn); - if (len1 != (((n * 14) + 7) >> 3)) { - fprintf(stderr, "ERR modq encode(0): %zu\n", len1); - exit(EXIT_FAILURE); - } - len1 = Zf(modq_encode)(ee, maxlen, m1, logn); - if (len1 != (((n * 14) + 7) >> 3)) { - fprintf(stderr, "ERR modq encode: %zu\n", len1); - exit(EXIT_FAILURE); - } - len2 = Zf(modq_decode)(m2, logn, ee, len1); - if (len2 != len1) { - fprintf(stderr, "ERR modq decode: %zu\n", len2); - exit(EXIT_FAILURE); - } - check_eq(m1, m2, n * sizeof *m2, "modq encode/decode"); - - s1 = (int16_t *)tmp; - s2 = s1 + n; - ee = (uint8_t *)(s2 + n); - maxlen = tlen - 4 * n; - for (bits = 4; bits <= 12; bits ++) { - unsigned mask1, mask2; - - mask1 = 1u << (bits - 1); - mask2 = mask1 - 1u; - - for (u = 0; u < n; u ++) { - uint8_t tt[2]; - unsigned w, a; - - inner_shake256_extract(&sc, tt, sizeof tt); - w = (unsigned)tt[0] | ((unsigned)tt[1] << 8); - a = w & mask2; - s1[u] = ((w & mask1) != 0) ? -(int)a : (int)a; - } - - len1 = Zf(trim_i16_encode)(NULL, 0, s1, logn, bits); - if (len1 != (((n * bits) + 7) >> 3)) { - fprintf(stderr, - "ERR trim_i16 encode(0): %zu\n", len1); - exit(EXIT_FAILURE); - } - len1 = Zf(trim_i16_encode)(ee, maxlen, s1, logn, bits); - if (len1 != (((n * bits) + 7) >> 3)) { - fprintf(stderr, - "ERR trim_i16 encode: %zu\n", len1); - exit(EXIT_FAILURE); - } - len2 = Zf(trim_i16_decode)(s2, logn, bits, ee, len1); - if (len2 != len1) { - fprintf(stderr, - "ERR trim_i16 decode: %zu\n", len2); - exit(EXIT_FAILURE); - } - check_eq(s1, s2, n * sizeof *s2, - "trim_i16 encode/decode"); - - memset(s2, 0, n * sizeof *s2); - len1 = Zf(comp_encode)(ee, maxlen, s1, logn); - if (len1 == 0) { - fprintf(stderr, - "ERR comp encode: %zu\n", len1); - exit(EXIT_FAILURE); - } - len2 = Zf(comp_decode)(s2, logn, ee, len1); - if (len2 != len1) { - fprintf(stderr, - "ERR comp decode: %zu\n", len2); - exit(EXIT_FAILURE); - } - check_eq(s1, s2, n * sizeof *s2, - "comp encode/decode"); - } - - b1 = (int8_t *)tmp; - b2 = b1 + n; - ee = (uint8_t *)(b2 + n); - maxlen = tlen - 2 * n; - for (bits = 4; bits <= 8; bits ++) { - unsigned mask1, mask2; - - mask1 = 1u << (bits - 1); - mask2 = mask1 - 1u; - - for (u = 0; u < n; u ++) { - uint8_t tt; - unsigned a; - - inner_shake256_extract(&sc, &tt, 1); - a = tt & mask2; - b1[u] = ((tt & mask1) != 0) ? -(int)a : (int)a; - } - - len1 = Zf(trim_i8_encode)(NULL, 0, b1, logn, bits); - if (len1 != (((n * bits) + 7) >> 3)) { - fprintf(stderr, - "ERR trim_i8 encode(0): %zu\n", len1); - exit(EXIT_FAILURE); - } - len1 = Zf(trim_i8_encode)(ee, maxlen, b1, logn, bits); - if (len1 != (((n * bits) + 7) >> 3)) { - fprintf(stderr, - "ERR trim_i8 encode: %zu\n", len1); - exit(EXIT_FAILURE); - } - len2 = Zf(trim_i8_decode)(b2, logn, bits, ee, len1); - if (len2 != len1) { - fprintf(stderr, - "ERR trim_i8 decode: %zu\n", len2); - exit(EXIT_FAILURE); - } - check_eq(b1, b2, n * sizeof *b2, - "trim_i8 encode/decode"); - } - } -} - -static void -test_codec(void) -{ - unsigned logn; - uint8_t *tmp; - size_t tlen; - - printf("Test encode/decode: "); - fflush(stdout); - tlen = 8192; - tmp = xmalloc(tlen); - - for (logn = 1; logn <= 10; logn ++) { - test_codec_inner(logn, tmp, tlen); - printf("."); - fflush(stdout); - } - - xfree(tmp); - printf(" done.\n"); - fflush(stdout); -} - -static void -test_vrfy_inner(unsigned logn, const int8_t *f, const int8_t *g, - const int8_t *F, const int8_t *G, const uint16_t *h, - const char *hexpkey, const char *const *kat, uint8_t *tmp, size_t tlen) -{ - size_t u, n, len1, len2; - int8_t *G2; - uint16_t *h2; - - n = (size_t)1 << logn; - - /* - * Test computation of public key from private key. - */ - h2 = (uint16_t *)tmp; - if (tlen < 4 * n) { - fprintf(stderr, "Insufficient buffer size\n"); - exit(EXIT_FAILURE); - } - if (!Zf(compute_public)(h2, f, g, logn, (uint8_t *)(h2 + n))) { - fprintf(stderr, "compute_public failed\n"); - exit(EXIT_FAILURE); - } - check_eq(h, h2, n, "compute_public"); - - /* - * Test reconstruction of G from f, g and F. - */ - G2 = (int8_t *)tmp; - if (tlen < 5 * n) { - fprintf(stderr, "Insufficient buffer size\n"); - exit(EXIT_FAILURE); - } - if (!Zf(complete_private)(G2, f, g, F, logn, (uint8_t *)(G2 + n))) { - fprintf(stderr, "complete_private failed\n"); - exit(EXIT_FAILURE); - } - check_eq(G, G2, n, "complete_private"); - - /* - * Test encoding of public key. - */ - len1 = hextobin(tmp, tlen, hexpkey); - if (len1 != 1 + (((n * 14) + 7) >> 3)) { - fprintf(stderr, "unexpected public key length: %zu\n", len1); - exit(EXIT_FAILURE); - } - if (tmp[0] != logn) { - fprintf(stderr, "unexpected first pkey byte: %u\n", tmp[0]); - exit(EXIT_FAILURE); - } - len1 --; - if (tlen < 2 * len1) { - fprintf(stderr, "Insufficient buffer size\n"); - exit(EXIT_FAILURE); - } - memmove(tmp, tmp + 1, len1); - len2 = Zf(modq_encode)(tmp + len1, tlen - len1, h, logn); - if (len2 != len1) { - fprintf(stderr, "wrong encoded public key length: %zu\n", len2); - exit(EXIT_FAILURE); - } - check_eq(tmp, tmp + len1, len1, "pubkey encode\n"); - - /* - * Verify sample signatures. - */ - if (tlen < 8 * n) { - fprintf(stderr, "Insufficient buffer size\n"); - exit(EXIT_FAILURE); - } - for (u = 0; kat[u] != NULL; u += 3) { - uint8_t *nonce, *sig; - size_t nonce_len; - inner_shake256_context sc; - int16_t *s2; - uint16_t *c0; - - /* - * Hash nonce + message. - */ - nonce = tmp; - nonce_len = hextobin(nonce, tlen, kat[u + 0]); - inner_shake256_init(&sc); - inner_shake256_inject(&sc, nonce, nonce_len); - inner_shake256_inject(&sc, - (const uint8_t *)kat[u + 1], strlen(kat[u + 1])); - inner_shake256_flip(&sc); - - /* - * Decode signature. - */ - sig = tmp; - len1 = hextobin(sig, tlen, kat[u + 2]); - if (len1 == 0 || sig[0] != logn) { - fprintf(stderr, "Invalid sig KAT\n"); - exit(EXIT_FAILURE); - } - len1 --; - memmove(sig, sig + 1, len1); - s2 = (int16_t *)(sig + len1); - if ((tlen - len1) < 2 * n) { - fprintf(stderr, "Insufficient buffer size\n"); - exit(EXIT_FAILURE); - } - len2 = Zf(trim_i16_decode)(s2, logn, 16, sig, len1); - if (len2 != len1) { - fprintf(stderr, "Invalid sig KAT\n"); - exit(EXIT_FAILURE); - } - memmove(tmp, s2, n * sizeof *s2); - s2 = (int16_t *)tmp; - - /* - * Convert public key to NTT + Montgomery representation. - */ - h2 = (uint16_t *)(s2 + n); - memcpy(h2, h, n * sizeof *h); - Zf(to_ntt_monty)(h2, logn); - - /* - * Hash nonce + message into a point. - */ - c0 = h2 + n; - Zf(hash_to_point_vartime)(&sc, c0, logn); - - /* - * Verify the signature. - */ - if (!Zf(verify_raw)(c0, s2, h2, logn, (uint8_t *)(c0 + n))) { - fprintf(stderr, "KAT signature failed\n"); - exit(EXIT_FAILURE); - } - - printf("."); - fflush(stdout); - } - - printf(" "); - fflush(stdout); -} - -static void -test_vrfy(void) -{ - uint8_t *tmp; - size_t tlen; - - printf("Test verify: "); - fflush(stdout); - tlen = 8192; - tmp = xmalloc(tlen); - - test_vrfy_inner(4, ntru_f_16, ntru_g_16, ntru_F_16, ntru_G_16, - ntru_h_16, ntru_pkey_16, KAT_SIG_16, tmp, tlen); - test_vrfy_inner(9, ntru_f_512, ntru_g_512, ntru_F_512, ntru_G_512, - ntru_h_512, ntru_pkey_512, KAT_SIG_512, tmp, tlen); - test_vrfy_inner(10, ntru_f_1024, ntru_g_1024, ntru_F_1024, ntru_G_1024, - ntru_h_1024, ntru_pkey_1024, KAT_SIG_1024, tmp, tlen); - - xfree(tmp); - printf("done.\n"); - fflush(stdout); -} - -static const uint64_t KAT_RNG_1[] = { - 0xDB1F30843AAD694Cu, 0xFAD9C14E86D5B53Cu, 0x7F84F914F46C439Fu, - 0xC46A6E399A376C6Du, 0x47A5CD6F8C6B1789u, 0x1E85D879707DA987u, - 0xC7B0CE6C2C1DB3E7u, 0xA65795537B3D977Cu, 0x748457A98AC7F19Cu, - 0xD8C8F161EEB7231Fu, 0xE81CAE53A7E8967Fu, 0x27EAD55A75ED57F8u, - 0x9680953F3A192413u, 0x784145D6687EA318u, 0x9B454489BE56BAEBu, - 0xF546834B0F799C67u, 0xAC8E4F657C93FB88u, 0xD0E6C7610CC4028Bu, - 0x417296FB7E1124BDu, 0xE7968F18E3221DDCu, 0x1DDEC33FC7F2D5FBu, - 0x76556A8C07FB48EEu, 0x7910EAA4C163BC2Fu, 0xAAC5C6291F779D17u, - 0x575B2692885C4CFAu, 0x0664AA8C3E99DA19u, 0xFA55C1AE9A615133u, - 0x7F1DB1A620F63220u, 0xE740AE9AF9CC9755u, 0x8393056E1D0D81E1u, - 0x556EEF4483B434AAu, 0xC6D17BEF7C2FB0C3u, 0x27D142BD5BBF6014u, - 0x6FD90B14DB4AA0BBu, 0x7ACDD6F240530D0Du, 0xE980F9F9DBE6109Au, - 0xA30C677211C7BF37u, 0x1E41FD290B90CE8Bu, 0x478FCD48D5E4A9EDu, - 0x10586F987EA5FA7Au, 0x691891C568F5DAC7u, 0x3277735ED18D9107u, - 0x78FCC576E47E8D71u, 0x940A2C6777E3BEBBu, 0x814612E210DD9715u, - 0xABBCAFCC6B54279Bu, 0x2550E2538A063BFCu, 0x7965EFC9D3F8A5BEu, - 0xAE35E74B5A0B8717u, 0xD855D6ABB96EA3AFu, 0xAB4689B903C01C4Eu, - 0x8D8018988CA554ACu, 0x0BB6689524F3A2B1u, 0xAC0676FCBB193A87u, - 0xD0A83D30F34F65ECu, 0x26D3A8C167CA09F4u, 0x7D17403D2B1DD9A0u, - 0x47B1C836A0224550u, 0xF6ABECF6422C5A56u, 0x6FB1B2FF5CDDEC25u, - 0x118276B244B55F88u, 0x1FB953EF9E6C2C41u, 0xF351C2717ACE9BF3u, - 0xDF787B64D51A5440u, 0xE4B8B81149B8A70Bu, 0x337E5363F506228Bu, - 0x48948ADE314B5980u, 0x7FBF7A7139004610u, 0xA6CB33F6802C96C7u, - 0x745888A51A99BBEDu, 0x49D411403BA9CFDAu, 0xA547A6EA4BDD5538u, - 0x2D65DCF44F045E9Fu, 0x734FBE9360EFCC44u, 0x1131E0AD573D37A0u, - 0xADF3E9199FD90113u, 0x8EDF3EAF50E6E00Bu, 0xFE0240D04C171901u, - 0x45A97204596F7C46u, 0x54D1D1F962484BC5u, 0xEBAC109CDB975ED4u, - 0x51182BF46BD2D61Cu, 0xF12D0EC8A80092D3u, 0x69CA22BA55B34270u, - 0x5FF97BBE7A525BF7u, 0xF4E19780A4149ACAu, 0x2CD5AE45826309FCu, - 0xF0EF1F0A309C1BCFu, 0xC16AF49962FE8A87u, 0x2CD2575C27761E54u, - 0xD9199411E9CC816Du, 0xA0C397A63D036B05u, 0xF439D283DFE4C172u, - 0x5DAAD309E61F2A60u, 0x2E7DDC8F9CD47E91u, 0x2E1BFCDDC439FD58u, - 0x8E62B7C84C3C27F8u, 0xECD06ED0C1938A5Eu, 0x0335351E644A9155u, - 0x71A735982C6DBBF7u, 0xD8FE9FAF2DDF9AFFu, 0x06BC9F654B9814E7u, - 0x2DF46A488EC46052u, 0x80CB8E04CDEF7F98u, 0x9B65042EE20B4DAFu, - 0x203BF49ACB5B34D2u, 0x54E8F69957D8903Bu, 0x84D63D4BA389AF36u, - 0x7A2D4A2230D0DC82u, 0x3052659534D82FB8u, 0xC5058A8EC3716238u, - 0xB8063774064F4A27u, 0x2F0BE0CE382BFD5Bu, 0xEE4CEAD41973DA0Fu, - 0xFB56581EB2424A5Au, 0x09F21B654D835F66u, 0x1968C7264664F9CCu, - 0x2CBD6BB3DD21732Cu, 0xA9FB1E69F446231Cu, 0xDBEAD8399CB25257u, - 0x28FF84E3ECC86113u, 0x19A3B2D11BA6E80Fu, 0xC3ADAE73363651E7u, - 0xF33FFB4923D82396u, 0x36FE16582AD8C34Cu, 0x728910D4AA3BB137u, - 0x2F351F2EF8B05525u, 0x8727C7A39A617AE4u -}; - -static const uint8_t KAT_RNG_2[] = { - 0xC9, 0x45, 0xBC, 0xC4, 0x5B, 0x67, 0xA3, 0x25, 0x97, 0x19, - 0x64, 0x67, 0x4A, 0x98, 0xD4, 0xB7, 0xA7, 0x83, 0x18, 0xC8, - 0x40, 0xE2, 0x7F, 0xB8, 0x25, 0x8B, 0x7E, 0x92, 0x4A, 0x8C, - 0x68, 0x1B, 0x77, 0x61, 0x1E, 0x70, 0xED, 0xC2, 0xC4, 0xA5, - 0xDF, 0x9E, 0x76, 0xED, 0x49, 0x84, 0x3D, 0x08, 0xFE, 0xFE, - 0x99, 0xE2, 0xC6, 0xEF, 0xFE, 0x2C, 0xD4, 0xC0, 0x04, 0xD8, - 0x9A, 0x51, 0x21, 0xCD, 0x5B, 0xDB, 0x9F, 0x0B, 0x9C, 0x47, - 0xCF, 0xE8, 0x38, 0x6B, 0xB4, 0x94, 0xDC, 0xCD, 0x9A, 0x9B, - 0xB7, 0xED, 0xEE, 0x82, 0x64, 0x53, 0x20, 0xA0, 0x8F, 0x59, - 0xB2, 0x4F, 0xE2, 0x5A, 0x35, 0x88, 0x39, 0x5B, 0x6C, 0x59, - 0x59, 0x8C, 0x10, 0xC5, 0x2B, 0xF3, 0x7C, 0x49, 0xFD, 0x99, - 0x0C, 0x86, 0x07, 0x9E, 0x35, 0x71, 0x8E, 0x23, 0x7B, 0x9D, - 0x23, 0x34, 0x7A, 0xC8, 0x8A, 0x17, 0xDA, 0x7B, 0xA2, 0x97, - 0x0A, 0x78, 0x2B, 0x19, 0xAD, 0xB1, 0x35, 0xBD, 0xB1, 0xE7, - 0x74, 0x4B, 0x82, 0xFB, 0x72, 0x9C, 0x8C, 0x51, 0x3B, 0xE3, - 0xF0, 0x31, 0x11, 0xAA, 0x59, 0xA4, 0x66, 0xAC, 0xAA, 0x9E, - 0x85, 0xD9, 0x2D, 0xAD, 0xCA, 0x2B, 0x69, 0x5E, 0x19, 0x9F, - 0x77, 0x15, 0x43, 0xF0, 0xC9, 0x9F, 0xBC, 0x5B, 0x66, 0x26, - 0x7F, 0x7D, 0x7C, 0x95, 0x5D, 0x60, 0xE0, 0x49, 0x15, 0xC4, - 0x56, 0x47, 0x7E, 0x8D, 0x68, 0x3C, 0x54, 0x6F, 0x20, 0xF9, - 0x00, 0x43, 0xB4, 0x52, 0xD8, 0x46, 0x51, 0xFC, 0x0B, 0x92, - 0x15, 0xEF, 0x56, 0x45, 0x49, 0x94, 0xC2, 0xD0, 0x5E, 0x95, - 0xC4, 0x6D, 0x00, 0xDD, 0x13, 0x93, 0x78, 0xC2, 0x85, 0x21, - 0x5D, 0x18, 0x92, 0xB9, 0x48, 0xD2, 0x96, 0x45, 0x89, 0x0D, - 0x69, 0x2B, 0x85, 0x5D, 0x23, 0x5D, 0x10, 0x92, 0xD7, 0xDC, - 0xDC, 0xF8, 0x60, 0x5E, 0xED, 0x1F, 0x21, 0xB2, 0x19, 0x27, - 0xB7, 0xB7, 0xCD, 0x49, 0x98, 0x29, 0x90, 0xC9, 0x81, 0xCD, - 0x4E, 0x44, 0xB5, 0x39, 0x56, 0xED, 0x2B, 0xAA, 0x53, 0x34, - 0x3B, 0xB0, 0xBA, 0x1F, 0xBC, 0xF8, 0x58, 0x5F, 0x3E, 0xD0, - 0x4D, 0xB3, 0xA8, 0x5E, 0xC9, 0xB8, 0xD2, 0x70, 0xD3, 0x30, - 0xC0, 0x3C, 0x45, 0x89, 0x9B, 0x4C, 0x5F, 0xE8, 0x05, 0x7F, - 0x78, 0x99, 0x48, 0x3A, 0xD7, 0xCB, 0x96, 0x9A, 0x33, 0x97, - 0x62, 0xE9, 0xBD, 0xCE, 0x04, 0x72, 0x4D, 0x85, 0x67, 0x51, - 0x69, 0xFB, 0xD3, 0x12, 0xBC, 0xFC, 0xB5, 0x77, 0x56, 0x3B, - 0xB9, 0xB5, 0x3D, 0x5D, 0x7D, 0x2B, 0x34, 0xB0, 0x36, 0x2D, - 0x56, 0xE9, 0x24, 0xC2, 0x5A, 0xE9, 0x2A, 0xF8, 0xEE, 0x83, - 0x74, 0xC1, 0x0C, 0x80, 0xAD, 0x43, 0x5C, 0x04, 0x49, 0xB0, - 0x41, 0xD2, 0x29, 0x32, 0x9C, 0x7D, 0x70, 0xD5, 0x3D, 0xFE, - 0x82, 0x27, 0x8A, 0x38, 0x19, 0x12, 0x14, 0x78, 0xAA, 0x2A, - 0x29, 0xE2, 0x2B, 0xBB, 0x87, 0x4F, 0x7A, 0xDC, 0xC0, 0x72, - 0x30, 0xB6, 0xDE, 0x73, 0x7C, 0x04, 0x2D, 0xB6, 0xDF, 0x5E, - 0x4C, 0x3B, 0x82, 0xF6, 0x10, 0xE4, 0x94, 0xCE, 0x90, 0xD4, - 0x23, 0x0C, 0xBD, 0xCA, 0x56, 0xB7, 0x09, 0x6C, 0xAC, 0x35, - 0xA8, 0x47, 0xF0, 0x94, 0x21, 0xBD, 0xD5, 0x09, 0x18, 0x78, - 0x7C, 0x8D, 0x1E, 0x03, 0x15, 0xB1, 0x1A, 0xE8, 0x72, 0xB7, - 0x98, 0x5F, 0x23, 0x3A, 0x91, 0xB2, 0xDF, 0xFD, 0x70, 0x69, - 0xC4, 0x3B, 0xFA, 0x73, 0x17, 0xCC, 0xFB, 0xCF, 0xA6, 0xCF, - 0xC1, 0x32, 0x3E, 0x74, 0x0C, 0xCC, 0x73, 0xB2, 0xBE, 0x73, - 0xAC, 0x8E, 0x44, 0x51, 0x45, 0xED, 0xF6, 0x60, 0x21, 0x3D, - 0x0C, 0xE3, 0x3E, 0x1B, 0x11, 0x55, 0x68, 0x1A, 0x15, 0x97, - 0x80, 0x67, 0x23, 0x4F, 0x37, 0xF5, 0x30, 0x3D, 0x05, 0x4E, - 0xCF, 0x0E, 0x03, 0xB9, 0x2F, 0xD1, 0xD5, 0xD6, 0x5F, 0x79, - 0xF6, 0x61, 0x15, 0xBC, 0x79, 0x80, 0xA4, 0xD7, 0x98, 0x5B, - 0x38, 0x7A, 0x07, 0x9B, 0x02, 0xB2, 0x47, 0x89, 0xB2, 0x25, - 0xEF, 0x7B, 0xB1, 0xB0, 0xA5, 0x35, 0x39, 0xEB, 0xA0, 0x1C, - 0x24, 0xF4, 0xDB, 0x0C, 0x6C, 0x2B, 0xA3, 0x75, 0x47, 0x00, - 0xA3, 0xC8, 0xBC, 0x1E, 0x15, 0x3A, 0xC6, 0x1D, 0x91, 0x19, - 0xBA, 0xB4, 0xCA, 0x28, 0xD2, 0x57, 0x7C, 0x0D, 0x71, 0x4A, - 0x03, 0xD5, 0xAE, 0x96, 0x6D, 0x92, 0x70, 0x27, 0x82, 0x88, - 0xB6, 0x12, 0x1A, 0x84, 0x38, 0x1B, 0x74, 0x2F, 0x74, 0x33, - 0xE0, 0xA1, 0x82, 0x93, 0x62, 0xB6, 0x5B, 0x9E, 0x4E, 0xC2, - 0xE6, 0x5B, 0x49, 0x7E, 0x4A, 0x68, 0x8D, 0x08, 0xA9, 0xD8, - 0xEA, 0x47, 0xFC, 0xD2, 0x31, 0x21, 0x38, 0xEE, 0xE4, 0xE4, - 0x97, 0xFA, 0x91, 0x90, 0xC4, 0x26, 0x4B, 0xA5, 0xB3, 0x7D, - 0x33, 0x7F, 0x5A, 0x2D, 0x54, 0xB3, 0x01, 0xCF, 0x9C, 0x0D, - 0x9E, 0x97, 0x01, 0xE8, 0x54, 0x3C, 0xC2, 0x13, 0x69, 0x0C, - 0x35, 0xCD, 0x63, 0x02, 0x70, 0xC8, 0xA1, 0x1F, 0xC2, 0xBE, - 0x8F, 0xFC, 0xCE, 0x05, 0xA7, 0x3F, 0xCC, 0x04, 0x3D, 0x18, - 0xC4, 0x13, 0x38, 0x0D, 0x4C, 0xEE, 0x81, 0xFA, 0x02, 0xF8, - 0xFC, 0x4F, 0x21, 0xD0, 0xE6, 0xF2, 0x7B, 0x92, 0x76, 0xC5, - 0x8E, 0x96, 0x6C, 0x53, 0x84, 0x3E, 0x74, 0x1D, 0xD5, 0x0F, - 0x98, 0x03, 0x0E, 0x6A, 0x9D, 0x49, 0x03, 0xAE, 0xBE, 0x70, - 0x61, 0x5B, 0x45, 0xC0, 0x1E, 0x2F, 0x94, 0x42, 0xFA, 0x16, - 0x9F, 0xFA, 0xD5, 0x9B, 0x60, 0x88, 0x92, 0x19, 0x08, 0x02, - 0x31, 0x99, 0x6D, 0xA1, 0x72, 0xCB, 0x45, 0xC6, 0x93, 0xBA, - 0xA8, 0x71, 0x42, 0xC6, 0x85, 0x28, 0x6C, 0x1B, 0x60, 0x7C, - 0x14, 0x2F, 0x9A, 0x17, 0x10, 0x34, 0x27, 0x48, 0x36, 0xB2, - 0xE8, 0xD3, 0xEA, 0xE4, 0x9D, 0x67, 0xE4, 0x46, 0x2E, 0xC6, - 0x41, 0xE1, 0x83, 0x42, 0xB8, 0x82, 0x5F, 0x79, 0x61, 0xA3, - 0x0C, 0x63, 0x00, 0xCB, 0x7C, 0xB9, 0x30, 0x53, 0xF4, 0xFC, - 0xAF, 0xAC, 0x22, 0x71, 0x87, 0x4D, 0x4B, 0x4B, 0x9E, 0xAE, - 0x69, 0xB5, 0x58, 0x04, 0x9C, 0x03, 0x57, 0x58, 0x8D, 0x2F, - 0x82, 0x95, 0x57, 0x2F, 0xC3, 0xA1, 0xC5, 0xB1, 0xF1, 0xF1, - 0x98, 0x9A, 0xF8, 0x99, 0x74, 0x5C, 0xC5, 0xAC, 0x4A, 0x32, - 0xE9, 0x24, 0xCF, 0x1D, 0x1E, 0x29, 0x18, 0x7C, 0xBF, 0x43, - 0x74, 0x23, 0x28, 0xB0, 0x3D, 0xD1, 0xB3, 0x8C, 0xE1, 0x28, - 0x02, 0x3E, 0x8F, 0x7F, 0xDD, 0xF0, 0x5B, 0x4D, 0x37, 0x96, - 0xF7, 0x73, 0x73, 0x7F, 0xBC, 0xAD, 0x6C, 0x84, 0xFC, 0x47, - 0xD2, 0x1E, 0xAB, 0xEB, 0xB6, 0xCA, 0x4E, 0x3A, 0x2C, 0x47, - 0x59, 0x61, 0x0D, 0xA0, 0x17, 0xCF, 0xDD, 0x62, 0x6F, 0xA3, - 0xF4, 0x72, 0x2D, 0xB0, 0xB2, 0x34, 0x2A, 0xE1, 0x63, 0xC3, - 0x5B, 0xAC, 0xE8, 0x6F, 0x92, 0x77, 0x78, 0xE2, 0x34, 0xAD, - 0x4F, 0x6C, 0xFF, 0x71, 0xE1, 0x92, 0xFD, 0xED, 0xA1, 0x20, - 0xCA, 0xCB, 0x80, 0x32, 0xD1, 0x78, 0x72, 0x68, 0xFE, 0xAE, - 0x73, 0x22, 0xD7, 0x60, 0x23, 0x1D, 0x3D, 0x06, 0xD6, 0x2A, - 0x81, 0xC4, 0x43, 0x98, 0xFD, 0x4E, 0xBD, 0x85, 0x09, 0x29, - 0x11, 0xE8, 0x36, 0xE1, 0xCE, 0xCF, 0x07, 0xA7, 0x45, 0x8C, - 0xCB, 0xB2, 0xDC, 0xD0, 0x98, 0xB9, 0x93, 0x33, 0x8A, 0x2A, - 0x13, 0x82, 0x36, 0x3D, 0x22, 0xB0, 0x9C, 0x74, 0x3F, 0xCE, - 0x6F, 0xCC, 0x69, 0xFF, 0x81, 0xE8, 0xAE, 0xC8, 0x57, 0x0D, - 0x98, 0xEB, 0xC5, 0x2A, 0x45, 0x55, 0xDC, 0xBB, 0x0A, 0x5B, - 0x3D, 0xB4, 0x61, 0xC4, 0xAE, 0x11, 0x68, 0x7D, 0xD4, 0x45, - 0x83, 0xAE, 0x66, 0xC8 -}; - -static void -test_RNG(void) -{ - inner_shake256_context sc; - prng p; - size_t u; - - printf("Test RNG: "); - fflush(stdout); - - inner_shake256_init(&sc); - inner_shake256_inject(&sc, (const uint8_t *)"rng", 3); - inner_shake256_flip(&sc); - Zf(prng_init)(&p, &sc); - for (u = 0; u < (sizeof KAT_RNG_1) / sizeof(KAT_RNG_1[0]); u ++) { - if (KAT_RNG_1[u] != prng_get_u64(&p)) { - fprintf(stderr, "ERR KAT_RNG_1(%zu)\n", u); - exit(EXIT_FAILURE); - } - } - for (u = 0; u < (sizeof KAT_RNG_2) / sizeof(KAT_RNG_2[0]); u ++) { - if (KAT_RNG_2[u] != prng_get_u8(&p)) { - fprintf(stderr, "ERR KAT_RNG_2(%zu)\n", u); - exit(EXIT_FAILURE); - } - } - - printf("done.\n"); - fflush(stdout); -} - -static void -testfp_hash_u(inner_shake256_context *sc, uint64_t x) -{ -#if FALCON_LE - inner_shake256_inject(sc, (const uint8_t *)&x, 8); -#else - uint8_t buf[8]; - - buf[0] = (uint8_t)x; - buf[1] = (uint8_t)(x >> 8); - buf[2] = (uint8_t)(x >> 16); - buf[3] = (uint8_t)(x >> 24); - buf[4] = (uint8_t)(x >> 32); - buf[5] = (uint8_t)(x >> 40); - buf[6] = (uint8_t)(x >> 48); - buf[7] = (uint8_t)(x >> 56); - inner_shake256_inject(sc, buf, 8); -#endif -} - -static void -testfp_hash_d(inner_shake256_context *sc, fpr x) -{ - union { - fpr f; - uint64_t u; - } t; - - t.f = x; - testfp_hash_u(sc, t.u); -} - -static fpr -rand_fp(prng *p) -{ - uint64_t m; - int e; - union { - fpr x; - uint64_t u; - } t; - - m = prng_get_u64(p); - e = (m >> 52) & 0x7FF; - e = (e & 0x7F) + 1023; - t.u = (m & ~((uint64_t)0x7FF << 52)) | ((uint64_t)e << 52); - return t.x; -} - -/* - * The FPEMU code defines fpr_scaled(), but the FPNATIVE code does not. - * Also, neither defines fpr_ldexp(), though they previously did, and some - * tests still rely on it. - */ - -#ifndef fpr_scaled -static inline fpr -fpr_scaled(int64_t i, int sc) -{ - return FPR(ldexp((double)i, sc)); -} -#endif - -static inline fpr -fpr_ldexp(fpr x, int e) -{ -#if FALCON_FPEMU - uint32_t ex; - - /* - * Extract the exponent. - */ - ex = (x >> 52) & 0x7FF; - - /* - * Add 'e' to the exponent. However, if the result is negative, - * or the original exponent was 0, then the result should be 0. - */ - ex = (ex + (uint32_t)e) & -((ex + 0x7FF) >> 11); - ex &= (ex >> 31) - 1; - x = (x & (((uint64_t)1 << 63) + ((uint64_t)1 << 52) - (uint64_t)1)) - | ((uint64_t)ex << 52); - return x; -#else - return FPR(ldexp(x.v, e)); -#endif -} - -TARGET_AVX2 -static void -test_FP_block(void) -{ - long ctr; - inner_shake256_context sc, rng; - prng p; - int e; - fpr nzero; - unsigned char tmp[16], tmp2[16]; - size_t u; - - printf("Test floating-point (block): "); - fflush(stdout); - - inner_shake256_init(&sc); - - testfp_hash_d(&sc, fpr_of(0)); - testfp_hash_d(&sc, fpr_neg(fpr_zero)); - testfp_hash_d(&sc, fpr_half(fpr_zero)); - testfp_hash_d(&sc, fpr_double(fpr_zero)); - - nzero = fpr_neg(fpr_zero); - testfp_hash_d(&sc, fpr_add(fpr_zero, fpr_zero)); - testfp_hash_d(&sc, fpr_add(fpr_zero, nzero)); - testfp_hash_d(&sc, fpr_add(nzero, fpr_zero)); - testfp_hash_d(&sc, fpr_add(nzero, fpr_zero)); - testfp_hash_d(&sc, fpr_add(fpr_zero, fpr_zero)); - testfp_hash_d(&sc, fpr_add(fpr_zero, nzero)); - testfp_hash_d(&sc, fpr_add(nzero, fpr_zero)); - testfp_hash_d(&sc, fpr_add(nzero, fpr_zero)); - - for (e = -60; e <= +60; e ++) { - fpr a, b; - int i, j; - - for (i = -5; i <= +5; i ++) { - a = fpr_of(((int64_t)1 << 53) + i); - testfp_hash_d(&sc, a); - for (j = -5; j <= +5; j ++) { - b = fpr_scaled(((int64_t)1 << 53) + j, e); - testfp_hash_d(&sc, b); - testfp_hash_d(&sc, fpr_add(a, b)); - a = fpr_neg(a); - testfp_hash_d(&sc, fpr_add(a, b)); - b = fpr_neg(b); - testfp_hash_d(&sc, fpr_add(a, b)); - a = fpr_neg(a); - testfp_hash_d(&sc, fpr_add(a, b)); - } - } - printf("."); - fflush(stdout); - } - printf(" "); - fflush(stdout); - - inner_shake256_init(&rng); - inner_shake256_inject(&rng, (const uint8_t *)"fpemu", 5); - inner_shake256_flip(&rng); - Zf(prng_init)(&p, &rng); - for (ctr = 1; ctr <= 65536L; ctr ++) { - fpr a, b; - int64_t j; - - *(uint64_t *)&j = prng_get_u64(&p); - j >>= (int)(ctr & 63); - a = fpr_of(j); - testfp_hash_d(&sc, a); - - e = prng_get_u8(&p); - e -= 128; - a = fpr_scaled(j, e); - testfp_hash_d(&sc, a); - - *(uint64_t *)&j = prng_get_u64(&p); - a = fpr_scaled(j, -8); - testfp_hash_d(&sc, a); - testfp_hash_u(&sc, (uint64_t)fpr_rint(a)); - a = fpr_scaled(j, -52); - testfp_hash_d(&sc, a); - testfp_hash_u(&sc, (uint64_t)fpr_floor(a)); - - a = rand_fp(&p); - b = rand_fp(&p); - - for (e = -60; e <= 60; e ++) { - testfp_hash_d(&sc, fpr_ldexp(a, e)); - } - - testfp_hash_u(&sc, fpr_lt(a, b)); - testfp_hash_u(&sc, fpr_lt(a, a)); - - testfp_hash_d(&sc, fpr_add(a, b)); - testfp_hash_d(&sc, fpr_add(b, a)); - testfp_hash_d(&sc, fpr_add(a, fpr_zero)); - testfp_hash_d(&sc, fpr_add(fpr_zero, a)); - testfp_hash_d(&sc, fpr_add(a, fpr_neg(a))); - testfp_hash_d(&sc, fpr_add(fpr_neg(a), a)); - - testfp_hash_d(&sc, fpr_sub(a, b)); - testfp_hash_d(&sc, fpr_sub(b, a)); - testfp_hash_d(&sc, fpr_sub(a, fpr_zero)); - testfp_hash_d(&sc, fpr_sub(fpr_zero, a)); - testfp_hash_d(&sc, fpr_sub(a, a)); - - testfp_hash_d(&sc, fpr_neg(a)); - testfp_hash_d(&sc, fpr_half(a)); - testfp_hash_d(&sc, fpr_double(a)); - - testfp_hash_d(&sc, fpr_mul(a, b)); - testfp_hash_d(&sc, fpr_mul(b, a)); - testfp_hash_d(&sc, fpr_mul(a, fpr_zero)); - testfp_hash_d(&sc, fpr_mul(fpr_zero, a)); - - if (fpr_lt(b, fpr_zero) || fpr_lt(fpr_zero, b)) { - testfp_hash_d(&sc, fpr_div(a, b)); - } - if (fpr_lt(a, fpr_zero)) { - a = fpr_neg(a); - } - testfp_hash_d(&sc, fpr_sqrt(a)); - - if ((ctr & 0x3FF) == 0) { - printf("."); - fflush(stdout); - } - } - - /* - * Should be: 77cea0ea343b8c1c578af7c9fa3267b6 - */ - - inner_shake256_flip(&sc); - inner_shake256_extract(&sc, tmp, sizeof tmp); - printf(" "); - for (u = 0; u < sizeof tmp; u ++) { - printf("%02x", tmp[u]); - } - hextobin(tmp2, sizeof tmp2, "77cea0ea343b8c1c578af7c9fa3267b6"); - if (memcmp(tmp, tmp2, sizeof tmp) != 0) { - fprintf(stderr, "Wrong hash" - " (expected: 77cea0ea343b8c1c578af7c9fa3267b6)\n"); - exit(EXIT_FAILURE); - } - - printf(" done.\n"); - fflush(stdout); -} - -#if 0 -/* - * Similar to test_FP_block(), but using the native 'double' as expected - * values; this can be used to pinpoint discrepancies. IMPORTANT: this - * assumes that the native 'double' faithfully follows IEEE 754. In - * particular, software emulation shipped with GCC 7.3.0 for ARM Cortex - * M4 sometimes gets rounding wrong in the last bit; in that case, the - * code below would report an error while the Falcon FP emulation is - * actually the correct one. - */ - -static uint64_t -double_to_u64(double x) -{ - union { - double d; - uint64_t u; - } t; - - t.d = x; - return t.u; -} - -static double -u64_to_double(uint64_t x) -{ - union { - double d; - uint64_t u; - } t; - - t.u = x; - return t.d; -} - -static void -check_fpeq(const char *name, fpr a, double ax) -{ - uint64_t au; - - au = double_to_u64(ax); - if (a != au) { - fprintf(stderr, "ERR (%s):\n", name); - fprintf(stderr, " %20llu %.20f\n", - (unsigned long long)a, u64_to_double(a)); - fprintf(stderr, " %20llu %.20f\n", - (unsigned long long)au, ax); - exit(EXIT_FAILURE); - } -} - -static void -check_fpeq1(const char *name, fpr a, fpr c, double cx) -{ - uint64_t cu; - - cu = double_to_u64(cx); - if (c != cu) { - fprintf(stderr, "ERR (%s):\n", name); - fprintf(stderr, " a = %20llu %.20f\n", - (unsigned long long)a, u64_to_double(a)); - fprintf(stderr, " c = %20llu %.20f\n", - (unsigned long long)c, u64_to_double(c)); - fprintf(stderr, " x = %20llu %.20f\n", - (unsigned long long)cu, cx); - exit(EXIT_FAILURE); - } -} - -static void -check_fpeq2(const char *name, fpr a, fpr b, fpr c, double cx) -{ - uint64_t cu; - - cu = double_to_u64(cx); - if (c != cu) { - fprintf(stderr, "ERR (%s):\n", name); - fprintf(stderr, " a = %20llu %.20f\n", - (unsigned long long)a, u64_to_double(a)); - fprintf(stderr, " b = %20llu %.20f\n", - (unsigned long long)b, u64_to_double(b)); - fprintf(stderr, " c = %20llu %.20f\n", - (unsigned long long)c, u64_to_double(c)); - fprintf(stderr, " x = %20llu %.20f\n", - (unsigned long long)cu, cx); - exit(EXIT_FAILURE); - } -} - -static void -test_FP_detailed(void) -{ - long ctr; - inner_shake256_context rng; - prng p; - int e; - fpr nzero; - - printf("Test floating-point (detailed): "); - fflush(stdout); - - check_fpeq("fpr_of(0)", fpr_of(0), 0.0); - check_fpeq1("fpr_neg(0)", fpr_zero, fpr_neg(fpr_zero), -0.0); - check_fpeq1("fpr_half(0)", fpr_zero, fpr_half(fpr_zero), 0.0); - check_fpeq1("fpr_double(0)", fpr_zero, fpr_double(fpr_zero), 0.0); - - nzero = fpr_neg(fpr_zero); - check_fpeq("fpr_add(+0,+0)", fpr_add(fpr_zero, fpr_zero), 0.0 + 0.0); - check_fpeq("fpr_add(+0,-0)", fpr_add(fpr_zero, nzero), 0.0 + (-0.0)); - check_fpeq("fpr_add(-0,+0)", fpr_add(nzero, fpr_zero), (-0.0) + 0.0); - check_fpeq("fpr_add(-0,-0)", fpr_add(nzero, nzero), (-0.0) + (-0.0)); - check_fpeq("fpr_sub(+0,+0)", fpr_add(fpr_zero, fpr_zero), 0.0 + 0.0); - check_fpeq("fpr_sub(+0,-0)", fpr_add(fpr_zero, nzero), 0.0 + (-0.0)); - check_fpeq("fpr_sub(-0,+0)", fpr_add(nzero, fpr_zero), (-0.0) + 0.0); - check_fpeq("fpr_sub(-0,-0)", fpr_add(nzero, nzero), (-0.0) + (-0.0)); - - for (e = -60; e <= +60; e ++) { - fpr a, b; - double ax, bx; - int i, j; - - for (i = -5; i <= +5; i ++) { - a = fpr_of(((int64_t)1 << 53) + i); - ax = ldexp(1.0, 53) + (double)i; - check_fpeq("fpr_of+", a, ax); - for (j = -5; j <= +5; j ++) { - b = fpr_scaled(((int64_t)1 << 53) + j, e); - bx = ldexp(ldexp(1.0, 53) + (double)j, e); - check_fpeq("fpr_scaled+", b, bx); - - check_fpeq2("fpr_add1+", - a, b, fpr_add(a, b), ax + bx); - a = fpr_neg(a); - check_fpeq2("fpr_add2+", - a, b, fpr_add(a, b), bx - ax); - b = fpr_neg(b); - check_fpeq2("fpr_add3+", - a, b, fpr_add(a, b), -bx - ax); - a = fpr_neg(a); - check_fpeq2("fpr_add4+", - a, b, fpr_add(a, b), ax - bx); - } - } - printf("."); - fflush(stdout); - } - printf(" "); - fflush(stdout); - - inner_shake256_init(&rng); - inner_shake256_inject(&rng, (const uint8_t *)"fpemu", 5); - inner_shake256_flip(&rng); - Zf(prng_init)(&p, &rng); - for (ctr = 1; ctr <= 65536L; ctr ++) { - fpr a, b; - double ax, bx; - int64_t j; - int sc; - - *(uint64_t *)&j = prng_get_u64(&p); - j >>= (int)(ctr & 63); - a = fpr_of(j); - ax = (double)j; - check_fpeq("fpr_of", a, ax); - - sc = prng_get_u8(&p); - sc -= 128; - a = fpr_scaled(j, sc); - ax = ldexp((double)j, sc); - check_fpeq("fpr_scaled", a, ax); - - *(uint64_t *)&j = prng_get_u64(&p); - a = fpr_scaled(j, -8); - ax = ldexp((double)j, -8); - if (fpr_rint(a) != llrint(ax)) { - fprintf(stderr, - "ERR (fpr_rint): %.7f -> %lld / %lld\n", - ax, - (long long)fpr_rint(a), (long long)llrint(ax)); - exit(EXIT_FAILURE); - } - a = fpr_scaled(j, -52); - ax = ldexp((double)j, -52); - if (fpr_trunc(a) != (long)ax) { - fprintf(stderr, - "ERR (fpr_trunc): %.7f -> %ld / %ld\n", - ax, - (long)fpr_trunc(a), (long)ax); - exit(EXIT_FAILURE); - } - - a = rand_fp(&p); - b = rand_fp(&p); - ax = u64_to_double(a); - bx = u64_to_double(b); - - for (sc = -60; sc <= 60; sc ++) { - check_fpeq1("fpr_ldexp", a, - fpr_ldexp(a, sc), ldexp(ax, sc)); - } - - if (fpr_lt(a, b) != (ax < bx)) { - fprintf(stderr, - "ERR (fpr_lt): %.7f / %.7f\n", - u64_to_double(ax), u64_to_double(bx)); - exit(EXIT_FAILURE); - } - if (fpr_lt(a, a) != 0) { - fprintf(stderr, - "ERR (fpr_lt): %.7f / (self)\n", - u64_to_double(ax)); - exit(EXIT_FAILURE); - } - - check_fpeq2("fpr_add 1", a, b, fpr_add(a, b), ax + bx); - check_fpeq2("fpr_add 2", b, a, fpr_add(b, a), bx + ax); - check_fpeq2("fpr_add 3", a, fpr_zero, - fpr_add(a, fpr_zero), ax + 0.0); - check_fpeq2("fpr_add 4", fpr_zero, a, - fpr_add(fpr_zero, a), 0.0 + ax); - check_fpeq1("fpr_add 5", a, fpr_add(a, fpr_neg(a)), ax + (-ax)); - check_fpeq1("fpr_add 6", a, fpr_add(fpr_neg(a), a), (-ax) + ax); - - check_fpeq2("fpr_sub 1", a, b, fpr_sub(a, b), ax - bx); - check_fpeq2("fpr_sub 2", b, a, fpr_sub(b, a), bx - ax); - check_fpeq2("fpr_sub 3", a, fpr_zero, - fpr_sub(a, fpr_zero), ax - 0.0); - check_fpeq2("fpr_sub 4", fpr_zero, a, - fpr_sub(fpr_zero, a), 0.0 - ax); - check_fpeq("fpr_sub 5", fpr_sub(a, a), ax - ax); - - check_fpeq1("fpr_neg", a, fpr_neg(a), -ax); - check_fpeq1("fpr_half", a, fpr_half(a), ax * 0.5); - check_fpeq1("fpr_double", a, fpr_double(a), ax * 2.0); - - check_fpeq2("fpr_mul 1", a, b, fpr_mul(a, b), ax * bx); - check_fpeq2("fpr_mul 2", a, b, fpr_mul(b, a), bx * ax); - check_fpeq2("fpr_mul 3", a, fpr_zero, - fpr_mul(a, fpr_zero), ax * 0.0); - check_fpeq2("fpr_mul 4", fpr_zero, a, - fpr_mul(fpr_zero, a), 0.0 * ax); - - if (bx != 0.0) { - check_fpeq2("fpr_div", a, b, fpr_div(a, b), ax / bx); - } - if (fpr_lt(a, fpr_zero)) { - a = fpr_neg(a); - } - check_fpeq1("fpr_sqrt", a, fpr_sqrt(a), sqrt(fabs(ax))); - - if ((ctr & 0x3FF) == 0) { - printf("."); - fflush(stdout); - } - } - - printf(" done.\n"); - fflush(stdout); -} - -#endif - -/* - * Make a polynomial with random coefficients in -512..511 (uniform). - */ -static void -mk_rand_poly(prng *p, fpr *f, unsigned logn) -{ - size_t u, n; - - n = (size_t)1 << logn; - for (u = 0; u < n; u ++) { - int32_t x; - - x = prng_get_u8(p); - x = (x << 8) + prng_get_u8(p); - x &= 0x3FF; - f[u] = fpr_of(x - 512); - } -} - -static void -test_poly_inner(unsigned logn, uint8_t *tmp, size_t tlen) -{ - unsigned long ctr, num; - inner_shake256_context rng; - prng p; - uint8_t xb; - size_t n; - - printf("[%u]", logn); - fflush(stdout); - - n = (size_t)1 << logn; - if (tlen < 5 * n * sizeof(fpr)) { - fprintf(stderr, "Insufficient buffer size\n"); - exit(EXIT_FAILURE); - } - inner_shake256_init(&rng); - xb = logn; - inner_shake256_inject(&rng, &xb, 1); - inner_shake256_flip(&rng); - Zf(prng_init)(&p, &rng); - num = 131072UL >> logn; - for (ctr = 0; ctr < num; ctr ++) { - fpr *f, *g, *h; - fpr *f0, *f1, *g0, *g1; - size_t u; - - f = (fpr *)tmp; - g = f + n; - h = g + n; - f0 = h + n; - f1 = f0 + (n >> 1); - g0 = f1 + (n >> 1); - g1 = g0 + (n >> 1); - mk_rand_poly(&p, f, logn); - memcpy(g, f, n * sizeof *f); - Zf(FFT)(g, logn); - Zf(iFFT)(g, logn); - for (u = 0; u < n; u ++) { - if (fpr_rint(f[u]) != fpr_rint(g[u])) { - fprintf(stderr, "FFT/iFFT error\n"); - exit(EXIT_FAILURE); - } - } - - mk_rand_poly(&p, g, logn); - for (u = 0; u < n; u ++) { - h[u] = fpr_of(0); - } - for (u = 0; u < n; u ++) { - size_t v; - - for (v = 0; v < n; v ++) { - fpr s; - size_t k; - - s = fpr_mul(f[u], g[v]); - k = u + v; - if (k >= n) { - k -= n; - s = fpr_neg(s); - } - h[k] = fpr_add(h[k], s); - } - } - Zf(FFT)(f, logn); - Zf(FFT)(g, logn); - Zf(poly_mul_fft)(f, g, logn); - Zf(iFFT)(f, logn); - for (u = 0; u < n; u ++) { - if (fpr_rint(f[u]) != fpr_rint(h[u])) { - fprintf(stderr, "FFT mul error\n"); - exit(EXIT_FAILURE); - } - } - - mk_rand_poly(&p, f, logn); - memcpy(h, f, n * sizeof *f); - Zf(FFT)(f, logn); - Zf(poly_split_fft)(f0, f1, f, logn); - - memcpy(g0, f0, (n >> 1) * sizeof *f0); - memcpy(g1, f1, (n >> 1) * sizeof *f1); - Zf(iFFT)(g0, logn - 1); - Zf(iFFT)(g1, logn - 1); - for (u = 0; u < (n >> 1); u ++) { - if (fpr_rint(g0[u]) != fpr_rint(h[(u << 1) + 0]) - || fpr_rint(g1[u]) != fpr_rint(h[(u << 1) + 1])) - { - fprintf(stderr, "split error\n"); - exit(EXIT_FAILURE); - } - } - - Zf(poly_merge_fft)(g, f0, f1, logn); - Zf(iFFT)(g, logn); - for (u = 0; u < n; u ++) { - if (fpr_rint(g[u]) != fpr_rint(h[u])) { - fprintf(stderr, "split/merge error\n"); - exit(EXIT_FAILURE); - } - } - - if (((ctr + 1) & 0xFF) == 0) { - printf("."); - fflush(stdout); - } - } -} - -static void -test_poly(void) -{ - unsigned logn; - uint8_t *tmp; - size_t tlen; - - printf("Test polynomials: "); - fflush(stdout); - tlen = 40960; - tmp = xmalloc(tlen); - for (logn = 1; logn <= 10; logn ++) { - test_poly_inner(logn, tmp, tlen); - } - xfree(tmp); - printf(" done.\n"); - fflush(stdout); -} - -typedef struct { - uint8_t v[9]; -} u72; - -static void -u72_set_zero(u72 *x) -{ - memset(x->v, 0, sizeof x->v); -} - -static unsigned -u72_add_small(u72 *x, unsigned d) -{ - size_t u; - - for (u = 0; u < sizeof x->v; u ++) { - unsigned w; - - w = x->v[u] + d; - x->v[u] = (w & 0xFF); - d = w >> 8; - } - return d; -} - -static unsigned -u72_add(u72 *x, const u72 *y) -{ - size_t u; - unsigned cc; - - cc = 0; - for (u = 0; u < sizeof x->v; u ++) { - unsigned w; - - w = x->v[u] + y->v[u] + cc; - x->v[u] = (w & 0xFF); - cc = w >> 8; - } - return cc; -} - -static void -u72_from_decimal(u72 *x, const char *str) -{ - u72_set_zero(x); - while (*str != 0) { - size_t u; - unsigned cc; - - cc = 0; - for (u = 0; u < sizeof x->v; u ++) { - unsigned w; - - w = (x->v[u] * 10) + cc; - x->v[u] = w & 0xFF; - cc = w >> 8; - } - u72_add_small(x, (*str ++) - '0'); - } -} - -/* - * Expected probability distribution, as specified in the - * Prest-Ricosset-Rossi paper: "Simple, Fast and Constant-Time Gaussian - * Sampling over the Integers for Falcon" - * - * The sum of these values is exactly 2^72. - * gaussian0_sampler() uses a CDT that splits the 0..2^72-1 range into - * ranges of the right size to achieve the relevant probabilities: - * P(18) = 1*2^(-72) -> 0 - * P(17) = 197*2^(-72) -> 1..197 - * P(16) = 28626*2^(-72) -> 198..28823 - * (etc) - */ -static const char *GAUSSIAN0_DIST[] = { - "1697680241746640300030", - "1459943456642912959616", - "928488355018011056515", - "436693944817054414619", - "151893140790369201013", - "39071441848292237840", - "7432604049020375675", - "1045641569992574730", - "108788995549429682", - "8370422445201343", - "476288472308334", - "20042553305308", - "623729532807", - "14354889437", - "244322621", - "3075302", - "28626", - "197", - "1" -}; - -static void -prefill_prng(prng *p, const void *buf, size_t len) -{ - memcpy(p->buf.d, buf, len); - p->ptr = 0; -} - -static void -check_gaussian0_sampler(const u72 *x, int r) -{ - prng p; - int z; - - prefill_prng(&p, x->v, sizeof x->v); - z = Zf(gaussian0_sampler)(&p); - if (z != r) { - size_t u; - - fprintf(stderr, - "wrong half-Gaussian output %d (exp: %d), val = 0x", - z, r); - for (u = sizeof x->v; u > 0; u --) { - fprintf(stderr, "%02X", x->v[u - 1]); - } - fprintf(stderr, "\n"); - exit(EXIT_FAILURE); - } -} - -static void -test_gaussian0_sampler(void) -{ - u72 t, s; - int i; - - printf("Test half-Gaussian sampler: "); - fflush(stdout); - - /* - * gaussian0_sampler() reads a 72-bit value from the PRNG, - * and follows a CDT table. Bottom value is 18; it should be - * obtained when the PRNG bytes are all zeros. - */ - u72_set_zero(&t); - check_gaussian0_sampler(&t, 18); - - /* - * Each iteration exercises the two extremes of the range: - * t+1, where t is the maximum of the previous range - * t+dist[i], where dist[i] is from the table in the source article - */ - for (i = 17; i >= 0; i --) { - s = t; - u72_add_small(&s, 1); - check_gaussian0_sampler(&s, i); - u72_from_decimal(&s, GAUSSIAN0_DIST[i]); - u72_add(&t, &s); - check_gaussian0_sampler(&t, i); - - printf("."); - fflush(stdout); - } - - /* - * At that point, t is the top value of the highest range; thus, - * it should be (2^72)-1. We check it by adding 1: this should - * yield a carry. - */ - if (u72_add_small(&t, 1) != 1) { - fprintf(stderr, "wrong distribution sum\n"); - exit(EXIT_FAILURE); - } - - printf(" done.\n"); - fflush(stdout); -} - -static fpr -make_fpr(int64_t m, int sc) -{ - fpr x; - - x = fpr_of(m); - if (sc > 0) { - while (sc -- > 0) { - x = fpr_double(x); - } - } else { - while (sc ++ < 0) { - x = fpr_half(x); - } - } - return x; -} - -/* - * Custom exponential computation. - * - * If |x| >= 512*log(2) then this function returns exactly 0 (this is - * meant to avoid subnormals or infinites, which are not necessarily - * supported by the underlying 'fpr' implementation). - */ -static fpr -approximate_exp(fpr x) -{ - /* - * We need a few constants, but we cannot make them actual - * constants since that depends on how the fpr type is implemented. - * Instead, we use a run-once block of code. - */ - static fpr RANGE_MIN, RANGE_MAX, P1, P2, P3, P4, P5; - static int init = 0; - - if (!init) { - RANGE_MIN = make_fpr(-6243314768165359, -54); - RANGE_MAX = make_fpr(6243314768165359, -54); - P1 = make_fpr(6004799503160638, -55); - P2 = make_fpr(-6405119469862291, -61); - P3 = make_fpr(4880090809097772, -66); - P4 = make_fpr(-7807914560613361, -72); - P5 = make_fpr(6253375523824848, -77); - init = 1; - } - - int k; - fpr t, c; - - /* - * First halve the value repeatedly until it is in the - * +/-0.5*log(2) range. - */ - k = 0; - for (;;) { - if (fpr_lt(RANGE_MIN, x) && fpr_lt(x, RANGE_MAX)) { - break; - } - x = fpr_half(x); - k ++; - } - if (k > 10) { - return fpr_zero; - } - - /* - * Apply the approximation function from fdlibm: - * http://www.netlib.org/fdlibm/e_exp.c - */ - t = fpr_sqr(x); - c = fpr_sub(x, fpr_mul(t, - fpr_add(P1, fpr_mul(t, - fpr_add(P2, fpr_mul(t, - fpr_add(P3, fpr_mul(t, - fpr_add(P4, fpr_mul(t, P5)))))))))); - x = fpr_sub(fpr_one, fpr_sub( - fpr_div(fpr_mul(x, c), fpr_sub(c, fpr_two)), x)); - - /* - * Square repeatedly to cancel the initial halvings. - */ - while (k -- > 0) { - x = fpr_sqr(x); - } - return x; -} - -/* - * For given center mu, and isigma = 1/sigma (where sigma is the standard - * deviation of the distribution for sampling), run the sampler many - * times, and use a chi square test to compare the result with the - * expected distribution. - */ -static void -test_sampler_rand(sampler_context *sc, fpr mu, fpr isigma) -{ -#define MAX_DEV 30 -#define NUM_SAMPLES 100000 - - static fpr chi_dt_13, chi_dt_14; - static int init = 0; - - int z, zmin, zmax, df; - long ctr, szlo, szhi; - long zz[1 + (MAX_DEV << 1)]; - fpr rzz[1 + (MAX_DEV << 1)]; - int c; - fpr s, chi, elo, ehi; - - /* - * One-time initialization code to have the chi-square critical - * values for 13 and 14 degrees of freedom. We use alpha = 0.01. - * - * Indeed, when the chi-square test statistic is above the - * critical value, then this means that, under the null - * hypothesis (i.e. the hypothesis that the sampler really - * follows the expected distribution), what we obtained could - * have occurred with probability less than alpha. The null - * hypothesis is said to be rejected when that probability is - * "too low". The traditional significance level is alpha = - * 0.05, which means that events which happen less than 1/20th - * of the time are deemed "too improbable". But we are going - * to call this test_sampler_rand() function more than 20 times, - * thus events that occur with probability 1/20 will really - * happen. Using alpha = 0.01 appears to let our tests pass. - */ - if (!init) { - chi_dt_13 = make_fpr(7794042105118065, -48); /* 27.69 */ - chi_dt_14 = make_fpr(8202180821348516, -48); /* 29.14 */ - init = 1; - } - - /* - * We call the sampler 100000 times and check that each value is - * within +/-30 of the center. We also accumulate the values. - */ - c = (int)fpr_trunc(mu); - for (z = -MAX_DEV; z <= +MAX_DEV; z ++) { - zz[z + MAX_DEV] = 0; - } - for (ctr = 0; ctr < NUM_SAMPLES; ctr ++) { - z = Zf(sampler)(sc, mu, isigma); - z -= c; - if (z < -MAX_DEV || z > +MAX_DEV) { - fprintf(stderr, "out-of-range sampled value: %d\n", z); - exit(EXIT_FAILURE); - } - zz[z + MAX_DEV] ++; - } - - /* - * Distribution should have approximately the right shape. With - * only 100000 samples, we cannot detect small deviations, but we - * can still check that the overall shape is proper. Expected - * distribution is: - * - * P(z) = K*exp(-((z-mu)^2 / 2*(sigma^2))) - * - * where K is a constant such that the sum over all integers z - * is 1. - * - * We compute into rzz[] the expected number of outcomes (for - * the used total number of samples). - */ - s = fpr_zero; - for (z = -MAX_DEV; z <= +MAX_DEV; z ++) { - fpr x; - - x = fpr_sqr(fpr_sub(fpr_of(z + c), mu)); - x = fpr_mul(x, fpr_sqr(isigma)); - x = fpr_neg(fpr_half(x)); - rzz[z + MAX_DEV] = approximate_exp(x); - s = fpr_add(rzz[z + MAX_DEV], s); - } - s = fpr_div(fpr_of(NUM_SAMPLES), s); - for (z = -MAX_DEV; z <= +MAX_DEV; z ++) { - rzz[z + MAX_DEV] = fpr_mul(rzz[z + MAX_DEV], s); - } - - /* - * Now that we have the expected distribution, we can compute a - * simple chi-square test over what we actually obtained. - * - * For better test accuracy, we group the two tails of the - * distribution into two 'bins': one for z <= zmin, the other - * for z >= zmax. Values zmin and zmax are set so that the - * expected number of samples in each bin is at least 5. - */ - elo = fpr_zero; - for (zmin = -MAX_DEV;; zmin ++) { - elo = fpr_add(elo, rzz[zmin + MAX_DEV]); - if (!fpr_lt(elo, fpr_of(5))) { - break; - } - } - ehi = fpr_zero; - for (zmax = +MAX_DEV;; zmax --) { - ehi = fpr_add(ehi, rzz[zmax + MAX_DEV]); - if (!fpr_lt(ehi, fpr_of(5))) { - break; - } - } - - szlo = 0; - for (z = -MAX_DEV; z <= zmin; z ++) { - szlo += zz[z + MAX_DEV]; - } - szhi = 0; - for (z = zmax; z <= +MAX_DEV; z ++) { - szhi += zz[z + MAX_DEV]; - } - chi = fpr_zero; - for (z = zmin + 1; z <= zmax - 1; z ++) { - fpr x, e; - - x = fpr_of(zz[z + MAX_DEV]); - e = rzz[z + MAX_DEV]; - chi = fpr_add(chi, fpr_div(fpr_sqr(fpr_sub(x, e)), e)); - } - - chi = fpr_add(chi, fpr_div(fpr_sqr(fpr_sub(fpr_of(szlo), elo)), elo)); - chi = fpr_add(chi, fpr_div(fpr_sqr(fpr_sub(fpr_of(szhi), ehi)), ehi)); - - /* - * In practice, (zmin,zmax) = (-6,7) or (-7,7), i.e. we have either - * 14 or 15 classes. The number of degrees of freedom is then 13 - * or 14. - */ - df = zmax - zmin; - if (df == 13) { - if (!fpr_lt(chi, chi_dt_13)) { - fprintf(stderr, "chi-square test fail\n"); - exit(EXIT_FAILURE); - } - } else if (df == 14) { - if (!fpr_lt(chi, chi_dt_14)) { - fprintf(stderr, "chi-square test fail\n"); - exit(EXIT_FAILURE); - } - } else { - fprintf(stderr, "unexpected number of classes: %d\n", - zmax - zmin + 1); - exit(EXIT_FAILURE); - } - -#undef MAX_DEV -#undef NUM_SAMPLES -} - -static void -test_sampler(void) -{ - inner_shake256_context rng; - sampler_context sc; - fpr isigma, mu, muinc; - int i; - - printf("Test sampler: "); - fflush(stdout); - - inner_shake256_init(&rng); - inner_shake256_inject(&rng, (const void *)"test sampler", 12); - inner_shake256_flip(&rng); - Zf(prng_init)(&sc.p, &rng); - sc.sigma_min = fpr_sigma_min[9]; - - isigma = fpr_div(fpr_of(10), fpr_of(17)); - mu = fpr_neg(fpr_one); - muinc = fpr_div(fpr_one, fpr_of(10)); - for (i = 0; i < 21; i ++) { - test_sampler_rand(&sc, mu, isigma); - mu = fpr_add(mu, muinc); - - printf("."); - fflush(stdout); - } - - printf(" done.\n"); - fflush(stdout); -} - -static void -test_sign_self(const int8_t *f, const int8_t *g, - const int8_t *F, const int8_t *G, const uint16_t *h_src, - unsigned logn, uint8_t *tmp) -{ - int i; - size_t n; - inner_shake256_context rng; - char buf[20]; - uint16_t *h, *hm, *hm2; - int16_t *sig; - uint8_t *tt; - fpr *expanded_key; - - n = (size_t)1 << logn; - h = (uint16_t *)tmp; - hm = h + n; - sig = (int16_t *)(hm + n); - hm2 = (uint16_t *)sig; - tt = (uint8_t *)(sig + n); - if (logn == 1) { - tt += 4; - } - - memcpy(h, h_src, n * sizeof *h); - Zf(to_ntt_monty)(h, logn); - - /* sprintf(buf, "sign %u", logn); */ - memcpy(buf, "sign 0", 7); - buf[5] = '0' + logn; - - inner_shake256_init(&rng); - inner_shake256_inject(&rng, (uint8_t *)buf, strlen(buf)); - inner_shake256_flip(&rng); - for (i = 0; i < 100; i ++) { - uint8_t msg[50]; /* nonce + plain */ - inner_shake256_context sc, sc2; - size_t u; - - inner_shake256_extract(&rng, msg, sizeof msg); - - inner_shake256_init(&sc); - inner_shake256_inject(&sc, msg, sizeof msg); - inner_shake256_flip(&sc); - sc2 = sc; - Zf(hash_to_point_vartime)(&sc, hm, logn); - Zf(hash_to_point_ct)(&sc2, hm2, logn, tt); - for (u = 0; u < n; u ++) { - if (hm2[u] != hm[u]) { - fprintf(stderr, "hash_to_point() mismatch\n"); - exit(EXIT_FAILURE); - } - } - Zf(sign_dyn)(sig, &rng, f, g, F, G, hm, logn, tt); - if (!Zf(verify_raw)(hm, sig, h, logn, tt)) { - fprintf(stderr, "self signature (dyn) not verified\n"); - exit(EXIT_FAILURE); - } - - if (i % 10 == 0) { - printf("."); - fflush(stdout); - } - } - - expanded_key = (fpr *)tt; - tt = (uint8_t *)expanded_key + (8 * logn + 40) * n; - Zf(expand_privkey)(expanded_key, f, g, F, G, logn, tt); - - for (i = 0; i < 100; i ++) { - uint8_t msg[50]; /* nonce + plain */ - inner_shake256_context sc; - - inner_shake256_extract(&rng, msg, sizeof msg); - - inner_shake256_init(&sc); - inner_shake256_inject(&sc, msg, sizeof msg); - inner_shake256_flip(&sc); - Zf(hash_to_point_vartime)(&sc, hm, logn); - Zf(sign_tree)(sig, &rng, expanded_key, hm, logn, tt); - - if (!Zf(verify_raw)(hm, sig, h, logn, tt)) { - fprintf(stderr, "self signature (dyn) not verified\n"); - exit(EXIT_FAILURE); - } - - if (i % 10 == 0) { - printf("."); - fflush(stdout); - } - } - - printf(" "); - fflush(stdout); -} - -static void -test_sign(void) -{ - uint8_t *tmp; - size_t tlen; - - printf("Test sign: "); - fflush(stdout); - - tlen = 178176; - tmp = xmalloc(tlen); - - test_sign_self(ntru_f_16, ntru_g_16, ntru_F_16, ntru_G_16, - ntru_h_16, 4, tmp); - test_sign_self(ntru_f_512, ntru_g_512, ntru_F_512, ntru_G_512, - ntru_h_512, 9, tmp); - test_sign_self(ntru_f_1024, ntru_g_1024, ntru_F_1024, ntru_G_1024, - ntru_h_1024, 10, tmp); - - xfree(tmp); - - printf("done.\n"); - fflush(stdout); -} - -static void -test_keygen_inner(unsigned logn, uint8_t *tmp) -{ - size_t n; - int8_t *f, *g, *F, *G; - uint16_t *h, *hm, *h2; - int16_t *sig, *s1; - uint8_t *tt; - int i; - inner_shake256_context rng; - char buf[20]; - - printf("[%u]", logn); - fflush(stdout); - - /* sprintf(buf, "keygen %u", logn); */ - memcpy(buf, "keygen 0", 9); - buf[7] = '0' + logn; - - inner_shake256_init(&rng); - inner_shake256_inject(&rng, (uint8_t *)buf, strlen(buf)); - inner_shake256_flip(&rng); - n = (size_t)1 << logn; - f = (int8_t *)tmp; - g = f + n; - F = g + n; - G = F + n; - h = (uint16_t *)(G + n); - h2 = h + n; - hm = h2 + n; - sig = (int16_t *)(hm + n); - s1 = sig + n; - tt = (uint8_t *)(s1 + n); - if (logn == 1) { - tt += 4; - } - for (i = 0; i < 12; i ++) { - uint8_t msg[50]; /* nonce + message */ - inner_shake256_context sc; - - Zf(keygen)(&rng, f, g, F, G, h, logn, tt); - - inner_shake256_extract(&rng, msg, sizeof msg); - - inner_shake256_init(&sc); - inner_shake256_inject(&sc, msg, sizeof msg); - inner_shake256_flip(&sc); - Zf(hash_to_point_vartime)(&sc, hm, logn); - do { - Zf(sign_dyn)(sig, &rng, f, g, F, G, hm, logn, tt); - memcpy(s1, tt, n * sizeof *s1); - } while (!Zf(is_invertible)(sig, logn, tt)); - Zf(to_ntt_monty)(h, logn); - if (!Zf(verify_raw)(hm, sig, h, logn, tt)) { - fprintf(stderr, "self signature not verified\n"); - exit(EXIT_FAILURE); - } - if (!Zf(verify_recover)(h2, hm, s1, sig, logn, tt)) { - fprintf(stderr, "self signature recovery failed\n"); - exit(EXIT_FAILURE); - } - Zf(to_ntt_monty)(h2, logn); - check_eq(h, h2, n * sizeof *h, "recovered public key"); - - printf("."); - fflush(stdout); - } -} - -static void -test_keygen(void) -{ - uint8_t *tmp; - size_t tlen; - unsigned logn; - - printf("Test keygen: "); - fflush(stdout); - tlen = 90112; - tmp = xmalloc(tlen); - for (logn = 1; logn <= 10; logn ++) { - test_keygen_inner(logn, tmp); - } - xfree(tmp); - printf("done.\n"); - fflush(stdout); -} - -static void -test_external_API_inner(unsigned logn, shake256_context *rng) -{ - int i; - void *pubkey, *pubkey2, *privkey, *sig, *sigpad, *sigct, *expkey; - size_t pubkey_len, privkey_len, sig_len, sigpad_len, sigct_len; - size_t expkey_len; - uint8_t *tmpkg, *tmpmp, *tmpsd, *tmpst, *tmpvv, *tmpek; - size_t tmpkg_len, tmpmp_len, tmpsd_len, tmpst_len, tmpvv_len, tmpek_len; - - printf("[%u]", logn); - fflush(stdout); - - pubkey_len = FALCON_PUBKEY_SIZE(logn); - privkey_len = FALCON_PRIVKEY_SIZE(logn); - sig_len = FALCON_SIG_COMPRESSED_MAXSIZE(logn); - sigpad_len = FALCON_SIG_PADDED_SIZE(logn); - sigct_len = FALCON_SIG_CT_SIZE(logn); - expkey_len = FALCON_EXPANDEDKEY_SIZE(logn); - - pubkey = xmalloc(pubkey_len); - pubkey2 = xmalloc(pubkey_len); - privkey = xmalloc(privkey_len); - sig = xmalloc(sig_len); - sigpad = xmalloc(sig_len); - sigct = xmalloc(sigct_len); - expkey = xmalloc(expkey_len); - - tmpkg_len = FALCON_TMPSIZE_KEYGEN(logn); - tmpmp_len = FALCON_TMPSIZE_MAKEPUB(logn); - tmpsd_len = FALCON_TMPSIZE_SIGNDYN(logn); - tmpst_len = FALCON_TMPSIZE_SIGNTREE(logn); - tmpvv_len = FALCON_TMPSIZE_VERIFY(logn); - tmpek_len = FALCON_TMPSIZE_EXPANDPRIV(logn); - - tmpkg = xmalloc(tmpkg_len); - tmpmp = xmalloc(tmpmp_len); - tmpsd = xmalloc(tmpsd_len); - tmpst = xmalloc(tmpst_len); - tmpvv = xmalloc(tmpvv_len); - tmpek = xmalloc(tmpek_len); - - for (i = 0; i < 12; i ++) { - int r; - - memset(privkey, 0, privkey_len); - memset(pubkey, 0, pubkey_len); - r = falcon_keygen_make(rng, logn, privkey, privkey_len, - pubkey, pubkey_len, tmpkg, tmpkg_len); - if (r != 0) { - fprintf(stderr, "keygen failed: %d\n", r); - exit(EXIT_FAILURE); - } - memset(pubkey2, 0xFF, pubkey_len); - r = falcon_make_public(pubkey2, pubkey_len, - privkey, privkey_len, tmpmp, tmpmp_len); - if (r != 0) { - fprintf(stderr, "makepub failed: %d\n", r); - exit(EXIT_FAILURE); - } - check_eq(pubkey, pubkey2, pubkey_len, "pub / repub"); - - r = falcon_get_logn(pubkey, pubkey_len); - if (r != (int)logn) { - fprintf(stderr, "get_logn failed: %d\n", r); - exit(EXIT_FAILURE); - } - - sig_len = FALCON_SIG_COMPRESSED_MAXSIZE(logn); - memset(sig, 0, sig_len); - r = falcon_sign_dyn(rng, sig, &sig_len, FALCON_SIG_COMPRESSED, - privkey, privkey_len, - "data1", 5, tmpsd, tmpsd_len); - if (r != 0) { - fprintf(stderr, "sign_dyn failed: %d\n", r); - exit(EXIT_FAILURE); - } - r = falcon_verify(sig, sig_len, FALCON_SIG_COMPRESSED, - pubkey, pubkey_len, "data1", 5, tmpvv, tmpvv_len); - if (r != 0) { - fprintf(stderr, "verify failed: %d\n", r); - exit(EXIT_FAILURE); - } - if (logn >= 5) { - /* - * At very low degrees, it may happen that the - * alternate data hashes to a point which is close - * enough to the correct one that the signature - * matches both. Thus, we skip that check for very - * low degrees. - */ - r = falcon_verify(sig, sig_len, FALCON_SIG_COMPRESSED, - pubkey, pubkey_len, "data2", 5, - tmpvv, tmpvv_len); - if (r != FALCON_ERR_BADSIG) { - fprintf(stderr, "wrong verify err: %d\n", r); - exit(EXIT_FAILURE); - } - } - - sigpad_len = FALCON_SIG_PADDED_SIZE(logn); - memset(sigpad, 0, sigpad_len); - r = falcon_sign_dyn(rng, sigpad, &sigpad_len, FALCON_SIG_PADDED, - privkey, privkey_len, - "data1", 5, tmpsd, tmpsd_len); - if (r != 0) { - fprintf(stderr, "sign_dyn(padded) failed: %d\n", r); - exit(EXIT_FAILURE); - } - if (sigpad_len != FALCON_SIG_PADDED_SIZE(logn)) { - fprintf(stderr, "sign_dyn(padded): wrong length %lu\n", - (unsigned long)sigpad_len); - exit(EXIT_FAILURE); - } - r = falcon_verify(sigpad, sigpad_len, FALCON_SIG_PADDED, - pubkey, pubkey_len, "data1", 5, tmpvv, tmpvv_len); - if (r != 0) { - fprintf(stderr, "verify(padded) failed: %d\n", r); - exit(EXIT_FAILURE); - } - if (logn >= 5) { - r = falcon_verify(sigpad, sigpad_len, FALCON_SIG_PADDED, - pubkey, pubkey_len, "data2", 5, - tmpvv, tmpvv_len); - if (r != FALCON_ERR_BADSIG) { - fprintf(stderr, - "wrong verify(padded) err: %d\n", r); - exit(EXIT_FAILURE); - } - } - - sigct_len = FALCON_SIG_CT_SIZE(logn); - memset(sigct, 0, sigct_len); - r = falcon_sign_dyn(rng, sigct, &sigct_len, FALCON_SIG_CT, - privkey, privkey_len, - "data1", 5, tmpsd, tmpsd_len); - if (r != 0) { - fprintf(stderr, "sign_dyn(ct) failed: %d\n", r); - exit(EXIT_FAILURE); - } - if (sigct_len != FALCON_SIG_CT_SIZE(logn)) { - fprintf(stderr, "sign_dyn(ct): wrong length %lu\n", - (unsigned long)sigct_len); - exit(EXIT_FAILURE); - } - r = falcon_verify(sigct, sigct_len, FALCON_SIG_CT, - pubkey, pubkey_len, "data1", 5, tmpvv, tmpvv_len); - if (r != 0) { - fprintf(stderr, "verify(ct) failed: %d\n", r); - exit(EXIT_FAILURE); - } - if (logn >= 5) { - r = falcon_verify(sigct, sigct_len, FALCON_SIG_CT, - pubkey, pubkey_len, "data2", 5, - tmpvv, tmpvv_len); - if (r != FALCON_ERR_BADSIG) { - fprintf(stderr, - "wrong verify(ct) err: %d\n", r); - exit(EXIT_FAILURE); - } - } - - r = falcon_expand_privkey(expkey, expkey_len, - privkey, privkey_len, tmpek, tmpek_len); - if (r != 0) { - fprintf(stderr, "expand_privkey failed: %d\n", r); - exit(EXIT_FAILURE); - } - - sig_len = FALCON_SIG_COMPRESSED_MAXSIZE(logn); - memset(sig, 0, sig_len); - r = falcon_sign_tree(rng, sig, &sig_len, FALCON_SIG_COMPRESSED, - expkey, - "data1", 5, tmpst, tmpst_len); - if (r != 0) { - fprintf(stderr, "sign_tree failed: %d\n", r); - exit(EXIT_FAILURE); - } - r = falcon_verify(sig, sig_len, FALCON_SIG_COMPRESSED, - pubkey, pubkey_len, "data1", 5, tmpvv, tmpvv_len); - if (r != 0) { - fprintf(stderr, "verify2 failed: %d\n", r); - exit(EXIT_FAILURE); - } - if (logn >= 5) { - r = falcon_verify(sig, sig_len, FALCON_SIG_COMPRESSED, - pubkey, pubkey_len, "data2", 5, - tmpvv, tmpvv_len); - if (r != FALCON_ERR_BADSIG) { - fprintf(stderr, "wrong verify2 err: %d\n", r); - exit(EXIT_FAILURE); - } - } - - sigpad_len = FALCON_SIG_PADDED_SIZE(logn); - memset(sigpad, 0, sigpad_len); - r = falcon_sign_tree(rng, sigpad, &sigpad_len, - FALCON_SIG_PADDED, - expkey, - "data1", 5, tmpst, tmpst_len); - if (r != 0) { - fprintf(stderr, "sign_tree(padded) failed: %d\n", r); - exit(EXIT_FAILURE); - } - r = falcon_verify(sigpad, sigpad_len, FALCON_SIG_PADDED, - pubkey, pubkey_len, "data1", 5, tmpvv, tmpvv_len); - if (r != 0) { - fprintf(stderr, "verify2(padded) failed: %d\n", r); - exit(EXIT_FAILURE); - } - if (logn >= 5) { - r = falcon_verify(sigpad, sigpad_len, FALCON_SIG_PADDED, - pubkey, pubkey_len, "data2", 5, - tmpvv, tmpvv_len); - if (r != FALCON_ERR_BADSIG) { - fprintf(stderr, - "wrong verify2(padded) err: %d\n", r); - exit(EXIT_FAILURE); - } - } - - sigct_len = FALCON_SIG_CT_SIZE(logn); - memset(sigct, 0, sigct_len); - r = falcon_sign_tree(rng, sigct, &sigct_len, FALCON_SIG_CT, - expkey, - "data1", 5, tmpst, tmpst_len); - if (r != 0) { - fprintf(stderr, "sign_tree(ct) failed: %d\n", r); - exit(EXIT_FAILURE); - } - r = falcon_verify(sigct, sigct_len, FALCON_SIG_CT, - pubkey, pubkey_len, "data1", 5, tmpvv, tmpvv_len); - if (r != 0) { - fprintf(stderr, "verify2(ct) failed: %d\n", r); - exit(EXIT_FAILURE); - } - if (logn >= 5) { - r = falcon_verify(sigct, sigct_len, FALCON_SIG_CT, - pubkey, pubkey_len, "data2", 5, - tmpvv, tmpvv_len); - if (r != FALCON_ERR_BADSIG) { - fprintf(stderr, - "wrong verify2(ct) err: %d\n", r); - exit(EXIT_FAILURE); - } - } - - printf("."); - fflush(stdout); - } - - xfree(pubkey); - xfree(pubkey2); - xfree(privkey); - xfree(sig); - xfree(sigpad); - xfree(sigct); - xfree(expkey); - xfree(tmpkg); - xfree(tmpmp); - xfree(tmpsd); - xfree(tmpst); - xfree(tmpvv); - xfree(tmpek); -} - -static void -test_external_API(void) -{ - unsigned logn; - shake256_context rng; - - printf("Test external API: "); - fflush(stdout); - - shake256_init_prng_from_seed(&rng, "external", 8); - for (logn = 1; logn <= 10; logn ++) { - test_external_API_inner(logn, &rng); - } - - printf("done.\n"); - fflush(stdout); -} - -#if DO_NIST_TESTS - -/* ===================================================================== */ -/* - * Custom perfunctory AES-256 implementation (included to avoid any - * dependency on OpenSSL). This implementation is for tests only; it - * is not constant-time. - */ - -static inline uint32_t -dec32be(const void *src) -{ - const unsigned char *buf; - - buf = src; - return ((uint32_t)buf[0] << 24) - | ((uint32_t)buf[1] << 16) - | ((uint32_t)buf[2] << 8) - | (uint32_t)buf[3]; -} - -static inline void -enc32be(void *dst, uint32_t x) -{ - unsigned char *buf; - - buf = dst; - buf[0] = (unsigned char)(x >> 24); - buf[1] = (unsigned char)(x >> 16); - buf[2] = (unsigned char)(x >> 8); - buf[3] = (unsigned char)x; -} - -static const uint32_t Rcon[] = { - 0x01000000, 0x02000000, 0x04000000, 0x08000000, 0x10000000, 0x20000000, - 0x40000000, 0x80000000, 0x1B000000, 0x36000000 -}; - -/* see inner.h */ -static const unsigned char S[] = { - 0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B, - 0xFE, 0xD7, 0xAB, 0x76, 0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, - 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0, 0xB7, 0xFD, 0x93, 0x26, - 0x36, 0x3F, 0xF7, 0xCC, 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15, - 0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2, - 0xEB, 0x27, 0xB2, 0x75, 0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, - 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84, 0x53, 0xD1, 0x00, 0xED, - 0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF, - 0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F, - 0x50, 0x3C, 0x9F, 0xA8, 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, - 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2, 0xCD, 0x0C, 0x13, 0xEC, - 0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73, - 0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, 0x46, 0xEE, 0xB8, 0x14, - 0xDE, 0x5E, 0x0B, 0xDB, 0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, - 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79, 0xE7, 0xC8, 0x37, 0x6D, - 0x8D, 0xD5, 0x4E, 0xA9, 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08, - 0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, 0xE8, 0xDD, 0x74, 0x1F, - 0x4B, 0xBD, 0x8B, 0x8A, 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, - 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E, 0xE1, 0xF8, 0x98, 0x11, - 0x69, 0xD9, 0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF, - 0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99, 0x2D, 0x0F, - 0xB0, 0x54, 0xBB, 0x16 -}; - -static uint32_t -SubWord(uint32_t x) -{ - return ((uint32_t)S[x >> 24] << 24) - | ((uint32_t)S[(x >> 16) & 0xFF] << 16) - | ((uint32_t)S[(x >> 8) & 0xFF] << 8) - | (uint32_t)S[x & 0xFF]; -} - -static void -aes256_keysched(uint32_t *skey, const void *key) -{ - int i, j, k; - - for (i = 0; i < 8; i ++) { - skey[i] = dec32be((const unsigned char *)key + (i << 2)); - } - for (i = 8, j = 0, k = 0; i < 60; i ++) { - uint32_t tmp; - - tmp = skey[i - 1]; - if (j == 0) { - tmp = (tmp << 8) | (tmp >> 24); - tmp = SubWord(tmp) ^ Rcon[k]; - } else if (j == 4) { - tmp = SubWord(tmp); - } - skey[i] = skey[i - 8] ^ tmp; - if (++ j == 8) { - j = 0; - k ++; - } - } -} - -static const uint32_t Ssm0[] = { - 0xC66363A5, 0xF87C7C84, 0xEE777799, 0xF67B7B8D, 0xFFF2F20D, 0xD66B6BBD, - 0xDE6F6FB1, 0x91C5C554, 0x60303050, 0x02010103, 0xCE6767A9, 0x562B2B7D, - 0xE7FEFE19, 0xB5D7D762, 0x4DABABE6, 0xEC76769A, 0x8FCACA45, 0x1F82829D, - 0x89C9C940, 0xFA7D7D87, 0xEFFAFA15, 0xB25959EB, 0x8E4747C9, 0xFBF0F00B, - 0x41ADADEC, 0xB3D4D467, 0x5FA2A2FD, 0x45AFAFEA, 0x239C9CBF, 0x53A4A4F7, - 0xE4727296, 0x9BC0C05B, 0x75B7B7C2, 0xE1FDFD1C, 0x3D9393AE, 0x4C26266A, - 0x6C36365A, 0x7E3F3F41, 0xF5F7F702, 0x83CCCC4F, 0x6834345C, 0x51A5A5F4, - 0xD1E5E534, 0xF9F1F108, 0xE2717193, 0xABD8D873, 0x62313153, 0x2A15153F, - 0x0804040C, 0x95C7C752, 0x46232365, 0x9DC3C35E, 0x30181828, 0x379696A1, - 0x0A05050F, 0x2F9A9AB5, 0x0E070709, 0x24121236, 0x1B80809B, 0xDFE2E23D, - 0xCDEBEB26, 0x4E272769, 0x7FB2B2CD, 0xEA75759F, 0x1209091B, 0x1D83839E, - 0x582C2C74, 0x341A1A2E, 0x361B1B2D, 0xDC6E6EB2, 0xB45A5AEE, 0x5BA0A0FB, - 0xA45252F6, 0x763B3B4D, 0xB7D6D661, 0x7DB3B3CE, 0x5229297B, 0xDDE3E33E, - 0x5E2F2F71, 0x13848497, 0xA65353F5, 0xB9D1D168, 0x00000000, 0xC1EDED2C, - 0x40202060, 0xE3FCFC1F, 0x79B1B1C8, 0xB65B5BED, 0xD46A6ABE, 0x8DCBCB46, - 0x67BEBED9, 0x7239394B, 0x944A4ADE, 0x984C4CD4, 0xB05858E8, 0x85CFCF4A, - 0xBBD0D06B, 0xC5EFEF2A, 0x4FAAAAE5, 0xEDFBFB16, 0x864343C5, 0x9A4D4DD7, - 0x66333355, 0x11858594, 0x8A4545CF, 0xE9F9F910, 0x04020206, 0xFE7F7F81, - 0xA05050F0, 0x783C3C44, 0x259F9FBA, 0x4BA8A8E3, 0xA25151F3, 0x5DA3A3FE, - 0x804040C0, 0x058F8F8A, 0x3F9292AD, 0x219D9DBC, 0x70383848, 0xF1F5F504, - 0x63BCBCDF, 0x77B6B6C1, 0xAFDADA75, 0x42212163, 0x20101030, 0xE5FFFF1A, - 0xFDF3F30E, 0xBFD2D26D, 0x81CDCD4C, 0x180C0C14, 0x26131335, 0xC3ECEC2F, - 0xBE5F5FE1, 0x359797A2, 0x884444CC, 0x2E171739, 0x93C4C457, 0x55A7A7F2, - 0xFC7E7E82, 0x7A3D3D47, 0xC86464AC, 0xBA5D5DE7, 0x3219192B, 0xE6737395, - 0xC06060A0, 0x19818198, 0x9E4F4FD1, 0xA3DCDC7F, 0x44222266, 0x542A2A7E, - 0x3B9090AB, 0x0B888883, 0x8C4646CA, 0xC7EEEE29, 0x6BB8B8D3, 0x2814143C, - 0xA7DEDE79, 0xBC5E5EE2, 0x160B0B1D, 0xADDBDB76, 0xDBE0E03B, 0x64323256, - 0x743A3A4E, 0x140A0A1E, 0x924949DB, 0x0C06060A, 0x4824246C, 0xB85C5CE4, - 0x9FC2C25D, 0xBDD3D36E, 0x43ACACEF, 0xC46262A6, 0x399191A8, 0x319595A4, - 0xD3E4E437, 0xF279798B, 0xD5E7E732, 0x8BC8C843, 0x6E373759, 0xDA6D6DB7, - 0x018D8D8C, 0xB1D5D564, 0x9C4E4ED2, 0x49A9A9E0, 0xD86C6CB4, 0xAC5656FA, - 0xF3F4F407, 0xCFEAEA25, 0xCA6565AF, 0xF47A7A8E, 0x47AEAEE9, 0x10080818, - 0x6FBABAD5, 0xF0787888, 0x4A25256F, 0x5C2E2E72, 0x381C1C24, 0x57A6A6F1, - 0x73B4B4C7, 0x97C6C651, 0xCBE8E823, 0xA1DDDD7C, 0xE874749C, 0x3E1F1F21, - 0x964B4BDD, 0x61BDBDDC, 0x0D8B8B86, 0x0F8A8A85, 0xE0707090, 0x7C3E3E42, - 0x71B5B5C4, 0xCC6666AA, 0x904848D8, 0x06030305, 0xF7F6F601, 0x1C0E0E12, - 0xC26161A3, 0x6A35355F, 0xAE5757F9, 0x69B9B9D0, 0x17868691, 0x99C1C158, - 0x3A1D1D27, 0x279E9EB9, 0xD9E1E138, 0xEBF8F813, 0x2B9898B3, 0x22111133, - 0xD26969BB, 0xA9D9D970, 0x078E8E89, 0x339494A7, 0x2D9B9BB6, 0x3C1E1E22, - 0x15878792, 0xC9E9E920, 0x87CECE49, 0xAA5555FF, 0x50282878, 0xA5DFDF7A, - 0x038C8C8F, 0x59A1A1F8, 0x09898980, 0x1A0D0D17, 0x65BFBFDA, 0xD7E6E631, - 0x844242C6, 0xD06868B8, 0x824141C3, 0x299999B0, 0x5A2D2D77, 0x1E0F0F11, - 0x7BB0B0CB, 0xA85454FC, 0x6DBBBBD6, 0x2C16163A -}; - -static inline uint32_t -rotr(uint32_t x, int n) -{ - return (x << (32 - n)) | (x >> n); -} - -#define SboxExt0(x) (Ssm0[x]) -#define SboxExt1(x) (rotr(Ssm0[x], 8)) -#define SboxExt2(x) (rotr(Ssm0[x], 16)) -#define SboxExt3(x) (rotr(Ssm0[x], 24)) - -static void -aes256_encrypt(const uint32_t *skey, void *data) -{ - unsigned char *buf; - uint32_t s0, s1, s2, s3; - uint32_t t0, t1, t2, t3; - unsigned u; - - buf = data; - s0 = dec32be(buf); - s1 = dec32be(buf + 4); - s2 = dec32be(buf + 8); - s3 = dec32be(buf + 12); - s0 ^= skey[0]; - s1 ^= skey[1]; - s2 ^= skey[2]; - s3 ^= skey[3]; - for (u = 1; u < 14; u ++) { - uint32_t v0, v1, v2, v3; - - v0 = SboxExt0(s0 >> 24) - ^ SboxExt1((s1 >> 16) & 0xFF) - ^ SboxExt2((s2 >> 8) & 0xFF) - ^ SboxExt3(s3 & 0xFF); - v1 = SboxExt0(s1 >> 24) - ^ SboxExt1((s2 >> 16) & 0xFF) - ^ SboxExt2((s3 >> 8) & 0xFF) - ^ SboxExt3(s0 & 0xFF); - v2 = SboxExt0(s2 >> 24) - ^ SboxExt1((s3 >> 16) & 0xFF) - ^ SboxExt2((s0 >> 8) & 0xFF) - ^ SboxExt3(s1 & 0xFF); - v3 = SboxExt0(s3 >> 24) - ^ SboxExt1((s0 >> 16) & 0xFF) - ^ SboxExt2((s1 >> 8) & 0xFF) - ^ SboxExt3(s2 & 0xFF); - s0 = v0; - s1 = v1; - s2 = v2; - s3 = v3; - s0 ^= skey[u << 2]; - s1 ^= skey[(u << 2) + 1]; - s2 ^= skey[(u << 2) + 2]; - s3 ^= skey[(u << 2) + 3]; - } - t0 = ((uint32_t)S[s0 >> 24] << 24) - | ((uint32_t)S[(s1 >> 16) & 0xFF] << 16) - | ((uint32_t)S[(s2 >> 8) & 0xFF] << 8) - | (uint32_t)S[s3 & 0xFF]; - t1 = ((uint32_t)S[s1 >> 24] << 24) - | ((uint32_t)S[(s2 >> 16) & 0xFF] << 16) - | ((uint32_t)S[(s3 >> 8) & 0xFF] << 8) - | (uint32_t)S[s0 & 0xFF]; - t2 = ((uint32_t)S[s2 >> 24] << 24) - | ((uint32_t)S[(s3 >> 16) & 0xFF] << 16) - | ((uint32_t)S[(s0 >> 8) & 0xFF] << 8) - | (uint32_t)S[s1 & 0xFF]; - t3 = ((uint32_t)S[s3 >> 24] << 24) - | ((uint32_t)S[(s0 >> 16) & 0xFF] << 16) - | ((uint32_t)S[(s1 >> 8) & 0xFF] << 8) - | (uint32_t)S[s2 & 0xFF]; - s0 = t0 ^ skey[56]; - s1 = t1 ^ skey[57]; - s2 = t2 ^ skey[58]; - s3 = t3 ^ skey[59]; - enc32be(buf, s0); - enc32be(buf + 4, s1); - enc32be(buf + 8, s2); - enc32be(buf + 12, s3); -} - -/* ===================================================================== */ -/* - * Perfunctory SHA-1 implementation. - */ - -static void -sha1_round_inner(const uint8_t *buf, uint32_t *val) -{ -#define F(B, C, D) ((((C) ^ (D)) & (B)) ^ (D)) -#define G(B, C, D) ((B) ^ (C) ^ (D)) -#define H(B, C, D) (((D) & (C)) | (((D) | (C)) & (B))) -#define I(B, C, D) G(B, C, D) - -#define ROTL(x, n) (((x) << (n)) | ((x) >> (32 - (n)))) - -#define K1 ((uint32_t)0x5A827999) -#define K2 ((uint32_t)0x6ED9EBA1) -#define K3 ((uint32_t)0x8F1BBCDC) -#define K4 ((uint32_t)0xCA62C1D6) - - uint32_t m[80]; - uint32_t a, b, c, d, e; - int i; - - a = val[0]; - b = val[1]; - c = val[2]; - d = val[3]; - e = val[4]; - for (i = 0; i < 16; i ++) { - m[i] = dec32be(&buf[i << 2]); - } - for (i = 16; i < 80; i ++) { - uint32_t x; - - x = m[i - 3] ^ m[i - 8] ^ m[i - 14] ^ m[i - 16]; - m[i] = ROTL(x, 1); - } - - for (i = 0; i < 20; i += 5) { - e += ROTL(a, 5) + F(b, c, d) + K1 + m[i + 0]; b = ROTL(b, 30); - d += ROTL(e, 5) + F(a, b, c) + K1 + m[i + 1]; a = ROTL(a, 30); - c += ROTL(d, 5) + F(e, a, b) + K1 + m[i + 2]; e = ROTL(e, 30); - b += ROTL(c, 5) + F(d, e, a) + K1 + m[i + 3]; d = ROTL(d, 30); - a += ROTL(b, 5) + F(c, d, e) + K1 + m[i + 4]; c = ROTL(c, 30); - } - for (i = 20; i < 40; i += 5) { - e += ROTL(a, 5) + G(b, c, d) + K2 + m[i + 0]; b = ROTL(b, 30); - d += ROTL(e, 5) + G(a, b, c) + K2 + m[i + 1]; a = ROTL(a, 30); - c += ROTL(d, 5) + G(e, a, b) + K2 + m[i + 2]; e = ROTL(e, 30); - b += ROTL(c, 5) + G(d, e, a) + K2 + m[i + 3]; d = ROTL(d, 30); - a += ROTL(b, 5) + G(c, d, e) + K2 + m[i + 4]; c = ROTL(c, 30); - } - for (i = 40; i < 60; i += 5) { - e += ROTL(a, 5) + H(b, c, d) + K3 + m[i + 0]; b = ROTL(b, 30); - d += ROTL(e, 5) + H(a, b, c) + K3 + m[i + 1]; a = ROTL(a, 30); - c += ROTL(d, 5) + H(e, a, b) + K3 + m[i + 2]; e = ROTL(e, 30); - b += ROTL(c, 5) + H(d, e, a) + K3 + m[i + 3]; d = ROTL(d, 30); - a += ROTL(b, 5) + H(c, d, e) + K3 + m[i + 4]; c = ROTL(c, 30); - } - for (i = 60; i < 80; i += 5) { - e += ROTL(a, 5) + I(b, c, d) + K4 + m[i + 0]; b = ROTL(b, 30); - d += ROTL(e, 5) + I(a, b, c) + K4 + m[i + 1]; a = ROTL(a, 30); - c += ROTL(d, 5) + I(e, a, b) + K4 + m[i + 2]; e = ROTL(e, 30); - b += ROTL(c, 5) + I(d, e, a) + K4 + m[i + 3]; d = ROTL(d, 30); - a += ROTL(b, 5) + I(c, d, e) + K4 + m[i + 4]; c = ROTL(c, 30); - } - - val[0] += a; - val[1] += b; - val[2] += c; - val[3] += d; - val[4] += e; - -#undef F -#undef G -#undef H -#undef I -#undef ROTL -#undef K1 -#undef K2 -#undef K3 -#undef K4 -} - -typedef struct { - uint8_t buf[64]; - uint32_t val[5]; - uint64_t count; -} sha1_context; - -static void -sha1_init(sha1_context *sc) -{ - static const uint32_t IV[5] = { - 0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0 - }; - - memset(sc->buf, 0, sizeof sc->buf); - memcpy(sc->val, IV, sizeof sc->val); - sc->count = 0; -} - -static void -sha1_update(sha1_context *sc, const void *data, size_t len) -{ - const uint8_t *buf; - size_t ptr; - - buf = data; - ptr = (size_t)sc->count & 63; - sc->count += (uint64_t)len; - while (len > 0) { - size_t clen; - - clen = 64 - ptr; - if (clen > len) { - clen = len; - } - memcpy(sc->buf + ptr, buf, clen); - buf += clen; - len -= clen; - ptr += clen; - if (ptr == 64) { - sha1_round_inner(sc->buf, sc->val); - ptr = 0; - } - } -} - -static void -sha1_out(const sha1_context *cc, void *dst) -{ - uint8_t buf[64]; - uint32_t val[5]; - size_t ptr; - int i; - - ptr = (size_t)cc->count & 63; - memcpy(buf, cc->buf, ptr); - memcpy(val, cc->val, sizeof val); - buf[ptr ++] = 0x80; - if (ptr > 56) { - memset(buf + ptr, 0, 64 - ptr); - sha1_round_inner(buf, val); - memset(buf, 0, 56); - } else { - memset(buf + ptr, 0, 56 - ptr); - } - enc32be(buf + 56, (uint32_t)(cc->count >> 29)); - enc32be(buf + 60, (uint32_t)(cc->count << 3)); - sha1_round_inner(buf, val); - for (i = 0; i < 5; i ++) { - enc32be((uint8_t *)dst + (i << 2), val[i]); - } -} - -static void -sha1_print_line(sha1_context *sc, const char *s) -{ - char c; - - sha1_update(sc, s, strlen(s)); - c = '\n'; - sha1_update(sc, &c, 1); -} - -static void -sha1_print_line_with_int(sha1_context *sc, const char *s, unsigned x) -{ - char tmp[30]; - size_t u; - - sha1_update(sc, s, strlen(s)); - u = sizeof tmp; - tmp[-- u] = '\n'; - if (x == 0) { - tmp[-- u] = '0'; - } else { - while (x != 0) { - tmp[-- u] = '0' + (x % 10); - x /= 10; - } - } - sha1_update(sc, tmp + u, (sizeof tmp) - u); -} - -static void -sha1_print_line_with_hex(sha1_context *sc, - const char *s, const void *data, size_t len) -{ - const uint8_t *buf; - char c; - - sha1_update(sc, s, strlen(s)); - buf = data; - while (len -- > 0) { - unsigned b; - char tmp[2]; - - b = *buf ++; - tmp[0] = "0123456789ABCDEF"[b >> 4]; - tmp[1] = "0123456789ABCDEF"[b & 15]; - sha1_update(sc, tmp, 2); - } - c = '\n'; - sha1_update(sc, &c, 1); -} - -/* ===================================================================== */ -/* - * NIST test vectors. - * - * The code below reproduces the generation of test vectors as per the - * code provided by NIST for the PQC process; a deterministic PRNG based - * on AES-256 is used. The test_nist_KAT() function recomputes the NIST - * vectors and compares the resulting hash value with the expected one. - */ - -/* - * Static state for the AES-based DRBG used in NIST tests. - */ -static uint8_t DRBG_key[32]; -static uint8_t DRBG_V[16]; - -static void -aes256_DRBG_update(const uint8_t *provided_data, uint8_t *key, uint8_t *V) -{ - uint32_t skey[60]; - uint8_t tmp[48]; - int i, j; - - aes256_keysched(skey, key); - for (i = 0; i < 3; i ++) { - unsigned cc; - - cc = 1; - for (j = 15; j >= 0; j --) { - unsigned w; - - w = V[j] + cc; - V[j] = (uint8_t)w; - cc = w >> 8; - } - memcpy(tmp + (i << 4), V, 16); - aes256_encrypt(skey, tmp + (i << 4)); - } - if (provided_data != NULL) { - for (i = 0; i < 48; i ++) { - tmp[i] ^= provided_data[i]; - } - } - memcpy(key, tmp, 32); - memcpy(V, tmp + 32, 16); -} - -static void -nist_randombytes_init(uint8_t *entropy_input) -{ - memset(DRBG_key, 0x00, sizeof DRBG_key); - memset(DRBG_V, 0x00, sizeof DRBG_V); - aes256_DRBG_update(entropy_input, DRBG_key, DRBG_V); -} - -static void -nist_randombytes(uint8_t *buf, size_t len) -{ - while (len > 0) { - unsigned cc; - uint32_t skey[60]; - uint8_t tmp[16]; - size_t clen; - int j; - - cc = 1; - for (j = 15; j >= 0; j --) { - unsigned w; - - w = DRBG_V[j] + cc; - DRBG_V[j] = (uint8_t)w; - cc = w >> 8; - } - aes256_keysched(skey, DRBG_key); - memcpy(tmp, DRBG_V, 16); - aes256_encrypt(skey, tmp); - clen = (len < 16) ? len : 16; - memcpy(buf, tmp, clen); - buf += clen; - len -= clen; - } - aes256_DRBG_update(NULL, DRBG_key, DRBG_V); -} - -#endif - -static void -test_nist_KAT(unsigned logn, const char *srefhash) -{ -#if DO_NIST_TESTS - int i; - uint8_t entropy_input[48]; - uint8_t hhv[20], hhref[20]; - uint8_t *msg, *sk, *pk, *sm, *tmp; - size_t n, sk_len, pk_len, over_len; - fpr *esk; - sha1_context hhc; - - n = (size_t)1 << logn; - printf("Test NIST KAT (%zu): ", n); - fflush(stdout); - - hextobin(hhref, sizeof hhref, srefhash); - sha1_init(&hhc); - - sk_len = (logn == 9) ? 1281 : 2305; - pk_len = (logn == 9) ? 897 : 1793; - over_len = (logn == 9) ? 690 : 1330; - - msg = xmalloc(3300); - sk = xmalloc(sk_len); - pk = xmalloc(pk_len); - sm = xmalloc(3300 + over_len); - - tmp = xmalloc((size_t)84 << logn); - esk = xmalloc((size_t)(8 * logn + 40) << logn); - - sha1_print_line_with_int(&hhc, "# Falcon-", (unsigned)n); - sha1_print_line(&hhc, ""); - - for (i = 0; i < 48; i ++) { - entropy_input[i] = i; - } - nist_randombytes_init(entropy_input); - - for (i = 0; i < 100; i ++) { - uint8_t seed[48], seed2[48], nonce[40]; - uint8_t drbg_sav[48]; - size_t mlen, smlen; - int8_t *f, *g, *F, *G; - uint16_t *h; - uint16_t *hm; - int16_t *sig, *sig2; - inner_shake256_context sc; - size_t u, v; - - f = (int8_t *)(tmp + ((size_t)72 << logn)); - g = f + n; - F = g + n; - G = F + n; - h = (uint16_t *)(G + n); - hm = h + n; - sig = (int16_t *)(hm + n); - sig2 = sig + n; - - /* - * Generate test seed and message. - */ - nist_randombytes(seed, 48); - mlen = 33 * (i + 1); - nist_randombytes(msg, mlen); - - /* - * Save DRBG state, and reinitialize it with the seed. - */ - memcpy(drbg_sav, DRBG_key, 32); - memcpy(drbg_sav + 32, DRBG_V, 16); - nist_randombytes_init(seed); - - /* - * Do keygen. - */ - nist_randombytes(seed2, 48); - inner_shake256_init(&sc); - inner_shake256_inject(&sc, seed2, 48); - inner_shake256_flip(&sc); - Zf(keygen)(&sc, f, g, F, G, h, logn, tmp); - - /* - * Encode private key. - */ - sk[0] = 0x50 + logn; - u = 1; - v = Zf(trim_i8_encode)(sk + u, sk_len - u, - f, logn, Zf(max_fg_bits)[logn]); - if (v == 0) { - fprintf(stderr, "ERR encoding sk(f)\n"); - exit(EXIT_FAILURE); - } - u += v; - v = Zf(trim_i8_encode)(sk + u, sk_len - u, - g, logn, Zf(max_fg_bits)[logn]); - if (v == 0) { - fprintf(stderr, "ERR encoding sk(g)\n"); - exit(EXIT_FAILURE); - } - u += v; - v = Zf(trim_i8_encode)(sk + u, sk_len - u, - F, logn, Zf(max_FG_bits)[logn]); - if (v == 0) { - fprintf(stderr, "ERR encoding sk(F)\n"); - exit(EXIT_FAILURE); - } - u += v; - if (u != sk_len) { - fprintf(stderr, "wrong private key length: %zu\n", u); - exit(EXIT_FAILURE); - } - - /* - * Encode public key. - */ - pk[0] = 0x00 + logn; - v = Zf(modq_encode)(pk + 1, pk_len - 1, h, logn); - u = 1 + v; - if (u != pk_len) { - fprintf(stderr, "wrong public key length: %zu\n", u); - exit(EXIT_FAILURE); - } - - /* - * Sign the message. - */ - nist_randombytes(nonce, 40); - inner_shake256_init(&sc); - inner_shake256_inject(&sc, nonce, 40); - inner_shake256_inject(&sc, msg, mlen); - inner_shake256_flip(&sc); - Zf(hash_to_point_vartime)(&sc, hm, logn); - - nist_randombytes(seed2, 48); - inner_shake256_init(&sc); - inner_shake256_inject(&sc, seed2, 48); - inner_shake256_flip(&sc); - - Zf(sign_dyn)(sig, &sc, f, g, F, G, hm, logn, tmp); - - /* - * Expand the private key and sign again the message, - * and check that the same signature is obtained. - */ - Zf(expand_privkey)(esk, f, g, F, G, logn, tmp); - inner_shake256_init(&sc); - inner_shake256_inject(&sc, seed2, 48); - inner_shake256_flip(&sc); - Zf(sign_tree)(sig2, &sc, esk, hm, logn, tmp); - check_eq(sig, sig2, n * sizeof *sig, "Sign dyn/tree mismatch"); - - /* - * Verify the signature. - */ - Zf(to_ntt_monty)(h, logn); - if (!Zf(verify_raw)(hm, sig, h, logn, tmp)) { - fprintf(stderr, "Invalid signature\n"); - exit(EXIT_FAILURE); - } - - /* - * Encode the signature and bundle it with the message. - */ - memcpy(sm + 2, nonce, 40); - memcpy(sm + 42, msg, mlen); - sm[42 + mlen] = 0x20 + logn; - u = Zf(comp_encode)(sm + 43 + mlen, over_len - 43, sig, logn); - if (u == 0) { - fprintf(stderr, "Could not encode signature\n"); - exit(EXIT_FAILURE); - } - u ++; - smlen = 42 + mlen + u; - sm[0] = (uint8_t)(u >> 8); - sm[1] = (uint8_t)u; - - /* - * Restore DRBG state. - */ - memcpy(DRBG_key, drbg_sav, 32); - memcpy(DRBG_V, drbg_sav + 32, 16); - - sha1_print_line_with_int(&hhc, "count = ", (unsigned)i); - sha1_print_line_with_hex(&hhc, "seed = ", seed, 48); - sha1_print_line_with_int(&hhc, "mlen = ", (unsigned)mlen); - sha1_print_line_with_hex(&hhc, "msg = ", msg, mlen); - sha1_print_line_with_hex(&hhc, "pk = ", pk, pk_len); - sha1_print_line_with_hex(&hhc, "sk = ", sk, sk_len); - sha1_print_line_with_int(&hhc, "smlen = ", (unsigned)smlen); - sha1_print_line_with_hex(&hhc, "sm = ", sm, smlen); - sha1_print_line(&hhc, ""); - - printf("."); - fflush(stdout); - } - - xfree(msg); - xfree(sk); - xfree(pk); - xfree(sm); - - xfree(tmp); - xfree(esk); - - sha1_out(&hhc, hhv); - printf(" "); - for (i = 0; i < 20; i ++) { - printf("%02x", hhv[i]); - } - check_eq(hhv, hhref, 20, "NIST KAT (SHA-1 hash)"); - printf(" done.\n"); - fflush(stdout); - -#else - size_t n; - - (void)srefhash; - n = (size_t)1 << logn; - printf("Test NIST KAT (%zu): skipped because of incompatible build" - " options\n", n); - fflush(stdout); -#endif -} - -/* ===================================================================== */ - -#if 0 -/* unused */ -static void -test_speed_falcon(unsigned logn, uint8_t *tmp) -{ - size_t n; - int8_t *f, *g, *F, *G; - uint16_t *h, *hm; - fpr *expanded_key; - int16_t *sig; - uint8_t *tt, *tt2; - inner_shake256_context rng; - uint8_t seed[32]; - unsigned long num; - - n = (size_t)1 << logn; - printf(" %4zu ", n); - fflush(stdout); - - if (!Zf(get_seed)(seed, sizeof seed)) { - memset(seed, 0, sizeof seed); - seed[0] = logn; - } - inner_shake256_init(&rng); - inner_shake256_inject(&rng, seed, sizeof seed); - inner_shake256_flip(&rng); - - f = (int8_t *)tmp; - g = f + n; - F = g + n; - G = F + n; - h = (uint16_t *)(G + n); - hm = h + n; - sig = (int16_t *)(hm + n); - tt = (uint8_t *)(sig + n); - if (logn == 1) { - tt += 4; - } - - num = 1; - for (;;) { - clock_t begin, end; - unsigned long c; - double d; - - begin = clock(); - for (c = 0; c < num; c ++) { - Zf(keygen)(&rng, f, g, F, G, h, logn, tt); - } - end = clock(); - d = (double)(end - begin) / (double)CLOCKS_PER_SEC; - if (d >= 2.0) { - printf(" %7.2f ", d * 1000.0 / (double)num); - fflush(stdout); - break; - } - num <<= 1; - } - - num = 1; - for (;;) { - uint8_t msg[50]; /* nonce + message */ - inner_shake256_context sc; - clock_t begin, end; - unsigned long c; - double d; - - inner_shake256_extract(&rng, msg, sizeof msg); - - inner_shake256_init(&sc); - inner_shake256_inject(&sc, msg, sizeof msg); - inner_shake256_flip(&sc); - Zf(hash_to_point_vartime)(&sc, hm, logn); - - begin = clock(); - for (c = 0; c < num; c ++) { - Zf(sign_dyn)(sig, &rng, f, g, F, G, hm, logn, tt); - } - end = clock(); - d = (double)(end - begin) / (double)CLOCKS_PER_SEC; - if (d >= 2.0) { - printf(" %8.2f ", (double)num / d); - fflush(stdout); - break; - } - num <<= 1; - } - - expanded_key = (fpr *)tt; - tt2 = (uint8_t *)expanded_key + (8 * logn + 40) * n; - Zf(expand_privkey)(expanded_key, f, g, F, G, logn, tt2); - - num = 1; - for (;;) { - uint8_t msg[50]; /* nonce + message */ - inner_shake256_context sc; - clock_t begin, end; - unsigned long c; - double d; - - inner_shake256_extract(&rng, msg, sizeof msg); - - inner_shake256_init(&sc); - inner_shake256_inject(&sc, msg, sizeof msg); - inner_shake256_flip(&sc); - Zf(hash_to_point_vartime)(&sc, hm, logn); - - begin = clock(); - for (c = 0; c < num; c ++) { - Zf(sign_tree)(sig, &rng, expanded_key, hm, logn, tt2); - } - end = clock(); - d = (double)(end - begin) / (double)CLOCKS_PER_SEC; - if (d >= 2.0) { - printf(" %8.2f ", (double)num / d); - fflush(stdout); - break; - } - num <<= 1; - } - - Zf(to_ntt_monty)(h, logn); - - num = 1; - for (;;) { - clock_t begin, end; - unsigned long c; - double d; - - begin = clock(); - for (c = 0; c < num; c ++) { - Zf(verify_raw)(hm, sig, h, logn, tt); - } - end = clock(); - d = (double)(end - begin) / (double)CLOCKS_PER_SEC; - if (d >= 2.0) { - printf("%9.2f\n", (double)num / d); - fflush(stdout); - break; - } - num <<= 1; - } -} - -static void -test_speed(void) -{ - size_t tlen; - uint8_t *tmp; - - tlen = 182272; - tmp = xmalloc(tlen); - printf("degree keygen(ms) sign/s(dyn) sign/s(tree) vrfy/s\n"); - fflush(stdout); - test_speed_falcon(8, tmp); - test_speed_falcon(9, tmp); - test_speed_falcon(10, tmp); - xfree(tmp); -} -#endif - -int -main(void) -{ - unsigned old; - - old = set_fpu_cw(2); - - test_SHAKE256(); - test_codec(); - test_vrfy(); - test_RNG(); - test_FP_block(); - test_poly(); - test_gaussian0_sampler(); - test_sampler(); - test_sign(); - test_keygen(); - test_external_API(); - test_nist_KAT(9, "a57400cbaee7109358859a56c735a3cf048a9da2"); - test_nist_KAT(10, "affdeb3aa83bf9a2039fa9c17d65fd3e3b9828e2"); - /* test_speed(); */ - - set_fpu_cw(old); - return 0; -} diff --git a/falcon/vrfy.c b/falcon/vrfy.c deleted file mode 100644 index c74a3dd..0000000 --- a/falcon/vrfy.c +++ /dev/null @@ -1,871 +0,0 @@ -/* - * Falcon signature verification. - * - * ==========================(LICENSE BEGIN)============================ - * - * Copyright (c) 2017-2019 Falcon Project - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * ===========================(LICENSE END)============================= - * - * @author Thomas Pornin - */ - -#include "inner.h" - -/* ===================================================================== */ -/* - * Constants for NTT. - * - * n = 2^logn (2 <= n <= 1024) - * phi = X^n + 1 - * q = 12289 - * q0i = -1/q mod 2^16 - * R = 2^16 mod q - * R2 = 2^32 mod q - */ - -#define Q 12289 -#define Q0I 12287 -#define R 4091 -#define R2 10952 - -/* - * Table for NTT, binary case: - * GMb[x] = R*(g^rev(x)) mod q - * where g = 7 (it is a 2048-th primitive root of 1 modulo q) - * and rev() is the bit-reversal function over 10 bits. - */ -static const uint16_t GMb[] = { - 4091, 7888, 11060, 11208, 6960, 4342, 6275, 9759, - 1591, 6399, 9477, 5266, 586, 5825, 7538, 9710, - 1134, 6407, 1711, 965, 7099, 7674, 3743, 6442, - 10414, 8100, 1885, 1688, 1364, 10329, 10164, 9180, - 12210, 6240, 997, 117, 4783, 4407, 1549, 7072, - 2829, 6458, 4431, 8877, 7144, 2564, 5664, 4042, - 12189, 432, 10751, 1237, 7610, 1534, 3983, 7863, - 2181, 6308, 8720, 6570, 4843, 1690, 14, 3872, - 5569, 9368, 12163, 2019, 7543, 2315, 4673, 7340, - 1553, 1156, 8401, 11389, 1020, 2967, 10772, 7045, - 3316, 11236, 5285, 11578, 10637, 10086, 9493, 6180, - 9277, 6130, 3323, 883, 10469, 489, 1502, 2851, - 11061, 9729, 2742, 12241, 4970, 10481, 10078, 1195, - 730, 1762, 3854, 2030, 5892, 10922, 9020, 5274, - 9179, 3604, 3782, 10206, 3180, 3467, 4668, 2446, - 7613, 9386, 834, 7703, 6836, 3403, 5351, 12276, - 3580, 1739, 10820, 9787, 10209, 4070, 12250, 8525, - 10401, 2749, 7338, 10574, 6040, 943, 9330, 1477, - 6865, 9668, 3585, 6633, 12145, 4063, 3684, 7680, - 8188, 6902, 3533, 9807, 6090, 727, 10099, 7003, - 6945, 1949, 9731, 10559, 6057, 378, 7871, 8763, - 8901, 9229, 8846, 4551, 9589, 11664, 7630, 8821, - 5680, 4956, 6251, 8388, 10156, 8723, 2341, 3159, - 1467, 5460, 8553, 7783, 2649, 2320, 9036, 6188, - 737, 3698, 4699, 5753, 9046, 3687, 16, 914, - 5186, 10531, 4552, 1964, 3509, 8436, 7516, 5381, - 10733, 3281, 7037, 1060, 2895, 7156, 8887, 5357, - 6409, 8197, 2962, 6375, 5064, 6634, 5625, 278, - 932, 10229, 8927, 7642, 351, 9298, 237, 5858, - 7692, 3146, 12126, 7586, 2053, 11285, 3802, 5204, - 4602, 1748, 11300, 340, 3711, 4614, 300, 10993, - 5070, 10049, 11616, 12247, 7421, 10707, 5746, 5654, - 3835, 5553, 1224, 8476, 9237, 3845, 250, 11209, - 4225, 6326, 9680, 12254, 4136, 2778, 692, 8808, - 6410, 6718, 10105, 10418, 3759, 7356, 11361, 8433, - 6437, 3652, 6342, 8978, 5391, 2272, 6476, 7416, - 8418, 10824, 11986, 5733, 876, 7030, 2167, 2436, - 3442, 9217, 8206, 4858, 5964, 2746, 7178, 1434, - 7389, 8879, 10661, 11457, 4220, 1432, 10832, 4328, - 8557, 1867, 9454, 2416, 3816, 9076, 686, 5393, - 2523, 4339, 6115, 619, 937, 2834, 7775, 3279, - 2363, 7488, 6112, 5056, 824, 10204, 11690, 1113, - 2727, 9848, 896, 2028, 5075, 2654, 10464, 7884, - 12169, 5434, 3070, 6400, 9132, 11672, 12153, 4520, - 1273, 9739, 11468, 9937, 10039, 9720, 2262, 9399, - 11192, 315, 4511, 1158, 6061, 6751, 11865, 357, - 7367, 4550, 983, 8534, 8352, 10126, 7530, 9253, - 4367, 5221, 3999, 8777, 3161, 6990, 4130, 11652, - 3374, 11477, 1753, 292, 8681, 2806, 10378, 12188, - 5800, 11811, 3181, 1988, 1024, 9340, 2477, 10928, - 4582, 6750, 3619, 5503, 5233, 2463, 8470, 7650, - 7964, 6395, 1071, 1272, 3474, 11045, 3291, 11344, - 8502, 9478, 9837, 1253, 1857, 6233, 4720, 11561, - 6034, 9817, 3339, 1797, 2879, 6242, 5200, 2114, - 7962, 9353, 11363, 5475, 6084, 9601, 4108, 7323, - 10438, 9471, 1271, 408, 6911, 3079, 360, 8276, - 11535, 9156, 9049, 11539, 850, 8617, 784, 7919, - 8334, 12170, 1846, 10213, 12184, 7827, 11903, 5600, - 9779, 1012, 721, 2784, 6676, 6552, 5348, 4424, - 6816, 8405, 9959, 5150, 2356, 5552, 5267, 1333, - 8801, 9661, 7308, 5788, 4910, 909, 11613, 4395, - 8238, 6686, 4302, 3044, 2285, 12249, 1963, 9216, - 4296, 11918, 695, 4371, 9793, 4884, 2411, 10230, - 2650, 841, 3890, 10231, 7248, 8505, 11196, 6688, - 4059, 6060, 3686, 4722, 11853, 5816, 7058, 6868, - 11137, 7926, 4894, 12284, 4102, 3908, 3610, 6525, - 7938, 7982, 11977, 6755, 537, 4562, 1623, 8227, - 11453, 7544, 906, 11816, 9548, 10858, 9703, 2815, - 11736, 6813, 6979, 819, 8903, 6271, 10843, 348, - 7514, 8339, 6439, 694, 852, 5659, 2781, 3716, - 11589, 3024, 1523, 8659, 4114, 10738, 3303, 5885, - 2978, 7289, 11884, 9123, 9323, 11830, 98, 2526, - 2116, 4131, 11407, 1844, 3645, 3916, 8133, 2224, - 10871, 8092, 9651, 5989, 7140, 8480, 1670, 159, - 10923, 4918, 128, 7312, 725, 9157, 5006, 6393, - 3494, 6043, 10972, 6181, 11838, 3423, 10514, 7668, - 3693, 6658, 6905, 11953, 10212, 11922, 9101, 8365, - 5110, 45, 2400, 1921, 4377, 2720, 1695, 51, - 2808, 650, 1896, 9997, 9971, 11980, 8098, 4833, - 4135, 4257, 5838, 4765, 10985, 11532, 590, 12198, - 482, 12173, 2006, 7064, 10018, 3912, 12016, 10519, - 11362, 6954, 2210, 284, 5413, 6601, 3865, 10339, - 11188, 6231, 517, 9564, 11281, 3863, 1210, 4604, - 8160, 11447, 153, 7204, 5763, 5089, 9248, 12154, - 11748, 1354, 6672, 179, 5532, 2646, 5941, 12185, - 862, 3158, 477, 7279, 5678, 7914, 4254, 302, - 2893, 10114, 6890, 9560, 9647, 11905, 4098, 9824, - 10269, 1353, 10715, 5325, 6254, 3951, 1807, 6449, - 5159, 1308, 8315, 3404, 1877, 1231, 112, 6398, - 11724, 12272, 7286, 1459, 12274, 9896, 3456, 800, - 1397, 10678, 103, 7420, 7976, 936, 764, 632, - 7996, 8223, 8445, 7758, 10870, 9571, 2508, 1946, - 6524, 10158, 1044, 4338, 2457, 3641, 1659, 4139, - 4688, 9733, 11148, 3946, 2082, 5261, 2036, 11850, - 7636, 12236, 5366, 2380, 1399, 7720, 2100, 3217, - 10912, 8898, 7578, 11995, 2791, 1215, 3355, 2711, - 2267, 2004, 8568, 10176, 3214, 2337, 1750, 4729, - 4997, 7415, 6315, 12044, 4374, 7157, 4844, 211, - 8003, 10159, 9290, 11481, 1735, 2336, 5793, 9875, - 8192, 986, 7527, 1401, 870, 3615, 8465, 2756, - 9770, 2034, 10168, 3264, 6132, 54, 2880, 4763, - 11805, 3074, 8286, 9428, 4881, 6933, 1090, 10038, - 2567, 708, 893, 6465, 4962, 10024, 2090, 5718, - 10743, 780, 4733, 4623, 2134, 2087, 4802, 884, - 5372, 5795, 5938, 4333, 6559, 7549, 5269, 10664, - 4252, 3260, 5917, 10814, 5768, 9983, 8096, 7791, - 6800, 7491, 6272, 1907, 10947, 6289, 11803, 6032, - 11449, 1171, 9201, 7933, 2479, 7970, 11337, 7062, - 8911, 6728, 6542, 8114, 8828, 6595, 3545, 4348, - 4610, 2205, 6999, 8106, 5560, 10390, 9321, 2499, - 2413, 7272, 6881, 10582, 9308, 9437, 3554, 3326, - 5991, 11969, 3415, 12283, 9838, 12063, 4332, 7830, - 11329, 6605, 12271, 2044, 11611, 7353, 11201, 11582, - 3733, 8943, 9978, 1627, 7168, 3935, 5050, 2762, - 7496, 10383, 755, 1654, 12053, 4952, 10134, 4394, - 6592, 7898, 7497, 8904, 12029, 3581, 10748, 5674, - 10358, 4901, 7414, 8771, 710, 6764, 8462, 7193, - 5371, 7274, 11084, 290, 7864, 6827, 11822, 2509, - 6578, 4026, 5807, 1458, 5721, 5762, 4178, 2105, - 11621, 4852, 8897, 2856, 11510, 9264, 2520, 8776, - 7011, 2647, 1898, 7039, 5950, 11163, 5488, 6277, - 9182, 11456, 633, 10046, 11554, 5633, 9587, 2333, - 7008, 7084, 5047, 7199, 9865, 8997, 569, 6390, - 10845, 9679, 8268, 11472, 4203, 1997, 2, 9331, - 162, 6182, 2000, 3649, 9792, 6363, 7557, 6187, - 8510, 9935, 5536, 9019, 3706, 12009, 1452, 3067, - 5494, 9692, 4865, 6019, 7106, 9610, 4588, 10165, - 6261, 5887, 2652, 10172, 1580, 10379, 4638, 9949 -}; - -/* - * Table for inverse NTT, binary case: - * iGMb[x] = R*((1/g)^rev(x)) mod q - * Since g = 7, 1/g = 8778 mod 12289. - */ -static const uint16_t iGMb[] = { - 4091, 4401, 1081, 1229, 2530, 6014, 7947, 5329, - 2579, 4751, 6464, 11703, 7023, 2812, 5890, 10698, - 3109, 2125, 1960, 10925, 10601, 10404, 4189, 1875, - 5847, 8546, 4615, 5190, 11324, 10578, 5882, 11155, - 8417, 12275, 10599, 7446, 5719, 3569, 5981, 10108, - 4426, 8306, 10755, 4679, 11052, 1538, 11857, 100, - 8247, 6625, 9725, 5145, 3412, 7858, 5831, 9460, - 5217, 10740, 7882, 7506, 12172, 11292, 6049, 79, - 13, 6938, 8886, 5453, 4586, 11455, 2903, 4676, - 9843, 7621, 8822, 9109, 2083, 8507, 8685, 3110, - 7015, 3269, 1367, 6397, 10259, 8435, 10527, 11559, - 11094, 2211, 1808, 7319, 48, 9547, 2560, 1228, - 9438, 10787, 11800, 1820, 11406, 8966, 6159, 3012, - 6109, 2796, 2203, 1652, 711, 7004, 1053, 8973, - 5244, 1517, 9322, 11269, 900, 3888, 11133, 10736, - 4949, 7616, 9974, 4746, 10270, 126, 2921, 6720, - 6635, 6543, 1582, 4868, 42, 673, 2240, 7219, - 1296, 11989, 7675, 8578, 11949, 989, 10541, 7687, - 7085, 8487, 1004, 10236, 4703, 163, 9143, 4597, - 6431, 12052, 2991, 11938, 4647, 3362, 2060, 11357, - 12011, 6664, 5655, 7225, 5914, 9327, 4092, 5880, - 6932, 3402, 5133, 9394, 11229, 5252, 9008, 1556, - 6908, 4773, 3853, 8780, 10325, 7737, 1758, 7103, - 11375, 12273, 8602, 3243, 6536, 7590, 8591, 11552, - 6101, 3253, 9969, 9640, 4506, 3736, 6829, 10822, - 9130, 9948, 3566, 2133, 3901, 6038, 7333, 6609, - 3468, 4659, 625, 2700, 7738, 3443, 3060, 3388, - 3526, 4418, 11911, 6232, 1730, 2558, 10340, 5344, - 5286, 2190, 11562, 6199, 2482, 8756, 5387, 4101, - 4609, 8605, 8226, 144, 5656, 8704, 2621, 5424, - 10812, 2959, 11346, 6249, 1715, 4951, 9540, 1888, - 3764, 39, 8219, 2080, 2502, 1469, 10550, 8709, - 5601, 1093, 3784, 5041, 2058, 8399, 11448, 9639, - 2059, 9878, 7405, 2496, 7918, 11594, 371, 7993, - 3073, 10326, 40, 10004, 9245, 7987, 5603, 4051, - 7894, 676, 11380, 7379, 6501, 4981, 2628, 3488, - 10956, 7022, 6737, 9933, 7139, 2330, 3884, 5473, - 7865, 6941, 5737, 5613, 9505, 11568, 11277, 2510, - 6689, 386, 4462, 105, 2076, 10443, 119, 3955, - 4370, 11505, 3672, 11439, 750, 3240, 3133, 754, - 4013, 11929, 9210, 5378, 11881, 11018, 2818, 1851, - 4966, 8181, 2688, 6205, 6814, 926, 2936, 4327, - 10175, 7089, 6047, 9410, 10492, 8950, 2472, 6255, - 728, 7569, 6056, 10432, 11036, 2452, 2811, 3787, - 945, 8998, 1244, 8815, 11017, 11218, 5894, 4325, - 4639, 3819, 9826, 7056, 6786, 8670, 5539, 7707, - 1361, 9812, 2949, 11265, 10301, 9108, 478, 6489, - 101, 1911, 9483, 3608, 11997, 10536, 812, 8915, - 637, 8159, 5299, 9128, 3512, 8290, 7068, 7922, - 3036, 4759, 2163, 3937, 3755, 11306, 7739, 4922, - 11932, 424, 5538, 6228, 11131, 7778, 11974, 1097, - 2890, 10027, 2569, 2250, 2352, 821, 2550, 11016, - 7769, 136, 617, 3157, 5889, 9219, 6855, 120, - 4405, 1825, 9635, 7214, 10261, 11393, 2441, 9562, - 11176, 599, 2085, 11465, 7233, 6177, 4801, 9926, - 9010, 4514, 9455, 11352, 11670, 6174, 7950, 9766, - 6896, 11603, 3213, 8473, 9873, 2835, 10422, 3732, - 7961, 1457, 10857, 8069, 832, 1628, 3410, 4900, - 10855, 5111, 9543, 6325, 7431, 4083, 3072, 8847, - 9853, 10122, 5259, 11413, 6556, 303, 1465, 3871, - 4873, 5813, 10017, 6898, 3311, 5947, 8637, 5852, - 3856, 928, 4933, 8530, 1871, 2184, 5571, 5879, - 3481, 11597, 9511, 8153, 35, 2609, 5963, 8064, - 1080, 12039, 8444, 3052, 3813, 11065, 6736, 8454, - 2340, 7651, 1910, 10709, 2117, 9637, 6402, 6028, - 2124, 7701, 2679, 5183, 6270, 7424, 2597, 6795, - 9222, 10837, 280, 8583, 3270, 6753, 2354, 3779, - 6102, 4732, 5926, 2497, 8640, 10289, 6107, 12127, - 2958, 12287, 10292, 8086, 817, 4021, 2610, 1444, - 5899, 11720, 3292, 2424, 5090, 7242, 5205, 5281, - 9956, 2702, 6656, 735, 2243, 11656, 833, 3107, - 6012, 6801, 1126, 6339, 5250, 10391, 9642, 5278, - 3513, 9769, 3025, 779, 9433, 3392, 7437, 668, - 10184, 8111, 6527, 6568, 10831, 6482, 8263, 5711, - 9780, 467, 5462, 4425, 11999, 1205, 5015, 6918, - 5096, 3827, 5525, 11579, 3518, 4875, 7388, 1931, - 6615, 1541, 8708, 260, 3385, 4792, 4391, 5697, - 7895, 2155, 7337, 236, 10635, 11534, 1906, 4793, - 9527, 7239, 8354, 5121, 10662, 2311, 3346, 8556, - 707, 1088, 4936, 678, 10245, 18, 5684, 960, - 4459, 7957, 226, 2451, 6, 8874, 320, 6298, - 8963, 8735, 2852, 2981, 1707, 5408, 5017, 9876, - 9790, 2968, 1899, 6729, 4183, 5290, 10084, 7679, - 7941, 8744, 5694, 3461, 4175, 5747, 5561, 3378, - 5227, 952, 4319, 9810, 4356, 3088, 11118, 840, - 6257, 486, 6000, 1342, 10382, 6017, 4798, 5489, - 4498, 4193, 2306, 6521, 1475, 6372, 9029, 8037, - 1625, 7020, 4740, 5730, 7956, 6351, 6494, 6917, - 11405, 7487, 10202, 10155, 7666, 7556, 11509, 1546, - 6571, 10199, 2265, 7327, 5824, 11396, 11581, 9722, - 2251, 11199, 5356, 7408, 2861, 4003, 9215, 484, - 7526, 9409, 12235, 6157, 9025, 2121, 10255, 2519, - 9533, 3824, 8674, 11419, 10888, 4762, 11303, 4097, - 2414, 6496, 9953, 10554, 808, 2999, 2130, 4286, - 12078, 7445, 5132, 7915, 245, 5974, 4874, 7292, - 7560, 10539, 9952, 9075, 2113, 3721, 10285, 10022, - 9578, 8934, 11074, 9498, 294, 4711, 3391, 1377, - 9072, 10189, 4569, 10890, 9909, 6923, 53, 4653, - 439, 10253, 7028, 10207, 8343, 1141, 2556, 7601, - 8150, 10630, 8648, 9832, 7951, 11245, 2131, 5765, - 10343, 9781, 2718, 1419, 4531, 3844, 4066, 4293, - 11657, 11525, 11353, 4313, 4869, 12186, 1611, 10892, - 11489, 8833, 2393, 15, 10830, 5003, 17, 565, - 5891, 12177, 11058, 10412, 8885, 3974, 10981, 7130, - 5840, 10482, 8338, 6035, 6964, 1574, 10936, 2020, - 2465, 8191, 384, 2642, 2729, 5399, 2175, 9396, - 11987, 8035, 4375, 6611, 5010, 11812, 9131, 11427, - 104, 6348, 9643, 6757, 12110, 5617, 10935, 541, - 135, 3041, 7200, 6526, 5085, 12136, 842, 4129, - 7685, 11079, 8426, 1008, 2725, 11772, 6058, 1101, - 1950, 8424, 5688, 6876, 12005, 10079, 5335, 927, - 1770, 273, 8377, 2271, 5225, 10283, 116, 11807, - 91, 11699, 757, 1304, 7524, 6451, 8032, 8154, - 7456, 4191, 309, 2318, 2292, 10393, 11639, 9481, - 12238, 10594, 9569, 7912, 10368, 9889, 12244, 7179, - 3924, 3188, 367, 2077, 336, 5384, 5631, 8596, - 4621, 1775, 8866, 451, 6108, 1317, 6246, 8795, - 5896, 7283, 3132, 11564, 4977, 12161, 7371, 1366, - 12130, 10619, 3809, 5149, 6300, 2638, 4197, 1418, - 10065, 4156, 8373, 8644, 10445, 882, 8158, 10173, - 9763, 12191, 459, 2966, 3166, 405, 5000, 9311, - 6404, 8986, 1551, 8175, 3630, 10766, 9265, 700, - 8573, 9508, 6630, 11437, 11595, 5850, 3950, 4775, - 11941, 1446, 6018, 3386, 11470, 5310, 5476, 553, - 9474, 2586, 1431, 2741, 473, 11383, 4745, 836, - 4062, 10666, 7727, 11752, 5534, 312, 4307, 4351, - 5764, 8679, 8381, 8187, 5, 7395, 4363, 1152, - 5421, 5231, 6473, 436, 7567, 8603, 6229, 8230 -}; - -/* - * Reduce a small signed integer modulo q. The source integer MUST - * be between -q/2 and +q/2. - */ -static inline uint32_t -mq_conv_small(int x) -{ - /* - * If x < 0, the cast to uint32_t will set the high bit to 1. - */ - uint32_t y; - - y = (uint32_t)x; - y += Q & -(y >> 31); - return y; -} - -/* - * Addition modulo q. Operands must be in the 0..q-1 range. - */ -static inline uint32_t -mq_add(uint32_t x, uint32_t y) -{ - /* - * We compute x + y - q. If the result is negative, then the - * high bit will be set, and 'd >> 31' will be equal to 1; - * thus '-(d >> 31)' will be an all-one pattern. Otherwise, - * it will be an all-zero pattern. In other words, this - * implements a conditional addition of q. - */ - uint32_t d; - - d = x + y - Q; - d += Q & -(d >> 31); - return d; -} - -/* - * Subtraction modulo q. Operands must be in the 0..q-1 range. - */ -static inline uint32_t -mq_sub(uint32_t x, uint32_t y) -{ - /* - * As in mq_add(), we use a conditional addition to ensure the - * result is in the 0..q-1 range. - */ - uint32_t d; - - d = x - y; - d += Q & -(d >> 31); - return d; -} - -/* - * Division by 2 modulo q. Operand must be in the 0..q-1 range. - */ -static inline uint32_t -mq_rshift1(uint32_t x) -{ - x += Q & -(x & 1); - return (x >> 1); -} - -/* - * Montgomery multiplication modulo q. If we set R = 2^16 mod q, then - * this function computes: x * y / R mod q - * Operands must be in the 0..q-1 range. - */ -static inline uint32_t -mq_montymul(uint32_t x, uint32_t y) -{ - uint32_t z, w; - - /* - * We compute x*y + k*q with a value of k chosen so that the 16 - * low bits of the result are 0. We can then shift the value. - * After the shift, result may still be larger than q, but it - * will be lower than 2*q, so a conditional subtraction works. - */ - - z = x * y; - w = ((z * Q0I) & 0xFFFF) * Q; - - /* - * When adding z and w, the result will have its low 16 bits - * equal to 0. Since x, y and z are lower than q, the sum will - * be no more than (2^15 - 1) * q + (q - 1)^2, which will - * fit on 29 bits. - */ - z = (z + w) >> 16; - - /* - * After the shift, analysis shows that the value will be less - * than 2q. We do a subtraction then conditional subtraction to - * ensure the result is in the expected range. - */ - z -= Q; - z += Q & -(z >> 31); - return z; -} - -/* - * Montgomery squaring (computes (x^2)/R). - */ -static inline uint32_t -mq_montysqr(uint32_t x) -{ - return mq_montymul(x, x); -} - -/* - * Divide x by y modulo q = 12289. - */ -static inline uint32_t -mq_div_12289(uint32_t x, uint32_t y) -{ - /* - * We invert y by computing y^(q-2) mod q. - * - * We use the following addition chain for exponent e = 12287: - * - * e0 = 1 - * e1 = 2 * e0 = 2 - * e2 = e1 + e0 = 3 - * e3 = e2 + e1 = 5 - * e4 = 2 * e3 = 10 - * e5 = 2 * e4 = 20 - * e6 = 2 * e5 = 40 - * e7 = 2 * e6 = 80 - * e8 = 2 * e7 = 160 - * e9 = e8 + e2 = 163 - * e10 = e9 + e8 = 323 - * e11 = 2 * e10 = 646 - * e12 = 2 * e11 = 1292 - * e13 = e12 + e9 = 1455 - * e14 = 2 * e13 = 2910 - * e15 = 2 * e14 = 5820 - * e16 = e15 + e10 = 6143 - * e17 = 2 * e16 = 12286 - * e18 = e17 + e0 = 12287 - * - * Additions on exponents are converted to Montgomery - * multiplications. We define all intermediate results as so - * many local variables, and let the C compiler work out which - * must be kept around. - */ - uint32_t y0, y1, y2, y3, y4, y5, y6, y7, y8, y9; - uint32_t y10, y11, y12, y13, y14, y15, y16, y17, y18; - - y0 = mq_montymul(y, R2); - y1 = mq_montysqr(y0); - y2 = mq_montymul(y1, y0); - y3 = mq_montymul(y2, y1); - y4 = mq_montysqr(y3); - y5 = mq_montysqr(y4); - y6 = mq_montysqr(y5); - y7 = mq_montysqr(y6); - y8 = mq_montysqr(y7); - y9 = mq_montymul(y8, y2); - y10 = mq_montymul(y9, y8); - y11 = mq_montysqr(y10); - y12 = mq_montysqr(y11); - y13 = mq_montymul(y12, y9); - y14 = mq_montysqr(y13); - y15 = mq_montysqr(y14); - y16 = mq_montymul(y15, y10); - y17 = mq_montysqr(y16); - y18 = mq_montymul(y17, y0); - - /* - * Final multiplication with x, which is not in Montgomery - * representation, computes the correct division result. - */ - return mq_montymul(y18, x); -} - -/* - * Compute NTT on a ring element. - */ -static void -mq_NTT(uint16_t *a, unsigned logn) -{ - size_t n, t, m; - - n = (size_t)1 << logn; - t = n; - for (m = 1; m < n; m <<= 1) { - size_t ht, i, j1; - - ht = t >> 1; - for (i = 0, j1 = 0; i < m; i ++, j1 += t) { - size_t j, j2; - uint32_t s; - - s = GMb[m + i]; - j2 = j1 + ht; - for (j = j1; j < j2; j ++) { - uint32_t u, v; - - u = a[j]; - v = mq_montymul(a[j + ht], s); - a[j] = (uint16_t)mq_add(u, v); - a[j + ht] = (uint16_t)mq_sub(u, v); - } - } - t = ht; - } -} - -/* - * Compute the inverse NTT on a ring element, binary case. - */ -static void -mq_iNTT(uint16_t *a, unsigned logn) -{ - size_t n, t, m; - uint32_t ni; - - n = (size_t)1 << logn; - t = 1; - m = n; - while (m > 1) { - size_t hm, dt, i, j1; - - hm = m >> 1; - dt = t << 1; - for (i = 0, j1 = 0; i < hm; i ++, j1 += dt) { - size_t j, j2; - uint32_t s; - - j2 = j1 + t; - s = iGMb[hm + i]; - for (j = j1; j < j2; j ++) { - uint32_t u, v, w; - - u = a[j]; - v = a[j + t]; - a[j] = (uint16_t)mq_add(u, v); - w = mq_sub(u, v); - a[j + t] = (uint16_t) - mq_montymul(w, s); - } - } - t = dt; - m = hm; - } - - /* - * To complete the inverse NTT, we must now divide all values by - * n (the vector size). We thus need the inverse of n, i.e. we - * need to divide 1 by 2 logn times. But we also want it in - * Montgomery representation, i.e. we also want to multiply it - * by R = 2^16. In the common case, this should be a simple right - * shift. The loop below is generic and works also in corner cases; - * its computation time is negligible. - */ - ni = R; - for (m = n; m > 1; m >>= 1) { - ni = mq_rshift1(ni); - } - for (m = 0; m < n; m ++) { - a[m] = (uint16_t)mq_montymul(a[m], ni); - } -} - -/* - * Convert a polynomial (mod q) to Montgomery representation. - */ -static void -mq_poly_tomonty(uint16_t *f, unsigned logn) -{ - size_t u, n; - - n = (size_t)1 << logn; - for (u = 0; u < n; u ++) { - f[u] = (uint16_t)mq_montymul(f[u], R2); - } -} - -/* - * Multiply two polynomials together (NTT representation, and using - * a Montgomery multiplication). Result f*g is written over f. - */ -static void -mq_poly_montymul_ntt(uint16_t *f, const uint16_t *g, unsigned logn) -{ - size_t u, n; - - n = (size_t)1 << logn; - for (u = 0; u < n; u ++) { - f[u] = (uint16_t)mq_montymul(f[u], g[u]); - } -} - -/* - * Subtract polynomial g from polynomial f. - */ -static void -mq_poly_sub(uint16_t *f, const uint16_t *g, unsigned logn) -{ - size_t u, n; - - n = (size_t)1 << logn; - for (u = 0; u < n; u ++) { - f[u] = (uint16_t)mq_sub(f[u], g[u]); - } -} - -/* ===================================================================== */ - -/* see inner.h */ -void -Zf(to_ntt_monty)(uint16_t *h, unsigned logn) -{ - mq_NTT(h, logn); - mq_poly_tomonty(h, logn); -} - -/* see inner.h */ -int -Zf(verify_raw)(const uint16_t *c0, const int16_t *s2, - const uint16_t *h, unsigned logn, uint8_t *tmp) -{ - size_t u, n; - uint16_t *tt; - - n = (size_t)1 << logn; - tt = (uint16_t *)tmp; - - /* - * Reduce s2 elements modulo q ([0..q-1] range). - */ - for (u = 0; u < n; u ++) { - uint32_t w; - - w = (uint32_t)s2[u]; - w += Q & -(w >> 31); - tt[u] = (uint16_t)w; - } - - /* - * Compute -s1 = s2*h - c0 mod phi mod q (in tt[]). - */ - mq_NTT(tt, logn); - mq_poly_montymul_ntt(tt, h, logn); - mq_iNTT(tt, logn); - mq_poly_sub(tt, c0, logn); - - /* - * Normalize -s1 elements into the [-q/2..q/2] range. - */ - for (u = 0; u < n; u ++) { - int32_t w; - - w = (int32_t)tt[u]; - w -= (int32_t)(Q & -(((Q >> 1) - (uint32_t)w) >> 31)); - ((int16_t *)tt)[u] = (int16_t)w; - } - - /* - * Signature is valid if and only if the aggregate (-s1,s2) vector - * is short enough. - */ - return Zf(is_short)((int16_t *)tt, s2, logn); -} - -/* see inner.h */ -int -Zf(compute_public)(uint16_t *h, - const int8_t *f, const int8_t *g, unsigned logn, uint8_t *tmp) -{ - size_t u, n; - uint16_t *tt; - - n = (size_t)1 << logn; - tt = (uint16_t *)tmp; - for (u = 0; u < n; u ++) { - tt[u] = (uint16_t)mq_conv_small(f[u]); - h[u] = (uint16_t)mq_conv_small(g[u]); - } - mq_NTT(h, logn); - mq_NTT(tt, logn); - for (u = 0; u < n; u ++) { - if (tt[u] == 0) { - return 0; - } - h[u] = (uint16_t)mq_div_12289(h[u], tt[u]); - } - mq_iNTT(h, logn); - return 1; -} - -/* see inner.h */ -int -Zf(complete_private)(int8_t *G, - const int8_t *f, const int8_t *g, const int8_t *F, - unsigned logn, uint8_t *tmp) -{ - size_t u, n; - uint16_t *t1, *t2; - - n = (size_t)1 << logn; - t1 = (uint16_t *)tmp; - t2 = t1 + n; - for (u = 0; u < n; u ++) { - t1[u] = (uint16_t)mq_conv_small(g[u]); - t2[u] = (uint16_t)mq_conv_small(F[u]); - } - mq_NTT(t1, logn); - mq_NTT(t2, logn); - mq_poly_tomonty(t1, logn); - mq_poly_montymul_ntt(t1, t2, logn); - for (u = 0; u < n; u ++) { - t2[u] = (uint16_t)mq_conv_small(f[u]); - } - mq_NTT(t2, logn); - for (u = 0; u < n; u ++) { - if (t2[u] == 0) { - return 0; - } - t1[u] = (uint16_t)mq_div_12289(t1[u], t2[u]); - } - mq_iNTT(t1, logn); - for (u = 0; u < n; u ++) { - uint32_t w; - int32_t gi; - - w = t1[u]; - w -= (Q & ~-((w - (Q >> 1)) >> 31)); - gi = *(int32_t *)&w; - if (gi < -127 || gi > +127) { - return 0; - } - G[u] = (int8_t)gi; - } - return 1; -} - -/* see inner.h */ -int -Zf(is_invertible)( - const int16_t *s2, unsigned logn, uint8_t *tmp) -{ - size_t u, n; - uint16_t *tt; - uint32_t r; - - n = (size_t)1 << logn; - tt = (uint16_t *)tmp; - for (u = 0; u < n; u ++) { - uint32_t w; - - w = (uint32_t)s2[u]; - w += Q & -(w >> 31); - tt[u] = (uint16_t)w; - } - mq_NTT(tt, logn); - r = 0; - for (u = 0; u < n; u ++) { - r |= (uint32_t)(tt[u] - 1); - } - return (int)(1u - (r >> 31)); -} - -/* see inner.h */ -int -Zf(verify_recover)(uint16_t *h, - const uint16_t *c0, const int16_t *s1, const int16_t *s2, - unsigned logn, uint8_t *tmp) -{ - size_t u, n; - uint16_t *tt; - uint32_t r; - - n = (size_t)1 << logn; - - /* - * Reduce elements of s1 and s2 modulo q; then write s2 into tt[] - * and c0 - s1 into h[]. - */ - tt = (uint16_t *)tmp; - for (u = 0; u < n; u ++) { - uint32_t w; - - w = (uint32_t)s2[u]; - w += Q & -(w >> 31); - tt[u] = (uint16_t)w; - - w = (uint32_t)s1[u]; - w += Q & -(w >> 31); - w = mq_sub(c0[u], w); - h[u] = (uint16_t)w; - } - - /* - * Compute h = (c0 - s1) / s2. If one of the coefficients of s2 - * is zero (in NTT representation) then the operation fails. We - * keep that information into a flag so that we do not deviate - * from strict constant-time processing; if all coefficients of - * s2 are non-zero, then the high bit of r will be zero. - */ - mq_NTT(tt, logn); - mq_NTT(h, logn); - r = 0; - for (u = 0; u < n; u ++) { - r |= (uint32_t)(tt[u] - 1); - h[u] = (uint16_t)mq_div_12289(h[u], tt[u]); - } - mq_iNTT(h, logn); - - /* - * Signature is acceptable if and only if it is short enough, - * and s2 was invertible mod phi mod q. The caller must still - * check that the rebuilt public key matches the expected - * value (e.g. through a hash). - */ - r = ~r & (uint32_t)-Zf(is_short)(s1, s2, logn); - return (int)(r >> 31); -} - -/* see inner.h */ -int -Zf(count_nttzero)(const int16_t *sig, unsigned logn, uint8_t *tmp) -{ - uint16_t *s2; - size_t u, n; - uint32_t r; - - n = (size_t)1 << logn; - s2 = (uint16_t *)tmp; - for (u = 0; u < n; u ++) { - uint32_t w; - - w = (uint32_t)sig[u]; - w += Q & -(w >> 31); - s2[u] = (uint16_t)w; - } - mq_NTT(s2, logn); - r = 0; - for (u = 0; u < n; u ++) { - uint32_t w; - - w = (uint32_t)s2[u] - 1u; - r += (w >> 31); - } - return (int)r; -} diff --git a/fuzz/fuzz_targets/cross_algorithm_fuzz.rs b/fuzz/fuzz_targets/cross_algorithm_fuzz.rs index 5d388d0..a79806c 100644 --- a/fuzz/fuzz_targets/cross_algorithm_fuzz.rs +++ b/fuzz/fuzz_targets/cross_algorithm_fuzz.rs @@ -13,7 +13,7 @@ fuzz_target!(|data: &[u8]| { let key_data = &data[0..128]; // Generate two keypairs with different algorithms - let alg1 = Algorithm::FN_DSA_512; + let alg1 = Algorithm::SECP256K1_SCHNORR; let alg2 = Algorithm::ML_DSA_44; let keypair1 = match generate_keypair(alg1, key_data) { diff --git a/fuzz/fuzz_targets/key_parsing_fuzz.rs b/fuzz/fuzz_targets/key_parsing_fuzz.rs index a53c103..ea4f3a4 100644 --- a/fuzz/fuzz_targets/key_parsing_fuzz.rs +++ b/fuzz/fuzz_targets/key_parsing_fuzz.rs @@ -3,7 +3,7 @@ use bitcoinpqc::{algorithm_from_index, PublicKey, SecretKey}; use libfuzzer_sys::fuzz_target; -const NUM_ALGORITHMS: u8 = 4; // SECP256K1_SCHNORR, FN_DSA_512, ML_DSA_44, SLH_DSA_128S +const NUM_ALGORITHMS: u8 = 3; // SECP256K1_SCHNORR, ML_DSA_44, SLH_DSA_128S fuzz_target!(|data: &[u8]| { if data.len() < 2 { diff --git a/fuzz/fuzz_targets/signature_parsing_fuzz.rs b/fuzz/fuzz_targets/signature_parsing_fuzz.rs index c1ef992..8ab27e9 100644 --- a/fuzz/fuzz_targets/signature_parsing_fuzz.rs +++ b/fuzz/fuzz_targets/signature_parsing_fuzz.rs @@ -3,7 +3,7 @@ use bitcoinpqc::{algorithm_from_index, Signature}; use libfuzzer_sys::fuzz_target; -const NUM_ALGORITHMS: u8 = 4; // SECP256K1_SCHNORR, FN_DSA_512, ML_DSA_44, SLH_DSA_128S +const NUM_ALGORITHMS: u8 = 3; // SECP256K1_SCHNORR, ML_DSA_44, SLH_DSA_128S fuzz_target!(|data: &[u8]| { if data.is_empty() { diff --git a/include/libbitcoinpqc/bitcoinpqc.h b/include/libbitcoinpqc/bitcoinpqc.h index ada6753..37f48ec 100644 --- a/include/libbitcoinpqc/bitcoinpqc.h +++ b/include/libbitcoinpqc/bitcoinpqc.h @@ -6,7 +6,6 @@ * signature algorithms for use with BIP-360 and the Bitcoin QuBit soft fork: * - ML-DSA-44 (CRYSTALS-Dilithium) * - SLH-DSA-Shake-128s (SPHINCS+) - * - FN-DSA-512 (FALCON) */ #ifndef BITCOIN_PQC_H @@ -22,9 +21,8 @@ extern "C" { /* Algorithm identifiers */ typedef enum { BITCOIN_PQC_SECP256K1_SCHNORR = 0, /* BIP-340 Schnorr + X-Only */ - BITCOIN_PQC_FN_DSA_512 = 1, /* FIPS 206 - FALCON-512 */ - BITCOIN_PQC_ML_DSA_44 = 2, /* FIPS 204 - CRYSTALS-Dilithium Level I */ - BITCOIN_PQC_SLH_DSA_SHAKE_128S = 3 /* FIPS 205 - SPHINCS+-128s */ + BITCOIN_PQC_ML_DSA_44 = 1, /* FIPS 204 - CRYSTALS-Dilithium Level I */ + BITCOIN_PQC_SLH_DSA_SHAKE_128S = 2 /* FIPS 205 - SPHINCS+-128s */ } bitcoin_pqc_algorithm_t; /* Common error codes */ @@ -155,7 +153,6 @@ bitcoin_pqc_error_t bitcoin_pqc_verify( /* Algorithm-specific header includes */ #include "ml_dsa.h" #include "slh_dsa.h" -#include "fn_dsa.h" #ifdef __cplusplus } diff --git a/include/libbitcoinpqc/fn_dsa.h b/include/libbitcoinpqc/fn_dsa.h deleted file mode 100644 index 34aa4b5..0000000 --- a/include/libbitcoinpqc/fn_dsa.h +++ /dev/null @@ -1,76 +0,0 @@ -/** - * @file fn_dsa.h - * @brief FN-DSA-512 (FALCON) specific functions - */ - -#ifndef BITCOIN_PQC_FN_DSA_H -#define BITCOIN_PQC_FN_DSA_H - -#include -#include - -/* FN-DSA-512 constants */ -#define FN_DSA_512_PUBLIC_KEY_SIZE 897 -#define FN_DSA_512_SECRET_KEY_SIZE 1281 -#define FN_DSA_512_SIGNATURE_SIZE 666 /* Average size, actual size may vary */ -#define FN_DSA_512_SIG_MAX_SIZE 809 /* Maximum signature size */ - -/* Key Generation Functions */ - -/** - * @brief Generate a FN-DSA-512 key pair - * - * @param pk Output public key (must have space for FN_DSA_512_PUBLIC_KEY_SIZE bytes) - * @param sk Output secret key (must have space for FN_DSA_512_SECRET_KEY_SIZE bytes) - * @param random_data User-provided random data (entropy) - * @param random_data_size Size of random data, must be >= 128 bytes - * @return 0 on success, non-zero on failure - */ -int fn_dsa_512_keygen( - uint8_t *pk, - uint8_t *sk, - const uint8_t *random_data, - size_t random_data_size -); - -/* Signing Functions */ - -/** - * @brief Sign a message using FN-DSA-512 - * - * @param sig Output signature (must have space for FN_DSA_512_SIG_MAX_SIZE bytes) - * @param siglen Output signature length - * @param m Message to sign - * @param mlen Message length - * @param sk Secret key - * @return 0 on success, non-zero on failure - */ -int fn_dsa_512_sign( - uint8_t *sig, - size_t *siglen, - const uint8_t *m, - size_t mlen, - const uint8_t *sk -); - -/* Verification Functions */ - -/** - * @brief Verify a FN-DSA-512 signature - * - * @param sig Signature - * @param siglen Signature length - * @param m Message - * @param mlen Message length - * @param pk Public key - * @return 0 if signature is valid, non-zero otherwise - */ -int fn_dsa_512_verify( - const uint8_t *sig, - size_t siglen, - const uint8_t *m, - size_t mlen, - const uint8_t *pk -); - -#endif /* BITCOIN_PQC_FN_DSA_H */ diff --git a/src/bindings_include.rs b/src/bindings_include.rs index 4851cc5..f3a33ab 100644 --- a/src/bindings_include.rs +++ b/src/bindings_include.rs @@ -17,10 +17,9 @@ pub mod doc_bindings { impl bitcoin_pqc_algorithm_t { pub const BITCOIN_PQC_SECP256K1_SCHNORR: bitcoin_pqc_algorithm_t = bitcoin_pqc_algorithm_t(0); - pub const BITCOIN_PQC_FN_DSA_512: bitcoin_pqc_algorithm_t = bitcoin_pqc_algorithm_t(1); - pub const BITCOIN_PQC_ML_DSA_44: bitcoin_pqc_algorithm_t = bitcoin_pqc_algorithm_t(2); + pub const BITCOIN_PQC_ML_DSA_44: bitcoin_pqc_algorithm_t = bitcoin_pqc_algorithm_t(1); pub const BITCOIN_PQC_SLH_DSA_SHAKE_128S: bitcoin_pqc_algorithm_t = - bitcoin_pqc_algorithm_t(3); + bitcoin_pqc_algorithm_t(2); } #[repr(C)] @@ -132,10 +131,9 @@ pub mod ide_bindings { impl bitcoin_pqc_algorithm_t { pub const BITCOIN_PQC_SECP256K1_SCHNORR: bitcoin_pqc_algorithm_t = bitcoin_pqc_algorithm_t(0); - pub const BITCOIN_PQC_FN_DSA_512: bitcoin_pqc_algorithm_t = bitcoin_pqc_algorithm_t(1); - pub const BITCOIN_PQC_ML_DSA_44: bitcoin_pqc_algorithm_t = bitcoin_pqc_algorithm_t(2); + pub const BITCOIN_PQC_ML_DSA_44: bitcoin_pqc_algorithm_t = bitcoin_pqc_algorithm_t(1); pub const BITCOIN_PQC_SLH_DSA_SHAKE_128S: bitcoin_pqc_algorithm_t = - bitcoin_pqc_algorithm_t(3); + bitcoin_pqc_algorithm_t(2); } #[repr(C)] diff --git a/src/bitcoinpqc.c b/src/bitcoinpqc.c index 791e8de..92d0015 100644 --- a/src/bitcoinpqc.c +++ b/src/bitcoinpqc.c @@ -4,7 +4,6 @@ #include "libbitcoinpqc/bitcoinpqc.h" #include "libbitcoinpqc/ml_dsa.h" #include "libbitcoinpqc/slh_dsa.h" -#include "libbitcoinpqc/fn_dsa.h" // Debug mode flag - set to 0 to disable debug output #define BITCOIN_PQC_DEBUG 0 @@ -21,8 +20,6 @@ size_t bitcoin_pqc_public_key_size(bitcoin_pqc_algorithm_t algorithm) { return ML_DSA_44_PUBLIC_KEY_SIZE; case BITCOIN_PQC_SLH_DSA_SHAKE_128S: return SLH_DSA_SHAKE_128S_PUBLIC_KEY_SIZE; - case BITCOIN_PQC_FN_DSA_512: - return FN_DSA_512_PUBLIC_KEY_SIZE; default: return 0; } @@ -36,8 +33,6 @@ size_t bitcoin_pqc_secret_key_size(bitcoin_pqc_algorithm_t algorithm) { return ML_DSA_44_SECRET_KEY_SIZE; case BITCOIN_PQC_SLH_DSA_SHAKE_128S: return SLH_DSA_SHAKE_128S_SECRET_KEY_SIZE; - case BITCOIN_PQC_FN_DSA_512: - return FN_DSA_512_SECRET_KEY_SIZE; default: return 0; } @@ -51,8 +46,6 @@ size_t bitcoin_pqc_signature_size(bitcoin_pqc_algorithm_t algorithm) { return ML_DSA_44_SIGNATURE_SIZE; case BITCOIN_PQC_SLH_DSA_SHAKE_128S: return SLH_DSA_SHAKE_128S_SIGNATURE_SIZE; - case BITCOIN_PQC_FN_DSA_512: - return FN_DSA_512_SIG_MAX_SIZE; // Use max size for buffer allocation default: return 0; } @@ -103,9 +96,6 @@ bitcoin_pqc_error_t bitcoin_pqc_keygen( case BITCOIN_PQC_SLH_DSA_SHAKE_128S: result = slh_dsa_shake_128s_keygen(pk, sk, random_data, random_data_size); break; - case BITCOIN_PQC_FN_DSA_512: - result = fn_dsa_512_keygen(pk, sk, random_data, random_data_size); - break; default: free(pk); free(sk); @@ -207,11 +197,6 @@ bitcoin_pqc_error_t bitcoin_pqc_sign( result = slh_dsa_shake_128s_sign(sig, &actual_sig_len, message, message_size, secret_key); break; - case BITCOIN_PQC_FN_DSA_512: - DEBUG_PRINT("bitcoin_pqc_sign: Calling fn_dsa_512_sign\n"); - result = fn_dsa_512_sign(sig, &actual_sig_len, message, message_size, - secret_key); - break; default: free(sig); DEBUG_PRINT("bitcoin_pqc_sign: Unsupported algorithm %d\n", algorithm); @@ -277,17 +262,10 @@ bitcoin_pqc_error_t bitcoin_pqc_verify( // Get expected signature size size_t expected_sig_size = bitcoin_pqc_signature_size(algorithm); - if (algorithm != BITCOIN_PQC_FN_DSA_512 && signature_size != expected_sig_size) { - // For FALCON, signature size can vary but must be <= max size - if (algorithm == BITCOIN_PQC_FN_DSA_512 && signature_size > expected_sig_size) { - DEBUG_PRINT("bitcoin_pqc_verify: Bad signature size for FALCON. Max %zu, got %zu\n", - expected_sig_size, signature_size); - return BITCOIN_PQC_ERROR_BAD_SIGNATURE; - } else if (algorithm != BITCOIN_PQC_FN_DSA_512) { - DEBUG_PRINT("bitcoin_pqc_verify: Bad signature size. Expected %zu, got %zu\n", - expected_sig_size, signature_size); - return BITCOIN_PQC_ERROR_BAD_SIGNATURE; - } + if (signature_size != expected_sig_size) { + DEBUG_PRINT("bitcoin_pqc_verify: Bad signature size. Expected %zu, got %zu\n", + expected_sig_size, signature_size); + return BITCOIN_PQC_ERROR_BAD_SIGNATURE; } int result; @@ -306,10 +284,6 @@ bitcoin_pqc_error_t bitcoin_pqc_verify( DEBUG_PRINT("bitcoin_pqc_verify: Calling slh_dsa_shake_128s_verify\n"); result = slh_dsa_shake_128s_verify(signature, signature_size, message, message_size, public_key); break; - case BITCOIN_PQC_FN_DSA_512: - DEBUG_PRINT("bitcoin_pqc_verify: Calling fn_dsa_512_verify\n"); - result = fn_dsa_512_verify(signature, signature_size, message, message_size, public_key); - break; default: DEBUG_PRINT("bitcoin_pqc_verify: Unsupported algorithm %d\n", algorithm); return BITCOIN_PQC_ERROR_NOT_IMPLEMENTED; diff --git a/src/fn_dsa/keygen.c b/src/fn_dsa/keygen.c deleted file mode 100644 index 9884e08..0000000 --- a/src/fn_dsa/keygen.c +++ /dev/null @@ -1,68 +0,0 @@ -#include -#include -#include "libbitcoinpqc/fn_dsa.h" - -/* - * This file implements the key generation function for FN-DSA-512 (FALCON) - */ - -/* Include necessary headers from FALCON reference implementation */ -#include "../../falcon/falcon.h" - -/* External declaration for utility functions */ -extern void fn_dsa_shake256_with_entropy(void *out, size_t out_len, - const void *in1, size_t in1_len, - const void *in2, size_t in2_len, - const uint8_t *entropy, size_t entropy_len); - -int fn_dsa_512_keygen( - uint8_t *pk, - uint8_t *sk, - const uint8_t *random_data, - size_t random_data_size -) { - if (!pk || !sk || !random_data || random_data_size < 128) { - return -1; - } - - /* - * FN-DSA-512's key generation requires a source of randomness, - * which we'll provide through a SHAKE256 instance pre-seeded - * with our user-provided entropy - */ - - /* Buffer for SHAKE256 state */ - shake256_context rng; - - /* Initialize SHAKE256 with user-provided entropy */ - shake256_init(&rng); - shake256_inject(&rng, random_data, random_data_size); - shake256_flip(&rng); - - /* - * Generate a FN-DSA-512 key pair - * FALCON_TMPSIZE_KEYGEN(9) = size needed for temporary buffer in keygen for degree 2^9 = 512 - */ - uint8_t *tmp = malloc(FALCON_TMPSIZE_KEYGEN(9)); - if (!tmp) { - return -1; - } - - /* Generate the key pair using our RNG */ - int result = falcon_keygen_make( - &rng, /* RNG context */ - 9, /* log of degree (9 for Falcon-512) */ - sk, /* output: private key */ - FN_DSA_512_SECRET_KEY_SIZE, /* size of private key buffer */ - pk, /* output: public key */ - FN_DSA_512_PUBLIC_KEY_SIZE, /* size of public key buffer */ - tmp, /* temporary buffer */ - FALCON_TMPSIZE_KEYGEN(9) /* size of temporary buffer */ - ); - - /* Clean up */ - memset(tmp, 0, FALCON_TMPSIZE_KEYGEN(9)); - free(tmp); - - return result; -} diff --git a/src/fn_dsa/sign.c b/src/fn_dsa/sign.c deleted file mode 100644 index 8fc4dbb..0000000 --- a/src/fn_dsa/sign.c +++ /dev/null @@ -1,82 +0,0 @@ -#include -#include -#include -#include "libbitcoinpqc/fn_dsa.h" - -/* - * This file implements the signing function for FN-DSA-512 (FALCON) - */ - -/* Include necessary headers from FALCON reference implementation */ -#include "../../falcon/falcon.h" - -// Debug mode flag - set to 0 to disable debug output -#define FN_DSA_DEBUG 0 - -// Conditional debug print macro -#define DEBUG_PRINT(fmt, ...) \ - do { if (FN_DSA_DEBUG) printf(fmt, ##__VA_ARGS__); } while (0) - -/* External declaration for utility functions */ -extern void fn_dsa_shake256_with_entropy(void *out, size_t out_len, - const void *in1, size_t in1_len, - const void *in2, size_t in2_len, - const uint8_t *entropy, size_t entropy_len); - -int fn_dsa_512_sign( - uint8_t *sig, - size_t *siglen, - const uint8_t *m, - size_t mlen, - const uint8_t *sk -) { - if (!sig || !siglen || !m || !sk) { - DEBUG_PRINT("FN-DSA sign: Invalid arguments\n"); - return -1; - } - - // Create a deterministic RNG for signing based on the message and secret key - shake256_context rng; - shake256_init(&rng); - - // Mix message and secret key to create deterministic randomness - shake256_inject(&rng, sk, FN_DSA_512_SECRET_KEY_SIZE); - shake256_inject(&rng, m, mlen); - shake256_flip(&rng); - - /* - * Temporary buffer size needed for Falcon-512 signature - * FALCON_TMPSIZE_SIGNDYN(9) is the buffer size for degree 2^9 = 512 - */ - size_t tmp_size = FALCON_TMPSIZE_SIGNDYN(9); - uint8_t *tmp = malloc(tmp_size); - if (!tmp) { - DEBUG_PRINT("FN-DSA sign: Memory allocation failed\n"); - return -1; - } - - DEBUG_PRINT("FN-DSA sign: Calling falcon_sign_dyn\n"); - - // Sign the message using the FALCON implementation - int result = falcon_sign_dyn( - &rng, // RNG context (deterministic) - sig, // output signature - siglen, // output signature length - FALCON_SIG_COMPRESSED, // signature format - sk, // secret key - FN_DSA_512_SECRET_KEY_SIZE, // secret key size - m, // message to sign - mlen, // message length - tmp, // temporary buffer - tmp_size // temporary buffer size - ); - - DEBUG_PRINT("FN-DSA sign: Created signature of length %zu, result %d\n", - *siglen, result); - - // Clean up - memset(tmp, 0, tmp_size); - free(tmp); - - return result; -} diff --git a/src/fn_dsa/utils.c b/src/fn_dsa/utils.c deleted file mode 100644 index 32b3b21..0000000 --- a/src/fn_dsa/utils.c +++ /dev/null @@ -1,42 +0,0 @@ -#include -#include -#include "../../falcon/falcon.h" - -/* - * This file implements utility functions for FN-DSA-512 (FALCON) - * particularly related to random data handling - */ - -/* Custom implementation of SHAKE256 for entropy */ -void fn_dsa_shake256_with_entropy(void *out, size_t out_len, - const void *in1, size_t in1_len, - const void *in2, size_t in2_len, - const uint8_t *entropy, size_t entropy_len) { - /* Combine inputs with entropy to get final output */ - size_t total_len = in1_len + in2_len + entropy_len; - uint8_t *combined = malloc(total_len); - shake256_context sc; - - if (!combined) { - memset(out, 0, out_len); /* fallback to zeros */ - return; - } - - /* Combine all inputs */ - memcpy(combined, in1, in1_len); - memcpy(combined + in1_len, in2, in2_len); - - if (entropy && entropy_len > 0) { - memcpy(combined + in1_len + in2_len, entropy, entropy_len); - } - - /* Call FALCON's SHAKE256 */ - shake256_init(&sc); - shake256_inject(&sc, combined, total_len); - shake256_flip(&sc); - shake256_extract(&sc, out, out_len); - - /* Clean up */ - memset(combined, 0, total_len); - free(combined); -} diff --git a/src/fn_dsa/verify.c b/src/fn_dsa/verify.c deleted file mode 100644 index 2fe39f3..0000000 --- a/src/fn_dsa/verify.c +++ /dev/null @@ -1,65 +0,0 @@ -#include -#include -#include -#include "libbitcoinpqc/fn_dsa.h" - -/* - * This file implements the verification function for FN-DSA-512 (FALCON) - */ - -/* Include necessary headers from FALCON reference implementation */ -#include "../../falcon/falcon.h" - -// Debug mode flag - set to 0 to disable debug output -#define FN_DSA_DEBUG 0 - -// Conditional debug print macro -#define DEBUG_PRINT(fmt, ...) \ - do { if (FN_DSA_DEBUG) printf(fmt, ##__VA_ARGS__); } while (0) - -int fn_dsa_512_verify( - const uint8_t *sig, - size_t siglen, - const uint8_t *m, - size_t mlen, - const uint8_t *pk -) { - if (!sig || !m || !pk) { - DEBUG_PRINT("FN-DSA verify: Invalid arguments\n"); - return -1; - } - - /* - * Temporary buffer size needed for Falcon-512 verification - * FALCON_TMPSIZE_VERIFY(9) is the buffer size for degree 2^9 = 512 - */ - size_t tmp_size = FALCON_TMPSIZE_VERIFY(9); - uint8_t *tmp = malloc(tmp_size); - if (!tmp) { - DEBUG_PRINT("FN-DSA verify: Memory allocation failed\n"); - return -1; - } - - DEBUG_PRINT("FN-DSA verify: Calling falcon_verify\n"); - - // Verify the signature using the FALCON implementation - int result = falcon_verify( - sig, // signature to verify - siglen, // signature length - FALCON_SIG_COMPRESSED, // signature format - pk, // public key - FN_DSA_512_PUBLIC_KEY_SIZE, // public key size - m, // message - mlen, // message length - tmp, // temporary buffer - tmp_size // temporary buffer size - ); - - DEBUG_PRINT("FN-DSA verify: Verification result %d\n", result); - - // Clean up - memset(tmp, 0, tmp_size); - free(tmp); - - return result; -} diff --git a/src/lib.rs b/src/lib.rs index ac1e3ff..7e8e978 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -122,8 +122,6 @@ impl From for Result<(), PqcError> { pub enum Algorithm { /// BIP-340 Schnorr + X-Only - Elliptic Curve Digital Signature Algorithm SECP256K1_SCHNORR, - /// FN-DSA-512 (FALCON) - Fast Fourier lattice-based signature scheme - FN_DSA_512, /// ML-DSA-44 (CRYSTALS-Dilithium) - Lattice-based signature scheme ML_DSA_44, /// SLH-DSA-Shake-128s (SPHINCS+) - Hash-based signature scheme @@ -134,7 +132,6 @@ impl From for bitcoin_pqc_algorithm_t { fn from(alg: Algorithm) -> Self { match alg { Algorithm::SECP256K1_SCHNORR => bitcoin_pqc_algorithm_t::BITCOIN_PQC_SECP256K1_SCHNORR, - Algorithm::FN_DSA_512 => bitcoin_pqc_algorithm_t::BITCOIN_PQC_FN_DSA_512, Algorithm::ML_DSA_44 => bitcoin_pqc_algorithm_t::BITCOIN_PQC_ML_DSA_44, Algorithm::SLH_DSA_128S => bitcoin_pqc_algorithm_t::BITCOIN_PQC_SLH_DSA_SHAKE_128S, _ => panic!("Invalid algorithm"), @@ -150,7 +147,6 @@ impl TryFrom for Algorithm { fn try_from(s: String) -> Result { match s.as_str() { "SECP256K1_SCHNORR" => Ok(Algorithm::SECP256K1_SCHNORR), - "FN_DSA_512" => Ok(Algorithm::FN_DSA_512), "ML_DSA_44" => Ok(Algorithm::ML_DSA_44), "SLH_DSA_128S" => Ok(Algorithm::SLH_DSA_128S), _ => Err(format!("Unknown algorithm string: {s}")), @@ -163,7 +159,6 @@ impl From for String { fn from(alg: Algorithm) -> Self { match alg { Algorithm::SECP256K1_SCHNORR => "SECP256K1_SCHNORR".to_string(), - Algorithm::FN_DSA_512 => "FN_DSA_512".to_string(), Algorithm::ML_DSA_44 => "ML_DSA_44".to_string(), Algorithm::SLH_DSA_128S => "SLH_DSA_128S".to_string(), _ => panic!("Invalid algorithm variant"), // Should not happen with bitmask @@ -175,7 +170,6 @@ impl fmt::Display for Algorithm { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match *self { Algorithm::SECP256K1_SCHNORR => write!(f, "SECP256K1_SCHNORR"), - Algorithm::FN_DSA_512 => write!(f, "FN_DSA_512"), Algorithm::ML_DSA_44 => write!(f, "ML_DSA_44"), Algorithm::SLH_DSA_128S => write!(f, "SLH_DSA_128S"), _ => write!(f, "Unknown({:b})", self.bits), @@ -188,7 +182,6 @@ impl Algorithm { pub fn debug_name(&self) -> String { match *self { Algorithm::SECP256K1_SCHNORR => "SECP256K1_SCHNORR".to_string(), - Algorithm::FN_DSA_512 => "FN_DSA_512".to_string(), Algorithm::ML_DSA_44 => "ML_DSA_44".to_string(), Algorithm::SLH_DSA_128S => "SLH_DSA_128S".to_string(), _ => format!("Unknown({:b})", self.bits), @@ -196,14 +189,6 @@ impl Algorithm { } } -/// Creates an Algorithm variant infallibly from an index 0..3. -/// Maps 0 -> SECP256K1_SCHNORR (1), 1 -> FN_DSA_512 (2), 2 -> ML_DSA_44 (4), 3 -> SLH_DSA_128S (8) -pub fn algorithm_from_index(index: u8) -> Algorithm { - let valid_index = index % 4; // Ensure value is within 0..3 - let bits = 1u8 << valid_index; // Map 0->1, 1->2, 2->4, 3->8 - Algorithm::from(bits) -} - #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub struct PublicKey { diff --git a/tests/algorithm_tests.rs b/tests/algorithm_tests.rs index 2209ae6..82a8848 100644 --- a/tests/algorithm_tests.rs +++ b/tests/algorithm_tests.rs @@ -25,9 +25,6 @@ fn get_random_bytes(size: usize) -> Vec { // SLH-DSA-128S key generation test vector let slh_dsa_keygen_data = "dd348981dfba96c006d27d64ad0ae37c9a358e3a03df7e9ffac1519eca12dc3b64bea0144f3536a74d9caba846b7143788e89a2a279a81947364f422d491dcb47925a77be4d551b25a81070e6a460effe30939224240e4f4dc9470d3d99f7312c24523a28128ea448ef47bcc1b0ae637ad6ece2251d3e2d55c0bba6d346ca66b"; - // FN-DSA-512 key generation test vector - let fn_dsa_keygen_data = "fe098b0f5f45b28b229542daacf0f58b0a509bae17a86b58200f7e2b6427ae2aeee78412f453d32660809c52766643d229f81a8b5565f80283f0ea437ed09cc7b2b3ccea91af20aa30ee6f15acb17cc3e86248f867c847b96cdb73a011b998c66f74dd28dd987ba578226fd24947331496ba997933dc0d57d37e2e9c218aff32"; - // Deterministic signing test vectors // ML-DSA-44 deterministic signing test vector @@ -36,9 +33,6 @@ fn get_random_bytes(size: usize) -> Vec { // SLH-DSA-128S deterministic signing test vector let slh_dsa_det_data = "8ca905fd3e122d02e411683b52ecb1863104793aeba57718aabc9a65db5d61a66ca4bd29376d8118ceb555868b7054b59e23a45538d4ca28ad2080f70c56cce85f1fd5568661cb6ac06a9296ae77d97a7b854dab7eda10a4b78dd3a8f2e741f5c4686278eda9a1ac255a0cdbc79081435161331b69f9cbc04e7ae50cbfbab0ec"; - // FN-DSA-512 deterministic signing test vector - let fn_dsa_det_data = "5f9ebd7e7c3d6b1c953e0637e7d66a48089c39b540284fd3aa2f7a4bc9a905889bb7129b7cd46c1b40c50724bb7d242c47efe02d76bf0905b6c39ada0b9a01e0b83df191271d2d61c39243af3161e8a0f56a6b4a7c5d064bc439e271e59e7118c03efe8cc8e63f89cf526a1d467447dc6fe17a275a20377e843779d8b2b373a2"; - // Choose which data to return based on the test context let thread = std::thread::current(); let test_name = thread.name().unwrap_or("unknown"); @@ -47,16 +41,13 @@ fn get_random_bytes(size: usize) -> Vec { ml_dsa_keygen_data } else if test_name.contains("slh_dsa_128s") { slh_dsa_keygen_data - } else if test_name.contains("fn_dsa_512") { - fn_dsa_keygen_data } else if test_name.contains("deterministic_signing") { // Choose based on current test progress static mut COUNTER: usize = 0; unsafe { let data = match COUNTER { 0 => ml_dsa_det_data, - 1 => slh_dsa_det_data, - _ => fn_dsa_det_data, + _ => slh_dsa_det_data }; COUNTER += 1; data @@ -77,12 +68,6 @@ fn get_random_bytes(size: usize) -> Vec { // SLH-DSA-128S signing test vector let slh_dsa_sign_data = "c2dd94eec866f66b5fe8cbc07cfdbc8b4b92880f4fe53131feb1539323e87f64d3b32fd22375ead15c6c0f5c68323ed343041acfd3d962382b406e9aa30aa45c"; - // FN-DSA-512 signing test vector - let fn_dsa_sign_data = "5d67661f8b7dbe950cccd5c3924c4e1bbfb557c8fa38be57db5c5d1a3ce951aa874af91e1cf9aa7935580c86c6a09a2fa46a77ed44e560cb1de243111cc8c7dc"; - - // FN-DSA-512 deterministic signing test vector - let fn_dsa_det_sign_data = "c76e9ae6931e1c0f5e8926303f32b67e12e2fc5f22b1536dc86a90d6787bb5f634024770c57cb6509627ffc88fdd4e59111cbe18d57830fd47ddff75b63b1fa9"; - // Choose which data to return based on the test context let thread = std::thread::current(); let test_name = thread.name().unwrap_or("unknown"); @@ -91,10 +76,6 @@ fn get_random_bytes(size: usize) -> Vec { ml_dsa_sign_data } else if test_name.contains("slh_dsa_128s") { slh_dsa_sign_data - } else if test_name.contains("fn_dsa_512") { - fn_dsa_sign_data - } else if test_name.contains("deterministic_signing") { - fn_dsa_det_sign_data } else { // Default to ML-DSA data ml_dsa_sign_data @@ -122,10 +103,6 @@ fn test_key_sizes() { assert_eq!(public_key_size(Algorithm::SLH_DSA_128S), 32); assert_eq!(secret_key_size(Algorithm::SLH_DSA_128S), 64); assert_eq!(signature_size(Algorithm::SLH_DSA_128S), 7856); - - assert_eq!(public_key_size(Algorithm::FN_DSA_512), 897); - assert_eq!(secret_key_size(Algorithm::FN_DSA_512), 1281); - assert_eq!(signature_size(Algorithm::FN_DSA_512), 809); // Max signature size } #[test] @@ -246,73 +223,6 @@ fn test_slh_dsa_128s_keygen_sign_verify() { ); } -#[test] -fn test_fn_dsa_512_keygen_sign_verify() { - println!("Starting FN-DSA-512 test"); - let random_data = get_random_bytes(128); - println!("Generated random data of size {}", random_data.len()); - - let keypair = generate_keypair(Algorithm::FN_DSA_512, &random_data) - .expect("Failed to generate FN-DSA-512 keypair"); - - println!("Key generation successful"); - - // Verify the key sizes match expected values - assert_eq!( - keypair.public_key.bytes.len(), - public_key_size(Algorithm::FN_DSA_512) - ); - println!("Public key size: {}", keypair.public_key.bytes.len()); - - assert_eq!( - keypair.secret_key.bytes.len(), - secret_key_size(Algorithm::FN_DSA_512) - ); - println!("Secret key size: {}", keypair.secret_key.bytes.len()); - - // Test signing and verification - let message = b"FN-DSA-512 Test Message"; - println!("Message to sign: {message:?}"); - - let signature = sign(&keypair.secret_key, message).expect("Failed to sign with FN-DSA-512"); - - println!( - "Signature created successfully, size: {}", - signature.bytes.len() - ); - println!( - "Signature prefix: {:02x?}", - &signature.bytes[..8.min(signature.bytes.len())] - ); - - // Verify the signature size is within expected range - // FN-DSA-512 has variable signature size that depends on the message - assert!( - !signature.bytes.is_empty() - && signature.bytes.len() <= signature_size(Algorithm::FN_DSA_512), - "FN-DSA-512 signature size should be within expected range (0-809 bytes)" - ); - - // Verify the signature - println!("Verifying signature..."); - let result = verify(&keypair.public_key, message, &signature); - println!("Verification result: {result:?}"); - - assert!(result.is_ok(), "FN-DSA-512 signature verification failed"); - - // Try to verify with a modified message - should fail - let modified_message = b"FN-DSA-512 Modified Message"; - println!("Modified message: {modified_message:?}"); - - let result = verify(&keypair.public_key, modified_message, &signature); - println!("Verification with modified message result: {result:?}"); - - assert!( - result.is_err(), - "FN-DSA-512 verification should fail with modified message" - ); -} - #[test] fn test_deterministic_signing() { // Test ML-DSA-44 deterministic signing @@ -356,27 +266,6 @@ fn test_deterministic_signing() { verify(&keypair.public_key, message, &signature2).is_ok(), "Second SLH-DSA-128S signature should be valid" ); - - // Test FN-DSA-512 deterministic signing - let random_data = get_random_bytes(128); - let keypair = generate_keypair(Algorithm::FN_DSA_512, &random_data) - .expect("Failed to generate FN-DSA-512 keypair"); - let message = b"Test message for deterministic signing"; - - // Generate first signature - let signature1 = sign(&keypair.secret_key, message).expect("Failed to create first signature"); - // Generate second signature (should be identical with deterministic signing) - let signature2 = sign(&keypair.secret_key, message).expect("Failed to create second signature"); - - // Verify both signatures - assert!( - verify(&keypair.public_key, message, &signature1).is_ok(), - "First FN-DSA-512 signature should be valid" - ); - assert!( - verify(&keypair.public_key, message, &signature2).is_ok(), - "Second FN-DSA-512 signature should be valid" - ); } #[test] @@ -398,21 +287,12 @@ fn test_error_conditions() { "SLH-DSA-128S should fail with insufficient random data" ); - // Test FN-DSA-512 - let result = generate_keypair(Algorithm::FN_DSA_512, &short_random); - assert!( - result.is_err(), - "FN-DSA-512 should fail with insufficient random data" - ); - // Create valid keypairs for ML-DSA and SLH-DSA let random_data = get_random_bytes(128); let ml_keypair = generate_keypair(Algorithm::ML_DSA_44, &random_data) .expect("Failed to generate ML-DSA-44 keypair"); let slh_keypair = generate_keypair(Algorithm::SLH_DSA_128S, &random_data) .expect("Failed to generate SLH-DSA-128S keypair"); - let fn_keypair = generate_keypair(Algorithm::FN_DSA_512, &random_data) - .expect("Failed to generate FN-DSA-512 keypair"); // Create message for testing let message = b"Test message"; @@ -420,7 +300,6 @@ fn test_error_conditions() { // Create signatures let ml_sig = sign(&ml_keypair.secret_key, message).expect("Failed to sign with ML-DSA-44"); let slh_sig = sign(&slh_keypair.secret_key, message).expect("Failed to sign with SLH-DSA-128S"); - let fn_sig = sign(&fn_keypair.secret_key, message).expect("Failed to sign with FN-DSA-512"); // Try to verify with mismatched algorithms let result = verify(&slh_keypair.public_key, message, &ml_sig); @@ -434,28 +313,4 @@ fn test_error_conditions() { result.is_err(), "Verification should fail with SLH-DSA-128S signature and ML-DSA-44 key" ); - - let result = verify(&fn_keypair.public_key, message, &ml_sig); - assert!( - result.is_err(), - "Verification should fail with ML-DSA-44 signature and FN-DSA-512 key" - ); - - let result = verify(&fn_keypair.public_key, message, &slh_sig); - assert!( - result.is_err(), - "Verification should fail with SLH-DSA-128S signature and FN-DSA-512 key" - ); - - let result = verify(&ml_keypair.public_key, message, &fn_sig); - assert!( - result.is_err(), - "Verification should fail with FN-DSA-512 signature and ML-DSA-44 key" - ); - - let result = verify(&slh_keypair.public_key, message, &fn_sig); - assert!( - result.is_err(), - "Verification should fail with FN-DSA-512 signature and SLH-DSA-128S key" - ); } diff --git a/tests/serialization_tests.rs b/tests/serialization_tests.rs index 545dbe7..b78ef2d 100644 --- a/tests/serialization_tests.rs +++ b/tests/serialization_tests.rs @@ -255,19 +255,6 @@ fn test_serialization_consistency() { hex_encode(&slh_keypair.secret_key.bytes[0..16]) ); - // FN-DSA-512 - Just print for informational purposes - let fn_keypair = generate_keypair(Algorithm::FN_DSA_512, &random_data) - .expect("Failed to generate FN-DSA-512 keypair"); - - println!( - "FN-DSA-512 public key prefix: {}", - hex_encode(&fn_keypair.public_key.bytes[0..16]) - ); - println!( - "FN-DSA-512 secret key prefix: {}", - hex_encode(&fn_keypair.secret_key.bytes[0..16]) - ); - // Test serialization/deserialization consistency let message = b"Serialization consistency test"; @@ -309,7 +296,6 @@ fn test_serde_roundtrip() { for algorithm in [ Algorithm::ML_DSA_44, Algorithm::SLH_DSA_128S, - Algorithm::FN_DSA_512, ] .iter() { @@ -337,12 +323,6 @@ fn test_serde_roundtrip() { r#"{ "algorithm": "SLH_DSA_128S", "bytes": "f47e7324fb639d867a35eea3558a54224e7ca5e357c588c136d2d514facd5fc0d93a31a624a7c3d9ba02f8a73bd2e9dad0261c237a3fa1df610b30f2a06bc750" -}"# - } - Algorithm::FN_DSA_512 => { - r#"{ - "algorithm": "FN_DSA_512", - "bytes": "59dc5e3d0c6f81fbae80dc4fc6f81ff8efbe82041041f46044fbcec6079ec70fff7803ff82ffbe82ec103de82044ffe080e41140f01000fff0be100f7e10207d08307e146ffe03ffc4103f092b717df82085ec30f9f8003e0c1f82201ec6007f81003f3f07f1c7f7ff831040c1e83fc02fdec307e085f7dd470be07c1010810c4f42ec0002083e3ffc1fb7fc1101dc103a03c0bdf81f40201f08000f410440bc0431040b90000bb03c105f3d0410840c10010fe03eefd0fcf02243f7f082f82104000181e830ff0fd00017e0bfeba082fba03ceff041043e010440bdfbc1421bf1c1f42fca0c2fc0f82ffaf03e7e102f8407e0fff00f061bef45fb9002f46147fb6f84f41ec4000fbef41202f42fbffc2e7e17ff49efffc003ed80104e0403c0c11fc0440ffe7e181081142043142f7f04023f0c3040fc613c001efe13d181f0503c2ba27bebd17b28217e13cfc00400bde40fbff3afc2005fc31010bf1be17b0bd10004103dff7fc3ffe0c2e03046002e80fbf0bef79f8113afc1fbc0bffc3083fc40c2fbaf820c00bdf8113ff0003f03ff3e08203eff4f8200307a0c2efdf7e180000f40203f40000f3f0f8042f8020207dff7ffbdc00c1f7f083fbe239ec0efeebef7d03e0bdf3ff02f81ebcf400bdecbe04f40045e0403e243d00041006184ec1084fbcf000bdf44f830860c2f7f07dffd03c03ddc9fbd0c1140040fb713de470c02021fd03df40f44d810bfeff0be044f80ffffc5ec81fdebdf7bec4f83ec6f80003fc2082f830c207d1ff0ff03ef7e0f804608400403bfbc105f7ffc2f3e13ce81f8a03ce40fbc0c3102efbffe045fff0fcfb8f7f18007ffc108508803e0bcf3afb9e42ffdeba0002bc083fba045048ffb0c2080280ec4045f3df81e3d0071bce7efb9dc8ec0083f00084081f4113dfbdf4304107f07bfc207b08314307f204043ebffc4ec10772bdd7f003fc4fc204504d03cfbaf84ec60bcf43f05ffff41ec2f86fc6ffe07f183e40ffe18bec50fb03c00017e17a0be07d0820c5ec2e860cafbb104141181f80002f06f4113fffe0c518327b0c607fe3af80041000f3f0efadbe70d201e22f30bee0c2109f50aee0cebef36efebd1ec1ff3fd0af4f0f2f510e3ee041205f9fbfe1004dee019c8d01a12e8e0ef1003dc1a1bcff5fbfdec20eee816e5ff010406fc140028ead40c0010ffe605e8fc13f9e3d741ffc70701f01ecd0cf8fc1d0fe0100a11eb0e2a03e31ccb0701fd16ffea1ed905e101e121fcf8f817e1fa16ff05f4e92005e911f7cc072706f305ffc711f3cb050bf3d1df3a08130bf20df31ce50d21161eeedd0102fdfafe24011300ea0616b02ae4fc021ada25d6cecf10f327ffedf9f5fce7e502f4fd0a0108dd2337e72704f72008e60fdff6fadc100cd30dee02f11910f1f3f6fd1bfc0ce110faddf22225e922f2efee23f907fef10fff25ef09de000c1322ee072eed0bf1d907ebf31bb21613e81ee014070d49e605e607fde419daf10639f2dd1124f0ee1307d0e4221339e8d5fa07cd020607fde10e0dcc23f50505cc0a010efc2e080be503f318e9e7e1df070cf10cf5eeffdf0408fa08fefbccfd020af116d01100f30a3b061501fff425f4130b1d06e9fc0b1b0ef6e8d5f5322df71916f9c90f270be9effd36ee1c12f1e705e308cbe90e0d07f2ed0123eef7160efb10fe06efe0f61b00341b06e108f5fac01019f0fa04080102efe3f813faf613dcf9f715fdf1ee21f80df215fcf0ed3cfff217090d0dd2190bfbf510cdf5fa05d7ffd71f08f935efe80ef41118eeebff1f" }"# } _ => panic!("Fixture missing for algorithm {algorithm:?}"), @@ -382,12 +362,6 @@ fn test_serde_roundtrip() { r#"{ "algorithm": "SLH_DSA_128S", "bytes": "f47e7324fb639d867a35eea3558a54224e7ca5e357c588c136d2d514facd5fc0d93a31a624a7c3d9ba02f8a73bd2e9dad0261c237a3fa1df610b30f2a06bc750" -}"# - } - Algorithm::FN_DSA_512 => { - r#"{ - "algorithm": "FN_DSA_512", - "bytes": "094048b817ccc551458200973105f10a0e5d8954851c1092bf7871dd3e865cf5b4fcee405a18e312bc8aa823aa6cb0cd5cd49f79bfa17bd34692798d48a99a7e9ef5589528e2455111a5402e85f45d7443f3cee4df2d468f31124c204e365b07fea9e1100486a6c9c833152d3ee26ac91a7151d6a2929024a9edbfe5f789f2b30dc8c12961b69bbafba9f7d7181cd1d0f1220e067a187a8a254da339a53a00852ff529c06e49221b0d159d25e014c2c36ed8722a65c6f4330d7b117d1cd48328faa41e5d1b7e859265718dbc92a85d9696080a73ba7161e3552c6694def708886521b9d7541d1e856fcc134083556c17d2fc004897468bfdc9f96f4f7a0f25a3306baaf962123e994014c011b45fb7f201f50ea803029b59b1a68d9031749daba3090ed54b029e8e52f0cab8d50bb599ab07d91a6f53ca43a250e1bea9252135f282654c41382b94537269463288d3c52a2222ace23d9befb496867821651ea84ada4b465dd31b6abd358407c39a0a42d15ad0edbe89515a4bce12804846a376ac6c222e440346c00da4107f449142931a842e3868cba56415df4a65197760b51503c4c220a7d96dbaeb493267c810d3b6640f0f96b9f2178009b441b5509489efbcec97282307f69eb26f78bc55c941c15316c2acda29593613d22372020261f534e4aa5b6d5bd4f44e0765f65a818742a26b7d95d2648e429c455d64c8688abadd2adbfc1f7a39fee167e35eef4d28c85304843283b0ec36b70d8c96817648cf1d4f3e91d1140a1756189cabd03bda631fd9d295beea6e56411530ce5a085466c7f5f6218711f5dc456fa41b2ffc5387b7a3043fa104339f2a3e32c13730b748364d4d5a1addd8852c05b7e7cf88e6aea94c1230a5968aca6b21b9940c098527e432cd0b8e693ed0121b270599d2f32f5cd382a47ce7315da79676d960a5cfb795983d998c10616980d554f767375fdc19312862e1515c3fd032a4c73ee49174185fd70d0652194805333ff67791a2844f58553a72a720a68142ef8a019814ac0a8943de20ab18020693578d880f62c9b328c15a09bd89c0e3ebacb5aaabd8d626dc5026d2f734006a24e60f070d6f9625080fd3c3199040b5b5972aa4ec23193aca8c64d20d744853f5dddabd5527418454cd093caf65265070ac0815c5a8121733ddd69b188e2b7b6491066365123b4aeb8969c2e7799c77a0e1a12a7d3de20471c8558628b164982564055cef78630dfe738ace60ff01ac78fdc16b0ad036" }"# } _ => panic!("Fixture missing for algorithm {algorithm:?}"), @@ -423,12 +397,6 @@ fn test_serde_roundtrip() { r#"{ "algorithm": "ML_DSA_44", "bytes": "d44770409f4dacafbc779f68ef129f8f15138a5befa38a9ced36031ebae7bdcbb09e900350de29cf4b9c2ce04e41bfb40739dd9bd985ed1bbed4c9c7bc96cca6f4d0c921b43b8e4067789b6e7744e7a055a5edc5b4bf0d8fc5ec404c980b5b298e5d930df3375b7ab686177c99ec4be848ce7cc162adb578896d11d4fcc5f0cf1af5f9ad070ea6f3460c06627f937782aaa185304c068748ee86c91fec03853a7ce81a304fcc2afcbb66c2e308af5269cd1c9b45a2ab73d04474d96b1c5890947485dd6c3d6e7bdc7b8e445fb27fb525677b2a3b95954dfd3bb163985d4640a4c1c1102452341e4ad5cbf5b8eb4d30c3323a6572502670e748cddca9d18f12d3a3fffcfec7099f16f6542eb39d3032094023649de67af9ee8e06c9a53cc926388345d6a9412d2de82a4e59c6c11b6f3b259243e45ee57ccd2e4f3a68a8e53b808911b4afe9d72891ca40739e1ab7142ca935e161a19dedf234ed27a7c18ba722780dd53aefc40e921ff0de9ca3ed37ebbe02237f802ea073f11c1b2ef2b703d65739b1d8c060d62a834138d7a2e663854ac794999c95360d849f57b00c37f1cf90a13e0b831df1ada26742097b6465bd2755794e20271077b80ac4d2aa6b5c8e3c77c34ee574dace472eee5eb88b0c59209bb6081a63e3cd9280b4d766e00da79af6d496c90b3ae5800397ecabcaa94d80e765b016a250dddc227d2fd1f6342290cc4ed53d1416fca988cb3d4577e27d76bbd1adcc6b22e80bf9d5901ab5797081012e4fddd320238f5ebf4c4dc5cb17ca57cc76089c8fe54ac7b3bd909ffd37ab4440c4716bb1ea42582c12b195ec38f5654146476bb72bead204fc250671567098ef2fc7c63c111a8cd3abdc5ab6aa4ff47ba5e2998e2aa4950f0725c4c770f974e7e16975068ece9b81e76fe65c84134f31855d910bb2f8ce6de08b59c6020b9292913a6322757176bdb70d2a01428161cc4f858b777d0af656366aaab65bd54cf2ed7820c26f93152cc7e827e403b71a10863409e75dbfb450618c718c3d0ac6b6686f3efc41c07a226547fa21721aeacf09b9707cedca25624f17b52a9fbb80045b62099d31f71dffa551af1d7a7276aed9036939f6c04884d13db33783adfbdd9de05824f6fe2cfbadeecf0e318f1e34bfc03d5a70c4dc8c9cebe1c1b9b605d421144a3d66b7d86710a2b87171680569222480db421b1bd678999d22aa561c55942fd7c2a7900759ee095ed2213d6ed0b5354846a010328f81600b42949be02f48fce7caf64a03dcc97edadc42ef4971f5371ff3e520d2c1de923c0dac6439c3a7e9dd4e55090584f9e2eeea96f29b69417673a8e150efe779166ba498f4ec58b9ecd00aac8b01dff155f29750852fe2e30cb0d6378b1a17ce9d90b93a5c838bbea80cedeb609c600f3bb44314a8c36713c849ec47a3794f3b828b7a8f169f33f3a1eb6867ba5d1fb71e658e1709dd08ac7e874ef3b2077edf570eb3d3989874d729aea331e03caa07ba672bc6b512a7902557bea55ee5466205064193de95ff92d2f5fac41d914e6c7e6fc62cbfe5b9ada3383a502c391782374a1b1241c7368598492f48085aea05f065213f13d9463c4b144e80a426fa5c415e593bef0b541068a8ffa1464e9b8f4ded4da5caad827142778a17d119c3e7121020ff452aefaf816c7ebf190b684d43e2c5547cece9eb7fa4f5312b19fae7f2645ff38c6c9a2514fdfdb74d3ec40e93402027f5af826aaa6c076dc1815b0b7425d5c9f7880f0e82258ff88cc3090e561524bab84bd167840463802df66a18340d7d0ef438a5c99c788ab7f07aaa2ee6e37ae0488967600421e6ddcde2a44dd3ceec3e8914f7fb5a1a42c38e20c1666ccfad1a1ae0364cc85a5612f35e087c77c0c212099c4a60138cb9486a571a59a9993ee00abd77902b684163b50fb02373baa75834ac3638a6c8e6a6038ce2a907c6ba2647cbd3437fb4920b1a5d46fb04b2c36a8aee0f3fcae7709e4508d2c7cfdfb724483dc71881a385eecd8b4dc32f793037be625a8427690ddbd6e0e8d80a15516cbadba4034d6700cb6ec807815f6dd5e8619a336bab503cfe6473cc913a80f9e5897ea68f2866ef145a3f1ef371ebe1151a4a93eceb3059a27fa93a309363b8b23cbf401dff0134a6080805837ae9fcff26a58e86ce37ded0d08f7022a979f0f788e99e7cdf32f16e09282b61d4528c5b79a38feeedf210722a20a428ae5b404c7923d1fa10e790b166b98ab1e44ae6fa3612a723045d7c4b77570345f7e7204227433611644a2c75715184da36f0688fd406c878773c58646bb130146f7ec75f8b03c97eb4329c942d9d6006bd1fcbb4e9f56031191d00334ca77cf71bb895521ea7ba6f9c4d9b67f7c4fd38f4e914cbb9717dac45c802234505de0951f8d897365002feac6dcc8616bab1ec0583de1c3cbbbaab3cbd5db94ff2721c9a22541e6796fca0a217f4eee5e1441398a1286b4638533d4a455f3c83c85d886911072eb45c808306514ef4ad1c31e3e5f7151dab4d2d18ec8ac812e0c03c86d879865281cfa517b955c1842c7e093e35b107eda832356e2992adaa697565e2c4a8e9994767a9a61d717dd2a860695c83ea2c5b5f692493e79f2c184df7db7973dfd79abf00f042ba10ad9ade75ea1b01b62efcebc6a2c7b59a2af01b8691855919b1826799f0bba13509f5db2cb55e3f7c7f72eec95df0da8021ebbbb60d2f063c4129fcd9ed825d8671bb913b4b9cf91e148d941590536a44511b62296be5222a253a19c9293126b5e8b1aebb7a58c4353fced6f23c35f7414730e78024b7ba2f8bfead124bed379d4098a3be2abd3cc10a47fd0fdb40b35ec517fbc66bf2c06e1f6960f8595452705339cdda9a9b5102b8a1a5c1f1f872d0fc564555cc431f95b7ac24fb679188f4d49a94a20f6734c20acc0c7a2463e4eb23350d386198c086818f6ddf32d5842f41d7ef3f1644f76dc401f41e87027aa77671132e3d6faa099f1e28b10d4642fe3364cd82b4950211d741392454d5b395dbf89745cdcf43910add671639829495ceca0b0d6fb2c85a9a3369cc6228ab65d88198167de7519a4857d9f2a5b37b88f4258f9d01780f23174eb9c0b3cbc888e59144c3ccfcef165f6ebe1be85a73976bcb54ba95966299e6eeeeb8fbfc51ce86075a672107e84a56c61a00ebb08e579407da3651fcec5c515ca4a5e49a51fbb07915356b0fc1654a86be032fe6ca14a0ae2526b5c78c04c842ce586a85aa1dd7a80cf355af293be254236c9952f8b1a2f2663613154a74754d0913181d2324272f3d4b577285868999abb5b9bcc5d3dde9f5fbfc050e51595eadf0f1f3273d415e6069799da1b7babfc8c9cdd1d6e7f90a16313345465d7677aeafb5c8ced4ecfb00000000000000001b243748" - }"# - } - Algorithm::FN_DSA_512 => { - r#"{ - "algorithm": "FN_DSA_512", - "bytes": "39eefb6b924b3aee2a433639048859593790fc1d96736dbaba41236bf1d8a13cba44ba25b360f89a3c67fa4b34cc8a40d9c0f695b203a521d45d27e3a55ff3e2f448b4d99e647b792e8cc914316ff7c6fb9262778d5d1ed477e3ee94e60c795ac47a308df6a64c187be9a105c74e9fdbcacd166b8b3579e8751a046a9bb0903ff1536dd5fd574a754ce3af884662385388b281107221ee52192fb4dc8cac2e448eebd8fcca231d3668fd3d8c2e93eef57bd53f8d279115ee44fbf037ca65be3514af543e19243f3eed60d8db9097adb6fc34a18a5923537932d3839f69d7865f29fe61e4f2ed540a87b2e7ad6cba5a955e50998af9136a0c576f1f8443517c1060a9b64fded1824e929914d3793046e132de08ac69faef8433056763a1cafbdac6c1e5082a73f7ed78b6103d0f43096b86441157972d4a8c4d3422066b70d0bc8e10c0f3f00b62ef64b6279a65074f5a9392dd011fc2acf84269faf0ea54662916db217f192b8d744656f83b86541f32312281a1fd4c6224c0c04e0e798c54eb09ebdae4d8e372c59a494a4b8eb619cf4ffc303c830d5479a1f8f1ad65bd3b581cdd0e6a90e15031a5fe79f1288df57b006e9897421a45b3641910b54e5b3cd23a50ce32015ef67c13c83356deabddc59a0ec0a1c43accd867120527222fa5a3049938ac11afdea45a9b073ad9064fd86cf688e74ddbcdee8281961c1cdc664b1182d451aa3392e1a358fe1204c7ac0e23f158294c8117ebfc69741f0a84caa064eb46411e6c535251c4d47e0809b4c716bb54f3fee474677064291135b91eeb25fe8cc436125620b1934eafea6c84b37edf97f7976ec24299aa992610c7a20efa187f85d3792a84235ead926fe951b3d90b76728fea6dd938a6212fc85ff20bff87e33f80b56611fdd16f585663d5" }"# } // Add cases for other deterministic algorithms like SECP256K1_SCHNORR if needed